Gateway destinations (#21040)
* Gateway generation * Gateway stuff * gatewehs * mercenaries * play area * Range fixes and tweaks * weh * Gateway UI polish * Lots of fixes * Knock some items off * Fix dungeon spawning Realistically we should probably be using a salvage job. * wahwah * wehvs * expression * weh * eee * a * a * WEH * frfr * Gatwey * Fix gateway windows * Fix gateway windows * a * a * Better layer masking * a * a * Noise fixes * a * Fix fractal calculations * a * More fixes * Fixes * Add layers back in * Fixes * namespaces and ftl * Other TODO * Fix distance * Cleanup * Fix test
This commit is contained in:
@@ -6,6 +6,7 @@ using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Noise;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.Manager;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Parallax.Biomes;
|
||||
@@ -13,21 +14,11 @@ namespace Content.Shared.Parallax.Biomes;
|
||||
public abstract class SharedBiomeSystem : EntitySystem
|
||||
{
|
||||
[Dependency] protected readonly IPrototypeManager ProtoManager = default!;
|
||||
[Dependency] private readonly ISerializationManager _serManager = default!;
|
||||
[Dependency] protected readonly ITileDefinitionManager TileDefManager = default!;
|
||||
|
||||
protected const byte ChunkSize = 8;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<BiomeComponent, AfterAutoHandleStateEvent>(OnBiomeAfterHandleState);
|
||||
}
|
||||
|
||||
private void OnBiomeAfterHandleState(EntityUid uid, BiomeComponent component, ref AfterAutoHandleStateEvent args)
|
||||
{
|
||||
component.Noise.SetSeed(component.Seed);
|
||||
}
|
||||
|
||||
private T Pick<T>(List<T> collection, float value)
|
||||
{
|
||||
// Listen I don't need this exact and I'm too lazy to finetune just for random ent picking.
|
||||
@@ -89,13 +80,13 @@ public abstract class SharedBiomeSystem : EntitySystem
|
||||
return false;
|
||||
}
|
||||
|
||||
return TryGetBiomeTile(indices, biome.Layers, biome.Noise, grid, out tile);
|
||||
return TryGetBiomeTile(indices, biome.Layers, biome.Seed, grid, out tile);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get the tile, real or otherwise, for the specified indices.
|
||||
/// </summary>
|
||||
public bool TryGetBiomeTile(Vector2i indices, List<IBiomeLayer> layers, FastNoiseLite noise, MapGridComponent? grid, [NotNullWhen(true)] out Tile? tile)
|
||||
public bool TryGetBiomeTile(Vector2i indices, List<IBiomeLayer> layers, int seed, MapGridComponent? grid, [NotNullWhen(true)] out Tile? tile)
|
||||
{
|
||||
if (grid?.TryGetTileRef(indices, out var tileRef) == true && !tileRef.Tile.IsEmpty)
|
||||
{
|
||||
@@ -103,23 +94,23 @@ public abstract class SharedBiomeSystem : EntitySystem
|
||||
return true;
|
||||
}
|
||||
|
||||
var oldSeed = noise.GetSeed();
|
||||
|
||||
for (var i = layers.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var layer = layers[i];
|
||||
var noiseCopy = GetNoise(layer.Noise, seed);
|
||||
|
||||
var invert = layer.Invert;
|
||||
var value = noiseCopy.GetNoise(indices.X, indices.Y);
|
||||
value = invert ? value * -1 : value;
|
||||
|
||||
if (value < layer.Threshold)
|
||||
continue;
|
||||
|
||||
// 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<BiomeTemplatePrototype>(meta.Template).Layers, noise,
|
||||
grid, out tile))
|
||||
if (TryGetBiomeTile(indices, ProtoManager.Index<BiomeTemplatePrototype>(meta.Template).Layers, seed, grid, out tile))
|
||||
{
|
||||
noise.SetSeed(oldSeed);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -129,16 +120,12 @@ public abstract class SharedBiomeSystem : EntitySystem
|
||||
if (layer is not BiomeTileLayer tileLayer)
|
||||
continue;
|
||||
|
||||
SetNoise(noise, oldSeed, layer.Noise);
|
||||
|
||||
if (TryGetTile(indices, noise, tileLayer.Invert, tileLayer.Threshold, ProtoManager.Index<ContentTileDefinition>(tileLayer.Tile), tileLayer.Variants, out tile))
|
||||
if (TryGetTile(indices, noiseCopy, tileLayer.Invert, tileLayer.Threshold, ProtoManager.Index<ContentTileDefinition>(tileLayer.Tile), tileLayer.Variants, out tile))
|
||||
{
|
||||
noise.SetSeed(oldSeed);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
noise.SetSeed(oldSeed);
|
||||
tile = null;
|
||||
return false;
|
||||
}
|
||||
@@ -146,9 +133,9 @@ public abstract class SharedBiomeSystem : EntitySystem
|
||||
/// <summary>
|
||||
/// Gets the underlying biome tile, ignoring any existing tile that may be there.
|
||||
/// </summary>
|
||||
private bool TryGetTile(Vector2i indices, FastNoiseLite seed, bool invert, float threshold, ContentTileDefinition tileDef, List<byte>? variants, [NotNullWhen(true)] out Tile? tile)
|
||||
private bool TryGetTile(Vector2i indices, FastNoiseLite noise, bool invert, float threshold, ContentTileDefinition tileDef, List<byte>? variants, [NotNullWhen(true)] out Tile? tile)
|
||||
{
|
||||
var found = seed.GetNoise(indices.X, indices.Y);
|
||||
var found = noise.GetNoise(indices.X, indices.Y);
|
||||
found = invert ? found * -1 : found;
|
||||
|
||||
if (found < threshold)
|
||||
@@ -163,7 +150,7 @@ public abstract class SharedBiomeSystem : EntitySystem
|
||||
// Pick a variant tile if they're available as well
|
||||
if (variantCount > 1)
|
||||
{
|
||||
var variantValue = (seed.GetNoise(indices.X * 8, indices.Y * 8, variantCount) + 1f) / 2f;
|
||||
var variantValue = (noise.GetNoise(indices.X * 8, indices.Y * 8, variantCount) + 1f) / 2f;
|
||||
variant = (byte) Pick(variantCount, variantValue);
|
||||
|
||||
if (variants != null)
|
||||
@@ -179,23 +166,28 @@ public abstract class SharedBiomeSystem : EntitySystem
|
||||
/// <summary>
|
||||
/// Tries to get the relevant entity for this tile.
|
||||
/// </summary>
|
||||
protected bool TryGetEntity(Vector2i indices, List<IBiomeLayer> layers, FastNoiseLite noise, MapGridComponent grid,
|
||||
public bool TryGetEntity(Vector2i indices, BiomeComponent component, MapGridComponent grid,
|
||||
[NotNullWhen(true)] out string? entity)
|
||||
{
|
||||
if (!TryGetBiomeTile(indices, layers, noise, grid, out var tileRef))
|
||||
if (!TryGetBiomeTile(indices, component.Layers, component.Seed, grid, out var tile))
|
||||
{
|
||||
entity = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
var tileId = TileDefManager[tileRef.Value.TypeId].ID;
|
||||
var oldSeed = noise.GetSeed();
|
||||
return TryGetEntity(indices, component.Layers, tile.Value, component.Seed, grid, out entity);
|
||||
}
|
||||
|
||||
|
||||
private bool TryGetEntity(Vector2i indices, List<IBiomeLayer> layers, Tile tileRef, int seed, MapGridComponent grid,
|
||||
[NotNullWhen(true)] out string? entity)
|
||||
{
|
||||
var tileId = TileDefManager[tileRef.TypeId].ID;
|
||||
|
||||
for (var i = layers.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var layer = layers[i];
|
||||
|
||||
// Decals might block entity so need to check if there's one in front of us.
|
||||
switch (layer)
|
||||
{
|
||||
case BiomeDummyLayer:
|
||||
@@ -211,9 +203,10 @@ public abstract class SharedBiomeSystem : EntitySystem
|
||||
continue;
|
||||
}
|
||||
|
||||
SetNoise(noise, oldSeed, layer.Noise);
|
||||
var noiseCopy = GetNoise(layer.Noise, seed);
|
||||
|
||||
var invert = layer.Invert;
|
||||
var value = noise.GetNoise(indices.X, indices.Y);
|
||||
var value = noiseCopy.GetNoise(indices.X, indices.Y);
|
||||
value = invert ? value * -1 : value;
|
||||
|
||||
if (value < layer.Threshold)
|
||||
@@ -221,29 +214,26 @@ public abstract class SharedBiomeSystem : EntitySystem
|
||||
|
||||
if (layer is BiomeMetaLayer meta)
|
||||
{
|
||||
if (TryGetEntity(indices, ProtoManager.Index<BiomeTemplatePrototype>(meta.Template).Layers, noise, grid, out entity))
|
||||
if (TryGetEntity(indices, ProtoManager.Index<BiomeTemplatePrototype>(meta.Template).Layers, tileRef, seed, grid, out entity))
|
||||
{
|
||||
noise.SetSeed(oldSeed);
|
||||
return true;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Decals might block entity so need to check if there's one in front of us.
|
||||
if (layer is not BiomeEntityLayer biomeLayer)
|
||||
{
|
||||
entity = null;
|
||||
noise.SetSeed(oldSeed);
|
||||
return false;
|
||||
}
|
||||
|
||||
var noiseValue = noise.GetNoise(indices.X, indices.Y, i);
|
||||
var noiseValue = noiseCopy.GetNoise(indices.X, indices.Y, i);
|
||||
entity = Pick(biomeLayer.Entities, (noiseValue + 1f) / 2f);
|
||||
noise.SetSeed(oldSeed);
|
||||
return true;
|
||||
}
|
||||
|
||||
noise.SetSeed(oldSeed);
|
||||
entity = null;
|
||||
return false;
|
||||
}
|
||||
@@ -251,17 +241,16 @@ public abstract class SharedBiomeSystem : EntitySystem
|
||||
/// <summary>
|
||||
/// Tries to get the relevant decals for this tile.
|
||||
/// </summary>
|
||||
public bool TryGetDecals(Vector2i indices, List<IBiomeLayer> layers, FastNoiseLite noise, MapGridComponent grid,
|
||||
public bool TryGetDecals(Vector2i indices, List<IBiomeLayer> layers, int seed, MapGridComponent grid,
|
||||
[NotNullWhen(true)] out List<(string ID, Vector2 Position)>? decals)
|
||||
{
|
||||
if (!TryGetBiomeTile(indices, layers, noise, grid, out var tileRef))
|
||||
if (!TryGetBiomeTile(indices, layers, seed, grid, out var tileRef))
|
||||
{
|
||||
decals = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
var tileId = TileDefManager[tileRef.Value.TypeId].ID;
|
||||
var oldSeed = noise.GetSeed();
|
||||
|
||||
for (var i = layers.Count - 1; i >= 0; i--)
|
||||
{
|
||||
@@ -283,17 +272,18 @@ public abstract class SharedBiomeSystem : EntitySystem
|
||||
continue;
|
||||
}
|
||||
|
||||
SetNoise(noise, oldSeed, layer.Noise);
|
||||
var invert = layer.Invert;
|
||||
var noiseCopy = GetNoise(layer.Noise, seed);
|
||||
var value = noiseCopy.GetNoise(indices.X, indices.Y);
|
||||
value = invert ? value * -1 : value;
|
||||
|
||||
if (value < layer.Threshold)
|
||||
continue;
|
||||
|
||||
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<BiomeTemplatePrototype>(meta.Template).Layers, noise, grid, out decals))
|
||||
if (TryGetDecals(indices, ProtoManager.Index<BiomeTemplatePrototype>(meta.Template).Layers, seed, grid, out decals))
|
||||
{
|
||||
noise.SetSeed(oldSeed);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -303,14 +293,7 @@ public abstract class SharedBiomeSystem : EntitySystem
|
||||
// Check if the other layer should even render, if not then keep going.
|
||||
if (layer is not BiomeDecalLayer decalLayer)
|
||||
{
|
||||
var value = noise.GetNoise(indices.X, indices.Y);
|
||||
value = invert ? value * -1 : value;
|
||||
|
||||
if (value < layer.Threshold)
|
||||
continue;
|
||||
|
||||
decals = null;
|
||||
noise.SetSeed(oldSeed);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -321,13 +304,13 @@ public abstract class SharedBiomeSystem : EntitySystem
|
||||
for (var y = 0; y < decalLayer.Divisions; y++)
|
||||
{
|
||||
var index = new Vector2(indices.X + x * 1f / decalLayer.Divisions, indices.Y + y * 1f / decalLayer.Divisions);
|
||||
var decalValue = noise.GetNoise(index.X, index.Y);
|
||||
var decalValue = noiseCopy.GetNoise(index.X, index.Y);
|
||||
decalValue = invert ? decalValue * -1 : decalValue;
|
||||
|
||||
if (decalValue < decalLayer.Threshold)
|
||||
continue;
|
||||
|
||||
decals.Add((Pick(decalLayer.Decals, (noise.GetNoise(indices.X, indices.Y, x + y * decalLayer.Divisions) + 1f) / 2f), index));
|
||||
decals.Add((Pick(decalLayer.Decals, (noiseCopy.GetNoise(indices.X, indices.Y, x + y * decalLayer.Divisions) + 1f) / 2f), index));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,34 +318,20 @@ public abstract class SharedBiomeSystem : EntitySystem
|
||||
if (decals.Count == 0)
|
||||
continue;
|
||||
|
||||
noise.SetSeed(oldSeed);
|
||||
return true;
|
||||
}
|
||||
|
||||
noise.SetSeed(oldSeed);
|
||||
decals = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private void SetNoise(FastNoiseLite noise, int oldSeed, FastNoiseLite data)
|
||||
private FastNoiseLite GetNoise(FastNoiseLite seedNoise, int seed)
|
||||
{
|
||||
// General
|
||||
noise.SetSeed(oldSeed + data.GetSeed());
|
||||
noise.SetFrequency(data.GetFrequency());
|
||||
noise.SetNoiseType(data.GetNoiseType());
|
||||
|
||||
noise.GetRotationType3D();
|
||||
|
||||
// Fractal
|
||||
noise.SetFractalType(data.GetFractalType());
|
||||
noise.SetFractalOctaves(data.GetFractalOctaves());
|
||||
noise.SetFractalLacunarity(data.GetFractalLacunarity());
|
||||
|
||||
// Cellular
|
||||
noise.SetCellularDistanceFunction(data.GetCellularDistanceFunction());
|
||||
noise.SetCellularReturnType(data.GetCellularReturnType());
|
||||
noise.SetCellularJitter(data.GetCellularJitter());
|
||||
|
||||
// Domain warps require separate noise
|
||||
var noiseCopy = new FastNoiseLite();
|
||||
_serManager.CopyTo(seedNoise, ref noiseCopy, notNullableOverride: true);
|
||||
noiseCopy.SetSeed(noiseCopy.GetSeed() + seed);
|
||||
// Ensure re-calculate is run.
|
||||
noiseCopy.SetFractalOctaves(noiseCopy.GetFractalOctaves());
|
||||
return noiseCopy;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user