7 Commits

Author SHA1 Message Date
wish
e412592745 Merge branch 'refs/heads/main' into feature/hunting-tournament 2024-06-25 22:51:21 +10:00
wish
94e0f20682 fix EnumerateOrder 2024-06-25 22:24:44 +10:00
wish
79dce0bc52 fix EnumerateOrder & TournamentEvent struct 2024-06-25 21:49:41 +10:00
wish
4c485ef55a update branch, handle EnumerateOrder 2024-06-25 21:04:51 +10:00
wish
fe1052a517 Merge branch 'refs/heads/main' into feature/hunting-tournament 2024-06-25 21:00:47 +10:00
stratic-dev
687ad05172 Merge branch 'main' into feature/hunting-tournament 2024-02-24 22:45:45 +00:00
wish
38f4399cab initial hunting-tournament commit 2023-09-05 23:58:39 +10:00
3 changed files with 176 additions and 62 deletions

View File

@@ -1,18 +1,18 @@
package mhfpacket
import (
"errors"
import (
"errors"
"erupe-ce/network/clientctx"
"erupe-ce/network"
"erupe-ce/common/byteframe"
"erupe-ce/network"
"erupe-ce/network/clientctx"
)
// MsgMhfEnumerateOrder represents the MSG_MHF_ENUMERATE_ORDER
type MsgMhfEnumerateOrder struct {
AckHandle uint32
Unk0 uint32
Unk1 uint32
EventID uint32
ClanID uint32
}
// Opcode returns the ID associated with this packet type.
@@ -23,8 +23,8 @@ func (m *MsgMhfEnumerateOrder) Opcode() network.PacketID {
// Parse parses the packet from binary
func (m *MsgMhfEnumerateOrder) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
m.AckHandle = bf.ReadUint32()
m.Unk0 = bf.ReadUint32()
m.Unk1 = bf.ReadUint32()
m.EventID = bf.ReadUint32()
m.ClanID = bf.ReadUint32()
return nil
}

View File

@@ -811,11 +811,6 @@ func handleMsgMhfEnumeratePrice(s *Session, p mhfpacket.MHFPacket) {
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
func handleMsgMhfEnumerateOrder(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfEnumerateOrder)
stubEnumerateNoResults(s, pkt.AckHandle)
}
func handleMsgMhfGetExtraInfo(s *Session, p mhfpacket.MHFPacket) {}
func userGetItems(s *Session) []mhfitem.MHFItemStack {

View File

@@ -3,6 +3,7 @@ package channelserver
import (
"erupe-ce/common/byteframe"
ps "erupe-ce/common/pascalstring"
"erupe-ce/common/stringsupport"
"erupe-ce/common/token"
_config "erupe-ce/config"
"erupe-ce/network/mhfpacket"
@@ -33,62 +34,180 @@ func handleMsgMhfLoadMezfesData(s *Session, p mhfpacket.MHFPacket) {
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
func generateTournamentTimestamps(start uint32, debug bool) []uint32 {
timestamps := make([]uint32, 4)
midnight := TimeMidnight()
if debug && start <= 3 {
midnight := uint32(midnight.Unix())
switch start {
case 1:
timestamps[0] = midnight
timestamps[1] = timestamps[0] + 259200
timestamps[2] = timestamps[1] + 766800
timestamps[3] = timestamps[2] + 604800
case 2:
timestamps[0] = midnight - 259200
timestamps[1] = midnight
timestamps[2] = timestamps[1] + 766800
timestamps[3] = timestamps[2] + 604800
case 3:
timestamps[0] = midnight - 1026000
timestamps[1] = midnight - 766800
timestamps[2] = midnight
timestamps[3] = timestamps[2] + 604800
}
return timestamps
}
timestamps[0] = start
timestamps[1] = timestamps[0] + 259200
timestamps[2] = timestamps[1] + 766800
timestamps[3] = timestamps[2] + 604800
return timestamps
}
type TournamentEvent struct {
ID uint32
CupGroup uint16
EventSubType int16
QuestFileID uint32
Name string
}
type TournamentCup struct {
ID uint32
CupGroup uint16
Type uint16
Unk uint16
Name string
Description string
}
func handleMsgMhfEnumerateRanking(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfEnumerateRanking)
bf := byteframe.NewByteFrame()
state := s.server.erupeConfig.DebugOptions.TournamentOverride
// Unk
// Unk
// Start?
// End?
midnight := TimeMidnight()
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:
id, start := uint32(0xBEEFDEAD), 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.DebugOptions.TournamentOverride >= 0 {
if s.server.erupeConfig.DebugOptions.TournamentOverride == 0 {
bf.WriteBytes(make([]byte, 16))
bf.WriteUint32(uint32(TimeAdjusted().Unix()))
bf.WriteUint8(0)
ps.Uint8(bf, "", true)
bf.WriteUint16(0)
bf.WriteUint8(0)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
return
}
timestamps = generateTournamentTimestamps(uint32(s.server.erupeConfig.DebugOptions.TournamentOverride), true)
} else {
timestamps = generateTournamentTimestamps(start, false)
}
if timestamps[0] > uint32(TimeAdjusted().Unix()) {
bf.WriteBytes(make([]byte, 16))
bf.WriteUint32(uint32(TimeAdjusted().Unix())) // TS Current Time
bf.WriteUint8(3)
bf.WriteBytes(make([]byte, 4))
bf.WriteUint32(uint32(TimeAdjusted().Unix()))
bf.WriteUint8(0)
ps.Uint8(bf, "", true)
bf.WriteUint16(0)
bf.WriteUint8(0)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
return
}
bf.WriteUint32(uint32(TimeAdjusted().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
for _, timestamp := range timestamps {
bf.WriteUint32(timestamp)
}
bf.WriteUint32(uint32(TimeAdjusted().Unix()))
bf.WriteUint8(1) // TODO: Make this dynamic depending on timestamp
ps.Uint8(bf, "第150回公式狩猟大会", true)
struct cup
uint32 cupID
uint16 unk
uint16 unk
uint16 unk
psUint8 name
psUint16 desc
*/
// Temp direct port
tournamentEvents := []TournamentEvent{
{2644, 16, 0, 60691, "爆霧竜討伐!"},
{2645, 16, 1, 60691, "爆霧竜討伐!"},
{2646, 16, 2, 60691, "爆霧竜討伐!"},
{2647, 16, 3, 60691, "爆霧竜討伐!"},
{2648, 16, 4, 60691, "爆霧竜討伐!"},
{2649, 16, 5, 60691, "爆霧竜討伐!"},
{2650, 16, 6, 60691, "爆霧竜討伐!"},
{2651, 16, 7, 60691, "爆霧竜討伐!"},
{2652, 16, 8, 60691, "爆霧竜討伐!"},
{2653, 16, 9, 60691, "爆霧竜討伐!"},
{2654, 16, 10, 60691, "爆霧竜討伐!"},
{2655, 16, 11, 60691, "爆霧竜討伐!"},
{2656, 16, 12, 60691, "爆霧竜討伐!"},
{2657, 16, 13, 60691, "爆霧竜討伐!"},
{2658, 17, -1, 60690, "みんなで爆霧竜討伐!"},
{2659, 6, 234, 0, "キレアジ"},
{2660, 6, 237, 0, "ハリマグロ"},
{2661, 6, 239, 0, "カクサンデメキン"},
}
tournamentCups := []TournamentCup{
{569, 6, 6, 0, "個人 巨大魚杯", "~C05【競技内容】\n~C00クエストで釣った魚のサイズを競う\n~C04【対象魚】\n~C00キレアジ、\nハリマグロ、カクサンデメキン\n~C07【入賞賞品】\n~C00魚杯のしるし、タルネコ生産券、\nグーク生産券、グーク足生産券、\nグーク解放券(1〜3位)\n/猟団ポイント(1〜100位)\n/匠チケット+ハーフチケット白\n(1〜500位)\n~C03【開催期間】\n~C002019年11月22日 14:00から\n2019年11月25日 14:00まで"},
{570, 17, 7, 0, "猟団 G級韋駄天杯", "~C05【競技内容】\n~C00≪みんなで爆霧竜討伐≫を\n同じ猟団に所属する4人までの\n猟団員でいかに早くクリアするか\nを競う\n\n~C07【入賞賞品】\n~C00第147回狩人祭の魂(1〜200位)\n\n~C03【開催期間】\n~C002019年11月22日 14:00から\n2019年11月25日 14:00まで\n\n"},
{571, 16, 7, 0, "個人 G級韋駄天杯", "~C05【競技内容】\n~C00≪爆霧竜討伐≫を\nいかに早くクリアするかを競う\n\n~C07【入賞賞品】\n~C00王者のメダル(1位)\n/公式のしるし、タルネコ生産券、\nグーク生産券、グーク足生産券、\nグーク解放券(1〜3位)\n/猟団ポイント(1〜100位)\n/匠チケット+ハーフチケット白\n(1〜500位)\n~C03【開催期間】\n~C002019年11月22日 14:00から\n2019年11月25日 14:00まで"},
}
bf.WriteUint16(uint16(len(tournamentEvents)))
for _, event := range tournamentEvents {
bf.WriteUint32(event.ID)
bf.WriteUint16(event.CupGroup)
bf.WriteInt16(event.EventSubType)
bf.WriteUint32(event.QuestFileID)
ps.Uint8(bf, event.Name, true)
}
bf.WriteUint8(uint8(len(tournamentCups)))
for _, cup := range tournamentCups {
bf.WriteUint32(cup.ID)
bf.WriteUint16(cup.CupGroup)
bf.WriteUint16(cup.Type)
bf.WriteUint16(cup.Unk)
ps.Uint8(bf, cup.Name, true)
ps.Uint16(bf, cup.Description, true)
}
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
type TournamentRank struct {
CID uint32
Rank uint32
Grade uint16
HR uint16
GR uint16
CharName string
GuildName string
}
func handleMsgMhfEnumerateOrder(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfEnumerateOrder)
bf := byteframe.NewByteFrame()
bf.WriteUint32(pkt.EventID)
bf.WriteUint32(uint32(TimeAdjusted().Unix()))
tournamentRanks := []TournamentRank{}
bf.WriteUint16(uint16(len(tournamentRanks)))
bf.WriteUint16(0) // Unk
for _, rank := range tournamentRanks {
bf.WriteUint32(rank.CID)
bf.WriteUint32(rank.Rank)
bf.WriteUint16(rank.Grade)
bf.WriteUint16(0)
bf.WriteUint16(rank.HR)
if _config.ErupeConfig.RealClientMode >= _config.G10 {
bf.WriteUint16(rank.GR)
}
bf.WriteUint16(0)
bf.WriteUint8(uint8(len(rank.CharName) + 1))
bf.WriteUint8(uint8(len(rank.GuildName) + 1))
bf.WriteNullTerminatedBytes(stringsupport.UTF8ToSJIS(rank.CharName))
bf.WriteNullTerminatedBytes(stringsupport.UTF8ToSJIS(rank.GuildName))
}
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
@@ -127,10 +246,10 @@ func generateFestaTimestamps(s *Session, start uint32, debug bool) []uint32 {
}
return timestamps
}
if start == 0 || TimeAdjusted().Unix() > int64(start)+2977200 {
if start == 0 || TimeAdjusted().Unix() > int64(start)+3024000 {
cleanupFesta(s)
// Generate a new festa, starting midnight tomorrow
start = uint32(midnight.Add(24 * time.Hour).Unix())
// Generate a new festa, starting 11am tomorrow
start = uint32(midnight.Add(35 * 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