PageRenderTime 28ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/js/network/Client.js

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