/js/network/Client.js

https://github.com/pamplona/RealtimeMultiplayerNodeJs · JavaScript · 195 lines · 98 code · 31 blank · 66 comment · 5 complexity · f447b1bed0b0ac0a9d1beda54f2dd0f9 MD5 · raw file

  1. /**
  2. File:
  3. Client.js
  4. Created By:
  5. Mario Gonzalez
  6. Project:
  7. RealtimeMultiplayerNodeJS
  8. Abstract:
  9. Stores information about a connection to a client
  10. Basic Usage:
  11. var aNewClient = new Client(this, connection, false);
  12. // Add to our list of connected users
  13. this.clients[clientid] = aNewClient;
  14. // broadcast message to all clients
  15. for( var clientid in this.clients ) {
  16. this.clients[clientid].sendMessage(encodedMessage);
  17. }
  18. Version:
  19. 1.0
  20. */
  21. (function(){
  22. var BUFFER_MASK = RealtimeMultiplayerGame.Constants.CLIENT_SETTING.MAX_BUFFER;
  23. // Retrieve the namespace
  24. RealtimeMultiplayerGame.namespace("RealtimeMultiplayerGame.network");
  25. RealtimeMultiplayerGame.network.Client = function( aConnection, aClientid ) {
  26. this.clientid = aClientid;
  27. this.connection = aConnection;
  28. if(!this.connection.sessionId) { // No sessionId variable means we're not using socket.io - just set that property to use our clientid
  29. this.connection.sessionId = aClientid;
  30. }
  31. this.stagnantEntities = new SortedLookupTable();
  32. return this;
  33. };
  34. RealtimeMultiplayerGame.network.Client.prototype = {
  35. connection : null, // SocketIO connection for this specific client
  36. clientid : -1, // UUID for this client
  37. // Configuration
  38. cl_updateRate : RealtimeMultiplayerGame.Constants.CLIENT_SETTING.UPDATE_RATE, // How often we can receive messages per sec
  39. outgoingMessageBuffer : [], // Store array of incoming messages, slots are resused
  40. outgoingSequenceNumber : 0, // Number of total outgoing messages received
  41. incomingMessageBuffer : [], // Store array of incoming messages, slots are resused
  42. incomingSequenceNumber : 0, // Number of total incoming messages received
  43. entityDescriptionBuffer : [], // Store WorldEntityDescriptions before ready to send
  44. // Used to track if we can send a new message to this user
  45. lastSentMessageTime : -1,
  46. lastReceivedMessageTime : -1,
  47. // Entries that have not changed since the last frame
  48. stagnantEntities : null,
  49. onMessage: function( messageData )
  50. {
  51. var messageIndex = this.incomingSequenceNumber & RealtimeMultiplayerGame.Constants.CLIENT_SETTING.UPDATE_RATE;
  52. // this.incomingMessageBuffer[messageIndex] = messageData;
  53. this.incomingSequenceNumber++;
  54. },
  55. dealloc: function() {
  56. this.outgoingMessageBuffer = null;
  57. this.incomingMessageBuffer = null;
  58. this.entityDescriptionBuffer = null;
  59. this.stagnantEntities.dealloc();
  60. this.stagnantEntities = null;
  61. this.connection.removeAllListeners();
  62. this.connection = null;
  63. },
  64. /**
  65. * Compares the worldDescription to the last one we sent - removes unchanged values
  66. * @param worldDescription A description of all the entities currently in the world
  67. * @param gameClock The current (zero-based) game clock
  68. */
  69. compressDeltaAndQueueMessage: function( worldDescription, gameClock )
  70. {
  71. debugger;
  72. var allEntities = worldDescription.entities,
  73. len = allEntities.length;
  74. var resultDescStr = '';
  75. while(len--) {
  76. var anEntityDescStr = allEntities[len],
  77. anEntityDesc = anEntityDescStr.split(','),
  78. entityid = +anEntityDesc[0],
  79. clientid = +anEntityDesc[1];
  80. var hasNewData = true;
  81. if(clientid == RealtimeMultiplayerGame.Constants.SERVER_SETTING.CLIENT_ID) {
  82. var previouslySentEntityDescription = this.stagnantEntities.objectForKey(entityid);
  83. if(previouslySentEntityDescription) {
  84. // hasNewData = false;
  85. }
  86. }
  87. // Store for next time
  88. //this.stagnentEntities.setObjectForKey(anEntityDesc, entityid);
  89. // Only send if it has new data
  90. if(hasNewData) {
  91. resultDescStr += "|" + anEntityDescStr;
  92. }
  93. }
  94. var entityDescriptionObject = {};
  95. entityDescriptionObject.entities = resultDescStr;
  96. entityDescriptionObject.gameClock = worldDescription.gameClock;
  97. entityDescriptionObject.gameTick = worldDescription.gameTick;
  98. this.entityDescriptionBuffer.push( entityDescriptionObject );
  99. },
  100. /**
  101. * Sends the current cmdBuffer
  102. */
  103. sendQueuedCommands: function( gameClock )
  104. {
  105. var messageContent = {
  106. gameClock: gameClock,
  107. id: RealtimeMultiplayerGame.Constants.SERVER_SETTING.CLIENT_ID,
  108. seq: this.outgoingSequenceNumber,
  109. cmd: RealtimeMultiplayerGame.Constants.CMDS.SERVER_FULL_UPDATE,
  110. data:this.entityDescriptionBuffer
  111. };
  112. var anEncodedMessage = messageContent; // Encode?
  113. this.sendMessage( anEncodedMessage, gameClock);
  114. this.entityDescriptionBuffer = [];
  115. },
  116. /**
  117. * Send an encoded (and delta compressed) message to the connection
  118. * @param anEncodedMessage Bison Encoded message
  119. * @param gameClock The current (zero-based) game clock
  120. */
  121. sendMessage: function( anEncodedMessage, gameClock )
  122. {
  123. // anEncodedMessage = RealtimeMultiplayerGame.modules.bison.encode(anEncodedMessage)
  124. this.lastSentMessageTime = gameClock;
  125. // Store inside our outgoingMessageBuffer - which holds 'MESSAGE_BUFFER_MASK' lerped number of messages
  126. // var messageIndex = this.outgoingSequenceNumber & BUFFER_MASK;
  127. // this.outgoingMessageBuffer[messageIndex] = anEncodedMessage;
  128. // Send and increment our message count
  129. this.connection.send( anEncodedMessage );
  130. this.outgoingSequenceNumber++;
  131. },
  132. ///// MEMORY
  133. ///// ACCESSORS
  134. /**
  135. * Returns true if its ok to send this client a new message
  136. * @param {Number} gameClock
  137. */
  138. canSendMessage: function( gameClock ) {
  139. return (gameClock - this.lastSentMessageTime) > this.cl_updateRate;
  140. },
  141. /**
  142. * Returns the sessionId as created by Socket.io for this client
  143. * @return {String} A hash representing the session id
  144. */
  145. getSessionId: function() {
  146. return this.connection.sessionId;
  147. },
  148. /**
  149. * UUID given to us by ServerNetChannel
  150. * This is used instead of sessionid since we send this around a lot and sessionid is a 12 digit string
  151. */
  152. getClientid: function() {
  153. return this.clientid;
  154. },
  155. /**
  156. * @return {
  157. */
  158. getConnection: function() {
  159. return this.connection;
  160. }
  161. }
  162. })();