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