From 8e3ed21a3a9d1b3e2d5928082fbb007647fb86d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <12574910+72wo@users.noreply.github.com> Date: Fri, 20 Feb 2026 23:33:24 +0800 Subject: [PATCH] 1 --- common/socket/ServerEvent.go | 2 +- logic/controller/action_扭蛋.go | 4 +- logic/controller/fight_boss野怪和地图怪.go | 10 +---- logic/main.go | 46 ++++++++++++++----- logic/service/player/Monster.go | 12 +++-- logic/service/player/wscodec.go | 2 +- modules/config/service/map.go | 2 +- modules/config/service/shiny.go | 3 ++ modules/player/service/info.go | 52 ++++++++++++++++++++++ 9 files changed, 105 insertions(+), 28 deletions(-) diff --git a/common/socket/ServerEvent.go b/common/socket/ServerEvent.go index 71f2beef6..e5e5cbb1b 100644 --- a/common/socket/ServerEvent.go +++ b/common/socket/ServerEvent.go @@ -251,7 +251,7 @@ func handle(c gnet.Conn) { } if string(data) == TEXT { //判断是否是跨域请求 - log.Printf("Received cross-domain request from %s", c.RemoteAddr()) + //log.Printf("Received cross-domain request from %s", c.RemoteAddr()) // 处理跨域请求 c.Write([]byte(CROSS_DOMAIN)) c.Discard(len(TEXT)) diff --git a/logic/controller/action_扭蛋.go b/logic/controller/action_扭蛋.go index 191f5987d..0bab37721 100644 --- a/logic/controller/action_扭蛋.go +++ b/logic/controller/action_扭蛋.go @@ -35,9 +35,7 @@ func (h Controller) EggGamePlay(data1 *egg.C2S_EGG_GAME_PLAY, c *player.Player) if grand.Meet(int(data1.EggNum), 100) { r := service.NewPetRewardService().GetEgg() newPet := model.GenPetInfo(int(r.MonID), int(r.DV), int(r.Nature), int(r.Effect), int(r.Lv), nil, 0) - if grand.Meet(int(data1.EggNum), 100) { - newPet.RandShiny() - } + newPet.RandShiny() c.Service.Pet.PetAdd(newPet) result.HadTime = newPet.CatchTime diff --git a/logic/controller/fight_boss野怪和地图怪.go b/logic/controller/fight_boss野怪和地图怪.go index bb08bdb69..74f01f528 100644 --- a/logic/controller/fight_boss野怪和地图怪.go +++ b/logic/controller/fight_boss野怪和地图怪.go @@ -117,11 +117,7 @@ func (Controller) PlayerFightBoss(data *fight.ChallengeBossInboundInfo, p *playe if bc.BossCatchable == 1 { canCapture = xmlres.PetMAP[int(monster.ID)].CatchRate - if grand.Meet(1, 100) { - r := monsterInfo.PetList[0] - r.RandShiny() - monsterInfo.PetList[0] = r - } + monsterInfo.PetList[0].RandShiny() } monsterInfo.Nick = bc.Name //xmlres.PetMAP[int(monster.ID)].DefName @@ -182,9 +178,7 @@ func (Controller) OnPlayerFightNpcMonster(data1 *fight.FightNpcMonsterInboundInf refPet.ShinyInfo, -1) monster.CatchMap = p.Info.MapID //设置当前地图 if refPet.Ext != 0 { - if grand.Meet(2, 1000) { - monster.RandShiny() - } + monster.RandShiny() } monsterInfo := &model.PlayerInfo{} diff --git a/logic/main.go b/logic/main.go index 947a583c3..3e5fadc69 100644 --- a/logic/main.go +++ b/logic/main.go @@ -5,6 +5,7 @@ import ( "log" "os" "runtime" + "strconv" "strings" "time" @@ -25,15 +26,37 @@ import ( ) // PprofWeb 启动pprof性能分析web服务 +// PprofWeb 启动pprof web服务,仅重试2个端口保证监听成功 func PprofWeb() { - runtime.SetMutexProfileFraction(1) // (非必需)开启对锁调用的跟踪 - runtime.SetBlockProfileRate(1) // (非必需)开启对阻塞操作的跟踪 - err := http.ListenAndServe(":9909", nil) - if err != nil { - panic(err) - } -} + // 开启pprof跟踪 + runtime.SetMutexProfileFraction(1) + runtime.SetBlockProfileRate(1) + // 定义2个重试端口:主端口9909 + 备用端口9910 + ports := []int{9909, 9910} + + // 遍历端口尝试监听 + for _, port := range ports { + addr := ":" + strconv.Itoa(port) + fmt.Printf("[INFO] 尝试启动pprof服务,监听端口: %d\n", port) + + // 尝试监听并处理错误 + err := http.ListenAndServe(addr, nil) + // 只有端口被占用等致命错误才重试下一个端口 + if err != nil { + fmt.Printf("[WARN] 端口%d监听失败: %v\n", port, err) + continue + } + // 监听成功则直接返回 + return + } + + // 所有端口都失败时的兜底 + errMsg := fmt.Sprintf("[FATAL] 端口9909/9910均监听失败,pprof服务启动失败") + fmt.Println(errMsg) + // 可选:根据业务需求决定是否panic + // panic(errMsg) +} func cleanup() { fmt.Println("执行优雅清理资源...") @@ -75,10 +98,11 @@ func main() { // } // 解析命令行参数 cool.Config.GameOnlineID = gcmd.GetOpt("id", "1").Uint16() - go Start() //注入service - if cool.Config.GameOnlineID == 2 { //只分析1服务器的 - go PprofWeb() - } + go Start() //注入service + // if cool.Config.GameOnlineID == 2 { //只分析1服务器的 + // go PprofWeb() + // } + go PprofWeb() //go PprofWeb() go monitorMemAndQuit() fmt.Println("Process start, pid:", os.Getpid()) diff --git a/logic/service/player/Monster.go b/logic/service/player/Monster.go index ca744e19c..fd4e536f0 100644 --- a/logic/service/player/Monster.go +++ b/logic/service/player/Monster.go @@ -3,6 +3,7 @@ package player import ( "blazing/common/data/xmlres" "blazing/cool" + "blazing/modules/config/service" "strings" "sync/atomic" "time" @@ -25,6 +26,11 @@ func (p *Player) GenMonster() { if atomic.LoadUint32(&p.Canmon) == 0 { //已经进入地图或者没在战斗中,就可以刷新怪 return } + + mapinfo := service.NewMapService().GetData(p.Info.MapID) + if mapinfo == nil { + return + } var oldnum, newNum int var replce []int p.monsters, oldnum, newNum = replaceOneNumber(p.monsters) @@ -40,7 +46,7 @@ func (p *Player) GenMonster() { mapss, ok := xmlres.MonsterMap[gconv.Int(p.Info.MapID)] if ok && mapss.Monsters != nil { - ok, _, _ := p.PlayerCaptureContext.Roll(mapss.Monsters.WildBonusProb, mapss.Monsters.WildBonusTotalProb) + ok := grand.Meet(3, 10) for i, m := range mapss.Monsters.Monsters { //这里是9个 _, rok := lo.Find(replce, func(it int) bool { @@ -77,12 +83,12 @@ func (p *Player) GenMonster() { if cool.Config.ServerInfo.IsVip != 0 { //测试服,百分百异色 p.OgreInfo.Data[i].RandomByWeightShiny() } - if xmlres.PetMAP[int(p.OgreInfo.Data[i].ID)].CatchRate != 0 && grand.Meet(1, 500) { + if xmlres.PetMAP[int(p.OgreInfo.Data[i].ID)].CatchRate != 0 { p.OgreInfo.Data[i].RandSHiny() } if ok { - p.OgreInfo.Data[i].Item = int64(mapss.Monsters.ItemBonusID) + p.OgreInfo.Data[i].Item = int64(mapinfo.DropItemIds[grand.Intn(len(mapinfo.DropItemIds))]) } } diff --git a/logic/service/player/wscodec.go b/logic/service/player/wscodec.go index e8c4e421c..5f83b2165 100644 --- a/logic/service/player/wscodec.go +++ b/logic/service/player/wscodec.go @@ -65,7 +65,7 @@ func (w *WsCodec) Upgrade(c gnet.Conn) (ok bool, action gnet.Action) { } tmpReader := bytes.NewReader(buf.Bytes()) oldLen := tmpReader.Len() - logging.Infof("do Upgrade") + //logging.Infof("do Upgrade") hs, err := ws.Upgrade(readWrite{tmpReader, c}) skipN := oldLen - tmpReader.Len() diff --git a/modules/config/service/map.go b/modules/config/service/map.go index 6ded5cf1d..31b39c486 100644 --- a/modules/config/service/map.go +++ b/modules/config/service/map.go @@ -24,7 +24,7 @@ func (s *MapService) GetData(p1 uint32) (ret *model.MapConfig) { //cacheKey := strings.Join([]string{fmt.Sprintf("%d", p1), fmt.Sprintf("%d", p2)}, ":") m := dbm_notenable(s.Model) - m.Wheref(`male_pet_ids @> ARRAY[?]::integer[]`, p1).Scan(&ret) + m.Where(`map_id`, p1).Scan(&ret) return diff --git a/modules/config/service/shiny.go b/modules/config/service/shiny.go index 75d7b7dda..f70b3f816 100644 --- a/modules/config/service/shiny.go +++ b/modules/config/service/shiny.go @@ -44,6 +44,9 @@ func (s *ShinyService) ModifyBefore(ctx context.Context, method string, param g. return nil } func (s *ShinyService) RandShiny(id uint32) *model.ColorfulSkin { + if !grand.Meet(1, 500) { + return nil + } var ret []model.ColorfulSkin // 执行 Raw SQL 并扫描返回值 diff --git a/modules/player/service/info.go b/modules/player/service/info.go index 0ae7cf120..a2f141cc8 100644 --- a/modules/player/service/info.go +++ b/modules/player/service/info.go @@ -7,7 +7,10 @@ import ( "blazing/modules/player/model" "context" "encoding/hex" + "encoding/json" "fmt" + "os" + "path/filepath" "time" @@ -175,6 +178,54 @@ func (s *InfoService) Kick(id uint32) error { } return nil } + +// saveToLocalFile 兜底保存:将数据写入本地lose文件夹 +func (s *InfoService) saveToLocalFile(player *model.Player, err error) { + // 1. 创建lose文件夹(如果不存在) + loseDir := "./lose" + if err := os.MkdirAll(loseDir, 0755); err != nil { + fmt.Printf("[ERROR] 创建lose文件夹失败: %v\n", err) + return + } + + // 2. 构造保存的数据结构,包含错误信息和时间戳 + type FallbackData struct { + PlayerData *model.Player `json:"player_data"` + ErrorMsg string `json:"error_msg"` + SaveTime string `json:"save_time"` + ServerInfo string `json:"server_info"` + } + + fallbackData := FallbackData{ + PlayerData: player, + ErrorMsg: err.Error(), + SaveTime: time.Now().Format("20060102150405.000"), // 精确到毫秒的时间戳 + ServerInfo: fmt.Sprintf("server_vip:%d", cool.Config.ServerInfo.IsVip), + } + + // 3. 生成唯一的文件名(避免覆盖) + playerID := fmt.Sprintf("%d", player.PlayerID) // 假设Player有PlayerID字段,根据实际调整 + filename := fmt.Sprintf("player_%s_%s.json", playerID, fallbackData.SaveTime) + filePath := filepath.Join(loseDir, filename) + + // 4. 将数据序列化为JSON并写入文件 + file, err := os.Create(filePath) + if err != nil { + fmt.Printf("[ERROR] 创建兜底文件失败 %s: %v\n", filePath, err) + return + } + defer file.Close() + + encoder := json.NewEncoder(file) + encoder.SetIndent("", " ") // 格式化JSON,方便查看 + if err := encoder.Encode(fallbackData); err != nil { + fmt.Printf("[ERROR] 写入兜底文件失败 %s: %v\n", filePath, err) + return + } + + // 5. 记录日志,方便排查 + fmt.Printf("[INFO] 数据库保存失败,已将玩家[%s]数据兜底保存到: %s\n", playerID, filePath) +} func (s *InfoService) Save(data model.PlayerInfo) { if cool.Config.ServerInfo.IsVip != 0 { @@ -190,6 +241,7 @@ func (s *InfoService) Save(data model.PlayerInfo) { _, err := m.Save(tt) if err != nil { //todo 待实现兜底保存,现在有可能出错 + s.saveToLocalFile(tt, err) panic(err) }