Skip to content

Commit

Permalink
Merge pull request #21 from shutterbug2000/matchmaking-util-change
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniElectra authored Oct 19, 2023
2 parents 8358d71 + 942f04d commit 2e542d8
Show file tree
Hide file tree
Showing 14 changed files with 377 additions and 366 deletions.
1 change: 1 addition & 0 deletions globals/matchmaking_globals.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ type CommonMatchmakeSession struct {

var Sessions map[uint32]*CommonMatchmakeSession
var CurrentGatheringID = nex.NewCounter(0)
var CurrentMatchmakingCallID = nex.NewCounter(0)
257 changes: 246 additions & 11 deletions globals/matchmaking_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"math"
"strconv"
"strings"
"crypto/rand"

nex "github.com/PretendoNetwork/nex-go"
match_making "github.com/PretendoNetwork/nex-protocols-go/match-making"
Expand Down Expand Up @@ -90,7 +91,7 @@ func RemoveClientFromAllSessions(client *nex.Client) {

rmcMessage := nex.NewRMCRequest()
rmcMessage.SetProtocolID(notifications.ProtocolID)
rmcMessage.SetCallID(0xffff0000)
rmcMessage.SetCallID(CurrentMatchmakingCallID.Increment())
rmcMessage.SetMethodID(notifications.MethodProcessNotificationEvent)

category := notifications.NotificationCategories.Participation
Expand All @@ -103,8 +104,8 @@ func RemoveClientFromAllSessions(client *nex.Client) {
oEvent.Param2 = client.PID()

stream := nex.NewStreamOut(server)
oEventBytes := oEvent.Bytes(stream)
rmcMessage.SetParameters(oEventBytes)
stream.WriteStructure(oEvent)
rmcMessage.SetParameters(stream.Bytes())

rmcMessageBytes := rmcMessage.Bytes()

Expand Down Expand Up @@ -140,6 +141,33 @@ func RemoveClientFromAllSessions(client *nex.Client) {
}
}

// CreateSessionByMatchmakeSession creates a gathering from a MatchmakeSession
func CreateSessionByMatchmakeSession(matchmakeSession *match_making_types.MatchmakeSession, searchMatchmakeSession *match_making_types.MatchmakeSession, hostPID uint32) (*CommonMatchmakeSession, error, uint32) {
sessionIndex := GetAvailableGatheringID()
if sessionIndex == 0 {
CurrentGatheringID = nex.NewCounter(0)
sessionIndex = GetAvailableGatheringID()
}

session := CommonMatchmakeSession{
SearchMatchmakeSession: searchMatchmakeSession,
GameMatchmakeSession: matchmakeSession,
}

session.GameMatchmakeSession.Gathering.ID = sessionIndex
session.GameMatchmakeSession.Gathering.OwnerPID = hostPID
session.GameMatchmakeSession.Gathering.HostPID = hostPID

session.GameMatchmakeSession.StartedTime = nex.NewDateTime(0)
session.GameMatchmakeSession.StartedTime.UTC()
session.GameMatchmakeSession.SessionKey = make([]byte, 32)
rand.Read(session.GameMatchmakeSession.SessionKey)

Sessions[sessionIndex] = &session

return Sessions[sessionIndex], nil, 0
}

// FindSessionByMatchmakeSession finds a gathering that matches with a MatchmakeSession
func FindSessionByMatchmakeSession(searchMatchmakeSession *match_making_types.MatchmakeSession) uint32 {
// * This portion finds any sessions that match the search session
Expand Down Expand Up @@ -168,6 +196,33 @@ func FindSessionByMatchmakeSession(searchMatchmakeSession *match_making_types.Ma
return 0
}

// CreateSessionBySearchCriteria creates a gathering from MatchmakeSessionSearchCriteria
func CreateSessionBySearchCriteria(matchmakeSession *match_making_types.MatchmakeSession, lstSearchCriteria []*match_making_types.MatchmakeSessionSearchCriteria, hostPID uint32) (*CommonMatchmakeSession, error, uint32) {
sessionIndex := GetAvailableGatheringID()
if sessionIndex == 0 {
CurrentGatheringID = nex.NewCounter(0)
sessionIndex = GetAvailableGatheringID()
}

session := CommonMatchmakeSession{
SearchCriteria: lstSearchCriteria,
GameMatchmakeSession: matchmakeSession,
}

session.GameMatchmakeSession.Gathering.ID = sessionIndex
session.GameMatchmakeSession.Gathering.OwnerPID = hostPID
session.GameMatchmakeSession.Gathering.HostPID = hostPID

session.GameMatchmakeSession.StartedTime = nex.NewDateTime(0)
session.GameMatchmakeSession.StartedTime.UTC()
session.GameMatchmakeSession.SessionKey = make([]byte, 32)
rand.Read(session.GameMatchmakeSession.SessionKey)

Sessions[sessionIndex] = &session

return Sessions[sessionIndex], nil, 0
}

// FindSessionsByMatchmakeSessionSearchCriterias finds a gathering that matches with a MatchmakeSession
func FindSessionsByMatchmakeSessionSearchCriterias(lstSearchCriteria []*match_making_types.MatchmakeSessionSearchCriteria, gameSpecificChecks func(requestSearchCriteria, sessionSearchCriteria *match_making_types.MatchmakeSessionSearchCriteria) bool) []*CommonMatchmakeSession {
// * This portion finds any sessions that match the search session
Expand Down Expand Up @@ -200,7 +255,7 @@ func FindSessionsByMatchmakeSessionSearchCriterias(lstSearchCriteria []*match_ma
continue
}

if session.SearchMatchmakeSession.MinimumParticipants < uint16(min) {
if session.GameMatchmakeSession.MinimumParticipants < uint16(min) {
continue
}
}
Expand All @@ -212,7 +267,7 @@ func FindSessionsByMatchmakeSessionSearchCriterias(lstSearchCriteria []*match_ma
continue
}

if session.SearchMatchmakeSession.MinimumParticipants > uint16(max) {
if session.GameMatchmakeSession.MinimumParticipants > uint16(max) {
continue
}
}
Expand All @@ -234,7 +289,7 @@ func FindSessionsByMatchmakeSessionSearchCriterias(lstSearchCriteria []*match_ma
continue
}

if session.SearchMatchmakeSession.MaximumParticipants < uint16(min) {
if session.GameMatchmakeSession.MaximumParticipants < uint16(min) {
continue
}
}
Expand All @@ -246,7 +301,7 @@ func FindSessionsByMatchmakeSessionSearchCriterias(lstSearchCriteria []*match_ma
continue
}

if session.SearchMatchmakeSession.MaximumParticipants > uint16(max) {
if session.GameMatchmakeSession.MaximumParticipants > uint16(max) {
continue
}
}
Expand Down Expand Up @@ -277,7 +332,7 @@ func FindSessionsByMatchmakeSessionSearchCriterias(lstSearchCriteria []*match_ma

// AddPlayersToSession updates the given sessions state to include the provided connection IDs
// Returns a NEX error code if failed
func AddPlayersToSession(session *CommonMatchmakeSession, connectionIDs []uint32) (error, uint32) {
func AddPlayersToSession(session *CommonMatchmakeSession, connectionIDs []uint32, initiatingClient *nex.Client, joinMessage string) (error, uint32) {
if (len(session.ConnectionIDs) + len(connectionIDs)) > int(session.GameMatchmakeSession.Gathering.MaximumParticipants) {
return fmt.Errorf("Gathering %d is full", session.GameMatchmakeSession.Gathering.ID), nex.Errors.RendezVous.SessionFull
}
Expand All @@ -292,6 +347,186 @@ func AddPlayersToSession(session *CommonMatchmakeSession, connectionIDs []uint32
session.GameMatchmakeSession.ParticipationCount += 1
}

server := initiatingClient.Server()


for i := 0; i < len(session.ConnectionIDs); i++ {
target := server.FindClientFromConnectionID(session.ConnectionIDs[i])
if target == nil {
// TODO - Error here?
//logger.Warning("Player not found")
continue
}

notificationRequestMessage := nex.NewRMCRequest()
notificationRequestMessage.SetProtocolID(notifications.ProtocolID)
notificationRequestMessage.SetCallID(CurrentMatchmakingCallID.Increment())
notificationRequestMessage.SetMethodID(notifications.MethodProcessNotificationEvent)

notificationCategory := notifications.NotificationCategories.Participation
notificationSubtype := notifications.NotificationSubTypes.Participation.NewParticipant

oEvent := notifications_types.NewNotificationEvent()
oEvent.PIDSource = initiatingClient.PID()
oEvent.Type = notifications.BuildNotificationType(notificationCategory, notificationSubtype)
oEvent.Param1 = session.GameMatchmakeSession.ID
oEvent.Param2 = target.PID()
oEvent.StrParam = joinMessage
oEvent.Param3 = uint32(len(connectionIDs))

notificationStream := nex.NewStreamOut(server)

notificationStream.WriteStructure(oEvent)

notificationRequestMessage.SetParameters(notificationStream.Bytes())
notificationRequestBytes := notificationRequestMessage.Bytes()

var messagePacket nex.PacketInterface

if server.PRUDPVersion() == 0 {
messagePacket, _ = nex.NewPacketV0(target, nil)
messagePacket.SetVersion(0)
} else {
messagePacket, _ = nex.NewPacketV1(target, nil)
messagePacket.SetVersion(1)
}

messagePacket.SetSource(0xA1)
messagePacket.SetDestination(0xAF)
messagePacket.SetType(nex.DataPacket)
messagePacket.SetPayload(notificationRequestBytes)

messagePacket.AddFlag(nex.FlagNeedsAck)
messagePacket.AddFlag(nex.FlagReliable)

server.Send(messagePacket)
}

// This appears to be correct. Tri-Force Heroes uses 3.9.0, and has issues if these notifications are sent
// Minecraft, however, requires these to be sent
// TODO: Check other games both pre and post 3.10.0 and validate
if server.MatchMakingProtocolVersion().GreaterOrEqual("3.10.0") {
for i := 0; i < len(session.ConnectionIDs); i++ {
target := server.FindClientFromConnectionID(session.ConnectionIDs[i])
if target == nil {
// TODO - Error here?
//logger.Warning("Player not found")
continue
}

notificationRequestMessage := nex.NewRMCRequest()
notificationRequestMessage.SetProtocolID(notifications.ProtocolID)
notificationRequestMessage.SetCallID(CurrentMatchmakingCallID.Increment())
notificationRequestMessage.SetMethodID(notifications.MethodProcessNotificationEvent)

notificationCategory := notifications.NotificationCategories.Participation
notificationSubtype := notifications.NotificationSubTypes.Participation.NewParticipant

oEvent := notifications_types.NewNotificationEvent()
oEvent.PIDSource = initiatingClient.PID()
oEvent.Type = notifications.BuildNotificationType(notificationCategory, notificationSubtype)
oEvent.Param1 = session.GameMatchmakeSession.ID
oEvent.Param2 = target.PID()
oEvent.StrParam = joinMessage
oEvent.Param3 = uint32(len(connectionIDs))

notificationStream := nex.NewStreamOut(server)

notificationStream.WriteStructure(oEvent)

notificationRequestMessage.SetParameters(notificationStream.Bytes())
notificationRequestBytes := notificationRequestMessage.Bytes()

var messagePacket nex.PacketInterface

if server.PRUDPVersion() == 0 {
messagePacket, _ = nex.NewPacketV0(initiatingClient, nil)
messagePacket.SetVersion(0)
} else {
messagePacket, _ = nex.NewPacketV1(initiatingClient, nil)
messagePacket.SetVersion(1)
}

messagePacket.SetSource(0xA1)
messagePacket.SetDestination(0xAF)
messagePacket.SetType(nex.DataPacket)
messagePacket.SetPayload(notificationRequestBytes)

messagePacket.AddFlag(nex.FlagNeedsAck)
messagePacket.AddFlag(nex.FlagReliable)

server.Send(messagePacket)
}

notificationRequestMessage := nex.NewRMCRequest()
notificationRequestMessage.SetProtocolID(notifications.ProtocolID)
notificationRequestMessage.SetCallID(CurrentMatchmakingCallID.Increment())
notificationRequestMessage.SetMethodID(notifications.MethodProcessNotificationEvent)

notificationCategory := notifications.NotificationCategories.Participation
notificationSubtype := notifications.NotificationSubTypes.Participation.NewParticipant

oEvent := notifications_types.NewNotificationEvent()
oEvent.PIDSource = initiatingClient.PID()
oEvent.Type = notifications.BuildNotificationType(notificationCategory, notificationSubtype)
oEvent.Param1 = session.GameMatchmakeSession.ID
oEvent.Param2 = initiatingClient.PID()
oEvent.StrParam = joinMessage
oEvent.Param3 = uint32(len(connectionIDs))

notificationStream := nex.NewStreamOut(server)

notificationStream.WriteStructure(oEvent)

notificationRequestMessage.SetParameters(notificationStream.Bytes())
notificationRequestBytes := notificationRequestMessage.Bytes()

var messagePacket nex.PacketInterface

if server.PRUDPVersion() == 0 {
messagePacket, _ = nex.NewPacketV0(initiatingClient, nil)
messagePacket.SetVersion(0)
} else {
messagePacket, _ = nex.NewPacketV1(initiatingClient, nil)
messagePacket.SetVersion(1)
}

messagePacket.SetSource(0xA1)
messagePacket.SetDestination(0xAF)
messagePacket.SetType(nex.DataPacket)
messagePacket.SetPayload(notificationRequestBytes)

messagePacket.AddFlag(nex.FlagNeedsAck)
messagePacket.AddFlag(nex.FlagReliable)

server.Send(messagePacket)

target := server.FindClientFromPID(uint32(session.GameMatchmakeSession.Gathering.OwnerPID))
if target == nil {
// TODO - Error here?
//logger.Warning("Player not found")
return nil, 0
}

if server.PRUDPVersion() == 0 {
messagePacket, _ = nex.NewPacketV0(target, nil)
messagePacket.SetVersion(0)
} else {
messagePacket, _ = nex.NewPacketV1(target, nil)
messagePacket.SetVersion(1)
}

messagePacket.SetSource(0xA1)
messagePacket.SetDestination(0xAF)
messagePacket.SetType(nex.DataPacket)
messagePacket.SetPayload(notificationRequestBytes)

messagePacket.AddFlag(nex.FlagNeedsAck)
messagePacket.AddFlag(nex.FlagReliable)

server.Send(messagePacket)
}

return nil, 0
}

Expand All @@ -316,7 +551,7 @@ func ChangeSessionOwner(ownerClient *nex.Client, gathering uint32) {

rmcMessage := nex.NewRMCRequest()
rmcMessage.SetProtocolID(notifications.ProtocolID)
rmcMessage.SetCallID(0xffff0000)
rmcMessage.SetCallID(CurrentMatchmakingCallID.Increment())
rmcMessage.SetMethodID(notifications.MethodProcessNotificationEvent)

category := notifications.NotificationCategories.OwnershipChanged
Expand All @@ -334,8 +569,8 @@ func ChangeSessionOwner(ownerClient *nex.Client, gathering uint32) {
// oEvent.StrParam = strconv.FormatInt(unixTime.UnixMicro(), 10)

stream := nex.NewStreamOut(server)
oEventBytes := oEvent.Bytes(stream)
rmcMessage.SetParameters(oEventBytes)
stream.WriteStructure(oEvent)
rmcMessage.SetParameters(stream.Bytes())

rmcRequestBytes := rmcMessage.Bytes()

Expand Down
Loading

0 comments on commit 2e542d8

Please sign in to comment.