Files
RobustToolbox/Robust.Server/Maps/YamlGridSerializer.cs
AcruidandGitHub 6b9b56ca83 Grid Components Allocate Grids (#2597)
* Deleting a map is now routed through MapComponent deletion.

* Remove map and grid deletions from map networking, just delete the entity if you want to remove the map.

* Moved the chunkSize property of created grids from the networked MapData to the MapGridComponent state.

* Remove unused IMapManager.DefaultMap property.

* Removed MapCreationTick field from MapManager.MapCollection.

* Removed _maps hashset field from MapManager.

* Removed CreatedMaps array from network MapData.

* MapGrid.ParentMapId is now derived from the bound TransformComponent, and isn't required in the MapGrid ctor.
Removed MapGrid.CreatedTick, it can be found on MapGridComponent.CreationTick.

* Remove a bunch of ApplyGameStatePre code duplication.

* Completely refactored CreateGrid.

* Adds AddComponentUninitialized to the ECS system. This allows you to access a component before it is initialized in a using block.

* Use AddComponentUninitialized to allocate a grid after the component is allocated.

* MapLoader now creates the grids after creating the map entities.

* Chunksize and TileSize properties are now actually read out of the map yaml.
TileSize has a public Setter.

* Minor cleanup.

* Moved grid allocation onto the MapGridComponent.

* Final Cleanup.

* Merge Fail.

* Fixed test, grid was getting deleted because it was empty.

* Remove DeletedChunkDatum from grid networking.

* ApplyMapGridState moved from map manager to the MapGridComponent.
2022-03-13 18:28:59 -07:00

121 lines
3.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using Robust.Shared.Map;
using Robust.Shared.Utility;
using YamlDotNet.Core;
using YamlDotNet.RepresentationModel;
namespace Robust.Server.Maps
{
internal static class YamlGridSerializer
{
public static YamlMappingNode SerializeGrid(IMapGrid mapGrid)
{
var grid = (IMapGridInternal) mapGrid;
var gridn = new YamlMappingNode();
var info = new YamlMappingNode();
var chunkSeq = new YamlSequenceNode();
gridn.Add("settings", info);
gridn.Add("chunks", chunkSeq);
info.Add("chunksize", grid.ChunkSize.ToString(CultureInfo.InvariantCulture));
info.Add("tilesize", grid.TileSize.ToString(CultureInfo.InvariantCulture));
var chunks = grid.GetMapChunks();
foreach (var chunk in chunks)
{
var chunkNode = SerializeChunk(chunk.Value);
chunkSeq.Add(chunkNode);
}
return gridn;
}
private static YamlNode SerializeChunk(MapChunk chunk)
{
var root = new YamlMappingNode();
var value = new YamlScalarNode($"{chunk.X},{chunk.Y}");
value.Style = ScalarStyle.DoubleQuoted;
root.Add("ind", value);
var gridNode = new YamlScalarNode();
root.Add("tiles", gridNode);
gridNode.Value = SerializeTiles(chunk);
return root;
}
private static string SerializeTiles(MapChunk chunk)
{
// number of bytes written per tile, because sizeof(Tile) is useless.
const int structSize = 4;
var nTiles = chunk.ChunkSize * chunk.ChunkSize * structSize;
var barr = new byte[nTiles];
using (var stream = new MemoryStream(barr))
using (var writer = new BinaryWriter(stream))
{
for (ushort y = 0; y < chunk.ChunkSize; y++)
{
for (ushort x = 0; x < chunk.ChunkSize; x++)
{
var tile = chunk.GetTile(x, y);
writer.Write(tile.TypeId);
writer.Write((byte)tile.Flags);
writer.Write(tile.Variant);
}
}
}
return Convert.ToBase64String(barr);
}
public static void DeserializeChunk(IMapManager mapMan, IMapGridInternal grid,
YamlMappingNode chunkData,
IReadOnlyDictionary<ushort, string> tileDefMapping,
ITileDefinitionManager tileDefinitionManager)
{
var indNode = chunkData["ind"];
var tileNode = chunkData["tiles"];
var (chunkOffsetX, chunkOffsetY) = indNode.AsVector2i();
var tileBytes = Convert.FromBase64String(tileNode.ToString());
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++)
{
for (ushort x = 0; x < grid.ChunkSize; x++)
{
var id = reader.ReadUInt16();
var flags = (TileRenderFlag)reader.ReadByte();
var variant = reader.ReadByte();
var defName = tileDefMapping[id];
id = tileDefinitionManager[defName].TileId;
var tile = new Tile(id, flags, variant);
chunk.SetTile(x, y, tile);
}
}
chunk.SuppressCollisionRegeneration = false;
mapMan.SuppressOnTileChanged = false;
}
}
}