/// <summary> /// Updates the client state by processing server snapshots, updating rendered frame (with interpolation and prediction), and sending commands to the server. /// </summary> public void Update(TCommandData commandData) { Log <LogGameClient> .StartNew(); if (this.LatestServerTickReceived >= 0) { // Only tick the client if we started getting data from the server (i.e. fully connected) this.FrameTick++; } this.receiveServerUpdates(); if (this.HasRenderingStarted) { // Once we are rendering we can start taking user commands and sending them to the server // Take the latest command and add it to the command history buffer (overwriting an old command) ClientCommand <TCommandData> newClientCommand = this.clientCommandHistory.Dequeue(); newClientCommand.Update(this.FrameTick, this.RenderedSnapshot.ServerFrameTick, this.InterpolationStartSnapshot.ServerFrameTick, this.InterpolationEndSnapshot.ServerFrameTick, this.ShouldInterpolate, this.CommandingEntityID, commandData); this.clientCommandHistory.Enqueue(newClientCommand); if (this.FrameTick % this.NetworkSendRate == 0) { ClientUpdateSerializer <TCommandData> .Send(this.serverNetworkConnection, this.clientCommandHistory, this.LatestServerTickReceived, this.LatestFrameTickAcknowledgedByServer); } } this.updateRenderedSnapshot(); this.updatePrediction(); if (this.HasRenderingStarted) { this.SystemArray.ClientUpdate(this.RenderedSnapshot.EntityArray, this.GetCommandingEntity()); } }
/// <summary> /// Checks for and processes any new commands coming in from the client. /// </summary> public void ReceiveClientCommands(EntityArray entityArray) { IncomingMessage incomingMessage; while ((incomingMessage = this.clientNetworkConnection.GetNextIncomingMessage()) != null) { int numberOfCommands = ClientUpdateSerializer <TCommandData> .Deserialize(incomingMessage, this.deserializedClientCommandHistory, out int newlatestFrameTickAcknowledgedByClient); if (this.LatestFrameTickAcknowledgedByClient < newlatestFrameTickAcknowledgedByClient) { this.LatestFrameTickAcknowledgedByClient = newlatestFrameTickAcknowledgedByClient; } for (int i = 0; i < numberOfCommands; i++) { ClientCommand <TCommandData> clientCommand = this.deserializedClientCommandHistory[i]; // Make sure we don't process a command we've already received and processed in a previous tick if (!clientCommand.HasData || clientCommand.ClientFrameTick <= this.LatestClientTickReceived) { continue; } this.parentServer.executeClientCommand(this, clientCommand); if (this.LatestClientTickReceived < clientCommand.ClientFrameTick) { this.LatestClientTickReceived = clientCommand.ClientFrameTick; } } } }
/// <summary> /// Serializes the given client update (client commands) and immediately sends a packet. /// </summary> public static void Send(INetworkConnection serverNetworkConnection, Queue <ClientCommand <TCommandData> > clientCommands, int latestServerTickReceived, int latestFrameTickAcknowledgedByServer) { OutgoingMessage outgoingMessage = serverNetworkConnection.GetOutgoingMessageToSend(); ClientUpdateSerializer <TCommandData> .Serialize(outgoingMessage, clientCommands, latestServerTickReceived, latestFrameTickAcknowledgedByServer); serverNetworkConnection.SendMessage(outgoingMessage); }