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

View File

@@ -16,6 +16,7 @@ using System.Globalization;
using Robust.Shared.Interfaces.GameObjects;
using System.Linq;
using Robust.Server.Interfaces.Timing;
using Robust.Shared.GameObjects.Components.Map;
using YamlDotNet.Core;
namespace Robust.Server.Maps
@@ -32,7 +33,7 @@ namespace Robust.Server.Maps
private readonly IResourceManager _resMan;
[Dependency]
private readonly IMapManager _mapManager;
private readonly IMapManagerInternal _mapManager;
[Dependency]
private readonly ITileDefinitionManager _tileDefinitionManager;
@@ -207,7 +208,7 @@ namespace Robust.Server.Maps
/// </summary>
private class MapContext : YamlObjectSerializer.Context, IEntityLoadContext
{
private readonly IMapManager _mapManager;
private readonly IMapManagerInternal _mapManager;
private readonly ITileDefinitionManager _tileDefinitionManager;
private readonly IServerEntityManagerInternal _serverEntityManager;
private readonly IPauseManager _pauseManager;
@@ -219,6 +220,10 @@ namespace Robust.Server.Maps
private readonly Dictionary<int, EntityUid> UidEntityMap = new Dictionary<int, EntityUid>();
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;
@@ -234,7 +239,7 @@ namespace Robust.Server.Maps
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;
_tileDefinitionManager = tileDefs;
@@ -244,7 +249,7 @@ namespace Robust.Server.Maps
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)
{
_mapManager = maps;
@@ -273,6 +278,14 @@ namespace Robust.Server.Maps
// Actually instance components and run ExposeData on them.
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.
FinishEntitiesInitialization();
@@ -280,6 +293,29 @@ namespace Robust.Server.Maps
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()
{
var meta = RootNode.GetNode<YamlMappingNode>("meta");
@@ -340,23 +376,28 @@ namespace Robust.Server.Maps
var entities = RootNode.GetNode<YamlSequenceNode>("entities");
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;
if (entityDef.TryGetNode("uid", out var uidNode))
{
uid = uidNode.AsInt();
}
var entity = _serverEntityManager.AllocEntity(type);
Entities.Add(entity);
UidEntityMap.Add(uid, entity.Uid);
_entitiesToDeserialize.Add((entity, entityDef));
}
}
private void FinishEntitiesLoad()
{
var entityData = RootNode.GetNode<YamlSequenceNode>("entities");
foreach (var (entity, data) in Entities.Zip(entityData, (a, b) => (a, (YamlMappingNode)b)))
foreach (var (entity, data) in _entitiesToDeserialize)
{
CurrentReadingEntityComponents = new Dictionary<string, YamlMappingNode>();
if (data.TryGetNode("components", out YamlSequenceNode componentList))
@@ -478,10 +519,14 @@ namespace Robust.Server.Maps
CurrentWritingEntity = entity;
var mapping = new YamlMappingNode
{
{"type", entity.Prototype.ID},
{"uid", EntityUidMap[entity.Uid].ToString(CultureInfo.InvariantCulture)}
};
if (entity.Prototype != null)
{
mapping.Add("type", entity.Prototype.ID);
}
var components = new YamlSequenceNode();
// See engine#636 for why the Distinct() call.
foreach (var component in entity.GetAllComponents())
@@ -514,6 +559,12 @@ namespace Robust.Server.Maps
{
if (type == typeof(GridId))
{
if (node.AsString() == "null")
{
obj = GridId.Nullspace;
return true;
}
var val = node.AsInt();
if (val >= Grids.Count)
{
@@ -527,6 +578,12 @@ namespace Robust.Server.Maps
}
if (type == typeof(EntityUid))
{
if (node.AsString() == "null")
{
obj = EntityUid.Invalid;
return true;
}
var val = node.AsInt();
if (val >= Entities.Count)
{
@@ -574,8 +631,15 @@ namespace Robust.Server.Maps
case EntityUid entityUid:
if (!EntityUidMap.TryGetValue(entityUid, out var entityUidMapped))
{
Logger.WarningS("map", "Cannot write entity UID '{0}'.", entityUid);
break;
// Terrible hack to mute this warning on the grids themselves when serializing blueprints.
if (!IsBlueprintMode || !CurrentWritingEntity.HasComponent<MapGridComponent>() ||
CurrentWritingComponent != "Transform")
{
Logger.WarningS("map", "Cannot write entity UID '{0}'.", entityUid);
}
node = new YamlScalarNode("null");
return true;
}
else
{
@@ -627,11 +691,18 @@ namespace Robust.Server.Maps
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))
{
// This component was added mid-game.
return false;
}
var testSer = YamlObjectSerializer.NewReader(compData);
if (testSer.TryReadDataFieldCached(field, out T prototypeVal))
{
@@ -648,7 +719,7 @@ namespace Robust.Server.Maps
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;
}
@@ -658,7 +729,7 @@ namespace Robust.Server.Maps
var current = entity.Transform;
while (current.Parent != null)
{
if (!current.Parent.Owner.Prototype.MapSavable)
if (current.Parent.Owner.Prototype?.MapSavable == false)
{
return false;
}

View File

@@ -12,7 +12,7 @@ using YamlDotNet.RepresentationModel;
namespace Robust.Server.Maps
{
public static class YamlGridSerializer
internal static class YamlGridSerializer
{
public static YamlMappingNode SerializeGrid(IMapGrid mapGrid)
{
@@ -28,7 +28,6 @@ namespace Robust.Server.Maps
info.Add("chunksize", grid.ChunkSize.ToString(CultureInfo.InvariantCulture));
info.Add("tilesize", grid.TileSize.ToString(CultureInfo.InvariantCulture));
info.Add("snapsize", grid.SnapSize.ToString(CultureInfo.InvariantCulture));
info.Add("worldpos", $"{grid.WorldPosition.X},{grid.WorldPosition.Y}");
var chunks = grid.GetMapChunks();
foreach (var chunk in chunks)
@@ -80,14 +79,13 @@ namespace Robust.Server.Maps
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,
ITileDefinitionManager tileDefinitionManager)
{
ushort csz = 0;
ushort tsz = 0;
float sgsz = 0.0f;
var worldPos = Vector2.Zero;
foreach (var kvInfo in info)
{
@@ -99,11 +97,9 @@ namespace Robust.Server.Maps
tsz = ushort.Parse(val);
else if (key == "snapsize")
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;

View File

@@ -1,24 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Robust.Shared.Animations;
using Robust.Shared.Containers;
using Robust.Shared.Enums;
using Robust.Shared.GameObjects.Components.Map;
using Robust.Shared.GameObjects.EntitySystemMessages;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.Interfaces.Timing;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
using System;
using System.Collections.Generic;
using System.Linq;
using Robust.Shared.Animations;
using Robust.Shared.Containers;
using Robust.Shared.Enums;
using Robust.Shared.GameObjects.Components.Map;
using Robust.Shared.GameObjects.EntitySystemMessages;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.Interfaces.Timing;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
namespace Robust.Shared.GameObjects.Components.Transform
namespace Robust.Shared.GameObjects.Components.Transform
{
internal class TransformComponent : Component, ITransformComponent, IComponentDebug
{
@@ -33,22 +32,23 @@
private Vector2 _nextPosition;
private Angle _nextRotation;
[ViewVariables]
private readonly List<EntityUid> _children = new List<EntityUid>();
[ViewVariables] private readonly List<EntityUid> _children = new List<EntityUid>();
#pragma warning disable 649
#pragma warning disable 649
[Dependency] private readonly IMapManager _mapManager;
[Dependency] private readonly IGameTiming _gameTiming;
[Dependency] private readonly IEntityManager _entityManager;
#pragma warning restore 649
#pragma warning restore 649
/// <inheritdoc />
public event EventHandler<MoveEventArgs> OnMove;
/// <inheritdoc />
public override string Name => "Transform";
/// <inheritdoc />
public sealed override uint? NetID => NetIDs.TRANSFORM;
/// <inheritdoc />
public sealed override Type StateType => typeof(TransformComponentState);
@@ -77,7 +77,7 @@
get
{
// root node, grid id is undefined
if(Owner.HasComponent<IMapComponent>())
if (Owner.HasComponent<IMapComponent>())
return GridId.Nullspace;
// second level node, terminates recursion up the branch of the tree
@@ -119,6 +119,7 @@
{
return Parent.WorldRotation + GetLocalRotation();
}
return GetLocalRotation();
}
set
@@ -158,6 +159,7 @@
Matrix3.Multiply(ref myMatrix, ref parentMatrix, out var result);
return result;
}
return GetWorldMatrix();
}
}
@@ -174,6 +176,7 @@
Matrix3.Multiply(ref matP, ref myMatrix, out var result);
return result;
}
return GetWorldMatrixInv();
}
}
@@ -304,59 +307,12 @@
}
[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 />
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 />
protected override void Startup()
{
@@ -403,7 +359,7 @@
var newMapEntity = _mapManager.GetMapEntity(mapPos.MapId);
// this would be a no-op
if(newMapEntity == Parent.Owner)
if (newMapEntity == Parent.Owner)
return;
var concrete = (TransformComponent) Parent;
@@ -414,7 +370,6 @@
MapPosition = mapPos;
Dirty();
}
@@ -461,6 +416,7 @@
{
return Parent.GetMapTransform();
}
return this;
}
@@ -481,7 +437,9 @@
}
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);
serializer.DataField(ref _parent, "parent", new EntityUid());
serializer.DataField(ref _gridID, "grid", GridId.Nullspace);
serializer.DataField(ref _localPosition, "pos", Vector2.Zero);
serializer.DataField(ref _localRotation, "rot", new Angle());
if (serializer.Reading && serializer.TryReadDataField("grid", out GridId grid))
{
_gridID = grid;
}
}
/// <inheritdoc />
public override ComponentState GetComponentState()
{
return new TransformComponentState(_localPosition, GridID, LocalRotation, Parent?.Owner?.Uid);
return new TransformComponentState(_localPosition, LocalRotation, Parent?.Owner?.Uid);
}
/// <inheritdoc />
@@ -527,7 +489,7 @@
rebuildMatrices = true;
}
if (_localPosition != newState.LocalPosition || (!_parent.IsValid() && GridID != newState.GridID))
if (_localPosition != newState.LocalPosition)
{
var oldPos = GridPosition;
if (_localPosition != newState.LocalPosition)
@@ -535,11 +497,6 @@
SetPosition(newState.LocalPosition);
}
if (!_parent.IsValid() && GridID != newState.GridID)
{
_recurseSetGridId(newState.GridID);
}
OnMove?.Invoke(this, new MoveEventArgs(oldPos, GridPosition));
rebuildMatrices = true;
}
@@ -556,7 +513,7 @@
_nextPosition = _localPosition; // this should cause the lerp to do nothing
if (nextState != null)
_nextRotation = ((TransformComponentState)nextState).Rotation;
_nextRotation = ((TransformComponentState) nextState).Rotation;
else
_nextRotation = _localRotation; // this should cause the lerp to do nothing
}
@@ -574,10 +531,11 @@
protected virtual Vector2 GetLocalPosition()
{
if(_gameTiming.InSimulation || _localPosition == _nextPosition || Owner.Uid.IsClientSide())
if (_gameTiming.InSimulation || _localPosition == _nextPosition || Owner.Uid.IsClientSide())
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()
@@ -585,7 +543,8 @@
if (_gameTiming.InSimulation || _localRotation == _nextRotation || Owner.Uid.IsClientSide())
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()
@@ -598,7 +557,7 @@
var rot = GetLocalRotation().Theta;
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);
@@ -615,7 +574,7 @@
var rot = GetLocalRotation().Theta;
var posMat = Matrix3.CreateTranslation(pos);
var rotMat = Matrix3.CreateRotation((float)rot);
var rotMat = Matrix3.CreateRotation((float) rot);
var posImat = Matrix3.Invert(posMat);
var rotImap = Matrix3.Invert(rotMat);
@@ -634,7 +593,7 @@
var rot = _localRotation.Theta;
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);
@@ -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()
{
return $"pos/rot/wpos/wrot: {GridPosition}/{LocalRotation}/{WorldPosition}/{WorldRotation}";
@@ -700,8 +649,6 @@
/// </summary>
public readonly Vector2 LocalPosition;
public readonly GridId GridID;
/// <summary>
/// Current rotation offset of the entity.
/// </summary>
@@ -711,14 +658,12 @@
/// Constructs a new state snapshot of a TransformComponent.
/// </summary>
/// <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="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)
{
LocalPosition = localPosition;
GridID = gridId;
Rotation = rotation;
ParentID = parentId;
}

View File

@@ -278,13 +278,13 @@ namespace Robust.Shared.GameObjects
return AllocEntity(uid);
var entity = AllocEntity(prototypeName, uid);
entity.Prototype.LoadEntity(entity, ComponentFactory, null);
EntityPrototype.LoadEntity(entity.Prototype, entity, ComponentFactory, null);
return entity;
}
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)

View File

@@ -14,5 +14,7 @@ namespace Robust.Shared.Map
/// <param name="tileRef">A reference to the new tile.</param>
/// <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);
}
}

View File

@@ -127,7 +127,7 @@ namespace Robust.Shared.Map
_mapCreationTick.Remove(mapID);
var ent = _mapEntities[mapID];
if(_entityManager.TryGetEntity(ent, out var mapEnt))
if (_entityManager.TryGetEntity(ent, out var mapEnt))
mapEnt.Delete();
_mapEntities.Remove(mapID);
@@ -138,13 +138,13 @@ namespace Robust.Shared.Map
_mapDeletionHistory.Add((_gameTiming.CurTick, mapID));
}
/// <inheritdoc />
public MapId CreateMap(MapId? mapID = null, GridId? defaultGridID = null)
{
if (defaultGridID != null && GridExists(defaultGridID.Value))
{
throw new InvalidOperationException($"Grid '{defaultGridID}' already exists.");
}
MapId actualID;
if (mapID != null)
{
@@ -190,7 +190,7 @@ namespace Robust.Shared.Map
}
else
{
var newEnt = (Entity)_entityManager.CreateEntityUninitialized(null, GridCoordinates.Nullspace);
var newEnt = (Entity) _entityManager.CreateEntityUninitialized(null, GridCoordinates.Nullspace);
_mapEntities.Add(actualID, newEnt.Uid);
var mapComp = newEnt.AddComponent<MapComponent>();
@@ -236,7 +236,7 @@ namespace Robust.Shared.Map
public GridId GetDefaultGridId(MapId mapID)
{
if(_defaultGrids.TryGetValue(mapID, out var gridID))
if (_defaultGrids.TryGetValue(mapID, out var gridID))
return gridID;
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)
{
return CreateGridImpl(currentMapID, gridID, chunkSize, snapSize, true);
}
private IMapGrid CreateGridImpl(MapId currentMapID, GridId? gridID, ushort chunkSize, float snapSize, bool createEntity)
{
GridId actualID;
if (gridID != null)
@@ -272,7 +277,7 @@ namespace Robust.Shared.Map
_grids.Add(actualID, grid);
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
IMapGridComponent result = null;
@@ -292,7 +297,9 @@ namespace Robust.Shared.Map
}
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;
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.InitializeComponents();
newEnt.StartAllComponents();
if (createEntity)
{
newEnt.InitializeComponents();
newEnt.StartAllComponents();
}
}
}
@@ -311,6 +321,12 @@ namespace Robust.Shared.Map
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)
{
return _grids[gridID];
@@ -323,6 +339,7 @@ namespace Robust.Shared.Map
grid = gridinterface;
return true;
}
grid = null;
return false;
}
@@ -359,7 +376,7 @@ namespace Robust.Shared.Map
public void DeleteGrid(GridId gridID)
{
// nullspace grid cannot be deleted
if(gridID == GridId.Nullspace)
if (gridID == GridId.Nullspace)
return;
var grid = _grids[gridID];
@@ -370,7 +387,7 @@ namespace Robust.Shared.Map
if (_defaultGrids.ContainsKey(grid.ParentMapId))
_defaultGrids.Remove(grid.ParentMapId);
if(_entityManager.TryGetEntity(grid.GridEntity, out var gridEnt))
if (_entityManager.TryGetEntity(grid.GridEntity, out var gridEnt))
gridEnt.Delete();
OnGridRemoved?.Invoke(gridID);

View File

@@ -70,12 +70,14 @@ namespace Robust.Shared.GameObjects
/// </summary>
[ViewVariables]
public int PlacementRange { get; protected set; } = DEFAULT_RANGE;
private const int DEFAULT_RANGE = 200;
/// <summary>
/// Set to hold snapping categories that this object has applied to it such as pipe/wire/wallmount
/// </summary>
private readonly HashSet<string> _snapFlags = new HashSet<string>();
private bool _snapOverriden = false;
/// <summary>
@@ -83,6 +85,7 @@ namespace Robust.Shared.GameObjects
/// </summary>
[ViewVariables]
public Vector2i PlacementOffset { get; protected set; }
private bool _placementOverriden = false;
/// <summary>
@@ -102,6 +105,7 @@ namespace Robust.Shared.GameObjects
/// </summary>
[ViewVariables]
public List<EntityPrototype> Children { get; private set; }
public bool IsRoot => Parent == null;
/// <summary>
@@ -122,7 +126,10 @@ namespace Robust.Shared.GameObjects
private readonly HashSet<Type> ReferenceTypes = new HashSet<Type>();
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>();
public EntityPrototype()
@@ -170,8 +177,10 @@ namespace Robust.Shared.GameObjects
{
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);
}
}
@@ -233,6 +242,7 @@ namespace Robust.Shared.GameObjects
{
_snapFlags.Add(flag);
}
_snapOverriden = true;
}
}
@@ -253,6 +263,7 @@ namespace Robust.Shared.GameObjects
{
Parent.Children = new List<EntityPrototype>();
}
Parent.Children.Add(this);
return false;
@@ -266,9 +277,11 @@ namespace Robust.Shared.GameObjects
{
break;
}
PushInheritanceAll();
break;
}
return false;
}
@@ -292,10 +305,12 @@ namespace Robust.Shared.GameObjects
{
continue;
}
foreach (var target in targetList)
{
PushInheritance(source, target);
}
newSources.AddRange(targetList);
}
@@ -303,11 +318,13 @@ namespace Robust.Shared.GameObjects
{
break;
}
sourceTargets.Clear();
foreach (var newSource in newSources)
{
sourceTargets.Add((newSource, newSource.Children));
}
newSources.Clear();
}
}
@@ -341,9 +358,11 @@ namespace Robust.Shared.GameObjects
goto next;
}
}
target.Components[component.Key] = new YamlMappingNode(component.Value.AsEnumerable());
}
next:;
next: ;
}
// 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;
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;
if (entity.TryGetComponent(compRegistration.Type, out var existingComp))
{
component = (Component) existingComp;
}
else
{
component = (Component) factory.GetComponent(name);
component.Owner = entity;
entity.AddComponent(component);
}
Component component;
if (entity.TryGetComponent(compRegistration.Type, out var existingComp))
{
component = (Component) existingComp;
}
else
{
component = (Component) factory.GetComponent(name);
component.Owner = entity;
entity.AddComponent(component);
}
ObjectSerializer ser;
if (context != null)
{
ser = context.GetComponentSerializer(name, data);
ObjectSerializer ser;
if (context != null)
{
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)
@@ -436,12 +461,12 @@ namespace Robust.Shared.GameObjects
// Components that have been ADDED NEW need to be handled too.
foreach (var name in context.GetExtraComponentTypes())
{
if (Components.ContainsKey(name))
if ((prototype != null && prototype.Components.ContainsKey(name)) || name == "Transform" || name == "Metadata")
{
continue;
}
var component = (Component)factory.GetComponent(name);
var component = (Component) factory.GetComponent(name);
component.Owner = entity;
var ser = context.GetComponentSerializer(name, null);
component.ExposeData(ser);
@@ -496,6 +521,7 @@ namespace Robust.Shared.GameObjects
base.SetCachedField<T>(field, value);
return;
}
if (!prototype.FieldCache.TryGetValue(prototype.CurrentDeserializingComponent, out var fieldList))
{
fieldList = new Dictionary<(string, Type), object>();
@@ -511,11 +537,12 @@ namespace Robust.Shared.GameObjects
{
return base.TryGetCachedField<T>(field, out value);
}
if (prototype.FieldCache.TryGetValue(prototype.CurrentDeserializingComponent, out var dict))
{
if (dict.TryGetValue((field, typeof(T)), out var theValue))
{
value = (T)theValue;
value = (T) theValue;
return true;
}
}
@@ -531,6 +558,7 @@ namespace Robust.Shared.GameObjects
base.SetDataCache(field, value);
return;
}
prototype.DataCache[field] = value;
}
@@ -540,6 +568,7 @@ namespace Robust.Shared.GameObjects
{
return base.TryGetDataCache(field, out value);
}
return prototype.DataCache.TryGetValue(field, out value);
}
}

View File

@@ -38,6 +38,7 @@ namespace Robust.Shared
IoCManager.Register<ILocalizationManager, LocalizationManager>();
IoCManager.Register<ILogManager, LogManager>();
IoCManager.Register<IMapManager, MapManager>();
IoCManager.Register<IMapManagerInternal, MapManager>();
IoCManager.Register<IModLoader, ModLoader>();
IoCManager.Register<INetManager, NetManager>();
IoCManager.Register<IPhysicsManager, PhysicsManager>();

View File

@@ -68,16 +68,16 @@ namespace Robust.UnitTesting.Client.GameObjects.Components
var parentTrans = parent.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);
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);
// World pos should be 6, 6 now.
// Act
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);
var newWpos = childTrans.WorldPosition;
@@ -105,11 +105,11 @@ namespace Robust.UnitTesting.Client.GameObjects.Components
var node2Trans = node2.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);
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);
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);
// Act

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).
* `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.
* `worldpos`: Position in the world of this grid.
* `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
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.