mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-14 19:29:36 +01:00
Optimizations:
Use PLINQ for prototype loading. Most of the time is spent reading YAML so this should help a lot. Don't regenerate collision for every tile placed by the map loader.
This commit is contained in:
@@ -103,42 +103,47 @@ namespace Robust.Server.Maps
|
||||
|
||||
gridId = grid.Index;
|
||||
|
||||
foreach (YamlMappingNode chunkNode in chunks.Cast<YamlMappingNode>())
|
||||
foreach (var chunkNode in chunks.Cast<YamlMappingNode>())
|
||||
{
|
||||
DeserializeChunk(mapMan, grid, chunkNode, tileDefMapping, tileDefinitionManager);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DeserializeChunk(IMapManager mapMan, IMapGrid grid, YamlMappingNode chunk, IReadOnlyDictionary<ushort, string> tileDefMapping, ITileDefinitionManager tileDefinitionManager)
|
||||
private static void DeserializeChunk(IMapManager mapMan, IMapGridInternal grid, YamlMappingNode chunkData, IReadOnlyDictionary<ushort, string> tileDefMapping, ITileDefinitionManager tileDefinitionManager)
|
||||
{
|
||||
var indNode = chunk["ind"];
|
||||
var tileNode = chunk["tiles"];
|
||||
var indNode = chunkData["ind"];
|
||||
var tileNode = chunkData["tiles"];
|
||||
|
||||
var (chunkOffsetX, chunkOffsetY) = indNode.AsVector2i() * grid.ChunkSize;
|
||||
var (chunkOffsetX, chunkOffsetY) = indNode.AsVector2i();
|
||||
var tileBytes = Convert.FromBase64String(tileNode.ToString());
|
||||
|
||||
using (var stream = new MemoryStream(tileBytes))
|
||||
using (var reader = new BinaryReader(stream))
|
||||
using var stream = new MemoryStream(tileBytes);
|
||||
using var reader = new BinaryReader(stream);
|
||||
|
||||
mapMan.SuppressOnTileChanged = true;
|
||||
|
||||
var chunk = grid.GetChunk(chunkOffsetX, chunkOffsetY);
|
||||
|
||||
chunk.SuppressCollisionRegeneration = true;
|
||||
|
||||
for (ushort y = 0; y < grid.ChunkSize; y++)
|
||||
{
|
||||
mapMan.SuppressOnTileChanged = true;
|
||||
|
||||
for (var y = 0; y < grid.ChunkSize; y++)
|
||||
for (ushort x = 0; x < grid.ChunkSize; x++)
|
||||
{
|
||||
for (var x = 0; x < grid.ChunkSize; x++)
|
||||
{
|
||||
var id = reader.ReadUInt16();
|
||||
var data = reader.ReadUInt16();
|
||||
var id = reader.ReadUInt16();
|
||||
var data = reader.ReadUInt16();
|
||||
|
||||
var defName = tileDefMapping[id];
|
||||
id = tileDefinitionManager[defName].TileId;
|
||||
var defName = tileDefMapping[id];
|
||||
id = tileDefinitionManager[defName].TileId;
|
||||
|
||||
var tile = new Tile(id, data);
|
||||
grid.SetTile(new MapIndices(chunkOffsetX + x, chunkOffsetY + y), tile);
|
||||
}
|
||||
var tile = new Tile(id, data);
|
||||
chunk.SetTile(x, y, tile);
|
||||
}
|
||||
|
||||
mapMan.SuppressOnTileChanged = false;
|
||||
}
|
||||
|
||||
chunk.SuppressCollisionRegeneration = false;
|
||||
chunk.RegenerateCollision();
|
||||
mapMan.SuppressOnTileChanged = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,10 @@ namespace Robust.Shared.Map
|
||||
/// <inheritdoc />
|
||||
internal interface IMapChunkInternal : IMapChunk
|
||||
{
|
||||
bool SuppressCollisionRegeneration { get; set; }
|
||||
|
||||
void RegenerateCollision();
|
||||
|
||||
/// <summary>
|
||||
/// The last game simulation tick that this chunk was modified.
|
||||
/// </summary>
|
||||
|
||||
@@ -17,6 +17,6 @@ namespace Robust.Shared.Map
|
||||
/// <param name="oldTile">The old tile that got replaced.</param>
|
||||
void RaiseOnTileChanged(TileRef tileRef, Tile oldTile);
|
||||
|
||||
IMapGrid CreateGridNoEntity(MapId currentMapID, GridId? gridID = null, ushort chunkSize = 16, float snapSize = 1);
|
||||
IMapGridInternal CreateGridNoEntity(MapId currentMapID, GridId? gridID = null, ushort chunkSize = 16, float snapSize = 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +125,11 @@ namespace Robust.Shared.Map
|
||||
LastModifiedTick = _grid.CurTick;
|
||||
|
||||
_tiles[xIndex, yIndex] = tile;
|
||||
RegenerateCollision();
|
||||
|
||||
if (!SuppressCollisionRegeneration)
|
||||
{
|
||||
RegenerateCollision();
|
||||
}
|
||||
|
||||
_grid.NotifyTileChanged(newTileRef, oldTile);
|
||||
}
|
||||
@@ -237,7 +241,9 @@ namespace Robust.Shared.Map
|
||||
}
|
||||
}
|
||||
|
||||
private void RegenerateCollision()
|
||||
public bool SuppressCollisionRegeneration { get; set; }
|
||||
|
||||
public void RegenerateCollision()
|
||||
{
|
||||
// generate collision rects
|
||||
GridChunkPartition.PartitionChunk(this, ref _colBoxes, out _cachedBounds);
|
||||
|
||||
@@ -71,6 +71,8 @@ namespace Robust.Shared.Map
|
||||
/// <inheritdoc />
|
||||
public Box2 LocalBounds { get; private set; }
|
||||
|
||||
public bool SuppressCollisionRegeneration { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public ushort ChunkSize { get; }
|
||||
|
||||
@@ -268,6 +270,11 @@ namespace Robust.Shared.Map
|
||||
|
||||
#region ChunkAccess
|
||||
|
||||
public void RegenerateCollision()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The total number of allocated chunks in the grid.
|
||||
/// </summary>
|
||||
|
||||
@@ -12,7 +12,7 @@ using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Shared.Map
|
||||
{
|
||||
public partial class MapManager
|
||||
internal partial class MapManager
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly INetManager _netManager;
|
||||
|
||||
@@ -16,7 +16,7 @@ using Robust.Shared.Utility;
|
||||
namespace Robust.Shared.Map
|
||||
{
|
||||
/// <inheritdoc cref="IMapManager"/>
|
||||
public partial class MapManager : IMapManagerInternal
|
||||
internal partial class MapManager : IMapManagerInternal
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IGameTiming _gameTiming;
|
||||
@@ -346,7 +346,7 @@ namespace Robust.Shared.Map
|
||||
return CreateGridImpl(currentMapID, gridID, chunkSize, snapSize, true);
|
||||
}
|
||||
|
||||
private IMapGrid CreateGridImpl(MapId currentMapID, GridId? gridID, ushort chunkSize, float snapSize, bool createEntity)
|
||||
private IMapGridInternal CreateGridImpl(MapId currentMapID, GridId? gridID, ushort chunkSize, float snapSize, bool createEntity)
|
||||
{
|
||||
GridId actualID;
|
||||
if (gridID != null)
|
||||
@@ -418,7 +418,7 @@ namespace Robust.Shared.Map
|
||||
return grid;
|
||||
}
|
||||
|
||||
public IMapGrid CreateGridNoEntity(MapId currentMapID, GridId? gridID = null, ushort chunkSize = 16,
|
||||
public IMapGridInternal CreateGridNoEntity(MapId currentMapID, GridId? gridID = null, ushort chunkSize = 16,
|
||||
float snapSize = 1)
|
||||
{
|
||||
return CreateGridImpl(currentMapID, gridID, chunkSize, snapSize, false);
|
||||
|
||||
@@ -203,23 +203,39 @@ namespace Robust.Shared.Prototypes
|
||||
/// <inheritdoc />
|
||||
public void LoadDirectory(ResourcePath path)
|
||||
{
|
||||
foreach (var filePath in _resources.ContentFindFiles(path))
|
||||
{
|
||||
if (filePath.Extension != "yml" || filePath.Filename.StartsWith("."))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
using (var reader = new StreamReader(_resources.ContentFileRead(filePath), EncodingHelpers.UTF8))
|
||||
_hasEverBeenReloaded = true;
|
||||
var yamlStreams = _resources.ContentFindFiles(path).ToList().AsParallel()
|
||||
.Where(filePath => filePath.Extension == "yml" && !filePath.Filename.StartsWith("."))
|
||||
.Select(filePath =>
|
||||
{
|
||||
try
|
||||
{
|
||||
LoadFromStream(reader);
|
||||
using var reader = new StreamReader(_resources.ContentFileRead(filePath), EncodingHelpers.UTF8);
|
||||
var yamlStream = new YamlStream();
|
||||
yamlStream.Load(reader);
|
||||
|
||||
return (yamlStream, filePath);
|
||||
}
|
||||
catch (Exception e)
|
||||
when (e is YamlException || e is PrototypeLoadException)
|
||||
catch (YamlException e)
|
||||
{
|
||||
Logger.ErrorS("eng", $"Exception whilst loading prototypes from {filePath}: {e}");
|
||||
return (null, null);
|
||||
}
|
||||
})
|
||||
.Where(p => p.yamlStream != null) // Filter out loading errors.
|
||||
.ToList();
|
||||
|
||||
foreach (var (stream, filePath) in yamlStreams)
|
||||
{
|
||||
for (var i = 0; i < stream.Documents.Count; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
LoadFromDocument(stream.Documents[i]);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.ErrorS("eng", $"Exception whilst loading prototypes from {filePath}#{i}:\n{e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user