Remove byte[] allocations for GasTileOverlaySystem.UpdateChunkTile (#12617)
This commit is contained in:
@@ -166,7 +166,7 @@ namespace Content.Client.Atmos.Overlays
|
|||||||
|
|
||||||
while (enumerator.MoveNext(out var gas))
|
while (enumerator.MoveNext(out var gas))
|
||||||
{
|
{
|
||||||
if (gas.Value.Opacity == null)
|
if (gas.Opacity == null!)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var tilePosition = chunk.Origin + (enumerator.X, enumerator.Y);
|
var tilePosition = chunk.Origin + (enumerator.X, enumerator.Y);
|
||||||
@@ -175,7 +175,7 @@ namespace Content.Client.Atmos.Overlays
|
|||||||
|
|
||||||
for (var i = 0; i < _gasCount; i++)
|
for (var i = 0; i < _gasCount; i++)
|
||||||
{
|
{
|
||||||
var opacity = gas.Value.Opacity[i];
|
var opacity = gas.Opacity[i];
|
||||||
if (opacity > 0)
|
if (opacity > 0)
|
||||||
drawHandle.DrawTexture(_frames[i][_frameCounter[i]], tilePosition, Color.White.WithAlpha(opacity));
|
drawHandle.DrawTexture(_frames[i][_frameCounter[i]], tilePosition, Color.White.WithAlpha(opacity));
|
||||||
}
|
}
|
||||||
@@ -190,14 +190,14 @@ namespace Content.Client.Atmos.Overlays
|
|||||||
|
|
||||||
while (enumerator.MoveNext(out var gas))
|
while (enumerator.MoveNext(out var gas))
|
||||||
{
|
{
|
||||||
if (gas.Value.FireState == 0)
|
if (gas.FireState == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var index = chunk.Origin + (enumerator.X, enumerator.Y);
|
var index = chunk.Origin + (enumerator.X, enumerator.Y);
|
||||||
if (!localBounds.Contains(index))
|
if (!localBounds.Contains(index))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var state = gas.Value.FireState - 1;
|
var state = gas.FireState - 1;
|
||||||
var texture = _fireFrames[state][_fireFrameCounter[state]];
|
var texture = _fireFrames[state][_fireFrameCounter[state]];
|
||||||
drawHandle.DrawTexture(texture, index);
|
drawHandle.DrawTexture(texture, index);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Content.Server.Atmos.Components;
|
using Content.Server.Atmos.Components;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.Atmos.EntitySystems;
|
using Content.Shared.Atmos.EntitySystems;
|
||||||
@@ -14,10 +17,6 @@ using Robust.Shared.Map;
|
|||||||
using Robust.Shared.Threading;
|
using Robust.Shared.Threading;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using DependencyAttribute = Robust.Shared.IoC.DependencyAttribute;
|
|
||||||
|
|
||||||
// ReSharper disable once RedundantUsingDirective
|
// ReSharper disable once RedundantUsingDirective
|
||||||
|
|
||||||
@@ -26,13 +25,13 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
internal sealed class GasTileOverlaySystem : SharedGasTileOverlaySystem
|
internal sealed class GasTileOverlaySystem : SharedGasTileOverlaySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
[Robust.Shared.IoC.Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
[Robust.Shared.IoC.Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
[Robust.Shared.IoC.Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
[Dependency] private readonly IConfigurationManager _confMan = default!;
|
[Robust.Shared.IoC.Dependency] private readonly IConfigurationManager _confMan = default!;
|
||||||
[Dependency] private readonly IParallelManager _parMan = default!;
|
[Robust.Shared.IoC.Dependency] private readonly IParallelManager _parMan = default!;
|
||||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
[Robust.Shared.IoC.Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||||
[Dependency] private readonly ChunkingSystem _chunkingSys = default!;
|
[Robust.Shared.IoC.Dependency] private readonly ChunkingSystem _chunkingSys = default!;
|
||||||
|
|
||||||
private readonly Dictionary<IPlayerSession, Dictionary<EntityUid, HashSet<Vector2i>>> _lastSentChunks = new();
|
private readonly Dictionary<IPlayerSession, Dictionary<EntityUid, HashSet<Vector2i>>> _lastSentChunks = new();
|
||||||
|
|
||||||
@@ -120,40 +119,57 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void UpdateChunkTile(GridAtmosphereComponent gridAtmosphere, GasOverlayChunk chunk, Vector2i index, GameTick curTick)
|
private void UpdateChunkTile(GridAtmosphereComponent gridAtmosphere, GasOverlayChunk chunk, Vector2i index, GameTick curTick)
|
||||||
{
|
{
|
||||||
var oldData = chunk.GetData(index);
|
ref var oldData = ref chunk.GetData(index);
|
||||||
if (!gridAtmosphere.Tiles.TryGetValue(index, out var tile))
|
if (!gridAtmosphere.Tiles.TryGetValue(index, out var tile))
|
||||||
{
|
{
|
||||||
if (oldData == null)
|
if (oldData.Equals(default))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
chunk.LastUpdate = curTick;
|
chunk.LastUpdate = curTick;
|
||||||
chunk.SetData(index, null);
|
oldData = default;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var opacity = new byte[VisibleGasId.Length];
|
var changed = oldData.Equals(default) || oldData.FireState != tile.Hotspot.State;
|
||||||
GasOverlayData newData = new(tile!.Hotspot.State, opacity);
|
if (oldData.Equals(default))
|
||||||
|
oldData = new GasOverlayData(tile.Hotspot.State, new byte[VisibleGasId.Length]);
|
||||||
|
|
||||||
if (tile.Air != null)
|
if (tile.Air != null)
|
||||||
{
|
{
|
||||||
var i = 0;
|
for (var i = 0; i < VisibleGasId.Length; i++)
|
||||||
foreach (var id in VisibleGasId)
|
|
||||||
{
|
{
|
||||||
|
var id = VisibleGasId[i];
|
||||||
var gas = _atmosphereSystem.GetGas(id);
|
var gas = _atmosphereSystem.GetGas(id);
|
||||||
var moles = tile.Air.Moles[id];
|
var moles = tile.Air.Moles[id];
|
||||||
|
ref var oldOpacity = ref oldData.Opacity[i];
|
||||||
|
|
||||||
if (moles >= gas.GasMolesVisible)
|
if (moles < gas.GasMolesVisible)
|
||||||
{
|
{
|
||||||
opacity[i] = (byte) (ContentHelpers.RoundToLevels(
|
if (oldOpacity != 0)
|
||||||
MathHelper.Clamp01((moles - gas.GasMolesVisible) / (gas.GasMolesVisibleMax - gas.GasMolesVisible)) * 255, byte.MaxValue, _thresholds) * 255 / (_thresholds - 1));
|
{
|
||||||
|
oldOpacity = 0;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
|
var opacity = (byte) (ContentHelpers.RoundToLevels(
|
||||||
|
MathHelper.Clamp01((moles - gas.GasMolesVisible) /
|
||||||
|
(gas.GasMolesVisibleMax - gas.GasMolesVisible)) * 255, byte.MaxValue,
|
||||||
|
_thresholds) * 255 / (_thresholds - 1));
|
||||||
|
|
||||||
|
if (oldOpacity == opacity)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
oldOpacity = opacity;
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldData != null && oldData.Value.Equals(newData))
|
if (!changed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
chunk.SetData(index, newData);
|
|
||||||
chunk.LastUpdate = curTick;
|
chunk.LastUpdate = curTick;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,10 +63,16 @@ namespace Content.Shared.Atmos.EntitySystems
|
|||||||
if (FireState != other.FireState)
|
if (FireState != other.FireState)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (var i = 0; i < Opacity.Length; i++)
|
if (Opacity?.Length != other.Opacity?.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (Opacity != null && other.Opacity != null)
|
||||||
{
|
{
|
||||||
if (Opacity[i] != other.Opacity[i])
|
for (var i = 0; i < Opacity.Length; i++)
|
||||||
return false;
|
{
|
||||||
|
if (Opacity[i] != other.Opacity[i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using Content.Shared.Atmos.EntitySystems;
|
|||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using static Content.Shared.Atmos.EntitySystems.SharedGasTileOverlaySystem;
|
using static Content.Shared.Atmos.EntitySystems.SharedGasTileOverlaySystem;
|
||||||
|
|
||||||
namespace Content.Shared.Atmos
|
namespace Content.Shared.Atmos
|
||||||
@@ -17,7 +16,7 @@ namespace Content.Shared.Atmos
|
|||||||
public readonly Vector2i Index;
|
public readonly Vector2i Index;
|
||||||
public readonly Vector2i Origin;
|
public readonly Vector2i Origin;
|
||||||
|
|
||||||
public GasOverlayData?[][] TileData = new GasOverlayData?[ChunkSize][];
|
public GasOverlayData[][] TileData = new GasOverlayData[ChunkSize][];
|
||||||
|
|
||||||
[NonSerialized]
|
[NonSerialized]
|
||||||
public GameTick LastUpdate;
|
public GameTick LastUpdate;
|
||||||
@@ -30,20 +29,14 @@ namespace Content.Shared.Atmos
|
|||||||
// For whatever reason, net serialize does not like multi_D arrays. So Jagged it is.
|
// For whatever reason, net serialize does not like multi_D arrays. So Jagged it is.
|
||||||
for (var i = 0; i < ChunkSize; i++)
|
for (var i = 0; i < ChunkSize; i++)
|
||||||
{
|
{
|
||||||
TileData[i] = new GasOverlayData?[ChunkSize];
|
TileData[i] = new GasOverlayData[ChunkSize];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public GasOverlayData? GetData(Vector2i gridIndices)
|
public ref GasOverlayData GetData(Vector2i gridIndices)
|
||||||
{
|
{
|
||||||
DebugTools.Assert(InBounds(gridIndices));
|
DebugTools.Assert(InBounds(gridIndices));
|
||||||
return TileData[gridIndices.X - Origin.X][gridIndices.Y - Origin.Y];
|
return ref TileData[gridIndices.X - Origin.X][gridIndices.Y - Origin.Y];
|
||||||
}
|
|
||||||
|
|
||||||
public GasOverlayData? SetData(Vector2i gridIndices, GasOverlayData? data)
|
|
||||||
{
|
|
||||||
DebugTools.Assert(InBounds(gridIndices));
|
|
||||||
return TileData[gridIndices.X - Origin.X][gridIndices.Y - Origin.Y] = data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool InBounds(Vector2i gridIndices)
|
private bool InBounds(Vector2i gridIndices)
|
||||||
@@ -60,7 +53,7 @@ namespace Content.Shared.Atmos
|
|||||||
private GasOverlayChunk _chunk;
|
private GasOverlayChunk _chunk;
|
||||||
public int X = 0;
|
public int X = 0;
|
||||||
public int Y = -1;
|
public int Y = -1;
|
||||||
private GasOverlayData?[] _column;
|
private GasOverlayData[] _column;
|
||||||
|
|
||||||
|
|
||||||
public GasChunkEnumerator(GasOverlayChunk chunk)
|
public GasChunkEnumerator(GasOverlayChunk chunk)
|
||||||
@@ -69,18 +62,18 @@ namespace Content.Shared.Atmos
|
|||||||
_column = _chunk.TileData[0];
|
_column = _chunk.TileData[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool MoveNext([NotNullWhen(true)] out GasOverlayData? gas)
|
public bool MoveNext(out GasOverlayData gas)
|
||||||
{
|
{
|
||||||
while (X < ChunkSize)
|
while (X < ChunkSize)
|
||||||
{
|
{
|
||||||
// We want to increment Y before returning, but we also want it to match the current Y coordinate for
|
// We want to increment Y before returning, but we also want it to match the current Y coordinate for
|
||||||
// the returned gas, so using a slightly different logic for the Y loop.
|
// the returned gas, so using a slightly different logic for the Y loop.
|
||||||
while (Y < ChunkSize - 1)
|
while (Y < ChunkSize - 1)
|
||||||
{
|
{
|
||||||
Y++;
|
Y++;
|
||||||
gas = _column[Y];
|
gas = _column[Y];
|
||||||
|
|
||||||
if (gas != null)
|
if (!gas.Equals(default))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +83,7 @@ namespace Content.Shared.Atmos
|
|||||||
Y = -1;
|
Y = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
gas = null;
|
gas = default;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user