mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-13 07:25:03 +01:00
212 lines
6.1 KiB
Go
212 lines
6.1 KiB
Go
package channelserver
|
|
|
|
import (
|
|
"erupe-ce/common/byteframe"
|
|
ps "erupe-ce/common/pascalstring"
|
|
"fmt"
|
|
"time"
|
|
|
|
"erupe-ce/network/mhfpacket"
|
|
"github.com/jmoiron/sqlx"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
const allianceInfoSelectQuery = `
|
|
SELECT
|
|
ga.id,
|
|
ga.name,
|
|
created_at,
|
|
parent_id,
|
|
CASE
|
|
WHEN sub1_id IS NULL THEN 0
|
|
ELSE sub1_id
|
|
END,
|
|
CASE
|
|
WHEN sub2_id IS NULL THEN 0
|
|
ELSE sub2_id
|
|
END
|
|
FROM guild_alliances ga
|
|
`
|
|
|
|
type GuildAlliance struct {
|
|
ID uint32 `db:"id"`
|
|
Name string `db:"name"`
|
|
CreatedAt time.Time `db:"created_at"`
|
|
TotalMembers uint16
|
|
|
|
ParentGuildID uint32 `db:"parent_id"`
|
|
SubGuild1ID uint32 `db:"sub1_id"`
|
|
SubGuild2ID uint32 `db:"sub2_id"`
|
|
|
|
ParentGuild Guild
|
|
SubGuild1 Guild
|
|
SubGuild2 Guild
|
|
}
|
|
|
|
func GetAllianceData(s *Session, AllianceID uint32) (*GuildAlliance, error) {
|
|
rows, err := s.server.db.Queryx(fmt.Sprintf(`
|
|
%s
|
|
WHERE ga.id = $1
|
|
`, allianceInfoSelectQuery), AllianceID)
|
|
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.Fatal("Failed to get parent guild info", 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.Fatal("Failed to get sub guild 1 info", zap.Error(err))
|
|
} else {
|
|
alliance.SubGuild1 = *subGuild1
|
|
alliance.TotalMembers += subGuild1.MemberCount
|
|
}
|
|
}
|
|
|
|
if alliance.SubGuild2ID > 0 {
|
|
subGuild2, err := GetGuildInfoByID(s, alliance.SubGuild2ID)
|
|
if err != nil {
|
|
s.logger.Fatal("Failed to get sub guild 2 info", zap.Error(err))
|
|
} else {
|
|
alliance.SubGuild2 = *subGuild2
|
|
alliance.TotalMembers += subGuild2.MemberCount
|
|
}
|
|
}
|
|
|
|
return alliance, nil
|
|
}
|
|
|
|
func handleMsgMhfCreateJoint(s *Session, p mhfpacket.MHFPacket) {
|
|
pkt := p.(*mhfpacket.MsgMhfCreateJoint)
|
|
_, err := s.server.db.Exec("INSERT INTO guild_alliances (name, parent_id) VALUES ($1, $2)", pkt.Name, pkt.GuildID)
|
|
if err != nil {
|
|
s.logger.Fatal("Failed to create guild alliance in db", zap.Error(err))
|
|
}
|
|
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x01, 0x01, 0x01, 0x01})
|
|
}
|
|
|
|
func handleMsgMhfOperateJoint(s *Session, p mhfpacket.MHFPacket) {
|
|
pkt := p.(*mhfpacket.MsgMhfOperateJoint)
|
|
|
|
guild, err := GetGuildInfoByID(s, pkt.GuildID)
|
|
if err != nil {
|
|
s.logger.Fatal("Failed to get guild info", zap.Error(err))
|
|
}
|
|
alliance, err := GetAllianceData(s, pkt.AllianceID)
|
|
if err != nil {
|
|
s.logger.Fatal("Failed to get alliance info", zap.Error(err))
|
|
}
|
|
|
|
switch pkt.Action {
|
|
case mhfpacket.OPERATE_JOINT_DISBAND:
|
|
if guild.LeaderCharID == s.charID && alliance.ParentGuildID == guild.ID {
|
|
_, err = s.server.db.Exec("DELETE FROM guild_alliances WHERE id=$1", alliance.ID)
|
|
if err != nil {
|
|
s.logger.Fatal("Failed to disband alliance", zap.Error(err))
|
|
}
|
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
|
} else {
|
|
s.logger.Warn(
|
|
"Non-owner of alliance attempted disband",
|
|
zap.Uint32("CharID", s.charID),
|
|
zap.Uint32("AllyID", alliance.ID),
|
|
)
|
|
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
|
}
|
|
case mhfpacket.OPERATE_JOINT_LEAVE:
|
|
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)
|
|
} else if guild.ID == alliance.SubGuild1ID && alliance.SubGuild2ID == 0 {
|
|
s.server.db.Exec(`UPDATE guild_alliances SET sub1_id = NULL WHERE id = $1`, alliance.ID)
|
|
} else {
|
|
s.server.db.Exec(`UPDATE guild_alliances SET sub2_id = NULL WHERE id = $1`, alliance.ID)
|
|
}
|
|
// TODO: Handle deleting Alliance applications
|
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
|
} else {
|
|
s.logger.Warn(
|
|
"Non-owner of guild attempted alliance leave",
|
|
zap.Uint32("CharID", s.charID),
|
|
)
|
|
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
|
}
|
|
default:
|
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
|
panic(fmt.Sprintf("Unhandled operate joint action '%d'", pkt.Action))
|
|
}
|
|
}
|
|
|
|
func handleMsgMhfInfoJoint(s *Session, p mhfpacket.MHFPacket) {
|
|
pkt := p.(*mhfpacket.MsgMhfInfoJoint)
|
|
bf := byteframe.NewByteFrame()
|
|
alliance, err := GetAllianceData(s, pkt.AllianceID)
|
|
if err != nil {
|
|
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
|
} else {
|
|
bf.WriteUint32(alliance.ID)
|
|
bf.WriteUint32(uint32(alliance.CreatedAt.Unix()))
|
|
bf.WriteUint16(alliance.TotalMembers)
|
|
bf.WriteUint16(0x0000) // Unk
|
|
ps.Uint16(bf, alliance.Name, true)
|
|
if alliance.SubGuild1ID > 0 {
|
|
if alliance.SubGuild2ID > 0 {
|
|
bf.WriteUint8(3)
|
|
} else {
|
|
bf.WriteUint8(2)
|
|
}
|
|
} else {
|
|
bf.WriteUint8(1)
|
|
}
|
|
bf.WriteUint32(alliance.ParentGuildID)
|
|
bf.WriteUint32(alliance.ParentGuild.LeaderCharID)
|
|
bf.WriteUint16(alliance.ParentGuild.Rank)
|
|
bf.WriteUint16(alliance.ParentGuild.MemberCount)
|
|
ps.Uint16(bf, alliance.ParentGuild.Name, true)
|
|
ps.Uint16(bf, alliance.ParentGuild.LeaderName, true)
|
|
if alliance.SubGuild1ID > 0 {
|
|
bf.WriteUint32(alliance.SubGuild1ID)
|
|
bf.WriteUint32(alliance.SubGuild1.LeaderCharID)
|
|
bf.WriteUint16(alliance.SubGuild1.Rank)
|
|
bf.WriteUint16(alliance.SubGuild1.MemberCount)
|
|
ps.Uint16(bf, alliance.SubGuild1.Name, true)
|
|
ps.Uint16(bf, alliance.SubGuild1.LeaderName, true)
|
|
}
|
|
if alliance.SubGuild2ID > 0 {
|
|
bf.WriteUint32(alliance.SubGuild2ID)
|
|
bf.WriteUint32(alliance.SubGuild2.LeaderCharID)
|
|
bf.WriteUint16(alliance.SubGuild2.Rank)
|
|
bf.WriteUint16(alliance.SubGuild2.MemberCount)
|
|
ps.Uint16(bf, alliance.SubGuild2.Name, true)
|
|
ps.Uint16(bf, alliance.SubGuild2.LeaderName, true)
|
|
}
|
|
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
|
}
|
|
}
|