| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- using Content.Client.Decals.Overlays;
- using Content.Shared.Decals;
- using Robust.Client.GameObjects;
- using Robust.Client.Graphics;
- using Robust.Shared.GameStates;
- using Robust.Shared.Utility;
- using static Content.Shared.Decals.DecalGridComponent;
- namespace Content.Client.Decals
- {
- public sealed class DecalSystem : SharedDecalSystem
- {
- [Dependency] private readonly IOverlayManager _overlayManager = default!;
- [Dependency] private readonly SpriteSystem _sprites = default!;
- private DecalOverlay _overlay = default!;
- private HashSet<uint> _removedUids = new();
- private readonly List<Vector2i> _removedChunks = new();
- public override void Initialize()
- {
- base.Initialize();
- _overlay = new DecalOverlay(_sprites, EntityManager, PrototypeManager);
- _overlayManager.AddOverlay(_overlay);
- SubscribeLocalEvent<DecalGridComponent, ComponentHandleState>(OnHandleState);
- SubscribeNetworkEvent<DecalChunkUpdateEvent>(OnChunkUpdate);
- }
- public void ToggleOverlay()
- {
- if (_overlayManager.HasOverlay<DecalOverlay>())
- {
- _overlayManager.RemoveOverlay(_overlay);
- }
- else
- {
- _overlayManager.AddOverlay(_overlay);
- }
- }
- public override void Shutdown()
- {
- base.Shutdown();
- _overlayManager.RemoveOverlay(_overlay);
- }
- protected override void OnDecalRemoved(EntityUid gridId, uint decalId, DecalGridComponent component, Vector2i indices, DecalChunk chunk)
- {
- base.OnDecalRemoved(gridId, decalId, component, indices, chunk);
- DebugTools.Assert(chunk.Decals.ContainsKey(decalId));
- chunk.Decals.Remove(decalId);
- }
- private void OnHandleState(EntityUid gridUid, DecalGridComponent gridComp, ref ComponentHandleState args)
- {
- // is this a delta or full state?
- _removedChunks.Clear();
- Dictionary<Vector2i, DecalChunk> modifiedChunks;
- switch (args.Current)
- {
- case DecalGridDeltaState delta:
- {
- modifiedChunks = delta.ModifiedChunks;
- foreach (var key in gridComp.ChunkCollection.ChunkCollection.Keys)
- {
- if (!delta.AllChunks.Contains(key))
- _removedChunks.Add(key);
- }
- break;
- }
- case DecalGridState state:
- {
- modifiedChunks = state.Chunks;
- foreach (var key in gridComp.ChunkCollection.ChunkCollection.Keys)
- {
- if (!state.Chunks.ContainsKey(key))
- _removedChunks.Add(key);
- }
- break;
- }
- default:
- return;
- }
- if (_removedChunks.Count > 0)
- RemoveChunks(gridUid, gridComp, _removedChunks);
- if (modifiedChunks.Count > 0)
- UpdateChunks(gridUid, gridComp, modifiedChunks);
- }
- private void OnChunkUpdate(DecalChunkUpdateEvent ev)
- {
- foreach (var (netGrid, updatedGridChunks) in ev.Data)
- {
- if (updatedGridChunks.Count == 0)
- continue;
- var gridId = GetEntity(netGrid);
- if (!TryComp(gridId, out DecalGridComponent? gridComp))
- {
- Log.Error($"Received decal information for an entity without a decal component: {ToPrettyString(gridId)}");
- continue;
- }
- UpdateChunks(gridId, gridComp, updatedGridChunks);
- }
- // Now we'll cull old chunks out of range as the server will send them to us anyway.
- foreach (var (netGrid, chunks) in ev.RemovedChunks)
- {
- if (chunks.Count == 0)
- continue;
- var gridId = GetEntity(netGrid);
- if (!TryComp(gridId, out DecalGridComponent? gridComp))
- {
- Log.Error($"Received decal information for an entity without a decal component: {ToPrettyString(gridId)}");
- continue;
- }
- RemoveChunks(gridId, gridComp, chunks);
- }
- }
- private void UpdateChunks(EntityUid gridId, DecalGridComponent gridComp, Dictionary<Vector2i, DecalChunk> updatedGridChunks)
- {
- var chunkCollection = gridComp.ChunkCollection.ChunkCollection;
- // Update any existing data / remove decals we didn't receive data for.
- foreach (var (indices, newChunkData) in updatedGridChunks)
- {
- if (chunkCollection.TryGetValue(indices, out var chunk))
- {
- _removedUids.Clear();
- _removedUids.UnionWith(chunk.Decals.Keys);
- _removedUids.ExceptWith(newChunkData.Decals.Keys);
- foreach (var removedUid in _removedUids)
- {
- OnDecalRemoved(gridId, removedUid, gridComp, indices, chunk);
- gridComp.DecalIndex.Remove(removedUid);
- }
- }
- chunkCollection[indices] = newChunkData;
- foreach (var (uid, decal) in newChunkData.Decals)
- {
- gridComp.DecalIndex[uid] = indices;
- }
- }
- }
- private void RemoveChunks(EntityUid gridId, DecalGridComponent gridComp, IEnumerable<Vector2i> chunks)
- {
- var chunkCollection = gridComp.ChunkCollection.ChunkCollection;
- foreach (var index in chunks)
- {
- if (!chunkCollection.TryGetValue(index, out var chunk))
- continue;
- foreach (var decalId in chunk.Decals.Keys)
- {
- OnDecalRemoved(gridId, decalId, gridComp, index, chunk);
- gridComp.DecalIndex.Remove(decalId);
- }
- chunkCollection.Remove(index);
- }
- }
- }
- }
|