/// <summary> /// Copies the given entity and its component data to another entity in another entity array. /// </summary> public void CopyEntityTo(int thisEntityID, EntityArray otherEntityArray, int otherEntityID) { for (int componentTypeID = 0; componentTypeID < this.componentArrays.Length; componentTypeID++) { this.componentArrays[componentTypeID].CopyEntityTo(thisEntityID, otherEntityArray.componentArrays[componentTypeID], otherEntityID); } }
/// <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> /// Allows for each <see cref="IClientSystem"/> to render the given <see cref="EntityArray"/>. /// </summary> public void ClientRender(EntityArray entityArray, Entity commandingEntity) { foreach (IClientSystem system in this.systems) { system.ClientRender(entityArray, commandingEntity); } }
/// <summary> /// Updates the state of all entities and components to represent an interpolation between two other entity arrays. /// </summary> public void Interpolate(EntityArray otherA, EntityArray otherB, float amount) { Array.Copy(otherB.entityStates, this.entityStates, this.Capacity); for (int componentTypeID = 0; componentTypeID < this.componentArrays.Length; componentTypeID++) { this.componentArrays[componentTypeID].Interpolate(otherA.componentArrays[componentTypeID], otherB.componentArrays[componentTypeID], amount); } }
/// <summary> /// Copies all entity and component data to another entity array. /// </summary> public void CopyTo(EntityArray other) { Array.Copy(this.entityStates, other.entityStates, this.Capacity); for (int componentTypeID = 0; componentTypeID < this.componentArrays.Length; componentTypeID++) { this.componentArrays[componentTypeID].CopyTo(other.componentArrays[componentTypeID]); } }
/// <summary> /// Updates the systems, allowing for each <see cref="IClientSystem"/> to run its logic on the given <see cref="EntityArray"/>. /// </summary> public void ClientUpdate(EntityArray entityArray, Entity commandingEntity) { entityArray.BeginUpdate(); foreach (IClientSystem system in this.systems) { system.ClientUpdate(entityArray, commandingEntity); } entityArray.EndUpdate(); }
/// <summary> /// Updates the systems, allowing for each <see cref="IServerSystem"/> to run its logic on the given <see cref="EntityArray"/>. /// </summary> public void ServerUpdate(EntityArray entityArray) { entityArray.BeginUpdate(); foreach (IServerSystem system in this.systems) { system.ServerUpdate(entityArray); } entityArray.EndUpdate(); }
/// <summary> /// Reads and overwrites all current entity and component data from a binary source, basing incoming data on a previous entity array's data. /// </summary> public void Deserialize(EntityArray previousEntityArray, IReader reader) { for (int i = 0; i < this.entityStates.Length; i++) { this.entityStates[i] = (EntityState)reader.ReadByte(); } for (int componentTypeID = 0; componentTypeID < this.componentArrays.Length; componentTypeID++) { this.componentArrays[componentTypeID].Deserialize(previousEntityArray?.componentArrays[componentTypeID], reader); } }
/// <summary> /// Writes all entity and component data to a binary source, only writing data that has changed from a previous entity array. /// </summary> public void Serialize(EntityArray previousEntityArray, IWriter writer) { for (int i = 0; i < this.entityStates.Length; i++) { writer.Write((byte)this.entityStates[i]); } for (int componentTypeID = 0; componentTypeID < this.componentArrays.Length; componentTypeID++) { this.componentArrays[componentTypeID].Serialize(previousEntityArray?.componentArrays[componentTypeID], writer); } }
/// <summary> /// Updates the systems, allowing for each <see cref="IClientSystem"/> to run its logic to do client-side prediction on the commanding entity /// with the specified command. /// </summary> public void PredictClientCommand <TCommandData>(EntityArray entityArray, Entity commandingEntity, TCommandData commandData) where TCommandData : struct, ICommandData { foreach (IClientSystem system in this.systems) { if (system is IClientPredictedSystem <TCommandData> clientPredictedSystem) { clientPredictedSystem.PredictClientCommand(entityArray, commandingEntity, commandData); } } }
/// <summary> /// Updates the systems for a specific client's command on a commanding entity. The provided lag compensated entity array might be null /// but otherwise contains the rough state of the server at the time the client issued the command (the client's render frame). /// </summary> public void ProcessClientCommand <TCommandData>(EntityArray entityArray, Entity commandingEntity, TCommandData commandData, EntityArray lagCompensatedEntityArray) where TCommandData : struct, ICommandData { entityArray.BeginUpdate(); foreach (IServerSystem system in this.systems) { if (system is IServerCommandProcessorSystem <TCommandData> serverCommandProcessorSystem) { serverCommandProcessorSystem.ProcessClientCommand(entityArray, commandingEntity, commandData, lagCompensatedEntityArray); } } entityArray.EndUpdate(); }
/// <summary> /// Constructor. /// </summary> public Enumerator(EntityArray parent) { this.parent = parent; this.currentEntityID = -1; this.Current = Entity.NoEntity; }
/// <summary> /// Updates this entity snapshot to be a new snapshot at a new point in time, given the new server frame tick and new entities. /// </summary> public void Update(int serverFrameTick, EntityArray other) { this.ServerFrameTick = serverFrameTick; other.CopyTo(this.EntityArray); }
/// <summary> /// Constructor. /// </summary> internal Entity(EntityArray parentEntityArray, int id) { this.parentEntityArray = parentEntityArray; this.ID = id; }