rework guild operations

This commit is contained in:
wish
2022-09-03 19:49:39 +10:00
parent df1a4834ba
commit cd6561dd61
2 changed files with 73 additions and 80 deletions

View File

@@ -3,9 +3,9 @@ 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 OperateGuildAction uint8 type OperateGuildAction uint8
@@ -30,7 +30,7 @@ const (
OPERATE_GUILD_CHANGE_PUGI_3 = 0x11 OPERATE_GUILD_CHANGE_PUGI_3 = 0x11
// pugi something // pugi something
OPERATE_GUILD_DONATE_EVENT = 0x15 OPERATE_GUILD_DONATE_EVENT = 0x15
// pugi something OPERATE_GUILD_EVENT_EXCHANGE = 0x16
OPERATE_GUILD_CHANGE_DIVA_PUGI_1 = 0x19 OPERATE_GUILD_CHANGE_DIVA_PUGI_1 = 0x19
OPERATE_GUILD_CHANGE_DIVA_PUGI_2 = 0x1a OPERATE_GUILD_CHANGE_DIVA_PUGI_2 = 0x1a
OPERATE_GUILD_CHANGE_DIVA_PUGI_3 = 0x1b OPERATE_GUILD_CHANGE_DIVA_PUGI_3 = 0x1b
@@ -41,7 +41,8 @@ type MsgMhfOperateGuild struct {
AckHandle uint32 AckHandle uint32
GuildID uint32 GuildID uint32
Action OperateGuildAction Action OperateGuildAction
UnkData []byte Data1 *byteframe.ByteFrame
Data2 *byteframe.ByteFrame
} }
// Opcode returns the ID associated with this packet type. // Opcode returns the ID associated with this packet type.
@@ -54,8 +55,9 @@ func (m *MsgMhfOperateGuild) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Clien
m.AckHandle = bf.ReadUint32() m.AckHandle = bf.ReadUint32()
m.GuildID = bf.ReadUint32() m.GuildID = bf.ReadUint32()
m.Action = OperateGuildAction(bf.ReadUint8()) m.Action = OperateGuildAction(bf.ReadUint8())
m.UnkData = bf.DataFromCurrent() dataLen := uint(bf.ReadUint8())
bf.Seek(int64(len(bf.Data()) - 2), 0) m.Data1 = byteframe.NewByteFrameFromBytes(bf.ReadBytes(4))
m.Data2 = byteframe.NewByteFrameFromBytes(bf.ReadBytes(dataLen))
return nil return nil
} }

View File

@@ -634,11 +634,8 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) {
} }
bf.WriteUint32(uint32(response)) bf.WriteUint32(uint32(response))
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
return
case mhfpacket.OPERATE_GUILD_RESIGN: case mhfpacket.OPERATE_GUILD_RESIGN:
guildMembers, err := GetGuildMembers(s, guild.ID, false) guildMembers, err := GetGuildMembers(s, guild.ID, false)
success := false
if err == nil { if err == nil {
sort.Slice(guildMembers[:], func(i, j int) bool { sort.Slice(guildMembers[:], func(i, j int) bool {
return guildMembers[i].OrderIndex < guildMembers[j].OrderIndex return guildMembers[i].OrderIndex < guildMembers[j].OrderIndex
@@ -651,29 +648,17 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) {
guildMembers[0].Save(s) guildMembers[0].Save(s)
guildMembers[i].Save(s) guildMembers[i].Save(s)
bf.WriteUint32(guildMembers[i].CharID) bf.WriteUint32(guildMembers[i].CharID)
success = true
break break
} }
} }
guild.Save(s) guild.Save(s)
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
} }
if !success {
bf.WriteUint32(0)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
return
case mhfpacket.OPERATE_GUILD_APPLY: case mhfpacket.OPERATE_GUILD_APPLY:
err = guild.CreateApplication(s, s.charID, GuildApplicationTypeApplied, nil) err = guild.CreateApplication(s, s.charID, GuildApplicationTypeApplied, nil)
if err != nil { if err == nil {
// All successful acks return 0x01, assuming 0x00 is failure
bf.WriteUint32(0x00)
} else {
bf.WriteUint32(guild.LeaderCharID) bf.WriteUint32(guild.LeaderCharID)
} }
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
return
case mhfpacket.OPERATE_GUILD_LEAVE: case mhfpacket.OPERATE_GUILD_LEAVE:
var err error var err error
@@ -698,10 +683,8 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) {
} }
bf.WriteUint32(uint32(response)) bf.WriteUint32(uint32(response))
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
return
case mhfpacket.OPERATE_GUILD_DONATE_RANK: case mhfpacket.OPERATE_GUILD_DONATE_RANK:
handleDonateRP(s, pkt, bf, guild, false) bf.WriteBytes(handleDonateRP(s, uint16(pkt.Data1.ReadUint32()), guild, false))
case mhfpacket.OPERATE_GUILD_SET_APPLICATION_DENY: case mhfpacket.OPERATE_GUILD_SET_APPLICATION_DENY:
s.server.db.Exec("UPDATE guilds SET recruiting=false WHERE id=$1", guild.ID) s.server.db.Exec("UPDATE guilds SET recruiting=false WHERE id=$1", guild.ID)
case mhfpacket.OPERATE_GUILD_SET_APPLICATION_ALLOW: case mhfpacket.OPERATE_GUILD_SET_APPLICATION_ALLOW:
@@ -711,46 +694,55 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) {
case mhfpacket.OPERATE_GUILD_SET_AVOID_LEADERSHIP_FALSE: case mhfpacket.OPERATE_GUILD_SET_AVOID_LEADERSHIP_FALSE:
handleAvoidLeadershipUpdate(s, pkt, false) handleAvoidLeadershipUpdate(s, pkt, false)
case mhfpacket.OPERATE_GUILD_UPDATE_COMMENT: case mhfpacket.OPERATE_GUILD_UPDATE_COMMENT:
pbf := byteframe.NewByteFrameFromBytes(pkt.UnkData)
if !characterGuildInfo.IsLeader && !characterGuildInfo.IsSubLeader() { if !characterGuildInfo.IsLeader && !characterGuildInfo.IsSubLeader() {
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
return return
} }
_ = pbf.ReadUint8() // len guild.Comment = stringsupport.SJISToUTF8(pkt.Data2.ReadNullTerminatedBytes())
_ = pbf.ReadUint32()
guild.Comment = stringsupport.SJISToUTF8(pbf.ReadNullTerminatedBytes())
guild.Save(s) guild.Save(s)
case mhfpacket.OPERATE_GUILD_UPDATE_MOTTO: case mhfpacket.OPERATE_GUILD_UPDATE_MOTTO:
if !characterGuildInfo.IsLeader && !characterGuildInfo.IsSubLeader() { if !characterGuildInfo.IsLeader && !characterGuildInfo.IsSubLeader() {
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
return return
} }
guild.SubMotto = pkt.UnkData[3] _ = pkt.Data1.ReadUint16()
guild.MainMotto = pkt.UnkData[4] guild.SubMotto = pkt.Data1.ReadUint8()
guild.MainMotto = pkt.Data1.ReadUint8()
guild.Save(s) guild.Save(s)
case mhfpacket.OPERATE_GUILD_RENAME_PUGI_1: case mhfpacket.OPERATE_GUILD_RENAME_PUGI_1:
handleRenamePugi(s, pkt.UnkData, guild, 1) handleRenamePugi(s, pkt.Data2, guild, 1)
case mhfpacket.OPERATE_GUILD_RENAME_PUGI_2: case mhfpacket.OPERATE_GUILD_RENAME_PUGI_2:
handleRenamePugi(s, pkt.UnkData, guild, 2) handleRenamePugi(s, pkt.Data2, guild, 2)
case mhfpacket.OPERATE_GUILD_RENAME_PUGI_3: case mhfpacket.OPERATE_GUILD_RENAME_PUGI_3:
handleRenamePugi(s, pkt.UnkData, guild, 3) handleRenamePugi(s, pkt.Data2, guild, 3)
case mhfpacket.OPERATE_GUILD_CHANGE_PUGI_1: case mhfpacket.OPERATE_GUILD_CHANGE_PUGI_1:
// TODO: decode guild poogie outfits // TODO: decode guild poogie outfits
case mhfpacket.OPERATE_GUILD_CHANGE_PUGI_2: case mhfpacket.OPERATE_GUILD_CHANGE_PUGI_2:
case mhfpacket.OPERATE_GUILD_CHANGE_PUGI_3: case mhfpacket.OPERATE_GUILD_CHANGE_PUGI_3:
case mhfpacket.OPERATE_GUILD_DONATE_EVENT: case mhfpacket.OPERATE_GUILD_DONATE_EVENT:
handleDonateRP(s, pkt, bf, guild, true) bf.WriteBytes(handleDonateRP(s, uint16(pkt.Data1.ReadUint32()), guild, true))
case mhfpacket.OPERATE_GUILD_EVENT_EXCHANGE:
rp := uint16(pkt.Data1.ReadUint32())
saveData, _ := GetCharacterSaveData(s, s.charID)
saveData.RP -= rp
transaction, err := s.server.db.Begin()
err = saveData.Save(s, transaction)
if err != nil {
transaction.Rollback()
}
bf.WriteUint32(uint32(saveData.RP))
default: default:
panic(fmt.Sprintf("unhandled operate guild action '%d'", pkt.Action)) panic(fmt.Sprintf("unhandled operate guild action '%d'", pkt.Action))
} }
if len(bf.Data()) > 0 {
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
} else {
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
}
} }
func handleRenamePugi(s *Session, data []byte, guild *Guild, num int) { func handleRenamePugi(s *Session, bf *byteframe.ByteFrame, guild *Guild, num int) {
bf := byteframe.NewByteFrameFromBytes(data)
_ = bf.ReadUint8() // len
_ = bf.ReadUint32() // unk
name := stringsupport.SJISToUTF8(bf.ReadNullTerminatedBytes()) name := stringsupport.SJISToUTF8(bf.ReadNullTerminatedBytes())
switch num { switch num {
case 1: case 1:
@@ -763,33 +755,30 @@ func handleRenamePugi(s *Session, data []byte, guild *Guild, num int) {
guild.Save(s) guild.Save(s)
} }
func handleDonateRP(s *Session, pkt *mhfpacket.MsgMhfOperateGuild, bf *byteframe.ByteFrame, guild *Guild, isEvent bool) error { func handleDonateRP(s *Session, amount uint16, guild *Guild, isEvent bool) []byte {
rp := binary.BigEndian.Uint16(pkt.UnkData[3:5]) bf := byteframe.NewByteFrame()
bf.WriteUint32(0)
saveData, err := GetCharacterSaveData(s, s.charID) saveData, err := GetCharacterSaveData(s, s.charID)
if err != nil { if err != nil {
return err return bf.Data()
} }
saveData.RP -= rp saveData.RP -= amount
transaction, err := s.server.db.Begin() transaction, err := s.server.db.Begin()
err = saveData.Save(s, transaction) err = saveData.Save(s, transaction)
if err != nil { if err != nil {
transaction.Rollback() transaction.Rollback()
return err return bf.Data()
} else {
transaction.Commit()
} }
updateSQL := "UPDATE guilds SET rank_rp = rank_rp + $1 WHERE id = $2" updateSQL := "UPDATE guilds SET rank_rp = rank_rp + $1 WHERE id = $2"
if isEvent { if isEvent {
updateSQL = "UPDATE guilds SET event_rp = event_rp + $1 WHERE id = $2" updateSQL = "UPDATE guilds SET event_rp = event_rp + $1 WHERE id = $2"
} }
_, err = s.server.db.Exec(updateSQL, rp, guild.ID) s.server.db.Exec(updateSQL, amount, guild.ID)
if err != nil { bf.Seek(0, 0)
s.logger.Error("Failed to donate rank RP to guild", zap.Error(err), zap.Uint32("guildID", guild.ID))
transaction.Rollback()
return err
} else {
transaction.Commit()
}
bf.WriteUint32(uint32(saveData.RP)) bf.WriteUint32(uint32(saveData.RP))
return nil return bf.Data()
} }
func handleAvoidLeadershipUpdate(s *Session, pkt *mhfpacket.MsgMhfOperateGuild, avoidLeadership bool) { func handleAvoidLeadershipUpdate(s *Session, pkt *mhfpacket.MsgMhfOperateGuild, avoidLeadership bool) {
@@ -1712,9 +1701,11 @@ func handleMsgMhfGetGuildWeeklyBonusMaster(s *Session, p mhfpacket.MHFPacket) {
} }
func handleMsgMhfGetGuildWeeklyBonusActiveCount(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfGetGuildWeeklyBonusActiveCount(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetGuildWeeklyBonusActiveCount) pkt := p.(*mhfpacket.MsgMhfGetGuildWeeklyBonusActiveCount)
bf := byteframe.NewByteFrame()
// Values taken from brand new guild capture bf.WriteUint8(0x3C) // Active count
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 0x03)) bf.WriteUint8(0x3C) // Current active count
bf.WriteUint8(0x00) // New active count
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
} }
func handleMsgMhfGuildHuntdata(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfGuildHuntdata(s *Session, p mhfpacket.MHFPacket) {