rewrite Earth packet handlers

This commit is contained in:
wish
2023-06-10 23:09:50 +10:00
parent d16acbc824
commit fbecbfa571
4 changed files with 240 additions and 155 deletions

View File

@@ -11,8 +11,13 @@ import (
// MsgMhfGetGemInfo represents the MSG_MHF_GET_GEM_INFO // MsgMhfGetGemInfo represents the MSG_MHF_GET_GEM_INFO
type MsgMhfGetGemInfo struct { type MsgMhfGetGemInfo struct {
AckHandle uint32 AckHandle uint32
Unk uint32 Unk0 uint32
Unk1 []byte Unk1 uint32
Unk2 int32
Unk3 int32
Unk4 int32
Unk5 int32
Unk6 int32
} }
// Opcode returns the ID associated with this packet type. // Opcode returns the ID associated with this packet type.
@@ -23,8 +28,13 @@ func (m *MsgMhfGetGemInfo) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgMhfGetGemInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { func (m *MsgMhfGetGemInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
m.AckHandle = bf.ReadUint32() m.AckHandle = bf.ReadUint32()
m.Unk = bf.ReadUint32() m.Unk0 = bf.ReadUint32()
m.Unk1 = bf.ReadBytes(24) m.Unk1 = bf.ReadUint32()
m.Unk2 = bf.ReadInt32()
m.Unk3 = bf.ReadInt32()
m.Unk4 = bf.ReadInt32()
m.Unk5 = bf.ReadInt32()
m.Unk6 = bf.ReadInt32()
return nil return nil
} }

View File

@@ -38,6 +38,18 @@ func stubGetNoResults(s *Session, ackHandle uint32) {
doAckBufSucceed(s, ackHandle, resp.Data()) doAckBufSucceed(s, ackHandle, resp.Data())
} }
func doAckEarthSucceed(s *Session, ackHandle uint32, data []*byteframe.ByteFrame) {
bf := byteframe.NewByteFrame()
bf.WriteUint32(uint32(s.server.erupeConfig.DevModeOptions.EarthIDOverride))
bf.WriteUint32(0)
bf.WriteUint32(0)
bf.WriteUint32(uint32(len(data)))
for i := range data {
bf.WriteBytes(data[i].Data())
}
doAckBufSucceed(s, ackHandle, bf.Data())
}
func doAckBufSucceed(s *Session, ackHandle uint32, data []byte) { func doAckBufSucceed(s *Session, ackHandle uint32, data []byte) {
s.QueueSendMHF(&mhfpacket.MsgSysAck{ s.QueueSendMHF(&mhfpacket.MsgSysAck{
AckHandle: ackHandle, AckHandle: ackHandle,
@@ -1648,18 +1660,15 @@ func handleMsgMhfGetEarthValue(s *Session, p mhfpacket.MHFPacket) {
} }
} }
bf := byteframe.NewByteFrame() var data []*byteframe.ByteFrame
bf.WriteUint32(uint32(s.server.erupeConfig.DevModeOptions.EarthIDOverride))
bf.WriteUint32(0)
bf.WriteUint32(0)
bf.WriteUint32(uint32(len(earthValues)))
for _, i := range earthValues { for _, i := range earthValues {
bf := byteframe.NewByteFrame()
for _, j := range i.Value { for _, j := range i.Value {
bf.WriteUint32(j) bf.WriteUint32(j)
} }
data = append(data, bf)
} }
doAckEarthSucceed(s, pkt.AckHandle, data)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
} }
func handleMsgMhfDebugPostValue(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfDebugPostValue(s *Session, p mhfpacket.MHFPacket) {}
@@ -1672,56 +1681,142 @@ func handleMsgMhfGetRandFromTable(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfGetSenyuDailyCount(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfGetSenyuDailyCount(s *Session, p mhfpacket.MHFPacket) {}
type SeibattleTimetable struct {
Start time.Time
End time.Time
}
type SeibattleKeyScore struct {
Unk0 uint8
Unk1 int32
}
type SeibattleCareer struct {
Unk0 uint16
Unk1 uint16
Unk2 uint16
}
type SeibattleOpponent struct {
Unk0 int32
Unk1 int8
}
type SeibattleConventionResult struct {
Unk0 uint32
Unk1 uint16
Unk2 uint16
Unk3 uint16
Unk4 uint16
}
type SeibattleCharScore struct {
Unk0 uint32
}
type SeibattleCurResult struct {
Unk0 uint32
Unk1 uint16
Unk2 uint16
Unk3 uint16
}
type Seibattle struct {
Timetable []SeibattleTimetable
KeyScore []SeibattleKeyScore
Career []SeibattleCareer
Opponent []SeibattleOpponent
ConventionResult []SeibattleConventionResult
CharScore []SeibattleCharScore
CurResult []SeibattleCurResult
}
func handleMsgMhfGetSeibattle(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfGetSeibattle(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetSeibattle) pkt := p.(*mhfpacket.MsgMhfGetSeibattle)
bf := byteframe.NewByteFrame() var data []*byteframe.ByteFrame
bf.WriteUint32(0) // Unk seibattle := Seibattle{
bf.WriteUint32(0) // Unk Timetable: []SeibattleTimetable{
bf.WriteUint32(0) // Unk {TimeMidnight(), TimeMidnight().Add(time.Hour * 8)},
bf.WriteUint32(1) // Entries {TimeMidnight().Add(time.Hour * 8), TimeMidnight().Add(time.Hour * 16)},
{TimeMidnight().Add(time.Hour * 16), TimeMidnight().Add(time.Hour * 24)},
switch pkt.Type { },
case 1: // Timetable KeyScore: []SeibattleKeyScore{
bf.Seek(-4, 1) {0, 0},
bf.WriteUint32(3) },
Career: []SeibattleCareer{
bf.WriteUint32(uint32(TimeMidnight().Unix())) {0, 0, 0},
bf.WriteUint32(uint32(TimeMidnight().Add(time.Hour * 8).Unix())) },
Opponent: []SeibattleOpponent{
bf.WriteUint32(uint32(TimeMidnight().Add(time.Hour * 8).Unix())) {1, 1},
bf.WriteUint32(uint32(TimeMidnight().Add(time.Hour * 16).Unix())) },
ConventionResult: []SeibattleConventionResult{
bf.WriteUint32(uint32(TimeMidnight().Add(time.Hour * 16).Unix())) {0, 0, 0, 0, 0},
bf.WriteUint32(uint32(TimeMidnight().Add(time.Hour * 24).Unix())) },
case 2: // Reward CharScore: []SeibattleCharScore{
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 16)) {0},
return },
case 3: // Key score? CurResult: []SeibattleCurResult{
bf.WriteUint8(0) {0, 0, 0, 0},
bf.WriteInt32(0) },
case 4: // Career?
bf.WriteUint16(0)
bf.WriteUint16(0)
bf.WriteUint16(0)
case 5: // Opponent?
bf.WriteInt32(1)
bf.WriteInt8(1)
case 6: // Convention result?
bf.WriteUint32(0)
bf.WriteUint16(0)
bf.WriteUint16(0)
bf.WriteUint16(0)
bf.WriteUint16(0)
case 7: // Char score?
bf.WriteUint32(0)
case 8: // Cur result?
bf.WriteUint32(0)
bf.WriteUint16(0)
bf.WriteUint16(0)
bf.WriteUint16(0)
} }
doAckBufSucceed(s, pkt.AckHandle, bf.Data()) switch pkt.Type {
case 1:
for _, timetable := range seibattle.Timetable {
bf := byteframe.NewByteFrame()
bf.WriteUint32(uint32(timetable.Start.Unix()))
bf.WriteUint32(uint32(timetable.End.Unix()))
data = append(data, bf)
}
case 3: // Key score?
for _, keyScore := range seibattle.KeyScore {
bf := byteframe.NewByteFrame()
bf.WriteUint8(keyScore.Unk0)
bf.WriteInt32(keyScore.Unk1)
data = append(data, bf)
}
case 4: // Career?
for _, career := range seibattle.Career {
bf := byteframe.NewByteFrame()
bf.WriteUint16(career.Unk0)
bf.WriteUint16(career.Unk1)
bf.WriteUint16(career.Unk2)
data = append(data, bf)
}
case 5: // Opponent?
for _, opponent := range seibattle.Opponent {
bf := byteframe.NewByteFrame()
bf.WriteInt32(opponent.Unk0)
bf.WriteInt8(opponent.Unk1)
data = append(data, bf)
}
case 6: // Convention result?
for _, conventionResult := range seibattle.ConventionResult {
bf := byteframe.NewByteFrame()
bf.WriteUint32(conventionResult.Unk0)
bf.WriteUint16(conventionResult.Unk1)
bf.WriteUint16(conventionResult.Unk2)
bf.WriteUint16(conventionResult.Unk3)
bf.WriteUint16(conventionResult.Unk4)
data = append(data, bf)
}
case 7: // Char score?
for _, charScore := range seibattle.CharScore {
bf := byteframe.NewByteFrame()
bf.WriteUint32(charScore.Unk0)
data = append(data, bf)
}
case 8: // Cur result?
for _, curResult := range seibattle.CurResult {
bf := byteframe.NewByteFrame()
bf.WriteUint32(curResult.Unk0)
bf.WriteUint16(curResult.Unk1)
bf.WriteUint16(curResult.Unk2)
bf.WriteUint16(curResult.Unk3)
data = append(data, bf)
}
}
doAckEarthSucceed(s, pkt.AckHandle, data)
} }
func handleMsgMhfPostSeibattle(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfPostSeibattle(s *Session, p mhfpacket.MHFPacket) {}

View File

@@ -42,37 +42,32 @@ type Ryoudama struct {
func handleMsgMhfGetRyoudama(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfGetRyoudama(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetRyoudama) pkt := p.(*mhfpacket.MsgMhfGetRyoudama)
var data []*byteframe.ByteFrame
bf := byteframe.NewByteFrame()
bf.WriteUint32(uint32(s.server.erupeConfig.DevModeOptions.EarthIDOverride))
bf.WriteUint32(0)
bf.WriteUint32(0)
ryoudama := Ryoudama{Score: []int32{0}} ryoudama := Ryoudama{Score: []int32{0}}
switch pkt.Request2 { switch pkt.Request2 {
case 4: case 4:
bf.WriteUint32(uint32(len(ryoudama.Score)))
for _, score := range ryoudama.Score { for _, score := range ryoudama.Score {
bf := byteframe.NewByteFrame()
bf.WriteInt32(score) bf.WriteInt32(score)
data = append(data, bf)
} }
case 5: case 5:
bf.WriteUint32(uint32(len(ryoudama.CharInfo)))
for _, info := range ryoudama.CharInfo { for _, info := range ryoudama.CharInfo {
bf := byteframe.NewByteFrame()
bf.WriteUint32(info.CID) bf.WriteUint32(info.CID)
bf.WriteInt32(info.Unk0) bf.WriteInt32(info.Unk0)
bf.WriteBytes(stringsupport.PaddedString(info.Name, 14, true)) bf.WriteBytes(stringsupport.PaddedString(info.Name, 14, true))
data = append(data, bf)
} }
case 6: case 6:
bf.WriteUint32(uint32(len(ryoudama.BoostInfo)))
for _, info := range ryoudama.BoostInfo { for _, info := range ryoudama.BoostInfo {
bf := byteframe.NewByteFrame()
bf.WriteUint32(uint32(info.Start.Unix())) bf.WriteUint32(uint32(info.Start.Unix()))
bf.WriteUint32(uint32(info.End.Unix())) bf.WriteUint32(uint32(info.End.Unix()))
data = append(data, bf)
} }
default:
bf.WriteUint32(0)
} }
doAckEarthSucceed(s, pkt.AckHandle, data)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
} }
func handleMsgMhfPostRyoudama(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfPostRyoudama(s *Session, p mhfpacket.MHFPacket) {}
@@ -90,30 +85,19 @@ func handleMsgMhfPostTinyBin(s *Session, p mhfpacket.MHFPacket) {
func handleMsgMhfCaravanMyScore(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfCaravanMyScore(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfCaravanMyScore) pkt := p.(*mhfpacket.MsgMhfCaravanMyScore)
bf := byteframe.NewByteFrame() var data []*byteframe.ByteFrame
bf.WriteUint32(0)
bf.WriteUint32(0)
bf.WriteUint32(0)
bf.WriteUint32(0) // Entries
/* /*
bf.WriteInt32(0) bf.WriteInt32(0)
bf.WriteInt32(0) bf.WriteInt32(0)
bf.WriteInt32(0) bf.WriteInt32(0)
bf.WriteInt32(0) bf.WriteInt32(0)
*/ */
doAckEarthSucceed(s, pkt.AckHandle, data)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
} }
func handleMsgMhfCaravanRanking(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfCaravanRanking(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfCaravanRanking) pkt := p.(*mhfpacket.MsgMhfCaravanRanking)
bf := byteframe.NewByteFrame() var data []*byteframe.ByteFrame
bf.WriteUint32(0)
bf.WriteUint32(0)
bf.WriteUint32(0)
bf.WriteUint32(0) // Entries
/* RYOUDAN /* RYOUDAN
bf.WriteInt32(1) bf.WriteInt32(1)
bf.WriteUint32(2) bf.WriteUint32(2)
@@ -124,22 +108,16 @@ func handleMsgMhfCaravanRanking(s *Session, p mhfpacket.MHFPacket) {
bf.WriteInt32(1) bf.WriteInt32(1)
bf.WriteBytes(stringsupport.PaddedString("Test", 14, true)) bf.WriteBytes(stringsupport.PaddedString("Test", 14, true))
*/ */
doAckBufSucceed(s, pkt.AckHandle, bf.Data()) doAckEarthSucceed(s, pkt.AckHandle, data)
} }
func handleMsgMhfCaravanMyRank(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfCaravanMyRank(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfCaravanMyRank) pkt := p.(*mhfpacket.MsgMhfCaravanMyRank)
bf := byteframe.NewByteFrame() var data []*byteframe.ByteFrame
bf.WriteUint32(0)
bf.WriteUint32(0)
bf.WriteUint32(0)
bf.WriteUint32(0) // Entries
/* /*
bf.WriteInt32(0) bf.WriteInt32(0)
bf.WriteInt32(0) bf.WriteInt32(0)
bf.WriteInt32(0) bf.WriteInt32(0)
*/ */
doAckEarthSucceed(s, pkt.AckHandle, data)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
} }

View File

@@ -8,50 +8,43 @@ import (
func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetTowerInfo) pkt := p.(*mhfpacket.MsgMhfGetTowerInfo)
var data []byte var data []*byteframe.ByteFrame
var err error type TowerInfo struct {
/* TRP []uint64
type: TowerSkill [][]byte // 132 bytes
1 == TOWER_RANK_POINT, TowerHistory [][]byte // 20 bytes
2 == GET_OWN_TOWER_SKILL }
3 == GET_OWN_TOWER_LEVEL_V3
4 == TOWER_TOUHA_HISTORY
5 = ?
[] = type towerInfo := TowerInfo{
req TRP: []uint64{0},
resp TowerSkill: [][]byte{make([]byte, 132)},
TowerHistory: [][]byte{make([]byte, 20)},
}
01 1d 01 fc 00 09 [00 00 00 01] 00 00 00 02 00 00 00 00 // Example data
00 12 01 fc 00 09 01 00 00 18 0a 21 8e ad 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 // towerInfo.TowerSkill[0], _ = hex.DecodeString("0000001C0000000500050000000000020000000000000000000000000000000000030003000000000003000500050000000300030003000300030003000200030001000300020002000300010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
01 1d 01 fc 00 0a [00 00 00 02] 00 00 00 00 00 00 00 00
00 12 01 fc 00 0a 01 00 00 94 0a 21 8e ad 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 1d 01 ff 00 0f [00 00 00 04] 00 00 00 00 00 00 00 00
00 12 01 ff 00 0f 01 00 00 24 0a 21 8e ad 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 1d 01 fc 00 0b [00 00 00 05] 00 00 00 00 00 00 00 00
00 12 01 fc 00 0b 01 00 00 10 0a 21 8e ad 00 00 00 00 00 00 00 00 00 00 00 00
*/
switch pkt.InfoType { switch pkt.InfoType {
case mhfpacket.TowerInfoTypeTowerRankPoint: case 1:
data, err = hex.DecodeString("0A218EAD0000000000000000000000010000000000000000") for _, trp := range towerInfo.TRP {
case mhfpacket.TowerInfoTypeGetOwnTowerSkill: bf := byteframe.NewByteFrame()
//data, err = hex.DecodeString("0A218EAD000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") bf.WriteUint64(trp)
data, err = hex.DecodeString("0A218EAD0000000000000000000000010000001C0000000500050000000000020000000000000000000000000000000000030003000000000003000500050000000300030003000300030003000200030001000300020002000300010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") data = append(data, bf)
case mhfpacket.TowerInfoTypeGetOwnTowerLevelV3:
panic("No known response values for GetOwnTowerLevelV3")
case mhfpacket.TowerInfoTypeTowerTouhaHistory:
data, err = hex.DecodeString("0A218EAD0000000000000000000000010000000000000000000000000000000000000000")
case mhfpacket.TowerInfoTypeUnk5:
data, err = hex.DecodeString("0A218EAD000000000000000000000000")
} }
case 2:
if err != nil { for _, skills := range towerInfo.TowerSkill {
stubGetNoResults(s, pkt.AckHandle) bf := byteframe.NewByteFrame()
bf.WriteBytes(skills)
data = append(data, bf)
} }
doAckBufSucceed(s, pkt.AckHandle, data) case 4:
for _, history := range towerInfo.TowerHistory {
bf := byteframe.NewByteFrame()
bf.WriteBytes(history)
data = append(data, bf)
}
}
doAckEarthSucceed(s, pkt.AckHandle, data)
} }
func handleMsgMhfPostTowerInfo(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfPostTowerInfo(s *Session, p mhfpacket.MHFPacket) {
@@ -85,32 +78,37 @@ func handleMsgMhfPostTenrouirai(s *Session, p mhfpacket.MHFPacket) {
func handleMsgMhfGetBreakSeibatuLevelReward(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfGetBreakSeibatuLevelReward(s *Session, p mhfpacket.MHFPacket) {}
type WeeklySeibatuRankingReward struct {
Unk0 int32
Unk1 int32
Unk2 uint32
Unk3 int32
Unk4 int32
Unk5 int32
}
func handleMsgMhfGetWeeklySeibatuRankingReward(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfGetWeeklySeibatuRankingReward(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetWeeklySeibatuRankingReward) pkt := p.(*mhfpacket.MsgMhfGetWeeklySeibatuRankingReward)
var data []*byteframe.ByteFrame
weeklySeibatuRankingRewards := []WeeklySeibatuRankingReward{
{0, 0, 0, 0, 0, 0},
}
for _, reward := range weeklySeibatuRankingRewards {
bf := byteframe.NewByteFrame() bf := byteframe.NewByteFrame()
bf.WriteUint32(0) bf.WriteInt32(reward.Unk0)
bf.WriteUint32(0) bf.WriteInt32(reward.Unk1)
bf.WriteUint32(0) bf.WriteUint32(reward.Unk2)
bf.WriteUint32(1) // Entries bf.WriteInt32(reward.Unk3)
bf.WriteInt32(reward.Unk4)
bf.WriteInt32(0) bf.WriteInt32(reward.Unk5)
bf.WriteInt32(0) data = append(data, bf)
bf.WriteUint32(0) }
bf.WriteInt32(0) doAckEarthSucceed(s, pkt.AckHandle, data)
bf.WriteInt32(0)
bf.WriteInt32(0)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
} }
func handleMsgMhfPresentBox(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfPresentBox(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfPresentBox) pkt := p.(*mhfpacket.MsgMhfPresentBox)
bf := byteframe.NewByteFrame() var data []*byteframe.ByteFrame
bf.WriteUint32(0)
bf.WriteUint32(0)
bf.WriteUint32(0)
bf.WriteUint32(0) // Entries
/* /*
bf.WriteUint32(0) bf.WriteUint32(0)
bf.WriteInt32(0) bf.WriteInt32(0)
@@ -124,13 +122,17 @@ func handleMsgMhfPresentBox(s *Session, p mhfpacket.MHFPacket) {
bf.WriteInt32(0) bf.WriteInt32(0)
bf.WriteInt32(0) bf.WriteInt32(0)
*/ */
doAckEarthSucceed(s, pkt.AckHandle, data)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
} }
func handleMsgMhfGetGemInfo(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfGetGemInfo(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetGemInfo) pkt := p.(*mhfpacket.MsgMhfGetGemInfo)
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) var data []*byteframe.ByteFrame
/*
bf.WriteUint16(0)
bf.WriteUint16(0)
*/
doAckEarthSucceed(s, pkt.AckHandle, data)
} }
func handleMsgMhfPostGemInfo(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfPostGemInfo(s *Session, p mhfpacket.MHFPacket) {}