diff --git a/core/plugins/Iris/cache/instance b/core/plugins/Iris/cache/instance index 6a677cd79..6f4c51402 100644 --- a/core/plugins/Iris/cache/instance +++ b/core/plugins/Iris/cache/instance @@ -1 +1 @@ --1504154581 \ No newline at end of file +748295809 \ No newline at end of file diff --git a/core/src/main/java/art/arcane/iris/core/commands/CommandIris.java b/core/src/main/java/art/arcane/iris/core/commands/CommandIris.java index 06ad68aaf..f9a78c62e 100644 --- a/core/src/main/java/art/arcane/iris/core/commands/CommandIris.java +++ b/core/src/main/java/art/arcane/iris/core/commands/CommandIris.java @@ -21,6 +21,7 @@ package art.arcane.iris.core.commands; import art.arcane.iris.Iris; import art.arcane.iris.core.IrisSettings; import art.arcane.iris.core.IrisWorlds; +import art.arcane.iris.core.ServerConfigurator; import art.arcane.iris.core.lifecycle.WorldLifecycleService; import art.arcane.iris.core.loader.IrisData; import art.arcane.iris.core.service.StudioSVC; @@ -468,6 +469,7 @@ public class CommandIris implements DirectorExecutor { } else { Iris.service(StudioSVC.class).downloadSearch(sender(), "IrisDimensions/" + pack + "/" + branch, overwrite); } + ServerConfigurator.installDataPacksIfChanged(true); } @Director(description = "Get metrics for your world", aliases = "measure", origin = DirectorOrigin.PLAYER) diff --git a/core/src/main/java/art/arcane/iris/core/commands/CommandStudio.java b/core/src/main/java/art/arcane/iris/core/commands/CommandStudio.java index 625198a84..c23e5a129 100644 --- a/core/src/main/java/art/arcane/iris/core/commands/CommandStudio.java +++ b/core/src/main/java/art/arcane/iris/core/commands/CommandStudio.java @@ -100,7 +100,7 @@ public class CommandStudio implements DirectorExecutor { @Director(description = "Open a new studio world", aliases = "o", sync = true) public void open( - @Param(defaultValue = "default", description = "The dimension to open a studio for", aliases = "dim", customHandler = DimensionHandler.class) + @Param(description = "The dimension pack to open a studio for", aliases = "dim", customHandler = DimensionHandler.class) IrisDimension dimension, @Param(defaultValue = "1337", description = "The seed to generate the studio with", aliases = "s") long seed) { @@ -186,7 +186,7 @@ public class CommandStudio implements DirectorExecutor { @Director(description = "Create a new studio project", aliases = "+", sync = true) public void create( - @Param(description = "The name of this new Iris Project.") + @Param(description = "The name of this new Iris Project.", defaultValue = "studio") String name, @Param( description = "Copy the contents of an existing project in your packs folder and use it as a template in this new project.", @@ -194,10 +194,19 @@ public class CommandStudio implements DirectorExecutor { customHandler = NullableDimensionHandler.class ) IrisDimension template) { + String projectName = name; + if (name.equals("studio")) { + File workspace = Iris.service(StudioSVC.class).getWorkspaceFolder(); + int suffix = 2; + while (new File(workspace, projectName).exists()) { + projectName = "studio" + suffix++; + } + } + if (template != null) { - Iris.service(StudioSVC.class).create(sender(), name, template.getLoadKey()); + Iris.service(StudioSVC.class).create(sender(), projectName, template.getLoadKey()); } else { - Iris.service(StudioSVC.class).create(sender(), name); + Iris.service(StudioSVC.class).create(sender(), projectName); } } diff --git a/core/src/main/java/art/arcane/iris/core/safeguard/Mode.java b/core/src/main/java/art/arcane/iris/core/safeguard/Mode.java index f45474db1..371d21c0a 100644 --- a/core/src/main/java/art/arcane/iris/core/safeguard/Mode.java +++ b/core/src/main/java/art/arcane/iris/core/safeguard/Mode.java @@ -61,7 +61,7 @@ public enum Mode { } public void splash() { - String padd = Form.repeat(" ", 8); + String padd = Form.repeat(" ", 4); String padd2 = Form.repeat(" ", 4); String version = Iris.instance.getDescription().getVersion(); String releaseTrain = getReleaseTrain(version); @@ -98,10 +98,8 @@ public enum Mode { double headThickness = 3.7 + random.nextDouble() * 0.6; double tipReach = 19.0 + random.nextDouble() * 4.0; double notchX = 3.5 + random.nextDouble() * 1.5; - double streamReach = 22.0 + random.nextDouble() * 3.0; double[][][] spines = splashFinSpines(tipReach); double[][][] voids = splashNotchVoids(notchX); - double[][][] streams = splashStreamSpines(notchX, streamReach); String[] lines = new String[SPLASH_HEIGHT]; for (int y = 0; y < SPLASH_HEIGHT; y++) { StringBuilder line = new StringBuilder(); @@ -109,7 +107,7 @@ public enum Mode { for (int x = 0; x < SPLASH_WIDTH; x++) { char glyph = splashEyeGlyph(x, y); if (glyph == 0) { - glyph = splashFinGlyph(x, y, spines, voids, streams, headThickness); + glyph = splashFinGlyph(x, y, spines, voids, headThickness); } if (glyph == 0 || glyph == ' ') { line.append(' '); @@ -160,7 +158,7 @@ public enum Mode { return 0; } - private char splashFinGlyph(int x, int y, double[][][] spines, double[][][] voids, double[][][] streams, double headThickness) { + private char splashFinGlyph(int x, int y, double[][][] spines, double[][][] voids, double headThickness) { if (splashEyeRadius(x, y) <= 1.26) { return 0; } @@ -181,7 +179,6 @@ public enum Mode { } double best = Double.MAX_VALUE; double bestT = 0.0; - double bestSpineY = 0.0; for (double[][] spine : spines) { for (int i = 0; i < spine.length; i++) { double t = i / (double) (spine.length - 1); @@ -192,7 +189,6 @@ public enum Mode { if (distance < best) { best = distance; bestT = t; - bestSpineY = spine[i][1]; } } } @@ -200,41 +196,20 @@ public enum Mode { + Math.max(0.0, 3.0 - Math.min(x, SPLASH_WIDTH - 1 - x)) * 0.12 + Math.max(0.0, 0.10 - bestT) * 1.5 + Math.max(0.0, 1.30 - voidDistance) * 0.15; - if (shade <= 1.0) { - int level = shade <= 0.70 ? 0 : shade <= 0.90 ? 1 : 2; - if (bestT > 0.97) { - level += 2; - } else if (bestT > 0.88) { - level += 1; - } - return switch (Math.min(level, 2)) { - case 0 -> '#'; - case 1 -> '='; - default -> '-'; - }; + if (shade > 1.0) { + return 0; } - if (bestT < 0.25 && Math.abs(bestSpineY - SPLASH_CENTER_Y) > 2.5 && shade <= 1.25) { - return '-'; + int level = shade <= 0.70 ? 0 : shade <= 0.90 ? 1 : 2; + if (bestT > 0.97) { + level += 2; + } else if (bestT > 0.88) { + level += 1; } - if (bestT > 0.88 && shade <= 1.45) { - return '-'; - } - double streamBest = Double.MAX_VALUE; - for (double[][] stream : streams) { - for (double[] sample : stream) { - double thickness = Math.max(0.4, 0.85 - 0.4 * sample[2]); - double dx = (x - sample[0]) / SPLASH_ASPECT; - double dy = y - sample[1]; - double distance = Math.sqrt(dx * dx + dy * dy) / thickness; - if (distance < streamBest) { - streamBest = distance; - } - } - } - if (streamBest <= 1.0) { - return '-'; - } - return 0; + return switch (Math.min(level, 2)) { + case 0 -> '#'; + case 1 -> '='; + default -> '-'; + }; } private double splashEyeRadius(int x, int y) { @@ -265,26 +240,6 @@ public enum Mode { return new double[][][]{left, right}; } - private double[][][] splashStreamSpines(double notchX, double streamReach) { - double[][] control = {{notchX + 2.5, 10.2}, {13.0, 10.4}, {streamReach, 10.9}}; - int samples = 41; - double[][] left = new double[samples][3]; - double[][] right = new double[samples][3]; - for (int i = 0; i < samples; i++) { - double t = i / (double) (samples - 1); - double u = 1.0 - t; - double bx = u * u * control[0][0] + 2.0 * u * t * control[1][0] + t * t * control[2][0]; - double by = u * u * control[0][1] + 2.0 * u * t * control[1][1] + t * t * control[2][1]; - left[i][0] = bx; - left[i][1] = by; - left[i][2] = t; - right[i][0] = (SPLASH_WIDTH - 1.0) - bx; - right[i][1] = (SPLASH_HEIGHT - 1.0) - by; - right[i][2] = t; - } - return new double[][][]{left, right}; - } - private double[][][] splashFinSpines(double tipReach) { double[][] control = {{-1.5, 9.8}, {0.4, 4.4}, {5.2, 1.0}, {tipReach, 0.4}}; int samples = 61; diff --git a/core/src/main/java/art/arcane/iris/core/safeguard/task/Tasks.java b/core/src/main/java/art/arcane/iris/core/safeguard/task/Tasks.java index a2a1778ac..ca7982939 100644 --- a/core/src/main/java/art/arcane/iris/core/safeguard/task/Tasks.java +++ b/core/src/main/java/art/arcane/iris/core/safeguard/task/Tasks.java @@ -107,14 +107,6 @@ public final class Tasks { }); private static final Task INJECTION = Task.of("injection", () -> { - if (!isPaperPreferredServer() && !Agent.isInstalled()) { - return withDiagnostics(Mode.WARNING, - Diagnostic.Logger.WARN.create("Java Agent"), - Diagnostic.Logger.WARN.create("- Skipping dynamic Java agent attach on Spigot/Bukkit to avoid runtime agent warnings."), - Diagnostic.Logger.WARN.create("- For full runtime injection support, run with -javaagent:" - + Agent.AGENT_JAR.getPath() + " or use Canvas/Folia/Paper/Purpur.")); - } - if (!Agent.install()) { return withDiagnostics(Mode.UNSTABLE, Diagnostic.Logger.ERROR.create("Java Agent"), @@ -193,15 +185,6 @@ public final class Tasks { return Bukkit.getServer(); } - private static boolean isPaperPreferredServer() { - String name = server().getName().toLowerCase(Locale.ROOT); - return isCanvasServer() - || name.contains("folia") - || name.contains("paper") - || name.contains("purpur") - || name.contains("pufferfish"); - } - private static boolean isCanvasServer() { ClassLoader loader = server().getClass().getClassLoader(); try { diff --git a/core/src/main/java/art/arcane/iris/core/service/StudioSVC.java b/core/src/main/java/art/arcane/iris/core/service/StudioSVC.java index 147cea270..218ab2b3b 100644 --- a/core/src/main/java/art/arcane/iris/core/service/StudioSVC.java +++ b/core/src/main/java/art/arcane/iris/core/service/StudioSVC.java @@ -73,6 +73,7 @@ public class StudioSVC implements IrisService { if (pack.equals("overworld")) { Iris.info("Downloading Default Pack " + pack + " (latest on master)"); Iris.service(StudioSVC.class).downloadBranch(Iris.getSender(), "IrisDimensions/overworld", "master", false); + ServerConfigurator.installDataPacksIfChanged(true); } else { Iris.warn("Default pack '" + pack + "' is not installed. Please download it manually with /iris download " + pack); } diff --git a/core/src/main/java/art/arcane/iris/core/tools/IrisCreator.java b/core/src/main/java/art/arcane/iris/core/tools/IrisCreator.java index 869b48600..f45609327 100644 --- a/core/src/main/java/art/arcane/iris/core/tools/IrisCreator.java +++ b/core/src/main/java/art/arcane/iris/core/tools/IrisCreator.java @@ -223,6 +223,10 @@ public class IrisCreator { if (J.isFolia() && containsCreateWorldUnsupportedOperation(e)) { throw new IrisException("Runtime world creation is blocked and the selected world lifecycle backend could not create the world.", e); } + if (containsMissingDimensionTypes(e)) { + throw new IrisException("The dimension types for pack \"" + dimension() + "\" are not loaded on this server yet. " + + "Iris installed its datapack files - restart the server, then run the command again.", e); + } throw new IrisException("Failed to create world with backend family " + WorldLifecycleService.get().capabilities().serverFamily().id() + "!", e); } @@ -389,6 +393,17 @@ public class IrisCreator { return false; } + private static boolean containsMissingDimensionTypes(Throwable throwable) { + Throwable cursor = throwable; + while (cursor != null) { + if (cursor instanceof IllegalStateException && String.valueOf(cursor.getMessage()).contains("Missing dimension types")) { + return true; + } + cursor = cursor.getCause(); + } + return false; + } + private void addToBukkitYml() { YamlConfiguration yml = YamlConfiguration.loadConfiguration(BUKKIT_YML); String gen = "Iris:" + dimension; diff --git a/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/CustomBiomeSource.java b/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/CustomBiomeSource.java index c95ce7a6d..75d0b10a9 100644 --- a/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/CustomBiomeSource.java +++ b/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/CustomBiomeSource.java @@ -60,6 +60,13 @@ public class CustomBiomeSource extends BiomeSource { } for (IrisBiome i : engine.getAllBiomes()) { + Holder vanillaHolder = NMSBinding.biomeToBiomeBase(registry, i.getVanillaDerivative()); + if (vanillaHolder != null) { + biomes.add(vanillaHolder); + } else if (!i.isCustom() && fallback != null) { + biomes.add(fallback); + } + if (i.isCustom()) { for (IrisBiomeCustom j : i.getCustomDerivitives()) { Holder customHolder = resolveCustomBiomeHolder(customRegistry, engine, j.getId()); @@ -69,13 +76,6 @@ public class CustomBiomeSource extends BiomeSource { biomes.add(fallback); } } - } else { - Holder vanillaHolder = NMSBinding.biomeToBiomeBase(registry, i.getVanillaDerivative()); - if (vanillaHolder != null) { - biomes.add(vanillaHolder); - } else if (fallback != null) { - biomes.add(fallback); - } } } @@ -219,15 +219,15 @@ public class CustomBiomeSource extends BiomeSource { return getFallbackBiome(); } - if (resolution.irisBiome.isCustom()) { - return resolveCustomHolder(resolution); - } - Holder holder = NMSBinding.biomeToBiomeBase(biomeRegistry, resolution.irisBiome.getVanillaDerivative()); if (holder != null) { return holder; } + if (resolution.irisBiome.isCustom()) { + return resolveCustomHolder(resolution); + } + return getFallbackBiome(); } diff --git a/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/IrisChunkGenerator.java b/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/IrisChunkGenerator.java index 2b582e504..a570093ef 100644 --- a/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/IrisChunkGenerator.java +++ b/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/IrisChunkGenerator.java @@ -58,7 +58,7 @@ public class IrisChunkGenerator extends CustomChunkGenerator { } private IrisChunkGenerator(ChunkGenerator delegate, Engine engine, World world, CustomBiomeSource customBiomeSource) { - super(((CraftWorld) world).getHandle(), edit(delegate, customBiomeSource), null); + super(((CraftWorld) world).getHandle(), edit(delegate, customBiomeSource), world.getGenerator()); this.delegate = delegate; this.engine = engine; this.customBiomeSource = customBiomeSource; @@ -105,6 +105,8 @@ public class IrisChunkGenerator extends CustomChunkGenerator { try { return delegate.findNearestMapStructure(level, reachable, pos, radius, findUnexplored); } catch (Throwable e) { + Iris.error("Vanilla structure locate failed near " + pos.getX() + ", " + pos.getZ() + ": " + e); + Iris.reportError(e); return null; } } @@ -159,7 +161,7 @@ public class IrisChunkGenerator extends CustomChunkGenerator { if (!importedControl().active()) { return; } - delegate.createStructures(registryAccess, structureState, structureManager, access, templateManager, levelKey); + super.createStructures(registryAccess, structureState, structureManager, access, templateManager, levelKey); } private IrisImportedStructureControl importedControl() { diff --git a/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/NMSBinding.java b/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/NMSBinding.java index 30eb85956..6e82a120c 100644 --- a/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/NMSBinding.java +++ b/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/NMSBinding.java @@ -61,6 +61,7 @@ import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.levelgen.FlatLevelSource; import net.minecraft.world.level.levelgen.flat.FlatLayerInfo; import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings; +import net.minecraft.world.level.levelgen.structure.StructureCheck; import net.minecraft.world.level.storage.LevelStorageSource; import org.bukkit.*; import org.bukkit.block.Biome; @@ -624,11 +625,28 @@ public class NMSBinding implements INMSBinding { Iris.error("Loaded world %s with unknown dimension type! expected=%s", world.getName(), expectedDimensionType); } + IrisChunkGenerator irisGenerator = new IrisChunkGenerator(worldGenContext.generator(), seed, engine, world); var newContext = new WorldGenContext( - worldGenContext.level(), new IrisChunkGenerator(worldGenContext.generator(), seed, engine, world), + worldGenContext.level(), irisGenerator, worldGenContext.structureManager(), worldGenContext.lightEngine(), worldGenContext.mainThreadExecutor(), worldGenContext.unsavedListener()); worldGenContextField.set(chunkMap, newContext); + retargetStructureCheck(((CraftWorld) world).getHandle(), irisGenerator); + } + + private static void retargetStructureCheck(ServerLevel level, IrisChunkGenerator generator) throws NoSuchFieldException, IllegalAccessException { + Field structureCheckField = getField(level.getClass(), StructureCheck.class); + structureCheckField.setAccessible(true); + Object structureCheck = structureCheckField.get(level); + if (structureCheck == null) { + return; + } + Field generatorField = getField(structureCheck.getClass(), net.minecraft.world.level.chunk.ChunkGenerator.class); + generatorField.setAccessible(true); + generatorField.set(structureCheck, generator); + Field biomeSourceField = getField(structureCheck.getClass(), BiomeSource.class); + biomeSourceField.setAccessible(true); + biomeSourceField.set(structureCheck, generator.getBiomeSource()); } public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) { diff --git a/nms/v26_1_R1/src/main/java/art/arcane/iris/core/nms/v26_1_R1/CustomBiomeSource.java b/nms/v26_1_R1/src/main/java/art/arcane/iris/core/nms/v26_1_R1/CustomBiomeSource.java index 5aefe7c64..f992a6472 100644 --- a/nms/v26_1_R1/src/main/java/art/arcane/iris/core/nms/v26_1_R1/CustomBiomeSource.java +++ b/nms/v26_1_R1/src/main/java/art/arcane/iris/core/nms/v26_1_R1/CustomBiomeSource.java @@ -60,6 +60,13 @@ public class CustomBiomeSource extends BiomeSource { } for (IrisBiome i : engine.getAllBiomes()) { + Holder vanillaHolder = NMSBinding.biomeToBiomeBase(registry, i.getVanillaDerivative()); + if (vanillaHolder != null) { + biomes.add(vanillaHolder); + } else if (!i.isCustom() && fallback != null) { + biomes.add(fallback); + } + if (i.isCustom()) { for (IrisBiomeCustom j : i.getCustomDerivitives()) { Holder customHolder = resolveCustomBiomeHolder(customRegistry, engine, j.getId()); @@ -69,13 +76,6 @@ public class CustomBiomeSource extends BiomeSource { biomes.add(fallback); } } - } else { - Holder vanillaHolder = NMSBinding.biomeToBiomeBase(registry, i.getVanillaDerivative()); - if (vanillaHolder != null) { - biomes.add(vanillaHolder); - } else if (fallback != null) { - biomes.add(fallback); - } } } @@ -219,15 +219,15 @@ public class CustomBiomeSource extends BiomeSource { return getFallbackBiome(); } - if (resolution.irisBiome.isCustom()) { - return resolveCustomHolder(resolution); - } - Holder holder = NMSBinding.biomeToBiomeBase(biomeRegistry, resolution.irisBiome.getVanillaDerivative()); if (holder != null) { return holder; } + if (resolution.irisBiome.isCustom()) { + return resolveCustomHolder(resolution); + } + return getFallbackBiome(); } diff --git a/nms/v26_1_R1/src/main/java/art/arcane/iris/core/nms/v26_1_R1/IrisChunkGenerator.java b/nms/v26_1_R1/src/main/java/art/arcane/iris/core/nms/v26_1_R1/IrisChunkGenerator.java index 59532c319..aa5eebdbf 100644 --- a/nms/v26_1_R1/src/main/java/art/arcane/iris/core/nms/v26_1_R1/IrisChunkGenerator.java +++ b/nms/v26_1_R1/src/main/java/art/arcane/iris/core/nms/v26_1_R1/IrisChunkGenerator.java @@ -58,7 +58,7 @@ public class IrisChunkGenerator extends CustomChunkGenerator { } private IrisChunkGenerator(ChunkGenerator delegate, Engine engine, World world, CustomBiomeSource customBiomeSource) { - super(((CraftWorld) world).getHandle(), edit(delegate, customBiomeSource), null); + super(((CraftWorld) world).getHandle(), edit(delegate, customBiomeSource), world.getGenerator()); this.delegate = delegate; this.engine = engine; this.customBiomeSource = customBiomeSource; @@ -105,6 +105,8 @@ public class IrisChunkGenerator extends CustomChunkGenerator { try { return delegate.findNearestMapStructure(level, reachable, pos, radius, findUnexplored); } catch (Throwable e) { + Iris.error("Vanilla structure locate failed near " + pos.getX() + ", " + pos.getZ() + ": " + e); + Iris.reportError(e); return null; } } @@ -159,7 +161,7 @@ public class IrisChunkGenerator extends CustomChunkGenerator { if (!importedControl().active()) { return; } - delegate.createStructures(registryAccess, structureState, structureManager, access, templateManager, levelKey); + super.createStructures(registryAccess, structureState, structureManager, access, templateManager, levelKey); } private IrisImportedStructureControl importedControl() { diff --git a/nms/v26_1_R1/src/main/java/art/arcane/iris/core/nms/v26_1_R1/NMSBinding.java b/nms/v26_1_R1/src/main/java/art/arcane/iris/core/nms/v26_1_R1/NMSBinding.java index 4b98994a5..abaa1b1ae 100644 --- a/nms/v26_1_R1/src/main/java/art/arcane/iris/core/nms/v26_1_R1/NMSBinding.java +++ b/nms/v26_1_R1/src/main/java/art/arcane/iris/core/nms/v26_1_R1/NMSBinding.java @@ -65,6 +65,7 @@ import net.minecraft.world.level.levelgen.FlatLevelSource; import net.minecraft.world.level.levelgen.Heightmap; import net.minecraft.world.level.levelgen.WorldgenRandom; import net.minecraft.world.level.levelgen.XoroshiroRandomSource; +import net.minecraft.world.level.levelgen.structure.StructureCheck; import net.minecraft.world.level.levelgen.feature.AbstractHugeMushroomFeature; import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; import net.minecraft.world.level.levelgen.feature.FallenTreeFeature; @@ -853,11 +854,28 @@ public class NMSBinding implements INMSBinding { Iris.error("Loaded world %s with unknown dimension type! expected=%s", world.getName(), expectedDimensionType); } + IrisChunkGenerator irisGenerator = new IrisChunkGenerator(worldGenContext.generator(), seed, engine, world); var newContext = new WorldGenContext( - worldGenContext.level(), new IrisChunkGenerator(worldGenContext.generator(), seed, engine, world), + worldGenContext.level(), irisGenerator, worldGenContext.structureManager(), worldGenContext.lightEngine(), worldGenContext.mainThreadExecutor(), worldGenContext.unsavedListener()); worldGenContextField.set(chunkMap, newContext); + retargetStructureCheck(((CraftWorld) world).getHandle(), irisGenerator); + } + + private static void retargetStructureCheck(ServerLevel level, IrisChunkGenerator generator) throws NoSuchFieldException, IllegalAccessException { + Field structureCheckField = getField(level.getClass(), StructureCheck.class); + structureCheckField.setAccessible(true); + Object structureCheck = structureCheckField.get(level); + if (structureCheck == null) { + return; + } + Field generatorField = getField(structureCheck.getClass(), net.minecraft.world.level.chunk.ChunkGenerator.class); + generatorField.setAccessible(true); + generatorField.set(structureCheck, generator); + Field biomeSourceField = getField(structureCheck.getClass(), BiomeSource.class); + biomeSourceField.setAccessible(true); + biomeSourceField.set(structureCheck, generator.getBiomeSource()); } public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) {