Files
hanfuit 645b64fe21 DNF90 服务端与启动器完整源码(含 GM 工具功能增强)
服务端(Go):
- GM 塞背包/带属性装备发放:在线角色推送 op14 增量物品行,背包实时刷新,无需回角色选择界面
- GM 改金币/改等级:去掉在线拒绝,落库后推送 op14 钱包/op37 等级状态,在线实时刷新
- 等级端点统一切换到新版 GMSetCharacterLevel(自带在线刷新)
- 无限/锁死疲劳模式 + 燃烧疲劳:每房间消耗 2 点、打怪与通关经验双倍
- 燃烧疲劳开关时给所有在线角色推送系统提示(op12 mode 0)
- 深渊史诗掉率:GM 全局倍率 + 城镇增益药剂窗口倍率,真实接入掉落结算

启动器(Python/JS):
- 标题栏自绘、窗口 1204x717、禁止拖拽改大小、仅最小化/关闭
- GM 工具:疲劳与燃烧、深渊史诗掉率、拍卖行上架(单一定价对齐)
- 拍卖行上架前端对齐服务端单一价格语义,修复 400 报错
2026-11-04 14:31:55 +08:00

72 lines
1.7 KiB
Go

package config
import (
"os"
"reflect"
"regexp"
)
var configEnvPattern = regexp.MustCompile(`\$\{[A-Za-z_][A-Za-z0-9_]*\}`)
func expandEnvString(value string) string {
return configEnvPattern.ReplaceAllStringFunc(value, func(token string) string {
key := token[2 : len(token)-1]
if value, ok := os.LookupEnv(key); ok {
return value
}
return token
})
}
func expandEnvValues(target any) {
expandConfigEnvValue(reflect.ValueOf(target))
}
func expandConfigEnvValue(value reflect.Value) {
if !value.IsValid() {
return
}
if value.Kind() == reflect.Pointer {
if value.IsNil() {
return
}
expandConfigEnvValue(value.Elem())
return
}
switch value.Kind() {
case reflect.Struct:
for idx := 0; idx < value.NumField(); idx++ {
field := value.Field(idx)
if !field.CanSet() && field.Kind() != reflect.Struct {
continue
}
expandConfigEnvValue(field)
}
case reflect.String:
if value.CanSet() {
value.SetString(expandEnvString(value.String()))
}
case reflect.Slice, reflect.Array:
for idx := 0; idx < value.Len(); idx++ {
expandConfigEnvValue(value.Index(idx))
}
case reflect.Map:
if value.IsNil() || !value.CanSet() {
return
}
replacement := reflect.MakeMapWithSize(value.Type(), value.Len())
for _, key := range value.MapKeys() {
outKey := key
outValue := value.MapIndex(key)
if key.Kind() == reflect.String {
outKey = reflect.ValueOf(expandEnvString(key.String())).Convert(key.Type())
}
if outValue.Kind() == reflect.String {
outValue = reflect.ValueOf(expandEnvString(outValue.String())).Convert(outValue.Type())
}
replacement.SetMapIndex(outKey, outValue)
}
value.Set(replacement)
}
}