mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-06-18 14:50:57 +00:00
f
This commit is contained in:
@@ -239,34 +239,15 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
@BlockCoordinates
|
@BlockCoordinates
|
||||||
default IrisBiome getCaveBiome(int x, int y, int z) {
|
default IrisBiome getCaveBiome(int x, int y, int z) {
|
||||||
IrisBiome surfaceBiome = getSurfaceBiome(x, z);
|
IrisBiome surfaceBiome = getSurfaceBiome(x, z);
|
||||||
IrisBiome entryBiome = null;
|
|
||||||
int worldY = y + getWorld().minHeight();
|
int worldY = y + getWorld().minHeight();
|
||||||
KList<IrisDimensionCarvingEntry> carvingEntries = getDimension().getCarving();
|
IrisDimensionCarvingEntry rootCarvingEntry = IrisDimensionCarvingResolver.resolveRootEntry(this, worldY);
|
||||||
if (carvingEntries != null && !carvingEntries.isEmpty()) {
|
if (rootCarvingEntry != null) {
|
||||||
for (IrisDimensionCarvingEntry entry : carvingEntries) {
|
IrisDimensionCarvingEntry resolvedCarvingEntry = IrisDimensionCarvingResolver.resolveFromRoot(this, rootCarvingEntry, x, z);
|
||||||
if (entry == null || !entry.isEnabled()) {
|
IrisBiome resolvedCarvingBiome = IrisDimensionCarvingResolver.resolveEntryBiome(this, resolvedCarvingEntry);
|
||||||
continue;
|
if (resolvedCarvingBiome != null) {
|
||||||
}
|
return resolvedCarvingBiome;
|
||||||
|
|
||||||
String key = entry.getBiome();
|
|
||||||
if (key == null || key.isBlank()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
IrisRange worldYRange = entry.getWorldYRange();
|
|
||||||
if (worldYRange != null && !worldYRange.contains(worldY)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
IrisBiome loadedBiome = getData().getBiomeLoader().load(key.trim());
|
|
||||||
if (loadedBiome != null) {
|
|
||||||
entryBiome = loadedBiome;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (entryBiome != null) {
|
|
||||||
return entryBiome;
|
|
||||||
}
|
|
||||||
|
|
||||||
IrisBiome caveBiome = getCaveBiome(x, z);
|
IrisBiome caveBiome = getCaveBiome(x, z);
|
||||||
if (caveBiome == null) {
|
if (caveBiome == null) {
|
||||||
|
|||||||
+32
-22
@@ -25,6 +25,7 @@ import art.arcane.iris.engine.mantle.MantleWriter;
|
|||||||
import art.arcane.iris.engine.object.IrisBiome;
|
import art.arcane.iris.engine.object.IrisBiome;
|
||||||
import art.arcane.iris.engine.object.IrisCaveProfile;
|
import art.arcane.iris.engine.object.IrisCaveProfile;
|
||||||
import art.arcane.iris.engine.object.IrisDimensionCarvingEntry;
|
import art.arcane.iris.engine.object.IrisDimensionCarvingEntry;
|
||||||
|
import art.arcane.iris.engine.object.IrisDimensionCarvingResolver;
|
||||||
import art.arcane.iris.engine.object.IrisRegion;
|
import art.arcane.iris.engine.object.IrisRegion;
|
||||||
import art.arcane.iris.engine.object.IrisRange;
|
import art.arcane.iris.engine.object.IrisRange;
|
||||||
import art.arcane.iris.util.project.context.ChunkContext;
|
import art.arcane.iris.util.project.context.ChunkContext;
|
||||||
@@ -32,7 +33,6 @@ import art.arcane.volmlib.util.documentation.ChunkCoordinates;
|
|||||||
import art.arcane.volmlib.util.mantle.flag.ReservedFlag;
|
import art.arcane.volmlib.util.mantle.flag.ReservedFlag;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.IdentityHashMap;
|
import java.util.IdentityHashMap;
|
||||||
@@ -106,11 +106,11 @@ public class MantleCarvingComponent extends IrisMantleComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
weightedProfiles.sort(Comparator.comparingDouble(WeightedProfile::averageWeight));
|
weightedProfiles.sort(Comparator.comparingDouble(WeightedProfile::averageWeight));
|
||||||
weightedProfiles.addAll(0, resolveDimensionCarvingProfiles());
|
weightedProfiles.addAll(0, resolveDimensionCarvingProfiles(chunkX, chunkZ));
|
||||||
return weightedProfiles;
|
return weightedProfiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<WeightedProfile> resolveDimensionCarvingProfiles() {
|
private List<WeightedProfile> resolveDimensionCarvingProfiles(int chunkX, int chunkZ) {
|
||||||
List<WeightedProfile> weightedProfiles = new ArrayList<>();
|
List<WeightedProfile> weightedProfiles = new ArrayList<>();
|
||||||
List<IrisDimensionCarvingEntry> entries = getDimension().getCarving();
|
List<IrisDimensionCarvingEntry> entries = getDimension().getCarving();
|
||||||
if (entries == null || entries.isEmpty()) {
|
if (entries == null || entries.isEmpty()) {
|
||||||
@@ -122,23 +122,39 @@ public class MantleCarvingComponent extends IrisMantleComponent {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
String biomeKey = entry.getBiome();
|
IrisBiome rootBiome = IrisDimensionCarvingResolver.resolveEntryBiome(getEngineMantle().getEngine(), entry);
|
||||||
if (biomeKey == null || biomeKey.isBlank()) {
|
if (rootBiome == null) {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
IrisBiome biome = getData().getBiomeLoader().load(biomeKey.trim());
|
|
||||||
if (biome == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
IrisCaveProfile profile = biome.getCaveProfile();
|
|
||||||
if (!isProfileEnabled(profile)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Map<IrisCaveProfile, double[]> rootProfileWeights = new IdentityHashMap<>();
|
||||||
IrisRange worldYRange = entry.getWorldYRange();
|
IrisRange worldYRange = entry.getWorldYRange();
|
||||||
weightedProfiles.add(new WeightedProfile(profile, fullWeights(), -1D, worldYRange));
|
for (int localX = 0; localX < CHUNK_SIZE; localX++) {
|
||||||
|
for (int localZ = 0; localZ < CHUNK_SIZE; localZ++) {
|
||||||
|
int worldX = (chunkX << 4) + localX;
|
||||||
|
int worldZ = (chunkZ << 4) + localZ;
|
||||||
|
int columnIndex = (localX << 4) | localZ;
|
||||||
|
IrisDimensionCarvingEntry resolvedEntry = IrisDimensionCarvingResolver.resolveFromRoot(getEngineMantle().getEngine(), entry, worldX, worldZ);
|
||||||
|
IrisBiome resolvedBiome = IrisDimensionCarvingResolver.resolveEntryBiome(getEngineMantle().getEngine(), resolvedEntry);
|
||||||
|
if (resolvedBiome == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
IrisCaveProfile profile = resolvedBiome.getCaveProfile();
|
||||||
|
if (!isProfileEnabled(profile)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
double[] weights = rootProfileWeights.computeIfAbsent(profile, key -> new double[CHUNK_AREA]);
|
||||||
|
weights[columnIndex] = 1D;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Map.Entry<IrisCaveProfile, double[]>> profileEntries = new ArrayList<>(rootProfileWeights.entrySet());
|
||||||
|
profileEntries.sort((a, b) -> Integer.compare(a.getKey().hashCode(), b.getKey().hashCode()));
|
||||||
|
for (Map.Entry<IrisCaveProfile, double[]> profileEntry : profileEntries) {
|
||||||
|
weightedProfiles.add(new WeightedProfile(profileEntry.getKey(), profileEntry.getValue(), -1D, worldYRange));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return weightedProfiles;
|
return weightedProfiles;
|
||||||
@@ -198,12 +214,6 @@ public class MantleCarvingComponent extends IrisMantleComponent {
|
|||||||
return (BLEND_RADIUS + 1D) - edgeDistance;
|
return (BLEND_RADIUS + 1D) - edgeDistance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private double[] fullWeights() {
|
|
||||||
double[] weights = new double[CHUNK_AREA];
|
|
||||||
Arrays.fill(weights, 1D);
|
|
||||||
return weights;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IrisCaveProfile resolveColumnProfile(int worldX, int worldZ) {
|
private IrisCaveProfile resolveColumnProfile(int worldX, int worldZ) {
|
||||||
IrisCaveProfile resolved = null;
|
IrisCaveProfile resolved = null;
|
||||||
IrisCaveProfile dimensionProfile = getDimension().getCaveProfile();
|
IrisCaveProfile dimensionProfile = getDimension().getCaveProfile();
|
||||||
|
|||||||
+2
-2
@@ -161,7 +161,7 @@ public class MantleObjectComponent extends IrisMantleComponent {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
biomeCaveChecked++;
|
biomeCaveChecked++;
|
||||||
boolean chance = rng.chance(i.getChance() + rng.d(-0.005, 0.005));
|
boolean chance = rng.chance(i.getChance());
|
||||||
if (traceRegen) {
|
if (traceRegen) {
|
||||||
Iris.info("Regen object placer chance: chunk=" + x + "," + z
|
Iris.info("Regen object placer chance: chunk=" + x + "," + z
|
||||||
+ " scope=biome-cave"
|
+ " scope=biome-cave"
|
||||||
@@ -226,7 +226,7 @@ public class MantleObjectComponent extends IrisMantleComponent {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
regionCaveChecked++;
|
regionCaveChecked++;
|
||||||
boolean chance = rng.chance(i.getChance() + rng.d(-0.005, 0.005));
|
boolean chance = rng.chance(i.getChance());
|
||||||
if (traceRegen) {
|
if (traceRegen) {
|
||||||
Iris.info("Regen object placer chance: chunk=" + x + "," + z
|
Iris.info("Regen object placer chance: chunk=" + x + "," + z
|
||||||
+ " scope=region-cave"
|
+ " scope=region-cave"
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ import java.nio.file.AtomicMoveNotSupportedException;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.StandardCopyOption;
|
import java.nio.file.StandardCopyOption;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -78,6 +79,7 @@ public class IrisDimension extends IrisRegistrant {
|
|||||||
private final transient AtomicCache<Double> rad = new AtomicCache<>();
|
private final transient AtomicCache<Double> rad = new AtomicCache<>();
|
||||||
private final transient AtomicCache<Boolean> featuresUsed = new AtomicCache<>();
|
private final transient AtomicCache<Boolean> featuresUsed = new AtomicCache<>();
|
||||||
private final transient AtomicCache<KMap<String, KList<String>>> cachedPreProcessors = new AtomicCache<>();
|
private final transient AtomicCache<KMap<String, KList<String>>> cachedPreProcessors = new AtomicCache<>();
|
||||||
|
private final transient AtomicCache<Map<String, IrisDimensionCarvingEntry>> carvingEntryIndex = new AtomicCache<>();
|
||||||
@MinNumber(2)
|
@MinNumber(2)
|
||||||
@Required
|
@Required
|
||||||
@Desc("The human readable name of this dimension")
|
@Desc("The human readable name of this dimension")
|
||||||
@@ -270,9 +272,39 @@ public class IrisDimension extends IrisRegistrant {
|
|||||||
return (int) getDimensionHeight().getMax();
|
return (int) getDimensionHeight().getMax();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMinHeight() {
|
public int getMinHeight() {
|
||||||
return (int) getDimensionHeight().getMin();
|
return (int) getDimensionHeight().getMin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, IrisDimensionCarvingEntry> getCarvingEntryIndex() {
|
||||||
|
return carvingEntryIndex.aquire(() -> {
|
||||||
|
Map<String, IrisDimensionCarvingEntry> index = new HashMap<>();
|
||||||
|
KList<IrisDimensionCarvingEntry> entries = getCarving();
|
||||||
|
if (entries == null || entries.isEmpty()) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (IrisDimensionCarvingEntry entry : entries) {
|
||||||
|
if (entry == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String entryId = entry.getId();
|
||||||
|
if (entryId == null || entryId.isBlank()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
index.put(entryId.trim(), entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCarving(KList<IrisDimensionCarvingEntry> carving) {
|
||||||
|
this.carving = carving == null ? new KList<>() : carving;
|
||||||
|
carvingEntryIndex.reset();
|
||||||
|
}
|
||||||
|
|
||||||
public BlockData generateOres(int x, int y, int z, RNG rng, IrisData data, boolean surface) {
|
public BlockData generateOres(int x, int y, int z, RNG rng, IrisData data, boolean surface) {
|
||||||
if (ores.isEmpty()) {
|
if (ores.isEmpty()) {
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
package art.arcane.iris.engine.object;
|
package art.arcane.iris.engine.object;
|
||||||
|
|
||||||
|
import art.arcane.iris.core.loader.IrisData;
|
||||||
|
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||||
|
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||||
import art.arcane.iris.engine.object.annotations.Desc;
|
import art.arcane.iris.engine.object.annotations.Desc;
|
||||||
|
import art.arcane.iris.engine.object.annotations.DependsOn;
|
||||||
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
||||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||||
|
import art.arcane.iris.util.project.noise.CNG;
|
||||||
|
import art.arcane.volmlib.util.collection.KList;
|
||||||
|
import art.arcane.volmlib.util.math.RNG;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
@@ -15,6 +22,9 @@ import lombok.experimental.Accessors;
|
|||||||
@Desc("Dimension-level cave biome override with absolute world Y bounds.")
|
@Desc("Dimension-level cave biome override with absolute world Y bounds.")
|
||||||
@Data
|
@Data
|
||||||
public class IrisDimensionCarvingEntry {
|
public class IrisDimensionCarvingEntry {
|
||||||
|
private final transient AtomicCache<IrisBiome> realBiome = new AtomicCache<>(true);
|
||||||
|
private final transient AtomicCache<CNG> childGenerator = new AtomicCache<>();
|
||||||
|
|
||||||
@Desc("Stable id for this carving entry")
|
@Desc("Stable id for this carving entry")
|
||||||
private String id = "";
|
private String id = "";
|
||||||
|
|
||||||
@@ -27,4 +37,41 @@ public class IrisDimensionCarvingEntry {
|
|||||||
|
|
||||||
@Desc("Absolute world Y bounds where this carving entry applies")
|
@Desc("Absolute world Y bounds where this carving entry applies")
|
||||||
private IrisRange worldYRange = new IrisRange(-64, 320);
|
private IrisRange worldYRange = new IrisRange(-64, 320);
|
||||||
|
|
||||||
|
@DependsOn({"children"})
|
||||||
|
@Desc("If this carving entry has child carving entries, this controls how small those child carving patches are.")
|
||||||
|
private double childShrinkFactor = 1.5;
|
||||||
|
|
||||||
|
@DependsOn({"children"})
|
||||||
|
@Desc("If this carving entry has child carving entries, this controls the shape pattern used to pick them.")
|
||||||
|
private IrisGeneratorStyle childStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
|
||||||
|
|
||||||
|
@ArrayType(min = 1, type = String.class)
|
||||||
|
@Desc("Child carving entry ids. Child ids can point back to parent ids to create cycles; recursion is bounded by childRecursionDepth.")
|
||||||
|
private KList<String> children = new KList<>();
|
||||||
|
|
||||||
|
@Desc("Maximum recursion depth when resolving child carving entries from this entry.")
|
||||||
|
private int childRecursionDepth = 3;
|
||||||
|
|
||||||
|
public IrisBiome getRealBiome(IrisData data) {
|
||||||
|
return realBiome.aquire(() -> {
|
||||||
|
String biomeKey = getBiome();
|
||||||
|
if (biomeKey == null || biomeKey.isBlank()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.getBiomeLoader().load(biomeKey.trim());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public CNG getChildrenGenerator(long seed, IrisData data) {
|
||||||
|
return childGenerator.aquire(() -> {
|
||||||
|
String entryId = getId();
|
||||||
|
long idHash = entryId == null ? 0L : entryId.trim().hashCode();
|
||||||
|
long generatorSeed = seed ^ (idHash << 32) ^ 2137L;
|
||||||
|
double scale = Math.max(0.0001D, getChildShrinkFactor());
|
||||||
|
RNG random = new RNG(generatorSeed);
|
||||||
|
return getChildStyle().create(random.nextParallelRNG(2137), data).bake().scale(scale).bake();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,175 @@
|
|||||||
|
package art.arcane.iris.engine.object;
|
||||||
|
|
||||||
|
import art.arcane.iris.engine.framework.Engine;
|
||||||
|
import art.arcane.volmlib.util.collection.KList;
|
||||||
|
import art.arcane.iris.util.project.noise.CNG;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public final class IrisDimensionCarvingResolver {
|
||||||
|
private static final int MAX_CHILD_DEPTH = 32;
|
||||||
|
private static final long CHILD_SEED_SALT = 0x9E3779B97F4A7C15L;
|
||||||
|
|
||||||
|
private IrisDimensionCarvingResolver() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IrisDimensionCarvingEntry resolveRootEntry(Engine engine, int worldY) {
|
||||||
|
IrisDimension dimension = engine.getDimension();
|
||||||
|
List<IrisDimensionCarvingEntry> entries = dimension.getCarving();
|
||||||
|
if (entries == null || entries.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
IrisDimensionCarvingEntry resolved = null;
|
||||||
|
for (IrisDimensionCarvingEntry entry : entries) {
|
||||||
|
if (!isRootCandidate(engine, entry, worldY)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolved = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolved;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IrisDimensionCarvingEntry resolveFromRoot(Engine engine, IrisDimensionCarvingEntry rootEntry, int worldX, int worldZ) {
|
||||||
|
if (rootEntry == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
IrisBiome rootBiome = resolveEntryBiome(engine, rootEntry);
|
||||||
|
if (rootBiome == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int remainingDepth = clampDepth(rootEntry.getChildRecursionDepth());
|
||||||
|
if (remainingDepth <= 0) {
|
||||||
|
return rootEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, IrisDimensionCarvingEntry> entryIndex = engine.getDimension().getCarvingEntryIndex();
|
||||||
|
IrisDimensionCarvingEntry current = rootEntry;
|
||||||
|
int depth = remainingDepth;
|
||||||
|
while (depth > 0) {
|
||||||
|
IrisDimensionCarvingEntry selected = selectChild(engine, current, worldX, worldZ, entryIndex);
|
||||||
|
if (selected == null || selected == current) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
depth--;
|
||||||
|
int childDepthLimit = clampDepth(selected.getChildRecursionDepth());
|
||||||
|
if (childDepthLimit < depth) {
|
||||||
|
depth = childDepthLimit;
|
||||||
|
}
|
||||||
|
current = selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IrisBiome resolveEntryBiome(Engine engine, IrisDimensionCarvingEntry entry) {
|
||||||
|
if (entry == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry.getRealBiome(engine.getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isRootCandidate(Engine engine, IrisDimensionCarvingEntry entry, int worldY) {
|
||||||
|
if (entry == null || !entry.isEnabled()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IrisRange worldYRange = entry.getWorldYRange();
|
||||||
|
if (worldYRange != null && !worldYRange.contains(worldY)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolveEntryBiome(engine, entry) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IrisDimensionCarvingEntry selectChild(
|
||||||
|
Engine engine,
|
||||||
|
IrisDimensionCarvingEntry parent,
|
||||||
|
int worldX,
|
||||||
|
int worldZ,
|
||||||
|
Map<String, IrisDimensionCarvingEntry> entryIndex
|
||||||
|
) {
|
||||||
|
KList<String> children = parent.getChildren();
|
||||||
|
if (children == null || children.isEmpty()) {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
IrisBiome parentBiome = resolveEntryBiome(engine, parent);
|
||||||
|
if (parentBiome == null) {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
KList<CarvingChoice> options = new KList<>();
|
||||||
|
for (String childId : children) {
|
||||||
|
if (childId == null || childId.isBlank()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
IrisDimensionCarvingEntry child = entryIndex.get(childId.trim());
|
||||||
|
if (child == null || !child.isEnabled()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
IrisBiome childBiome = resolveEntryBiome(engine, child);
|
||||||
|
if (childBiome == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
options.add(new CarvingChoice(child, rarity(childBiome)));
|
||||||
|
}
|
||||||
|
|
||||||
|
options.add(new CarvingChoice(parent, rarity(parentBiome)));
|
||||||
|
if (options.size() <= 1) {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
long seed = engine.getSeedManager().getCarve() ^ CHILD_SEED_SALT;
|
||||||
|
CNG childGenerator = parent.getChildrenGenerator(seed, engine.getData());
|
||||||
|
CarvingChoice selected = childGenerator.fitRarity(options, worldX, worldZ);
|
||||||
|
if (selected == null || selected.entry == null) {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return selected.entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int rarity(IrisBiome biome) {
|
||||||
|
if (biome == null) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rarity = biome.getRarity();
|
||||||
|
return Math.max(rarity, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int clampDepth(int depth) {
|
||||||
|
if (depth <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.min(depth, MAX_CHILD_DEPTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class CarvingChoice implements IRare {
|
||||||
|
private final IrisDimensionCarvingEntry entry;
|
||||||
|
private final int rarity;
|
||||||
|
|
||||||
|
private CarvingChoice(IrisDimensionCarvingEntry entry, int rarity) {
|
||||||
|
this.entry = entry;
|
||||||
|
this.rarity = rarity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRarity() {
|
||||||
|
return rarity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user