]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Prevent ghosts from spawning on terminating maps/grids (#28099)
authorTayrtahn <tayrtahn@gmail.com>
Mon, 20 May 2024 13:52:49 +0000 (09:52 -0400)
committerGitHub <noreply@github.com>
Mon, 20 May 2024 13:52:49 +0000 (06:52 -0700)
* Extra checks to prevent ghosts spawning on terminating maps/grids

* Add test for grid deletion

Content.IntegrationTests/Tests/Minds/GhostTests.cs
Content.Server/GameTicking/GameTicker.Spawning.cs
Content.Server/Ghost/GhostSystem.cs

index ad9d53a70dbfa0f9d2e01728820f75d7b2b96533..7a156e71e419e4f9aa41aa80c55b44c0018f8d67 100644 (file)
@@ -156,4 +156,20 @@ public sealed class GhostTests
         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();
+    }
+
 }
index 74785603799bf1c6ae90d51670deede1383f2af5..843122e0feaa3ac8d3c44b5bbe92f9fb8c303fea 100644 (file)
@@ -369,11 +369,16 @@ namespace Content.Server.GameTicking
         public EntityCoordinates GetObserverSpawnPoint()
         {
             _possiblePositions.Clear();
-
-            foreach (var (point, transform) in EntityManager.EntityQuery<SpawnPointComponent, TransformComponent>(true))
+            var spawnPointQuery = EntityManager.EntityQueryEnumerator<SpawnPointComponent, TransformComponent>();
+            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;
+                }
 
                 _possiblePositions.Add(transform.Coordinates);
             }
@@ -415,7 +420,9 @@ namespace Content.Server.GameTicking
 
             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.
index f4e6a4d607da1602dba40b22cd432b173bbc24b2..6c3d69fea7f1a18d57bf1289450837c159d7b0c5 100644 (file)
@@ -409,23 +409,41 @@ namespace Content.Server.Ghost
             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,
             bool canReturn = false)
         {
             if (!Resolve(mind, ref mind.Comp))
                 return null;
 
-            // Test if the map is being deleted
-            var mapUid = spawnPosition?.GetMapUid(EntityManager);
-            if (mapUid == null || TerminatingOrDeleted(mapUid.Value))
+            // Test if the map or grid is being deleted
+            if (!IsValidSpawnPosition(spawnPosition))
                 spawnPosition = null;
 
+            // If it's bad, look for a valid point to spawn
             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}"
-                    + " \"{ToPrettyString(mind)}\"");
+                    + $" \"{ToPrettyString(mind)}\"");
                 _minds.TransferTo(mind.Owner, null, createGhost: false, mind: mind.Comp);
                 return null;
             }