mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-14 19:29:36 +01:00
Update map loader to work with grid entities.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user