Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into 2023-08-20-arch
Browse files Browse the repository at this point in the history
  • Loading branch information
metalgearsloth committed Nov 22, 2023
2 parents f35c573 + a761fbc commit d7cdca9
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 27 deletions.
2 changes: 1 addition & 1 deletion MSBuild/Robust.Engine.Version.props
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project>
<!-- This file automatically reset by Tools/version.py -->
<PropertyGroup><Version>180.1.0</Version></PropertyGroup>
<PropertyGroup><Version>180.2.0</Version></PropertyGroup>
</Project>
Expand Down
12 changes: 12 additions & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@ END TEMPLATE-->
*None yet*


## 180.2.0

### New features

* Add EnsureEntity variants that take in collections.
* Add more MapSystem helper methods.

### Internal

* Cache some more PVS data to avoid re-allocating every tick.


## 180.1.0

### New features
Expand Down
68 changes: 45 additions & 23 deletions Robust.Server/GameStates/PvsSystem.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices;
Expand Down Expand Up @@ -271,6 +272,7 @@ private void OnEntityDeleted(EntityUid e, MetaDataComponent metadata)
{
sessionData.LastSeenAt.Remove(metadata.NetEntity);
sessionData.LastLeftView.Remove(metadata.NetEntity);

if (sessionData.SentEntities.TryGetValue(previousTick, out var ents))
ents.Remove(metadata.NetEntity);
}
Expand Down Expand Up @@ -433,10 +435,15 @@ private void OnMapCreated(MapChangedEvent e)

#endregion

public (List<(int, IChunkIndexLocation)> , HashSet<int>[], EntityUid[][] viewers) GetChunks(ICommonSession[] sessions)
public List<(int, IChunkIndexLocation)> GetChunks(
ICommonSession[] sessions,
ref HashSet<int>[] playerChunks,
ref EntityUid[][] viewerEntities)
{
var playerChunks = new HashSet<int>[sessions.Length];
var viewerEntities = new EntityUid[sessions.Length][];
// Pass these in to avoid allocating new ones every tick, 99% of the time sessions length is going to be the same size.
// These values will get overridden here and the old values have already been returned to the pool by this point.
Array.Resize(ref playerChunks, sessions.Length);
Array.Resize(ref viewerEntities, sessions.Length);

_chunkList.Clear();
// Keep track of the index of each chunk we use for a faster index lookup.
Expand All @@ -459,8 +466,8 @@ private void OnMapCreated(MapChangedEvent e)
var session = sessions[i];
playerChunks[i] = _playerChunkPool.Get();

var viewers = GetSessionViewers(session);
viewerEntities[i] = viewers;
ref var viewers = ref viewerEntities[i];
GetSessionViewers(session, ref viewers);

for (var j = 0; j < viewers.Length; j++)
{
Expand Down Expand Up @@ -552,7 +559,7 @@ private void OnMapCreated(MapChangedEvent e)
}
}

return (_chunkList, playerChunks, viewerEntities);
return _chunkList;
}

public void RegisterNewPreviousChunkTrees(
Expand All @@ -569,23 +576,20 @@ public void RegisterNewPreviousChunkTrees(
_reusedTrees.Add(chunks[i]);
}

var previousIndices = _previousTrees.Keys.ToArray();
for (var i = 0; i < previousIndices.Length; i++)
foreach (var (index, chunk) in _previousTrees)
{
var index = previousIndices[i];
// ReSharper disable once InconsistentlySynchronizedField
if (_reusedTrees.Contains(index)) continue;
var chunk = _previousTrees[index];
if (chunk.HasValue)
if (_reusedTrees.Contains(index))
continue;

if (chunk != null)
{
_chunkCachePool.Return(chunk.Value.metadata);
_treePool.Return(chunk.Value.tree);
}

if (!chunks.Contains(index))
{
_previousTrees.Remove(index);
}
}

_previousTrees.EnsureCapacity(chunks.Count);
Expand Down Expand Up @@ -1313,26 +1317,44 @@ private EntityState GetFullEntityState(ICommonSession player, EntityUid entityUi
return entState;
}

private EntityUid[] GetSessionViewers(ICommonSession session)
private void GetSessionViewers(ICommonSession session, [NotNull] ref EntityUid[]? viewers)
{
if (session.Status != SessionStatus.InGame)
return Array.Empty<EntityUid>();
{
viewers = Array.Empty<EntityUid>();
return;
}

// Fast path
if (session.ViewSubscriptions.Count == 0)
{
if (session.AttachedEntity == null)
return Array.Empty<EntityUid>();
{
viewers = Array.Empty<EntityUid>();
return;
}

return new[] { session.AttachedEntity.Value };
Array.Resize(ref viewers, 1);
viewers[0] = session.AttachedEntity.Value;
return;
}

var viewers = new HashSet<EntityUid>();
if (session.AttachedEntity != null)
viewers.Add(session.AttachedEntity.Value);
int i = 0;
if (session.AttachedEntity is { } local)
{
DebugTools.Assert(!session.ViewSubscriptions.Contains(local));
Array.Resize(ref viewers, session.ViewSubscriptions.Count + 1);
viewers[i++] = local;
}
else
{
Array.Resize(ref viewers, session.ViewSubscriptions.Count);
}

viewers.UnionWith(session.ViewSubscriptions);
return viewers.ToArray();
foreach (var ent in session.ViewSubscriptions)
{
viewers[i++] = ent;
}
}

// Read Safe
Expand Down
9 changes: 6 additions & 3 deletions Robust.Server/GameStates/ServerGameStateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ public sealed class ServerGameStateManager : IServerGameStateManager, IPostInjec
// Mapping of net UID of clients -> last known acked state.
private GameTick _lastOldestAck = GameTick.Zero;

private HashSet<int>[] _playerChunks = Array.Empty<HashSet<int>>();
private EntityUid[][] _viewerEntities = Array.Empty<EntityUid[]>();

private PvsSystem _pvs = default!;

[Dependency] private readonly EntityManager _entityManager = default!;
Expand Down Expand Up @@ -267,7 +270,7 @@ private struct PvsData

private PvsData? GetPVSData(ICommonSession[] players)
{
var (chunks, playerChunks, viewerEntities) = _pvs.GetChunks(players);
var chunks= _pvs.GetChunks(players, ref _playerChunks, ref _viewerEntities);
const int ChunkBatchSize = 2;
var chunksCount = chunks.Count;
var chunkBatches = (int)MathF.Ceiling((float)chunksCount / ChunkBatchSize);
Expand Down Expand Up @@ -310,8 +313,8 @@ private struct PvsData
ArrayPool<bool>.Shared.Return(reuse);
return new PvsData()
{
PlayerChunks = playerChunks,
ViewerEntities = viewerEntities,
PlayerChunks = _playerChunks,
ViewerEntities = _viewerEntities,
ChunkCache = chunkCache,
};
}
Expand Down
33 changes: 33 additions & 0 deletions Robust.Shared/GameObjects/Systems/SharedMapSystem.Grid.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1291,6 +1291,9 @@ public bool CollidesWithGrid(EntityUid uid, MapGridComponent grid, Vector2i indi
}

public Vector2i GridTileToChunkIndices(EntityUid uid, MapGridComponent grid, Vector2i gridTile)
=> GridTileToChunkIndices(grid, gridTile);

public Vector2i GridTileToChunkIndices(MapGridComponent grid, Vector2i gridTile)
{
var x = (int)Math.Floor(gridTile.X / (float) grid.ChunkSize);
var y = (int)Math.Floor(gridTile.Y / (float) grid.ChunkSize);
Expand Down Expand Up @@ -1333,6 +1336,36 @@ public bool TryGetTileRef(EntityUid uid, MapGridComponent grid, Vector2i indices
return true;
}

public bool TryGetTile(MapGridComponent grid, Vector2i indices, out Tile tile)
{
var chunkIndices = GridTileToChunkIndices(grid, indices);
if (!grid.Chunks.TryGetValue(chunkIndices, out var chunk))
{
tile = default;
return false;
}

var cTileIndices = chunk.GridTileToChunkTile(indices);
tile = chunk.Tiles[cTileIndices.X, cTileIndices.Y];
return true;
}

/// <summary>
/// Attempts to get the <see cref="ITileDefinition"/> for the tile at the given grid indices. This will throw an
/// exception if the tile at this location has no registered tile definition.
/// </summary>
public bool TryGetTileDef(MapGridComponent grid, Vector2i indices, [NotNullWhen(true)] out ITileDefinition? tileDef)
{
if (!TryGetTile(grid, indices, out var tile))
{
tileDef = null;
return false;
}

tileDef = _tileMan[tile.TypeId];
return true;
}

public bool TryGetTileRef(EntityUid uid, MapGridComponent grid, EntityCoordinates coords, out TileRef tile)
{
return TryGetTileRef(uid, grid, CoordinatesToTile(uid, grid, coords), out tile);
Expand Down
1 change: 1 addition & 0 deletions Robust.Shared/GameObjects/Systems/SharedMapSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace Robust.Shared.GameObjects
{
public abstract partial class SharedMapSystem : EntitySystem
{
[Dependency] private readonly ITileDefinitionManager _tileMan = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] protected readonly IMapManager MapManager = default!;
[Dependency] private readonly IMapManagerInternal _mapInternal = default!;
Expand Down
1 change: 1 addition & 0 deletions Robust.Shared/Map/ITileDefinitionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public interface ITileDefinitionManager : IEnumerable<ITileDefinition>
/// <param name="id">The ID of the tile definition.</param>
/// <returns>The tile definition.</returns>
ITileDefinition this[int id] { get; }
// TODO add a try get and get-or-null variant.

/// <summary>
/// The number of tile definitions contained inside of this manager.
Expand Down

0 comments on commit d7cdca9

Please sign in to comment.