1
1
/**
2
- File:
3
- ServerNetChannel.js
4
- Created By:
5
- Mario Gonzalez
6
- Project:
7
- RealtimeMultiplayerNodeJS
8
- Abstract:
9
- This class is responsible for managing the socket connection for each client
10
-
11
- -> ClientNetChannel talks to this object
12
- <--> ServerNetChannel talks to it's GameController via delegation
13
- <-- ServerNetChannel broadcast the message to all clients
14
-
15
- Basic Usage:
2
+ File:
3
+ ServerNetChannel.js
4
+ Created By:
5
+ Mario Gonzalez
6
+ Project:
7
+ RealtimeMultiplayerNodeJS
8
+ Abstract:
9
+ This class is responsible for managing the socket connection for each client
10
+
11
+ -> ClientNetChannel talks to this object
12
+ <--> ServerNetChannel talks to it's GameController via delegation
13
+ <-- ServerNetChannel broadcast the message to all clients
14
+
15
+ Basic Usage:
16
16
TODO: UPDATE USAGE
17
- Version:
18
- 1.0
19
- */
20
- ( function ( ) {
21
- // Node.JS Imports
22
- var http = require ( 'http' ) ;
23
- var url = require ( 'url' ) ;
24
- var fs = require ( 'fs' ) ;
25
- var sys = require ( process . binding ( 'natives' ) . util ? 'util' : 'sys' ) ;
26
- var io = require ( '../lib/Socket.IO-node' ) ;
27
-
28
- // Local variables for private things in this class
17
+ Version:
18
+ 1.1.0
19
+ */
20
+ ( function ( ) {
21
+ /**
22
+ *
23
+ * The auto-incrimented ID to use for the next client
24
+ */
29
25
var nextClientID = RealtimeMultiplayerGame . Constants . SERVER_SETTING . CLIENT_ID ;
30
26
31
- // Retrieve the namespace
32
- RealtimeMultiplayerGame . namespace ( "RealtimeMultiplayerGame.network" ) ;
27
+ RealtimeMultiplayerGame . namespace ( "RealtimeMultiplayerGame.network" ) ;
33
28
34
29
/**
35
30
* Creates a new ServerNetChannel instance
36
31
* @param {RealtimeMultiplayerGame.network.ServerNetChannelDelegateProtocol } aDelegate A delegate that conforms to RealtimeMultiplayerGame.network.ServerNetChannelDelegateProtocol
37
32
*/
38
- RealtimeMultiplayerGame . network . ServerNetChannel = function ( aDelegate ) {
33
+ RealtimeMultiplayerGame . network . ServerNetChannel = function ( aDelegate ) {
39
34
this . clients = new SortedLookupTable ( ) ;
40
35
41
36
this . setDelegate ( aDelegate ) ;
@@ -46,35 +41,42 @@ Version:
46
41
} ;
47
42
48
43
RealtimeMultiplayerGame . network . ServerNetChannel . prototype = {
49
- httpserver : null , // A minimal HTTP server which socket.io can listen on
50
- socketio : null , // Socket.IO server
44
+ socketio : null , // Socket.IO server
51
45
clients : null , // SortedLookupTable
52
46
delegate : null , // Should conform to ServerNetChannel delegate
53
47
outgoingSequenceNumber : 0 , // A unique ID for each message
54
48
cmdMap : { } , // Map the CMD constants to functions
55
- // Methods
49
+
50
+ // Methods
56
51
/**
57
52
* Initializes socket.io
58
53
*/
59
- setupSocketIO : function ( ) {
60
- // Create a minimal http server to listen
61
- this . httpserver = http . createServer ( function ( req , res ) { } ) ;
62
- this . httpserver . listen ( RealtimeMultiplayerGame . Constants . SERVER_SETTING . SOCKET_PORT ) ;
63
- // Start socket.io
64
- this . socketio = io . listen ( this . httpserver ) ;
65
-
54
+ setupSocketIO : function ( ) {
55
+ var server = require ( 'http' ) . createServer ( function ( req , res ) {
56
+ } ) ;
57
+ server . listen ( RealtimeMultiplayerGame . Constants . SERVER_SETTING . SOCKET_PORT ) ;
58
+ this . socketio = require ( 'socket.io' ) . listen ( server ) ;
66
59
67
60
var that = this ;
68
- this . socketio . on ( 'connection' , function ( client ) { that . onSocketConnection ( client ) } ) ;
69
- this . socketio . on ( 'clientMessage' , function ( data , client ) { that . onSocketMessage ( data , client ) } ) ;
70
- this . socketio . on ( 'clientDisconnect' , function ( client ) { that . onSocketClosed ( client ) } ) ;
61
+ this . socketio . on ( 'connection' , function ( client ) {
62
+ console . log ( client ) ;
63
+ that . onSocketConnection ( client )
64
+ } ) ;
65
+ this . socketio . on ( 'clientMessage' , function ( data , client ) {
66
+ console . log ( data )
67
+ that . onSocketMessage ( data , client )
68
+ } ) ;
69
+ this . socketio . on ( 'clientDisconnect' , function ( client ) {
70
+ console . log ( client )
71
+ that . onSocketClosed ( client )
72
+ } ) ;
71
73
} ,
72
74
73
- setupWSServer : function ( ) {
75
+ setupWSServer : function ( ) {
74
76
75
- var profiler = require ( 'v8-profiler' ) ;
76
- var util = require ( 'util' ) ;
77
- var ws = require ( "../lib/bonsai-ws/ws.js" ) ;
77
+ var profiler = require ( 'v8-profiler' ) ;
78
+ var util = require ( 'util' ) ;
79
+ var ws = require ( "../lib/bonsai-ws/ws.js" ) ;
78
80
79
81
this . clientCount = 0 ;
80
82
this . maxClients = 8 ;
@@ -83,29 +85,29 @@ Version:
83
85
var that = this ;
84
86
85
87
this . $ = new ws . Server ( false ) ;
86
- this . $ . onConnect = function ( conn ) {
88
+ this . $ . onConnect = function ( conn ) {
87
89
var aClient = new RealtimeMultiplayerGame . network . Client ( conn , that . getNextClientID ( ) ) ;
88
90
89
91
// Send the first message back to the client, which gives them a clientid
90
- var connectMessage = new RealtimeMultiplayerGame . model . NetChannelMessage ( ++ this . outgoingSequenceNumber , aClient . getClientid ( ) , true , RealtimeMultiplayerGame . Constants . CMDS . SERVER_CONNECT , { gameClock : that . delegate . getGameClock ( ) } ) ;
92
+ var connectMessage = new RealtimeMultiplayerGame . model . NetChannelMessage ( ++ this . outgoingSequenceNumber , aClient . getClientid ( ) , true , RealtimeMultiplayerGame . Constants . CMDS . SERVER_CONNECT , { gameClock : that . delegate . getGameClock ( ) } ) ;
91
93
connectMessage . messageTime = that . delegate . getGameClock ( ) ;
92
- aClient . getConnection ( ) . send ( RealtimeMultiplayerGame . modules . bison . encode ( connectMessage ) ) ;
94
+ aClient . getConnection ( ) . send ( RealtimeMultiplayerGame . modules . bison . encode ( connectMessage ) ) ;
93
95
94
96
// Add to our list of connected users
95
97
that . clients . setObjectForKey ( aClient , aClient . getSessionId ( ) ) ;
96
98
} ;
97
99
98
- this . $ . onMessage = function ( conn , msg ) {
99
- console . log ( "MESSAGE RECEIVED" , msg ) ;
100
+ this . $ . onMessage = function ( conn , msg ) {
101
+ console . log ( "MESSAGE RECEIVED" , msg ) ;
100
102
} ;
101
103
102
- this . $ . onClose = function ( conn ) {
103
- that . removeClient ( conn . $clientID ) ;
104
- console . log ( "Disconnected!" ) ;
104
+ this . $ . onClose = function ( conn ) {
105
+ that . removeClient ( conn . $clientID ) ;
106
+ console . log ( "Disconnected!" ) ;
105
107
} ;
106
108
107
- this . removeClient = function ( id ) {
108
- if ( this . socketClients [ id ] ) {
109
+ this . removeClient = function ( id ) {
110
+ if ( this . socketClients [ id ] ) {
109
111
this . clientCount -- ;
110
112
this . socketClients [ id ] . remove ( ) ;
111
113
delete this . socketClients [ id ] ;
@@ -118,19 +120,18 @@ Version:
118
120
/**
119
121
* Map RealtimeMultiplayerGame.Constants.CMDS to functions
120
122
*/
121
- setupCmdMap : function ( ) {
123
+ setupCmdMap : function ( ) {
122
124
this . cmdMap = { } ;
123
125
this . cmdMap [ RealtimeMultiplayerGame . Constants . CMDS . PLAYER_JOINED ] = this . onPlayerJoined ;
124
126
} ,
125
127
126
128
/**
127
129
* Checks all the clients to see if its ready for a new message.
128
130
* If they are, have the client perform delta-compression on the worldDescription and send it off.
129
- * @param gameClock The current (zero-based) game clock
131
+ * @param gameClock The current (zero-based) game clock
130
132
* @param worldDescription A description of all the entities currently in the world
131
133
*/
132
- tick : function ( gameClock , worldDescription )
133
- {
134
+ tick : function ( gameClock , worldDescription ) {
134
135
var worldEntityDescriptionString = worldDescription . getEntityDescriptionAsString ( ) ;
135
136
var entityDescriptionObject = {
136
137
entities : worldEntityDescriptionString ,
@@ -139,30 +140,29 @@ Version:
139
140
} ;
140
141
141
142
// Send client the current world info
142
- this . clients . forEach ( function ( key , client )
143
- {
143
+ this . clients . forEach ( function ( key , client ) {
144
144
// Collapse delta - store the world state
145
145
client . entityDescriptionBuffer . push ( entityDescriptionObject ) ;
146
146
147
147
// Ask if enough time passed, and send a new world update
148
- if ( client . canSendMessage ( gameClock ) ) {
149
- client . sendQueuedCommands ( gameClock ) ;
148
+ if ( client . canSendMessage ( gameClock ) ) {
149
+ client . sendQueuedCommands ( gameClock ) ;
150
150
}
151
151
152
152
} , this ) ;
153
153
} ,
154
154
155
- // Socket.IO callbacks
155
+ // Socket.IO callbacks
156
156
/**
157
157
* Callback from socket.io when a client has connected
158
158
* @param clientConnection
159
159
*/
160
- onSocketConnection : function ( clientConnection ) {
160
+ onSocketConnection : function ( clientConnection ) {
161
161
162
162
var aClient = new RealtimeMultiplayerGame . network . Client ( clientConnection , this . getNextClientID ( ) ) ;
163
163
164
164
// Send the first message back to the client, which gives them a clientid
165
- var connectMessage = new RealtimeMultiplayerGame . model . NetChannelMessage ( ++ this . outgoingSequenceNumber , aClient . getClientid ( ) , true , RealtimeMultiplayerGame . Constants . CMDS . SERVER_CONNECT , { gameClock : this . delegate . getGameClock ( ) } ) ;
165
+ var connectMessage = new RealtimeMultiplayerGame . model . NetChannelMessage ( ++ this . outgoingSequenceNumber , aClient . getClientid ( ) , true , RealtimeMultiplayerGame . Constants . CMDS . SERVER_CONNECT , { gameClock : this . delegate . getGameClock ( ) } ) ;
166
166
connectMessage . messageTime = this . delegate . getGameClock ( ) ;
167
167
aClient . getConnection ( ) . send ( connectMessage ) ;
168
168
@@ -174,10 +174,10 @@ Version:
174
174
* Callback from socket.io when a client has disconnected
175
175
* @param client
176
176
*/
177
- onSocketClosed : function ( clientConnection ) {
177
+ onSocketClosed : function ( clientConnection ) {
178
178
var client = this . clients . objectForKey ( clientConnection . sessionId ) ;
179
- if ( ! client ) {
180
- console . warn ( "(ServerNetChannel)::onSocketClosed - ERROR - Attempting to remove client that was not found in our list! " ) ;
179
+ if ( ! client ) {
180
+ console . warn ( "(ServerNetChannel)::onSocketClosed - ERROR - Attempting to remove client that was not found in our list! " ) ;
181
181
return ;
182
182
}
183
183
@@ -192,54 +192,60 @@ Version:
192
192
* @param data
193
193
* @param connection
194
194
*/
195
- onSocketMessage : function ( data , connection )
196
- {
197
- var client = this . clients . objectForKey ( connection . sessionId ) ;
195
+ onSocketMessage : function ( data , connection ) {
196
+ var client = this . clients . objectForKey ( connection . sessionId ) ;
198
197
//that.CMD_TO_FUNCTION[decodedMessage.cmds.cmd].apply(that, [connection, decodedMessage]);
199
198
200
199
// Allow the client to track that data was received
201
- if ( client ) {
200
+ if ( client ) {
202
201
client . onMessage ( data ) ;
203
202
} else {
204
- console . log ( "(NetChannel)::onSocketMessage - no such client!" ) ;
203
+ console . log ( "(NetChannel)::onSocketMessage - no such client!" ) ;
205
204
return ;
206
205
}
207
-
206
+
208
207
//// Call the mapped function, always pass the connection. Also pass data if available
209
- if ( this . cmdMap [ data . cmd ] ) {
210
- this . cmdMap [ data . cmd ] . call ( this , client , data ) ;
211
- } else if ( this . delegate . cmdMap [ data . cmd ] ) { // See if delegate has function mapped
212
- this . delegate . cmdMap [ data . cmd ] . call ( this . delegate , client , data ) ;
208
+ if ( this . cmdMap [ data . cmd ] ) {
209
+ this . cmdMap [ data . cmd ] . call ( this , client , data ) ;
210
+ } else if ( this . delegate . cmdMap [ data . cmd ] ) { // See if delegate has function mapped
211
+ this . delegate . cmdMap [ data . cmd ] . call ( this . delegate , client , data ) ;
213
212
} else { // Display error
214
- console . log ( "(NetChannel)::onSocketMessage could not map '" + data . cmd + "' to function!" ) ;
213
+ console . log ( "(NetChannel)::onSocketMessage could not map '" + data . cmd + "' to function!" ) ;
215
214
}
216
215
} ,
217
216
218
- ////// Game callbacks
217
+ ////// Game callbacks
219
218
/**
220
219
* Callback for when a player has joined the match.
221
220
* Note that joining the match, happens after connecting.
222
221
* For example a player might be able to connect to the match, and watch the game for a while then want to join the match
223
222
* @param client
224
223
* @param data
225
224
*/
226
- onPlayerJoined : function ( client , data ) {
227
- console . log ( client . getClientid ( ) + " joined the game!" ) ;
228
- this . delegate . shouldAddPlayer ( client . getClientid ( ) , data ) ;
225
+ onPlayerJoined : function ( client , data ) {
226
+ console . log ( client . getClientid ( ) + " joined the game!" ) ;
227
+ this . delegate . shouldAddPlayer ( client . getClientid ( ) , data ) ;
229
228
client . getConnection ( ) . send ( data ) ;
230
229
} ,
231
230
232
- // Accessors
233
- getNextClientID : function ( ) { return ++ nextClientID } ,
231
+ /*************
232
+ * ACCESSORS *
233
+ *************/
234
+
235
+
236
+ getNextClientID : function ( ) {
237
+ return ++ nextClientID
238
+ } ,
239
+
234
240
/**
235
241
* Checks that an object contains the required methods and sets it as the delegate for this ServerNetChannel instance
236
242
* @param {RealtimeMultiplayerGame.network.ServerNetChannelDelegateProtocol } aDelegate A delegate that conforms to RealtimeMultiplayerGame.network.ServerNetChannelDelegateProtocol
237
243
*/
238
- setDelegate : function ( aDelegate ) {
244
+ setDelegate : function ( aDelegate ) {
239
245
var theInterface = RealtimeMultiplayerGame . network . ServerNetChannelDelegateProtocol ;
240
- for ( var member in theInterface ) {
246
+ for ( var member in theInterface ) {
241
247
if ( ( typeof aDelegate [ member ] != typeof theInterface [ member ] ) ) {
242
- console . log ( "object failed to implement interface member " + member ) ;
248
+ console . log ( "object failed to implement interface member " + member ) ;
243
249
return false ;
244
250
}
245
251
}
@@ -253,12 +259,19 @@ Version:
253
259
* Required methods for the ServerNetChannel delegate
254
260
*/
255
261
RealtimeMultiplayerGame . network . ServerNetChannelDelegateProtocol = {
256
- setupCmdMap : function ( ) { } ,
257
- shouldUpdatePlayer : function ( clientID , data ) { } ,
258
- shouldAddPlayer : function ( clientID , data ) { } ,
259
- shouldRemovePlayer : function ( clientID ) { } ,
260
- getNextEntityID : function ( ) { } ,
261
- getGameClock : function ( ) { } ,
262
- log : function ( ) { }
262
+ setupCmdMap : function ( ) {
263
+ } ,
264
+ shouldUpdatePlayer : function ( clientID , data ) {
265
+ } ,
266
+ shouldAddPlayer : function ( clientID , data ) {
267
+ } ,
268
+ shouldRemovePlayer : function ( clientID ) {
269
+ } ,
270
+ getNextEntityID : function ( ) {
271
+ } ,
272
+ getGameClock : function ( ) {
273
+ } ,
274
+ log : function ( ) {
275
+ }
263
276
}
264
277
} ) ( ) ;
0 commit comments