Biome rework (#37735)

* DungeonData rework

Back to fields, serializes better, just make new layers dumby.

* wawawewa

* Fix this

* Fixes

* Port the work over

* wawawewa

* zoom

* Kinda workin

* Adjust wawa

* Unloading work

* Ore + entitytable fixes

Iterate every dungeon not just last.

* Big shot

* wawawewa

* Fixes

* true

* Fixes

# Conflicts:
#	Content.Server/Procedural/DungeonJob/DungeonJob.cs

* wawawewa

* Fixes

* Fix

* Lot of work

* wawawewa

* Fixing

* eh?

* a

* Fix a heap of stuff

* Better ignored check

* Reserve tile changes

* biome

* changes

* wawawewa

* Fixes & snow

* Shadow fixes

* wawawewa

* smol

* Add layer API

* More work

* wawawewa

* Preloads and running again

* wawawewa

* Modified

* Replacements and command

* Runtime support

* werk

* Fix expeds + dungeon alltiles

* reh

---------

Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com>
This commit is contained in:
metalgearsloth
2025-07-03 14:36:06 +10:00
committed by GitHub
parent fdf3d6715e
commit fe7b96147c
116 changed files with 3005 additions and 3537 deletions

View File

@@ -1,12 +0,0 @@
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Runs cables throughout the dungeon.
/// </summary>
public sealed partial class AutoCablingDunGen : IDunGenLayer
{
[DataField(required: true)]
public EntProtoId Entity;
}

View File

@@ -1,21 +0,0 @@
using Content.Shared.Maps;
using Content.Shared.Parallax.Biomes;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Generates a biome on top of valid tiles, then removes the biome when done.
/// Only works if no existing biome is present.
/// </summary>
public sealed partial class BiomeDunGen : IDunGenLayer
{
[DataField(required: true)]
public ProtoId<BiomeTemplatePrototype> BiomeTemplate;
/// <summary>
/// creates a biome only on the specified tiles
/// </summary>
[DataField]
public HashSet<ProtoId<ContentTileDefinition>>? TileMask;
}

View File

@@ -1,19 +0,0 @@
using Content.Shared.Random;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Spawns the specified marker layer on top of the dungeon rooms.
/// </summary>
public sealed partial class BiomeMarkerLayerDunGen : IDunGenLayer
{
/// <summary>
/// How many times to spawn marker layers; can duplicate.
/// </summary>
[DataField]
public int Count = 6;
[DataField(required: true)]
public ProtoId<WeightedRandomPrototype> MarkerTemplate;
}

View File

@@ -1,35 +0,0 @@
using Content.Shared.Maps;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Iterates room edges and places the relevant tiles and walls on any free indices.
/// </summary>
/// <remarks>
/// Dungeon data keys are:
/// - CornerWalls (Optional)
/// - FallbackTile
/// - Walls
/// </remarks>
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<ContentTileDefinition> Tile;
}
[Flags]
public enum BoundaryWallFlags : byte
{
Rooms = 1 << 0,
Corridors = 1 << 1,
}

View File

@@ -1,17 +0,0 @@
using Content.Shared.EntityTable;
using Content.Shared.Storage;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Spawns entities inside corners.
/// </summary>
public sealed partial class CornerClutterDunGen : IDunGenLayer
{
[DataField]
public float Chance = 0.50f;
[DataField(required:true)]
public ProtoId<EntityTablePrototype> Contents = new();
}

View File

@@ -1,20 +0,0 @@
using Content.Shared.EntityTable;
using Content.Shared.Storage;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Adds entities randomly to the corridors.
/// </summary>
public sealed partial class CorridorClutterDunGen : IDunGenLayer
{
[DataField]
public float Chance = 0.05f;
/// <summary>
/// The default starting bulbs
/// </summary>
[DataField(required: true)]
public ProtoId<EntityTablePrototype> Contents;
}

View File

@@ -1,31 +0,0 @@
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Applies decal skirting to corridors.
/// </summary>
public sealed partial class CorridorDecalSkirtingDunGen : IDunGenLayer
{
/// <summary>
/// Decal where 1 edge is found.
/// </summary>
[DataField]
public Dictionary<DirectionFlag, string> CardinalDecals = new();
/// <summary>
/// Decal where 1 corner edge is found.
/// </summary>
[DataField]
public Dictionary<Direction, string> PocketDecals = new();
/// <summary>
/// Decal where 2 or 3 edges are found.
/// </summary>
[DataField]
public Dictionary<DirectionFlag, string> CornerDecals = new();
/// <summary>
/// Optional color to apply to the decals.
/// </summary>
[DataField]
public Color? Color;
}

View File

@@ -1,28 +0,0 @@
using Content.Shared.Maps;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Connects room entrances via corridor segments.
/// </summary>
public sealed partial class CorridorDunGen : IDunGenLayer
{
/// <summary>
/// How far we're allowed to generate a corridor before calling it.
/// </summary>
/// <remarks>
/// Given the heavy weightings this needs to be fairly large for larger dungeons.
/// </remarks>
[DataField]
public int PathLimit = 2048;
/// <summary>
/// How wide to make the corridor.
/// </summary>
[DataField]
public float Width = 3f;
[DataField(required: true)]
public ProtoId<ContentTileDefinition> Tile;
}

View File

@@ -1,24 +0,0 @@
using Content.Shared.EntityTable;
using Content.Shared.Maps;
using Content.Shared.Storage;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Selects [count] rooms and places external doors to them.
/// </summary>
public sealed partial class DungeonEntranceDunGen : IDunGenLayer
{
/// <summary>
/// How many rooms we place doors on.
/// </summary>
[DataField]
public int Count = 1;
[DataField(required: true)]
public ProtoId<ContentTileDefinition> Tile;
[DataField(required: true)]
public ProtoId<EntityTablePrototype> Contents;
}

View File

@@ -1,17 +0,0 @@
using Content.Shared.EntityTable;
using Content.Shared.Maps;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Spawns entities on either side of an entrance.
/// </summary>
public sealed partial class EntranceFlankDunGen : IDunGenLayer
{
[DataField(required: true)]
public ProtoId<ContentTileDefinition> Tile;
[DataField(required: true)]
public ProtoId<EntityTablePrototype> Contents = new();
}

View File

@@ -1,18 +0,0 @@
using Content.Shared.EntityTable;
using Content.Shared.Maps;
using Content.Shared.Storage;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// If external areas are found will try to generate windows.
/// </summary>
public sealed partial class ExternalWindowDunGen : IDunGenLayer
{
[DataField(required: true)]
public ProtoId<ContentTileDefinition> Tile;
[DataField(required: true)]
public ProtoId<EntityTablePrototype> Contents;
}

View File

@@ -1,17 +0,0 @@
using Content.Shared.EntityTable;
using Content.Shared.Maps;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// If internal areas are found will try to generate windows.
/// </summary>
public sealed partial class InternalWindowDunGen : IDunGenLayer
{
[DataField(required: true)]
public ProtoId<ContentTileDefinition> Tile;
[DataField(required: true)]
public ProtoId<EntityTablePrototype> Contents;
}

View File

@@ -1,24 +0,0 @@
using Content.Shared.EntityTable;
using Content.Shared.Maps;
using Content.Shared.Storage;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Places the specified entities at junction areas.
/// </summary>
public sealed partial class JunctionDunGen : IDunGenLayer
{
/// <summary>
/// Width to check for junctions.
/// </summary>
[DataField]
public int Width = 3;
[DataField(required: true)]
public ProtoId<ContentTileDefinition> Tile;
[DataField(required: true)]
public ProtoId<EntityTablePrototype> Contents;
}

View File

@@ -1,33 +0,0 @@
using Content.Shared.EntityTable;
using Content.Shared.Maps;
using Content.Shared.Storage;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Places the specified entities on the middle connections between rooms
/// </summary>
public sealed partial class MiddleConnectionDunGen : IDunGenLayer
{
/// <summary>
/// How much overlap there needs to be between 2 rooms exactly.
/// </summary>
[DataField]
public int OverlapCount = -1;
/// <summary>
/// How many connections to spawn between rooms.
/// </summary>
[DataField]
public int Count = 1;
[DataField(required: true)]
public ProtoId<ContentTileDefinition> Tile;
[DataField(required: true)]
public ProtoId<EntityTablePrototype> Contents;
[DataField]
public ProtoId<EntityTablePrototype>? Flank;
}

View File

@@ -1,18 +0,0 @@
using Content.Shared.EntityTable;
using Content.Shared.Maps;
using Content.Shared.Storage;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Places tiles / entities onto room entrances.
/// </summary>
public sealed partial class RoomEntranceDunGen : IDunGenLayer
{
[DataField(required: true)]
public ProtoId<ContentTileDefinition> Tile;
[DataField]
public ProtoId<EntityTablePrototype> Contents;
}

View File

@@ -1,28 +0,0 @@
using Content.Shared.Maps;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Connects dungeons via points that get subdivided.
/// </summary>
public sealed partial class SplineDungeonConnectorDunGen : IDunGenLayer
{
[DataField(required: true)]
public ProtoId<ContentTileDefinition> Tile;
[DataField]
public ProtoId<ContentTileDefinition>? WidenTile;
/// <summary>
/// Will divide the distance between the start and end points so that no subdivision is more than these metres away.
/// </summary>
[DataField]
public int DivisionDistance = 10;
/// <summary>
/// How much each subdivision can vary from the middle.
/// </summary>
[DataField]
public float VarianceMax = 0.35f;
}

View File

@@ -1,24 +0,0 @@
using Content.Shared.EntityTable;
using Content.Shared.Maps;
using Content.Shared.Storage;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Spawns on the boundary tiles of rooms.
/// </summary>
public sealed partial class WallMountDunGen : IDunGenLayer
{
/// <summary>
/// Chance per free tile to spawn a wallmount.
/// </summary>
[DataField]
public double Prob = 0.1;
[DataField(required: true)]
public ProtoId<ContentTileDefinition> Tile;
[DataField(required: true)]
public ProtoId<EntityTablePrototype> Contents;
}

View File

@@ -1,41 +0,0 @@
using Content.Shared.Maps;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;
// Ime a worm
/// <summary>
/// Generates worm corridors.
/// </summary>
public sealed partial class WormCorridorDunGen : IDunGenLayer
{
[DataField]
public int PathLimit = 2048;
/// <summary>
/// How many times to run the worm
/// </summary>
[DataField]
public int Count = 20;
/// <summary>
/// How long to make each worm
/// </summary>
[DataField]
public int Length = 20;
/// <summary>
/// Maximum amount the angle can change in a single step.
/// </summary>
[DataField]
public Angle MaxAngleChange = Angle.FromDegrees(45);
/// <summary>
/// How wide to make the corridor.
/// </summary>
[DataField]
public float Width = 3f;
[DataField(required: true)]
public ProtoId<ContentTileDefinition> Tile;
}