using Robust.Shared.GameStates; using Robust.Shared.Serialization; using Robust.Shared.Serialization.TypeSerializers.Implementations.Generic; 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 partial class DecalGridComponent : Component { [Access(Other = AccessPermissions.ReadExecute)] [DataField(serverOnly: true)] public DecalGridChunkCollection ChunkCollection = new(new ()); /// /// Dictionary mapping decals to their corresponding grid chunks. /// public readonly Dictionary DecalIndex = new(); /// /// Tick at which PVS was last toggled. Ensures that all players receive a full update when toggling PVS. /// public GameTick ForceTick { get; set; } [DataDefinition] [Serializable, NetSerializable] public sealed partial class DecalChunk { [IncludeDataField(customTypeSerializer:typeof(DictionarySerializer))] public Dictionary Decals; [NonSerialized] public GameTick LastModified; public DecalChunk() { Decals = new(); } public DecalChunk(Dictionary 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 partial record DecalGridChunkCollection(Dictionary ChunkCollection) { public uint NextDecalId; } } [Serializable, NetSerializable] public sealed class DecalGridState(Dictionary chunks) : ComponentState { public Dictionary Chunks = chunks; } [Serializable, NetSerializable] public sealed class DecalGridDeltaState(Dictionary modifiedChunks, HashSet allChunks) : ComponentState, IComponentDeltaState { public Dictionary ModifiedChunks = modifiedChunks; public HashSet AllChunks = allChunks; public void ApplyToFullState(DecalGridState state) { foreach (var key in state.Chunks.Keys) { if (!AllChunks!.Contains(key)) state.Chunks.Remove(key); } foreach (var (chunk, data) in ModifiedChunks) { state.Chunks[chunk] = new(data); } } public DecalGridState CreateNewFullState(DecalGridState state) { var chunks = new Dictionary(state.Chunks.Count); foreach (var (chunk, data) in ModifiedChunks) { chunks[chunk] = new(data); } foreach (var (chunk, data) in state.Chunks) { if (AllChunks!.Contains(chunk)) chunks.TryAdd(chunk, new(data)); } return new DecalGridState(chunks); } } }