diff --git a/core/src/main/java/com/volmit/iris/core/IrisSettings.java b/core/src/main/java/com/volmit/iris/core/IrisSettings.java
index 681cbeca2..30a7b089d 100644
--- a/core/src/main/java/com/volmit/iris/core/IrisSettings.java
+++ b/core/src/main/java/com/volmit/iris/core/IrisSettings.java
@@ -184,6 +184,7 @@ public class IrisSettings {
public static class IrisSettingsStudio {
public boolean studio = true;
public boolean openVSCode = true;
+ public boolean displayTrueHeight = false;
public boolean disableTimeAndWeather = true;
public boolean autoStartDefaultStudio = false;
}
diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandDeepSearch.java b/core/src/main/java/com/volmit/iris/core/commands/CommandDeepSearch.java
new file mode 100644
index 000000000..96c91305f
--- /dev/null
+++ b/core/src/main/java/com/volmit/iris/core/commands/CommandDeepSearch.java
@@ -0,0 +1,134 @@
+/*
+ * Iris is a World Generator for Minecraft Bukkit Servers
+ * Copyright (c) 2022 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.commands;
+
+import com.volmit.iris.Iris;
+import com.volmit.iris.core.pregenerator.DeepSearchPregenerator;
+import com.volmit.iris.core.pregenerator.PregenTask;
+import com.volmit.iris.core.pregenerator.TurboPregenerator;
+import com.volmit.iris.core.tools.IrisToolbelt;
+import com.volmit.iris.util.data.Dimension;
+import com.volmit.iris.util.decree.DecreeExecutor;
+import com.volmit.iris.util.decree.annotations.Decree;
+import com.volmit.iris.util.decree.annotations.Param;
+import com.volmit.iris.util.format.C;
+import com.volmit.iris.util.math.Position2;
+import org.bukkit.Bukkit;
+import org.bukkit.World;
+import org.bukkit.util.Vector;
+
+import java.io.File;
+import java.io.IOException;
+
+@Decree(name = "DeepSearch", aliases = "search", description = "Pregenerate your Iris worlds!")
+public class CommandDeepSearch implements DecreeExecutor {
+ public String worldName;
+ @Decree(description = "DeepSearch a world")
+ public void start(
+ @Param(description = "The radius of the pregen in blocks", aliases = "size")
+ int radius,
+ @Param(description = "The world to pregen", contextual = true)
+ World world,
+ @Param(aliases = "middle", description = "The center location of the pregen. Use \"me\" for your current location", defaultValue = "0,0")
+ Vector center
+ ) {
+
+ worldName = world.getName();
+ File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
+ File TurboFile = new File(worldDirectory, "DeepSearch.json");
+ if (TurboFile.exists()) {
+ if (DeepSearchPregenerator.getInstance() != null) {
+ sender().sendMessage(C.BLUE + "DeepSearch is already in progress");
+ Iris.info(C.YELLOW + "DeepSearch is already in progress");
+ return;
+ } else {
+ try {
+ TurboFile.delete();
+ } catch (Exception e){
+ Iris.error("Failed to delete the old instance file of DeepSearch!");
+ return;
+ }
+ }
+ }
+
+ try {
+ if (sender().isPlayer() && access() == null) {
+ sender().sendMessage(C.RED + "The engine access for this world is null!");
+ sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
+ }
+
+ DeepSearchPregenerator.DeepSearchJob DeepSearchJob = DeepSearchPregenerator.DeepSearchJob.builder()
+ .world(worldName)
+ .radiusBlocks(radius)
+ .position(0)
+ .build();
+
+ File SearchGenFile = new File(worldDirectory, "DeepSearch.json");
+ DeepSearchPregenerator pregenerator = new DeepSearchPregenerator(DeepSearchJob, SearchGenFile);
+ pregenerator.start();
+
+ String msg = C.GREEN + "DeepSearch started in " + C.GOLD + worldName + C.GREEN + " of " + C.GOLD + (radius * 2) + C.GREEN + " by " + C.GOLD + (radius * 2) + C.GREEN + " blocks from " + C.GOLD + center.getX() + "," + center.getZ();
+ sender().sendMessage(msg);
+ Iris.info(msg);
+ } catch (Throwable e) {
+ sender().sendMessage(C.RED + "Epic fail. See console.");
+ Iris.reportError(e);
+ e.printStackTrace();
+ }
+ }
+
+ @Decree(description = "Stop the active DeepSearch task", aliases = "x")
+ public void stop(@Param(aliases = "world", description = "The world to pause") World world) throws IOException {
+ DeepSearchPregenerator DeepSearchInstance = DeepSearchPregenerator.getInstance();
+ File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
+ File turboFile = new File(worldDirectory, "DeepSearch.json");
+
+ if (DeepSearchInstance != null) {
+ DeepSearchInstance.shutdownInstance(world);
+ sender().sendMessage(C.LIGHT_PURPLE + "Closed Turbogen instance for " + world.getName());
+ } else if (turboFile.exists() && turboFile.delete()) {
+ sender().sendMessage(C.LIGHT_PURPLE + "Closed Turbogen instance for " + world.getName());
+ } else if (turboFile.exists()) {
+ Iris.error("Failed to delete the old instance file of Turbo Pregen!");
+ } else {
+ sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop");
+ }
+ }
+
+ @Decree(description = "Pause / continue the active pregeneration task", aliases = {"t", "resume", "unpause"})
+ public void pause(
+ @Param(aliases = "world", description = "The world to pause")
+ World world
+ ) {
+ if (TurboPregenerator.getInstance() != null) {
+ TurboPregenerator.setPausedTurbo(world);
+ sender().sendMessage(C.GREEN + "Paused/unpaused Turbo Pregen, now: " + (TurboPregenerator.isPausedTurbo(world) ? "Paused" : "Running") + ".");
+ } else {
+ File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
+ File TurboFile = new File(worldDirectory, "DeepSearch.json");
+ if (TurboFile.exists()){
+ TurboPregenerator.loadTurboGenerator(world.getName());
+ sender().sendMessage(C.YELLOW + "Started DeepSearch back up!");
+ } else {
+ sender().sendMessage(C.YELLOW + "No active DeepSearch tasks to pause/unpause.");
+ }
+
+ }
+ }
+}
diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandIris.java b/core/src/main/java/com/volmit/iris/core/commands/CommandIris.java
index 3601b3f11..2470d0efa 100644
--- a/core/src/main/java/com/volmit/iris/core/commands/CommandIris.java
+++ b/core/src/main/java/com/volmit/iris/core/commands/CommandIris.java
@@ -72,6 +72,7 @@ public class CommandIris implements DecreeExecutor {
private CommandEdit edit;
private CommandFind find;
private CommandDeveloper developer;
+ private CommandTurboPregen turboPregen;
public static @Getter String BenchDimension;
public static boolean worldCreation = false;
diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandStudio.java b/core/src/main/java/com/volmit/iris/core/commands/CommandStudio.java
index 41a271c57..621915632 100644
--- a/core/src/main/java/com/volmit/iris/core/commands/CommandStudio.java
+++ b/core/src/main/java/com/volmit/iris/core/commands/CommandStudio.java
@@ -47,6 +47,7 @@ import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.json.JSONArray;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.math.M;
+import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.math.Spiraler;
import com.volmit.iris.util.noise.CNG;
@@ -76,12 +77,14 @@ import java.util.Date;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
@Decree(name = "studio", aliases = {"std", "s"}, description = "Studio Commands", studio = true)
public class CommandStudio implements DecreeExecutor {
private CommandFind find;
private CommandEdit edit;
+ private CommandDeepSearch deepSearch;
public static String hrf(Duration duration) {
return duration.toString().substring(2).replaceAll("(\\d[HMS])(?!$)", "$1 ").toLowerCase();
diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandTurboPregen.java b/core/src/main/java/com/volmit/iris/core/commands/CommandTurboPregen.java
new file mode 100644
index 000000000..2e85de859
--- /dev/null
+++ b/core/src/main/java/com/volmit/iris/core/commands/CommandTurboPregen.java
@@ -0,0 +1,131 @@
+/*
+ * Iris is a World Generator for Minecraft Bukkit Servers
+ * Copyright (c) 2022 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.commands;
+
+import com.volmit.iris.Iris;
+import com.volmit.iris.core.pregenerator.LazyPregenerator;
+import com.volmit.iris.core.pregenerator.TurboPregenerator;
+import com.volmit.iris.core.pregenerator.TurboPregenerator;
+import com.volmit.iris.util.decree.DecreeExecutor;
+import com.volmit.iris.util.decree.annotations.Decree;
+import com.volmit.iris.util.decree.annotations.Param;
+import com.volmit.iris.util.format.C;
+import org.bukkit.Bukkit;
+import org.bukkit.World;
+import org.bukkit.util.Vector;
+
+import java.io.File;
+import java.io.IOException;
+
+@Decree(name = "turbopregen", aliases = "turbo", description = "Pregenerate your Iris worlds!")
+public class CommandTurboPregen implements DecreeExecutor {
+ public String worldName;
+ @Decree(description = "Pregenerate a world")
+ public void start(
+ @Param(description = "The radius of the pregen in blocks", aliases = "size")
+ int radius,
+ @Param(description = "The world to pregen", contextual = true)
+ World world,
+ @Param(aliases = "middle", description = "The center location of the pregen. Use \"me\" for your current location", defaultValue = "0,0")
+ Vector center
+ ) {
+
+ worldName = world.getName();
+ File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
+ File TurboFile = new File(worldDirectory, "Turbogen.json");
+ if (TurboFile.exists()) {
+ if (TurboPregenerator.getInstance() != null) {
+ sender().sendMessage(C.BLUE + "Turbo pregen is already in progress");
+ Iris.info(C.YELLOW + "Turbo pregen is already in progress");
+ return;
+ } else {
+ try {
+ TurboFile.delete();
+ } catch (Exception e){
+ Iris.error("Failed to delete the old instance file of Turbo Pregen!");
+ return;
+ }
+ }
+ }
+
+ try {
+ if (sender().isPlayer() && access() == null) {
+ sender().sendMessage(C.RED + "The engine access for this world is null!");
+ sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
+ }
+
+ TurboPregenerator.TurboPregenJob pregenJob = TurboPregenerator.TurboPregenJob.builder()
+ .world(worldName)
+ .radiusBlocks(radius)
+ .position(0)
+ .build();
+
+ File TurboGenFile = new File(worldDirectory, "turbogen.json");
+ TurboPregenerator pregenerator = new TurboPregenerator(pregenJob, TurboGenFile);
+ pregenerator.start();
+
+ String msg = C.GREEN + "TurboPregen started in " + C.GOLD + worldName + C.GREEN + " of " + C.GOLD + (radius * 2) + C.GREEN + " by " + C.GOLD + (radius * 2) + C.GREEN + " blocks from " + C.GOLD + center.getX() + "," + center.getZ();
+ sender().sendMessage(msg);
+ Iris.info(msg);
+ } catch (Throwable e) {
+ sender().sendMessage(C.RED + "Epic fail. See console.");
+ Iris.reportError(e);
+ e.printStackTrace();
+ }
+ }
+
+ @Decree(description = "Stop the active pregeneration task", aliases = "x")
+ public void stop(@Param(aliases = "world", description = "The world to pause") World world) throws IOException {
+ TurboPregenerator turboPregenInstance = TurboPregenerator.getInstance();
+ File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
+ File turboFile = new File(worldDirectory, "turbogen.json");
+
+ if (turboPregenInstance != null) {
+ turboPregenInstance.shutdownInstance(world);
+ sender().sendMessage(C.LIGHT_PURPLE + "Closed Turbogen instance for " + world.getName());
+ } else if (turboFile.exists() && turboFile.delete()) {
+ sender().sendMessage(C.LIGHT_PURPLE + "Closed Turbogen instance for " + world.getName());
+ } else if (turboFile.exists()) {
+ Iris.error("Failed to delete the old instance file of Turbo Pregen!");
+ } else {
+ sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop");
+ }
+ }
+
+ @Decree(description = "Pause / continue the active pregeneration task", aliases = {"t", "resume", "unpause"})
+ public void pause(
+ @Param(aliases = "world", description = "The world to pause")
+ World world
+ ) {
+ if (TurboPregenerator.getInstance() != null) {
+ TurboPregenerator.setPausedTurbo(world);
+ sender().sendMessage(C.GREEN + "Paused/unpaused Turbo Pregen, now: " + (TurboPregenerator.isPausedTurbo(world) ? "Paused" : "Running") + ".");
+ } else {
+ File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
+ File TurboFile = new File(worldDirectory, "turbogen.json");
+ if (TurboFile.exists()){
+ TurboPregenerator.loadTurboGenerator(world.getName());
+ sender().sendMessage(C.YELLOW + "Started Turbo Pregen back up!");
+ } else {
+ sender().sendMessage(C.YELLOW + "No active Turbo Pregen tasks to pause/unpause.");
+ }
+
+ }
+ }
+}
diff --git a/core/src/main/java/com/volmit/iris/core/pregenerator/DeepSearchPregenerator.java b/core/src/main/java/com/volmit/iris/core/pregenerator/DeepSearchPregenerator.java
new file mode 100644
index 000000000..308ff3b41
--- /dev/null
+++ b/core/src/main/java/com/volmit/iris/core/pregenerator/DeepSearchPregenerator.java
@@ -0,0 +1,297 @@
+package com.volmit.iris.core.pregenerator;
+
+import com.google.gson.Gson;
+import com.volmit.iris.Iris;
+import com.volmit.iris.core.tools.IrisToolbelt;
+import com.volmit.iris.engine.framework.Engine;
+import com.volmit.iris.util.format.C;
+import com.volmit.iris.util.format.Form;
+import com.volmit.iris.util.io.IO;
+import com.volmit.iris.util.mantle.MantleFlag;
+import com.volmit.iris.util.math.M;
+import com.volmit.iris.util.math.Position2;
+import com.volmit.iris.util.math.RollingSequence;
+import com.volmit.iris.util.math.Spiraler;
+import com.volmit.iris.util.scheduling.ChronoLatch;
+import com.volmit.iris.util.scheduling.J;
+import com.volmit.iris.util.scheduling.PrecisionStopwatch;
+import io.papermc.lib.PaperLib;
+import lombok.Builder;
+import lombok.Data;
+import lombok.Getter;
+import org.bukkit.Bukkit;
+import org.bukkit.World;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.world.WorldUnloadEvent;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class DeepSearchPregenerator extends Thread implements Listener {
+ @Getter
+ private static DeepSearchPregenerator instance;
+ private final DeepSearchJob job;
+ private final File destination;
+ private final int maxPosition;
+ private World world;
+ private final ChronoLatch latch;
+ private static AtomicInteger foundChunks;
+ private final AtomicInteger foundLast;
+ private final AtomicInteger foundTotalChunks;
+ private final AtomicLong startTime;
+ private final RollingSequence chunksPerSecond;
+ private final RollingSequence chunksPerMinute;
+ private final AtomicInteger chunkCachePos;
+ private final AtomicInteger chunkCacheSize;
+ private final AtomicInteger foundCacheLast;
+ private final AtomicInteger foundCache;
+ private LinkedHashMap chunkCache;
+ private final ReentrantLock cacheLock = new ReentrantLock();
+
+ private static final Map jobs = new HashMap<>();
+
+ public DeepSearchPregenerator(DeepSearchJob job, File destination) {
+ this.job = job;
+ this.chunkCacheSize = new AtomicInteger(); // todo
+ this.chunkCachePos = new AtomicInteger(1000);
+ this.foundCacheLast = new AtomicInteger();
+ this.foundCache = new AtomicInteger();
+ this.destination = destination;
+ this.chunkCache = new LinkedHashMap();
+ this.maxPosition = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
+ }).count();
+ this.world = Bukkit.getWorld(job.getWorld());
+ this.latch = new ChronoLatch(3000);
+ this.startTime = new AtomicLong(M.ms());
+ this.chunksPerSecond = new RollingSequence(10);
+ this.chunksPerMinute = new RollingSequence(10);
+ foundChunks = new AtomicInteger(0);
+ this.foundLast = new AtomicInteger(0);
+ this.foundTotalChunks = new AtomicInteger((int) Math.ceil(Math.pow((2.0 * job.getRadiusBlocks()) / 16, 2)));
+ jobs.put(job.getWorld(), job);
+ DeepSearchPregenerator.instance = this;
+ }
+
+ @EventHandler
+ public void on(WorldUnloadEvent e) {
+ if (e.getWorld().equals(world)) {
+ interrupt();
+ }
+ }
+
+ public void run() {
+ while (!interrupted()) {
+ tick();
+ }
+ try {
+ saveNow();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void tick() {
+ DeepSearchJob job = jobs.get(world.getName());
+ // chunkCache(); //todo finish this
+ if (latch.flip() && !job.paused) {
+ if (cacheLock.isLocked()) {
+
+ Iris.info("DeepFinder: Caching: " + chunkCachePos.get() + " Of " + chunkCacheSize.get());
+ }
+ long eta = computeETA();
+ save();
+ int secondGenerated = foundChunks.get() - foundLast.get();
+ foundLast.set(foundChunks.get());
+ secondGenerated = secondGenerated / 3;
+ chunksPerSecond.put(secondGenerated);
+ chunksPerMinute.put(secondGenerated * 60);
+ Iris.info("deepFinder: " + C.IRIS + world.getName() + C.RESET + " RTT: " + Form.f(foundChunks.get()) + " of " + Form.f(foundTotalChunks.get()) + " " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration((double) eta, 2));
+
+ }
+
+ if (foundChunks.get() >= foundTotalChunks.get()) {
+ Iris.info("Completed DeepSearch!");
+ interrupt();
+ } else {
+ int pos = job.getPosition() + 1;
+ job.setPosition(pos);
+ if (!job.paused) {
+ tickSearch(getChunk(pos));
+ }
+ }
+ }
+
+ private long computeETA() {
+ return (long) ((foundTotalChunks.get() - foundChunks.get()) / chunksPerSecond.getAverage()) * 1000;
+ // todo broken
+ }
+
+ private void chunkCache() {
+ if (chunkCache.isEmpty()) {
+ cacheLock.lock();
+ PrecisionStopwatch p = PrecisionStopwatch.start();
+ executorService.submit(() -> {
+ for (; chunkCacheSize.get() > chunkCachePos.get(); chunkCacheSize.getAndAdd(-1)) {
+ chunkCache.put(chunkCachePos.get(), getChunk(chunkCachePos.get()));
+ chunkCachePos.getAndAdd(1);
+ }
+ Iris.info("Total Time: " + p.getMinutes());
+ });
+ }
+ if (cacheLock.isLocked()) {
+ cacheLock.unlock();
+ }
+ }
+
+ private final ExecutorService executorService = Executors.newSingleThreadExecutor();
+
+ private void tickSearch(Position2 chunk) {
+ executorService.submit(() -> {
+ CountDownLatch latch = new CountDownLatch(1);
+ try {
+ findInChunk(world, chunk.getX(), chunk.getZ());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ Iris.verbose("Generated Async " + chunk);
+ latch.countDown();
+
+ try {
+ latch.await();
+ } catch (InterruptedException ignored) {}
+ foundChunks.addAndGet(1);
+ });
+ }
+
+ private void findInChunk(World world, int x, int z) throws IOException {
+ int xx = x * 16;
+ int zz = z * 16;
+ Engine engine = IrisToolbelt.access(world).getEngine();
+ for (int i = 0; i < 16; i++) {
+ for (int j = 0; j < 16; j++) {
+ int height = engine.getHeight(xx + i, zz + j);
+ if (height > 300) {
+ File found = new File("plugins" + "iris" + "found.txt");
+ FileWriter writer = new FileWriter(found);
+ if (!found.exists()) {
+ found.createNewFile();
+ }
+ Iris.info("Found at! " + x + ", " + z);
+ writer.write("Found at: X: " + xx + " Z: " + zz + ", ");
+ }
+ }
+ }
+ }
+
+ public Position2 getChunk(int position) {
+ int p = -1;
+ AtomicInteger xx = new AtomicInteger();
+ AtomicInteger zz = new AtomicInteger();
+ Spiraler s = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
+ xx.set(x);
+ zz.set(z);
+ });
+
+ while (s.hasNext() && p++ < position) {
+ s.next();
+ }
+
+ return new Position2(xx.get(), zz.get());
+ }
+
+ public void save() {
+ J.a(() -> {
+ try {
+ saveNow();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ });
+ }
+
+ public static void setPausedDeep(World world) {
+ DeepSearchJob job = jobs.get(world.getName());
+ if (isPausedDeep(world)){
+ job.paused = false;
+ } else {
+ job.paused = true;
+ }
+
+ if ( job.paused) {
+ Iris.info(C.BLUE + "DeepSearch: " + C.IRIS + world.getName() + C.BLUE + " Paused");
+ } else {
+ Iris.info(C.BLUE + "DeepSearch: " + C.IRIS + world.getName() + C.BLUE + " Resumed");
+ }
+ }
+
+ public static boolean isPausedDeep(World world) {
+ DeepSearchJob job = jobs.get(world.getName());
+ return job != null && job.isPaused();
+ }
+
+ public void shutdownInstance(World world) throws IOException {
+ Iris.info("DeepSearch: " + C.IRIS + world.getName() + C.BLUE + " Shutting down..");
+ DeepSearchJob job = jobs.get(world.getName());
+ File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
+ File deepFile = new File(worldDirectory, "DeepSearch.json");
+
+ if (job == null) {
+ Iris.error("No DeepSearch job found for world: " + world.getName());
+ return;
+ }
+
+ try {
+ if (!job.isPaused()) {
+ job.setPaused(true);
+ }
+ save();
+ jobs.remove(world.getName());
+ new BukkitRunnable() {
+ @Override
+ public void run() {
+ while (deepFile.exists()){
+ deepFile.delete();
+ J.sleep(1000);
+ }
+ Iris.info("DeepSearch: " + C.IRIS + world.getName() + C.BLUE + " File deleted and instance closed.");
+ }
+ }.runTaskLater(Iris.instance, 20L);
+ } catch (Exception e) {
+ Iris.error("Failed to shutdown DeepSearch for " + world.getName());
+ e.printStackTrace();
+ } finally {
+ saveNow();
+ interrupt();
+ }
+ }
+
+
+ public void saveNow() throws IOException {
+ IO.writeAll(this.destination, new Gson().toJson(job));
+ }
+
+ @Data
+ @Builder
+ public static class DeepSearchJob {
+ private String world;
+ @Builder.Default
+ private int radiusBlocks = 5000;
+ @Builder.Default
+ private int position = 0;
+ @Builder.Default
+ boolean paused = false;
+ }
+}
+
diff --git a/core/src/main/java/com/volmit/iris/core/pregenerator/LazyPregenerator.java b/core/src/main/java/com/volmit/iris/core/pregenerator/LazyPregenerator.java
index d3ee26b54..20e3ace96 100644
--- a/core/src/main/java/com/volmit/iris/core/pregenerator/LazyPregenerator.java
+++ b/core/src/main/java/com/volmit/iris/core/pregenerator/LazyPregenerator.java
@@ -49,7 +49,6 @@ public class LazyPregenerator extends Thread implements Listener {
private final RollingSequence chunksPerSecond;
private final RollingSequence chunksPerMinute;
- // A map to keep track of jobs for each world
private static final Map jobs = new HashMap<>();
public LazyPregenerator(LazyPregenJob job, File destination) {
@@ -155,10 +154,7 @@ public class LazyPregenerator extends Thread implements Listener {
if (PaperLib.isPaper()) {
PaperLib.getChunkAtAsync(world, chunk.getX(), chunk.getZ(), true)
.thenAccept((i) -> {
- LazyPregenJob j = jobs.get(world.getName());
- if (!j.paused) {
- Iris.verbose("Generated Async " + chunk);
- }
+ Iris.verbose("Generated Async " + chunk);
latch.countDown();
});
} else {
@@ -207,7 +203,6 @@ public class LazyPregenerator extends Thread implements Listener {
}
public static void setPausedLazy(World world) {
- // todo: doesnt actually pause
LazyPregenJob job = jobs.get(world.getName());
if (isPausedLazy(world)){
job.paused = false;
diff --git a/core/src/main/java/com/volmit/iris/core/pregenerator/TurboPregenerator.java b/core/src/main/java/com/volmit/iris/core/pregenerator/TurboPregenerator.java
new file mode 100644
index 000000000..92b76293a
--- /dev/null
+++ b/core/src/main/java/com/volmit/iris/core/pregenerator/TurboPregenerator.java
@@ -0,0 +1,276 @@
+package com.volmit.iris.core.pregenerator;
+
+import com.google.gson.Gson;
+import com.volmit.iris.Iris;
+import com.volmit.iris.core.IrisSettings;
+import com.volmit.iris.util.collection.KList;
+import com.volmit.iris.util.format.C;
+import com.volmit.iris.util.format.Form;
+import com.volmit.iris.util.io.IO;
+import com.volmit.iris.util.math.M;
+import com.volmit.iris.util.math.Position2;
+import com.volmit.iris.util.math.RollingSequence;
+import com.volmit.iris.util.math.Spiraler;
+import com.volmit.iris.util.scheduling.ChronoLatch;
+import com.volmit.iris.util.scheduling.J;
+import io.papermc.lib.PaperLib;
+import lombok.Builder;
+import lombok.Data;
+import lombok.Getter;
+import org.bukkit.Bukkit;
+import org.bukkit.World;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.world.WorldUnloadEvent;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class TurboPregenerator extends Thread implements Listener {
+ @Getter
+ private static TurboPregenerator instance;
+ private final TurboPregenJob job;
+ private final File destination;
+ private final int maxPosition;
+ private World world;
+ private final ChronoLatch latch;
+ private static AtomicInteger turboGeneratedChunks;
+ private final AtomicInteger generatedLast;
+ private final AtomicInteger turboTotalChunks;
+ private final AtomicLong startTime;
+ private final RollingSequence chunksPerSecond;
+ private final RollingSequence chunksPerMinute;
+ private KList queue = new KList<>();
+ private AtomicInteger maxWaiting;
+ private static final Map jobs = new HashMap<>();
+
+ public TurboPregenerator(TurboPregenJob job, File destination) {
+ this.job = job;
+ queue = new KList<>(512);
+ this.maxWaiting = new AtomicInteger(128);
+ this.destination = destination;
+ this.maxPosition = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
+ }).count();
+ this.world = Bukkit.getWorld(job.getWorld());
+ this.latch = new ChronoLatch(3000);
+ this.startTime = new AtomicLong(M.ms());
+ this.chunksPerSecond = new RollingSequence(10);
+ this.chunksPerMinute = new RollingSequence(10);
+ turboGeneratedChunks = new AtomicInteger(0);
+ this.generatedLast = new AtomicInteger(0);
+ this.turboTotalChunks = new AtomicInteger((int) Math.ceil(Math.pow((2.0 * job.getRadiusBlocks()) / 16, 2)));
+ jobs.put(job.getWorld(), job);
+ TurboPregenerator.instance = this;
+ }
+ public TurboPregenerator(File file) throws IOException {
+ this(new Gson().fromJson(IO.readAll(file), TurboPregenerator.TurboPregenJob.class), file);
+ }
+
+ public static void loadTurboGenerator(String i) {
+ World x = Bukkit.getWorld(i);
+ File turbogen = new File(x.getWorldFolder(), "turbogen.json");
+ if (turbogen.exists()) {
+ try {
+ TurboPregenerator p = new TurboPregenerator(turbogen);
+ p.start();
+ Iris.info("Started Turbo Pregenerator: " + p.job);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ }
+
+ @EventHandler
+ public void on(WorldUnloadEvent e) {
+ if (e.getWorld().equals(world)) {
+ interrupt();
+ }
+ }
+
+ public void run() {
+ while (!interrupted()) {
+ tick();
+ }
+
+ try {
+ saveNow();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void tick() {
+ TurboPregenJob job = jobs.get(world.getName());
+ if (latch.flip() && !job.paused) {
+ long eta = computeETA();
+ save();
+ int secondGenerated = turboGeneratedChunks.get() - generatedLast.get();
+ generatedLast.set(turboGeneratedChunks.get());
+ secondGenerated = secondGenerated / 3;
+ chunksPerSecond.put(secondGenerated);
+ chunksPerMinute.put(secondGenerated * 60);
+ Iris.info("TurboGen: " + C.IRIS + world.getName() + C.RESET + " RTT: " + Form.f(turboGeneratedChunks.get()) + " of " + Form.f(turboTotalChunks.get()) + " " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration((double) eta, 2));
+
+ }
+ if (turboGeneratedChunks.get() >= turboTotalChunks.get()) {
+ Iris.info("Completed Turbo Gen!");
+ interrupt();
+ } else {
+ int pos = job.getPosition() + 1;
+ job.setPosition(pos);
+ if (!job.paused) {
+ if (queue.size() < maxWaiting.get()) {
+ Position2 chunk = getChunk(pos);
+ queue.add(chunk);
+ }
+ waitForChunksPartial();
+ }
+ }
+ }
+
+ private void waitForChunksPartial() {
+ while (!queue.isEmpty() && maxWaiting.get() > queue.size()) {
+ try {
+ for (Position2 c : new KList<>(queue)) {
+ tickGenerate(c);
+ queue.remove(c);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private long computeETA() {
+ return (long) ((turboTotalChunks.get() - turboGeneratedChunks.get()) / chunksPerMinute.getAverage()) * 1000;
+ // todo broken
+ }
+
+ private final ExecutorService executorService = Executors.newFixedThreadPool(10);
+ private void tickGenerate(Position2 chunk) {
+ executorService.submit(() -> {
+ CountDownLatch latch = new CountDownLatch(1);
+ PaperLib.getChunkAtAsync(world, chunk.getX(), chunk.getZ(), true)
+ .thenAccept((i) -> {
+ Iris.verbose("Generated Async " + chunk);
+ latch.countDown();
+ });
+ try {
+ latch.await();
+ } catch (InterruptedException ignored) {
+ }
+ turboGeneratedChunks.addAndGet(1);
+ });
+ }
+
+ public Position2 getChunk(int position) {
+ int p = -1;
+ AtomicInteger xx = new AtomicInteger();
+ AtomicInteger zz = new AtomicInteger();
+ Spiraler s = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
+ xx.set(x);
+ zz.set(z);
+ });
+
+ while (s.hasNext() && p++ < position) {
+ s.next();
+ }
+
+ return new Position2(xx.get(), zz.get());
+ }
+
+ public void save() {
+ J.a(() -> {
+ try {
+ saveNow();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ });
+ }
+
+ public static void setPausedTurbo(World world) {
+ TurboPregenJob job = jobs.get(world.getName());
+ if (isPausedTurbo(world)) {
+ job.paused = false;
+ } else {
+ job.paused = true;
+ }
+
+ if (job.paused) {
+ Iris.info(C.BLUE + "TurboGen: " + C.IRIS + world.getName() + C.BLUE + " Paused");
+ } else {
+ Iris.info(C.BLUE + "TurboGen: " + C.IRIS + world.getName() + C.BLUE + " Resumed");
+ }
+ }
+
+ public static boolean isPausedTurbo(World world) {
+ TurboPregenJob job = jobs.get(world.getName());
+ return job != null && job.isPaused();
+ }
+
+ public void shutdownInstance(World world) throws IOException {
+ Iris.info("turboGen: " + C.IRIS + world.getName() + C.BLUE + " Shutting down..");
+ TurboPregenJob job = jobs.get(world.getName());
+ File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
+ File turboFile = new File(worldDirectory, "turbogen.json");
+
+ if (job == null) {
+ Iris.error("No turbogen job found for world: " + world.getName());
+ return;
+ }
+
+ try {
+ if (!job.isPaused()) {
+ job.setPaused(true);
+ }
+ save();
+ jobs.remove(world.getName());
+ new BukkitRunnable() {
+ @Override
+ public void run() {
+ while (turboFile.exists()) {
+ turboFile.delete();
+ J.sleep(1000);
+ }
+ Iris.info("turboGen: " + C.IRIS + world.getName() + C.BLUE + " File deleted and instance closed.");
+ }
+ }.runTaskLater(Iris.instance, 20L);
+ } catch (Exception e) {
+ Iris.error("Failed to shutdown turbogen for " + world.getName());
+ e.printStackTrace();
+ } finally {
+ saveNow();
+ interrupt();
+ }
+ }
+
+
+ public void saveNow() throws IOException {
+ IO.writeAll(this.destination, new Gson().toJson(job));
+ }
+
+ @Data
+ @Builder
+ public static class TurboPregenJob {
+ private String world;
+ @Builder.Default
+ private int radiusBlocks = 5000;
+ @Builder.Default
+ private int position = 0;
+ @Builder.Default
+ boolean paused = false;
+ }
+}
+
diff --git a/core/src/main/java/com/volmit/iris/core/safeguard/ServerBootSFG.java b/core/src/main/java/com/volmit/iris/core/safeguard/ServerBootSFG.java
index 0a8b2983c..46dda64d7 100644
--- a/core/src/main/java/com/volmit/iris/core/safeguard/ServerBootSFG.java
+++ b/core/src/main/java/com/volmit/iris/core/safeguard/ServerBootSFG.java
@@ -3,14 +3,23 @@ package com.volmit.iris.core.safeguard;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
+import org.apache.logging.log4j.core.util.ExecutorServices;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import javax.print.attribute.standard.Severity;
import java.io.File;
+import java.nio.channels.FileChannel;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
import java.util.HashMap;
import java.util.Map;
import java.util.StringJoiner;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import static com.volmit.iris.Iris.getJavaVersion;
import static com.volmit.iris.Iris.instance;
@@ -19,9 +28,9 @@ import static com.volmit.iris.core.safeguard.IrisSafeguard.*;
public class ServerBootSFG {
public static final Map incompatibilities = new HashMap<>();
public static boolean isJDK17 = true;
- public static boolean hasEnoughDiskSpace = false;
+ public static boolean hasEnoughDiskSpace = true;
public static boolean isJRE = false;
- public static boolean hasPrivileges = false;
+ public static boolean hasPrivileges = true;
public static boolean unsuportedversion = false;
protected static boolean safeguardPassed;
public static boolean passedserversoftware = true;
@@ -38,7 +47,7 @@ public class ServerBootSFG {
incompatibilities.clear();
incompatibilities.put("Multiverse-Core", false);
- incompatibilities.put("Dynmap", false);
+ incompatibilities.put("dynmap", false);
incompatibilities.put("TerraformGenerator", false);
incompatibilities.put("Stratos", false);
@@ -80,20 +89,23 @@ public class ServerBootSFG {
joiner.add("Unsupported Java version");
severityMedium++;
}
+
if (!isJDK()) {
isJRE = true;
joiner.add("Unsupported JDK");
severityMedium++;
}
+
if (!hasPrivileges()){
hasPrivileges = true;
joiner.add("Insufficient Privileges");
- severityHigh++;
+ severityMedium++;
}
+
if (!enoughDiskSpace()){
hasEnoughDiskSpace = false;
joiner.add("Insufficient Disk Space");
- severityHigh++;
+ severityMedium++;
}
allIncompatibilities = joiner.toString();
@@ -136,18 +148,12 @@ public class ServerBootSFG {
}
public static boolean hasPrivileges() {
- File pv = new File(Bukkit.getWorldContainer() + "iristest.json");
- if (pv.exists()){
- pv.delete();
- }
- try {
- if (pv.createNewFile()){
- if (pv.canWrite() && pv.canRead()){
- pv.delete();
- return true;
- }
+ Path pv = Paths.get(Bukkit.getWorldContainer() + "iristest.json");
+ try (FileChannel fc = FileChannel.open(pv, StandardOpenOption.CREATE, StandardOpenOption.DELETE_ON_CLOSE, StandardOpenOption.READ, StandardOpenOption.WRITE)) {
+ if (Files.isReadable(pv) && Files.isWritable(pv)) {
+ return true;
}
- } catch (Exception e){
+ } catch (Exception e) {
return false;
}
return false;
diff --git a/core/src/main/java/com/volmit/iris/core/safeguard/UtilsSFG.java b/core/src/main/java/com/volmit/iris/core/safeguard/UtilsSFG.java
index b4dac8a9d..c9155c7b3 100644
--- a/core/src/main/java/com/volmit/iris/core/safeguard/UtilsSFG.java
+++ b/core/src/main/java/com/volmit/iris/core/safeguard/UtilsSFG.java
@@ -26,7 +26,7 @@ public class UtilsSFG {
Iris.safeguard(C.RED + "- The plugin Multiverse is not compatible with the server.");
Iris.safeguard(C.RED + "- If you want to have a world manager, consider using PhantomWorlds or MyWorlds instead.");
}
- if (ServerBootSFG.incompatibilities.get("Dynmap")) {
+ if (ServerBootSFG.incompatibilities.get("dynmap")) {
Iris.safeguard(C.RED + "Dynmap");
Iris.safeguard(C.RED + "- The plugin Dynmap is not compatible with the server.");
Iris.safeguard(C.RED + "- If you want to have a map plugin like Dynmap, consider Bluemap.");
@@ -40,22 +40,22 @@ public class UtilsSFG {
Iris.safeguard(C.RED + "- Iris only supports 1.19.2 > 1.20.2");
}
if (!ServerBootSFG.passedserversoftware) {
- Iris.safeguard(C.RED + "Unsupported Server Software");
- Iris.safeguard(C.RED + "- Please consider using Paper or Purpur instead.");
+ Iris.safeguard(C.YELLOW + "Unsupported Server Software");
+ Iris.safeguard(C.YELLOW + "- Please consider using Paper or Purpur instead.");
}
if (!ServerBootSFG.hasPrivileges) {
- Iris.safeguard(C.RED + "Insufficient Privileges");
- Iris.safeguard(C.RED + "- The server has insufficient Privileges to run iris. Please contact support.");
+ Iris.safeguard(C.YELLOW + "Insufficient Privileges");
+ Iris.safeguard(C.YELLOW + "- The server has insufficient Privileges to run iris. Please contact support.");
}
if (!ServerBootSFG.hasEnoughDiskSpace) {
- Iris.safeguard(C.RED + "Insufficient Disk Space");
- Iris.safeguard(C.RED + "- The server has insufficient Free DiskSpace to run iris required 3GB+.");
+ Iris.safeguard(C.YELLOW + "Insufficient Disk Space");
+ Iris.safeguard(C.YELLOW + "- The server has insufficient Free DiskSpace to run iris required 3GB+.");
}
if (!ServerBootSFG.isJDK17) {
Iris.safeguard(C.YELLOW + "Unsupported java version");
Iris.safeguard(C.YELLOW + "- Please consider using JDK 17 Instead of JDK " + Iris.getJavaVersion());
}
- if (!ServerBootSFG.isJRE) {
+ if (ServerBootSFG.isJRE) {
Iris.safeguard(C.YELLOW + "Unsupported Server JDK");
Iris.safeguard(C.YELLOW + "- Please consider using JDK 17 Instead of JRE " + Iris.getJavaVersion());
}
diff --git a/core/src/main/java/com/volmit/iris/core/service/BoardSVC.java b/core/src/main/java/com/volmit/iris/core/service/BoardSVC.java
index 4fa115cdd..d8456b0a5 100644
--- a/core/src/main/java/com/volmit/iris/core/service/BoardSVC.java
+++ b/core/src/main/java/com/volmit/iris/core/service/BoardSVC.java
@@ -19,6 +19,7 @@
package com.volmit.iris.core.service;
import com.volmit.iris.Iris;
+import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
@@ -131,7 +132,11 @@ public class BoardSVC implements IrisService, BoardProvider {
lines.add("&7&m ");
lines.add(C.AQUA + "Region" + C.GRAY + ": " + engine.getRegion(x, z).getName());
lines.add(C.AQUA + "Biome" + C.GRAY + ": " + engine.getBiomeOrMantle(x, y, z).getName());
- lines.add(C.AQUA + "Height" + C.GRAY + ": " + Math.round(engine.getHeight(x, z) + player.getWorld().getMinHeight()));
+ if (!IrisSettings.get().getStudio().displayTrueHeight) {
+ lines.add(C.AQUA + "Height" + C.GRAY + ": " + Math.round(engine.getHeight(x, z) + player.getWorld().getMinHeight()));
+ } else {
+ lines.add(C.AQUA + "Height" + C.GRAY + ": " + Math.round(engine.getHeight(x, z)));
+ }
lines.add(C.AQUA + "Slope" + C.GRAY + ": " + Form.f(engine.getComplex().getSlopeStream().get(x, z), 2));
lines.add(C.AQUA + "BUD/s" + C.GRAY + ": " + Form.f(engine.getBlockUpdatesPerSecond()));
lines.add("&7&m ");
diff --git a/core/src/main/java/com/volmit/iris/core/service/IrisEngineSVC.java b/core/src/main/java/com/volmit/iris/core/service/IrisEngineSVC.java
index ad79ed916..6f3f79535 100644
--- a/core/src/main/java/com/volmit/iris/core/service/IrisEngineSVC.java
+++ b/core/src/main/java/com/volmit/iris/core/service/IrisEngineSVC.java
@@ -79,7 +79,7 @@ public class IrisEngineSVC implements IrisService {
}
} catch (Throwable e) {
Iris.reportError(e);
- return -1;
+ // return -1;
}
int size = lastUse.size();
diff --git a/core/src/main/java/com/volmit/iris/engine/jigsaw/PlannedStructure.java b/core/src/main/java/com/volmit/iris/engine/jigsaw/PlannedStructure.java
index 81986c252..dd7eade40 100644
--- a/core/src/main/java/com/volmit/iris/engine/jigsaw/PlannedStructure.java
+++ b/core/src/main/java/com/volmit/iris/engine/jigsaw/PlannedStructure.java
@@ -100,7 +100,7 @@ public class PlannedStructure {
int sz = (v.getD() / 2);
int xx = i.getPosition().getX() + sx;
int zz = i.getPosition().getZ() + sz;
- RNG rng = new RNG(Cache.key(xx, zz));
+ RNG rngf = new RNG(Cache.key(xx, zz));
int offset = i.getPosition().getY() - startHeight;
int height;
diff --git a/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java b/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java
index 7457b9f1c..4b7f415b3 100644
--- a/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java
+++ b/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java
@@ -421,22 +421,27 @@ public class Mantle {
}
ioTrim.set(true);
- //unloadLock.lock();
+ unloadLock.lock();
try {
Iris.debug("Trimming Tectonic Plates older than " + Form.duration(adjustedIdleDuration.get(), 0));
if (lastUse != null) {
- for (Long i : new ArrayList<>(lastUse.keySet())) {
- double finalAdjustedIdleDuration = adjustedIdleDuration.get();
- hyperLock.withLong(i, () -> {
- Long lastUseTime = lastUse.get(i);
- if (lastUseTime != null && M.ms() - lastUseTime >= finalAdjustedIdleDuration) {
- toUnload.add(i);
- Iris.debug("Tectonic Region added to unload");
- }
- });
+ if (!lastUse.isEmpty()) {
+ for (Long i : new ArrayList<>(lastUse.keySet())) {
+ double finalAdjustedIdleDuration = adjustedIdleDuration.get();
+ hyperLock.withLong(i, () -> {
+ Long lastUseTime = lastUse.get(i);
+ if (lastUseTime != null && M.ms() - lastUseTime >= finalAdjustedIdleDuration) {
+ toUnload.add(i);
+ Iris.debug("Tectonic Region added to unload");
+ //Iris.panic();
+ }
+ });
+ }
}
}
+ } catch (Throwable e) {
+ Iris.reportError(e);
} finally {
ioTrim.set(false);
unloadLock.unlock();
@@ -444,7 +449,6 @@ public class Mantle {
}
public synchronized int unloadTectonicPlate(int tectonicLimit) {
- // todo: Make it advanced with bursts etc
AtomicInteger i = new AtomicInteger();
unloadLock.lock();
BurstExecutor burst = null;
@@ -465,12 +469,12 @@ public class Mantle {
i.incrementAndGet();
Iris.debug("Unloaded Tectonic Plate " + C.DARK_GREEN + Cache.keyX(id) + " " + Cache.keyZ(id));
} catch (IOException e) {
- e.printStackTrace();
+ Iris.reportError(e);
}
}
}));
- }
+ }
burst.complete();
} catch (Throwable e) {
e.printStackTrace();