Decal state handling (#12624)
This commit is contained in:
@@ -6,12 +6,13 @@ namespace Content.Shared.Decals
|
||||
[DataDefinition]
|
||||
public sealed class Decal
|
||||
{
|
||||
// if these are made not-readonly, then decal grid state handling needs to be updated to clone decals.
|
||||
[DataField("coordinates")] public readonly Vector2 Coordinates = Vector2.Zero;
|
||||
[DataField("id")] public readonly string Id = string.Empty;
|
||||
[DataField("color")] public readonly Color? Color;
|
||||
[DataField("angle")] public readonly Angle Angle = Angle.Zero;
|
||||
[DataField("zIndex")] public readonly int ZIndex;
|
||||
[DataField("cleanable")] public bool Cleanable;
|
||||
[DataField("cleanable")] public readonly bool Cleanable;
|
||||
|
||||
public Decal() {}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Serialization;
|
||||
using static Content.Shared.Decals.DecalGridComponent;
|
||||
|
||||
namespace Content.Shared.Decals
|
||||
{
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class DecalChunkUpdateEvent : EntityEventArgs
|
||||
{
|
||||
public Dictionary<EntityUid, Dictionary<Vector2i, Dictionary<uint, Decal>>> Data = new();
|
||||
public Dictionary<EntityUid, Dictionary<Vector2i, DecalChunk>> Data = new();
|
||||
public Dictionary<EntityUid, HashSet<Vector2i>> RemovedChunks = new();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using Robust.Shared.Serialization.Markdown;
|
||||
using Robust.Shared.Serialization.Markdown.Mapping;
|
||||
using Robust.Shared.Serialization.Markdown.Validation;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Interfaces;
|
||||
using static Content.Shared.Decals.DecalGridComponent;
|
||||
|
||||
namespace Content.Shared.Decals
|
||||
{
|
||||
@@ -20,13 +21,13 @@ namespace Content.Shared.Decals
|
||||
IDependencyCollection dependencies, bool skipHook, ISerializationContext? context = null,
|
||||
ISerializationManager.InstantiationDelegate<DecalGridComponent.DecalGridChunkCollection>? _ = default)
|
||||
{
|
||||
var dictionary = serializationManager.Read<Dictionary<Vector2i, Dictionary<uint, Decal>>>(node, context, skipHook, notNullableOverride: true);
|
||||
var dictionary = serializationManager.Read<Dictionary<Vector2i, DecalChunk>>(node, context, skipHook: skipHook, notNullableOverride: true);
|
||||
|
||||
var uids = new SortedSet<uint>();
|
||||
var uidChunkMap = new Dictionary<uint, Vector2i>();
|
||||
foreach (var (indices, decals) in dictionary)
|
||||
{
|
||||
foreach (var (uid, _) in decals)
|
||||
foreach (var uid in decals.Decals.Keys)
|
||||
{
|
||||
uids.Add(uid);
|
||||
uidChunkMap[uid] = indices;
|
||||
@@ -40,13 +41,13 @@ namespace Content.Shared.Decals
|
||||
uidMap[uid] = nextIndex++;
|
||||
}
|
||||
|
||||
var newDict = new Dictionary<Vector2i, Dictionary<uint, Decal>>();
|
||||
var newDict = new Dictionary<Vector2i, DecalChunk>();
|
||||
foreach (var (oldUid, newUid) in uidMap)
|
||||
{
|
||||
var indices = uidChunkMap[oldUid];
|
||||
if(!newDict.ContainsKey(indices))
|
||||
newDict[indices] = new();
|
||||
newDict[indices][newUid] = dictionary[indices][oldUid];
|
||||
newDict[indices].Decals[newUid] = dictionary[indices].Decals[oldUid];
|
||||
}
|
||||
|
||||
return new DecalGridComponent.DecalGridChunkCollection(newDict){NextUid = nextIndex};
|
||||
|
||||
@@ -1,16 +1,110 @@
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
using static Content.Shared.Decals.DecalGridComponent;
|
||||
|
||||
namespace Content.Shared.Decals
|
||||
{
|
||||
[RegisterComponent]
|
||||
[Access(typeof(SharedDecalSystem))]
|
||||
[NetworkedComponent]
|
||||
public sealed class DecalGridComponent : Component
|
||||
{
|
||||
[DataField("chunkCollection", serverOnly: true)]
|
||||
public DecalGridChunkCollection ChunkCollection = new(new ());
|
||||
|
||||
[DataRecord]
|
||||
public record DecalGridChunkCollection(Dictionary<Vector2i, Dictionary<uint, Decal>> ChunkCollection)
|
||||
/// <summary>
|
||||
/// Tick at which PVS was last toggled. Ensures that all players receive a full update when toggling PVS.
|
||||
/// </summary>
|
||||
public GameTick ForceTick { get; set; }
|
||||
|
||||
[DataDefinition]
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class DecalChunk
|
||||
{
|
||||
[DataField("decals")]
|
||||
public Dictionary<uint, Decal> Decals;
|
||||
|
||||
[NonSerialized]
|
||||
public GameTick LastModified;
|
||||
|
||||
public DecalChunk()
|
||||
{
|
||||
Decals = new();
|
||||
}
|
||||
|
||||
public DecalChunk(Dictionary<uint, Decal> decals)
|
||||
{
|
||||
Decals = decals;
|
||||
}
|
||||
|
||||
public DecalChunk(DecalChunk chunk)
|
||||
{
|
||||
// decals are readonly, so this should be fine.
|
||||
Decals = chunk.Decals.ShallowClone();
|
||||
LastModified = chunk.LastModified;
|
||||
}
|
||||
}
|
||||
|
||||
[DataRecord, Serializable, NetSerializable]
|
||||
public record DecalGridChunkCollection(Dictionary<Vector2i, DecalChunk> ChunkCollection)
|
||||
{
|
||||
public uint NextUid;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class DecalGridState : ComponentState, IComponentDeltaState
|
||||
{
|
||||
public Dictionary<Vector2i, DecalChunk> Chunks;
|
||||
public bool FullState => AllChunks == null;
|
||||
|
||||
// required to infer deleted/missing chunks for delta states
|
||||
public HashSet<Vector2i>? AllChunks;
|
||||
|
||||
public DecalGridState(Dictionary<Vector2i, DecalChunk> chunks)
|
||||
{
|
||||
Chunks = chunks;
|
||||
}
|
||||
|
||||
public void ApplyToFullState(ComponentState fullState)
|
||||
{
|
||||
DebugTools.Assert(!FullState);
|
||||
var state = (DecalGridState) fullState;
|
||||
DebugTools.Assert(state.FullState);
|
||||
|
||||
foreach (var key in state.Chunks.Keys)
|
||||
{
|
||||
if (!AllChunks!.Contains(key))
|
||||
state.Chunks.Remove(key);
|
||||
}
|
||||
|
||||
foreach (var (chunk, data) in Chunks)
|
||||
{
|
||||
state.Chunks[chunk] = new(data);
|
||||
}
|
||||
}
|
||||
|
||||
public ComponentState CreateNewFullState(ComponentState fullState)
|
||||
{
|
||||
DebugTools.Assert(!FullState);
|
||||
var state = (DecalGridState) fullState;
|
||||
DebugTools.Assert(state.FullState);
|
||||
|
||||
var chunks = new Dictionary<Vector2i, DecalChunk>(state.Chunks.Count);
|
||||
|
||||
foreach (var (chunk, data) in Chunks)
|
||||
{
|
||||
chunks[chunk] = new(data);
|
||||
}
|
||||
|
||||
foreach (var (chunk, data) in state.Chunks)
|
||||
{
|
||||
if (AllChunks!.Contains(chunk))
|
||||
chunks.TryAdd(chunk, new(data));
|
||||
}
|
||||
return new DecalGridState(chunks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using static Content.Shared.Decals.DecalGridComponent;
|
||||
|
||||
namespace Content.Shared.Decals
|
||||
{
|
||||
@@ -32,7 +33,7 @@ namespace Content.Shared.Decals
|
||||
ChunkIndex[msg.EntityUid] = new();
|
||||
foreach (var (indices, decals) in comp.ChunkCollection.ChunkCollection)
|
||||
{
|
||||
foreach (var uid in decals.Keys)
|
||||
foreach (var uid in decals.Decals.Keys)
|
||||
{
|
||||
ChunkIndex[msg.EntityUid][uid] = indices;
|
||||
}
|
||||
@@ -47,13 +48,13 @@ namespace Content.Shared.Decals
|
||||
return comp.ChunkCollection;
|
||||
}
|
||||
|
||||
protected Dictionary<Vector2i, Dictionary<uint, Decal>>? ChunkCollection(EntityUid gridEuid, DecalGridComponent? comp = null)
|
||||
protected Dictionary<Vector2i, DecalChunk>? ChunkCollection(EntityUid gridEuid, DecalGridComponent? comp = null)
|
||||
{
|
||||
var collection = DecalGridChunkCollection(gridEuid, comp);
|
||||
return collection?.ChunkCollection;
|
||||
}
|
||||
|
||||
protected virtual void DirtyChunk(EntityUid id, Vector2i chunkIndices) {}
|
||||
protected virtual void DirtyChunk(EntityUid id, Vector2i chunkIndices, DecalChunk chunk) {}
|
||||
|
||||
protected bool RemoveDecalInternal(EntityUid gridId, uint uid)
|
||||
{
|
||||
@@ -65,16 +66,16 @@ namespace Content.Shared.Decals
|
||||
}
|
||||
|
||||
var chunkCollection = ChunkCollection(gridId);
|
||||
if (chunkCollection == null || !chunkCollection.TryGetValue(indices, out var chunk) || !chunk.Remove(uid))
|
||||
if (chunkCollection == null || !chunkCollection.TryGetValue(indices, out var chunk) || !chunk.Decals.Remove(uid))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (chunk.Count == 0)
|
||||
if (chunk.Decals.Count == 0)
|
||||
chunkCollection.Remove(indices);
|
||||
|
||||
ChunkIndex[gridId].Remove(uid);
|
||||
DirtyChunk(gridId, indices);
|
||||
DirtyChunk(gridId, indices, chunk);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user