diff --git a/Content.Server/Procedural/DungeonJob.PostGen.cs b/Content.Server/Procedural/DungeonJob.PostGen.cs index f0c96e490d..1bbcc438ef 100644 --- a/Content.Server/Procedural/DungeonJob.PostGen.cs +++ b/Content.Server/Procedural/DungeonJob.PostGen.cs @@ -23,9 +23,6 @@ public sealed partial class DungeonJob * Run after the main dungeon generation */ - private const int CollisionMask = (int) CollisionGroup.Impassable; - private const int CollisionLayer = (int) CollisionGroup.Impassable; - private bool HasWall(MapGridComponent grid, Vector2i tile) { var anchored = grid.GetAnchoredEntitiesEnumerator(tile); @@ -194,7 +191,7 @@ public sealed partial class DungeonJob if (dungeon.RoomTiles.Contains(neighbor)) continue; - if (!_anchorable.TileFree(grid, neighbor, CollisionLayer, CollisionMask)) + if (!_anchorable.TileFree(grid, neighbor, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask)) continue; tiles.Add((neighbor, _tileDefManager.GetVariantTile(tileDef, random))); @@ -205,7 +202,7 @@ public sealed partial class DungeonJob if (dungeon.RoomTiles.Contains(index)) continue; - if (!_anchorable.TileFree(grid, index, CollisionLayer, CollisionMask)) + if (!_anchorable.TileFree(grid, index, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask)) continue; tiles.Add((index, _tileDefManager.GetVariantTile(tileDef, random))); @@ -217,7 +214,7 @@ public sealed partial class DungeonJob for (var i = 0; i < tiles.Count; i++) { var index = tiles[i]; - if (!_anchorable.TileFree(grid, index.Index, CollisionLayer, CollisionMask)) + if (!_anchorable.TileFree(grid, index.Index, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask)) continue; // If no cardinal neighbors in dungeon then we're a corner. @@ -469,13 +466,13 @@ public sealed partial class DungeonJob } // Check if exterior spot free. - if (!_anchorable.TileFree(_grid, tile, CollisionLayer, CollisionMask)) + if (!_anchorable.TileFree(_grid, tile, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask)) { continue; } // Check if interior spot free (no guarantees on exterior but ClearDoor should handle it) - if (!_anchorable.TileFree(_grid, dirVec, CollisionLayer, CollisionMask)) + if (!_anchorable.TileFree(_grid, dirVec, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask)) { continue; } @@ -542,7 +539,7 @@ public sealed partial class DungeonJob break; // Room tile / already used. - if (!_anchorable.TileFree(_grid, tile, CollisionLayer, CollisionMask) || + if (!_anchorable.TileFree(_grid, tile, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask) || takenTiles.Contains(tile)) { continue; @@ -562,7 +559,7 @@ public sealed partial class DungeonJob if (!allExterior.Contains(neighbor) || takenTiles.Contains(neighbor) || - !_anchorable.TileFree(grid, neighbor, CollisionLayer, CollisionMask)) + !_anchorable.TileFree(grid, neighbor, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask)) { isValid = false; break; @@ -577,7 +574,7 @@ public sealed partial class DungeonJob if (allExterior.Contains(perpTile) || takenTiles.Contains(neighbor) || - !_anchorable.TileFree(_grid, perpTile, CollisionLayer, CollisionMask)) + !_anchorable.TileFree(_grid, perpTile, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask)) { isValid = false; break; @@ -684,7 +681,7 @@ public sealed partial class DungeonJob var windowTile = tile + dirVec; - if (!_anchorable.TileFree(grid, windowTile, CollisionLayer, CollisionMask)) + if (!_anchorable.TileFree(grid, windowTile, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask)) continue; validTiles.Add(windowTile); @@ -930,7 +927,7 @@ public sealed partial class DungeonJob // N-wide junctions foreach (var tile in dungeon.CorridorTiles) { - if (!_anchorable.TileFree(_grid, tile, CollisionLayer, CollisionMask)) + if (!_anchorable.TileFree(_grid, tile, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask)) continue; // Check each direction: @@ -967,7 +964,7 @@ public sealed partial class DungeonJob } // If we're not at the end tile then check it + perpendicular are free. - if (!_anchorable.TileFree(_grid, neighbor, CollisionLayer, CollisionMask)) + if (!_anchorable.TileFree(_grid, neighbor, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask)) { isValid = false; break; @@ -976,13 +973,13 @@ public sealed partial class DungeonJob var perp1 = tile + neighborVec * j + ((Direction) ((i * 2 + 2) % 8)).ToIntVec(); var perp2 = tile + neighborVec * j + ((Direction) ((i * 2 + 6) % 8)).ToIntVec(); - if (!_anchorable.TileFree(_grid, perp1, CollisionLayer, CollisionMask)) + if (!_anchorable.TileFree(_grid, perp1, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask)) { isValid = false; break; } - if (!_anchorable.TileFree(_grid, perp2, CollisionLayer, CollisionMask)) + if (!_anchorable.TileFree(_grid, perp2, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask)) { isValid = false; break; @@ -1004,7 +1001,7 @@ public sealed partial class DungeonJob var cornerVec = cornerDir.ToIntVec(); var cornerNeighbor = tile + neighborVec * j + cornerVec; - if (_anchorable.TileFree(_grid, cornerNeighbor, CollisionLayer, CollisionMask)) + if (_anchorable.TileFree(_grid, cornerNeighbor, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask)) { freeCount++; } @@ -1071,7 +1068,7 @@ public sealed partial class DungeonJob if (dungeon.RoomTiles.Contains(neighbor)) continue; - if (!_anchorable.TileFree(grid, neighbor, CollisionLayer, CollisionMask)) + if (!_anchorable.TileFree(grid, neighbor, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask)) continue; roomEdges.Add(neighbor); @@ -1133,7 +1130,7 @@ public sealed partial class DungeonJob { var node = nodeDistances[i].Node; var gridPos = grid.GridTileToLocal(node); - if (!_anchorable.TileFree(grid, node, CollisionLayer, CollisionMask)) + if (!_anchorable.TileFree(grid, node, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask)) continue; width--; @@ -1193,8 +1190,8 @@ public sealed partial class DungeonJob { if (!physicsQuery.TryGetComponent(ent, out var physics) || !physics.Hard || - (CollisionMask & physics.CollisionLayer) == 0x0 && - (CollisionLayer & physics.CollisionMask) == 0x0) + (DungeonSystem.CollisionMask & physics.CollisionLayer) == 0x0 && + (DungeonSystem.CollisionLayer & physics.CollisionMask) == 0x0) { continue; } @@ -1217,7 +1214,7 @@ public sealed partial class DungeonJob foreach (var neighbor in allExterior) { // Occupado - if (dungeon.RoomTiles.Contains(neighbor) || checkedTiles.Contains(neighbor) || !_anchorable.TileFree(grid, neighbor, CollisionLayer, CollisionMask)) + if (dungeon.RoomTiles.Contains(neighbor) || checkedTiles.Contains(neighbor) || !_anchorable.TileFree(grid, neighbor, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask)) continue; if (!random.Prob(gen.Prob) || !checkedTiles.Add(neighbor)) diff --git a/Content.Server/Procedural/DungeonSystem.cs b/Content.Server/Procedural/DungeonSystem.cs index e7ffc4fc02..0fb343cdfc 100644 --- a/Content.Server/Procedural/DungeonSystem.cs +++ b/Content.Server/Procedural/DungeonSystem.cs @@ -6,6 +6,7 @@ using Content.Server.Decals; using Content.Server.GameTicking.Events; using Content.Shared.CCVar; using Content.Shared.Construction.EntitySystems; +using Content.Shared.Physics; using Content.Shared.Procedural; using Robust.Server.GameObjects; using Robust.Shared.Configuration; @@ -33,6 +34,9 @@ public sealed partial class DungeonSystem : SharedDungeonSystem private const double DungeonJobTime = 0.005; + public const int CollisionMask = (int) CollisionGroup.Impassable; + public const int CollisionLayer = (int) CollisionGroup.Impassable; + private readonly JobQueue _dungeonJobQueue = new(DungeonJobTime); private readonly Dictionary _dungeonJobs = new(); diff --git a/Content.Server/Salvage/SalvageSystem.Expeditions.cs b/Content.Server/Salvage/SalvageSystem.Expeditions.cs index d074812624..9568fbfe6f 100644 --- a/Content.Server/Salvage/SalvageSystem.Expeditions.cs +++ b/Content.Server/Salvage/SalvageSystem.Expeditions.cs @@ -20,8 +20,6 @@ public sealed partial class SalvageSystem * Handles setup / teardown of salvage expeditions. */ - [Dependency] private readonly CargoSystem _cargo = default!; - private const int MissionLimit = 5; private readonly JobQueue _salvageQueue = new(); @@ -269,7 +267,7 @@ public sealed partial class SalvageSystem _timing, _mapManager, _prototypeManager, - _tileDefManager, + _anchorable, _biome, _dungeon, this, diff --git a/Content.Server/Salvage/SalvageSystem.cs b/Content.Server/Salvage/SalvageSystem.cs index cccc81a239..678a36c2c5 100644 --- a/Content.Server/Salvage/SalvageSystem.cs +++ b/Content.Server/Salvage/SalvageSystem.cs @@ -1,5 +1,6 @@ using System.Linq; using System.Numerics; +using Content.Server.Cargo.Systems; using Content.Server.Construction; using Content.Server.GameTicking; using Content.Server.Radio.EntitySystems; @@ -21,6 +22,7 @@ using Content.Server.Procedural; using Content.Server.Shuttles.Systems; using Content.Server.Station.Systems; using Content.Shared.CCVar; +using Content.Shared.Construction.EntitySystems; using Content.Shared.Random; using Content.Shared.Random.Helpers; using Robust.Server.Maps; @@ -37,8 +39,9 @@ namespace Content.Server.Salvage [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IRobustRandom _random = default!; - [Dependency] private readonly ITileDefinitionManager _tileDefManager = default!; + [Dependency] private readonly AnchorableSystem _anchorable = default!; [Dependency] private readonly BiomeSystem _biome = default!; + [Dependency] private readonly CargoSystem _cargo = default!; [Dependency] private readonly DungeonSystem _dungeon = default!; [Dependency] private readonly MapLoaderSystem _map = default!; [Dependency] private readonly SharedPopupSystem _popupSystem = default!; diff --git a/Content.Server/Salvage/SpawnSalvageMissionJob.cs b/Content.Server/Salvage/SpawnSalvageMissionJob.cs index 949ae834ec..2fa4df1bdf 100644 --- a/Content.Server/Salvage/SpawnSalvageMissionJob.cs +++ b/Content.Server/Salvage/SpawnSalvageMissionJob.cs @@ -12,25 +12,23 @@ using Content.Server.Procedural; using Content.Server.Salvage.Expeditions; using Content.Server.Salvage.Expeditions.Structure; using Content.Shared.Atmos; +using Content.Shared.Construction.EntitySystems; using Content.Shared.Dataset; using Content.Shared.Gravity; using Content.Shared.Parallax.Biomes; -using Content.Shared.Parallax.Biomes.Markers; +using Content.Shared.Physics; using Content.Shared.Procedural; using Content.Shared.Procedural.Loot; -using Content.Shared.Random; -using Content.Shared.Random.Helpers; using Content.Shared.Salvage; using Content.Shared.Salvage.Expeditions; using Content.Shared.Salvage.Expeditions.Modifiers; using Content.Shared.Storage; +using Robust.Shared.Collections; using Robust.Shared.Map; using Robust.Shared.Map.Components; -using Robust.Shared.Noise; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Timing; -using Robust.Shared.Utility; namespace Content.Server.Salvage; @@ -40,7 +38,7 @@ public sealed class SpawnSalvageMissionJob : Job private readonly IGameTiming _timing; private readonly IMapManager _mapManager; private readonly IPrototypeManager _prototypeManager; - private readonly ITileDefinitionManager _tileDefManager; + private readonly AnchorableSystem _anchorable; private readonly BiomeSystem _biome; private readonly DungeonSystem _dungeon; private readonly SalvageSystem _salvage; @@ -54,7 +52,7 @@ public sealed class SpawnSalvageMissionJob : Job IGameTiming timing, IMapManager mapManager, IPrototypeManager protoManager, - ITileDefinitionManager tileDefManager, + AnchorableSystem anchorable, BiomeSystem biome, DungeonSystem dungeon, SalvageSystem salvage, @@ -66,7 +64,7 @@ public sealed class SpawnSalvageMissionJob : Job _timing = timing; _mapManager = mapManager; _prototypeManager = protoManager; - _tileDefManager = tileDefManager; + _anchorable = anchorable; _biome = biome; _dungeon = dungeon; _salvage = salvage; @@ -314,6 +312,7 @@ public sealed class SpawnSalvageMissionJob : Job // scale affects how many groups are spawned, not the size of the groups themselves var groupSpawns = _salvage.GetSpawnCount(mission.Difficulty) * scale; var groupSum = faction.MobGroups.Sum(o => o.Prob); + var validSpawns = new List(); for (var i = 0; i < groupSpawns; i++) { @@ -332,15 +331,31 @@ public sealed class SpawnSalvageMissionJob : Job var spawnRoomIndex = random.Next(dungeon.Rooms.Count); var spawnRoom = dungeon.Rooms[spawnRoomIndex]; - var spawnTile = spawnRoom.Tiles.ElementAt(random.Next(spawnRoom.Tiles.Count)); - var spawnPosition = grid.GridTileToLocal(spawnTile); + validSpawns.Clear(); + validSpawns.AddRange(spawnRoom.Tiles); + random.Shuffle(validSpawns); - foreach (var entry in EntitySpawnCollection.GetSpawns(mobGroup.Entries, random)) + while (validSpawns.Count > 0) { - var uid = _entManager.CreateEntityUninitialized(entry, spawnPosition); - _entManager.RemoveComponent(uid); - _entManager.RemoveComponent(uid); - _entManager.InitializeAndStartEntity(uid); + var spawnTile = validSpawns[^1]; + + if (!_anchorable.TileFree(grid, spawnTile, (int) CollisionGroup.MachineLayer, (int) CollisionGroup.MachineLayer)) + { + validSpawns.RemoveAt(validSpawns.Count - 1); + continue; + } + + var spawnPosition = grid.GridTileToLocal(spawnTile); + + foreach (var entry in EntitySpawnCollection.GetSpawns(mobGroup.Entries, random)) + { + var uid = _entManager.CreateEntityUninitialized(entry, spawnPosition); + _entManager.RemoveComponent(uid); + _entManager.RemoveComponent(uid); + _entManager.InitializeAndStartEntity(uid); + } + + break; } await SuspendIfOutOfTime();