From 95097571558c2607dc17ba8cce36b1e27ff794b6 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Sun, 9 Jul 2023 15:26:16 +1000 Subject: [PATCH] Add sub-biomes (#17855) --- .../Parallax/Biomes/Layers/BiomeMetaLayer.cs | 27 ++++++++++++ .../Parallax/Biomes/SharedBiomeSystem.cs | 44 +++++++++++++++++++ .../Prototypes/Procedural/biome_templates.yml | 37 ++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 Content.Shared/Parallax/Biomes/Layers/BiomeMetaLayer.cs diff --git a/Content.Shared/Parallax/Biomes/Layers/BiomeMetaLayer.cs b/Content.Shared/Parallax/Biomes/Layers/BiomeMetaLayer.cs new file mode 100644 index 0000000000..a33d6c522d --- /dev/null +++ b/Content.Shared/Parallax/Biomes/Layers/BiomeMetaLayer.cs @@ -0,0 +1,27 @@ +using Robust.Shared.Noise; +using Robust.Shared.Serialization; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Shared.Parallax.Biomes.Layers; + +/// +/// Contains more biome layers recursively via a biome template. +/// Can be used for sub-biomes. +/// +[Serializable, NetSerializable] +public sealed class BiomeMetaLayer : IBiomeLayer +{ + [DataField("noise")] + public FastNoiseLite Noise { get; } = new(0); + + /// + [DataField("threshold")] + public float Threshold { get; } = -1f; + + /// + [DataField("invert")] + public bool Invert { get; } + + [DataField("template", required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] + public string Template = string.Empty; +} diff --git a/Content.Shared/Parallax/Biomes/SharedBiomeSystem.cs b/Content.Shared/Parallax/Biomes/SharedBiomeSystem.cs index 4608b863dc..4780883b11 100644 --- a/Content.Shared/Parallax/Biomes/SharedBiomeSystem.cs +++ b/Content.Shared/Parallax/Biomes/SharedBiomeSystem.cs @@ -106,6 +106,23 @@ public abstract class SharedBiomeSystem : EntitySystem { var layer = layers[i]; + // Check if the tile is from meta layer, otherwise fall back to default layers. + if (layer is BiomeMetaLayer meta) + { + SetNoise(noise, oldSeed, layer.Noise); + var found = noise.GetNoise(indices.X, indices.Y); + found *= layer.Invert ? -1 : 1; + + if (found > layer.Threshold && TryGetBiomeTile(indices, ProtoManager.Index(meta.Template).Layers, noise, + grid, out tile)) + { + noise.SetSeed(oldSeed); + return true; + } + + continue; + } + if (layer is not BiomeTileLayer tileLayer) continue; @@ -184,6 +201,8 @@ public abstract class SharedBiomeSystem : EntitySystem if (!worldLayer.AllowedTiles.Contains(tileId)) continue; + break; + case BiomeMetaLayer: break; default: continue; @@ -195,7 +214,16 @@ public abstract class SharedBiomeSystem : EntitySystem value = invert ? value * -1 : value; if (value < layer.Threshold) + continue; + + if (layer is BiomeMetaLayer meta) { + if (TryGetEntity(indices, ProtoManager.Index(meta.Template).Layers, noise, grid, out entity)) + { + noise.SetSeed(oldSeed); + return true; + } + continue; } @@ -244,6 +272,8 @@ public abstract class SharedBiomeSystem : EntitySystem if (!worldLayer.AllowedTiles.Contains(tileId)) continue; + break; + case BiomeMetaLayer: break; default: continue; @@ -252,6 +282,20 @@ public abstract class SharedBiomeSystem : EntitySystem SetNoise(noise, oldSeed, layer.Noise); var invert = layer.Invert; + if (layer is BiomeMetaLayer meta) + { + var found = noise.GetNoise(indices.X, indices.Y); + found *= layer.Invert ? -1 : 1; + + if (found > layer.Threshold && TryGetDecals(indices, ProtoManager.Index(meta.Template).Layers, noise, grid, out decals)) + { + noise.SetSeed(oldSeed); + return true; + } + + continue; + } + // Check if the other layer should even render, if not then keep going. if (layer is not BiomeDecalLayer decalLayer) { diff --git a/Resources/Prototypes/Procedural/biome_templates.yml b/Resources/Prototypes/Procedural/biome_templates.yml index 51b3a28a46..1dd0a0aaa4 100644 --- a/Resources/Prototypes/Procedural/biome_templates.yml +++ b/Resources/Prototypes/Procedural/biome_templates.yml @@ -1,3 +1,40 @@ +# Contains several biomes +- type: biomeTemplate + id: Continental + layers: + - !type:BiomeMetaLayer + template: Lava + - !type:BiomeMetaLayer + template: Caves + threshold: -0.5 + noise: + frequency: 0.001 + noiseType: OpenSimplex2 + fractalType: FBm + octaves: 2 + lacunarity: 2 + gain: 0.5 + - !type:BiomeMetaLayer + template: Grasslands + threshold: 0 + noise: + frequency: 0.001 + noiseType: OpenSimplex2 + fractalType: FBm + octaves: 2 + lacunarity: 2 + gain: 0.5 + - !type:BiomeMetaLayer + template: Snow + threshold: 0.5 + noise: + frequency: 0.001 + noiseType: OpenSimplex2 + fractalType: FBm + octaves: 2 + lacunarity: 2 + gain: 0.5 + # Desert # TODO: Water in desert - type: biomeTemplate