diff --git a/IMPROVEMENTS.md b/IMPROVEMENTS.md index 35dde60ad..cf8b4b0e4 100644 --- a/IMPROVEMENTS.md +++ b/IMPROVEMENTS.md @@ -4,26 +4,36 @@ This document outlines prioritized improvements identified through codebase anal --- +## Progress Summary + +| Area | Status | +|------|--------| +| Tier 1: Critical Stability Fixes | ✅ Complete (7/7) | +| Tier 2: Security Updates | Pending | +| Tier 3: Important Bug Fixes | Partial (3/6) | +| Tier 4: Version Compatibility | Partial (3/7) | +| Tier 5: Warehouse & Save System | Pending | +| Test Coverage (channelserver) | 25% (was 7.5%) | +| CI: gofmt + golangci-lint | ✅ Added | +| Panic Cleanup | ✅ Complete (51 removed, 3 remain in tests/lib) | + +--- + ## Cherry-Pick from Main Branch The `main` branch is 589 commits ahead of `9.2.0-clean` but is unstable for players. The following commits should be cherry-picked (and fixed if necessary) for 9.3.0. -### Tier 1: Critical Stability Fixes (Cherry-pick immediately) +### Tier 1: Critical Stability Fixes ✅ COMPLETE -| Commit | Description | Files Changed | Risk | -|--------|-------------|---------------|------| -| `e1a461e` | fix(stage): fix deadlock preventing stage change | handlers_stage.go, sys_session.go | Low | -| `060635e` | fix(stage): fix race condition with stages | handlers_stage.go | Low | -| `1c32be9` | fix(session): race condition | sys_session.go | Low | -| `73e874f` | fix: array bound crashes on clans | Multiple | Low | -| `5028355` | prevent nil pointer in MhfGetGuildManageRight | handlers_guild.go | Low | -| `ba1eea8` | prevent save error crashes | handlers.go, handlers_character.go | Low | -| `60e86c7` | mitigate LoadDecoMyset crashing on older versions | handlers | Low | - -**Command:** -```bash -git cherry-pick e1a461e 060635e 1c32be9 73e874f 5028355 ba1eea8 60e86c7 -``` +| Commit | Description | Applied As | Status | +|--------|-------------|------------|--------| +| `e1a461e` | fix(stage): fix deadlock preventing stage change | 488e8fa | ✅ Done | +| `060635e` | fix(stage): fix race condition with stages | e654bc4 | ✅ Done | +| `1c32be9` | fix(session): race condition | 80c3634 | ✅ Done | +| `73e874f` | fix: array bound crashes on clans | 4201862 | ✅ Done | +| `5028355` | prevent nil pointer in MhfGetGuildManageRight | 94175e6 | ✅ Done | +| `ba1eea8` | prevent save error crashes | 633061c | ✅ Done | +| `60e86c7` | mitigate LoadDecoMyset crashing on older versions | 813cf16 | ✅ Done | ### Tier 2: Security Updates (Cherry-pick after Tier 1) @@ -38,25 +48,26 @@ git cherry-pick e1a461e 060635e 1c32be9 73e874f 5028355 ba1eea8 60e86c7 ### Tier 3: Important Bug Fixes (Review before cherry-pick) -| Commit | Description | Files | Notes | -|--------|-------------|-------|-------| -| `d1dfc3f` | packet queue fix proposal | 6 files | Review carefully - touches core networking | -| `76858bb` | bypass full Stage check if reserve slot | handlers_stage.go | Simple fix | -| `c539905` | implement SysWaitStageBinary timeout | handlers_stage.go | Simple fix | -| `7459ded` | fix guild poogie outfit unlock | handlers | Simple fix | -| `8a55c5f` | fix inflated festa rewards | handlers | Review impact | -| `7d760bd` | fix EntranceServer clan member list limits | entranceserver | Simple fix | +| Commit | Description | Files | Status | +|--------|-------------|-------|--------| +| `d1dfc3f` | packet queue fix proposal | 6 files | Pending - Review carefully | +| `76858bb` | bypass full Stage check if reserve slot | handlers_stage.go | Pending | +| `c539905` | implement SysWaitStageBinary timeout | handlers_stage.go | ✅ Done (a66b15d) | +| `7459ded` | fix guild poogie outfit unlock | handlers | ✅ Done (355c2c0) | +| `8a55c5f` | fix inflated festa rewards | handlers | Pending | +| `7d760bd` | fix EntranceServer clan member list limits | entranceserver | ✅ Done (fb14a78) | ### Tier 4: Version Compatibility Fixes -| Commit | Description | Versions Affected | -|--------|-------------|-------------------| -| `8d1c6a7` | S6 compatibility fix | Season 6.0 | -| `d26ae45` | fix G1 compatibility | G1 | -| `3d0114c` | fix MhfAcquireCafeItem cost in G1-G5.2 | G1-G5.2 | -| `8c219be` | fix InfoGuild response on 0 { @@ -1418,28 +1414,31 @@ func handleMsgMhfEnumerateGuildMember(s *Session, p mhfpacket.MHFPacket) { if guild.ID != alliance.ParentGuildID { mems, err := GetGuildMembers(s, alliance.ParentGuildID, false) if err != nil { - panic(err) - } - for _, m := range mems { - bf.WriteUint32(m.CharID) + s.logger.Error("failed to get parent guild members", zap.Error(err), zap.Uint32("guildID", alliance.ParentGuildID)) + } else { + for _, m := range mems { + bf.WriteUint32(m.CharID) + } } } if guild.ID != alliance.SubGuild1ID { mems, err := GetGuildMembers(s, alliance.SubGuild1ID, false) if err != nil { - panic(err) - } - for _, m := range mems { - bf.WriteUint32(m.CharID) + s.logger.Error("failed to get sub guild 1 members", zap.Error(err), zap.Uint32("guildID", alliance.SubGuild1ID)) + } else { + for _, m := range mems { + bf.WriteUint32(m.CharID) + } } } if guild.ID != alliance.SubGuild2ID { mems, err := GetGuildMembers(s, alliance.SubGuild2ID, false) if err != nil { - panic(err) - } - for _, m := range mems { - bf.WriteUint32(m.CharID) + s.logger.Error("failed to get sub guild 2 members", zap.Error(err), zap.Uint32("guildID", alliance.SubGuild2ID)) + } else { + for _, m := range mems { + bf.WriteUint32(m.CharID) + } } } } else { @@ -1627,13 +1626,17 @@ func handleMsgMhfUpdateGuildIcon(s *Session, p mhfpacket.MHFPacket) { guild, err := GetGuildInfoByID(s, pkt.GuildID) if err != nil { - panic(err) + s.logger.Error("failed to get guild info for icon update", zap.Error(err), zap.Uint32("guildID", pkt.GuildID)) + doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + return } characterInfo, err := GetCharacterGuildData(s, s.charID) if err != nil { - panic(err) + s.logger.Error("failed to get character guild data for icon update", zap.Error(err), zap.Uint32("charID", s.charID)) + doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + return } if !characterInfo.IsSubLeader() && !characterInfo.IsLeader { @@ -1699,7 +1702,9 @@ func handleMsgMhfGetGuildMissionList(s *Session, p mhfpacket.MHFPacket) { decoded, err := hex.DecodeString("000694610000023E000112990023000100000200015DDD232100069462000002F30000005F000C000200000300025DDD232100069463000002EA0000005F0006000100000100015DDD23210006946400000245000000530010000200000400025DDD232100069465000002B60001129B0019000100000200015DDD232100069466000003DC0000001B0010000100000600015DDD232100069467000002DA000112A00019000100000400015DDD232100069468000002A800010DEF0032000200000200025DDD2321000694690000045500000022003C000200000600025DDD23210006946A00000080000122D90046000200000300025DDD23210006946B000001960000003B000A000100000100015DDD23210006946C0000049200000046005A000300000600035DDD23210006946D000000A4000000260018000200000600025DDD23210006946E0000017A00010DE40096000300000100035DDD23210006946F000001BE0000005E0014000200000400025DDD2355000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") if err != nil { - panic(err) + s.logger.Error("failed to decode guild mission list hex data", zap.Error(err)) + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) + return } doAckBufSucceed(s, pkt.AckHandle, decoded) diff --git a/server/channelserver/handlers_guild_alliance.go b/server/channelserver/handlers_guild_alliance.go index fbb285e0a..bf7dc0fb4 100644 --- a/server/channelserver/handlers_guild_alliance.go +++ b/server/channelserver/handlers_guild_alliance.go @@ -181,8 +181,8 @@ func handleMsgMhfOperateJoint(s *Session, p mhfpacket.MHFPacket) { doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) } default: + s.logger.Warn("unhandled operate joint action", zap.Uint8("action", uint8(pkt.Action))) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) - panic(fmt.Sprintf("Unhandled operate joint action '%d'", pkt.Action)) } } diff --git a/server/channelserver/handlers_guild_scout.go b/server/channelserver/handlers_guild_scout.go index fceeb037d..d8bbe1ef8 100644 --- a/server/channelserver/handlers_guild_scout.go +++ b/server/channelserver/handlers_guild_scout.go @@ -15,8 +15,9 @@ func handleMsgMhfPostGuildScout(s *Session, p mhfpacket.MHFPacket) { actorCharGuildData, err := GetCharacterGuildData(s, s.charID) if err != nil { + s.logger.Error("failed to get character guild data", zap.Error(err), zap.Uint32("charID", s.charID)) doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) - panic(err) + return } if actorCharGuildData == nil || !actorCharGuildData.CanRecruit() { @@ -27,15 +28,17 @@ func handleMsgMhfPostGuildScout(s *Session, p mhfpacket.MHFPacket) { guildInfo, err := GetGuildInfoByID(s, actorCharGuildData.GuildID) if err != nil { + s.logger.Error("failed to get guild info", zap.Error(err), zap.Uint32("guildID", actorCharGuildData.GuildID)) doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) - panic(err) + return } hasApplication, err := guildInfo.HasApplicationForCharID(s, pkt.CharID) if err != nil { + s.logger.Error("failed to check application status", zap.Error(err), zap.Uint32("charID", pkt.CharID)) doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) - panic(err) + return } if hasApplication { @@ -46,15 +49,18 @@ func handleMsgMhfPostGuildScout(s *Session, p mhfpacket.MHFPacket) { transaction, err := s.server.db.Begin() if err != nil { - panic(err) + s.logger.Error("failed to begin transaction", zap.Error(err)) + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + return } err = guildInfo.CreateApplication(s, pkt.CharID, GuildApplicationTypeInvited, transaction) if err != nil { + s.logger.Error("failed to create guild application", zap.Error(err), zap.Uint32("charID", pkt.CharID)) rollbackTransaction(s, transaction) doAckBufFail(s, pkt.AckHandle, nil) - panic(err) + return } mail := &Mail{ @@ -79,8 +85,9 @@ func handleMsgMhfPostGuildScout(s *Session, p mhfpacket.MHFPacket) { err = transaction.Commit() if err != nil { + s.logger.Error("failed to commit transaction", zap.Error(err)) doAckBufFail(s, pkt.AckHandle, nil) - panic(err) + return } doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) @@ -92,7 +99,9 @@ func handleMsgMhfCancelGuildScout(s *Session, p mhfpacket.MHFPacket) { guildCharData, err := GetCharacterGuildData(s, s.charID) if err != nil { - panic(err) + s.logger.Error("failed to get character guild data", zap.Error(err), zap.Uint32("charID", s.charID)) + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + return } if guildCharData == nil || !guildCharData.CanRecruit() { @@ -123,7 +132,11 @@ func handleMsgMhfAnswerGuildScout(s *Session, p mhfpacket.MHFPacket) { guild, err := GetGuildInfoByCharacterId(s, pkt.LeaderID) if err != nil { - panic(err) + s.logger.Error("failed to get guild info by character", zap.Error(err), zap.Uint32("leaderID", pkt.LeaderID)) + bf.WriteUint32(7) // Error code + bf.WriteUint32(0) + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + return } app, err := guild.GetApplicationForCharID(s, s.charID, GuildApplicationTypeInvited) @@ -255,7 +268,9 @@ func handleMsgMhfGetGuildScoutList(s *Session, p mhfpacket.MHFPacket) { _, err = bf.Seek(0, io.SeekStart) if err != nil { - panic(err) + s.logger.Error("failed to seek in byte frame", zap.Error(err)) + doAckBufFail(s, pkt.AckHandle, nil) + return } bf.WriteUint32(count) diff --git a/server/channelserver/handlers_guild_tresure.go b/server/channelserver/handlers_guild_tresure.go index 3d0918a84..4cd12217d 100644 --- a/server/channelserver/handlers_guild_tresure.go +++ b/server/channelserver/handlers_guild_tresure.go @@ -4,6 +4,7 @@ import ( "erupe-ce/common/byteframe" "erupe-ce/common/stringsupport" "erupe-ce/network/mhfpacket" + "go.uber.org/zap" ) type TreasureHunt struct { @@ -23,7 +24,9 @@ func handleMsgMhfEnumerateGuildTresure(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateGuildTresure) guild, err := GetGuildInfoByCharacterId(s, s.charID) if err != nil { - panic(err) + s.logger.Error("failed to get guild info", zap.Error(err), zap.Uint32("charID", s.charID)) + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) + return } bf := byteframe.NewByteFrame() hunts := 0 @@ -34,7 +37,8 @@ func handleMsgMhfEnumerateGuildTresure(s *Session, p mhfpacket.MHFPacket) { // Remove self from other hunter count hunt.Hunters = stringsupport.CSVRemove(hunt.Hunters, int(s.charID)) if err != nil { - panic(err) + s.logger.Error("failed to scan treasure hunt row", zap.Error(err)) + continue } if pkt.MaxHunts == 1 { if hunt.HostID != s.charID || hunt.Acquired { @@ -78,7 +82,9 @@ func handleMsgMhfRegistGuildTresure(s *Session, p mhfpacket.MHFPacket) { huntData := byteframe.NewByteFrame() guild, err := GetGuildInfoByCharacterId(s, s.charID) if err != nil { - panic(err) + s.logger.Error("failed to get guild info for treasure registration", zap.Error(err), zap.Uint32("charID", s.charID)) + doAckSimpleFail(s, pkt.AckHandle, nil) + return } guildCats := getGuildAirouList(s) destination := bf.ReadUint32() @@ -103,7 +109,9 @@ func handleMsgMhfRegistGuildTresure(s *Session, p mhfpacket.MHFPacket) { _, err = s.server.db.Exec("INSERT INTO guild_hunts (guild_id, host_id, destination, level, return, hunt_data, cats_used) VALUES ($1, $2, $3, $4, $5, $6, $7)", guild.ID, s.charID, destination, level, TimeAdjusted().Unix(), huntData.Data(), catsUsed) if err != nil { - panic(err) + s.logger.Error("failed to insert guild hunt", zap.Error(err), zap.Uint32("guildID", guild.ID)) + doAckSimpleFail(s, pkt.AckHandle, nil) + return } doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } @@ -112,7 +120,9 @@ func handleMsgMhfAcquireGuildTresure(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfAcquireGuildTresure) _, err := s.server.db.Exec("UPDATE guild_hunts SET acquired=true WHERE id=$1", pkt.HuntID) if err != nil { - panic(err) + s.logger.Error("failed to acquire guild treasure", zap.Error(err), zap.Uint32("huntID", pkt.HuntID)) + doAckSimpleFail(s, pkt.AckHandle, nil) + return } doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } @@ -145,12 +155,16 @@ func handleMsgMhfOperateGuildTresureReport(s *Session, p mhfpacket.MHFPacket) { // Register to selected hunt err := s.server.db.QueryRow("SELECT hunters FROM guild_hunts WHERE id=$1", pkt.HuntID).Scan(&csv) if err != nil { - panic(err) + s.logger.Error("failed to get hunters for guild hunt", zap.Error(err), zap.Uint32("huntID", pkt.HuntID)) + doAckSimpleFail(s, pkt.AckHandle, nil) + return } csv = stringsupport.CSVAdd(csv, int(s.charID)) _, err = s.server.db.Exec("UPDATE guild_hunts SET hunters=$1 WHERE id=$2", csv, pkt.HuntID) if err != nil { - panic(err) + s.logger.Error("failed to update hunters for guild hunt", zap.Error(err), zap.Uint32("huntID", pkt.HuntID)) + doAckSimpleFail(s, pkt.AckHandle, nil) + return } } } else if pkt.State == 1 { // Collected by hunter @@ -158,12 +172,16 @@ func handleMsgMhfOperateGuildTresureReport(s *Session, p mhfpacket.MHFPacket) { } else if pkt.State == 2 { // Claim treasure err := s.server.db.QueryRow("SELECT treasure FROM guild_hunts WHERE id=$1", pkt.HuntID).Scan(&csv) if err != nil { - panic(err) + s.logger.Error("failed to get treasure for guild hunt", zap.Error(err), zap.Uint32("huntID", pkt.HuntID)) + doAckSimpleFail(s, pkt.AckHandle, nil) + return } csv = stringsupport.CSVAdd(csv, int(s.charID)) _, err = s.server.db.Exec("UPDATE guild_hunts SET treasure=$1 WHERE id=$2", csv, pkt.HuntID) if err != nil { - panic(err) + s.logger.Error("failed to update treasure for guild hunt", zap.Error(err), zap.Uint32("huntID", pkt.HuntID)) + doAckSimpleFail(s, pkt.AckHandle, nil) + return } } doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) diff --git a/server/channelserver/handlers_mail.go b/server/channelserver/handlers_mail.go index 7e9784ee3..36967ce6a 100644 --- a/server/channelserver/handlers_mail.go +++ b/server/channelserver/handlers_mail.go @@ -258,15 +258,17 @@ func handleMsgMhfReadMail(s *Session, p mhfpacket.MHFPacket) { mailId := s.mailList[pkt.AccIndex] if mailId == 0 { + s.logger.Warn("attempting to read mail that doesn't exist in session map", zap.Uint8("accIndex", pkt.AccIndex)) doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) - panic("attempting to read mail that doesn't exist in session map") + return } mail, err := GetMailByID(s, mailId) if err != nil { + s.logger.Error("failed to get mail by ID", zap.Error(err), zap.Int("mailID", mailId)) doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) - panic(err) + return } _ = mail.MarkRead(s) @@ -285,8 +287,9 @@ func handleMsgMhfListMail(s *Session, p mhfpacket.MHFPacket) { mail, err := GetMailListForCharacter(s, s.charID) if err != nil { + s.logger.Error("failed to get mail list", zap.Error(err), zap.Uint32("charID", s.charID)) doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) - panic(err) + return } if s.mailList == nil { @@ -354,7 +357,9 @@ func handleMsgMhfOprtMail(s *Session, p mhfpacket.MHFPacket) { mail, err := GetMailByID(s, s.mailList[pkt.AccIndex]) if err != nil { - panic(err) + s.logger.Error("failed to get mail for operation", zap.Error(err), zap.Uint8("accIndex", pkt.AccIndex)) + doAckSimpleFail(s, pkt.AckHandle, nil) + return } switch pkt.Operation { @@ -369,7 +374,9 @@ func handleMsgMhfOprtMail(s *Session, p mhfpacket.MHFPacket) { } if err != nil { - panic(err) + s.logger.Error("failed to perform mail operation", zap.Error(err), zap.Uint8("operation", uint8(pkt.Operation))) + doAckSimpleFail(s, pkt.AckHandle, nil) + return } doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) diff --git a/server/channelserver/handlers_quest.go b/server/channelserver/handlers_quest.go index 850daf8d8..3eff1c75d 100644 --- a/server/channelserver/handlers_quest.go +++ b/server/channelserver/handlers_quest.go @@ -112,7 +112,9 @@ func handleMsgSysGetFile(s *Session, p mhfpacket.MHFPacket) { if _, err := os.Stat(filepath.Join(s.server.erupeConfig.BinPath, "quest_override.bin")); err == nil { data, err := os.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, "quest_override.bin")) if err != nil { - panic(err) + s.logger.Error("failed to read quest_override.bin", zap.Error(err)) + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 0)) + return } doAckBufSucceed(s, pkt.AckHandle, data) } else { diff --git a/server/channelserver/handlers_rengoku.go b/server/channelserver/handlers_rengoku.go index 63a591fd2..6e0523243 100644 --- a/server/channelserver/handlers_rengoku.go +++ b/server/channelserver/handlers_rengoku.go @@ -94,7 +94,9 @@ func handleMsgMhfGetRengokuBinary(s *Session, p mhfpacket.MHFPacket) { // a (massively out of date) version resides in the game's /dat/ folder or up to date can be pulled from packets data, err := os.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, "rengoku_data.bin")) if err != nil { - panic(err) + s.logger.Error("failed to read rengoku_data.bin", zap.Error(err)) + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 0)) + return } doAckBufSucceed(s, pkt.AckHandle, data) } diff --git a/server/channelserver/handlers_stage.go b/server/channelserver/handlers_stage.go index 6bdf61862..04a355c0b 100644 --- a/server/channelserver/handlers_stage.go +++ b/server/channelserver/handlers_stage.go @@ -287,7 +287,9 @@ func handleMsgSysBackStage(s *Session, p mhfpacket.MHFPacket) { s.stageMoveStack.Unlock() backStage, err := s.stageMoveStack.Pop() if err != nil { - panic(err) + s.logger.Error("failed to pop stage from move stack", zap.Error(err)) + doAckSimpleFail(s, pkt.AckHandle, nil) + return } if _, exists := s.stage.reservedClientSlots[s.charID]; exists { diff --git a/server/channelserver/handlers_tower.go b/server/channelserver/handlers_tower.go index 0a2675812..114258a39 100644 --- a/server/channelserver/handlers_tower.go +++ b/server/channelserver/handlers_tower.go @@ -3,6 +3,7 @@ package channelserver import ( "encoding/hex" "erupe-ce/network/mhfpacket" + "go.uber.org/zap" ) func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) { @@ -40,7 +41,9 @@ func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) { //data, err = hex.DecodeString("0A218EAD000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") data, err = hex.DecodeString("0A218EAD0000000000000000000000010000001C0000000500050000000000020000000000000000000000000000000000030003000000000003000500050000000300030003000300030003000200030001000300020002000300010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") case mhfpacket.TowerInfoTypeGetOwnTowerLevelV3: - panic("No known response values for GetOwnTowerLevelV3") + // TODO: No known response values for GetOwnTowerLevelV3 + stubGetNoResults(s, pkt.AckHandle) + return case mhfpacket.TowerInfoTypeTowerTouhaHistory: data, err = hex.DecodeString("0A218EAD0000000000000000000000010000000000000000000000000000000000000000") case mhfpacket.TowerInfoTypeUnk5: @@ -72,7 +75,9 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { s.logger.Info("GET_TENROUIRAI request for unknown type") } if err != nil { - panic(err) + s.logger.Error("failed to decode tenrouirai hex data", zap.Error(err)) + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + return } doAckBufSucceed(s, pkt.AckHandle, data) } diff --git a/server/signserver/sign_server.go b/server/signserver/sign_server.go index fd4bd9bed..722c8eec0 100644 --- a/server/signserver/sign_server.go +++ b/server/signserver/sign_server.go @@ -77,7 +77,8 @@ func (s *Server) acceptClients() { if shutdown { break } else { - panic(err) + s.logger.Error("failed to accept connection", zap.Error(err)) + continue } }