Update map loader to work with grid entities.

This commit is contained in:
Pieter-Jan Briers
2019-12-28 03:19:26 +01:00
parent 472bd67ace
commit cb563c75fd
10 changed files with 239 additions and 177 deletions
+84 -13
View File
@@ -16,6 +16,7 @@ using System.Globalization;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using System.Linq; using System.Linq;
using Robust.Server.Interfaces.Timing; using Robust.Server.Interfaces.Timing;
using Robust.Shared.GameObjects.Components.Map;
using YamlDotNet.Core; using YamlDotNet.Core;
namespace Robust.Server.Maps namespace Robust.Server.Maps
@@ -32,7 +33,7 @@ namespace Robust.Server.Maps
private readonly IResourceManager _resMan; private readonly IResourceManager _resMan;
[Dependency] [Dependency]
private readonly IMapManager _mapManager; private readonly IMapManagerInternal _mapManager;
[Dependency] [Dependency]
private readonly ITileDefinitionManager _tileDefinitionManager; private readonly ITileDefinitionManager _tileDefinitionManager;
@@ -207,7 +208,7 @@ namespace Robust.Server.Maps
/// </summary> /// </summary>
private class MapContext : YamlObjectSerializer.Context, IEntityLoadContext private class MapContext : YamlObjectSerializer.Context, IEntityLoadContext
{ {
private readonly IMapManager _mapManager; private readonly IMapManagerInternal _mapManager;
private readonly ITileDefinitionManager _tileDefinitionManager; private readonly ITileDefinitionManager _tileDefinitionManager;
private readonly IServerEntityManagerInternal _serverEntityManager; private readonly IServerEntityManagerInternal _serverEntityManager;
private readonly IPauseManager _pauseManager; private readonly IPauseManager _pauseManager;
@@ -219,6 +220,10 @@ namespace Robust.Server.Maps
private readonly Dictionary<int, EntityUid> UidEntityMap = new Dictionary<int, EntityUid>(); private readonly Dictionary<int, EntityUid> UidEntityMap = new Dictionary<int, EntityUid>();
public readonly List<IEntity> Entities = new List<IEntity>(); public readonly List<IEntity> Entities = new List<IEntity>();
private readonly List<(IEntity, YamlMappingNode)> _entitiesToDeserialize
= new List<(IEntity, YamlMappingNode)>();
private bool IsBlueprintMode => GridIDMap.Count == 1;
private int uidCounter; private int uidCounter;
@@ -234,7 +239,7 @@ namespace Robust.Server.Maps
public bool MapIsPostInit { get; private set; } public bool MapIsPostInit { get; private set; }
public MapContext(IMapManager maps, ITileDefinitionManager tileDefs, IServerEntityManagerInternal entities, IPauseManager pauseManager) public MapContext(IMapManagerInternal maps, ITileDefinitionManager tileDefs, IServerEntityManagerInternal entities, IPauseManager pauseManager)
{ {
_mapManager = maps; _mapManager = maps;
_tileDefinitionManager = tileDefs; _tileDefinitionManager = tileDefs;
@@ -244,7 +249,7 @@ namespace Robust.Server.Maps
RootNode = new YamlMappingNode(); RootNode = new YamlMappingNode();
} }
public MapContext(IMapManager maps, ITileDefinitionManager tileDefs, IServerEntityManagerInternal entities, public MapContext(IMapManagerInternal maps, ITileDefinitionManager tileDefs, IServerEntityManagerInternal entities,
IPauseManager pauseManager, YamlMappingNode node, MapId targetMapId) IPauseManager pauseManager, YamlMappingNode node, MapId targetMapId)
{ {
_mapManager = maps; _mapManager = maps;
@@ -273,6 +278,14 @@ namespace Robust.Server.Maps
// Actually instance components and run ExposeData on them. // Actually instance components and run ExposeData on them.
FinishEntitiesLoad(); FinishEntitiesLoad();
// Grid entities were NOT created inside ReadGridSection().
// We have to fix the created grids up with the grid entities deserialized from the map.
FixMapEntities();
// We have to attach grids to the target map here.
// If we don't, initialization & startup can fail for some entities.
AttachMapEntities();
// Run Initialize on all components. // Run Initialize on all components.
FinishEntitiesInitialization(); FinishEntitiesInitialization();
@@ -280,6 +293,29 @@ namespace Robust.Server.Maps
FinishEntitiesStartup(); FinishEntitiesStartup();
} }
private void AttachMapEntities()
{
var mapEntity = _mapManager.GetMapEntity(TargetMap);
foreach (var grid in Grids)
{
var entity = _serverEntityManager.GetEntity(grid.GridEntity);
entity.Transform.AttachParent(mapEntity);
}
}
private void FixMapEntities()
{
foreach (var entity in Entities)
{
if (entity.TryGetComponent(out IMapGridComponent grid))
{
var castGrid = (MapGrid) grid.Grid;
castGrid.GridEntity = entity.Uid;
}
}
}
private void ReadMetaSection() private void ReadMetaSection()
{ {
var meta = RootNode.GetNode<YamlMappingNode>("meta"); var meta = RootNode.GetNode<YamlMappingNode>("meta");
@@ -340,23 +376,28 @@ namespace Robust.Server.Maps
var entities = RootNode.GetNode<YamlSequenceNode>("entities"); var entities = RootNode.GetNode<YamlSequenceNode>("entities");
foreach (var entityDef in entities.Cast<YamlMappingNode>()) foreach (var entityDef in entities.Cast<YamlMappingNode>())
{ {
var type = entityDef.GetNode("type").AsString(); string type = null;
if (entityDef.TryGetNode("type", out var typeNode))
{
type = typeNode.AsString();
}
var uid = Entities.Count; var uid = Entities.Count;
if (entityDef.TryGetNode("uid", out var uidNode)) if (entityDef.TryGetNode("uid", out var uidNode))
{ {
uid = uidNode.AsInt(); uid = uidNode.AsInt();
} }
var entity = _serverEntityManager.AllocEntity(type); var entity = _serverEntityManager.AllocEntity(type);
Entities.Add(entity); Entities.Add(entity);
UidEntityMap.Add(uid, entity.Uid); UidEntityMap.Add(uid, entity.Uid);
_entitiesToDeserialize.Add((entity, entityDef));
} }
} }
private void FinishEntitiesLoad() private void FinishEntitiesLoad()
{ {
var entityData = RootNode.GetNode<YamlSequenceNode>("entities"); foreach (var (entity, data) in _entitiesToDeserialize)
foreach (var (entity, data) in Entities.Zip(entityData, (a, b) => (a, (YamlMappingNode)b)))
{ {
CurrentReadingEntityComponents = new Dictionary<string, YamlMappingNode>(); CurrentReadingEntityComponents = new Dictionary<string, YamlMappingNode>();
if (data.TryGetNode("components", out YamlSequenceNode componentList)) if (data.TryGetNode("components", out YamlSequenceNode componentList))
@@ -478,10 +519,14 @@ namespace Robust.Server.Maps
CurrentWritingEntity = entity; CurrentWritingEntity = entity;
var mapping = new YamlMappingNode var mapping = new YamlMappingNode
{ {
{"type", entity.Prototype.ID},
{"uid", EntityUidMap[entity.Uid].ToString(CultureInfo.InvariantCulture)} {"uid", EntityUidMap[entity.Uid].ToString(CultureInfo.InvariantCulture)}
}; };
if (entity.Prototype != null)
{
mapping.Add("type", entity.Prototype.ID);
}
var components = new YamlSequenceNode(); var components = new YamlSequenceNode();
// See engine#636 for why the Distinct() call. // See engine#636 for why the Distinct() call.
foreach (var component in entity.GetAllComponents()) foreach (var component in entity.GetAllComponents())
@@ -514,6 +559,12 @@ namespace Robust.Server.Maps
{ {
if (type == typeof(GridId)) if (type == typeof(GridId))
{ {
if (node.AsString() == "null")
{
obj = GridId.Nullspace;
return true;
}
var val = node.AsInt(); var val = node.AsInt();
if (val >= Grids.Count) if (val >= Grids.Count)
{ {
@@ -527,6 +578,12 @@ namespace Robust.Server.Maps
} }
if (type == typeof(EntityUid)) if (type == typeof(EntityUid))
{ {
if (node.AsString() == "null")
{
obj = EntityUid.Invalid;
return true;
}
var val = node.AsInt(); var val = node.AsInt();
if (val >= Entities.Count) if (val >= Entities.Count)
{ {
@@ -574,8 +631,15 @@ namespace Robust.Server.Maps
case EntityUid entityUid: case EntityUid entityUid:
if (!EntityUidMap.TryGetValue(entityUid, out var entityUidMapped)) if (!EntityUidMap.TryGetValue(entityUid, out var entityUidMapped))
{ {
Logger.WarningS("map", "Cannot write entity UID '{0}'.", entityUid); // Terrible hack to mute this warning on the grids themselves when serializing blueprints.
break; if (!IsBlueprintMode || !CurrentWritingEntity.HasComponent<MapGridComponent>() ||
CurrentWritingComponent != "Transform")
{
Logger.WarningS("map", "Cannot write entity UID '{0}'.", entityUid);
}
node = new YamlScalarNode("null");
return true;
} }
else else
{ {
@@ -627,11 +691,18 @@ namespace Robust.Server.Maps
public override bool IsValueDefault<T>(string field, T value) public override bool IsValueDefault<T>(string field, T value)
{ {
if (CurrentWritingEntity.Prototype == null)
{
// No prototype, can't be default.
return false;
}
if (!CurrentWritingEntity.Prototype.Components.TryGetValue(CurrentWritingComponent, out var compData)) if (!CurrentWritingEntity.Prototype.Components.TryGetValue(CurrentWritingComponent, out var compData))
{ {
// This component was added mid-game. // This component was added mid-game.
return false; return false;
} }
var testSer = YamlObjectSerializer.NewReader(compData); var testSer = YamlObjectSerializer.NewReader(compData);
if (testSer.TryReadDataFieldCached(field, out T prototypeVal)) if (testSer.TryReadDataFieldCached(field, out T prototypeVal))
{ {
@@ -648,7 +719,7 @@ namespace Robust.Server.Maps
private bool IsMapSavable(IEntity entity) private bool IsMapSavable(IEntity entity)
{ {
if (!entity.Prototype.MapSavable || !GridIDMap.ContainsKey(entity.Transform.GridID)) if (entity.Prototype?.MapSavable == false || !GridIDMap.ContainsKey(entity.Transform.GridID))
{ {
return false; return false;
} }
@@ -658,7 +729,7 @@ namespace Robust.Server.Maps
var current = entity.Transform; var current = entity.Transform;
while (current.Parent != null) while (current.Parent != null)
{ {
if (!current.Parent.Owner.Prototype.MapSavable) if (current.Parent.Owner.Prototype?.MapSavable == false)
{ {
return false; return false;
} }
+3 -7
View File
@@ -12,7 +12,7 @@ using YamlDotNet.RepresentationModel;
namespace Robust.Server.Maps namespace Robust.Server.Maps
{ {
public static class YamlGridSerializer internal static class YamlGridSerializer
{ {
public static YamlMappingNode SerializeGrid(IMapGrid mapGrid) public static YamlMappingNode SerializeGrid(IMapGrid mapGrid)
{ {
@@ -28,7 +28,6 @@ namespace Robust.Server.Maps
info.Add("chunksize", grid.ChunkSize.ToString(CultureInfo.InvariantCulture)); info.Add("chunksize", grid.ChunkSize.ToString(CultureInfo.InvariantCulture));
info.Add("tilesize", grid.TileSize.ToString(CultureInfo.InvariantCulture)); info.Add("tilesize", grid.TileSize.ToString(CultureInfo.InvariantCulture));
info.Add("snapsize", grid.SnapSize.ToString(CultureInfo.InvariantCulture)); info.Add("snapsize", grid.SnapSize.ToString(CultureInfo.InvariantCulture));
info.Add("worldpos", $"{grid.WorldPosition.X},{grid.WorldPosition.Y}");
var chunks = grid.GetMapChunks(); var chunks = grid.GetMapChunks();
foreach (var chunk in chunks) foreach (var chunk in chunks)
@@ -80,14 +79,13 @@ namespace Robust.Server.Maps
return Convert.ToBase64String(barr); return Convert.ToBase64String(barr);
} }
public static void DeserializeGrid(IMapManager mapMan, MapId mapId, ref GridId? gridId, YamlMappingNode info, public static void DeserializeGrid(IMapManagerInternal mapMan, MapId mapId, ref GridId? gridId, YamlMappingNode info,
YamlSequenceNode chunks, IReadOnlyDictionary<ushort, string> tileDefMapping, YamlSequenceNode chunks, IReadOnlyDictionary<ushort, string> tileDefMapping,
ITileDefinitionManager tileDefinitionManager) ITileDefinitionManager tileDefinitionManager)
{ {
ushort csz = 0; ushort csz = 0;
ushort tsz = 0; ushort tsz = 0;
float sgsz = 0.0f; float sgsz = 0.0f;
var worldPos = Vector2.Zero;
foreach (var kvInfo in info) foreach (var kvInfo in info)
{ {
@@ -99,11 +97,9 @@ namespace Robust.Server.Maps
tsz = ushort.Parse(val); tsz = ushort.Parse(val);
else if (key == "snapsize") else if (key == "snapsize")
sgsz = float.Parse(val); sgsz = float.Parse(val);
else if (key == "worldpos")
worldPos = kvInfo.Value.AsVector2();
} }
var grid = mapMan.CreateGrid(mapId, gridId); var grid = mapMan.CreateGridNoEntity(mapId, gridId);
gridId = grid.Index; gridId = grid.Index;
@@ -1,24 +1,23 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Robust.Shared.Animations; using Robust.Shared.Animations;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.Enums; using Robust.Shared.Enums;
using Robust.Shared.GameObjects.Components.Map; using Robust.Shared.GameObjects.Components.Map;
using Robust.Shared.GameObjects.EntitySystemMessages; using Robust.Shared.GameObjects.EntitySystemMessages;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.GameObjects.Components; using Robust.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.Interfaces.Map; using Robust.Shared.Interfaces.Map;
using Robust.Shared.Interfaces.Timing; using Robust.Shared.Interfaces.Timing;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Log; using Robust.Shared.Map;
using Robust.Shared.Map; using Robust.Shared.Maths;
using Robust.Shared.Maths; using Robust.Shared.Serialization;
using Robust.Shared.Serialization; using Robust.Shared.Utility;
using Robust.Shared.Utility; using Robust.Shared.ViewVariables;
using Robust.Shared.ViewVariables;
namespace Robust.Shared.GameObjects.Components.Transform namespace Robust.Shared.GameObjects.Components.Transform
{ {
internal class TransformComponent : Component, ITransformComponent, IComponentDebug internal class TransformComponent : Component, ITransformComponent, IComponentDebug
{ {
@@ -33,22 +32,23 @@
private Vector2 _nextPosition; private Vector2 _nextPosition;
private Angle _nextRotation; private Angle _nextRotation;
[ViewVariables] [ViewVariables] private readonly List<EntityUid> _children = new List<EntityUid>();
private readonly List<EntityUid> _children = new List<EntityUid>();
#pragma warning disable 649 #pragma warning disable 649
[Dependency] private readonly IMapManager _mapManager; [Dependency] private readonly IMapManager _mapManager;
[Dependency] private readonly IGameTiming _gameTiming; [Dependency] private readonly IGameTiming _gameTiming;
[Dependency] private readonly IEntityManager _entityManager; [Dependency] private readonly IEntityManager _entityManager;
#pragma warning restore 649 #pragma warning restore 649
/// <inheritdoc /> /// <inheritdoc />
public event EventHandler<MoveEventArgs> OnMove; public event EventHandler<MoveEventArgs> OnMove;
/// <inheritdoc /> /// <inheritdoc />
public override string Name => "Transform"; public override string Name => "Transform";
/// <inheritdoc /> /// <inheritdoc />
public sealed override uint? NetID => NetIDs.TRANSFORM; public sealed override uint? NetID => NetIDs.TRANSFORM;
/// <inheritdoc /> /// <inheritdoc />
public sealed override Type StateType => typeof(TransformComponentState); public sealed override Type StateType => typeof(TransformComponentState);
@@ -77,7 +77,7 @@
get get
{ {
// root node, grid id is undefined // root node, grid id is undefined
if(Owner.HasComponent<IMapComponent>()) if (Owner.HasComponent<IMapComponent>())
return GridId.Nullspace; return GridId.Nullspace;
// second level node, terminates recursion up the branch of the tree // second level node, terminates recursion up the branch of the tree
@@ -119,6 +119,7 @@
{ {
return Parent.WorldRotation + GetLocalRotation(); return Parent.WorldRotation + GetLocalRotation();
} }
return GetLocalRotation(); return GetLocalRotation();
} }
set set
@@ -158,6 +159,7 @@
Matrix3.Multiply(ref myMatrix, ref parentMatrix, out var result); Matrix3.Multiply(ref myMatrix, ref parentMatrix, out var result);
return result; return result;
} }
return GetWorldMatrix(); return GetWorldMatrix();
} }
} }
@@ -174,6 +176,7 @@
Matrix3.Multiply(ref matP, ref myMatrix, out var result); Matrix3.Multiply(ref matP, ref myMatrix, out var result);
return result; return result;
} }
return GetWorldMatrixInv(); return GetWorldMatrixInv();
} }
} }
@@ -304,59 +307,12 @@
} }
[ViewVariables] [ViewVariables]
public IEnumerable<ITransformComponent> Children => _children.Select(u => Owner.EntityManager.GetEntity(u).Transform); public IEnumerable<ITransformComponent> Children =>
_children.Select(u => Owner.EntityManager.GetEntity(u).Transform);
/// <inheritdoc /> /// <inheritdoc />
public Vector2 LerpDestination => _nextPosition; public Vector2 LerpDestination => _nextPosition;
public override void Initialize()
{
// Attempt to parent itself it the defined grid.
if (!_parent.IsValid())
{
if (!Owner.HasComponent<IMapComponent>())
{
if (Owner.HasComponent<IMapGridComponent>())
{
DebugTools.Assert("This should have been set up by the map system.");
}
else
{
// Parent me to the grid comp
if (_gridID != GridId.Nullspace)
{
var mapGrid = _mapManager.GetGrid(_gridID);
if(mapGrid.IsDefaultGrid)
{
var mapEnt = _mapManager.GetMapEntity(mapGrid.ParentMapId);
Logger.WarningS("scene", $"Auto-parenting entity {Owner.Uid} to map {mapGrid.ParentMapId}'s entity {mapEnt.Uid}");
AttachParent(mapEnt);
}
else
{
var gridEnt = _entityManager.GetEntity(mapGrid.GridEntity);
Logger.WarningS("scene", $"Auto-parenting entity {Owner.Uid} to grid {_gridID}'s entity {gridEnt.Uid}");
AttachParent(gridEnt);
}
}
else
{
DebugTools.Assert("My location is unknown!");
}
}
}
else
{
// I am the root node of the scene graph
_gridID = GridId.Nullspace;
_localPosition = Vector2.Zero;
}
}
base.Initialize();
}
/// <inheritdoc /> /// <inheritdoc />
protected override void Startup() protected override void Startup()
{ {
@@ -403,7 +359,7 @@
var newMapEntity = _mapManager.GetMapEntity(mapPos.MapId); var newMapEntity = _mapManager.GetMapEntity(mapPos.MapId);
// this would be a no-op // this would be a no-op
if(newMapEntity == Parent.Owner) if (newMapEntity == Parent.Owner)
return; return;
var concrete = (TransformComponent) Parent; var concrete = (TransformComponent) Parent;
@@ -414,7 +370,6 @@
MapPosition = mapPos; MapPosition = mapPos;
Dirty(); Dirty();
} }
@@ -461,6 +416,7 @@
{ {
return Parent.GetMapTransform(); return Parent.GetMapTransform();
} }
return this; return this;
} }
@@ -481,7 +437,9 @@
} }
else else
{ {
return ContainsEntity(entityTransform.Parent); //Recursively search up the entities containers for this object return
ContainsEntity(entityTransform
.Parent); //Recursively search up the entities containers for this object
} }
} }
@@ -490,15 +448,19 @@
base.ExposeData(serializer); base.ExposeData(serializer);
serializer.DataField(ref _parent, "parent", new EntityUid()); serializer.DataField(ref _parent, "parent", new EntityUid());
serializer.DataField(ref _gridID, "grid", GridId.Nullspace);
serializer.DataField(ref _localPosition, "pos", Vector2.Zero); serializer.DataField(ref _localPosition, "pos", Vector2.Zero);
serializer.DataField(ref _localRotation, "rot", new Angle()); serializer.DataField(ref _localRotation, "rot", new Angle());
if (serializer.Reading && serializer.TryReadDataField("grid", out GridId grid))
{
_gridID = grid;
}
} }
/// <inheritdoc /> /// <inheritdoc />
public override ComponentState GetComponentState() public override ComponentState GetComponentState()
{ {
return new TransformComponentState(_localPosition, GridID, LocalRotation, Parent?.Owner?.Uid); return new TransformComponentState(_localPosition, LocalRotation, Parent?.Owner?.Uid);
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -527,7 +489,7 @@
rebuildMatrices = true; rebuildMatrices = true;
} }
if (_localPosition != newState.LocalPosition || (!_parent.IsValid() && GridID != newState.GridID)) if (_localPosition != newState.LocalPosition)
{ {
var oldPos = GridPosition; var oldPos = GridPosition;
if (_localPosition != newState.LocalPosition) if (_localPosition != newState.LocalPosition)
@@ -535,11 +497,6 @@
SetPosition(newState.LocalPosition); SetPosition(newState.LocalPosition);
} }
if (!_parent.IsValid() && GridID != newState.GridID)
{
_recurseSetGridId(newState.GridID);
}
OnMove?.Invoke(this, new MoveEventArgs(oldPos, GridPosition)); OnMove?.Invoke(this, new MoveEventArgs(oldPos, GridPosition));
rebuildMatrices = true; rebuildMatrices = true;
} }
@@ -556,7 +513,7 @@
_nextPosition = _localPosition; // this should cause the lerp to do nothing _nextPosition = _localPosition; // this should cause the lerp to do nothing
if (nextState != null) if (nextState != null)
_nextRotation = ((TransformComponentState)nextState).Rotation; _nextRotation = ((TransformComponentState) nextState).Rotation;
else else
_nextRotation = _localRotation; // this should cause the lerp to do nothing _nextRotation = _localRotation; // this should cause the lerp to do nothing
} }
@@ -574,10 +531,11 @@
protected virtual Vector2 GetLocalPosition() protected virtual Vector2 GetLocalPosition()
{ {
if(_gameTiming.InSimulation || _localPosition == _nextPosition || Owner.Uid.IsClientSide()) if (_gameTiming.InSimulation || _localPosition == _nextPosition || Owner.Uid.IsClientSide())
return _localPosition; return _localPosition;
return Vector2.Lerp(_localPosition, _nextPosition, (float) (_gameTiming.TickRemainder.TotalSeconds / _gameTiming.TickPeriod.TotalSeconds)); return Vector2.Lerp(_localPosition, _nextPosition,
(float) (_gameTiming.TickRemainder.TotalSeconds / _gameTiming.TickPeriod.TotalSeconds));
} }
protected virtual Angle GetLocalRotation() protected virtual Angle GetLocalRotation()
@@ -585,7 +543,8 @@
if (_gameTiming.InSimulation || _localRotation == _nextRotation || Owner.Uid.IsClientSide()) if (_gameTiming.InSimulation || _localRotation == _nextRotation || Owner.Uid.IsClientSide())
return _localRotation; return _localRotation;
return Angle.Lerp(_localRotation, _nextRotation, (float)(_gameTiming.TickRemainder.TotalSeconds / _gameTiming.TickPeriod.TotalSeconds)); return Angle.Lerp(_localRotation, _nextRotation,
(float) (_gameTiming.TickRemainder.TotalSeconds / _gameTiming.TickPeriod.TotalSeconds));
} }
protected virtual Matrix3 GetWorldMatrix() protected virtual Matrix3 GetWorldMatrix()
@@ -598,7 +557,7 @@
var rot = GetLocalRotation().Theta; var rot = GetLocalRotation().Theta;
var posMat = Matrix3.CreateTranslation(pos); var posMat = Matrix3.CreateTranslation(pos);
var rotMat = Matrix3.CreateRotation((float)rot); var rotMat = Matrix3.CreateRotation((float) rot);
Matrix3.Multiply(ref rotMat, ref posMat, out var transMat); Matrix3.Multiply(ref rotMat, ref posMat, out var transMat);
@@ -615,7 +574,7 @@
var rot = GetLocalRotation().Theta; var rot = GetLocalRotation().Theta;
var posMat = Matrix3.CreateTranslation(pos); var posMat = Matrix3.CreateTranslation(pos);
var rotMat = Matrix3.CreateRotation((float)rot); var rotMat = Matrix3.CreateRotation((float) rot);
var posImat = Matrix3.Invert(posMat); var posImat = Matrix3.Invert(posMat);
var rotImap = Matrix3.Invert(rotMat); var rotImap = Matrix3.Invert(rotMat);
@@ -634,7 +593,7 @@
var rot = _localRotation.Theta; var rot = _localRotation.Theta;
var posMat = Matrix3.CreateTranslation(pos); var posMat = Matrix3.CreateTranslation(pos);
var rotMat = Matrix3.CreateRotation((float)rot); var rotMat = Matrix3.CreateRotation((float) rot);
Matrix3.Multiply(ref rotMat, ref posMat, out var transMat); Matrix3.Multiply(ref rotMat, ref posMat, out var transMat);
@@ -669,16 +628,6 @@
} }
} }
private void _recurseSetGridId(GridId gridId)
{
_gridID = gridId;
foreach (var child in Children)
{
var cast = (TransformComponent) child;
cast._recurseSetGridId(gridId);
}
}
public string GetDebugString() public string GetDebugString()
{ {
return $"pos/rot/wpos/wrot: {GridPosition}/{LocalRotation}/{WorldPosition}/{WorldRotation}"; return $"pos/rot/wpos/wrot: {GridPosition}/{LocalRotation}/{WorldPosition}/{WorldRotation}";
@@ -700,8 +649,6 @@
/// </summary> /// </summary>
public readonly Vector2 LocalPosition; public readonly Vector2 LocalPosition;
public readonly GridId GridID;
/// <summary> /// <summary>
/// Current rotation offset of the entity. /// Current rotation offset of the entity.
/// </summary> /// </summary>
@@ -711,14 +658,12 @@
/// Constructs a new state snapshot of a TransformComponent. /// Constructs a new state snapshot of a TransformComponent.
/// </summary> /// </summary>
/// <param name="localPosition">Current position offset of this entity.</param> /// <param name="localPosition">Current position offset of this entity.</param>
/// <param name="gridId">Current grid ID of this entity.</param>
/// <param name="rotation">Current direction offset of this entity.</param> /// <param name="rotation">Current direction offset of this entity.</param>
/// <param name="parentId">Current parent transform of this entity.</param> /// <param name="parentId">Current parent transform of this entity.</param>
public TransformComponentState(Vector2 localPosition, GridId gridId, Angle rotation, EntityUid? parentId) public TransformComponentState(Vector2 localPosition, Angle rotation, EntityUid? parentId)
: base(NetIDs.TRANSFORM) : base(NetIDs.TRANSFORM)
{ {
LocalPosition = localPosition; LocalPosition = localPosition;
GridID = gridId;
Rotation = rotation; Rotation = rotation;
ParentID = parentId; ParentID = parentId;
} }
+2 -2
View File
@@ -278,13 +278,13 @@ namespace Robust.Shared.GameObjects
return AllocEntity(uid); return AllocEntity(uid);
var entity = AllocEntity(prototypeName, uid); var entity = AllocEntity(prototypeName, uid);
entity.Prototype.LoadEntity(entity, ComponentFactory, null); EntityPrototype.LoadEntity(entity.Prototype, entity, ComponentFactory, null);
return entity; return entity;
} }
private protected void LoadEntity(Entity entity, IEntityLoadContext context) private protected void LoadEntity(Entity entity, IEntityLoadContext context)
{ {
entity.Prototype.LoadEntity(entity, ComponentFactory, context); EntityPrototype.LoadEntity(entity.Prototype, entity, ComponentFactory, context);
} }
private protected static void InitializeAndStartEntity(Entity entity) private protected static void InitializeAndStartEntity(Entity entity)
+2
View File
@@ -14,5 +14,7 @@ namespace Robust.Shared.Map
/// <param name="tileRef">A reference to the new tile.</param> /// <param name="tileRef">A reference to the new tile.</param>
/// <param name="oldTile">The old tile that got replaced.</param> /// <param name="oldTile">The old tile that got replaced.</param>
void RaiseOnTileChanged(TileRef tileRef, Tile oldTile); void RaiseOnTileChanged(TileRef tileRef, Tile oldTile);
IMapGrid CreateGridNoEntity(MapId currentMapID, GridId? gridID = null, ushort chunkSize = 16, float snapSize = 1);
} }
} }
+27 -10
View File
@@ -127,7 +127,7 @@ namespace Robust.Shared.Map
_mapCreationTick.Remove(mapID); _mapCreationTick.Remove(mapID);
var ent = _mapEntities[mapID]; var ent = _mapEntities[mapID];
if(_entityManager.TryGetEntity(ent, out var mapEnt)) if (_entityManager.TryGetEntity(ent, out var mapEnt))
mapEnt.Delete(); mapEnt.Delete();
_mapEntities.Remove(mapID); _mapEntities.Remove(mapID);
@@ -138,13 +138,13 @@ namespace Robust.Shared.Map
_mapDeletionHistory.Add((_gameTiming.CurTick, mapID)); _mapDeletionHistory.Add((_gameTiming.CurTick, mapID));
} }
/// <inheritdoc />
public MapId CreateMap(MapId? mapID = null, GridId? defaultGridID = null) public MapId CreateMap(MapId? mapID = null, GridId? defaultGridID = null)
{ {
if (defaultGridID != null && GridExists(defaultGridID.Value)) if (defaultGridID != null && GridExists(defaultGridID.Value))
{ {
throw new InvalidOperationException($"Grid '{defaultGridID}' already exists."); throw new InvalidOperationException($"Grid '{defaultGridID}' already exists.");
} }
MapId actualID; MapId actualID;
if (mapID != null) if (mapID != null)
{ {
@@ -190,7 +190,7 @@ namespace Robust.Shared.Map
} }
else else
{ {
var newEnt = (Entity)_entityManager.CreateEntityUninitialized(null, GridCoordinates.Nullspace); var newEnt = (Entity) _entityManager.CreateEntityUninitialized(null, GridCoordinates.Nullspace);
_mapEntities.Add(actualID, newEnt.Uid); _mapEntities.Add(actualID, newEnt.Uid);
var mapComp = newEnt.AddComponent<MapComponent>(); var mapComp = newEnt.AddComponent<MapComponent>();
@@ -236,7 +236,7 @@ namespace Robust.Shared.Map
public GridId GetDefaultGridId(MapId mapID) public GridId GetDefaultGridId(MapId mapID)
{ {
if(_defaultGrids.TryGetValue(mapID, out var gridID)) if (_defaultGrids.TryGetValue(mapID, out var gridID))
return gridID; return gridID;
return GridId.Nullspace; //TODO: Hack to make shutdown work return GridId.Nullspace; //TODO: Hack to make shutdown work
} }
@@ -247,6 +247,11 @@ namespace Robust.Shared.Map
} }
public IMapGrid CreateGrid(MapId currentMapID, GridId? gridID = null, ushort chunkSize = 16, float snapSize = 1) public IMapGrid CreateGrid(MapId currentMapID, GridId? gridID = null, ushort chunkSize = 16, float snapSize = 1)
{
return CreateGridImpl(currentMapID, gridID, chunkSize, snapSize, true);
}
private IMapGrid CreateGridImpl(MapId currentMapID, GridId? gridID, ushort chunkSize, float snapSize, bool createEntity)
{ {
GridId actualID; GridId actualID;
if (gridID != null) if (gridID != null)
@@ -272,7 +277,7 @@ namespace Robust.Shared.Map
_grids.Add(actualID, grid); _grids.Add(actualID, grid);
Logger.DebugS("map", $"Creating new grid {actualID}"); Logger.DebugS("map", $"Creating new grid {actualID}");
if(actualID != GridId.Nullspace) // nullspace default grid is not bound to an entity if (actualID != GridId.Nullspace && createEntity) // nullspace default grid is not bound to an entity
{ {
// the entity may already exist from map deserialization // the entity may already exist from map deserialization
IMapGridComponent result = null; IMapGridComponent result = null;
@@ -292,7 +297,9 @@ namespace Robust.Shared.Map
} }
else else
{ {
var newEnt = (Entity)_entityManager.CreateEntityUninitialized(null, new MapCoordinates(Vector2.Zero, currentMapID)); var newEnt =
(Entity) _entityManager.CreateEntityUninitialized(null,
new MapCoordinates(Vector2.Zero, currentMapID));
grid.GridEntity = newEnt.Uid; grid.GridEntity = newEnt.Uid;
Logger.DebugS("map", $"Binding grid {actualID} to entity {grid.GridEntity}"); Logger.DebugS("map", $"Binding grid {actualID} to entity {grid.GridEntity}");
@@ -302,8 +309,11 @@ namespace Robust.Shared.Map
newEnt.Transform.AttachParent(_entityManager.GetEntity(_mapEntities[currentMapID])); newEnt.Transform.AttachParent(_entityManager.GetEntity(_mapEntities[currentMapID]));
newEnt.InitializeComponents(); if (createEntity)
newEnt.StartAllComponents(); {
newEnt.InitializeComponents();
newEnt.StartAllComponents();
}
} }
} }
@@ -311,6 +321,12 @@ namespace Robust.Shared.Map
return grid; return grid;
} }
public IMapGrid CreateGridNoEntity(MapId currentMapID, GridId? gridID = null, ushort chunkSize = 16,
float snapSize = 1)
{
return CreateGridImpl(currentMapID, gridID, chunkSize, snapSize, false);
}
public IMapGrid GetGrid(GridId gridID) public IMapGrid GetGrid(GridId gridID)
{ {
return _grids[gridID]; return _grids[gridID];
@@ -323,6 +339,7 @@ namespace Robust.Shared.Map
grid = gridinterface; grid = gridinterface;
return true; return true;
} }
grid = null; grid = null;
return false; return false;
} }
@@ -359,7 +376,7 @@ namespace Robust.Shared.Map
public void DeleteGrid(GridId gridID) public void DeleteGrid(GridId gridID)
{ {
// nullspace grid cannot be deleted // nullspace grid cannot be deleted
if(gridID == GridId.Nullspace) if (gridID == GridId.Nullspace)
return; return;
var grid = _grids[gridID]; var grid = _grids[gridID];
@@ -370,7 +387,7 @@ namespace Robust.Shared.Map
if (_defaultGrids.ContainsKey(grid.ParentMapId)) if (_defaultGrids.ContainsKey(grid.ParentMapId))
_defaultGrids.Remove(grid.ParentMapId); _defaultGrids.Remove(grid.ParentMapId);
if(_entityManager.TryGetEntity(grid.GridEntity, out var gridEnt)) if (_entityManager.TryGetEntity(grid.GridEntity, out var gridEnt))
gridEnt.Delete(); gridEnt.Delete();
OnGridRemoved?.Invoke(gridID); OnGridRemoved?.Invoke(gridID);
+60 -31
View File
@@ -70,12 +70,14 @@ namespace Robust.Shared.GameObjects
/// </summary> /// </summary>
[ViewVariables] [ViewVariables]
public int PlacementRange { get; protected set; } = DEFAULT_RANGE; public int PlacementRange { get; protected set; } = DEFAULT_RANGE;
private const int DEFAULT_RANGE = 200; private const int DEFAULT_RANGE = 200;
/// <summary> /// <summary>
/// Set to hold snapping categories that this object has applied to it such as pipe/wire/wallmount /// Set to hold snapping categories that this object has applied to it such as pipe/wire/wallmount
/// </summary> /// </summary>
private readonly HashSet<string> _snapFlags = new HashSet<string>(); private readonly HashSet<string> _snapFlags = new HashSet<string>();
private bool _snapOverriden = false; private bool _snapOverriden = false;
/// <summary> /// <summary>
@@ -83,6 +85,7 @@ namespace Robust.Shared.GameObjects
/// </summary> /// </summary>
[ViewVariables] [ViewVariables]
public Vector2i PlacementOffset { get; protected set; } public Vector2i PlacementOffset { get; protected set; }
private bool _placementOverriden = false; private bool _placementOverriden = false;
/// <summary> /// <summary>
@@ -102,6 +105,7 @@ namespace Robust.Shared.GameObjects
/// </summary> /// </summary>
[ViewVariables] [ViewVariables]
public List<EntityPrototype> Children { get; private set; } public List<EntityPrototype> Children { get; private set; }
public bool IsRoot => Parent == null; public bool IsRoot => Parent == null;
/// <summary> /// <summary>
@@ -122,7 +126,10 @@ namespace Robust.Shared.GameObjects
private readonly HashSet<Type> ReferenceTypes = new HashSet<Type>(); private readonly HashSet<Type> ReferenceTypes = new HashSet<Type>();
string CurrentDeserializingComponent; string CurrentDeserializingComponent;
readonly Dictionary<string, Dictionary<(string, Type), object>> FieldCache = new Dictionary<string, Dictionary<(string, Type), object>>();
readonly Dictionary<string, Dictionary<(string, Type), object>> FieldCache =
new Dictionary<string, Dictionary<(string, Type), object>>();
readonly Dictionary<string, object> DataCache = new Dictionary<string, object>(); readonly Dictionary<string, object> DataCache = new Dictionary<string, object>();
public EntityPrototype() public EntityPrototype()
@@ -170,8 +177,10 @@ namespace Robust.Shared.GameObjects
{ {
if (ReferenceTypes.Contains(type)) if (ReferenceTypes.Contains(type))
{ {
throw new InvalidOperationException($"Duplicate component reference in prototype: '{type}'"); throw new InvalidOperationException(
$"Duplicate component reference in prototype: '{type}'");
} }
ReferenceTypes.Add(type); ReferenceTypes.Add(type);
} }
} }
@@ -233,6 +242,7 @@ namespace Robust.Shared.GameObjects
{ {
_snapFlags.Add(flag); _snapFlags.Add(flag);
} }
_snapOverriden = true; _snapOverriden = true;
} }
} }
@@ -253,6 +263,7 @@ namespace Robust.Shared.GameObjects
{ {
Parent.Children = new List<EntityPrototype>(); Parent.Children = new List<EntityPrototype>();
} }
Parent.Children.Add(this); Parent.Children.Add(this);
return false; return false;
@@ -266,9 +277,11 @@ namespace Robust.Shared.GameObjects
{ {
break; break;
} }
PushInheritanceAll(); PushInheritanceAll();
break; break;
} }
return false; return false;
} }
@@ -292,10 +305,12 @@ namespace Robust.Shared.GameObjects
{ {
continue; continue;
} }
foreach (var target in targetList) foreach (var target in targetList)
{ {
PushInheritance(source, target); PushInheritance(source, target);
} }
newSources.AddRange(targetList); newSources.AddRange(targetList);
} }
@@ -303,11 +318,13 @@ namespace Robust.Shared.GameObjects
{ {
break; break;
} }
sourceTargets.Clear(); sourceTargets.Clear();
foreach (var newSource in newSources) foreach (var newSource in newSources)
{ {
sourceTargets.Add((newSource, newSource.Children)); sourceTargets.Add((newSource, newSource.Children));
} }
newSources.Clear(); newSources.Clear();
} }
} }
@@ -341,9 +358,11 @@ namespace Robust.Shared.GameObjects
goto next; goto next;
} }
} }
target.Components[component.Key] = new YamlMappingNode(component.Value.AsEnumerable()); target.Components[component.Key] = new YamlMappingNode(component.Value.AsEnumerable());
} }
next:;
next: ;
} }
// Copy all simple data over. // Copy all simple data over.
@@ -391,40 +410,46 @@ namespace Robust.Shared.GameObjects
} }
} }
internal void LoadEntity(Entity entity, IComponentFactory factory, IEntityLoadContext context) internal static void LoadEntity(EntityPrototype prototype, Entity entity, IComponentFactory factory,
IEntityLoadContext context)
{ {
YamlObjectSerializer.Context defaultContext = null; YamlObjectSerializer.Context defaultContext = null;
if (context == null) if (context == null)
{ {
defaultContext = new PrototypeSerializationContext(this); defaultContext = new PrototypeSerializationContext(prototype);
} }
foreach (var (name, data) in Components)
if (prototype != null)
{ {
var compRegistration = factory.GetRegistration(name); foreach (var (name, data) in prototype.Components)
{
var compRegistration = factory.GetRegistration(name);
Component component; Component component;
if (entity.TryGetComponent(compRegistration.Type, out var existingComp)) if (entity.TryGetComponent(compRegistration.Type, out var existingComp))
{ {
component = (Component) existingComp; component = (Component) existingComp;
} }
else else
{ {
component = (Component) factory.GetComponent(name); component = (Component) factory.GetComponent(name);
component.Owner = entity; component.Owner = entity;
entity.AddComponent(component); entity.AddComponent(component);
} }
ObjectSerializer ser; ObjectSerializer ser;
if (context != null) if (context != null)
{ {
ser = context.GetComponentSerializer(name, data); ser = context.GetComponentSerializer(name, data);
}
else
{
prototype.CurrentDeserializingComponent = name;
ser = YamlObjectSerializer.NewReader(data, defaultContext);
}
component.ExposeData(ser);
} }
else
{
CurrentDeserializingComponent = name;
ser = YamlObjectSerializer.NewReader(data, defaultContext);
}
component.ExposeData(ser);
} }
if (context == null) if (context == null)
@@ -436,12 +461,12 @@ namespace Robust.Shared.GameObjects
// Components that have been ADDED NEW need to be handled too. // Components that have been ADDED NEW need to be handled too.
foreach (var name in context.GetExtraComponentTypes()) foreach (var name in context.GetExtraComponentTypes())
{ {
if (Components.ContainsKey(name)) if ((prototype != null && prototype.Components.ContainsKey(name)) || name == "Transform" || name == "Metadata")
{ {
continue; continue;
} }
var component = (Component)factory.GetComponent(name); var component = (Component) factory.GetComponent(name);
component.Owner = entity; component.Owner = entity;
var ser = context.GetComponentSerializer(name, null); var ser = context.GetComponentSerializer(name, null);
component.ExposeData(ser); component.ExposeData(ser);
@@ -496,6 +521,7 @@ namespace Robust.Shared.GameObjects
base.SetCachedField<T>(field, value); base.SetCachedField<T>(field, value);
return; return;
} }
if (!prototype.FieldCache.TryGetValue(prototype.CurrentDeserializingComponent, out var fieldList)) if (!prototype.FieldCache.TryGetValue(prototype.CurrentDeserializingComponent, out var fieldList))
{ {
fieldList = new Dictionary<(string, Type), object>(); fieldList = new Dictionary<(string, Type), object>();
@@ -511,11 +537,12 @@ namespace Robust.Shared.GameObjects
{ {
return base.TryGetCachedField<T>(field, out value); return base.TryGetCachedField<T>(field, out value);
} }
if (prototype.FieldCache.TryGetValue(prototype.CurrentDeserializingComponent, out var dict)) if (prototype.FieldCache.TryGetValue(prototype.CurrentDeserializingComponent, out var dict))
{ {
if (dict.TryGetValue((field, typeof(T)), out var theValue)) if (dict.TryGetValue((field, typeof(T)), out var theValue))
{ {
value = (T)theValue; value = (T) theValue;
return true; return true;
} }
} }
@@ -531,6 +558,7 @@ namespace Robust.Shared.GameObjects
base.SetDataCache(field, value); base.SetDataCache(field, value);
return; return;
} }
prototype.DataCache[field] = value; prototype.DataCache[field] = value;
} }
@@ -540,6 +568,7 @@ namespace Robust.Shared.GameObjects
{ {
return base.TryGetDataCache(field, out value); return base.TryGetDataCache(field, out value);
} }
return prototype.DataCache.TryGetValue(field, out value); return prototype.DataCache.TryGetValue(field, out value);
} }
} }
+1
View File
@@ -38,6 +38,7 @@ namespace Robust.Shared
IoCManager.Register<ILocalizationManager, LocalizationManager>(); IoCManager.Register<ILocalizationManager, LocalizationManager>();
IoCManager.Register<ILogManager, LogManager>(); IoCManager.Register<ILogManager, LogManager>();
IoCManager.Register<IMapManager, MapManager>(); IoCManager.Register<IMapManager, MapManager>();
IoCManager.Register<IMapManagerInternal, MapManager>();
IoCManager.Register<IModLoader, ModLoader>(); IoCManager.Register<IModLoader, ModLoader>();
IoCManager.Register<INetManager, NetManager>(); IoCManager.Register<INetManager, NetManager>();
IoCManager.Register<IPhysicsManager, PhysicsManager>(); IoCManager.Register<IPhysicsManager, PhysicsManager>();
@@ -68,16 +68,16 @@ namespace Robust.UnitTesting.Client.GameObjects.Components
var parentTrans = parent.Transform; var parentTrans = parent.Transform;
var childTrans = child.Transform; var childTrans = child.Transform;
var compState = new TransformComponent.TransformComponentState(new Vector2(5, 5), GridB.Index, new Angle(0), GridB.GridEntity); var compState = new TransformComponent.TransformComponentState(new Vector2(5, 5), new Angle(0), GridB.GridEntity);
parentTrans.HandleComponentState(compState, null); parentTrans.HandleComponentState(compState, null);
compState = new TransformComponent.TransformComponentState(new Vector2(6, 6), GridB.Index, new Angle(0), GridB.GridEntity); compState = new TransformComponent.TransformComponentState(new Vector2(6, 6), new Angle(0), GridB.GridEntity);
childTrans.HandleComponentState(compState, null); childTrans.HandleComponentState(compState, null);
// World pos should be 6, 6 now. // World pos should be 6, 6 now.
// Act // Act
var oldWpos = childTrans.WorldPosition; var oldWpos = childTrans.WorldPosition;
compState = new TransformComponent.TransformComponentState(new Vector2(1, 1), GridB.Index, new Angle(0), parent.Uid); compState = new TransformComponent.TransformComponentState(new Vector2(1, 1), new Angle(0), parent.Uid);
childTrans.HandleComponentState(compState, null); childTrans.HandleComponentState(compState, null);
var newWpos = childTrans.WorldPosition; var newWpos = childTrans.WorldPosition;
@@ -105,11 +105,11 @@ namespace Robust.UnitTesting.Client.GameObjects.Components
var node2Trans = node2.Transform; var node2Trans = node2.Transform;
var node3Trans = node3.Transform; var node3Trans = node3.Transform;
var compState = new TransformComponent.TransformComponentState(new Vector2(6, 6), GridB.Index, Angle.FromDegrees(135), GridB.GridEntity); var compState = new TransformComponent.TransformComponentState(new Vector2(6, 6), Angle.FromDegrees(135), GridB.GridEntity);
node1Trans.HandleComponentState(compState, null); node1Trans.HandleComponentState(compState, null);
compState = new TransformComponent.TransformComponentState(new Vector2(1, 1), GridB.Index, Angle.FromDegrees(45), node1.Uid); compState = new TransformComponent.TransformComponentState(new Vector2(1, 1), Angle.FromDegrees(45), node1.Uid);
node2Trans.HandleComponentState(compState, null); node2Trans.HandleComponentState(compState, null);
compState = new TransformComponent.TransformComponentState(new Vector2(0, 0), GridB.Index, Angle.FromDegrees(45), node2.Uid); compState = new TransformComponent.TransformComponentState(new Vector2(0, 0), Angle.FromDegrees(45), node2.Uid);
node3Trans.HandleComponentState(compState, null); node3Trans.HandleComponentState(compState, null);
// Act // Act
+2 -1
View File
@@ -37,10 +37,11 @@ Contains data for all the grids. The section is an ordered sequence. Each sequen
* `tilesize`: An integer representing the length of one side of a grid tile, in world units (meters). * `tilesize`: An integer representing the length of one side of a grid tile, in world units (meters).
* `chunksize`: An integer representing the tile dimensions of a chunk in this grid. Basically, when chunksize is `x`, a single chunk contains a square region of `x` by `x` tiles. * `chunksize`: An integer representing the tile dimensions of a chunk in this grid. Basically, when chunksize is `x`, a single chunk contains a square region of `x` by `x` tiles.
* `snapsize`: A float representing snap grid size. * `snapsize`: A float representing snap grid size.
* `worldpos`: Position in the world of this grid.
* `chunks`: A sequence containing the actual chunk data for this grid. See below. * `chunks`: A sequence containing the actual chunk data for this grid. See below.
Grids also have their **grid entity** serialized like regular entities.
### The `entities` Section ### The `entities` Section
Contains data for all entities on the map. Just like grids these are stored in an indexed list, and an entity declaration is pretty much just like a prototype. Contains data for all entities on the map. Just like grids these are stored in an indexed list, and an entity declaration is pretty much just like a prototype.