mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-08-18 09:16:22 +00:00
Compare commits
12 Commits
c11b5342e3
...
1b3916749a
Author | SHA1 | Date | |
---|---|---|---|
|
1b3916749a | ||
|
e29ec657d3 | ||
|
04f3a226a1 | ||
|
099d1cc362 | ||
|
c11e9bf704 | ||
|
ffa0b984a0 | ||
|
f0f9261ed3 | ||
|
ba433bc244 | ||
|
02c7ab71d4 | ||
|
8ec1ac9875 | ||
|
e03027a386 | ||
|
9421d788f3 |
@ -184,6 +184,7 @@ public class IrisSettings {
|
|||||||
public static class IrisSettingsStudio {
|
public static class IrisSettingsStudio {
|
||||||
public boolean studio = true;
|
public boolean studio = true;
|
||||||
public boolean openVSCode = true;
|
public boolean openVSCode = true;
|
||||||
|
public boolean displayTrueHeight = false;
|
||||||
public boolean disableTimeAndWeather = true;
|
public boolean disableTimeAndWeather = true;
|
||||||
public boolean autoStartDefaultStudio = false;
|
public boolean autoStartDefaultStudio = false;
|
||||||
}
|
}
|
||||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -72,6 +72,7 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
private CommandEdit edit;
|
private CommandEdit edit;
|
||||||
private CommandFind find;
|
private CommandFind find;
|
||||||
private CommandDeveloper developer;
|
private CommandDeveloper developer;
|
||||||
|
private CommandTurboPregen turboPregen;
|
||||||
|
|
||||||
public static @Getter String BenchDimension;
|
public static @Getter String BenchDimension;
|
||||||
public static boolean worldCreation = false;
|
public static boolean worldCreation = false;
|
||||||
|
@ -47,6 +47,7 @@ import com.volmit.iris.util.io.IO;
|
|||||||
import com.volmit.iris.util.json.JSONArray;
|
import com.volmit.iris.util.json.JSONArray;
|
||||||
import com.volmit.iris.util.json.JSONObject;
|
import com.volmit.iris.util.json.JSONObject;
|
||||||
import com.volmit.iris.util.math.M;
|
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.RNG;
|
||||||
import com.volmit.iris.util.math.Spiraler;
|
import com.volmit.iris.util.math.Spiraler;
|
||||||
import com.volmit.iris.util.noise.CNG;
|
import com.volmit.iris.util.noise.CNG;
|
||||||
@ -76,12 +77,14 @@ import java.util.Date;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
@Decree(name = "studio", aliases = {"std", "s"}, description = "Studio Commands", studio = true)
|
@Decree(name = "studio", aliases = {"std", "s"}, description = "Studio Commands", studio = true)
|
||||||
public class CommandStudio implements DecreeExecutor {
|
public class CommandStudio implements DecreeExecutor {
|
||||||
private CommandFind find;
|
private CommandFind find;
|
||||||
private CommandEdit edit;
|
private CommandEdit edit;
|
||||||
|
private CommandDeepSearch deepSearch;
|
||||||
|
|
||||||
public static String hrf(Duration duration) {
|
public static String hrf(Duration duration) {
|
||||||
return duration.toString().substring(2).replaceAll("(\\d[HMS])(?!$)", "$1 ").toLowerCase();
|
return duration.toString().substring(2).replaceAll("(\\d[HMS])(?!$)", "$1 ").toLowerCase();
|
||||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<Integer, Position2> chunkCache;
|
||||||
|
private final ReentrantLock cacheLock = new ReentrantLock();
|
||||||
|
|
||||||
|
private static final Map<String, DeepSearchJob> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -49,7 +49,6 @@ public class LazyPregenerator extends Thread implements Listener {
|
|||||||
private final RollingSequence chunksPerSecond;
|
private final RollingSequence chunksPerSecond;
|
||||||
private final RollingSequence chunksPerMinute;
|
private final RollingSequence chunksPerMinute;
|
||||||
|
|
||||||
// A map to keep track of jobs for each world
|
|
||||||
private static final Map<String, LazyPregenJob> jobs = new HashMap<>();
|
private static final Map<String, LazyPregenJob> jobs = new HashMap<>();
|
||||||
|
|
||||||
public LazyPregenerator(LazyPregenJob job, File destination) {
|
public LazyPregenerator(LazyPregenJob job, File destination) {
|
||||||
@ -155,10 +154,7 @@ public class LazyPregenerator extends Thread implements Listener {
|
|||||||
if (PaperLib.isPaper()) {
|
if (PaperLib.isPaper()) {
|
||||||
PaperLib.getChunkAtAsync(world, chunk.getX(), chunk.getZ(), true)
|
PaperLib.getChunkAtAsync(world, chunk.getX(), chunk.getZ(), true)
|
||||||
.thenAccept((i) -> {
|
.thenAccept((i) -> {
|
||||||
LazyPregenJob j = jobs.get(world.getName());
|
|
||||||
if (!j.paused) {
|
|
||||||
Iris.verbose("Generated Async " + chunk);
|
Iris.verbose("Generated Async " + chunk);
|
||||||
}
|
|
||||||
latch.countDown();
|
latch.countDown();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -207,7 +203,6 @@ public class LazyPregenerator extends Thread implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void setPausedLazy(World world) {
|
public static void setPausedLazy(World world) {
|
||||||
// todo: doesnt actually pause
|
|
||||||
LazyPregenJob job = jobs.get(world.getName());
|
LazyPregenJob job = jobs.get(world.getName());
|
||||||
if (isPausedLazy(world)){
|
if (isPausedLazy(world)){
|
||||||
job.paused = false;
|
job.paused = false;
|
||||||
|
@ -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<Position2> queue = new KList<>();
|
||||||
|
private AtomicInteger maxWaiting;
|
||||||
|
private static final Map<String, TurboPregenJob> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,14 +3,23 @@ package com.volmit.iris.core.safeguard;
|
|||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.nms.INMS;
|
import com.volmit.iris.core.nms.INMS;
|
||||||
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
||||||
|
import org.apache.logging.log4j.core.util.ExecutorServices;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
import javax.print.attribute.standard.Severity;
|
import javax.print.attribute.standard.Severity;
|
||||||
import java.io.File;
|
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.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.StringJoiner;
|
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.getJavaVersion;
|
||||||
import static com.volmit.iris.Iris.instance;
|
import static com.volmit.iris.Iris.instance;
|
||||||
@ -19,9 +28,9 @@ import static com.volmit.iris.core.safeguard.IrisSafeguard.*;
|
|||||||
public class ServerBootSFG {
|
public class ServerBootSFG {
|
||||||
public static final Map<String, Boolean> incompatibilities = new HashMap<>();
|
public static final Map<String, Boolean> incompatibilities = new HashMap<>();
|
||||||
public static boolean isJDK17 = true;
|
public static boolean isJDK17 = true;
|
||||||
public static boolean hasEnoughDiskSpace = false;
|
public static boolean hasEnoughDiskSpace = true;
|
||||||
public static boolean isJRE = false;
|
public static boolean isJRE = false;
|
||||||
public static boolean hasPrivileges = false;
|
public static boolean hasPrivileges = true;
|
||||||
public static boolean unsuportedversion = false;
|
public static boolean unsuportedversion = false;
|
||||||
protected static boolean safeguardPassed;
|
protected static boolean safeguardPassed;
|
||||||
public static boolean passedserversoftware = true;
|
public static boolean passedserversoftware = true;
|
||||||
@ -38,7 +47,7 @@ public class ServerBootSFG {
|
|||||||
|
|
||||||
incompatibilities.clear();
|
incompatibilities.clear();
|
||||||
incompatibilities.put("Multiverse-Core", false);
|
incompatibilities.put("Multiverse-Core", false);
|
||||||
incompatibilities.put("Dynmap", false);
|
incompatibilities.put("dynmap", false);
|
||||||
incompatibilities.put("TerraformGenerator", false);
|
incompatibilities.put("TerraformGenerator", false);
|
||||||
incompatibilities.put("Stratos", false);
|
incompatibilities.put("Stratos", false);
|
||||||
|
|
||||||
@ -80,20 +89,23 @@ public class ServerBootSFG {
|
|||||||
joiner.add("Unsupported Java version");
|
joiner.add("Unsupported Java version");
|
||||||
severityMedium++;
|
severityMedium++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isJDK()) {
|
if (!isJDK()) {
|
||||||
isJRE = true;
|
isJRE = true;
|
||||||
joiner.add("Unsupported JDK");
|
joiner.add("Unsupported JDK");
|
||||||
severityMedium++;
|
severityMedium++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasPrivileges()){
|
if (!hasPrivileges()){
|
||||||
hasPrivileges = true;
|
hasPrivileges = true;
|
||||||
joiner.add("Insufficient Privileges");
|
joiner.add("Insufficient Privileges");
|
||||||
severityHigh++;
|
severityMedium++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!enoughDiskSpace()){
|
if (!enoughDiskSpace()){
|
||||||
hasEnoughDiskSpace = false;
|
hasEnoughDiskSpace = false;
|
||||||
joiner.add("Insufficient Disk Space");
|
joiner.add("Insufficient Disk Space");
|
||||||
severityHigh++;
|
severityMedium++;
|
||||||
}
|
}
|
||||||
|
|
||||||
allIncompatibilities = joiner.toString();
|
allIncompatibilities = joiner.toString();
|
||||||
@ -136,17 +148,11 @@ public class ServerBootSFG {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasPrivileges() {
|
public static boolean hasPrivileges() {
|
||||||
File pv = new File(Bukkit.getWorldContainer() + "iristest.json");
|
Path pv = Paths.get(Bukkit.getWorldContainer() + "iristest.json");
|
||||||
if (pv.exists()){
|
try (FileChannel fc = FileChannel.open(pv, StandardOpenOption.CREATE, StandardOpenOption.DELETE_ON_CLOSE, StandardOpenOption.READ, StandardOpenOption.WRITE)) {
|
||||||
pv.delete();
|
if (Files.isReadable(pv) && Files.isWritable(pv)) {
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (pv.createNewFile()){
|
|
||||||
if (pv.canWrite() && pv.canRead()){
|
|
||||||
pv.delete();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ public class UtilsSFG {
|
|||||||
Iris.safeguard(C.RED + "- The plugin Multiverse is not compatible with the server.");
|
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.");
|
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 + "Dynmap");
|
||||||
Iris.safeguard(C.RED + "- The plugin Dynmap is not compatible with the server.");
|
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.");
|
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");
|
Iris.safeguard(C.RED + "- Iris only supports 1.19.2 > 1.20.2");
|
||||||
}
|
}
|
||||||
if (!ServerBootSFG.passedserversoftware) {
|
if (!ServerBootSFG.passedserversoftware) {
|
||||||
Iris.safeguard(C.RED + "Unsupported Server Software");
|
Iris.safeguard(C.YELLOW + "Unsupported Server Software");
|
||||||
Iris.safeguard(C.RED + "- Please consider using Paper or Purpur instead.");
|
Iris.safeguard(C.YELLOW + "- Please consider using Paper or Purpur instead.");
|
||||||
}
|
}
|
||||||
if (!ServerBootSFG.hasPrivileges) {
|
if (!ServerBootSFG.hasPrivileges) {
|
||||||
Iris.safeguard(C.RED + "Insufficient Privileges");
|
Iris.safeguard(C.YELLOW + "Insufficient Privileges");
|
||||||
Iris.safeguard(C.RED + "- The server has insufficient Privileges to run iris. Please contact support.");
|
Iris.safeguard(C.YELLOW + "- The server has insufficient Privileges to run iris. Please contact support.");
|
||||||
}
|
}
|
||||||
if (!ServerBootSFG.hasEnoughDiskSpace) {
|
if (!ServerBootSFG.hasEnoughDiskSpace) {
|
||||||
Iris.safeguard(C.RED + "Insufficient Disk Space");
|
Iris.safeguard(C.YELLOW + "Insufficient Disk Space");
|
||||||
Iris.safeguard(C.RED + "- The server has insufficient Free DiskSpace to run iris required 3GB+.");
|
Iris.safeguard(C.YELLOW + "- The server has insufficient Free DiskSpace to run iris required 3GB+.");
|
||||||
}
|
}
|
||||||
if (!ServerBootSFG.isJDK17) {
|
if (!ServerBootSFG.isJDK17) {
|
||||||
Iris.safeguard(C.YELLOW + "Unsupported java version");
|
Iris.safeguard(C.YELLOW + "Unsupported java version");
|
||||||
Iris.safeguard(C.YELLOW + "- Please consider using JDK 17 Instead of JDK " + Iris.getJavaVersion());
|
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 + "Unsupported Server JDK");
|
||||||
Iris.safeguard(C.YELLOW + "- Please consider using JDK 17 Instead of JRE " + Iris.getJavaVersion());
|
Iris.safeguard(C.YELLOW + "- Please consider using JDK 17 Instead of JRE " + Iris.getJavaVersion());
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package com.volmit.iris.core.service;
|
package com.volmit.iris.core.service;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
@ -131,7 +132,11 @@ public class BoardSVC implements IrisService, BoardProvider {
|
|||||||
lines.add("&7&m ");
|
lines.add("&7&m ");
|
||||||
lines.add(C.AQUA + "Region" + C.GRAY + ": " + engine.getRegion(x, z).getName());
|
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 + "Biome" + C.GRAY + ": " + engine.getBiomeOrMantle(x, y, z).getName());
|
||||||
|
if (!IrisSettings.get().getStudio().displayTrueHeight) {
|
||||||
lines.add(C.AQUA + "Height" + C.GRAY + ": " + Math.round(engine.getHeight(x, z) + player.getWorld().getMinHeight()));
|
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 + "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(C.AQUA + "BUD/s" + C.GRAY + ": " + Form.f(engine.getBlockUpdatesPerSecond()));
|
||||||
lines.add("&7&m ");
|
lines.add("&7&m ");
|
||||||
|
@ -79,7 +79,7 @@ public class IrisEngineSVC implements IrisService {
|
|||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
return -1;
|
// return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int size = lastUse.size();
|
int size = lastUse.size();
|
||||||
|
@ -101,7 +101,7 @@ public class PlannedStructure {
|
|||||||
int sz = (v.getD() / 2);
|
int sz = (v.getD() / 2);
|
||||||
int xx = i.getPosition().getX() + sx;
|
int xx = i.getPosition().getX() + sx;
|
||||||
int zz = i.getPosition().getZ() + sz;
|
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 offset = i.getPosition().getY() - startHeight;
|
||||||
int height;
|
int height;
|
||||||
|
|
||||||
|
@ -421,10 +421,11 @@ public class Mantle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ioTrim.set(true);
|
ioTrim.set(true);
|
||||||
//unloadLock.lock();
|
unloadLock.lock();
|
||||||
try {
|
try {
|
||||||
Iris.debug("Trimming Tectonic Plates older than " + Form.duration(adjustedIdleDuration.get(), 0));
|
Iris.debug("Trimming Tectonic Plates older than " + Form.duration(adjustedIdleDuration.get(), 0));
|
||||||
if (lastUse != null) {
|
if (lastUse != null) {
|
||||||
|
if (!lastUse.isEmpty()) {
|
||||||
for (Long i : new ArrayList<>(lastUse.keySet())) {
|
for (Long i : new ArrayList<>(lastUse.keySet())) {
|
||||||
double finalAdjustedIdleDuration = adjustedIdleDuration.get();
|
double finalAdjustedIdleDuration = adjustedIdleDuration.get();
|
||||||
hyperLock.withLong(i, () -> {
|
hyperLock.withLong(i, () -> {
|
||||||
@ -432,11 +433,15 @@ public class Mantle {
|
|||||||
if (lastUseTime != null && M.ms() - lastUseTime >= finalAdjustedIdleDuration) {
|
if (lastUseTime != null && M.ms() - lastUseTime >= finalAdjustedIdleDuration) {
|
||||||
toUnload.add(i);
|
toUnload.add(i);
|
||||||
Iris.debug("Tectonic Region added to unload");
|
Iris.debug("Tectonic Region added to unload");
|
||||||
|
//Iris.panic();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Iris.reportError(e);
|
||||||
} finally {
|
} finally {
|
||||||
ioTrim.set(false);
|
ioTrim.set(false);
|
||||||
unloadLock.unlock();
|
unloadLock.unlock();
|
||||||
@ -444,7 +449,6 @@ public class Mantle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public synchronized int unloadTectonicPlate(int tectonicLimit) {
|
public synchronized int unloadTectonicPlate(int tectonicLimit) {
|
||||||
// todo: Make it advanced with bursts etc
|
|
||||||
AtomicInteger i = new AtomicInteger();
|
AtomicInteger i = new AtomicInteger();
|
||||||
unloadLock.lock();
|
unloadLock.lock();
|
||||||
BurstExecutor burst = null;
|
BurstExecutor burst = null;
|
||||||
@ -465,12 +469,12 @@ public class Mantle {
|
|||||||
i.incrementAndGet();
|
i.incrementAndGet();
|
||||||
Iris.debug("Unloaded Tectonic Plate " + C.DARK_GREEN + Cache.keyX(id) + " " + Cache.keyZ(id));
|
Iris.debug("Unloaded Tectonic Plate " + C.DARK_GREEN + Cache.keyX(id) + " " + Cache.keyZ(id));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
Iris.reportError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
burst.complete();
|
burst.complete();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user