mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-18 18:23:06 +00:00
commit
2c1d4cfc40
@ -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");
|
||||
|
351
src/main/java/com/volmit/iris/core/gui/PregeneratorJob.java
Normal file
351
src/main/java/com/volmit/iris/core/gui/PregeneratorJob.java
Normal file
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<Runnable> 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<Runnable> 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<Position2, Color> 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;
|
||||
}
|
||||
}
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<String> 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();
|
||||
}
|
||||
}
|
@ -16,7 +16,22 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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();
|
||||
}
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<Position2> 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<Position2> computeChunkOrder() {
|
||||
Position2 center = new Position2(15, 15);
|
||||
KList<Position2> 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;
|
||||
}
|
||||
}
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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) {
|
||||
|
||||
}
|
||||
}
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<CompletableFuture<?>> 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);
|
||||
}));
|
||||
}
|
||||
}
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<CompletableFuture<?>> 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)));
|
||||
}
|
||||
}
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user