mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
TransformComponent.GridID now returns GridID.Nullspace instead of throwing when the entity in question is not on a grid.
Added MapManager.Restart(). Added MapManager.CreateNewMapEntity() and MapManager.SetMapEntity() for manipulating the map root entity. You can now spawn entities directly into Nullspace, after setting up the Nullspace map entity.
This commit is contained in:
@@ -186,6 +186,11 @@ namespace Robust.Client.GameObjects
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
public override IEntity CreateEntityUninitialized(string prototypeName)
|
||||
{
|
||||
return CreateEntity(prototypeName);
|
||||
}
|
||||
|
||||
public override IEntity CreateEntityUninitialized(string prototypeName, GridCoordinates coordinates)
|
||||
{
|
||||
var newEntity = CreateEntity(prototypeName, NewClientEntityUid());
|
||||
@@ -226,6 +231,15 @@ namespace Robust.Client.GameObjects
|
||||
return SpawnEntity(entityType, coordinates);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEntity SpawnEntityAt(string entityType, MapCoordinates coordinates)
|
||||
{
|
||||
var grid = _mapManager.FindGridAt(coordinates);
|
||||
var gridCoords = new GridCoordinates(grid.WorldToLocal(coordinates.Position), grid);
|
||||
|
||||
return SpawnEntityAt(entityType, gridCoords);
|
||||
}
|
||||
|
||||
private EntityUid NewClientEntityUid()
|
||||
{
|
||||
return new EntityUid(NextClientEntityUid++);
|
||||
|
||||
@@ -27,6 +27,11 @@ namespace Robust.Server.GameObjects
|
||||
|
||||
private readonly List<(GameTick tick, EntityUid uid)> DeletionHistory = new List<(GameTick, EntityUid)>();
|
||||
|
||||
public override IEntity CreateEntityUninitialized(string prototypeName)
|
||||
{
|
||||
return CreateEntity(prototypeName);
|
||||
}
|
||||
|
||||
public override IEntity CreateEntityUninitialized(string prototypeName, GridCoordinates coordinates)
|
||||
{
|
||||
var newEntity = CreateEntity(prototypeName);
|
||||
@@ -42,11 +47,8 @@ namespace Robust.Server.GameObjects
|
||||
public override IEntity CreateEntityUninitialized(string prototypeName, MapCoordinates coordinates)
|
||||
{
|
||||
var newEntity = CreateEntity(prototypeName);
|
||||
if(coordinates.MapId != MapId.Nullspace)
|
||||
{
|
||||
newEntity.Transform.AttachParent(_mapManager.GetMapEntity(coordinates.MapId));
|
||||
newEntity.Transform.WorldPosition = coordinates.Position;
|
||||
}
|
||||
newEntity.Transform.AttachParent(_mapManager.GetMapEntity(coordinates.MapId));
|
||||
newEntity.Transform.WorldPosition = coordinates.Position;
|
||||
return newEntity;
|
||||
}
|
||||
|
||||
@@ -77,6 +79,14 @@ namespace Robust.Server.GameObjects
|
||||
return entity;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEntity SpawnEntityAt(string entityType, MapCoordinates coordinates)
|
||||
{
|
||||
var entity = CreateEntityUninitialized(entityType, coordinates);
|
||||
InitializeAndStartEntity((Entity)entity);
|
||||
return entity;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public List<EntityState> GetEntityStates(GameTick fromTick)
|
||||
{
|
||||
|
||||
@@ -37,12 +37,12 @@ namespace Robust.Shared.GameObjects.Components.Map
|
||||
internal set => _mapIndex = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ClearMapId()
|
||||
{
|
||||
_mapIndex = MapId.Nullspace;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public override ComponentState GetComponentState()
|
||||
{
|
||||
|
||||
@@ -88,7 +88,8 @@ namespace Robust.Shared.GameObjects.Components.Transform
|
||||
if (_parent.IsValid())
|
||||
return Parent.GridID;
|
||||
|
||||
throw new InvalidOperationException("Transform node does not exist inside scene tree!");
|
||||
// Not on a grid
|
||||
return GridId.Nullspace;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,6 +314,17 @@ namespace Robust.Shared.GameObjects.Components.Transform
|
||||
/// <inheritdoc />
|
||||
public Vector2 LerpDestination => _nextPosition;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
// Verifies MapID can be resolved.
|
||||
// If it cannot, then this is an orphan entity, and an exception will be thrown.
|
||||
// DO NOT REMOVE THIS LINE
|
||||
var _ = MapID;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Startup()
|
||||
{
|
||||
|
||||
@@ -106,6 +106,8 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
#region Entity Management
|
||||
|
||||
public abstract IEntity CreateEntityUninitialized(string prototypeName);
|
||||
|
||||
public abstract IEntity CreateEntityUninitialized(string prototypeName, GridCoordinates coordinates);
|
||||
|
||||
public abstract IEntity CreateEntityUninitialized(string prototypeName, MapCoordinates coordinates);
|
||||
@@ -115,13 +117,7 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
public abstract IEntity SpawnEntityAt(string entityType, GridCoordinates coordinates);
|
||||
|
||||
public IEntity SpawnEntityAt(string entityType, MapCoordinates coordinates)
|
||||
{
|
||||
var grid = _mapManager.FindGridAt(coordinates);
|
||||
var gridCoords = new GridCoordinates(grid.WorldToLocal(coordinates.Position), grid);
|
||||
|
||||
return SpawnEntityAt(entityType, gridCoords);
|
||||
}
|
||||
public abstract IEntity SpawnEntityAt(string entityType, MapCoordinates coordinates);
|
||||
|
||||
/// <summary>
|
||||
/// Returns an entity by id
|
||||
|
||||
@@ -31,6 +31,8 @@ namespace Robust.Shared.Interfaces.GameObjects
|
||||
|
||||
#region Entity Management
|
||||
|
||||
IEntity CreateEntityUninitialized(string prototypeName);
|
||||
|
||||
IEntity CreateEntityUninitialized(string prototypeName, GridCoordinates coordinates);
|
||||
|
||||
IEntity CreateEntityUninitialized(string prototypeName, MapCoordinates coordinates);
|
||||
|
||||
@@ -45,6 +45,8 @@ namespace Robust.Shared.Interfaces.Map
|
||||
void Shutdown();
|
||||
void Startup();
|
||||
|
||||
void Restart();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new map.
|
||||
/// </summary>
|
||||
@@ -68,6 +70,24 @@ namespace Robust.Shared.Interfaces.Map
|
||||
/// <returns>True if the map exists, false otherwise.</returns>
|
||||
bool MapExists(MapId mapID);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new entity, then sets it as the map entity.
|
||||
/// </summary>
|
||||
/// <returns>Newly created entity.</returns>
|
||||
IEntity CreateNewMapEntity(MapId mapId);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the MapEntity(root node) for a given map. If an entity is already set, it will be deleted
|
||||
/// before the new one is set.
|
||||
/// </summary>
|
||||
void SetMapEntity(MapId mapId, EntityUid newMapEntityId);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the MapEntity(root node) for a given map. If an entity is already set, it will be deleted
|
||||
/// before the new one is set.
|
||||
/// </summary>
|
||||
void SetMapEntity(MapId mapId, IEntity newMapEntity);
|
||||
|
||||
EntityUid GetMapEntityId(MapId mapId);
|
||||
IEntity GetMapEntity(MapId mapId);
|
||||
|
||||
|
||||
@@ -89,6 +89,39 @@ namespace Robust.Shared.Map
|
||||
DebugTools.Assert(_grids.Count == 1);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Restart()
|
||||
{
|
||||
foreach (var mapId in _maps.ToArray())
|
||||
{
|
||||
if (mapId != MapId.Nullspace)
|
||||
{
|
||||
DeleteMap(mapId);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_maps.Contains(MapId.Nullspace))
|
||||
{
|
||||
CreateMap(MapId.Nullspace, GridId.Nullspace);
|
||||
}
|
||||
else if(_mapEntities.TryGetValue(MapId.Nullspace, out var mapEntId))
|
||||
{
|
||||
var mapEnt = _entityManager.GetEntity(mapEntId);
|
||||
var defaultGridId = _defaultGrids[MapId.Nullspace];
|
||||
var defaultGridEntityId = GetGrid(defaultGridId).GridEntity;
|
||||
foreach (var childTransform in mapEnt.Transform.Children.ToArray())
|
||||
{
|
||||
if(childTransform.Owner.Uid == defaultGridEntityId)
|
||||
continue;
|
||||
|
||||
childTransform.Owner.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
DebugTools.Assert(_grids.Count == 1);
|
||||
DebugTools.Assert(GridExists(GridId.Nullspace));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the OnTileChanged event.
|
||||
/// </summary>
|
||||
@@ -214,6 +247,62 @@ namespace Robust.Shared.Map
|
||||
return _maps.Contains(mapID);
|
||||
}
|
||||
|
||||
public IEntity CreateNewMapEntity(MapId mapId)
|
||||
{
|
||||
var newEntity = _entityManager.CreateEntityUninitialized(null);
|
||||
SetMapEntity(mapId, newEntity);
|
||||
return newEntity;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SetMapEntity(MapId mapId, EntityUid newMapEntityId)
|
||||
{
|
||||
var newMapEntity = _entityManager.GetEntity(newMapEntityId);
|
||||
SetMapEntity(mapId, newMapEntity);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SetMapEntity(MapId mapId, IEntity newMapEntity)
|
||||
{
|
||||
if(!_maps.Contains(mapId))
|
||||
throw new InvalidOperationException($"Map {mapId} does not exist.");
|
||||
|
||||
foreach (var kvEntity in _mapEntities)
|
||||
{
|
||||
if (kvEntity.Value == newMapEntity.Uid)
|
||||
{
|
||||
throw new InvalidOperationException($"Entity {newMapEntity} is already the root node of map {kvEntity.Key}.");
|
||||
}
|
||||
}
|
||||
|
||||
// remove existing graph
|
||||
if (_mapEntities.TryGetValue(mapId, out var oldEntId))
|
||||
{
|
||||
//Note: This prevents setting a subgraph as the root, since the subgraph will be deleted
|
||||
var oldMapEnt = _entityManager.GetEntity(oldEntId);
|
||||
_entityManager.DeleteEntity(oldMapEnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
_mapEntities.Add(mapId, EntityUid.Invalid);
|
||||
}
|
||||
|
||||
// re-use or add map component
|
||||
if (!newMapEntity.TryGetComponent(out MapComponent mapComp))
|
||||
{
|
||||
mapComp = newMapEntity.AddComponent<MapComponent>();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mapComp.WorldMap != mapId)
|
||||
Logger.WarningS("map", $"Setting map {mapId} root to entity {newMapEntity}, but entity thinks it is root node of map {mapComp.WorldMap}.");
|
||||
}
|
||||
|
||||
// set as new map entity
|
||||
mapComp.WorldMap = mapId;
|
||||
_mapEntities[mapId] = newMapEntity.Uid;
|
||||
}
|
||||
|
||||
public EntityUid GetMapEntityId(MapId mapId)
|
||||
{
|
||||
return _mapEntities[mapId];
|
||||
@@ -221,6 +310,9 @@ namespace Robust.Shared.Map
|
||||
|
||||
public IEntity GetMapEntity(MapId mapId)
|
||||
{
|
||||
if(!_mapEntities.ContainsKey(mapId))
|
||||
throw new InvalidOperationException($"Map {mapId} does not have a set map entity.");
|
||||
|
||||
return _entityManager.GetEntity(_mapEntities[mapId]);
|
||||
}
|
||||
|
||||
|
||||
125
Robust.UnitTesting/Shared/Map/MapManager_Tests.cs
Normal file
125
Robust.UnitTesting/Shared/Map/MapManager_Tests.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
using NUnit.Framework;
|
||||
using Robust.Server.Interfaces.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components.Map;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Map;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Robust.UnitTesting.Shared.Map
|
||||
{
|
||||
[TestFixture, TestOf(typeof(MapManager))]
|
||||
class MapManager_Tests : RobustUnitTest
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
var mapMan = IoCManager.Resolve<IMapManager>();
|
||||
mapMan.Restart();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When the map manager is restarted, the maps are deleted.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Restart_ExistingMap_IsRemoved()
|
||||
{
|
||||
var mapMan = IoCManager.Resolve<IMapManager>();
|
||||
|
||||
var mapID = new MapId(11);
|
||||
mapMan.CreateMap(mapID);
|
||||
|
||||
mapMan.Restart();
|
||||
|
||||
Assert.That(mapMan.MapExists(mapID), Is.False);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When the map manager is restarted, the grids are removed.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Restart_ExistingGrid_IsRemoved()
|
||||
{
|
||||
var mapMan = IoCManager.Resolve<IMapManager>();
|
||||
|
||||
var mapID = new MapId(11);
|
||||
var gridId = new GridId(7);
|
||||
mapMan.CreateMap(mapID);
|
||||
mapMan.CreateGrid(mapID, gridId);
|
||||
|
||||
mapMan.Restart();
|
||||
|
||||
Assert.That(mapMan.GridExists(gridId), Is.False);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When the map manager is restarted, Nullspace is recreated.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Restart_NullspaceMap_IsEmptied()
|
||||
{
|
||||
var mapMan = IoCManager.Resolve<IMapManager>();
|
||||
var entMan = IoCManager.Resolve<IServerEntityManager>();
|
||||
|
||||
mapMan.CreateNewMapEntity(MapId.Nullspace);
|
||||
|
||||
var oldEntity = (Entity)entMan.CreateEntityUninitialized(null, new MapCoordinates(Vector2.Zero, MapId.Nullspace));
|
||||
oldEntity.InitializeComponents();
|
||||
|
||||
mapMan.Restart();
|
||||
|
||||
Assert.That(mapMan.MapExists(MapId.Nullspace), Is.True);
|
||||
Assert.That(mapMan.GridExists(GridId.Nullspace), Is.True);
|
||||
Assert.That(oldEntity.Deleted, Is.True);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When using SetMapEntity, the existing entities on the map are removed, and the new map entity gets a IMapComponent.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void SetMapEntity_WithExistingEntity_ExistingEntityDeleted()
|
||||
{
|
||||
// Arrange
|
||||
var mapID = new MapId(11);
|
||||
var mapMan = IoCManager.Resolve<IMapManager>();
|
||||
var entMan = IoCManager.Resolve<IServerEntityManager>();
|
||||
|
||||
mapMan.CreateMap(new MapId(7));
|
||||
mapMan.CreateMap(mapID);
|
||||
var oldMapEntity = mapMan.GetMapEntity(mapID);
|
||||
var newMapEntity = entMan.CreateEntityUninitialized(null, new MapCoordinates(Vector2.Zero, new MapId(7)));
|
||||
|
||||
// Act
|
||||
mapMan.SetMapEntity(mapID, newMapEntity);
|
||||
|
||||
// Assert
|
||||
Assert.That(oldMapEntity.Deleted);
|
||||
Assert.That(newMapEntity.HasComponent<IMapComponent>());
|
||||
|
||||
var mapComp = newMapEntity.GetComponent<IMapComponent>();
|
||||
Assert.That(mapComp.WorldMap == mapID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// After creating a new map entity for nullspace, you can spawn entities into nullspace like any other map.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void SpawnEntityAt_IntoNullspace_Success()
|
||||
{
|
||||
// Arrange
|
||||
var mapMan = IoCManager.Resolve<IMapManager>();
|
||||
var entMan = IoCManager.Resolve<IEntityManager>();
|
||||
|
||||
mapMan.CreateNewMapEntity(MapId.Nullspace);
|
||||
|
||||
// Act
|
||||
var newEntity = entMan.SpawnEntityAt(null, new MapCoordinates(Vector2.Zero, MapId.Nullspace));
|
||||
|
||||
// Assert
|
||||
Assert.That(newEntity.Transform.MapID, Is.EqualTo(MapId.Nullspace));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user