From 40a86364d9a91cceb524b1479f13ac7d04c65689 Mon Sep 17 00:00:00 2001 From: wish Date: Fri, 30 Sep 2022 23:05:10 +1000 Subject: [PATCH] handle alliance enumeration --- network/mhfpacket/msg_mhf_info_joint.go | 19 ++- server/channelserver/handlers_guild.go | 110 +++++++++++++----- .../channelserver/handlers_guild_alliance.go | 51 +++++++- 3 files changed, 146 insertions(+), 34 deletions(-) diff --git a/network/mhfpacket/msg_mhf_info_joint.go b/network/mhfpacket/msg_mhf_info_joint.go index 6426b9211..17e468c7c 100644 --- a/network/mhfpacket/msg_mhf_info_joint.go +++ b/network/mhfpacket/msg_mhf_info_joint.go @@ -1,15 +1,19 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfInfoJoint represents the MSG_MHF_INFO_JOINT -type MsgMhfInfoJoint struct{} +type MsgMhfInfoJoint struct { + AckHandle uint32 + AllianceID uint32 + Unk uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfInfoJoint) Opcode() network.PacketID { @@ -18,7 +22,10 @@ func (m *MsgMhfInfoJoint) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfInfoJoint) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - return errors.New("NOT IMPLEMENTED") + m.AckHandle = bf.ReadUint32() + m.AllianceID = bf.ReadUint32() + m.Unk = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. diff --git a/server/channelserver/handlers_guild.go b/server/channelserver/handlers_guild.go index f7646926c..5f56baf6d 100644 --- a/server/channelserver/handlers_guild.go +++ b/server/channelserver/handlers_guild.go @@ -1065,6 +1065,7 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateGuild) var guilds []*Guild + var alliances []*GuildAlliance var rows *sqlx.Rows var err error bf := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload) @@ -1159,41 +1160,98 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) { guilds = append(guilds, guild) } } - case mhfpacket.ENUMERATE_ALLIANCE_TYPE_ALLIANCE_NAME: - // - case mhfpacket.ENUMERATE_ALLIANCE_TYPE_LEADER_NAME: - // - case mhfpacket.ENUMERATE_ALLIANCE_TYPE_LEADER_ID: - // - case mhfpacket.ENUMERATE_ALLIANCE_TYPE_ORDER_MEMBERS: - // - case mhfpacket.ENUMERATE_ALLIANCE_TYPE_ORDER_REGISTRATION: - // - default: - panic(fmt.Sprintf("no handler for guild search type '%d'", pkt.Type)) } - if err != nil || guilds == nil { + if pkt.Type > 8 { + var tempAlliances []*GuildAlliance + rows, err = s.server.db.Queryx(allianceInfoSelectQuery) + if err == nil { + for rows.Next() { + alliance, _ := buildAllianceObjectFromDbResult(rows, err, s) + tempAlliances = append(tempAlliances, alliance) + } + } + switch pkt.Type { + case mhfpacket.ENUMERATE_ALLIANCE_TYPE_ALLIANCE_NAME: + bf.ReadBytes(10) + searchTerm := stringsupport.SJISToUTF8(bf.ReadNullTerminatedBytes()) + for _, alliance := range tempAlliances { + if strings.Contains(alliance.Name, searchTerm) { + alliances = append(alliances, alliance) + } + } + case mhfpacket.ENUMERATE_ALLIANCE_TYPE_LEADER_NAME: + bf.ReadBytes(10) + searchTerm := stringsupport.SJISToUTF8(bf.ReadNullTerminatedBytes()) + for _, alliance := range tempAlliances { + if strings.Contains(alliance.ParentGuild.LeaderName, searchTerm) { + alliances = append(alliances, alliance) + } + } + case mhfpacket.ENUMERATE_ALLIANCE_TYPE_LEADER_ID: + bf.ReadBytes(2) + ID := bf.ReadUint32() + for _, alliance := range tempAlliances { + if alliance.ParentGuild.LeaderCharID == ID { + alliances = append(alliances, alliance) + } + } + case mhfpacket.ENUMERATE_ALLIANCE_TYPE_ORDER_MEMBERS: + sort.Slice(tempAlliances, func(i, j int) bool { + return tempAlliances[i].TotalMembers < tempAlliances[j].TotalMembers + }) + alliances = tempAlliances + case mhfpacket.ENUMERATE_ALLIANCE_TYPE_ORDER_REGISTRATION: + sort.Slice(tempAlliances, func(i, j int) bool { + return tempAlliances[i].CreatedAt.Unix() < tempAlliances[j].CreatedAt.Unix() + }) + alliances = tempAlliances + } + } + + if err != nil || (guilds == nil && alliances == nil) { stubEnumerateNoResults(s, pkt.AckHandle) return } bf = byteframe.NewByteFrame() - bf.WriteUint16(uint16(len(guilds))) - bf.WriteUint8(0x01) // Unk - - for _, guild := range guilds { - bf.WriteUint32(guild.ID) - bf.WriteUint32(guild.LeaderCharID) - bf.WriteUint16(guild.MemberCount) - bf.WriteUint16(0x0000) // Unk - bf.WriteUint16(guild.Rank) // OR guilds in alliance - bf.WriteUint32(uint32(guild.CreatedAt.Unix())) - ps.Uint8(bf, guild.Name, true) - ps.Uint8(bf, guild.LeaderName, true) + if pkt.Type > 8 { + bf.WriteUint16(uint16(len(alliances))) + for _, alliance := range alliances { + bf.WriteUint8(0x00) // Unk + bf.WriteUint32(alliance.ID) + bf.WriteUint32(alliance.ParentGuild.LeaderCharID) + bf.WriteUint16(alliance.TotalMembers) + bf.WriteUint16(0x0000) + if alliance.SubGuild1ID == 0 && alliance.SubGuild2ID == 0 { + bf.WriteUint16(1) + } else if alliance.SubGuild1ID > 0 && alliance.SubGuild2ID == 0 || alliance.SubGuild1ID == 0 && alliance.SubGuild2ID > 0 { + bf.WriteUint16(2) + } else { + bf.WriteUint16(3) + } + bf.WriteUint32(uint32(alliance.CreatedAt.Unix())) + ps.Uint8(bf, alliance.Name, true) + ps.Uint8(bf, alliance.ParentGuild.LeaderName, true) + bf.WriteUint8(0x01) // Unk + bf.WriteBool(true) // TODO: Enable GuildAlliance applications + } + } else { bf.WriteUint8(0x01) // Unk - bf.WriteBool(!guild.Recruiting) + bf.WriteUint16(uint16(len(guilds))) + for _, guild := range guilds { + bf.WriteUint32(guild.ID) + bf.WriteUint32(guild.LeaderCharID) + bf.WriteUint16(guild.MemberCount) + bf.WriteUint16(0x0000) // Unk + bf.WriteUint16(guild.Rank) // OR guilds in alliance + bf.WriteUint32(uint32(guild.CreatedAt.Unix())) + ps.Uint8(bf, guild.Name, true) + ps.Uint8(bf, guild.LeaderName, true) + bf.WriteUint8(0x01) // Unk + bf.WriteBool(!guild.Recruiting) + } } doAckBufSucceed(s, pkt.AckHandle, bf.Data()) diff --git a/server/channelserver/handlers_guild_alliance.go b/server/channelserver/handlers_guild_alliance.go index 77f204adc..8f3a6313e 100644 --- a/server/channelserver/handlers_guild_alliance.go +++ b/server/channelserver/handlers_guild_alliance.go @@ -1,6 +1,8 @@ package channelserver import ( + "erupe-ce/common/byteframe" + ps "erupe-ce/common/pascalstring" "fmt" "time" @@ -149,9 +151,54 @@ func handleMsgMhfOperateJoint(s *Session, p mhfpacket.MHFPacket) { doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) } default: - panic(fmt.Sprintf("Unhandled operate joint action '%d'", pkt.Action)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + panic(fmt.Sprintf("Unhandled operate joint action '%d'", pkt.Action)) } } -func handleMsgMhfInfoJoint(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfInfoJoint(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfInfoJoint) + bf := byteframe.NewByteFrame() + alliance, err := GetAllianceData(s, pkt.AllianceID) + if err != nil { + doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + } else { + bf.WriteUint32(alliance.ID) + bf.WriteUint32(uint32(alliance.CreatedAt.Unix())) + bf.WriteUint16(alliance.TotalMembers) + bf.WriteUint16(0x0000) // Unk + ps.Uint16(bf, alliance.Name, true) + if alliance.SubGuild1ID > 0 { + if alliance.SubGuild2ID > 0 { + bf.WriteUint8(3) + } else { + bf.WriteUint8(2) + } + } else { + bf.WriteUint8(1) + } + bf.WriteUint32(alliance.ParentGuildID) + bf.WriteUint32(alliance.ParentGuild.LeaderCharID) + bf.WriteUint16(alliance.ParentGuild.Rank) + bf.WriteUint16(alliance.ParentGuild.MemberCount) + ps.Uint16(bf, alliance.ParentGuild.Name, true) + ps.Uint16(bf, alliance.ParentGuild.LeaderName, true) + if alliance.SubGuild1ID > 0 { + bf.WriteUint32(alliance.SubGuild1ID) + bf.WriteUint32(alliance.SubGuild1.LeaderCharID) + bf.WriteUint16(alliance.SubGuild1.Rank) + bf.WriteUint16(alliance.SubGuild1.MemberCount) + ps.Uint16(bf, alliance.SubGuild1.Name, true) + ps.Uint16(bf, alliance.SubGuild1.LeaderName, true) + } + if alliance.SubGuild2ID > 0 { + bf.WriteUint32(alliance.SubGuild2ID) + bf.WriteUint32(alliance.SubGuild2.LeaderCharID) + bf.WriteUint16(alliance.SubGuild2.Rank) + bf.WriteUint16(alliance.SubGuild2.MemberCount) + ps.Uint16(bf, alliance.SubGuild2.Name, true) + ps.Uint16(bf, alliance.SubGuild2.LeaderName, true) + } + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + } +}