1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
|
#pragma once
#include <np.h>
#ifdef __PS3__
#include <netex\libnetctl.h>
#include <netex\net.h>
#else
#include <libnetctl.h>
#include <net.h>
#include <np_toolkit.h>
#endif
#include <queue>
#include <unordered_map>
#if defined __PSVITA__
#include "..\..\Minecraft.Client\PSVita\4JLibs\inc\4J_Profile.h"
#endif
class SQRNetworkPlayer;
class ISQRNetworkManagerListener;
class SonyVoiceChat;
class C4JThread;
// This is the lowest level manager for providing network functionality on Sony platforms. This manages various network activities including the players within a gaming session.
// The game shouldn't directly use this class, it is here to provide functionality required by PlatformNetworkManagerSony.
class SQRNetworkManager
{
public:
static const int MAX_LOCAL_PLAYER_COUNT = XUSER_MAX_COUNT;
static const int MAX_ONLINE_PLAYER_COUNT = MINECRAFT_NET_MAX_PLAYERS;
static const int NP_POOL_SIZE = 128 * 1024;
protected:
friend class SQRNetworkPlayer;
friend class SonyVoiceChat;
#ifdef __PSVITA__
friend class HelloSyncInfo;
#endif
static const int MAX_FRIENDS = 100;
#ifdef __PS3__
static const int RUDP_THREAD_PRIORITY = 999;
#else // __ORBIS_
static const int RUDP_THREAD_PRIORITY = 500;
#endif
static const int RUDP_THREAD_STACK_SIZE = 32878;
static const int MAX_SIMULTANEOUS_INVITES = 10;
// This class stores everything about a player that must be synchronised between machines. This syncing is carried out
// by the Matching2 lib by using internal room binary data (ie data that is only visible to current members of a room)
class PlayerSyncData
{
public:
PlayerUID m_UID; // Assigned by the associated player->GetUID()
SceNpMatching2RoomMemberId m_roomMemberId; // Assigned by Matching2 lib, we can use to indicate which machine this player belongs to (note - 16 bits)
unsigned char m_smallId; // Assigned by SQRNetworkManager, to attach a permanent id to this player (until we have to wrap round), to match a similar concept in qnet
unsigned char m_localIdx : 4; // Which local player (by controller index) this represents
unsigned char m_playerCount : 4;
};
class RoomSyncData
{
public:
PlayerSyncData players[MAX_ONLINE_PLAYER_COUNT];
void setPlayerCount(int c) { players[0].m_playerCount = c;}
int getPlayerCount() { return players[0].m_playerCount;}
};
public:
class PresenceSyncInfo
{
public:
GameSessionUID hostPlayerUID;
SceNpMatching2RoomId m_RoomId;
SceNpMatching2ServerId m_ServerId;
unsigned int texturePackParentId;
unsigned short netVersion;
unsigned char subTexturePackId;
bool inviteOnly;
};
// Externally exposed state. All internal states are mapped to one of these broader states.
typedef enum
{
SNM_STATE_INITIALISING,
SNM_STATE_INITIALISE_FAILED,
SNM_STATE_IDLE,
SNM_STATE_HOSTING,
SNM_STATE_JOINING,
SNM_STATE_STARTING,
SNM_STATE_PLAYING,
SNM_STATE_LEAVING,
SNM_STATE_ENDING,
} eSQRNetworkManagerState;
struct SessionID
{
SceNpMatching2RoomId m_RoomId;
SceNpMatching2ServerId m_ServerId;
};
struct SessionSearchResult
{
SceNpId m_NpId;
SessionID m_sessionId;
void *m_extData;
#ifdef __PSVITA__
SceNetInAddr m_netAddr;
#endif
};
protected:
// On initialisation, state should transition from SNM_INT_STATE_UNINITIALISED -> SNM_INT_STATE_SIGNING_IN -> SNM_INT_STATE_SIGNED_IN -> SNM_INT_STATE_STARTING_CONTEXT -> SNM_INT_STATE_IDLE.
// Error indicated if we transition at any point to SNM_INT_STATE_INITIALISE_FAILED.
// NOTE: If anything changes in here, then the mapping from internal -> external state needs to be updated (m_INTtoEXTStateMappings, defined in the cpp file)
typedef enum
{
SNM_INT_STATE_UNINITIALISED,
SNM_INT_STATE_SIGNING_IN,
SNM_INT_STATE_STARTING_CONTEXT,
SNM_INT_STATE_INITIALISE_FAILED,
SNM_INT_STATE_IDLE,
SNM_INT_STATE_IDLE_RECREATING_MATCHING_CONTEXT,
SNM_INT_STATE_HOSTING_STARTING_MATCHING_CONTEXT,
SNM_INT_STATE_HOSTING_SEARCHING_FOR_SERVER,
SNM_INT_STATE_HOSTING_SERVER_SEARCH_SERVER_ERROR,
SNM_INT_STATE_HOSTING_SERVER_FOUND,
SNM_INT_STATE_HOSTING_SERVER_SEARCH_CREATING_CONTEXT,
SNM_INT_STATE_HOSTING_SERVER_SEARCH_FAILED,
SNM_INT_STATE_HOSTING_CREATE_ROOM_SEARCHING_FOR_WORLD,
SNM_INT_STATE_HOSTING_CREATE_ROOM_WORLD_FOUND,
SNM_INT_STATE_HOSTING_CREATE_ROOM_CREATING_ROOM,
SNM_INT_STATE_HOSTING_CREATE_ROOM_SUCCESS,
SNM_INT_STATE_HOSTING_CREATE_ROOM_FAILED,
SNM_INT_STATE_HOSTING_CREATE_ROOM_RESTART_MATCHING_CONTEXT,
SNM_INT_STATE_HOSTING_WAITING_TO_PLAY,
SNM_INT_STATE_JOINING_STARTING_MATCHING_CONTEXT,
SNM_INT_STATE_JOINING_SEARCHING_FOR_SERVER,
SNM_INT_STATE_JOINING_SERVER_SEARCH_SERVER_ERROR,
SNM_INT_STATE_JOINING_SERVER_FOUND,
SNM_INT_STATE_JOINING_SERVER_SEARCH_CREATING_CONTEXT,
SNM_INT_STATE_JOINING_SERVER_SEARCH_FAILED,
SNM_INT_STATE_JOINING_JOIN_ROOM,
SNM_INT_STATE_JOINING_JOIN_ROOM_FAILED,
SNM_INT_STATE_JOINING_WAITING_FOR_LOCAL_PLAYERS,
SNM_INT_STATE_SERVER_DELETING_CONTEXT,
SNM_INT_STATE_STARTING,
SNM_INT_STATE_PLAYING,
SNM_INT_STATE_LEAVING,
SNM_INT_STATE_LEAVING_FAILED,
SNM_INT_STATE_ENDING,
SNM_INT_STATE_COUNT
} eSQRNetworkManagerInternalState;
typedef enum
{
SNM_FORCE_ERROR_NP2_INIT,
SNM_FORCE_ERROR_NET_INITIALIZE_NETWORK,
SNM_FORCE_ERROR_NET_CTL_INIT,
SNM_FORCE_ERROR_RUDP_INIT,
SNM_FORCE_ERROR_NET_START_DIALOG,
SNM_FORCE_ERROR_MATCHING2_INIT,
SNM_FORCE_ERROR_REGISTER_NP_CALLBACK,
SNM_FORCE_ERROR_GET_NPID,
SNM_FORCE_ERROR_CREATE_MATCHING_CONTEXT,
SNM_FORCE_ERROR_REGISTER_CALLBACKS,
SNM_FORCE_ERROR_CONTEXT_START_ASYNC,
SNM_FORCE_ERROR_SET_EXTERNAL_ROOM_DATA,
SNM_FORCE_ERROR_GET_FRIEND_LIST_ENTRY_COUNT,
SNM_FORCE_ERROR_GET_FRIEND_LIST_ENTRY,
SNM_FORCE_ERROR_GET_USER_INFO_LIST,
SNM_FORCE_ERROR_LEAVE_ROOM,
SNM_FORCE_ERROR_SET_ROOM_MEMBER_DATA_INTERNAL,
SNM_FORCE_ERROR_SET_ROOM_MEMBER_DATA_INTERNAL2,
SNM_FORCE_ERROR_CREATE_SERVER_CONTEXT,
SNM_FORCE_ERROR_CREATE_JOIN_ROOM,
SNM_FORCE_ERROR_GET_SERVER_INFO,
SNM_FORCE_ERROR_DELETE_SERVER_CONTEXT,
SNM_FORCE_ERROR_SETSOCKOPT_0,
SNM_FORCE_ERROR_SETSOCKOPT_1,
SNM_FORCE_ERROR_SETSOCKOPT_2,
SNM_FORCE_ERROR_SOCK_BIND,
SNM_FORCE_ERROR_CREATE_RUDP_CONTEXT,
SNM_FORCE_ERROR_RUDP_BIND,
SNM_FORCE_ERROR_RUDP_INIT2,
SNM_FORCE_ERROR_GET_ROOM_EXTERNAL_DATA,
SNM_FORCE_ERROR_GET_SERVER_INFO_DATA,
SNM_FORCE_ERROR_GET_WORLD_INFO_DATA,
SNM_FORCE_ERROR_GET_CREATE_JOIN_ROOM_DATA,
SNM_FORCE_ERROR_GET_USER_INFO_LIST_DATA,
SNM_FORCE_ERROR_GET_JOIN_ROOM_DATA,
SNM_FORCE_ERROR_GET_ROOM_MEMBER_DATA_INTERNAL,
SNM_FORCE_ERROR_GET_ROOM_EXTERNAL_DATA2,
SNM_FORCE_ERROR_CREATE_SERVER_CONTEXT_CALLBACK,
SNM_FORCE_ERROR_SET_ROOM_DATA_CALLBACK,
SNM_FORCE_ERROR_UPDATED_ROOM_DATA,
SNM_FORCE_ERROR_UPDATED_ROOM_MEMBER_DATA_INTERNAL1,
SNM_FORCE_ERROR_UPDATED_ROOM_MEMBER_DATA_INTERNAL2,
SNM_FORCE_ERROR_UPDATED_ROOM_MEMBER_DATA_INTERNAL3,
SNM_FORCE_ERROR_UPDATED_ROOM_MEMBER_DATA_INTERNAL4,
SNM_FORCE_ERROR_GET_WORLD_INFO_LIST,
SNM_FORCE_ERROR_JOIN_ROOM,
SNM_FORCE_ERROR_COUNT,
} eSQRForceError;
class StateChangeInfo
{
public:
eSQRNetworkManagerState m_oldState;
eSQRNetworkManagerState m_newState;
bool m_idleReasonIsSessionFull;
StateChangeInfo(eSQRNetworkManagerState oldState, eSQRNetworkManagerState newState,bool idleReasonIsSessionFull) : m_oldState(oldState), m_newState(newState), m_idleReasonIsSessionFull(idleReasonIsSessionFull) {}
};
std::queue<StateChangeInfo> m_stateChangeQueue;
CRITICAL_SECTION m_csStateChangeQueue;
CRITICAL_SECTION m_csMatching;
CRITICAL_SECTION m_csAckQueue;
std::queue<int> m_queuedAckRequests;
typedef enum
{
SNM_FRIEND_SEARCH_STATE_IDLE, // Idle - search result will be valid (although it may not have any entries)
SNM_FRIEND_SEARCH_STATE_GETTING_FRIEND_COUNT, // Getting count of friends in friend list
SNM_FRIEND_SEARCH_STATE_GETTING_FRIEND_INFO, // Getting presence/NpId info for each friend
} eSQRNetworkManagerFriendSearchState;
typedef void (*ServerContextValidCallback)(SQRNetworkManager *manager);
static bool s_safeToRespondToGameBootInvite;
public:
// General
virtual void Tick() = 0;
virtual void Initialise() = 0;
#ifdef __PSVITA__
virtual void UnInitialise() = 0; // to switch from PSN to Adhoc
virtual bool IsInitialised() = 0;
#endif
virtual void Terminate() = 0;
virtual eSQRNetworkManagerState GetState() = 0;
virtual bool IsHost() = 0;
virtual bool IsReadyToPlayOrIdle() = 0;
virtual bool IsInSession() = 0;
// Session management
virtual void CreateAndJoinRoom(int hostIndex, int localPlayerMask, void *extData, int extDataSize, bool offline) = 0;
virtual void UpdateExternalRoomData() = 0;
virtual bool FriendRoomManagerIsBusy() = 0;
virtual bool FriendRoomManagerSearch() = 0;
virtual bool FriendRoomManagerSearch2() = 0;
virtual int FriendRoomManagerGetCount() = 0;
virtual void FriendRoomManagerGetRoomInfo(int idx, SessionSearchResult *searchResult) = 0;
virtual bool JoinRoom(SessionSearchResult *searchResult, int localPlayerMask) = 0;
virtual bool JoinRoom(SceNpMatching2RoomId roomId, SceNpMatching2ServerId serverId, int localPlayerMask, const SQRNetworkManager::PresenceSyncInfo *presence) = 0;
virtual void StartGame() = 0;
virtual void LeaveRoom(bool bActuallyLeaveRoom) = 0;
virtual void EndGame() = 0;
virtual bool SessionHasSpace(int spaceRequired) = 0;
virtual bool AddLocalPlayerByUserIndex(int idx) = 0;
virtual bool RemoveLocalPlayerByUserIndex(int idx) = 0;
virtual void SendInviteGUI() = 0;
virtual void GetExtDataForRoom( SceNpMatching2RoomId roomId, void *extData, void (* FriendSessionUpdatedFn)(bool success, void *pParam), void *pParam ) = 0;
// Player retrieval
virtual int GetPlayerCount() = 0;
virtual int GetOnlinePlayerCount() = 0;
virtual SQRNetworkPlayer *GetPlayerByIndex(int idx) = 0;
virtual SQRNetworkPlayer *GetPlayerBySmallId(int idx) = 0;
virtual SQRNetworkPlayer *GetPlayerByXuid(PlayerUID xuid) = 0;
virtual SQRNetworkPlayer *GetLocalPlayerByUserIndex(int idx) = 0;
virtual SQRNetworkPlayer *GetHostPlayer() = 0;
virtual void SetPresenceDataStartHostingGame() = 0;
virtual int GetJoiningReadyPercentage() = 0;
virtual void LocalDataSend(SQRNetworkPlayer *playerFrom, SQRNetworkPlayer *playerTo, const void *data, unsigned int dataSize) = 0;
virtual int GetSessionIndex(SQRNetworkPlayer *player) = 0;
static void SafeToRespondToGameBootInvite();
int GetOutstandingAckCount(SQRNetworkPlayer *pSonyPlayer);
int GetSendQueueSizeBytes();
int GetSendQueueSizeMessages();
void RequestWriteAck(int smallId);
void TickWriteAcks();
};
// Class defining interface to be implemented for class that handles callbacks
class ISQRNetworkManagerListener
{
public:
virtual void HandleDataReceived(SQRNetworkPlayer *playerFrom, SQRNetworkPlayer *playerTo, unsigned char *data, unsigned int dataSize) = 0;
virtual void HandlePlayerJoined(SQRNetworkPlayer *player) = 0;
virtual void HandlePlayerLeaving(SQRNetworkPlayer *player) = 0;
virtual void HandleStateChange(SQRNetworkManager::eSQRNetworkManagerState oldState, SQRNetworkManager::eSQRNetworkManagerState newState, bool idleReasonIsSessionFull) = 0;
virtual void HandleResyncPlayerRequest(SQRNetworkPlayer **aPlayers) = 0;
virtual void HandleAddLocalPlayerFailed(int idx) = 0;
virtual void HandleDisconnect(bool bLostRoomOnly,bool bPSNSignOut=false) = 0;
virtual void HandleInviteReceived( int userIndex, const SQRNetworkManager::PresenceSyncInfo *pInviteInfo) = 0;
};
|