mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-13 15:34:38 +01:00
implement Festa Bonus Categories & Guild Character optimisations
This commit is contained in:
@@ -1,19 +1,20 @@
|
|||||||
package mhfpacket
|
package mhfpacket
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"erupe-ce/network/clientctx"
|
|
||||||
"erupe-ce/network"
|
|
||||||
"erupe-ce/common/byteframe"
|
"erupe-ce/common/byteframe"
|
||||||
|
"erupe-ce/network"
|
||||||
|
"erupe-ce/network/clientctx"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MsgMhfChargeFesta represents the MSG_MHF_CHARGE_FESTA
|
// MsgMhfChargeFesta represents the MSG_MHF_CHARGE_FESTA
|
||||||
type MsgMhfChargeFesta struct {
|
type MsgMhfChargeFesta struct {
|
||||||
AckHandle uint32
|
AckHandle uint32
|
||||||
FestaID uint32
|
FestaID uint32
|
||||||
GuildID uint32
|
GuildID uint32
|
||||||
Souls int
|
Souls []uint16
|
||||||
|
Auto bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opcode returns the ID associated with this packet type.
|
// Opcode returns the ID associated with this packet type.
|
||||||
@@ -23,15 +24,14 @@ func (m *MsgMhfChargeFesta) Opcode() network.PacketID {
|
|||||||
|
|
||||||
// Parse parses the packet from binary
|
// Parse parses the packet from binary
|
||||||
func (m *MsgMhfChargeFesta) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
func (m *MsgMhfChargeFesta) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||||
m.AckHandle = bf.ReadUint32()
|
m.AckHandle = bf.ReadUint32()
|
||||||
m.FestaID = bf.ReadUint32()
|
m.FestaID = bf.ReadUint32()
|
||||||
m.GuildID = bf.ReadUint32()
|
m.GuildID = bf.ReadUint32()
|
||||||
m.Souls = 0
|
for i := bf.ReadUint16(); i > 0; i-- {
|
||||||
for i := bf.ReadUint16(); i > 0; i-- {
|
m.Souls = append(m.Souls, bf.ReadUint16())
|
||||||
m.Souls += int(bf.ReadUint16())
|
}
|
||||||
}
|
m.Auto = bf.ReadBool()
|
||||||
_ = bf.ReadUint8() // Unk
|
return nil
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build builds a binary packet from the current data.
|
// Build builds a binary packet from the current data.
|
||||||
|
|||||||
15
schemas/patch-schema/festa-submissions.sql
Normal file
15
schemas/patch-schema/festa-submissions.sql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
CREATE TABLE festa_submissions (
|
||||||
|
character_id int NOT NULL,
|
||||||
|
guild_id int NOT NULL,
|
||||||
|
trial_type int NOT NULL,
|
||||||
|
souls int NOT NULL,
|
||||||
|
timestamp timestamp with time zone NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE guild_characters DROP COLUMN souls;
|
||||||
|
|
||||||
|
ALTER TYPE festival_colour RENAME TO festival_color;
|
||||||
|
|
||||||
|
END;
|
||||||
@@ -95,8 +95,9 @@ func handleMsgMhfEnumerateRanking(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
func cleanupFesta(s *Session) {
|
func cleanupFesta(s *Session) {
|
||||||
s.server.db.Exec("DELETE FROM events WHERE event_type='festa'")
|
s.server.db.Exec("DELETE FROM events WHERE event_type='festa'")
|
||||||
s.server.db.Exec("DELETE FROM festa_registrations")
|
s.server.db.Exec("DELETE FROM festa_registrations")
|
||||||
|
s.server.db.Exec("DELETE FROM festa_submissions")
|
||||||
s.server.db.Exec("DELETE FROM festa_prizes_accepted")
|
s.server.db.Exec("DELETE FROM festa_prizes_accepted")
|
||||||
s.server.db.Exec("UPDATE guild_characters SET souls=0, trial_vote=NULL")
|
s.server.db.Exec("UPDATE guild_characters SET trial_vote=NULL")
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateFestaTimestamps(s *Session, start uint32, debug bool) []uint32 {
|
func generateFestaTimestamps(s *Session, start uint32, debug bool) []uint32 {
|
||||||
@@ -293,22 +294,45 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
}
|
}
|
||||||
bf.WriteUint16(500)
|
bf.WriteUint16(500)
|
||||||
|
|
||||||
categoryWinners := uint16(4) // NYI
|
var temp uint32
|
||||||
bf.WriteUint16(categoryWinners)
|
bf.WriteUint16(4)
|
||||||
for i := uint16(0); i < categoryWinners; i++ {
|
for i := uint16(0); i < 4; i++ {
|
||||||
bf.WriteUint32(0) // Guild ID
|
var guildID uint32
|
||||||
bf.WriteUint16(i + 1) // Category ID
|
var guildName string
|
||||||
bf.WriteInt16(int16(FestivalColourCodes[FestivalColourNone])) // Festa Team
|
var guildTeam = FestivalColorNone
|
||||||
ps.Uint8(bf, "", true) // Guild Name
|
s.server.db.QueryRow(`
|
||||||
|
SELECT fs.guild_id, g.name, fr.team, SUM(fs.souls) as _
|
||||||
|
FROM festa_submissions fs
|
||||||
|
LEFT JOIN festa_registrations fr ON fs.guild_id = fr.guild_id
|
||||||
|
LEFT JOIN guilds g ON fs.guild_id = g.id
|
||||||
|
WHERE fs.trial_type = $1
|
||||||
|
GROUP BY fs.guild_id, g.name, fr.team
|
||||||
|
ORDER BY _ DESC LIMIT 1
|
||||||
|
`, i+1).Scan(&guildID, &guildName, &guildTeam, &temp)
|
||||||
|
bf.WriteUint32(guildID)
|
||||||
|
bf.WriteUint16(i + 1)
|
||||||
|
bf.WriteInt16(FestivalColorCodes[guildTeam])
|
||||||
|
ps.Uint8(bf, guildName, true)
|
||||||
}
|
}
|
||||||
|
bf.WriteUint16(7)
|
||||||
dailyWinners := uint16(7) // NYI
|
for i := uint16(0); i < 7; i++ {
|
||||||
bf.WriteUint16(dailyWinners)
|
var guildID uint32
|
||||||
for i := uint16(0); i < dailyWinners; i++ {
|
var guildName string
|
||||||
bf.WriteUint32(0) // Guild ID
|
var guildTeam = FestivalColorNone
|
||||||
bf.WriteUint16(i + 1) // Category ID
|
offset := 86400 * uint32(i)
|
||||||
bf.WriteInt16(int16(FestivalColourCodes[FestivalColourNone])) // Festa Team
|
s.server.db.QueryRow(`
|
||||||
ps.Uint8(bf, "", true) // Guild Name
|
SELECT fs.guild_id, g.name, fr.team, SUM(fs.souls) as _
|
||||||
|
FROM festa_submissions fs
|
||||||
|
LEFT JOIN festa_registrations fr ON fs.guild_id = fr.guild_id
|
||||||
|
LEFT JOIN guilds g ON fs.guild_id = g.id
|
||||||
|
WHERE EXTRACT(EPOCH FROM fs.timestamp)::int > $1 AND EXTRACT(EPOCH FROM fs.timestamp)::int < $2
|
||||||
|
GROUP BY fs.guild_id, g.name, fr.team
|
||||||
|
ORDER BY _ DESC LIMIT 1
|
||||||
|
`, timestamps[1]+offset, timestamps[1]+offset+86400).Scan(&guildID, &guildName, &guildTeam, &temp)
|
||||||
|
bf.WriteUint32(guildID)
|
||||||
|
bf.WriteUint16(i + 1)
|
||||||
|
bf.WriteInt16(FestivalColorCodes[guildTeam])
|
||||||
|
ps.Uint8(bf, guildName, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
bf.WriteUint32(0) // Clan goal
|
bf.WriteUint32(0) // Clan goal
|
||||||
@@ -445,7 +469,14 @@ func handleMsgMhfEntryFesta(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
func handleMsgMhfChargeFesta(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfChargeFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfChargeFesta)
|
pkt := p.(*mhfpacket.MsgMhfChargeFesta)
|
||||||
s.server.db.Exec("UPDATE guild_characters SET souls=souls+$1 WHERE character_id=$2", pkt.Souls, s.charID)
|
tx, _ := s.server.db.Begin()
|
||||||
|
for i := range pkt.Souls {
|
||||||
|
if pkt.Souls[i] == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
_, _ = tx.Exec(`INSERT INTO festa_submissions VALUES ($1, $2, $3, $4, now())`, s.charID, pkt.GuildID, i, pkt.Souls[i])
|
||||||
|
}
|
||||||
|
_ = tx.Commit()
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,41 +61,35 @@ func (gm *GuildMember) Save(s *Session) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const guildMembersSelectSQL = `
|
const guildMembersSelectSQL = `
|
||||||
SELECT
|
SELECT * FROM (
|
||||||
g.id as guild_id,
|
SELECT
|
||||||
joined_at,
|
g.id AS guild_id,
|
||||||
coalesce(souls, 0) as souls,
|
joined_at,
|
||||||
COALESCE(rp_today, 0) AS rp_today,
|
COALESCE((SELECT SUM(souls) FROM festa_submissions fs WHERE fs.character_id=c.id), 0) AS souls,
|
||||||
COALESCE(rp_yesterday, 0) AS rp_yesterday,
|
COALESCE(rp_today, 0) AS rp_today,
|
||||||
c.name,
|
COALESCE(rp_yesterday, 0) AS rp_yesterday,
|
||||||
character.character_id,
|
c.name,
|
||||||
coalesce(gc.order_index, 0) as order_index,
|
c.id AS character_id,
|
||||||
c.last_login,
|
COALESCE(order_index, 0) AS order_index,
|
||||||
coalesce(gc.recruiter, false) as recruiter,
|
c.last_login,
|
||||||
coalesce(gc.avoid_leadership, false) as avoid_leadership,
|
COALESCE(recruiter, false) AS recruiter,
|
||||||
c.hrp,
|
COALESCE(avoid_leadership, false) AS avoid_leadership,
|
||||||
c.gr,
|
c.hrp,
|
||||||
c.weapon_id,
|
c.gr,
|
||||||
c.weapon_type,
|
c.weapon_id,
|
||||||
character.is_applicant,
|
c.weapon_type,
|
||||||
CASE WHEN g.leader_id = c.id THEN 1 ELSE 0 END as is_leader
|
EXISTS(SELECT 1 FROM guild_applications ga WHERE ga.character_id=c.id AND application_type='applied') AS is_applicant,
|
||||||
FROM (
|
CASE WHEN g.leader_id = c.id THEN true ELSE false END AS is_leader
|
||||||
SELECT character_id, true as is_applicant, guild_id
|
|
||||||
FROM guild_applications ga
|
|
||||||
WHERE ga.application_type = 'applied'
|
|
||||||
UNION
|
|
||||||
SELECT character_id, false as is_applicant, guild_id
|
|
||||||
FROM guild_characters gc
|
FROM guild_characters gc
|
||||||
) character
|
LEFT JOIN characters c ON c.id = gc.character_id
|
||||||
JOIN characters c on character.character_id = c.id
|
LEFT JOIN guilds g ON g.id = gc.guild_id
|
||||||
LEFT JOIN guild_characters gc ON gc.character_id = character.character_id
|
) AS subquery
|
||||||
JOIN guilds g ON g.id = character.guild_id
|
|
||||||
`
|
`
|
||||||
|
|
||||||
func GetGuildMembers(s *Session, guildID uint32, applicants bool) ([]*GuildMember, error) {
|
func GetGuildMembers(s *Session, guildID uint32, applicants bool) ([]*GuildMember, error) {
|
||||||
rows, err := s.server.db.Queryx(fmt.Sprintf(`
|
rows, err := s.server.db.Queryx(fmt.Sprintf(`
|
||||||
%s
|
%s
|
||||||
WHERE character.guild_id = $1 AND is_applicant = $2
|
WHERE guild_id = $1 AND is_applicant = $2
|
||||||
`, guildMembersSelectSQL), guildID, applicants)
|
`, guildMembersSelectSQL), guildID, applicants)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -121,7 +115,7 @@ func GetGuildMembers(s *Session, guildID uint32, applicants bool) ([]*GuildMembe
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetCharacterGuildData(s *Session, charID uint32) (*GuildMember, error) {
|
func GetCharacterGuildData(s *Session, charID uint32) (*GuildMember, error) {
|
||||||
rows, err := s.server.db.Queryx(fmt.Sprintf("%s WHERE character.character_id=$1", guildMembersSelectSQL), charID)
|
rows, err := s.server.db.Queryx(fmt.Sprintf("%s WHERE character_id=$1", guildMembersSelectSQL), charID)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Error(fmt.Sprintf("failed to retrieve membership data for character '%d'", charID))
|
s.logger.Error(fmt.Sprintf("failed to retrieve membership data for character '%d'", charID))
|
||||||
|
|||||||
Reference in New Issue
Block a user