Fix decals (finally) (#7771)
This commit is contained in:
@@ -45,6 +45,8 @@ namespace Content.Client.Decals
|
|||||||
|
|
||||||
foreach (var (gridId, zIndexDictionary) in _decals.DecalRenderIndex)
|
foreach (var (gridId, zIndexDictionary) in _decals.DecalRenderIndex)
|
||||||
{
|
{
|
||||||
|
if (zIndexDictionary.Count == 0) continue;
|
||||||
|
|
||||||
var gridUid = _mapManager.GetGridEuid(gridId);
|
var gridUid = _mapManager.GetGridEuid(gridId);
|
||||||
var xform = xformQuery.GetComponent(gridUid);
|
var xform = xformQuery.GetComponent(gridUid);
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ namespace Content.Client.Decals
|
|||||||
protected override bool RemoveDecalHook(GridId gridId, uint uid)
|
protected override bool RemoveDecalHook(GridId gridId, uint uid)
|
||||||
{
|
{
|
||||||
RemoveDecalFromRenderIndex(gridId, uid);
|
RemoveDecalFromRenderIndex(gridId, uid);
|
||||||
|
|
||||||
return base.RemoveDecalHook(gridId, uid);
|
return base.RemoveDecalHook(gridId, uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,8 +79,11 @@ namespace Content.Client.Decals
|
|||||||
{
|
{
|
||||||
foreach (var (gridId, gridChunks) in ev.Data)
|
foreach (var (gridId, gridChunks) in ev.Data)
|
||||||
{
|
{
|
||||||
|
if (gridChunks.Count == 0) continue;
|
||||||
|
|
||||||
var chunkCollection = ChunkCollection(gridId);
|
var chunkCollection = ChunkCollection(gridId);
|
||||||
|
|
||||||
|
// Update any existing data / remove decals we didn't receive data for.
|
||||||
foreach (var (indices, newChunkData) in gridChunks)
|
foreach (var (indices, newChunkData) in gridChunks)
|
||||||
{
|
{
|
||||||
if (chunkCollection.TryGetValue(indices, out var chunk))
|
if (chunkCollection.TryGetValue(indices, out var chunk))
|
||||||
@@ -90,8 +92,14 @@ namespace Content.Client.Decals
|
|||||||
removedUids.ExceptWith(newChunkData.Keys);
|
removedUids.ExceptWith(newChunkData.Keys);
|
||||||
foreach (var removedUid in removedUids)
|
foreach (var removedUid in removedUids)
|
||||||
{
|
{
|
||||||
RemoveDecalFromRenderIndex(gridId, removedUid);
|
RemoveDecalInternal(gridId, removedUid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chunkCollection[indices] = newChunkData;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
chunkCollection.Add(indices, newChunkData);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var (uid, decal) in newChunkData)
|
foreach (var (uid, decal) in newChunkData)
|
||||||
@@ -107,25 +115,27 @@ namespace Content.Client.Decals
|
|||||||
|
|
||||||
DecalRenderIndex[gridId][decal.ZIndex][uid] = decal;
|
DecalRenderIndex[gridId][decal.ZIndex][uid] = decal;
|
||||||
DecalZIndexIndex[gridId][uid] = decal.ZIndex;
|
DecalZIndexIndex[gridId][uid] = decal.ZIndex;
|
||||||
|
|
||||||
ChunkIndex[gridId][uid] = indices;
|
ChunkIndex[gridId][uid] = indices;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
chunkCollection[indices] = newChunkData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we'll cull old chunks out of range as the server will send them to us anyway.
|
// Now we'll cull old chunks out of range as the server will send them to us anyway.
|
||||||
var toRemove = new RemQueue<Vector2i>();
|
foreach (var (gridId, chunks) in ev.RemovedChunks)
|
||||||
|
|
||||||
foreach (var (index, _) in chunkCollection)
|
|
||||||
{
|
{
|
||||||
if (gridChunks.ContainsKey(index)) continue;
|
if (chunks.Count == 0) continue;
|
||||||
|
|
||||||
toRemove.Add(index);
|
var chunkCollection = ChunkCollection(gridId);
|
||||||
|
|
||||||
|
foreach (var index in chunks)
|
||||||
|
{
|
||||||
|
if (!chunkCollection.TryGetValue(index, out var chunk)) continue;
|
||||||
|
|
||||||
|
foreach (var (uid, _) in chunk)
|
||||||
|
{
|
||||||
|
RemoveDecalInternal(gridId, uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var index in toRemove)
|
|
||||||
{
|
|
||||||
chunkCollection.Remove(index);
|
chunkCollection.Remove(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ namespace Content.Server.Chemistry.TileReactions
|
|||||||
}
|
}
|
||||||
|
|
||||||
var decalSystem = EntitySystem.Get<DecalSystem>();
|
var decalSystem = EntitySystem.Get<DecalSystem>();
|
||||||
foreach (var uid in decalSystem.GetDecalsInRange(tile.GridIndex, tile.GridIndices+new Vector2(0.5f, 0.5f), validDelegate: x => x.Cleanable))
|
foreach (var (uid, _) in decalSystem.GetDecalsInRange(tile.GridIndex, tile.GridIndices+new Vector2(0.5f, 0.5f), validDelegate: x => x.Cleanable))
|
||||||
{
|
{
|
||||||
decalSystem.RemoveDecal(tile.GridIndex, uid);
|
decalSystem.RemoveDecal(tile.GridIndex, uid);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using Robust.Server.Player;
|
|||||||
using Robust.Shared.Enums;
|
using Robust.Shared.Enums;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Server.Decals
|
namespace Content.Server.Decals
|
||||||
{
|
{
|
||||||
@@ -42,6 +43,52 @@ namespace Content.Server.Decals
|
|||||||
|
|
||||||
SubscribeNetworkEvent<RequestDecalPlacementEvent>(OnDecalPlacementRequest);
|
SubscribeNetworkEvent<RequestDecalPlacementEvent>(OnDecalPlacementRequest);
|
||||||
SubscribeNetworkEvent<RequestDecalRemovalEvent>(OnDecalRemovalRequest);
|
SubscribeNetworkEvent<RequestDecalRemovalEvent>(OnDecalRemovalRequest);
|
||||||
|
SubscribeLocalEvent<PostGridSplitEvent>(OnGridSplit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGridSplit(ref PostGridSplitEvent ev)
|
||||||
|
{
|
||||||
|
// Transfer decals over to the new grid.
|
||||||
|
var enumerator = MapManager.GetGrid(ev.Grid).GetAllTilesEnumerator();
|
||||||
|
var oldChunkCollection = DecalGridChunkCollection(ev.OldGrid);
|
||||||
|
var chunkCollection = DecalGridChunkCollection(ev.Grid);
|
||||||
|
|
||||||
|
while (enumerator.MoveNext(out var tile))
|
||||||
|
{
|
||||||
|
var tilePos = (Vector2) tile.Value.GridIndices;
|
||||||
|
var chunkIndices = GetChunkIndices(tilePos);
|
||||||
|
|
||||||
|
if (!oldChunkCollection.ChunkCollection.TryGetValue(chunkIndices, out var oldChunk)) continue;
|
||||||
|
|
||||||
|
var bounds = new Box2(tilePos - 0.01f, tilePos + 1.01f);
|
||||||
|
var toRemove = new RemQueue<uint>();
|
||||||
|
|
||||||
|
foreach (var (oldUid, decal) in oldChunk)
|
||||||
|
{
|
||||||
|
if (!bounds.Contains(decal.Coordinates)) continue;
|
||||||
|
|
||||||
|
var uid = chunkCollection.NextUid++;
|
||||||
|
var chunk = chunkCollection.ChunkCollection.GetOrNew(chunkIndices);
|
||||||
|
|
||||||
|
chunk[uid] = decal;
|
||||||
|
ChunkIndex[ev.Grid][uid] = chunkIndices;
|
||||||
|
DirtyChunk(ev.Grid, chunkIndices);
|
||||||
|
|
||||||
|
toRemove.Add(oldUid);
|
||||||
|
ChunkIndex[ev.OldGrid].Remove(oldUid);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var uid in toRemove)
|
||||||
|
{
|
||||||
|
oldChunk.Remove(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldChunk.Count == 0)
|
||||||
|
oldChunkCollection.ChunkCollection.Remove(chunkIndices);
|
||||||
|
|
||||||
|
if (toRemove.List?.Count > 0)
|
||||||
|
DirtyChunk(ev.OldGrid, chunkIndices);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Shutdown()
|
public override void Shutdown()
|
||||||
@@ -127,9 +174,10 @@ namespace Content.Server.Decals
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// remove all decals on the same tile
|
// remove all decals on the same tile
|
||||||
foreach (var decal in GetDecalsInRange(gridId, ev.Coordinates.Position))
|
foreach (var (uid, decal) in GetDecalsInRange(gridId, ev.Coordinates.Position))
|
||||||
{
|
{
|
||||||
RemoveDecal(gridId, decal);
|
var chunkIndices = GetChunkIndices(decal.Coordinates);
|
||||||
|
RemoveDecal(gridId, uid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,10 +206,10 @@ namespace Content.Server.Decals
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
var gridId = coordinates.GetGridId(EntityManager);
|
var gridId = coordinates.GetGridId(EntityManager);
|
||||||
if (!gridId.IsValid())
|
if (!MapManager.TryGetGrid(gridId, out var grid))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (MapManager.GetGrid(gridId).GetTileRef(coordinates).IsSpace())
|
if (grid.GetTileRef(coordinates).IsSpace(_tileDefMan))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var chunkCollection = DecalGridChunkCollection(gridId);
|
var chunkCollection = DecalGridChunkCollection(gridId);
|
||||||
@@ -178,9 +226,9 @@ namespace Content.Server.Decals
|
|||||||
|
|
||||||
public bool RemoveDecal(GridId gridId, uint uid) => RemoveDecalInternal(gridId, uid);
|
public bool RemoveDecal(GridId gridId, uint uid) => RemoveDecalInternal(gridId, uid);
|
||||||
|
|
||||||
public HashSet<uint> GetDecalsInRange(GridId gridId, Vector2 position, float distance = 0.75f, Func<Decal, bool>? validDelegate = null)
|
public HashSet<(uint Index, Decal Decal)> GetDecalsInRange(GridId gridId, Vector2 position, float distance = 0.75f, Func<Decal, bool>? validDelegate = null)
|
||||||
{
|
{
|
||||||
var uids = new HashSet<uint>();
|
var uids = new HashSet<(uint, Decal)>();
|
||||||
var chunkCollection = ChunkCollection(gridId);
|
var chunkCollection = ChunkCollection(gridId);
|
||||||
var chunkIndices = GetChunkIndices(position);
|
var chunkIndices = GetChunkIndices(position);
|
||||||
if (!chunkCollection.TryGetValue(chunkIndices, out var chunk))
|
if (!chunkCollection.TryGetValue(chunkIndices, out var chunk))
|
||||||
@@ -193,7 +241,7 @@ namespace Content.Server.Decals
|
|||||||
|
|
||||||
if (validDelegate == null || validDelegate(decal))
|
if (validDelegate == null || validDelegate(decal))
|
||||||
{
|
{
|
||||||
uids.Add(uid);
|
uids.Add((uid, decal));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,15 +358,33 @@ namespace Content.Server.Decals
|
|||||||
{
|
{
|
||||||
base.Update(frameTime);
|
base.Update(frameTime);
|
||||||
|
|
||||||
|
|
||||||
foreach (var session in Filter.GetAllPlayers(_playerManager))
|
foreach (var session in Filter.GetAllPlayers(_playerManager))
|
||||||
{
|
{
|
||||||
if (session is not IPlayerSession { Status: SessionStatus.InGame } playerSession)
|
if (session is not IPlayerSession { Status: SessionStatus.InGame } playerSession)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var chunks = GetChunksForSession(playerSession);
|
var chunksInRange = GetChunksForSession(playerSession);
|
||||||
|
var staleChunks = new Dictionary<GridId, HashSet<Vector2i>>();
|
||||||
|
|
||||||
|
// Get any chunks not in range anymore
|
||||||
|
foreach (var (gridId, oldIndices) in _previousSentChunks[playerSession])
|
||||||
|
{
|
||||||
|
if (!chunksInRange.TryGetValue(gridId, out var chunks))
|
||||||
|
{
|
||||||
|
staleChunks[gridId] = oldIndices;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var chunk in oldIndices)
|
||||||
|
{
|
||||||
|
if (chunks.Contains(chunk)) continue;
|
||||||
|
var elmo = staleChunks.GetOrNew(gridId);
|
||||||
|
elmo.Add(chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var updatedChunks = _chunkViewerPool.Get();
|
var updatedChunks = _chunkViewerPool.Get();
|
||||||
foreach (var (gridId, gridChunks) in chunks)
|
foreach (var (gridId, gridChunks) in chunksInRange)
|
||||||
{
|
{
|
||||||
var newChunks = _chunkIndexPool.Get();
|
var newChunks = _chunkIndexPool.Get();
|
||||||
newChunks.UnionWith(gridChunks);
|
newChunks.UnionWith(gridChunks);
|
||||||
@@ -344,17 +410,18 @@ namespace Content.Server.Decals
|
|||||||
|
|
||||||
if (updatedChunks.Count == 0)
|
if (updatedChunks.Count == 0)
|
||||||
{
|
{
|
||||||
ReturnToPool(chunks);
|
ReturnToPool(chunksInRange);
|
||||||
// Even if updatedChunks is empty we'll still return it to the pool as it may have been allocated higher.
|
// Even if updatedChunks is empty we'll still return it to the pool as it may have been allocated higher.
|
||||||
ReturnToPool(updatedChunks);
|
ReturnToPool(updatedChunks);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (updatedChunks.Count == 0 && staleChunks.Count == 0) continue;
|
||||||
|
|
||||||
ReturnToPool(_previousSentChunks[playerSession]);
|
ReturnToPool(_previousSentChunks[playerSession]);
|
||||||
_previousSentChunks[playerSession] = chunks;
|
_previousSentChunks[playerSession] = chunksInRange;
|
||||||
|
|
||||||
//send all gridChunks to client
|
//send all gridChunks to client
|
||||||
SendChunkUpdates(playerSession, updatedChunks);
|
SendChunkUpdates(playerSession, updatedChunks, staleChunks);
|
||||||
}
|
}
|
||||||
|
|
||||||
_dirtyChunks.Clear();
|
_dirtyChunks.Clear();
|
||||||
@@ -372,7 +439,10 @@ namespace Content.Server.Decals
|
|||||||
_chunkViewerPool.Return(chunks);
|
_chunkViewerPool.Return(chunks);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendChunkUpdates(IPlayerSession session, Dictionary<GridId, HashSet<Vector2i>> updatedChunks)
|
private void SendChunkUpdates(
|
||||||
|
IPlayerSession session,
|
||||||
|
Dictionary<GridId, HashSet<Vector2i>> updatedChunks,
|
||||||
|
Dictionary<GridId, HashSet<Vector2i>> staleChunks)
|
||||||
{
|
{
|
||||||
var updatedDecals = new Dictionary<GridId, Dictionary<Vector2i, Dictionary<uint, Decal>>>();
|
var updatedDecals = new Dictionary<GridId, Dictionary<Vector2i, Dictionary<uint, Decal>>>();
|
||||||
foreach (var (gridId, chunks) in updatedChunks)
|
foreach (var (gridId, chunks) in updatedChunks)
|
||||||
@@ -388,7 +458,7 @@ namespace Content.Server.Decals
|
|||||||
updatedDecals[gridId] = gridChunks;
|
updatedDecals[gridId] = gridChunks;
|
||||||
}
|
}
|
||||||
|
|
||||||
RaiseNetworkEvent(new DecalChunkUpdateEvent{Data = updatedDecals}, Filter.SinglePlayer(session));
|
RaiseNetworkEvent(new DecalChunkUpdateEvent{Data = updatedDecals, RemovedChunks = staleChunks}, Filter.SinglePlayer(session));
|
||||||
}
|
}
|
||||||
|
|
||||||
private HashSet<EntityUid> GetSessionViewers(IPlayerSession session)
|
private HashSet<EntityUid> GetSessionViewers(IPlayerSession session)
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Maths;
|
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.Decals
|
namespace Content.Shared.Decals
|
||||||
@@ -11,5 +7,6 @@ namespace Content.Shared.Decals
|
|||||||
public sealed class DecalChunkUpdateEvent : EntityEventArgs
|
public sealed class DecalChunkUpdateEvent : EntityEventArgs
|
||||||
{
|
{
|
||||||
public Dictionary<GridId, Dictionary<Vector2i, Dictionary<uint, Decal>>> Data = new();
|
public Dictionary<GridId, Dictionary<Vector2i, Dictionary<uint, Decal>>> Data = new();
|
||||||
|
public Dictionary<GridId, HashSet<Vector2i>> RemovedChunks = new();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ namespace Content.Shared.Decals
|
|||||||
if (chunkCollection[indices].Count == 0)
|
if (chunkCollection[indices].Count == 0)
|
||||||
chunkCollection.Remove(indices);
|
chunkCollection.Remove(indices);
|
||||||
|
|
||||||
ChunkIndex[gridId]?.Remove(uid);
|
ChunkIndex[gridId].Remove(uid);
|
||||||
DirtyChunk(gridId, indices);
|
DirtyChunk(gridId, indices);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user