From 7fec85311e3a726c9b7bcb14c559b918d06dec61 Mon Sep 17 00:00:00 2001 From: RevenantX Date: Mon, 13 Jan 2025 20:34:46 +0200 Subject: [PATCH] make history size readonly and set from constructor. Read tickrate from server (client don't need to set FPS) --- LiteEntitySystem/ClientEntityManager.cs | 16 ++++---- .../Collections/CircularBuffer.cs | 7 ++++ LiteEntitySystem/EntityManager.cs | 40 ++++++++++++------- LiteEntitySystem/Internal/InternalPackets.cs | 1 + LiteEntitySystem/ServerEntityManager.cs | 21 ++++++---- 5 files changed, 55 insertions(+), 30 deletions(-) create mode 100644 LiteEntitySystem/Collections/CircularBuffer.cs diff --git a/LiteEntitySystem/ClientEntityManager.cs b/LiteEntitySystem/ClientEntityManager.cs index ef77569..f4986bf 100644 --- a/LiteEntitySystem/ClientEntityManager.cs +++ b/LiteEntitySystem/ClientEntityManager.cs @@ -212,13 +212,13 @@ public T GetPlayerController() where T : ControllerLogic /// Input processor (you can use default InputProcessor/ or derive from abstract one to make your own input serialization /// Local AbstractPeer /// Header byte that will be used for packets (to distinguish entity system packets) - /// Fixed framerate of game logic + /// Maximum size of lag compensation history in ticks public ClientEntityManager( EntityTypesMap typesMap, InputProcessor inputProcessor, AbstractNetPeer netPeer, byte headerByte, - byte framesPerSecond) : base(typesMap, inputProcessor, NetworkMode.Client, framesPerSecond, headerByte) + MaxHistorySize maxHistorySize = MaxHistorySize.Size32) : base(typesMap, inputProcessor, NetworkMode.Client, headerByte, maxHistorySize) { _netPeer = netPeer; _sendBuffer[0] = headerByte; @@ -241,18 +241,18 @@ public override void Reset() /// EntityTypesMap with registered entity types /// Local AbstractPeer /// Header byte that will be used for packets (to distinguish entity system packets) - /// Fixed framerate of game logic + /// Maximum size of lag compensation history in ticks /// Main input packet type public static ClientEntityManager Create( EntityTypesMap typesMap, AbstractNetPeer netPeer, byte headerByte, - byte framesPerSecond) where TInput : unmanaged => + MaxHistorySize maxHistorySize = MaxHistorySize.Size32) where TInput : unmanaged => new (typesMap, new InputProcessor(), netPeer, headerByte, - framesPerSecond); + maxHistorySize); /// /// Add local entity that will be not synchronized @@ -331,6 +331,7 @@ public unsafe DeserializeResult Deserialize(ReadOnlySpan inData) { if (inData.Length < sizeof(BaselineDataHeader)) return DeserializeResult.Error; + _entitiesToConstruct.Clear(); _syncCallsCount = 0; _syncCallsBeforeConstructCount = 0; @@ -339,6 +340,7 @@ public unsafe DeserializeResult Deserialize(ReadOnlySpan inData) var header = *(BaselineDataHeader*)rawData; if (header.OriginalLength < 0) return DeserializeResult.Error; + SetTickrate(header.Tickrate); _serverSendRate = (ServerSendRate)header.SendRate; //reset pooled @@ -386,7 +388,6 @@ public unsafe DeserializeResult Deserialize(ReadOnlySpan inData) ServerTick = _stateA.Tick; _lastReadyTick = ServerTick; _inputCommands.Clear(); - _isSyncReceived = true; _jitterTimer.Reset(); ConstructAndSync(true); _entitiesToConstruct.Clear(); @@ -720,7 +721,8 @@ protected override unsafe void OnLogicTick() /// public override unsafe void Update() { - if (!_isSyncReceived) + //skip update until receive first sync and tickrate + if (Tickrate == 0) return; //logic update diff --git a/LiteEntitySystem/Collections/CircularBuffer.cs b/LiteEntitySystem/Collections/CircularBuffer.cs new file mode 100644 index 0000000..d84022e --- /dev/null +++ b/LiteEntitySystem/Collections/CircularBuffer.cs @@ -0,0 +1,7 @@ +namespace LiteEntitySystem.Collections +{ + public class CircularBuffer + { + + } +} \ No newline at end of file diff --git a/LiteEntitySystem/EntityManager.cs b/LiteEntitySystem/EntityManager.cs index 7fe5479..e1d9c63 100644 --- a/LiteEntitySystem/EntityManager.cs +++ b/LiteEntitySystem/EntityManager.cs @@ -121,24 +121,24 @@ public abstract class EntityManager public readonly bool IsClient; /// - /// FPS of game logic + /// tick rate of game logic (logic FPS, not visual) /// - public readonly int FramesPerSecond; + public byte Tickrate { get; private set; } /// /// Fixed delta time /// - public readonly double DeltaTime; + public double DeltaTime { get; private set; } /// /// Fixed delta time (float for less precision) /// - public readonly float DeltaTimeF; + public float DeltaTimeF { get; private set; } /// /// Size of history (in ticks) for lag compensation. Tune for your game fps /// - public MaxHistorySize MaxHistorySize = MaxHistorySize.Size32; + public readonly MaxHistorySize MaxHistorySize; /// /// Local player id (0 on server) @@ -173,8 +173,8 @@ public abstract class EntityManager internal readonly InternalEntity[] EntitiesDict = new InternalEntity[MaxEntityCount+1]; internal readonly EntityClassData[] ClassDataDict; - private readonly long _deltaTimeTicks; - private readonly long _slowdownTicks; + private long _deltaTimeTicks; + private long _slowdownTicks; private long _accumulator; private long _lastTime; private bool _lagCompensationEnabled; @@ -230,21 +230,31 @@ static EntityManager() RegisterFieldType(FloatAngle.Lerp); } - protected EntityManager(EntityTypesMap typesMap, InputProcessor inputProcessor, NetworkMode mode, byte framesPerSecond, byte headerByte) + protected void SetTickrate(byte tickrate) { + Tickrate = tickrate; + DeltaTime = 1.0 / tickrate; + DeltaTimeF = (float) DeltaTime; + _deltaTimeTicks = (long)(DeltaTime * Stopwatch.Frequency); + _slowdownTicks = (long)(DeltaTime * TimeSpeedChangeCoef * Stopwatch.Frequency); + if (_slowdownTicks < 100) + _slowdownTicks = 100; + } + + protected EntityManager( + EntityTypesMap typesMap, + InputProcessor inputProcessor, + NetworkMode mode, + byte headerByte, + MaxHistorySize maxHistorySize) + { + MaxHistorySize = maxHistorySize; HeaderByte = headerByte; ClassDataDict = new EntityClassData[typesMap.MaxId+1]; Mode = mode; IsServer = Mode == NetworkMode.Server; IsClient = Mode == NetworkMode.Client; InputProcessor = inputProcessor; - FramesPerSecond = framesPerSecond; - DeltaTime = 1.0 / framesPerSecond; - DeltaTimeF = (float) DeltaTime; - _deltaTimeTicks = (long)(DeltaTime * Stopwatch.Frequency); - _slowdownTicks = (long)(DeltaTime * TimeSpeedChangeCoef * Stopwatch.Frequency); - if (_slowdownTicks < 100) - _slowdownTicks = 100; ushort filterCount = 0; ushort singletonCount = 0; diff --git a/LiteEntitySystem/Internal/InternalPackets.cs b/LiteEntitySystem/Internal/InternalPackets.cs index 9947916..1b2d3a1 100644 --- a/LiteEntitySystem/Internal/InternalPackets.cs +++ b/LiteEntitySystem/Internal/InternalPackets.cs @@ -10,6 +10,7 @@ internal struct BaselineDataHeader public byte PlayerId; public byte SendRate; public ushort Tick; + public byte Tickrate; public int OriginalLength; } diff --git a/LiteEntitySystem/ServerEntityManager.cs b/LiteEntitySystem/ServerEntityManager.cs index a34e116..ecd12fe 100644 --- a/LiteEntitySystem/ServerEntityManager.cs +++ b/LiteEntitySystem/ServerEntityManager.cs @@ -81,17 +81,20 @@ public sealed class ServerEntityManager : EntityManager /// Header byte that will be used for packets (to distinguish entity system packets) /// Fixed framerate of game logic /// Send rate of server (depends on fps) + /// Maximum size of lag compensation history in ticks public ServerEntityManager( EntityTypesMap typesMap, InputProcessor inputProcessor, byte packetHeader, byte framesPerSecond, - ServerSendRate sendRate) - : base(typesMap, inputProcessor, NetworkMode.Server, framesPerSecond, packetHeader) + ServerSendRate sendRate, + MaxHistorySize maxHistorySize = MaxHistorySize.Size32) + : base(typesMap, inputProcessor, NetworkMode.Server, packetHeader, maxHistorySize) { InternalPlayerId = ServerPlayerId; _packetBuffer[0] = packetHeader; SendRate = sendRate; + SetTickrate(framesPerSecond); } /// @@ -101,20 +104,21 @@ public ServerEntityManager( /// Header byte that will be used for packets (to distinguish entity system packets) /// Fixed framerate of game logic /// Send rate of server (depends on fps) + /// Maximum size of lag compensation history in ticks /// Main input packet type public static ServerEntityManager Create( EntityTypesMap typesMap, byte packetHeader, byte framesPerSecond, - ServerSendRate sendRate) where TInput : unmanaged - { - return new ServerEntityManager( + ServerSendRate sendRate, + MaxHistorySize maxHistorySize = MaxHistorySize.Size32) where TInput : unmanaged => + new ServerEntityManager( typesMap, new InputProcessor(), packetHeader, framesPerSecond, - sendRate); - } + sendRate, + maxHistorySize); public override void Reset() { @@ -527,7 +531,8 @@ protected override unsafe void OnLogicTick() OriginalLength = originalLength, Tick = _tick, PlayerId = player.Id, - SendRate = (byte)SendRate + SendRate = (byte)SendRate, + Tickrate = Tickrate }; //compress