mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-13 15:34:38 +01:00
429 lines
14 KiB
Go
429 lines
14 KiB
Go
package channelserver
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"erupe-ce/common/byteframe"
|
|
ps "erupe-ce/common/pascalstring"
|
|
"erupe-ce/network/mhfpacket"
|
|
"math/rand"
|
|
"time"
|
|
)
|
|
|
|
func handleMsgMhfSaveMezfesData(s *Session, p mhfpacket.MHFPacket) {
|
|
pkt := p.(*mhfpacket.MsgMhfSaveMezfesData)
|
|
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
|
}
|
|
|
|
func handleMsgMhfLoadMezfesData(s *Session, p mhfpacket.MHFPacket) {
|
|
pkt := p.(*mhfpacket.MsgMhfLoadMezfesData)
|
|
|
|
resp := byteframe.NewByteFrame()
|
|
resp.WriteUint32(0) // Unk
|
|
|
|
resp.WriteUint8(2) // Count of the next 2 uint32s
|
|
resp.WriteUint32(0)
|
|
resp.WriteUint32(0)
|
|
|
|
resp.WriteUint32(0) // Unk
|
|
|
|
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
|
}
|
|
|
|
func handleMsgMhfEnumerateRanking(s *Session, p mhfpacket.MHFPacket) {
|
|
pkt := p.(*mhfpacket.MsgMhfEnumerateRanking)
|
|
bf := byteframe.NewByteFrame()
|
|
state := s.server.erupeConfig.DevModeOptions.TournamentEvent
|
|
// Unk
|
|
// Unk
|
|
// Start?
|
|
// End?
|
|
midnight := Time_Current_Midnight()
|
|
switch state {
|
|
case 1:
|
|
bf.WriteUint32(uint32(midnight.Unix()))
|
|
bf.WriteUint32(uint32(midnight.Add(3 * 24 * time.Hour).Unix()))
|
|
bf.WriteUint32(uint32(midnight.Add(13 * 24 * time.Hour).Unix()))
|
|
bf.WriteUint32(uint32(midnight.Add(20 * 24 * time.Hour).Unix()))
|
|
case 2:
|
|
bf.WriteUint32(uint32(midnight.Add(-3 * 24 * time.Hour).Unix()))
|
|
bf.WriteUint32(uint32(midnight.Unix()))
|
|
bf.WriteUint32(uint32(midnight.Add(10 * 24 * time.Hour).Unix()))
|
|
bf.WriteUint32(uint32(midnight.Add(17 * 24 * time.Hour).Unix()))
|
|
case 3:
|
|
bf.WriteUint32(uint32(midnight.Add(-13 * 24 * time.Hour).Unix()))
|
|
bf.WriteUint32(uint32(midnight.Add(-10 * 24 * time.Hour).Unix()))
|
|
bf.WriteUint32(uint32(midnight.Unix()))
|
|
bf.WriteUint32(uint32(midnight.Add(7 * 24 * time.Hour).Unix()))
|
|
default:
|
|
bf.WriteBytes(make([]byte, 16))
|
|
bf.WriteUint32(uint32(Time_Current_Adjusted().Unix())) // TS Current Time
|
|
bf.WriteUint8(3)
|
|
bf.WriteBytes(make([]byte, 4))
|
|
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
|
return
|
|
}
|
|
bf.WriteUint32(uint32(Time_Current_Adjusted().Unix())) // TS Current Time
|
|
bf.WriteUint8(3)
|
|
ps.Uint8(bf, "", false)
|
|
bf.WriteUint16(0) // numEvents
|
|
bf.WriteUint8(0) // numCups
|
|
|
|
/*
|
|
struct event
|
|
uint32 eventID
|
|
uint16 unk
|
|
uint16 unk
|
|
uint32 unk
|
|
psUint8 name
|
|
|
|
struct cup
|
|
uint32 cupID
|
|
uint16 unk
|
|
uint16 unk
|
|
uint16 unk
|
|
psUint8 name
|
|
psUint16 desc
|
|
*/
|
|
|
|
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
|
}
|
|
|
|
func cleanupFesta(s *Session) {
|
|
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_prizes_accepted")
|
|
s.server.db.Exec("UPDATE guild_characters SET souls=0")
|
|
}
|
|
|
|
func generateFestaTimestamps(s *Session, start uint32, debug bool) []uint32 {
|
|
timestamps := make([]uint32, 5)
|
|
midnight := Time_Current_Midnight()
|
|
if debug && start <= 3 {
|
|
midnight := uint32(midnight.Unix())
|
|
switch start {
|
|
case 1:
|
|
timestamps[0] = midnight
|
|
timestamps[1] = timestamps[0] + 604800
|
|
timestamps[2] = timestamps[1] + 604800
|
|
timestamps[3] = timestamps[2] + 9000
|
|
timestamps[4] = timestamps[3] + 1240200
|
|
case 2:
|
|
timestamps[0] = midnight - 604800
|
|
timestamps[1] = midnight
|
|
timestamps[2] = timestamps[1] + 604800
|
|
timestamps[3] = timestamps[2] + 9000
|
|
timestamps[4] = timestamps[3] + 1240200
|
|
case 3:
|
|
timestamps[0] = midnight - 1209600
|
|
timestamps[1] = midnight - 604800
|
|
timestamps[2] = midnight
|
|
timestamps[3] = timestamps[2] + 9000
|
|
timestamps[4] = timestamps[3] + 1240200
|
|
}
|
|
return timestamps
|
|
}
|
|
if start == 0 || Time_Current_Adjusted().Unix() > int64(start)+2977200 {
|
|
cleanupFesta(s)
|
|
// Generate a new festa, starting midnight tomorrow
|
|
start = uint32(midnight.Add(24 * time.Hour).Unix())
|
|
s.server.db.Exec("INSERT INTO events (event_type, start_time) VALUES ('festa', to_timestamp($1)::timestamp without time zone)", start)
|
|
}
|
|
timestamps[0] = start
|
|
timestamps[1] = timestamps[0] + 604800
|
|
timestamps[2] = timestamps[1] + 604800
|
|
timestamps[3] = timestamps[2] + 9000
|
|
timestamps[4] = timestamps[3] + 1240200
|
|
return timestamps
|
|
}
|
|
|
|
type Trial struct {
|
|
ID uint32 `db:"id"`
|
|
Objective uint8 `db:"objective"`
|
|
GoalID uint32 `db:"goal_id"`
|
|
TimesReq uint16 `db:"times_req"`
|
|
Locale uint16 `db:"locale_req"`
|
|
Reward uint16 `db:"reward"`
|
|
}
|
|
|
|
func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
|
|
pkt := p.(*mhfpacket.MsgMhfInfoFesta)
|
|
bf := byteframe.NewByteFrame()
|
|
|
|
id, start := uint32(0xDEADBEEF), uint32(0)
|
|
rows, _ := s.server.db.Queryx("SELECT id, (EXTRACT(epoch FROM start_time)::int) as start_time FROM events WHERE event_type='festa'")
|
|
for rows.Next() {
|
|
rows.Scan(&id, &start)
|
|
}
|
|
|
|
var timestamps []uint32
|
|
if s.server.erupeConfig.DevMode && s.server.erupeConfig.DevModeOptions.FestaEvent >= 0 {
|
|
if s.server.erupeConfig.DevModeOptions.FestaEvent == 0 {
|
|
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
|
return
|
|
}
|
|
timestamps = generateFestaTimestamps(s, uint32(s.server.erupeConfig.DevModeOptions.FestaEvent), true)
|
|
} else {
|
|
timestamps = generateFestaTimestamps(s, start, false)
|
|
}
|
|
|
|
if timestamps[0] > uint32(Time_Current_Adjusted().Unix()) {
|
|
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
|
return
|
|
}
|
|
|
|
var blueSouls, redSouls uint32
|
|
s.server.db.QueryRow("SELECT SUM(gc.souls) FROM guild_characters gc INNER JOIN festa_registrations fr ON fr.guild_id = gc.guild_id WHERE fr.team = 'blue'").Scan(&blueSouls)
|
|
s.server.db.QueryRow("SELECT SUM(gc.souls) FROM guild_characters gc INNER JOIN festa_registrations fr ON fr.guild_id = gc.guild_id WHERE fr.team = 'red'").Scan(&redSouls)
|
|
|
|
bf.WriteUint32(id)
|
|
for _, timestamp := range timestamps {
|
|
bf.WriteUint32(timestamp)
|
|
}
|
|
bf.WriteUint32(uint32(Time_Current_Adjusted().Unix()))
|
|
bf.WriteUint8(4)
|
|
ps.Uint8(bf, "", false)
|
|
bf.WriteUint32(0)
|
|
bf.WriteUint32(blueSouls)
|
|
bf.WriteUint32(redSouls)
|
|
|
|
rows, _ = s.server.db.Queryx("SELECT * FROM festa_trials")
|
|
trialData := byteframe.NewByteFrame()
|
|
var count uint16
|
|
for rows.Next() {
|
|
trial := &Trial{}
|
|
err := rows.StructScan(&trial)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
count++
|
|
trialData.WriteUint32(trial.ID)
|
|
trialData.WriteUint8(0) // Unk
|
|
trialData.WriteUint8(trial.Objective)
|
|
trialData.WriteUint32(trial.GoalID)
|
|
trialData.WriteUint16(trial.TimesReq)
|
|
trialData.WriteUint16(trial.Locale)
|
|
trialData.WriteUint16(trial.Reward)
|
|
trialData.WriteUint8(0xFF) // Unk
|
|
trialData.WriteUint8(0xFF) // MonopolyState
|
|
trialData.WriteUint16(0) // Unk
|
|
}
|
|
bf.WriteUint16(count)
|
|
bf.WriteBytes(trialData.Data())
|
|
|
|
// Static bonus rewards
|
|
rewards, _ := hex.DecodeString("001901000007015E05F000000000000100000703E81B6300000000010100000C03E8000000000000000100000D0000000000000000000100000100000000000000000002000007015E05F000000000000200000703E81B6300000000010200000C03E8000000000000000200000D0000000000000000000200000400000000000000000003000007015E05F000000000000300000703E81B6300000000010300000C03E8000000000000000300000D0000000000000000000300000100000000000000000004000007015E05F000000000000400000703E81B6300000000010400000C03E8000000000000000400000D0000000000000000000400000400000000000000000005000007015E05F000000000000500000703E81B6300000000010500000C03E8000000000000000500000D00000000000000000005000001000000000000000000")
|
|
bf.WriteBytes(rewards)
|
|
|
|
bf.WriteUint16(0x0001)
|
|
bf.WriteUint32(0xD4C001F4)
|
|
|
|
categoryWinners := uint16(0) // NYI
|
|
bf.WriteUint16(categoryWinners)
|
|
for i := uint16(0); i < categoryWinners; i++ {
|
|
bf.WriteUint32(0) // Guild ID
|
|
bf.WriteUint16(i + 1) // Category ID
|
|
bf.WriteUint16(0) // Festa Team
|
|
ps.Uint8(bf, "", true) // Guild Name
|
|
}
|
|
|
|
dailyWinners := uint16(0) // NYI
|
|
bf.WriteUint16(dailyWinners)
|
|
for i := uint16(0); i < dailyWinners; i++ {
|
|
bf.WriteUint32(0) // Guild ID
|
|
bf.WriteUint16(i + 1) // Category ID
|
|
bf.WriteUint16(0) // Festa Team
|
|
ps.Uint8(bf, "", true) // Guild Name
|
|
}
|
|
|
|
d, _ := hex.DecodeString("000000000000000100001388000007D0000003E800000064012C00C8009600640032")
|
|
bf.WriteBytes(d)
|
|
ps.Uint16(bf, "", false)
|
|
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
|
}
|
|
|
|
// 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 {
|
|
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
|
return
|
|
}
|
|
var souls, exists uint32
|
|
s.server.db.QueryRow("SELECT souls FROM guild_characters WHERE character_id=$1", 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)
|
|
bf := byteframe.NewByteFrame()
|
|
bf.WriteUint32(souls)
|
|
if err != nil {
|
|
bf.WriteBool(true)
|
|
bf.WriteBool(false)
|
|
} else {
|
|
bf.WriteBool(false)
|
|
bf.WriteBool(true)
|
|
}
|
|
bf.WriteUint16(0) // Unk
|
|
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
|
}
|
|
|
|
// 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)
|
|
}
|
|
resp := byteframe.NewByteFrame()
|
|
if err != nil || guild == nil || applicant {
|
|
resp.WriteUint32(0)
|
|
resp.WriteUint32(0)
|
|
resp.WriteUint32(0xFFFFFFFF)
|
|
resp.WriteUint32(0)
|
|
resp.WriteUint32(0)
|
|
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
|
return
|
|
}
|
|
resp.WriteUint32(guild.Souls)
|
|
resp.WriteUint32(1) // unk
|
|
resp.WriteUint32(1) // unk
|
|
resp.WriteUint32(1) // unk, rank?
|
|
resp.WriteUint32(1) // unk
|
|
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
|
}
|
|
|
|
func handleMsgMhfEnumerateFestaMember(s *Session, p mhfpacket.MHFPacket) {
|
|
pkt := p.(*mhfpacket.MsgMhfEnumerateFestaMember)
|
|
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
|
if err != nil || guild == nil {
|
|
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
|
return
|
|
}
|
|
members, err := GetGuildMembers(s, guild.ID, false)
|
|
if err != nil {
|
|
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
|
return
|
|
}
|
|
bf := byteframe.NewByteFrame()
|
|
bf.WriteUint16(uint16(len(members)))
|
|
bf.WriteUint16(0) // Unk
|
|
for _, member := range members {
|
|
bf.WriteUint32(member.CharID)
|
|
bf.WriteUint32(member.Souls)
|
|
}
|
|
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
|
}
|
|
|
|
func handleMsgMhfVoteFesta(s *Session, p mhfpacket.MHFPacket) {
|
|
pkt := p.(*mhfpacket.MsgMhfVoteFesta)
|
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
|
}
|
|
|
|
func handleMsgMhfEntryFesta(s *Session, p mhfpacket.MHFPacket) {
|
|
pkt := p.(*mhfpacket.MsgMhfEntryFesta)
|
|
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
|
if err != nil || guild == nil {
|
|
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
|
return
|
|
}
|
|
rand.Seed(time.Now().UnixNano())
|
|
team := uint32(rand.Intn(2))
|
|
switch team {
|
|
case 0:
|
|
s.server.db.Exec("INSERT INTO festa_registrations VALUES ($1, 'blue')", guild.ID)
|
|
case 1:
|
|
s.server.db.Exec("INSERT INTO festa_registrations VALUES ($1, 'red')", guild.ID)
|
|
}
|
|
bf := byteframe.NewByteFrame()
|
|
bf.WriteUint32(team)
|
|
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
|
}
|
|
|
|
func handleMsgMhfChargeFesta(s *Session, p mhfpacket.MHFPacket) {
|
|
pkt := p.(*mhfpacket.MsgMhfChargeFesta)
|
|
s.server.db.Exec("UPDATE guild_characters SET souls=souls+$1 WHERE character_id=$2", pkt.Souls, s.charID)
|
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
|
}
|
|
|
|
func handleMsgMhfAcquireFesta(s *Session, p mhfpacket.MHFPacket) {
|
|
pkt := p.(*mhfpacket.MsgMhfAcquireFesta)
|
|
s.server.db.Exec("INSERT INTO public.festa_prizes_accepted VALUES (0, $1)", s.charID)
|
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
|
}
|
|
|
|
func handleMsgMhfAcquireFestaPersonalPrize(s *Session, p mhfpacket.MHFPacket) {
|
|
pkt := p.(*mhfpacket.MsgMhfAcquireFestaPersonalPrize)
|
|
s.server.db.Exec("INSERT INTO public.festa_prizes_accepted VALUES ($1, $2)", pkt.PrizeID, s.charID)
|
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
|
}
|
|
|
|
func handleMsgMhfAcquireFestaIntermediatePrize(s *Session, p mhfpacket.MHFPacket) {
|
|
pkt := p.(*mhfpacket.MsgMhfAcquireFestaIntermediatePrize)
|
|
s.server.db.Exec("INSERT INTO public.festa_prizes_accepted VALUES ($1, $2)", pkt.PrizeID, s.charID)
|
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
|
}
|
|
|
|
type Prize struct {
|
|
ID uint32 `db:"id"`
|
|
Tier uint32 `db:"tier"`
|
|
SoulsReq uint32 `db:"souls_req"`
|
|
ItemID uint32 `db:"item_id"`
|
|
NumItem uint32 `db:"num_item"`
|
|
Claimed int `db:"claimed"`
|
|
}
|
|
|
|
func handleMsgMhfEnumerateFestaPersonalPrize(s *Session, p mhfpacket.MHFPacket) {
|
|
pkt := p.(*mhfpacket.MsgMhfEnumerateFestaPersonalPrize)
|
|
rows, _ := s.server.db.Queryx("SELECT id, tier, souls_req, item_id, num_item, (SELECT count(*) FROM festa_prizes_accepted fpa WHERE fp.id = fpa.prize_id AND fpa.character_id = 4) AS claimed FROM festa_prizes fp WHERE type='personal'")
|
|
var count uint32
|
|
prizeData := byteframe.NewByteFrame()
|
|
for rows.Next() {
|
|
prize := &Prize{}
|
|
err := rows.StructScan(&prize)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
count++
|
|
prizeData.WriteUint32(prize.ID)
|
|
prizeData.WriteUint32(prize.Tier)
|
|
prizeData.WriteUint32(prize.SoulsReq)
|
|
prizeData.WriteUint32(7) // Unk
|
|
prizeData.WriteUint32(prize.ItemID)
|
|
prizeData.WriteUint32(prize.NumItem)
|
|
prizeData.WriteBool(prize.Claimed > 0)
|
|
}
|
|
bf := byteframe.NewByteFrame()
|
|
bf.WriteUint32(count)
|
|
bf.WriteBytes(prizeData.Data())
|
|
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
|
}
|
|
|
|
func handleMsgMhfEnumerateFestaIntermediatePrize(s *Session, p mhfpacket.MHFPacket) {
|
|
pkt := p.(*mhfpacket.MsgMhfEnumerateFestaIntermediatePrize)
|
|
rows, _ := s.server.db.Queryx("SELECT id, tier, souls_req, item_id, num_item, (SELECT count(*) FROM festa_prizes_accepted fpa WHERE fp.id = fpa.prize_id AND fpa.character_id = 4) AS claimed FROM festa_prizes fp WHERE type='guild'")
|
|
var count uint32
|
|
prizeData := byteframe.NewByteFrame()
|
|
for rows.Next() {
|
|
prize := &Prize{}
|
|
err := rows.StructScan(&prize)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
count++
|
|
prizeData.WriteUint32(prize.ID)
|
|
prizeData.WriteUint32(prize.Tier)
|
|
prizeData.WriteUint32(prize.SoulsReq)
|
|
prizeData.WriteUint32(7) // Unk
|
|
prizeData.WriteUint32(prize.ItemID)
|
|
prizeData.WriteUint32(prize.NumItem)
|
|
prizeData.WriteBool(prize.Claimed > 0)
|
|
}
|
|
bf := byteframe.NewByteFrame()
|
|
bf.WriteUint32(count)
|
|
bf.WriteBytes(prizeData.Data())
|
|
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
|
}
|