diff --git a/Robust.Client/GameStates/ClientGameStateManager.cs b/Robust.Client/GameStates/ClientGameStateManager.cs index 09d2fb02be..2f8e31f7cc 100644 --- a/Robust.Client/GameStates/ClientGameStateManager.cs +++ b/Robust.Client/GameStates/ClientGameStateManager.cs @@ -412,10 +412,10 @@ namespace Robust.Client.GameStates private List ApplyGameState(GameState curState, GameState? nextState) { _config.TickProcessMessages(); - _mapManager.ApplyGameStatePre(curState.MapData, curState.EntityStates); - var createdEntities = ApplyEntityStates(curState.EntityStates, curState.EntityDeletions, - nextState?.EntityStates); - _players.ApplyPlayerStates(curState.PlayerStates); + _mapManager.ApplyGameStatePre(curState.MapData, curState.EntityStates.Array); + var createdEntities = ApplyEntityStates(curState.EntityStates.Array, curState.EntityDeletions.Array, + nextState?.EntityStates.Array); + _players.ApplyPlayerStates(curState.PlayerStates.Array); _mapManager.ApplyGameStatePost(curState.MapData); GameStateApplied?.Invoke(new GameStateAppliedArgs(curState)); @@ -442,7 +442,7 @@ namespace Robust.Client.GameStates } else //Unknown entities { - var metaState = (MetaDataComponentState?) es.ComponentChanges?.FirstOrDefault(c => c.NetID == _metaCompNetId).State; + var metaState = (MetaDataComponentState?) es.ComponentChanges.Value?.FirstOrDefault(c => c.NetID == _metaCompNetId).State; if (metaState == null) { throw new InvalidOperationException($"Server sent new entity state for {es.Uid} without metadata component!"); @@ -553,9 +553,9 @@ namespace Robust.Client.GameStates var compStateWork = new Dictionary(); var entityUid = entity.Uid; - if (curState?.ComponentChanges != null) + if (curState?.ComponentChanges.Array is { } changes) { - foreach (var compChange in curState.ComponentChanges) + foreach (var compChange in changes) { if (compChange.Deleted) { @@ -580,17 +580,17 @@ namespace Robust.Client.GameStates } } - if (curState?.ComponentChanges != null) + if (curState?.ComponentChanges.Array is { } changes2) { - foreach (var compChange in curState.ComponentChanges) + foreach (var compChange in changes2) { compStateWork[compChange.NetID] = (compChange.State, null); } } - if (nextState?.ComponentChanges != null) + if (nextState?.ComponentChanges.Array is { } nextChanges) { - foreach (var compState in nextState.ComponentChanges) + foreach (var compState in nextChanges) { if (compStateWork.TryGetValue(compState.NetID, out var state)) { diff --git a/Robust.Client/GameStates/GameStateProcessor.cs b/Robust.Client/GameStates/GameStateProcessor.cs index a5ffe6e76d..c21db04746 100644 --- a/Robust.Client/GameStates/GameStateProcessor.cs +++ b/Robust.Client/GameStates/GameStateProcessor.cs @@ -168,37 +168,31 @@ namespace Robust.Client.GameStates } else { - if (state.EntityDeletions != null) + foreach (var deletion in state.EntityDeletions.Array) { - foreach (var deletion in state.EntityDeletions) - { - _lastStateFullRep.Remove(deletion); - } + _lastStateFullRep.Remove(deletion); } } - if (state.EntityStates != null) + foreach (var entityState in state.EntityStates.Array) { - foreach (var entityState in state.EntityStates) + if (!_lastStateFullRep.TryGetValue(entityState.Uid, out var compData)) { - if (!_lastStateFullRep.TryGetValue(entityState.Uid, out var compData)) - { - compData = new Dictionary(); - _lastStateFullRep.Add(entityState.Uid, compData); - } + compData = new Dictionary(); + _lastStateFullRep.Add(entityState.Uid, compData); + } - if (entityState.ComponentChanges != null) + if (entityState.ComponentChanges.Array is { } changes) + { + foreach (var change in changes) { - foreach (var change in entityState.ComponentChanges) + if (change.Deleted) { - if (change.Deleted) - { - compData.Remove(change.NetID); - } - else if (change.State is not null) - { - compData[change.NetID] = change.State; - } + compData.Remove(change.NetID); + } + else if (change.State is not null) + { + compData[change.NetID] = change.State; } } } @@ -352,7 +346,7 @@ namespace Robust.Client.GameStates /// private static GameState ExtrapolateState(GameTick fromSequence, GameTick toSequence, uint lastInput) { - var state = new GameState(fromSequence, toSequence, lastInput, null, null, null, null); + var state = new GameState(fromSequence, toSequence, lastInput, default, default, default, null); state.Extrapolated = true; return state; } diff --git a/Robust.Client/GameStates/NetEntityOverlay.cs b/Robust.Client/GameStates/NetEntityOverlay.cs index fd1ddc8a48..99dec446e2 100644 --- a/Robust.Client/GameStates/NetEntityOverlay.cs +++ b/Robust.Client/GameStates/NetEntityOverlay.cs @@ -65,10 +65,10 @@ namespace Robust.Client.GameStates var gameState = args.AppliedState; - if(gameState.EntityStates is not null) + if(gameState.EntityStates.HasContents) { // Loop over every entity that gets updated this state and record the traffic - foreach (var entityState in gameState.EntityStates) + foreach (var entityState in gameState.EntityStates.Array) { var newEnt = true; for(var i=0;i<_netEnts.Count;i++) diff --git a/Robust.Client/GameStates/NetGraphOverlay.cs b/Robust.Client/GameStates/NetGraphOverlay.cs index c47b51cb7e..aaa8cd1640 100644 --- a/Robust.Client/GameStates/NetGraphOverlay.cs +++ b/Robust.Client/GameStates/NetGraphOverlay.cs @@ -79,17 +79,17 @@ namespace Robust.Client.GameStates var conShell = IoCManager.Resolve().LocalShell; var entStates = args.AppliedState.EntityStates; - if (entStates is not null) + if (entStates.HasContents) { var sb = new StringBuilder(); - foreach (var entState in entStates) + foreach (var entState in entStates.Array) { if (entState.Uid == WatchEntId) { - if(entState.ComponentChanges is not null) + if(entState.ComponentChanges.Array is { } changes) { sb.Append($"\n Changes:"); - foreach (var compChange in entState.ComponentChanges) + foreach (var compChange in changes) { var registration = _componentFactory.GetRegistration(compChange.NetID); var create = compChange.Created ? 'C' : '\0'; @@ -107,10 +107,10 @@ namespace Robust.Client.GameStates } var entDeletes = args.AppliedState.EntityDeletions; - if (entDeletes is not null) + if (entDeletes.HasContents) { var sb = new StringBuilder(); - foreach (var entDelete in entDeletes) + foreach (var entDelete in entDeletes.Array) { if (entDelete == WatchEntId) { diff --git a/Robust.Client/Map/ClientMapManager.cs b/Robust.Client/Map/ClientMapManager.cs index 4be20e4c9c..35ce0c9553 100644 --- a/Robust.Client/Map/ClientMapManager.cs +++ b/Robust.Client/Map/ClientMapManager.cs @@ -33,10 +33,11 @@ namespace Robust.Client.Map //get shared euid of map comp entity foreach (var entityState in entityStates!) { - if(entityState.ComponentChanges is null) + var changes = entityState.ComponentChanges.Array; + if (changes is null) continue; - foreach (var compChange in entityState.ComponentChanges) + foreach (var compChange in changes) { if (compChange.State is not MapComponentState mapCompState || mapCompState.MapId != mapId) continue; @@ -68,10 +69,11 @@ namespace Robust.Client.Map //get shared euid of map comp entity foreach (var entityState in entityStates!) { - if (entityState.ComponentChanges is null) + var changes = entityState.ComponentChanges.Array; + if (changes is null) continue; - foreach (var compState in entityState.ComponentChanges) + foreach (var compState in changes) { if (compState.State is not MapGridComponentState gridCompState || gridCompState.GridIndex != gridId) continue; diff --git a/Robust.Client/Player/IPlayerManager.cs b/Robust.Client/Player/IPlayerManager.cs index ae9a386b52..da6eaa435b 100644 --- a/Robust.Client/Player/IPlayerManager.cs +++ b/Robust.Client/Player/IPlayerManager.cs @@ -24,7 +24,7 @@ namespace Robust.Client.Player void Startup(); void Shutdown(); - void ApplyPlayerStates(IEnumerable? list); + void ApplyPlayerStates(PlayerState[] list); } public class LocalPlayerChangedEventArgs : EventArgs diff --git a/Robust.Client/Player/PlayerManager.cs b/Robust.Client/Player/PlayerManager.cs index 866bb0282a..d94cd2feb6 100644 --- a/Robust.Client/Player/PlayerManager.cs +++ b/Robust.Client/Player/PlayerManager.cs @@ -103,9 +103,9 @@ namespace Robust.Client.Player } /// - public void ApplyPlayerStates(IEnumerable? list) + public void ApplyPlayerStates(PlayerState[] list) { - if (list == null) + if (list.Length == 0) { // This happens when the server says "nothing changed!" return; diff --git a/Robust.Server/GameStates/ServerGameStateManager.cs b/Robust.Server/GameStates/ServerGameStateManager.cs index 2ce1c6d2e6..e97027a5df 100644 --- a/Robust.Server/GameStates/ServerGameStateManager.cs +++ b/Robust.Server/GameStates/ServerGameStateManager.cs @@ -208,11 +208,11 @@ namespace Robust.Server.GameStates // lastAck varies with each client based on lag and such, we can't just make 1 global state and send it to everyone var lastInputCommand = inputSystem.GetLastInputCommand(session); var lastSystemMessage = _entityNetworkManager.GetLastMessageSequence(session); - var state = new GameState(lastAck, _gameTiming.CurTick, Math.Max(lastInputCommand, lastSystemMessage), entStates?.ToArray(), playerStates?.ToArray(), deletions?.ToArray(), mapData); + var state = new GameState(lastAck, _gameTiming.CurTick, Math.Max(lastInputCommand, lastSystemMessage), entStates, playerStates, deletions, mapData); InterlockedHelper.Min(ref oldestAckValue, lastAck.Value); - DebugTools.Assert(state.MapData?.CreatedMaps is null || (state.MapData?.CreatedMaps is not null && state.EntityStates is not null), "Sending new maps, but no entity state."); + DebugTools.Assert(state.MapData?.CreatedMaps is null || (state.MapData?.CreatedMaps is not null && state.EntityStates.HasContents), "Sending new maps, but no entity state."); // actually send the state var stateUpdateMessage = _networkManager.CreateNetMessage(); diff --git a/Robust.Shared/GameObjects/EntityState.cs b/Robust.Shared/GameObjects/EntityState.cs index a96ca17340..8297b31833 100644 --- a/Robust.Shared/GameObjects/EntityState.cs +++ b/Robust.Shared/GameObjects/EntityState.cs @@ -1,5 +1,6 @@ using Robust.Shared.Serialization; using System; +using NetSerializer; namespace Robust.Shared.GameObjects { @@ -8,16 +9,15 @@ namespace Robust.Shared.GameObjects { public EntityUid Uid { get; } - public ComponentChange[]? ComponentChanges { get; } + public NetListAsArray ComponentChanges { get; } - public bool Empty => ComponentChanges is null; + public bool Empty => ComponentChanges.Value is null or { Count: 0 }; - public EntityState(EntityUid uid, ComponentChange[]? changedComponents) + public EntityState(EntityUid uid, NetListAsArray changedComponents) { Uid = uid; - // empty lists are 5 bytes each - ComponentChanges = changedComponents == null || changedComponents.Length == 0 ? null : changedComponents; + ComponentChanges = changedComponents; } } diff --git a/Robust.Shared/GameStates/GameState.cs b/Robust.Shared/GameStates/GameState.cs index 89a4afbd6c..7f036e4207 100644 --- a/Robust.Shared/GameStates/GameState.cs +++ b/Robust.Shared/GameStates/GameState.cs @@ -2,6 +2,7 @@ using Robust.Shared.Serialization; using System; using System.Diagnostics; +using NetSerializer; using Robust.Shared.Timing; namespace Robust.Shared.GameStates @@ -26,7 +27,7 @@ namespace Robust.Shared.GameStates /// /// Constructor! /// - public GameState(GameTick fromSequence, GameTick toSequence, uint lastInput, EntityState[]? entities, PlayerState[]? players, EntityUid[]? deletions, GameStateMapData? mapData) + public GameState(GameTick fromSequence, GameTick toSequence, uint lastInput, NetListAsArray entities, NetListAsArray players, NetListAsArray deletions, GameStateMapData? mapData) { FromSequence = fromSequence; ToSequence = toSequence; @@ -42,9 +43,9 @@ namespace Robust.Shared.GameStates public readonly uint LastProcessedInput; - public readonly EntityState[]? EntityStates; - public readonly PlayerState[]? PlayerStates; - public readonly EntityUid[]? EntityDeletions; + public readonly NetListAsArray EntityStates; + public readonly NetListAsArray PlayerStates; + public readonly NetListAsArray EntityDeletions; public readonly GameStateMapData? MapData; } } diff --git a/Robust.UnitTesting/Client/GameStates/GameStateProcessor_Tests.cs b/Robust.UnitTesting/Client/GameStates/GameStateProcessor_Tests.cs index 5f80327cd2..b8ed0f7d37 100644 --- a/Robust.UnitTesting/Client/GameStates/GameStateProcessor_Tests.cs +++ b/Robust.UnitTesting/Client/GameStates/GameStateProcessor_Tests.cs @@ -235,7 +235,7 @@ namespace Robust.UnitTesting.Client.GameStates /// private static GameState GameStateFactory(uint from, uint to) { - return new(new GameTick(@from), new GameTick(to), 0, null, null, null, null); + return new(new GameTick(@from), new GameTick(to), 0, default, default, default, null); } ///