mirror of
https://github.com/WiiLink24/wfc-server.git
synced 2026-03-21 17:44:58 -05:00
API: Add join order and local player count
This commit is contained in:
parent
61d3176e11
commit
4e8ad85020
|
|
@ -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"]
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ type GameSpySession struct {
|
|||
AuthFriendList []uint32
|
||||
|
||||
QR2IP uint64
|
||||
Reservation common.MatchCommandData
|
||||
ReservationPID uint32
|
||||
|
||||
NeedsExploit bool
|
||||
|
|
|
|||
80
qr2/group.go
80
qr2/group.go
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user