[VERY VERY VERY BAD IDEA]

This commit is contained in:
Brian Neumann-Fopiano
2026-09-20 04:24:42 -04:00
parent f0e7fea13b
commit 2fa0853e42
892 changed files with 13482 additions and 53554 deletions
+3
View File
@@ -12,6 +12,9 @@ java {
}
dependencies {
api("com.github.VolmitSoftware.VolmLib:native-api:${providers.gradleProperty('volmLibCoordinate').get().tokenize(':').last()}") {
transitive = false
}
testImplementation('junit:junit:4.13.2')
}
@@ -18,6 +18,8 @@
package art.arcane.iris.spi;
import art.arcane.volmlib.nativelib.terrain.NativeWorld;
import java.io.File;
/**
@@ -27,7 +29,7 @@ import java.io.File;
* ({@link #registries()}, {@link #scheduler()}, {@link #structureHooks()}, {@link #biomeWriter()}, the
* version and path methods) are called from generation threads and must not block on the server thread.
* The mutating methods ({@link #callEvent(Object)}, {@link #dispatchConsoleCommand(String)},
* {@link #spawnEntity(PlatformWorld, String, double, double, double)}) touch live server state and are
* {@link #spawnEntity(NativeWorld, String, double, double, double)}) touch live server state and are
* expected to be invoked on the thread that owns it - the global/server thread, or the region thread
* owning the target chunk on regionized platforms. Use {@link #scheduler()} to get there.
* <p>
@@ -179,14 +181,14 @@ public interface IrisPlatform {
/**
* Spawns a vanilla entity by namespaced key at the given block-space position.
* <p>
* Adapters unwrap {@link PlatformWorld#nativeHandle()} to reach the host world, so {@code world} must
* be a {@link PlatformWorld} produced by the active adapter. Returns false - never throws - when
* Adapters unwrap {@link NativeWorld#nativeHandle()} to reach the host world, so {@code world} must
* be a {@link NativeWorld} produced by the active adapter. Returns false - never throws - when
* {@code world} or {@code entityKey} is null, the world belongs to a different adapter, the key does
* not parse, the entity type is unknown, or the platform refuses the spawn.
* <p>
* Invoke on the thread owning the target chunk.
*/
boolean spawnEntity(PlatformWorld world, String entityKey, double x, double y, double z);
boolean spawnEntity(NativeWorld world, String entityKey, double x, double y, double z);
/**
* Routes a log line to the host logger at {@code level}. Safe from any thread. Prefer
@@ -1,44 +0,0 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2026 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package art.arcane.iris.spi;
/**
* Neutral handle for a resolved biome backed by an adapter-owned native handle.
* <p>
* Immutable and safe to share across threads. Internal to Iris; not a published integration surface.
*
* @see PlatformRegistries#biome(String)
*/
public interface PlatformBiome {
/**
* Canonical {@code namespace:path} biome key. Never null.
*/
String key();
/**
* Namespace half of {@link #key()}. Never null.
*/
String namespace();
/**
* The adapter's backing biome object - {@code org.bukkit.block.Biome} on Bukkit, a {@code Biome} registry
* value on a mod loader. Never null. Only code inside the owning adapter may cast it.
*/
Object nativeHandle();
}
@@ -18,6 +18,8 @@
package art.arcane.iris.spi;
import art.arcane.volmlib.nativelib.terrain.NativeBiome;
import java.util.List;
/**
@@ -42,5 +44,5 @@ public interface PlatformBiomeWriter {
/**
* Every biome in the host registry, including datapack and mod biomes. Never null.
*/
List<PlatformBiome> allBiomes();
List<NativeBiome> allBiomes();
}
@@ -1,43 +0,0 @@
/*
* Iris is a World Generator for Minecraft Servers
* Copyright (c) 2026 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package art.arcane.iris.spi;
import java.util.List;
/**
* One block state property as JSON schema vocabulary, so pack schema generation can describe block keys without
* knowing platform property types.
* <p>
* Immutable. Produced by {@link PlatformRegistries#blockStateProperties()} and consumed only by schema
* generation, never on the generation path. Internal to Iris; not a published integration surface.
*
* @param name the property name as it appears in a block key, for example {@code waterlogged}
* @param jsonType JSON schema type: {@code boolean}, {@code integer} or {@code string}. Never null or empty
* @param defaultValue the value the host's default state carries, boxed as its JSON representation
* @param allowedValues every legal value, empty when the adapter cannot enumerate them. Never null
* @param numericRange bounds for a numeric property, null for {@code boolean} and {@code string}
*/
public record PlatformBlockProperty(String name, String jsonType, Object defaultValue, List<Object> allowedValues, PlatformNumericRange numericRange) {
/**
* Whether {@link #numericRange()} is present, and therefore whether schema output should emit bounds.
*/
public boolean hasNumericRange() {
return numericRange != null;
}
}
@@ -1,201 +0,0 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2026 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package art.arcane.iris.spi;
/**
* Neutral handle for a resolved block state; the canonical key is the config currency and the native handle is adapter-owned.
* <p>
* Instances are immutable value handles, interned by the adapter, and read from generation threads in bulk -
* every predicate here must be a cached field read or cheap computation, never a registry or world lookup.
* Compare with {@link #matches(PlatformBlockState)} rather than {@code equals}; only interned singletons such as
* {@link PlatformRegistries#air()} are safe to compare by identity.
* <p>
* Internal to Iris; not a published integration surface.
*
* @see PlatformRegistries#block(String)
*/
public interface PlatformBlockState {
/**
* Canonical {@code namespace:path[prop=value,...]} key, the form packs and objects store. Never null.
*/
String key();
/**
* Namespace half of {@link #key()}, for example {@code minecraft}. Never null.
*/
String namespace();
/**
* The key with any property block stripped, memoized by implementors that intern their states.
* Returning null means "not memoized"; callers must then derive it from {@link #key()}.
*/
default String materialKey() {
return null;
}
/**
* Whether this is air, including cave and void air.
*/
boolean isAir();
/**
* Whether the host treats this as a solid collision block.
*/
boolean isSolid();
/**
* Whether this blocks light fully. Drives Iris's own light and surface reasoning.
*/
boolean isOccluding();
/**
* Whether this state came from a custom-content provider rather than a vanilla registry entry. Custom
* states carry a {@link #deferredPlacementKey()} and a {@link #placementBaseState()}.
*/
boolean isCustom();
/**
* For a custom state, the provider key to hand back after the block is written, so the provider can finish
* placement once the chunk exists. Null for ordinary states.
*/
default String deferredPlacementKey() {
return null;
}
/**
* The vanilla state to actually write for a custom state - the placeholder the provider later replaces.
* Returns {@code this} for ordinary states. Never null.
*/
default PlatformBlockState placementBaseState() {
return this;
}
/**
* Whether this is a fluid block, water or lava.
*/
boolean isFluid();
/**
* Whether this is water specifically.
*/
boolean isWater();
/**
* Whether this state carries a {@code waterlogged=true} property.
*/
boolean isWaterLogged();
/**
* Whether this state carries a {@code lit=true} property.
*/
boolean isLit();
/**
* Whether the host needs a block update after this is placed - stairs, fences, redstone and other states
* that resolve their shape from neighbours.
*/
boolean isUpdatable();
/**
* Whether this is plant foliage: grass, ferns, flowers and similar decoration.
*/
boolean isFoliage();
/**
* Whether this is part of a tree - tagged as a log or as leaves.
*/
boolean isTreeBlock();
/**
* Whether foliage can be planted on top of this block.
*/
boolean isFoliagePlantable();
/**
* Whether this is a decorant: a thin block that sits on a surface and cannot support anything.
*/
boolean isDecorant();
/**
* Whether this block has an inventory Iris can fill from a loot table.
*/
boolean isStorage();
/**
* Whether this is specifically a chest, which needs the pairing and orientation handling chests require.
*/
boolean isStorageChest();
/**
* Whether this is an ore block, and therefore a candidate for
* {@link PlatformRegistries#deepSlateOre(PlatformBlockState, PlatformBlockState)}.
*/
boolean isOre();
/**
* Whether this is deepslate or a deepslate variant.
*/
boolean isDeepSlate();
/**
* Whether this is a vine-like block that attaches to a face and hangs.
*/
boolean isVineBlock();
/**
* Whether this block can be placed onto {@code onto} - the support check Iris runs before writing
* decoration. Passing a state from a different adapter fails at runtime.
*/
boolean canPlaceOnto(PlatformBlockState onto);
/**
* Whether the two states are the same block with the same properties. Prefer this to {@code equals}, which
* is identity-based on some adapters.
*/
boolean matches(PlatformBlockState state);
/**
* Convenience for the common "nothing solid here" test.
*/
default boolean isAirOrFluid() {
return isAir() || isFluid();
}
/**
* Whether the host attaches a block entity to this block - signs, chests, spawners and similar. Such blocks
* need their tile data applied after the block write.
*/
boolean hasTileEntity();
/**
* This state with one property overridden, merged into {@link #key()} and re-resolved. Never mutates the
* receiver.
* <p>
* Strict: a property name or value the block does not accept throws rather than being dropped. Validate
* against {@link PlatformRegistries#blockStateProperties()} first, or resolve the full key through
* {@link PlatformRegistries#blockOrNull(String)} instead.
*/
PlatformBlockState withProperty(String name, String value);
/**
* The adapter's backing state object - {@code org.bukkit.block.data.BlockData} on Bukkit,
* {@code BlockState} on a mod loader. Never null. Only code inside the owning adapter may cast it.
*/
Object nativeHandle();
}
@@ -1,51 +0,0 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2026 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package art.arcane.iris.spi;
/**
* Neutral handle for a resolved entity type backed by an adapter-owned native handle.
* <p>
* Immutable and safe to share across threads. Internal to Iris; not a published integration surface.
*
* @see PlatformRegistries#entity(String)
*/
public interface PlatformEntityType {
/**
* Canonical {@code namespace:path} entity type key. Never null.
*/
String key();
/**
* Namespace half of {@link #key()}. Never null.
*/
String namespace();
/**
* The host's spawn category, lowercased - {@code monster}, {@code creature}, {@code ambient} and so on.
* Iris matches it against pack spawn rules, so the string form is the contract rather than any enum. Never
* null.
*/
String spawnCategory();
/**
* The adapter's backing entity type object - {@code org.bukkit.entity.EntityType} on Bukkit,
* {@code EntityType} on a mod loader. Never null. Only code inside the owning adapter may cast it.
*/
Object nativeHandle();
}
@@ -1,10 +1,12 @@
package art.arcane.iris.spi;
import art.arcane.volmlib.nativelib.terrain.NativeGenerationRegistry;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;
public interface PlatformGenerationRegistry {
public interface PlatformGenerationRegistry extends NativeGenerationRegistry {
Pattern SHA_256_PATTERN = Pattern.compile("[0-9a-f]{64}");
String runtimeIdentity();
@@ -25,16 +27,6 @@ public interface PlatformGenerationRegistry {
String dimensionTypeResourceKey(String packName, String dimensionKey, String dimensionTypeKey);
Definition definition(String registryKey, String resourceKey);
default Definition generatedDefinition(String registryKey, String resourceKey) {
return definition(registryKey, resourceKey);
}
default Definition canonicalDefinition(String registryKey, String resourceKey, String sourceJson) {
return Definition.exactJson(sourceJson);
}
static String contentAddressedCustomBiomeResourceKey(String identitySha256) {
String requiredFingerprint = Objects.requireNonNull(identitySha256, "identitySha256");
if (!SHA_256_PATTERN.matcher(requiredFingerprint).matches()) {
@@ -43,42 +35,4 @@ public interface PlatformGenerationRegistry {
return "iris:biomes/" + requiredFingerprint;
}
enum Encoding {
JSON,
CONSERVATIVE_IDENTITY
}
record Definition(Encoding encoding, String value) {
public Definition {
encoding = Objects.requireNonNull(encoding, "encoding");
value = Objects.requireNonNull(value, "value");
if (value.isBlank()) {
throw new IllegalArgumentException("Platform registry definition must not be blank.");
}
}
public static Definition exactJson(String json) {
return new Definition(Encoding.JSON, json);
}
public static Definition conservativeIdentity(String identity) {
return new Definition(Encoding.CONSERVATIVE_IDENTITY, identity);
}
public static Definition resourceIdentity(String registryKey, String resourceKey) {
String requiredRegistryKey = requireText(registryKey, "registryKey");
String requiredResourceKey = requireText(resourceKey, "resourceKey");
return conservativeIdentity(
"registry-resource-key-v1|" + requiredRegistryKey + "|" + requiredResourceKey
);
}
private static String requireText(String value, String label) {
String required = Objects.requireNonNull(value, label).trim();
if (required.isEmpty()) {
throw new IllegalArgumentException(label + " must not be blank.");
}
return required;
}
}
}
@@ -1,45 +0,0 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2026 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package art.arcane.iris.spi;
/**
* Neutral handle for a resolved item type backed by an adapter-owned native handle.
* <p>
* Describes an item type, not a stack - no count, no components. Immutable and safe to share across threads.
* Internal to Iris; not a published integration surface.
*
* @see PlatformRegistries#item(String)
*/
public interface PlatformItem {
/**
* Canonical {@code namespace:path} item key. Never null.
*/
String key();
/**
* Namespace half of {@link #key()}. Never null.
*/
String namespace();
/**
* The adapter's backing item object - {@code org.bukkit.Material} on Bukkit, an {@code Item} registry value
* on a mod loader. Never null. Only code inside the owning adapter may cast it.
*/
Object nativeHandle();
}
@@ -1,35 +0,0 @@
/*
* Iris is a World Generator for Minecraft Servers
* Copyright (c) 2026 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package art.arcane.iris.spi;
/**
* Inclusive-or-exclusive numeric bounds for a {@link PlatformBlockProperty}, mirroring JSON schema's
* {@code minimum}/{@code maximum} pair.
* <p>
* Immutable. Bounds are carried as {@code double} regardless of the property's JSON type; an
* {@code integer} property's bounds are whole numbers and are narrowed by the schema writer. Internal to Iris;
* not a published integration surface.
*
* @param minimum lower bound
* @param maximum upper bound
* @param exclusiveMinimum whether {@code minimum} itself is disallowed
* @param exclusiveMaximum whether {@code maximum} itself is disallowed
*/
public record PlatformNumericRange(double minimum, double maximum, boolean exclusiveMinimum, boolean exclusiveMaximum) {
}
@@ -18,6 +18,16 @@
package art.arcane.iris.spi;
import art.arcane.volmlib.nativelib.terrain.NativeBlockProperty;
import art.arcane.volmlib.nativelib.entity.NativeEntityType;
import art.arcane.volmlib.nativelib.item.NativeItem;
import art.arcane.volmlib.nativelib.terrain.NativeBiome;
import art.arcane.volmlib.nativelib.terrain.NativeBlockState;
import java.util.List;
import java.util.Map;
@@ -43,7 +53,7 @@ public interface PlatformRegistries {
* falls back to air; a key that cannot be parsed at all may come back null. Callers that need to tell
* absence from air use {@link #blockOrNull(String)}.
*/
PlatformBlockState block(String key);
NativeBlockState block(String key);
/**
* Resolves a block key, returning null instead of an air fallback when it does not resolve. Silent.
@@ -52,40 +62,40 @@ public interface PlatformRegistries {
* sees keys the underlying lookup could not answer at all, so an unregistered key resolves to air through
* {@link #block(String)} on every platform - the Bukkit-only legacy rewrite table cannot fork generation output.
*/
PlatformBlockState blockOrNull(String key);
NativeBlockState blockOrNull(String key);
/**
* {@link #blockOrNull(String)} with control over whether an unresolved key is logged. Pass
* {@code warn = false} for speculative lookups.
*/
PlatformBlockState blockOrNull(String key, boolean warn);
NativeBlockState blockOrNull(String key, boolean warn);
/**
* The interned air state. Never null; identity-comparable across calls.
*/
PlatformBlockState air();
NativeBlockState air();
/**
* The deepslate variant of {@code ore} when {@code block} is deepslate, otherwise {@code ore} unchanged.
* Lets ore placement follow the host stone without the pack enumerating variants.
*/
PlatformBlockState deepSlateOre(PlatformBlockState block, PlatformBlockState ore);
NativeBlockState deepSlateOre(NativeBlockState block, NativeBlockState ore);
/**
* Resolves a biome key against the live biome registry, including datapack and mod biomes. Null when the
* key does not parse or is not registered.
*/
PlatformBiome biome(String key);
NativeBiome biome(String key);
/**
* Resolves an item key. Null when unknown.
*/
PlatformItem item(String key);
NativeItem item(String key);
/**
* Resolves an entity type key. Null when unknown.
*/
PlatformEntityType entity(String key);
NativeEntityType entity(String key);
/**
* Every registered block state key, properties included. Drives schema completion and command
@@ -147,5 +157,5 @@ public interface PlatformRegistries {
* Block key to its declared state properties, used to generate pack schema enums and numeric ranges.
* Keyed by material-level block key. Never null.
*/
Map<String, List<PlatformBlockProperty>> blockStateProperties();
Map<String, List<NativeBlockProperty>> blockStateProperties();
}
@@ -18,6 +18,8 @@
package art.arcane.iris.spi;
import art.arcane.volmlib.nativelib.terrain.NativeWorld;
/**
* Platform task dispatch; region scheduling targets the owning region thread on regionized platforms and the global thread elsewhere.
* <p>
@@ -42,7 +44,7 @@ public interface PlatformScheduler {
* touches blocks or entities in a known chunk. Adapters that cannot resolve a region owner fall back to
* {@link #global(Runnable)}.
*/
void region(PlatformWorld world, int chunkX, int chunkZ, Runnable task);
void region(NativeWorld world, int chunkX, int chunkZ, Runnable task);
/**
* Runs {@code task} on a pooled thread off the server thread. Must not touch world state.
@@ -56,9 +58,9 @@ public interface PlatformScheduler {
void laterGlobal(Runnable task, int ticks);
/**
* {@link #region(PlatformWorld, int, int, Runnable)} delayed by {@code ticks}, with the same non-positive-delay
* {@link #region(NativeWorld, int, int, Runnable)} delayed by {@code ticks}, with the same non-positive-delay
* degradation as {@link #laterGlobal(Runnable, int)}. Adapters without regions fall back to the delayed global
* queue.
*/
void laterRegion(PlatformWorld world, int chunkX, int chunkZ, Runnable task, int ticks);
void laterRegion(NativeWorld world, int chunkX, int chunkZ, Runnable task, int ticks);
}
@@ -18,7 +18,10 @@
package art.arcane.iris.spi;
import art.arcane.volmlib.nativelib.terrain.NativeWorld;
import java.util.List;
import art.arcane.volmlib.nativelib.terrain.JigsawSourceMetadata;
/**
* Neutral access to the host platform's structure, structure-set and configured-feature registries plus placement entry points.
@@ -84,18 +87,18 @@ public interface PlatformStructureHooks {
* Structure keys actually reachable in {@code world}, after its dimension's structure sets and biome filter
* are applied. Narrower than {@link #structureKeys()}. Never null.
*/
List<String> reachableStructureKeys(PlatformWorld world);
List<String> reachableStructureKeys(NativeWorld world);
/**
* Biome keys the world's biome source can emit. Never null.
*/
List<String> possibleBiomeKeys(PlatformWorld world);
List<String> possibleBiomeKeys(NativeWorld world);
/**
* Places a configured feature at world coordinates with the given seed. Returns false when the key is
* unknown or the feature declines to place. Mutates the world; see the threading note on this interface.
*/
boolean placeFeature(PlatformWorld world, int x, int y, int z, String featureKey, long seed);
boolean placeFeature(NativeWorld world, int x, int y, int z, String featureKey, long seed);
/**
* Generates and places a structure anchored at the given chunk.
@@ -104,30 +107,13 @@ public interface PlatformStructureHooks {
* @return the placed bounding box as {@code {minX, minY, minZ, maxX, maxY, maxZ}}, or null when the key is
* unknown, the structure produced no valid start, or the box exceeded {@code maxSpan}
*/
int[] placeStructure(PlatformWorld world, int chunkX, int chunkZ, String structureKey, long seed, int maxSpan);
int[] placeStructure(NativeWorld world, int chunkX, int chunkZ, String structureKey, long seed, int maxSpan);
/**
* Whether this adapter implements {@link #placeStructure(PlatformWorld, int, int, String, long, int)}.
* Whether this adapter implements {@link #placeStructure(NativeWorld, int, int, String, long, int)}.
* Check before offering structure capture; adapters without the required host access return false.
*/
boolean supportsStructurePlacement();
record JigsawSourceMetadata(int maxDistanceHorizontal, int referenceExpansion,
int maxStartElementHorizontalSpan) {
public JigsawSourceMetadata(int maxDistanceHorizontal, int referenceExpansion) {
this(maxDistanceHorizontal, referenceExpansion, 0);
}
public JigsawSourceMetadata {
if (maxDistanceHorizontal < 1 || maxDistanceHorizontal > 128) {
throw new IllegalArgumentException("Jigsaw horizontal distance must be between 1 and 128");
}
if (referenceExpansion < 0) {
throw new IllegalArgumentException("Jigsaw reference expansion must not be negative");
}
if (maxStartElementHorizontalSpan < 0) {
throw new IllegalArgumentException("Jigsaw start element horizontal span must not be negative");
}
}
}
}
@@ -1,97 +0,0 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2026 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package art.arcane.iris.spi;
/**
* Neutral view of a loaded world for edit and lifecycle paths; never used on the generation hot path.
* <p>
* Metadata reads ({@link #name()}, {@link #seed()}, the height bounds) are cheap and safe from any thread. The
* block, biome and weather accessors read or mutate live world state and must be called on the thread that
* owns the target chunk - the region thread on regionized platforms, the server thread elsewhere. Reach that
* thread with {@link PlatformScheduler#region(PlatformWorld, int, int, Runnable)}.
* <p>
* Internal to Iris; not a published integration surface.
*/
public interface PlatformWorld {
/**
* The host's world name. Never null.
*/
String name();
/**
* The world seed, as the host reports it.
*/
long seed();
/**
* Lowest buildable Y, inclusive. Usually negative.
*/
int minHeight();
/**
* Highest buildable Y, exclusive.
*/
int maxHeight();
/**
* The block state at world coordinates. Loads the chunk if it is not resident, so treat it as blocking.
* Adapters delegate straight to the host, so a coordinate outside {@link #minHeight()}/{@link #maxHeight()}
* gets whatever the host does with it - clamp, air, or throw. Bounds-check first.
*/
PlatformBlockState getBlock(int x, int y, int z);
/**
* Writes a block state at world coordinates. Same out-of-bounds caveat as {@link #getBlock(int, int, int)}.
*
* @param flags platform update flags; bit 0 requests neighbour/physics updates, higher bits are
* adapter-specific. Pass 0 for a silent write
*/
void setBlock(int x, int y, int z, PlatformBlockState block, int flags);
/**
* The biome at world coordinates. Loads the chunk if it is not resident.
*/
PlatformBiome getBiome(int x, int y, int z);
/**
* Whether the chunk is currently resident. Cheap; the only accessor here that never triggers a load.
*/
boolean isChunkLoaded(int chunkX, int chunkZ);
/**
* The world's time of day in ticks.
*/
long getTime();
/**
* Whether it is raining or snowing.
*/
boolean isStorming();
/**
* Whether a thunderstorm is active.
*/
boolean isThundering();
/**
* The adapter's backing world object - {@code org.bukkit.World} on Bukkit, {@code ServerLevel} on a mod
* loader. Never null. Only code inside the owning adapter may cast it; core must not.
*/
Object nativeHandle();
}
@@ -1,5 +1,7 @@
package art.arcane.iris.spi;
import art.arcane.volmlib.nativelib.terrain.NativeWorld;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -153,7 +155,7 @@ public class IrisPlatformsBindContractTest {
}
@Override
public boolean spawnEntity(PlatformWorld world, String entityKey, double x, double y, double z) {
public boolean spawnEntity(NativeWorld world, String entityKey, double x, double y, double z) {
return false;
}
@@ -1,5 +1,13 @@
package art.arcane.iris.spi;
import art.arcane.volmlib.nativelib.terrain.NativeWorld;
import art.arcane.volmlib.nativelib.terrain.NativeNumericRange;
import art.arcane.volmlib.nativelib.terrain.NativeBlockProperty;
import art.arcane.volmlib.nativelib.terrain.JigsawSourceMetadata;
import org.junit.Test;
import java.util.List;
@@ -14,10 +22,10 @@ public class PlatformValueContractTest {
@Test
public void jigsawMetadataAcceptsTheWholeDocumentedRange() {
PlatformStructureHooks.JigsawSourceMetadata smallest =
new PlatformStructureHooks.JigsawSourceMetadata(1, 0, 0);
PlatformStructureHooks.JigsawSourceMetadata largest =
new PlatformStructureHooks.JigsawSourceMetadata(128, 7, 96);
JigsawSourceMetadata smallest =
new JigsawSourceMetadata(1, 0, 0);
JigsawSourceMetadata largest =
new JigsawSourceMetadata(128, 7, 96);
assertEquals(1, smallest.maxDistanceHorizontal());
assertEquals(128, largest.maxDistanceHorizontal());
@@ -27,8 +35,8 @@ public class PlatformValueContractTest {
@Test
public void jigsawMetadataDefaultsTheStartElementSpanToZero() {
PlatformStructureHooks.JigsawSourceMetadata metadata =
new PlatformStructureHooks.JigsawSourceMetadata(64, 3);
JigsawSourceMetadata metadata =
new JigsawSourceMetadata(64, 3);
assertEquals(0, metadata.maxStartElementHorizontalSpan());
}
@@ -36,13 +44,13 @@ public class PlatformValueContractTest {
@Test
public void jigsawMetadataRejectsOutOfRangeGeometry() {
assertThrows(IllegalArgumentException.class,
() -> new PlatformStructureHooks.JigsawSourceMetadata(0, 0, 0));
() -> new JigsawSourceMetadata(0, 0, 0));
assertThrows(IllegalArgumentException.class,
() -> new PlatformStructureHooks.JigsawSourceMetadata(129, 0, 0));
() -> new JigsawSourceMetadata(129, 0, 0));
assertThrows(IllegalArgumentException.class,
() -> new PlatformStructureHooks.JigsawSourceMetadata(64, -1, 0));
() -> new JigsawSourceMetadata(64, -1, 0));
assertThrows(IllegalArgumentException.class,
() -> new PlatformStructureHooks.JigsawSourceMetadata(64, 0, -1));
() -> new JigsawSourceMetadata(64, 0, -1));
}
@Test
@@ -112,11 +120,11 @@ public class PlatformValueContractTest {
@Test
public void blockPropertiesReportWhetherTheyCarryANumericRange() {
PlatformNumericRange range = new PlatformNumericRange(0D, 15D, false, true);
PlatformBlockProperty numeric =
new PlatformBlockProperty("level", "integer", 0, List.of(0, 15), range);
PlatformBlockProperty enumerated =
new PlatformBlockProperty("axis", "string", "y", List.of("x", "y", "z"), null);
NativeNumericRange range = new NativeNumericRange(0D, 15D, false, true);
NativeBlockProperty numeric =
new NativeBlockProperty("level", "integer", 0, List.of(0, 15), range);
NativeBlockProperty enumerated =
new NativeBlockProperty("axis", "string", "y", List.of("x", "y", "z"), null);
assertTrue(numeric.hasNumericRange());
assertEquals(range, numeric.numericRange());
@@ -150,22 +158,22 @@ public class PlatformValueContractTest {
}
@Override
public List<String> reachableStructureKeys(PlatformWorld world) {
public List<String> reachableStructureKeys(NativeWorld world) {
return List.of();
}
@Override
public List<String> possibleBiomeKeys(PlatformWorld world) {
public List<String> possibleBiomeKeys(NativeWorld world) {
return List.of();
}
@Override
public boolean placeFeature(PlatformWorld world, int x, int y, int z, String featureKey, long seed) {
public boolean placeFeature(NativeWorld world, int x, int y, int z, String featureKey, long seed) {
return false;
}
@Override
public int[] placeStructure(PlatformWorld world, int chunkX, int chunkZ, String structureKey, long seed, int maxSpan) {
public int[] placeStructure(NativeWorld world, int chunkX, int chunkZ, String structureKey, long seed, int maxSpan) {
return new int[0];
}