First Test MV

This commit is contained in:
Brian Neumann-Fopiano
2026-08-07 14:04:17 -06:00
parent 42b8db4856
commit 68b842d5dc
24 changed files with 237 additions and 128 deletions
@@ -46,7 +46,6 @@ public final class IrisDatapackCompiler {
List<File> packRoots,
KList<File> datapackRoots,
IDataFixer fixer,
int packFormat,
boolean adjustVanillaHeight
) throws IOException {
Objects.requireNonNull(packRoots, "packRoots");
@@ -98,7 +97,7 @@ public final class IrisDatapackCompiler {
}
}
IrisDimension.writeShared(datapackRoots, height, packFormat, adjustVanillaHeight);
IrisDimension.writeShared(datapackRoots, height, adjustVanillaHeight);
validateOutputs(datapackRoots, dimensionCount);
return new CompilationResult(packCount, dimensionCount, countBiomes(biomes));
}
@@ -200,7 +200,6 @@ public class ServerConfigurator {
packRoots,
stagedRoots,
fixer,
BukkitPlatform.dataPackFormat(),
IrisSettings.get().getGeneral().adjustVanillaHeight
);
for (int i = 0; i < liveRoots.size(); i++) {
@@ -257,7 +257,7 @@ public interface INMSBinding {
if (!supportsIrisWorldGeneration()) {
throw new IllegalStateException("Iris world '" + c.name() + "' cannot be created with limited NMS binding "
+ getClass().getSimpleName()
+ "; set general.disableNMS=false and use the supported Minecraft 26.2 server runtime");
+ "; set general.disableNMS=false and use a supported Minecraft server runtime (26.1.2 or 26.2)");
}
if (missingDimensionTypes(generator.getTarget().getDimension().getDimensionTypeKey())) {
throw new IllegalStateException("Missing dimension types to create world");
@@ -1,7 +1,7 @@
package art.arcane.iris.core.nms;
final class NmsBindingSelector {
private static final String SUPPORTED_VERSION = "26.2";
private static final String SUPPORTED_VERSIONS = "26.1.2 or 26.2";
private static final String SUPPORTED_TAG = "v26_2_R1";
private NmsBindingSelector() {
@@ -11,8 +11,8 @@ final class NmsBindingSelector {
if (version == null) {
throw new IllegalStateException("Iris requires an exact Minecraft version before selecting NMS");
}
if (!version.isSameRelease(26, 2, 0)) {
throw new IllegalStateException("Iris requires Minecraft " + SUPPORTED_VERSION
if (!version.isSameRelease(26, 2, 0) && !version.isSameRelease(26, 1, 2)) {
throw new IllegalStateException("Iris requires Minecraft " + SUPPORTED_VERSIONS
+ ". Detected server version: " + version.value());
}
return SUPPORTED_TAG;
@@ -13,6 +13,7 @@ import java.util.function.Supplier;
@Getter
public enum DataVersion {
UNSUPPORTED("0.0.0", 0, () -> null),
V26_1_2("26.1.2", 101, DataFixerV1217::new),
V26_2("26.2", 107, DataFixerV1217::new);
private static final KMap<DataVersion, IDataFixer> cache = new KMap<>();
@Getter(AccessLevel.NONE)
@@ -51,4 +52,15 @@ public enum DataVersion {
public static DataVersion getLatest() {
return values()[values().length - 1];
}
public static int minSupportedPackFormat() {
int minimum = Integer.MAX_VALUE;
for (DataVersion version : values()) {
if (version == UNSUPPORTED) {
continue;
}
minimum = Math.min(minimum, version.packFormat);
}
return minimum;
}
}
@@ -293,6 +293,6 @@ public class NMSBinding1X implements INMSBinding {
private IllegalStateException unsupportedStructureHook(String operation) {
return new IllegalStateException("Iris cannot " + operation + " with limited NMS binding "
+ getClass().getSimpleName()
+ "; set general.disableNMS=false and use the supported Minecraft 26.2 server runtime");
+ "; set general.disableNMS=false and use a supported Minecraft server runtime (26.1.2 or 26.2)");
}
}
@@ -41,7 +41,6 @@ import java.util.zip.ZipInputStream;
public final class DefaultPackBootstrapProvisioner {
private static final URI DEFAULT_SOURCE = URI.create("https://github.com/IrisDimensions/overworld/releases/download/beta/overworld.zip");
private static final String WORLD_DATAPACK_DIRECTORY = "iris";
private static final int PACK_FORMAT = 107;
private static final int MARKER_SCHEMA = 2;
private static final int MAX_ARCHIVE_ENTRIES = 100_000;
private static final long MAX_ARCHIVE_BYTES = 512L * 1024L * 1024L;
@@ -189,7 +188,7 @@ public final class DefaultPackBootstrapProvisioner {
if (fixer == null) {
throw new IOException("Latest Iris datapack fixer is unavailable during bootstrap");
}
IrisDatapackCompiler.compile(packRoots, outputFolders, fixer, PACK_FORMAT, false);
IrisDatapackCompiler.compile(packRoots, outputFolders, fixer, false);
if (!isDatapackRoot(compileContainer)) {
throw new IOException("Canonical Iris datapack compiler produced incomplete output at " + compileContainer);
}
@@ -23,6 +23,7 @@ import art.arcane.iris.core.loader.IrisData;
import art.arcane.iris.spi.IrisLogging;
import art.arcane.iris.spi.PlatformBlockState;
import art.arcane.iris.core.loader.IrisRegistrant;
import art.arcane.iris.core.nms.datapack.DataVersion;
import art.arcane.iris.core.nms.datapack.IDataFixer;
import art.arcane.iris.core.nms.datapack.IDataFixer.Dimension;
import art.arcane.iris.engine.data.cache.AtomicCache;
@@ -763,7 +764,6 @@ public class IrisDimension extends IrisRegistrant {
public static void writeShared(
KList<File> datapackRoots,
DimensionHeight height,
int packFormat,
boolean adjustVanillaHeight
) throws IOException {
IrisLogging.debug(" Installing Data Pack Vanilla Dimension Types");
@@ -774,16 +774,22 @@ public class IrisDimension extends IrisRegistrant {
write(datapackRoot, "the_end", jsonStrings[2], adjustVanillaHeight);
}
// Ranged formats spanning every supported runtime (26.1.2 = 101, 26.2 = 107). The bootstrap
// provisioner stages this datapack before the server (and INMS) exists, so the runtime
// version cannot be resolved there; a range keeps the emitted bytes identical on both
// install paths and both Paper versions parse ranged min_format/max_format.
int minFormat = DataVersion.minSupportedPackFormat();
int maxFormat = DataVersion.getLatest().getPackFormat();
String raw = """
{
"pack": {
"description": "Iris Data Pack. This pack contains all installed Iris Packs' resources.",
"pack_format": {},
"min_format": {},
"max_format": {}
"pack_format": %d,
"min_format": %d,
"max_format": %d
}
}
""".replace("{}", Integer.toString(packFormat));
""".formatted(maxFormat, minFormat, maxFormat);
for (File datapackRoot : datapackRoots) {
File mcm = new File(datapackRoot, "pack.mcmeta");
@@ -242,10 +242,6 @@ public final class BukkitPlatform implements IrisPlatform {
return INMS.get().applyCustomNbt(itemStack, customNbt);
}
public static int dataPackFormat() {
return INMS.get().getDataVersion().getPackFormat();
}
public static java.util.concurrent.CompletableFuture<Boolean> teleportAsync(Entity entity, Location destination) {
return io.papermc.lib.PaperLib.teleportAsync(entity, destination);
}
@@ -36,6 +36,11 @@ public interface DirectorExecutor extends DirectorExecutorBase {
return sender == null ? null : sender.player();
}
default boolean playerWorldGeneratesStructures() {
Player activePlayer = player();
return activePlayer != null && activePlayer.getWorld().canGenerateStructures();
}
default IrisData data() {
var access = access();
if (access != null) {
@@ -29,7 +29,6 @@ import art.arcane.iris.spi.PlatformStructureHooks;
import art.arcane.iris.util.common.director.DirectorParameterHandler;
import art.arcane.volmlib.util.collection.KList;
import art.arcane.volmlib.util.director.exceptions.DirectorParsingException;
import org.bukkit.entity.Player;
import java.util.LinkedHashMap;
import java.util.List;
@@ -100,8 +99,7 @@ public class StructureHandler implements DirectorParameterHandler<String> {
}
protected boolean nativeStructureGenerationEnabled() {
Player activePlayer = player();
return activePlayer != null && activePlayer.getWorld().canGenerateStructures();
return playerWorldGeneratesStructures();
}
private static Map<String, String> distinctKeys(List<String> keys) {
@@ -1,7 +1,9 @@
package art.arcane.iris.core;
import art.arcane.iris.core.nms.datapack.DataVersion;
import art.arcane.iris.core.nms.datapack.v1217.DataFixerV1217;
import art.arcane.volmlib.util.collection.KList;
import art.arcane.volmlib.util.json.JSONObject;
import org.junit.Rule;
import org.junit.Test;
import org.junit.Assume;
@@ -41,7 +43,6 @@ public class IrisDatapackCompilerTest {
packRoots,
new KList<File>().qadd(datapackRoot.toFile()),
new DataFixerV1217(),
107,
false
);
@@ -72,7 +73,6 @@ public class IrisDatapackCompilerTest {
List.of(packRoot.toFile()),
new KList<File>().qadd(datapackRoot.toFile()),
new DataFixerV1217(),
107,
false
);
@@ -99,6 +99,33 @@ public class IrisDatapackCompilerTest {
IrisDatapackCompiler.collectPackRoots(dataDirectory, serverRoot));
}
@Test
public void packMcmetaSpansEverySupportedRuntimeFormat() throws Exception {
Path datapackRoot = temporaryFolder.newFolder("mcmeta-datapack").toPath();
IrisDatapackCompiler.compile(
List.of(),
new KList<File>().qadd(datapackRoot.toFile()),
new DataFixerV1217(),
false
);
JSONObject pack = new JSONObject(Files.readString(datapackRoot.resolve("pack.mcmeta"), StandardCharsets.UTF_8))
.getJSONObject("pack");
int minFormat = pack.getInt("min_format");
int maxFormat = pack.getInt("max_format");
assertEquals(101, minFormat);
assertEquals(107, maxFormat);
assertEquals(maxFormat, pack.getInt("pack_format"));
// One artifact serves both runtimes: each supported DataVersion's format must be in range.
assertTrue(minFormat <= DataVersion.V26_1_2.getPackFormat()
&& DataVersion.V26_1_2.getPackFormat() <= maxFormat);
assertTrue(minFormat <= DataVersion.V26_2.getPackFormat()
&& DataVersion.V26_2.getPackFormat() <= maxFormat);
}
@Test
public void compilingNoPacksPublishesCleanEmptyDatapack() throws Exception {
Path datapackRoot = temporaryFolder.newFolder("empty-datapack").toPath();
@@ -110,7 +137,6 @@ public class IrisDatapackCompilerTest {
List.of(),
new KList<File>().qadd(datapackRoot.toFile()),
new DataFixerV1217(),
107,
false
);
@@ -57,6 +57,30 @@ public class MinecraftVersionTest {
assertEquals(0, version.patch());
}
@Test
public void parsesThreePartNewSchemeVersion() {
MinecraftVersion version = MinecraftVersion.fromBukkitVersion("26.1.2-R0.1-SNAPSHOT");
assertEquals("26.1.2", version.value());
assertEquals(26, version.major());
assertEquals(1, version.minor());
assertEquals(2, version.patch());
assertTrue(version.isSameRelease(26, 1, 2));
assertFalse(version.isSameRelease(26, 2, 0));
}
@Test
public void detectsThreePartVersionFromDecoratedVersion() {
Server server = mock(Server.class);
doReturn("git-Paper-74 (MC: 26.1.2)").when(server).getVersion();
doReturn("26.1.2-R0.1-SNAPSHOT").when(server).getBukkitVersion();
MinecraftVersion version = MinecraftVersion.detect(server);
assertEquals("26.1.2", version.value());
assertEquals(26, version.major());
assertEquals(1, version.minor());
assertEquals(2, version.patch());
}
@Test
public void comparesMajorBeforeMinor() {
MinecraftVersion version = MinecraftVersion.fromBukkitVersion("26.2-R0.1-SNAPSHOT");
@@ -14,6 +14,13 @@ public class NmsBindingSelectorTest {
assertEquals("v26_2_R1", NmsBindingSelector.select(version));
}
@Test
public void selectsSharedRevisionFor2612() {
MinecraftVersion version = MinecraftVersion.fromBukkitVersion("26.1.2-R0.1-SNAPSHOT");
assertEquals("v26_2_R1", NmsBindingSelector.select(version));
}
@Test
public void rejectsUnsupportedVersionsWithoutProbingAnotherRevision() {
MinecraftVersion version = MinecraftVersion.fromBukkitVersion("26.3-R0.1-SNAPSHOT");
@@ -24,6 +31,16 @@ public class NmsBindingSelectorTest {
assertTrue(failure.getMessage().contains("26.3"));
}
@Test
public void rejectsBasePatchOfSupportedMinorLine() {
MinecraftVersion version = MinecraftVersion.fromBukkitVersion("26.1-R0.1-SNAPSHOT");
IllegalStateException failure = assertThrows(IllegalStateException.class,
() -> NmsBindingSelector.select(version));
assertTrue(failure.getMessage().contains("26.1"));
}
@Test
public void rejectsMissingVersionDetection() {
assertThrows(IllegalStateException.class, () -> NmsBindingSelector.select(null));
@@ -0,0 +1,32 @@
package art.arcane.iris.core.nms.datapack;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
public class DataVersionTest {
@Test
public void latestRemainsNewestSupportedRelease() {
assertSame(DataVersion.V26_2, DataVersion.getLatest());
}
@Test
public void packFormatsMatchServerVersionJson() {
assertEquals(101, DataVersion.V26_1_2.getPackFormat());
assertEquals(107, DataVersion.V26_2.getPackFormat());
}
@Test
public void minSupportedPackFormatIsTheOldestSupportedRuntime() {
assertEquals(101, DataVersion.minSupportedPackFormat());
}
@Test
public void bothSupportedReleasesShareAFixer() {
assertNotNull(DataVersion.V26_1_2.get());
assertNotNull(DataVersion.V26_2.get());
assertSame(DataVersion.V26_1_2.get().getClass(), DataVersion.V26_2.get().getClass());
}
}