```
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful

feat(xmlres): 添加磁盘配置文件回退机制并支持JSON格式配置

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

View File

@@ -5,7 +5,10 @@ import (
_ "blazing/common/data/xmlres/packed" _ "blazing/common/data/xmlres/packed"
"encoding/json" "encoding/json"
"fmt"
"os" "os"
"path/filepath"
"strings"
"github.com/ECUST-XX/xml" "github.com/ECUST-XX/xml"
"github.com/gogf/gf/v2/os/gres" "github.com/gogf/gf/v2/os/gres"
@@ -13,23 +16,55 @@ import (
) )
var path string 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 { func getXml[T any](path string) T {
// 解析XML到结构体 // 解析XML到结构体
var xmls T var xmls T
t1 := gres.GetContent(path) t1 := readConfigContent(path)
xml.Unmarshal(t1, &xmls) xml.Unmarshal(t1, &xmls)
return xmls return xmls
} }
func getJson[T any](path string) T { func getJson[T any](path string) T {
// 解析XML到结构体 // 解析JSON到结构体
var xmls T var xmls T
t1 := gres.GetContent(path) t1 := readConfigContent(path)
json.Unmarshal(t1, &xmls) 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 return xmls
} }
@@ -59,6 +94,7 @@ var (
func Initfile() { func Initfile() {
//gres.Dump() //gres.Dump()
path1, _ := os.Getwd() path1, _ := os.Getwd()
diskConfigPath = filepath.Join(path1, "public", "config")
path = path1 + "/public/config/" path = path1 + "/public/config/"
path = "config/" path = "config/"
MapConfig = getXml[Maps](path + "210.xml") MapConfig = getXml[Maps](path + "210.xml")
@@ -87,10 +123,10 @@ func Initfile() {
return gconv.Int(m.ProductID) return gconv.Int(m.ProductID)
}) })
Skill := getXml[MovesTbl](path + "227.xml") skillConfig := getJson[MovesJSON](path + "moves_flash.json")
SkillMap = make(map[int]Move, len(Skill.Moves)) SkillMap = make(map[int]Move, len(skillConfig.MovesTbl.Moves.Move))
for _, v := range Skill.Moves { for _, v := range skillConfig.MovesTbl.Moves.Move {
v.SideEffectS = ParseSideEffectArgs(v.SideEffect) v.SideEffectS = ParseSideEffectArgs(v.SideEffect)
v.SideEffectArgS = ParseSideEffectArgs(v.SideEffectArg) v.SideEffectArgS = ParseSideEffectArgs(v.SideEffectArg)
SkillMap[v.ID] = v SkillMap[v.ID] = v

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,7 @@
package xmlres package xmlres
import ( import (
"encoding/json"
"encoding/xml" "encoding/xml"
"fmt" "fmt"
"io" "io"
@@ -33,52 +34,156 @@ type MovesTbl struct {
Moves []Move `xml:"Moves>Move"` Moves []Move `xml:"Moves>Move"`
EFF []SideEffect `xml:"SideEffects>SideEffect"` EFF []SideEffect `xml:"SideEffects>SideEffect"`
} }
type MovesJSON struct {
MovesTbl MovesJSONRoot `json:"MovesTbl"`
}
type MovesJSONRoot struct {
Moves struct {
Move []Move `json:"Move"`
} `json:"Moves"`
SideEffects struct {
SideEffect []SideEffect `json:"SideEffect"`
} `json:"SideEffects"`
}
type MovesMap struct { type MovesMap struct {
XMLName xml.Name `xml:"MovesTbl"` XMLName xml.Name `xml:"MovesTbl"`
Moves map[int]Move Moves map[int]Move
EFF []SideEffect `xml:"SideEffects>SideEffect"` EFF []SideEffect `xml:"SideEffects>SideEffect"`
} }
type rawFlexibleString string
func (s *rawFlexibleString) UnmarshalJSON(data []byte) error {
text := strings.TrimSpace(string(data))
if text == "" || text == "null" {
*s = ""
return nil
}
if len(text) >= 2 && text[0] == '"' && text[len(text)-1] == '"' {
var decoded string
if err := json.Unmarshal(data, &decoded); err != nil {
return err
}
*s = rawFlexibleString(decoded)
return nil
}
*s = rawFlexibleString(text)
return nil
}
// Move 定义单个技能的结构 // Move 定义单个技能的结构
type Move struct { type Move struct {
ID int `xml:"ID,attr"` ID int `xml:"ID,attr" json:"ID"`
Name string `xml:"Name,attr"` Name string `xml:"Name,attr" json:"Name"`
Category int `xml:"Category,attr"` //属性 Category int `xml:"Category,attr" json:"Category"` //属性
Type int `xml:"Type,attr"` //类型 Type int `xml:"Type,attr" json:"Type"` //类型
Power int `xml:"Power,attr"` //威力 Power int `xml:"Power,attr" json:"Power"` //威力
MaxPP int `xml:"MaxPP,attr"` //最大PP MaxPP int `xml:"MaxPP,attr" json:"MaxPP"` //最大PP
Accuracy int `xml:"Accuracy,attr"` //命中率 Accuracy int `xml:"Accuracy,attr" json:"Accuracy"` //命中率
CritRate int `xml:"CritRate,attr,omitempty"` //暴击率 CritRate int `xml:"CritRate,attr,omitempty" json:"CritRate,omitempty"` //暴击率
Priority int `xml:"Priority,attr,omitempty"` //优先级 Priority int `xml:"Priority,attr,omitempty" json:"Priority,omitempty"` //优先级
MustHit int `xml:"MustHit,attr,omitempty"` //是否必中 MustHit int `xml:"MustHit,attr,omitempty" json:"MustHit,omitempty"` //是否必中
SwapElemType int `xml:"SwapElemType,attr,omitempty"` //技能交换属性 SwapElemType int `xml:"SwapElemType,attr,omitempty" json:"SwapElemType,omitempty"` //技能交换属性
CopyElemType int `xml:"CopyElemType,attr,omitempty"` // 技能复制属性 CopyElemType int `xml:"CopyElemType,attr,omitempty" json:"CopyElemType,omitempty"` // 技能复制属性
CritAtkFirst int `xml:"CritAtkFirst,attr,omitempty"` // 先出手时必定致命一击 CritAtkFirst int `xml:"CritAtkFirst,attr,omitempty" json:"CritAtkFirst,omitempty"` // 先出手时必定致命一击
CritAtkSecond int `xml:"CritAtkSecond,attr,omitempty"` //后出手时必定致命一击 CritAtkSecond int `xml:"CritAtkSecond,attr,omitempty" json:"CritAtkSecond,omitempty"` //后出手时必定致命一击
CritSelfHalfHp int `xml:"CritSelfHalfHp,attr,omitempty"` //自身体力低于一半时必定致命一击 CritSelfHalfHp int `xml:"CritSelfHalfHp,attr,omitempty" json:"CritSelfHalfHp,omitempty"` //自身体力低于一半时必定致命一击
CritFoeHalfHp int `xml:"CritFoeHalfHp,attr,omitempty"` //对方体力低于一半时必定致命一击 CritFoeHalfHp int `xml:"CritFoeHalfHp,attr,omitempty" json:"CritFoeHalfHp,omitempty"` //对方体力低于一半时必定致命一击
DmgBindLv int `xml:"DmgBindLv,attr,omitempty"` //使对方受到的伤害值等于自身的等级 DmgBindLv int `xml:"DmgBindLv,attr,omitempty" json:"DmgBindLv,omitempty"` //使对方受到的伤害值等于自身的等级
PwrBindDv int `xml:"PwrBindDv,attr,omitempty"` //威力power取决于自身的潜力个体值 PwrBindDv int `xml:"PwrBindDv,attr,omitempty" json:"PwrBindDv,omitempty"` //威力power取决于自身的潜力个体值
PwrDouble int `xml:"PwrDouble,attr,omitempty"` //攻击时,若对方处于异常状态, 则威力翻倍; PwrDouble int `xml:"PwrDouble,attr,omitempty" json:"PwrDouble,omitempty"` //攻击时,若对方处于异常状态, 则威力翻倍;
DmgBindHpDv int `xml:"DmgBindHpDv,attr,omitempty"` //使对方受到的伤害值等于自身的体力值 DmgBindHpDv int `xml:"DmgBindHpDv,attr,omitempty" json:"DmgBindHpDv,omitempty"` //使对方受到的伤害值等于自身的体力值
SideEffect string `xml:"SideEffect,attr,omitempty"` SideEffect string `xml:"SideEffect,attr,omitempty" json:"SideEffect,omitempty"`
SideEffectArg string `xml:"SideEffectArg,attr,omitempty"` SideEffectArg string `xml:"SideEffectArg,attr,omitempty" json:"SideEffectArg,omitempty"`
SideEffectS []int SideEffectS []int
SideEffectArgS []int SideEffectArgS []int
AtkNum int `xml:"AtkNum,attr,omitempty"` AtkNum int `xml:"AtkNum,attr,omitempty" json:"AtkNum,omitempty"`
AtkType int `xml:"AtkType,attr,omitempty"` // 0:所有人 1:仅己方 2:仅对方 3:仅自己 AtkType int `xml:"AtkType,attr,omitempty" json:"AtkType,omitempty"` // 0:所有人 1:仅己方 2:仅对方 3:仅自己
Url string `xml:"Url,attr,omitempty"` Url string `xml:"Url,attr,omitempty" json:"Url,omitempty"`
Info string `xml:"info,attr,omitempty"` Info string `xml:"info,attr,omitempty" json:"info,omitempty"`
CD *int `xml:"CD,attr"` CD *int `xml:"CD,attr" json:"CD"`
}
func (m *Move) UnmarshalJSON(data []byte) error {
type moveAlias struct {
ID int `json:"ID"`
Name string `json:"Name"`
Category int `json:"Category"`
Type int `json:"Type"`
Power int `json:"Power"`
MaxPP int `json:"MaxPP"`
Accuracy int `json:"Accuracy"`
CritRate int `json:"CritRate,omitempty"`
Priority int `json:"Priority,omitempty"`
MustHit int `json:"MustHit,omitempty"`
SwapElemType int `json:"SwapElemType,omitempty"`
CopyElemType int `json:"CopyElemType,omitempty"`
CritAtkFirst int `json:"CritAtkFirst,omitempty"`
CritAtkSecond int `json:"CritAtkSecond,omitempty"`
CritSelfHalfHp int `json:"CritSelfHalfHp,omitempty"`
CritFoeHalfHp int `json:"CritFoeHalfHp,omitempty"`
DmgBindLv int `json:"DmgBindLv,omitempty"`
PwrBindDv int `json:"PwrBindDv,omitempty"`
PwrDouble int `json:"PwrDouble,omitempty"`
DmgBindHpDv int `json:"DmgBindHpDv,omitempty"`
SideEffect rawFlexibleString `json:"SideEffect,omitempty"`
SideEffectArg rawFlexibleString `json:"SideEffectArg,omitempty"`
AtkNum int `json:"AtkNum,omitempty"`
AtkType int `json:"AtkType,omitempty"`
Url string `json:"Url,omitempty"`
Info string `json:"info,omitempty"`
CD *int `json:"CD"`
}
var aux moveAlias
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
*m = Move{
ID: aux.ID,
Name: aux.Name,
Category: aux.Category,
Type: aux.Type,
Power: aux.Power,
MaxPP: aux.MaxPP,
Accuracy: aux.Accuracy,
CritRate: aux.CritRate,
Priority: aux.Priority,
MustHit: aux.MustHit,
SwapElemType: aux.SwapElemType,
CopyElemType: aux.CopyElemType,
CritAtkFirst: aux.CritAtkFirst,
CritAtkSecond: aux.CritAtkSecond,
CritSelfHalfHp: aux.CritSelfHalfHp,
CritFoeHalfHp: aux.CritFoeHalfHp,
DmgBindLv: aux.DmgBindLv,
PwrBindDv: aux.PwrBindDv,
PwrDouble: aux.PwrDouble,
DmgBindHpDv: aux.DmgBindHpDv,
SideEffect: string(aux.SideEffect),
SideEffectArg: string(aux.SideEffectArg),
AtkNum: aux.AtkNum,
AtkType: aux.AtkType,
Url: aux.Url,
Info: aux.Info,
CD: aux.CD,
}
return nil
} }
type SideEffect struct { type SideEffect struct {
ID int `xml:"ID,attr"` ID int `xml:"ID,attr" json:"ID"`
Help string `xml:"help,attr"` Help string `xml:"help,attr" json:"help"`
Des string `xml:"des,attr"` Des string `xml:"des,attr" json:"des"`
} }
// ReadHTTPFile 通过HTTP GET请求获取远程文件内容 // ReadHTTPFile 通过HTTP GET请求获取远程文件内容

View File

@@ -1 +0,0 @@
E:/newcode/sun/public/assets/227.xml

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
E:/newcode/flash/out/resource/json/moves_flash.json