diff --git a/src/main/java/com/volmit/iris/Iris.java b/src/main/java/com/volmit/iris/Iris.java index 9c2c52cc4..51d28fe8e 100644 --- a/src/main/java/com/volmit/iris/Iris.java +++ b/src/main/java/com/volmit/iris/Iris.java @@ -29,6 +29,7 @@ import com.volmit.iris.core.link.MythicMobsLink; import com.volmit.iris.core.link.OraxenLink; import com.volmit.iris.core.nms.INMS; import com.volmit.iris.core.project.loader.IrisData; +import com.volmit.iris.core.tools.IrisToolbelt; import com.volmit.iris.core.tools.IrisWorlds; import com.volmit.iris.engine.framework.EngineCompositeGenerator; import com.volmit.iris.engine.object.biome.IrisBiome; @@ -266,8 +267,8 @@ public class Iris extends VolmitPlugin implements Listener { proj.close(); for (World i : Bukkit.getWorlds()) { - if (IrisWorlds.isIrisWorld(i)) { - IrisWorlds.access(i).close(); + if (IrisToolbelt.isIrisWorld(i)) { + IrisToolbelt.access(i).close(); } } diff --git a/src/main/java/com/volmit/iris/core/command/CommandIris.java b/src/main/java/com/volmit/iris/core/command/CommandIris.java index 7e3d37420..a8f4250c8 100644 --- a/src/main/java/com/volmit/iris/core/command/CommandIris.java +++ b/src/main/java/com/volmit/iris/core/command/CommandIris.java @@ -21,6 +21,7 @@ package com.volmit.iris.core.command; import com.volmit.iris.Iris; import com.volmit.iris.core.command.jigsaw.CommandIrisJigsaw; import com.volmit.iris.core.command.object.CommandIrisObject; +import com.volmit.iris.core.command.pregen.CommandIrisPregen; import com.volmit.iris.core.command.studio.CommandIrisStudio; import com.volmit.iris.core.command.what.CommandIrisWhat; import com.volmit.iris.core.command.world.*; diff --git a/src/main/java/com/volmit/iris/core/command/pregen/CommandIrisPregen.java b/src/main/java/com/volmit/iris/core/command/pregen/CommandIrisPregen.java new file mode 100644 index 000000000..53fdf10c9 --- /dev/null +++ b/src/main/java/com/volmit/iris/core/command/pregen/CommandIrisPregen.java @@ -0,0 +1,70 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.core.command.pregen; + +import com.volmit.iris.Iris; +import com.volmit.iris.core.tools.IrisToolbelt; +import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.plugin.Command; +import com.volmit.iris.util.plugin.MortarCommand; +import com.volmit.iris.util.plugin.VolmitSender; + +public class CommandIrisPregen extends MortarCommand { + @Command + private CommandIrisPregenStart start; + + @Command + private CommandIrisPregenStop stop; + + @Command + private CommandIrisPregenPause toggle; + + public CommandIrisPregen() { + super("pregen", "preg", "p"); + requiresPermission(Iris.perm); + setCategory("Pregen"); + setDescription("Pregeneration Commands"); + } + + @Override + public void addTabOptions(VolmitSender sender, String[] args, KList list) { + + } + + @Override + public boolean handle(VolmitSender sender, String[] args) { + if (sender.isPlayer()) { + if (!IrisToolbelt.isIrisWorld(sender.player().getWorld())) { + sender.sendMessage("Pregen only works in Iris worlds!"); + } + } else { + sender.sendMessage("Note that pregeneration only works in Iris worlds!"); + } + + sender.sendMessage("Iris Pregen Commands:"); + printHelp(sender); + sender.sendMessage("Pregen wiki page: https://docs.volmit.com/iris/pregeneration"); + return true; + } + + @Override + protected String getArgsUsage() { + return "[subcommand]"; + } +} diff --git a/src/main/java/com/volmit/iris/core/command/pregen/CommandIrisPregenPause.java b/src/main/java/com/volmit/iris/core/command/pregen/CommandIrisPregenPause.java new file mode 100644 index 000000000..66d324d3d --- /dev/null +++ b/src/main/java/com/volmit/iris/core/command/pregen/CommandIrisPregenPause.java @@ -0,0 +1,37 @@ +package com.volmit.iris.core.command.pregen; + +import com.volmit.iris.Iris; +import com.volmit.iris.core.gui.PregeneratorJob; +import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.plugin.MortarCommand; +import com.volmit.iris.util.plugin.VolmitSender; + +public class CommandIrisPregenPause extends MortarCommand { + + public CommandIrisPregenPause() { + super("pause", "toggle", "t", "continue", "resume", "p", "c", "unpause", "up"); + requiresPermission(Iris.perm); + setCategory("Pregen"); + setDescription("Toggle an ongoing pregeneration task"); + } + + @Override + public boolean handle(VolmitSender sender, String[] args) { + if (PregeneratorJob.pauseResume()){ + sender.sendMessage("Paused/unpaused pregeneration task, now: " + (PregeneratorJob.isPaused() ? "Paused" : "Running") + "."); + } else { + sender.sendMessage("No active pregeneration tasks to pause/unpause."); + } + return true; + } + + @Override + public void addTabOptions(VolmitSender sender, String[] args, KList list) { + + } + + @Override + protected String getArgsUsage() { + return ""; + } +} diff --git a/src/main/java/com/volmit/iris/core/command/pregen/CommandIrisPregenStart.java b/src/main/java/com/volmit/iris/core/command/pregen/CommandIrisPregenStart.java new file mode 100644 index 000000000..1c0ea3342 --- /dev/null +++ b/src/main/java/com/volmit/iris/core/command/pregen/CommandIrisPregenStart.java @@ -0,0 +1,297 @@ +package com.volmit.iris.core.command.pregen; + +import com.volmit.iris.Iris; +import com.volmit.iris.core.gui.PregeneratorJob; +import com.volmit.iris.core.pregenerator.PregenTask; +import com.volmit.iris.core.tools.IrisToolbelt; +import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.math.Position2; +import com.volmit.iris.util.plugin.MortarCommand; +import com.volmit.iris.util.plugin.VolmitSender; +import org.bukkit.Bukkit; +import org.bukkit.World; + +import java.util.Arrays; + + +public class CommandIrisPregenStart extends MortarCommand { + + private static final KList argus = new KList<>("radius=", "x=", "z="); + + public CommandIrisPregenStart() { + super("start", "s", "create", "c", "new", "+"); + requiresPermission(Iris.perm); + setCategory("Pregen"); + setDescription(""" + Create a new pregeneration task. + Command usage: + /iris pregen create [radius=] [x=] [z=] [world=] [-here] + + Examples: + /iris pregen start 5k -here + /iris pregen start radius=5000 x=10r z=10r world=IrisWorld + /iris pregen start 10k world=WorldName + + : Sets both width and height to a value. (Size is: 2 * radius by 2 * radius) + & : Give the center point of the pregen. + : Specify a different world name for generation than the one you're currently in. + The console is not in any world, so this is required for console! + If you specify this, the `-here` is ignored. + -here: If added, the center location is set to your position (player only) + This overrides and . + + For all numeric values (radius, centerX, etc.) you may use: + c => 16, r => 512, k => 1000 + Example: entering '1000' is the same as '1k' (1 * 1000) + https://docs.volmit.com/iris/pregeneration"""); + } + + @Override + public void addTabOptions(VolmitSender sender, String[] args, KList list) { + + // Add arguments + argus.forEach(p -> { + boolean hasArg = false; + for (String arg : args) { + if (!arg.contains("=") || !p.contains("=")){ + continue; + } + if (arg.split("=")[0].equals(p.split("=")[0])) { + hasArg = true; + break; + } + } + if (!hasArg){ + list.add(p); + } + }); + + // Add -here + boolean hasHere = false; + for (String arg : args) { + if (arg.equals("-here")) { + hasHere = true; + break; + } + } + if (!hasHere){ + list.add("-here"); + } + + // Add Iris worlds + if (Bukkit.getWorlds().isEmpty()){ + list.add("world="); + } else { + Bukkit.getWorlds().forEach(w -> { + if (IrisToolbelt.isIrisWorld(w)) { + list.add("world=" + w.getName()); + } + }); + } + } + + @Override + protected String getArgsUsage() { + return " [x=] [z=] [world=] [-here]"; + } + + @Override + public boolean handle(VolmitSender sender, String[] args) { + + if (PregeneratorJob.getInstance() != null) { + sender.sendMessage("Pregeneration task already ongoing. You can stop it with /ir p stop."); + sender.sendMessage("Cannot create new pregen while one is already going. Cancelling..."); + return true; + } + + World world = null; + int width = -1; + int height = -1; + int x = 0; + int z = 0; + boolean here = false; + + // Check all arguments + KList failed = new KList<>(); + for (String a : args) { + if (a.equals("-here")){ + here = true; + } else if (a.contains("=")) { + String pre = a.split("=")[0]; + String val = a.split("=")[1]; + if (pre.equals("world")){ + world = Bukkit.getWorld(val); + if (world == null){ + failed.add(a + " (invalid world)"); + sender.sendMessage("Entered world is " + val + ", but that world does not exist."); + sender.sendMessage("Cancelling the command."); + sender.sendMessage(getDescription()); + return true; + } + } else if (!isVal(val)){ + failed.add(a + " (non-value)"); + } else { + switch (pre) { + case "width" -> width = getVal(val); + case "height" -> height = getVal(val); + case "radius" -> { + width = getVal(val); + height = getVal(val); + } + case "x" -> x = getVal(val); + case "z" -> z = getVal(val); + default -> failed.add(a + " (no type)"); + } + } + } else if (isVal(a)) { + width = getVal(a); + height = getVal(a); + } else { + failed.add(a + " (nothing)"); + } + } + + // Checking if a radius was specified or forgotten + if (width == -1 || height == -1){ + sender.sendMessage("Radius not specified! Cancelling..."); + sender.sendMessage(getDescription()); + return true; + } + + // World specified & cancelling `-here` if it's another world + if (world == null){ + if (sender.isPlayer()){ + world = sender.player().getWorld(); + } else { + sender.sendMessage("Must specify world= if sending from console! Cancelling..."); + sender.sendMessage(getDescription()); + return true; + } + } else { + if (sender.isPlayer()){ + if (!world.equals(sender.player().getWorld())){ + if (here) { + sender.sendMessage("Ignoring `-here` because `world=` is specified!"); + here = false; + } + } + } + } + + // Checking if -here is used + if (here){ + if (sender.isPlayer()) { + x = sender.player().getLocation().getBlockX(); + z = sender.player().getLocation().getBlockZ(); + } else { + sender.sendMessage("Specifying -here does not work from console!"); + } + } + + // Build details print + StringBuilder details = new StringBuilder("Pregeneration details:") + .append("\n") + .append(" - World > ") + .append(world.getName()) + .append("\n") + .append(" - Radius > ") + .append(width) + .append("(") + .append(width * 2) + .append(" by ") + .append(height * 2) + .append(")\n") + .append(" - Center x,z > ") + .append(x) + .append(",") + .append(z) + .append("\n") + + // Append failed args + .append(failed.isEmpty() ? "(No failed arguments)\n" : "FAILED ARGS:\n"); + for (String s : failed) { + details.append(s).append("\n"); + } + + // Start pregen and append info to details + if (pregenerate(world, width, height, x, z)){ + details.append("Successfully started pregen"); + } else { + details.append("Failed to start pregen. Doublecheck your arguments!"); + } + + // Send details + sender.sendMessage(details.toString()); + + return true; + } + + /** + * Pregenerate a + * @param world world with a + * @param width and + * @param height with center + * @param x and + * @param z coords + * @return true if successful + */ + private boolean pregenerate(World world, int width, int height, int x, int z){ + try { + IrisToolbelt.pregenerate(PregenTask + .builder() + .center(new Position2(x, z)) + .width(width >> 9 + 1) + .height(height >> 9 + 1) + .build(), world); + } catch (Throwable e){ + Iris.reportError(e); + e.printStackTrace(); + return false; + } + return true; + } + + /** + * Get the ingeger value from an argument that may contain `c` `chunks` `r` `regions` or `k`
+ * "5r" returns 5 * 512 = 2560 + * @param arg the string argument to parse into a value + * @return the integer value result + */ + private int getVal(String arg) { + + if (arg.toLowerCase().endsWith("c") || arg.toLowerCase().endsWith("chunks")) { + return Integer.parseInt(arg.toLowerCase().replaceAll("\\Qc\\E", "").replaceAll("\\Qchunks\\E", "")) * 16; + } + + if (arg.toLowerCase().endsWith("r") || arg.toLowerCase().endsWith("regions")) { + return Integer.parseInt(arg.toLowerCase().replaceAll("\\Qr\\E", "").replaceAll("\\Qregions\\E", "")) * 512; + } + + if (arg.toLowerCase().endsWith("k")) { + return Integer.parseInt(arg.toLowerCase().replaceAll("\\Qk\\E", "")) * 1000; + } + + return Integer.parseInt(arg.toLowerCase()); + } + + /** + * Checks if the + * @param arg string value + * @return is valid -> true + */ + private boolean isVal(String arg) { + try { + Integer.parseInt( + arg.toLowerCase() + .replace("chunks", "") + .replace("c", "") + .replace("regions", "") + .replace("r", "") + .replace("k", "") + ); + } catch (NumberFormatException e) { + return false; + } + return true; + } +} diff --git a/src/main/java/com/volmit/iris/core/command/pregen/CommandIrisPregenStop.java b/src/main/java/com/volmit/iris/core/command/pregen/CommandIrisPregenStop.java new file mode 100644 index 000000000..17a864730 --- /dev/null +++ b/src/main/java/com/volmit/iris/core/command/pregen/CommandIrisPregenStop.java @@ -0,0 +1,43 @@ +package com.volmit.iris.core.command.pregen; + +import com.volmit.iris.Iris; +import com.volmit.iris.core.gui.PregeneratorJob; +import com.volmit.iris.core.pregenerator.PregenTask; +import com.volmit.iris.core.pregenerator.methods.HybridPregenMethod; +import com.volmit.iris.core.tools.IrisToolbelt; +import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.math.Position2; +import com.volmit.iris.util.plugin.MortarCommand; +import com.volmit.iris.util.plugin.VolmitSender; +import org.bukkit.Bukkit; +import org.bukkit.World; + +public class CommandIrisPregenStop extends MortarCommand { + + public CommandIrisPregenStop() { + super("stop", "s", "x", "close"); + requiresPermission(Iris.perm); + setCategory("Pregen"); + setDescription("Stop an ongoing pregeneration task"); + } + + @Override + public boolean handle(VolmitSender sender, String[] args) { + if (PregeneratorJob.shutdownInstance()){ + sender.sendMessage("Stopped pregeneration task"); + } else { + sender.sendMessage("No active pregeneration tasks to stop"); + } + return true; + } + + @Override + public void addTabOptions(VolmitSender sender, String[] args, KList list) { + + } + + @Override + protected String getArgsUsage() { + return ""; + } +} diff --git a/src/main/java/com/volmit/iris/core/command/world/CommandIrisPregen.java b/src/main/java/com/volmit/iris/core/command/world/CommandIrisPregen.java deleted file mode 100644 index cd083c332..000000000 --- a/src/main/java/com/volmit/iris/core/command/world/CommandIrisPregen.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Iris is a World Generator for Minecraft Bukkit Servers - * Copyright (c) 2021 Arcane Arts (Volmit Software) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.volmit.iris.core.command.world; - -import com.volmit.iris.Iris; -import com.volmit.iris.core.gui.PregeneratorJob; -import com.volmit.iris.core.pregenerator.PregenTask; -import com.volmit.iris.core.pregenerator.methods.HybridPregenMethod; -import com.volmit.iris.core.tools.IrisToolbelt; -import com.volmit.iris.util.collection.KList; -import com.volmit.iris.util.math.Position2; -import com.volmit.iris.util.plugin.MortarCommand; -import com.volmit.iris.util.plugin.VolmitSender; -import org.bukkit.Bukkit; -import org.bukkit.World; -import org.bukkit.entity.Player; - -import java.awt.*; - -public class CommandIrisPregen extends MortarCommand { - public CommandIrisPregen() { - super("pregen", "preg", "p"); - setDescription( - """ - Pregen this world with optional parameters:\s - '1k' = 1000 * 2 by 1000 * 2 blocks, '1c' = 2 by 2 chunks, and '1r' = 64 by 64 chunks. - If you are using the console or want to pregen a world you're not in: - also specify the name of the world. E.g. /ir pregen 5k world""" - ); - requiresPermission(Iris.perm.studio); - setCategory("Pregen"); - } - - @Override - public void addTabOptions(VolmitSender sender, String[] args, KList list) { - list.add("stop"); - list.add("pause"); - list.add("resume"); - list.add("500"); - list.add("1000"); - list.add("10k"); - list.add("25k"); - list.add("10c"); - list.add("25c"); - list.add("5r"); - list.add("10r"); - for (World w : Bukkit.getServer().getWorlds()) { - list.add(w.getName()); - } - } - - @Override - public boolean handle(VolmitSender sender, String[] args) { - if (args.length == 0) { - sender.sendMessage("/iris pregen "); - return true; - } - - if (args[0].equalsIgnoreCase("stop") || args[0].equalsIgnoreCase("x")) { - if (PregeneratorJob.shutdownInstance()) { - sender.sendMessage("Stopped Pregen. Finishing last region file before shutting down..."); - } else { - sender.sendMessage("No Active Pregens."); - } - return true; - } else if (args[0].equalsIgnoreCase("pause") || args[0].equalsIgnoreCase("resume")) { - if (PregeneratorJob.getInstance() != null) { - PregeneratorJob.pauseResume(); - - if (PregeneratorJob.isPaused()) { - sender.sendMessage("Pregen Paused"); - } else { - sender.sendMessage("Pregen Resumed"); - } - } else { - sender.sendMessage("No Active Pregens"); - } - - return true; - } else if (sender.isPlayer()) { - Player p = sender.player(); - World world; - if (args.length != 2) { - world = p.getWorld(); - } else { - try { - world = Bukkit.getWorld(args[1]); - } catch (Exception e) { - Iris.reportError(e); - sender.sendMessage("Could not find specified world"); - sender.sendMessage("Please doublecheck your command. E.g. /ir pregen 5k world"); - return true; - } - } - try { - IrisToolbelt.pregenerate(PregenTask - .builder() - .center(new Position2(0, 0)) - .radius(((getVal(args[0]) >> 4) >> 5) + 1) - .build(), world); - } catch (NumberFormatException e) { - Iris.reportError(e); - sender.sendMessage("Invalid argument in command"); - return true; - } catch (NullPointerException e) { - Iris.reportError(e); - e.printStackTrace(); - sender.sendMessage("No radius specified (check error in console)"); - } catch (HeadlessException e) { - Iris.reportError(e); - sender.sendMessage("If you are seeing this and are using a hosted server, please turn off 'useServerLaunchedGUIs' in the settings"); - } - - return true; - } else { - if (args.length < 1) { - sender.sendMessage("Please specify the radius of the pregen and the name of the world. E.g. /ir pregen 5k world"); - return true; - } - if (args.length < 2) { - sender.sendMessage("Please specify the name of the world after the command. E.g. /ir pregen 5k world"); - return true; - } - World world = Bukkit.getWorld(args[1]); - try { - new PregeneratorJob(PregenTask - .builder() - .center(new Position2(0, 0)) - .radius(((getVal(args[0]) >> 4) >> 5) + 1) - .build(), - new HybridPregenMethod(world, Runtime.getRuntime().availableProcessors())); - } catch (NumberFormatException e) { - Iris.reportError(e); - sender.sendMessage("Invalid argument in command"); - return true; - } catch (NullPointerException e) { - Iris.reportError(e); - sender.sendMessage("Not all required parameters specified"); - } catch (HeadlessException e) { - Iris.reportError(e); - sender.sendMessage("If you are seeing this and are using a hosted server, please turn off 'useServerLaunchedGUIs' in the settings"); - } - - return true; - } - } - - private int getVal(String arg) { - - if (arg.toLowerCase().endsWith("c") || arg.toLowerCase().endsWith("chunks")) { - return Integer.parseInt(arg.toLowerCase().replaceAll("\\Qc\\E", "").replaceAll("\\Qchunks\\E", "")) * 16; - } - - if (arg.toLowerCase().endsWith("r") || arg.toLowerCase().endsWith("regions")) { - return Integer.parseInt(arg.toLowerCase().replaceAll("\\Qr\\E", "").replaceAll("\\Qregions\\E", "")) * 512; - } - - if (arg.toLowerCase().endsWith("k")) { - return Integer.parseInt(arg.toLowerCase().replaceAll("\\Qk\\E", "")) * 1000; - } - - return Integer.parseInt(arg.toLowerCase()); - } - - @Override - protected String getArgsUsage() { - return "[radius]"; - } -} diff --git a/src/main/java/com/volmit/iris/core/gui/PregeneratorJob.java b/src/main/java/com/volmit/iris/core/gui/PregeneratorJob.java index 801b98d6f..6757a5a7f 100644 --- a/src/main/java/com/volmit/iris/core/gui/PregeneratorJob.java +++ b/src/main/java/com/volmit/iris/core/gui/PregeneratorJob.java @@ -103,9 +103,9 @@ public class PregeneratorJob implements PregenListener { return instance; } - public static void pauseResume() { + public static boolean pauseResume() { if (instance == null) { - return; + return false; } if (isPaused()) { @@ -113,6 +113,7 @@ public class PregeneratorJob implements PregenListener { } else { instance.pregenerator.pause(); } + return true; } public static boolean isPaused() { diff --git a/src/main/java/com/volmit/iris/core/pregenerator/PregenTask.java b/src/main/java/com/volmit/iris/core/pregenerator/PregenTask.java index cc87b439d..5a1907ca3 100644 --- a/src/main/java/com/volmit/iris/core/pregenerator/PregenTask.java +++ b/src/main/java/com/volmit/iris/core/pregenerator/PregenTask.java @@ -34,12 +34,15 @@ public class PregenTask { private Position2 center = new Position2(0, 0); @Builder.Default - private int radius = 1; + private int width = 1; + + @Builder.Default + private int height = 1; private static final KList order = computeChunkOrder(); public void iterateRegions(Spiraled s) { - new Spiraler(radius * 2, radius * 2, s) + new Spiraler(getWidth() * 2, getHeight() * 2, s) .setOffset(center.getX(), center.getZ()).drain(); } @@ -50,7 +53,7 @@ public class PregenTask { } public void iterateAllChunks(Spiraled s) { - new Spiraler(radius * 2, radius * 2, (x, z) -> iterateRegion(x, z, s)) + new Spiraler(getWidth() * 2, getHeight() * 2, (x, z) -> iterateRegion(x, z, s)) .setOffset(center.getX(), center.getZ()).drain(); }