fix guild enumeration and applications

This commit is contained in:
wish
2022-08-04 06:43:41 +10:00
parent 872a0b3785
commit ba927f877d
5 changed files with 97 additions and 98 deletions

View File

@@ -2,6 +2,7 @@ package mhfpacket
import ( import (
"errors" "errors"
"io"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"erupe-ce/network" "erupe-ce/network"
@@ -30,6 +31,7 @@ const (
type MsgMhfEnumerateGuild struct { type MsgMhfEnumerateGuild struct {
AckHandle uint32 AckHandle uint32
Type EnumerateGuildType Type EnumerateGuildType
Page uint8
RawDataPayload []byte RawDataPayload []byte
} }
@@ -42,8 +44,9 @@ func (m *MsgMhfEnumerateGuild) Opcode() network.PacketID {
func (m *MsgMhfEnumerateGuild) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { func (m *MsgMhfEnumerateGuild) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
m.AckHandle = bf.ReadUint32() m.AckHandle = bf.ReadUint32()
m.Type = EnumerateGuildType(bf.ReadUint8()) m.Type = EnumerateGuildType(bf.ReadUint8())
m.Page = bf.ReadUint8()
m.RawDataPayload = bf.DataFromCurrent() m.RawDataPayload = bf.DataFromCurrent()
bf.Seek(int64(len(bf.Data())-2), 0) bf.Seek(-2, io.SeekEnd)
return nil return nil
} }

View File

@@ -1,11 +1,11 @@
package mhfpacket package mhfpacket
import ( import (
"errors" "errors"
"erupe-ce/network/clientctx"
"erupe-ce/network"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"erupe-ce/network"
"erupe-ce/network/clientctx"
) )
type OperateGuildMemberAction uint8 type OperateGuildMemberAction uint8
@@ -23,6 +23,7 @@ type MsgMhfOperateGuildMember struct {
GuildID uint32 GuildID uint32
CharID uint32 CharID uint32
Action uint8 Action uint8
Unk []byte
} }
// Opcode returns the ID associated with this packet type. // Opcode returns the ID associated with this packet type.
@@ -36,7 +37,7 @@ func (m *MsgMhfOperateGuildMember) Parse(bf *byteframe.ByteFrame, ctx *clientctx
m.GuildID = bf.ReadUint32() m.GuildID = bf.ReadUint32()
m.CharID = bf.ReadUint32() m.CharID = bf.ReadUint32()
m.Action = bf.ReadUint8() m.Action = bf.ReadUint8()
m.Unk = bf.ReadBytes(3)
return nil return nil
} }

View File

@@ -12,7 +12,6 @@ import (
"strings" "strings"
"time" "time"
"erupe-ce/common/bfutil"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
ps "erupe-ce/common/pascalstring" ps "erupe-ce/common/pascalstring"
"erupe-ce/common/stringsupport" "erupe-ce/common/stringsupport"
@@ -854,42 +853,45 @@ func handleMsgMhfOperateGuildMember(s *Session, p mhfpacket.MHFPacket) {
return return
} }
if pkt.Action == mhfpacket.OPERATE_GUILD_MEMBER_ACTION_ACCEPT || pkt.Action == mhfpacket.OPERATE_GUILD_MEMBER_ACTION_REJECT { var mail Mail
switch pkt.Action {
case mhfpacket.OPERATE_GUILD_MEMBER_ACTION_ACCEPT:
err = guild.AcceptApplication(s, pkt.CharID)
case mhfpacket.OPERATE_GUILD_MEMBER_ACTION_REJECT:
err = guild.RejectApplication(s, pkt.CharID)
}
if err != nil {
doAckSimpleFail(s, pkt.AckHandle, nil)
}
doAckSimpleSucceed(s, pkt.AckHandle, nil)
return
}
character, err := GetCharacterGuildData(s, pkt.CharID)
if err != nil || character == nil {
doAckSimpleFail(s, pkt.AckHandle, nil)
return
}
switch pkt.Action { switch pkt.Action {
case mhfpacket.OPERATE_GUILD_MEMBER_ACTION_ACCEPT:
err = guild.AcceptApplication(s, pkt.CharID)
mail = Mail{
SenderID: s.charID,
RecipientID: pkt.CharID,
Subject: "Accepted!",
Body: fmt.Sprintf("Your application to join 「%s」 was accepted.", guild.Name),
IsGuildInvite: false,
}
case mhfpacket.OPERATE_GUILD_MEMBER_ACTION_REJECT:
err = guild.RejectApplication(s, pkt.CharID)
mail = Mail{
SenderID: s.charID,
RecipientID: pkt.CharID,
Subject: "Rejected",
Body: fmt.Sprintf("Your application to join 「%s」 was rejected.", guild.Name),
IsGuildInvite: false,
}
case mhfpacket.OPERATE_GUILD_MEMBER_ACTION_KICK: case mhfpacket.OPERATE_GUILD_MEMBER_ACTION_KICK:
err = guild.RemoveCharacter(s, pkt.CharID) err = guild.RemoveCharacter(s, pkt.CharID)
mail = Mail{
SenderID: s.charID,
RecipientID: pkt.CharID,
Subject: "Kicked",
Body: fmt.Sprintf("You were kicked from 「%s」.", guild.Name),
IsGuildInvite: false,
}
default: default:
doAckSimpleFail(s, pkt.AckHandle, nil) doAckSimpleFail(s, pkt.AckHandle, nil)
panic(fmt.Sprintf("unhandled operateGuildMember action '%d'", pkt.Action)) s.logger.Warn(fmt.Sprintf("unhandled operateGuildMember action '%d'", pkt.Action))
} }
if err != nil { if err != nil {
doAckSimpleFail(s, pkt.AckHandle, nil) doAckSimpleFail(s, pkt.AckHandle, nil)
return } else {
mail.Send(s, nil)
} }
doAckSimpleSucceed(s, pkt.AckHandle, nil) doAckSimpleSucceed(s, pkt.AckHandle, nil)
} }
@@ -906,6 +908,8 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
} }
if err == nil && guild != nil { if err == nil && guild != nil {
s.prevGuildID = guild.ID
guildName := stringsupport.UTF8ToSJIS(guild.Name) guildName := stringsupport.UTF8ToSJIS(guild.Name)
guildComment := stringsupport.UTF8ToSJIS(guild.Comment) guildComment := stringsupport.UTF8ToSJIS(guild.Comment)
guildLeaderName := stringsupport.UTF8ToSJIS(guild.LeaderName) guildLeaderName := stringsupport.UTF8ToSJIS(guild.LeaderName)
@@ -1057,19 +1061,22 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
if err != nil { if err != nil {
resp := byteframe.NewByteFrame() resp := byteframe.NewByteFrame()
resp.WriteUint32(0) // Count resp.WriteUint32(0) // Count
resp.WriteUint8(5) // Unk, read if count == 0. resp.WriteUint8(0) // Unk, read if count == 0.
doAckBufSucceed(s, pkt.AckHandle, resp.Data()) doAckBufSucceed(s, pkt.AckHandle, resp.Data())
} }
if err != nil {
bf.WriteUint16(uint16(len(applicants))) bf.WriteUint16(0)
} else {
for _, applicant := range applicants { bf.WriteUint16(uint16(len(applicants)))
bf.WriteUint32(applicant.CharID) for _, applicant := range applicants {
bf.WriteUint32(0x05) bf.WriteUint32(applicant.CharID)
bf.WriteUint16(0x0032) bf.WriteUint16(0)
bf.WriteUint8(0x00) bf.WriteUint16(0)
ps.Uint16(bf, applicant.Name, true) bf.WriteUint16(applicant.HRP)
bf.WriteUint16(applicant.GR)
ps.Uint8(bf, applicant.Name, true)
}
} }
bf.WriteUint16(0x0000) bf.WriteUint16(0x0000)
@@ -1128,100 +1135,74 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
switch pkt.Type { switch pkt.Type {
case mhfpacket.ENUMERATE_GUILD_TYPE_GUILD_NAME: case mhfpacket.ENUMERATE_GUILD_TYPE_GUILD_NAME:
bf.ReadBytes(8) bf.ReadBytes(10)
searchTermLength := bf.ReadUint16() searchTerm := stringsupport.SJISToUTF8(bf.ReadNullTerminatedBytes())
bf.ReadBytes(1) guilds, err = FindGuildsByName(s, searchTerm)
searchTerm := bf.ReadBytes(uint(searchTermLength))
var searchTermSafe string
searchTermSafe, err = s.clientContext.StrConv.Decode(bfutil.UpToNull(searchTerm))
if err != nil {
panic(err)
}
guilds, err = FindGuildsByName(s, searchTermSafe)
case mhfpacket.ENUMERATE_GUILD_TYPE_LEADER_NAME: case mhfpacket.ENUMERATE_GUILD_TYPE_LEADER_NAME:
bf.ReadBytes(8) bf.ReadBytes(10)
searchTermLength := bf.ReadUint16() searchTerm := stringsupport.SJISToUTF8(bf.ReadNullTerminatedBytes())
bf.ReadBytes(1) rows, err = s.server.db.Queryx(fmt.Sprintf(`%s WHERE lc.name ILIKE $1`, guildInfoSelectQuery), searchTerm)
searchTerm := bf.ReadBytes(uint(searchTermLength)) if err == nil {
var searchTermSafe string
searchTermSafe, err = s.clientContext.StrConv.Decode(bfutil.UpToNull(searchTerm))
if err != nil {
panic(err)
}
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s WHERE lc.name ILIKE $1`, guildInfoSelectQuery), searchTermSafe)
if err != nil {
s.logger.Error("Failed to retrieve guild by leader name", zap.Error(err))
} else {
for rows.Next() { for rows.Next() {
guild, _ := buildGuildObjectFromDbResult(rows, err, s) guild, _ := buildGuildObjectFromDbResult(rows, err, s)
guilds = append(guilds, guild) guilds = append(guilds, guild)
} }
} }
case mhfpacket.ENUMERATE_GUILD_TYPE_LEADER_ID: case mhfpacket.ENUMERATE_GUILD_TYPE_LEADER_ID:
bf.ReadBytes(3) bf.ReadBytes(2)
ID := bf.ReadUint32() ID := bf.ReadUint32()
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s WHERE leader_id = $1`, guildInfoSelectQuery), ID) rows, err = s.server.db.Queryx(fmt.Sprintf(`%s WHERE leader_id = $1`, guildInfoSelectQuery), ID)
if err != nil { if err == nil {
s.logger.Error("Failed to retrieve guild by leader ID", zap.Error(err))
} else {
for rows.Next() { for rows.Next() {
guild, _ := buildGuildObjectFromDbResult(rows, err, s) guild, _ := buildGuildObjectFromDbResult(rows, err, s)
guilds = append(guilds, guild) guilds = append(guilds, guild)
} }
} }
case mhfpacket.ENUMERATE_GUILD_TYPE_ORDER_MEMBERS: case mhfpacket.ENUMERATE_GUILD_TYPE_ORDER_MEMBERS:
sorting := bf.ReadUint16() sorting := bf.ReadUint8()
if sorting == 1 { if sorting == 1 {
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY member_count DESC`, guildInfoSelectQuery)) rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY member_count DESC`, guildInfoSelectQuery))
} else { } else {
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY member_count ASC`, guildInfoSelectQuery)) rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY member_count ASC`, guildInfoSelectQuery))
} }
if err != nil { if err == nil {
s.logger.Error("Failed to retrieve guild by member count", zap.Error(err))
} else {
for rows.Next() { for rows.Next() {
guild, _ := buildGuildObjectFromDbResult(rows, err, s) guild, _ := buildGuildObjectFromDbResult(rows, err, s)
guilds = append(guilds, guild) guilds = append(guilds, guild)
} }
} }
case mhfpacket.ENUMERATE_GUILD_TYPE_ORDER_REGISTRATION: case mhfpacket.ENUMERATE_GUILD_TYPE_ORDER_REGISTRATION:
sorting := bf.ReadUint16() sorting := bf.ReadUint8()
if sorting == 1 { if sorting == 1 {
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY id ASC`, guildInfoSelectQuery)) rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY id ASC`, guildInfoSelectQuery))
} else { } else {
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY id DESC`, guildInfoSelectQuery)) rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY id DESC`, guildInfoSelectQuery))
} }
if err != nil { if err == nil {
s.logger.Error("Failed to retrieve guild by registration date", zap.Error(err))
} else {
for rows.Next() { for rows.Next() {
guild, _ := buildGuildObjectFromDbResult(rows, err, s) guild, _ := buildGuildObjectFromDbResult(rows, err, s)
guilds = append(guilds, guild) guilds = append(guilds, guild)
} }
} }
case mhfpacket.ENUMERATE_GUILD_TYPE_ORDER_RANK: case mhfpacket.ENUMERATE_GUILD_TYPE_ORDER_RANK:
sorting := bf.ReadUint16() sorting := bf.ReadUint8()
if sorting == 1 { if sorting == 1 {
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY rank_rp DESC`, guildInfoSelectQuery)) rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY rank_rp DESC`, guildInfoSelectQuery))
} else { } else {
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY rank_rp ASC`, guildInfoSelectQuery)) rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY rank_rp ASC`, guildInfoSelectQuery))
} }
if err != nil { if err == nil {
s.logger.Error("Failed to retrieve guild by rank", zap.Error(err))
} else {
for rows.Next() { for rows.Next() {
guild, _ := buildGuildObjectFromDbResult(rows, err, s) guild, _ := buildGuildObjectFromDbResult(rows, err, s)
guilds = append(guilds, guild) guilds = append(guilds, guild)
} }
} }
case mhfpacket.ENUMERATE_GUILD_TYPE_MOTTO: case mhfpacket.ENUMERATE_GUILD_TYPE_MOTTO:
bf.ReadBytes(3) bf.ReadBytes(2)
mainMotto := bf.ReadUint16() mainMotto := bf.ReadUint16()
subMotto := bf.ReadUint16() subMotto := bf.ReadUint16()
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s WHERE main_motto = $1 AND sub_motto = $2`, guildInfoSelectQuery), mainMotto, subMotto) rows, err = s.server.db.Queryx(fmt.Sprintf(`%s WHERE main_motto = $1 AND sub_motto = $2`, guildInfoSelectQuery), mainMotto, subMotto)
if err != nil { if err == nil {
s.logger.Error("Failed to retrieve guild by motto", zap.Error(err))
} else {
for rows.Next() { for rows.Next() {
guild, _ := buildGuildObjectFromDbResult(rows, err, s) guild, _ := buildGuildObjectFromDbResult(rows, err, s)
guilds = append(guilds, guild) guilds = append(guilds, guild)
@@ -1251,23 +1232,21 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
bf = byteframe.NewByteFrame() bf = byteframe.NewByteFrame()
bf.WriteUint16(uint16(len(guilds))) bf.WriteUint16(uint16(len(guilds)))
bf.WriteUint8(0x01) // Unk
for _, guild := range guilds { for _, guild := range guilds {
bf.WriteUint8(0x00) // Unk
bf.WriteUint32(guild.ID) bf.WriteUint32(guild.ID)
bf.WriteUint32(guild.LeaderCharID) bf.WriteUint32(guild.LeaderCharID)
bf.WriteUint16(guild.MemberCount) bf.WriteUint16(guild.MemberCount)
bf.WriteUint8(0x00) // Unk bf.WriteUint16(0x0000) // Unk
bf.WriteUint8(0x00) // Unk bf.WriteUint16(guild.Rank) // OR guilds in alliance
bf.WriteUint16(guild.Rank)
bf.WriteUint32(uint32(guild.CreatedAt.Unix())) bf.WriteUint32(uint32(guild.CreatedAt.Unix()))
ps.Uint8(bf, guild.Name, true) ps.Uint8(bf, guild.Name, true)
ps.Uint8(bf, guild.LeaderName, true) ps.Uint8(bf, guild.LeaderName, true)
bf.WriteUint8(0x01) // Unk bf.WriteUint8(0x01) // Unk
bf.WriteBool(false) // closed
} }
bf.WriteUint8(0x01) // Unk
bf.WriteUint8(0x00) // Unk
doAckBufSucceed(s, pkt.AckHandle, bf.Data()) doAckBufSucceed(s, pkt.AckHandle, bf.Data())
} }
@@ -1318,6 +1297,10 @@ func handleMsgMhfEnumerateGuildMember(s *Session, p mhfpacket.MHFPacket) {
guild, err = GetGuildInfoByCharacterId(s, s.charID) guild, err = GetGuildInfoByCharacterId(s, s.charID)
} }
if guild == nil && s.prevGuildID > 0 {
guild, err = GetGuildInfoByID(s, s.prevGuildID)
}
if err != nil { if err != nil {
s.logger.Warn("failed to retrieve guild sending no result message") s.logger.Warn("failed to retrieve guild sending no result message")
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 2)) doAckBufSucceed(s, pkt.AckHandle, make([]byte, 2))
@@ -1411,6 +1394,15 @@ func handleMsgMhfGetGuildManageRight(s *Session, p mhfpacket.MHFPacket) {
guild, err := GetGuildInfoByCharacterId(s, s.charID) guild, err := GetGuildInfoByCharacterId(s, s.charID)
if guild == nil && s.prevGuildID != 0 {
guild, err = GetGuildInfoByID(s, s.prevGuildID)
s.prevGuildID = 0
if guild == nil || err != nil {
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
return
}
}
if err != nil { if err != nil {
s.logger.Warn("failed to respond to manage rights message") s.logger.Warn("failed to respond to manage rights message")
return return

View File

@@ -190,13 +190,15 @@ func handleMsgMhfGetGuildScoutList(s *Session, p mhfpacket.MHFPacket) {
guildInfo, err := GetGuildInfoByCharacterId(s, s.charID) guildInfo, err := GetGuildInfoByCharacterId(s, s.charID)
if err != nil { if guildInfo == nil && s.prevGuildID == 0 {
panic(err)
}
if guildInfo == nil {
doAckSimpleFail(s, pkt.AckHandle, nil) doAckSimpleFail(s, pkt.AckHandle, nil)
return return
} else {
guildInfo, err = GetGuildInfoByID(s, s.prevGuildID)
if guildInfo == nil || err != nil {
doAckSimpleFail(s, pkt.AckHandle, nil)
return
}
} }
rows, err := s.server.db.Queryx(` rows, err := s.server.db.Queryx(`

View File

@@ -33,6 +33,7 @@ type Session struct {
stage *Stage stage *Stage
reservationStage *Stage // Required for the stateful MsgSysUnreserveStage packet. reservationStage *Stage // Required for the stateful MsgSysUnreserveStage packet.
stagePass string // Temporary storage stagePass string // Temporary storage
prevGuildID uint32 // Stores the last GuildID used in InfoGuild
charID uint32 charID uint32
logKey []byte logKey []byte
sessionStart int64 sessionStart int64