mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-15 00:15:08 +01:00
initial databasing
This commit is contained in:
@@ -10,10 +10,10 @@ import (
|
|||||||
|
|
||||||
// MsgMhfAcquireItem represents the MSG_MHF_ACQUIRE_ITEM
|
// MsgMhfAcquireItem represents the MSG_MHF_ACQUIRE_ITEM
|
||||||
type MsgMhfAcquireItem struct {
|
type MsgMhfAcquireItem struct {
|
||||||
AckHandle uint32
|
AckHandle uint32
|
||||||
Unk0 uint16
|
NullPadding uint16 //0 in Z2
|
||||||
Length uint16
|
Length uint16
|
||||||
Unk1 []uint32
|
Unk1 []uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opcode returns the ID associated with this packet type.
|
// Opcode returns the ID associated with this packet type.
|
||||||
@@ -24,7 +24,7 @@ func (m *MsgMhfAcquireItem) Opcode() network.PacketID {
|
|||||||
// Parse parses the packet from binary
|
// Parse parses the packet from binary
|
||||||
func (m *MsgMhfAcquireItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
func (m *MsgMhfAcquireItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||||
m.AckHandle = bf.ReadUint32()
|
m.AckHandle = bf.ReadUint32()
|
||||||
m.Unk0 = bf.ReadUint16()
|
m.NullPadding = bf.ReadUint16()
|
||||||
m.Length = bf.ReadUint16()
|
m.Length = bf.ReadUint16()
|
||||||
for i := 0; i < int(m.Length); i++ {
|
for i := 0; i < int(m.Length); i++ {
|
||||||
m.Unk1 = append(m.Unk1, bf.ReadUint32())
|
m.Unk1 = append(m.Unk1, bf.ReadUint32())
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ import (
|
|||||||
|
|
||||||
// MsgMhfApplyCampaign represents the MSG_MHF_APPLY_CAMPAIGN
|
// MsgMhfApplyCampaign represents the MSG_MHF_APPLY_CAMPAIGN
|
||||||
type MsgMhfApplyCampaign struct {
|
type MsgMhfApplyCampaign struct {
|
||||||
AckHandle uint32
|
AckHandle uint32
|
||||||
Unk0 uint32
|
CampaignID uint32
|
||||||
Unk1 uint16
|
NullPadding uint16 // set as 0 in z2
|
||||||
Unk2 []byte
|
CodeString []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opcode returns the ID associated with this packet type.
|
// Opcode returns the ID associated with this packet type.
|
||||||
@@ -23,9 +23,9 @@ func (m *MsgMhfApplyCampaign) Opcode() network.PacketID {
|
|||||||
// Parse parses the packet from binary
|
// Parse parses the packet from binary
|
||||||
func (m *MsgMhfApplyCampaign) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
func (m *MsgMhfApplyCampaign) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||||
m.AckHandle = bf.ReadUint32()
|
m.AckHandle = bf.ReadUint32()
|
||||||
m.Unk0 = bf.ReadUint32()
|
m.CampaignID = bf.ReadUint32()
|
||||||
m.Unk1 = bf.ReadUint16()
|
m.NullPadding = bf.ReadUint16()
|
||||||
m.Unk2 = bf.ReadBytes(16)
|
m.CodeString = bf.ReadBytes(16)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ import (
|
|||||||
|
|
||||||
// MsgMhfEnumerateCampaign represents the MSG_MHF_ENUMERATE_CAMPAIGN
|
// MsgMhfEnumerateCampaign represents the MSG_MHF_ENUMERATE_CAMPAIGN
|
||||||
type MsgMhfEnumerateCampaign struct {
|
type MsgMhfEnumerateCampaign struct {
|
||||||
AckHandle uint32
|
AckHandle uint32
|
||||||
Unk0 uint16
|
NullPadding1 uint16 // 0 in z2
|
||||||
Unk1 uint16
|
NullPadding2 uint16 // 0 in z2
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opcode returns the ID associated with this packet type.
|
// Opcode returns the ID associated with this packet type.
|
||||||
@@ -21,15 +21,15 @@ func (m *MsgMhfEnumerateCampaign) Opcode() network.PacketID {
|
|||||||
// Parse parses the packet from binary
|
// Parse parses the packet from binary
|
||||||
func (m *MsgMhfEnumerateCampaign) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
func (m *MsgMhfEnumerateCampaign) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||||
m.AckHandle = bf.ReadUint32()
|
m.AckHandle = bf.ReadUint32()
|
||||||
m.Unk0 = bf.ReadUint16()
|
m.NullPadding1 = bf.ReadUint16()
|
||||||
m.Unk1 = bf.ReadUint16()
|
m.NullPadding2 = bf.ReadUint16()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build builds a binary packet from the current data.
|
// Build builds a binary packet from the current data.
|
||||||
func (m *MsgMhfEnumerateCampaign) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
func (m *MsgMhfEnumerateCampaign) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||||
bf.WriteUint32(m.AckHandle)
|
bf.WriteUint32(m.AckHandle)
|
||||||
bf.WriteUint16(m.Unk0)
|
bf.WriteUint16(m.NullPadding1)
|
||||||
bf.WriteUint16(m.Unk1)
|
bf.WriteUint16(m.NullPadding2)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ import (
|
|||||||
|
|
||||||
// MsgMhfEnumerateItem represents the MSG_MHF_ENUMERATE_ITEM
|
// MsgMhfEnumerateItem represents the MSG_MHF_ENUMERATE_ITEM
|
||||||
type MsgMhfEnumerateItem struct {
|
type MsgMhfEnumerateItem struct {
|
||||||
AckHandle uint32
|
AckHandle uint32
|
||||||
Unk0 uint16
|
NullPadding uint16 // 0 in Z2
|
||||||
Unk1 uint16
|
Unk1 uint16 //0002
|
||||||
CampaignID uint32
|
CampaignID uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opcode returns the ID associated with this packet type.
|
// Opcode returns the ID associated with this packet type.
|
||||||
@@ -24,7 +24,7 @@ func (m *MsgMhfEnumerateItem) Opcode() network.PacketID {
|
|||||||
// Parse parses the packet from binary
|
// Parse parses the packet from binary
|
||||||
func (m *MsgMhfEnumerateItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
func (m *MsgMhfEnumerateItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||||
m.AckHandle = bf.ReadUint32()
|
m.AckHandle = bf.ReadUint32()
|
||||||
m.Unk0 = bf.ReadUint16()
|
m.NullPadding = bf.ReadUint16()
|
||||||
m.Unk1 = bf.ReadUint16()
|
m.Unk1 = bf.ReadUint16()
|
||||||
m.CampaignID = bf.ReadUint32()
|
m.CampaignID = bf.ReadUint32()
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ import (
|
|||||||
|
|
||||||
// MsgMhfStateCampaign represents the MSG_MHF_STATE_CAMPAIGN
|
// MsgMhfStateCampaign represents the MSG_MHF_STATE_CAMPAIGN
|
||||||
type MsgMhfStateCampaign struct {
|
type MsgMhfStateCampaign struct {
|
||||||
AckHandle uint32
|
AckHandle uint32
|
||||||
CampaignID uint32
|
CampaignID uint32
|
||||||
Unk1 uint16
|
NullPadding uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opcode returns the ID associated with this packet type.
|
// Opcode returns the ID associated with this packet type.
|
||||||
@@ -24,7 +24,7 @@ func (m *MsgMhfStateCampaign) Opcode() network.PacketID {
|
|||||||
func (m *MsgMhfStateCampaign) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
func (m *MsgMhfStateCampaign) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||||
m.AckHandle = bf.ReadUint32()
|
m.AckHandle = bf.ReadUint32()
|
||||||
m.CampaignID = bf.ReadUint32()
|
m.CampaignID = bf.ReadUint32()
|
||||||
m.Unk1 = bf.ReadUint16()
|
m.NullPadding = bf.ReadUint16() //0 in Z2
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
56
patch-schema/12-campaign.sql
Normal file
56
patch-schema/12-campaign.sql
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS public.campaigns (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
unk0 INTEGER,
|
||||||
|
min_hr INTEGER,
|
||||||
|
max_hr INTEGER,
|
||||||
|
min_sr INTEGER,
|
||||||
|
max_sr INTEGER,
|
||||||
|
min_gr INTEGER,
|
||||||
|
max_gr INTEGER,
|
||||||
|
unk1 INTEGER,
|
||||||
|
unk2 INTEGER,
|
||||||
|
unk3 INTEGER,
|
||||||
|
background_id INTEGER,
|
||||||
|
hide_npc BOOLEAN,
|
||||||
|
start_time TIMESTAMP WITH TIME ZONE,
|
||||||
|
end_time TIMESTAMP WITH TIME ZONE,
|
||||||
|
period_ended BOOLEAN,
|
||||||
|
string0 TEXT,
|
||||||
|
string1 TEXT,
|
||||||
|
string2 TEXT,
|
||||||
|
string3 TEXT,
|
||||||
|
link TEXT,
|
||||||
|
code_prefix TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS public.campaign_categories (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
cat_type INTEGER,
|
||||||
|
title TEXT,
|
||||||
|
description_text TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS public.campaign_category_links (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
campaign_id INTEGER,
|
||||||
|
category_id INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS public.campaign_entries (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
campaign_id INTEGER,
|
||||||
|
hide BOOLEAN,
|
||||||
|
item_type INTEGER,
|
||||||
|
item_amount INTEGER,
|
||||||
|
item_no INTEGER,
|
||||||
|
unk1 INTEGER,
|
||||||
|
unk2 INTEGER,
|
||||||
|
deadline TIMESTAMP WITH TIME ZONE
|
||||||
|
);
|
||||||
|
|
||||||
|
END;
|
||||||
@@ -10,51 +10,69 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type CampaignEvent struct {
|
type CampaignEvent struct {
|
||||||
ID uint32
|
ID uint32 `db:"id"`
|
||||||
Unk0 uint32
|
Unk0 uint32 `db:"unk0"`
|
||||||
MinHR int16
|
MinHR int16 `db:"min_hr"`
|
||||||
MaxHR int16
|
MaxHR int16 `db:"max_hr"`
|
||||||
MinSR int16
|
MinSR int16 `db:"min_sr"`
|
||||||
MaxSR int16
|
MaxSR int16 `db:"max_sr"`
|
||||||
MinGR int16
|
MinGR int16 `db:"min_gr"`
|
||||||
MaxGR int16
|
MaxGR int16 `db:"max_gr"`
|
||||||
Unk1 uint16
|
Unk1 uint16 `db:"unk1"`
|
||||||
Unk2 uint8
|
Unk2 uint8 `db:"unk2"`
|
||||||
Unk3 uint8
|
Unk3 uint8 `db:"unk3"`
|
||||||
Unk4 uint16
|
BackgroundID uint16 `db:"background_id"`
|
||||||
Unk5 uint16
|
HideNPC bool `db:"hide_npc"` //TODO: FIX this is actual a uint16 however giving this thew value 1 or above made the NPC glitch / hide
|
||||||
Start time.Time
|
Start time.Time `db:"start_time"`
|
||||||
End time.Time
|
End time.Time `db:"end_time"`
|
||||||
Unk6 uint8
|
PeriodEnded bool `db:"period_ended"`
|
||||||
String0 string
|
String0 string `db:"string0"`
|
||||||
String1 string
|
String1 string `db:"string1"`
|
||||||
String2 string
|
String2 string `db:"string2"`
|
||||||
String3 string
|
String3 string `db:"string3"`
|
||||||
Link string
|
Link string `db:"link"`
|
||||||
Prefix string
|
Prefix string `db:"code_prefix"`
|
||||||
Categories []uint16
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type CampaignCategory struct {
|
type CampaignCategory struct {
|
||||||
ID uint16
|
ID uint16 `db:"id"`
|
||||||
Type uint8
|
Type uint8 `db:"cat_type"`
|
||||||
Title string
|
Title string `db:"title"`
|
||||||
Description string
|
Description string `db:"description_text"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CampaignLink struct {
|
type CampaignLink struct {
|
||||||
CategoryID uint16
|
CategoryID uint16 `db:"category_id"`
|
||||||
CampaignID uint32
|
CampaignID uint32 `db:"campaign_id"`
|
||||||
|
}
|
||||||
|
type CampaignEntry struct {
|
||||||
|
ID uint32 `db:"id"`
|
||||||
|
Hide bool `db:"hide"`
|
||||||
|
ItemType uint8 `db:"item_type"`
|
||||||
|
Amount uint16 `db:"item_amount"`
|
||||||
|
ItemNo uint16 `db:"item_no"`
|
||||||
|
Unk4 uint16 `db:"unk1"`
|
||||||
|
Unk5 uint32 `db:"unk2"`
|
||||||
|
DeadLine time.Time `db:"deadline"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfEnumerateCampaign)
|
pkt := p.(*mhfpacket.MsgMhfEnumerateCampaign)
|
||||||
bf := byteframe.NewByteFrame()
|
bf := byteframe.NewByteFrame()
|
||||||
|
|
||||||
events := []CampaignEvent{}
|
var events []CampaignEvent
|
||||||
categories := []CampaignCategory{}
|
var categories []CampaignCategory
|
||||||
|
|
||||||
var campaignLinks []CampaignLink
|
var campaignLinks []CampaignLink
|
||||||
|
|
||||||
|
err := s.server.db.Select(&events, "SELECT id,unk0,min_hr,max_hr,min_sr,max_sr,min_gr,max_gr,unk1,unk2,unk3,background_id,hide_npc,start_time,end_time,period_ended,string0,string1,string2,string3,link,code_prefix FROM campaigns")
|
||||||
|
err = s.server.db.Select(&categories, "SELECT id, cat_type, title, description_text FROM campaign_categories")
|
||||||
|
err = s.server.db.Select(&campaignLinks, "SELECT campaign_id, category_id FROM campaign_category_links")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
return
|
||||||
|
}
|
||||||
if len(events) > 255 {
|
if len(events) > 255 {
|
||||||
bf.WriteUint8(255)
|
bf.WriteUint8(255)
|
||||||
bf.WriteUint16(uint16(len(events)))
|
bf.WriteUint16(uint16(len(events)))
|
||||||
@@ -75,19 +93,17 @@ func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
bf.WriteUint16(event.Unk1)
|
bf.WriteUint16(event.Unk1)
|
||||||
bf.WriteUint8(event.Unk2)
|
bf.WriteUint8(event.Unk2)
|
||||||
bf.WriteUint8(event.Unk3)
|
bf.WriteUint8(event.Unk3)
|
||||||
bf.WriteUint16(event.Unk4)
|
bf.WriteUint16(event.BackgroundID)
|
||||||
bf.WriteUint16(event.Unk5)
|
bf.WriteUint16(uint16(0))
|
||||||
bf.WriteUint32(uint32(event.Start.Unix()))
|
bf.WriteUint32(uint32(event.Start.Unix()))
|
||||||
bf.WriteUint32(uint32(event.End.Unix()))
|
bf.WriteUint32(uint32(event.End.Unix()))
|
||||||
bf.WriteUint8(event.Unk6)
|
bf.WriteBool(event.PeriodEnded)
|
||||||
ps.Uint8(bf, event.String0, true)
|
ps.Uint8(bf, event.String0, true)
|
||||||
ps.Uint8(bf, event.String1, true)
|
ps.Uint8(bf, event.String1, true)
|
||||||
ps.Uint8(bf, event.String2, true)
|
ps.Uint8(bf, event.String2, true)
|
||||||
ps.Uint8(bf, event.String3, true)
|
ps.Uint8(bf, event.String3, true)
|
||||||
ps.Uint8(bf, event.Link, true)
|
ps.Uint8(bf, event.Link, true)
|
||||||
for i := range event.Categories {
|
|
||||||
campaignLinks = append(campaignLinks, CampaignLink{event.Categories[i], event.ID})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(events) > 255 {
|
if len(events) > 255 {
|
||||||
@@ -135,39 +151,57 @@ func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
func handleMsgMhfStateCampaign(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfStateCampaign(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfStateCampaign)
|
pkt := p.(*mhfpacket.MsgMhfStateCampaign)
|
||||||
bf := byteframe.NewByteFrame()
|
bf := byteframe.NewByteFrame()
|
||||||
bf.WriteUint16(1)
|
var unk []uint32
|
||||||
bf.WriteUint16(0)
|
var result uint16 = 1 //3 stamp//2 Event already acomplished //1 Stamp? //0 stamp
|
||||||
|
bf.WriteUint16(uint16(len(unk)))
|
||||||
|
bf.WriteUint16(result)
|
||||||
|
for _, value := range unk {
|
||||||
|
bf.WriteUint32(value)
|
||||||
|
}
|
||||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgMhfApplyCampaign(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfApplyCampaign(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfApplyCampaign)
|
pkt := p.(*mhfpacket.MsgMhfApplyCampaign)
|
||||||
bf := byteframe.NewByteFrame()
|
|
||||||
bf.WriteUint32(1)
|
// Check campaign ID
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
// Check code against campaign list of codes to see if valid....
|
||||||
|
//checkCode(pkt.CodeString,pkt.CampaignID)
|
||||||
|
validCode := true
|
||||||
|
if validCode {
|
||||||
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
} else {
|
||||||
|
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgMhfEnumerateItem(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfEnumerateItem(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfEnumerateItem)
|
pkt := p.(*mhfpacket.MsgMhfEnumerateItem)
|
||||||
items := []struct {
|
|
||||||
Unk0 uint32
|
|
||||||
Unk1 uint16
|
|
||||||
Unk2 uint16
|
|
||||||
Unk3 uint16
|
|
||||||
Unk4 uint32
|
|
||||||
Unk5 uint32
|
|
||||||
}{}
|
|
||||||
bf := byteframe.NewByteFrame()
|
bf := byteframe.NewByteFrame()
|
||||||
|
var items []CampaignEntry
|
||||||
|
err := s.server.db.Select(&items, "SELECT id,hide,item_type,item_amount,item_no,unk1,unk2,deadline FROM campaign_entries WHERE campaign_id = $1", pkt.CampaignID)
|
||||||
|
if err != nil {
|
||||||
|
doAckBufFail(s, pkt.AckHandle, bf.Data())
|
||||||
|
return
|
||||||
|
}
|
||||||
bf.WriteUint16(uint16(len(items)))
|
bf.WriteUint16(uint16(len(items)))
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
bf.WriteUint32(item.Unk0)
|
bf.WriteUint32(item.ID)
|
||||||
bf.WriteUint16(item.Unk1)
|
bf.WriteBool(item.Hide)
|
||||||
bf.WriteUint16(item.Unk2)
|
bf.WriteUint8(item.ItemType)
|
||||||
bf.WriteUint16(item.Unk3)
|
bf.WriteUint16(item.Amount)
|
||||||
bf.WriteUint32(item.Unk4)
|
bf.WriteUint16(item.ItemNo)
|
||||||
|
bf.WriteUint16(item.Unk4)
|
||||||
bf.WriteUint32(item.Unk5)
|
bf.WriteUint32(item.Unk5)
|
||||||
|
bf.WriteUint32(uint32(item.DeadLine.Unix()))
|
||||||
|
}
|
||||||
|
if len(items) == 0 {
|
||||||
|
doAckBufFail(s, pkt.AckHandle, bf.Data())
|
||||||
|
|
||||||
|
} else {
|
||||||
|
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||||
|
|
||||||
}
|
}
|
||||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgMhfAcquireItem(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfAcquireItem(s *Session, p mhfpacket.MHFPacket) {
|
||||||
|
|||||||
Reference in New Issue
Block a user