Adapter and papi fixes

This commit is contained in:
Brian Neumann-Fopiano committed 2026-09-13 21:27:44 -04:00
1 parent c14a972ab8
commit dfb3748059
15 files changed
+796 -30

No files matched your search

@@ -0,0 +1,24 @@
package art.arcane.iris.api.terrain;
import java.util.List;
public record IrisBiomeInfo(
String key,
String name,
String regionKey,
String regionName,
String derivativeKey,
String vanillaDerivativeKey,
String type,
List<IrisCustomBiomeInfo> customDerivatives) {
public IrisBiomeInfo {
key = key == null ? "" : key;
name = name == null ? "" : name;
regionKey = regionKey == null ? "" : regionKey;
regionName = regionName == null ? "" : regionName;
derivativeKey = derivativeKey == null ? "" : derivativeKey;
vanillaDerivativeKey = vanillaDerivativeKey == null ? "" : vanillaDerivativeKey;
type = type == null ? "" : type;
customDerivatives = List.copyOf(customDerivatives);
}
}
@@ -0,0 +1,8 @@
package art.arcane.iris.api.terrain;
public record IrisCustomBiomeInfo(String id, String registryKey) {
public IrisCustomBiomeInfo {
id = id == null ? "" : id;
registryKey = registryKey == null ? "" : registryKey;
}
}
@@ -18,6 +18,8 @@ public interface IrisTerrainService {
Optional<String> surfaceBiomeName(World world, int blockX, int blockZ);
Optional<IrisBiomeInfo> surfaceBiomeInfo(World world, int blockX, int blockZ);
Optional<String> biomeKey(World world, int blockX, int blockY, int blockZ);
Optional<String> regionKey(World world, int blockX, int blockZ);
@@ -42,6 +42,19 @@ public final class IrisPapiExpansion extends VolmitPlaceholderExpansion {
.key("world.available", state::worldAvailable)
.key("world.biome", state::biome)
.key("world.biome-key", state::biomeKey)
.key("world.biome-custom", state::biomeCustom)
.key("world.biome-custom-id", state::biomeCustomId)
.key("world.biome-custom-ids", state::biomeCustomIds)
.key("world.biome-custom-key", state::biomeCustomKey)
.key("world.biome-custom-keys", state::biomeCustomKeys)
.key("world.biome-custom-count", state::biomeCustomCount)
.key("world.biome-derivative", state::biomeDerivative)
.key("world.biome-vanilla-derivative", state::biomeVanillaDerivative)
.key("world.biome-type", state::biomeType)
.key("world.min-height", state::minHeight)
.key("world.max-height", state::maxHeight)
.key("world.height", state::height)
.key("world.fluid-height", state::fluidHeight)
.key("world.region", state::region)
.key("world.region-key", state::regionKey)
.key("world.dimension", state::dimension)
@@ -3,7 +3,6 @@ package art.arcane.iris.integration;
import art.arcane.iris.api.pregen.IrisPregenPhase;
import art.arcane.iris.api.pregen.IrisPregenProgress;
import art.arcane.iris.api.terrain.IrisTerrainService;
import art.arcane.iris.api.terrain.IrisWorldInfo;
import art.arcane.volmlib.util.bukkit.papi.PlaceholderSnapshot;
import art.arcane.volmlib.util.bukkit.papi.PlaceholderValues;
import art.arcane.volmlib.util.bukkit.papi.PlayerSnapshotStore;
@@ -103,6 +102,71 @@ public final class IrisPapiState {
return view == null ? PlaceholderValues.UNAVAILABLE : view.biomeKey();
}
public String biomeCustom(UUID playerId) {
IrisPapiWorldView view = viewOf(playerId);
return view == null ? PlaceholderValues.UNAVAILABLE : view.details().custom();
}
public String biomeCustomId(UUID playerId) {
IrisPapiWorldView view = viewOf(playerId);
return view == null ? PlaceholderValues.UNAVAILABLE : view.details().customId();
}
public String biomeCustomIds(UUID playerId) {
IrisPapiWorldView view = viewOf(playerId);
return view == null ? PlaceholderValues.UNAVAILABLE : view.details().customIds();
}
public String biomeCustomKey(UUID playerId) {
IrisPapiWorldView view = viewOf(playerId);
return view == null ? PlaceholderValues.UNAVAILABLE : view.details().customKey();
}
public String biomeCustomKeys(UUID playerId) {
IrisPapiWorldView view = viewOf(playerId);
return view == null ? PlaceholderValues.UNAVAILABLE : view.details().customKeys();
}
public String biomeCustomCount(UUID playerId) {
IrisPapiWorldView view = viewOf(playerId);
return view == null ? PlaceholderValues.UNAVAILABLE : view.details().customCount();
}
public String biomeDerivative(UUID playerId) {
IrisPapiWorldView view = viewOf(playerId);
return view == null ? PlaceholderValues.UNAVAILABLE : view.details().derivative();
}
public String biomeVanillaDerivative(UUID playerId) {
IrisPapiWorldView view = viewOf(playerId);
return view == null ? PlaceholderValues.UNAVAILABLE : view.details().vanillaDerivative();
}
public String biomeType(UUID playerId) {
IrisPapiWorldView view = viewOf(playerId);
return view == null ? PlaceholderValues.UNAVAILABLE : view.details().type();
}
public String minHeight(UUID playerId) {
IrisPapiWorldView view = viewOf(playerId);
return view == null ? PlaceholderValues.UNAVAILABLE : view.heights().minimum();
}
public String maxHeight(UUID playerId) {
IrisPapiWorldView view = viewOf(playerId);
return view == null ? PlaceholderValues.UNAVAILABLE : view.heights().maximum();
}
public String height(UUID playerId) {
IrisPapiWorldView view = viewOf(playerId);
return view == null ? PlaceholderValues.UNAVAILABLE : view.heights().height();
}
public String fluidHeight(UUID playerId) {
IrisPapiWorldView view = viewOf(playerId);
return view == null ? PlaceholderValues.UNAVAILABLE : view.heights().fluid();
}
public String region(UUID playerId) {
IrisPapiWorldView view = viewOf(playerId);
return view == null ? PlaceholderValues.UNAVAILABLE : view.region();
@@ -195,10 +259,7 @@ public final class IrisPapiState {
return IrisPapiWorldView.present(
position,
now,
service.surfaceBiomeName(world, blockX, blockZ),
service.surfaceBiomeKey(world, blockX, blockZ),
service.regionName(world, blockX, blockZ),
service.regionKey(world, blockX, blockZ),
service.worldInfo(world).map(IrisWorldInfo::dimensionKey));
service.surfaceBiomeInfo(world, blockX, blockZ),
service.worldInfo(world));
}
}
@@ -1,8 +1,13 @@
package art.arcane.iris.integration;
import art.arcane.iris.api.terrain.IrisBiomeInfo;
import art.arcane.iris.api.terrain.IrisCustomBiomeInfo;
import art.arcane.iris.api.terrain.IrisWorldInfo;
import art.arcane.volmlib.util.bukkit.papi.PlaceholderValues;
import java.util.List;
import java.util.Optional;
import java.util.StringJoiner;
public record IrisPapiWorldView(
IrisPapiPosition position,
@@ -12,7 +17,9 @@ public record IrisPapiWorldView(
String biomeKey,
String region,
String regionKey,
String dimension) {
String dimension,
BiomeDetails details,
Heights heights) {
public static IrisPapiWorldView absent(IrisPapiPosition position, long builtAtMs) {
return new IrisPapiWorldView(
position,
@@ -22,29 +29,82 @@ public record IrisPapiWorldView(
PlaceholderValues.UNAVAILABLE,
PlaceholderValues.UNAVAILABLE,
PlaceholderValues.UNAVAILABLE,
PlaceholderValues.UNAVAILABLE);
PlaceholderValues.UNAVAILABLE,
BiomeDetails.absent(),
Heights.absent());
}
public static IrisPapiWorldView present(
IrisPapiPosition position,
long builtAtMs,
Optional<String> biome,
Optional<String> biomeKey,
Optional<String> region,
Optional<String> regionKey,
Optional<String> dimension) {
Optional<IrisBiomeInfo> biome,
Optional<IrisWorldInfo> world) {
return new IrisPapiWorldView(
position,
builtAtMs,
PlaceholderValues.TRUE,
text(biome),
text(biomeKey),
text(region),
text(regionKey),
text(dimension));
text(biome.map(IrisBiomeInfo::name)),
text(biome.map(IrisBiomeInfo::key)),
text(biome.map(IrisBiomeInfo::regionName)),
text(biome.map(IrisBiomeInfo::regionKey)),
text(world.map(IrisWorldInfo::dimensionKey)),
biome.map(BiomeDetails::of).orElseGet(BiomeDetails::absent),
world.map(Heights::of).orElseGet(Heights::absent));
}
static String text(Optional<String> value) {
return value == null || value.isEmpty() ? PlaceholderValues.UNAVAILABLE : PlaceholderValues.text(value.get());
}
public record BiomeDetails(
String custom,
String customId,
String customIds,
String customKey,
String customKeys,
String customCount,
String derivative,
String vanillaDerivative,
String type) {
static BiomeDetails absent() {
String unavailable = PlaceholderValues.UNAVAILABLE;
return new BiomeDetails(unavailable, unavailable, unavailable, unavailable, unavailable,
unavailable, unavailable, unavailable, unavailable);
}
static BiomeDetails of(IrisBiomeInfo biome) {
List<IrisCustomBiomeInfo> derivatives = biome.customDerivatives();
StringJoiner ids = new StringJoiner(", ");
StringJoiner keys = new StringJoiner(", ");
boolean keysComplete = true;
for (IrisCustomBiomeInfo derivative : derivatives) {
ids.add(derivative.id());
keys.add(derivative.registryKey());
keysComplete &= !derivative.registryKey().isBlank();
}
IrisCustomBiomeInfo single = derivatives.size() == 1 ? derivatives.getFirst() : null;
return new BiomeDetails(
PlaceholderValues.bool(!derivatives.isEmpty()),
single == null ? PlaceholderValues.UNAVAILABLE : PlaceholderValues.text(single.id()),
PlaceholderValues.text(ids.toString()),
single == null ? PlaceholderValues.UNAVAILABLE : PlaceholderValues.text(single.registryKey()),
keysComplete ? PlaceholderValues.text(keys.toString()) : PlaceholderValues.UNAVAILABLE,
Integer.toString(derivatives.size()),
PlaceholderValues.text(biome.derivativeKey()),
PlaceholderValues.text(biome.vanillaDerivativeKey()),
PlaceholderValues.text(biome.type()));
}
}
public record Heights(String minimum, String maximum, String height, String fluid) {
static Heights absent() {
String unavailable = PlaceholderValues.UNAVAILABLE;
return new Heights(unavailable, unavailable, unavailable, unavailable);
}
static Heights of(IrisWorldInfo world) {
return new Heights(Integer.toString(world.minHeight()), Integer.toString(world.maxHeight()),
Integer.toString(world.height()), Integer.toString(world.fluidHeight()));
}
}
}
@@ -1,5 +1,6 @@
package art.arcane.iris.platform.bukkit.api;
import art.arcane.iris.api.terrain.IrisBiomeInfo;
import art.arcane.iris.api.terrain.IrisColumnField;
import art.arcane.iris.api.terrain.IrisColumnQuery;
import art.arcane.iris.api.terrain.IrisColumnSample;
@@ -10,6 +11,7 @@ import art.arcane.iris.api.terrain.IrisTerrainService;
import art.arcane.iris.api.terrain.IrisWorldInfo;
import art.arcane.iris.configuration.IrisSettings;
import art.arcane.iris.platform.bukkit.terrain.IrisApiFaultGuard;
import art.arcane.iris.platform.bukkit.terrain.IrisBiomeInfoFactory;
import art.arcane.iris.platform.bukkit.terrain.IrisColumnWalk;
import art.arcane.iris.platform.bukkit.terrain.IrisSampleLimits;
import art.arcane.iris.platform.bukkit.terrain.IrisSurfaceClassifier;
@@ -25,6 +27,7 @@ import art.arcane.iris.platform.bukkit.BukkitPlatform;
import art.arcane.iris.spi.IrisLogging;
import art.arcane.iris.spi.IrisServices;
import art.arcane.iris.platform.bukkit.plugin.IrisService;
import art.arcane.iris.world.history.SavedBiomeUnavailableException;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.generator.ChunkGenerator;
@@ -150,6 +153,22 @@ public class IrisTerrainSVC implements IrisService, IrisTerrainService {
}
}
@Override
public Optional<IrisBiomeInfo> surfaceBiomeInfo(World world, int blockX, int blockZ) {
Engine engine = liveEngineOf(world);
if (engine == null) {
return Optional.empty();
}
try {
return Optional.of(IrisBiomeInfoFactory.surface(engine, blockX, blockZ,
error -> reportQueryFault("surfaceBiomeInfo", world, error)));
} catch (Throwable error) {
reportQueryFault("surfaceBiomeInfo", world, error);
return Optional.empty();
}
}
@Override
public Optional<String> biomeKey(World world, int blockX, int blockY, int blockZ) {
Engine engine = liveEngineOf(world);
@@ -371,6 +390,10 @@ public class IrisTerrainSVC implements IrisService, IrisTerrainService {
}
private void reportQueryFault(String operation, World world, Throwable error) {
if (error instanceof SavedBiomeUnavailableException unavailable
&& unavailable.isLoading() && unavailable.getSuppressed().length == 0) {
return;
}
if (queryFaults.record(System.currentTimeMillis())) {
IrisLogging.reportError("Iris terrain API query \"" + operation + "\" failed for world \""
+ (world == null ? "null" : world.getName()) + "\" (" + queryFaults.faults()
@@ -379,6 +402,10 @@ public class IrisTerrainSVC implements IrisService, IrisTerrainService {
}
private void reportSinkFault(World world, Throwable error) {
if (error instanceof SavedBiomeUnavailableException unavailable
&& unavailable.isLoading() && unavailable.getSuppressed().length == 0) {
return;
}
if (sinkFaults.record(System.currentTimeMillis())) {
IrisLogging.reportError("Iris terrain API column sample failed for world \""
+ (world == null ? "null" : world.getName()) + "\" (" + sinkFaults.faults()
@@ -0,0 +1,59 @@
package art.arcane.iris.platform.bukkit.terrain;
import art.arcane.iris.api.terrain.IrisBiomeInfo;
import art.arcane.iris.api.terrain.IrisCustomBiomeInfo;
import art.arcane.iris.generation.biome.IrisBiome;
import art.arcane.iris.generation.biome.IrisBiomeCustom;
import art.arcane.iris.generation.runtime.BiomeEnvironment;
import art.arcane.iris.generation.runtime.Engine;
import art.arcane.iris.generation.terrain.InferredType;
import art.arcane.volmlib.util.collection.KList;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.function.Consumer;
public final class IrisBiomeInfoFactory {
private IrisBiomeInfoFactory() {
}
public static IrisBiomeInfo surface(Engine engine, int blockX, int blockZ, Consumer<Throwable> reportFailure) {
Objects.requireNonNull(reportFailure, "reportFailure");
BiomeEnvironment environment = engine.getSurfaceBiomeEnvironment(blockX, blockZ);
IrisBiome biome = environment.biome();
InferredType inferredType = biome.getInferredType();
return new IrisBiomeInfo(
biome.getLoadKey(),
biome.getName(),
environment.region().getLoadKey(),
environment.region().getName(),
biome.getDerivativeKey(),
biome.getVanillaDerivativeKey(),
inferredType == null ? "" : inferredType.name().toLowerCase(Locale.ROOT),
customDerivatives(environment, reportFailure));
}
private static List<IrisCustomBiomeInfo> customDerivatives(
BiomeEnvironment environment,
Consumer<Throwable> reportFailure) {
KList<IrisBiomeCustom> customBiomes = environment.biome().getCustomDerivitives();
if (customBiomes == null || customBiomes.isEmpty()) {
return List.of();
}
List<IrisCustomBiomeInfo> derivatives = new ArrayList<>(customBiomes.size());
for (IrisBiomeCustom customBiome : customBiomes) {
String registryKey = "";
try {
registryKey = environment.data().customBiomeResourceKey(environment.dimension(), customBiome);
} catch (RuntimeException failure) {
reportFailure.accept(new IllegalStateException(
"Unable to resolve the registry key for Iris custom biome '" + customBiome.getId() + "'.", failure));
}
derivatives.add(new IrisCustomBiomeInfo(customBiome.getId(), registryKey));
}
return derivatives;
}
}