Grid delta states (#3635)

This commit is contained in:
Leon Friedrich
2023-01-08 18:43:49 +13:00
committed by GitHub
parent 987d76b53d
commit a323f2ef84
3 changed files with 127 additions and 12 deletions

View File

@@ -103,10 +103,15 @@ public abstract partial class SharedMapSystem
component.ChunkSize = state.ChunkSize;
if (state.ChunkData == null && state.FullGridData == null)
return;
var modified = new List<(Vector2i position, Tile tile)>();
MapManager.SuppressOnTileChanged = true;
// delta state
if (state.ChunkData != null)
{
var modified = new List<(Vector2i position, Tile tile)>();
MapManager.SuppressOnTileChanged = true;
foreach (var chunkData in state.ChunkData)
{
if (chunkData.IsDeleted())
@@ -143,19 +148,55 @@ public abstract partial class SharedMapSystem
chunk.SuppressCollisionRegeneration = false;
component.RegenerateCollision(chunk);
}
}
MapManager.SuppressOnTileChanged = false;
if (modified.Count != 0)
// full state
if (state.FullGridData != null)
{
foreach (var index in component.Chunks.Keys)
{
RaiseLocalEvent(uid, new GridModifiedEvent(component, modified), true);
if (!state.FullGridData.ContainsKey(index))
component.RemoveChunk(index);
}
foreach (var (index, tiles) in state.FullGridData)
{
var chunk = component.GetOrAddChunk(index);
chunk.SuppressCollisionRegeneration = true;
DebugTools.Assert(tiles.Length == component.ChunkSize * component.ChunkSize);
var counter = 0;
for (ushort x = 0; x < component.ChunkSize; x++)
{
for (ushort y = 0; y < component.ChunkSize; y++)
{
var tile = tiles[counter++];
if (chunk.GetTile(x, y) == tile)
continue;
chunk.SetTile(x, y, tile);
modified.Add((new Vector2i(chunk.X * component.ChunkSize + x, chunk.Y * component.ChunkSize + y), tile));
}
}
chunk.SuppressCollisionRegeneration = false;
component.RegenerateCollision(chunk);
}
}
MapManager.SuppressOnTileChanged = false;
if (modified.Count != 0)
RaiseLocalEvent(uid, new GridModifiedEvent(component, modified), true);
}
private void OnGridGetState(EntityUid uid, MapGridComponent component, ref ComponentGetState args)
{
// TODO: Actual deltas.
if (args.FromTick <= component.CreationTick)
{
GetFullState(component, ref args);
return;
}
List<ChunkDatum>? chunkData;
var fromTick = args.FromTick;
@@ -170,7 +211,7 @@ public abstract partial class SharedMapSystem
foreach (var (tick, indices) in chunks)
{
if (tick < fromTick)
if (tick < fromTick && fromTick != GameTick.Zero)
continue;
chunkData.Add(ChunkDatum.CreateDeleted(indices));
@@ -197,7 +238,27 @@ public abstract partial class SharedMapSystem
}
}
// TODO: Mark it as delta proper
args.State = new MapGridComponentState(component.ChunkSize, chunkData);
}
private void GetFullState(MapGridComponent component, ref ComponentGetState args)
{
var chunkData = new Dictionary<Vector2i, Tile[]>();
foreach (var (index, chunk) in component.GetMapChunks())
{
var tileBuffer = new Tile[component.ChunkSize * (uint)component.ChunkSize];
for (var x = 0; x < component.ChunkSize; x++)
{
for (var y = 0; y < component.ChunkSize; y++)
{
tileBuffer[x * component.ChunkSize + y] = chunk.GetTile((ushort)x, (ushort)y);
}
}
chunkData.Add(index, tileBuffer);
}
args.State = new MapGridComponentState(component.ChunkSize, chunkData);
}

View File

@@ -5,6 +5,7 @@ using System.Linq;
using Robust.Shared.GameObjects;
using Robust.Shared.GameStates;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Map.Enumerators;
using Robust.Shared.Map.Events;
using Robust.Shared.Maths;
@@ -901,7 +902,7 @@ namespace Robust.Shared.Map.Components
/// Serialized state of a <see cref="MapGridComponentState"/>.
/// </summary>
[Serializable, NetSerializable]
internal sealed class MapGridComponentState : ComponentState
internal sealed class MapGridComponentState : ComponentState, IComponentDeltaState
{
/// <summary>
/// The size of the chunks in the map grid.
@@ -914,12 +915,65 @@ namespace Robust.Shared.Map.Components
public List<ChunkDatum>? ChunkData;
/// <summary>
/// Constructs a new instance of <see cref="MapGridComponentState"/>.
/// Networked chunk data containing the full grid state.
/// </summary>
public Dictionary<Vector2i, Tile[]>? FullGridData;
public bool FullState => FullGridData != null;
/// <summary>
/// Constructs a new grid component delta state.
/// </summary>
public MapGridComponentState(ushort chunkSize, List<ChunkDatum>? chunkData)
{
ChunkSize = chunkSize;
ChunkData = chunkData;
}
/// <summary>
/// Constructs a new full component state.
/// </summary>
public MapGridComponentState(ushort chunkSize, Dictionary<Vector2i, Tile[]> fullGridData)
{
ChunkSize = chunkSize;
FullGridData = fullGridData;
}
public void ApplyToFullState(ComponentState fullState)
{
var state = (MapGridComponentState)fullState;
DebugTools.Assert(!FullState && state.FullState);
state.ChunkSize = ChunkSize;
if (ChunkData == null)
return;
foreach (var data in ChunkData)
{
if (data.IsDeleted())
state.FullGridData!.Remove(data.Index);
else
state.FullGridData![data.Index] = data.TileData;
}
}
public ComponentState CreateNewFullState(ComponentState fullState)
{
var state = (MapGridComponentState)fullState;
DebugTools.Assert(!FullState && state.FullState);
var fullGridData = new Dictionary<Vector2i, Tile[]>(state.FullGridData!.Count);
foreach (var (key, value) in state.FullGridData)
{
var arr = fullGridData[key] = new Tile[value.Length];
Array.Copy(value, arr, value.Length);
}
var newState = new MapGridComponentState(ChunkSize, fullGridData);
ApplyToFullState(newState);
return newState;
}
}
}

View File

@@ -65,7 +65,7 @@ namespace Robust.UnitTesting.Shared.GameObjects
new EntityUid(512),
new []
{
new ComponentChange(0, new MapGridComponentState(16, null), default)
new ComponentChange(0, new MapGridComponentState(16, chunkData: null), default)
}, default);
serializer.Serialize(stream, payload);