From 2c8391b5a47373a36c128a027a4a1e81530fb9c6 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 11 Jun 2023 18:51:56 +1000 Subject: [PATCH] various Tower changes --- common/stringsupport/string_convert.go | 21 +++ network/mhfpacket/msg_mhf_get_tower_info.go | 11 -- network/mhfpacket/msg_mhf_post_gem_info.go | 29 +++- network/mhfpacket/msg_mhf_post_tower_info.go | 47 +++--- patch-schema/tower.sql | 12 ++ server/channelserver/handlers.go | 11 -- server/channelserver/handlers_tower.go | 166 ++++++++++++++++--- 7 files changed, 225 insertions(+), 72 deletions(-) create mode 100644 patch-schema/tower.sql diff --git a/common/stringsupport/string_convert.go b/common/stringsupport/string_convert.go index 53ed2ec69..452c85321 100644 --- a/common/stringsupport/string_convert.go +++ b/common/stringsupport/string_convert.go @@ -2,6 +2,7 @@ package stringsupport import ( "bytes" + "fmt" "io" "strconv" "strings" @@ -96,3 +97,23 @@ func CSVElems(csv string) []int { } return r } + +func CSVGetIndex(csv string, i int) int { + s := CSVElems(csv) + if i < len(s) { + return s[i] + } + return 0 +} + +func CSVSetIndex(csv string, i int, v int) string { + s := CSVElems(csv) + if i < len(s) { + s[i] = v + } + var r []string + for j := 0; j < len(s); j++ { + r = append(r, fmt.Sprintf(`%d`, s[j])) + } + return strings.Join(r, ",") +} diff --git a/network/mhfpacket/msg_mhf_get_tower_info.go b/network/mhfpacket/msg_mhf_get_tower_info.go index a0b686485..4041e26e4 100644 --- a/network/mhfpacket/msg_mhf_get_tower_info.go +++ b/network/mhfpacket/msg_mhf_get_tower_info.go @@ -8,19 +8,8 @@ import ( "erupe-ce/network/clientctx" ) -// The server sends different responses based on these values. -const ( - TowerInfoTypeUnk0 = iota - TowerInfoTypeTowerRankPoint - TowerInfoTypeGetOwnTowerSkill - TowerInfoTypeGetOwnTowerLevelV3 - TowerInfoTypeTowerTouhaHistory - TowerInfoTypeUnk5 -) - // MsgMhfGetTowerInfo represents the MSG_MHF_GET_TOWER_INFO type MsgMhfGetTowerInfo struct { - // Communicator type, multi-format. This might be valid for only one type. AckHandle uint32 InfoType uint32 // Requested response type Unk0 uint32 diff --git a/network/mhfpacket/msg_mhf_post_gem_info.go b/network/mhfpacket/msg_mhf_post_gem_info.go index 13a0a9a0d..2e89b89b7 100644 --- a/network/mhfpacket/msg_mhf_post_gem_info.go +++ b/network/mhfpacket/msg_mhf_post_gem_info.go @@ -1,15 +1,24 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfPostGemInfo represents the MSG_MHF_POST_GEM_INFO -type MsgMhfPostGemInfo struct{} +type MsgMhfPostGemInfo struct { + AckHandle uint32 + Unk0 uint32 + Unk1 uint32 + Unk2 int32 + Unk3 int32 + Unk4 int32 + Unk5 int32 + Unk6 int32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfPostGemInfo) Opcode() network.PacketID { @@ -18,7 +27,15 @@ func (m *MsgMhfPostGemInfo) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfPostGemInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + 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 } // Build builds a binary packet from the current data. diff --git a/network/mhfpacket/msg_mhf_post_tower_info.go b/network/mhfpacket/msg_mhf_post_tower_info.go index 7719086ff..3499d1f98 100644 --- a/network/mhfpacket/msg_mhf_post_tower_info.go +++ b/network/mhfpacket/msg_mhf_post_tower_info.go @@ -1,28 +1,26 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfPostTowerInfo represents the MSG_MHF_POST_TOWER_INFO type MsgMhfPostTowerInfo struct { - // Communicator type, multi-format. This might be valid for only one type. AckHandle uint32 - Unk0 uint32 + InfoType uint32 Unk1 uint32 - Unk2 uint32 - Unk3 uint32 - Unk4 uint32 - Unk5 uint32 - Unk6 uint32 - Unk7 uint32 - Unk8 uint32 - Unk9 uint32 - Unk10 uint32 + Unk2 int32 + Unk3 int32 + Unk4 int32 + Unk5 int32 + Unk6 int32 + Unk7 int32 + Unk8 int32 + Unk9 int64 } // Opcode returns the ID associated with this packet type. @@ -33,17 +31,16 @@ func (m *MsgMhfPostTowerInfo) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfPostTowerInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() - m.Unk0 = bf.ReadUint32() + m.InfoType = bf.ReadUint32() m.Unk1 = bf.ReadUint32() - m.Unk2 = bf.ReadUint32() - m.Unk3 = bf.ReadUint32() - m.Unk4 = bf.ReadUint32() - m.Unk5 = bf.ReadUint32() - m.Unk6 = bf.ReadUint32() - m.Unk7 = bf.ReadUint32() - m.Unk8 = bf.ReadUint32() - m.Unk9 = bf.ReadUint32() - m.Unk10 = bf.ReadUint32() + m.Unk2 = bf.ReadInt32() + m.Unk3 = bf.ReadInt32() + m.Unk4 = bf.ReadInt32() + m.Unk5 = bf.ReadInt32() + m.Unk6 = bf.ReadInt32() + m.Unk7 = bf.ReadInt32() + m.Unk8 = bf.ReadInt32() + m.Unk9 = bf.ReadInt64() return nil } diff --git a/patch-schema/tower.sql b/patch-schema/tower.sql new file mode 100644 index 000000000..661393c27 --- /dev/null +++ b/patch-schema/tower.sql @@ -0,0 +1,12 @@ +BEGIN; + +CREATE TABLE IF NOT EXISTS tower ( + char_id INT, + tr INT, + trp INT, + tsp INT, + zone1 INT, + skills TEXT DEFAULT '0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0' +); + +END; \ No newline at end of file diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index 5081bb2c4..ed00f2275 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -27,17 +27,6 @@ func stubEnumerateNoResults(s *Session, ackHandle uint32) { doAckBufSucceed(s, ackHandle, enumBf.Data()) } -// Temporary function to just return no results for many MSG_MHF_GET* packets. -func stubGetNoResults(s *Session, ackHandle uint32) { - resp := byteframe.NewByteFrame() - resp.WriteUint32(0x0A218EAD) // Unk shared ID. Sent in response of MSG_MHF_GET_TOWER_INFO, MSG_MHF_GET_PAPER_DATA etc. (World ID?) - resp.WriteUint32(0) // Unk - resp.WriteUint32(0) // Unk - resp.WriteUint32(0) // Entry count - - 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)) diff --git a/server/channelserver/handlers_tower.go b/server/channelserver/handlers_tower.go index 1bec51dde..3fb859b9a 100644 --- a/server/channelserver/handlers_tower.go +++ b/server/channelserver/handlers_tower.go @@ -1,46 +1,97 @@ package channelserver import ( - "encoding/hex" "erupe-ce/common/byteframe" + "erupe-ce/common/stringsupport" "erupe-ce/network/mhfpacket" ) +type TowerInfoTRP struct { + TR int32 + TRP int32 +} + +type TowerInfoSkill struct { + TSP int32 + Unk1 []int16 // 40 +} + +type TowerInfoHistory struct { + Unk0 []int16 // 5 + Unk1 []int16 // 5 +} + +type TowerInfoLevel struct { + Zone1 int32 + Unk1 int32 + Unk2 int32 + Unk3 int32 +} + func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetTowerInfo) var data []*byteframe.ByteFrame type TowerInfo struct { - TRP []uint64 - TowerSkill [][]byte // 132 bytes - TowerHistory [][]byte // 20 bytes + TRP []TowerInfoTRP + Skill []TowerInfoSkill + History []TowerInfoHistory + Level []TowerInfoLevel } towerInfo := TowerInfo{ - TRP: []uint64{0}, - TowerSkill: [][]byte{make([]byte, 132)}, - TowerHistory: [][]byte{make([]byte, 20)}, + TRP: []TowerInfoTRP{{0, 0}}, + Skill: []TowerInfoSkill{{0, make([]int16, 40)}}, + History: []TowerInfoHistory{{make([]int16, 5), make([]int16, 5)}}, + Level: []TowerInfoLevel{{0, 0, 0, 0}}, } - // Example data - // towerInfo.TowerSkill[0], _ = hex.DecodeString("0000001C0000000500050000000000020000000000000000000000000000000000030003000000000003000500050000000300030003000300030003000200030001000300020002000300010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + tempSkills := "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0" + + err := s.server.db.QueryRow(`SELECT COALESCE(tr, 0), COALESCE(trp, 0), COALESCE(tsp, 0), COALESCE(zone1, 0), skills FROM tower WHERE char_id=$1 + `, s.charID).Scan(&towerInfo.TRP[0].TR, &towerInfo.TRP[0].TRP, &towerInfo.Skill[0].TSP, &towerInfo.Level[0].Zone1, &tempSkills) + if err != nil { + s.server.db.Exec(`INSERT INTO tower (char_id) VALUES ($1)`, s.charID) + } + + for i, skill := range stringsupport.CSVElems(tempSkills) { + towerInfo.Skill[0].Unk1[i] = int16(skill) + } switch pkt.InfoType { case 1: for _, trp := range towerInfo.TRP { bf := byteframe.NewByteFrame() - bf.WriteUint64(trp) + bf.WriteInt32(trp.TR) + bf.WriteInt32(trp.TRP) data = append(data, bf) } case 2: - for _, skills := range towerInfo.TowerSkill { + for _, skills := range towerInfo.Skill { bf := byteframe.NewByteFrame() - bf.WriteBytes(skills) + bf.WriteInt32(skills.TSP) + for i := range skills.Unk1 { + bf.WriteInt16(skills.Unk1[i]) + } data = append(data, bf) } case 4: - for _, history := range towerInfo.TowerHistory { + for _, history := range towerInfo.History { bf := byteframe.NewByteFrame() - bf.WriteBytes(history) + for i := range history.Unk0 { + bf.WriteInt16(history.Unk0[i]) + } + for i := range history.Unk1 { + bf.WriteInt16(history.Unk1[i]) + } + data = append(data, bf) + } + case 5: + for _, level := range towerInfo.Level { + bf := byteframe.NewByteFrame() + bf.WriteInt32(level.Zone1) + bf.WriteInt32(level.Unk1) + bf.WriteInt32(level.Unk2) + bf.WriteInt32(level.Unk3) data = append(data, bf) } } @@ -49,9 +100,55 @@ func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfPostTowerInfo(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfPostTowerInfo) + switch pkt.InfoType { + case 2: + skills := "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0" + s.server.db.QueryRow(`SELECT skills FROM tower WHERE char_id=$1`, s.charID).Scan(&skills) + s.server.db.Exec(`UPDATE tower SET skills=$1, tsp=tsp-$2 WHERE char_id=$3`, stringsupport.CSVSetIndex(skills, int(pkt.Unk2), stringsupport.CSVGetIndex(skills, int(pkt.Unk2))+1), pkt.Unk5, s.charID) + case 7: + s.server.db.Exec(`UPDATE tower SET tr=$1, trp=$2, zone1=zone1+$3 WHERE char_id=$4`, pkt.Unk3, pkt.Unk4, pkt.Unk8, s.charID) + } doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } +type TenrouiraiCharScore struct { + Score int32 + Name string +} + +type TenrouiraiProgress struct { + Unk0 uint8 + Unk1 uint16 + Unk2 uint16 + Unk3 uint16 +} + +type TenrouiraiTicket struct { + Unk0 uint8 + Unk1 uint32 + Unk2 uint32 +} + +type TenrouiraiData struct { + Unk0 uint8 + Unk1 uint8 + Unk2 uint16 + Unk3 uint16 + Unk4 uint8 + Unk5 uint8 + Unk6 uint8 + Unk7 uint8 + Unk8 uint8 + Unk9 uint8 +} + +type Tenrouirai struct { + CharScore []TenrouiraiCharScore + Progress []TenrouiraiProgress + Ticket []TenrouiraiTicket + Data []TenrouiraiData +} + func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { // if the game gets bad responses for this it breaks the ability to save pkt := p.(*mhfpacket.MsgMhfGetTenrouirai) @@ -125,14 +222,45 @@ func handleMsgMhfPresentBox(s *Session, p mhfpacket.MHFPacket) { doAckEarthSucceed(s, pkt.AckHandle, data) } +type GemInfo struct { + Unk0 uint16 + Unk1 uint16 +} + +type GemHistory struct { + Unk0 uint16 + Unk1 uint16 + Unk2 uint32 + Unk3 string +} + func handleMsgMhfGetGemInfo(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetGemInfo) var data []*byteframe.ByteFrame - /* - bf.WriteUint16(0) - bf.WriteUint16(0) - */ + gemInfo := []GemInfo{} + gemHistory := []GemHistory{} + switch pkt.Unk0 { + case 1: + for _, history := range gemHistory { + bf := byteframe.NewByteFrame() + bf.WriteUint16(history.Unk0) + bf.WriteUint16(history.Unk1) + bf.WriteUint32(history.Unk2) + bf.WriteBytes(stringsupport.PaddedString(history.Unk3, 14, true)) + data = append(data, bf) + } + default: + for _, info := range gemInfo { + bf := byteframe.NewByteFrame() + bf.WriteUint16(info.Unk0) + bf.WriteUint16(info.Unk1) + data = append(data, bf) + } + } doAckEarthSucceed(s, pkt.AckHandle, data) } -func handleMsgMhfPostGemInfo(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfPostGemInfo(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfPostGemInfo) + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) +}