Revert biome rework (#38724)

* Revert "Fix world generation (#38713)"

This reverts commit 10fa6ff4af.

* Revert "Biome rework (#37735)"

This reverts commit fe7b96147c.
This commit is contained in:
Pieter-Jan Briers
2025-07-03 20:48:04 +02:00
committed by GitHub
parent 047a49a505
commit e99fc501a6
116 changed files with 3541 additions and 3009 deletions

View File

@@ -1,86 +0,0 @@
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.Components;
/// <summary>
/// A layer inside of <see cref="BiomeComponent"/>
/// </summary>
[DataRecord]
public sealed record BiomeMetaLayer
{
/// <summary>
/// Chunk dimensions for this meta layer. Will try to infer it from the first layer of the dungeon if null.
/// </summary>
[DataField]
public int? Size;
/// <summary>
/// Meta layers that this one requires to be loaded first.
/// Will ensure all of the chunks for our corresponding area are loaded.
/// </summary>
public List<string>? DependsOn;
/// <summary>
/// Can this layer be unloaded if no one is in range.
/// </summary>
public bool CanUnload = true;
/// <summary>
/// Dungeon config to load inside the specified area.
/// </summary>
[DataField(required: true)]
public ProtoId<DungeonConfigPrototype> Dungeon = new();
}
[RegisterComponent]
public sealed partial class BiomeComponent : Component
{
/// <summary>
/// Can we load / unload chunks.
/// </summary>
[DataField]
public bool Enabled = true;
/// <summary>
/// Areas queued for preloading. Will add these during <see cref="BiomeLoadJob"/> and then flag as modified so they retain.
/// </summary>
[DataField]
public List<Box2i> PreloadAreas = new();
/// <summary>
/// Is there currently a job that's loading.
/// </summary>
public bool Loading = false;
[DataField]
public int Seed;
/// <summary>
/// Layer key and associated data.
/// </summary>
[DataField(required: true)]
public Dictionary<string, BiomeMetaLayer> Layers = new();
/// <summary>
/// Layer removals that are pending.
/// </summary>
[DataField]
public List<string> PendingRemovals = new();
/// <summary>
/// Data that is currently loaded.
/// </summary>
[DataField]
public Dictionary<string, Dictionary<Vector2i, DungeonData>> LoadedData = new();
/// <summary>
/// Flag modified tiles so we don't try and unload / reload them.
/// </summary>
[DataField]
public HashSet<Vector2i> ModifiedTiles = new();
/// <summary>
/// Bounds loaded by players for this tick.
/// </summary>
public List<Box2i> LoadedBounds = new();
}

View File

@@ -1,9 +0,0 @@
using Robust.Shared.GameStates;
namespace Content.Shared.Procedural.Components;
/// <summary>
/// Will forcibly unload an entity no matter what. Useful if you have consistent entities that will never be default or the likes.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed partial class BiomeForceUnloadComponent : Component;

View File

@@ -1,7 +0,0 @@
namespace Content.Shared.Procedural.Distance;
public sealed partial class DunGenDistanceSquared : IDunGenDistance
{
[DataField]
public float BlendWeight { get; set; } = 0.50f;
}

View File

@@ -12,18 +12,11 @@ public partial class DungeonConfig
public List<IDunGenLayer> Layers = new();
/// <summary>
/// Should we reserve the tiles generated by this config so no other layers at the same level can spawn on this tile?
/// Should we reserve the tiles generated by this config so no other dungeons can spawn on it within the same job?
/// </summary>
[DataField]
public bool ReserveTiles;
/// <summary>
/// Should we return the reserved tiles to the upper level.
/// Set to false if you don't care if this dungeon has its tiles overwritten at higher levels.
/// </summary>
[DataField]
public bool ReturnReserved = true;
/// <summary>
/// Minimum times to run the config.
/// </summary>

View File

@@ -1,41 +0,0 @@
using System.Linq;
using System.Numerics;
using Robust.Shared.Map;
namespace Content.Shared.Procedural;
/// <summary>
/// Contains the loaded data for a dungeon.
/// </summary>
[DataDefinition]
public sealed partial class DungeonData
{
[DataField]
public Dictionary<uint, Vector2> Decals = new();
[DataField]
public Dictionary<EntityUid, Vector2i> Entities = new();
[DataField]
public Dictionary<Vector2i, Tile> Tiles = new();
public static DungeonData Empty = new();
public void Merge(DungeonData data)
{
foreach (var did in data.Decals)
{
Decals[did.Key] = did.Value;
}
foreach (var ent in data.Entities)
{
Entities[ent.Key] = ent.Value;
}
foreach (var tile in data.Tiles)
{
Tiles[tile.Key] = tile.Value;
}
}
}

View File

@@ -1,24 +0,0 @@
using Robust.Shared.Noise;
namespace Content.Shared.Procedural.DungeonGenerators;
/// <summary>
/// Turns a chunked area into a dungeon for layer purposes. Assumes the position is the BL origin.
/// </summary>
public sealed partial class ChunkDunGen : IDunGenLayer
{
[DataField]
public int Size = 16;
/// <summary>
/// Noise to apply for each tile conditionally.
/// </summary>
[DataField]
public FastNoiseLite? Noise;
/// <summary>
/// Threshold for noise. Does nothing if <see cref="Noise"/> is null.
/// </summary>
[DataField]
public float Threshold = -1f;
}

View File

@@ -10,10 +10,4 @@ public sealed partial class ExteriorDunGen : IDunGenLayer
{
[DataField(required: true)]
public ProtoId<DungeonConfigPrototype> Proto;
/// <summary>
/// Minimum and maximum penetration.
/// </summary>
[DataField]
public Vector2i Penetration = new Vector2i(5, 15);
}

View File

@@ -14,12 +14,6 @@ public sealed partial class PrototypeDunGen : IDunGenLayer
[DataField]
public DungeonInheritance InheritDungeons = DungeonInheritance.None;
/// <summary>
/// Should we pass in the current level's reserved tiles to the prototype.
/// </summary>
[DataField]
public ReservedInheritance InheritReserved = ReservedInheritance.All;
[DataField(required: true)]
public ProtoId<DungeonConfigPrototype> Proto;
}
@@ -41,16 +35,3 @@ public enum DungeonInheritance : byte
/// </summary>
All,
}
public enum ReservedInheritance : byte
{
/// <summary>
/// Don't inherit any reserved tiles.
/// </summary>
None,
/// <summary>
/// Inherit reserved tiles,
/// </summary>
All,
}

View File

@@ -1,7 +1,4 @@
using System.Numerics;
using Content.Shared.Maps;
using Content.Shared.Procedural.Distance;
using Robust.Shared.Noise;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.DungeonLayers;
@@ -9,6 +6,10 @@ namespace Content.Shared.Procedural.DungeonLayers;
/// <summary>
/// Fills unreserved tiles with the specified entity prototype.
/// </summary>
/// <remarks>
/// DungeonData keys are:
/// - Fill
/// </remarks>
public sealed partial class FillGridDunGen : IDunGenLayer
{
/// <summary>
@@ -19,29 +20,4 @@ public sealed partial class FillGridDunGen : IDunGenLayer
[DataField(required: true)]
public EntProtoId Entity;
#region Noise
[DataField]
public bool Invert;
/// <summary>
/// Optionally don't spawn entities if the noise value matches.
/// </summary>
[DataField]
public FastNoiseLite? ReservedNoise;
/// <summary>
/// Noise threshold for <see cref="ReservedNoise"/>. Does nothing without it.
/// </summary>
[DataField]
public float Threshold = -1f;
[DataField]
public IDunGenDistance? DistanceConfig;
[DataField]
public Vector2 Size;
#endregion
}

View File

@@ -1,8 +1,10 @@
using Content.Shared.EntityTable;
using Content.Shared.Storage;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.DungeonLayers;
/// <summary>
/// Spawns mobs inside of the dungeon randomly.
/// </summary>

View File

@@ -1,15 +0,0 @@
using Robust.Shared.Noise;
namespace Content.Shared.Procedural.DungeonLayers;
/// <summary>
/// Sets tiles as rooved.
/// </summary>
public sealed partial class RoofDunGen : IDunGenLayer
{
[DataField]
public float Threshold = -1f;
[DataField]
public FastNoiseLite? Noise;
}

View File

@@ -1,36 +0,0 @@
using Content.Shared.Decals;
using Content.Shared.Maps;
using Robust.Shared.Noise;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
namespace Content.Shared.Procedural.DungeonLayers;
public sealed partial class SampleDecalDunGen : IDunGenLayer
{
/// <summary>
/// Reserve any tiles we update.
/// </summary>
[DataField]
public bool ReserveTiles = true;
[DataField(customTypeSerializer:typeof(PrototypeIdListSerializer<ContentTileDefinition>))]
public List<string> AllowedTiles { get; private set; } = new();
/// <summary>
/// Divide each tile up by this amount.
/// </summary>
[DataField]
public float Divisions = 1f;
[DataField]
public FastNoiseLite Noise { get; private set; } = new(0);
[DataField]
public float Threshold { get; private set; } = 0.8f;
[DataField] public bool Invert { get; private set; } = false;
[DataField(required: true)]
public List<ProtoId<DecalPrototype>> Decals = new();
}

View File

@@ -1,31 +0,0 @@
using Content.Shared.Maps;
using Robust.Shared.Noise;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
namespace Content.Shared.Procedural.DungeonLayers;
/// <summary>
/// Samples noise to spawn the specified entity
/// </summary>
public sealed partial class SampleEntityDunGen : IDunGenLayer
{
/// <summary>
/// Reserve any tiles we update.
/// </summary>
[DataField]
public bool ReserveTiles = true;
[DataField(customTypeSerializer:typeof(PrototypeIdListSerializer<ContentTileDefinition>))]
public List<string> AllowedTiles { get; private set; } = new();
[DataField] public FastNoiseLite Noise { get; private set; } = new(0);
[DataField]
public float Threshold { get; private set; } = 0.5f;
[DataField] public bool Invert { get; private set; } = false;
[DataField]
public List<EntProtoId> Entities = new();
}

View File

@@ -1,35 +0,0 @@
using Content.Shared.Maps;
using Robust.Shared.Noise;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
namespace Content.Shared.Procedural.DungeonLayers;
/// <summary>
/// Samples noise and spawns the specified tile in the dungeon area.
/// </summary>
[Serializable, NetSerializable]
public sealed partial class SampleTileDunGen : IDunGenLayer
{
/// <summary>
/// Reserve any tiles we update.
/// </summary>
[DataField]
public bool ReserveTiles = true;
[DataField] public FastNoiseLite Noise { get; private set; } = new(0);
[DataField]
public float Threshold { get; private set; } = 0.5f;
[DataField] public bool Invert { get; private set; } = false;
/// <summary>
/// Which tile variants to use for this layer. Uses all of the tile's variants if none specified
/// </summary>
[DataField]
public List<byte>? Variants = null;
[DataField(required: true)]
public ProtoId<ContentTileDefinition> Tile = string.Empty;
}

View File

@@ -1,12 +0,0 @@
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.Loot;
/// <summary>
/// Adds the prototype as a biome layer.
/// </summary>
public sealed partial class BiomeLoot : IDungeonLoot
{
[DataField(required: true)]
public ProtoId<DungeonConfigPrototype> Proto;
}

View File

@@ -0,0 +1,15 @@
using Content.Shared.Parallax.Biomes.Markers;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
namespace Content.Shared.Procedural.Loot;
/// <summary>
/// Adds a biome marker layer for dungeon loot.
/// </summary>
public sealed partial class BiomeMarkerLoot : IDungeonLoot
{
[DataField("proto", required: true)]
public ProtoId<BiomeMarkerLayerPrototype> Prototype = new();
}

View File

@@ -0,0 +1,14 @@
using Content.Shared.Parallax.Biomes;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared.Procedural.Loot;
/// <summary>
/// Adds a biome template layer for dungeon loot.
/// </summary>
public sealed partial class BiomeTemplateLoot : IDungeonLoot
{
[DataField("proto", required: true)]
public ProtoId<BiomeTemplatePrototype> Prototype = string.Empty;
}

View File

@@ -0,0 +1,21 @@
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

@@ -0,0 +1,19 @@
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,6 +1,5 @@
using Content.Shared.EntityTable;
using Content.Shared.Maps;
using Content.Shared.Storage;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;

View File

@@ -1,5 +1,6 @@
using Content.Shared.EntityTable;
using Content.Shared.Maps;
using Content.Shared.Storage;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;

View File

@@ -1,5 +1,6 @@
using Content.Shared.EntityTable;
using Content.Shared.Maps;
using Content.Shared.Storage;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.PostGeneration;

View File

@@ -1,7 +1,7 @@
using Content.Shared.Maps;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.DungeonLayers;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Connects dungeons via points that get subdivided.
@@ -18,11 +18,11 @@ public sealed partial class SplineDungeonConnectorDunGen : IDunGenLayer
/// 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 = 20;
public int DivisionDistance = 10;
/// <summary>
/// How much each subdivision can vary from the middle.
/// </summary>
[DataField]
public float VarianceMax = 0.15f;
public float VarianceMax = 0.35f;
}