diff --git a/src/main/java/com/volmit/iris/core/command/world/CommandIrisPregen.java b/src/main/java/com/volmit/iris/core/command/world/CommandIrisPregen.java
index de70f9ce3..74837c9cb 100644
--- a/src/main/java/com/volmit/iris/core/command/world/CommandIrisPregen.java
+++ b/src/main/java/com/volmit/iris/core/command/world/CommandIrisPregen.java
@@ -19,8 +19,13 @@
package com.volmit.iris.core.command.world;
import com.volmit.iris.Iris;
+import com.volmit.iris.core.gui.PregeneratorJob;
import com.volmit.iris.core.gui.components.Pregenerator;
+import com.volmit.iris.core.pregenerator.PregenTask;
+import com.volmit.iris.core.pregenerator.methods.HybridPregenMethod;
+import com.volmit.iris.core.pregenerator.methods.PaperOrMedievalPregenMethod;
import com.volmit.iris.util.collection.KList;
+import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.plugin.MortarCommand;
import com.volmit.iris.util.plugin.VolmitSender;
import org.bukkit.Bukkit;
@@ -69,17 +74,17 @@ public class CommandIrisPregen extends MortarCommand {
}
if (args[0].equalsIgnoreCase("stop") || args[0].equalsIgnoreCase("x")) {
- if (Pregenerator.shutdownInstance()) {
+ if (PregeneratorJob.shutdownInstance()) {
sender.sendMessage("Stopped Pregen.");
} else {
sender.sendMessage("No Active Pregens.");
}
return true;
} else if (args[0].equalsIgnoreCase("pause") || args[0].equalsIgnoreCase("resume")) {
- if (Pregenerator.getInstance() != null) {
- Pregenerator.pauseResume();
+ if (PregeneratorJob.getInstance() != null) {
+ PregeneratorJob.pauseResume();
- if (Pregenerator.isPaused()) {
+ if (PregeneratorJob.isPaused()) {
sender.sendMessage("Pregen Paused");
} else {
sender.sendMessage("Pregen Resumed");
@@ -105,7 +110,12 @@ public class CommandIrisPregen extends MortarCommand {
}
}
try {
- new Pregenerator(world, getVal(args[0]) * 2);
+ new PregeneratorJob(PregenTask
+ .builder()
+ .center(new Position2(0, 0))
+ .radius(((getVal(args[0])>>4)>>5) + 1)
+ .build(),
+ new HybridPregenMethod(world, Runtime.getRuntime().availableProcessors()));
} catch (NumberFormatException e) {
Iris.reportError(e);
sender.sendMessage("Invalid argument in command");
@@ -131,7 +141,12 @@ public class CommandIrisPregen extends MortarCommand {
}
World world = Bukkit.getWorld(args[1]);
try {
- new Pregenerator(world, getVal(args[0]) * 2);
+ new PregeneratorJob(PregenTask
+ .builder()
+ .center(new Position2(0, 0))
+ .radius(((getVal(args[0])>>4)>>5) + 1)
+ .build(),
+ new HybridPregenMethod(world, Runtime.getRuntime().availableProcessors()));
} catch (NumberFormatException e) {
Iris.reportError(e);
sender.sendMessage("Invalid argument in command");
diff --git a/src/main/java/com/volmit/iris/core/gui/PregeneratorJob.java b/src/main/java/com/volmit/iris/core/gui/PregeneratorJob.java
new file mode 100644
index 000000000..d4bf7c490
--- /dev/null
+++ b/src/main/java/com/volmit/iris/core/gui/PregeneratorJob.java
@@ -0,0 +1,351 @@
+/*
+ * 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.gui;
+
+import com.volmit.iris.Iris;
+import com.volmit.iris.core.IrisSettings;
+import com.volmit.iris.core.pregenerator.IrisPregenerator;
+import com.volmit.iris.core.pregenerator.PregenListener;
+import com.volmit.iris.core.pregenerator.PregenTask;
+import com.volmit.iris.core.pregenerator.PregeneratorMethod;
+import com.volmit.iris.util.collection.KList;
+import com.volmit.iris.util.format.Form;
+import com.volmit.iris.util.function.Consumer2;
+import com.volmit.iris.util.math.M;
+import com.volmit.iris.util.math.Position2;
+import com.volmit.iris.util.math.Spiraler;
+import com.volmit.iris.util.scheduling.J;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.image.BufferedImage;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class PregeneratorJob implements PregenListener {
+ public static PregeneratorJob instance;
+ private static final Color COLOR_GENERATING = parseColor("#346beb");
+ private static final Color COLOR_GENERATED = parseColor("#34eb93");
+ private JFrame frame;
+ private final PregenTask task;
+ private boolean saving;
+ private final IrisPregenerator pregenerator;
+ private PregenRenderer renderer;
+ private String[] info;
+ private Position2 min;
+ private Position2 max;
+
+ public PregeneratorJob(PregenTask task, PregeneratorMethod method)
+ {
+ instance = this;
+ saving = false;
+ info = new String[]{"Initializing..."};
+ this.task = task;
+ this.pregenerator = new IrisPregenerator(task, method, this);
+ J.a(this.pregenerator::start);
+ max = new Position2(0, 0);
+ min = new Position2(0, 0);
+ KList draw = new KList<>();
+ task.iterateRegions((xx,zz) -> {
+ min.setX(Math.min(xx << 5, min.getX()));
+ min.setZ(Math.min(zz << 5, min.getZ()));
+ max.setX(Math.max((xx << 5) + 31, max.getX()));
+ max.setZ(Math.max((zz << 5) + 31, max.getZ()));
+ });
+ open();
+ }
+
+ public static boolean shutdownInstance() {
+ if(instance == null)
+ {
+ return false;
+ }
+
+ J.a(() -> instance.pregenerator.close());
+ return true;
+ }
+
+ public static PregeneratorJob getInstance() {
+ return instance;
+ }
+
+ public static void pauseResume() {
+ if(instance == null)
+ {
+ return;
+ }
+
+ if(isPaused())
+ {
+ instance.pregenerator.resume();
+ }
+
+ else
+ {
+ instance.pregenerator.pause();
+ }
+ }
+
+ public static boolean isPaused() {
+ if(instance == null)
+ {
+ return true;
+ }
+
+ return instance.paused();
+ }
+
+ public void draw(int x, int z, Color color)
+ {
+ try
+ {
+ if(renderer != null && frame != null && frame.isVisible())
+ {
+ renderer.func.accept(new Position2(x, z), color);
+ }
+ }
+
+ catch(Throwable ignored)
+ {
+
+ }
+ }
+
+ public void stop()
+ {
+ J.a(() -> {
+ pregenerator.close();
+ close();
+ instance = null;
+ });
+ }
+
+ public void close()
+ {
+ J.a(() -> {
+ try
+ {
+ J.sleep(3000);
+ frame.setVisible(false);
+ }
+
+ catch(Throwable e)
+ {
+
+ }
+ });
+ }
+
+ public void open()
+ {
+ J.a(() -> {
+ try
+ {
+ frame = new JFrame("Pregen View");
+ renderer = new PregenRenderer();
+ frame.addKeyListener(renderer);
+ renderer.l = new ReentrantLock();
+ renderer.frame = frame;
+ renderer.job = this;
+ renderer.func = (c, b) ->
+ {
+ renderer.l.lock();
+ renderer.order.add(() -> renderer.draw(c, b, renderer.bg));
+ renderer.l.unlock();
+ };
+ frame.add(renderer);
+ frame.setSize(1000, 1000);
+ frame.setVisible(true);
+ }
+
+ catch(Throwable e)
+ {
+
+ }
+ });
+ }
+
+ @Override
+ public void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, int generated, int totalChunks, int chunksRemaining, long eta, long elapsed, String method) {
+ info = new String[] {
+ (paused() ? "PAUSED" : (saving ? "Saving... " : "Generating")) + " " + Form.f(generated) + " of " + Form.f(totalChunks) + " (" + Form.pc(percent, 0) + " Complete)",
+ "Speed: " + Form.f(chunksPerSecond, 0) + " Chunks/s, " + Form.f(regionsPerMinute, 1) + " Regions/m, " + Form.f(chunksPerMinute, 0) + " Chunks/m",
+ Form.duration(eta, 2) + " Remaining " + " (" + Form.duration(elapsed, 2) + " Elapsed)",
+ "Generation Method: " + method,
+ };
+ }
+
+ @Override
+ public void onChunkGenerating(int x, int z) {
+ draw(x, z, COLOR_GENERATING);
+ }
+
+ @Override
+ public void onChunkGenerated(int x, int z) {
+ draw(x, z, COLOR_GENERATED);
+ }
+
+ @Override
+ public void onRegionGenerated(int x, int z) {
+
+ }
+
+ @Override
+ public void onRegionGenerating(int x, int z) {
+
+ }
+
+ @Override
+ public void onRegionSkipped(int x, int z) {
+
+ }
+
+ @Override
+ public void onClose() {
+ close();
+ instance = null;
+ }
+
+ @Override
+ public void onSaving() {
+
+ }
+
+ private Position2 getMax() {
+ return max;
+ }
+
+ private Position2 getMin() {
+ return min;
+ }
+
+ private boolean paused() {
+ return pregenerator.paused();
+ }
+
+ private String[] getProgress() {
+ return info;
+ }
+
+ public static class PregenRenderer extends JPanel implements KeyListener {
+ private PregeneratorJob job;
+ private static final long serialVersionUID = 2094606939770332040L;
+ private final KList order = new KList<>();
+ private final int res = 512;
+ Graphics2D bg;
+ private ReentrantLock l;
+ private final BufferedImage image = new BufferedImage(res, res, BufferedImage.TYPE_INT_RGB);
+ private Consumer2 func;
+ private JFrame frame;
+
+ public PregenRenderer() {
+
+ }
+
+ public void paint(int x, int z, Color c) {
+ func.accept(new Position2(x, z), c);
+ }
+
+ @Override
+ public void paint(Graphics gx) {
+ Graphics2D g = (Graphics2D) gx;
+ bg = (Graphics2D) image.getGraphics();
+ l.lock();
+
+ while (order.isNotEmpty()) {
+ try {
+ order.pop().run();
+ } catch (Throwable e) {
+ Iris.reportError(e);
+
+ }
+ }
+
+ l.unlock();
+ g.drawImage(image, 0, 0, getParent().getWidth(), getParent().getHeight(), (img, infoflags, x, y, width, height) -> true);
+ g.setColor(Color.WHITE);
+ g.setFont(new Font("Hevetica", Font.BOLD, 28));
+ String[] prog = job.getProgress();
+ int h = g.getFontMetrics().getHeight() + 5;
+ int hh = 20;
+
+ if (job.paused()) {
+ g.drawString("PAUSED", 20, hh += h);
+
+ g.drawString("Press P to Resume", 20, hh += h);
+ } else {
+ for (String i : prog) {
+ g.drawString(i, 20, hh += h);
+ }
+
+ g.drawString("Press P to Pause", 20, hh += h);
+ }
+
+ J.sleep(IrisSettings.get().getGui().isMaximumPregenGuiFPS() ? 4 : 250);
+ repaint();
+ }
+
+ private void draw(Position2 p, Color c, Graphics2D bg) {
+ double pw = M.lerpInverse(job.getMin().getX(), job.getMax().getX(), p.getX());
+ double ph = M.lerpInverse(job.getMin().getZ(), job.getMax().getZ(), p.getZ());
+ double pwa = M.lerpInverse(job.getMin().getX(), job.getMax().getX(), p.getX() + 1);
+ double pha = M.lerpInverse(job.getMin().getZ(), job.getMax().getZ(), p.getZ() + 1);
+ int x = (int) M.lerp(0, res, pw);
+ int z = (int) M.lerp(0, res, ph);
+ int xa = (int) M.lerp(0, res, pwa);
+ int za = (int) M.lerp(0, res, pha);
+ bg.setColor(c);
+ bg.fillRect(x, z, xa - x, za - z);
+ }
+
+ @Override
+ public void keyTyped(KeyEvent e) {
+
+ }
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+
+ }
+
+ @Override
+ public void keyReleased(KeyEvent e) {
+ if (e.getKeyCode() == KeyEvent.VK_P) {
+ PregeneratorJob.pauseResume();
+ }
+ }
+
+ public void close() {
+ frame.setVisible(false);
+ }
+ }
+
+ private static Color parseColor(String c) {
+ String v = (c.startsWith("#") ? c : "#" + c).trim();
+ try {
+ return Color.decode(v);
+ } catch (Throwable e) {
+ Iris.reportError(e);
+ Iris.error("Error Parsing 'color', (" + c + ")");
+ }
+
+ return Color.RED;
+ }
+}
diff --git a/src/main/java/com/volmit/iris/core/pregenerator/IrisPregenerator.java b/src/main/java/com/volmit/iris/core/pregenerator/IrisPregenerator.java
new file mode 100644
index 000000000..16a2052b9
--- /dev/null
+++ b/src/main/java/com/volmit/iris/core/pregenerator/IrisPregenerator.java
@@ -0,0 +1,212 @@
+/*
+ * 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;
+
+import com.volmit.iris.util.math.M;
+import com.volmit.iris.util.math.RollingSequence;
+import com.volmit.iris.util.scheduling.ChronoLatch;
+import com.volmit.iris.util.scheduling.J;
+import com.volmit.iris.util.scheduling.Looper;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+
+public class IrisPregenerator {
+ private final PregenTask task;
+ private final PregeneratorMethod generator;
+ private final PregenListener listener;
+ private final Looper ticker;
+ private final AtomicBoolean paused;
+ private final AtomicBoolean shutdown;
+ private final RollingSequence chunksPerSecond;
+ private final RollingSequence chunksPerMinute;
+ private final RollingSequence regionsPerMinute;
+ private final AtomicInteger generated;
+ private final AtomicInteger generatedLast;
+ private final AtomicInteger generatedLastMinute;
+ private final AtomicInteger totalChunks;
+ private final AtomicLong startTime;
+ private final ChronoLatch minuteLatch;
+ private final AtomicReference currentGeneratorMethod;
+
+ public IrisPregenerator(PregenTask task, PregeneratorMethod generator, PregenListener listener)
+ {
+ this.listener = listenify(listener);
+ this.shutdown = new AtomicBoolean(false);
+ this.paused = new AtomicBoolean(false);
+ this.task = task;
+ this.generator = generator;
+ currentGeneratorMethod = new AtomicReference<>("Void");
+ minuteLatch = new ChronoLatch(60000, false);
+ chunksPerSecond = new RollingSequence(10);
+ chunksPerMinute = new RollingSequence(10);
+ regionsPerMinute = new RollingSequence(10);
+ generated = new AtomicInteger(0);
+ generatedLast = new AtomicInteger(0);
+ generatedLastMinute = new AtomicInteger(0);
+ totalChunks = new AtomicInteger(0);
+ task.iterateRegions((_a, _b) -> totalChunks.addAndGet(1024));
+ startTime = new AtomicLong(M.ms());
+ ticker = new Looper() {
+ @Override
+ protected long loop() {
+ long eta = computeETA();
+ int secondGenerated = generated.get() - generatedLast.get();
+ generatedLast.set(generated.get());
+ chunksPerSecond.put(secondGenerated);
+
+ if(minuteLatch.flip())
+ {
+ int minuteGenerated = generated.get() - generatedLastMinute.get();
+ generatedLastMinute.set(generated.get());
+ chunksPerMinute.put(minuteGenerated);
+ regionsPerMinute.put((double)minuteGenerated / 1024D);
+ }
+
+ listener.onTick(chunksPerSecond.getAverage(), chunksPerMinute.getAverage(),
+ regionsPerMinute.getAverage(),
+ (double)generated.get() / (double)totalChunks.get(),
+ generated.get(), totalChunks.get(),
+ totalChunks.get() - generated.get(),
+ eta, M.ms() - startTime.get(), currentGeneratorMethod.get());
+ return 1000;
+ }
+ };
+ }
+
+ private long computeETA() {
+ return (long) ((totalChunks.get() - generated.get()) *
+ ((double) (M.ms() - startTime.get()) / (double) generated.get()));
+ }
+
+ public void close()
+ {
+ shutdown.set(true);
+ }
+
+ public void start()
+ {
+ init();
+ ticker.start();
+ task.iterateRegions(this::visitRegion);
+ shutdown();
+ }
+
+ private void init() {
+ generator.init();
+ }
+
+ private void shutdown() {
+ listener.onSaving();
+ generator.close();
+ ticker.interrupt();
+ listener.onClose();
+ }
+
+ private void visitRegion(int x, int z) {
+ while(paused.get() && !shutdown.get())
+ {
+ J.sleep(50);
+ }
+
+ if(shutdown.get())
+ {
+ listener.onRegionSkipped(x, z);
+ return;
+ }
+
+ listener.onRegionGenerating(x, z);
+ currentGeneratorMethod.set(generator.getMethod(x, z));
+
+ if(generator.supportsRegions(x, z))
+ {
+ generator.generateRegion(x, z, listener);
+ }
+
+ else
+ {
+ PregenTask.iterateRegion(x, z, (xx, zz) -> generator.generateChunk(xx, zz, listener));
+ }
+
+ listener.onRegionGenerated(x, z);
+ listener.onSaving();
+ generator.save();
+ }
+
+ public void pause()
+ {
+ paused.set(true);
+ }
+
+ public void resume()
+ {
+ paused.set(false);
+ }
+
+ private PregenListener listenify(PregenListener listener) {
+ return new PregenListener() {
+ @Override
+ public void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, int generated, int totalChunks, int chunksRemaining, long eta, long elapsed, String method) {
+ listener.onTick( chunksPerSecond, chunksPerMinute, regionsPerMinute, percent, generated, totalChunks, chunksRemaining, eta, elapsed, method);
+ }
+
+ @Override
+ public void onChunkGenerating(int x, int z) {
+ listener.onChunkGenerating(x, z);
+ }
+
+ @Override
+ public void onChunkGenerated(int x, int z) {
+ listener.onChunkGenerated(x, z);
+ generated.addAndGet(1);
+ }
+
+ @Override
+ public void onRegionGenerated(int x, int z) {
+ listener.onRegionGenerated(x, z);
+ }
+
+ @Override
+ public void onRegionGenerating(int x, int z) {
+ listener.onRegionGenerating(x, z);
+ }
+
+ @Override
+ public void onRegionSkipped(int x, int z) {
+ listener.onRegionSkipped(x, z);
+ }
+
+ @Override
+ public void onClose() {
+ listener.onClose();
+ }
+
+ @Override
+ public void onSaving() {
+ listener.onSaving();
+ }
+ };
+ }
+
+ public boolean paused() {
+ return paused.get();
+ }
+}
diff --git a/src/main/java/com/volmit/iris/core/gui/PregeneratorGUI.java b/src/main/java/com/volmit/iris/core/pregenerator/PregenListener.java
similarity index 59%
rename from src/main/java/com/volmit/iris/core/gui/PregeneratorGUI.java
rename to src/main/java/com/volmit/iris/core/pregenerator/PregenListener.java
index 0aada2f15..5faec9d13 100644
--- a/src/main/java/com/volmit/iris/core/gui/PregeneratorGUI.java
+++ b/src/main/java/com/volmit/iris/core/pregenerator/PregenListener.java
@@ -16,7 +16,22 @@
* along with this program. If not, see .
*/
-package com.volmit.iris.core.gui;
+package com.volmit.iris.core.pregenerator;
-public class PregeneratorGUI {
+public interface PregenListener {
+ void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, int generated, int totalChunks, int chunksRemaining, long eta, long elapsed, String method);
+
+ void onChunkGenerating(int x, int z);
+
+ void onChunkGenerated(int x, int z);
+
+ void onRegionGenerated(int x, int z);
+
+ void onRegionGenerating(int x, int z);
+
+ void onRegionSkipped(int x, int z);
+
+ void onClose();
+
+ void onSaving();
}
diff --git a/src/main/java/com/volmit/iris/core/pregenerator/PregenTask.java b/src/main/java/com/volmit/iris/core/pregenerator/PregenTask.java
new file mode 100644
index 000000000..007b3a49b
--- /dev/null
+++ b/src/main/java/com/volmit/iris/core/pregenerator/PregenTask.java
@@ -0,0 +1,76 @@
+/*
+ * 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;
+
+import com.volmit.iris.util.collection.KList;
+import com.volmit.iris.util.math.Position2;
+import com.volmit.iris.util.math.Spiraled;
+import com.volmit.iris.util.math.Spiraler;
+import lombok.Builder;
+import lombok.Data;
+
+import java.util.Comparator;
+
+@Builder
+@Data
+public class PregenTask {
+ @Builder.Default
+ private Position2 center = new Position2(0,0);
+
+ @Builder.Default
+ private int radius = 1;
+
+ private static final KList order = computeChunkOrder();
+
+ public void iterateRegions(Spiraled s)
+ {
+ new Spiraler(radius * 2, radius * 2, s)
+ .setOffset(center.getX(), center.getZ()).drain();
+ }
+
+ public static void iterateRegion(int xr, int zr, Spiraled s)
+ {
+ for(Position2 i : order)
+ {
+ s.on(i.getX() + (xr << 5), i.getZ() + (zr << 5));
+ }
+ }
+
+ public void iterateAllChunks(Spiraled s)
+ {
+ new Spiraler(radius * 2, radius * 2, (x, z) -> iterateRegion(x, z, s))
+ .setOffset(center.getX(), center.getZ()).drain();
+ }
+
+ private static KList computeChunkOrder() {
+ Position2 center = new Position2(15, 15);
+ KList p = new KList<>();
+ new Spiraler(33, 33, (x, z) -> {
+ int xx = x + 15;
+ int zz = z + 15;
+ if (xx < 0 || xx > 31 || zz < 0 || zz > 31) {
+ return;
+ }
+
+ p.add(new Position2(xx, zz));
+ }).drain();
+ p.sort(Comparator.comparing((i) -> i.distance(center)));
+ return p;
+ }
+}
diff --git a/src/main/java/com/volmit/iris/core/pregenerator/PregeneratorMethod.java b/src/main/java/com/volmit/iris/core/pregenerator/PregeneratorMethod.java
new file mode 100644
index 000000000..a5c698ba8
--- /dev/null
+++ b/src/main/java/com/volmit/iris/core/pregenerator/PregeneratorMethod.java
@@ -0,0 +1,73 @@
+/*
+ * 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;
+
+/**
+ * Represents something that is capable of generating in chunks or regions, or both
+ */
+public interface PregeneratorMethod {
+ /**
+ * This is called before any generate methods are called. Setup your generator here
+ */
+ void init();
+
+ /**
+ * This is called after the pregenerator is done. Save your work and stop threads
+ */
+ void close();
+
+ /**
+ * This is called every X amount of chunks or regions. Save work,
+ * but no need to save all of it. At the end, close() will still be called.
+ */
+ void save();
+
+ /**
+ * Return true if regions can be generated
+ * @return true if they can be
+ * @param x the x region
+ * @param z the z region
+ */
+ boolean supportsRegions(int x, int z);
+
+ /**
+ * Return the name of the method being used
+ * @return the name
+ * @param x the x region
+ * @param z the z region
+ */
+ String getMethod(int x, int z);
+
+ /**
+ * Called to generate a region. Execute sync, if multicore internally, wait
+ * for the task to complete
+ * @param x the x
+ * @param z the z
+ * @param listener signal chunks generating & generated. Parallel capable.
+ */
+ void generateRegion(int x, int z, PregenListener listener);
+
+ /**
+ * Called to generate a chunk. You can go async so long as save will wait on the threads to finish
+ * @param x the x
+ * @param z the z
+ * @param listener
+ */
+ void generateChunk(int x, int z, PregenListener listener);
+}
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..0147a0441
--- /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, PregenListener listener) {
+
+ }
+}
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..bac3fe69c
--- /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, PregenListener listener) {
+ 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..a50538405
--- /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, PregenListener listener) {
+ inWorld.generateChunk(x, z, listener);
+ }
+}
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..49d2ed28a
--- /dev/null
+++ b/src/main/java/com/volmit/iris/core/pregenerator/methods/MedievalPregenMethod.java
@@ -0,0 +1,108 @@
+/*
+ * 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.collection.KList;
+import com.volmit.iris.util.scheduling.J;
+import org.bukkit.Chunk;
+import org.bukkit.World;
+
+import java.util.concurrent.CompletableFuture;
+
+public class MedievalPregenMethod implements PregeneratorMethod {
+ private final World world;
+ private final KList> futures;
+
+ public MedievalPregenMethod(World world)
+ {
+ this.world = world;
+ futures = new KList<>();
+ }
+
+ private void waitForChunks()
+ {
+ for(CompletableFuture> i : futures)
+ {
+ try {
+ i.get();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+
+ futures.clear();
+ }
+
+ private void unloadAndSaveAllChunks() {
+ waitForChunks();
+ J.s(() -> {
+ for(Chunk i : world.getLoadedChunks())
+ {
+ i.unload(true);
+ }
+ world.save();
+ });
+ }
+
+ @Override
+ public void init() {
+ unloadAndSaveAllChunks();
+ }
+
+ @Override
+ public void close() {
+ unloadAndSaveAllChunks();
+ }
+
+ @Override
+ public void save() {
+ unloadAndSaveAllChunks();
+ }
+
+ @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, PregenListener listener) {
+ if(futures.size() > 32)
+ {
+ waitForChunks();
+ }
+
+ listener.onChunkGenerating(x, z);
+ futures.add(J.sfut(() -> {
+ world.getChunkAt(x, z);
+ listener.onChunkGenerated(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..51eeb9ac4
--- /dev/null
+++ b/src/main/java/com/volmit/iris/core/pregenerator/methods/PaperAsyncPregenMethod.java
@@ -0,0 +1,125 @@
+/*
+ * 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);
+ }
+ world.save();
+ });
+ }
+
+ private void completeChunk(int x, int z, PregenListener listener) {
+ try {
+ PaperLib.getChunkAtAsync(world, x, z, true).get();
+ listener.onChunkGenerated(x, z);
+ } 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();
+ }
+
+ @Override
+ public void save() {
+ waitForChunks();
+ unloadAndSaveAllChunks();
+ }
+
+ @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, PregenListener listener) {
+ if(future.size() > 128)
+ {
+ waitForChunks();
+ }
+
+ listener.onChunkGenerating(x, z);
+ future.add(burst.complete(() -> completeChunk(x, z, listener)));
+ }
+}
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..6df75a9b7
--- /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, PregenListener listener) {
+ method.generateChunk(x, z, listener);
+ }
+}
diff --git a/src/main/java/com/volmit/iris/engine/data/mca/NBTWorld.java b/src/main/java/com/volmit/iris/engine/data/mca/NBTWorld.java
index 3801412a5..22ed2935d 100644
--- a/src/main/java/com/volmit/iris/engine/data/mca/NBTWorld.java
+++ b/src/main/java/com/volmit/iris/engine/data/mca/NBTWorld.java
@@ -313,15 +313,7 @@ public class NBTWorld {
if(mcaf == null)
{
- File f = getRegionFile(x, z);
- try {
- mcaf = f.exists() ? MCAUtil.read(f) : new MCAFile(x, z);
- } catch (IOException e) {
- Iris.error("Failed to properly read MCA File " + f.getPath() + " Using a blank one.");
- e.printStackTrace();
- mcaf = new MCAFile(x, z);
- }
-
+ mcaf = new MCAFile(x, z);
regionLock.lock();
loadedRegions.put(key, mcaf);
regionLock.unlock();
diff --git a/src/main/java/com/volmit/iris/engine/framework/EngineCompositeGenerator.java b/src/main/java/com/volmit/iris/engine/framework/EngineCompositeGenerator.java
index f16276dcb..145c10abc 100644
--- a/src/main/java/com/volmit/iris/engine/framework/EngineCompositeGenerator.java
+++ b/src/main/java/com/volmit/iris/engine/framework/EngineCompositeGenerator.java
@@ -23,6 +23,8 @@ import com.volmit.iris.core.IrisDataManager;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.nms.BiomeBaseInjector;
import com.volmit.iris.core.nms.INMS;
+import com.volmit.iris.core.pregenerator.PregenListener;
+import com.volmit.iris.core.pregenerator.PregenTask;
import com.volmit.iris.engine.IrisEngineCompound;
import com.volmit.iris.engine.IrisWorlds;
import com.volmit.iris.engine.cache.Cache;
@@ -460,17 +462,24 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
@Override
public void directWriteMCA(IrisWorld w, int x, int z, NBTWorld writer, MultiBurst burst) {
- BurstExecutor e = burst.burst(1024);
- int mcaox = x << 5;
- int mcaoz = z << 5;
+ directWriteMCA(w, x, z, writer, burst, null);
+ }
- for (int i = 0; i < 32; i++) {
- int ii = i;
- for (int j = 0; j < 32; j++) {
- int jj = j;
- e.queue(() -> directWriteChunk(w, ii + mcaox, jj + mcaoz, writer));
+ @Override
+ public void directWriteMCA(IrisWorld w, int x, int z, NBTWorld writer, MultiBurst burst, PregenListener l) {
+ BurstExecutor e = burst.burst(1024);
+
+ PregenTask.iterateRegion(x, z, (ii, jj) -> e.queue(() -> {
+ if(l != null)
+ {
+ l.onChunkGenerating(ii, jj);
}
- }
+ directWriteChunk(w, ii, jj, writer);
+ if(l != null)
+ {
+ l.onChunkGenerated(ii, jj);
+ }
+ }));
e.complete();
}
diff --git a/src/main/java/com/volmit/iris/engine/framework/IrisAccess.java b/src/main/java/com/volmit/iris/engine/framework/IrisAccess.java
index 8c6e692f7..1f8919b50 100644
--- a/src/main/java/com/volmit/iris/engine/framework/IrisAccess.java
+++ b/src/main/java/com/volmit/iris/engine/framework/IrisAccess.java
@@ -20,6 +20,7 @@ package com.volmit.iris.engine.framework;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisDataManager;
+import com.volmit.iris.core.pregenerator.PregenListener;
import com.volmit.iris.engine.IrisComplex;
import com.volmit.iris.engine.data.DataProvider;
import com.volmit.iris.engine.data.mca.NBTWorld;
@@ -47,6 +48,8 @@ public interface IrisAccess extends Hotloadable, DataProvider {
void directWriteMCA(IrisWorld w, int x, int z, NBTWorld writer, MultiBurst burst);
+ void directWriteMCA(IrisWorld w, int x, int z, NBTWorld writer, MultiBurst burst, PregenListener listener);
+
void directWriteChunk(IrisWorld w, int x, int z, NBTWorld writer);
int getGenerated();
diff --git a/src/main/java/com/volmit/iris/engine/headless/HeadlessGenerator.java b/src/main/java/com/volmit/iris/engine/headless/HeadlessGenerator.java
index 68a2dcbc9..95b4e7251 100644
--- a/src/main/java/com/volmit/iris/engine/headless/HeadlessGenerator.java
+++ b/src/main/java/com/volmit/iris/engine/headless/HeadlessGenerator.java
@@ -18,6 +18,7 @@
package com.volmit.iris.engine.headless;
+import com.volmit.iris.core.pregenerator.PregenListener;
import com.volmit.iris.engine.data.mca.NBTWorld;
import com.volmit.iris.engine.framework.EngineCompositeGenerator;
import com.volmit.iris.engine.parallel.MultiBurst;
@@ -51,6 +52,11 @@ public class HeadlessGenerator {
generator.directWriteMCA(world.getWorld(), x, z, writer, burst);
}
+ public void generateRegion(int x, int z, PregenListener listener)
+ {
+ generator.directWriteMCA(world.getWorld(), x, z, writer, burst, listener);
+ }
+
public File generateRegionToFile(int x, int z)
{
generateRegionToFile(x, z);
diff --git a/src/main/java/com/volmit/iris/engine/headless/HeadlessWorld.java b/src/main/java/com/volmit/iris/engine/headless/HeadlessWorld.java
index c0c09565a..4397274f9 100644
--- a/src/main/java/com/volmit/iris/engine/headless/HeadlessWorld.java
+++ b/src/main/java/com/volmit/iris/engine/headless/HeadlessWorld.java
@@ -20,7 +20,9 @@ package com.volmit.iris.engine.headless;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisDataManager;
+import com.volmit.iris.engine.IrisWorlds;
import com.volmit.iris.engine.framework.EngineCompositeGenerator;
+import com.volmit.iris.engine.framework.IrisAccess;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.engine.object.common.IrisWorld;
import com.volmit.iris.util.plugin.VolmitSender;
@@ -73,6 +75,10 @@ public class HeadlessWorld {
.createWorld();
}
+ public static HeadlessWorld from(World world) {
+ return new HeadlessWorld(world.getName(), IrisWorlds.access(world).getTarget().getDimension(), world.getSeed());
+ }
+
public static HeadlessWorld from(String name, String dimension, long seed)
{
return new HeadlessWorld(name, IrisDataManager.loadAnyDimension(dimension), seed);
diff --git a/src/main/java/com/volmit/iris/util/math/Position2.java b/src/main/java/com/volmit/iris/util/math/Position2.java
index 94be84e6e..93b17a101 100644
--- a/src/main/java/com/volmit/iris/util/math/Position2.java
+++ b/src/main/java/com/volmit/iris/util/math/Position2.java
@@ -43,6 +43,11 @@ public class Position2 {
this.z = z;
}
+ public String toString()
+ {
+ return "[" + x + "," + z + "]";
+ }
+
@Override
public int hashCode() {
final int prime = 31;
@@ -52,6 +57,11 @@ public class Position2 {
return result;
}
+ public Position2 regionToChunk()
+ {
+ return new Position2(x << 5, z << 5);
+ }
+
@Override
public boolean equals(Object obj) {
if (this == obj) {
@@ -66,4 +76,8 @@ public class Position2 {
public double distance(Position2 center) {
return Math.pow(center.getX() - x, 2) + Math.pow(center.getZ() - z, 2);
}
+
+ public Position2 add(int x, int z) {
+ return new Position2(this.x + x, this.z + z);
+ }
}
diff --git a/src/main/java/com/volmit/iris/util/scheduling/J.java b/src/main/java/com/volmit/iris/util/scheduling/J.java
index a9706c505..583492d51 100644
--- a/src/main/java/com/volmit/iris/util/scheduling/J.java
+++ b/src/main/java/com/volmit/iris/util/scheduling/J.java
@@ -208,6 +208,15 @@ public class J {
Bukkit.getScheduler().scheduleSyncDelayedTask(Iris.instance, r);
}
+ public static CompletableFuture sfut(Runnable r) {
+ CompletableFuture f = new CompletableFuture();
+ Bukkit.getScheduler().scheduleSyncDelayedTask(Iris.instance, () -> {
+ r.run();
+ f.complete(null);
+ });
+ return f;
+ }
+
/**
* Queue a sync task
*