1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
5 #include "CrySharedLobbyPacket.h"
9 #include "CryPSN2Lobby.h"
10 #include "CryPSN2Response.h"
11 #include "CryPSN2MatchMaking.h"
14 #if USE_CRY_MATCHMAKING
16 #include <CryCore/CryEndian.h>
17 #include <CryGame/IGameFramework.h>
19 #include <libsysmodule.h>
20 #include "CryPSN2WebApi.h"
21 #include "CryPSN2WebApi_Session.h"
23 #define SIGNALING_TIMEOUT (15 * 1000) // 15 seconds using our own timeout code
24 #define PSN_MATCHMAKING_DEFAULT_UNKNOWN_PING (3000)
26 #define MAX_ROOMS_PER_WORLD (5000) //-- Max 5000 rooms available for one world
28 #define PSN_MATCHMAKING_PSNSUPPORT_LEAVE_REQUEST_SLOT (0)
29 #define PSN_MATCHMAKING_WEBAPI_LEAVE_REQUEST_SLOT (1)
31 #define PSN_MATCHMAKING_SEARCH_PARAMS_SLOT (0)
32 #define PSN_MATCHMAKING_SEARCH_DATA_SLOT (1)
33 #define PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT (2)
34 #define PSN_MATCHMAKING_PSNSUPPORT_SEARCH_QOS_SLOT (3)
36 #define PSN_MATCHMAKING_PSNSUPPORT_JOIN_REQUEST_SLOT (0)
37 #define PSN_MATCHMAKING_PSNSUPPORT_JOIN_RESPONSE_SLOT (1)
38 #define PSN_MATCHMAKING_WEBAPI_JOIN_SLOT (2)
40 #define PSN_MATCHMAKING_CREATE_PARAMS_SLOT (0)
41 #define PSN_MATCHMAKING_CREATE_DATA_SLOT (1)
42 #define PSN_MATCHMAKING_PSNSUPPORT_CREATE_REQUEST_SLOT (2)
43 #define PSN_MATCHMAKING_WEBAPI_CREATE_SLOT (3)
45 #define PSN_MATCHMAKING_UPDATE_DATA_SLOT (0)
46 #define PSN_MATCHMAKING_PSNSUPPORT_UPDATE_REQUEST_SLOT (1)
48 #define PSN_MATCHMAKING_USERDATA_DATA_SLOT (0)
49 #define PSN_MATCHMAKING_PSNSUPPORT_USERDATA_REQUEST_SLOT (1)
51 #define PSN_MATCHMAKING_PSNSUPPORT_QUERY_REQUEST_SLOT (0)
52 #define PSN_MATCHMAKING_PSNSUPPORT_QUERY_RESPONSE_SLOT (1)
54 #define PSN_MATCHMAKING_PSNSUPPORT_HOSTHINT_REQUEST_SLOT (0)
55 #define PSN_MATCHMAKING_PSNSUPPORT_HOSTHINT_RESTART (1)
57 #define PSN_MATCHMAKING_PSNSUPPORT_GRANTROOM_REQUEST_SLOT (0)
59 #define PSN_MATCHMAKING_PSNSUPPORT_UPDATEADVERT_REQUEST_SLOT (0)
60 #define PSN_MATCHMAKING_WEBAPI_UPDATEADVERT_REQUEST_SLOT (1)
62 #define PSN_MATCHMAKING_PSNSUPPORT_GETADVERT_REQUEST_SLOT (0)
63 #define PSN_MATCHMAKING_WEBAPI_GETADVERT_REQUEST_SLOT (1)
64 #define PSN_MATCHMAKING_WEBAPI_GETADVERT_RESPONSE_SLOT (2)
66 CryMatchMakingConnectionID
CCryPSNMatchMaking::FindConnectionIDFromRoomMemberID(CryLobbySessionHandle sessionHandle
, SceNpMatching2RoomMemberId memberId
)
68 if ((sessionHandle
!= CryLobbyInvalidSessionHandle
) && (memberId
!= INVALID_PSN_ROOM_MEMBER_ID
))
70 SSession
* pSession
= &m_sessions
[sessionHandle
];
71 if (pSession
->IsUsed())
73 for (uint32 a
= 0; a
< MAX_LOBBY_CONNECTIONS
; a
++)
75 SSession::SRConnection
* pConnection
= &pSession
->remoteConnection
[a
];
76 if (pConnection
->used
&& pConnection
->registered
&& (pConnection
->memberId
== memberId
))
84 return CryMatchMakingInvalidConnectionID
;
87 CCryPSNMatchMaking::SSession::SRoomMember
* CCryPSNMatchMaking::FindRoomMemberFromRoomMemberID(CryLobbySessionHandle sessionHandle
, SceNpMatching2RoomMemberId memberId
)
89 if ((sessionHandle
!= CryLobbyInvalidSessionHandle
) && (memberId
!= INVALID_PSN_ROOM_MEMBER_ID
))
91 SSession
* pSession
= &m_sessions
[sessionHandle
];
92 if (pSession
->IsUsed())
94 for (uint32 a
= 0; a
< MAX_PSN_ROOM_MEMBERS
; a
++)
96 if (pSession
->m_members
[a
].IsUsed() && (pSession
->m_members
[a
].m_memberId
== memberId
))
98 return &pSession
->m_members
[a
];
107 uint64
CCryPSNMatchMaking::GetSIDFromSessionHandle(CryLobbySessionHandle h
)
109 CRY_ASSERT_MESSAGE((h
< MAX_MATCHMAKING_SESSIONS
) && m_sessions
[h
].IsUsed(), "CCryPSNMatchMaking::GetSIDFromSessionHandle: invalid session handle");
111 return m_sessions
[h
].m_roomId
;
114 CrySessionID
CCryPSNMatchMaking::SessionGetCrySessionIDFromCrySessionHandle(CrySessionHandle gh
)
116 CryLobbySessionHandle h
= GetSessionHandleFromGameSessionHandle(gh
);
118 if ((h
< MAX_MATCHMAKING_SESSIONS
) && m_sessions
[h
].IsUsed())
120 SCryPSNSessionID
* pID
= new SCryPSNSessionID
;
124 pID
->m_sessionInfo
.m_roomId
= m_sessions
[h
].m_roomId
;
125 pID
->m_sessionInfo
.m_worldId
= m_sessions
[h
].m_worldId
;
126 pID
->m_sessionInfo
.m_serverId
= m_sessions
[h
].m_serverId
;
127 pID
->m_sessionInfo
.m_gameType
= m_sessions
[h
].m_gameType
;
128 memcpy(&pID
->m_sessionId
, &m_sessions
[h
].m_sessionId
, sizeof(pID
->m_sessionId
));
129 pID
->m_fromInvite
= false;
131 memcpy(&pID
->m_sessionId
, &m_sessions
[h
].m_sessionId
, sizeof(SceNpSessionId
));
140 TNetAddress
CCryPSNMatchMaking::GetHostAddressFromSessionHandle(CrySessionHandle gh
)
144 CryLobbySessionHandle h
= GetSessionHandleFromGameSessionHandle(gh
);
145 SSession
* pSession
= &m_sessions
[h
];
147 if (pSession
->serverConnectionID
!= CryMatchMakingInvalidConnectionID
)
149 const TNetAddress
* pDedicatedServerAddr
= m_lobby
->GetNetAddress(pSession
->remoteConnection
[pSession
->serverConnectionID
].connectionID
);
151 if (pDedicatedServerAddr
)
153 return *pDedicatedServerAddr
;
157 SSession::SRoomMember
* pMember
= FindRoomMemberFromRoomMemberID(h
, pSession
->m_ownerMemberId
);
158 if (pSession
->m_ownerMemberId
== pSession
->m_myMemberId
)
160 return TNetAddress(TLocalNetAddress(m_lobby
->GetInternalSocketPort(eCLS_Online
)));
164 addr4
.addr
= ntohl(pMember
->m_peerAddr
.s_addr
);
165 addr4
.port
= ntohs(pMember
->m_peerPort
);
167 #if !ENABLE_PLATFORM_PROTOCOL
170 uint16 connectPort
, listenPort
;
171 m_pService
->GetSocketPorts(connectPort
, listenPort
);
172 addr4
.port
= ntohs(connectPort
);
176 return TNetAddress(addr4
);
179 void CCryPSNMatchMaking::SessionDisconnectRemoteConnection(CrySessionHandle gh
, const TNetAddress
& addr
)
181 // At present i don't need to worry about this
184 void CCryPSNMatchMaking::FreeRemoteConnection(CryLobbySessionHandle h
, CryMatchMakingConnectionID id
)
186 if (id
!= CryMatchMakingInvalidConnectionID
)
188 SSession
* pSession
= &m_sessions
[h
];
189 SSession::SRConnection
* pConnection
= &pSession
->remoteConnection
[id
];
191 if (pConnection
->used
)
193 SessionUserDataEvent(eCLSE_SessionUserLeave
, h
, id
);
195 CCryMatchMaking::FreeRemoteConnection(h
, id
);
197 pConnection
->registered
= false;
198 pConnection
->memberId
= INVALID_PSN_ROOM_MEMBER_ID
;
203 uint32
CCryPSNMatchMaking::GetSessionIDSizeInPacket() const
205 return sizeof(SSynchronisedSessionID
);
208 ECryLobbyError
CCryPSNMatchMaking::WriteSessionIDToPacket(CrySessionID sessionId
, CCryLobbyPacket
* pPacket
) const
212 SCryPSNSessionID blank
;
214 if (sessionId
!= CrySessionInvalidID
)
216 SCryPSNSessionID
* psnID
= (SCryPSNSessionID
*)sessionId
.get();
219 pPacket
->WriteData(&psnID
->m_sessionInfo
, sizeof(psnID
->m_sessionInfo
));
223 pPacket
->WriteData(&blank
.m_sessionInfo
, sizeof(blank
.m_sessionInfo
));
228 pPacket
->WriteData(&blank
.m_sessionInfo
, sizeof(blank
.m_sessionInfo
));
234 return eCLE_InternalError
;
237 CrySessionID
CCryPSNMatchMaking::ReadSessionIDFromPacket(CCryLobbyPacket
* pPacket
) const
241 CrySessionID returnId
= new SCryPSNSessionID
;
242 SCryPSNSessionID
* psnID
= (SCryPSNSessionID
*)returnId
.get();
245 SCryPSNSessionID blank
;
247 pPacket
->ReadData(&psnID
->m_sessionInfo
, sizeof(psnID
->m_sessionInfo
));
249 //-- Cannot use the SCryPSNSessionID equals operator because we write more than just the roomId to the packet
250 //-- to signify a null session ID.
251 if ((psnID
->m_sessionInfo
.m_roomId
!= blank
.m_sessionInfo
.m_roomId
) ||
252 (psnID
->m_sessionInfo
.m_worldId
!= blank
.m_sessionInfo
.m_worldId
) ||
253 (psnID
->m_sessionInfo
.m_serverId
!= blank
.m_sessionInfo
.m_serverId
) ||
254 (psnID
->m_sessionInfo
.m_gameType
!= blank
.m_sessionInfo
.m_gameType
))
256 //-- assume it's a valid session id if any field does not match the blank
262 return CrySessionInvalidID
;
265 void CCryPSNMatchMaking::DumpMemberInfo(SSession::SRoomMember
* pMember
)
267 #if !defined(_RELEASE) || defined(RELEASE_LOGGING)
268 NetLog("%s , uid %d , %d.%d.%d.%d:%d",
269 pMember
->m_npId
.handle
.data
,
271 (pMember
->m_peerAddr
.s_addr
>> 24) & 0xFF, (pMember
->m_peerAddr
.s_addr
>> 16) & 0xFF, (pMember
->m_peerAddr
.s_addr
>> 8) & 0xFF, (pMember
->m_peerAddr
.s_addr
) & 0xFF,
272 pMember
->m_peerPort
);
273 #endif // #if !defined(_RELEASE) || defined(RELEASE_LOGGING)
276 void CCryPSNMatchMaking::ClearRoomMember(CryLobbySessionHandle sessionHandle
, uint32 nMember
)
278 if (sessionHandle
!= CryLobbyInvalidSessionHandle
)
280 SSession
* pSession
= &m_sessions
[sessionHandle
];
281 SSession::SRoomMember
* pMember
= &pSession
->m_members
[nMember
];
283 if (pMember
->IsUsed())
285 if (pMember
->IsValid(ePSNMI_Other
))
287 // Remove the player (if we have connection information we will need to drop that here too)
288 CryMatchMakingConnectionID id
= FindConnectionIDFromRoomMemberID(sessionHandle
, pMember
->m_memberId
);
289 if (id
!= CryMatchMakingInvalidConnectionID
)
291 // This disconnect should be treated as if it came from the host.
292 SessionDisconnectRemoteConnectionViaNub(sessionHandle
, id
, eDS_FromID
, pSession
->hostConnectionID
, eDC_Unknown
, "Clear Room Member");
296 pMember
->m_signalingState
= ePSNCS_None
;
297 pMember
->m_memberId
= INVALID_PSN_ROOM_MEMBER_ID
;
298 pMember
->m_valid
= ePSNMI_None
;
299 pMember
->m_bHostJoinAck
= false;
300 memset(pMember
->m_userData
, 0, sizeof(pMember
->m_userData
));
305 void CCryPSNMatchMaking::AddRoomMember(CryLobbySessionHandle sessionHandle
, const SCryPSNRoomMemberDataInternal
& memberInfo
, ECryPSNMemberInfo info
)
307 if (sessionHandle
!= CryLobbyInvalidSessionHandle
)
309 SSession
* pSession
= &m_sessions
[sessionHandle
];
310 if (pSession
->IsUsed())
312 SSession::SRoomMember
* pMember
= NULL
;
314 for (uint32 a
= 0; a
< MAX_PSN_ROOM_MEMBERS
; a
++)
316 if (pSession
->m_members
[a
].IsUsed())
318 if (pSession
->m_members
[a
].m_memberId
== memberInfo
.m_memberId
)
321 CRY_ASSERT_MESSAGE(pSession
->m_members
[a
].m_memberId
!= memberInfo
.m_memberId
, "Adding a room member who already exists!");
329 pMember
= &pSession
->m_members
[a
];
336 pMember
->m_npId
= memberInfo
.m_npId
;
337 pMember
->m_memberId
= memberInfo
.m_memberId
;
338 pMember
->m_valid
= info
;
339 pMember
->m_signalingState
= ePSNCS_None
;
340 pMember
->m_bHostJoinAck
= false;
342 if (memberInfo
.m_numBinAttributes
> 0)
344 memcpy(pMember
->m_userData
, memberInfo
.m_binAttributes
[0].m_data
, CRYLOBBY_USER_DATA_SIZE_IN_BYTES
);
347 if (pMember
->IsValid(ePSNMI_Me
))
349 pSession
->m_myMemberId
= pMember
->m_memberId
;
351 pSession
->localConnection
.uid
.m_uid
= pMember
->m_memberId
;
352 pSession
->localConnection
.uid
.m_sid
= pSession
->m_roomId
;
355 if (pMember
->IsValid(ePSNMI_Owner
))
357 pSession
->m_ownerMemberId
= pMember
->m_memberId
;
360 if (pMember
->IsValid(ePSNMI_Other
))
362 // We don't have connection information yet (ip / port etc)
363 SCryMatchMakingConnectionUID matchingUID
;
365 matchingUID
.m_uid
= pMember
->m_memberId
;
366 matchingUID
.m_sid
= pSession
->m_roomId
;
368 CryMatchMakingConnectionID id
= CCryMatchMaking::AddRemoteConnection(sessionHandle
, CryLobbyInvalidConnectionID
, matchingUID
, 1);
369 if (id
!= CryMatchMakingInvalidConnectionID
)
371 SSession::SRConnection
* pConnection
= &pSession
->remoteConnection
[id
];
373 // pConnection->flags |= CMMRC_FLAG_PLATFORM_DATA_VALID;
374 pConnection
->registered
= true;
375 pConnection
->connectionID
= CryLobbyInvalidConnectionID
;
376 pConnection
->memberId
= pMember
->m_memberId
;
378 if ((pSession
->localFlags
& CRYSESSION_LOCAL_FLAG_HOST
) != CRYSESSION_LOCAL_FLAG_HOST
)
380 if (!pMember
->IsValid(ePSNMI_Owner
))
382 //-- If person being added is not the owner, and I am not the owner, send a user joined event to the game immediately -
383 //-- there is no need to wait for signaling to establish.
384 //-- This should allow peers behind strict firewalls to see each other joining
385 //-- but still ensure clients are only added to the server when the signaling establishes.
386 DumpMemberInfo(pMember
);
387 AddVoiceUser(pMember
);
388 SessionUserDataEvent(eCLSE_SessionUserJoin
, sessionHandle
, id
);
393 //-- Not me, and no peer state defined yet, so lets kick off a peer connection test for this member
394 pMember
->m_signalingState
= ePSNCS_Pending
;
395 pMember
->m_signalingTimer
= g_time
;
402 void CCryPSNMatchMaking::RemoveRoomMember(CryLobbySessionHandle sessionHandle
, const SCryPSNRoomMemberDataInternal
& memberInfo
)
404 if (sessionHandle
!= CryLobbyInvalidSessionHandle
)
406 SSession
* pSession
= &m_sessions
[sessionHandle
];
407 if (pSession
->IsUsed())
409 for (uint32 a
= 0; a
< MAX_PSN_ROOM_MEMBERS
; a
++)
411 SSession::SRoomMember
* pMember
= &pSession
->m_members
[a
];
413 if (pMember
->IsUsed() && (sceNpCmpNpId(&pMember
->m_npId
, &memberInfo
.m_npId
) == 0))
415 ClearRoomMember(sessionHandle
, a
);
423 void CCryPSNMatchMaking::UpdateRoomMember(CryLobbySessionHandle sessionHandle
, const SCryPSNRoomMemberDataInternal
& updatedMemberInfo
)
425 if (sessionHandle
!= CryLobbyInvalidSessionHandle
)
427 SSession
* pSession
= &m_sessions
[sessionHandle
];
428 if (pSession
->IsUsed())
430 for (uint32 a
= 0; a
< MAX_PSN_ROOM_MEMBERS
; a
++)
432 SSession::SRoomMember
* pMember
= &pSession
->m_members
[a
];
434 if (pMember
->m_valid
&& (pMember
->m_memberId
== updatedMemberInfo
.m_memberId
))
436 if (updatedMemberInfo
.m_numBinAttributes
> 0)
438 memcpy(pMember
->m_userData
, updatedMemberInfo
.m_binAttributes
[0].m_data
, CRYLOBBY_USER_DATA_SIZE_IN_BYTES
);
441 CryMatchMakingConnectionID id
= FindConnectionIDFromRoomMemberID(sessionHandle
, pMember
->m_memberId
);
442 SessionUserDataEvent(eCLSE_SessionUserUpdate
, sessionHandle
, id
);
451 void CCryPSNMatchMaking::ClearSessionInfo(CryLobbySessionHandle sessionHandle
)
453 assert(sessionHandle
!= CryLobbyInvalidSessionHandle
);
455 if (sessionHandle
!= CryLobbyInvalidSessionHandle
)
457 SSession
* pSession
= &m_sessions
[sessionHandle
];
459 if (pSession
->IsUsed() && (pSession
->m_roomId
!= INVALID_PSN_ROOM_ID
))
461 SceNpMatching2RequestId IDontCareReqId
;
462 SceNpMatching2LeaveRoomRequest IDontCareLeaveParam
;
464 memset(&IDontCareLeaveParam
, 0, sizeof(SceNpMatching2LeaveRoomRequest
));
465 IDontCareLeaveParam
.roomId
= pSession
->m_roomId
;
467 sceNpMatching2LeaveRoom(m_pPSNSupport
->GetMatchmakingContextId(), &IDontCareLeaveParam
, NULL
, &IDontCareReqId
);
468 if (pSession
->m_sessionId
.data
[0] != 0)
470 // TODO: the only trouble here is that leaveSessionParamsHdl needs to be allocated, but when do we free it? There's no task to complete!
471 // m_pPSNSupport->GetWebApiInterface().AddJob(CCryPSNOrbisWebApiThread::LeaveSession, leaveSessionParamsHdl);
475 for (uint32 a
= 0; a
< MAX_PSN_ROOM_MEMBERS
; a
++)
477 ClearRoomMember(sessionHandle
, a
);
482 void CCryPSNMatchMaking::AddInitialRoomMembers(CryLobbySessionHandle sessionHandle
, const SCryPSNRoomMemberDataInternalList
& memberList
)
484 if (sessionHandle
!= CryLobbyInvalidSessionHandle
)
486 SSession
* pSession
= &m_sessions
[sessionHandle
];
487 if (pSession
->IsUsed())
489 for (uint32 a
= 0; a
< memberList
.m_numRoomMembers
; a
++)
491 SCryPSNRoomMemberDataInternal
& memberInfo
= memberList
.m_pRoomMembers
[a
];
492 uint32 info
= ePSNMI_None
;
494 if (a
== memberList
.m_owner
)
496 info
|= ePSNMI_Owner
;
499 if (a
== memberList
.m_me
)
505 info
|= ePSNMI_Other
;
508 AddRoomMember(sessionHandle
, memberInfo
, (ECryPSNMemberInfo
)info
);
514 void CCryPSNMatchMaking::DispatchRoomOwnerChangedEvent(TMemHdl mh
)
516 UCryLobbyEventData eventData
;
517 eventData
.pRoomOwnerChanged
= (SCryLobbyRoomOwnerChanged
*)m_lobby
->MemGetPtr(mh
);
519 m_lobby
->DispatchEvent(eCLSE_RoomOwnerChanged
, eventData
);
521 m_lobby
->MemFree(mh
);
524 void CCryPSNMatchMaking::ChangeRoomOwner(CryLobbySessionHandle sessionHandle
, SceNpMatching2RoomMemberId prevOwner
, SceNpMatching2RoomMemberId newOwner
)
526 if (sessionHandle
!= CryLobbyInvalidSessionHandle
)
528 SSession
* pSession
= &m_sessions
[sessionHandle
];
529 if (pSession
->localFlags
& CRYSESSION_LOCAL_FLAG_USED
)
531 SSession::SRoomMember
* pMember
= NULL
;
533 pSession
->m_ownerMemberId
= newOwner
;
535 //-- remove the old room owner
536 for (uint32 a
= 0; a
< MAX_PSN_ROOM_MEMBERS
; a
++)
538 pMember
= &pSession
->m_members
[a
];
539 if (pMember
->m_valid
)
541 if (pMember
->m_memberId
== prevOwner
)
543 assert(pMember
->m_valid
& ePSNMI_Owner
);
545 if (pMember
->m_valid
& ePSNMI_Me
)
547 pMember
->m_valid
= ePSNMI_Me
;
551 pMember
->m_valid
= ePSNMI_Other
;
555 if (pMember
->m_memberId
== newOwner
)
557 if (pMember
->m_valid
& ePSNMI_Me
)
559 pMember
->m_valid
= ePSNMI_MeOwner
;
563 pMember
->m_valid
= ePSNMI_OtherOwner
;
569 #if NETWORK_HOST_MIGRATION
570 CryLobbySessionHandle h
;
572 SCryMatchMakingConnectionUID matchingUID
;
574 matchingUID
.m_uid
= newOwner
;
575 matchingUID
.m_sid
= pSession
->m_roomId
;
577 FindConnectionFromUID(matchingUID
, &h
, &pSession
->hostConnectionID
); // It is valid for the h to be invalid (basically if hostConnectionID comes back with 0 we don't have any remotes - thats allowed!)
579 // Ensure we're migrating the session (covers catastrophic migration, and migration within migration)
580 HostMigrationInitiate(sessionHandle
, eDC_Unknown
);
581 pSession
->hostMigrationInfo
.m_newHostAddressValid
= true;
582 pSession
->newHostUID
= matchingUID
;
584 SSession::SRoomMember
* pRoomMember
= FindRoomMemberFromRoomMemberID(sessionHandle
, newOwner
);
588 if (pRoomMember
->IsValid(ePSNMI_Other
) && (pRoomMember
->m_signalingState
== ePSNCS_Active
))
592 TMemHdl mh
= m_lobby
->MemAlloc(sizeof(SCryLobbyRoomOwnerChanged
));
593 if (mh
!= TMemInvalidHdl
)
595 SCryLobbyRoomOwnerChanged
* pOwnerData
= (SCryLobbyRoomOwnerChanged
*)m_lobby
->MemGetPtr(mh
);
597 pOwnerData
->m_session
= CreateGameSessionHandle(sessionHandle
, pSession
->localConnection
.uid
);
598 pOwnerData
->m_port
= pRoomMember
->m_peerPort
;
599 pOwnerData
->m_ip
= pRoomMember
->m_peerAddr
.s_addr
;
601 TO_GAME_FROM_LOBBY(&CCryPSNMatchMaking::DispatchRoomOwnerChangedEvent
, this, mh
);
611 void CCryPSNMatchMaking::UpdateSignaling(CryMatchMakingTaskID mmTaskID
)
613 STask
* pTask
= &m_task
[mmTaskID
];
615 if (pTask
->used
&& pTask
->running
&& (pTask
->session
!= CryLobbyInvalidSessionHandle
))
617 SSession
* pSession
= &m_sessions
[pTask
->session
];
618 if (pSession
->IsUsed())
620 for (uint32 a
= 0; a
< MAX_PSN_ROOM_MEMBERS
; a
++)
622 SSession::SRoomMember
* pMember
= &pSession
->m_members
[a
];
624 if (pMember
->IsUsed())
627 bool bTestTimeout
= false;
629 if (pMember
->m_signalingState
== ePSNCS_Pending
)
635 if ((pTask
->startedTask
== eT_SessionJoin
) && pMember
->IsValid(ePSNMI_Owner
) && (pMember
->m_signalingState
== ePSNCS_Active
) && (pMember
->m_bHostJoinAck
== false))
643 if ((g_time
.GetMilliSecondsAsInt64() - pMember
->m_signalingTimer
.GetMilliSecondsAsInt64()) > SIGNALING_TIMEOUT
)
645 pMember
->m_signalingState
= ePSNCS_Dead
;
647 CryMatchMakingConnectionID id
= FindConnectionIDFromRoomMemberID(pTask
->session
, pMember
->m_memberId
);
648 if (id
!= CryMatchMakingInvalidConnectionID
)
650 SSession::SRConnection
* pConnection
= &pSession
->remoteConnection
[id
];
651 NetLog("[Lobby] CCryPSNMatchMaking::UpdateSignaling() : Signaling dead event setting connection " PRFORMAT_LCID
" to eCLCS_NotConnected", PRARG_LCID(pConnection
->connectionID
));
652 m_lobby
->ConnectionSetState(pConnection
->connectionID
, eCLCS_NotConnected
);
662 CCryPSNMatchMaking::ECryPSNConnectionState
CCryPSNMatchMaking::CheckSignaling(CryMatchMakingTaskID mmTaskID
)
664 STask
* pTask
= &m_task
[mmTaskID
];
666 if (pTask
->used
&& pTask
->running
&& (pTask
->session
!= CryLobbyInvalidSessionHandle
))
668 SSession
* pSession
= &m_sessions
[pTask
->session
];
669 if (pSession
->IsUsed())
671 //-- If we can talk to the room owner, we'll allow the session state machine to run
672 for (uint32 a
= 0; a
< MAX_PSN_ROOM_MEMBERS
; a
++)
674 SSession::SRoomMember
* pMember
= &pSession
->m_members
[a
];
676 if (pMember
->IsValid(ePSNMI_Owner
))
678 //-- Are we the owner?
679 if (pMember
->IsValid(ePSNMI_Me
))
681 //-- technically, 'me' always has a signaling state of ePSNMI_None, so we'll fake it just for this return.
682 return ePSNCS_Active
;
685 //-- Is peer connection to remote owner active?
686 if (pMember
->m_signalingState
== ePSNCS_Active
)
688 if (pMember
->m_bHostJoinAck
)
690 return ePSNCS_Active
;
694 return ePSNCS_Pending
;
698 return pMember
->m_signalingState
;
704 //-- No owner at all! This is wrong!
708 bool CCryPSNMatchMaking::ProcessCorrectTaskForRequest(SCryPSNSupportCallbackEventData
& data
, ETask subTaskCheck
, const char* pRequestString
, EventRequestResponseCallback pCB
)
710 for (uint32 i
= 0; i
< MAX_MATCHMAKING_TASKS
; i
++)
712 STask
* pTask
= &m_task
[i
];
713 if (pTask
->used
&& pTask
->running
)
715 if (pTask
->m_reqId
== data
.m_requestEvent
.m_reqId
)
717 bool bHandled
= false;
719 if (pTask
->subTask
== subTaskCheck
)
721 bHandled
= pCB(this, pTask
, i
, data
);
725 data
.m_requestEvent
.m_returnFlags
|= SCryPSNSupportCallbackEventData::SRequestEvent::REQUEST_EVENT_HANDLED
;
729 data
.m_requestEvent
.m_returnFlags
= SCryPSNSupportCallbackEventData::SRequestEvent::REQUEST_EVENT_NOT_HANDLED
;
731 // a task was found, but not handled. mark the task with an error so it stops itself
733 // Some generic behaviours for non-critical errors
734 switch (data
.m_requestEvent
.m_error
)
736 case SCE_NP_MATCHING2_ERROR_ROOM_NOT_FOUND
:
737 case SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM
:
738 case SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM_INSTANCE
:
740 UpdateTaskError(i
, eCLE_RoomDoesNotExist
);
741 data
.m_requestEvent
.m_returnFlags
|= SCryPSNSupportCallbackEventData::SRequestEvent::REQUEST_EVENT_HANDLED
;
744 case SCE_NP_MATCHING2_SERVER_ERROR_ROOM_FULL
:
746 UpdateTaskError(i
, eCLE_SessionFull
);
747 data
.m_requestEvent
.m_returnFlags
|= SCryPSNSupportCallbackEventData::SRequestEvent::REQUEST_EVENT_HANDLED
;
752 UpdateTaskError(i
, eCLE_InternalError
);
753 // If we leave it unhandled, PSNSupport will attempt to handle any critical errors for us
759 pTask
->m_reqId
= INVALID_PSN_REQUEST_ID
;
761 if (pTask
->error
!= eCLE_Success
)
772 NetLog("%s event received, but no tasks in correct state to process it!", pRequestString
);
776 bool CCryPSNMatchMaking::ProcessCorrectTaskForSearch(SCryPSNSupportCallbackEventData
& data
, ETask subTaskCheck
, const char* pRequestString
, EventRequestResponseCallback pCB
)
778 for (uint32 i
= 0; i
< MAX_MATCHMAKING_TASKS
; i
++)
780 STask
* pTask
= &m_task
[i
];
781 if (pTask
->used
&& pTask
->running
)
783 if (pTask
->subTask
== subTaskCheck
)
785 assert(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT
] != TMemInvalidHdl
);
787 SSearchInfoData
* pSearchInfo
= (SSearchInfoData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT
]);
790 for (int a
= 0; a
< pSearchInfo
->m_numResults
; a
++)
792 if (data
.m_requestEvent
.m_reqId
== pSearchInfo
->m_reqId
[a
])
794 pTask
->m_reqId
= data
.m_requestEvent
.m_reqId
;
796 bool bHandled
= pCB(this, pTask
, i
, data
);
800 data
.m_requestEvent
.m_returnFlags
|= SCryPSNSupportCallbackEventData::SRequestEvent::REQUEST_EVENT_HANDLED
;
804 data
.m_requestEvent
.m_returnFlags
= SCryPSNSupportCallbackEventData::SRequestEvent::REQUEST_EVENT_NOT_HANDLED
;
806 // a task was found, but not handled, stop the task.
807 // If we leave it unhandled, the PSNSupport will attempt to handle any critical errors for us
808 UpdateTaskError(i
, eCLE_InternalError
);
811 pTask
->m_reqId
= INVALID_PSN_REQUEST_ID
;
813 if (pTask
->error
!= eCLE_Success
)
825 NetLog("%s event received, task %d found with correct subtask %d, but no pSearchInfo!", pRequestString
, i
, subTaskCheck
);
826 UpdateTaskError(i
, eCLE_OutOfMemory
);
834 NetLog("%s event received, but no tasks in correct state to process it!", pRequestString
);
838 void CCryPSNMatchMaking::ProcessRequestEvent(SCryPSNSupportCallbackEventData
& data
)
840 switch (data
.m_requestEvent
.m_event
)
842 case REQUEST_EVENT_GET_WORLD_INFO_LIST
:
844 if (!ProcessCorrectTaskForRequest(data
, eST_WaitingForCreateRoomWorldInfo
, "REQUEST_EVENT_GET_WORLD_INFO_LIST", EventRequestResponse_GetWorldInfoListForCreate
))
846 NetLog("Not a create, so trying search instead...");
847 if (!ProcessCorrectTaskForRequest(data
, eST_WaitingForSearchRoomWorldInfo
, "REQUEST_EVENT_GET_WORLD_INFO_LIST", EventRequestResponse_GetWorldInfoListForSearch
))
849 NetLog("Not a search either! Time to trigger unhandled REQUEST_EVENT_GET_WORLD_INFO_LIST!");
854 case REQUEST_EVENT_LEAVE_ROOM
:
856 ProcessCorrectTaskForRequest(data
, eST_WaitingForLeaveRoomRequestCallback
, "REQUEST_EVENT_LEAVE_ROOM", EventRequestResponse_LeaveRoom
);
859 case REQUEST_EVENT_SET_ROOM_MEMBER_DATA_INTERNAL
:
861 ProcessCorrectTaskForRequest(data
, eST_WaitingForUserDataRequestCallback
, "REQUEST_EVENT_SET_ROOM_MEMBER_DATA_INTERNAL", EventRequestResponse_SetRoomMemberDataInternal
);
864 case REQUEST_EVENT_SET_ROOM_DATA_EXTERNAL
:
866 ProcessCorrectTaskForRequest(data
, eST_WaitingForUpdateRoomRequestCallback
, "REQUEST_EVENT_SET_ROOM_DATA_EXTERNAL", EventRequestResponse_SetRoomDataExternal
);
869 case REQUEST_EVENT_SET_ROOM_DATA_INTERNAL
:
871 #if NETWORK_HOST_MIGRATION
872 ProcessCorrectTaskForRequest(data
, eST_WaitingForNewHostHintCallback
, "REQUEST_EVENT_SET_ROOM_DATA_INTERNAL", EventRequestResponse_SetRoomDataInternal
);
876 case REQUEST_EVENT_GET_ROOM_DATA_EXTERNAL_LIST
:
878 ProcessCorrectTaskForRequest(data
, eST_WaitingForQueryRoomRequestCallback
, "REQUEST_EVENT_GET_ROOM_DATA_EXTERNAL_LIST", EventRequestResponse_GetRoomDataExternalList
);
881 case REQUEST_EVENT_SEARCH_ROOM
:
883 ProcessCorrectTaskForRequest(data
, eST_WaitingForSearchRoomRequestCallback
, "REQUEST_EVENT_SEARCH_ROOM", EventRequestResponse_SearchRoom
);
886 case REQUEST_EVENT_SIGNALING_GET_PING_INFO
:
888 ProcessCorrectTaskForSearch(data
, eST_WaitingForSearchQOSRequestCallback
, "REQUEST_EVENT_SIGNALING_GET_PING_INFO", EventRequestResponse_SearchQOS
);
891 case REQUEST_EVENT_JOIN_ROOM
:
893 ProcessCorrectTaskForRequest(data
, eST_WaitingForJoinRoomRequestCallback
, "REQUEST_EVENT_JOIN_ROOM", EventRequestResponse_JoinRoom
);
896 case REQUEST_EVENT_CREATE_JOIN_ROOM
:
898 ProcessCorrectTaskForRequest(data
, eST_WaitingForCreateRoomRequestCallback
, "REQUEST_EVENT_CREATE_JOIN_ROOM", EventRequestResponse_CreateRoom
);
901 case REQUEST_EVENT_GRANT_ROOM_OWNER
:
903 #if NETWORK_HOST_MIGRATION
904 ProcessCorrectTaskForRequest(data
, eST_WaitingForGrantRoomOwnerRequestCallback
, "REQUEST_EVENT_GRANT_ROOM_OWNER", EventRequestResponse_GrantRoomOwner
);
913 void CCryPSNMatchMaking::ProcessSignalingEvent(SCryPSNSupportCallbackEventData
& data
)
915 for (uint32 i
= 0; i
< MAX_MATCHMAKING_SESSIONS
; i
++)
917 SSession
* pSession
= &m_sessions
[i
];
919 if (pSession
->IsUsed())
921 SSession::SRoomMember
* pMember
= FindRoomMemberFromRoomMemberID(i
, data
.m_signalEvent
.m_subject
);
922 if (pMember
&& pMember
->IsValid(ePSNMI_Other
) && (pMember
->m_signalingState
!= ePSNCS_None
))
924 switch (data
.m_signalEvent
.m_event
)
926 case SIGNALING_EVENT_DEAD
:
928 pMember
->m_signalingState
= ePSNCS_Dead
;
930 DumpMemberInfo(pMember
);
931 CryMatchMakingConnectionID id
= FindConnectionIDFromRoomMemberID(i
, pMember
->m_memberId
);
932 if (id
!= CryMatchMakingInvalidConnectionID
)
934 SSession::SRConnection
* pConnection
= &pSession
->remoteConnection
[id
];
935 NetLog("[Lobby] CCryPSNMatchMaking::ProcessSignalingEvent() : SCE_NP_SIGNALING_EVENT_DEAD : Signaling dead event setting connection " PRFORMAT_LCID
" to eCLCS_NotConnected", PRARG_LCID(pConnection
->connectionID
));
936 NetLog("[Lobby] Signaling ID %d: SIGNALING_EVENT_DEAD not handled: error %08X", data
.m_signalEvent
.m_subject
, data
.m_signalEvent
.m_error
);
937 m_lobby
->ConnectionSetState(pConnection
->connectionID
, eCLCS_NotConnected
);
940 data
.m_signalEvent
.m_bHandled
= true;
944 case SIGNALING_EVENT_CONNECTED
:
947 int ret
= sceNpMatching2SignalingGetConnectionStatus(m_pPSNSupport
->GetMatchmakingContextId(), data
.m_signalEvent
.m_roomId
, data
.m_signalEvent
.m_subject
, &conStatus
, (SceNetInAddr
*)&pMember
->m_peerAddr
, &pMember
->m_peerPort
);
948 if ((ret
== PSN_OK
) && (conStatus
== SCE_NP_MATCHING2_SIGNALING_CONN_STATUS_ACTIVE
))
950 pMember
->m_signalingState
= ePSNCS_Active
;
952 CryMatchMakingConnectionID id
= FindConnectionIDFromRoomMemberID(i
, pMember
->m_memberId
);
953 if (id
!= CryMatchMakingInvalidConnectionID
)
955 SSession::SRConnection
* pConnection
= &pSession
->remoteConnection
[id
];
957 if (pConnection
->connectionID
== CryLobbyInvalidConnectionID
)
959 TNetAddress netAddr
= TNetAddress(SIPv4Addr(ntohl(pMember
->m_peerAddr
.s_addr
), ntohs(pMember
->m_peerPort
)));
961 #if !ENABLE_PLATFORM_PROTOCOL
964 uint16 connectPort
, listenPort
;
966 m_pService
->GetSocketPorts(connectPort
, listenPort
);
967 netAddr
= TNetAddress(SIPv4Addr(ntohl(pMember
->m_peerAddr
.s_addr
), connectPort
));
970 // Add connection - if not found
971 CryLobbyConnectionID lID
= m_lobby
->FindConnection(netAddr
);
972 if (lID
== CryLobbyInvalidConnectionID
)
974 lID
= m_lobby
->CreateConnection(netAddr
);
978 if (m_lobby
->ConnectionGetState(lID
) == eCLCS_Freeing
)
980 NetLog("[Lobby] Signaling active on existing Freeing connection " PRFORMAT_LCID
, PRARG_LCID(lID
));
981 m_lobby
->FreeConnection(lID
);
982 lID
= m_lobby
->CreateConnection(netAddr
);
986 m_lobby
->ConnectionAddRef(lID
);
987 pConnection
->connectionID
= lID
;
989 DumpMemberInfo(pMember
);
990 NetLog("[Lobby] CCryPSNMatchMaking::ProcessSignalingEvent() : SIGNALING_EVENT_CONNECTED : Signaling established for " PRFORMAT_SHMMCINFO
, PRARG_SHMMCINFO(CryLobbySessionHandle(i
), id
, pConnection
->connectionID
, pConnection
->uid
));
992 AddVoiceUser(pMember
);
993 SessionUserDataEvent(eCLSE_SessionUserJoin
, i
, id
);
995 if (pSession
->localFlags
& CRYSESSION_LOCAL_FLAG_HOST
)
997 // Include the SceNpSessionId the host got from registering the session on PSN when room was created.
998 // Pass this over to all connecting clients so they can join the same session
999 const uint32 maxBufferSize
= CryLobbyPacketHeaderSize
+ sizeof(SceNpSessionId
);
1000 uint8 buffer
[maxBufferSize
];
1001 CCryLobbyPacket packet
;
1003 packet
.SetWriteBuffer(buffer
, maxBufferSize
);
1004 packet
.StartWrite(ePSNPT_JoinSessionAck
, true);
1005 packet
.WriteString((const char*)&pSession
->m_sessionId
, sizeof(SceNpSessionId
));
1007 Send(CryMatchMakingInvalidTaskID
, &packet
, i
, id
);
1012 else if (ret
< PSN_OK
)
1014 NetLog("sceNpMatching2SignalingGetConnectionStatus : %08X", ret
);
1016 pMember
->m_signalingState
= ePSNCS_Dead
;
1018 CryMatchMakingConnectionID id
= FindConnectionIDFromRoomMemberID(i
, pMember
->m_memberId
);
1019 if (id
!= CryMatchMakingInvalidConnectionID
)
1021 SSession::SRConnection
* pConnection
= &pSession
->remoteConnection
[id
];
1022 NetLog("[Lobby] CCryPSNMatchMaking::ProcessSignalingEvent() : SIGNALING_EVENT_CONNECTED(1) : Signaling connected failure event, setting " PRFORMAT_SHMMCINFO
" to eCLCS_NotConnected", PRARG_SHMMCINFO(CryLobbySessionHandle(i
), id
, pConnection
->connectionID
, pConnection
->uid
));
1023 m_lobby
->ConnectionSetState(pConnection
->connectionID
, eCLCS_NotConnected
);
1026 m_pPSNSupport
->HandlePSNError(ret
);
1030 pMember
->m_signalingState
= ePSNCS_Dead
;
1032 CryMatchMakingConnectionID id
= FindConnectionIDFromRoomMemberID(i
, pMember
->m_memberId
);
1033 if (id
!= CryMatchMakingInvalidConnectionID
)
1035 SSession::SRConnection
* pConnection
= &pSession
->remoteConnection
[id
];
1036 NetLog("[Lobby] CCryPSNMatchMaking::ProcessSignalingEvent() : SIGNALING_EVENT_CONNECTED(2) : Signaling connected failure event, setting " PRFORMAT_SHMMCINFO
" to eCLCS_NotConnected", PRARG_SHMMCINFO(CryLobbySessionHandle(i
), id
, pConnection
->connectionID
, pConnection
->uid
));
1037 m_lobby
->ConnectionSetState(pConnection
->connectionID
, eCLCS_NotConnected
);
1040 data
.m_signalEvent
.m_bHandled
= true;
1044 case SIGNALING_EVENT_NETINFO_RESULT
:
1046 NetLog("[SIGNALING] Ignored Event : %08X", data
.m_signalEvent
.m_event
);
1047 data
.m_signalEvent
.m_bHandled
= true;
1052 // handle unknown responses - future sdks
1060 void CCryPSNMatchMaking::DispatchForcedFromRoomEvent(CrySessionHandle gh
, SceNpMatching2Event how
, SceNpMatching2EventCause why
)
1064 UCryLobbyEventData eventData
;
1065 SCryLobbyForcedFromRoomData eventRoomData
;
1066 eventData
.pForcedFromRoomData
= &eventRoomData
;
1068 eventRoomData
.m_session
= gh
;
1072 case SCE_NP_MATCHING2_EVENT_CAUSE_SERVER_OPERATION
:
1073 case SCE_NP_MATCHING2_EVENT_CAUSE_CONTEXT_ACTION
:
1075 NetLog("DispatchForcedFromRoomEvent(eFFRR_ServerForced)");
1076 eventRoomData
.m_why
= eFFRR_ServerForced
;
1079 case SCE_NP_MATCHING2_EVENT_CAUSE_LEAVE_ACTION
:
1080 case SCE_NP_MATCHING2_EVENT_CAUSE_MEMBER_DISAPPEARED
:
1082 NetLog("DispatchForcedFromRoomEvent(eFFRR_Left)");
1083 eventRoomData
.m_why
= eFFRR_Left
;
1086 case SCE_NP_MATCHING2_EVENT_CAUSE_KICKOUT_ACTION
:
1088 NetLog("DispatchForcedFromRoomEvent(eFFRR_Kicked)");
1089 eventRoomData
.m_why
= eFFRR_Kicked
;
1092 case SCE_NP_MATCHING2_EVENT_CAUSE_SERVER_INTERNAL
:
1093 case SCE_NP_MATCHING2_EVENT_CAUSE_SYSTEM_ERROR
:
1094 case SCE_NP_MATCHING2_EVENT_CAUSE_CONTEXT_ERROR
:
1096 NetLog("DispatchForcedFromRoomEvent(eFFRR_ServerInternalError)");
1097 eventRoomData
.m_why
= eFFRR_ServerInternalError
;
1100 case SCE_NP_MATCHING2_EVENT_CAUSE_CONNECTION_ERROR
:
1102 NetLog("DispatchForcedFromRoomEvent(eFFRR_ConnectionError)");
1103 eventRoomData
.m_why
= eFFRR_ConnectionError
;
1106 case SCE_NP_MATCHING2_EVENT_CAUSE_NP_SIGNED_OUT
:
1108 NetLog("DispatchForcedFromRoomEvent(eFFRR_SignedOut)");
1109 eventRoomData
.m_why
= eFFRR_SignedOut
;
1114 NetLog("DispatchForcedFromRoomEvent(eFFRR_Unknown)");
1115 eventRoomData
.m_why
= eFFRR_Unknown
;
1120 m_lobby
->DispatchEvent(eCLSE_ForcedFromRoom
, eventData
);
1124 void CCryPSNMatchMaking::ProcessRoomEvent(SCryPSNSupportCallbackEventData
& data
)
1126 for (uint32 i
= 0; i
< MAX_MATCHMAKING_SESSIONS
; i
++)
1128 SSession
* pSession
= &m_sessions
[i
];
1130 if (pSession
->IsUsed() && (pSession
->m_roomId
== data
.m_roomEvent
.m_roomId
))
1132 switch (data
.m_roomEvent
.m_event
)
1134 case ROOM_EVENT_MEMBER_JOINED
:
1136 if ((data
.m_roomEvent
.m_error
== 0) &&
1137 (data
.m_roomEvent
.m_dataHdl
!= TMemInvalidHdl
) &&
1138 (data
.m_roomEvent
.m_dataSize
== sizeof(SCryPSNRoomMemberUpdateInfoResponse
)))
1140 SCryPSNRoomMemberUpdateInfoResponse
* pMemberUpdateInfo
= (SCryPSNRoomMemberUpdateInfoResponse
*)m_pPSNSupport
->GetLobby()->MemGetPtr(data
.m_roomEvent
.m_dataHdl
);
1142 if (pMemberUpdateInfo
->m_member
.m_flagAttr
& SCE_NP_MATCHING2_ROOMMEMBER_FLAG_ATTR_OWNER
)
1144 AddRoomMember(i
, pMemberUpdateInfo
->m_member
, ePSNMI_OtherOwner
);
1148 AddRoomMember(i
, pMemberUpdateInfo
->m_member
, ePSNMI_Other
);
1151 data
.m_roomEvent
.m_returnFlags
|= SCryPSNSupportCallbackEventData::SRoomEvent::ROOM_EVENT_HANDLED
;
1155 //-- error occurred on room member join event
1156 //-- leave data.m_roomEvent.m_returnFlags as 0 to let the default error handler take care of any serious errors.
1160 case ROOM_EVENT_MEMBER_LEFT
:
1162 if ((data
.m_roomEvent
.m_error
== 0) &&
1163 (data
.m_roomEvent
.m_dataHdl
!= TMemInvalidHdl
) &&
1164 (data
.m_roomEvent
.m_dataSize
== sizeof(SCryPSNRoomMemberUpdateInfoResponse
)))
1166 SCryPSNRoomMemberUpdateInfoResponse
* pMemberUpdateInfo
= (SCryPSNRoomMemberUpdateInfoResponse
*)m_pPSNSupport
->GetLobby()->MemGetPtr(data
.m_roomEvent
.m_dataHdl
);
1167 RemoveRoomMember(i
, pMemberUpdateInfo
->m_member
);
1169 data
.m_roomEvent
.m_returnFlags
|= SCryPSNSupportCallbackEventData::SRoomEvent::ROOM_EVENT_HANDLED
;
1173 //-- error occurred on room member left event
1174 //-- leave data.m_roomEvent.m_returnFlags as 0 to let the default error handler take care of any serious errors.
1178 case ROOM_EVENT_ROOM_OWNER_CHANGED
:
1180 if ((data
.m_roomEvent
.m_error
== 0) &&
1181 (data
.m_roomEvent
.m_dataHdl
!= TMemInvalidHdl
) &&
1182 (data
.m_roomEvent
.m_dataSize
== sizeof(SCryPSNRoomOwnerUpdateInfoResponse
)))
1184 SCryPSNRoomOwnerUpdateInfoResponse
* pOwnerInfo
= (SCryPSNRoomOwnerUpdateInfoResponse
*)m_pPSNSupport
->GetLobby()->MemGetPtr(data
.m_roomEvent
.m_dataHdl
);
1185 NetLog("[LEE] Got Request for room owner change : Old Owner %d, New Owner %d", pOwnerInfo
->m_prevOwner
, pOwnerInfo
->m_newOwner
);
1186 ChangeRoomOwner(i
, pOwnerInfo
->m_prevOwner
, pOwnerInfo
->m_newOwner
);
1188 data
.m_roomEvent
.m_returnFlags
|= SCryPSNSupportCallbackEventData::SRoomEvent::ROOM_EVENT_HANDLED
;
1192 //-- error occurred on room owner changed event
1193 //-- leave data.m_roomEvent.m_returnFlags as 0 to let the default error handler take care of any serious errors.
1197 case ROOM_EVENT_KICKED_OUT
:
1199 NetLog("ROOM_EVENT_KICKED_OUT i:%d", i
);
1201 if ((data
.m_roomEvent
.m_error
== 0) &&
1202 (data
.m_roomEvent
.m_dataHdl
!= TMemInvalidHdl
) &&
1203 (data
.m_roomEvent
.m_dataSize
== sizeof(SCryPSNRoomUpdateInfoResponse
)))
1205 ClearSessionInfo(i
);
1206 FreeSessionHandle(i
);
1208 SCryPSNRoomUpdateInfoResponse
* pUpdateInfo
= (SCryPSNRoomUpdateInfoResponse
*)m_pPSNSupport
->GetLobby()->MemGetPtr(data
.m_roomEvent
.m_dataHdl
);
1210 TO_GAME_FROM_LOBBY(&CCryPSNMatchMaking::DispatchForcedFromRoomEvent
, this, CreateGameSessionHandle(i
, pSession
->localConnection
.uid
), data
.m_roomEvent
.m_event
, pUpdateInfo
->m_eventCause
);
1212 data
.m_roomEvent
.m_returnFlags
|= SCryPSNSupportCallbackEventData::SRoomEvent::ROOM_EVENT_HANDLED
;
1216 //-- error occurred on kicked out of room event
1217 //-- leave data.m_roomEvent.m_returnFlags as 0 to let the default error handler take care of any serious errors.
1221 case ROOM_EVENT_ROOM_DESTROYED
:
1223 if ((data
.m_roomEvent
.m_error
== 0) &&
1224 (data
.m_roomEvent
.m_dataHdl
!= TMemInvalidHdl
) &&
1225 (data
.m_roomEvent
.m_dataSize
== sizeof(SCryPSNRoomUpdateInfoResponse
)))
1227 ClearSessionInfo(i
);
1228 FreeSessionHandle(i
);
1230 SCryPSNRoomUpdateInfoResponse
* pUpdateInfo
= (SCryPSNRoomUpdateInfoResponse
*)m_pPSNSupport
->GetLobby()->MemGetPtr(data
.m_roomEvent
.m_dataHdl
);
1232 TO_GAME_FROM_LOBBY(&CCryPSNMatchMaking::DispatchForcedFromRoomEvent
, this, CreateGameSessionHandle(i
, pSession
->localConnection
.uid
), data
.m_roomEvent
.m_event
, pUpdateInfo
->m_eventCause
);
1234 data
.m_roomEvent
.m_returnFlags
|= SCryPSNSupportCallbackEventData::SRoomEvent::ROOM_EVENT_HANDLED
;
1238 //-- error occurred on room destroyed event
1239 //-- leave data.m_roomEvent.m_returnFlags as 0 to let the default error handler take care of any serious errors.
1243 case ROOM_EVENT_UPDATED_ROOM_DATA_INTERNAL
:
1245 //-- Don't actually care about this event:- we just trap it so it doesn't get flagged as unhandled.
1246 if (data
.m_roomEvent
.m_error
== 0)
1248 data
.m_roomEvent
.m_returnFlags
|= SCryPSNSupportCallbackEventData::SRoomEvent::ROOM_EVENT_HANDLED
;
1252 //-- error occurred on internal room data updated event
1253 //-- leave data.m_roomEvent.m_returnFlags as 0 to let the default error handler take care of any serious errors.
1257 case ROOM_EVENT_UPDATED_ROOM_MEMBER_DATA_INTERNAL
:
1259 if ((data
.m_roomEvent
.m_error
== 0) &&
1260 (data
.m_roomEvent
.m_dataHdl
!= TMemInvalidHdl
) &&
1261 (data
.m_roomEvent
.m_dataSize
== sizeof(SCryPSNRoomMemberUpdateInfoResponse
)))
1264 const SCryPSNRoomMemberUpdateInfoResponse
* const pUpdateInfo
= (SCryPSNRoomMemberUpdateInfoResponse
*)m_pPSNSupport
->GetLobby()->MemGetPtr(data
.m_requestEvent
.m_dataHdl
);
1265 UpdateRoomMember(i
, pUpdateInfo
->m_member
);
1267 data
.m_roomEvent
.m_returnFlags
|= SCryPSNSupportCallbackEventData::SRoomEvent::ROOM_EVENT_HANDLED
;
1271 //-- error occurred on internal room member data updated event
1272 //-- leave data.m_roomEvent.m_returnFlags as 0 to let the default error handler take care of any serious errors.
1276 case ROOM_EVENT_UPDATED_SIGNALING_OPT_PARAM
:
1278 //-- Don't actually care about this event:- we just trap it so it doesn't get flagged as unhandled.
1279 if (data
.m_roomEvent
.m_error
== 0)
1281 data
.m_roomEvent
.m_returnFlags
|= SCryPSNSupportCallbackEventData::SRoomEvent::ROOM_EVENT_HANDLED
;
1285 //-- error occurred on signaling opt param updated event
1286 //-- leave data.m_roomEvent.m_returnFlags as 0 to let the default error handler take care of any serious errors.
1297 void CCryPSNMatchMaking::ProcessErrorEvent(SCryPSNSupportCallbackEventData
& data
)
1299 for (uint32 i
= 0; i
< MAX_MATCHMAKING_TASKS
; i
++)
1301 STask
* pTask
= &m_task
[i
];
1302 if (pTask
->used
&& pTask
->running
)
1304 UpdateTaskError(i
, MapSupportErrorToLobbyError(data
.m_errorEvent
.m_error
));
1309 for (uint32 j
= 0; j
< MAX_MATCHMAKING_SESSIONS
; j
++)
1311 SSession
* pSession
= &m_sessions
[j
];
1312 if (pSession
->IsUsed())
1314 ClearSessionInfo(j
);
1315 FreeSessionHandle(j
);
1320 void CCryPSNMatchMaking::ProcessWebApiEvent(SCryPSNSupportCallbackEventData
& data
)
1322 for (uint32 i
= 0; i
< MAX_MATCHMAKING_TASKS
; i
++)
1324 STask
* pTask
= &m_task
[i
];
1325 if (pTask
->used
&& pTask
->running
)
1327 switch (pTask
->subTask
)
1329 case eST_WaitingForCreateRoomWebApiCallback
:
1331 SCreateParamData
* pCreateParams
= (SCreateParamData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_CREATE_REQUEST_SLOT
]);
1332 if (pCreateParams
&& (pCreateParams
->m_createJobId
== data
.m_webApiEvent
.m_id
))
1334 EventWebApiCreateSession(i
, data
);
1335 data
.m_webApiEvent
.m_returnFlags
|= SCryPSNSupportCallbackEventData::SWebApiEvent::WEBAPI_EVENT_HANDLED
;
1339 case eST_WaitingForJoinRoomWebApiCallback
:
1341 SJoinParamData
* pJoinParams
= (SJoinParamData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_JOIN_REQUEST_SLOT
]);
1342 if (pJoinParams
&& (pJoinParams
->m_joinJobId
== data
.m_webApiEvent
.m_id
))
1344 EventWebApiJoinSession(i
, data
);
1345 data
.m_webApiEvent
.m_returnFlags
|= SCryPSNSupportCallbackEventData::SWebApiEvent::WEBAPI_EVENT_HANDLED
;
1349 case eST_WaitingForLeaveRoomWebApiCallback
:
1351 SLeaveParamData
* pLeaveParams
= (SLeaveParamData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_LEAVE_REQUEST_SLOT
]);
1352 if (pLeaveParams
&& (pLeaveParams
->m_leaveJobId
== data
.m_webApiEvent
.m_id
))
1354 EventWebApiLeaveSession(i
, data
);
1355 data
.m_webApiEvent
.m_returnFlags
|= SCryPSNSupportCallbackEventData::SWebApiEvent::WEBAPI_EVENT_HANDLED
;
1359 case eST_WaitingForUpdateAdvertisementDataWebApiCallback
:
1361 SUpdateAdvertisementDataParamData
* pAdParams
= (SUpdateAdvertisementDataParamData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_UPDATEADVERT_REQUEST_SLOT
]);
1362 if (pAdParams
&& (pAdParams
->m_jobId
== data
.m_webApiEvent
.m_id
))
1364 EventWebApiUpdateSessionAdvertisement(i
, data
);
1365 data
.m_webApiEvent
.m_returnFlags
|= SCryPSNSupportCallbackEventData::SWebApiEvent::WEBAPI_EVENT_HANDLED
;
1369 case eST_WaitingForGetAdvertisementDataWebApiCallback
:
1371 SGetAdvertisementDataParamData
* pAdParams
= (SGetAdvertisementDataParamData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_GETADVERT_REQUEST_SLOT
]);
1372 if (pAdParams
&& (pAdParams
->m_jobId
== data
.m_webApiEvent
.m_id
))
1374 EventWebApiGetSessionLinkData(i
, data
);
1375 data
.m_webApiEvent
.m_returnFlags
|= SCryPSNSupportCallbackEventData::SWebApiEvent::WEBAPI_EVENT_HANDLED
;
1384 void CCryPSNMatchMaking::SupportCallback(ECryPSNSupportCallbackEvent ecb
, SCryPSNSupportCallbackEventData
& data
, void* pArg
)
1386 CCryPSNMatchMaking
* _this
= static_cast<CCryPSNMatchMaking
*>(pArg
);
1390 case eCE_RequestEvent
:
1392 _this
->ProcessRequestEvent(data
);
1395 case eCE_SignalEvent
:
1397 _this
->ProcessSignalingEvent(data
);
1402 _this
->ProcessRoomEvent(data
);
1405 case eCE_ErrorEvent
:
1407 _this
->ProcessErrorEvent(data
);
1410 case eCE_WebApiEvent
:
1412 _this
->ProcessWebApiEvent(data
);
1418 ECryLobbyError
CCryPSNMatchMaking::Initialise()
1420 ECryLobbyError error
= CCryMatchMaking::Initialise();
1422 if (error
== eCLE_Success
)
1426 ret
= sceSysmoduleLoadModule(SCE_SYSMODULE_NP_MATCHING2
);
1429 NetLog("sceSysmoduleLoadModule(SCE_SYSMODULE_NP_MATCHING2) failed. ret = 0x%x\n", ret
);
1430 return eCLE_InternalError
;
1433 SceNpMatching2InitializeParameter configurationMatching2
;
1434 memset(&configurationMatching2
, 0, sizeof(configurationMatching2
));
1435 configurationMatching2
.size
= sizeof(configurationMatching2
);
1436 configurationMatching2
.poolSize
= SCE_NP_MATCHING2_POOLSIZE_DEFAULT
;
1437 configurationMatching2
.cpuAffinityMask
= SCE_KERNEL_CPUMASK_USER_ALL
;
1438 configurationMatching2
.threadPriority
= SCE_KERNEL_PRIO_FIFO_DEFAULT
; //CLobbyCVars::Get().psnMatching2ThreadPriority;
1439 configurationMatching2
.threadStackSize
= SCE_NP_MATCHING2_THREAD_STACK_SIZE_DEFAULT
;
1441 ret
= sceNpMatching2Initialize(&configurationMatching2
);
1444 NetLog("sceNpMatching2Initialize() failed. ret = 0x%x\n", ret
);
1445 return eCLE_InternalError
;
1448 m_registeredUserData
.num
= 0;
1450 for (uint32 i
= 0; i
< MAX_MATCHMAKING_SESSIONS
; i
++)
1452 m_sessions
[i
].localFlags
&= ~CRYSESSION_LOCAL_FLAG_USED
;
1454 for (uint32 j
= 0; j
< MAX_LOBBY_CONNECTIONS
; j
++)
1456 m_sessions
[i
].remoteConnection
[j
].connectionID
= CryLobbyInvalidConnectionID
;
1457 m_sessions
[i
].remoteConnection
[j
].used
= false;
1458 m_sessions
[i
].remoteConnection
[j
].registered
= false;
1459 m_sessions
[i
].remoteConnection
[j
].memberId
= INVALID_PSN_ROOM_MEMBER_ID
;
1462 ClearSessionInfo(i
);
1465 for (uint32 i
= 0; i
< MAX_MATCHMAKING_TASKS
; i
++)
1467 m_task
[i
].m_reqId
= INVALID_PSN_REQUEST_ID
;
1474 ECryLobbyError
CCryPSNMatchMaking::Terminate()
1476 for (uint32 i
= 0; i
< MAX_MATCHMAKING_SESSIONS
; i
++)
1478 SSession
* pSession
= &m_sessions
[i
];
1479 if (pSession
->IsUsed())
1481 ClearSessionInfo(i
);
1482 FreeSessionHandle(i
);
1487 ret
= sceNpMatching2Terminate();
1490 NetLog("sceNpMatching2Termimate() failed. ret = 0x%x\n", ret
);
1493 ret
= sceSysmoduleUnloadModule(SCE_SYSMODULE_NP_MATCHING2
);
1496 NetLog("sceSysmoduleUnloadModule(SCE_SYSMODULE_NP_MATCHING2) failed. ret = 0x%x\n", ret
);
1499 return eCLE_Success
;
1502 CCryPSNMatchMaking::CCryPSNMatchMaking(CCryLobby
* lobby
, CCryLobbyService
* service
, CCryPSNSupport
* pSupport
, ECryLobbyService serviceType
) : CCryMatchMaking(lobby
, service
, serviceType
)
1504 m_pPSNSupport
= pSupport
;
1506 m_oldNatType
= SCE_NP_MATCHING2_SIGNALING_NETINFO_NAT_STATUS_UNKNOWN
;
1508 // Make the CCryMatchMaking base pointers point to our data so we can use the common code in CCryMatchMaking
1509 for (uint32 i
= 0; i
< MAX_MATCHMAKING_SESSIONS
; i
++)
1511 CCryMatchMaking::m_sessions
[i
] = &m_sessions
[i
];
1512 CCryMatchMaking::m_sessions
[i
]->localConnection
= &m_sessions
[i
].localConnection
;
1514 for (uint32 j
= 0; j
< MAX_LOBBY_CONNECTIONS
; j
++)
1516 CCryMatchMaking::m_sessions
[i
]->remoteConnection
[j
] = &m_sessions
[i
].remoteConnection
[j
];
1520 for (uint32 i
= 0; i
< MAX_MATCHMAKING_TASKS
; i
++)
1522 CCryMatchMaking::m_task
[i
] = &m_task
[i
];
1525 REGISTER_CVAR2("net_enable_psn_hinting", &net_enable_psn_hinting
, 1, VF_DUMPTODISK
, "Toggles whether PSN hinting enabled or not");
1528 CCryPSNMatchMaking::~CCryPSNMatchMaking()
1532 ECryLobbyError
CCryPSNMatchMaking::StartTask(ETask etask
, bool startRunning
, uint32 user
, CryMatchMakingTaskID
* mmTaskID
, CryLobbyTaskID
* lTaskID
, CryLobbySessionHandle h
, void* cb
, void* cbArg
)
1534 CryMatchMakingTaskID tmpMMTaskID
;
1535 CryMatchMakingTaskID
* useMMTaskID
= mmTaskID
? mmTaskID
: &tmpMMTaskID
;
1536 ECryLobbyError error
= CCryMatchMaking::StartTask(etask
, startRunning
, useMMTaskID
, lTaskID
, h
, cb
, cbArg
);
1538 if (error
== eCLE_Success
)
1540 ResetTask(*useMMTaskID
);
1546 void CCryPSNMatchMaking::ResetTask(CryMatchMakingTaskID mmTaskID
)
1548 STask
* pTask
= &m_task
[mmTaskID
];
1549 pTask
->returnTaskID
= CryMatchMakingInvalidTaskID
;
1550 pTask
->m_reqId
= INVALID_PSN_REQUEST_ID
;
1553 const char* CCryPSNMatchMaking::SSession::GetLocalUserName(uint32 localUserIndex
) const
1555 if (localFlags
& CRYSESSION_LOCAL_FLAG_USED
)
1557 for (uint32 memberIndex
= 0; memberIndex
< MAX_PSN_ROOM_MEMBERS
; ++memberIndex
)
1559 const SRoomMember
* pRoomMember
= &m_members
[memberIndex
];
1560 if ((pRoomMember
->m_valid
!= ePSNMI_None
) && (pRoomMember
->m_memberId
== m_myMemberId
))
1562 return pRoomMember
->m_npId
.handle
.data
;
1570 void CCryPSNMatchMaking::SSession::Reset()
1575 remoteConnectionProcessingToDo
= false;
1576 remoteConnectionTaskID
= CryMatchMakingInvalidTaskID
;
1577 hostConnectionID
= CryMatchMakingInvalidConnectionID
;
1578 unregisteredConnectionsKicked
= false;
1580 m_serverId
= INVALID_PSN_SERVER_ID
;
1581 m_worldId
= INVALID_PSN_WORLD_ID
;
1582 m_roomId
= INVALID_PSN_ROOM_ID
;
1583 memset(&m_sessionId
, 0, sizeof(SceNpSessionId
));
1585 m_myMemberId
= INVALID_PSN_ROOM_MEMBER_ID
;
1586 m_ownerMemberId
= INVALID_PSN_ROOM_MEMBER_ID
;
1589 const char* CCryPSNMatchMaking::GetConnectionName(CCryMatchMaking::SSession::SRConnection
* pConnection
, uint32 localUserIndex
) const
1591 SSession::SRConnection
* pPlatformConnection
= reinterpret_cast<SSession::SRConnection
*>(pConnection
);
1593 if (pPlatformConnection
->uid
.m_uid
== DEDICATED_SERVER_CONNECTION_UID
)
1595 return "DedicatedServer";
1598 for (uint32 sessionIndex
= 0; sessionIndex
< MAX_MATCHMAKING_SESSIONS
; ++sessionIndex
)
1600 const SSession
* pSession
= &m_sessions
[sessionIndex
];
1602 if (pSession
->localFlags
& CRYSESSION_LOCAL_FLAG_USED
)
1604 for (uint32 memberIndex
= 0; memberIndex
< MAX_PSN_ROOM_MEMBERS
; ++memberIndex
)
1606 const SSession::SRoomMember
* pRoomMember
= &pSession
->m_members
[memberIndex
];
1607 if ((pRoomMember
->m_valid
!= ePSNMI_None
) && (pRoomMember
->m_memberId
== pPlatformConnection
->memberId
))
1609 return pRoomMember
->m_npId
.handle
.data
;
1618 void CCryPSNMatchMaking::StartTaskRunning(CryMatchMakingTaskID mmTaskID
)
1622 STask
* task
= &m_task
[mmTaskID
];
1626 #if ENABLE_CRYLOBBY_DEBUG_TESTS
1627 ECryLobbyError error
;
1629 if (!m_lobby
->DebugOKToStartTaskRunning(task
->lTaskID
))
1634 if (m_lobby
->DebugGenerateError(task
->lTaskID
, error
))
1636 UpdateTaskError(mmTaskID
, error
);
1637 StopTaskRunning(mmTaskID
);
1639 if ((task
->startedTask
== eT_SessionCreate
) || (task
->startedTask
== eT_SessionJoin
))
1641 FreeSessionHandle(task
->session
);
1648 task
->running
= true;
1650 switch (task
->startedTask
)
1652 case eT_SessionDelete
:
1653 StartSessionDelete(mmTaskID
);
1656 case eT_SessionUpdateSlots
:
1657 case eT_SessionStart
:
1659 case eT_SessionRegisterUserData
:
1660 StopTaskRunning(mmTaskID
);
1663 case eT_SessionSearch
:
1664 StartSessionSearch(mmTaskID
);
1667 #if NETWORK_HOST_MIGRATION
1668 case eT_SessionMigrateHostStart
:
1669 HostMigrationStartNT(mmTaskID
);
1671 case eT_SessionMigrateHostServer
:
1672 HostMigrationServerNT(mmTaskID
);
1674 case eT_SessionSendHostHintExternal
:
1675 StartSessionSendHostHintExternal(mmTaskID
);
1682 void CCryPSNMatchMaking::EndTask(CryMatchMakingTaskID mmTaskID
)
1686 STask
* pTask
= &m_task
[mmTaskID
];
1690 if (m_pPSNSupport
->GetNetInfo().natStatus
!= m_oldNatType
)
1692 m_oldNatType
= m_pPSNSupport
->GetNetInfo().natStatus
;
1694 UCryLobbyEventData eventData
;
1695 SCryLobbyNatTypeData natTypeData
;
1697 eventData
.pNatTypeData
= &natTypeData
;
1699 switch (m_oldNatType
)
1702 case SCE_NP_MATCHING2_SIGNALING_NETINFO_NAT_STATUS_UNKNOWN
:
1703 natTypeData
.m_curState
= eNT_Unknown
;
1705 case SCE_NP_MATCHING2_SIGNALING_NETINFO_NAT_STATUS_TYPE
:
1706 natTypeData
.m_curState
= eNT_Open
;
1708 case SCE_NP_MATCHING2_SIGNALING_NETINFO_NAT_STATUS_TYPE2
:
1709 natTypeData
.m_curState
= eNT_Moderate
;
1711 case SCE_NP_MATCHING2_SIGNALING_NETINFO_NAT_STATUS_TYPE3
:
1712 natTypeData
.m_curState
= eNT_Strict
;
1718 m_lobby
->DispatchEvent(eCLSE_NatType
, eventData
);
1719 m_lobby
->SetNATType(natTypeData
.m_curState
);
1723 #if NETWORK_HOST_MIGRATION
1724 if (pTask
->startedTask
& HOST_MIGRATION_TASK_ID_FLAG
)
1726 m_sessions
[pTask
->session
].hostMigrationInfo
.m_taskID
= CryLobbyInvalidTaskID
;
1732 switch (pTask
->startedTask
)
1734 case eT_SessionRegisterUserData
:
1735 ((CryMatchmakingCallback
)pTask
->cb
)(pTask
->lTaskID
, pTask
->error
, pTask
->cbArg
);
1738 case eT_SessionSearch
:
1739 EndSessionSearch(mmTaskID
);
1742 case eT_SessionMigrate
:
1743 ((CryMatchmakingSessionCreateCallback
)pTask
->cb
)(pTask
->lTaskID
, pTask
->error
, CreateGameSessionHandle(pTask
->session
, m_sessions
[pTask
->session
].localConnection
.uid
), pTask
->cbArg
);
1746 case eT_SessionCreate
:
1747 EndSessionCreate(mmTaskID
);
1750 case eT_SessionQuery
:
1751 EndSessionQuery(mmTaskID
);
1754 case eT_SessionGetUsers
:
1755 ((CryMatchmakingSessionGetUsersCallback
)pTask
->cb
)(pTask
->lTaskID
, pTask
->error
, NULL
, pTask
->cbArg
);
1758 case eT_SessionJoin
:
1759 EndSessionJoin(mmTaskID
);
1762 case eT_SessionSetAdvertisementData
:
1763 EndSessionSetAdvertisementData(mmTaskID
);
1766 case eT_SessionGetAdvertisementData
:
1767 EndSessionGetAdvertisementData(mmTaskID
);
1770 #if NETWORK_HOST_MIGRATION
1771 case eT_SessionSendHostHintExternal
:
1772 EndSessionSendHostHintExternal(mmTaskID
);
1776 case eT_SessionUserData
:
1777 case eT_SessionUpdate
:
1778 case eT_SessionUpdateSlots
:
1779 case eT_SessionStart
:
1781 case eT_SessionDelete
:
1782 #if NETWORK_HOST_MIGRATION
1783 case eT_SessionMigrateHostStart
:
1785 ((CryMatchmakingCallback
)pTask
->cb
)(pTask
->lTaskID
, pTask
->error
, pTask
->cbArg
);
1790 if (pTask
->canceled
)
1792 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
1795 if (pTask
->error
!= eCLE_Success
)
1797 if ((pTask
->startedTask
== eT_SessionCreate
) || (pTask
->startedTask
== eT_SessionJoin
))
1799 if (pTask
->session
!= CryLobbyInvalidSessionHandle
)
1801 ClearSessionInfo(pTask
->session
);
1802 FreeSessionHandle(pTask
->session
);
1803 pTask
->session
= CryLobbyInvalidSessionHandle
;
1807 NetLog("[Lobby] EndTask %d (%d) error %d", pTask
->startedTask
, pTask
->subTask
, pTask
->error
);
1810 // Clear PSN specific task state so that base class tasks can use this slot
1811 ResetTask(mmTaskID
);
1817 void CCryPSNMatchMaking::StopTaskRunning(CryMatchMakingTaskID mmTaskID
)
1819 STask
* pTask
= &m_task
[mmTaskID
];
1823 pTask
->running
= false;
1824 TO_GAME_FROM_LOBBY(&CCryPSNMatchMaking::EndTask
, this, mmTaskID
);
1828 ECryLobbyError
CCryPSNMatchMaking::CreateSessionHandle(CryLobbySessionHandle
* h
, bool host
, uint32
* users
, int numUsers
, uint32 flags
)
1830 ECryLobbyError error
= CCryMatchMaking::CreateSessionHandle(h
, host
, flags
, numUsers
);
1832 if (error
== eCLE_Success
)
1834 SSession
* pSession
= &m_sessions
[*h
];
1836 for (uint32 j
= 0; j
< numUsers
; j
++)
1838 pSession
->localConnection
.users
[j
] = users
[j
];
1841 ClearSessionInfo(*h
);
1847 void CCryPSNMatchMaking::Tick(CTimeValue tv
)
1849 CCryMatchMaking::Tick(tv
);
1851 for (uint32 i
= 0; i
< MAX_MATCHMAKING_TASKS
; i
++)
1853 STask
* pTask
= &m_task
[i
];
1855 #if ENABLE_CRYLOBBY_DEBUG_TESTS
1858 if (m_lobby
->DebugTickCallStartTaskRunning(pTask
->lTaskID
))
1860 StartTaskRunning(i
);
1863 if (!m_lobby
->DebugOKToTickTask(pTask
->lTaskID
, pTask
->running
))
1870 if (pTask
->used
&& pTask
->running
)
1872 if (pTask
->error
== eCLE_Success
)
1874 switch (pTask
->subTask
)
1876 case eT_SessionQuery
:
1877 TickSessionQuery(i
);
1880 case eT_SessionUpdate
:
1881 TickSessionUpdate(i
);
1884 case eT_SessionUserData
:
1885 TickSessionUserData(i
);
1888 case eT_SessionRegisterUserData
:
1889 case eT_SessionStart
:
1893 case eST_WaitingForJoinRoomSignalingCallback
:
1895 TickSessionJoinSignaling(i
);
1899 case eST_WaitingForCreateRoomSignalingCallback
:
1901 TickSessionCreateSignaling(i
);
1905 case eT_SessionSearch
:
1906 TickSessionSearch(i
);
1908 case eST_SessionSearchRequest
:
1909 TickSessionSearchRequest(i
);
1911 case eST_SessionSearchKickQOS
:
1912 TickSessionQOSSearch(i
);
1914 case eST_WaitingForSearchQOSRequestCallback
:
1915 TickSessionWaitForQOS(i
);
1918 case eT_SessionCreate
:
1919 TickSessionCreate(i
);
1921 case eST_SessionCreateRequest
:
1922 TickSessionCreateRequest(i
);
1925 case eT_SessionMigrate
:
1926 TickSessionMigrate(i
);
1929 case eT_SessionJoin
:
1933 case eT_SessionGetUsers
:
1934 TickSessionGetUsers(i
);
1937 case eT_SessionDelete
:
1938 TickSessionDelete(i
);
1941 case eT_SessionSetAdvertisementData
:
1942 TickSessionSetAdvertisementData(i
);
1945 case eT_SessionGetAdvertisementData
:
1946 TickSessionGetAdvertisementData(i
);
1949 #if NETWORK_HOST_MIGRATION
1950 case eT_SessionMigrateHostStart
:
1951 TickHostMigrationStartNT(i
);
1954 case eT_SessionMigrateHostServer
:
1955 TickHostMigrationServerNT(i
);
1958 case eT_SessionSendHostHintExternal
:
1959 TickSessionSendHostHintExternal(i
);
1968 if (pTask
->error
!= eCLE_Success
)
1977 const int psnShowRooms
= CLobbyCVars::Get().psnShowRooms
;
1978 if ((psnShowRooms
!= 0) && gEnv
->pRenderer
)
1980 static float yellow
[] = { 1.0f
, 1.0f
, 0.4f
, 1.0f
};
1983 for (uint32 i
= 0; i
< MAX_MATCHMAKING_SESSIONS
; i
++)
1985 SSession
* pSession
= &m_sessions
[i
];
1986 if (pSession
->IsUsed())
1988 f32 xpos
= 50.0f
+ (250.0f
* i
);
1990 // gEnv->pRenderer->Draw2dLabel(xpos, ypos, 1.5f, yellow, false, "S%d-W%d-R%lld",
1991 // pSession->m_serverId, pSession->m_worldId, pSession->m_roomId);
1997 ECryLobbyError
CCryPSNMatchMaking::SessionRegisterUserData(SCrySessionUserData
* data
, uint32 numData
, CryLobbyTaskID
* taskID
, CryMatchmakingCallback cb
, void* cbArg
)
1999 ECryLobbyError error
= eCLE_Success
;
2003 if (numData
< MAX_MATCHMAKING_SESSION_USER_DATA
)
2005 CryMatchMakingTaskID mmTaskID
;
2007 error
= StartTask(eT_SessionRegisterUserData
, false, 0, &mmTaskID
, taskID
, 0, (void*)cb
, cbArg
);
2009 if (error
== eCLE_Success
)
2011 memcpy(m_registeredUserData
.data
, data
, numData
* sizeof(data
[0]));
2012 m_registeredUserData
.num
= numData
;
2014 uint32 searchableCount
= 0;
2015 uint32 binBucketOffset
= 0;
2016 for (uint32 a
= 0; a
< numData
; a
++)
2018 if ((m_registeredUserData
.data
[a
].m_type
== eCSUDT_Int32
) && (searchableCount
< SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_NUM
))
2020 m_registeredUserData
.mapping
[a
].integerField
= 1;
2021 m_registeredUserData
.mapping
[a
].fieldOffset
= searchableCount
;
2027 // Either we have run out of searchable integers or the data type is not 32bit
2028 m_registeredUserData
.mapping
[a
].integerField
= 0;
2029 m_registeredUserData
.mapping
[a
].fieldOffset
= binBucketOffset
;
2030 switch (m_registeredUserData
.data
[a
].m_type
)
2033 case eCSUDT_Int64NoEndianSwap
:
2034 case eCSUDT_Float64
:
2035 binBucketOffset
+= 8;
2038 case eCSUDT_Float32
:
2039 binBucketOffset
+= 4;
2042 binBucketOffset
+= 2;
2045 binBucketOffset
+= 1;
2048 error
= eCLE_UserDataTypeMissMatch
;
2051 if (binBucketOffset
> (SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_MAX_SIZE
* SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_NUM
))
2053 error
= eCLE_OutOfSessionUserData
;
2059 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning
, this, mmTaskID
);
2064 error
= eCLE_OutOfSessionUserData
;
2067 NetLog("[Lobby] Start SessionRegisterUserData error %d", error
);
2072 uint32
CCryPSNMatchMaking::SortWorlds(const SCryPSNGetWorldInfoListResponse
* pWorldList
, SceNpMatching2WorldId
* pReturnIdList
, uint32 nMaxListSize
, bool bIsForSearch
)
2074 uint32 numWorldsSorted
= 0;
2076 if (pReturnIdList
&& (nMaxListSize
> 0))
2078 for (uint32 w
= 0; w
< nMaxListSize
; w
++)
2080 pReturnIdList
[w
] = INVALID_PSN_ROOM_ID
;
2083 uint32 numTotalWorlds
= pWorldList
? pWorldList
->m_numWorlds
: 0;
2084 if (pWorldList
&& numTotalWorlds
)
2086 int forceWorld
= CLobbyCVars::Get().psnForceWorld
;
2087 if (forceWorld
== 0)
2089 //-- For worlds metrics, we have access to two values:
2090 //-- ~ number of rooms on a world. The more rooms on a world, the better list of search results we'll get back
2091 //-- ~ players-per-room ratio. The higher the ratio, the more likely it is that the world is hosting game sessions.
2093 uint32 mostRooms
= 1;
2094 f32 mostPPRRatio
= 1.0f
;
2095 for (uint32 i
= 0; i
< numTotalWorlds
; i
++)
2097 SCryPSNWorld
& world
= pWorldList
->m_pWorlds
[i
];
2100 world
.m_sortState
= SCryPSNWorld::SORT_WORLD_NONE
;
2102 if (world
.m_numRooms
> 0)
2104 if (world
.m_numRooms
> mostRooms
)
2106 mostRooms
= world
.m_numRooms
;
2109 f32 fRatio
= (f32
)world
.m_numTotalRoomMembers
/ (f32
)world
.m_numRooms
;
2110 if (fRatio
> mostPPRRatio
)
2112 mostPPRRatio
= fRatio
;
2117 f32 roomsBonus
= (f32
)CLobbyCVars::Get().psnBestWorldNumRoomsBonus
;
2118 f32 roomsPCth
= (f32
)mostRooms
* CLobbyCVars::Get().psnBestWorldNumRoomsPivot
;
2119 f32 roomsRampUp
= roomsBonus
/ roomsPCth
;
2120 f32 roomsRampDown
= 0.0f
;
2121 if (CLobbyCVars::Get().psnBestWorldNumRoomsPivot
< 1.0f
)
2123 roomsRampDown
= (roomsBonus
* 0.33f
) / (mostRooms
- roomsPCth
);
2126 f32 ratioBonus
= (f32
)CLobbyCVars::Get().psnBestWorldPlayersPerRoomBonus
;
2127 f32 ratioPCth
= mostPPRRatio
* CLobbyCVars::Get().psnBestWorldPlayersPerRoomPivot
;
2128 f32 ratioRampUp
= ratioBonus
/ ratioPCth
;
2129 f32 ratioRampDown
= 0.0f
;
2130 if (CLobbyCVars::Get().psnBestWorldPlayersPerRoomPivot
< 1.0f
)
2132 ratioRampDown
= (ratioBonus
* 0.33f
) / (mostPPRRatio
- ratioPCth
);
2135 NetLog("SortWorlds: Room Setup: %d maximum, optimal is %.02f at position %.02f", mostRooms
, roomsPCth
, CLobbyCVars::Get().psnBestWorldNumRoomsPivot
);
2136 NetLog("SortWorlds: PPR Setup: %.04f maximum, optimal is %.04f at position %.02f", mostPPRRatio
, ratioPCth
, CLobbyCVars::Get().psnBestWorldPlayersPerRoomPivot
);
2138 uint32 maxRooms
= max(0, min(CLobbyCVars::Get().psnBestWorldMaxRooms
, MAX_ROOMS_PER_WORLD
));
2139 uint32 maxBonus
= CLobbyCVars::Get().psnBestWorldNumRoomsBonus
2140 + CLobbyCVars::Get().psnBestWorldPlayersPerRoomBonus
2141 + CLobbyCVars::Get().psnBestWorldRandomBonus
2144 for (uint32 i
= 0; i
< numTotalWorlds
; i
++)
2149 f32 playersPerRoomRatio
= 0.0f
;
2151 SCryPSNWorld
& world
= pWorldList
->m_pWorlds
[i
];
2153 if (world
.m_numRooms
> 0)
2155 //-- This could probably do with some statistical study to provide a good world score,
2156 //-- but using only the number of rooms (as we have in the past) isn't necessarily going to
2157 //-- provide a good world (it might be full of squads).
2159 f32 curNumOfRoom
= (f32
)world
.m_numRooms
;
2160 if (curNumOfRoom
<= roomsPCth
)
2162 scoreA
= (uint32
)(curNumOfRoom
* roomsRampUp
);
2166 scoreA
= (uint32
)(roomsBonus
- ((curNumOfRoom
- roomsPCth
) * roomsRampDown
));
2169 //-- And maybe some points for players per room density, which should skew the results towards
2170 //-- worlds with bigger rooms and hopefully those are more likely to contain game sessions and not squads.
2172 playersPerRoomRatio
= (f32
)world
.m_numTotalRoomMembers
/ (f32
)world
.m_numRooms
;
2173 if (playersPerRoomRatio
<= ratioPCth
)
2175 scoreB
= (uint32
)(playersPerRoomRatio
* ratioRampUp
);
2179 scoreB
= (uint32
)(ratioBonus
- ((playersPerRoomRatio
- ratioPCth
) * ratioRampDown
));
2182 world
.m_score
= scoreA
+ scoreB
;
2187 //-- if sorting is for a room search, only include worlds with a score > 0
2188 if (world
.m_score
> 0)
2190 world
.m_sortState
= SCryPSNWorld::SORT_WORLD_NEEDS_SORTING
;
2192 //-- We also have to make sure that at least 1 world is returned, so lets use world[0].
2195 world
.m_sortState
= SCryPSNWorld::SORT_WORLD_NEEDS_SORTING
;
2198 //-- also add a slightly random element so there's a chance that the sorted world list can change
2199 //-- (only useful if we return a subset of the sorted worlds (eg: top 3) and want some variation, otherwise it's pointless.)
2200 //-- Since we return all worlds for a search this is no longer necessary. But might be in the future.
2201 //scoreC = (cry_rand() % CNetCVars::Get().psnBestWorldRandomBonus);
2202 //world.m_score += scoreC;
2206 //-- if sorting is for a room create, only include worlds that are not full.
2207 if (world
.m_numRooms
< maxRooms
)
2209 world
.m_sortState
= SCryPSNWorld::SORT_WORLD_NEEDS_SORTING
;
2213 NetLog("SortWorlds: World %02d : ID %d: Score = %d + %d + %d = %d (%d rooms ~ %.2f PPR)", i
+ 1, world
.m_worldId
,
2214 scoreA
, scoreB
, scoreC
, world
.m_score
, world
.m_numRooms
, playersPerRoomRatio
);
2217 //-- We have a set of valid worlds to sort now, so we just have to add them to the return list in the correct order.
2218 //-- It's a pretty bad selection sort algorithm, but it doesn't need to be hugely performance critical.
2219 bool bSorting
= true;
2222 SCryPSNWorld
* pBestWorld
= NULL
;
2223 uint32 highestWorldScore
= 0;
2224 uint32 lowestWorldScore
= maxBonus
;
2226 for (uint32 l
= 0; l
< numTotalWorlds
; l
++)
2228 SCryPSNWorld
* pWorld
= &pWorldList
->m_pWorlds
[l
];
2230 if (pWorld
->m_sortState
== SCryPSNWorld::SORT_WORLD_NEEDS_SORTING
)
2234 // search returns the highest scoring worlds first
2235 if (pWorld
->m_score
>= highestWorldScore
)
2237 highestWorldScore
= pWorld
->m_score
;
2238 pBestWorld
= pWorld
;
2243 // create returns the lowest scoring worlds first.
2244 // I'm not sure this is really what we want...
2245 if (pWorld
->m_score
< lowestWorldScore
)
2247 lowestWorldScore
= pWorld
->m_score
;
2248 pBestWorld
= pWorld
;
2256 pReturnIdList
[numWorldsSorted
] = pBestWorld
->m_worldId
;
2257 pBestWorld
->m_sortState
= SCryPSNWorld::SORT_WORLD_SORTED
;
2260 if (numWorldsSorted
>= nMaxListSize
)
2265 NetLog("SortWorlds: Sorted %02d : ID %d: Score = %d", numWorldsSorted
, pBestWorld
->m_worldId
, pBestWorld
->m_score
);
2269 //-- No more worlds to add to sorted list
2276 if ((forceWorld
>= 1) && (forceWorld
<= numTotalWorlds
))
2278 pReturnIdList
[0] = pWorldList
->m_pWorlds
[forceWorld
- 1].m_worldId
;
2282 pReturnIdList
[0] = pWorldList
->m_pWorlds
[0].m_worldId
;
2284 numWorldsSorted
= 1;
2289 return numWorldsSorted
;
2292 void CCryPSNMatchMaking::ProcessExternalRoomData(const SCryPSNRoomDataExternal
& curRoom
, SCrySessionSearchResult
& result
, SCrySessionUserData userData
[MAX_MATCHMAKING_SESSION_USER_DATA
])
2294 SCryPSNSessionID
* pRoomInfo
= new SCryPSNSessionID
;
2296 pRoomInfo
->m_sessionInfo
.m_roomId
= curRoom
.m_roomId
;
2297 pRoomInfo
->m_sessionInfo
.m_worldId
= curRoom
.m_worldId
;
2298 pRoomInfo
->m_sessionInfo
.m_serverId
= curRoom
.m_serverId
;
2299 pRoomInfo
->m_sessionInfo
.m_gameType
= 0;
2300 memset(&pRoomInfo
->m_sessionId
, 0, sizeof(pRoomInfo
->m_sessionId
));
2301 pRoomInfo
->m_fromInvite
= false;
2303 result
.m_id
= pRoomInfo
;
2305 result
.m_numFilledSlots
= curRoom
.m_numPublicSlots
- curRoom
.m_numOpenPublicSlots
;
2306 result
.m_numFriends
= 0;
2309 result
.m_data
.m_ranked
= false;
2310 result
.m_data
.m_name
[0] = 0;
2311 result
.m_data
.m_data
= userData
;
2312 result
.m_data
.m_numData
= 0;
2314 result
.m_data
.m_numPublicSlots
= curRoom
.m_numPublicSlots
;
2315 result
.m_data
.m_numPrivateSlots
= curRoom
.m_numPrivateSlots
;
2317 for (uint32 k
= 0; k
< SCE_NP_ONLINEID_MAX_LENGTH
; k
++)
2319 result
.m_data
.m_name
[k
] = (char)curRoom
.m_owner
.handle
.data
[k
];
2321 result
.m_data
.m_name
[SCE_NP_ONLINEID_MAX_LENGTH
] = 0;
2323 for (int a
= 0; a
< curRoom
.m_numSearchableUIntAttributes
; a
++)
2325 for (int b
= 0; b
< m_registeredUserData
.num
; b
++)
2327 if (m_registeredUserData
.mapping
[b
].integerField
)
2329 if (curRoom
.m_searchableUIntAttributes
[a
].m_id
== m_registeredUserData
.mapping
[b
].fieldOffset
+ SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_1_ID
)
2331 result
.m_data
.m_data
[result
.m_data
.m_numData
].m_id
= m_registeredUserData
.data
[b
].m_id
;
2332 result
.m_data
.m_data
[result
.m_data
.m_numData
].m_type
= m_registeredUserData
.data
[b
].m_type
;
2333 result
.m_data
.m_data
[result
.m_data
.m_numData
].m_int32
= curRoom
.m_searchableUIntAttributes
[a
].m_num
;
2335 result
.m_data
.m_numData
++;
2342 char binAttrExternalData
[SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_MAX_SIZE
* SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_NUM
];
2344 for (int a
= 0; a
< curRoom
.m_numBinAttributes
; a
++)
2346 memcpy(&binAttrExternalData
[SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_MAX_SIZE
* a
], curRoom
.m_binAttributes
[a
].m_data
, curRoom
.m_binAttributes
[a
].m_dataSize
);
2349 for (int b
= 0; b
< m_registeredUserData
.num
; b
++)
2351 if (!m_registeredUserData
.mapping
[b
].integerField
)
2353 result
.m_data
.m_data
[result
.m_data
.m_numData
].m_id
= m_registeredUserData
.data
[b
].m_id
;
2354 result
.m_data
.m_data
[result
.m_data
.m_numData
].m_type
= m_registeredUserData
.data
[b
].m_type
;
2357 switch (result
.m_data
.m_data
[result
.m_data
.m_numData
].m_type
)
2360 case eCSUDT_Int64NoEndianSwap
:
2361 case eCSUDT_Float64
:
2362 dPtr
= (void*)&result
.m_data
.m_data
[result
.m_data
.m_numData
].m_int64
;
2363 memcpy(dPtr
, &binAttrExternalData
[m_registeredUserData
.mapping
[b
].fieldOffset
], sizeof(result
.m_data
.m_data
[result
.m_data
.m_numData
].m_int64
));
2366 case eCSUDT_Float32
:
2367 dPtr
= (void*)&result
.m_data
.m_data
[result
.m_data
.m_numData
].m_int32
;
2368 memcpy(dPtr
, &binAttrExternalData
[m_registeredUserData
.mapping
[b
].fieldOffset
], sizeof(result
.m_data
.m_data
[result
.m_data
.m_numData
].m_int32
));
2371 dPtr
= (void*)&result
.m_data
.m_data
[result
.m_data
.m_numData
].m_int16
;
2372 memcpy(dPtr
, &binAttrExternalData
[m_registeredUserData
.mapping
[b
].fieldOffset
], sizeof(result
.m_data
.m_data
[result
.m_data
.m_numData
].m_int16
));
2375 dPtr
= (void*)&result
.m_data
.m_data
[result
.m_data
.m_numData
].m_int8
;
2376 memcpy(dPtr
, &binAttrExternalData
[m_registeredUserData
.mapping
[b
].fieldOffset
], sizeof(result
.m_data
.m_data
[result
.m_data
.m_numData
].m_int8
));
2379 result
.m_data
.m_numData
++;
2384 void CCryPSNMatchMaking::BuildUserSessionParams(SSession
* pSession
, SCrySessionUserData
* pData
, uint32 numData
,
2385 SceNpMatching2BinAttr binAttrExternal
[SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_NUM
],
2386 SceNpMatching2IntAttr intAttrExternal
[SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_NUM
],
2387 char binAttrExternalData
[SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_MAX_SIZE
* SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_NUM
])
2389 // Setup our advertiser data
2390 for (int a
= 0; a
< SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_NUM
; a
++)
2392 binAttrExternal
[a
].id
= SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_1_ID
+ a
;
2393 binAttrExternal
[a
].ptr
= &binAttrExternalData
[SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_MAX_SIZE
* a
];
2394 binAttrExternal
[a
].size
= SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_MAX_SIZE
; // should really shrink these to avoid sending unused data
2397 for (int a
= 0; a
< SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_NUM
; a
++)
2399 intAttrExternal
[a
].id
= SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_1_ID
+ a
;
2402 // Build user data into psn format
2403 if (pSession
->IsUsed())
2405 for (uint32 i
= 0; i
< numData
; i
++)
2409 for (j
= 0; j
< m_registeredUserData
.num
; j
++)
2411 if (pData
[i
].m_id
== m_registeredUserData
.data
[j
].m_id
)
2413 if (pData
[i
].m_type
== m_registeredUserData
.data
[j
].m_type
)
2415 if (m_registeredUserData
.mapping
[j
].integerField
)
2417 intAttrExternal
[m_registeredUserData
.mapping
[j
].fieldOffset
].num
= pData
[i
].m_int32
;
2422 switch (pData
[i
].m_type
)
2425 case eCSUDT_Int64NoEndianSwap
:
2426 case eCSUDT_Float64
:
2427 dPtr
= (void*)&pData
[i
].m_int64
;
2428 memcpy(&binAttrExternalData
[m_registeredUserData
.mapping
[j
].fieldOffset
], dPtr
, sizeof(pData
[i
].m_int64
));
2431 case eCSUDT_Float32
:
2432 dPtr
= (void*)&pData
[i
].m_int32
;
2433 memcpy(&binAttrExternalData
[m_registeredUserData
.mapping
[j
].fieldOffset
], dPtr
, sizeof(pData
[i
].m_int32
));
2436 dPtr
= (void*)&pData
[i
].m_int16
;
2437 memcpy(&binAttrExternalData
[m_registeredUserData
.mapping
[j
].fieldOffset
], dPtr
, sizeof(pData
[i
].m_int16
));
2440 dPtr
= (void*)&pData
[i
].m_int8
;
2441 memcpy(&binAttrExternalData
[m_registeredUserData
.mapping
[j
].fieldOffset
], dPtr
, sizeof(pData
[i
].m_int8
));
2452 // SESSION CREATE -----------------------------------------------------------------------------------------
2454 ECryLobbyError
CCryPSNMatchMaking::SessionCreate(uint32
* users
, int numUsers
, uint32 flags
, SCrySessionData
* data
, CryLobbyTaskID
* taskID
, CryMatchmakingSessionCreateCallback cb
, void* cbArg
)
2458 CryLobbySessionHandle h
;
2459 ECryLobbyError error
= CreateSessionHandle(&h
, true, users
, numUsers
, flags
);
2461 if (error
== eCLE_Success
)
2463 CryMatchMakingTaskID mmTaskID
;
2465 error
= StartTask(eT_SessionCreate
, false, users
[0], &mmTaskID
, taskID
, h
, (void*)cb
, cbArg
);
2467 if (error
== eCLE_Success
)
2469 SSession
* pSession
= &m_sessions
[h
];
2471 pSession
->m_flags
= SCE_NP_MATCHING2_ROOM_FLAG_ATTR_OWNER_AUTO_GRANT
; // Auto migrate
2473 if ((flags
& CRYSESSION_CREATE_FLAG_SEARCHABLE
) == 0)
2475 pSession
->m_flags
|= SCE_NP_MATCHING2_ROOM_FLAG_ATTR_HIDDEN
;
2480 pSession
->m_flags
|= 0; // TODO.. implement ranked rooms
2481 pSession
->m_gameType
= 0;
2485 pSession
->m_gameType
= 0;
2488 pSession
->m_gameMode
= 0;
2489 pSession
->m_numPublicSlots
= data
->m_numPublicSlots
;
2490 pSession
->m_numPrivateSlots
= data
->m_numPrivateSlots
;
2492 NetLog("[Lobby] Created local connection " PRFORMAT_SH
" " PRFORMAT_UID
, PRARG_SH(h
), PRARG_UID(pSession
->localConnection
.uid
));
2494 for (uint32 i
= 0; i
< numUsers
; i
++)
2496 pSession
->localConnection
.privateSlot
[i
] = TRUE
;
2499 error
= CreateTaskParam(mmTaskID
, PSN_MATCHMAKING_CREATE_PARAMS_SLOT
, data
, 1, sizeof(SCrySessionData
));
2501 if (error
== eCLE_Success
)
2503 error
= CreateTaskParam(mmTaskID
, PSN_MATCHMAKING_CREATE_DATA_SLOT
, data
->m_data
, data
->m_numData
, data
->m_numData
* sizeof(data
->m_data
[0]));
2505 if (error
== eCLE_Success
)
2507 error
= CreateTaskParam(mmTaskID
, PSN_MATCHMAKING_PSNSUPPORT_CREATE_REQUEST_SLOT
, NULL
, 1, sizeof(SCreateParamData
));
2509 if (error
== eCLE_Success
)
2511 // This next alloc is a doozy - 165KB-ish
2512 error
= CreateTaskParam(mmTaskID
, PSN_MATCHMAKING_WEBAPI_CREATE_SLOT
, NULL
, 1, sizeof(SCryPSNOrbisWebApiCreateSessionInput
));
2513 if (error
== eCLE_Success
)
2515 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
2517 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning
, this, mmTaskID
);
2523 if (error
!= eCLE_Success
)
2526 FreeSessionHandle(h
);
2531 FreeSessionHandle(h
);
2535 NetLog("[Lobby] Start SessionCreate error %d", error
);
2540 void CCryPSNMatchMaking::TickSessionCreate(CryMatchMakingTaskID mmTaskID
)
2542 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
2543 if (m_pPSNSupport
->HasTransitioningReachedState(ePSNOS_Matchmaking_Available
))
2545 STask
* pTask
= &m_task
[mmTaskID
];
2547 //-- get the world list
2548 StartSubTask(eST_WaitingForCreateRoomWorldInfo
, mmTaskID
);
2550 SceNpMatching2GetWorldInfoListRequest reqParam
;
2551 memset(&reqParam
, 0, sizeof(reqParam
));
2552 reqParam
.serverId
= m_pPSNSupport
->GetServerInfo()->server
.serverId
;
2554 int ret
= sceNpMatching2GetWorldInfoList(m_pPSNSupport
->GetMatchmakingContextId(), &reqParam
, NULL
, &pTask
->m_reqId
);
2557 //-- Waiting for callback
2561 NetLog("sceNpMatching2GetWorldInfoList : error %08X", ret
);
2562 if (!m_pPSNSupport
->HandlePSNError(ret
))
2564 UpdateTaskError(mmTaskID
, eCLE_WorldNotDefined
);
2570 bool CCryPSNMatchMaking::EventRequestResponse_GetWorldInfoListForCreate(CCryPSNMatchMaking
* _this
, STask
* pTask
, CryMatchMakingTaskID taskId
, SCryPSNSupportCallbackEventData
& data
)
2572 assert(pTask
->subTask
== eST_WaitingForCreateRoomWorldInfo
);
2573 assert(data
.m_requestEvent
.m_event
== REQUEST_EVENT_GET_WORLD_INFO_LIST
);
2574 assert(data
.m_requestEvent
.m_dataSize
== sizeof(SCryPSNGetWorldInfoListResponse
));
2576 if ((data
.m_requestEvent
.m_error
== 0) &&
2577 (data
.m_requestEvent
.m_dataHdl
!= TMemInvalidHdl
) &&
2578 (data
.m_requestEvent
.m_dataSize
== sizeof(SCryPSNGetWorldInfoListResponse
)))
2580 SCreateParamData
* pCreateParams
= (SCreateParamData
*)_this
->m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_CREATE_REQUEST_SLOT
]);
2583 memset(pCreateParams
, 0, sizeof(SCreateParamData
));
2585 const SCryPSNGetWorldInfoListResponse
* pWorldList
= (SCryPSNGetWorldInfoListResponse
*)_this
->m_lobby
->MemGetPtr(data
.m_requestEvent
.m_dataHdl
);
2587 uint32 listSize
= SortWorlds(pWorldList
, &pCreateParams
->m_createRequest
.worldId
, 1, false);
2588 if ((listSize
> 0) && (pCreateParams
->m_createRequest
.worldId
!= INVALID_PSN_WORLD_ID
))
2590 _this
->StartSubTask(eST_SessionCreateRequest
, taskId
);
2594 _this
->UpdateTaskError(taskId
, eCLE_WorldNotDefined
);
2599 _this
->UpdateTaskError(taskId
, eCLE_OutOfMemory
);
2610 // At present there are only 8 possible searchable integer values (so we need to be careful with which attributes use them.
2611 // For now I have chucked all the data into the 2 binary attributes (256 bytes each). If I run out, i`ll panic later.
2612 void CCryPSNMatchMaking::TickSessionCreateRequest(CryMatchMakingTaskID mmTaskID
)
2614 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
2615 if (m_pPSNSupport
->HasTransitioningReachedState(ePSNOS_Matchmaking_Available
))
2617 STask
* pTask
= &m_task
[mmTaskID
];
2619 if (pTask
->params
[PSN_MATCHMAKING_CREATE_PARAMS_SLOT
] != TMemInvalidHdl
)
2621 if (pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_CREATE_REQUEST_SLOT
] != TMemInvalidHdl
)
2623 SCrySessionData
* pData
= (SCrySessionData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_CREATE_PARAMS_SLOT
]);
2624 if (pTask
->params
[PSN_MATCHMAKING_CREATE_DATA_SLOT
] != TMemInvalidHdl
)
2626 pData
->m_data
= (SCrySessionUserData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_CREATE_DATA_SLOT
]);
2630 pData
->m_data
= NULL
;
2633 SCreateParamData
* pCreateParams
= (SCreateParamData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_CREATE_REQUEST_SLOT
]);
2634 SSession
* pSession
= &m_sessions
[pTask
->session
];
2636 BuildUserSessionParams(pSession
, pData
->m_data
, pData
->m_numData
, pCreateParams
->m_binAttrExternal
, pCreateParams
->m_intAttrExternal
, pCreateParams
->m_binAttrExternalData
);
2638 // Internal data defaults
2639 for (int32 index
= 0; index
< SCE_NP_MATCHING2_ROOM_BIN_ATTR_INTERNAL_NUM
; ++index
)
2641 pCreateParams
->m_binAttrInternal
[index
].id
= SCE_NP_MATCHING2_ROOM_BIN_ATTR_INTERNAL_1_ID
+ index
;
2642 pCreateParams
->m_binAttrInternal
[index
].ptr
= &pCreateParams
->m_binAttrInternalData
[SCE_NP_MATCHING2_ROOM_BIN_ATTR_INTERNAL_MAX_SIZE
* index
];
2643 pCreateParams
->m_binAttrInternal
[index
].size
= SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_MAX_SIZE
; // should really shrink these to avoid sending unused data
2646 // Build internal data
2647 const int numInternalData
= 1;
2648 uint16 sessionCreateGameFlags
= (pSession
->createFlags
& CRYSESSION_CREATE_FLAG_GAME_MASK
) >> CRYSESSION_CREATE_FLAG_GAME_FLAGS_SHIFT
;
2649 memcpy((void*)pCreateParams
->m_binAttrInternal
[0].ptr
, &sessionCreateGameFlags
, sizeof(sessionCreateGameFlags
));
2650 pCreateParams
->m_binAttrInternal
[0].size
= sizeof(sessionCreateGameFlags
);
2652 SceNpMatching2SignalingOptParam sigParams
;
2653 sigParams
.type
= SCE_NP_MATCHING2_SIGNALING_TYPE_MESH
;
2655 sigParams
.hubMemberId
= 0;
2657 pCreateParams
->m_createRequest
.maxSlot
= pSession
->m_numPrivateSlots
+ pSession
->m_numPublicSlots
;
2658 pCreateParams
->m_createRequest
.flagAttr
= pSession
->m_flags
;
2659 pCreateParams
->m_createRequest
.roomPassword
= NULL
;
2660 pCreateParams
->m_createRequest
.groupConfig
= NULL
;
2661 pCreateParams
->m_createRequest
.groupConfigNum
= 0;
2662 pCreateParams
->m_createRequest
.passwordSlotMask
= NULL
;
2663 pCreateParams
->m_createRequest
.allowedUser
= NULL
;
2664 pCreateParams
->m_createRequest
.allowedUserNum
= 0;
2665 pCreateParams
->m_createRequest
.blockedUser
= NULL
;
2666 pCreateParams
->m_createRequest
.blockedUserNum
= 0;
2667 pCreateParams
->m_createRequest
.sigOptParam
= &sigParams
;
2668 pCreateParams
->m_createRequest
.roomBinAttrInternal
= pCreateParams
->m_binAttrInternal
;
2669 pCreateParams
->m_createRequest
.roomBinAttrInternalNum
= numInternalData
;
2670 pCreateParams
->m_createRequest
.roomBinAttrExternal
= pCreateParams
->m_binAttrExternal
;
2671 pCreateParams
->m_createRequest
.roomBinAttrExternalNum
= SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_NUM
;
2672 pCreateParams
->m_createRequest
.roomSearchableBinAttrExternal
= NULL
;
2673 pCreateParams
->m_createRequest
.roomSearchableBinAttrExternalNum
= 0;
2674 pCreateParams
->m_createRequest
.roomSearchableIntAttrExternal
= pCreateParams
->m_intAttrExternal
;
2675 pCreateParams
->m_createRequest
.roomSearchableIntAttrExternalNum
= SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_NUM
;
2676 pCreateParams
->m_createRequest
.joinRoomGroupLabel
= NULL
;
2677 pCreateParams
->m_createRequest
.roomMemberBinAttrInternal
= NULL
;
2678 pCreateParams
->m_createRequest
.roomMemberBinAttrInternalNum
= 0;
2679 pCreateParams
->m_createRequest
.teamId
= 0;
2681 StartSubTask(eST_WaitingForCreateRoomRequestCallback
, mmTaskID
);
2683 int ret
= sceNpMatching2CreateJoinRoom(m_pPSNSupport
->GetMatchmakingContextId(), &pCreateParams
->m_createRequest
, NULL
, &pTask
->m_reqId
);
2686 //-- waiting for callback
2690 NetLog("sceNpMatching2CreateJoinRoom : error %08X", ret
);
2691 //-- triggering a PSN error will cause an error event into SupportCallback() and set a task error if it needs to clean up.
2692 //-- otherwise, we have to update the task error ourself.
2693 if (!m_pPSNSupport
->HandlePSNError(ret
))
2695 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
2701 UpdateTaskError(mmTaskID
, eCLE_OutOfMemory
);
2706 UpdateTaskError(mmTaskID
, eCLE_OutOfMemory
);
2711 bool CCryPSNMatchMaking::EventRequestResponse_CreateRoom(CCryPSNMatchMaking
* _this
, STask
* pTask
, CryMatchMakingTaskID taskId
, SCryPSNSupportCallbackEventData
& data
)
2714 assert(pTask
->subTask
== eST_WaitingForCreateRoomRequestCallback
);
2715 assert(data
.m_requestEvent
.m_event
== REQUEST_EVENT_CREATE_JOIN_ROOM
);
2716 assert(data
.m_requestEvent
.m_dataHdl
!= TMemInvalidHdl
);
2717 assert(data
.m_requestEvent
.m_dataSize
== sizeof(SCryPSNCreateJoinRoomResponse
));
2719 if ((data
.m_requestEvent
.m_error
== 0) &&
2720 (data
.m_requestEvent
.m_dataHdl
!= TMemInvalidHdl
) &&
2721 (data
.m_requestEvent
.m_dataSize
== sizeof(SCryPSNCreateJoinRoomResponse
)))
2723 const SCryPSNCreateJoinRoomResponse
* pCreateResponse
= (SCryPSNCreateJoinRoomResponse
*)_this
->m_pPSNSupport
->GetLobby()->MemGetPtr(data
.m_requestEvent
.m_dataHdl
);
2725 if (pTask
->session
!= CryLobbyInvalidSessionHandle
)
2727 SSession
* pSession
= &_this
->m_sessions
[pTask
->session
];
2728 if (pSession
->IsUsed())
2730 pSession
->m_roomId
= pCreateResponse
->m_roomInfo
.m_roomId
;
2731 pSession
->m_worldId
= pCreateResponse
->m_roomInfo
.m_worldId
;
2732 pSession
->m_serverId
= pCreateResponse
->m_roomInfo
.m_serverId
;
2734 if (!pTask
->canceled
)
2736 _this
->AddInitialRoomMembers(pTask
->session
, pCreateResponse
->m_roomMembers
);
2737 _this
->StartSubTask(eST_WaitingForCreateRoomSignalingCallback
, taskId
);
2741 _this
->UpdateTaskError(taskId
, eCLE_IllegalSessionJoin
);
2746 _this
->UpdateTaskError(taskId
, eCLE_InternalError
);
2751 _this
->UpdateTaskError(taskId
, eCLE_InternalError
);
2762 void CCryPSNMatchMaking::TickSessionCreateSignaling(CryMatchMakingTaskID mmTaskID
)
2764 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
2765 if (m_pPSNSupport
->HasTransitioningReachedState(ePSNOS_Matchmaking_Available
))
2767 STask
* pTask
= &m_task
[mmTaskID
];
2769 UpdateSignaling(mmTaskID
);
2771 switch (CheckSignaling(mmTaskID
))
2775 //-- This is bad, means there is no room owner!
2776 UpdateTaskError(mmTaskID
, eCLE_InvalidParam
);
2782 assert(pTask
->subTask
== eST_WaitingForCreateRoomSignalingCallback
);
2784 if (pTask
->session
!= CryLobbyInvalidSessionHandle
)
2786 SSession
* pSession
= &m_sessions
[pTask
->session
];
2787 if (pSession
->IsUsed())
2789 if (!pTask
->canceled
)
2791 if (pSession
->createFlags
& CRYSESSION_CREATE_FLAG_INVITABLE
)
2793 SCrySessionData
* pSessionData
= (SCrySessionData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_CREATE_PARAMS_SLOT
]);
2794 SCreateParamData
* pCreateParams
= (SCreateParamData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_CREATE_REQUEST_SLOT
]);
2795 SCryPSNOrbisWebApiCreateSessionInput
* pWebApiCreateParams
= (SCryPSNOrbisWebApiCreateSessionInput
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_WEBAPI_CREATE_SLOT
]);
2796 if (pSessionData
&& pCreateParams
&& pWebApiCreateParams
)
2798 StartSubTask(eST_WaitingForCreateRoomWebApiCallback
, mmTaskID
);
2800 memset(pWebApiCreateParams
, 0, sizeof(SCryPSNOrbisWebApiCreateSessionInput
));
2802 // Some of the SCryLobbySessionAdvertisement we can fill in now.
2803 SCryLobbySessionAdvertisement
& advertisement
= pWebApiCreateParams
->advertisement
;
2805 advertisement
.m_numSlots
= pSessionData
->m_numPublicSlots
+ pSessionData
->m_numPrivateSlots
;
2806 advertisement
.m_bIsPrivate
= false;
2807 advertisement
.m_bIsEditableByAll
= true;
2808 advertisement
.m_pData
= pWebApiCreateParams
->data
;
2810 if (pTask
->session
!= CryLobbyInvalidSessionHandle
)
2812 // default session advertisement data should be set to the matching2 room info if available
2813 SSession
* pSession
= &m_sessions
[pTask
->session
];
2814 SSynchronisedSessionID
* pSessionInfo
= (SSynchronisedSessionID
*)advertisement
.m_pData
;
2816 pSessionInfo
->m_serverId
= pSession
->m_serverId
;
2817 pSessionInfo
->m_worldId
= pSession
->m_worldId
;
2818 pSessionInfo
->m_roomId
= pSession
->m_roomId
;
2819 pSessionInfo
->m_gameType
= pSession
->m_gameType
;
2820 advertisement
.m_sizeofData
= sizeof(SSynchronisedSessionID
);
2824 // otherwise just set the session advertisement data to an empty chunk of maximum size
2825 advertisement
.m_sizeofData
= CRY_WEBAPI_CREATESESSION_LINKDATA_MAX_SIZE
;
2828 // The rest needs filling in and/or modifying via configuration callback to the game.
2829 SConfigurationParams neededInfo
= {
2830 CLCC_PSN_CREATE_SESSION_ADVERTISEMENT
, { NULL
}
2832 neededInfo
.m_pData
= (void*)&pWebApiCreateParams
->advertisement
;
2833 m_lobby
->GetConfigurationInformation(&neededInfo
, 1);
2835 // And now we should have a completed SCryLobbySessionAdvertisement structure available to us. We'll be using this in CCryPSNOrbisWebApiThread::CreateSession later on.
2836 pCreateParams
->m_createJobId
= m_pPSNSupport
->GetWebApiInterface().AddJob(CCryPSNOrbisWebApiThread::CreateSession
, pTask
->params
[PSN_MATCHMAKING_WEBAPI_CREATE_SLOT
]);
2837 if (pCreateParams
->m_createJobId
== INVALID_WEBAPI_JOB_ID
)
2840 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
2845 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
2850 // Session is not invitable, so we don't need the session Id.
2851 UpdateTaskError(mmTaskID
, eCLE_Success
);
2852 StopTaskRunning(mmTaskID
);
2858 UpdateTaskError(mmTaskID
, eCLE_IllegalSessionJoin
);
2863 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
2868 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
2875 assert(pTask
->subTask
== eST_WaitingForCreateRoomSignalingCallback
);
2877 UpdateTaskError(mmTaskID
, eCLE_ConnectionFailed
);
2884 void CCryPSNMatchMaking::EventWebApiCreateSession(CryMatchMakingTaskID mmTaskID
, SCryPSNSupportCallbackEventData
& data
)
2886 STask
* pTask
= &m_task
[mmTaskID
];
2888 if (pTask
->session
!= CryLobbyInvalidSessionHandle
)
2890 SSession
* pSession
= &m_sessions
[pTask
->session
];
2892 memset(&pSession
->m_sessionId
, 0, sizeof(SceNpSessionId
));
2894 if (data
.m_webApiEvent
.m_error
== PSN_OK
)
2896 if (data
.m_webApiEvent
.m_pResponseBody
)
2898 if (data
.m_webApiEvent
.m_pResponseBody
->eType
== SCryPSNWebApiResponseBody::E_JSON
)
2900 // parse json to get session ID
2901 // CCryPSNWebApiJobController::PrintResponseJSONTree(data.m_webApiEvent.m_pResponseBody);
2902 const sce::Json::Value
& val
= data
.m_webApiEvent
.m_pResponseBody
->jsonTreeRoot
["sessionId"];
2903 if (val
.getType() == sce::Json::kValueTypeString
)
2905 strncpy((char*)&pSession
->m_sessionId
, val
.toString().c_str(), sizeof(pSession
->m_sessionId
.data
));
2906 pSession
->m_sessionId
.term
= 0;
2908 // Completed successfully
2909 UpdateTaskError(mmTaskID
, eCLE_Success
);
2910 StopTaskRunning(mmTaskID
);
2918 // something went wrong
2919 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
2920 StopTaskRunning(mmTaskID
);
2923 // otherwise something went wrong!
2924 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
2925 StopTaskRunning(mmTaskID
);
2928 void CCryPSNMatchMaking::EndSessionCreate(CryMatchMakingTaskID mmTaskID
)
2930 STask
* pTask
= &m_task
[mmTaskID
];
2931 SSession
* pSession
= &m_sessions
[pTask
->session
];
2933 if (pTask
->error
== eCLE_Success
)
2935 SCryMatchMakingConnectionUID matchingUID
;
2936 matchingUID
.m_uid
= pSession
->m_myMemberId
;
2937 matchingUID
.m_sid
= pSession
->m_roomId
;
2939 pSession
->localConnection
.uid
= matchingUID
;
2940 pSession
->localConnection
.pingToServer
= CRYLOBBY_INVALID_PING
;
2941 pSession
->localConnection
.used
= true;
2942 pSession
->hostConnectionID
= CryMatchMakingInvalidConnectionID
;
2946 UpdateTaskError(mmTaskID
, eCLE_OutOfMemory
);
2949 ((CryMatchmakingSessionCreateCallback
)pTask
->cb
)(pTask
->lTaskID
, pTask
->error
, CreateGameSessionHandle(pTask
->session
, pSession
->localConnection
.uid
), pTask
->cbArg
);
2951 if (pTask
->error
== eCLE_Success
)
2953 InitialUserDataEvent(pTask
->session
);
2957 // END SESSON CREATE ---------------------------------------------------------------------------------------
2959 ECryLobbyError
CCryPSNMatchMaking::SessionMigrate(CrySessionHandle gh
, uint32
* pUsers
, int numUsers
, uint32 flags
, SCrySessionData
* pData
, CryLobbyTaskID
* pTaskID
, CryMatchmakingSessionCreateCallback pCB
, void* pCBArg
)
2961 ECryLobbyError error
= eCLE_Success
;
2965 // Because we simply want to re-use the session that is already available, we don't need to do much here
2967 CryLobbySessionHandle h
= GetSessionHandleFromGameSessionHandle(gh
);
2969 if ((h
< MAX_MATCHMAKING_SESSIONS
) && (m_sessions
[h
].localFlags
& CRYSESSION_LOCAL_FLAG_USED
))
2971 SSession
* pSession
= &m_sessions
[h
];
2972 CryMatchMakingTaskID mmTaskID
;
2974 error
= StartTask(eT_SessionMigrate
, false, pSession
->localConnection
.users
[0], &mmTaskID
, pTaskID
, h
, (void*)pCB
, pCBArg
);
2976 if (error
== eCLE_Success
)
2978 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning
, this, mmTaskID
);
2983 error
= eCLE_InvalidSession
;
2986 NetLog("[Lobby] Start SessionMigrate error %d", error
);
2991 void CCryPSNMatchMaking::TickSessionMigrate(CryMatchMakingTaskID mmTaskID
)
2993 UpdateTaskError(mmTaskID
, eCLE_Success
);
2994 StopTaskRunning(mmTaskID
);
2997 ECryLobbyError
CCryPSNMatchMaking::SessionUpdate(CrySessionHandle gh
, SCrySessionUserData
* pData
, uint32 numData
, CryLobbyTaskID
* pTaskID
, CryMatchmakingCallback pCB
, void* pCBArg
)
2999 ECryLobbyError error
= eCLE_Success
;
3003 CryLobbySessionHandle h
= GetSessionHandleFromGameSessionHandle(gh
);
3005 if ((h
< MAX_MATCHMAKING_SESSIONS
) && (m_sessions
[h
].localFlags
& CRYSESSION_LOCAL_FLAG_USED
))
3007 SSession
* session
= &m_sessions
[h
];
3009 if (session
->localFlags
& CRYSESSION_LOCAL_FLAG_HOST
)
3011 CryMatchMakingTaskID mmTaskID
;
3013 error
= StartTask(eT_SessionUpdate
, false, session
->localConnection
.users
[0], &mmTaskID
, pTaskID
, h
, (void*)pCB
, pCBArg
);
3015 if (error
== eCLE_Success
)
3017 STask
* task
= &m_task
[mmTaskID
];
3019 error
= CreateTaskParam(mmTaskID
, PSN_MATCHMAKING_UPDATE_DATA_SLOT
, pData
, numData
, numData
* sizeof(pData
[0]));
3021 if (error
== eCLE_Success
)
3023 error
= CreateTaskParam(mmTaskID
, PSN_MATCHMAKING_PSNSUPPORT_UPDATE_REQUEST_SLOT
, NULL
, 1, sizeof(SUpdateParamData
));
3024 if (error
== eCLE_Success
)
3026 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
3028 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning
, this, mmTaskID
);
3043 error
= eCLE_InvalidRequest
;
3048 error
= eCLE_InvalidSession
;
3051 NetLog("[Lobby] Start SessionUpdate error %d", error
);
3056 void CCryPSNMatchMaking::TickSessionUpdate(CryMatchMakingTaskID mmTaskID
)
3058 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
3059 if (m_pPSNSupport
->HasTransitioningReachedState(ePSNOS_Matchmaking_Available
))
3061 STask
* pTask
= &m_task
[mmTaskID
];
3063 if (pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_UPDATE_REQUEST_SLOT
] != TMemInvalidHdl
)
3065 SUpdateParamData
* pUpdateParams
= (SUpdateParamData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_UPDATE_REQUEST_SLOT
]);
3066 SCrySessionUserData
* pData
= (SCrySessionUserData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_UPDATE_DATA_SLOT
]);
3067 SSession
* pSession
= &m_sessions
[pTask
->session
];
3069 memset(pUpdateParams
, 0, sizeof(SUpdateParamData
));
3071 BuildUserSessionParams(pSession
, pData
, pTask
->numParams
[0], pUpdateParams
->m_binAttrExternal
, pUpdateParams
->m_intAttrExternal
, pUpdateParams
->m_binAttrExternalData
);
3073 pUpdateParams
->m_updateRequest
.roomId
= pSession
->m_roomId
;
3075 pUpdateParams
->m_updateRequest
.roomSearchableIntAttrExternal
= pUpdateParams
->m_intAttrExternal
;
3076 pUpdateParams
->m_updateRequest
.roomSearchableBinAttrExternal
= NULL
;
3077 pUpdateParams
->m_updateRequest
.roomBinAttrExternal
= pUpdateParams
->m_binAttrExternal
;
3079 pUpdateParams
->m_updateRequest
.roomSearchableBinAttrExternalNum
= 0;
3080 pUpdateParams
->m_updateRequest
.roomSearchableIntAttrExternalNum
= SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_NUM
;
3081 pUpdateParams
->m_updateRequest
.roomBinAttrExternalNum
= SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_NUM
;
3083 StartSubTask(eST_WaitingForUpdateRoomRequestCallback
, mmTaskID
);
3085 int ret
= sceNpMatching2SetRoomDataExternal(m_pPSNSupport
->GetMatchmakingContextId(), &pUpdateParams
->m_updateRequest
, NULL
, &pTask
->m_reqId
);
3088 //-- Waiting for callback
3092 NetLog("sceNpMatching2SetRoomDataExternal : error %08X", ret
);
3093 if (!m_pPSNSupport
->HandlePSNError(ret
))
3095 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
3101 UpdateTaskError(mmTaskID
, eCLE_OutOfMemory
);
3106 bool CCryPSNMatchMaking::EventRequestResponse_SetRoomDataExternal(CCryPSNMatchMaking
* _this
, STask
* pTask
, CryMatchMakingTaskID taskId
, SCryPSNSupportCallbackEventData
& data
)
3109 assert(pTask
->subTask
== eST_WaitingForUpdateRoomRequestCallback
);
3110 assert(data
.m_requestEvent
.m_event
== REQUEST_EVENT_SET_ROOM_DATA_EXTERNAL
);
3111 assert(data
.m_requestEvent
.m_dataSize
== 0);
3113 if (data
.m_requestEvent
.m_error
== 0)
3115 _this
->UpdateTaskError(taskId
, eCLE_Success
);
3116 _this
->StopTaskRunning(taskId
);
3122 // return false to let the default error handler work
3127 // END SESSION UPDATE ------------------------------------------------------------------------
3129 ECryLobbyError
CCryPSNMatchMaking::SessionUpdateSlots(CrySessionHandle gh
, uint32 numPublic
, uint32 numPrivate
, CryLobbyTaskID
* pTaskID
, CryMatchmakingCallback pCB
, void* pCBArg
)
3131 ECryLobbyError error
= eCLE_Success
;
3135 CryLobbySessionHandle h
= GetSessionHandleFromGameSessionHandle(gh
);
3137 if ((h
< MAX_MATCHMAKING_SESSIONS
) && (m_sessions
[h
].localFlags
& CRYSESSION_LOCAL_FLAG_USED
))
3139 CryMatchMakingTaskID tid
;
3141 error
= StartTask(eT_SessionUpdateSlots
, false, m_sessions
[h
].localConnection
.users
[0], &tid
, pTaskID
, h
, (void*)pCB
, pCBArg
);
3143 if (error
== eCLE_Success
)
3145 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning
, this, tid
);
3150 error
= eCLE_InvalidSession
;
3153 NetLog("[Lobby] Start SessionUpdateSlots return %d", error
);
3158 #if NETWORK_HOST_MIGRATION
3159 ECryLobbyError
CCryPSNMatchMaking::SendHostHintExternal(CryLobbySessionHandle h
)
3161 ECryLobbyError error
= eCLE_Success
;
3164 if (net_enable_psn_hinting
)
3166 if ((h
< MAX_MATCHMAKING_SESSIONS
) && (m_sessions
[h
].localFlags
& CRYSESSION_LOCAL_FLAG_USED
))
3168 SSession
* pSession
= &m_sessions
[h
];
3170 if (pSession
->localFlags
& CRYSESSION_LOCAL_FLAG_HOST
)
3172 CryMatchMakingTaskID mmTaskID
;
3174 bool taskRunning
= false;
3175 for (uint32 taskID
= 0; taskID
< MAX_MATCHMAKING_TASKS
; ++taskID
)
3177 STask
* pTask
= &m_task
[taskID
];
3179 if (pTask
->used
&& pTask
->running
&& (pTask
->startedTask
== eT_SessionSendHostHintExternal
) && (pTask
->session
== h
))
3181 #if NET_HOST_HINT_DEBUG
3182 NetLog("[Host Hints]: hints already in flight to PSN, will resend when done");
3183 #endif // #if NET_HOST_HINT_DEBUG
3184 pTask
->numParams
[PSN_MATCHMAKING_PSNSUPPORT_HOSTHINT_RESTART
] = eHHTB_REQUIRES_RESTART
;
3192 error
= StartTask(eT_SessionSendHostHintExternal
, false, pSession
->localConnection
.users
[0], &mmTaskID
, NULL
, h
, NULL
, NULL
);
3193 if (error
== eCLE_Success
)
3195 STask
* pTask
= &m_task
[mmTaskID
];
3196 pTask
->numParams
[PSN_MATCHMAKING_PSNSUPPORT_HOSTHINT_RESTART
] = eHHTB_NORMAL
;
3198 error
= CreateTaskParam(mmTaskID
, PSN_MATCHMAKING_PSNSUPPORT_HOSTHINT_REQUEST_SLOT
, NULL
, 1, sizeof(SHostHintParamData
));
3200 if (error
== eCLE_Success
)
3202 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
3204 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning
, this, mmTaskID
);
3209 error
= eCLE_InternalError
;
3215 error
= eCLE_InvalidRequest
;
3220 error
= eCLE_InvalidSession
;
3224 NetLog("[Host Hints] Start SendHostHintExternal error %d", error
);
3229 void CCryPSNMatchMaking::StartSessionSendHostHintExternal(CryMatchMakingTaskID mmTaskID
)
3231 STask
* pTask
= &m_task
[mmTaskID
];
3233 if (pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_HOSTHINT_REQUEST_SLOT
] != TMemInvalidHdl
)
3235 SHostHintParamData
* pHostHintParams
= (SHostHintParamData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_HOSTHINT_REQUEST_SLOT
]);
3236 memset(pHostHintParams
, 0, sizeof(SHostHintParamData
));
3237 SSession
* pSession
= &m_sessions
[pTask
->session
];
3239 for (uint32 index
= 0; index
< pSession
->newHostPriorityCount
; ++index
)
3241 pHostHintParams
->m_memberId
[index
] = ((CCryPSNMatchMaking::SSession::SRConnection
*)(pSession
->newHostPriority
[index
]))->memberId
;
3244 pHostHintParams
->m_reqParam
.roomId
= pSession
->m_roomId
;
3245 pHostHintParams
->m_reqParam
.ownerPrivilegeRank
= pHostHintParams
->m_memberId
;
3246 pHostHintParams
->m_reqParam
.ownerPrivilegeRankNum
= pSession
->newHostPriorityCount
;
3248 NetLog("[Host Hints]: PSN SendHostHintExternal " PRFORMAT_SH
" roomId 0x%llX Rank[0] %d RankNum %d",
3249 PRARG_SH(pTask
->session
), (uint64
)pHostHintParams
->m_reqParam
.roomId
, pHostHintParams
->m_reqParam
.ownerPrivilegeRank
[0], pHostHintParams
->m_reqParam
.ownerPrivilegeRankNum
);
3251 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
3255 UpdateTaskError(mmTaskID
, eCLE_OutOfMemory
);
3258 if (pTask
->error
!= eCLE_Success
)
3260 StopTaskRunning(mmTaskID
);
3264 void CCryPSNMatchMaking::TickSessionSendHostHintExternal(CryMatchMakingTaskID mmTaskID
)
3266 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
3267 if (m_pPSNSupport
->HasTransitioningReachedState(ePSNOS_Matchmaking_Available
))
3269 STask
* pTask
= &m_task
[mmTaskID
];
3271 if (pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_HOSTHINT_REQUEST_SLOT
] != TMemInvalidHdl
)
3273 SHostHintParamData
* pHostHintParams
= (SHostHintParamData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_HOSTHINT_REQUEST_SLOT
]);
3275 StartSubTask(eST_WaitingForNewHostHintCallback
, mmTaskID
);
3277 int ret
= sceNpMatching2SetRoomDataInternal(m_pPSNSupport
->GetMatchmakingContextId(), &pHostHintParams
->m_reqParam
, NULL
, &pTask
->m_reqId
);
3280 //-- waiting for callback
3284 NetLog("sceNpMatching2SetRoomDataInternal : error %08X", ret
);
3285 //-- triggering a PSN error will cause an error event into SupportCallback() and set a task error if it needs to clean up.
3286 //-- otherwise, we have to update the task error ourself.
3287 if (!m_pPSNSupport
->HandlePSNError(ret
))
3289 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
3295 UpdateTaskError(mmTaskID
, eCLE_OutOfMemory
);
3300 bool CCryPSNMatchMaking::EventRequestResponse_SetRoomDataInternal(CCryPSNMatchMaking
* _this
, STask
* pTask
, CryMatchMakingTaskID taskId
, SCryPSNSupportCallbackEventData
& data
)
3303 assert(pTask
->subTask
== eST_WaitingForNewHostHintCallback
);
3304 assert(data
.m_requestEvent
.m_event
== REQUEST_EVENT_SET_ROOM_DATA_INTERNAL
);
3305 assert(data
.m_requestEvent
.m_dataSize
== 0);
3307 if (data
.m_requestEvent
.m_error
== 0)
3309 _this
->UpdateTaskError(taskId
, eCLE_Success
);
3310 _this
->StopTaskRunning(taskId
);
3316 // return false to let the default error handler work
3321 void CCryPSNMatchMaking::EndSessionSendHostHintExternal(CryMatchMakingTaskID mmTaskID
)
3323 STask
* pTask
= &m_task
[mmTaskID
];
3324 if (pTask
->numParams
[PSN_MATCHMAKING_PSNSUPPORT_HOSTHINT_RESTART
] == eHHTB_REQUIRES_RESTART
)
3326 #if NET_HOST_HINT_DEBUG
3327 NetLog("[Host Hints]: hints changed whilst informing PSN, resending hints to PSN");
3328 #endif // #if NET_HOST_HINT_DEBUG
3329 SendHostHintExternal(pTask
->session
);
3334 ECryLobbyError
CCryPSNMatchMaking::SessionQuery(CrySessionHandle gh
, CryLobbyTaskID
* pTaskID
, CryMatchmakingSessionQueryCallback pCB
, void* pCBArg
)
3336 ECryLobbyError error
= eCLE_Success
;
3340 CryLobbySessionHandle h
= GetSessionHandleFromGameSessionHandle(gh
);
3342 if ((h
< MAX_MATCHMAKING_SESSIONS
) && m_sessions
[h
].IsUsed())
3344 SSession
* pSession
= &m_sessions
[h
];
3345 CryMatchMakingTaskID mmTaskID
;
3347 error
= StartTask(eT_SessionQuery
, false, pSession
->localConnection
.users
[0], &mmTaskID
, pTaskID
, h
, (void*)pCB
, pCBArg
);
3348 if (error
== eCLE_Success
)
3350 error
= CreateTaskParam(mmTaskID
, PSN_MATCHMAKING_PSNSUPPORT_QUERY_REQUEST_SLOT
, NULL
, 1, sizeof(SQueryParamData
));
3351 if (error
== eCLE_Success
)
3353 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
3355 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning
, this, mmTaskID
);
3365 error
= eCLE_InvalidSession
;
3368 NetLog("[Lobby] Session Query Error %d", error
);
3373 void CCryPSNMatchMaking::TickSessionQuery(CryMatchMakingTaskID mmTaskID
)
3375 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
3376 if (m_pPSNSupport
->HasTransitioningReachedState(ePSNOS_Matchmaking_Available
))
3378 STask
* pTask
= &m_task
[mmTaskID
];
3380 if (pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_QUERY_REQUEST_SLOT
] != TMemInvalidHdl
)
3382 SQueryParamData
* pQueryParams
= (SQueryParamData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_QUERY_REQUEST_SLOT
]);
3384 memset(pQueryParams
, 0, sizeof(SQueryParamData
));
3386 SSession
* pSession
= &m_sessions
[pTask
->session
];
3388 pQueryParams
->m_queryRequest
.roomId
= pQueryParams
->m_roomIds
;
3389 pQueryParams
->m_queryRequest
.attrId
= pQueryParams
->m_attrTable
;
3390 pQueryParams
->m_roomIds
[0] = pSession
->m_roomId
;
3391 pQueryParams
->m_queryRequest
.roomIdNum
= 1;
3392 pQueryParams
->m_attrTable
[0] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_1_ID
;
3393 pQueryParams
->m_attrTable
[1] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_2_ID
;
3394 pQueryParams
->m_attrTable
[2] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_3_ID
;
3395 pQueryParams
->m_attrTable
[3] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_4_ID
;
3396 pQueryParams
->m_attrTable
[4] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_5_ID
;
3397 pQueryParams
->m_attrTable
[5] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_6_ID
;
3398 pQueryParams
->m_attrTable
[6] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_7_ID
;
3399 pQueryParams
->m_attrTable
[7] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_8_ID
;
3400 pQueryParams
->m_attrTable
[8] = SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_1_ID
;
3401 pQueryParams
->m_attrTable
[9] = SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_2_ID
;
3402 pQueryParams
->m_queryRequest
.attrIdNum
= 10;
3404 StartSubTask(eST_WaitingForQueryRoomRequestCallback
, mmTaskID
);
3406 int ret
= sceNpMatching2GetRoomDataExternalList(m_pPSNSupport
->GetMatchmakingContextId(), &pQueryParams
->m_queryRequest
, NULL
, &pTask
->m_reqId
);
3409 //-- waiting for callback
3413 NetLog("sceNpMatching2GetRoomDataExternalList : error %08X", ret
);
3414 //-- triggering a PSN error will cause an error event into SupportCallback() and set a task error if it needs to clean up.
3415 //-- otherwise, we have to update the task error ourself.
3416 if (!m_pPSNSupport
->HandlePSNError(ret
))
3418 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
3424 UpdateTaskError(mmTaskID
, eCLE_OutOfMemory
);
3429 bool CCryPSNMatchMaking::EventRequestResponse_GetRoomDataExternalList(CCryPSNMatchMaking
* _this
, STask
* pTask
, CryMatchMakingTaskID taskId
, SCryPSNSupportCallbackEventData
& data
)
3432 assert(pTask
->subTask
== eST_WaitingForQueryRoomRequestCallback
);
3433 assert(data
.m_requestEvent
.m_event
== REQUEST_EVENT_GET_ROOM_DATA_EXTERNAL_LIST
);
3434 assert(data
.m_requestEvent
.m_dataHdl
!= TMemInvalidHdl
);
3435 assert(data
.m_requestEvent
.m_dataSize
== sizeof(SCryPSNSearchRoomResponse
));
3437 if ((data
.m_requestEvent
.m_error
== 0) &&
3438 (data
.m_requestEvent
.m_dataHdl
!= TMemInvalidHdl
) &&
3439 (data
.m_requestEvent
.m_dataSize
== sizeof(SCryPSNSearchRoomResponse
)))
3441 // take ownership of the memory returned by the callback so it is not automatically discarded on return
3442 pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_QUERY_RESPONSE_SLOT
] = data
.m_requestEvent
.m_dataHdl
;
3443 data
.m_requestEvent
.m_dataHdl
= TMemInvalidHdl
;
3444 data
.m_requestEvent
.m_returnFlags
|= SCryPSNSupportCallbackEventData::SRequestEvent::REQUEST_EVENT_OWNS_MEMORY
;
3446 _this
->UpdateTaskError(taskId
, eCLE_Success
);
3447 _this
->StopTaskRunning(taskId
);
3453 // return false to let the default error handler work
3458 void CCryPSNMatchMaking::EndSessionQuery(CryMatchMakingTaskID mmTaskID
)
3460 STask
* pTask
= &m_task
[mmTaskID
];
3461 SCryPSNSearchRoomResponse
* pResponse
= NULL
;
3463 if (pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_QUERY_RESPONSE_SLOT
] != TMemInvalidHdl
)
3465 pResponse
= (SCryPSNSearchRoomResponse
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_QUERY_RESPONSE_SLOT
]);
3468 if (pTask
->error
== eCLE_Success
)
3472 for (uint16 i
= 0; i
< pResponse
->m_numRooms
; i
++)
3474 SCrySessionSearchResult result
;
3475 SCrySessionUserData userData
[MAX_MATCHMAKING_SESSION_USER_DATA
];
3477 ProcessExternalRoomData(pResponse
->m_pRooms
[i
], result
, userData
);
3479 ((CryMatchmakingSessionQueryCallback
)pTask
->cb
)(pTask
->lTaskID
, eCLE_SuccessContinue
, &result
, pTask
->cbArg
);
3484 UpdateTaskError(mmTaskID
, eCLE_OutOfMemory
);
3488 // free the memory allocated to the response
3491 pResponse
->Release(m_lobby
);
3494 ((CryMatchmakingSessionQueryCallback
)pTask
->cb
)(pTask
->lTaskID
, pTask
->error
, NULL
, pTask
->cbArg
);
3497 ECryLobbyError
CCryPSNMatchMaking::SessionGetUsers(CrySessionHandle gh
, CryLobbyTaskID
* pTaskID
, CryMatchmakingSessionGetUsersCallback pCB
, void* pCBArg
)
3499 ECryLobbyError error
= eCLE_Success
;
3503 CryLobbySessionHandle h
= GetSessionHandleFromGameSessionHandle(gh
);
3505 if ((h
< MAX_MATCHMAKING_SESSIONS
) && (m_sessions
[h
].localFlags
& CRYSESSION_LOCAL_FLAG_USED
))
3507 SSession
* session
= &m_sessions
[h
];
3508 CryMatchMakingTaskID mmTaskID
;
3510 error
= StartTask(eT_SessionGetUsers
, false, session
->localConnection
.users
[0], &mmTaskID
, pTaskID
, h
, (void*)pCB
, pCBArg
);
3512 if (error
== eCLE_Success
)
3514 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning
, this, mmTaskID
);
3519 error
= eCLE_InvalidSession
;
3522 if (error
!= eCLE_Success
)
3524 NetLog("[Lobby] Session Get Users Is Error %d", error
);
3530 void CCryPSNMatchMaking::GetRoomMemberData(CryLobbySessionHandle sessionHandle
, SCryUserInfoResult
& result
, SCryMatchMakingConnectionUID
& uid
)
3532 SSession::SRoomMember
* pRoomMember
= FindRoomMemberFromRoomMemberID(sessionHandle
, uid
.m_uid
);
3534 result
.m_conID
= uid
;
3535 result
.m_isDedicated
= false; // PSN does not support dedicated servers
3539 cry_strcpy(result
.m_userName
, pRoomMember
->m_npId
.handle
.data
);
3540 memcpy(result
.m_userData
, pRoomMember
->m_userData
, CRYLOBBY_USER_DATA_SIZE_IN_BYTES
);
3542 ((SCryPSNUserID
*)result
.m_userID
.get())->npId
= pRoomMember
->m_npId
;
3546 result
.m_userName
[0] = 0;
3550 void CCryPSNMatchMaking::TickSessionGetUsers(CryMatchMakingTaskID mmTaskID
)
3552 STask
* pTask
= &m_task
[mmTaskID
];
3554 SCryUserInfoResult temp
;
3555 temp
.m_userID
= new SCryPSNUserID
;
3559 // Glue in local user - arguably, this could all just iterate over the room members list (ho hum)
3560 GetRoomMemberData(pTask
->session
, temp
, m_sessions
[pTask
->session
].localConnection
.uid
);
3561 ((CryMatchmakingSessionGetUsersCallback
)pTask
->cb
)(pTask
->lTaskID
, pTask
->error
, &temp
, pTask
->cbArg
);
3563 for (a
= 0; a
< MAX_LOBBY_CONNECTIONS
; a
++)
3565 if (m_sessions
[pTask
->session
].remoteConnection
[a
].used
)
3567 GetRoomMemberData(pTask
->session
, temp
, m_sessions
[pTask
->session
].remoteConnection
[a
].uid
);
3568 ((CryMatchmakingSessionGetUsersCallback
)pTask
->cb
)(pTask
->lTaskID
, pTask
->error
, &temp
, pTask
->cbArg
);
3572 StopTaskRunning(mmTaskID
);
3575 ECryLobbyError
CCryPSNMatchMaking::SessionStart(CrySessionHandle gh
, CryLobbyTaskID
* taskID
, CryMatchmakingCallback cb
, void* cbArg
)
3577 ECryLobbyError error
= eCLE_Success
;
3581 CryLobbySessionHandle h
= GetSessionHandleFromGameSessionHandle(gh
);
3583 if ((h
< MAX_MATCHMAKING_SESSIONS
) && m_sessions
[h
].IsUsed())
3585 SSession
* pSession
= &m_sessions
[h
];
3586 CryMatchMakingTaskID mmTaskID
;
3588 error
= StartTask(eT_SessionStart
, false, pSession
->localConnection
.users
[0], &mmTaskID
, taskID
, h
, (void*)cb
, cbArg
);
3590 if (error
== eCLE_Success
)
3592 pSession
->localFlags
|= CRYSESSION_LOCAL_FLAG_STARTED
;
3593 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning
, this, mmTaskID
);
3598 error
= eCLE_InvalidSession
;
3601 NetLog("[Lobby] Start SessionStart error %d", error
);
3606 ECryLobbyError
CCryPSNMatchMaking::SessionEnd(CrySessionHandle gh
, CryLobbyTaskID
* taskID
, CryMatchmakingCallback cb
, void* cbArg
)
3608 ECryLobbyError error
= eCLE_Success
;
3612 CryLobbySessionHandle h
= GetSessionHandleFromGameSessionHandle(gh
);
3614 if ((h
< MAX_MATCHMAKING_SESSIONS
) && m_sessions
[h
].IsUsed())
3616 SSession
* pSession
= &m_sessions
[h
];
3617 CryMatchMakingTaskID mmTaskID
;
3619 error
= StartTask(eT_SessionEnd
, false, pSession
->localConnection
.users
[0], &mmTaskID
, taskID
, h
, (void*)cb
, cbArg
);
3621 if (error
== eCLE_Success
)
3623 pSession
->localFlags
&= ~CRYSESSION_LOCAL_FLAG_STARTED
;
3624 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning
, this, mmTaskID
);
3629 error
= eCLE_SuccessInvalidSession
;
3632 NetLog("[Lobby] Start SessionEnd error %d", error
);
3637 // SESSION DELETE ------------------------------------------------------------------------------------------
3639 ECryLobbyError
CCryPSNMatchMaking::SessionDelete(CrySessionHandle gh
, CryLobbyTaskID
* taskID
, CryMatchmakingCallback cb
, void* cbArg
)
3641 ECryLobbyError error
= eCLE_Success
;
3645 CryLobbySessionHandle h
= GetSessionHandleFromGameSessionHandle(gh
);
3647 if ((h
< MAX_MATCHMAKING_SESSIONS
) && m_sessions
[h
].IsUsed())
3649 SSession
* pSession
= &m_sessions
[h
];
3650 CryMatchMakingTaskID mmTaskID
;
3652 // Disconnect our local connection
3653 SessionDisconnectRemoteConnectionViaNub(h
, CryMatchMakingInvalidConnectionID
, eDS_Local
, CryMatchMakingInvalidConnectionID
, eDC_UserRequested
, "Session deleted");
3655 error
= StartTask(eT_SessionDelete
, false, pSession
->localConnection
.users
[0], &mmTaskID
, taskID
, h
, (void*)cb
, cbArg
);
3657 if (error
== eCLE_Success
)
3659 error
= CreateTaskParam(mmTaskID
, PSN_MATCHMAKING_PSNSUPPORT_LEAVE_REQUEST_SLOT
, NULL
, 1, sizeof(SLeaveParamData
));
3660 if (error
== eCLE_Success
)
3662 error
= CreateTaskParam(mmTaskID
, PSN_MATCHMAKING_WEBAPI_LEAVE_REQUEST_SLOT
, NULL
, 1, sizeof(SCryPSNOrbisWebApiLeaveSessionInput
));
3663 if (error
== eCLE_Success
)
3665 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
3667 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning
, this, mmTaskID
);
3669 #if NETWORK_HOST_MIGRATION
3670 // Since we're deleting this session, terminate any host migration
3671 if (pSession
->hostMigrationInfo
.m_state
!= eHMS_Idle
)
3673 m_hostMigration
.Terminate(&pSession
->hostMigrationInfo
);
3676 pSession
->createFlags
&= ~CRYSESSION_CREATE_FLAG_MIGRATABLE
;
3679 if (error
!= eCLE_Success
)
3687 error
= eCLE_SuccessInvalidSession
;
3690 NetLog("[Lobby] Start SessionDelete error %d", error
);
3695 void CCryPSNMatchMaking::StartSessionDelete(CryMatchMakingTaskID mmTaskID
)
3697 STask
* pTask
= &m_task
[mmTaskID
];
3698 SSession
* pSession
= &m_sessions
[pTask
->session
];
3700 #if NETWORK_HOST_MIGRATION
3701 // Since we're deleting this session, terminate any host migration
3702 if (pSession
->hostMigrationInfo
.m_state
!= eHMS_Idle
)
3704 m_hostMigration
.Terminate(&pSession
->hostMigrationInfo
);
3708 pSession
->createFlags
&= ~CRYSESSION_CREATE_FLAG_MIGRATABLE
;
3709 for (uint32 i
= 0; i
< MAX_LOBBY_CONNECTIONS
; i
++)
3711 SSession::SRConnection
* connection
= &pSession
->remoteConnection
[i
];
3713 if (connection
->used
)
3715 FreeRemoteConnection(pTask
->session
, i
);
3719 if (pTask
->error
!= eCLE_Success
)
3721 StopTaskRunning(mmTaskID
);
3725 void CCryPSNMatchMaking::TickSessionDelete(CryMatchMakingTaskID mmTaskID
)
3727 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
3728 if (m_pPSNSupport
->HasTransitioningReachedState(ePSNOS_Matchmaking_Available
))
3730 STask
* pTask
= &m_task
[mmTaskID
];
3732 if (pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_LEAVE_REQUEST_SLOT
] != TMemInvalidHdl
)
3734 SLeaveParamData
* pLeaveParams
= (SLeaveParamData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_LEAVE_REQUEST_SLOT
]);
3735 SSession
* pSession
= &m_sessions
[pTask
->session
];
3737 memset(pLeaveParams
, 0, sizeof(SLeaveParamData
));
3738 pLeaveParams
->m_leaveRequest
.roomId
= pSession
->m_roomId
;
3739 pLeaveParams
->m_leaveRequest
.optData
.len
= 0;
3741 StartSubTask(eST_WaitingForLeaveRoomRequestCallback
, mmTaskID
);
3743 int ret
= sceNpMatching2LeaveRoom(m_pPSNSupport
->GetMatchmakingContextId(), &pLeaveParams
->m_leaveRequest
, NULL
, &pTask
->m_reqId
);
3746 //-- wait for callback
3750 NetLog("sceNpMatching2LeaveRoom : error %08X", ret
);
3752 if ((ret
== SCE_NP_MATCHING2_ERROR_ROOM_NOT_FOUND
) || (ret
== SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM
) || (ret
== SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM_INSTANCE
))
3754 //-- To fix a bug in trying to delete a room that doesn't exist.
3755 //-- If we attempt to leave a room, and the room doesn't exist, we'll treat it the same as if we left
3756 //-- the room successfully, so call the event handler than deals with the cleanup of the room leaving.
3757 SCryPSNSupportCallbackEventData data
;
3758 memset(&data
, 0, sizeof(SCryPSNSupportCallbackEventData
));
3759 data
.m_requestEvent
.m_event
= REQUEST_EVENT_LEAVE_ROOM
;
3760 data
.m_requestEvent
.m_reqId
= pTask
->m_reqId
;
3762 EventRequestResponse_LeaveRoom(this, pTask
, mmTaskID
, data
);
3766 //-- triggering a PSN error will cause an error event into SupportCallback() and set a task error if it needs to clean up.
3767 //-- otherwise, we have to update the task error ourself.
3768 if (!m_pPSNSupport
->HandlePSNError(ret
))
3770 UpdateTaskError(mmTaskID
, eCLE_RoomDoesNotExist
);
3777 UpdateTaskError(mmTaskID
, eCLE_OutOfMemory
);
3782 bool CCryPSNMatchMaking::EventRequestResponse_LeaveRoom(CCryPSNMatchMaking
* _this
, STask
* pTask
, CryMatchMakingTaskID taskId
, SCryPSNSupportCallbackEventData
& data
)
3785 assert(pTask
->subTask
== eST_WaitingForLeaveRoomRequestCallback
);
3786 assert(data
.m_requestEvent
.m_event
== REQUEST_EVENT_LEAVE_ROOM
);
3788 if (data
.m_requestEvent
.m_error
== 0)
3790 if (pTask
->session
!= CryLobbyInvalidSessionHandle
)
3792 SSession
* pSession
= &_this
->m_sessions
[pTask
->session
];
3793 if (pSession
->IsUsed())
3795 if (pSession
->m_sessionId
.data
[0] != 0)
3797 _this
->StartSubTask(eST_WaitingForLeaveRoomWebApiCallback
, taskId
);
3799 SCryPSNOrbisWebApiLeaveSessionInput
* pLeaveWebApiParams
= (SCryPSNOrbisWebApiLeaveSessionInput
*)_this
->m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_WEBAPI_LEAVE_REQUEST_SLOT
]);
3800 if (pLeaveWebApiParams
)
3802 memcpy(&pLeaveWebApiParams
->sessionId
, &pSession
->m_sessionId
, sizeof(SceNpSessionId
));
3803 memcpy(&pLeaveWebApiParams
->playerId
, &_this
->m_pPSNSupport
->GetLocalNpId()->handle
, sizeof(SceNpOnlineId
));
3805 SLeaveParamData
* pLeaveParams
= (SLeaveParamData
*)_this
->m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_LEAVE_REQUEST_SLOT
]);
3806 pLeaveParams
->m_leaveJobId
= _this
->m_pPSNSupport
->GetWebApiInterface().AddJob(CCryPSNOrbisWebApiThread::LeaveSession
, pTask
->params
[PSN_MATCHMAKING_WEBAPI_LEAVE_REQUEST_SLOT
]);
3811 _this
->UpdateTaskError(taskId
, eCLE_OutOfMemory
);
3816 // no session advert to leave, so we're finished!
3817 _this
->ClearSessionInfo(pTask
->session
);
3818 _this
->FreeSessionHandle(pTask
->session
);
3820 _this
->UpdateTaskError(taskId
, eCLE_Success
);
3821 _this
->StopTaskRunning(taskId
);
3826 _this
->UpdateTaskError(taskId
, eCLE_InternalError
);
3831 _this
->UpdateTaskError(taskId
, eCLE_InternalError
);
3842 void CCryPSNMatchMaking::EventWebApiLeaveSession(CryMatchMakingTaskID mmTaskID
, SCryPSNSupportCallbackEventData
& data
)
3844 STask
* pTask
= &m_task
[mmTaskID
];
3846 if (pTask
->session
!= CryLobbyInvalidSessionHandle
)
3848 SSession
* pSession
= &m_sessions
[pTask
->session
];
3850 if (data
.m_webApiEvent
.m_error
== PSN_OK
)
3852 // Completed successfully
3853 // no session advert to leave, so we're finished!
3854 ClearSessionInfo(pTask
->session
);
3855 FreeSessionHandle(pTask
->session
);
3857 UpdateTaskError(mmTaskID
, eCLE_Success
);
3858 StopTaskRunning(mmTaskID
);
3863 // otherwise something went wrong!
3864 ClearSessionInfo(pTask
->session
);
3865 FreeSessionHandle(pTask
->session
);
3867 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
3868 StopTaskRunning(mmTaskID
);
3871 // END SESSION DELETE -----------------------------------------------------------------------------------------------------
3873 // SESSION SEARCH ---------------------------------------------------------------------------------------------------------
3875 ECryLobbyError
CCryPSNMatchMaking::SessionSearch(uint32 user
, SCrySessionSearchParam
* pParam
, CryLobbyTaskID
* pTaskID
, CryMatchmakingSessionSearchCallback cb
, void* cbArg
)
3879 CryMatchMakingTaskID mmTaskID
;
3881 ECryLobbyError error
= StartTask(eT_SessionSearch
, false, user
, &mmTaskID
, pTaskID
, 0, (void*)cb
, cbArg
);
3882 if (error
== eCLE_Success
)
3884 error
= CreateTaskParam(mmTaskID
, PSN_MATCHMAKING_SEARCH_PARAMS_SLOT
, pParam
, 1, sizeof(SCrySessionSearchParam
));
3885 if (error
== eCLE_Success
)
3887 error
= CreateTaskParam(mmTaskID
, PSN_MATCHMAKING_SEARCH_DATA_SLOT
, pParam
->m_data
, pParam
->m_numData
, pParam
->m_numData
* sizeof(pParam
->m_data
[0]));
3888 if (error
== eCLE_Success
)
3890 error
= CreateTaskParam(mmTaskID
, PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT
, NULL
, 1, sizeof(SSearchInfoData
));
3891 if (error
== eCLE_Success
)
3893 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
3895 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning
, this, mmTaskID
);
3900 if (error
!= eCLE_Success
)
3906 NetLog("[Lobby] Start SessionSearch error %d", error
);
3911 uint32
CCryPSNMatchMaking::BuildSearchFilterParams(SCrySessionSearchData
* pData
, uint32 numData
,
3912 SceNpMatching2IntSearchFilter intFilterExternal
[SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_NUM
])
3918 for (uint32 i
= 0; (i
< numData
) && (nCount
< SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_NUM
); i
++)
3920 SCrySessionSearchData
* pCurData
= &pData
[i
];
3922 for (uint32 j
= 0; (j
< m_registeredUserData
.num
) && (nCount
< SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_NUM
); j
++)
3924 SCrySessionUserData
* pRegUserData
= &m_registeredUserData
.data
[j
];
3925 SMappingToPSNLobbyData
* pRegMappingData
= &m_registeredUserData
.mapping
[j
];
3927 if (pCurData
->m_data
.m_id
== pRegUserData
->m_id
)
3929 if (pCurData
->m_data
.m_type
== pRegUserData
->m_type
)
3931 assert(pRegMappingData
->integerField
&& "Can only search using integer fields on PSN!");
3933 if (pRegMappingData
->integerField
)
3935 intFilterExternal
[nCount
].attr
.id
= SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_1_ID
+ pRegMappingData
->fieldOffset
;
3936 intFilterExternal
[nCount
].attr
.num
= pCurData
->m_data
.m_int32
;
3938 switch (pCurData
->m_operator
)
3942 NetLog("[PSN Search] No valid Search filter operator defined: using default EQUALS");
3943 intFilterExternal
[nCount
].searchOperator
= SCE_NP_MATCHING2_OPERATOR_EQ
;
3948 intFilterExternal
[nCount
].searchOperator
= SCE_NP_MATCHING2_OPERATOR_EQ
;
3951 case eCSSO_NotEqual
:
3953 intFilterExternal
[nCount
].searchOperator
= SCE_NP_MATCHING2_OPERATOR_NE
;
3956 case eCSSO_LessThan
:
3958 intFilterExternal
[nCount
].searchOperator
= SCE_NP_MATCHING2_OPERATOR_LT
;
3961 case eCSSO_LessThanEqual
:
3963 intFilterExternal
[nCount
].searchOperator
= SCE_NP_MATCHING2_OPERATOR_LE
;
3966 case eCSSO_GreaterThan
:
3968 intFilterExternal
[nCount
].searchOperator
= SCE_NP_MATCHING2_OPERATOR_GT
;
3971 case eCSSO_GreaterThanEqual
:
3973 intFilterExternal
[nCount
].searchOperator
= SCE_NP_MATCHING2_OPERATOR_GE
;
3982 NetLog("[PSN Search] Can only search using integer fields on PSN!");
3993 void CCryPSNMatchMaking::StartSessionSearch(CryMatchMakingTaskID mmTaskID
)
3995 STask
* pTask
= &m_task
[mmTaskID
];
3997 if (pTask
->params
[PSN_MATCHMAKING_SEARCH_PARAMS_SLOT
] != TMemInvalidHdl
)
3999 if (pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT
] != TMemInvalidHdl
)
4001 SCrySessionSearchParam
* pData
= (SCrySessionSearchParam
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_SEARCH_PARAMS_SLOT
]);
4002 if (pTask
->params
[PSN_MATCHMAKING_SEARCH_DATA_SLOT
] != TMemInvalidHdl
)
4004 pData
->m_data
= (SCrySessionSearchData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_SEARCH_DATA_SLOT
]);
4008 pData
->m_data
= NULL
;
4011 SSearchInfoData
* pSearchInfo
= (SSearchInfoData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT
]);
4012 memset(pSearchInfo
, 0, sizeof(SSearchInfoData
));
4014 uint32 nFields
= BuildSearchFilterParams(pData
->m_data
, pData
->m_numData
, pSearchInfo
->m_intFilterExternal
);
4016 pSearchInfo
->m_searchRequest
.worldId
= 0;
4017 pSearchInfo
->m_searchRequest
.lobbyId
= 0;
4018 pSearchInfo
->m_searchRequest
.flagFilter
= SCE_NP_MATCHING2_ROOM_FLAG_ATTR_CLOSED
| SCE_NP_MATCHING2_ROOM_FLAG_ATTR_FULL
;
4019 pSearchInfo
->m_searchRequest
.flagAttr
= 0;
4020 pSearchInfo
->m_searchRequest
.intFilter
= (nFields
> 0) ? (pSearchInfo
->m_intFilterExternal
) : (NULL
);
4021 pSearchInfo
->m_searchRequest
.intFilterNum
= nFields
;
4022 pSearchInfo
->m_searchRequest
.binFilter
= NULL
;
4023 pSearchInfo
->m_searchRequest
.binFilterNum
= 0;
4024 pSearchInfo
->m_searchRequest
.rangeFilter
.startIndex
= SCE_NP_MATCHING2_RANGE_FILTER_START_INDEX_MIN
;
4025 pSearchInfo
->m_searchRequest
.rangeFilter
.max
= SCE_NP_MATCHING2_RANGE_FILTER_MAX
;
4026 pSearchInfo
->m_searchRequest
.option
= SCE_NP_MATCHING2_SEARCH_ROOM_OPTION_RANDOM
;
4028 pSearchInfo
->m_attrId
[0] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_1_ID
;
4029 pSearchInfo
->m_attrId
[1] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_2_ID
;
4030 pSearchInfo
->m_attrId
[2] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_3_ID
;
4031 pSearchInfo
->m_attrId
[3] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_4_ID
;
4032 pSearchInfo
->m_attrId
[4] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_5_ID
;
4033 pSearchInfo
->m_attrId
[5] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_6_ID
;
4034 pSearchInfo
->m_attrId
[6] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_7_ID
;
4035 pSearchInfo
->m_attrId
[7] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_8_ID
;
4036 pSearchInfo
->m_attrId
[8] = SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_1_ID
;
4037 pSearchInfo
->m_attrId
[9] = SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_2_ID
;
4039 pSearchInfo
->m_searchRequest
.attrId
= pSearchInfo
->m_attrId
;
4040 pSearchInfo
->m_searchRequest
.attrIdNum
= 10;
4042 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
4046 UpdateTaskError(mmTaskID
, eCLE_OutOfMemory
);
4047 StopTaskRunning(mmTaskID
);
4052 UpdateTaskError(mmTaskID
, eCLE_OutOfMemory
);
4053 StopTaskRunning(mmTaskID
);
4057 void CCryPSNMatchMaking::TickSessionSearch(CryMatchMakingTaskID mmTaskID
)
4059 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
4060 if (m_pPSNSupport
->HasTransitioningReachedState(ePSNOS_Matchmaking_Available
))
4062 STask
* pTask
= &m_task
[mmTaskID
];
4064 //-- get a list of worlds
4065 StartSubTask(eST_WaitingForSearchRoomWorldInfo
, mmTaskID
);
4067 SceNpMatching2GetWorldInfoListRequest reqParam
;
4068 memset(&reqParam
, 0, sizeof(reqParam
));
4069 reqParam
.serverId
= m_pPSNSupport
->GetServerInfo()->server
.serverId
;
4071 int ret
= sceNpMatching2GetWorldInfoList(m_pPSNSupport
->GetMatchmakingContextId(), &reqParam
, NULL
, &pTask
->m_reqId
);
4074 //-- Waiting for callback
4078 NetLog("sceNpMatching2GetWorldInfoList : error %08X", ret
);
4079 if (!m_pPSNSupport
->HandlePSNError(ret
))
4081 UpdateTaskError(mmTaskID
, eCLE_WorldNotDefined
);
4087 bool CCryPSNMatchMaking::EventRequestResponse_GetWorldInfoListForSearch(CCryPSNMatchMaking
* _this
, STask
* pTask
, CryMatchMakingTaskID taskId
, SCryPSNSupportCallbackEventData
& data
)
4089 assert(pTask
->subTask
== eST_WaitingForSearchRoomWorldInfo
);
4090 assert(data
.m_requestEvent
.m_event
== REQUEST_EVENT_GET_WORLD_INFO_LIST
);
4091 assert(data
.m_requestEvent
.m_dataSize
== sizeof(SCryPSNGetWorldInfoListResponse
));
4093 if ((data
.m_requestEvent
.m_error
== 0) &&
4094 (data
.m_requestEvent
.m_dataHdl
!= TMemInvalidHdl
) &&
4095 (data
.m_requestEvent
.m_dataSize
== sizeof(SCryPSNGetWorldInfoListResponse
)))
4097 SSearchInfoData
* pSearchInfo
= (SSearchInfoData
*)_this
->m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT
]);
4100 const SCryPSNGetWorldInfoListResponse
* pWorldList
= (SCryPSNGetWorldInfoListResponse
*)_this
->m_lobby
->MemGetPtr(data
.m_requestEvent
.m_dataHdl
);
4102 pSearchInfo
->m_numWorlds
= SortWorlds(pWorldList
, pSearchInfo
->m_worldIds
, MAX_WORLDS_TO_SEARCH
, true);
4103 if (pSearchInfo
->m_numWorlds
> 0)
4105 pSearchInfo
->m_nIndex
= 0;
4106 pSearchInfo
->m_searchRequest
.worldId
= pSearchInfo
->m_worldIds
[pSearchInfo
->m_nIndex
];
4108 _this
->StartSubTask(eST_SessionSearchRequest
, taskId
);
4112 _this
->UpdateTaskError(taskId
, eCLE_WorldNotDefined
);
4117 _this
->UpdateTaskError(taskId
, eCLE_OutOfMemory
);
4128 void CCryPSNMatchMaking::TickSessionSearchRequest(CryMatchMakingTaskID mmTaskID
)
4130 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
4131 if (m_pPSNSupport
->HasTransitioningReachedState(ePSNOS_Matchmaking_Available
))
4133 STask
* pTask
= &m_task
[mmTaskID
];
4135 SSearchInfoData
* pSearchInfo
= (SSearchInfoData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT
]);
4137 StartSubTask(eST_WaitingForSearchRoomRequestCallback
, mmTaskID
);
4139 int ret
= sceNpMatching2SearchRoom(m_pPSNSupport
->GetMatchmakingContextId(), &pSearchInfo
->m_searchRequest
, NULL
, &pTask
->m_reqId
);
4142 //-- waiting for callback
4146 NetLog("sceNpMatching2SearchRoom : error %08X", ret
);
4147 //-- triggering a PSN error will cause an error event into SupportCallback() and set a task error if it needs to clean up.
4148 //-- otherwise, we have to update the task error ourself.
4149 if (!m_pPSNSupport
->HandlePSNError(ret
))
4151 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
4157 UpdateTaskError(mmTaskID
, eCLE_OutOfMemory
);
4161 bool CCryPSNMatchMaking::EventRequestResponse_SearchRoom(CCryPSNMatchMaking
* _this
, STask
* pTask
, CryMatchMakingTaskID taskId
, SCryPSNSupportCallbackEventData
& data
)
4164 assert(pTask
->subTask
== eST_WaitingForSearchRoomRequestCallback
);
4165 assert(data
.m_requestEvent
.m_event
== REQUEST_EVENT_SEARCH_ROOM
);
4166 assert(data
.m_requestEvent
.m_dataHdl
!= TMemInvalidHdl
);
4167 assert(data
.m_requestEvent
.m_dataSize
== sizeof(SCryPSNSearchRoomResponse
));
4169 if ((data
.m_requestEvent
.m_error
== 0) &&
4170 (data
.m_requestEvent
.m_dataHdl
!= TMemInvalidHdl
) &&
4171 (data
.m_requestEvent
.m_dataSize
== sizeof(SCryPSNSearchRoomResponse
)))
4173 const SCryPSNSearchRoomResponse
* const pResponse
= (SCryPSNSearchRoomResponse
*)_this
->m_lobby
->MemGetPtr(data
.m_requestEvent
.m_dataHdl
);
4174 SSearchInfoData
* pSearchInfo
= (SSearchInfoData
*)_this
->m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT
]);
4175 SCrySessionSearchParam
* pSearchParams
= (SCrySessionSearchParam
*)_this
->m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_SEARCH_PARAMS_SLOT
]);
4178 while ((pSearchInfo
->m_numResults
< MAX_ROOMS_TO_STORE
) && (pSearchInfo
->m_numResults
< pSearchParams
->m_maxNumReturn
) && (c
< pResponse
->m_numRooms
))
4180 _this
->ProcessExternalRoomData(pResponse
->m_pRooms
[c
], pSearchInfo
->m_results
[pSearchInfo
->m_numResults
], pSearchInfo
->m_resultUserData
[pSearchInfo
->m_numResults
]);
4181 pSearchInfo
->m_numResults
++;
4185 pSearchInfo
->m_nIndex
++;
4186 if ((pSearchInfo
->m_numResults
< MAX_ROOMS_TO_STORE
) && (pSearchInfo
->m_numResults
< pSearchParams
->m_maxNumReturn
) && (pSearchInfo
->m_nIndex
< pSearchInfo
->m_numWorlds
))
4188 //-- Chain start a new search on the next world in the list.
4189 assert(pSearchInfo
->m_worldIds
[pSearchInfo
->m_nIndex
] != 0);
4190 pSearchInfo
->m_searchRequest
.worldId
= pSearchInfo
->m_worldIds
[pSearchInfo
->m_nIndex
];
4191 _this
->StartSubTask(eST_SessionSearchRequest
, taskId
);
4195 if (pSearchInfo
->m_numResults
> 0)
4197 //-- We've filled the results buffer, or run out of worlds, so move onto QOS!
4198 pSearchInfo
->m_nIndex
= 0;
4199 _this
->StartSubTask(eST_SessionSearchKickQOS
, taskId
);
4203 //-- No results after searching all the worlds, so just give up on search task.
4204 _this
->UpdateTaskError(taskId
, eCLE_Success
);
4205 _this
->StopTaskRunning(taskId
);
4213 // an error was returned in the response. If we return false, the default error handler will deal with it
4218 void CCryPSNMatchMaking::TickSessionWaitForQOS(CryMatchMakingTaskID mmTaskID
)
4220 STask
* pTask
= &m_task
[mmTaskID
];
4222 if (pTask
->GetTimer() >= MAX_WAITTIME_FOR_QOS
)
4224 NetLog("Timeout Getting QOS Data - Returning what we have");
4225 UpdateTaskError(mmTaskID
, eCLE_Success
); // Don't return timeout, that way game gets some results
4226 StopTaskRunning(mmTaskID
);
4230 void CCryPSNMatchMaking::TickSessionQOSSearch(CryMatchMakingTaskID mmTaskID
)
4234 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
4235 if (m_pPSNSupport
->HasTransitioningReachedState(ePSNOS_Matchmaking_Available
))
4237 STask
* pTask
= &m_task
[mmTaskID
];
4239 SSearchInfoData
* pSearchInfo
= (SSearchInfoData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT
]);
4240 pSearchInfo
->m_nIndex
= 0;
4241 while (qosIndex
< pSearchInfo
->m_numResults
)
4243 SCryPSNSessionID
* pId
= (SCryPSNSessionID
*)pSearchInfo
->m_results
[qosIndex
].m_id
.get();
4246 memset(&pSearchInfo
->m_QOSRequest
[qosIndex
], 0, sizeof(SceNpMatching2SignalingGetPingInfoRequest
));
4247 pSearchInfo
->m_QOSRequest
[qosIndex
].roomId
= pId
->m_sessionInfo
.m_roomId
;
4248 pSearchInfo
->m_results
[qosIndex
].m_ping
= PSN_MATCHMAKING_DEFAULT_UNKNOWN_PING
;
4250 pTask
->m_reqId
= INVALID_PSN_REQUEST_ID
; // We cant use the global task id, because we have many qos subtasks potentially on one task
4252 StartSubTask(eST_WaitingForSearchQOSRequestCallback
, mmTaskID
);
4254 int ret
= sceNpMatching2SignalingGetPingInfo(m_pPSNSupport
->GetMatchmakingContextId(), &pSearchInfo
->m_QOSRequest
[qosIndex
], NULL
, &pSearchInfo
->m_reqId
[qosIndex
]);
4256 NetLog("Task ID : %d Idx : %d Request id : %d Room Id : %d", mmTaskID
, qosIndex
, (int32
)pSearchInfo
->m_reqId
[qosIndex
], (int32
)pId
->m_sessionInfo
.m_roomId
);
4261 //-- waiting for callback
4265 NetLog("sceNpMatching2SignalingGetPingInfo : error %08X", ret
);
4266 //-- triggering a PSN error will cause an error event into SupportCallback() and set a task error if it needs to clean up.
4267 //-- otherwise, we have to update the task error ourself.
4268 if (!m_pPSNSupport
->HandlePSNError(ret
))
4270 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
4276 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
4279 pSearchInfo
->m_nIndex
= qosIndex
;
4282 if (pSearchInfo
->m_nIndex
== 0)
4284 //-- SUCCESS End of search results, we can end the task now.
4285 UpdateTaskError(mmTaskID
, eCLE_Success
);
4286 StopTaskRunning(mmTaskID
);
4290 pTask
->StartTimer();
4295 bool CCryPSNMatchMaking::EventRequestResponse_SearchQOS(CCryPSNMatchMaking
* _this
, STask
* pTask
, CryMatchMakingTaskID taskId
, SCryPSNSupportCallbackEventData
& data
)
4297 assert(pTask
->subTask
== eST_WaitingForSearchQOSRequestCallback
);
4298 assert(data
.m_requestEvent
.m_event
== REQUEST_EVENT_SIGNALING_GET_PING_INFO
);
4299 assert(data
.m_requestEvent
.m_dataHdl
!= TMemInvalidHdl
);
4300 assert(data
.m_requestEvent
.m_dataSize
== sizeof(SCryPSNSignalingGetPingInfoResponse
));
4302 SSearchInfoData
* pSearchInfo
= (SSearchInfoData
*)_this
->m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT
]);
4303 SCrySessionSearchResult
* pSearchResult
= NULL
;
4305 for (int a
= 0; a
< pSearchInfo
->m_numResults
; a
++)
4307 if (data
.m_requestEvent
.m_reqId
== pSearchInfo
->m_reqId
[a
])
4309 pSearchResult
= &pSearchInfo
->m_results
[a
];
4310 pSearchInfo
->m_nIndex
--;
4315 if ((data
.m_requestEvent
.m_error
== 0) &&
4316 (data
.m_requestEvent
.m_dataHdl
!= TMemInvalidHdl
) &&
4317 (data
.m_requestEvent
.m_dataSize
== sizeof(SCryPSNSignalingGetPingInfoResponse
)) &&
4320 const SCryPSNSignalingGetPingInfoResponse
* const pQOSResponse
= (SCryPSNSignalingGetPingInfoResponse
*)_this
->m_lobby
->MemGetPtr(data
.m_requestEvent
.m_dataHdl
);
4321 pSearchResult
->m_ping
= pQOSResponse
->m_rtt
/ 1000;
4322 NetLog("Request Id: %d QoS Done: ping %d roomId %d", data
.m_requestEvent
.m_reqId
, (int32
)pSearchResult
->m_ping
, (int32
)pQOSResponse
->m_roomId
);
4326 // QoS can return socket errors, or a timeout as an error. In this rare case, we'll have to assume the error is not fatal and trap it
4327 // by marking it as handled with no ping value.
4328 NetLog("Request Id: %d QoS Done ERROR: ping %d, error %08X", data
.m_requestEvent
.m_reqId
, (int32
)pSearchResult
->m_ping
, data
.m_requestEvent
.m_error
);
4331 if (pSearchInfo
->m_nIndex
== 0)
4333 //-- SUCCESS End of search results, we can end the task now.
4334 _this
->UpdateTaskError(taskId
, eCLE_Success
);
4335 _this
->StopTaskRunning(taskId
);
4341 void CCryPSNMatchMaking::EndSessionSearch(CryMatchMakingTaskID mmTaskID
)
4343 STask
* pTask
= &m_task
[mmTaskID
];
4345 if (pTask
->error
== eCLE_Success
)
4347 if (pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT
] != TMemInvalidHdl
)
4349 SSearchInfoData
* pSearchInfo
= (SSearchInfoData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT
]);
4351 NetLog("[Lobby] Found %d sessions in %d worlds.", pSearchInfo
->m_numResults
, pSearchInfo
->m_numWorlds
);
4353 for (uint32 i
= 0; i
< pSearchInfo
->m_numResults
; i
++)
4355 SCrySessionSearchResult
* pResult
= &pSearchInfo
->m_results
[i
];
4356 ((CryMatchmakingSessionSearchCallback
)pTask
->cb
)(pTask
->lTaskID
, eCLE_SuccessContinue
, pResult
, pTask
->cbArg
);
4358 //-- remove reference to CrySessionID, since it's a smart pointer inside a larger alloc that wouldn't be cleaned up otherwise.
4359 pResult
->m_id
= NULL
;
4364 UpdateTaskError(mmTaskID
, eCLE_OutOfMemory
);
4368 ((CryMatchmakingSessionSearchCallback
)pTask
->cb
)(pTask
->lTaskID
, pTask
->error
, NULL
, pTask
->cbArg
);
4371 // END OF SEARCH -------------------------------------------------------------------------
4373 // SESSION JOIN --------------------------------------------------------------------------
4375 ECryLobbyError
CCryPSNMatchMaking::SessionJoin(uint32
* users
, int numUsers
, uint32 flags
, CrySessionID id
, CryLobbyTaskID
* taskID
, CryMatchmakingSessionJoinCallback cb
, void* cbArg
)
4379 CryLobbySessionHandle h
;
4380 ECryLobbyError error
= CreateSessionHandle(&h
, false, users
, numUsers
, flags
);
4381 if (error
== eCLE_Success
)
4383 CryMatchMakingTaskID mmTaskID
;
4385 error
= StartTask(eT_SessionJoin
, false, users
[0], &mmTaskID
, taskID
, h
, (void*)cb
, cbArg
);
4386 if (error
== eCLE_Success
)
4388 error
= CreateTaskParam(mmTaskID
, PSN_MATCHMAKING_PSNSUPPORT_JOIN_REQUEST_SLOT
, NULL
, 1, sizeof(SJoinParamData
));
4389 if (error
== eCLE_Success
)
4391 error
= CreateTaskParam(mmTaskID
, PSN_MATCHMAKING_WEBAPI_JOIN_SLOT
, NULL
, 1, sizeof(SCryPSNOrbisWebApiJoinSessionInput
));
4392 if (error
== eCLE_Success
)
4394 SCryPSNSessionID
* psnID
= (SCryPSNSessionID
*)id
.get();
4395 SSession
* pSession
= &m_sessions
[h
];
4397 pSession
->m_roomId
= psnID
->m_sessionInfo
.m_roomId
;
4398 pSession
->m_worldId
= psnID
->m_sessionInfo
.m_worldId
;
4399 pSession
->m_serverId
= psnID
->m_sessionInfo
.m_serverId
;
4400 pSession
->m_gameType
= psnID
->m_sessionInfo
.m_gameType
;
4401 pSession
->m_flags
= 0;
4403 for (uint32 i
= 0; i
< numUsers
; i
++)
4405 pSession
->localConnection
.privateSlot
[i
] = psnID
->m_fromInvite
;
4408 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
4410 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning
, this, mmTaskID
);
4414 if (error
!= eCLE_Success
)
4417 FreeSessionHandle(h
);
4422 FreeSessionHandle(h
);
4426 NetLog("[Lobby] Start SessionJoin error %d", error
);
4431 void CCryPSNMatchMaking::TickSessionJoin(CryMatchMakingTaskID mmTaskID
)
4433 STask
* pTask
= &m_task
[mmTaskID
];
4435 if (pTask
->error
== eCLE_Success
)
4437 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
4438 if (m_pPSNSupport
->HasTransitioningReachedState(ePSNOS_Matchmaking_Available
))
4440 if (pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_JOIN_REQUEST_SLOT
] != TMemInvalidHdl
)
4442 SJoinParamData
* pJoinParams
= (SJoinParamData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_JOIN_REQUEST_SLOT
]);
4443 SSession
* pSession
= &m_sessions
[pTask
->session
];
4445 memset(pJoinParams
, 0, sizeof(SJoinParamData
));
4447 pJoinParams
->m_joinRequest
.roomId
= pSession
->m_roomId
;
4448 pJoinParams
->m_joinRequest
.roomPassword
= NULL
;
4449 pJoinParams
->m_joinRequest
.joinRoomGroupLabel
= NULL
;
4450 pJoinParams
->m_joinRequest
.roomMemberBinAttrInternal
= NULL
;
4451 pJoinParams
->m_joinRequest
.roomMemberBinAttrInternalNum
= 0;
4452 pJoinParams
->m_joinRequest
.optData
.len
= 0;
4454 StartSubTask(eST_WaitingForJoinRoomRequestCallback
, mmTaskID
);
4456 int ret
= sceNpMatching2JoinRoom(m_pPSNSupport
->GetMatchmakingContextId(), &pJoinParams
->m_joinRequest
, NULL
, &pTask
->m_reqId
);
4459 //-- waiting for callback
4463 NetLog("sceNpMatching2JoinRoom : error %08X", ret
);
4464 //-- triggering a PSN error will cause an error event into SupportCallback() and set a task error if it needs to clean up.
4465 //-- otherwise, we have to update the task error ourself.
4466 if (!m_pPSNSupport
->HandlePSNError(ret
))
4468 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
4474 UpdateTaskError(mmTaskID
, eCLE_OutOfMemory
);
4480 bool CCryPSNMatchMaking::EventRequestResponse_JoinRoom(CCryPSNMatchMaking
* _this
, STask
* pTask
, CryMatchMakingTaskID taskId
, SCryPSNSupportCallbackEventData
& data
)
4483 assert(pTask
->subTask
== eST_WaitingForJoinRoomRequestCallback
);
4484 assert(data
.m_requestEvent
.m_event
== REQUEST_EVENT_JOIN_ROOM
);
4485 assert(data
.m_requestEvent
.m_dataHdl
!= TMemInvalidHdl
);
4486 assert(data
.m_requestEvent
.m_dataSize
== sizeof(SCryPSNJoinRoomResponse
));
4488 if ((data
.m_requestEvent
.m_error
== 0) &&
4489 (data
.m_requestEvent
.m_dataHdl
!= TMemInvalidHdl
) &&
4490 (data
.m_requestEvent
.m_dataSize
== sizeof(SCryPSNJoinRoomResponse
)))
4492 if (pTask
->session
!= CryLobbyInvalidSessionHandle
)
4494 SSession
* pSession
= &_this
->m_sessions
[pTask
->session
];
4495 if (pSession
->IsUsed())
4497 const SCryPSNJoinRoomResponse
* const pJoinResponse
= (SCryPSNJoinRoomResponse
*)_this
->m_lobby
->MemGetPtr(data
.m_requestEvent
.m_dataHdl
);
4498 pSession
->m_roomId
= pJoinResponse
->m_roomInfo
.m_roomId
;
4500 if (!pTask
->canceled
)
4502 _this
->AddInitialRoomMembers(pTask
->session
, pJoinResponse
->m_roomMembers
);
4504 // take ownership of the memory returned by the callback so it is not automatically discarded on return
4505 pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_JOIN_RESPONSE_SLOT
] = data
.m_requestEvent
.m_dataHdl
;
4506 data
.m_requestEvent
.m_dataHdl
= TMemInvalidHdl
;
4507 data
.m_requestEvent
.m_returnFlags
|= SCryPSNSupportCallbackEventData::SRequestEvent::REQUEST_EVENT_OWNS_MEMORY
;
4509 _this
->StartSubTask(eST_WaitingForJoinRoomSignalingCallback
, taskId
);
4513 _this
->UpdateTaskError(taskId
, eCLE_IllegalSessionJoin
);
4518 _this
->UpdateTaskError(taskId
, eCLE_InternalError
);
4523 _this
->UpdateTaskError(taskId
, eCLE_InternalError
);
4534 void CCryPSNMatchMaking::ProcessSessionJoinHostAck(const TNetAddress
& addr
, CCrySharedLobbyPacket
* pPacket
)
4536 CryLobbySessionHandle h
= CryLobbyInvalidSessionHandle
;
4537 SCryMatchMakingConnectionUID hostUID
= pPacket
->GetFromConnectionUID();
4538 CryMatchMakingConnectionID mmCxID
= CryMatchMakingInvalidConnectionID
;
4540 if (FindConnectionFromUID(hostUID
, &h
, &mmCxID
))
4542 SSession
* pSession
= &m_sessions
[h
];
4544 NetLog("[join session]: received join session server acknowledgment " PRFORMAT_SHMMCINFO
, PRARG_SHMMCINFO(h
, mmCxID
, pSession
->remoteConnection
[mmCxID
].connectionID
, hostUID
));
4546 // part of the join session ack packet is the host's session id, which we want to copy.
4547 pPacket
->ReadString((char*)&pSession
->m_sessionId
, sizeof(SceNpSessionId
));
4549 for (uint32 a
= 0; a
< MAX_PSN_ROOM_MEMBERS
; a
++)
4551 SSession::SRoomMember
* pMember
= &pSession
->m_members
[a
];
4552 if (pMember
->IsValid(ePSNMI_Owner
))
4554 if ((pMember
->m_signalingState
== ePSNCS_Active
) || (pMember
->m_signalingState
== ePSNCS_Pending
))
4556 pMember
->m_bHostJoinAck
= true;
4558 for (uint32 i
= 0; i
< MAX_MATCHMAKING_TASKS
; i
++)
4560 STask
* pTask
= &m_task
[i
];
4562 if (pTask
->used
&& pTask
->running
&& (pTask
->subTask
== eST_WaitingForJoinRoomSignalingCallback
))
4564 TickSessionJoinSignaling(i
);
4574 NetLog("[join session]: received join session server acknowledgement from unknown host " PRFORMAT_UID
, PRARG_UID(hostUID
));
4578 void CCryPSNMatchMaking::TickSessionJoinSignaling(CryMatchMakingTaskID mmTaskID
)
4580 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
4581 if (m_pPSNSupport
->HasTransitioningReachedState(ePSNOS_Matchmaking_Available
))
4583 STask
* pTask
= &m_task
[mmTaskID
];
4585 UpdateSignaling(mmTaskID
);
4587 switch (CheckSignaling(mmTaskID
))
4591 //-- This is bad, means there is no room owner!
4592 UpdateTaskError(mmTaskID
, eCLE_InvalidParam
);
4597 assert(pTask
->subTask
== eST_WaitingForJoinRoomSignalingCallback
);
4599 //-- Success! We can talk to the server p2p, and we also have the hosts session Id
4600 // Next step is to join the same session via webapi.
4601 if (!pTask
->canceled
)
4603 if (pTask
->session
!= CryLobbyInvalidSessionHandle
)
4605 SSession
* pSession
= &m_sessions
[pTask
->session
];
4606 if (pSession
->IsUsed())
4608 if (pSession
->createFlags
& CRYSESSION_CREATE_FLAG_INVITABLE
)
4610 if (pSession
->m_sessionId
.data
[0] != 0)
4612 SJoinParamData
* pJoinParams
= (SJoinParamData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_JOIN_REQUEST_SLOT
]);
4613 SCryPSNOrbisWebApiJoinSessionInput
* pWebApiJoinParams
= (SCryPSNOrbisWebApiJoinSessionInput
*)m_pPSNSupport
->GetLobby()->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_WEBAPI_JOIN_SLOT
]);
4614 if (pJoinParams
&& pWebApiJoinParams
)
4616 StartSubTask(eST_WaitingForJoinRoomWebApiCallback
, mmTaskID
);
4618 memcpy(&pWebApiJoinParams
->sessionId
, &pSession
->m_sessionId
, sizeof(SceNpSessionId
));
4620 pJoinParams
->m_joinJobId
= m_pPSNSupport
->GetWebApiInterface().AddJob(CCryPSNOrbisWebApiThread::JoinSession
, pTask
->params
[PSN_MATCHMAKING_WEBAPI_JOIN_SLOT
]);
4621 if (pJoinParams
->m_joinJobId
== INVALID_WEBAPI_JOB_ID
)
4624 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
4629 UpdateTaskError(mmTaskID
, eCLE_OutOfMemory
);
4634 // missing session Id
4635 UpdateTaskError(mmTaskID
, eCLE_InvalidParam
);
4640 // Session is not invitable, so we don't need to join a webapi session
4641 // This is the end of Join! Success!
4642 UpdateTaskError(mmTaskID
, eCLE_Success
);
4643 StopTaskRunning(mmTaskID
);
4648 // session not in use
4649 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
4654 // invalid session handle
4655 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
4661 UpdateTaskError(mmTaskID
, eCLE_IllegalSessionJoin
);
4667 assert(pTask
->subTask
== eST_WaitingForJoinRoomSignalingCallback
);
4669 //-- Failed! We cannot talk to the server via p2p, so we've failed at the last hurdle! Join task completed(failed)
4670 UpdateTaskError(mmTaskID
, eCLE_ConnectionFailed
);
4677 void CCryPSNMatchMaking::EventWebApiJoinSession(CryMatchMakingTaskID mmTaskID
, SCryPSNSupportCallbackEventData
& data
)
4679 STask
* pTask
= &m_task
[mmTaskID
];
4681 if (pTask
->session
!= CryLobbyInvalidSessionHandle
)
4683 SSession
* pSession
= &m_sessions
[pTask
->session
];
4685 if (data
.m_webApiEvent
.m_error
== PSN_OK
)
4687 // Completed successfully
4688 UpdateTaskError(mmTaskID
, eCLE_Success
);
4689 StopTaskRunning(mmTaskID
);
4694 // otherwise something went wrong!
4695 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
4696 StopTaskRunning(mmTaskID
);
4699 void CCryPSNMatchMaking::EndSessionJoin(CryMatchMakingTaskID mmTaskID
)
4701 uint32 myIP
= 0, myPort
= 0;
4702 STask
* pTask
= &m_task
[mmTaskID
];
4703 SSession
* pSession
= &m_sessions
[pTask
->session
];
4705 SCryPSNJoinRoomResponse
* pResponse
= NULL
;
4707 if (pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_JOIN_RESPONSE_SLOT
] != TMemInvalidHdl
)
4709 pResponse
= (SCryPSNJoinRoomResponse
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_JOIN_RESPONSE_SLOT
]);
4712 if (pTask
->error
== eCLE_Success
)
4716 SSession::SRoomMember
* pMember
= FindRoomMemberFromRoomMemberID(pTask
->session
, pSession
->m_ownerMemberId
);
4718 if (pSession
->m_ownerMemberId
!= pSession
->m_myMemberId
)
4720 if (pMember
&& (pMember
->m_signalingState
== ePSNCS_Active
))
4722 SCryMatchMakingConnectionUID matchingUID
;
4723 myIP
= pMember
->m_peerAddr
.s_addr
;
4724 myPort
= pMember
->m_peerPort
;
4726 matchingUID
.m_uid
= pSession
->m_myMemberId
;
4727 matchingUID
.m_sid
= pSession
->m_roomId
;
4729 pSession
->localConnection
.uid
= matchingUID
;
4730 pSession
->localConnection
.pingToServer
= CRYLOBBY_INVALID_PING
;
4731 pSession
->localConnection
.used
= true;
4733 uint16 sessionCreateGameFlags
= 0;
4734 memcpy(&sessionCreateGameFlags
, pResponse
->m_roomInfo
.m_binAttributes
[0].m_data
, sizeof(sessionCreateGameFlags
));
4735 pSession
->createFlags
= (pSession
->createFlags
& CRYSESSION_CREATE_FLAG_SYSTEM_MASK
) | (sessionCreateGameFlags
<< CRYSESSION_CREATE_FLAG_GAME_FLAGS_SHIFT
);
4737 bool hostMigrationSupported
= m_lobby
->GetLobbyServiceFlag(m_serviceType
, eCLSF_SupportHostMigration
);
4738 if ((pSession
->createFlags
& CRYSESSION_CREATE_FLAG_MIGRATABLE
) && hostMigrationSupported
)
4740 pSession
->localFlags
|= CRYSESSION_LOCAL_FLAG_CAN_SEND_HOST_HINTS
;
4743 matchingUID
.m_uid
= pSession
->m_ownerMemberId
;
4744 CryLobbySessionHandle h
;
4745 FindConnectionFromUID(matchingUID
, &h
, &pSession
->hostConnectionID
);
4746 assert(h
== pTask
->session
);
4748 // if (pSession->createFlags & CRYSESSION_CREATE_FLAG_INVITABLE)
4750 // if (m_pService->GetLobbyUI())
4752 // ((CCryPSNLobbyUI*)m_pService->GetLobbyUI())->SetStoredInviteSessionHandle(CreateGameSessionHandle(pTask->session, CryMatchMakingInvalidConnectionUID));
4758 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
4763 // we've become the owner in the middle of joining, that won't end well,
4764 // so terminate here
4765 UpdateTaskError(mmTaskID
, eCLE_ConnectionFailed
);
4770 UpdateTaskError(mmTaskID
, eCLE_OutOfMemory
);
4774 // free the memory allocated to the response
4777 pResponse
->Release(m_lobby
);
4780 ((CryMatchmakingSessionJoinCallback
)pTask
->cb
)(pTask
->lTaskID
, pTask
->error
, CreateGameSessionHandle(pTask
->session
, pSession
->localConnection
.uid
), myIP
, myPort
, pTask
->cbArg
);
4782 if (pTask
->error
== eCLE_Success
)
4784 InitialUserDataEvent(pTask
->session
);
4788 // END SESSION JOIN -------------------------------------------------------------
4790 // SESSION UPDATE USER ---------------------------------------------------------------
4792 ECryLobbyError
CCryPSNMatchMaking::SessionSetLocalUserData(CrySessionHandle gh
, CryLobbyTaskID
* pTaskID
, uint32 user
, uint8
* pData
, uint32 dataSize
, CryMatchmakingCallback pCB
, void* pCBArg
)
4794 ECryLobbyError error
= eCLE_Success
;
4798 CryLobbySessionHandle h
= GetSessionHandleFromGameSessionHandle(gh
);
4800 if ((h
< MAX_MATCHMAKING_SESSIONS
) && m_sessions
[h
].IsUsed())
4802 SSession
* session
= &m_sessions
[h
];
4804 if (dataSize
<= CRYLOBBY_USER_DATA_SIZE_IN_BYTES
)
4806 CryMatchMakingTaskID mmTaskID
;
4808 error
= StartTask(eT_SessionUserData
, false, session
->localConnection
.users
[0], &mmTaskID
, pTaskID
, h
, (void*)pCB
, pCBArg
);
4809 if (error
== eCLE_Success
)
4811 STask
* task
= &m_task
[mmTaskID
];
4813 error
= CreateTaskParam(mmTaskID
, PSN_MATCHMAKING_USERDATA_DATA_SLOT
, pData
, dataSize
, dataSize
);
4814 if (error
== eCLE_Success
)
4816 error
= CreateTaskParam(mmTaskID
, PSN_MATCHMAKING_PSNSUPPORT_USERDATA_REQUEST_SLOT
, NULL
, 1, sizeof(SUserDataParamData
));
4817 if (error
== eCLE_Success
)
4819 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
4821 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning
, this, mmTaskID
);
4836 error
= eCLE_OutOfUserData
;
4841 error
= eCLE_InvalidSession
;
4844 NetLog("[Lobby] Start SessionUpdate error %d", error
);
4849 void CCryPSNMatchMaking::TickSessionUserData(CryMatchMakingTaskID mmTaskID
)
4851 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
4852 if (m_pPSNSupport
->HasTransitioningReachedState(ePSNOS_Matchmaking_Available
))
4854 STask
* pTask
= &m_task
[mmTaskID
];
4856 if (pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_USERDATA_REQUEST_SLOT
] != TMemInvalidHdl
)
4858 SUserDataParamData
* pUserDataParams
= (SUserDataParamData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_USERDATA_REQUEST_SLOT
]);
4860 if (pTask
->params
[PSN_MATCHMAKING_USERDATA_DATA_SLOT
] != TMemInvalidHdl
)
4862 uint8
* pData
= (uint8
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_USERDATA_DATA_SLOT
]);
4863 SSession
* pSession
= &m_sessions
[pTask
->session
];
4865 memset((void*)pUserDataParams
, 0, sizeof(SUserDataParamData
));
4867 memcpy(pUserDataParams
->m_binAttrInternalData
, pData
, pTask
->numParams
[PSN_MATCHMAKING_USERDATA_DATA_SLOT
]);
4868 pUserDataParams
->m_userDataRequest
.roomMemberBinAttrInternal
= pUserDataParams
->m_binAttrInternal
;
4870 pUserDataParams
->m_userDataRequest
.roomId
= pSession
->m_roomId
;
4871 pUserDataParams
->m_userDataRequest
.memberId
= 0; // This is allowed, and means update my own data
4872 pUserDataParams
->m_userDataRequest
.teamId
= 0;
4874 for (int a
= 0; a
< SCE_NP_MATCHING2_ROOMMEMBER_BIN_ATTR_INTERNAL_NUM
; a
++)
4876 pUserDataParams
->m_binAttrInternal
[a
].id
= SCE_NP_MATCHING2_ROOMMEMBER_BIN_ATTR_INTERNAL_1_ID
+ a
;
4877 pUserDataParams
->m_binAttrInternal
[a
].ptr
= &pUserDataParams
->m_binAttrInternalData
[a
* SCE_NP_MATCHING2_ROOMMEMBER_BIN_ATTR_INTERNAL_MAX_SIZE
];
4878 pUserDataParams
->m_binAttrInternal
[a
].size
= SCE_NP_MATCHING2_ROOMMEMBER_BIN_ATTR_INTERNAL_MAX_SIZE
;
4880 pUserDataParams
->m_userDataRequest
.roomMemberBinAttrInternalNum
= SCE_NP_MATCHING2_ROOMMEMBER_BIN_ATTR_INTERNAL_NUM
;
4882 StartSubTask(eST_WaitingForUserDataRequestCallback
, mmTaskID
);
4884 int ret
= sceNpMatching2SetRoomMemberDataInternal(m_pPSNSupport
->GetMatchmakingContextId(), &pUserDataParams
->m_userDataRequest
, NULL
, &pTask
->m_reqId
);
4887 //-- Waiting for callback
4891 NetLog("sceNpMatching2SetRoomMemberDataInternal : error %08X", ret
);
4892 if (!m_pPSNSupport
->HandlePSNError(ret
))
4894 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
4900 UpdateTaskError(mmTaskID
, eCLE_OutOfMemory
);
4905 UpdateTaskError(mmTaskID
, eCLE_OutOfMemory
);
4910 bool CCryPSNMatchMaking::EventRequestResponse_SetRoomMemberDataInternal(CCryPSNMatchMaking
* _this
, STask
* pTask
, CryMatchMakingTaskID taskId
, SCryPSNSupportCallbackEventData
& data
)
4913 assert(pTask
->subTask
== eST_WaitingForUserDataRequestCallback
);
4914 assert(data
.m_requestEvent
.m_event
== REQUEST_EVENT_SET_ROOM_MEMBER_DATA_INTERNAL
);
4915 assert(data
.m_requestEvent
.m_dataSize
== 0);
4917 if (data
.m_requestEvent
.m_error
== 0)
4919 // We don't really care if this SetRoomMemberDataInternal succeeds for fails, so we'll just mark the task as complete
4920 _this
->UpdateTaskError(taskId
, eCLE_Success
);
4921 _this
->StopTaskRunning(taskId
);
4923 // this event is handled
4928 // return false to let the default error handler work
4933 // END SESSION UPDATE USER ------------------------------------------------------------------------
4935 void CCryPSNMatchMaking::OnPacket(const TNetAddress
& addr
, CCryLobbyPacket
* pPacket
)
4937 CCrySharedLobbyPacket
* pSPacket
= (CCrySharedLobbyPacket
*)pPacket
;
4939 switch (pSPacket
->StartRead())
4941 #if NETWORK_HOST_MIGRATION
4942 case ePSNPT_HostMigrationStart
:
4943 ProcessHostMigrationStart(addr
, pSPacket
);
4946 case ePSNPT_HostMigrationServer
:
4947 ProcessHostMigrationFromServer(addr
, pSPacket
);
4951 case ePSNPT_JoinSessionAck
:
4952 ProcessSessionJoinHostAck(addr
, pSPacket
);
4956 CCryMatchMaking::OnPacket(addr
, pSPacket
);
4961 void CCryPSNMatchMaking::SessionUserDataEvent(ECryLobbySystemEvent event
, CryLobbySessionHandle h
, CryMatchMakingConnectionID id
)
4963 SSession
* pSession
= &m_sessions
[h
];
4965 if (pSession
->localFlags
& CRYSESSION_LOCAL_FLAG_USER_DATA_EVENTS_STARTED
)
4967 SCryUserInfoResult userInfo
;
4968 userInfo
.m_userID
= new SCryPSNUserID
;
4970 if (id
== CryMatchMakingInvalidConnectionID
)
4972 SSession::SLConnection
* pConnection
= &pSession
->localConnection
;
4973 GetRoomMemberData(h
, userInfo
, pConnection
->uid
);
4977 SSession::SRConnection
* pConnection
= &pSession
->remoteConnection
[id
];
4978 GetRoomMemberData(h
, userInfo
, pConnection
->uid
);
4981 CCryMatchMaking::SessionUserDataEvent(event
, h
, &userInfo
);
4985 void CCryPSNMatchMaking::InitialUserDataEvent(CryLobbySessionHandle h
)
4987 SSession
* pSession
= &m_sessions
[h
];
4989 pSession
->localFlags
|= CRYSESSION_LOCAL_FLAG_USER_DATA_EVENTS_STARTED
;
4991 SessionUserDataEvent(eCLSE_SessionUserJoin
, h
, CryMatchMakingInvalidConnectionID
);
4993 for (uint32 i
= 0; i
< MAX_LOBBY_CONNECTIONS
; i
++)
4995 SSession::SRConnection
* pConnection
= &pSession
->remoteConnection
[i
];
4997 if (pConnection
->used
)
4999 SessionUserDataEvent(eCLSE_SessionUserJoin
, h
, i
);
5004 #if NETWORK_HOST_MIGRATION
5005 void CCryPSNMatchMaking::HostMigrationInitialise(CryLobbySessionHandle h
, EDisconnectionCause cause
)
5007 SSession
* pSession
= &m_sessions
[h
];
5009 pSession
->hostMigrationInfo
.Reset();
5012 ECryLobbyError
CCryPSNMatchMaking::HostMigrationServer(SHostMigrationInfo
* pInfo
)
5014 ECryLobbyError error
= eCLE_Success
;
5018 CryLobbySessionHandle h
= GetSessionHandleFromGameSessionHandle(pInfo
->m_session
);
5019 if (h
!= CryLobbyInvalidSessionHandle
)
5021 SSession
* pSession
= &m_sessions
[h
];
5022 CryMatchMakingTaskID mmTaskID
;
5024 pSession
->localFlags
|= CRYSESSION_LOCAL_FLAG_HOST
;
5025 pSession
->hostConnectionID
= CryMatchMakingInvalidConnectionID
;
5026 error
= StartTask(eT_SessionMigrateHostServer
, false, pSession
->localConnection
.users
[0], &mmTaskID
, NULL
, h
, NULL
, NULL
);
5028 if (error
== eCLE_Success
)
5030 STask
* pTask
= &m_task
[mmTaskID
];
5031 #if HOST_MIGRATION_SOAK_TEST_BREAK_DETECTION
5032 DetectHostMigrationTaskBreak(h
, "HostMigrationServer()");
5034 pSession
->hostMigrationInfo
.m_taskID
= pTask
->lTaskID
;
5036 NetLog("[Host Migration]: matchmaking migrating " PRFORMAT_SH
" on the SERVER", PRARG_SH(h
));
5037 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning
, this, mmTaskID
);
5042 error
= eCLE_InvalidSession
;
5045 if (error
!= eCLE_Success
)
5047 NetLog("[Host Migration]: CCryPSNMatchMaking::HostMigrationServer(): " PRFORMAT_SH
", error %d", PRARG_SH(h
), error
);
5053 void CCryPSNMatchMaking::HostMigrationServerNT(CryMatchMakingTaskID mmTaskID
)
5055 STask
* task
= &m_task
[mmTaskID
];
5059 void CCryPSNMatchMaking::TickHostMigrationServerNT(CryMatchMakingTaskID mmTaskID
)
5061 STask
* pTask
= &m_task
[mmTaskID
];
5062 SSession
* pSession
= &m_sessions
[pTask
->session
];
5064 if (pTask
->canceled
)
5066 NetLog("[Host Migration]: TickHostMigrationServerNT() cancelled for " PRFORMAT_SH
" - bailing", PRARG_SH(pTask
->session
));
5067 StopTaskRunning(mmTaskID
);
5071 float timeout
= CLobbyCVars::Get().hostMigrationTimeout
* 1000.0f
;
5072 if (pTask
->GetTimer() > timeout
)
5074 StopTaskRunning(mmTaskID
);
5078 NetLog("[Host Migration]: matchmaking SERVER migrated " PRFORMAT_SH
" successfully - informing CLIENTS", PRARG_SH(pTask
->session
));
5080 const uint32 MaxBufferSize
= CryLobbyPacketHeaderSize
;
5081 uint8 buffer
[MaxBufferSize
];
5082 CCrySharedLobbyPacket packet
;
5084 packet
.SetWriteBuffer(buffer
, MaxBufferSize
);
5085 packet
.StartWrite(ePSNPT_HostMigrationServer
, true);
5087 #if !defined(CRYNETWORK_RELEASEBUILD)
5089 CCryMatchMaking::SSession
* pSession
= CCryMatchMaking::m_sessions
[pTask
->session
];
5090 for (uint32 i
= 0; i
< MAX_LOBBY_CONNECTIONS
; i
++)
5092 CCryMatchMaking::SSession::SRConnection
* pConnection
= pSession
->remoteConnection
[i
];
5094 if (pConnection
->used
)
5097 if (m_lobby
->AddressFromConnection(ip
, pConnection
->connectionID
))
5099 NetLog(" sending to " PRFORMAT_ADDR
" client, " PRFORMAT_MMCINFO
, PRARG_ADDR(ip
), PRARG_MMCINFO(CryMatchMakingConnectionID(i
), pConnection
->connectionID
, pConnection
->uid
));
5105 NetLog(" sending to %i clients", count
);
5108 SendToAll(mmTaskID
, &packet
, pTask
->session
, CryMatchMakingInvalidConnectionID
);
5109 m_lobby
->FlushMessageQueue();
5111 pSession
->hostMigrationInfo
.m_sessionMigrated
= true;
5112 pSession
->hostMigrationInfo
.m_matchMakingFinished
= true;
5113 StopTaskRunning(mmTaskID
);
5116 void CCryPSNMatchMaking::ProcessHostMigrationFromServer(const TNetAddress
& addr
, CCrySharedLobbyPacket
* pPacket
)
5118 CryLobbySessionHandle h
= CryLobbyInvalidSessionHandle
;
5119 SCryMatchMakingConnectionUID hostUID
= pPacket
->GetFromConnectionUID();
5120 CryMatchMakingConnectionID mmCxID
= CryMatchMakingInvalidConnectionID
;
5122 if (FindConnectionFromUID(hostUID
, &h
, &mmCxID
))
5124 SSession
* pSession
= &m_sessions
[h
];
5125 if (pSession
->localFlags
& CRYSESSION_LOCAL_FLAG_HOST
)
5127 NetLog("[Host Migration]: ignoring session details from " PRFORMAT_SHMMCINFO
" as I am already the server " PRFORMAT_UID
,
5128 PRARG_SHMMCINFO(h
, mmCxID
, pSession
->remoteConnection
[mmCxID
].connectionID
, hostUID
), PRARG_UID(pSession
->localConnection
.uid
));
5132 NetLog("[Host Migration]: matchmaking CLIENT received session details from " PRFORMAT_SHMMCINFO
" - migrating to new PSN session",
5133 PRARG_SHMMCINFO(h
, mmCxID
, pSession
->remoteConnection
[mmCxID
].connectionID
, hostUID
));
5134 NetLog("[Host Migration]: matchmaking CLIENT received server confirmation for " PRFORMAT_SH
" - migrating to new session", PRARG_SH(h
));
5136 SSession
* pSession
= &m_sessions
[h
];
5137 if (pSession
->hostMigrationInfo
.m_state
== eHMS_Idle
)
5139 NetLog("[Host Migration]: received server confirmation before host migration initiated - initiating now");
5140 HostMigrationInitiate(h
, eDC_Unknown
);
5143 pSession
->localFlags
&= ~CRYSESSION_LOCAL_FLAG_HOST
;
5144 pSession
->hostMigrationInfo
.m_sessionMigrated
= true;
5145 pSession
->hostMigrationInfo
.m_matchMakingFinished
= true;
5147 if (pSession
->m_ownerMemberId
== hostUID
.m_uid
)
5149 pSession
->hostMigrationInfo
.m_newHostAddressValid
= true;
5155 NetLog("[Host Migration]: received server notification from unknown host " PRFORMAT_UID
, PRARG_UID(hostUID
));
5159 bool CCryPSNMatchMaking::GetNewHostAddress(char* address
, SHostMigrationInfo
* pInfo
)
5161 bool success
= false;
5163 CryLobbySessionHandle sessionIndex
= GetSessionHandleFromGameSessionHandle(pInfo
->m_session
);
5164 SSession
* pSession
= &m_sessions
[sessionIndex
];
5165 SHostMigrationInfo_Private
* pPrivateInfo
= &pSession
->hostMigrationInfo
;
5167 if ((pSession
->localFlags
& CRYSESSION_LOCAL_FLAG_USED
) && pPrivateInfo
->m_newHostAddressValid
)
5172 const SSession::SRoomMember
* const pMember
= FindRoomMemberFromRoomMemberID(sessionIndex
, pSession
->m_ownerMemberId
);
5176 if (pSession
->serverConnectionID
!= CryMatchMakingInvalidConnectionID
)
5178 if (pSession
->desiredHostUID
!= CryMatchMakingInvalidConnectionUID
)
5180 if ((pMember
->m_valid
& ePSNMI_Me
) == 0) // Make sure we are not the new host before updating the connection information
5182 if (!pSession
->hostMigrationInfo
.m_matchMakingFinished
)
5184 CryMatchMakingConnectionID remoteConnectionID
= FindConnectionIDFromRoomMemberID(sessionIndex
, pSession
->m_ownerMemberId
);
5185 if (remoteConnectionID
!= CryMatchMakingInvalidConnectionID
)
5187 pInfo
->SetIsNewHost(false);
5188 success
= (pSession
->remoteConnection
[remoteConnectionID
].uid
== pSession
->desiredHostUID
);
5190 NetLog("[Host Migration]: new host for session " PRFORMAT_SH
" host uid " PRFORMAT_UID
" desired uid " PRFORMAT_UID
, PRARG_SH(sessionIndex
), PRARG_UID(pSession
->remoteConnection
[remoteConnectionID
].uid
), PRARG_UID(pSession
->desiredHostUID
));
5194 NetLog("[Host Migration]: failed to find connection for new host " PRFORMAT_UID
" of session " PRFORMAT_SH
, PRARG_UID(pSession
->desiredHostUID
), PRARG_SH(sessionIndex
));
5199 NetLog("[Host Migration]: matchmaking not finished desiredHostUID " PRFORMAT_UID
" newHostUID " PRFORMAT_UID
, PRARG_UID(pSession
->desiredHostUID
), PRARG_UID(pSession
->newHostUID
));
5205 pInfo
->SetIsNewHost(true);
5206 success
= (pSession
->localConnection
.uid
== pSession
->desiredHostUID
);
5208 NetLog("[Host Migration]: becoming the new host for session " PRFORMAT_SH
" host uid " PRFORMAT_UID
" desired uid " PRFORMAT_UID
, PRARG_SH(sessionIndex
), PRARG_UID(pSession
->localConnection
.uid
), PRARG_UID(pSession
->desiredHostUID
));
5215 if (pMember
->m_signalingState
== ePSNCS_Active
)
5217 myIP
= pMember
->m_peerAddr
.s_addr
;
5218 myPort
= pMember
->m_peerPort
;
5220 if ((pMember
->m_valid
& ePSNMI_Me
) == 0) // Make sure we are not the new host before updating the connection information
5222 if (!pSession
->hostMigrationInfo
.m_matchMakingFinished
)
5224 pInfo
->SetIsNewHost(false);
5225 // Wait until the server has notified us that migration has completed
5229 NetLog("[Host Migration]: new host is uid %i " PRFORMAT_SH
, pSession
->m_ownerMemberId
, PRARG_SH(sessionIndex
));
5230 m_lobby
->DecodeAddress(myIP
, myPort
, address
, false);
5234 // We are the new host, we should return quickly
5235 pInfo
->SetIsNewHost(true);
5236 NetLog("[Host Migration]: becoming the new host for " PRFORMAT_SH
"...", PRARG_SH(sessionIndex
));
5238 const SCryLobbyParameters
& lobbyParams
= m_lobby
->GetLobbyParameters();
5239 uint16 port
= lobbyParams
.m_listenPort
;
5240 cry_sprintf(address
, HOST_MIGRATION_MAX_SERVER_NAME_SIZE
, "%s:%d", LOCAL_CONNECTION_STRING
, port
);
5244 NetLog("[Host Migration]: Using %s as connection address", address
);
5251 void CCryPSNMatchMaking::HostMigrationStartNT(CryMatchMakingTaskID mmTaskID
)
5253 STask
* pTask
= &m_task
[mmTaskID
];
5254 SSession
* pSession
= &m_sessions
[pTask
->session
];
5256 // Ensure we're the host and we've not started the session
5257 if ((pSession
->localFlags
& (CRYSESSION_LOCAL_FLAG_HOST
| CRYSESSION_LOCAL_FLAG_STARTED
)) == CRYSESSION_LOCAL_FLAG_HOST
)
5259 // Determine if host hinting has a better host
5260 SHostHintInformation newHost
;
5261 CryMatchMakingConnectionID newHostID
;
5262 if (FindConnectionFromSessionUID(pTask
->session
, pSession
->newHostUID
, &newHostID
))
5264 SSession::SRConnection
* pConnection
= &pSession
->remoteConnection
[newHostID
];
5265 newHost
= pConnection
->hostHintInfo
;
5268 bool isBetterHost
= false;
5269 if (SortNewHostPriorities_ComparatorHelper(newHost
, pSession
->hostHintInfo
) < 0)
5271 isBetterHost
= true;
5276 pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_GRANTROOM_REQUEST_SLOT
] = m_lobby
->MemAlloc(sizeof(SGrantRoomOwnerParamData
));
5277 if (pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_GRANTROOM_REQUEST_SLOT
] != TMemInvalidHdl
)
5279 if (HostMigrationInitiate(pTask
->session
, eDC_Unknown
))
5281 const uint32 maxBufferSize
= CryLobbyPacketHeaderSize
;
5282 uint8 buffer
[maxBufferSize
];
5283 CCryLobbyPacket packet
;
5285 NetLog("[Host Migration]: local server is not best host for " PRFORMAT_SH
"- instructing clients to choose new host (sent from " PRFORMAT_UID
")", PRARG_SH(pTask
->session
), PRARG_UID(pSession
->localConnection
.uid
));
5286 packet
.SetWriteBuffer(buffer
, maxBufferSize
);
5287 packet
.StartWrite(ePSNPT_HostMigrationStart
, true);
5289 SendToAll(mmTaskID
, &packet
, pTask
->session
, CryMatchMakingInvalidConnectionID
);
5290 pSession
->localFlags
&= ~CRYSESSION_LOCAL_FLAG_HOST
;
5292 SGrantRoomOwnerParamData
* pGrantRoomOwnerData
= (SGrantRoomOwnerParamData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_GRANTROOM_REQUEST_SLOT
]);
5293 memset(pGrantRoomOwnerData
, 0, sizeof(SGrantRoomOwnerParamData
));
5295 pGrantRoomOwnerData
->m_reqParam
.roomId
= pSession
->m_roomId
;
5296 pGrantRoomOwnerData
->m_reqParam
.newOwner
= (SceNpMatching2RoomMemberId
)(pSession
->newHostUID
.m_uid
);
5298 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
5302 NetLog("[Host Migration]: local server is not best host for " PRFORMAT_SH
", but session is not migratable", PRARG_SH(pTask
->session
));
5303 UpdateTaskError(mmTaskID
, eCLE_SessionNotMigratable
);
5304 StopTaskRunning(mmTaskID
);
5309 UpdateTaskError(mmTaskID
, eCLE_OutOfMemory
);
5312 if (pTask
->error
!= eCLE_Success
)
5314 StopTaskRunning(mmTaskID
);
5319 NetLog("[Host Migration]: local server is best host for " PRFORMAT_SH
, PRARG_SH(pTask
->session
));
5320 StopTaskRunning(mmTaskID
);
5325 if (pSession
->localFlags
& CRYSESSION_LOCAL_FLAG_STARTED
)
5327 NetLog("[Host Migration]: SessionEnsureBestHost() called after the session had started");
5330 StopTaskRunning(mmTaskID
);
5334 void CCryPSNMatchMaking::TickHostMigrationStartNT(CryMatchMakingTaskID mmTaskID
)
5336 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
5337 if (m_pPSNSupport
->HasTransitioningReachedState(ePSNOS_Matchmaking_Available
))
5339 STask
* pTask
= &m_task
[mmTaskID
];
5341 if (pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_GRANTROOM_REQUEST_SLOT
] != TMemInvalidHdl
)
5343 SGrantRoomOwnerParamData
* pGrantRoomOwnerData
= (SGrantRoomOwnerParamData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_GRANTROOM_REQUEST_SLOT
]);
5345 StartSubTask(eST_WaitingForGrantRoomOwnerRequestCallback
, mmTaskID
);
5347 int ret
= sceNpMatching2GrantRoomOwner(m_pPSNSupport
->GetMatchmakingContextId(), &pGrantRoomOwnerData
->m_reqParam
, NULL
, &pTask
->m_reqId
);
5350 //-- waiting for callback
5354 NetLog("sceNpMatching2GrantRoomOwnerRequest : error %08X", ret
);
5355 //-- triggering a PSN error will cause an error event into SupportCallback() and set a task error if it needs to clean up.
5356 //-- otherwise, we have to update the task error ourself.
5357 if (!m_pPSNSupport
->HandlePSNError(ret
))
5359 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
5365 UpdateTaskError(mmTaskID
, eCLE_OutOfMemory
);
5370 bool CCryPSNMatchMaking::EventRequestResponse_GrantRoomOwner(CCryPSNMatchMaking
* _this
, STask
* pTask
, CryMatchMakingTaskID taskId
, SCryPSNSupportCallbackEventData
& data
)
5373 assert(pTask
->subTask
== eST_WaitingForGrantRoomOwnerRequestCallback
);
5374 assert(data
.m_requestEvent
.m_event
== REQUEST_EVENT_GRANT_ROOM_OWNER
);
5375 assert(data
.m_requestEvent
.m_dataSize
== 0);
5377 // We don't really care if this GrantRoomOwnerRequest succeeds for fails, so we'll just mark the task as complete
5378 _this
->UpdateTaskError(taskId
, eCLE_Success
);
5379 _this
->StopTaskRunning(taskId
);
5381 // this event is handled
5385 void CCryPSNMatchMaking::ProcessHostMigrationStart(const TNetAddress
& addr
, CCrySharedLobbyPacket
* pPacket
)
5387 CryLobbySessionHandle h
= CryLobbyInvalidSessionHandle
;
5388 SCryMatchMakingConnectionUID hostUID
= pPacket
->GetFromConnectionUID();
5389 CryMatchMakingConnectionID mmCxID
= CryMatchMakingInvalidConnectionID
;
5391 if (FindConnectionFromUID(hostUID
, &h
, &mmCxID
))
5393 SSession
* pSession
= &m_sessions
[h
];
5395 NetLog("[Host Migration]: received host migration push event for " PRFORMAT_SHMMCINFO
, PRARG_SHMMCINFO(h
, mmCxID
, pSession
->remoteConnection
[mmCxID
].connectionID
, hostUID
));
5397 if (pSession
->IsUsed() && !(pSession
->localFlags
& CRYSESSION_LOCAL_FLAG_HOST
))
5399 if (pSession
->hostMigrationInfo
.m_state
== eHMS_Idle
)
5401 NetLog("[Host Migration]: remote server is not best host for " PRFORMAT_SH
" - instructed to choose new host", PRARG_SH(h
));
5402 HostMigrationInitiate(h
, eDC_Unknown
);
5406 NetLog("[Host Migration]: ignoring pushed migration event - already migrating " PRFORMAT_SH
, PRARG_SH(h
));
5412 NetLog("[Host Migration]: received push migration event from unknown host " PRFORMAT_UID
, PRARG_UID(hostUID
));
5415 #endif // NETWORK_HOST_MIGRATION
5417 ECryLobbyError
CCryPSNMatchMaking::SessionEnsureBestHost(CrySessionHandle gh
, CryLobbyTaskID
* pTaskID
, CryMatchmakingCallback pCB
, void* pCBArg
)
5419 ECryLobbyError rc
= eCLE_Success
;
5421 #if NETWORK_HOST_MIGRATION
5424 CryLobbySessionHandle h
= GetSessionHandleFromGameSessionHandle(gh
);
5426 if (h
!= CryLobbyInvalidSessionHandle
)
5428 CryMatchMakingTaskID mmTaskID
;
5429 SSession
* pSession
= &m_sessions
[h
];
5430 rc
= StartTask(eT_SessionMigrateHostStart
, false, pSession
->localConnection
.users
[0], &mmTaskID
, pTaskID
, h
, (void*)pCB
, pCBArg
);
5432 if (rc
== eCLE_Success
)
5434 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning
, this, mmTaskID
);
5442 void CCryPSNMatchMaking::AddVoiceUser(SSession::SRoomMember
* pMember
)
5445 CCryPSNVoice
* pVoice
= (CCryPSNVoice
*)m_pService
->GetVoice();
5448 assert(pMember
->IsValid(ePSNMI_Other
));
5449 pVoice
->AddRemoteTalker(pMember
->m_npId
, pMember
->m_peerAddr
, pMember
->m_peerPort
, (pMember
->m_signalingState
== ePSNCS_Active
) ? true : false);
5451 #endif // USE_PSN_VOICE
5454 void CCryPSNMatchMaking::ClearVoiceUser(SSession::SRoomMember
* pMember
)
5457 CCryPSNVoice
* pVoice
= (CCryPSNVoice
*)m_pService
->GetVoice();
5460 assert(pMember
->m_valid
& ePSNMI_Other
);
5461 pVoice
->ClearRemoteTalker(pMember
->m_npId
);
5463 #endif // USE_PSN_VOICE
5466 void CCryPSNMatchMaking::UpdateVoiceUsers()
5469 CCryPSNVoice
* pVoice
= (CCryPSNVoice
*)m_pService
->GetVoice();
5472 bool bNeedsVoice
= false;
5474 for (uint32 i
= 0; ((i
< MAX_MATCHMAKING_SESSIONS
) && (bNeedsVoice
== false)); i
++)
5476 SSession
* pSession
= &m_sessions
[i
];
5477 if (pSession
->IsUsed())
5479 for (uint32 j
= 0; j
< MAX_PSN_ROOM_MEMBERS
; j
++)
5481 SSession::SRoomMember
* pMember
= &pSession
->m_members
[j
];
5482 if (pMember
->IsValid(ePSNMI_Other
))
5491 if (bNeedsVoice
&& !m_pPSNSupport
->IsChatRestricted())
5497 pVoice
->Deactivate();
5500 #endif //USE_PSN_VOICE
5503 ECryLobbyError
CCryPSNMatchMaking::CopySessionIDToBuffer(CrySessionID sessionId
, void* pBuffer
, size_t& bufferSize
)
5505 if (SCryPSNSessionID
* pData
= (SCryPSNSessionID
*)sessionId
.get())
5507 size_t requiredSize
= sizeof(SCryPSNSessionID
);
5508 if (bufferSize
>= requiredSize
)
5510 memcpy(pBuffer
, pData
, requiredSize
);
5511 bufferSize
= requiredSize
;
5512 return eCLE_Success
;
5516 return eCLE_OutOfMemory
;
5519 return eCLE_InvalidSession
;
5522 ECryLobbyError
CCryPSNMatchMaking::CopySessionIDFromBuffer(const void* pBuffer
, size_t bufferSize
, CrySessionID
& sessionId
)
5524 size_t requiredSize
= sizeof(SCryPSNSessionID
);
5525 if (bufferSize
== requiredSize
)
5527 SCryPSNSessionID
* pData
= new SCryPSNSessionID();
5528 // cppcheck-suppress memsetClass (if used in conjunction with CopySessionIDToBuffer(), this is ok)
5529 memcpy(pData
, pBuffer
, requiredSize
);
5531 return eCLE_Success
;
5533 return eCLE_InvalidParam
;
5536 void CCryPSNMatchMaking::ForceFromInvite(CrySessionID sessionId
)
5538 if (SCryPSNSessionID
* pData
= (SCryPSNSessionID
*)sessionId
.get())
5540 pData
->m_fromInvite
= true;
5544 ECryLobbyError
CCryPSNMatchMaking::SessionSetAdvertisementData(CrySessionHandle gh
, uint8
* pData
, uint32 dataSize
, CryLobbyTaskID
* pTaskID
, CryMatchmakingCallback pCb
, void* pCbArg
)
5548 ECryLobbyError rc
= eCLE_InvalidSession
;
5549 CryLobbySessionHandle h
= GetSessionHandleFromGameSessionHandle(gh
);
5550 if (h
!= CryLobbyInvalidSessionHandle
)
5552 CryMatchMakingTaskID mmTaskID
;
5553 SSession
* pSession
= &m_sessions
[h
];
5554 rc
= StartTask(eT_SessionSetAdvertisementData
, false, 0, &mmTaskID
, pTaskID
, h
, (void*)pCb
, pCbArg
);
5555 if (rc
== eCLE_Success
)
5557 rc
= CreateTaskParam(mmTaskID
, PSN_MATCHMAKING_PSNSUPPORT_UPDATEADVERT_REQUEST_SLOT
, NULL
, 1, sizeof(SUpdateAdvertisementDataParamData
));
5558 if (rc
== eCLE_Success
)
5560 rc
= CreateTaskParam(mmTaskID
, PSN_MATCHMAKING_WEBAPI_UPDATEADVERT_REQUEST_SLOT
, NULL
, 1, sizeof(SCryPSNOrbisWebApiUpdateSessionInput
));
5561 if (rc
== eCLE_Success
)
5563 SCryPSNOrbisWebApiUpdateSessionInput
* pAdvertInput
= (SCryPSNOrbisWebApiUpdateSessionInput
*)m_lobby
->MemGetPtr(m_task
[mmTaskID
].params
[PSN_MATCHMAKING_WEBAPI_UPDATEADVERT_REQUEST_SLOT
]);
5564 memset(pAdvertInput
, 0, sizeof(SCryPSNOrbisWebApiUpdateSessionInput
));
5566 memcpy(&pAdvertInput
->sessionId
, &pSession
->m_sessionId
, sizeof(SceNpSessionId
));
5568 pAdvertInput
->advertisement
.m_pData
= pAdvertInput
->data
;
5569 pAdvertInput
->advertisement
.m_sizeofData
= MIN(dataSize
, CRY_WEBAPI_UPDATESESSION_LINKDATA_MAX_SIZE
);
5570 memcpy(pAdvertInput
->data
, pData
, pAdvertInput
->advertisement
.m_sizeofData
);
5572 SConfigurationParams neededInfo
= {
5573 CLCC_PSN_UPDATE_SESSION_ADVERTISEMENT
, { NULL
}
5575 neededInfo
.m_pData
= (void*)&pAdvertInput
->advertisement
;
5576 m_lobby
->GetConfigurationInformation(&neededInfo
, 1);
5578 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
5580 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning
, this, mmTaskID
);
5584 if (rc
!= eCLE_Success
)
5594 void CCryPSNMatchMaking::TickSessionSetAdvertisementData(CryMatchMakingTaskID mmTaskID
)
5596 STask
* pTask
= &m_task
[mmTaskID
];
5598 if (pTask
->error
== eCLE_Success
)
5600 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
5601 if (m_pPSNSupport
->HasTransitioningReachedState(ePSNOS_Matchmaking_Available
))
5603 if ((pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_UPDATEADVERT_REQUEST_SLOT
] != TMemInvalidHdl
) &&
5604 (pTask
->params
[PSN_MATCHMAKING_WEBAPI_UPDATEADVERT_REQUEST_SLOT
] != TMemInvalidHdl
))
5606 SUpdateAdvertisementDataParamData
* pParam
= (SUpdateAdvertisementDataParamData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_UPDATEADVERT_REQUEST_SLOT
]);
5608 StartSubTask(eST_WaitingForUpdateAdvertisementDataWebApiCallback
, mmTaskID
);
5610 pParam
->m_jobId
= m_pPSNSupport
->GetWebApiInterface().AddJob(CCryPSNOrbisWebApiThread::UpdateSession
, pTask
->params
[PSN_MATCHMAKING_WEBAPI_UPDATEADVERT_REQUEST_SLOT
]);
5611 if (pParam
->m_jobId
!= INVALID_WEBAPI_JOB_ID
)
5613 //-- waiting for callback
5617 // error - didn't add webapi job
5618 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
5623 // error - bad param slots
5624 UpdateTaskError(mmTaskID
, eCLE_OutOfMemory
);
5629 if ((pTask
->error
!= eCLE_Success
) || pTask
->canceled
)
5631 StopTaskRunning(mmTaskID
);
5635 void CCryPSNMatchMaking::EventWebApiUpdateSessionAdvertisement(CryMatchMakingTaskID mmTaskID
, SCryPSNSupportCallbackEventData
& data
)
5637 STask
* pTask
= &m_task
[mmTaskID
];
5639 if (pTask
->session
!= CryLobbyInvalidSessionHandle
)
5641 if (data
.m_webApiEvent
.m_error
== PSN_OK
)
5643 // not expecting a response body, just mark task successful and stop
5644 UpdateTaskError(mmTaskID
, eCLE_Success
);
5645 StopTaskRunning(mmTaskID
);
5650 // something went wrong
5651 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
5652 StopTaskRunning(mmTaskID
);
5655 void CCryPSNMatchMaking::EndSessionSetAdvertisementData(CryMatchMakingTaskID mmTaskID
)
5657 STask
* pTask
= &m_task
[mmTaskID
];
5658 ((CryMatchmakingCallback
)pTask
->cb
)(pTask
->lTaskID
, pTask
->error
, pTask
->cbArg
);
5661 ECryLobbyError
CCryPSNMatchMaking::SessionGetAdvertisementData(CrySessionID sessionId
, CryLobbyTaskID
* pTaskID
, CryMatchmakingSessionGetAdvertisementDataCallback pCb
, void* pCbArg
)
5665 ECryLobbyError rc
= eCLE_InvalidSession
;
5666 if (sessionId
!= CrySessionInvalidID
)
5668 CryMatchMakingTaskID mmTaskID
;
5669 rc
= StartTask(eT_SessionGetAdvertisementData
, false, 0, &mmTaskID
, pTaskID
, CryLobbyInvalidSessionHandle
, (void*)pCb
, pCbArg
);
5670 if (rc
== eCLE_Success
)
5672 rc
= CreateTaskParam(mmTaskID
, PSN_MATCHMAKING_PSNSUPPORT_GETADVERT_REQUEST_SLOT
, NULL
, 1, sizeof(SGetAdvertisementDataParamData
));
5673 if (rc
== eCLE_Success
)
5675 rc
= CreateTaskParam(mmTaskID
, PSN_MATCHMAKING_WEBAPI_GETADVERT_REQUEST_SLOT
, NULL
, 1, sizeof(SCryPSNOrbisWebApiGetSessionLinkDataInput
));
5676 if (rc
== eCLE_Success
)
5678 SCryPSNSessionID
* pPSNSessionId
= (SCryPSNSessionID
*)sessionId
.get();
5679 SCryPSNOrbisWebApiGetSessionLinkDataInput
* pAdvertInput
= (SCryPSNOrbisWebApiGetSessionLinkDataInput
*)m_lobby
->MemGetPtr(m_task
[mmTaskID
].params
[PSN_MATCHMAKING_WEBAPI_GETADVERT_REQUEST_SLOT
]);
5680 memcpy(&pAdvertInput
->sessionId
, &pPSNSessionId
->m_sessionId
, sizeof(SceNpSessionId
));
5682 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
5684 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning
, this, mmTaskID
);
5688 if (rc
!= eCLE_Success
)
5695 NetLog("[Lobby] Start SessionGetAdvertisementData error %d", rc
);
5699 void CCryPSNMatchMaking::TickSessionGetAdvertisementData(CryMatchMakingTaskID mmTaskID
)
5701 STask
* pTask
= &m_task
[mmTaskID
];
5703 if (pTask
->error
== eCLE_Success
)
5705 m_pPSNSupport
->ResumeTransitioning(ePSNOS_Matchmaking_Available
);
5706 if (m_pPSNSupport
->HasTransitioningReachedState(ePSNOS_Matchmaking_Available
))
5708 if ((pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_GETADVERT_REQUEST_SLOT
] != TMemInvalidHdl
) &&
5709 (pTask
->params
[PSN_MATCHMAKING_WEBAPI_GETADVERT_REQUEST_SLOT
] != TMemInvalidHdl
))
5711 SGetAdvertisementDataParamData
* pParam
= (SGetAdvertisementDataParamData
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_PSNSUPPORT_GETADVERT_REQUEST_SLOT
]);
5713 StartSubTask(eST_WaitingForGetAdvertisementDataWebApiCallback
, mmTaskID
);
5715 pParam
->m_jobId
= m_pPSNSupport
->GetWebApiInterface().AddJob(CCryPSNOrbisWebApiThread::GetSessionLinkData
, pTask
->params
[PSN_MATCHMAKING_WEBAPI_GETADVERT_REQUEST_SLOT
]);
5716 if (pParam
->m_jobId
!= INVALID_WEBAPI_JOB_ID
)
5718 //-- waiting for callback
5722 // error - didnt queue webapi job
5723 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
5728 // error - no slots allocated
5729 UpdateTaskError(mmTaskID
, eCLE_OutOfMemory
);
5734 if ((pTask
->error
!= eCLE_Success
) || pTask
->canceled
)
5736 StopTaskRunning(mmTaskID
);
5740 void CCryPSNMatchMaking::EventWebApiGetSessionLinkData(CryMatchMakingTaskID mmTaskID
, SCryPSNSupportCallbackEventData
& data
)
5742 STask
* pTask
= &m_task
[mmTaskID
];
5744 if (data
.m_webApiEvent
.m_error
== PSN_OK
)
5746 if (data
.m_webApiEvent
.m_pResponseBody
)
5748 if ((data
.m_webApiEvent
.m_pResponseBody
->eType
== SCryPSNWebApiResponseBody::E_RAW
) &&
5749 (data
.m_webApiEvent
.m_pResponseBody
->rawResponseBodyHdl
!= TMemInvalidHdl
) &&
5750 (data
.m_webApiEvent
.m_pResponseBody
->rawResponseBodySize
> 0))
5753 pTask
->params
[PSN_MATCHMAKING_WEBAPI_GETADVERT_RESPONSE_SLOT
] = data
.m_webApiEvent
.m_pResponseBody
->rawResponseBodyHdl
;
5754 pTask
->numParams
[PSN_MATCHMAKING_WEBAPI_GETADVERT_RESPONSE_SLOT
] = (uint32
)data
.m_webApiEvent
.m_pResponseBody
->rawResponseBodySize
;
5756 // We don't want the data to be deleted when this function returns since we copied the handle.
5757 // If we invalidate the handle, it won't be deleted when the event is cleared up.
5758 data
.m_webApiEvent
.m_pResponseBody
->rawResponseBodyHdl
= TMemInvalidHdl
;
5759 data
.m_webApiEvent
.m_pResponseBody
->rawResponseBodySize
= 0;
5761 UpdateTaskError(mmTaskID
, eCLE_Success
);
5762 StopTaskRunning(mmTaskID
);
5768 // something went wrong
5769 UpdateTaskError(mmTaskID
, eCLE_InternalError
);
5770 StopTaskRunning(mmTaskID
);
5773 void CCryPSNMatchMaking::EndSessionGetAdvertisementData(CryMatchMakingTaskID mmTaskID
)
5775 uint8
* pData
= NULL
;
5776 uint32 dataSize
= 0;
5778 STask
* pTask
= &m_task
[mmTaskID
];
5779 if (pTask
->error
== eCLE_Success
)
5781 pData
= (uint8
*)m_lobby
->MemGetPtr(pTask
->params
[PSN_MATCHMAKING_WEBAPI_GETADVERT_RESPONSE_SLOT
]);
5782 dataSize
= pTask
->numParams
[PSN_MATCHMAKING_WEBAPI_GETADVERT_RESPONSE_SLOT
];
5785 ((CryMatchmakingSessionGetAdvertisementDataCallback
)pTask
->cb
)(pTask
->lTaskID
, pTask
->error
, pData
, dataSize
, pTask
->cbArg
);
5788 #endif // USE_CRY_MATCHMAKING
5790 #endif // CRY_PLATFORM_ORBIS