From 4afccdd5dbb17e4f2cc8829264bda1750e45bce4 Mon Sep 17 00:00:00 2001
From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
Date: Sun, 18 May 2025 03:10:30 +1000
Subject: [PATCH] DungeonData rework (#37172)
* DungeonData rework
Back to fields, serializes better, just make new layers dumby.
* wawawewa
* Fix this
* Fixes
* review
* thanks fork
* fix
---
...toCabling.cs => DungeonJob.AutoCabling.cs} | 10 +-
...ob.PostGenBiome.cs => DungeonJob.Biome.cs} | 4 +-
...ayer.cs => DungeonJob.BiomeMarkerLayer.cs} | 2 +-
...daryWall.cs => DungeonJob.BoundaryWall.cs} | 22 +-
...Clutter.cs => DungeonJob.CornerClutter.cs} | 17 +-
...tGenCorridor.cs => DungeonJob.Corridor.cs} | 10 +-
...utter.cs => DungeonJob.CorridorClutter.cs} | 10 +-
...cs => DungeonJob.CorridorDecalSkirting.cs} | 13 +-
.../DungeonJob/DungeonJob.DunGenFill.cs | 54 ---
.../DungeonJob/DungeonJob.DunGenPrefab.cs | 40 +-
.../DungeonJob.DunGenReplaceTile.cs | 56 +--
...rance.cs => DungeonJob.DungeonEntrance.cs} | 14 +-
...ceFlank.cs => DungeonJob.EntranceFlank.cs} | 15 +-
...nGenExterior.cs => DungeonJob.Exterior.cs} | 5 +-
...Window.cs => DungeonJob.ExternalWindow.cs} | 17 +-
.../Procedural/DungeonJob/DungeonJob.Fill.cs | 39 ++
...onJob.PostGen.cs => DungeonJob.Helpers.cs} | 4 +-
...Window.cs => DungeonJob.InternalWindow.cs} | 15 +-
...tGenJunction.cs => DungeonJob.Junction.cs} | 15 +-
...tion.cs => DungeonJob.MiddleConnection.cs} | 23 +-
...eonJob.MobDunGen.cs => DungeonJob.Mobs.cs} | 7 +-
...Job.DunGenNoise.cs => DungeonJob.Noise.cs} | 0
...geonJob.OreDunGen.cs => DungeonJob.Ore.cs} | 0
.../DungeonJob.PostGenDungeonConnector.cs | 6 -
...Entrance.cs => DungeonJob.RoomEntrance.cs} | 28 +-
...s => DungeonJob.SplineDungeonConnector.cs} | 18 +-
...enWallMount.cs => DungeonJob.WallMount.cs} | 38 +-
...nJob.PostGenWorm.cs => DungeonJob.Worm.cs} | 10 +-
.../Procedural/DungeonJob/DungeonJob.cs | 92 ++--
.../EntityTable/EntityTableSystem.cs | 6 +
Content.Shared/Procedural/DungeonConfig.cs | 6 -
Content.Shared/Procedural/DungeonData.cs | 105 ----
.../DungeonGenerators/PrefabDunGen.cs | 12 +-
.../DungeonGenerators/PrototypeDunGen.cs | 24 +
.../FillGridDunGen.cs | 5 +-
.../Procedural/DungeonLayers/MobsDunGen.cs | 4 +-
.../Procedural/Loot/BiomeTemplateLoot.cs | 5 +-
.../PostGeneration/AutoCablingDunGen.cs | 12 +-
.../PostGeneration/BoundaryWallDunGen.cs | 12 +
.../PostGeneration/CornerClutterDunGen.cs | 11 +-
.../PostGeneration/CorridorClutterDunGen.cs | 4 +-
.../CorridorDecalSkirtingDunGen.cs | 10 +-
.../PostGeneration/CorridorDunGen.cs | 10 +-
.../PostGeneration/DungeonEntranceDunGen.cs | 16 +-
.../PostGeneration/EntranceFlankDunGen.cs | 18 +-
.../PostGeneration/ExternalWindowDunGen.cs | 19 +-
.../PostGeneration/InternalWindowDunGen.cs | 18 +-
.../PostGeneration/JunctionDunGen.cs | 16 +-
.../PostGeneration/MiddleConnectionDunGen.cs | 14 +
.../PostGeneration/RoomEntranceDunGen.cs | 19 +-
.../SplineDungeonConnectorDunGen.cs | 9 +
.../PostGeneration/WallMountDunGen.cs | 11 +
.../PostGeneration/WormCorridorDunGen.cs | 6 +
.../Salvage/SharedSalvageSystem.Magnet.cs | 4 -
Content.Shared/Storage/EntitySpawnEntry.cs | 12 +
.../Prototypes/Procedural/dungeon_configs.yml | 457 +++++++++++-------
Resources/Prototypes/Procedural/vgroid.yml | 26 +-
57 files changed, 759 insertions(+), 696 deletions(-)
rename Content.Server/Procedural/DungeonJob/{DungeonJob.PostGenAutoCabling.cs => DungeonJob.AutoCabling.cs} (92%)
rename Content.Server/Procedural/DungeonJob/{DungeonJob.PostGenBiome.cs => DungeonJob.Biome.cs} (94%)
rename Content.Server/Procedural/DungeonJob/{DungeonJob.PostGenBiomeMarkerLayer.cs => DungeonJob.BiomeMarkerLayer.cs} (97%)
rename Content.Server/Procedural/DungeonJob/{DungeonJob.PostGenBoundaryWall.cs => DungeonJob.BoundaryWall.cs} (80%)
rename Content.Server/Procedural/DungeonJob/{DungeonJob.PostGenCornerClutter.cs => DungeonJob.CornerClutter.cs} (69%)
rename Content.Server/Procedural/DungeonJob/{DungeonJob.PostGenCorridor.cs => DungeonJob.Corridor.cs} (89%)
rename Content.Server/Procedural/DungeonJob/{DungeonJob.PostGenCorridorClutter.cs => DungeonJob.CorridorClutter.cs} (82%)
rename Content.Server/Procedural/DungeonJob/{DungeonJob.PostGenCorridorDecalSkirting.cs => DungeonJob.CorridorDecalSkirting.cs} (93%)
delete mode 100644 Content.Server/Procedural/DungeonJob/DungeonJob.DunGenFill.cs
rename Content.Server/Procedural/DungeonJob/{DungeonJob.PostGenDungeonEntrance.cs => DungeonJob.DungeonEntrance.cs} (88%)
rename Content.Server/Procedural/DungeonJob/{DungeonJob.PostGenEntranceFlank.cs => DungeonJob.EntranceFlank.cs} (66%)
rename Content.Server/Procedural/DungeonJob/{DungeonJob.DunGenExterior.cs => DungeonJob.Exterior.cs} (88%)
rename Content.Server/Procedural/DungeonJob/{DungeonJob.PostGenExternalWindow.cs => DungeonJob.ExternalWindow.cs} (86%)
create mode 100644 Content.Server/Procedural/DungeonJob/DungeonJob.Fill.cs
rename Content.Server/Procedural/DungeonJob/{DungeonJob.PostGen.cs => DungeonJob.Helpers.cs} (98%)
rename Content.Server/Procedural/DungeonJob/{DungeonJob.PostGenInternalWindow.cs => DungeonJob.InternalWindow.cs} (84%)
rename Content.Server/Procedural/DungeonJob/{DungeonJob.PostGenJunction.cs => DungeonJob.Junction.cs} (87%)
rename Content.Server/Procedural/DungeonJob/{DungeonJob.PostGenMiddleConnection.cs => DungeonJob.MiddleConnection.cs} (81%)
rename Content.Server/Procedural/DungeonJob/{DungeonJob.MobDunGen.cs => DungeonJob.Mobs.cs} (90%)
rename Content.Server/Procedural/DungeonJob/{DungeonJob.DunGenNoise.cs => DungeonJob.Noise.cs} (100%)
rename Content.Server/Procedural/DungeonJob/{DungeonJob.OreDunGen.cs => DungeonJob.Ore.cs} (100%)
delete mode 100644 Content.Server/Procedural/DungeonJob/DungeonJob.PostGenDungeonConnector.cs
rename Content.Server/Procedural/DungeonJob/{DungeonJob.PostGenRoomEntrance.cs => DungeonJob.RoomEntrance.cs} (59%)
rename Content.Server/Procedural/DungeonJob/{DungeonJob.PostGenSplineDungeonConnector.cs => DungeonJob.SplineDungeonConnector.cs} (85%)
rename Content.Server/Procedural/DungeonJob/{DungeonJob.PostGenWallMount.cs => DungeonJob.WallMount.cs} (52%)
rename Content.Server/Procedural/DungeonJob/{DungeonJob.PostGenWorm.cs => DungeonJob.Worm.cs} (93%)
delete mode 100644 Content.Shared/Procedural/DungeonData.cs
rename Content.Shared/Procedural/{DungeonGenerators => DungeonLayers}/FillGridDunGen.cs (79%)
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenAutoCabling.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.AutoCabling.cs
similarity index 92%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.PostGenAutoCabling.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.AutoCabling.cs
index 1ff28719fc..8c49a7d606 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenAutoCabling.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.AutoCabling.cs
@@ -13,14 +13,8 @@ public sealed partial class DungeonJob
///
///
///
- private async Task PostGen(AutoCablingDunGen gen, DungeonData data, Dungeon dungeon, HashSet reservedTiles, Random random)
+ private async Task PostGen(AutoCablingDunGen gen, Dungeon dungeon, HashSet reservedTiles, Random random)
{
- if (!data.Entities.TryGetValue(DungeonDataKey.Cabling, out var ent))
- {
- LogDataError(typeof(AutoCablingDunGen));
- return;
- }
-
// There's a lot of ways you could do this.
// For now we'll just connect every LV cable in the dungeon.
var cableTiles = new HashSet();
@@ -157,7 +151,7 @@ public sealed partial class DungeonJob
if (found)
continue;
- _entManager.SpawnEntity(ent, _maps.GridTileToLocal(_gridUid, _grid, tile));
+ _entManager.SpawnEntity(gen.Entity, _maps.GridTileToLocal(_gridUid, _grid, tile));
}
}
}
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenBiome.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.Biome.cs
similarity index 94%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.PostGenBiome.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.Biome.cs
index 9e5f3bdcfc..ea2e7cfba1 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenBiome.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.Biome.cs
@@ -14,7 +14,7 @@ public sealed partial class DungeonJob
///
///
///
- private async Task PostGen(BiomeDunGen dunGen, DungeonData data, Dungeon dungeon, HashSet reservedTiles, Random random)
+ private async Task PostGen(BiomeDunGen dunGen, Dungeon dungeon, HashSet reservedTiles, Random random)
{
if (!_prototype.TryIndex(dunGen.BiomeTemplate, out var indexedBiome))
return;
@@ -31,7 +31,7 @@ public sealed partial class DungeonJob
if (reservedTiles.Contains(node))
continue;
-
+
if (dunGen.TileMask is not null)
{
if (!dunGen.TileMask.Contains(((ContentTileDefinition) _tileDefManager[tileRef.Value.Tile.TypeId]).ID))
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenBiomeMarkerLayer.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.BiomeMarkerLayer.cs
similarity index 97%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.PostGenBiomeMarkerLayer.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.BiomeMarkerLayer.cs
index fb0eaa0157..abc74ddc4f 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenBiomeMarkerLayer.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.BiomeMarkerLayer.cs
@@ -15,7 +15,7 @@ public sealed partial class DungeonJob
///
///
///
- private async Task PostGen(BiomeMarkerLayerDunGen dunGen, DungeonData data, Dungeon dungeon, HashSet reservedTiles, Random random)
+ private async Task PostGen(BiomeMarkerLayerDunGen dunGen, Dungeon dungeon, HashSet reservedTiles, Random random)
{
// If we're adding biome then disable it and just use for markers.
if (_entManager.EnsureComponent(_gridUid, out BiomeComponent biomeComp))
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenBoundaryWall.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.BoundaryWall.cs
similarity index 80%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.PostGenBoundaryWall.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.BoundaryWall.cs
index 84697a56bc..b56a97d40b 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenBoundaryWall.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.BoundaryWall.cs
@@ -12,27 +12,13 @@ public sealed partial class DungeonJob
///
///
///
- private async Task PostGen(BoundaryWallDunGen gen, DungeonData data, Dungeon dungeon, HashSet reservedTiles, Random random)
+ private async Task PostGen(BoundaryWallDunGen gen, Dungeon dungeon, HashSet reservedTiles, Random random)
{
- if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var protoTileDef) ||
- !data.Entities.TryGetValue(DungeonDataKey.Walls, out var wall))
- {
- _sawmill.Error($"Error finding dungeon data for {nameof(gen)}");
- return;
- }
-
- var tileDef = _tileDefManager[protoTileDef];
+ var tileDef = _tileDefManager[gen.Tile];
var tiles = new List<(Vector2i Index, Tile Tile)>(dungeon.RoomExteriorTiles.Count);
- if (!data.Entities.TryGetValue(DungeonDataKey.CornerWalls, out var cornerWall))
- {
- cornerWall = wall;
- }
-
- if (cornerWall == default)
- {
- cornerWall = wall;
- }
+ var wall = gen.Wall;
+ var cornerWall = gen.CornerWall ?? gen.Wall;
// Spawn wall outline
// - Tiles first
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenCornerClutter.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.CornerClutter.cs
similarity index 69%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.PostGenCornerClutter.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.CornerClutter.cs
index f785829850..e653ad4a4d 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenCornerClutter.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.CornerClutter.cs
@@ -1,8 +1,6 @@
using System.Threading.Tasks;
using Content.Shared.Procedural;
using Content.Shared.Procedural.PostGeneration;
-using Content.Shared.Storage;
-using Robust.Shared.Physics.Components;
using Robust.Shared.Random;
namespace Content.Server.Procedural.DungeonJob;
@@ -12,16 +10,15 @@ public sealed partial class DungeonJob
///
///
///
- private async Task PostGen(CornerClutterDunGen gen, DungeonData data, Dungeon dungeon, HashSet reservedTiles, Random random)
+ private async Task PostGen(CornerClutterDunGen gen, Dungeon dungeon, HashSet reservedTiles, Random random)
{
- if (!data.SpawnGroups.TryGetValue(DungeonDataKey.CornerClutter, out var corner))
- {
- _sawmill.Error(Environment.StackTrace);
- return;
- }
+ var contentsTable = _prototype.Index(gen.Contents);
foreach (var tile in dungeon.CorridorTiles)
{
+ if (reservedTiles.Contains(tile))
+ continue;
+
var blocked = _anchorable.TileFree(_grid, tile, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask);
if (blocked)
@@ -45,8 +42,8 @@ public sealed partial class DungeonJob
if (random.Prob(gen.Chance))
{
var coords = _maps.GridTileToLocal(_gridUid, _grid, tile);
- var protos = EntitySpawnCollection.GetSpawns(_prototype.Index(corner).Entries, random);
- _entManager.SpawnEntities(coords, protos);
+ var protos = contentsTable.Table.GetSpawns(random, _entManager, _prototype);
+ _entManager.SpawnEntitiesAttachedTo(coords, protos);
}
break;
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenCorridor.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.Corridor.cs
similarity index 89%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.PostGenCorridor.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.Corridor.cs
index 8ea79ffe54..bf9f910b94 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenCorridor.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.Corridor.cs
@@ -12,14 +12,8 @@ public sealed partial class DungeonJob
///
///
///
- private async Task PostGen(CorridorDunGen gen, DungeonData data, Dungeon dungeon, HashSet reservedTiles, Random random)
+ private async Task PostGen(CorridorDunGen gen, Dungeon dungeon, HashSet reservedTiles, Random random)
{
- if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var tileProto))
- {
- LogDataError(typeof(CorridorDunGen));
- return;
- }
-
var entrances = new List(dungeon.Rooms.Count);
// Grab entrances
@@ -98,7 +92,7 @@ public sealed partial class DungeonJob
WidenCorridor(dungeon, gen.Width, corridorTiles);
var setTiles = new List<(Vector2i, Tile)>();
- var tileDef = (ContentTileDefinition) _tileDefManager[tileProto];
+ var tileDef = (ContentTileDefinition) _tileDefManager[gen.Tile];
foreach (var tile in corridorTiles)
{
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenCorridorClutter.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.CorridorClutter.cs
similarity index 82%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.PostGenCorridorClutter.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.CorridorClutter.cs
index cb7c4b210c..e0be852733 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenCorridorClutter.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.CorridorClutter.cs
@@ -12,10 +12,11 @@ public sealed partial class DungeonJob
///
///
///
- private async Task PostGen(CorridorClutterDunGen gen, DungeonData data, Dungeon dungeon, HashSet reservedTiles, Random random)
+ private async Task PostGen(CorridorClutterDunGen gen, Dungeon dungeon, HashSet reservedTiles, Random random)
{
var physicsQuery = _entManager.GetEntityQuery();
var count = (int) Math.Ceiling(dungeon.CorridorTiles.Count * gen.Chance);
+ var contents = _prototype.Index(gen.Contents);
while (count > 0)
{
@@ -42,9 +43,12 @@ public sealed partial class DungeonJob
count--;
- var protos = EntitySpawnCollection.GetSpawns(gen.Contents, random);
+ if (reservedTiles.Contains(tile))
+ continue;
+
+ var protos = _entTable.GetSpawns(contents, random);
var coords = _maps.ToCenterCoordinates(_gridUid, tile, _grid);
- _entManager.SpawnEntities(coords, protos);
+ _entManager.SpawnEntitiesAttachedTo(coords, protos);
await SuspendIfOutOfTime();
if (!ValidateResume())
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenCorridorDecalSkirting.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.CorridorDecalSkirting.cs
similarity index 93%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.PostGenCorridorDecalSkirting.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.CorridorDecalSkirting.cs
index 3b516c3fa8..cd8737e6ec 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenCorridorDecalSkirting.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.CorridorDecalSkirting.cs
@@ -13,13 +13,8 @@ public sealed partial class DungeonJob
///
///
///
- private async Task PostGen(CorridorDecalSkirtingDunGen decks, DungeonData data, Dungeon dungeon, HashSet reservedTiles, Random random)
+ private async Task PostGen(CorridorDecalSkirtingDunGen decks, Dungeon dungeon, HashSet reservedTiles, Random random)
{
- if (!data.Colors.TryGetValue(DungeonDataKey.Decals, out var color))
- {
- _sawmill.Error(Environment.StackTrace);
- }
-
var directions = new ValueList(4);
var pocketDirections = new ValueList(4);
var doorQuery = _entManager.GetEntityQuery();
@@ -88,7 +83,7 @@ public sealed partial class DungeonJob
{
// Decals not being centered biting my ass again
var gridPos = _maps.GridTileToLocal(_gridUid, _grid, tile).Offset(offset);
- _decals.TryAddDecal(cDir, gridPos, out _, color: color);
+ _decals.TryAddDecal(cDir, gridPos, out _, color: decks.Color);
}
}
@@ -101,7 +96,7 @@ public sealed partial class DungeonJob
{
// Decals not being centered biting my ass again
var gridPos = _maps.GridTileToLocal(_gridUid, _grid, tile).Offset(offset);
- _decals.TryAddDecal(cDir, gridPos, out _, color: color);
+ _decals.TryAddDecal(cDir, gridPos, out _, color: decks.Color);
}
continue;
@@ -116,7 +111,7 @@ public sealed partial class DungeonJob
if (decks.CornerDecals.TryGetValue(dirFlag, out var cDir))
{
var gridPos = _maps.GridTileToLocal(_gridUid, _grid, tile).Offset(offset);
- _decals.TryAddDecal(cDir, gridPos, out _, color: color);
+ _decals.TryAddDecal(cDir, gridPos, out _, color: decks.Color);
}
}
}
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.DunGenFill.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.DunGenFill.cs
deleted file mode 100644
index 77c615d378..0000000000
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.DunGenFill.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using System.Numerics;
-using System.Threading.Tasks;
-using Content.Shared.Maps;
-using Content.Shared.Procedural;
-using Content.Shared.Procedural.DungeonGenerators;
-
-namespace Content.Server.Procedural.DungeonJob;
-
-public sealed partial class DungeonJob
-{
- ///
- ///
- ///
- private async Task GenerateFillDunGen(FillGridDunGen fill, DungeonData data, HashSet reservedTiles)
- {
- if (!data.Entities.TryGetValue(DungeonDataKey.Fill, out var fillEnt))
- {
- LogDataError(typeof(FillGridDunGen));
- return Dungeon.Empty;
- }
-
- var roomTiles = new HashSet();
- var tiles = _maps.GetAllTilesEnumerator(_gridUid, _grid);
-
- while (tiles.MoveNext(out var tileRef))
- {
- var tile = tileRef.Value.GridIndices;
-
- if (reservedTiles.Contains(tile))
- continue;
-
- if (fill.AllowedTiles != null && !fill.AllowedTiles.Contains(((ContentTileDefinition) _tileDefManager[tileRef.Value.Tile.TypeId]).ID))
- continue;
-
- if (!_anchorable.TileFree(_grid, tile, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask))
- continue;
-
- var gridPos = _maps.GridTileToLocal(_gridUid, _grid, tile);
- _entManager.SpawnEntity(fillEnt, gridPos);
-
- roomTiles.Add(tile);
-
- await SuspendDungeon();
- if (!ValidateResume())
- break;
- }
-
- var dungeon = new Dungeon();
- var room = new DungeonRoom(roomTiles, Vector2.Zero, Box2i.Empty, new HashSet());
- dungeon.AddRoom(room);
-
- return dungeon;
- }
-}
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.DunGenPrefab.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.DunGenPrefab.cs
index 33bbeba4b5..8eb85e2cb8 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.DunGenPrefab.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.DunGenPrefab.cs
@@ -14,15 +14,8 @@ public sealed partial class DungeonJob
///
///
///
- private async Task GeneratePrefabDunGen(Vector2i position, DungeonData data, PrefabDunGen prefab, HashSet reservedTiles, Random random)
+ private async Task GeneratePrefabDunGen(Vector2i position, PrefabDunGen prefab, HashSet reservedTiles, Random random)
{
- if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var tileProto) ||
- !data.Whitelists.TryGetValue(DungeonDataKey.Rooms, out var roomWhitelist))
- {
- LogDataError(typeof(PrefabDunGen));
- return Dungeon.Empty;
- }
-
var preset = prefab.Presets[random.Next(prefab.Presets.Count)];
var gen = _prototype.Index(preset);
@@ -50,9 +43,9 @@ public sealed partial class DungeonJob
{
var whitelisted = false;
- if (roomWhitelist?.Tags != null)
+ if (prefab.RoomWhitelist?.Tags != null)
{
- foreach (var tag in roomWhitelist.Tags)
+ foreach (var tag in prefab.RoomWhitelist.Tags)
{
if (proto.Tags.Contains(tag))
{
@@ -164,6 +157,7 @@ public sealed partial class DungeonJob
// Then for overlaps choose either 1x1 / 3x1
// Pick a random tile for it and then expand outwards as relevant (weighted towards middle?)
+ var fallbackTile = prefab.FallbackTile;
for (var i = 0; i < chosenPacks.Length; i++)
{
@@ -181,29 +175,35 @@ public sealed partial class DungeonJob
Angle roomRotation = Angle.Zero;
Matrix3x2 matty;
+ // If no room found then try rotated dimensions
if (!roomProtos.TryGetValue(roomDimensions, out var roomProto))
{
roomDimensions = new Vector2i(roomDimensions.Y, roomDimensions.X);
+ // If nothing at all then no valid rooms, try fallback tile and log it.
if (!roomProtos.TryGetValue(roomDimensions, out roomProto))
{
- matty = Matrix3x2.Multiply(packTransform, dungeonTransform);
-
- for (var x = roomSize.Left; x < roomSize.Right; x++)
+ if (fallbackTile != null)
{
- for (var y = roomSize.Bottom; y < roomSize.Top; y++)
+ matty = Matrix3x2.Multiply(packTransform, dungeonTransform);
+
+ for (var x = roomSize.Left; x < roomSize.Right; x++)
{
- var index = Vector2.Transform(new Vector2(x, y) + _grid.TileSizeHalfVector - packCenter, matty).Floored();
+ for (var y = roomSize.Bottom; y < roomSize.Top; y++)
+ {
+ var index = Vector2.Transform(new Vector2(x, y) + _grid.TileSizeHalfVector - packCenter, matty).Floored();
- if (reservedTiles.Contains(index))
- continue;
+ if (reservedTiles.Contains(index))
+ continue;
- tiles.Add((index, new Tile(_tileDefManager[tileProto].TileId)));
+ tiles.Add((index, new Tile(_tileDefManager[fallbackTile.Value].TileId)));
+ }
}
+
+ _maps.SetTiles(_gridUid, _grid, tiles);
+ tiles.Clear();
}
- _maps.SetTiles(_gridUid, _grid, tiles);
- tiles.Clear();
_sawmill.Error($"Unable to find room variant for {roomDimensions}, leaving empty.");
continue;
}
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.DunGenReplaceTile.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.DunGenReplaceTile.cs
index 6b36d10109..dfc0932915 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.DunGenReplaceTile.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.DunGenReplaceTile.cs
@@ -12,49 +12,43 @@ public sealed partial class DungeonJob
///
///
///
- private async Task GenerateTileReplacementDunGen(ReplaceTileDunGen gen, DungeonData data, HashSet reservedTiles, Random random)
+ private async Task GenerateTileReplacementDunGen(ReplaceTileDunGen gen, List dungeons, HashSet reservedTiles, Random random)
{
- var tiles = _maps.GetAllTilesEnumerator(_gridUid, _grid);
var replacements = new List<(Vector2i Index, Tile Tile)>();
- var reserved = new HashSet();
- while (tiles.MoveNext(out var tileRef))
+ foreach (var dungeon in dungeons)
{
- var node = tileRef.Value.GridIndices;
-
- if (reservedTiles.Contains(node))
- continue;
-
- foreach (var layer in gen.Layers)
+ foreach (var node in dungeon.AllTiles)
{
- var value = layer.Noise.GetNoise(node.X, node.Y);
-
- if (value < layer.Threshold)
+ if (reservedTiles.Contains(node))
continue;
- Tile tile;
+ foreach (var layer in gen.Layers)
+ {
+ var value = layer.Noise.GetNoise(node.X, node.Y);
- if (random.Prob(gen.VariantWeight))
- {
- tile = _tileDefManager.GetVariantTile(_prototype.Index(layer.Tile), random);
- }
- else
- {
- tile = new Tile(_prototype.Index(layer.Tile).TileId);
+ if (value < layer.Threshold)
+ continue;
+
+ Tile tile;
+
+ if (random.Prob(gen.VariantWeight))
+ {
+ tile = _tileDefManager.GetVariantTile(_prototype.Index(layer.Tile), random);
+ }
+ else
+ {
+ tile = new Tile(_prototype.Index(layer.Tile).TileId);
+ }
+
+ replacements.Add((node, tile));
+ break;
}
- replacements.Add((node, tile));
- reserved.Add(node);
- break;
+ await SuspendDungeon();
}
- await SuspendDungeon();
+ _maps.SetTiles(_gridUid, _grid, replacements);
}
-
- _maps.SetTiles(_gridUid, _grid, replacements);
- return new Dungeon(new List()
- {
- new DungeonRoom(reserved, _position, Box2i.Empty, new HashSet()),
- });
}
}
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenDungeonEntrance.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.DungeonEntrance.cs
similarity index 88%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.PostGenDungeonEntrance.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.DungeonEntrance.cs
index abc52f07c6..ef84fb77df 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenDungeonEntrance.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.DungeonEntrance.cs
@@ -12,18 +12,12 @@ public sealed partial class DungeonJob
///
///
///
- private async Task PostGen(DungeonEntranceDunGen gen, DungeonData data, Dungeon dungeon, HashSet reservedTiles, Random random)
+ private async Task PostGen(DungeonEntranceDunGen gen, Dungeon dungeon, HashSet reservedTiles, Random random)
{
- if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var tileProto) ||
- !data.SpawnGroups.TryGetValue(DungeonDataKey.Entrance, out var entrance))
- {
- LogDataError(typeof(DungeonEntranceDunGen));
- return;
- }
-
var rooms = new List(dungeon.Rooms);
var roomTiles = new List();
- var tileDef = (ContentTileDefinition) _tileDefManager[tileProto];
+ var tileDef = (ContentTileDefinition) _tileDefManager[gen.Tile];
+ var contents = _prototype.Index(gen.Contents);
for (var i = 0; i < gen.Count; i++)
{
@@ -82,7 +76,7 @@ public sealed partial class DungeonJob
var gridCoords = _maps.GridTileToLocal(_gridUid, _grid, tile);
// Need to offset the spawn to avoid spawning in the room.
- foreach (var ent in EntitySpawnCollection.GetSpawns(_prototype.Index(entrance).Entries, random))
+ foreach (var ent in _entTable.GetSpawns(contents, random))
{
_entManager.SpawnAtPosition(ent, gridCoords);
}
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenEntranceFlank.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.EntranceFlank.cs
similarity index 66%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.PostGenEntranceFlank.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.EntranceFlank.cs
index 3a1c7a3779..1788c23cae 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenEntranceFlank.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.EntranceFlank.cs
@@ -13,18 +13,12 @@ public sealed partial class DungeonJob
///
///
///
- private async Task PostGen(EntranceFlankDunGen gen, DungeonData data, Dungeon dungeon, HashSet reservedTiles, Random random)
+ private async Task PostGen(EntranceFlankDunGen gen, Dungeon dungeon, HashSet reservedTiles, Random random)
{
- if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var tileProto) ||
- !data.SpawnGroups.TryGetValue(DungeonDataKey.EntranceFlank, out var flankProto))
- {
- _sawmill.Error($"Unable to get dungeon data for {nameof(gen)}");
- return;
- }
-
var tiles = new List<(Vector2i Index, Tile)>();
- var tileDef = _tileDefManager[tileProto];
+ var tileDef = _tileDefManager[gen.Tile];
var spawnPositions = new ValueList(dungeon.Rooms.Count);
+ var contents = _prototype.Index(gen.Contents);
foreach (var room in dungeon.Rooms)
{
@@ -48,11 +42,10 @@ public sealed partial class DungeonJob
}
_maps.SetTiles(_gridUid, _grid, tiles);
- var entGroup = _prototype.Index(flankProto);
foreach (var entrance in spawnPositions)
{
- _entManager.SpawnEntities(_maps.GridTileToLocal(_gridUid, _grid, entrance), EntitySpawnCollection.GetSpawns(entGroup.Entries, random));
+ _entManager.SpawnEntitiesAttachedTo(_maps.GridTileToLocal(_gridUid, _grid, entrance), _entTable.GetSpawns(contents, random));
}
}
}
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.DunGenExterior.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.Exterior.cs
similarity index 88%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.DunGenExterior.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.Exterior.cs
index bb2c1cbbbf..92237dca2a 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.DunGenExterior.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.Exterior.cs
@@ -1,10 +1,8 @@
using System.Threading.Tasks;
-using Content.Server.NPC.Pathfinding;
using Content.Shared.Maps;
using Content.Shared.NPC;
using Content.Shared.Procedural;
using Content.Shared.Procedural.DungeonGenerators;
-using Robust.Shared.Collections;
using Robust.Shared.Random;
using Robust.Shared.Utility;
@@ -27,7 +25,6 @@ public sealed partial class DungeonJob
var startTile = new Vector2i(0, (int) distance).Rotate(angle);
Vector2i? dungeonSpawn = null;
- var pathfinder = _entManager.System();
// Gridcast
SharedPathfindingSystem.GridCast(startTile, position, tile =>
@@ -52,7 +49,7 @@ public sealed partial class DungeonJob
var config = _prototype.Index(dungen.Proto);
var nextSeed = random.Next();
- var dungeons = await GetDungeons(dungeonSpawn.Value, config, config.Data, config.Layers, reservedTiles, nextSeed, new Random(nextSeed));
+ var dungeons = await GetDungeons(dungeonSpawn.Value, config, config.Layers, reservedTiles, nextSeed, new Random(nextSeed));
return dungeons;
}
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenExternalWindow.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.ExternalWindow.cs
similarity index 86%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.PostGenExternalWindow.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.ExternalWindow.cs
index 9a1b44ec91..f390620186 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenExternalWindow.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.ExternalWindow.cs
@@ -24,15 +24,8 @@ public sealed partial class DungeonJob
///
///
///
- private async Task PostGen(ExternalWindowDunGen gen, DungeonData data, Dungeon dungeon, HashSet reservedTiles, Random random)
+ private async Task PostGen(ExternalWindowDunGen gen, Dungeon dungeon, HashSet reservedTiles, Random random)
{
- if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var tileProto) ||
- !data.SpawnGroups.TryGetValue(DungeonDataKey.Window, out var windowGroup))
- {
- _sawmill.Error($"Unable to get dungeon data for {nameof(gen)}");
- return;
- }
-
// Iterate every tile with N chance to spawn windows on that wall per cardinal dir.
var chance = 0.25 / 3f;
@@ -42,7 +35,7 @@ public sealed partial class DungeonJob
random.Shuffle(validTiles);
var tiles = new List<(Vector2i, Tile)>();
- var tileDef = _tileDefManager[tileProto];
+ var tileDef = _tileDefManager[gen.Tile];
var count = Math.Floor(validTiles.Count * chance);
var index = 0;
var takenTiles = new HashSet();
@@ -120,15 +113,13 @@ public sealed partial class DungeonJob
}
_maps.SetTiles(_gridUid, _grid, tiles);
- index = 0;
- var spawnEntry = _prototype.Index(windowGroup);
+ var contents = _prototype.Index(gen.Contents);
foreach (var tile in tiles)
{
var gridPos = _maps.GridTileToLocal(_gridUid, _grid, tile.Item1);
- index += spawnEntry.Entries.Count;
- _entManager.SpawnEntities(gridPos, EntitySpawnCollection.GetSpawns(spawnEntry.Entries, random));
+ _entManager.SpawnEntitiesAttachedTo(gridPos, _entTable.GetSpawns(contents, random));
await SuspendDungeon();
if (!ValidateResume())
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.Fill.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.Fill.cs
new file mode 100644
index 0000000000..43f453f29a
--- /dev/null
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.Fill.cs
@@ -0,0 +1,39 @@
+using System.Threading.Tasks;
+using Content.Shared.Procedural;
+using Content.Shared.Procedural.DungeonLayers;
+
+namespace Content.Server.Procedural.DungeonJob;
+
+public sealed partial class DungeonJob
+{
+ ///
+ ///
+ ///
+ private async Task GenerateFillDunGen(FillGridDunGen fill, List dungeons, HashSet reservedTiles)
+ {
+ foreach (var dungeon in dungeons)
+ {
+ foreach (var tile in dungeon.AllTiles)
+ {
+ if (reservedTiles.Contains(tile))
+ continue;
+
+ if (!_maps.TryGetTileDef(_grid, tile, out var tileDef))
+ continue;
+
+ if (fill.AllowedTiles != null && !fill.AllowedTiles.Contains(tileDef.ID))
+ continue;
+
+ if (!_anchorable.TileFree(_grid, tile, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask))
+ continue;
+
+ var gridPos = _maps.GridTileToLocal(_gridUid, _grid, tile);
+ _entManager.SpawnEntity(fill.Entity, gridPos);
+
+ await SuspendDungeon();
+ if (!ValidateResume())
+ break;
+ }
+ }
+ }
+}
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGen.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.Helpers.cs
similarity index 98%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.PostGen.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.Helpers.cs
index 84e7563f33..c57757b421 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGen.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.Helpers.cs
@@ -10,9 +10,7 @@ namespace Content.Server.Procedural.DungeonJob;
public sealed partial class DungeonJob
{
- /*
- * Run after the main dungeon generation
- */
+ // Various helper methods.
private static readonly ProtoId WallTag = "Wall";
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenInternalWindow.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.InternalWindow.cs
similarity index 84%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.PostGenInternalWindow.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.InternalWindow.cs
index d3b8c6d2f5..c9b1481450 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenInternalWindow.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.InternalWindow.cs
@@ -12,21 +12,14 @@ public sealed partial class DungeonJob
///
///
///
- private async Task PostGen(InternalWindowDunGen gen, DungeonData data, Dungeon dungeon, HashSet reservedTiles, Random random)
+ private async Task PostGen(InternalWindowDunGen gen, Dungeon dungeon, HashSet reservedTiles, Random random)
{
- if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var tileProto) ||
- !data.SpawnGroups.TryGetValue(DungeonDataKey.Window, out var windowGroup))
- {
- _sawmill.Error($"Unable to find dungeon data keys for {nameof(gen)}");
- return;
- }
-
// Iterate every room and check if there's a gap beyond it that leads to another room within N tiles
// If so then consider windows
var minDistance = 4;
var maxDistance = 6;
- var tileDef = _tileDefManager[tileProto];
- var window = _prototype.Index(windowGroup);
+ var tileDef = _tileDefManager[gen.Tile];
+ var contents = _prototype.Index(gen.Contents);
foreach (var room in dungeon.Rooms)
{
@@ -90,7 +83,7 @@ public sealed partial class DungeonJob
var gridPos = _maps.GridTileToLocal(_gridUid, _grid, tile);
_maps.SetTile(_gridUid, _grid, tile, _tile.GetVariantTile((ContentTileDefinition) tileDef, random));
- _entManager.SpawnEntities(gridPos, EntitySpawnCollection.GetSpawns(window.Entries, random));
+ _entManager.SpawnEntitiesAttachedTo(gridPos, _entTable.GetSpawns(contents, random));
}
if (validTiles.Count > 0)
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenJunction.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.Junction.cs
similarity index 87%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.PostGenJunction.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.Junction.cs
index 700406eb89..b491f3df27 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenJunction.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.Junction.cs
@@ -12,17 +12,10 @@ public sealed partial class DungeonJob
///
///
///
- private async Task PostGen(JunctionDunGen gen, DungeonData data, Dungeon dungeon, HashSet reservedTiles, Random random)
+ private async Task PostGen(JunctionDunGen gen, Dungeon dungeon, HashSet reservedTiles, Random random)
{
- if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var tileProto) ||
- !data.SpawnGroups.TryGetValue(DungeonDataKey.Junction, out var junctionProto))
- {
- _sawmill.Error($"Dungeon data keys are missing for {nameof(gen)}");
- return;
- }
-
- var tileDef = _tileDefManager[tileProto];
- var entranceGroup = _prototype.Index(junctionProto);
+ var tileDef = _tileDefManager[gen.Tile];
+ var contents = _prototype.Index(gen.Contents);
// N-wide junctions
foreach (var tile in dungeon.CorridorTiles)
@@ -123,7 +116,7 @@ public sealed partial class DungeonJob
_maps.SetTile(_gridUid, _grid, weh, _tile.GetVariantTile((ContentTileDefinition) tileDef, random));
var coords = _maps.GridTileToLocal(_gridUid, _grid, weh);
- _entManager.SpawnEntities(coords, EntitySpawnCollection.GetSpawns(entranceGroup.Entries, random));
+ _entManager.SpawnEntitiesAttachedTo(coords, _entTable.GetSpawns(contents, random));
}
break;
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenMiddleConnection.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.MiddleConnection.cs
similarity index 81%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.PostGenMiddleConnection.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.MiddleConnection.cs
index 15d0f63423..f2ea97b6e6 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenMiddleConnection.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.MiddleConnection.cs
@@ -13,19 +13,8 @@ public sealed partial class DungeonJob
///
///
///
- private async Task PostGen(MiddleConnectionDunGen gen, DungeonData data, Dungeon dungeon, HashSet reservedTiles, Random random)
+ private async Task PostGen(MiddleConnectionDunGen gen, Dungeon dungeon, HashSet reservedTiles, Random random)
{
- if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var tileProto) ||
- !data.SpawnGroups.TryGetValue(DungeonDataKey.Entrance, out var entranceProto) ||
- !_prototype.TryIndex(entranceProto, out var entrance))
- {
- _sawmill.Error($"Tried to run {nameof(MiddleConnectionDunGen)} without any dungeon data set which is unsupported");
- return;
- }
-
- data.SpawnGroups.TryGetValue(DungeonDataKey.EntranceFlank, out var flankProto);
- _prototype.TryIndex(flankProto, out var flank);
-
// Grab all of the room bounds
// Then, work out connections between them
var roomBorders = new Dictionary>(dungeon.Rooms.Count);
@@ -67,7 +56,9 @@ public sealed partial class DungeonJob
// TODO: Optional loops
var roomConnections = new Dictionary>();
- var tileDef = _tileDefManager[tileProto];
+ var tileDef = _tileDefManager[gen.Tile];
+ _prototype.TryIndex(gen.Flank, out var flankContents);
+ var contents = _prototype.Index(gen.Contents);
foreach (var (room, border) in roomBorders)
{
@@ -118,16 +109,16 @@ public sealed partial class DungeonJob
width--;
_maps.SetTile(_gridUid, _grid, node, _tile.GetVariantTile((ContentTileDefinition) tileDef, random));
- if (flank != null && nodeDistances.Count - i <= 2)
+ if (flankContents != null && nodeDistances.Count - i <= 2)
{
- _entManager.SpawnEntities(gridPos, EntitySpawnCollection.GetSpawns(flank.Entries, random));
+ _entManager.SpawnEntitiesAttachedTo(gridPos, _entTable.GetSpawns(flankContents, random));
}
else
{
// Iterate neighbors and check for blockers, if so bulldoze
ClearDoor(dungeon, _grid, node);
- _entManager.SpawnEntities(gridPos, EntitySpawnCollection.GetSpawns(entrance.Entries, random));
+ _entManager.SpawnEntitiesAttachedTo(gridPos, _entTable.GetSpawns(contents, random));
}
if (width == 0)
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.MobDunGen.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.Mobs.cs
similarity index 90%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.MobDunGen.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.Mobs.cs
index 150849d2c5..cf1c239b0e 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.MobDunGen.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.Mobs.cs
@@ -13,6 +13,9 @@ namespace Content.Server.Procedural.DungeonJob;
public sealed partial class DungeonJob
{
+ ///
+ ///
+ ///
private async Task PostGen(
MobsDunGen gen,
Dungeon dungeon,
@@ -21,8 +24,8 @@ public sealed partial class DungeonJob
var availableRooms = new ValueList();
availableRooms.AddRange(dungeon.Rooms);
var availableTiles = new ValueList(dungeon.AllTiles);
+ var contents = _prototype.Index(gen.Contents);
- var entities = EntitySpawnCollection.GetSpawns(gen.Groups, random);
var count = random.Next(gen.MinCount, gen.MaxCount + 1);
var npcs = _entManager.System();
@@ -38,6 +41,8 @@ public sealed partial class DungeonJob
continue;
}
+ var entities = _entTable.GetSpawns(contents, random);
+
foreach (var ent in entities)
{
var uid = _entManager.SpawnAtPosition(ent, _maps.GridTileToLocal(_gridUid, _grid, tile));
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.DunGenNoise.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.Noise.cs
similarity index 100%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.DunGenNoise.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.Noise.cs
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.OreDunGen.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.Ore.cs
similarity index 100%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.OreDunGen.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.Ore.cs
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenDungeonConnector.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenDungeonConnector.cs
deleted file mode 100644
index 917b1ffc9c..0000000000
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenDungeonConnector.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Content.Server.Procedural.DungeonJob;
-
-public sealed partial class DungeonJob
-{
-
-}
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenRoomEntrance.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.RoomEntrance.cs
similarity index 59%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.PostGenRoomEntrance.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.RoomEntrance.cs
index 09d223e86c..a4a01b5f0b 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenRoomEntrance.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.RoomEntrance.cs
@@ -12,23 +12,19 @@ public sealed partial class DungeonJob
///
///
///
- private async Task PostGen(RoomEntranceDunGen gen, DungeonData data, Dungeon dungeon, HashSet reservedTiles, Random random)
+ private async Task PostGen(RoomEntranceDunGen gen, Dungeon dungeon, HashSet reservedTiles, Random random)
{
- if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var tileProto) ||
- !data.SpawnGroups.TryGetValue(DungeonDataKey.Entrance, out var entranceProtos) ||
- !_prototype.TryIndex(entranceProtos, out var entranceIn))
- {
- LogDataError(typeof(RoomEntranceDunGen));
- return;
- }
-
var setTiles = new List<(Vector2i, Tile)>();
- var tileDef = _tileDefManager[tileProto];
+ var tileDef = _tileDefManager[gen.Tile];
+ var contents = _prototype.Index(gen.Contents);
foreach (var room in dungeon.Rooms)
{
foreach (var entrance in room.Entrances)
{
+ if (reservedTiles.Contains(entrance))
+ continue;
+
setTiles.Add((entrance, _tile.GetVariantTile((ContentTileDefinition) tileDef, random)));
}
}
@@ -39,9 +35,17 @@ public sealed partial class DungeonJob
{
foreach (var entrance in room.Entrances)
{
- _entManager.SpawnEntities(
+ if (reservedTiles.Contains(entrance))
+ continue;
+
+ _entManager.SpawnEntitiesAttachedTo(
_maps.GridTileToLocal(_gridUid, _grid, entrance),
- EntitySpawnCollection.GetSpawns(entranceIn.Entries, random));
+ _entTable.GetSpawns(contents, random));
+
+ await SuspendDungeon();
+
+ if (!ValidateResume())
+ return;
}
}
}
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenSplineDungeonConnector.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.SplineDungeonConnector.cs
similarity index 85%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.PostGenSplineDungeonConnector.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.SplineDungeonConnector.cs
index 8fe2f36665..a131efd353 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenSplineDungeonConnector.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.SplineDungeonConnector.cs
@@ -15,25 +15,14 @@ public sealed partial class DungeonJob
///
private async Task PostGen(
SplineDungeonConnectorDunGen gen,
- DungeonData data,
List dungeons,
HashSet reservedTiles,
Random random)
{
- // TODO: The path itself use the tile
- // Widen it randomly (probably for each tile offset it by some changing amount).
-
// NOOP
if (dungeons.Count <= 1)
return Dungeon.Empty;
- if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var fallback) ||
- !data.Tiles.TryGetValue(DungeonDataKey.WidenTile, out var widen))
- {
- LogDataError(typeof(SplineDungeonConnectorDunGen));
- return Dungeon.Empty;
- }
-
var nodes = new List();
foreach (var dungeon in dungeons)
@@ -57,7 +46,8 @@ public sealed partial class DungeonJob
var tiles = new List<(Vector2i Index, Tile Tile)>();
var pathfinding = _entManager.System();
var allTiles = new HashSet();
- var fallbackTile = new Tile(_prototype.Index(fallback).TileId);
+ var pathTile = new Tile(_prototype.Index(gen.Tile).TileId);
+ var widen = _prototype.Index(gen.WidenTile ?? gen.Tile);
foreach (var pair in tree)
{
@@ -112,7 +102,7 @@ public sealed partial class DungeonJob
if (random.Prob(0.9f))
{
- tile = new Tile(_prototype.Index(widen).TileId);
+ tile = new Tile(widen.TileId);
}
else
{
@@ -132,7 +122,7 @@ public sealed partial class DungeonJob
continue;
allTiles.Add(node);
- tiles.Add((node, fallbackTile));
+ tiles.Add((node, pathTile));
}
_maps.SetTiles(_gridUid, _grid, tiles);
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenWallMount.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.WallMount.cs
similarity index 52%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.PostGenWallMount.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.WallMount.cs
index d5c8587ea9..e01fa9b947 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenWallMount.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.WallMount.cs
@@ -1,4 +1,5 @@
using System.Threading.Tasks;
+using Content.Shared.Maps;
using Content.Shared.Procedural;
using Content.Shared.Procedural.PostGeneration;
using Content.Shared.Storage;
@@ -11,25 +12,13 @@ public sealed partial class DungeonJob
///
///
///
- private async Task PostGen(WallMountDunGen gen, DungeonData data, Dungeon dungeon, HashSet reservedTiles, Random random)
+ private async Task PostGen(WallMountDunGen gen, Dungeon dungeon, HashSet reservedTiles, Random random)
{
- if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var tileProto))
- {
- _sawmill.Error($"Tried to run {nameof(WallMountDunGen)} without any dungeon data set which is unsupported");
- return;
- }
-
- var tileDef = _prototype.Index(tileProto);
- if (!data.SpawnGroups.TryGetValue(DungeonDataKey.WallMounts, out var spawnProto))
- {
- // caves can have no walls
- return;
- }
-
var checkedTiles = new HashSet();
var allExterior = new HashSet(dungeon.CorridorExteriorTiles);
allExterior.UnionWith(dungeon.RoomExteriorTiles);
- var count = 0;
+ var tileDef = (ContentTileDefinition) _tileDefManager[gen.Tile];
+ var contents = _prototype.Index(gen.Contents);
foreach (var neighbor in allExterior)
{
@@ -40,21 +29,18 @@ public sealed partial class DungeonJob
if (!random.Prob(gen.Prob) || !checkedTiles.Add(neighbor))
continue;
+ if (reservedTiles.Contains(neighbor))
+ continue;
+
_maps.SetTile(_gridUid, _grid, neighbor, _tile.GetVariantTile(tileDef, random));
var gridPos = _maps.GridTileToLocal(_gridUid, _grid, neighbor);
- var protoNames = EntitySpawnCollection.GetSpawns(_prototype.Index(spawnProto).Entries, random);
+ var protoNames = _entTable.GetSpawns(contents, random);
- _entManager.SpawnEntities(gridPos, protoNames);
- count += protoNames.Count;
+ _entManager.SpawnEntitiesAttachedTo(gridPos, protoNames);
- if (count > 20)
- {
- count -= 20;
- await SuspendDungeon();
-
- if (!ValidateResume())
- return;
- }
+ await SuspendDungeon();
+ if (!ValidateResume())
+ return;
}
}
}
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenWorm.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.Worm.cs
similarity index 93%
rename from Content.Server/Procedural/DungeonJob/DungeonJob.PostGenWorm.cs
rename to Content.Server/Procedural/DungeonJob/DungeonJob.Worm.cs
index 6fd00e5482..7367b9147a 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenWorm.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.Worm.cs
@@ -1,5 +1,6 @@
using System.Linq;
using System.Threading.Tasks;
+using Content.Shared.Maps;
using Content.Shared.Procedural;
using Content.Shared.Procedural.PostGeneration;
using Robust.Shared.Collections;
@@ -14,19 +15,14 @@ public sealed partial class DungeonJob
///
///
///
- private async Task PostGen(WormCorridorDunGen gen, DungeonData data, Dungeon dungeon, HashSet reservedTiles, Random random)
+ private async Task PostGen(WormCorridorDunGen gen, Dungeon dungeon, HashSet reservedTiles, Random random)
{
- if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var tileProto) || !_prototype.TryIndex(tileProto, out var tileDef))
- {
- _sawmill.Error($"Tried to run {nameof(WormCorridorDunGen)} without any dungeon data set which is unsupported");
- return;
- }
-
var networks = new List<(Vector2i Start, HashSet Network)>();
// List of places to start from.
var worm = new ValueList();
var startAngles = new Dictionary();
+ var tileDef = (ContentTileDefinition) _tileDefManager[gen.Tile];
foreach (var room in dungeon.Rooms)
{
diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.cs
index cdb5eb0805..58583f833d 100644
--- a/Content.Server/Procedural/DungeonJob/DungeonJob.cs
+++ b/Content.Server/Procedural/DungeonJob/DungeonJob.cs
@@ -1,3 +1,4 @@
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Content.Server.Decals;
@@ -6,6 +7,7 @@ using Content.Server.NPC.HTN;
using Content.Server.NPC.Systems;
using Content.Server.Shuttles.Systems;
using Content.Shared.Construction.EntitySystems;
+using Content.Shared.EntityTable;
using Content.Shared.Maps;
using Content.Shared.Procedural;
using Content.Shared.Procedural.DungeonGenerators;
@@ -37,6 +39,7 @@ public sealed partial class DungeonJob : Job>
private readonly DecalSystem _decals;
private readonly DungeonSystem _dungeon;
private readonly EntityLookupSystem _lookup;
+ private readonly EntityTableSystem _entTable;
private readonly TagSystem _tags;
private readonly TileSystem _tile;
private readonly SharedMapSystem _maps;
@@ -88,6 +91,7 @@ public sealed partial class DungeonJob : Job>
_tile = tile;
_tags = _entManager.System();
_maps = _entManager.System();
+ _entTable = _entManager.System();
_transform = transform;
_physicsQuery = _entManager.GetEntityQuery();
@@ -108,13 +112,20 @@ public sealed partial class DungeonJob : Job>
private async Task> GetDungeons(
Vector2i position,
DungeonConfig config,
- DungeonData data,
List layers,
HashSet reservedTiles,
int seed,
- Random random)
+ Random random,
+ List? existing = null)
{
var dungeons = new List();
+
+ // Don't pass dungeons back up the "stack". They are ref types though it's a caller problem if they start trying to mutate it.
+ if (existing != null)
+ {
+ dungeons.AddRange(existing);
+ }
+
var count = random.Next(config.MinCount, config.MaxCount + 1);
for (var i = 0; i < count; i++)
@@ -123,10 +134,25 @@ public sealed partial class DungeonJob : Job>
foreach (var layer in layers)
{
- await RunLayer(dungeons, data, position, layer, reservedTiles, seed, random);
+ await RunLayer(dungeons, position, layer, reservedTiles, seed, random);
if (config.ReserveTiles)
{
+ // Remove any dungeons passed in so we don't interfere with them
+ // This is kinda goofy but okay for now.
+ if (existing != null)
+ {
+ for (var j = 0; j < dungeons.Count; j++)
+ {
+ var dung = dungeons[j];
+
+ if (existing.Contains(dung))
+ {
+ dungeons.RemoveSwap(j);
+ }
+ }
+ }
+
foreach (var dungeon in dungeons)
{
reservedTiles.UnionWith(dungeon.AllTiles);
@@ -152,7 +178,7 @@ public sealed partial class DungeonJob : Job>
// Tiles we can no longer generate on due to being reserved elsewhere.
var reservedTiles = new HashSet();
- var dungeons = await GetDungeons(position, _gen, _gen.Data, _gen.Layers, reservedTiles, _seed, random);
+ var dungeons = await GetDungeons(position, _gen, _gen.Layers, reservedTiles, _seed, random);
// To make it slightly more deterministic treat this RNG as separate ig.
// Post-processing after finishing loading.
@@ -181,7 +207,6 @@ public sealed partial class DungeonJob : Job>
private async Task RunLayer(
List dungeons,
- DungeonData data,
Vector2i position,
IDunGenLayer layer,
HashSet reservedTiles,
@@ -200,52 +225,52 @@ public sealed partial class DungeonJob : Job>
switch (layer)
{
case AutoCablingDunGen cabling:
- await PostGen(cabling, data, dungeons[^1], reservedTiles, random);
+ await PostGen(cabling, dungeons[^1], reservedTiles, random);
break;
case BiomeMarkerLayerDunGen markerPost:
- await PostGen(markerPost, data, dungeons[^1], reservedTiles, random);
+ await PostGen(markerPost, dungeons[^1], reservedTiles, random);
break;
case BiomeDunGen biome:
- await PostGen(biome, data, dungeons[^1], reservedTiles, random);
+ await PostGen(biome, dungeons[^1], reservedTiles, random);
break;
case BoundaryWallDunGen boundary:
- await PostGen(boundary, data, dungeons[^1], reservedTiles, random);
+ await PostGen(boundary, dungeons[^1], reservedTiles, random);
break;
case CornerClutterDunGen clutter:
- await PostGen(clutter, data, dungeons[^1], reservedTiles, random);
+ await PostGen(clutter, dungeons[^1], reservedTiles, random);
break;
case CorridorClutterDunGen corClutter:
- await PostGen(corClutter, data, dungeons[^1], reservedTiles, random);
+ await PostGen(corClutter, dungeons[^1], reservedTiles, random);
break;
case CorridorDunGen cordor:
- await PostGen(cordor, data, dungeons[^1], reservedTiles, random);
+ await PostGen(cordor, dungeons[^1], reservedTiles, random);
break;
case CorridorDecalSkirtingDunGen decks:
- await PostGen(decks, data, dungeons[^1], reservedTiles, random);
+ await PostGen(decks, dungeons[^1], reservedTiles, random);
break;
case EntranceFlankDunGen flank:
- await PostGen(flank, data, dungeons[^1], reservedTiles, random);
+ await PostGen(flank, dungeons[^1], reservedTiles, random);
break;
case ExteriorDunGen exterior:
dungeons.AddRange(await GenerateExteriorDungen(position, exterior, reservedTiles, random));
break;
case FillGridDunGen fill:
- dungeons.Add(await GenerateFillDunGen(fill, data, reservedTiles));
+ await GenerateFillDunGen(fill, dungeons, reservedTiles);
break;
case JunctionDunGen junc:
- await PostGen(junc, data, dungeons[^1], reservedTiles, random);
+ await PostGen(junc, dungeons[^1], reservedTiles, random);
break;
case MiddleConnectionDunGen dordor:
- await PostGen(dordor, data, dungeons[^1], reservedTiles, random);
+ await PostGen(dordor, dungeons[^1], reservedTiles, random);
break;
case DungeonEntranceDunGen entrance:
- await PostGen(entrance, data, dungeons[^1], reservedTiles, random);
+ await PostGen(entrance, dungeons[^1], reservedTiles, random);
break;
case ExternalWindowDunGen externalWindow:
- await PostGen(externalWindow, data, dungeons[^1], reservedTiles, random);
+ await PostGen(externalWindow, dungeons[^1], reservedTiles, random);
break;
case InternalWindowDunGen internalWindow:
- await PostGen(internalWindow, data, dungeons[^1], reservedTiles, random);
+ await PostGen(internalWindow, dungeons[^1], reservedTiles, random);
break;
case MobsDunGen mob:
await PostGen(mob, dungeons[^1], random);
@@ -263,31 +288,40 @@ public sealed partial class DungeonJob : Job>
await PostGen(ore, dungeons[^1], random);
break;
case PrefabDunGen prefab:
- dungeons.Add(await GeneratePrefabDunGen(position, data, prefab, reservedTiles, random));
+ dungeons.Add(await GeneratePrefabDunGen(position, prefab, reservedTiles, random));
break;
case PrototypeDunGen prototypo:
var groupConfig = _prototype.Index(prototypo.Proto);
position = (position + random.NextPolarVector2(groupConfig.MinOffset, groupConfig.MaxOffset)).Floored();
- var dataCopy = groupConfig.Data.Clone();
- dataCopy.Apply(data);
+ switch (prototypo.InheritDungeons)
+ {
+ case DungeonInheritance.All:
+ dungeons.AddRange(await GetDungeons(position, groupConfig, groupConfig.Layers, reservedTiles, seed, random, existing: dungeons));
+ break;
+ case DungeonInheritance.Last:
+ dungeons.AddRange(await GetDungeons(position, groupConfig, groupConfig.Layers, reservedTiles, seed, random, existing: dungeons.GetRange(dungeons.Count - 1, 1)));
+ break;
+ case DungeonInheritance.None:
+ dungeons.AddRange(await GetDungeons(position, groupConfig, groupConfig.Layers, reservedTiles, seed, random));
+ break;
+ }
- dungeons.AddRange(await GetDungeons(position, groupConfig, dataCopy, groupConfig.Layers, reservedTiles, seed, random));
break;
case ReplaceTileDunGen replace:
- dungeons.Add(await GenerateTileReplacementDunGen(replace, data, reservedTiles, random));
+ await GenerateTileReplacementDunGen(replace, dungeons, reservedTiles, random);
break;
case RoomEntranceDunGen rEntrance:
- await PostGen(rEntrance, data, dungeons[^1], reservedTiles, random);
+ await PostGen(rEntrance, dungeons[^1], reservedTiles, random);
break;
case SplineDungeonConnectorDunGen spline:
- dungeons.Add(await PostGen(spline, data, dungeons, reservedTiles, random));
+ dungeons.Add(await PostGen(spline, dungeons, reservedTiles, random));
break;
case WallMountDunGen wall:
- await PostGen(wall, data, dungeons[^1], reservedTiles, random);
+ await PostGen(wall, dungeons[^1], reservedTiles, random);
break;
case WormCorridorDunGen worm:
- await PostGen(worm, data, dungeons[^1], reservedTiles, random);
+ await PostGen(worm, dungeons[^1], reservedTiles, random);
break;
default:
throw new NotImplementedException();
diff --git a/Content.Shared/EntityTable/EntityTableSystem.cs b/Content.Shared/EntityTable/EntityTableSystem.cs
index ff499e6760..eab8b87ad7 100644
--- a/Content.Shared/EntityTable/EntityTableSystem.cs
+++ b/Content.Shared/EntityTable/EntityTableSystem.cs
@@ -9,6 +9,12 @@ public sealed class EntityTableSystem : EntitySystem
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;
+ public IEnumerable GetSpawns(EntityTablePrototype entTableProto, System.Random? rand = null)
+ {
+ // convenient
+ return GetSpawns(entTableProto.Table, rand);
+ }
+
public IEnumerable GetSpawns(EntityTableSelector? table, System.Random? rand = null)
{
if (table == null)
diff --git a/Content.Shared/Procedural/DungeonConfig.cs b/Content.Shared/Procedural/DungeonConfig.cs
index 2c2adc1803..7c84b1a6a3 100644
--- a/Content.Shared/Procedural/DungeonConfig.cs
+++ b/Content.Shared/Procedural/DungeonConfig.cs
@@ -5,12 +5,6 @@ namespace Content.Shared.Procedural;
[Virtual, DataDefinition]
public partial class DungeonConfig
{
- ///
- ///
- ///
- [DataField]
- public DungeonData Data = DungeonData.Empty;
-
///
/// The secret sauce, procedural generation layers that get run.
///
diff --git a/Content.Shared/Procedural/DungeonData.cs b/Content.Shared/Procedural/DungeonData.cs
deleted file mode 100644
index f15d974555..0000000000
--- a/Content.Shared/Procedural/DungeonData.cs
+++ /dev/null
@@ -1,105 +0,0 @@
-using System.Linq;
-using Content.Shared.Maps;
-using Content.Shared.Storage;
-using Content.Shared.Whitelist;
-using Robust.Shared.Prototypes;
-using Robust.Shared.Utility;
-
-namespace Content.Shared.Procedural;
-
-///
-/// Used to set dungeon values for all layers.
-///
-///
-/// This lets us share data between different dungeon configs without having to repeat entire configs.
-///
-[DataRecord]
-public sealed partial class DungeonData
-{
- // I hate this but it also significantly reduces yaml bloat if we add like 10 variations on the same set of layers
- // e.g. science rooms, engi rooms, cargo rooms all under PlanetBase for example.
- // without having to do weird nesting. It also means we don't need to copy-paste the same prototype across several layers
- // The alternative is doing like,
- // 2 layer prototype, 1 layer with the specified data, 3 layer prototype, 2 layers with specified data, etc.
- // As long as we just keep the code clean over time it won't be bad to maintain.
-
- public static DungeonData Empty = new();
-
- public Dictionary Colors = new();
- public Dictionary Entities = new();
- public Dictionary> SpawnGroups = new();
- public Dictionary> Tiles = new();
- public Dictionary Whitelists = new();
-
- ///
- /// Applies the specified data to this data.
- ///
- public void Apply(DungeonData data)
- {
- // Copy-paste moment.
- foreach (var color in data.Colors)
- {
- Colors[color.Key] = color.Value;
- }
-
- foreach (var color in data.Entities)
- {
- Entities[color.Key] = color.Value;
- }
-
- foreach (var color in data.SpawnGroups)
- {
- SpawnGroups[color.Key] = color.Value;
- }
-
- foreach (var color in data.Tiles)
- {
- Tiles[color.Key] = color.Value;
- }
-
- foreach (var color in data.Whitelists)
- {
- Whitelists[color.Key] = color.Value;
- }
- }
-
- public DungeonData Clone()
- {
- return new DungeonData
- {
- // Only shallow clones but won't matter for DungeonJob purposes.
- Colors = Colors.ShallowClone(),
- Entities = Entities.ShallowClone(),
- SpawnGroups = SpawnGroups.ShallowClone(),
- Tiles = Tiles.ShallowClone(),
- Whitelists = Whitelists.ShallowClone(),
- };
- }
-}
-
-public enum DungeonDataKey : byte
-{
- // Colors
- Decals,
-
- // Entities
- Cabling,
- CornerWalls,
- Fill,
- Junction,
- Walls,
-
- // SpawnGroups
- CornerClutter,
- Entrance,
- EntranceFlank,
- WallMounts,
- Window,
-
- // Tiles
- FallbackTile,
- WidenTile,
-
- // Whitelists
- Rooms,
-}
diff --git a/Content.Shared/Procedural/DungeonGenerators/PrefabDunGen.cs b/Content.Shared/Procedural/DungeonGenerators/PrefabDunGen.cs
index aeb24d0144..a9a6d12de4 100644
--- a/Content.Shared/Procedural/DungeonGenerators/PrefabDunGen.cs
+++ b/Content.Shared/Procedural/DungeonGenerators/PrefabDunGen.cs
@@ -1,3 +1,5 @@
+using Content.Shared.Maps;
+using Content.Shared.Whitelist;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.DungeonGenerators;
@@ -6,10 +8,6 @@ namespace Content.Shared.Procedural.DungeonGenerators;
/// Places rooms in pre-selected pack layouts. Chooses rooms from the specified whitelist.
///
///
-/// DungeonData keys are:
-/// - FallbackTile
-/// - Rooms
-///
public sealed partial class PrefabDunGen : IDunGenLayer
{
///
@@ -17,4 +15,10 @@ public sealed partial class PrefabDunGen : IDunGenLayer
///
[DataField(required: true)]
public List> Presets = new();
+
+ [DataField]
+ public EntityWhitelist? RoomWhitelist;
+
+ [DataField]
+ public ProtoId? FallbackTile;
}
diff --git a/Content.Shared/Procedural/DungeonGenerators/PrototypeDunGen.cs b/Content.Shared/Procedural/DungeonGenerators/PrototypeDunGen.cs
index 2772c97977..89a4ab216a 100644
--- a/Content.Shared/Procedural/DungeonGenerators/PrototypeDunGen.cs
+++ b/Content.Shared/Procedural/DungeonGenerators/PrototypeDunGen.cs
@@ -8,6 +8,30 @@ namespace Content.Shared.Procedural.DungeonGenerators;
///
public sealed partial class PrototypeDunGen : IDunGenLayer
{
+ ///
+ /// Should we pass in the current level's dungeons to the prototype.
+ ///
+ [DataField]
+ public DungeonInheritance InheritDungeons = DungeonInheritance.None;
+
[DataField(required: true)]
public ProtoId Proto;
}
+
+public enum DungeonInheritance : byte
+{
+ ///
+ /// Don't inherit any of the current layer's dungeons for this
+ ///
+ None,
+
+ ///
+ /// Inherit only the last dungeon ran.
+ ///
+ Last,
+
+ ///
+ /// Inherit all of the current layer's dungeons.
+ ///
+ All,
+}
diff --git a/Content.Shared/Procedural/DungeonGenerators/FillGridDunGen.cs b/Content.Shared/Procedural/DungeonLayers/FillGridDunGen.cs
similarity index 79%
rename from Content.Shared/Procedural/DungeonGenerators/FillGridDunGen.cs
rename to Content.Shared/Procedural/DungeonLayers/FillGridDunGen.cs
index 53c7dd8c66..363de0a511 100644
--- a/Content.Shared/Procedural/DungeonGenerators/FillGridDunGen.cs
+++ b/Content.Shared/Procedural/DungeonLayers/FillGridDunGen.cs
@@ -1,7 +1,7 @@
using Content.Shared.Maps;
using Robust.Shared.Prototypes;
-namespace Content.Shared.Procedural.DungeonGenerators;
+namespace Content.Shared.Procedural.DungeonLayers;
///
/// Fills unreserved tiles with the specified entity prototype.
@@ -17,4 +17,7 @@ public sealed partial class FillGridDunGen : IDunGenLayer
///
[DataField]
public HashSet>? AllowedTiles;
+
+ [DataField(required: true)]
+ public EntProtoId Entity;
}
diff --git a/Content.Shared/Procedural/DungeonLayers/MobsDunGen.cs b/Content.Shared/Procedural/DungeonLayers/MobsDunGen.cs
index 30b502efe0..5525341eb9 100644
--- a/Content.Shared/Procedural/DungeonLayers/MobsDunGen.cs
+++ b/Content.Shared/Procedural/DungeonLayers/MobsDunGen.cs
@@ -1,4 +1,6 @@
+using Content.Shared.EntityTable;
using Content.Shared.Storage;
+using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.DungeonLayers;
@@ -17,5 +19,5 @@ public sealed partial class MobsDunGen : IDunGenLayer
public int MaxCount = 1;
[DataField(required: true)]
- public List Groups = new();
+ public ProtoId Contents;
}
diff --git a/Content.Shared/Procedural/Loot/BiomeTemplateLoot.cs b/Content.Shared/Procedural/Loot/BiomeTemplateLoot.cs
index 1947779768..e4968b6e42 100644
--- a/Content.Shared/Procedural/Loot/BiomeTemplateLoot.cs
+++ b/Content.Shared/Procedural/Loot/BiomeTemplateLoot.cs
@@ -1,4 +1,5 @@
using Content.Shared.Parallax.Biomes;
+using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared.Procedural.Loot;
@@ -8,6 +9,6 @@ namespace Content.Shared.Procedural.Loot;
///
public sealed partial class BiomeTemplateLoot : IDungeonLoot
{
- [DataField("proto", required: true, customTypeSerializer:typeof(PrototypeIdSerializer))]
- public string Prototype = string.Empty;
+ [DataField("proto", required: true)]
+ public ProtoId Prototype = string.Empty;
}
diff --git a/Content.Shared/Procedural/PostGeneration/AutoCablingDunGen.cs b/Content.Shared/Procedural/PostGeneration/AutoCablingDunGen.cs
index 5afad7edb1..f6588aee41 100644
--- a/Content.Shared/Procedural/PostGeneration/AutoCablingDunGen.cs
+++ b/Content.Shared/Procedural/PostGeneration/AutoCablingDunGen.cs
@@ -1,10 +1,12 @@
+using Robust.Shared.Prototypes;
+
namespace Content.Shared.Procedural.PostGeneration;
///
/// Runs cables throughout the dungeon.
///
-///
-/// DungeonData keys are:
-/// - Cabling
-///
-public sealed partial class AutoCablingDunGen : IDunGenLayer;
+public sealed partial class AutoCablingDunGen : IDunGenLayer
+{
+ [DataField(required: true)]
+ public EntProtoId Entity;
+}
diff --git a/Content.Shared/Procedural/PostGeneration/BoundaryWallDunGen.cs b/Content.Shared/Procedural/PostGeneration/BoundaryWallDunGen.cs
index 4151527f8a..19e9d67343 100644
--- a/Content.Shared/Procedural/PostGeneration/BoundaryWallDunGen.cs
+++ b/Content.Shared/Procedural/PostGeneration/BoundaryWallDunGen.cs
@@ -1,3 +1,6 @@
+using Content.Shared.Maps;
+using Robust.Shared.Prototypes;
+
namespace Content.Shared.Procedural.PostGeneration;
///
@@ -13,6 +16,15 @@ public sealed partial class BoundaryWallDunGen : IDunGenLayer
{
[DataField]
public BoundaryWallFlags Flags = BoundaryWallFlags.Corridors | BoundaryWallFlags.Rooms;
+
+ [DataField(required: true)]
+ public EntProtoId Wall;
+
+ [DataField]
+ public EntProtoId? CornerWall;
+
+ [DataField(required: true)]
+ public ProtoId Tile;
}
[Flags]
diff --git a/Content.Shared/Procedural/PostGeneration/CornerClutterDunGen.cs b/Content.Shared/Procedural/PostGeneration/CornerClutterDunGen.cs
index 2a904281c8..dc048cfb55 100644
--- a/Content.Shared/Procedural/PostGeneration/CornerClutterDunGen.cs
+++ b/Content.Shared/Procedural/PostGeneration/CornerClutterDunGen.cs
@@ -1,14 +1,17 @@
+using Content.Shared.EntityTable;
+using Content.Shared.Storage;
+using Robust.Shared.Prototypes;
+
namespace Content.Shared.Procedural.PostGeneration;
///
/// Spawns entities inside corners.
///
-///
-/// Dungeon data keys are:
-/// - CornerClutter
-///
public sealed partial class CornerClutterDunGen : IDunGenLayer
{
[DataField]
public float Chance = 0.50f;
+
+ [DataField(required:true)]
+ public ProtoId Contents = new();
}
diff --git a/Content.Shared/Procedural/PostGeneration/CorridorClutterDunGen.cs b/Content.Shared/Procedural/PostGeneration/CorridorClutterDunGen.cs
index 5b397b40df..8e3d092d1b 100644
--- a/Content.Shared/Procedural/PostGeneration/CorridorClutterDunGen.cs
+++ b/Content.Shared/Procedural/PostGeneration/CorridorClutterDunGen.cs
@@ -1,4 +1,6 @@
+using Content.Shared.EntityTable;
using Content.Shared.Storage;
+using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;
@@ -14,5 +16,5 @@ public sealed partial class CorridorClutterDunGen : IDunGenLayer
/// The default starting bulbs
///
[DataField(required: true)]
- public List Contents = new();
+ public ProtoId Contents;
}
diff --git a/Content.Shared/Procedural/PostGeneration/CorridorDecalSkirtingDunGen.cs b/Content.Shared/Procedural/PostGeneration/CorridorDecalSkirtingDunGen.cs
index e609043655..fac9dc97da 100644
--- a/Content.Shared/Procedural/PostGeneration/CorridorDecalSkirtingDunGen.cs
+++ b/Content.Shared/Procedural/PostGeneration/CorridorDecalSkirtingDunGen.cs
@@ -1,7 +1,3 @@
-using Content.Shared.Decals;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
-
namespace Content.Shared.Procedural.PostGeneration;
///
@@ -26,4 +22,10 @@ public sealed partial class CorridorDecalSkirtingDunGen : IDunGenLayer
///
[DataField]
public Dictionary CornerDecals = new();
+
+ ///
+ /// Optional color to apply to the decals.
+ ///
+ [DataField]
+ public Color? Color;
}
diff --git a/Content.Shared/Procedural/PostGeneration/CorridorDunGen.cs b/Content.Shared/Procedural/PostGeneration/CorridorDunGen.cs
index 6d75cd9cb2..b36c6f9b64 100644
--- a/Content.Shared/Procedural/PostGeneration/CorridorDunGen.cs
+++ b/Content.Shared/Procedural/PostGeneration/CorridorDunGen.cs
@@ -1,12 +1,11 @@
+using Content.Shared.Maps;
+using Robust.Shared.Prototypes;
+
namespace Content.Shared.Procedural.PostGeneration;
///
/// Connects room entrances via corridor segments.
///
-///
-/// Dungeon data keys are:
-/// - FallbackTile
-///
public sealed partial class CorridorDunGen : IDunGenLayer
{
///
@@ -23,4 +22,7 @@ public sealed partial class CorridorDunGen : IDunGenLayer
///
[DataField]
public float Width = 3f;
+
+ [DataField(required: true)]
+ public ProtoId Tile;
}
diff --git a/Content.Shared/Procedural/PostGeneration/DungeonEntranceDunGen.cs b/Content.Shared/Procedural/PostGeneration/DungeonEntranceDunGen.cs
index 40cc95f5fc..406054cfdc 100644
--- a/Content.Shared/Procedural/PostGeneration/DungeonEntranceDunGen.cs
+++ b/Content.Shared/Procedural/PostGeneration/DungeonEntranceDunGen.cs
@@ -1,13 +1,13 @@
+using Content.Shared.EntityTable;
+using Content.Shared.Maps;
+using Content.Shared.Storage;
+using Robust.Shared.Prototypes;
+
namespace Content.Shared.Procedural.PostGeneration;
///
/// Selects [count] rooms and places external doors to them.
///
-///
-/// Dungeon data keys are:
-/// - Entrance
-/// - FallbackTile
-///
public sealed partial class DungeonEntranceDunGen : IDunGenLayer
{
///
@@ -15,4 +15,10 @@ public sealed partial class DungeonEntranceDunGen : IDunGenLayer
///
[DataField]
public int Count = 1;
+
+ [DataField(required: true)]
+ public ProtoId Tile;
+
+ [DataField(required: true)]
+ public ProtoId Contents;
}
diff --git a/Content.Shared/Procedural/PostGeneration/EntranceFlankDunGen.cs b/Content.Shared/Procedural/PostGeneration/EntranceFlankDunGen.cs
index 27baa48ec6..f9be6caf6a 100644
--- a/Content.Shared/Procedural/PostGeneration/EntranceFlankDunGen.cs
+++ b/Content.Shared/Procedural/PostGeneration/EntranceFlankDunGen.cs
@@ -1,11 +1,17 @@
+using Content.Shared.EntityTable;
+using Content.Shared.Maps;
+using Robust.Shared.Prototypes;
+
namespace Content.Shared.Procedural.PostGeneration;
///
/// Spawns entities on either side of an entrance.
///
-///
-/// Dungeon data keys are:
-/// - FallbackTile
-/// -
-///
-public sealed partial class EntranceFlankDunGen : IDunGenLayer;
+public sealed partial class EntranceFlankDunGen : IDunGenLayer
+{
+ [DataField(required: true)]
+ public ProtoId Tile;
+
+ [DataField(required: true)]
+ public ProtoId Contents = new();
+}
diff --git a/Content.Shared/Procedural/PostGeneration/ExternalWindowDunGen.cs b/Content.Shared/Procedural/PostGeneration/ExternalWindowDunGen.cs
index 0b29344b90..fc992ea7b8 100644
--- a/Content.Shared/Procedural/PostGeneration/ExternalWindowDunGen.cs
+++ b/Content.Shared/Procedural/PostGeneration/ExternalWindowDunGen.cs
@@ -1,11 +1,18 @@
+using Content.Shared.EntityTable;
+using Content.Shared.Maps;
+using Content.Shared.Storage;
+using Robust.Shared.Prototypes;
+
namespace Content.Shared.Procedural.PostGeneration;
///
/// If external areas are found will try to generate windows.
///
-///
-/// Dungeon data keys are:
-/// - EntranceFlank
-/// - FallbackTile
-///
-public sealed partial class ExternalWindowDunGen : IDunGenLayer;
+public sealed partial class ExternalWindowDunGen : IDunGenLayer
+{
+ [DataField(required: true)]
+ public ProtoId Tile;
+
+ [DataField(required: true)]
+ public ProtoId Contents;
+}
diff --git a/Content.Shared/Procedural/PostGeneration/InternalWindowDunGen.cs b/Content.Shared/Procedural/PostGeneration/InternalWindowDunGen.cs
index 11b1c6a785..22a4839ce2 100644
--- a/Content.Shared/Procedural/PostGeneration/InternalWindowDunGen.cs
+++ b/Content.Shared/Procedural/PostGeneration/InternalWindowDunGen.cs
@@ -1,11 +1,17 @@
+using Content.Shared.EntityTable;
+using Content.Shared.Maps;
+using Robust.Shared.Prototypes;
+
namespace Content.Shared.Procedural.PostGeneration;
///
/// If internal areas are found will try to generate windows.
///
-///
-/// Dungeon data keys are:
-/// - FallbackTile
-/// - Window
-///
-public sealed partial class InternalWindowDunGen : IDunGenLayer;
+public sealed partial class InternalWindowDunGen : IDunGenLayer
+{
+ [DataField(required: true)]
+ public ProtoId Tile;
+
+ [DataField(required: true)]
+ public ProtoId Contents;
+}
diff --git a/Content.Shared/Procedural/PostGeneration/JunctionDunGen.cs b/Content.Shared/Procedural/PostGeneration/JunctionDunGen.cs
index 899f271621..f18f63ddfe 100644
--- a/Content.Shared/Procedural/PostGeneration/JunctionDunGen.cs
+++ b/Content.Shared/Procedural/PostGeneration/JunctionDunGen.cs
@@ -1,13 +1,13 @@
+using Content.Shared.EntityTable;
+using Content.Shared.Maps;
+using Content.Shared.Storage;
+using Robust.Shared.Prototypes;
+
namespace Content.Shared.Procedural.PostGeneration;
///
/// Places the specified entities at junction areas.
///
-///
-/// Dungeon data keys are:
-/// - Entrance
-/// - FallbackTile
-///
public sealed partial class JunctionDunGen : IDunGenLayer
{
///
@@ -15,4 +15,10 @@ public sealed partial class JunctionDunGen : IDunGenLayer
///
[DataField]
public int Width = 3;
+
+ [DataField(required: true)]
+ public ProtoId Tile;
+
+ [DataField(required: true)]
+ public ProtoId Contents;
}
diff --git a/Content.Shared/Procedural/PostGeneration/MiddleConnectionDunGen.cs b/Content.Shared/Procedural/PostGeneration/MiddleConnectionDunGen.cs
index a5758c1498..a1040fef9b 100644
--- a/Content.Shared/Procedural/PostGeneration/MiddleConnectionDunGen.cs
+++ b/Content.Shared/Procedural/PostGeneration/MiddleConnectionDunGen.cs
@@ -1,3 +1,8 @@
+using Content.Shared.EntityTable;
+using Content.Shared.Maps;
+using Content.Shared.Storage;
+using Robust.Shared.Prototypes;
+
namespace Content.Shared.Procedural.PostGeneration;
///
@@ -16,4 +21,13 @@ public sealed partial class MiddleConnectionDunGen : IDunGenLayer
///
[DataField]
public int Count = 1;
+
+ [DataField(required: true)]
+ public ProtoId Tile;
+
+ [DataField(required: true)]
+ public ProtoId Contents;
+
+ [DataField]
+ public ProtoId? Flank;
}
diff --git a/Content.Shared/Procedural/PostGeneration/RoomEntranceDunGen.cs b/Content.Shared/Procedural/PostGeneration/RoomEntranceDunGen.cs
index d3b5672dcb..1436f7473d 100644
--- a/Content.Shared/Procedural/PostGeneration/RoomEntranceDunGen.cs
+++ b/Content.Shared/Procedural/PostGeneration/RoomEntranceDunGen.cs
@@ -1,11 +1,18 @@
+using Content.Shared.EntityTable;
+using Content.Shared.Maps;
+using Content.Shared.Storage;
+using Robust.Shared.Prototypes;
+
namespace Content.Shared.Procedural.PostGeneration;
///
/// Places tiles / entities onto room entrances.
///
-///
-/// DungeonData keys are:
-/// - Entrance
-/// - FallbackTile
-///
-public sealed partial class RoomEntranceDunGen : IDunGenLayer;
+public sealed partial class RoomEntranceDunGen : IDunGenLayer
+{
+ [DataField(required: true)]
+ public ProtoId Tile;
+
+ [DataField]
+ public ProtoId Contents;
+}
diff --git a/Content.Shared/Procedural/PostGeneration/SplineDungeonConnectorDunGen.cs b/Content.Shared/Procedural/PostGeneration/SplineDungeonConnectorDunGen.cs
index ec8349c671..d2f5a2126a 100644
--- a/Content.Shared/Procedural/PostGeneration/SplineDungeonConnectorDunGen.cs
+++ b/Content.Shared/Procedural/PostGeneration/SplineDungeonConnectorDunGen.cs
@@ -1,3 +1,6 @@
+using Content.Shared.Maps;
+using Robust.Shared.Prototypes;
+
namespace Content.Shared.Procedural.PostGeneration;
///
@@ -5,6 +8,12 @@ namespace Content.Shared.Procedural.PostGeneration;
///
public sealed partial class SplineDungeonConnectorDunGen : IDunGenLayer
{
+ [DataField(required: true)]
+ public ProtoId Tile;
+
+ [DataField]
+ public ProtoId? WidenTile;
+
///
/// Will divide the distance between the start and end points so that no subdivision is more than these metres away.
///
diff --git a/Content.Shared/Procedural/PostGeneration/WallMountDunGen.cs b/Content.Shared/Procedural/PostGeneration/WallMountDunGen.cs
index a5c790cb22..2a47146ca6 100644
--- a/Content.Shared/Procedural/PostGeneration/WallMountDunGen.cs
+++ b/Content.Shared/Procedural/PostGeneration/WallMountDunGen.cs
@@ -1,3 +1,8 @@
+using Content.Shared.EntityTable;
+using Content.Shared.Maps;
+using Content.Shared.Storage;
+using Robust.Shared.Prototypes;
+
namespace Content.Shared.Procedural.PostGeneration;
///
@@ -10,4 +15,10 @@ public sealed partial class WallMountDunGen : IDunGenLayer
///
[DataField]
public double Prob = 0.1;
+
+ [DataField(required: true)]
+ public ProtoId Tile;
+
+ [DataField(required: true)]
+ public ProtoId Contents;
}
diff --git a/Content.Shared/Procedural/PostGeneration/WormCorridorDunGen.cs b/Content.Shared/Procedural/PostGeneration/WormCorridorDunGen.cs
index b71e845a73..a587d03a7c 100644
--- a/Content.Shared/Procedural/PostGeneration/WormCorridorDunGen.cs
+++ b/Content.Shared/Procedural/PostGeneration/WormCorridorDunGen.cs
@@ -1,3 +1,6 @@
+using Content.Shared.Maps;
+using Robust.Shared.Prototypes;
+
namespace Content.Shared.Procedural.PostGeneration;
// Ime a worm
@@ -32,4 +35,7 @@ public sealed partial class WormCorridorDunGen : IDunGenLayer
///
[DataField]
public float Width = 3f;
+
+ [DataField(required: true)]
+ public ProtoId Tile;
}
diff --git a/Content.Shared/Salvage/SharedSalvageSystem.Magnet.cs b/Content.Shared/Salvage/SharedSalvageSystem.Magnet.cs
index c041722479..3950b1b72b 100644
--- a/Content.Shared/Salvage/SharedSalvageSystem.Magnet.cs
+++ b/Content.Shared/Salvage/SharedSalvageSystem.Magnet.cs
@@ -50,12 +50,8 @@ public abstract partial class SharedSalvageSystem
var configProto =_proto.Index(configId);
var layers = new Dictionary();
- var data = new DungeonData();
- data.Apply(configProto.Data);
-
var config = new DungeonConfig
{
- Data = data,
Layers = new(configProto.Layers),
MaxCount = configProto.MaxCount,
MaxOffset = configProto.MaxOffset,
diff --git a/Content.Shared/Storage/EntitySpawnEntry.cs b/Content.Shared/Storage/EntitySpawnEntry.cs
index 480863692e..c00d9e100b 100644
--- a/Content.Shared/Storage/EntitySpawnEntry.cs
+++ b/Content.Shared/Storage/EntitySpawnEntry.cs
@@ -76,6 +76,18 @@ public static class EntitySpawnCollection
public float CumulativeProbability { get; set; } = 0f;
}
+ public static List GetSpawns(ProtoId proto, IPrototypeManager? protoManager = null, IRobustRandom? random = null)
+ {
+ IoCManager.Resolve(ref protoManager, ref random);
+ return GetSpawns(protoManager.Index(proto).Entries, random);
+ }
+
+ public static List GetSpawns(ProtoId proto, System.Random random, IPrototypeManager? protoManager = null)
+ {
+ IoCManager.Resolve(ref protoManager);
+ return GetSpawns(protoManager.Index(proto).Entries, random);
+ }
+
///
/// Using a collection of entity spawn entries, picks a random list of entity prototypes to spawn from that collection.
///
diff --git a/Resources/Prototypes/Procedural/dungeon_configs.yml b/Resources/Prototypes/Procedural/dungeon_configs.yml
index c296aafad6..5da9592995 100644
--- a/Resources/Prototypes/Procedural/dungeon_configs.yml
+++ b/Resources/Prototypes/Procedural/dungeon_configs.yml
@@ -1,8 +1,11 @@
-# Base configs
+# Setups
- type: dungeonConfig
- id: PlanetBase
+ id: Experiment
layers:
- !type:PrefabDunGen
+ roomWhitelist:
+ tags:
+ - SalvageExperiment
presets:
- Bucket
- Wow
@@ -11,28 +14,49 @@
- !type:CorridorDunGen
width: 3
+ tile: FloorSteel
- !type:DungeonEntranceDunGen
count: 2
+ tile: FloorSteel
+ contents: BaseAirlock
- !type:RoomEntranceDunGen
+ tile: FloorSteel
+ contents: BaseAirlock
- !type:EntranceFlankDunGen
+ tile: FloorSteel
+ contents: BaseWindow
- !type:ExternalWindowDunGen
+ tile: FloorSteel
+ contents: BaseWindow
- !type:WallMountDunGen
+ contents: ScienceLabsWalls
+ tile: FloorSteel
- !type:BoundaryWallDunGen
+ wall: WallSolid
+ cornerWall: WallReinforced
+ tile: FloorSteel
- !type:JunctionDunGen
width: 1
+ tile: FloorSteel
+ contents: BaseAirlock
- !type:JunctionDunGen
+ width: 3
+ tile: FloorSteel
+ contents: BaseAirlock
- !type:AutoCablingDunGen
+ entity: CableApcExtension
- !type:CornerClutterDunGen
+ contents: BaseClutter
- !type:CorridorDecalSkirtingDunGen
cardinalDecals:
@@ -51,44 +75,8 @@
NorthWest: BrickTileWhiteInnerNw
NorthEast: BrickTileWhiteInnerNe
-# Setups
-- type: dungeonConfig
- id: Experiment
- data:
- colors:
- Decals: "#D381C996"
- entities:
- Cabling: CableApcExtension
- CornerWalls: WallReinforced
- Walls: WallSolid
- spawnGroups:
- CornerClutter: BaseClutter
- Entrance: BaseAirlock
- EntranceFlank: BaseWindow
- Junction: BaseAirlock
- WallMounts: ScienceLabsWalls
- Window: BaseWindow
- tiles:
- FallbackTile: FloorSteel
- whitelists:
- Rooms:
- tags:
- - SalvageExperiment
- layers:
- - !type:PrototypeDunGen
- proto: PlanetBase
-
- type: dungeonConfig
id: Haunted
- data:
- entities:
- Walls: WallRock
- tiles:
- FallbackTile: FloorCaveDrought
- whitelists:
- Rooms:
- tags:
- - Mineshaft
layers:
- !type:PrefabDunGen
presets:
@@ -99,183 +87,304 @@
- !type:WormCorridorDunGen
width: 3
+ tile: FloorCaveDrought
- !type:CorridorClutterDunGen
- contents:
- - id: FloraStalagmite
+ contents: HauntedClutter
- !type:BoundaryWallDunGen
+ tile: FloorCaveDrought
+ wall: WallRock
+
+- type: entityTable
+ id: HauntedClutter
+ table: !type:GroupSelector
+ children:
+ - id: FloraStalagmite
- type: dungeonConfig
id: LavaBrig
- data:
- colors:
- Decals: "#DE3A3A96"
- entities:
- Cabling: CableApcExtension
- CornerWalls: WallReinforced
- Walls: WallSolid
- spawnGroups:
- CornerClutter: BaseClutter
- Entrance: LavaBrigEntrance
- EntranceFlank: BaseWindow
- Junction: BaseAirlock
- WallMounts: ScienceLabsWalls
- Window: BaseWindow
- tiles:
- FallbackTile: FloorDark
- whitelists:
- Rooms:
- tags:
- - LavaBrig
layers:
- - !type:PrototypeDunGen
- proto: PlanetBase
+ - !type:PrefabDunGen
+ roomWhitelist:
+ tags:
+ - LavaBrig
+ presets:
+ - Bucket
+ - Wow
+ - SpaceShip
+ - Tall
+
+ - !type:CorridorDunGen
+ width: 3
+ tile: FloorDark
+
+ - !type:DungeonEntranceDunGen
+ count: 2
+ tile: FloorDark
+ contents: LavaBrigEntrance
+
+ - !type:RoomEntranceDunGen
+ tile: FloorDark
+ contents: BaseAirlock
+
+ - !type:EntranceFlankDunGen
+ tile: FloorDark
+ contents: BaseWindow
+
+ - !type:ExternalWindowDunGen
+ tile: FloorDark
+ contents: BaseWindow
+
+ - !type:WallMountDunGen
+ contents: ScienceLabsWalls
+ tile: FloorDark
+
+ - !type:BoundaryWallDunGen
+ wall: WallSolid
+ cornerWall: WallReinforced
+ tile: FloorDark
+
+ - !type:JunctionDunGen
+ width: 1
+ tile: FloorDark
+ contents: BaseAirlock
+
+ - !type:JunctionDunGen
+ width: 3
+ tile: FloorDark
+ contents: BaseAirlock
+
+ - !type:AutoCablingDunGen
+ entity: CableApcExtension
+
+ - !type:CornerClutterDunGen
+ contents: BaseClutter
+
+ - !type:CorridorDecalSkirtingDunGen
+ cardinalDecals:
+ South: BrickTileWhiteLineS
+ East: BrickTileWhiteLineE
+ North: BrickTileWhiteLineN
+ West: BrickTileWhiteLineW
+ cornerDecals:
+ SouthEast: BrickTileWhiteCornerSe
+ SouthWest: BrickTileWhiteCornerSw
+ NorthEast: BrickTileWhiteCornerNe
+ NorthWest: BrickTileWhiteCornerNw
+ pocketDecals:
+ SouthWest: BrickTileWhiteInnerSw
+ SouthEast: BrickTileWhiteInnerSe
+ NorthWest: BrickTileWhiteInnerNw
+ NorthEast: BrickTileWhiteInnerNe
- type: dungeonConfig
id: Mineshaft
- data:
- entities:
- Cabling: Catwalk
- spawnGroups:
- CornerClutter: MineshaftClutter
- Entrance: BaseWoodWall
- EntranceFlank: BaseWoodWall
- Junction: BaseWoodSupport
- Window: BaseWoodWall
- tiles:
- FallbackTile: FloorCaveDrought
- whitelists:
- Rooms:
- tags:
- - Mineshaft
layers:
- - !type:PrototypeDunGen
- proto: PlanetBase
+ - !type:PrefabDunGen
+ roomWhitelist:
+ tags:
+ - Mineshaft
+ presets:
+ - Bucket
+ - Wow
+ - SpaceShip
+ - Tall
+
+ - !type:CorridorDunGen
+ width: 3
+ tile: FloorCaveDrought
+
+ - !type:DungeonEntranceDunGen
+ count: 2
+ tile: FloorCaveDrought
+ contents: BaseWoodWall
+
+ - !type:RoomEntranceDunGen
+ tile: FloorCaveDrought
+ contents: BaseWoodWall
+
+ - !type:EntranceFlankDunGen
+ tile: FloorCaveDrought
+ contents: BaseWoodWall
+
+ - !type:ExternalWindowDunGen
+ tile: FloorCaveDrought
+ contents: BaseWoodWall
+
+ # No wallmounts
+
+ # No boundary wall
+
+ - !type:JunctionDunGen
+ width: 1
+ tile: FloorCaveDrought
+ contents: BaseWoodSupport
+
+ - !type:JunctionDunGen
+ width: 3
+ tile: FloorCaveDrought
+ contents: BaseWoodSupport
+
+ - !type:AutoCablingDunGen
+ entity: Catwalk
+
+ - !type:CornerClutterDunGen
+ contents: MineshaftClutter
+
+# TODO: Check decal skirting fix contents in code.
- type: dungeonConfig
id: SnowyLabs
- data:
- colors:
- Decals: "#4cc7aa96"
- entities:
- Cabling: CableApcExtension
- CornerWalls: WallSilver
- Walls: WallSilver
- spawnGroups:
- CornerClutter: BaseClutter
- Entrance: SnowyLabsEntrance
- EntranceFlank: BaseWindow
- Junction: BaseAirlock
- WallMounts: SnowyLabsWalls
- Window: BaseWindow
- tiles:
- FallbackTile: FloorSteel
- whitelists:
- Rooms:
- tags:
- - SnowyLabs
layers:
- - !type:PrototypeDunGen
- proto: PlanetBase
+ - !type:PrefabDunGen
+ roomWhitelist:
+ tags:
+ - SnowyLabs
+ presets:
+ - Bucket
+ - Wow
+ - SpaceShip
+ - Tall
+
+ - !type:CorridorDunGen
+ width: 3
+ tile: FloorSteel
+
+ - !type:DungeonEntranceDunGen
+ count: 2
+ tile: FloorSteel
+ contents: BaseAirlock
+
+ - !type:RoomEntranceDunGen
+ tile: FloorSteel
+ contents: BaseAirlock
+
+ - !type:EntranceFlankDunGen
+ tile: FloorSteel
+ contents: BaseWindow
+
+ - !type:ExternalWindowDunGen
+ tile: FloorSteel
+ contents: BaseWindow
+
+ - !type:WallMountDunGen
+ contents: SnowyLabsWalls
+ tile: FloorSteel
+
+ - !type:BoundaryWallDunGen
+ wall: WallSilver
+ tile: FloorSteel
+
+ - !type:JunctionDunGen
+ width: 1
+ tile: FloorSteel
+ contents: BaseAirlock
+
+ - !type:JunctionDunGen
+ width: 3
+ tile: FloorSteel
+ contents: BaseAirlock
+
+ - !type:AutoCablingDunGen
+ entity: CableApcExtension
# Spawn groups
# Basic
-- type: entitySpawnEntry
+- type: entityTable
id: BaseClutter
- entries:
- - id: PottedPlantRandom
- amount: 1
+ table: !type:GroupSelector
+ children:
+ - id: PottedPlantRandom
+ amount: 1
-- type: entitySpawnEntry
+- type: entityTable
id: BaseAirlock
- entries:
- - id: CableApcExtension
- - id: AirlockGlass
+ table: !type:GroupSelector
+ children:
+ - id: CableApcExtension
+ - id: AirlockGlass
-- type: entitySpawnEntry
+- type: entityTable
id: BaseWindow
- entries:
- - id: Grille
- - id: Window
+ table: !type:GroupSelector
+ children:
+ - id: Grille
+ - id: Window
# Lava brig
-- type: entitySpawnEntry
+- type: entityTable
id: LavaBrigEntrance
- entries:
- - id: CableApcExtension
- - id: AirlockSecurityGlassLocked
+ table: !type:GroupSelector
+ children:
+ - id: CableApcExtension
+ - id: AirlockSecurityGlassLocked
# Mineshaft
-- type: entitySpawnEntry
+- type: entityTable
id: BaseWoodWall
- entries:
- - id: RandomWoodenWall
+ table: !type:GroupSelector
+ children:
+ - id: RandomWoodenWall
-- type: entitySpawnEntry
+- type: entityTable
id: BaseWoodSupport
- entries:
- - id: RandomWoodenSupport
+ table: !type:GroupSelector
+ children:
+ - id: RandomWoodenSupport
-- type: entitySpawnEntry
+- type: entityTable
id: MineshaftClutter
- entries:
- - id: RandomStalagmiteOrCrystal
- amount: 1
+ table: !type:GroupSelector
+ children:
+ - id: RandomStalagmiteOrCrystal
+ amount: 1
-- type: entitySpawnEntry
+- type: entityTable
id: MineshaftWalls
- entries:
- # Ore
- - id: WallRockSalt
- prob: 0.6
- orGroup: content
- - id: WallRockCoal
- prob: 0.6
- orGroup: content
- - id: WallRockTin
- prob: 0.4
- orGroup: content
- - id: WallMining
- prob: 0.8
- orGroup: content
+ table: !type:GroupSelector
+ children:
+ # Ore
+ - id: WallRockSalt
+ prob: 0.6
+ - id: WallRockCoal
+ prob: 0.6
+ - id: WallRockTin
+ prob: 0.4
+ - id: WallMining
+ prob: 0.8
# Science lab
-- type: entitySpawnEntry
+- type: entityTable
id: ScienceLabsWalls
- entries:
- # Posters
- - id: RandomPosterLegit
- orGroup: content
- - id: ExtinguisherCabinetFilled
- prob: 0.2
- orGroup: content
- - id: RandomPainting
- prob: 0.05
- orGroup: content
- - id: IntercomCommon
- prob: 0.1
- orGroup: content
+ table: !type:GroupSelector
+ children:
+ # Posters
+ - id: RandomPosterLegit
+ - id: ExtinguisherCabinetFilled
+ prob: 0.2
+ - id: RandomPainting
+ prob: 0.05
+ - id: IntercomCommon
+ prob: 0.1
# Snowy labs
-- type: entitySpawnEntry
+- type: entityTable
id: SnowyLabsEntrance
- entries:
- - id: CableApcExtension
- - id: AirlockFreezerHydroponicsLocked
+ table: !type:GroupSelector
+ children:
+ - id: CableApcExtension
+ - id: AirlockFreezerHydroponicsLocked
-- type: entitySpawnEntry
+- type: entityTable
id: SnowyLabsWalls
- entries:
- # Posters
- - id: RandomPosterLegit
- orGroup: content
- - id: ExtinguisherCabinetFilled
- prob: 0.2
- orGroup: content
- - id: RandomPainting
- prob: 0.05
- orGroup: content
- - id: IntercomScience
- prob: 0.1
- orGroup: content
+ table: !type:GroupSelector
+ children:
+ # Posters
+ - id: RandomPosterLegit
+ - id: ExtinguisherCabinetFilled
+ prob: 0.2
+ - id: RandomPainting
+ prob: 0.05
+ - id: IntercomScience
+ prob: 0.1
diff --git a/Resources/Prototypes/Procedural/vgroid.yml b/Resources/Prototypes/Procedural/vgroid.yml
index e9044720cc..7547072c4d 100644
--- a/Resources/Prototypes/Procedural/vgroid.yml
+++ b/Resources/Prototypes/Procedural/vgroid.yml
@@ -18,6 +18,7 @@
proto: VGRoidSmaller
- !type:PrototypeDunGen
proto: VGRoidSmallPaths
+ inheritDungeons: All
- !type:EntityTableDunGen
minCount: 7
maxCount: 12
@@ -26,6 +27,7 @@
# Fill
- !type:PrototypeDunGen
proto: VGRoidFill
+ inheritDungeons: All
# Ores
- !type:OreDunGen
replacement: IronRock
@@ -135,14 +137,12 @@
- type: dungeonConfig
id: VGRoidExterior
reserveTiles: true
- data:
- tiles:
- FallbackTile: PlatingAsteroid
- WidenTile: FloorAsteroidSand
layers:
- !type:PrototypeDunGen
proto: VGRoidExteriorDungeons
- !type:SplineDungeonConnectorDunGen
+ tile: PlatingAsteroid
+ widenTile: FloorAsteroidSand
- type: dungeonConfig
id: VGRoidExteriorDungeons
@@ -185,7 +185,12 @@
- !type:MobsDunGen
minCount: 8
maxCount: 15
- groups:
+ contents: VGRoidExteriorDungeonsMobs
+
+- type: entityTable
+ id: VGRoidExteriorDungeonsMobs
+ table: !type:GroupSelector
+ children:
- id: SalvageSpawnerMobMiningAsteroid
amount: 1
@@ -215,7 +220,12 @@
- !type:MobsDunGen
minCount: 25
maxCount: 35
- groups:
+ contents: VGRoidSmallPathsMobs
+
+- type: entityTable
+ id: VGRoidSmallPathsMobs
+ table: !type:GroupSelector
+ children:
- id: SalvageSpawnerMobMiningAsteroid
amount: 1
@@ -225,10 +235,8 @@
# Fill with rocks.
- type: dungeonConfig
id: VGRoidFill
- data:
- entities:
- Fill: IronRock
layers:
- !type:FillGridDunGen
+ entity: IronRock
allowedTiles:
- FloorAsteroidSand