aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/Common/Network/Sony/SQRNetworkManager.h
blob: e3f15aca1b4099cab1f97aa2654f5e35aef6e65a (plain)
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;
};