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