diff --git a/src/main/java/com/volmit/iris/core/pregenerator/methods/DummyPregenMethod.java b/src/main/java/com/volmit/iris/core/pregenerator/methods/DummyPregenMethod.java
new file mode 100644
index 000000000..08c108431
--- /dev/null
+++ b/src/main/java/com/volmit/iris/core/pregenerator/methods/DummyPregenMethod.java
@@ -0,0 +1,59 @@
+/*
+ * Iris is a World Generator for Minecraft Bukkit Servers
+ * Copyright (c) 2021 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 .
+ */
+
+package com.volmit.iris.core.pregenerator.methods;
+
+import com.volmit.iris.core.pregenerator.PregenListener;
+import com.volmit.iris.core.pregenerator.PregeneratorMethod;
+
+public class DummyPregenMethod implements PregeneratorMethod {
+ @Override
+ public void init() {
+
+ }
+
+ @Override
+ public void close() {
+
+ }
+
+ @Override
+ public String getMethod(int x, int z) {
+ return "Dummy";
+ }
+
+ @Override
+ public void save() {
+
+ }
+
+ @Override
+ public boolean supportsRegions(int x, int z) {
+ return false;
+ }
+
+ @Override
+ public void generateRegion(int x, int z, PregenListener listener) {
+
+ }
+
+ @Override
+ public void generateChunk(int x, int z) {
+
+ }
+}
diff --git a/src/main/java/com/volmit/iris/core/pregenerator/methods/HeadlessPregenMethod.java b/src/main/java/com/volmit/iris/core/pregenerator/methods/HeadlessPregenMethod.java
new file mode 100644
index 000000000..c42155da0
--- /dev/null
+++ b/src/main/java/com/volmit/iris/core/pregenerator/methods/HeadlessPregenMethod.java
@@ -0,0 +1,70 @@
+/*
+ * Iris is a World Generator for Minecraft Bukkit Servers
+ * Copyright (c) 2021 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 .
+ */
+
+package com.volmit.iris.core.pregenerator.methods;
+
+import com.volmit.iris.core.pregenerator.PregenListener;
+import com.volmit.iris.core.pregenerator.PregeneratorMethod;
+import com.volmit.iris.engine.headless.HeadlessGenerator;
+import com.volmit.iris.engine.headless.HeadlessWorld;
+
+public class HeadlessPregenMethod implements PregeneratorMethod {
+ private final HeadlessWorld world;
+ private final HeadlessGenerator generator;
+
+ public HeadlessPregenMethod(HeadlessWorld world)
+ {
+ this.world = world;
+ this.generator = world.generate();
+ }
+
+ @Override
+ public void init() {
+
+ }
+
+ @Override
+ public void close() {
+ generator.close();
+ }
+
+ @Override
+ public void save() {
+ generator.save();
+ }
+
+ @Override
+ public boolean supportsRegions(int x, int z) {
+ return true;
+ }
+
+ @Override
+ public String getMethod(int x, int z) {
+ return "Headless";
+ }
+
+ @Override
+ public void generateRegion(int x, int z, PregenListener listener) {
+ generator.generateRegion(x, z, listener);
+ }
+
+ @Override
+ public void generateChunk(int x, int z) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/src/main/java/com/volmit/iris/core/pregenerator/methods/HybridPregenMethod.java b/src/main/java/com/volmit/iris/core/pregenerator/methods/HybridPregenMethod.java
new file mode 100644
index 000000000..b6efb1c25
--- /dev/null
+++ b/src/main/java/com/volmit/iris/core/pregenerator/methods/HybridPregenMethod.java
@@ -0,0 +1,87 @@
+/*
+ * Iris is a World Generator for Minecraft Bukkit Servers
+ * Copyright (c) 2021 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 .
+ */
+
+package com.volmit.iris.core.pregenerator.methods;
+
+import com.volmit.iris.core.pregenerator.PregenListener;
+import com.volmit.iris.core.pregenerator.PregeneratorMethod;
+import com.volmit.iris.engine.IrisWorlds;
+import com.volmit.iris.engine.headless.HeadlessWorld;
+import org.bukkit.World;
+
+import java.io.File;
+
+public class HybridPregenMethod implements PregeneratorMethod {
+ private final PregeneratorMethod headless;
+ private final PregeneratorMethod inWorld;
+ private final World world;
+
+ public HybridPregenMethod(World world, int threads)
+ {
+ this.world = world;
+ headless = supportsHeadless(world)
+ ? new HeadlessPregenMethod(HeadlessWorld.from(world)) : new DummyPregenMethod();
+ inWorld = new PaperOrMedievalPregenMethod(world, threads);
+ }
+
+ private boolean supportsHeadless(World world) {
+ return IrisWorlds.access(world) != null;
+ }
+
+ @Override
+ public String getMethod(int x, int z) {
+ return "Hybrid<" + ((supportsRegions(x, z) ? headless.getMethod(x, z) : inWorld.getMethod(x, z)) + ">");
+ }
+
+ @Override
+ public void init() {
+ headless.init();
+ inWorld.init();
+ }
+
+ @Override
+ public void close() {
+ headless.close();
+ inWorld.close();
+ }
+
+ @Override
+ public void save() {
+ headless.save();
+ inWorld.save();
+ }
+
+ @Override
+ public boolean supportsRegions(int x, int z) {
+ if (headless instanceof DummyPregenMethod) {
+ return false;
+ }
+
+ return !new File(world.getWorldFolder(), "region/r." + x + "." + z + ".mca").exists();
+ }
+
+ @Override
+ public void generateRegion(int x, int z, PregenListener listener) {
+ headless.generateRegion(x, z, listener);
+ }
+
+ @Override
+ public void generateChunk(int x, int z) {
+ inWorld.generateChunk(x, z);
+ }
+}
diff --git a/src/main/java/com/volmit/iris/core/pregenerator/methods/MedievalPregenMethod.java b/src/main/java/com/volmit/iris/core/pregenerator/methods/MedievalPregenMethod.java
new file mode 100644
index 000000000..51ec8086c
--- /dev/null
+++ b/src/main/java/com/volmit/iris/core/pregenerator/methods/MedievalPregenMethod.java
@@ -0,0 +1,80 @@
+/*
+ * Iris is a World Generator for Minecraft Bukkit Servers
+ * Copyright (c) 2021 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 .
+ */
+
+package com.volmit.iris.core.pregenerator.methods;
+
+import com.volmit.iris.core.pregenerator.PregenListener;
+import com.volmit.iris.core.pregenerator.PregeneratorMethod;
+import com.volmit.iris.util.scheduling.J;
+import org.bukkit.Chunk;
+import org.bukkit.World;
+
+public class MedievalPregenMethod implements PregeneratorMethod {
+ private final World world;
+
+ public MedievalPregenMethod(World world)
+ {
+ this.world = world;
+ }
+
+ private void unloadAndSaveAllChunks() {
+ J.s(() -> {
+ for(Chunk i : world.getLoadedChunks())
+ {
+ i.unload(true);
+ }
+ });
+ }
+
+ @Override
+ public void init() {
+ unloadAndSaveAllChunks();
+ }
+
+ @Override
+ public void close() {
+ unloadAndSaveAllChunks();
+ world.save();
+ }
+
+ @Override
+ public void save() {
+ unloadAndSaveAllChunks();
+ world.save();
+ }
+
+ @Override
+ public boolean supportsRegions(int x, int z) {
+ return false;
+ }
+
+ @Override
+ public void generateRegion(int x, int z, PregenListener listener) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getMethod(int x, int z) {
+ return "Medieval";
+ }
+
+ @Override
+ public void generateChunk(int x, int z) {
+ world.getChunkAt(x, z);
+ }
+}
diff --git a/src/main/java/com/volmit/iris/core/pregenerator/methods/PaperAsyncPregenMethod.java b/src/main/java/com/volmit/iris/core/pregenerator/methods/PaperAsyncPregenMethod.java
new file mode 100644
index 000000000..f38046a23
--- /dev/null
+++ b/src/main/java/com/volmit/iris/core/pregenerator/methods/PaperAsyncPregenMethod.java
@@ -0,0 +1,119 @@
+/*
+ * Iris is a World Generator for Minecraft Bukkit Servers
+ * Copyright (c) 2021 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 .
+ */
+
+package com.volmit.iris.core.pregenerator.methods;
+
+import com.volmit.iris.core.pregenerator.PregenListener;
+import com.volmit.iris.core.pregenerator.PregeneratorMethod;
+import com.volmit.iris.engine.parallel.MultiBurst;
+import com.volmit.iris.util.collection.KList;
+import com.volmit.iris.util.scheduling.J;
+import io.papermc.lib.PaperLib;
+import org.bukkit.Chunk;
+import org.bukkit.World;
+
+import java.util.concurrent.CompletableFuture;
+
+public class PaperAsyncPregenMethod implements PregeneratorMethod {
+ private final World world;
+ private final MultiBurst burst;
+ private final KList> future;
+
+ public PaperAsyncPregenMethod(World world, int threads)
+ {
+ if(!PaperLib.isPaper())
+ {
+ throw new UnsupportedOperationException("Cannot use PaperAsync on non paper!");
+ }
+
+ this.world = world;
+ burst = new MultiBurst("Iris PaperAsync Pregenerator", 6, threads);
+ future = new KList<>(1024);
+ }
+
+ private void unloadAndSaveAllChunks() {
+ J.s(() -> {
+ for(Chunk i : world.getLoadedChunks())
+ {
+ i.unload(true);
+ }
+ });
+ }
+
+ private void completeChunk(int x, int z) {
+ try {
+ PaperLib.getChunkAtAsync(world, x, z, true).get();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void waitForChunks()
+ {
+ for(CompletableFuture> i : future)
+ {
+ try {
+ i.get();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+
+ future.clear();
+ }
+
+ @Override
+ public void init() {
+ unloadAndSaveAllChunks();
+ }
+
+ @Override
+ public String getMethod(int x, int z) {
+ return "Async";
+ }
+
+ @Override
+ public void close() {
+ waitForChunks();
+ burst.shutdownAndAwait();
+ unloadAndSaveAllChunks();
+ world.save();
+ }
+
+ @Override
+ public void save() {
+ waitForChunks();
+ unloadAndSaveAllChunks();
+ world.save();
+ }
+
+ @Override
+ public boolean supportsRegions(int x, int z) {
+ return false;
+ }
+
+ @Override
+ public void generateRegion(int x, int z, PregenListener listener) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void generateChunk(int x, int z) {
+ future.add(burst.complete(() -> completeChunk(x, z)));
+ }
+}
diff --git a/src/main/java/com/volmit/iris/core/pregenerator/methods/PaperOrMedievalPregenMethod.java b/src/main/java/com/volmit/iris/core/pregenerator/methods/PaperOrMedievalPregenMethod.java
new file mode 100644
index 000000000..4608b68e6
--- /dev/null
+++ b/src/main/java/com/volmit/iris/core/pregenerator/methods/PaperOrMedievalPregenMethod.java
@@ -0,0 +1,68 @@
+/*
+ * Iris is a World Generator for Minecraft Bukkit Servers
+ * Copyright (c) 2021 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 .
+ */
+
+package com.volmit.iris.core.pregenerator.methods;
+
+import com.volmit.iris.core.pregenerator.PregenListener;
+import com.volmit.iris.core.pregenerator.PregeneratorMethod;
+import io.papermc.lib.PaperLib;
+import org.bukkit.World;
+
+public class PaperOrMedievalPregenMethod implements PregeneratorMethod {
+ private final PregeneratorMethod method;
+
+ public PaperOrMedievalPregenMethod(World world, int threads)
+ {
+ method = PaperLib.isPaper() ? new PaperAsyncPregenMethod(world, threads) : new MedievalPregenMethod(world);
+ }
+
+ @Override
+ public void init() {
+ method.init();
+ }
+
+ @Override
+ public void close() {
+ method.close();
+ }
+
+ @Override
+ public void save() {
+ method.save();
+ }
+
+ @Override
+ public String getMethod(int x, int z) {
+ return method.getMethod(x, z);
+ }
+
+ @Override
+ public boolean supportsRegions(int x, int z) {
+ return false;
+ }
+
+ @Override
+ public void generateRegion(int x, int z, PregenListener listener) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void generateChunk(int x, int z) {
+ method.generateChunk(x, z);
+ }
+}