From 4434cf6475ee7a3edab4db9ffc01273487dc1f1a Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Thu, 22 Aug 2024 20:31:24 +0200 Subject: [PATCH] add headless pregen to world creation --- .../iris/core/commands/CommandIris.java | 3 + .../iris/core/pregenerator/EmptyListener.java | 87 +++++++++++++++++++ .../volmit/iris/core/tools/IrisCreator.java | 33 ++++--- .../engine/platform/BukkitChunkGenerator.java | 65 +++++++++----- .../platform/PlatformChunkGenerator.java | 2 + 5 files changed, 154 insertions(+), 36 deletions(-) create mode 100644 core/src/main/java/com/volmit/iris/core/pregenerator/EmptyListener.java diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandIris.java b/core/src/main/java/com/volmit/iris/core/commands/CommandIris.java index f357aafac..d0d15cffe 100644 --- a/core/src/main/java/com/volmit/iris/core/commands/CommandIris.java +++ b/core/src/main/java/com/volmit/iris/core/commands/CommandIris.java @@ -103,6 +103,8 @@ public class CommandIris implements DecreeExecutor { IrisDimension type, @Param(description = "The seed to generate the world with", defaultValue = "1337") long seed, + @Param(description = "The radius of chunks to generate in headless mode (-1 to disable)", defaultValue = "10", aliases = "radius") + int headlessRadius, @Param(description = "If it should convert the dimension to match the vanilla height system.", defaultValue = "false") boolean vanillaheight ) { @@ -132,6 +134,7 @@ public class CommandIris implements DecreeExecutor { .sender(sender()) .studio(false) .smartVanillaHeight(vanillaheight) + .headlessRadius(headlessRadius) .create(); } catch (Throwable e) { sender().sendMessage(C.RED + "Exception raised during creation. See the console for more details."); diff --git a/core/src/main/java/com/volmit/iris/core/pregenerator/EmptyListener.java b/core/src/main/java/com/volmit/iris/core/pregenerator/EmptyListener.java new file mode 100644 index 000000000..13d4f696a --- /dev/null +++ b/core/src/main/java/com/volmit/iris/core/pregenerator/EmptyListener.java @@ -0,0 +1,87 @@ +package com.volmit.iris.core.pregenerator; + +public final class EmptyListener implements PregenListener { + public static final PregenListener INSTANCE = new EmptyListener(); + + private EmptyListener() {} + + @Override + public void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, int generated, int totalChunks, int chunksRemaining, long eta, long elapsed, String method) { + + } + + @Override + public void onChunkGenerating(int x, int z) { + + } + + @Override + public void onServerShutdown() { + + } + + @Override + public void onChunkGenerated(int x, int z) { + + } + + @Override + public void onRegionGenerated(int x, int z) { + + } + + @Override + public void onRegionGenerating(int x, int z) { + + } + + @Override + public void onChunkCleaned(int x, int z) { + + } + + @Override + public void onRegionSkipped(int x, int z) { + + } + + @Override + public void onNetworkStarted(int x, int z) { + + } + + @Override + public void onNetworkFailed(int x, int z) { + + } + + @Override + public void onNetworkReclaim(int revert) { + + } + + @Override + public void onNetworkGeneratedChunk(int x, int z) { + + } + + @Override + public void onNetworkDownloaded(int x, int z) { + + } + + @Override + public void onClose() { + + } + + @Override + public void onSaving() { + + } + + @Override + public void onChunkExistsInRegionGen(int x, int z) { + + } +} diff --git a/core/src/main/java/com/volmit/iris/core/tools/IrisCreator.java b/core/src/main/java/com/volmit/iris/core/tools/IrisCreator.java index e5f41908f..11876c6ed 100644 --- a/core/src/main/java/com/volmit/iris/core/tools/IrisCreator.java +++ b/core/src/main/java/com/volmit/iris/core/tools/IrisCreator.java @@ -83,6 +83,11 @@ public class IrisCreator { */ private boolean benchmark = false; private boolean smartVanillaHeight = false; + /** + * Radius of chunks to pregenerate in the headless mode + * if set to -1, headless mode is disabled + */ + private int headlessRadius = 10; public static boolean removeFromBukkitYml(String name) throws IOException { YamlConfiguration yml = YamlConfiguration.loadConfiguration(BUKKIT_YML); @@ -130,7 +135,6 @@ public class IrisCreator { Iris.service(StudioSVC.class).installIntoWorld(sender, d.getLoadKey(), new File(Bukkit.getWorldContainer(), name())); } - PlatformChunkGenerator access = null; AtomicReference world = new AtomicReference<>(); AtomicDouble pp = new AtomicDouble(0); O done = new O<>(); @@ -142,21 +146,26 @@ public class IrisCreator { .studio(studio) .smartVanillaHeight(smartVanillaHeight) .create(); + PlatformChunkGenerator access = (PlatformChunkGenerator) wc.generator(); + if (access == null) { + throw new IrisException("Access is null. Something bad happened."); + } - access = (PlatformChunkGenerator) wc.generator(); - PlatformChunkGenerator finalAccess1 = access; - - J.a(() -> - { + try { + access.prepareSpawnChunks(seed, headlessRadius); + } catch (Throwable e) { + Iris.error("Failed to prepare spawn chunks for " + name); + e.printStackTrace(); + } + J.a(() -> { Supplier g = () -> { - if (finalAccess1 == null || finalAccess1.getEngine() == null) { + if (access.getEngine() == null) { return 0; } - return finalAccess1.getEngine().getGenerated(); + return access.getEngine().getGenerated(); }; if (!benchmark) { - if (finalAccess1 == null) return; - int req = finalAccess1.getSpawnChunks().join(); + int req = access.getSpawnChunks().join(); while (g.get() < req) { double v = (double) g.get() / (double) req; @@ -180,10 +189,6 @@ public class IrisCreator { e.printStackTrace(); } - if (access == null) { - throw new IrisException("Access is null. Something bad happened."); - } - done.set(true); if (sender.isPlayer() && !benchmark) { diff --git a/core/src/main/java/com/volmit/iris/engine/platform/BukkitChunkGenerator.java b/core/src/main/java/com/volmit/iris/engine/platform/BukkitChunkGenerator.java index f6eeb1b5c..8919a7d16 100644 --- a/core/src/main/java/com/volmit/iris/engine/platform/BukkitChunkGenerator.java +++ b/core/src/main/java/com/volmit/iris/engine/platform/BukkitChunkGenerator.java @@ -21,6 +21,8 @@ package com.volmit.iris.engine.platform; import com.volmit.iris.Iris; import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.core.nms.INMS; +import com.volmit.iris.core.pregenerator.EmptyListener; +import com.volmit.iris.core.pregenerator.methods.HeadlessPregenMethod; import com.volmit.iris.core.service.StudioSVC; import com.volmit.iris.engine.IrisEngine; import com.volmit.iris.engine.data.chunk.TerrainChunk; @@ -132,27 +134,26 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun if (initialized || !world.name().equals(event.getWorld().getName())) return; world.setRawWorldSeed(event.getWorld().getSeed()); - Engine engine = getEngine(event.getWorld()); - if (engine == null) { - Iris.warn("Failed to get Engine!"); - J.s(() -> { - Engine engine1 = getEngine(event.getWorld()); - if (engine1 != null) { - try { - INMS.get().inject(event.getWorld().getSeed(), engine1, event.getWorld()); - Iris.info("Injected Iris Biome Source into " + event.getWorld().getName()); - initialized = true; - } catch (Throwable e) { - e.printStackTrace(); - } - } - }, 10); - } else { - INMS.get().inject(event.getWorld().getSeed(), engine, event.getWorld()); - Iris.info("Injected Iris Biome Source into " + event.getWorld().getName()); - spawnChunks.complete(INMS.get().getSpawnChunkCount(event.getWorld())); - initialized = true; - + Engine engine = getEngine(event.getWorld()); + if (engine == null) { + Iris.warn("Failed to get Engine!"); + J.s(() -> { + Engine engine1 = getEngine(event.getWorld()); + if (engine1 != null) { + try { + INMS.get().inject(event.getWorld().getSeed(), engine1, event.getWorld()); + Iris.info("Injected Iris Biome Source into " + event.getWorld().getName()); + initialized = true; + } catch (Throwable e) { + e.printStackTrace(); + } + } + }, 10); + } else { + INMS.get().inject(event.getWorld().getSeed(), engine, event.getWorld()); + Iris.info("Injected Iris Biome Source into " + event.getWorld().getName()); + spawnChunks.complete(INMS.get().getSpawnChunkCount(event.getWorld())); + initialized = true; } } catch (Throwable e) { e.printStackTrace(); @@ -265,7 +266,10 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun } private Engine getEngine(WorldInfo world) { + return getEngine(world.getSeed()); + } + private Engine getEngine(long seed) { if (setup.get()) { return getEngine(); } @@ -278,7 +282,7 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun } - getWorld().setRawWorldSeed(world.getSeed()); + getWorld().setRawWorldSeed(seed); setupEngine(); setup.set(true); this.hotloader = studio ? new Looper() { @@ -349,6 +353,23 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun getEngine(world); } + @Override + public void prepareSpawnChunks(long seed, int radius) { + if (radius < 0 || new File(world.worldFolder(), "level.dat").exists()) + return; + + var engine = getEngine(seed); + var headless = new HeadlessPregenMethod(engine); + Iris.info("Generating " + world.name() + " in headless mode"); + for (int x = -radius; x <= radius; x++) { + for (int z = -radius; z <= radius; z++) { + headless.generateChunk(x, z, EmptyListener.INSTANCE); + } + } + headless.close(); + Iris.info("Done generating " + world.name() + " in headless mode"); + } + @Override public void generateNoise(@NotNull WorldInfo world, @NotNull Random random, int x, int z, @NotNull ChunkGenerator.ChunkData d) { try { diff --git a/core/src/main/java/com/volmit/iris/engine/platform/PlatformChunkGenerator.java b/core/src/main/java/com/volmit/iris/engine/platform/PlatformChunkGenerator.java index ccb6ac7b0..be4803820 100644 --- a/core/src/main/java/com/volmit/iris/engine/platform/PlatformChunkGenerator.java +++ b/core/src/main/java/com/volmit/iris/engine/platform/PlatformChunkGenerator.java @@ -49,4 +49,6 @@ public interface PlatformChunkGenerator extends Hotloadable, DataProvider { void touch(World world); CompletableFuture getSpawnChunks(); + + void prepareSpawnChunks(long seed, int radius); }