mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-12 03:24:14 +00:00
Natural stronghold ring biomes
- The modded structure-state biome lookup resolves from the natural true biome stream, the same as the Bukkit ring search - Stronghold ring placement no longer plans hydrology tiles around its 128 positions, so chunk structure starts stop waiting on river plans out to ~24k blocks - Ring lookups are cached per runtime and cleared with the other biome caches
This commit is contained in:
@@ -72,6 +72,7 @@ final class ModdedBiomePolicy<H, S> implements NativeModdedBiomePolicy<H, S> {
|
|||||||
private volatile BiomeHolderTable<H> visibleBiomeCache = new BiomeHolderTable<>();
|
private volatile BiomeHolderTable<H> visibleBiomeCache = new BiomeHolderTable<>();
|
||||||
private volatile BiomeHolderTable<H> structureBiomeCache = new BiomeHolderTable<>();
|
private volatile BiomeHolderTable<H> structureBiomeCache = new BiomeHolderTable<>();
|
||||||
private volatile BiomeHolderTable<H> surfaceStructureBiomeCache = new BiomeHolderTable<>();
|
private volatile BiomeHolderTable<H> surfaceStructureBiomeCache = new BiomeHolderTable<>();
|
||||||
|
private volatile BiomeHolderTable<H> naturalStructureBiomeCache = new BiomeHolderTable<>();
|
||||||
private volatile RuntimeCallbacks runtime;
|
private volatile RuntimeCallbacks runtime;
|
||||||
private volatile Set<String> possibleStructureBiomeKeys;
|
private volatile Set<String> possibleStructureBiomeKeys;
|
||||||
private volatile BiomeKeySets biomeKeySets;
|
private volatile BiomeKeySets biomeKeySets;
|
||||||
@@ -94,6 +95,7 @@ final class ModdedBiomePolicy<H, S> implements NativeModdedBiomePolicy<H, S> {
|
|||||||
visibleBiomeCache = new BiomeHolderTable<>();
|
visibleBiomeCache = new BiomeHolderTable<>();
|
||||||
structureBiomeCache = new BiomeHolderTable<>();
|
structureBiomeCache = new BiomeHolderTable<>();
|
||||||
surfaceStructureBiomeCache = new BiomeHolderTable<>();
|
surfaceStructureBiomeCache = new BiomeHolderTable<>();
|
||||||
|
naturalStructureBiomeCache = new BiomeHolderTable<>();
|
||||||
warnedUnresolvedBiomeKeys.clear();
|
warnedUnresolvedBiomeKeys.clear();
|
||||||
possibleStructureBiomeKeys = null;
|
possibleStructureBiomeKeys = null;
|
||||||
biomeKeySets = null;
|
biomeKeySets = null;
|
||||||
@@ -104,6 +106,7 @@ final class ModdedBiomePolicy<H, S> implements NativeModdedBiomePolicy<H, S> {
|
|||||||
visibleBiomeCache.evictRuntime(runtimeIdentity);
|
visibleBiomeCache.evictRuntime(runtimeIdentity);
|
||||||
structureBiomeCache.evictRuntime(runtimeIdentity);
|
structureBiomeCache.evictRuntime(runtimeIdentity);
|
||||||
surfaceStructureBiomeCache.evictRuntime(runtimeIdentity);
|
surfaceStructureBiomeCache.evictRuntime(runtimeIdentity);
|
||||||
|
naturalStructureBiomeCache.evictRuntime(runtimeIdentity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -791,11 +794,40 @@ final class ModdedBiomePolicy<H, S> implements NativeModdedBiomePolicy<H, S> {
|
|||||||
if (!isReady(engine)) {
|
if (!isReady(engine)) {
|
||||||
throw new IllegalStateException("Iris structure biome lookup has no active engine runtime");
|
throw new IllegalStateException("Iris structure biome lookup has no active engine runtime");
|
||||||
}
|
}
|
||||||
return getNoiseBiome(engine, quartX, quartY, quartZ, sampler);
|
return getNaturalStructureBiome(engine, quartX, quartZ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The structure state only samples biomes for the concentric-ring search, which reaches ~24k blocks out for
|
||||||
|
// strongholds. The natural surface answers there without planning hydrology tiles, the same as the Bukkit ring search.
|
||||||
|
private H getNaturalStructureBiome(Engine engine, int quartX, int quartZ) {
|
||||||
|
long key = packColumnKey(quartX, quartZ);
|
||||||
|
int runtimeIdentity = engine.getCacheID();
|
||||||
|
BiomeHolderTable<H> cache = naturalStructureBiomeCache;
|
||||||
|
H cached = cache.get(runtimeIdentity, key);
|
||||||
|
if (cached != null) {
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
NativeBiomeSourceAccess.RegistryView<H> registry = biomeRegistry();
|
||||||
|
if (registry == null) {
|
||||||
|
throw new IllegalStateException("Iris structure biome lookup has no biome registry");
|
||||||
|
}
|
||||||
|
int blockX = quartX << 2;
|
||||||
|
int blockZ = quartZ << 2;
|
||||||
|
IrisBiome irisBiome = engine.getComplex().getNaturalTrueBiomeStream().get(blockX, blockZ);
|
||||||
|
if (irisBiome == null) {
|
||||||
|
throw new IllegalStateException("Iris returned no natural structure biome at block " + blockX + "," + blockZ);
|
||||||
|
}
|
||||||
|
H resolved = resolveHolder(registry, irisBiome.getStructureDerivativeKey());
|
||||||
|
if (resolved == null) {
|
||||||
|
throw new IllegalStateException("Iris natural structure biome derivative '"
|
||||||
|
+ irisBiome.getStructureDerivativeKey() + "' is not registered at block " + blockX + "," + blockZ);
|
||||||
|
}
|
||||||
|
cache.put(runtimeIdentity, key, resolved);
|
||||||
|
return resolved;
|
||||||
|
}
|
||||||
|
|
||||||
static long biomeResolutionSeed(long worldSeed, int blockX, int blockY, int blockZ) {
|
static long biomeResolutionSeed(long worldSeed, int blockX, int blockY, int blockZ) {
|
||||||
return worldSeed
|
return worldSeed
|
||||||
^ ((long) blockX * 341873128712L)
|
^ ((long) blockX * 341873128712L)
|
||||||
|
|||||||
+32
@@ -1,6 +1,12 @@
|
|||||||
package art.arcane.iris.modded;
|
package art.arcane.iris.modded;
|
||||||
|
|
||||||
|
import art.arcane.iris.generation.biome.IrisBiome;
|
||||||
|
import art.arcane.iris.generation.runtime.Engine;
|
||||||
|
import art.arcane.iris.generation.runtime.GenerationSessionLease;
|
||||||
|
import art.arcane.iris.generation.runtime.IrisComplex;
|
||||||
import art.arcane.volmlib.nativelib.terrain.NativeBiomeSourceAccess;
|
import art.arcane.volmlib.nativelib.terrain.NativeBiomeSourceAccess;
|
||||||
|
import art.arcane.volmlib.util.stream.ProceduralStream;
|
||||||
|
import art.arcane.volmlib.util.stream.interpolation.Interpolated;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -13,6 +19,9 @@ import static org.junit.Assert.assertEquals;
|
|||||||
import static org.junit.Assert.assertSame;
|
import static org.junit.Assert.assertSame;
|
||||||
import static org.junit.Assert.assertThrows;
|
import static org.junit.Assert.assertThrows;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
public class ModdedBiomePolicyTest {
|
public class ModdedBiomePolicyTest {
|
||||||
@Test
|
@Test
|
||||||
@@ -52,6 +61,29 @@ public class ModdedBiomePolicyTest {
|
|||||||
assertTrue(failure.getMessage().contains("example:missing"));
|
assertTrue(failure.getMessage().contains("example:missing"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void structureRingBiomesResolveFromTheNaturalSurfaceWithoutPlanningHydrology() throws Exception {
|
||||||
|
BiomeToken forest = new BiomeToken("minecraft:forest");
|
||||||
|
IrisBiome natural = mock(IrisBiome.class);
|
||||||
|
when(natural.getStructureDerivativeKey()).thenReturn(forest.key());
|
||||||
|
IrisComplex complex = mock(IrisComplex.class);
|
||||||
|
when(complex.getNaturalTrueBiomeStream()).thenReturn(
|
||||||
|
ProceduralStream.of((x, z) -> natural, Interpolated.of(value -> 0D, value -> null)));
|
||||||
|
when(complex.getTrueBiomeStream()).thenThrow(
|
||||||
|
new AssertionError("Stronghold ring lookups must not plan hydrology"));
|
||||||
|
Engine engine = mock(Engine.class);
|
||||||
|
when(engine.getComplex()).thenReturn(complex);
|
||||||
|
when(engine.getMinHeight()).thenReturn(-64);
|
||||||
|
when(engine.acquireGenerationLease(anyString())).thenReturn(GenerationSessionLease.noop());
|
||||||
|
ModdedBiomePolicy<BiomeToken, Object> policy = new ModdedBiomePolicy<>(
|
||||||
|
new Access(new ArrayList<>(List.of(forest))));
|
||||||
|
policy.bind(new ModdedBiomePolicy.RuntimeCallbacks(() -> engine, () -> engine, bound -> true,
|
||||||
|
() -> Set.of(forest.key()), bound -> Set.of(), () -> 0L));
|
||||||
|
|
||||||
|
assertSame(forest, policy.requiredStructureBiome(6000, 0, -6000, null));
|
||||||
|
assertSame(forest, policy.requiredStructureBiome(6000, -30, -6000, null));
|
||||||
|
}
|
||||||
|
|
||||||
private static ModdedBiomePolicy<BiomeToken, Object> policy(List<BiomeToken> entries,
|
private static ModdedBiomePolicy<BiomeToken, Object> policy(List<BiomeToken> entries,
|
||||||
AtomicReference<Set<String>> configured) {
|
AtomicReference<Set<String>> configured) {
|
||||||
ModdedBiomePolicy<BiomeToken, Object> policy = new ModdedBiomePolicy<>(new Access(entries));
|
ModdedBiomePolicy<BiomeToken, Object> policy = new ModdedBiomePolicy<>(new Access(entries));
|
||||||
|
|||||||
Reference in New Issue
Block a user