Files
bl/common/data/xmlres/file.go
昔念 174830731c
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
```
feat(xmlres): 添加磁盘配置文件回退机制并支持JSON格式配置

- 新增readConfigContent函数,优先从资源包读取配置,失败时回退到磁盘文件
- 添加diskConfigPath变量存储本地配置路径
- 支持从磁盘读取JSON格式配置文件,增强配置灵活性
- 修改getJson函数增加错误处理和调试日志输出
- 将技能配置从XML格式改为JSON格式,提升数据解析效率
- 初始化时设置默认磁盘配置路径为public/config目录
```
2026-04-12 04:09:19 +08:00

218 lines
5.3 KiB
Go

package xmlres
import (
"blazing/common/utils"
_ "blazing/common/data/xmlres/packed"
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/ECUST-XX/xml"
"github.com/gogf/gf/v2/os/gres"
"github.com/gogf/gf/v2/util/gconv"
)
var path string
var diskConfigPath string
func readConfigContent(path string) []byte {
content := gres.GetContent(path)
if len(content) > 0 {
return content
}
if diskConfigPath == "" {
return content
}
diskPath := filepath.Join(diskConfigPath, strings.TrimPrefix(path, "config/"))
data, err := os.ReadFile(diskPath)
if err != nil {
fmt.Printf("[xmlres] readConfigContent fallback failed: path=%s disk=%s err=%v\n", path, diskPath, err)
return content
}
fmt.Printf("[xmlres] readConfigContent fallback hit: path=%s disk=%s len=%d\n", path, diskPath, len(data))
return data
}
func getXml[T any](path string) T {
// 解析XML到结构体
var xmls T
t1 := readConfigContent(path)
xml.Unmarshal(t1, &xmls)
return xmls
}
func getJson[T any](path string) T {
// 解析JSON到结构体
var xmls T
t1 := readConfigContent(path)
if len(t1) == 0 {
fmt.Printf("[xmlres] getJson empty content: path=%s\n", path)
return xmls
}
if err := json.Unmarshal(t1, &xmls); err != nil {
head := string(t1)
if len(head) > 300 {
head = head[:300]
}
fmt.Printf("[xmlres] getJson unmarshal failed: path=%s len=%d err=%v head=%q\n", path, len(t1), err, head)
}
return xmls
}
var (
MapConfig Maps //地图配置
// ItemsConfig Items //物品配置
// EffectArgsConfig EffectArg //arg参数
//TalkConfig TalkRoot //任务配置
// //Monster MonsterRoot //野怪配置
//MonsterMap map[int]TMapConfig
//Skill MovesTbl //技能配置
SkillMap map[int]Move
PetMAP map[int]PetInfo //宠物配置
NatureRootMap map[int]NatureItem
EffectMAP map[int]NewSeIdx
PlayerEffectMAP map[int]NewSeIdx
ItemsMAP map[int]Item
TaskMap map[int]Task
ShopMap map[int]ShopItem
SkillTypeMap map[int]SkillType
RelationsMap map[int]Relation
//GoldProductMap = make(map[int]GoldProductItem, 0)
EVOLVMAP map[int]Evolve
)
func Initfile() {
//gres.Dump()
path1, _ := os.Getwd()
diskConfigPath = filepath.Join(path1, "public", "config")
path = path1 + "/public/config/"
path = "config/"
MapConfig = getXml[Maps](path + "210.xml")
EffectArgs = make(map[int]int)
for _, t := range getJson[EffectArg](path + "side_effect.json").SideEffects.SideEffect {
EffectArgs[t.ID] = t.SideEffectArgcount
}
ItemsMAP = utils.ToMap[Item, int](getXml[Items](path+"43.xml").Items, func(m Item) int {
return m.ID
})
EVOLVMAP = utils.ToMap[Evolve, int](getXml[CondEvolves](path+"进化仓.xml").Evolves, func(m Evolve) int {
return m.ID
})
//TalkConfig = getXml[TalkRoot](path + "talk.xml")
// MonsterMap = utils.ToMap(getXml[MonsterRoot](path+"地图配置野怪.xml").Maps, func(m TMapConfig) int {
// return m.ID
// })
ShopMap = utils.ToMap(getXml[ShopRoot](path+"地图配置野怪.xml").Items, func(m ShopItem) int {
return gconv.Int(m.ProductID)
})
skillConfig := getJson[MovesJSON](path + "moves_flash.json")
SkillMap = make(map[int]Move, len(skillConfig.MovesTbl.Moves.Move))
for _, v := range skillConfig.MovesTbl.Moves.Move {
v.SideEffectS = ParseSideEffectArgs(v.SideEffect)
v.SideEffectArgS = ParseSideEffectArgs(v.SideEffectArg)
SkillMap[v.ID] = v
}
TaskMap = utils.ToMap[Task, int](getXml[Tasks](path+"task.xml").Tasks, func(m Task) int {
return m.ID
})
pets := getXml[Monsters](path + "226.xml").Monsters
for i := range pets {
pets[i].YieldingEVValues = parseYieldingEV(pets[i].YieldingEV)
}
PetMAP = utils.ToMap[PetInfo, int](pets, func(m PetInfo) int {
return m.ID
})
NatureRootMap = utils.ToMap[NatureItem, int](getXml[NatureRoot](path+"nature.xml").Items, func(m NatureItem) int {
return m.ID
})
EffectMAP1 := getXml[NewSe](path + "bossbuff和特性.xml")
EffectMAP = make(map[int]NewSeIdx, len(EffectMAP1.SeIdxList))
for _, v := range EffectMAP1.SeIdxList {
v.ArgsS = ParseSideEffectArgs(v.Args)
EffectMAP[gconv.Int(v.Idx)] = v
}
PlayerEffectMAP = make(map[int]NewSeIdx)
for _, v := range EffectMAP1.SeIdxList {
if gconv.Int(v.Stat) == 1 && gconv.Int(v.Idx) > 1000 {
v.ArgsS = ParseSideEffectArgs(v.Args)
PlayerEffectMAP[gconv.Int(v.Idx)] = v
}
}
// GoldProductMap = utils.ToMap(getXml[GoldProductConfig](path+"30001.xml").Items,
// func(m GoldProductItem) int {
// return gconv.Int(m.ProductID)
// },
// )
}
// func init() {
// go func() {
// if !gfile.Exists(path) {
// fileHandle, _ := gfile.Create(path)
// fileHandle.Close()
// }
// //updatersares()
// ctx := gctx.New()
// _, err := gfsnotify.Add(path, func(event *gfsnotify.Event) {
// if event.IsCreate() {
// glog.Debug(ctx, "创建文件 : ", event.Path)
// }
// if event.IsWrite() {
// glog.Debug(ctx, "写入文件 : ", event.Path)
// //initfile() //先初始化一次
// }
// if event.IsRemove() {
// glog.Debug(ctx, "删除文件 : ", event.Path)
// }
// if event.IsRename() {
// glog.Debug(ctx, "重命名文件 : ", event.Path)
// }
// if event.IsChmod() {
// glog.Debug(ctx, "修改权限 : ", event.Path)
// }
// glog.Debug(ctx, event)
// })
// if err != nil {
// glog.Fatal(ctx, err)
// } else {
// select {}
// }
// }()
// }