mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-17 17:34:37 +01:00
implement missing guild alliance code
This commit is contained in:
20
Erupe/guild-additions.sql
Normal file
20
Erupe/guild-additions.sql
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
ALTER TABLE IF EXISTS public.guilds
|
||||||
|
(
|
||||||
|
ADD COLUMN pugi_name_1 character varying(12),
|
||||||
|
ADD COLUMN pugi_name_2 character varying(12),
|
||||||
|
ADD COLUMN pugi_name_3 character varying(12)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS public.guild_alliances
|
||||||
|
(
|
||||||
|
id serial NOT NULL PRIMARY KEY,
|
||||||
|
name character varying(24) NOT NULL,
|
||||||
|
created_at timestamp without time zone NOT NULL,
|
||||||
|
parent_id int NOT NULL,
|
||||||
|
sub1_id int,
|
||||||
|
sub2_id int
|
||||||
|
);
|
||||||
|
|
||||||
|
END;
|
||||||
@@ -3,13 +3,18 @@ package mhfpacket
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
|
"github.com/Solenataris/Erupe/common/bfutil"
|
||||||
"github.com/Solenataris/Erupe/network/clientctx"
|
"github.com/Solenataris/Erupe/network/clientctx"
|
||||||
"github.com/Solenataris/Erupe/network"
|
"github.com/Solenataris/Erupe/network"
|
||||||
"github.com/Andoryuuta/byteframe"
|
"github.com/Andoryuuta/byteframe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MsgMhfCreateJoint represents the MSG_MHF_CREATE_JOINT
|
// MsgMhfCreateJoint represents the MSG_MHF_CREATE_JOINT
|
||||||
type MsgMhfCreateJoint struct{}
|
type MsgMhfCreateJoint struct {
|
||||||
|
AckHandle uint32
|
||||||
|
GuildID uint32
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
// Opcode returns the ID associated with this packet type.
|
// Opcode returns the ID associated with this packet type.
|
||||||
func (m *MsgMhfCreateJoint) Opcode() network.PacketID {
|
func (m *MsgMhfCreateJoint) Opcode() network.PacketID {
|
||||||
@@ -18,7 +23,12 @@ func (m *MsgMhfCreateJoint) Opcode() network.PacketID {
|
|||||||
|
|
||||||
// Parse parses the packet from binary
|
// Parse parses the packet from binary
|
||||||
func (m *MsgMhfCreateJoint) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
func (m *MsgMhfCreateJoint) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||||
return errors.New("NOT IMPLEMENTED")
|
m.AckHandle = bf.ReadUint32()
|
||||||
|
m.GuildID = bf.ReadUint32()
|
||||||
|
nameLength := bf.ReadUint32()
|
||||||
|
nameBytes := bfutil.UpToNull(bf.ReadBytes(uint(nameLength)))
|
||||||
|
m.Name = ctx.StrConv.MustDecode(nameBytes)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build builds a binary packet from the current data.
|
// Build builds a binary packet from the current data.
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package channelserver
|
package channelserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"database/sql/driver"
|
"database/sql/driver"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
@@ -9,9 +8,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -23,8 +19,6 @@ import (
|
|||||||
"github.com/Solenataris/Erupe/network/mhfpacket"
|
"github.com/Solenataris/Erupe/network/mhfpacket"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"golang.org/x/text/encoding/japanese"
|
|
||||||
"golang.org/x/text/transform"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type FestivalColour string
|
type FestivalColour string
|
||||||
@@ -764,7 +758,7 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleRenamePugi(s *Session, data []byte, guild *Guild, num int) {
|
func handleRenamePugi(s *Session, data []byte, guild *Guild, num int) {
|
||||||
bf := NewByteFrameFromBytes(data)
|
bf := byteframe.NewByteFrameFromBytes(data)
|
||||||
_ = bf.ReadUint8() // len
|
_ = bf.ReadUint8() // len
|
||||||
_ = bf.ReadUint32() // unk
|
_ = bf.ReadUint32() // unk
|
||||||
name, _ := stringsupport.ConvertSJISBytesToString(bf.ReadNullTerminatedBytes())
|
name, _ := stringsupport.ConvertSJISBytesToString(bf.ReadNullTerminatedBytes())
|
||||||
@@ -776,7 +770,7 @@ func handleRenamePugi(s *Session, data []byte, guild *Guild, num int) {
|
|||||||
default:
|
default:
|
||||||
guild.PugiName3 = name
|
guild.PugiName3 = name
|
||||||
}
|
}
|
||||||
guild.Save()
|
guild.Save(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleDonateRP(s *Session, pkt *mhfpacket.MsgMhfOperateGuild, bf *byteframe.ByteFrame, guild *Guild, isEvent bool) error {
|
func handleDonateRP(s *Session, pkt *mhfpacket.MsgMhfOperateGuild, bf *byteframe.ByteFrame, guild *Guild, isEvent bool) error {
|
||||||
@@ -1918,9 +1912,3 @@ func handleMsgMhfEnumerateInvGuild(s *Session, p mhfpacket.MHFPacket) {}
|
|||||||
func handleMsgMhfOperationInvGuild(s *Session, p mhfpacket.MHFPacket) {}
|
func handleMsgMhfOperationInvGuild(s *Session, p mhfpacket.MHFPacket) {}
|
||||||
|
|
||||||
func handleMsgMhfUpdateGuildcard(s *Session, p mhfpacket.MHFPacket) {}
|
func handleMsgMhfUpdateGuildcard(s *Session, p mhfpacket.MHFPacket) {}
|
||||||
|
|
||||||
func handleMsgMhfCreateJoint(s *Session, p mhfpacket.MHFPacket) {}
|
|
||||||
|
|
||||||
func handleMsgMhfOperateJoint(s *Session, p mhfpacket.MHFPacket) {}
|
|
||||||
|
|
||||||
func handleMsgMhfInfoJoint(s *Session, p mhfpacket.MHFPacket) {}
|
|
||||||
|
|||||||
157
Erupe/server/channelserver/handlers_guild_alliance.go
Normal file
157
Erupe/server/channelserver/handlers_guild_alliance.go
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
package channelserver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/Solenataris/Erupe/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 {
|
||||||
|
// delete alliance application
|
||||||
|
// or leave alliance
|
||||||
|
} else {
|
||||||
|
s.logger.Warn(
|
||||||
|
"Non-owner of guild attempted alliance leave",
|
||||||
|
zap.Uint32("CharID", s.charID),
|
||||||
|
)
|
||||||
|
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("Unhandled operate joint action '%d'", pkt.Action))
|
||||||
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleMsgMhfInfoJoint(s *Session, p mhfpacket.MHFPacket) {}
|
||||||
Reference in New Issue
Block a user