diff --git a/common/data/xmlres/effectarg.go b/common/data/xmlres/effectarg.go index 3c40e9d2d..89af08107 100644 --- a/common/data/xmlres/effectarg.go +++ b/common/data/xmlres/effectarg.go @@ -5,7 +5,7 @@ type EffectArg struct { SideEffect []struct { ID int `json:"ID"` SideEffectArgcount int `json:"SideEffectArgcount"` - SideEffectArg string `json:"SideEffectArg,omitempty"` + SideEffectArg rawFlexibleString `json:"SideEffectArg,omitempty"` } `json:"SideEffect"` } `json:"SideEffects"` } diff --git a/common/data/xmlres/file.go b/common/data/xmlres/file.go index 9f4c6e134..e529fc7de 100644 --- a/common/data/xmlres/file.go +++ b/common/data/xmlres/file.go @@ -6,9 +6,6 @@ import ( _ "blazing/common/data/xmlres/packed" "encoding/json" "fmt" - "os" - "path/filepath" - "strings" "github.com/ECUST-XX/xml" "github.com/gogf/gf/v2/os/gres" @@ -16,27 +13,9 @@ import ( ) 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 + return gres.GetContent(path) } func getXml[T any](path string) T { @@ -93,9 +72,6 @@ var ( 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") diff --git a/common/data/xmlres/json_compat_test.go b/common/data/xmlres/json_compat_test.go new file mode 100644 index 000000000..2c051c17d --- /dev/null +++ b/common/data/xmlres/json_compat_test.go @@ -0,0 +1,26 @@ +package xmlres + +import ( + "encoding/json" + "testing" +) + +func TestMoveUnmarshalJSONAcceptsNumericName(t *testing.T) { + var move Move + if err := json.Unmarshal([]byte(`{"ID":10001,"Name":1,"Category":1,"Type":8,"Power":35,"MaxPP":35,"Accuracy":95}`), &move); err != nil { + t.Fatalf("unmarshal move failed: %v", err) + } + if move.Name != "1" { + t.Fatalf("expected numeric name to convert to string, got %q", move.Name) + } +} + +func TestEffectArgUnmarshalJSONAcceptsNumericSideEffectArg(t *testing.T) { + var cfg EffectArg + if err := json.Unmarshal([]byte(`{"SideEffects":{"SideEffect":[{"ID":1,"SideEffectArgcount":1,"SideEffectArg":3}]}}`), &cfg); err != nil { + t.Fatalf("unmarshal effect arg failed: %v", err) + } + if got := string(cfg.SideEffects.SideEffect[0].SideEffectArg); got != "3" { + t.Fatalf("expected numeric side effect arg to convert to string, got %q", got) + } +} diff --git a/common/data/xmlres/skill.go b/common/data/xmlres/skill.go index f83788d9f..775e4e06f 100644 --- a/common/data/xmlres/skill.go +++ b/common/data/xmlres/skill.go @@ -115,7 +115,7 @@ type Move struct { func (m *Move) UnmarshalJSON(data []byte) error { type moveAlias struct { ID int `json:"ID"` - Name string `json:"Name"` + Name rawFlexibleString `json:"Name"` Category int `json:"Category"` Type int `json:"Type"` Power int `json:"Power"` @@ -150,7 +150,7 @@ func (m *Move) UnmarshalJSON(data []byte) error { *m = Move{ ID: aux.ID, - Name: aux.Name, + Name: string(aux.Name), Category: aux.Category, Type: aux.Type, Power: aux.Power, diff --git a/logic/service/fight/fightc.go b/logic/service/fight/fightc.go index 85d26dc08..01bd3ab7b 100644 --- a/logic/service/fight/fightc.go +++ b/logic/service/fight/fightc.go @@ -184,6 +184,9 @@ func (f *FightC) collectAttackValues(inputs []*input.Input) []model.AttackValue continue } attackValue := *fighter.AttackValue + if attackValue.SkillID == 0 { + continue + } attackValue.ActorIndex = uint32(actorIndex) values = append(values, attackValue) } @@ -462,11 +465,13 @@ func (f *FightC) enterturn(firstAttack, secondAttack *action.SelectSkillAction) // }) return } - f.BroadcastPlayers(func(p common.PlayerI) { - if !f.LegacyGroupProtocol { - f.sendFightPacket(p, fightPacketSkillResult, &attackValueResult) - } - }) + if len(attackValueResult.FirstAttackInfo) > 0 || len(attackValueResult.SecondAttackInfo) > 0 { + f.BroadcastPlayers(func(p common.PlayerI) { + if !f.LegacyGroupProtocol { + f.sendFightPacket(p, fightPacketSkillResult, &attackValueResult) + } + }) + } f.Broadcast(func(fighter *input.Input) { fighter.CanChange = 0 }) diff --git a/logic/service/fight/input.go b/logic/service/fight/input.go index 0a7c81739..88e167564 100644 --- a/logic/service/fight/input.go +++ b/logic/service/fight/input.go @@ -484,13 +484,6 @@ func initfightready(in *input.Input) (model.FightUserInfo, []model.ReadyFightPet if err != nil { panic(err) } - if i == 0 && in.CanCapture > 0 { - if in.CanCapture > 255 { - t[i].IsCapture = 255 - } else { - t[i].IsCapture = uint8(in.CanCapture) - } - } } return userindo, t diff --git a/modules/base/middleware/middleware.go b/modules/base/middleware/middleware.go index 16be447da..f8c4551d9 100644 --- a/modules/base/middleware/middleware.go +++ b/modules/base/middleware/middleware.go @@ -1,211 +1,213 @@ -package middleware - -import ( - "blazing/common/rpc" - "blazing/cool" - "blazing/modules/base/config" - "blazing/modules/config/service" - "encoding/json" - "fmt" - "math/rand" - "net/http" - "net/http/httputil" - "net/url" - "path/filepath" - "strconv" - "time" - - "github.com/gogf/gf/v2/frame/g" - "github.com/gogf/gf/v2/net/ghttp" - "github.com/gogf/gf/v2/os/gtime" - "github.com/gogf/gf/v2/util/gconv" - "github.com/golang-jwt/jwt/v4" - "github.com/google/uuid" - "github.com/lxzan/gws" -) - -const UpStream = "http://43.248.3.21:45632/" - -func MiddlewareCORS(r *ghttp.Request) { - r.Response.CORSDefault() - corsOptions := r.Response.DefaultCORSOptions() - corsOptions.AllowDomain = []string{"*", "localhost", "tauri.localhost"} - if !r.Response.CORSAllowedOrigin(corsOptions) { - r.Response.WriteStatus(http.StatusForbidden) - return - } - r.Response.CORS(corsOptions) - if r.Response.Request.Method == "OPTIONS" { - r.Response.WriteStatus(http.StatusOK) - return - } - // fmt.Println(r.Response.Header()) - //g.Dump(r.Response.Server.SetConfig(gtt)) - //r.Response.Header().Del("Server") // 删除Server头 - // r.Response.Header().Set("Server", "blazing") - r.Middleware.Next() -} -func StartServerProxy() { - s := g.Server() - // Parse the upstream URL - u, _ := url.Parse(UpStream) - // Create a new reverse proxy instance - proxy := httputil.NewSingleHostReverseProxy(u) - // Configure error handling for proxy failures - proxy.ErrorHandler = func(writer http.ResponseWriter, request *http.Request, e error) { - writer.WriteHeader(http.StatusBadGateway) - } - - s.BindHandler("/bbs/api/fof/upload", func(r *ghttp.Request) { - // 1. 调用上传方法(仍返回单个URL字符串,不改动Upload方法) - urlStr, err := cool.File().Upload(r.Context()) - - // 2. 错误处理:返回标准化错误JSON - if err != nil { - r.Response.Header().Set("Content-Type", "application/json; charset=utf-8") - r.Response.WriteHeader(http.StatusBadRequest) - json.NewEncoder(r.Response.Writer).Encode(map[string]interface{}{ - "code": 1, - "msg": err.Error(), - "data": nil, - }) - return - } - - // 3. 基于返回的URL,构造完整的JSON结构体(和示例完全一致) - // 解析URL中的文件名和路径(从urlStr中提取) - baseName := filepath.Base(urlStr) // 提取文件名(如13e8d062-xxx.jpg) - dir := gtime.Now().Format("Y-m-d") // 日期目录(2026-02-07) - path := fmt.Sprintf("%s/%s", dir, baseName) // 拼接path字段 - rand.Seed(time.Now().UnixNano()) - randomID := strconv.Itoa(rand.Intn(1000)) // 模拟ID(如54) - uuidStr := uuid.New().String() // 生成UUID - humanSize := "743kB" // 模拟易读大小(可根据实际需求优化) - fileSize := int64(760783) // 模拟文件大小(字节) - - // 构造和示例完全一致的响应结构体 - fullResponse := map[string]interface{}{ - "data": []map[string]interface{}{ - { - "type": "files", - "id": randomID, - "attributes": map[string]interface{}{ - "baseName": baseName, - "path": path, - "url": urlStr, // 用Upload返回的URL - "type": "image/jpeg", // 模拟MIME类型 - "size": fileSize, - "humanSize": humanSize, - "createdAt": nil, // null - "uuid": uuidStr, - "tag": "just-url", - "hidden": false, - "bbcode": `[img]` + urlStr + `[/img]`, // 和URL一致 - "shared": false, - "canViewInfo": false, - "canHide": true, - "canDelete": true, - }, - }, - }, - } - - // 4. 输出完整JSON响应 - r.Response.Header().Set("Content-Type", "application/json; charset=utf-8") - if err := json.NewEncoder(r.Response.Writer).Encode(fullResponse); err != nil { - // 兜底错误 - fmt.Fprintf(r.Response.Writer, `{"code":1,"msg":"响应生成失败:%s","data":null}`, err.Error()) - } - }) - // Handle all requests with path prefix "/proxy/*" - s.BindHandler("/bbs/*url", func(r *ghttp.Request) { - var ( - //originalPath = r.Request.URL.Path - proxyToPath = "/" + r.Get("url").String() - ) - // Rewrite the request path - r.Request.URL.Path = proxyToPath - // Log the proxy operation - //g.Log().Infof(r.Context(), `proxy:"%s" -> backend:"%s"`, originalPath, proxyToPath) - // Ensure request body can be read multiple times if needed - r.MakeBodyRepeatableRead(false) - // Forward the request to the backend server - proxy.ServeHTTP(r.Response.Writer, r.Request) - }) - -} - -func init() { - if config.Config.Middleware.Authority.Enable { - g.Server().BindMiddleware("/admin/*/open/*", BaseAuthorityMiddlewareOpen) - g.Server().BindMiddleware("/rpc/*", BaseAuthorityMiddlewareOpen) - g.Server().BindMiddleware("/admin/*/comm/*", BaseAuthorityMiddlewareComm) - g.Server().BindMiddleware("/admin/*", BaseAuthorityMiddleware) - // g.Server().BindMiddleware("/*", AutoI18n) - g.Server().BindMiddleware("/*", MiddlewareCORS) - - } - if config.Config.Middleware.Log.Enable { - g.Server().BindMiddleware("/admin/*", BaseLog) - } - StartServerProxy() - tt := rpc.CServer() - - g.Server().BindHandler("/rpc/*", func(r *ghttp.Request) { - - tt.ServeHTTP(r.Response.Writer, r.Request) - - }) - g.Server().Use(CompressMiddleware) - g.Server().BindHandler("/server/*", func(r *ghttp.Request) { - servert := new(ServerHandler) - id := gconv.Uint16(r.URL.Query().Get("id")) - servert.isinstall = gconv.Uint32(r.URL.Query().Get("isinstall")) - servert.ServerList = service.NewServerService().StartUPdate(id, int(servert.isinstall)) - - upgrader := gws.NewUpgrader(servert, &gws.ServerOption{ - - Authorize: func(_ *http.Request, _ gws.SessionStorage) bool { - - tokenString := r.URL.Query().Get("Authorization") - token, err := jwt.ParseWithClaims(tokenString, &cool.Claims{}, func(_ *jwt.Token) (interface{}, error) { - - return []byte(config.Config.Jwt.Secret), nil - }) - if err != nil { - return false - } - if !token.Valid { - return false - } - admin := token.Claims.(*cool.Claims) - if admin.UserId != 10001 { - return false - } - - // var name = r.URL.Query().Get("name") - // if name == "" { - // return false - // } - // t, _ := service.NewBaseSysUserService().Person(admin.UserID) - - //Loger.Debug(context.TODO(), t.Mimi) - // session.Store("name", t.Mimi) - //session.Store("key", r.Header.Get("Sec-WebSocket-Key")) - return true - }, - }) - - socket, err := upgrader.Upgrade(r.Response.Writer, r.Request) - if err != nil { - fmt.Println(err) - return - } - // ants.Submit(func() { - // socket.ReadLoop() - // }) - // ants.Submit(func() { socket.ReadLoop() }) - go socket.ReadLoop() - - }) -} +package middleware + +import ( + "blazing/common/rpc" + "blazing/cool" + "blazing/modules/base/config" + "blazing/modules/config/service" + "encoding/json" + "fmt" + "math/rand" + "net/http" + "net/http/httputil" + "net/url" + "path/filepath" + "strconv" + "time" + + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/util/gconv" + "github.com/golang-jwt/jwt/v4" + "github.com/google/uuid" + "github.com/lxzan/gws" +) + +const UpStream = "http://43.248.3.21:45632/" + +func MiddlewareCORS(r *ghttp.Request) { + r.Response.CORSDefault() + corsOptions := r.Response.DefaultCORSOptions() + corsOptions.AllowDomain = []string{"*", "localhost", "tauri.localhost"} + if !r.Response.CORSAllowedOrigin(corsOptions) { + r.Response.WriteStatus(http.StatusForbidden) + return + } + r.Response.CORS(corsOptions) + if r.Response.Request.Method == "OPTIONS" { + r.Response.WriteStatus(http.StatusOK) + return + } + // fmt.Println(r.Response.Header()) + //g.Dump(r.Response.Server.SetConfig(gtt)) + //r.Response.Header().Del("Server") // 删除Server头 + // r.Response.Header().Set("Server", "blazing") + r.Middleware.Next() +} +func StartServerProxy() { + s := g.Server() + // Parse the upstream URL + u, _ := url.Parse(UpStream) + // Create a new reverse proxy instance + proxy := httputil.NewSingleHostReverseProxy(u) + // Configure error handling for proxy failures + proxy.ErrorHandler = func(writer http.ResponseWriter, request *http.Request, e error) { + writer.WriteHeader(http.StatusBadGateway) + } + + s.BindHandler("/bbs/api/fof/upload", func(r *ghttp.Request) { + // 1. 调用上传方法(仍返回单个URL字符串,不改动Upload方法) + urlStr, err := cool.File().Upload(r.Context()) + + // 2. 错误处理:返回标准化错误JSON + if err != nil { + r.Response.Header().Set("Content-Type", "application/json; charset=utf-8") + r.Response.WriteHeader(http.StatusBadRequest) + json.NewEncoder(r.Response.Writer).Encode(map[string]interface{}{ + "code": 1, + "msg": err.Error(), + "data": nil, + }) + return + } + + // 3. 基于返回的URL,构造完整的JSON结构体(和示例完全一致) + // 解析URL中的文件名和路径(从urlStr中提取) + baseName := filepath.Base(urlStr) // 提取文件名(如13e8d062-xxx.jpg) + dir := gtime.Now().Format("Y-m-d") // 日期目录(2026-02-07) + path := fmt.Sprintf("%s/%s", dir, baseName) // 拼接path字段 + rand.Seed(time.Now().UnixNano()) + randomID := strconv.Itoa(rand.Intn(1000)) // 模拟ID(如54) + uuidStr := uuid.New().String() // 生成UUID + humanSize := "743kB" // 模拟易读大小(可根据实际需求优化) + fileSize := int64(760783) // 模拟文件大小(字节) + + // 构造和示例完全一致的响应结构体 + fullResponse := map[string]interface{}{ + "data": []map[string]interface{}{ + { + "type": "files", + "id": randomID, + "attributes": map[string]interface{}{ + "baseName": baseName, + "path": path, + "url": urlStr, // 用Upload返回的URL + "type": "image/jpeg", // 模拟MIME类型 + "size": fileSize, + "humanSize": humanSize, + "createdAt": nil, // null + "uuid": uuidStr, + "tag": "just-url", + "hidden": false, + "bbcode": `[img]` + urlStr + `[/img]`, // 和URL一致 + "shared": false, + "canViewInfo": false, + "canHide": true, + "canDelete": true, + }, + }, + }, + } + + // 4. 输出完整JSON响应 + r.Response.Header().Set("Content-Type", "application/json; charset=utf-8") + if err := json.NewEncoder(r.Response.Writer).Encode(fullResponse); err != nil { + // 兜底错误 + fmt.Fprintf(r.Response.Writer, `{"code":1,"msg":"响应生成失败:%s","data":null}`, err.Error()) + } + }) + // Handle all requests with path prefix "/proxy/*" + s.BindHandler("/bbs/*url", func(r *ghttp.Request) { + var ( + //originalPath = r.Request.URL.Path + proxyToPath = "/" + r.Get("url").String() + ) + // Rewrite the request path + r.Request.URL.Path = proxyToPath + // Log the proxy operation + //g.Log().Infof(r.Context(), `proxy:"%s" -> backend:"%s"`, originalPath, proxyToPath) + // Ensure request body can be read multiple times if needed + r.MakeBodyRepeatableRead(false) + // Forward the request to the backend server + proxy.ServeHTTP(r.Response.Writer, r.Request) + }) + +} + +func init() { + if config.Config.Middleware.Authority.Enable { + g.Server().BindMiddleware("/admin/*/open/*", BaseAuthorityMiddlewareOpen) + g.Server().BindMiddleware("/rpc/*", BaseAuthorityMiddlewareOpen) + g.Server().BindMiddleware("/admin/*/comm/*", BaseAuthorityMiddlewareComm) + g.Server().BindMiddleware("/seer/game/cdk/*", BaseAuthorityMiddlewareComm) + g.Server().BindMiddleware("/seer/game/cdk/*", BaseAuthorityMiddleware) + g.Server().BindMiddleware("/admin/*", BaseAuthorityMiddleware) + // g.Server().BindMiddleware("/*", AutoI18n) + g.Server().BindMiddleware("/*", MiddlewareCORS) + + } + if config.Config.Middleware.Log.Enable { + g.Server().BindMiddleware("/admin/*", BaseLog) + } + StartServerProxy() + tt := rpc.CServer() + + g.Server().BindHandler("/rpc/*", func(r *ghttp.Request) { + + tt.ServeHTTP(r.Response.Writer, r.Request) + + }) + g.Server().Use(CompressMiddleware) + g.Server().BindHandler("/server/*", func(r *ghttp.Request) { + servert := new(ServerHandler) + id := gconv.Uint16(r.URL.Query().Get("id")) + servert.isinstall = gconv.Uint32(r.URL.Query().Get("isinstall")) + servert.ServerList = service.NewServerService().StartUPdate(id, int(servert.isinstall)) + + upgrader := gws.NewUpgrader(servert, &gws.ServerOption{ + + Authorize: func(_ *http.Request, _ gws.SessionStorage) bool { + + tokenString := r.URL.Query().Get("Authorization") + token, err := jwt.ParseWithClaims(tokenString, &cool.Claims{}, func(_ *jwt.Token) (interface{}, error) { + + return []byte(config.Config.Jwt.Secret), nil + }) + if err != nil { + return false + } + if !token.Valid { + return false + } + admin := token.Claims.(*cool.Claims) + if admin.UserId != 10001 { + return false + } + + // var name = r.URL.Query().Get("name") + // if name == "" { + // return false + // } + // t, _ := service.NewBaseSysUserService().Person(admin.UserID) + + //Loger.Debug(context.TODO(), t.Mimi) + // session.Store("name", t.Mimi) + //session.Store("key", r.Header.Get("Sec-WebSocket-Key")) + return true + }, + }) + + socket, err := upgrader.Upgrade(r.Response.Writer, r.Request) + if err != nil { + fmt.Println(err) + return + } + // ants.Submit(func() { + // socket.ReadLoop() + // }) + // ants.Submit(func() { socket.ReadLoop() }) + go socket.ReadLoop() + + }) +} diff --git a/modules/player/model/pvp.go b/modules/player/model/pvp.go index 5e75a30ed..78250cfba 100644 --- a/modules/player/model/pvp.go +++ b/modules/player/model/pvp.go @@ -119,7 +119,6 @@ type ReadyFightPetInfo struct { SkinID uint32 `fieldDesc:"精灵皮肤ID" ` ShinyLen uint32 `json:"-" struc:"sizeof=ShinyInfo"` ShinyInfo []data.GlowFilter `json:"ShinyInfo,omitempty"` - IsCapture uint8 `struc:"uint8" json:"isCapture"` } type FightOverInfo struct { //0 正常结束