PageRenderTime 64ms CodeModel.GetById 35ms RepoModel.GetById 0ms app.codeStats 0ms

/js/network/Client.js

https://github.com/jaehess/RealtimeMultiplayerNodeJs
JavaScript | 175 lines | 88 code | 25 blank | 62 comment | 4 complexity | 16d0c809292f994d1462b3f70207fe4b 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. this.stagnantEntities = new SortedLookupTable();
  29. return this;
  30. };
  31. RealtimeMultiplayerGame.network.Client.prototype = {
  32. connection : null, // SocketIO connection for this specific client
  33. clientid : -1, // UUID for this client
  34. // Configuration
  35. cl_updateRate : RealtimeMultiplayerGame.Constants.CLIENT_SETTING.UPDATE_RATE, // How often we can receive messages per sec
  36. outgoingMessageBuffer : [], // Store array of incoming messages, slots are resused
  37. outgoingSequenceNumber : 0, // Number of total outgoing messages received
  38. incomingMessageBuffer : [], // Store array of incoming messages, slots are resused
  39. incomingSequenceNumber : 0, // Number of total incoming messages received
  40. entityDescriptionBuffer : [], // Store WorldEntityDescriptions before ready to send
  41. // Used to track if we can send a new message to this user
  42. lastSentMessageTime : -1,
  43. lastReceivedMessageTime : -1,
  44. // Entries that have not changed since the last frame
  45. stagnantEntities : null,
  46. onMessage: function( messageData )
  47. {
  48. var messageIndex = this.incomingSequenceNumber & RealtimeMultiplayerGame.Constants.CLIENT_SETTING.UPDATE_RATE;
  49. this.incomingMessageBuffer[messageIndex] = messageData;
  50. this.incomingSequenceNumber++;
  51. },
  52. /**
  53. * Compares the worldDescription to the last one we sent - removes unchanged values
  54. * @param worldDescription A description of all the entities currently in the world
  55. * @param gameClock The current (zero-based) game clock
  56. */
  57. compressDeltaAndQueueMessage: function( worldDescription, gameClock )
  58. {
  59. var allEntities = worldDescription.entities,
  60. len = allEntities.length;
  61. var resultDescStr = '';
  62. while(len--) {
  63. var anEntityDescStr = allEntities[len],
  64. anEntityDesc = anEntityDescStr.split(','),
  65. entityid = +anEntityDesc[0],
  66. clientid = +anEntityDesc[1];
  67. var hasNewData = true;
  68. if(clientid == RealtimeMultiplayerGame.Constants.SERVER_SETTING.CLIENT_ID) {
  69. var previouslySentEntityDescription = this.stagnantEntities.objectForKey(entityid);
  70. if(previouslySentEntityDescription) {
  71. // hasNewData = false;
  72. }
  73. }
  74. // Store for next time
  75. //this.stagnentEntities.setObjectForKey(anEntityDesc, entityid);
  76. // Only send if it has new data
  77. if(hasNewData) {
  78. resultDescStr += "|" + anEntityDescStr;
  79. }
  80. }
  81. var entityDescriptionObject = {};
  82. entityDescriptionObject.entities = resultDescStr;
  83. entityDescriptionObject.gameClock = worldDescription.gameClock;
  84. entityDescriptionObject.gameTick = worldDescription.gameTick;
  85. this.entityDescriptionBuffer.push( entityDescriptionObject );
  86. },
  87. /**
  88. * Sends the current cmdBuffer
  89. */
  90. sendQueuedCommands: function( gameClock )
  91. {
  92. var messageContent = {
  93. gameClock: gameClock,
  94. id: RealtimeMultiplayerGame.Constants.SERVER_SETTING.CLIENT_ID,
  95. seq: this.outgoingSequenceNumber,
  96. cmd: RealtimeMultiplayerGame.Constants.CMDS.SERVER_FULL_UPDATE,
  97. data:this.entityDescriptionBuffer
  98. };
  99. var anEncodedMessage = messageContent; // Encode?
  100. // var encodedMessage = BISON.encode(messageContent);
  101. this.sendMessage( anEncodedMessage, gameClock);
  102. this.entityDescriptionBuffer = [];
  103. },
  104. /**
  105. * Send an encoded (and delta compressed) message to the connection
  106. * @param anEncodedMessage Bison Encoded message
  107. * @param gameClock The current (zero-based) game clock
  108. */
  109. sendMessage: function( anEncodedMessage, gameClock )
  110. {
  111. this.lastSentMessageTime = gameClock;
  112. // Store inside our outgoingMessageBuffer - which holds 'MESSAGE_BUFFER_MASK' lerped number of messages
  113. var messageIndex = this.outgoingSequenceNumber & BUFFER_MASK;
  114. this.outgoingMessageBuffer[messageIndex] = anEncodedMessage;
  115. // Send and increment our message count
  116. this.connection.send( anEncodedMessage );
  117. this.outgoingSequenceNumber++;
  118. },
  119. ///// ACCESSORS
  120. /**
  121. * Returns true if its ok to send this client a new message
  122. * @param {Number} gameClock
  123. */
  124. canSendMessage: function( gameClock ) {
  125. return (gameClock - this.lastSentMessageTime) > this.cl_updateRate;
  126. },
  127. /**
  128. * Returns the sessionId as created by Socket.io for this client
  129. * @return {String} A hash representing the session id
  130. */
  131. getSessionId: function() {
  132. return this.connection.sessionId;
  133. },
  134. /**
  135. * UUID given to us by ServerNetChannel
  136. * This is used instead of sessionid since we send this around a lot and sessionid is a 12 digit string
  137. */
  138. getClientid: function() {
  139. return this.clientid;
  140. },
  141. /**
  142. * @return {
  143. */
  144. getConnection: function() {
  145. return this.connection;
  146. }
  147. }
  148. })();