mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-12 23:14:36 +01:00
Compare commits
1 Commits
8f3624d589
...
fix/clan-i
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8d3fc3ead |
@@ -10,20 +10,19 @@ import (
|
||||
type EnumerateGuildType uint8
|
||||
|
||||
const (
|
||||
ENUMERATE_GUILD_UNKNOWN = iota
|
||||
ENUMERATE_GUILD_TYPE_GUILD_NAME
|
||||
ENUMERATE_GUILD_TYPE_LEADER_NAME
|
||||
ENUMERATE_GUILD_TYPE_LEADER_ID
|
||||
ENUMERATE_GUILD_TYPE_ORDER_MEMBERS
|
||||
ENUMERATE_GUILD_TYPE_ORDER_REGISTRATION
|
||||
ENUMERATE_GUILD_TYPE_ORDER_RANK
|
||||
ENUMERATE_GUILD_TYPE_MOTTO
|
||||
ENUMERATE_GUILD_TYPE_RECRUITING
|
||||
ENUMERATE_ALLIANCE_TYPE_ALLIANCE_NAME
|
||||
ENUMERATE_ALLIANCE_TYPE_LEADER_NAME
|
||||
ENUMERATE_ALLIANCE_TYPE_LEADER_ID
|
||||
ENUMERATE_ALLIANCE_TYPE_ORDER_MEMBERS
|
||||
ENUMERATE_ALLIANCE_TYPE_ORDER_REGISTRATION
|
||||
EnumerateGuildTypeGuildName = iota + 1
|
||||
EnumerateGuildTypeLeaderName
|
||||
EnumerateGuildTypeLeaderId
|
||||
EnumerateGuildTypeOrderMembers
|
||||
EnumerateGuildTypeOrderRegistration
|
||||
EnumerateGuildTypeOrderRank
|
||||
EnumerateGuildTypeMotto
|
||||
EnumerateGuildTypeRecruiting
|
||||
EnumerateAllianceTypeAllianceName
|
||||
EnumerateAllianceTypeLeaderName
|
||||
EnumerateAllianceTypeLeaderId
|
||||
EnumerateAllianceTypeOrderMembers
|
||||
EnumerateAllianceTypeOrderRegistration
|
||||
)
|
||||
|
||||
// MsgMhfEnumerateGuild represents the MSG_MHF_ENUMERATE_GUILD
|
||||
|
||||
@@ -12,8 +12,8 @@ import (
|
||||
type MsgMhfEnumerateInvGuild struct {
|
||||
AckHandle uint32
|
||||
Unk uint32
|
||||
Operation uint8
|
||||
ActiveHours uint8
|
||||
ActiveHours1 uint8
|
||||
ActiveHours2 uint8
|
||||
DaysActive uint8
|
||||
PlayStyle uint8
|
||||
GuildRequest uint8
|
||||
@@ -28,8 +28,8 @@ func (m *MsgMhfEnumerateInvGuild) Opcode() network.PacketID {
|
||||
func (m *MsgMhfEnumerateInvGuild) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.Unk = bf.ReadUint32()
|
||||
m.Operation = bf.ReadUint8()
|
||||
m.ActiveHours = bf.ReadUint8()
|
||||
m.ActiveHours1 = bf.ReadUint8()
|
||||
m.ActiveHours2 = bf.ReadUint8()
|
||||
m.DaysActive = bf.ReadUint8()
|
||||
m.PlayStyle = bf.ReadUint8()
|
||||
m.GuildRequest = bf.ReadUint8()
|
||||
|
||||
@@ -11,10 +11,9 @@ import (
|
||||
type OperateGuildMemberAction uint8
|
||||
|
||||
const (
|
||||
_ = iota
|
||||
OPERATE_GUILD_MEMBER_ACTION_ACCEPT
|
||||
OPERATE_GUILD_MEMBER_ACTION_REJECT
|
||||
OPERATE_GUILD_MEMBER_ACTION_KICK
|
||||
OperateGuildMemberAccept = iota + 1
|
||||
OperateGuildMemberReject
|
||||
OperateGuildMemberKick
|
||||
)
|
||||
|
||||
// MsgMhfOperateGuildMember represents the MSG_MHF_OPERATE_GUILD_MEMBER
|
||||
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
type OperateJointAction uint8
|
||||
|
||||
const (
|
||||
OPERATE_JOINT_DISBAND = 0x01
|
||||
OPERATE_JOINT_LEAVE = 0x03
|
||||
OPERATE_JOINT_KICK = 0x09
|
||||
OperateJointDisband = 1
|
||||
OperateJointLeave = 3
|
||||
OperateJointKick = 9
|
||||
)
|
||||
|
||||
// MsgMhfOperateJoint represents the MSG_MHF_OPERATE_JOINT
|
||||
|
||||
@@ -8,10 +8,17 @@ import (
|
||||
"erupe-ce/network/clientctx"
|
||||
)
|
||||
|
||||
type OperateInvGuildAction uint8
|
||||
|
||||
const (
|
||||
OperateInvGuildSend = iota + 1
|
||||
OperateInvGuildCancel
|
||||
)
|
||||
|
||||
// MsgMhfOperationInvGuild represents the MSG_MHF_OPERATION_INV_GUILD
|
||||
type MsgMhfOperationInvGuild struct {
|
||||
AckHandle uint32
|
||||
Operation uint8
|
||||
Action uint8
|
||||
ActiveHours uint8
|
||||
DaysActive uint8
|
||||
PlayStyle uint8
|
||||
@@ -26,7 +33,7 @@ func (m *MsgMhfOperationInvGuild) Opcode() network.PacketID {
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfOperationInvGuild) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.Operation = bf.ReadUint8()
|
||||
m.Action = bf.ReadUint8()
|
||||
m.ActiveHours = bf.ReadUint8()
|
||||
m.DaysActive = bf.ReadUint8()
|
||||
m.PlayStyle = bf.ReadUint8()
|
||||
|
||||
26
schemas/patch-schema/clan-applications-rework.sql
Normal file
26
schemas/patch-schema/clan-applications-rework.sql
Normal file
@@ -0,0 +1,26 @@
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE IF EXISTS public.guild_applications DROP COLUMN IF EXISTS actor_id;
|
||||
|
||||
ALTER TABLE IF EXISTS public.guild_applications DROP COLUMN IF EXISTS application_type;
|
||||
|
||||
ALTER TABLE IF EXISTS public.guild_applications
|
||||
ALTER COLUMN created_at DROP NOT NULL;
|
||||
ALTER TABLE IF EXISTS public.guild_applications DROP CONSTRAINT IF EXISTS guild_applications_actor_id_fkey;
|
||||
|
||||
create table public.guild_invites (
|
||||
id serial primary key,
|
||||
guild_id integer,
|
||||
character_id integer,
|
||||
actor_id integer,
|
||||
created_at timestamp with time zone not null default now(),
|
||||
foreign key (guild_id) references guilds (id),
|
||||
foreign key (character_id) references characters (id),
|
||||
foreign key (actor_id) references characters (id)
|
||||
);
|
||||
|
||||
drop type if exists guild_application_type;
|
||||
|
||||
ALTER TABLE IF EXISTS public.mail DROP CONSTRAINT IF EXISTS mail_sender_id_fkey;
|
||||
|
||||
END;
|
||||
@@ -356,18 +356,14 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
// state festa (U)ser
|
||||
func handleMsgMhfStateFestaU(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfStateFestaU)
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
applicant := false
|
||||
if guild != nil {
|
||||
applicant, _ = guild.HasApplicationForCharID(s, s.charID)
|
||||
}
|
||||
if err != nil || guild == nil || applicant {
|
||||
guild := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if guild.ID == 0 || IsGuildApplicant(s, s.charID) {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
var souls, exists uint32
|
||||
s.server.db.QueryRow(`SELECT COALESCE((SELECT SUM(souls) FROM festa_submissions WHERE character_id=$1), 0)`, s.charID).Scan(&souls)
|
||||
err = s.server.db.QueryRow("SELECT prize_id FROM festa_prizes_accepted WHERE prize_id=0 AND character_id=$1", s.charID).Scan(&exists)
|
||||
err := s.server.db.QueryRow("SELECT prize_id FROM festa_prizes_accepted WHERE prize_id=0 AND character_id=$1", s.charID).Scan(&exists)
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(souls)
|
||||
if err != nil {
|
||||
@@ -383,13 +379,9 @@ func handleMsgMhfStateFestaU(s *Session, p mhfpacket.MHFPacket) {
|
||||
// state festa (G)uild
|
||||
func handleMsgMhfStateFestaG(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfStateFestaG)
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
applicant := false
|
||||
if guild != nil {
|
||||
applicant, _ = guild.HasApplicationForCharID(s, s.charID)
|
||||
}
|
||||
guild := GetGuildInfoByCharacterId(s, s.charID)
|
||||
resp := byteframe.NewByteFrame()
|
||||
if err != nil || guild == nil || applicant {
|
||||
if guild.ID == 0 || IsGuildApplicant(s, s.charID) {
|
||||
resp.WriteUint32(0)
|
||||
resp.WriteInt32(0)
|
||||
resp.WriteInt32(-1)
|
||||
@@ -408,20 +400,20 @@ func handleMsgMhfStateFestaG(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
func handleMsgMhfEnumerateFestaMember(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateFestaMember)
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if err != nil || guild == nil {
|
||||
guild := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if guild.ID == 0 {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
members, err := GetGuildMembers(s, guild.ID, false)
|
||||
if err != nil {
|
||||
members := GetGuildMembers(s, guild.ID)
|
||||
if len(members) == 0 {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
sort.Slice(members, func(i, j int) bool {
|
||||
return members[i].Souls > members[j].Souls
|
||||
})
|
||||
var validMembers []*GuildMember
|
||||
var validMembers []GuildMember
|
||||
for _, member := range members {
|
||||
if member.Souls > 0 {
|
||||
validMembers = append(validMembers, member)
|
||||
@@ -450,8 +442,8 @@ func handleMsgMhfVoteFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
func handleMsgMhfEntryFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEntryFesta)
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if err != nil || guild == nil {
|
||||
guild := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if guild.ID == 0 {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -66,13 +66,9 @@ type Guild struct {
|
||||
Souls uint32 `db:"souls"`
|
||||
AllianceID uint32 `db:"alliance_id"`
|
||||
Icon *GuildIcon `db:"icon"`
|
||||
|
||||
GuildLeader
|
||||
}
|
||||
|
||||
type GuildLeader struct {
|
||||
LeaderCharID uint32 `db:"leader_id"`
|
||||
LeaderName string `db:"leader_name"`
|
||||
LeaderCharID uint32 `db:"leader_id"`
|
||||
LeaderName string `db:"leader_name"`
|
||||
Members []*GuildMember
|
||||
}
|
||||
|
||||
type GuildIconPart struct {
|
||||
@@ -89,12 +85,23 @@ type GuildIconPart struct {
|
||||
}
|
||||
|
||||
type GuildApplication struct {
|
||||
ID int `db:"id"`
|
||||
GuildID uint32 `db:"guild_id"`
|
||||
CharID uint32 `db:"character_id"`
|
||||
ActorID uint32 `db:"actor_id"`
|
||||
ApplicationType GuildApplicationType `db:"application_type"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
GuildID uint32 `db:"guild_id"`
|
||||
CharID uint32 `db:"character_id"`
|
||||
AppliedAt time.Time `db:"created_at"`
|
||||
HR uint16 `db:"hr"`
|
||||
GR uint16 `db:"gr"`
|
||||
Name string `db:"name"`
|
||||
}
|
||||
|
||||
type GuildInvite struct {
|
||||
ID uint32 `db:"id"`
|
||||
GuildID uint32 `db:"guild_id"`
|
||||
CharID uint32 `db:"character_id"`
|
||||
ActorID uint32 `db:"actor_id"`
|
||||
InvitedAt time.Time `db:"created_at"`
|
||||
HR uint16 `db:"hr"`
|
||||
GR uint16 `db:"gr"`
|
||||
Name string `db:"name"`
|
||||
}
|
||||
|
||||
type GuildIcon struct {
|
||||
@@ -191,7 +198,7 @@ func (guild *Guild) Save(s *Session) error {
|
||||
UPDATE guilds SET main_motto=$2, sub_motto=$3, comment=$4, pugi_name_1=$5, pugi_name_2=$6, pugi_name_3=$7,
|
||||
pugi_outfit_1=$8, pugi_outfit_2=$9, pugi_outfit_3=$10, pugi_outfits=$11, icon=$12, leader_id=$13 WHERE id=$1
|
||||
`, guild.ID, guild.MainMotto, guild.SubMotto, guild.Comment, guild.PugiName1, guild.PugiName2, guild.PugiName3,
|
||||
guild.PugiOutfit1, guild.PugiOutfit2, guild.PugiOutfit3, guild.PugiOutfits, guild.Icon, guild.GuildLeader.LeaderCharID)
|
||||
guild.PugiOutfit1, guild.PugiOutfit2, guild.PugiOutfit3, guild.PugiOutfits, guild.Icon, guild.LeaderCharID)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error("failed to update guild data", zap.Error(err), zap.Uint32("guildID", guild.ID))
|
||||
@@ -349,13 +356,8 @@ func (guild *Guild) AcceptApplication(s *Session, charID uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// This is relying on the fact that invitation ID is also character ID right now
|
||||
// if invitation ID changes, this will break.
|
||||
func (guild *Guild) CancelInvitation(s *Session, charID uint32) error {
|
||||
_, err := s.server.db.Exec(
|
||||
`DELETE FROM guild_applications WHERE character_id = $1 AND guild_id = $2 AND application_type = 'invited'`,
|
||||
charID, guild.ID,
|
||||
)
|
||||
_, err := s.server.db.Exec(`DELETE FROM guild_invites WHERE character_id = $1 AND guild_id = $2`, charID, guild.ID)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error(
|
||||
@@ -447,6 +449,17 @@ func (guild *Guild) GetApplicationForCharID(s *Session, charID uint32, applicati
|
||||
return application, nil
|
||||
}
|
||||
|
||||
func IsGuildApplicant(s *Session, charID uint32) bool {
|
||||
var exists bool
|
||||
err := s.server.db.QueryRowx(`
|
||||
SELECT 1 from guild_applications WHERE character_id = $1
|
||||
`, charID).Scan(&exists)
|
||||
if err == nil && exists {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (guild *Guild) HasApplicationForCharID(s *Session, charID uint32) (bool, error) {
|
||||
row := s.server.db.QueryRowx(`
|
||||
SELECT 1 from guild_applications WHERE character_id = $1 AND guild_id = $2
|
||||
@@ -545,62 +558,43 @@ func rollbackTransaction(s *Session, transaction *sql.Tx) {
|
||||
}
|
||||
}
|
||||
|
||||
func GetGuildInfoByID(s *Session, guildID uint32) (*Guild, error) {
|
||||
rows, err := s.server.db.Queryx(fmt.Sprintf(`
|
||||
func GetGuildInfoByID(s *Session, guildID uint32) Guild {
|
||||
var guild Guild
|
||||
err := s.server.db.QueryRowx(fmt.Sprintf(`
|
||||
%s
|
||||
WHERE g.id = $1
|
||||
LIMIT 1
|
||||
`, guildInfoSelectQuery), guildID)
|
||||
`, guildInfoSelectQuery), guildID).StructScan(&guild)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error("failed to retrieve guild", zap.Error(err), zap.Uint32("guildID", guildID))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
hasRow := rows.Next()
|
||||
|
||||
if !hasRow {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return buildGuildObjectFromDbResult(rows, err, s)
|
||||
return guild
|
||||
}
|
||||
|
||||
func GetGuildInfoByCharacterId(s *Session, charID uint32) (*Guild, error) {
|
||||
rows, err := s.server.db.Queryx(fmt.Sprintf(`
|
||||
func GetGuildInfoByCharacterId(s *Session, charID uint32) Guild {
|
||||
var guild Guild
|
||||
err := s.server.db.QueryRowx(fmt.Sprintf(`
|
||||
%s
|
||||
WHERE EXISTS(
|
||||
SELECT 1
|
||||
FROM guild_characters gc1
|
||||
WHERE gc1.character_id = $1
|
||||
AND gc1.guild_id = g.id
|
||||
)
|
||||
OR EXISTS(
|
||||
SELECT 1
|
||||
FROM guild_applications ga
|
||||
WHERE ga.character_id = $1
|
||||
AND ga.guild_id = g.id
|
||||
AND ga.application_type = 'applied'
|
||||
)
|
||||
WHERE EXISTS (
|
||||
SELECT 1
|
||||
FROM guild_characters gc1
|
||||
WHERE gc1.character_id = $1
|
||||
AND gc1.guild_id = g.id
|
||||
) OR EXISTS (
|
||||
SELECT 1
|
||||
FROM guild_applications ga
|
||||
WHERE ga.character_id = $1
|
||||
AND ga.guild_id = g.id
|
||||
)
|
||||
LIMIT 1
|
||||
`, guildInfoSelectQuery), charID)
|
||||
`, guildInfoSelectQuery), charID).StructScan(&guild)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error("failed to retrieve guild for character", zap.Error(err), zap.Uint32("charID", charID))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
hasRow := rows.Next()
|
||||
|
||||
if !hasRow {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return buildGuildObjectFromDbResult(rows, err, s)
|
||||
return guild
|
||||
}
|
||||
|
||||
func buildGuildObjectFromDbResult(result *sqlx.Rows, err error, s *Session) (*Guild, error) {
|
||||
@@ -642,12 +636,10 @@ func handleMsgMhfCreateGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfOperateGuild)
|
||||
|
||||
guild, err := GetGuildInfoByID(s, pkt.GuildID)
|
||||
characterGuildInfo, err := GetCharacterGuildData(s, s.charID)
|
||||
if err != nil {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
var err error
|
||||
|
||||
guild := GetGuildInfoByID(s, pkt.GuildID)
|
||||
characterGuildInfo := GetCharacterGuildData(s, s.charID)
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
@@ -665,8 +657,8 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
bf.WriteUint32(uint32(response))
|
||||
case mhfpacket.OperateGuildResign:
|
||||
guildMembers, err := GetGuildMembers(s, guild.ID, false)
|
||||
if err == nil {
|
||||
guildMembers := GetGuildMembers(s, guild.ID)
|
||||
if len(guildMembers) > 0 {
|
||||
sort.Slice(guildMembers[:], func(i, j int) bool {
|
||||
return guildMembers[i].OrderIndex < guildMembers[j].OrderIndex
|
||||
})
|
||||
@@ -682,71 +674,61 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
}
|
||||
guild.Save(s)
|
||||
} else {
|
||||
bf.WriteUint32(0)
|
||||
}
|
||||
case mhfpacket.OperateGuildApply:
|
||||
err = guild.CreateApplication(s, s.charID, GuildApplicationTypeApplied, nil)
|
||||
_, err = s.server.db.Exec(`INSERT INTO guild_applications (guild_id, character_id) VALUES ($1, $2)`, guild.ID, s.charID)
|
||||
if err == nil {
|
||||
bf.WriteUint32(guild.LeaderCharID)
|
||||
} else {
|
||||
bf.WriteUint32(0)
|
||||
}
|
||||
case mhfpacket.OperateGuildLeave:
|
||||
if characterGuildInfo.IsApplicant {
|
||||
err = guild.RejectApplication(s, s.charID)
|
||||
if characterGuildInfo.CharID == 0 {
|
||||
s.server.db.Exec(`DELETE FROM guild_applications WHERE character_id=$1 AND guild_id=$2`, s.charID, guild.ID)
|
||||
bf.WriteUint32(1)
|
||||
} else {
|
||||
err = guild.RemoveCharacter(s, s.charID)
|
||||
}
|
||||
response := 1
|
||||
if err != nil {
|
||||
response = 0
|
||||
} else {
|
||||
mail := Mail{
|
||||
RecipientID: s.charID,
|
||||
Subject: "Withdrawal",
|
||||
Body: fmt.Sprintf("You have withdrawn from 「%s」.", guild.Name),
|
||||
IsSystemMessage: true,
|
||||
if guild.RemoveCharacter(s, s.charID) != nil {
|
||||
bf.WriteUint32(0)
|
||||
} else {
|
||||
bf.WriteUint32(1)
|
||||
}
|
||||
mail.Send(s, nil)
|
||||
}
|
||||
bf.WriteUint32(uint32(response))
|
||||
mail := Mail{
|
||||
RecipientID: s.charID,
|
||||
Subject: "Withdrawal",
|
||||
Body: fmt.Sprintf("You have withdrawn from 「%s」.", guild.Name),
|
||||
IsSystemMessage: true,
|
||||
}
|
||||
mail.Send(s)
|
||||
case mhfpacket.OperateGuildDonateRank:
|
||||
bf.WriteBytes(handleDonateRP(s, uint16(pkt.Data1.ReadUint32()), guild, 0))
|
||||
case mhfpacket.OperateGuildSetApplicationDeny:
|
||||
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.OperateGuildSetApplicationAllow:
|
||||
s.server.db.Exec("UPDATE guilds SET recruiting=true WHERE id=$1", guild.ID)
|
||||
s.server.db.Exec(`UPDATE guilds SET recruiting=true WHERE id=$1`, guild.ID)
|
||||
case mhfpacket.OperateGuildSetAvoidLeadershipTrue:
|
||||
handleAvoidLeadershipUpdate(s, pkt, true)
|
||||
s.server.db.Exec(`UPDATE guild_characters SET avoid_leadership=true WHERE character_id=$1`, s.charID)
|
||||
case mhfpacket.OperateGuildSetAvoidLeadershipFalse:
|
||||
handleAvoidLeadershipUpdate(s, pkt, false)
|
||||
s.server.db.Exec(`UPDATE guild_characters SET avoid_leadership=false WHERE character_id=$1`, s.charID)
|
||||
case mhfpacket.OperateGuildUpdateComment:
|
||||
if !characterGuildInfo.IsLeader && !characterGuildInfo.IsSubLeader() {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
guild.Comment = stringsupport.SJISToUTF8(pkt.Data2.ReadNullTerminatedBytes())
|
||||
guild.Save(s)
|
||||
s.server.db.Exec(`UPDATE guilds SET comment=$1 WHERE id=$2`, stringsupport.SJISToUTF8(pkt.Data2.ReadNullTerminatedBytes()), guild.ID)
|
||||
case mhfpacket.OperateGuildUpdateMotto:
|
||||
if !characterGuildInfo.IsLeader && !characterGuildInfo.IsSubLeader() {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
_ = pkt.Data1.ReadUint16()
|
||||
guild.SubMotto = pkt.Data1.ReadUint8()
|
||||
guild.MainMotto = pkt.Data1.ReadUint8()
|
||||
guild.Save(s)
|
||||
s.server.db.Exec(`UPDATE guilds SET sub_motto=$1, main_motto=$2 WHERE id=$3`, pkt.Data1.ReadUint8(), pkt.Data1.ReadUint8(), guild.ID)
|
||||
case mhfpacket.OperateGuildRenamePugi1:
|
||||
handleRenamePugi(s, pkt.Data2, guild, 1)
|
||||
guild.RenamePoogie(s, stringsupport.SJISToUTF8(pkt.Data2.ReadNullTerminatedBytes()), 1)
|
||||
case mhfpacket.OperateGuildRenamePugi2:
|
||||
handleRenamePugi(s, pkt.Data2, guild, 2)
|
||||
guild.RenamePoogie(s, stringsupport.SJISToUTF8(pkt.Data2.ReadNullTerminatedBytes()), 2)
|
||||
case mhfpacket.OperateGuildRenamePugi3:
|
||||
handleRenamePugi(s, pkt.Data2, guild, 3)
|
||||
guild.RenamePoogie(s, stringsupport.SJISToUTF8(pkt.Data2.ReadNullTerminatedBytes()), 3)
|
||||
case mhfpacket.OperateGuildChangePugi1:
|
||||
handleChangePugi(s, uint8(pkt.Data1.ReadUint32()), guild, 1)
|
||||
guild.ChangePoogie(s, uint8(pkt.Data1.ReadUint32()), 1)
|
||||
case mhfpacket.OperateGuildChangePugi2:
|
||||
handleChangePugi(s, uint8(pkt.Data1.ReadUint32()), guild, 2)
|
||||
guild.ChangePoogie(s, uint8(pkt.Data1.ReadUint32()), 2)
|
||||
case mhfpacket.OperateGuildChangePugi3:
|
||||
handleChangePugi(s, uint8(pkt.Data1.ReadUint32()), guild, 3)
|
||||
guild.ChangePoogie(s, uint8(pkt.Data1.ReadUint32()), 3)
|
||||
case mhfpacket.OperateGuildUnlockOutfit:
|
||||
// TODO: This doesn't implement blocking, if someone unlocked the same outfit at the same time
|
||||
s.server.db.Exec(`UPDATE guilds SET pugi_outfits=pugi_outfits+$1 WHERE id=$2`, int(math.Pow(float64(pkt.Data1.ReadUint32()), 2)), guild.ID)
|
||||
@@ -774,32 +756,31 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
}
|
||||
|
||||
func handleRenamePugi(s *Session, bf *byteframe.ByteFrame, guild *Guild, num int) {
|
||||
name := stringsupport.SJISToUTF8(bf.ReadNullTerminatedBytes())
|
||||
func (g *Guild) RenamePoogie(s *Session, name string, num int) {
|
||||
switch num {
|
||||
case 1:
|
||||
guild.PugiName1 = name
|
||||
g.PugiName1 = name
|
||||
case 2:
|
||||
guild.PugiName2 = name
|
||||
g.PugiName2 = name
|
||||
default:
|
||||
guild.PugiName3 = name
|
||||
g.PugiName3 = name
|
||||
}
|
||||
guild.Save(s)
|
||||
g.Save(s)
|
||||
}
|
||||
|
||||
func handleChangePugi(s *Session, outfit uint8, guild *Guild, num int) {
|
||||
func (g *Guild) ChangePoogie(s *Session, outfit uint8, num int) {
|
||||
switch num {
|
||||
case 1:
|
||||
guild.PugiOutfit1 = outfit
|
||||
g.PugiOutfit1 = outfit
|
||||
case 2:
|
||||
guild.PugiOutfit2 = outfit
|
||||
g.PugiOutfit2 = outfit
|
||||
case 3:
|
||||
guild.PugiOutfit3 = outfit
|
||||
g.PugiOutfit3 = outfit
|
||||
}
|
||||
guild.Save(s)
|
||||
g.Save(s)
|
||||
}
|
||||
|
||||
func handleDonateRP(s *Session, amount uint16, guild *Guild, _type int) []byte {
|
||||
func handleDonateRP(s *Session, amount uint16, guild Guild, _type int) []byte {
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(0)
|
||||
saveData, err := GetCharacterSaveData(s, s.charID)
|
||||
@@ -835,63 +816,42 @@ func handleDonateRP(s *Session, amount uint16, guild *Guild, _type int) []byte {
|
||||
return bf.Data()
|
||||
}
|
||||
|
||||
func handleAvoidLeadershipUpdate(s *Session, pkt *mhfpacket.MsgMhfOperateGuild, avoidLeadership bool) {
|
||||
characterGuildData, err := GetCharacterGuildData(s, s.charID)
|
||||
|
||||
if err != nil {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
characterGuildData.AvoidLeadership = avoidLeadership
|
||||
|
||||
err = characterGuildData.Save(s)
|
||||
|
||||
if err != nil {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfOperateGuildMember(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfOperateGuildMember)
|
||||
|
||||
guild, err := GetGuildInfoByCharacterId(s, pkt.CharID)
|
||||
|
||||
if err != nil || guild == nil {
|
||||
guild := GetGuildInfoByCharacterId(s, pkt.CharID)
|
||||
if guild.ID == 0 {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
actorCharacter, err := GetCharacterGuildData(s, s.charID)
|
||||
|
||||
if err != nil || (!actorCharacter.IsSubLeader() && guild.LeaderCharID != s.charID) {
|
||||
actor := GetCharacterGuildData(s, s.charID)
|
||||
if !actor.IsSubLeader() {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
var mail Mail
|
||||
switch pkt.Action {
|
||||
case mhfpacket.OPERATE_GUILD_MEMBER_ACTION_ACCEPT:
|
||||
err = guild.AcceptApplication(s, pkt.CharID)
|
||||
case mhfpacket.OperateGuildMemberAccept:
|
||||
s.server.db.Exec(`DELETE FROM guild_applications WHERE character_id=$1`, pkt.CharID)
|
||||
s.server.db.Exec(`INSERT INTO guild_characters (guild_id, character_id, order_index) VALUES ($1, $2, (SELECT MAX(order_index) + 1 FROM guild_characters WHERE guild_id = $1))`, guild.ID, pkt.CharID)
|
||||
mail = Mail{
|
||||
RecipientID: pkt.CharID,
|
||||
Subject: "Accepted!",
|
||||
Body: fmt.Sprintf("Your application to join 「%s」 was accepted.", guild.Name),
|
||||
IsSystemMessage: true,
|
||||
}
|
||||
case mhfpacket.OPERATE_GUILD_MEMBER_ACTION_REJECT:
|
||||
err = guild.RejectApplication(s, pkt.CharID)
|
||||
case mhfpacket.OperateGuildMemberReject:
|
||||
s.server.db.Exec(`DELETE FROM guild_applications WHERE character_id=$1 AND guild_id=$2`, pkt.CharID, guild.ID)
|
||||
mail = Mail{
|
||||
RecipientID: pkt.CharID,
|
||||
Subject: "Rejected",
|
||||
Body: fmt.Sprintf("Your application to join 「%s」 was rejected.", guild.Name),
|
||||
IsSystemMessage: true,
|
||||
}
|
||||
case mhfpacket.OPERATE_GUILD_MEMBER_ACTION_KICK:
|
||||
err = guild.RemoveCharacter(s, pkt.CharID)
|
||||
case mhfpacket.OperateGuildMemberKick:
|
||||
_ = guild.RemoveCharacter(s, pkt.CharID)
|
||||
mail = Mail{
|
||||
RecipientID: pkt.CharID,
|
||||
Subject: "Kicked",
|
||||
@@ -903,10 +863,8 @@ func handleMsgMhfOperateGuildMember(s *Session, p mhfpacket.MHFPacket) {
|
||||
s.logger.Warn(fmt.Sprintf("unhandled operateGuildMember action '%d'", pkt.Action))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
} else {
|
||||
mail.Send(s, nil)
|
||||
if mail.RecipientID != 0 {
|
||||
mail.Send(s)
|
||||
for _, channel := range s.server.Channels {
|
||||
for _, session := range channel.sessions {
|
||||
if session.charID == pkt.CharID {
|
||||
@@ -914,44 +872,28 @@ func handleMsgMhfOperateGuildMember(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
}
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfInfoGuild)
|
||||
|
||||
var guild *Guild
|
||||
var err error
|
||||
|
||||
var guild Guild
|
||||
if pkt.GuildID > 0 {
|
||||
guild, err = GetGuildInfoByID(s, pkt.GuildID)
|
||||
guild = GetGuildInfoByID(s, pkt.GuildID)
|
||||
} else {
|
||||
guild, err = GetGuildInfoByCharacterId(s, s.charID)
|
||||
guild = GetGuildInfoByCharacterId(s, s.charID)
|
||||
}
|
||||
|
||||
if err == nil && guild != nil {
|
||||
if guild.ID > 0 {
|
||||
s.prevGuildID = guild.ID
|
||||
|
||||
guildName := stringsupport.UTF8ToSJIS(guild.Name)
|
||||
guildComment := stringsupport.UTF8ToSJIS(guild.Comment)
|
||||
guildLeaderName := stringsupport.UTF8ToSJIS(guild.LeaderName)
|
||||
|
||||
characterGuildData, err := GetCharacterGuildData(s, s.charID)
|
||||
characterJoinedAt := uint32(0xFFFFFFFF)
|
||||
|
||||
if characterGuildData != nil && characterGuildData.JoinedAt != nil {
|
||||
characterJoinedAt = uint32(characterGuildData.JoinedAt.Unix())
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
resp := byteframe.NewByteFrame()
|
||||
resp.WriteUint32(0) // Count
|
||||
resp.WriteUint8(0) // Unk, read if count == 0.
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
return
|
||||
}
|
||||
characterGuildData := GetCharacterGuildData(s, s.charID)
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
@@ -973,16 +915,20 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
bf.WriteBool(!guild.Recruiting)
|
||||
|
||||
if characterGuildData == nil || characterGuildData.IsApplicant {
|
||||
bf.WriteUint16(0x00)
|
||||
if characterGuildData.CharID == 0 {
|
||||
bf.WriteUint16(0)
|
||||
} else if guild.LeaderCharID == s.charID {
|
||||
bf.WriteUint16(0x01)
|
||||
bf.WriteUint16(1)
|
||||
} else {
|
||||
bf.WriteUint16(0x02)
|
||||
bf.WriteUint16(2)
|
||||
}
|
||||
|
||||
bf.WriteUint32(uint32(guild.CreatedAt.Unix()))
|
||||
bf.WriteUint32(characterJoinedAt)
|
||||
if characterGuildData.JoinedAt.IsZero() {
|
||||
bf.WriteInt32(-1)
|
||||
} else {
|
||||
bf.WriteInt32(int32(characterGuildData.JoinedAt.Unix()))
|
||||
}
|
||||
bf.WriteUint8(uint8(len(guildName)))
|
||||
bf.WriteUint8(uint8(len(guildComment)))
|
||||
bf.WriteUint8(uint8(5)) // Length of unknown string below
|
||||
@@ -1028,8 +974,8 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint16(0) // Ignored
|
||||
|
||||
if guild.AllianceID > 0 {
|
||||
alliance, err := GetAllianceData(s, guild.AllianceID)
|
||||
if err != nil {
|
||||
alliance := GetAllianceData(s, guild.AllianceID)
|
||||
if alliance.ID == 0 {
|
||||
bf.WriteUint32(0) // Error, no alliance
|
||||
} else {
|
||||
bf.WriteUint32(alliance.ID)
|
||||
@@ -1089,10 +1035,8 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint32(0) // No alliance
|
||||
}
|
||||
|
||||
applicants, err := GetGuildMembers(s, guild.ID, true)
|
||||
if err != nil || (characterGuildData != nil && !characterGuildData.CanRecruit()) {
|
||||
bf.WriteUint16(0)
|
||||
} else {
|
||||
applicants := GetGuildApplications(s, guild.ID)
|
||||
if characterGuildData.CanRecruit() {
|
||||
bf.WriteUint16(uint16(len(applicants)))
|
||||
for _, applicant := range applicants {
|
||||
bf.WriteUint32(applicant.CharID)
|
||||
@@ -1101,6 +1045,8 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint16(applicant.GR)
|
||||
ps.Uint8(bf, applicant.Name, true)
|
||||
}
|
||||
} else {
|
||||
bf.WriteUint16(0)
|
||||
}
|
||||
|
||||
type UnkGuildInfo struct {
|
||||
@@ -1166,17 +1112,18 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateGuild)
|
||||
|
||||
var guilds []*Guild
|
||||
var alliances []*GuildAlliance
|
||||
var guilds []Guild
|
||||
var alliances []GuildAlliance
|
||||
var rows *sqlx.Rows
|
||||
var err error
|
||||
|
||||
if pkt.Type <= 8 {
|
||||
var tempGuilds []*Guild
|
||||
var tempGuilds []Guild
|
||||
rows, err = s.server.db.Queryx(guildInfoSelectQuery)
|
||||
if err == nil {
|
||||
for rows.Next() {
|
||||
guild, err := buildGuildObjectFromDbResult(rows, err, s)
|
||||
var guild Guild
|
||||
err = rows.StructScan(&guild)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
@@ -1184,26 +1131,26 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
}
|
||||
switch pkt.Type {
|
||||
case mhfpacket.ENUMERATE_GUILD_TYPE_GUILD_NAME:
|
||||
case mhfpacket.EnumerateGuildTypeGuildName:
|
||||
for _, guild := range tempGuilds {
|
||||
if strings.Contains(guild.Name, stringsupport.SJISToUTF8(pkt.Data2.ReadNullTerminatedBytes())) {
|
||||
guilds = append(guilds, guild)
|
||||
}
|
||||
}
|
||||
case mhfpacket.ENUMERATE_GUILD_TYPE_LEADER_NAME:
|
||||
case mhfpacket.EnumerateGuildTypeLeaderName:
|
||||
for _, guild := range tempGuilds {
|
||||
if strings.Contains(guild.LeaderName, stringsupport.SJISToUTF8(pkt.Data2.ReadNullTerminatedBytes())) {
|
||||
guilds = append(guilds, guild)
|
||||
}
|
||||
}
|
||||
case mhfpacket.ENUMERATE_GUILD_TYPE_LEADER_ID:
|
||||
case mhfpacket.EnumerateGuildTypeLeaderId:
|
||||
CID := pkt.Data1.ReadUint32()
|
||||
for _, guild := range tempGuilds {
|
||||
if guild.LeaderCharID == CID {
|
||||
guilds = append(guilds, guild)
|
||||
}
|
||||
}
|
||||
case mhfpacket.ENUMERATE_GUILD_TYPE_ORDER_MEMBERS:
|
||||
case mhfpacket.EnumerateGuildTypeOrderMembers:
|
||||
if pkt.Sorting {
|
||||
sort.Slice(tempGuilds, func(i, j int) bool {
|
||||
return tempGuilds[i].MemberCount > tempGuilds[j].MemberCount
|
||||
@@ -1214,7 +1161,7 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
})
|
||||
}
|
||||
guilds = tempGuilds
|
||||
case mhfpacket.ENUMERATE_GUILD_TYPE_ORDER_REGISTRATION:
|
||||
case mhfpacket.EnumerateGuildTypeOrderRegistration:
|
||||
if pkt.Sorting {
|
||||
sort.Slice(tempGuilds, func(i, j int) bool {
|
||||
return tempGuilds[i].CreatedAt.Unix() > tempGuilds[j].CreatedAt.Unix()
|
||||
@@ -1225,7 +1172,7 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
})
|
||||
}
|
||||
guilds = tempGuilds
|
||||
case mhfpacket.ENUMERATE_GUILD_TYPE_ORDER_RANK:
|
||||
case mhfpacket.EnumerateGuildTypeOrderRank:
|
||||
if pkt.Sorting {
|
||||
sort.Slice(tempGuilds, func(i, j int) bool {
|
||||
return tempGuilds[i].RankRP > tempGuilds[j].RankRP
|
||||
@@ -1236,7 +1183,7 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
})
|
||||
}
|
||||
guilds = tempGuilds
|
||||
case mhfpacket.ENUMERATE_GUILD_TYPE_MOTTO:
|
||||
case mhfpacket.EnumerateGuildTypeMotto:
|
||||
mainMotto := uint8(pkt.Data1.ReadUint16())
|
||||
subMotto := uint8(pkt.Data1.ReadUint16())
|
||||
for _, guild := range tempGuilds {
|
||||
@@ -1244,7 +1191,7 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
guilds = append(guilds, guild)
|
||||
}
|
||||
}
|
||||
case mhfpacket.ENUMERATE_GUILD_TYPE_RECRUITING:
|
||||
case mhfpacket.EnumerateGuildTypeRecruiting:
|
||||
recruitingMotto := uint8(pkt.Data1.ReadUint16())
|
||||
for _, guild := range tempGuilds {
|
||||
if guild.MainMotto == recruitingMotto {
|
||||
@@ -1255,35 +1202,39 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
|
||||
if pkt.Type > 8 {
|
||||
var tempAlliances []*GuildAlliance
|
||||
var tempAlliances []GuildAlliance
|
||||
rows, err = s.server.db.Queryx(allianceInfoSelectQuery)
|
||||
if err == nil {
|
||||
for rows.Next() {
|
||||
alliance, _ := buildAllianceObjectFromDbResult(rows, err, s)
|
||||
var alliance GuildAlliance
|
||||
err = rows.StructScan(&alliance)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
tempAlliances = append(tempAlliances, alliance)
|
||||
}
|
||||
}
|
||||
switch pkt.Type {
|
||||
case mhfpacket.ENUMERATE_ALLIANCE_TYPE_ALLIANCE_NAME:
|
||||
case mhfpacket.EnumerateAllianceTypeAllianceName:
|
||||
for _, alliance := range tempAlliances {
|
||||
if strings.Contains(alliance.Name, stringsupport.SJISToUTF8(pkt.Data2.ReadNullTerminatedBytes())) {
|
||||
alliances = append(alliances, alliance)
|
||||
}
|
||||
}
|
||||
case mhfpacket.ENUMERATE_ALLIANCE_TYPE_LEADER_NAME:
|
||||
case mhfpacket.EnumerateAllianceTypeLeaderName:
|
||||
for _, alliance := range tempAlliances {
|
||||
if strings.Contains(alliance.ParentGuild.LeaderName, stringsupport.SJISToUTF8(pkt.Data2.ReadNullTerminatedBytes())) {
|
||||
alliances = append(alliances, alliance)
|
||||
}
|
||||
}
|
||||
case mhfpacket.ENUMERATE_ALLIANCE_TYPE_LEADER_ID:
|
||||
case mhfpacket.EnumerateAllianceTypeLeaderId:
|
||||
CID := pkt.Data1.ReadUint32()
|
||||
for _, alliance := range tempAlliances {
|
||||
if alliance.ParentGuild.LeaderCharID == CID {
|
||||
alliances = append(alliances, alliance)
|
||||
}
|
||||
}
|
||||
case mhfpacket.ENUMERATE_ALLIANCE_TYPE_ORDER_MEMBERS:
|
||||
case mhfpacket.EnumerateAllianceTypeOrderMembers:
|
||||
if pkt.Sorting {
|
||||
sort.Slice(tempAlliances, func(i, j int) bool {
|
||||
return tempAlliances[i].TotalMembers > tempAlliances[j].TotalMembers
|
||||
@@ -1294,7 +1245,7 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
})
|
||||
}
|
||||
alliances = tempAlliances
|
||||
case mhfpacket.ENUMERATE_ALLIANCE_TYPE_ORDER_REGISTRATION:
|
||||
case mhfpacket.EnumerateAllianceTypeOrderRegistration:
|
||||
if pkt.Sorting {
|
||||
sort.Slice(tempAlliances, func(i, j int) bool {
|
||||
return tempAlliances[i].CreatedAt.Unix() > tempAlliances[j].CreatedAt.Unix()
|
||||
@@ -1369,26 +1320,13 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
func handleMsgMhfArrangeGuildMember(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfArrangeGuildMember)
|
||||
|
||||
guild, err := GetGuildInfoByID(s, pkt.GuildID)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error(
|
||||
"failed to respond to ArrangeGuildMember message",
|
||||
zap.Uint32("charID", s.charID),
|
||||
)
|
||||
guild := GetGuildInfoByID(s, pkt.GuildID)
|
||||
if guild.ID == 0 {
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
if guild.LeaderCharID != s.charID {
|
||||
s.logger.Error("non leader attempting to rearrange guild members!",
|
||||
zap.Uint32("charID", s.charID),
|
||||
zap.Uint32("guildID", guild.ID),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
err = guild.ArrangeCharacters(s, pkt.CharIDs)
|
||||
|
||||
err := guild.ArrangeCharacters(s, pkt.CharIDs)
|
||||
if err != nil {
|
||||
s.logger.Error(
|
||||
"failed to respond to ArrangeGuildMember message",
|
||||
@@ -1404,47 +1342,29 @@ func handleMsgMhfArrangeGuildMember(s *Session, p mhfpacket.MHFPacket) {
|
||||
func handleMsgMhfEnumerateGuildMember(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateGuildMember)
|
||||
|
||||
var guild *Guild
|
||||
var err error
|
||||
|
||||
var guild Guild
|
||||
if pkt.GuildID > 0 {
|
||||
guild, err = GetGuildInfoByID(s, pkt.GuildID)
|
||||
guild = GetGuildInfoByID(s, pkt.GuildID)
|
||||
} else {
|
||||
guild, err = GetGuildInfoByCharacterId(s, s.charID)
|
||||
guild = GetGuildInfoByCharacterId(s, s.charID)
|
||||
}
|
||||
|
||||
if guild != nil {
|
||||
isApplicant, _ := guild.HasApplicationForCharID(s, s.charID)
|
||||
if isApplicant {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 2))
|
||||
return
|
||||
}
|
||||
if guild.ID == 0 && s.prevGuildID > 0 {
|
||||
guild = GetGuildInfoByID(s, s.prevGuildID)
|
||||
}
|
||||
|
||||
if guild == nil && s.prevGuildID > 0 {
|
||||
guild, err = GetGuildInfoByID(s, s.prevGuildID)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
s.logger.Warn("failed to retrieve guild sending no result message")
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 2))
|
||||
return
|
||||
} else if guild == nil {
|
||||
if guild.ID == 0 {
|
||||
s.logger.Warn("failed to get guild")
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 2))
|
||||
return
|
||||
}
|
||||
|
||||
guildMembers, err := GetGuildMembers(s, guild.ID, false)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error("failed to retrieve guild")
|
||||
return
|
||||
guildMembers := GetGuildMembers(s, guild.ID)
|
||||
if len(guildMembers) == 0 {
|
||||
s.logger.Error("failed to get guild members")
|
||||
}
|
||||
|
||||
alliance, err := GetAllianceData(s, guild.AllianceID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get alliance data")
|
||||
return
|
||||
alliance := GetAllianceData(s, guild.AllianceID)
|
||||
if alliance.ID == 0 {
|
||||
s.logger.Error("failed to get alliance data")
|
||||
}
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
@@ -1481,37 +1401,30 @@ func handleMsgMhfEnumerateGuildMember(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint32(member.LastLogin)
|
||||
}
|
||||
|
||||
var allianceMembers []GuildMember
|
||||
if guild.AllianceID > 0 {
|
||||
bf.WriteUint16(alliance.TotalMembers - uint16(len(guildMembers)))
|
||||
if guild.ID != alliance.ParentGuildID {
|
||||
mems, err := GetGuildMembers(s, alliance.ParentGuildID, false)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, m := range mems {
|
||||
bf.WriteUint32(m.CharID)
|
||||
members := GetGuildMembers(s, alliance.ParentGuildID)
|
||||
for i := range members {
|
||||
allianceMembers = append(allianceMembers, members[i])
|
||||
}
|
||||
}
|
||||
if guild.ID != alliance.SubGuild1ID {
|
||||
mems, err := GetGuildMembers(s, alliance.SubGuild1ID, false)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, m := range mems {
|
||||
bf.WriteUint32(m.CharID)
|
||||
members := GetGuildMembers(s, alliance.SubGuild1ID)
|
||||
for i := range members {
|
||||
allianceMembers = append(allianceMembers, members[i])
|
||||
}
|
||||
}
|
||||
if guild.ID != alliance.SubGuild2ID {
|
||||
mems, err := GetGuildMembers(s, alliance.SubGuild2ID, false)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, m := range mems {
|
||||
bf.WriteUint32(m.CharID)
|
||||
members := GetGuildMembers(s, alliance.SubGuild2ID)
|
||||
for i := range members {
|
||||
allianceMembers = append(allianceMembers, members[i])
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bf.WriteUint16(0)
|
||||
}
|
||||
bf.WriteUint16(uint16(len(allianceMembers)))
|
||||
for i := range allianceMembers {
|
||||
bf.WriteUint32(allianceMembers[i].CharID)
|
||||
}
|
||||
|
||||
for _, member := range guildMembers {
|
||||
@@ -1525,23 +1438,27 @@ func handleMsgMhfEnumerateGuildMember(s *Session, p mhfpacket.MHFPacket) {
|
||||
func handleMsgMhfGetGuildManageRight(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetGuildManageRight)
|
||||
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if guild == nil && s.prevGuildID != 0 {
|
||||
guild, err = GetGuildInfoByID(s, s.prevGuildID)
|
||||
guild := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if guild.ID == 0 && s.prevGuildID != 0 {
|
||||
guild = GetGuildInfoByID(s, s.prevGuildID)
|
||||
s.prevGuildID = 0
|
||||
if guild == nil || err != nil {
|
||||
if guild.ID == 0 {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
members := GetGuildMembers(s, guild.ID)
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(uint32(guild.MemberCount))
|
||||
members, _ := GetGuildMembers(s, guild.ID, false)
|
||||
for _, member := range members {
|
||||
bf.WriteUint32(member.CharID)
|
||||
bf.WriteBool(member.Recruiter)
|
||||
bf.WriteBytes(make([]byte, 3))
|
||||
if members != nil {
|
||||
bf.WriteUint32(uint32(len(members)))
|
||||
for _, member := range members {
|
||||
bf.WriteUint32(member.CharID)
|
||||
bf.WriteBool(member.Recruiter)
|
||||
bf.WriteBytes(make([]byte, 3))
|
||||
}
|
||||
} else {
|
||||
bf.WriteUint32(0)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
@@ -1554,25 +1471,23 @@ func handleMsgMhfGetUdGuildMapInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||
func handleMsgMhfGetGuildTargetMemberNum(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetGuildTargetMemberNum)
|
||||
|
||||
var guild *Guild
|
||||
var err error
|
||||
|
||||
if pkt.GuildID == 0x0 {
|
||||
guild, err = GetGuildInfoByCharacterId(s, s.charID)
|
||||
var guild Guild
|
||||
if pkt.GuildID == 0 {
|
||||
guild = GetGuildInfoByCharacterId(s, s.charID)
|
||||
} else {
|
||||
guild, err = GetGuildInfoByID(s, pkt.GuildID)
|
||||
}
|
||||
|
||||
if err != nil || guild == nil {
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x02})
|
||||
return
|
||||
guild = GetGuildInfoByID(s, pkt.GuildID)
|
||||
}
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
bf.WriteUint16(0x0)
|
||||
bf.WriteUint16(guild.MemberCount - 1)
|
||||
if guild.ID == 0 {
|
||||
bf.WriteUint32(2)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
return
|
||||
}
|
||||
|
||||
bf.WriteUint16(0)
|
||||
bf.WriteUint16(guild.MemberCount - 1)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
@@ -1609,32 +1524,14 @@ func handleMsgMhfUpdateGuildItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
func handleMsgMhfUpdateGuildIcon(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfUpdateGuildIcon)
|
||||
|
||||
guild, err := GetGuildInfoByID(s, pkt.GuildID)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
characterInfo, err := GetCharacterGuildData(s, s.charID)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if !characterInfo.IsSubLeader() && !characterInfo.IsLeader {
|
||||
s.logger.Warn(
|
||||
"character without leadership attempting to update guild icon",
|
||||
zap.Uint32("guildID", guild.ID),
|
||||
zap.Uint32("charID", s.charID),
|
||||
)
|
||||
guild := GetGuildInfoByID(s, pkt.GuildID)
|
||||
if guild.ID == 0 {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
icon := &GuildIcon{}
|
||||
|
||||
icon.Parts = make([]GuildIconPart, len(pkt.IconParts))
|
||||
|
||||
for i, p := range pkt.IconParts {
|
||||
icon.Parts[i] = GuildIconPart{
|
||||
Index: p.Index,
|
||||
@@ -1652,7 +1549,7 @@ func handleMsgMhfUpdateGuildIcon(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
guild.Icon = icon
|
||||
|
||||
err = guild.Save(s)
|
||||
err := guild.Save(s)
|
||||
|
||||
if err != nil {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
@@ -1756,7 +1653,7 @@ type GuildMeal struct {
|
||||
|
||||
func handleMsgMhfLoadGuildCooking(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfLoadGuildCooking)
|
||||
guild, _ := GetGuildInfoByCharacterId(s, s.charID)
|
||||
guild := GetGuildInfoByCharacterId(s, s.charID)
|
||||
data, err := s.server.db.Queryx("SELECT id, meal_id, level, created_at FROM guild_meals WHERE guild_id = $1", guild.ID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get guild meals from db", zap.Error(err))
|
||||
@@ -1787,7 +1684,7 @@ func handleMsgMhfLoadGuildCooking(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
func handleMsgMhfRegistGuildCooking(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfRegistGuildCooking)
|
||||
guild, _ := GetGuildInfoByCharacterId(s, s.charID)
|
||||
guild := GetGuildInfoByCharacterId(s, s.charID)
|
||||
startTime := TimeAdjusted().Add(time.Duration(s.server.erupeConfig.GameplayOptions.ClanMealDuration-3600) * time.Second)
|
||||
if pkt.OverwriteID != 0 {
|
||||
s.server.db.Exec("UPDATE guild_meals SET meal_id = $1, level = $2, created_at = $3 WHERE id = $4", pkt.MealID, pkt.Success, startTime, pkt.OverwriteID)
|
||||
@@ -1852,10 +1749,10 @@ func handleMsgMhfGuildHuntdata(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint8(count)
|
||||
}
|
||||
case 2: // Check
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if err == nil {
|
||||
guild := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if guild.ID > 0 {
|
||||
var count uint8
|
||||
err = s.server.db.QueryRow(`SELECT COUNT(*) FROM kill_logs kl
|
||||
err := s.server.db.QueryRow(`SELECT COUNT(*) FROM kill_logs kl
|
||||
INNER JOIN guild_characters gc ON kl.character_id = gc.character_id
|
||||
WHERE gc.guild_id=$1
|
||||
AND kl.timestamp >= (SELECT box_claimed FROM guild_characters WHERE character_id=$2)
|
||||
@@ -1884,13 +1781,13 @@ type MessageBoardPost struct {
|
||||
|
||||
func handleMsgMhfEnumerateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateGuildMessageBoard)
|
||||
guild, _ := GetGuildInfoByCharacterId(s, s.charID)
|
||||
guild := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if pkt.BoardType == 1 {
|
||||
pkt.MaxPosts = 4
|
||||
}
|
||||
msgs, err := s.server.db.Queryx("SELECT id, stamp_id, title, body, author_id, created_at, liked_by FROM guild_posts WHERE guild_id = $1 AND post_type = $2 ORDER BY created_at DESC", guild.ID, int(pkt.BoardType))
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get guild messages from db", zap.Error(err))
|
||||
s.logger.Error("failed to get guild messages from db", zap.Error(err))
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
@@ -1922,12 +1819,8 @@ func handleMsgMhfEnumerateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
func handleMsgMhfUpdateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfUpdateGuildMessageBoard)
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
applicant := false
|
||||
if guild != nil {
|
||||
applicant, _ = guild.HasApplicationForCharID(s, s.charID)
|
||||
}
|
||||
if err != nil || guild == nil || applicant {
|
||||
guild := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if guild.ID == 0 || IsGuildApplicant(s, s.charID) {
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
@@ -2011,12 +1904,13 @@ func handleMsgMhfAcquireMonthlyItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
func handleMsgMhfEnumerateInvGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateInvGuild)
|
||||
stubEnumerateNoResults(s, pkt.AckHandle)
|
||||
bf := byteframe.NewByteFrame()
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfOperationInvGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfOperationInvGuild)
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfUpdateGuildcard(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
@@ -20,7 +20,7 @@ type GuildAdventure struct {
|
||||
|
||||
func handleMsgMhfLoadGuildAdventure(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfLoadGuildAdventure)
|
||||
guild, _ := GetGuildInfoByCharacterId(s, s.charID)
|
||||
guild := GetGuildInfoByCharacterId(s, s.charID)
|
||||
data, err := s.server.db.Queryx("SELECT id, destination, charge, depart, return, collected_by FROM guild_adventures WHERE guild_id = $1", guild.ID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get guild adventures from db", zap.Error(err))
|
||||
@@ -51,7 +51,7 @@ func handleMsgMhfLoadGuildAdventure(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
func handleMsgMhfRegistGuildAdventure(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfRegistGuildAdventure)
|
||||
guild, _ := GetGuildInfoByCharacterId(s, s.charID)
|
||||
guild := GetGuildInfoByCharacterId(s, s.charID)
|
||||
_, err := s.server.db.Exec("INSERT INTO guild_adventures (guild_id, destination, depart, return) VALUES ($1, $2, $3, $4)", guild.ID, pkt.Destination, TimeAdjusted().Unix(), TimeAdjusted().Add(6*time.Hour).Unix())
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to register guild adventure", zap.Error(err))
|
||||
@@ -86,7 +86,7 @@ func handleMsgMhfChargeGuildAdventure(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
func handleMsgMhfRegistGuildAdventureDiva(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfRegistGuildAdventureDiva)
|
||||
guild, _ := GetGuildInfoByCharacterId(s, s.charID)
|
||||
guild := GetGuildInfoByCharacterId(s, s.charID)
|
||||
_, err := s.server.db.Exec("INSERT INTO guild_adventures (guild_id, destination, charge, depart, return) VALUES ($1, $2, $3, $4, $5)", guild.ID, pkt.Destination, pkt.Charge, TimeAdjusted().Unix(), TimeAdjusted().Add(1*time.Hour).Unix())
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to register guild adventure", zap.Error(err))
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"time"
|
||||
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
@@ -43,66 +42,36 @@ type GuildAlliance struct {
|
||||
SubGuild2 Guild
|
||||
}
|
||||
|
||||
func GetAllianceData(s *Session, AllianceID uint32) (*GuildAlliance, error) {
|
||||
rows, err := s.server.db.Queryx(fmt.Sprintf(`
|
||||
func GetAllianceData(s *Session, AllianceID uint32) GuildAlliance {
|
||||
var alliance GuildAlliance
|
||||
err := s.server.db.QueryRowx(fmt.Sprintf(`
|
||||
%s
|
||||
WHERE ga.id = $1
|
||||
`, allianceInfoSelectQuery), AllianceID)
|
||||
`, allianceInfoSelectQuery), AllianceID).StructScan(&alliance)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to retrieve alliance data from database", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
hasRow := rows.Next()
|
||||
if !hasRow {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return buildAllianceObjectFromDbResult(rows, err, s)
|
||||
}
|
||||
|
||||
func buildAllianceObjectFromDbResult(result *sqlx.Rows, err error, s *Session) (*GuildAlliance, error) {
|
||||
alliance := &GuildAlliance{}
|
||||
|
||||
err = result.StructScan(alliance)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error("failed to retrieve alliance from database", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
parentGuild, err := GetGuildInfoByID(s, alliance.ParentGuildID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get parent guild info", zap.Error(err))
|
||||
return nil, err
|
||||
s.logger.Error("failed to retrieve alliance data", zap.Error(err))
|
||||
} else {
|
||||
alliance.ParentGuild = *parentGuild
|
||||
alliance.TotalMembers += parentGuild.MemberCount
|
||||
}
|
||||
|
||||
if alliance.SubGuild1ID > 0 {
|
||||
subGuild1, err := GetGuildInfoByID(s, alliance.SubGuild1ID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get sub guild 1 info", zap.Error(err))
|
||||
return nil, err
|
||||
} else {
|
||||
alliance.SubGuild1 = *subGuild1
|
||||
alliance.TotalMembers += subGuild1.MemberCount
|
||||
parentGuild := GetGuildInfoByID(s, alliance.ParentGuildID)
|
||||
if parentGuild.ID > 0 {
|
||||
alliance.ParentGuild = parentGuild
|
||||
alliance.TotalMembers += parentGuild.MemberCount
|
||||
}
|
||||
if alliance.SubGuild1ID > 0 {
|
||||
subGuild1 := GetGuildInfoByID(s, alliance.SubGuild1ID)
|
||||
if subGuild1.ID > 0 {
|
||||
alliance.SubGuild1 = subGuild1
|
||||
alliance.TotalMembers += subGuild1.MemberCount
|
||||
}
|
||||
}
|
||||
if alliance.SubGuild2ID > 0 {
|
||||
subGuild2 := GetGuildInfoByID(s, alliance.SubGuild2ID)
|
||||
if subGuild2.ID > 0 {
|
||||
alliance.SubGuild2 = subGuild2
|
||||
alliance.TotalMembers += subGuild2.MemberCount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if alliance.SubGuild2ID > 0 {
|
||||
subGuild2, err := GetGuildInfoByID(s, alliance.SubGuild2ID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get sub guild 2 info", zap.Error(err))
|
||||
return nil, err
|
||||
} else {
|
||||
alliance.SubGuild2 = *subGuild2
|
||||
alliance.TotalMembers += subGuild2.MemberCount
|
||||
}
|
||||
}
|
||||
|
||||
return alliance, nil
|
||||
return alliance
|
||||
}
|
||||
|
||||
func handleMsgMhfCreateJoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -117,19 +86,19 @@ func handleMsgMhfCreateJoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
func handleMsgMhfOperateJoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfOperateJoint)
|
||||
|
||||
guild, err := GetGuildInfoByID(s, pkt.GuildID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get guild info", zap.Error(err))
|
||||
guild := GetGuildInfoByID(s, pkt.GuildID)
|
||||
if guild.ID == 0 {
|
||||
s.logger.Error("failed to get guild info")
|
||||
}
|
||||
alliance, err := GetAllianceData(s, pkt.AllianceID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get alliance info", zap.Error(err))
|
||||
alliance := GetAllianceData(s, pkt.AllianceID)
|
||||
if alliance.ID == 0 {
|
||||
s.logger.Error("failed to get alliance info")
|
||||
}
|
||||
|
||||
switch pkt.Action {
|
||||
case mhfpacket.OPERATE_JOINT_DISBAND:
|
||||
case mhfpacket.OperateJointDisband:
|
||||
if guild.LeaderCharID == s.charID && alliance.ParentGuildID == guild.ID {
|
||||
_, err = s.server.db.Exec("DELETE FROM guild_alliances WHERE id=$1", alliance.ID)
|
||||
_, err := s.server.db.Exec("DELETE FROM guild_alliances WHERE id=$1", alliance.ID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to disband alliance", zap.Error(err))
|
||||
}
|
||||
@@ -142,7 +111,7 @@ func handleMsgMhfOperateJoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
)
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
case mhfpacket.OPERATE_JOINT_LEAVE:
|
||||
case mhfpacket.OperateJointLeave:
|
||||
if guild.LeaderCharID == s.charID {
|
||||
if guild.ID == alliance.SubGuild1ID && alliance.SubGuild2ID > 0 {
|
||||
s.server.db.Exec(`UPDATE guild_alliances SET sub1_id = sub2_id, sub2_id = NULL WHERE id = $1`, alliance.ID)
|
||||
@@ -160,7 +129,7 @@ func handleMsgMhfOperateJoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
)
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
case mhfpacket.OPERATE_JOINT_KICK:
|
||||
case mhfpacket.OperateJointKick:
|
||||
if alliance.ParentGuild.LeaderCharID == s.charID {
|
||||
kickedGuildID := pkt.Data1.ReadUint32()
|
||||
if kickedGuildID == alliance.SubGuild1ID && alliance.SubGuild2ID > 0 {
|
||||
@@ -188,8 +157,8 @@ func handleMsgMhfOperateJoint(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 {
|
||||
alliance := GetAllianceData(s, pkt.AllianceID)
|
||||
if alliance.ID == 0 {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
} else {
|
||||
bf.WriteUint32(alliance.ID)
|
||||
|
||||
@@ -4,49 +4,44 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type GuildMember struct {
|
||||
GuildID uint32 `db:"guild_id"`
|
||||
CharID uint32 `db:"character_id"`
|
||||
JoinedAt *time.Time `db:"joined_at"`
|
||||
Souls uint32 `db:"souls"`
|
||||
RPToday uint16 `db:"rp_today"`
|
||||
RPYesterday uint16 `db:"rp_yesterday"`
|
||||
Name string `db:"name"`
|
||||
IsApplicant bool `db:"is_applicant"`
|
||||
OrderIndex uint16 `db:"order_index"`
|
||||
LastLogin uint32 `db:"last_login"`
|
||||
Recruiter bool `db:"recruiter"`
|
||||
AvoidLeadership bool `db:"avoid_leadership"`
|
||||
IsLeader bool `db:"is_leader"`
|
||||
HR uint16 `db:"hr"`
|
||||
GR uint16 `db:"gr"`
|
||||
WeaponID uint16 `db:"weapon_id"`
|
||||
WeaponType uint8 `db:"weapon_type"`
|
||||
GuildID uint32 `db:"guild_id"`
|
||||
CharID uint32 `db:"character_id"`
|
||||
JoinedAt time.Time `db:"joined_at"`
|
||||
Souls uint32 `db:"souls"`
|
||||
RPToday uint16 `db:"rp_today"`
|
||||
RPYesterday uint16 `db:"rp_yesterday"`
|
||||
Name string `db:"name"`
|
||||
OrderIndex uint16 `db:"order_index"`
|
||||
LastLogin uint32 `db:"last_login"`
|
||||
Recruiter bool `db:"recruiter"`
|
||||
AvoidLeadership bool `db:"avoid_leadership"`
|
||||
HR uint16 `db:"hr"`
|
||||
GR uint16 `db:"gr"`
|
||||
WeaponID uint16 `db:"weapon_id"`
|
||||
WeaponType uint8 `db:"weapon_type"`
|
||||
}
|
||||
|
||||
func (gm *GuildMember) CanRecruit() bool {
|
||||
func (gm GuildMember) CanRecruit() bool {
|
||||
if gm.Recruiter {
|
||||
return true
|
||||
}
|
||||
if gm.OrderIndex <= 3 {
|
||||
return true
|
||||
}
|
||||
if gm.IsLeader {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return gm.IsSubLeader()
|
||||
}
|
||||
|
||||
func (gm *GuildMember) IsSubLeader() bool {
|
||||
func (gm GuildMember) IsSubLeader() bool {
|
||||
return gm.OrderIndex <= 3
|
||||
}
|
||||
|
||||
func (gm *GuildMember) Save(s *Session) error {
|
||||
_, err := s.server.db.Exec("UPDATE guild_characters SET avoid_leadership=$1, order_index=$2 WHERE character_id=$3", gm.AvoidLeadership, gm.OrderIndex, gm.CharID)
|
||||
func (gm GuildMember) IsLeader() bool {
|
||||
return gm.OrderIndex == 1
|
||||
}
|
||||
|
||||
func (gm GuildMember) Save(s *Session) error {
|
||||
_, err := s.server.db.Exec("UPDATE guild_characters SET order_index=$1 WHERE character_id=$2", gm.OrderIndex, gm.CharID)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error(
|
||||
@@ -61,7 +56,6 @@ func (gm *GuildMember) Save(s *Session) error {
|
||||
}
|
||||
|
||||
const guildMembersSelectSQL = `
|
||||
SELECT * FROM (
|
||||
SELECT
|
||||
g.id AS guild_id,
|
||||
joined_at,
|
||||
@@ -77,71 +71,71 @@ SELECT * FROM (
|
||||
c.hr,
|
||||
c.gr,
|
||||
c.weapon_id,
|
||||
c.weapon_type,
|
||||
EXISTS(SELECT 1 FROM guild_applications ga WHERE ga.character_id=c.id AND application_type='applied') AS is_applicant,
|
||||
CASE WHEN g.leader_id = c.id THEN true ELSE false END AS is_leader
|
||||
c.weapon_type
|
||||
FROM guild_characters gc
|
||||
LEFT JOIN characters c ON c.id = gc.character_id
|
||||
LEFT JOIN guilds g ON g.id = gc.guild_id
|
||||
) AS subquery
|
||||
`
|
||||
|
||||
func GetGuildMembers(s *Session, guildID uint32, applicants bool) ([]*GuildMember, error) {
|
||||
func GetGuildApplications(s *Session, guildID uint32) []GuildApplication {
|
||||
var applications []GuildApplication
|
||||
var application GuildApplication
|
||||
rows, err := s.server.db.Queryx(`SELECT ga.character_id, ga.created_at, c.hr, c.gr, c.name FROM guild_applications ga LEFT JOIN characters c ON c.id = ga.character_id WHERE ga.guild_id=$1`, guildID)
|
||||
if err == nil {
|
||||
for rows.Next() {
|
||||
err = rows.StructScan(&application)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
applications = append(applications, application)
|
||||
}
|
||||
}
|
||||
return applications
|
||||
}
|
||||
|
||||
func GetGuildInvites(s *Session, guildID uint32) []GuildInvite {
|
||||
var invites []GuildInvite
|
||||
var invite GuildInvite
|
||||
rows, err := s.server.db.Queryx(`SELECT gi.character_id, gi.id, gi.created_at, gi.actor_id, c.hr, c.gr, c.name FROM guild_invites gi LEFT JOIN characters c ON c.id = gi.character_id WHERE gi.guild_id=$1`, guildID)
|
||||
if err == nil {
|
||||
for rows.Next() {
|
||||
err = rows.StructScan(&invite)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
invites = append(invites, invite)
|
||||
}
|
||||
}
|
||||
return invites
|
||||
}
|
||||
|
||||
func GetGuildMembers(s *Session, guildID uint32) []GuildMember {
|
||||
var members []GuildMember
|
||||
var member GuildMember
|
||||
rows, err := s.server.db.Queryx(fmt.Sprintf(`
|
||||
%s
|
||||
WHERE guild_id = $1 AND is_applicant = $2
|
||||
`, guildMembersSelectSQL), guildID, applicants)
|
||||
|
||||
WHERE guild_id = $1
|
||||
`, guildMembersSelectSQL), guildID)
|
||||
if err != nil {
|
||||
s.logger.Error("failed to retrieve membership data for guild", zap.Error(err), zap.Uint32("guildID", guildID))
|
||||
return nil, err
|
||||
s.logger.Error("Failed to retrieve membership data for guild", zap.Error(err), zap.Uint32("guildID", guildID))
|
||||
return members
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
members := make([]*GuildMember, 0)
|
||||
|
||||
for rows.Next() {
|
||||
member, err := buildGuildMemberObjectFromDBResult(rows, err, s)
|
||||
|
||||
err = rows.StructScan(&member)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
continue
|
||||
}
|
||||
|
||||
members = append(members, member)
|
||||
}
|
||||
|
||||
return members, nil
|
||||
return members
|
||||
}
|
||||
|
||||
func GetCharacterGuildData(s *Session, charID uint32) (*GuildMember, error) {
|
||||
rows, err := s.server.db.Queryx(fmt.Sprintf("%s WHERE character_id=$1", guildMembersSelectSQL), charID)
|
||||
|
||||
func GetCharacterGuildData(s *Session, charID uint32) GuildMember {
|
||||
var member GuildMember
|
||||
err := s.server.db.QueryRowx(fmt.Sprintf("%s WHERE character_id=$1", guildMembersSelectSQL), charID).StructScan(&member)
|
||||
if err != nil {
|
||||
s.logger.Error(fmt.Sprintf("failed to retrieve membership data for character '%d'", charID))
|
||||
return nil, err
|
||||
s.logger.Error("Failed to retrieve membership data for character", zap.Error(err), zap.Uint32("charID", charID))
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
hasRow := rows.Next()
|
||||
|
||||
if !hasRow {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return buildGuildMemberObjectFromDBResult(rows, err, s)
|
||||
}
|
||||
|
||||
func buildGuildMemberObjectFromDBResult(rows *sqlx.Rows, err error, s *Session) (*GuildMember, error) {
|
||||
memberData := &GuildMember{}
|
||||
|
||||
err = rows.StructScan(&memberData)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error("failed to retrieve guild data from database", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return memberData, nil
|
||||
return member
|
||||
}
|
||||
|
||||
@@ -5,57 +5,18 @@ import (
|
||||
"erupe-ce/common/stringsupport"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"fmt"
|
||||
"go.uber.org/zap"
|
||||
"io"
|
||||
)
|
||||
|
||||
func handleMsgMhfPostGuildScout(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfPostGuildScout)
|
||||
|
||||
actorCharGuildData, err := GetCharacterGuildData(s, s.charID)
|
||||
|
||||
if err != nil {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if actorCharGuildData == nil || !actorCharGuildData.CanRecruit() {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
guild := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if guild.ID == 0 {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
guildInfo, err := GetGuildInfoByID(s, actorCharGuildData.GuildID)
|
||||
|
||||
if err != nil {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
panic(err)
|
||||
}
|
||||
|
||||
hasApplication, err := guildInfo.HasApplicationForCharID(s, pkt.CharID)
|
||||
|
||||
if err != nil {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if hasApplication {
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x04})
|
||||
return
|
||||
}
|
||||
|
||||
transaction, err := s.server.db.Begin()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = guildInfo.CreateApplication(s, pkt.CharID, GuildApplicationTypeInvited, transaction)
|
||||
|
||||
if err != nil {
|
||||
rollbackTransaction(s, transaction)
|
||||
doAckBufFail(s, pkt.AckHandle, nil)
|
||||
panic(err)
|
||||
}
|
||||
s.server.db.Exec(`INSERT INTO guild_invites (guild_id, character_id, actor_id) VALUES ($1, $2, $3)`, s.charID, pkt.CharID, guild.ID)
|
||||
|
||||
mail := &Mail{
|
||||
SenderID: s.charID,
|
||||
@@ -63,85 +24,33 @@ func handleMsgMhfPostGuildScout(s *Session, p mhfpacket.MHFPacket) {
|
||||
Subject: s.server.i18n.guild.invite.title,
|
||||
Body: fmt.Sprintf(
|
||||
s.server.i18n.guild.invite.body,
|
||||
guildInfo.Name,
|
||||
guild.Name,
|
||||
),
|
||||
IsGuildInvite: true,
|
||||
}
|
||||
|
||||
err = mail.Send(s, transaction)
|
||||
|
||||
if err != nil {
|
||||
rollbackTransaction(s, transaction)
|
||||
doAckBufFail(s, pkt.AckHandle, nil)
|
||||
return
|
||||
}
|
||||
|
||||
err = transaction.Commit()
|
||||
|
||||
if err != nil {
|
||||
doAckBufFail(s, pkt.AckHandle, nil)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
mail.Send(s)
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfCancelGuildScout(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfCancelGuildScout)
|
||||
|
||||
guildCharData, err := GetCharacterGuildData(s, s.charID)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if guildCharData == nil || !guildCharData.CanRecruit() {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
guild, err := GetGuildInfoByID(s, guildCharData.GuildID)
|
||||
|
||||
if err != nil {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
err = guild.CancelInvitation(s, pkt.InvitationID)
|
||||
|
||||
if err != nil {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
s.server.db.Exec(`DELETE FROM guild_invites WHERE id=$1`, pkt.InvitationID)
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfAnswerGuildScout(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfAnswerGuildScout)
|
||||
bf := byteframe.NewByteFrame()
|
||||
guild, err := GetGuildInfoByCharacterId(s, pkt.LeaderID)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
app, err := guild.GetApplicationForCharID(s, s.charID, GuildApplicationTypeInvited)
|
||||
|
||||
if app == nil || err != nil {
|
||||
s.logger.Warn(
|
||||
"Guild invite missing, deleted?",
|
||||
zap.Error(err),
|
||||
zap.Uint32("guildID", guild.ID),
|
||||
zap.Uint32("charID", s.charID),
|
||||
)
|
||||
bf.WriteUint32(7)
|
||||
bf.WriteUint32(guild.ID)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
guild := GetGuildInfoByCharacterId(s, pkt.LeaderID)
|
||||
if guild.ID == 0 {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
var mail []Mail
|
||||
var err error
|
||||
if pkt.Answer {
|
||||
err = guild.AcceptApplication(s, s.charID)
|
||||
mail = append(mail, Mail{
|
||||
@@ -182,7 +91,7 @@ func handleMsgMhfAnswerGuildScout(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint32(guild.ID)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
for _, m := range mail {
|
||||
m.Send(s, nil)
|
||||
m.Send(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -190,121 +99,46 @@ func handleMsgMhfAnswerGuildScout(s *Session, p mhfpacket.MHFPacket) {
|
||||
func handleMsgMhfGetGuildScoutList(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetGuildScoutList)
|
||||
|
||||
guildInfo, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
|
||||
if guildInfo == nil && s.prevGuildID == 0 {
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
guild := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if guild.ID == 0 && s.prevGuildID == 0 {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
} else {
|
||||
guildInfo, err = GetGuildInfoByID(s, s.prevGuildID)
|
||||
if guildInfo == nil || err != nil {
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
guild = GetGuildInfoByID(s, s.prevGuildID)
|
||||
if guild.ID == 0 {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
rows, err := s.server.db.Queryx(`
|
||||
SELECT c.id, c.name, c.hr, c.gr, ga.actor_id
|
||||
FROM guild_applications ga
|
||||
JOIN characters c ON c.id = ga.character_id
|
||||
WHERE ga.guild_id = $1 AND ga.application_type = 'invited'
|
||||
`, guildInfo.ID)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error("failed to retrieve scouted characters", zap.Error(err))
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
invites := GetGuildInvites(s, guild.ID)
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
bf.SetBE()
|
||||
|
||||
// Result count, we will overwrite this later
|
||||
bf.WriteUint32(0x00)
|
||||
|
||||
count := uint32(0)
|
||||
|
||||
for rows.Next() {
|
||||
var charName string
|
||||
var charID, actorID uint32
|
||||
var HR, GR uint16
|
||||
|
||||
err = rows.Scan(&charID, &charName, &HR, &GR, &actorID)
|
||||
|
||||
if err != nil {
|
||||
doAckSimpleFail(s, pkt.AckHandle, nil)
|
||||
continue
|
||||
}
|
||||
|
||||
// This seems to be used as a unique ID for the invitation sent
|
||||
// we can just use the charID and then filter on guild_id+charID when performing operations
|
||||
// this might be a problem later with mails sent referencing IDs but we'll see.
|
||||
bf.WriteUint32(charID)
|
||||
bf.WriteUint32(actorID)
|
||||
bf.WriteUint32(charID)
|
||||
bf.WriteUint32(uint32(TimeAdjusted().Unix()))
|
||||
bf.WriteUint16(HR) // HR?
|
||||
bf.WriteUint16(GR) // GR?
|
||||
bf.WriteBytes(stringsupport.PaddedString(charName, 32, true))
|
||||
count++
|
||||
bf.WriteUint32(uint32(len(invites)))
|
||||
for _, invite := range invites {
|
||||
bf.WriteUint32(invite.ID)
|
||||
bf.WriteUint32(invite.ActorID)
|
||||
bf.WriteUint32(invite.CharID)
|
||||
bf.WriteUint32(uint32(invite.InvitedAt.Unix()))
|
||||
bf.WriteUint16(invite.HR)
|
||||
bf.WriteUint16(invite.GR)
|
||||
bf.WriteBytes(stringsupport.PaddedString(invite.Name, 32, true))
|
||||
}
|
||||
|
||||
_, err = bf.Seek(0, io.SeekStart)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
bf.WriteUint32(count)
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfGetRejectGuildScout(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetRejectGuildScout)
|
||||
|
||||
row := s.server.db.QueryRow("SELECT restrict_guild_scout FROM characters WHERE id=$1", s.charID)
|
||||
|
||||
var currentStatus bool
|
||||
|
||||
err := row.Scan(¤tStatus)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error(
|
||||
"failed to retrieve character guild scout status",
|
||||
zap.Error(err),
|
||||
zap.Uint32("charID", s.charID),
|
||||
)
|
||||
doAckSimpleFail(s, pkt.AckHandle, nil)
|
||||
return
|
||||
}
|
||||
|
||||
response := uint8(0x00)
|
||||
|
||||
s.server.db.QueryRow(`SELECT restrict_guild_scout FROM characters WHERE id=$1`, s.charID).Scan(¤tStatus)
|
||||
if currentStatus {
|
||||
response = 0x01
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01})
|
||||
} else {
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, response})
|
||||
}
|
||||
|
||||
func handleMsgMhfSetRejectGuildScout(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSetRejectGuildScout)
|
||||
|
||||
_, err := s.server.db.Exec("UPDATE characters SET restrict_guild_scout=$1 WHERE id=$2", pkt.Reject, s.charID)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error(
|
||||
"failed to update character guild scout status",
|
||||
zap.Error(err),
|
||||
zap.Uint32("charID", s.charID),
|
||||
)
|
||||
doAckSimpleFail(s, pkt.AckHandle, nil)
|
||||
return
|
||||
}
|
||||
|
||||
s.server.db.Exec(`UPDATE characters SET restrict_guild_scout=$1 WHERE id=$2`, pkt.Reject, s.charID)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, nil)
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@ type TreasureHunt struct {
|
||||
|
||||
func handleMsgMhfEnumerateGuildTresure(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateGuildTresure)
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if err != nil || guild == nil {
|
||||
guild := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if guild.ID == 0 {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
@@ -32,7 +32,7 @@ func handleMsgMhfEnumerateGuildTresure(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
switch pkt.MaxHunts {
|
||||
case 1:
|
||||
err = s.server.db.QueryRowx(`SELECT id, host_id, destination, level, start, hunt_data FROM guild_hunts WHERE host_id=$1 AND acquired=FALSE`, s.charID).StructScan(&hunt)
|
||||
err := s.server.db.QueryRowx(`SELECT id, host_id, destination, level, start, hunt_data FROM guild_hunts WHERE host_id=$1 AND acquired=FALSE`, s.charID).StructScan(&hunt)
|
||||
if err == nil {
|
||||
hunts = append(hunts, hunt)
|
||||
}
|
||||
@@ -83,8 +83,8 @@ func handleMsgMhfRegistGuildTresure(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfRegistGuildTresure)
|
||||
bf := byteframe.NewByteFrameFromBytes(pkt.Data)
|
||||
huntData := byteframe.NewByteFrame()
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if err != nil || guild == nil {
|
||||
guild := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if guild.ID == 0 {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -75,18 +75,18 @@ func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if err != nil || guild == nil {
|
||||
guild := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if guild.ID == 0 {
|
||||
break
|
||||
}
|
||||
guildMembers, err := GetGuildMembers(s, guild.ID, false)
|
||||
if err != nil {
|
||||
guildMembers := GetGuildMembers(s, guild.ID)
|
||||
if len(guildMembers) == 0 {
|
||||
break
|
||||
}
|
||||
for _, member := range guildMembers {
|
||||
house := HouseData{}
|
||||
row := s.server.db.QueryRowx(houseQuery, member.CharID)
|
||||
err = row.StructScan(&house)
|
||||
err := row.StructScan(&house)
|
||||
if err == nil {
|
||||
houses = append(houses, house)
|
||||
}
|
||||
@@ -176,12 +176,11 @@ func handleMsgMhfLoadHouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
// Guild verification
|
||||
if state > 3 {
|
||||
ownGuild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
isApplicant, _ := ownGuild.HasApplicationForCharID(s, s.charID)
|
||||
if err == nil && ownGuild != nil {
|
||||
othersGuild, err := GetGuildInfoByCharacterId(s, pkt.CharID)
|
||||
if err == nil && othersGuild != nil {
|
||||
if othersGuild.ID == ownGuild.ID && !isApplicant {
|
||||
ownGuild := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if ownGuild.ID != 0 && !IsGuildApplicant(s, s.charID) {
|
||||
othersGuild := GetGuildInfoByCharacterId(s, pkt.CharID)
|
||||
if othersGuild.ID != 0 && !IsGuildApplicant(s, pkt.CharID) {
|
||||
if othersGuild.ID == ownGuild.ID {
|
||||
allowed = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"erupe-ce/common/stringsupport"
|
||||
"time"
|
||||
|
||||
@@ -29,36 +28,16 @@ type Mail struct {
|
||||
SenderName string `db:"sender_name"`
|
||||
}
|
||||
|
||||
func (m *Mail) Send(s *Session, transaction *sql.Tx) error {
|
||||
func (m *Mail) Send(s *Session) error {
|
||||
query := `
|
||||
INSERT INTO mail (sender_id, recipient_id, subject, body, attached_item, attached_item_amount, is_guild_invite, is_sys_message)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||
`
|
||||
|
||||
var err error
|
||||
|
||||
if transaction == nil {
|
||||
_, err = s.server.db.Exec(query, m.SenderID, m.RecipientID, m.Subject, m.Body, m.AttachedItemID, m.AttachedItemAmount, m.IsGuildInvite, m.IsSystemMessage)
|
||||
} else {
|
||||
_, err = transaction.Exec(query, m.SenderID, m.RecipientID, m.Subject, m.Body, m.AttachedItemID, m.AttachedItemAmount, m.IsGuildInvite, m.IsSystemMessage)
|
||||
}
|
||||
|
||||
_, err := s.server.db.Exec(query, m.SenderID, m.RecipientID, m.Subject, m.Body, m.AttachedItemID, m.AttachedItemAmount, m.IsGuildInvite, m.IsSystemMessage)
|
||||
if err != nil {
|
||||
s.logger.Error(
|
||||
"failed to send mail",
|
||||
zap.Error(err),
|
||||
zap.Uint32("senderID", m.SenderID),
|
||||
zap.Uint32("recipientID", m.RecipientID),
|
||||
zap.String("subject", m.Subject),
|
||||
zap.String("body", m.Body),
|
||||
zap.Uint16("itemID", m.AttachedItemID),
|
||||
zap.Uint16("itemAmount", m.AttachedItemAmount),
|
||||
zap.Bool("isGuildInvite", m.IsGuildInvite),
|
||||
zap.Bool("isSystemMessage", m.IsSystemMessage),
|
||||
)
|
||||
s.logger.Error("failed to send mail", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -189,16 +168,9 @@ func SendMailNotification(s *Session, m *Mail, recipient *Session) {
|
||||
}
|
||||
|
||||
func getCharacterName(s *Session, charID uint32) string {
|
||||
row := s.server.db.QueryRow("SELECT name FROM characters WHERE id = $1", charID)
|
||||
|
||||
charName := ""
|
||||
|
||||
err := row.Scan(&charName)
|
||||
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return charName
|
||||
var name string
|
||||
s.server.db.QueryRow("SELECT name FROM characters WHERE id = $1", charID).Scan(&name)
|
||||
return name
|
||||
}
|
||||
|
||||
func handleMsgMhfReadMail(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -255,26 +227,21 @@ func handleMsgMhfListMail(s *Session, p mhfpacket.MHFPacket) {
|
||||
msg.WriteUint8(accIndex)
|
||||
msg.WriteUint8(uint8(i))
|
||||
|
||||
flags := uint8(0x00)
|
||||
|
||||
var flags uint8
|
||||
if m.Read {
|
||||
flags |= 0x01
|
||||
flags |= 1 << 0
|
||||
}
|
||||
|
||||
if m.Locked {
|
||||
flags |= 0x02
|
||||
flags |= 1 << 1
|
||||
}
|
||||
|
||||
if m.IsSystemMessage {
|
||||
flags |= 0x04
|
||||
flags |= 1 << 2
|
||||
}
|
||||
|
||||
if m.AttachedItemReceived {
|
||||
flags |= 0x08
|
||||
flags |= 1 << 3
|
||||
}
|
||||
|
||||
if m.IsGuildInvite {
|
||||
flags |= 0x10
|
||||
flags |= 1 << 4
|
||||
}
|
||||
|
||||
msg.WriteUint8(flags)
|
||||
@@ -322,31 +289,20 @@ func handleMsgMhfSendMail(s *Session, p mhfpacket.MHFPacket) {
|
||||
`
|
||||
|
||||
if pkt.RecipientID == 0 { // Guild mail
|
||||
g, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get guild info for mail")
|
||||
guild := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if guild.ID == 0 {
|
||||
s.logger.Error("failed to get guild info for mail")
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
gm, err := GetGuildMembers(s, g.ID, false)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get guild members for mail")
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
for i := 0; i < len(gm); i++ {
|
||||
_, err := s.server.db.Exec(query, s.charID, gm[i].CharID, pkt.Subject, pkt.Body, 0, 0, false)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to send mail")
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
guildMembers := GetGuildMembers(s, guild.ID)
|
||||
if len(guildMembers) > 0 {
|
||||
for _, member := range guildMembers {
|
||||
s.server.db.Exec(query, s.charID, member.CharID, pkt.Subject, pkt.Body, 0, 0, false)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_, err := s.server.db.Exec(query, s.charID, pkt.RecipientID, pkt.Subject, pkt.Body, pkt.ItemID, pkt.Quantity, false)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to send mail")
|
||||
}
|
||||
s.server.db.Exec(query, s.charID, pkt.RecipientID, pkt.Subject, pkt.Body, pkt.ItemID, pkt.Quantity, false)
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
@@ -327,8 +327,8 @@ type Airou struct {
|
||||
func getGuildAirouList(s *Session) []Airou {
|
||||
var guildCats []Airou
|
||||
bannedCats := make(map[uint32]int)
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if err != nil {
|
||||
guild := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if guild.ID == 0 {
|
||||
return guildCats
|
||||
}
|
||||
rows, err := s.server.db.Query(`SELECT cats_used FROM guild_hunts gh
|
||||
|
||||
@@ -111,14 +111,9 @@ type RengokuScore struct {
|
||||
func handleMsgMhfEnumerateRengokuRanking(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateRengokuRanking)
|
||||
|
||||
guild, _ := GetGuildInfoByCharacterId(s, s.charID)
|
||||
isApplicant, _ := guild.HasApplicationForCharID(s, s.charID)
|
||||
if isApplicant {
|
||||
guild = nil
|
||||
}
|
||||
|
||||
guild := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if pkt.Leaderboard == 2 || pkt.Leaderboard == 3 || pkt.Leaderboard == 6 || pkt.Leaderboard == 7 {
|
||||
if guild == nil {
|
||||
if guild.ID == 0 || IsGuildApplicant(s, s.charID) {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 11))
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user