API: Add join order and local player count

This commit is contained in:
mkwcat 2024-01-01 22:59:03 -05:00
parent 61d3176e11
commit 4e8ad85020
No known key found for this signature in database
GPG Key ID: 7A505679CE9E7AA9
7 changed files with 227 additions and 138 deletions

View File

@ -24,13 +24,14 @@ func HandleGroups(w http.ResponseWriter, r *http.Request) {
return
}
gameName := query.Get("gamename")
gameName := query.Get("game")
groups := qr2.GetGroups(gameName)
for _, group := range groups {
for i, player := range group.Players {
filtered := map[string]string{}
filtered["count"] = player["+localplayers"]
filtered["pid"] = player["dwc_pid"]
filtered["name"] = player["+ingamesn"]

View File

@ -3,8 +3,9 @@ package common
import (
"encoding/binary"
"fmt"
"github.com/logrusorgru/aurora/v3"
"wwfc/logging"
"github.com/logrusorgru/aurora/v3"
)
const (
@ -39,6 +40,9 @@ const (
)
type MatchCommandData struct {
Version int
Command byte
Reservation *MatchCommandDataReservation
ResvOK *MatchCommandDataResvOK
ResvDeny *MatchCommandDataResvDeny
@ -199,10 +203,14 @@ func DecodeMatchCommand(command byte, buffer []byte, version int) (MatchCommandD
}
if version == 3 && len(buffer) < 0x0C {
return MatchCommandData{Reservation: &MatchCommandDataReservation{
MatchType: byte(matchType),
HasPublicIP: false,
}}, true
return MatchCommandData{
Version: version,
Command: command,
Reservation: &MatchCommandDataReservation{
MatchType: byte(matchType),
HasPublicIP: false,
},
}, true
}
publicPort := binary.LittleEndian.Uint32(buffer[0x08:0x0C])
@ -212,13 +220,17 @@ func DecodeMatchCommand(command byte, buffer []byte, version int) (MatchCommandD
switch version {
case 3:
return MatchCommandData{Reservation: &MatchCommandDataReservation{
MatchType: byte(matchType),
HasPublicIP: true,
PublicIP: binary.BigEndian.Uint32(buffer[0x04:0x08]),
PublicPort: uint16(publicPort),
UserData: buffer[0x0C:],
}}, true
return MatchCommandData{
Version: version,
Command: command,
Reservation: &MatchCommandDataReservation{
MatchType: byte(matchType),
HasPublicIP: true,
PublicIP: binary.BigEndian.Uint32(buffer[0x04:0x08]),
PublicPort: uint16(publicPort),
UserData: buffer[0x0C:],
},
}, true
case 11:
isFriendValue := binary.LittleEndian.Uint32(buffer[0x0C:0x10])
@ -227,15 +239,19 @@ func DecodeMatchCommand(command byte, buffer []byte, version int) (MatchCommandD
}
isFriend := isFriendValue != 0
return MatchCommandData{Reservation: &MatchCommandDataReservation{
MatchType: byte(matchType),
HasPublicIP: true,
PublicIP: binary.BigEndian.Uint32(buffer[0x04:0x08]),
PublicPort: uint16(publicPort),
IsFriend: isFriend,
LocalPlayerCount: binary.LittleEndian.Uint32(buffer[0x10:0x14]),
UserData: buffer[0x14:],
}}, true
return MatchCommandData{
Version: version,
Command: command,
Reservation: &MatchCommandDataReservation{
MatchType: byte(matchType),
HasPublicIP: true,
PublicIP: binary.BigEndian.Uint32(buffer[0x04:0x08]),
PublicPort: uint16(publicPort),
IsFriend: isFriend,
LocalPlayerCount: binary.LittleEndian.Uint32(buffer[0x10:0x14]),
UserData: buffer[0x14:],
},
}, true
case 90:
localPort := binary.LittleEndian.Uint32(buffer[0x10:0x14])
@ -249,19 +265,22 @@ func DecodeMatchCommand(command byte, buffer []byte, version int) (MatchCommandD
}
isFriend := isFriendValue != 0
return MatchCommandData{Reservation: &MatchCommandDataReservation{
MatchType: byte(matchType),
HasPublicIP: true,
PublicIP: binary.BigEndian.Uint32(buffer[0x04:0x08]),
PublicPort: uint16(publicPort),
LocalIP: binary.BigEndian.Uint32(buffer[0x0C:0x10]),
LocalPort: uint16(localPort),
Unknown: binary.LittleEndian.Uint32(buffer[0x14:0x18]),
IsFriend: isFriend,
LocalPlayerCount: binary.LittleEndian.Uint32(buffer[0x1C:0x20]),
ResvCheckValue: binary.LittleEndian.Uint32(buffer[0x20:0x24]),
UserData: buffer[0x24:],
}}, true
return MatchCommandData{
Version: version,
Command: command,
Reservation: &MatchCommandDataReservation{
MatchType: byte(matchType),
HasPublicIP: true,
PublicIP: binary.BigEndian.Uint32(buffer[0x04:0x08]),
PublicPort: uint16(publicPort),
LocalIP: binary.BigEndian.Uint32(buffer[0x0C:0x10]),
LocalPort: uint16(localPort),
Unknown: binary.LittleEndian.Uint32(buffer[0x14:0x18]),
IsFriend: isFriend,
LocalPlayerCount: binary.LittleEndian.Uint32(buffer[0x1C:0x20]),
ResvCheckValue: binary.LittleEndian.Uint32(buffer[0x20:0x24]),
UserData: buffer[0x24:],
}}, true
}
case MatchResvOK:
@ -291,13 +310,17 @@ func DecodeMatchCommand(command byte, buffer []byte, version int) (MatchCommandD
}
if version == 3 {
return MatchCommandData{ResvOK: &MatchCommandDataResvOK{
PublicIP: binary.BigEndian.Uint32(buffer[index : index+0x04]),
PublicPort: uint16(publicPort),
ClientCount: clientCount,
ProfileIDs: profileIDs,
UserData: buffer[index+0x8:],
}}, true
return MatchCommandData{
Version: version,
Command: command,
ResvOK: &MatchCommandDataResvOK{
PublicIP: binary.BigEndian.Uint32(buffer[index : index+0x04]),
PublicPort: uint16(publicPort),
ClientCount: clientCount,
ProfileIDs: profileIDs,
UserData: buffer[index+0x8:],
},
}, true
} else if version == 11 {
isFriendValue := binary.LittleEndian.Uint32(buffer[index+0x08 : index+0x0C])
if isFriendValue > 1 {
@ -305,17 +328,20 @@ func DecodeMatchCommand(command byte, buffer []byte, version int) (MatchCommandD
}
isFriend := isFriendValue != 0
return MatchCommandData{ResvOK: &MatchCommandDataResvOK{
MaxPlayers: binary.LittleEndian.Uint32(buffer[index+0x14 : index+0x18]),
SenderAID: binary.LittleEndian.Uint32(buffer[index+0x0C : index+0x10]),
PublicIP: binary.BigEndian.Uint32(buffer[index : index+0x04]),
PublicPort: uint16(publicPort),
GroupID: binary.LittleEndian.Uint32(buffer[index+0x10 : index+0x14]),
ClientCount: clientCount,
ProfileIDs: profileIDs,
IsFriend: isFriend,
UserData: buffer[index+0x18:],
}}, true
return MatchCommandData{
Version: version,
Command: command,
ResvOK: &MatchCommandDataResvOK{
MaxPlayers: binary.LittleEndian.Uint32(buffer[index+0x14 : index+0x18]),
SenderAID: binary.LittleEndian.Uint32(buffer[index+0x0C : index+0x10]),
PublicIP: binary.BigEndian.Uint32(buffer[index : index+0x04]),
PublicPort: uint16(publicPort),
GroupID: binary.LittleEndian.Uint32(buffer[index+0x10 : index+0x14]),
ClientCount: clientCount,
ProfileIDs: profileIDs,
IsFriend: isFriend,
UserData: buffer[index+0x18:],
}}, true
}
break
}
@ -335,22 +361,26 @@ func DecodeMatchCommand(command byte, buffer []byte, version int) (MatchCommandD
break
}
return MatchCommandData{ResvOK: &MatchCommandDataResvOK{
MaxPlayers: binary.LittleEndian.Uint32(buffer[0x00:0x04]),
SenderAID: binary.LittleEndian.Uint32(buffer[0x04:0x08]),
ProfileID: binary.LittleEndian.Uint32(buffer[0x08:0x0C]),
PublicIP: binary.BigEndian.Uint32(buffer[0x0C:0x10]),
PublicPort: uint16(publicPort),
LocalIP: binary.BigEndian.Uint32(buffer[0x14:0x18]),
LocalPort: uint16(localPort),
Unknown: binary.LittleEndian.Uint32(buffer[0x1C:0x20]),
LocalPlayerCount: binary.LittleEndian.Uint32(buffer[0x20:0x24]),
GroupID: binary.LittleEndian.Uint32(buffer[0x24:0x28]),
ReceiverNewAID: binary.LittleEndian.Uint32(buffer[0x28:0x2C]),
ClientCount: binary.LittleEndian.Uint32(buffer[0x2C:0x30]),
ResvCheckValue: binary.LittleEndian.Uint32(buffer[0x30:0x34]),
UserData: buffer[0x34:],
}}, true
return MatchCommandData{
Version: version,
Command: command,
ResvOK: &MatchCommandDataResvOK{
MaxPlayers: binary.LittleEndian.Uint32(buffer[0x00:0x04]),
SenderAID: binary.LittleEndian.Uint32(buffer[0x04:0x08]),
ProfileID: binary.LittleEndian.Uint32(buffer[0x08:0x0C]),
PublicIP: binary.BigEndian.Uint32(buffer[0x0C:0x10]),
PublicPort: uint16(publicPort),
LocalIP: binary.BigEndian.Uint32(buffer[0x14:0x18]),
LocalPort: uint16(localPort),
Unknown: binary.LittleEndian.Uint32(buffer[0x1C:0x20]),
LocalPlayerCount: binary.LittleEndian.Uint32(buffer[0x20:0x24]),
GroupID: binary.LittleEndian.Uint32(buffer[0x24:0x28]),
ReceiverNewAID: binary.LittleEndian.Uint32(buffer[0x28:0x2C]),
ClientCount: binary.LittleEndian.Uint32(buffer[0x2C:0x30]),
ResvCheckValue: binary.LittleEndian.Uint32(buffer[0x30:0x34]),
UserData: buffer[0x34:],
},
}, true
case MatchResvDeny:
if len(buffer) != 0x04 {
@ -371,11 +401,15 @@ func DecodeMatchCommand(command byte, buffer []byte, version int) (MatchCommandD
break
}
return MatchCommandData{ResvDeny: &MatchCommandDataResvDeny{
Reason: reason,
ReasonString: reasonString,
UserData: buffer[0x4:],
}}, true
return MatchCommandData{
Version: version,
Command: command,
ResvDeny: &MatchCommandDataResvDeny{
Reason: reason,
ReasonString: reasonString,
UserData: buffer[0x4:],
},
}, true
case MatchResvWait:
if len(buffer) != 0x00 {
@ -399,10 +433,14 @@ func DecodeMatchCommand(command byte, buffer []byte, version int) (MatchCommandD
break
}
return MatchCommandData{TellAddr: &MatchCommandDataTellAddr{
LocalIP: binary.BigEndian.Uint32(buffer[0x00:0x04]),
LocalPort: uint16(localPort),
}}, true
return MatchCommandData{
Version: version,
Command: command,
TellAddr: &MatchCommandDataTellAddr{
LocalIP: binary.BigEndian.Uint32(buffer[0x00:0x04]),
LocalPort: uint16(localPort),
},
}, true
case MatchServerCloseClient:
// Max match command buffer size for QR2/GT2
@ -421,32 +459,46 @@ func DecodeMatchCommand(command byte, buffer []byte, version int) (MatchCommandD
pids = append(pids, binary.LittleEndian.Uint32(buffer[i*4:i*4+4]))
}
return MatchCommandData{ServerCloseClient: &MatchCommandDataServerCloseClient{
ProfileIDs: pids,
}}, true
return MatchCommandData{
Version: version,
Command: command,
ServerCloseClient: &MatchCommandDataServerCloseClient{
ProfileIDs: pids,
},
}, true
case MatchSuspendMatch:
if len(buffer) == 0x08 {
return MatchCommandData{SuspendMatch: &MatchCommandDataSuspendMatch{
HostProfileID: binary.LittleEndian.Uint32(buffer[0x00:0x04]),
IsHostFlag: binary.LittleEndian.Uint32(buffer[0x04:0x08]),
Short: true,
}}, true
return MatchCommandData{
Version: version,
Command: command,
SuspendMatch: &MatchCommandDataSuspendMatch{
HostProfileID: binary.LittleEndian.Uint32(buffer[0x00:0x04]),
IsHostFlag: binary.LittleEndian.Uint32(buffer[0x04:0x08]),
Short: true,
},
}, true
} else if len(buffer) == 0x10 {
return MatchCommandData{SuspendMatch: &MatchCommandDataSuspendMatch{
HostProfileID: binary.LittleEndian.Uint32(buffer[0x00:0x04]),
IsHostFlag: binary.LittleEndian.Uint32(buffer[0x04:0x08]),
Short: false,
SuspendValue: binary.LittleEndian.Uint32(buffer[0x08:0x0C]),
ClientAIDValue: binary.LittleEndian.Uint32(buffer[0x0C:0x10]),
}}, true
return MatchCommandData{
Version: version,
Command: command,
SuspendMatch: &MatchCommandDataSuspendMatch{
HostProfileID: binary.LittleEndian.Uint32(buffer[0x00:0x04]),
IsHostFlag: binary.LittleEndian.Uint32(buffer[0x04:0x08]),
Short: false,
SuspendValue: binary.LittleEndian.Uint32(buffer[0x08:0x0C]),
ClientAIDValue: binary.LittleEndian.Uint32(buffer[0x0C:0x10]),
},
}, true
}
}
return MatchCommandData{}, false
}
func EncodeMatchCommand(command byte, data MatchCommandData, version int) ([]byte, bool) {
func EncodeMatchCommand(command byte, data MatchCommandData) ([]byte, bool) {
version := data.Version
if version != 3 && version != 11 && version != 90 {
return []byte{}, false
}

View File

@ -417,12 +417,18 @@ func (g *GameSpySession) bestieMessage(command common.GameSpyCommand) {
msgMatchData.Reservation.LocalIP = 0
msgMatchData.Reservation.LocalPort = 0
} else if cmd == common.MatchResvOK || cmd == common.MatchResvDeny || cmd == common.MatchResvWait {
if toSession.ReservationPID != g.User.ProfileId {
if toSession.ReservationPID != g.User.ProfileId || g.Reservation.Reservation == nil {
logging.Error(g.ModuleName, "Destination", aurora.Cyan(toProfileId), "has no reservation with the sender")
g.replyError(ErrMessage)
return
}
if g.Reservation.Version != msgMatchData.Version {
logging.Error(g.ModuleName, "Reservation version mismatch")
g.replyError(ErrMessage)
return
}
if cmd == common.MatchResvOK {
if g.QR2IP == 0 || toSession.QR2IP == 0 {
logging.Error(g.ModuleName, "Missing QR2 IP")
@ -430,7 +436,7 @@ func (g *GameSpySession) bestieMessage(command common.GameSpyCommand) {
return
}
if !qr2.ProcessGPResvOK(*msgMatchData.ResvOK, g.QR2IP, g.User.ProfileId, toSession.QR2IP, uint32(toProfileId)) {
if !qr2.ProcessGPResvOK(msgMatchData.Version, *g.Reservation.Reservation, *msgMatchData.ResvOK, g.QR2IP, g.User.ProfileId, toSession.QR2IP, uint32(toProfileId)) {
g.replyError(ErrMessage)
return
}
@ -449,7 +455,7 @@ func (g *GameSpySession) bestieMessage(command common.GameSpyCommand) {
}
}
newMsg, ok := common.EncodeMatchCommand(cmd, msgMatchData, version)
newMsg, ok := common.EncodeMatchCommand(cmd, msgMatchData)
if !ok || len(newMsg) > 0x200 {
logging.Error(g.ModuleName, "Failed to encode match command; message:", msg)
g.replyError(ErrMessage)
@ -457,6 +463,7 @@ func (g *GameSpySession) bestieMessage(command common.GameSpyCommand) {
}
if cmd == common.MatchReservation {
g.Reservation = msgMatchData
g.ReservationPID = uint32(toProfileId)
}

View File

@ -35,6 +35,7 @@ type GameSpySession struct {
AuthFriendList []uint32
QR2IP uint64
Reservation common.MatchCommandData
ReservationPID uint32
NeedsExploit bool

View File

@ -11,18 +11,19 @@ import (
)
type Group struct {
GroupID uint32
GroupName string
GameName string
MatchType string
MKWRegion string
Server *Session
Players map[*Session]bool
GroupID uint32
GroupName string
GameName string
MatchType string
MKWRegion string
LastJoinIndex int
Server *Session
Players map[*Session]bool
}
var groups = map[string]*Group{}
func processResvOK(moduleName string, cmd common.MatchCommandDataResvOK, sender, destination *Session) bool {
func processResvOK(moduleName string, matchVersion int, reservation common.MatchCommandDataReservation, resvOK common.MatchCommandDataResvOK, sender, destination *Session) bool {
if len(groups) >= 100000 {
logging.Error(moduleName, "Hit arbitrary global maximum group count (somehow)")
return false
@ -31,13 +32,14 @@ func processResvOK(moduleName string, cmd common.MatchCommandDataResvOK, sender,
group := sender.GroupPointer
if group == nil {
group = &Group{
GroupID: cmd.GroupID,
GroupName: "",
GameName: sender.Data["gamename"],
MatchType: sender.Data["dwc_mtype"],
MKWRegion: "",
Server: sender,
Players: map[*Session]bool{sender: true},
GroupID: resvOK.GroupID,
GroupName: "",
GameName: sender.Data["gamename"],
MatchType: sender.Data["dwc_mtype"],
MKWRegion: "",
LastJoinIndex: 0,
Server: sender,
Players: map[*Session]bool{sender: true},
}
for {
@ -62,6 +64,11 @@ func processResvOK(moduleName string, cmd common.MatchCommandDataResvOK, sender,
group.MKWRegion = rk
}
sender.Data["+joinindex"] = "0"
if matchVersion == 90 {
sender.Data["+localplayers"] = strconv.FormatUint(uint64(resvOK.LocalPlayerCount), 10)
}
sender.GroupPointer = group
groups[group.GroupName] = group
@ -71,16 +78,23 @@ func processResvOK(moduleName string, cmd common.MatchCommandDataResvOK, sender,
// TODO: Check if the sender is the actual server (host) once host migration works
// Keep group ID updated
sender.GroupPointer.GroupID = cmd.GroupID
group.GroupID = resvOK.GroupID
logging.Info(moduleName, "New player", aurora.BrightCyan(destination.Data["dwc_pid"]), "in group", aurora.Cyan(group.GroupName))
group.LastJoinIndex++
destination.Data["+joinindex"] = strconv.Itoa(group.LastJoinIndex)
if matchVersion == 90 {
destination.Data["+localplayers"] = strconv.FormatUint(uint64(reservation.LocalPlayerCount), 10)
}
group.Players[destination] = true
destination.GroupPointer = group
return true
}
func ProcessGPResvOK(cmd common.MatchCommandDataResvOK, senderIP uint64, senderPid uint32, destIP uint64, destPid uint32) bool {
func ProcessGPResvOK(matchVersion int, reservation common.MatchCommandDataReservation, resvOK common.MatchCommandDataResvOK, senderIP uint64, senderPid uint32, destIP uint64, destPid uint32) bool {
senderPidStr := strconv.FormatUint(uint64(senderPid), 10)
destPidStr := strconv.FormatUint(uint64(destPid), 10)
@ -110,7 +124,7 @@ func ProcessGPResvOK(cmd common.MatchCommandDataResvOK, senderIP uint64, senderP
return false
}
return processResvOK(moduleName, cmd, from, to)
return processResvOK(moduleName, matchVersion, reservation, resvOK, from, to)
}
func ProcessGPStatusUpdate(profileID uint32, senderIP uint64, status string) {
@ -176,13 +190,13 @@ func ProcessGPStatusUpdate(profileID uint32, senderIP uint64, status string) {
}
type GroupInfo struct {
GroupName string `json:"id"`
GameName string `json:"gamename"`
MatchType string `json:"type"`
Suspend bool `json:"suspend"`
ServerPID string `json:"host,omitempty"`
MKWRegion string `json:"rk,omitempty"`
Players []map[string]string `json:"players"`
GroupName string `json:"id"`
GameName string `json:"game"`
MatchType string `json:"type"`
Suspend bool `json:"suspend"`
ServerIndex string `json:"host,omitempty"`
MKWRegion string `json:"rk,omitempty"`
Players map[string]map[string]string `json:"players"`
}
// GetGroups returns an unsorted copy of all online rooms
@ -196,12 +210,12 @@ func GetGroups(gameName string) []GroupInfo {
}
groupInfo := GroupInfo{
GroupName: group.GroupName,
GameName: group.GameName,
Suspend: true,
ServerPID: "",
MKWRegion: "",
Players: []map[string]string{},
GroupName: group.GroupName,
GameName: group.GameName,
Suspend: true,
ServerIndex: "",
MKWRegion: "",
Players: map[string]map[string]string{},
}
if group.MatchType == "0" || group.MatchType == "1" {
@ -213,7 +227,7 @@ func GetGroups(gameName string) []GroupInfo {
}
if groupInfo.MatchType == "private" && group.Server != nil {
groupInfo.ServerPID = group.Server.Data["dwc_pid"]
groupInfo.ServerIndex = group.Server.Data["+joinindex"]
}
if groupInfo.GameName == "mariokartwii" {
@ -228,7 +242,7 @@ func GetGroups(gameName string) []GroupInfo {
mapData["+ingamesn"] = session.Login.InGameName
groupInfo.Players = append(groupInfo.Players, mapData)
groupInfo.Players[mapData["+joinindex"]] = mapData
if mapData["dwc_hoststate"] == "2" && mapData["dwc_suspend"] == "0" {
groupInfo.Suspend = false

View File

@ -112,6 +112,14 @@ func SendClientMessage(senderIP string, destSearchID uint64, message []byte) {
return
}
mutex.Lock()
if sender.Data["gamename"] != receiver.Data["gamename"] {
mutex.Unlock()
logging.Error(moduleName, "Sender and receiver are not playing the same game")
return
}
mutex.Unlock()
var ok bool
matchData, ok = common.DecodeMatchCommand(message[8], message[0x14:], version)
if !ok {
@ -209,7 +217,7 @@ func SendClientMessage(senderIP string, destSearchID uint64, message []byte) {
}
var matchMessage []byte
matchMessage, ok = common.EncodeMatchCommand(message[8], matchData, version)
matchMessage, ok = common.EncodeMatchCommand(message[8], matchData)
if !ok || len(matchMessage) > 0x80 {
logging.Error(moduleName, "Failed to reencode match command:", aurora.Cyan(printHex(message)))
return
@ -223,6 +231,7 @@ func SendClientMessage(senderIP string, destSearchID uint64, message []byte) {
}
mutex.Lock()
defer mutex.Unlock()
destPid, ok := receiver.Data["dwc_pid"]
if !ok || destPid == "" {
@ -234,8 +243,6 @@ func SendClientMessage(senderIP string, destSearchID uint64, message []byte) {
receiver.PacketCount = packetCount
destAddr := receiver.Addr
mutex.Unlock()
if isNatnegPacket {
cookie := binary.BigEndian.Uint32(message[0x2:0x6])
logging.Notice(moduleName, "Send NN cookie", aurora.Cyan(cookie), "to", aurora.BrightCyan(destPid))
@ -244,20 +251,25 @@ func SendClientMessage(senderIP string, destSearchID uint64, message []byte) {
common.LogMatchCommand(moduleName, destPid, cmd, matchData)
if cmd == common.MatchReservation {
sender.Reservation = matchData
sender.ReservationID = receiver.SearchID
} else if cmd == common.MatchResvOK || cmd == common.MatchResvDeny || cmd == common.MatchResvWait {
if receiver.ReservationID != sender.SearchID {
if receiver.ReservationID != sender.SearchID || receiver.Reservation.Reservation == nil {
logging.Error(moduleName, "Destination has no reservation with the sender")
return
}
if receiver.Reservation.Version != matchData.Version {
logging.Error(moduleName, "Reservation version mismatch")
return
}
if cmd == common.MatchResvOK {
mutex.Lock()
if !processResvOK(moduleName, *matchData.ResvOK, sender, receiver) {
mutex.Unlock()
if !processResvOK(moduleName, matchData.Version, *receiver.Reservation.Reservation, *matchData.ResvOK, sender, receiver) {
return
}
mutex.Unlock()
} else {
receiver.ReservationID = 0
}
}
}

View File

@ -32,6 +32,7 @@ type Session struct {
Data map[string]string
PacketCount uint32
ReservationID uint64
Reservation common.MatchCommandData
GroupPointer *Group
}
@ -101,6 +102,7 @@ func setSessionData(moduleName string, addr net.Addr, sessionId uint32, payload
Endianness: ClientNoEndian,
Data: payload,
PacketCount: 0,
Reservation: common.MatchCommandData{},
ReservationID: 0,
}
}