Prevent ghosts from spawning on terminating maps/grids (#28099)
* Extra checks to prevent ghosts spawning on terminating maps/grids * Add test for grid deletion
This commit is contained in:
@@ -156,4 +156,20 @@ public sealed class GhostTests
|
|||||||
await data.Pair.CleanReturnAsync();
|
await data.Pair.CleanReturnAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task TestGhostGridNotTerminating()
|
||||||
|
{
|
||||||
|
var data = await SetupData();
|
||||||
|
|
||||||
|
Assert.DoesNotThrowAsync(async () =>
|
||||||
|
{
|
||||||
|
// Delete the grid
|
||||||
|
await data.Server.WaitPost(() => data.SEntMan.DeleteEntity(data.MapData.Grid.Owner));
|
||||||
|
});
|
||||||
|
|
||||||
|
await data.Pair.RunTicksSync(5);
|
||||||
|
|
||||||
|
await data.Pair.CleanReturnAsync();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -369,11 +369,16 @@ namespace Content.Server.GameTicking
|
|||||||
public EntityCoordinates GetObserverSpawnPoint()
|
public EntityCoordinates GetObserverSpawnPoint()
|
||||||
{
|
{
|
||||||
_possiblePositions.Clear();
|
_possiblePositions.Clear();
|
||||||
|
var spawnPointQuery = EntityManager.EntityQueryEnumerator<SpawnPointComponent, TransformComponent>();
|
||||||
foreach (var (point, transform) in EntityManager.EntityQuery<SpawnPointComponent, TransformComponent>(true))
|
while (spawnPointQuery.MoveNext(out var uid, out var point, out var transform))
|
||||||
{
|
{
|
||||||
if (point.SpawnType != SpawnPointType.Observer)
|
if (point.SpawnType != SpawnPointType.Observer
|
||||||
|
|| TerminatingOrDeleted(uid)
|
||||||
|
|| transform.MapUid == null
|
||||||
|
|| TerminatingOrDeleted(transform.MapUid.Value))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
_possiblePositions.Add(transform.Coordinates);
|
_possiblePositions.Add(transform.Coordinates);
|
||||||
}
|
}
|
||||||
@@ -415,7 +420,9 @@ namespace Content.Server.GameTicking
|
|||||||
|
|
||||||
if (_mapManager.MapExists(DefaultMap))
|
if (_mapManager.MapExists(DefaultMap))
|
||||||
{
|
{
|
||||||
return new EntityCoordinates(_mapManager.GetMapEntityId(DefaultMap), Vector2.Zero);
|
var mapUid = _mapManager.GetMapEntityId(DefaultMap);
|
||||||
|
if (!TerminatingOrDeleted(mapUid))
|
||||||
|
return new EntityCoordinates(mapUid, Vector2.Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Just pick a point at this point I guess.
|
// Just pick a point at this point I guess.
|
||||||
|
|||||||
@@ -409,23 +409,41 @@ namespace Content.Server.Ghost
|
|||||||
return SpawnGhost(mind, spawnPosition, canReturn);
|
return SpawnGhost(mind, spawnPosition, canReturn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsValidSpawnPosition(EntityCoordinates? spawnPosition)
|
||||||
|
{
|
||||||
|
if (spawnPosition?.IsValid(EntityManager) != true)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var mapUid = spawnPosition?.GetMapUid(EntityManager);
|
||||||
|
var gridUid = spawnPosition?.EntityId;
|
||||||
|
// Test if the map is being deleted
|
||||||
|
if (mapUid == null || TerminatingOrDeleted(mapUid.Value))
|
||||||
|
return false;
|
||||||
|
// Test if the grid is being deleted
|
||||||
|
if (gridUid != null && TerminatingOrDeleted(gridUid.Value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public EntityUid? SpawnGhost(Entity<MindComponent?> mind, EntityCoordinates? spawnPosition = null,
|
public EntityUid? SpawnGhost(Entity<MindComponent?> mind, EntityCoordinates? spawnPosition = null,
|
||||||
bool canReturn = false)
|
bool canReturn = false)
|
||||||
{
|
{
|
||||||
if (!Resolve(mind, ref mind.Comp))
|
if (!Resolve(mind, ref mind.Comp))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// Test if the map is being deleted
|
// Test if the map or grid is being deleted
|
||||||
var mapUid = spawnPosition?.GetMapUid(EntityManager);
|
if (!IsValidSpawnPosition(spawnPosition))
|
||||||
if (mapUid == null || TerminatingOrDeleted(mapUid.Value))
|
|
||||||
spawnPosition = null;
|
spawnPosition = null;
|
||||||
|
|
||||||
|
// If it's bad, look for a valid point to spawn
|
||||||
spawnPosition ??= _ticker.GetObserverSpawnPoint();
|
spawnPosition ??= _ticker.GetObserverSpawnPoint();
|
||||||
|
|
||||||
if (!spawnPosition.Value.IsValid(EntityManager))
|
// Make sure the new point is valid too
|
||||||
|
if (!IsValidSpawnPosition(spawnPosition))
|
||||||
{
|
{
|
||||||
Log.Warning($"No spawn valid ghost spawn position found for {mind.Comp.CharacterName}"
|
Log.Warning($"No spawn valid ghost spawn position found for {mind.Comp.CharacterName}"
|
||||||
+ " \"{ToPrettyString(mind)}\"");
|
+ $" \"{ToPrettyString(mind)}\"");
|
||||||
_minds.TransferTo(mind.Owner, null, createGhost: false, mind: mind.Comp);
|
_minds.TransferTo(mind.Owner, null, createGhost: false, mind: mind.Comp);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user