From 669ede5482cca03d6f5f410b3b105e623ae0cbeb Mon Sep 17 00:00:00 2001 From: RePixelatedMC Date: Sun, 14 Jan 2024 10:18:41 +0100 Subject: [PATCH 1/8] remove turbo for now --- .../src/main/java/com/volmit/iris/core/commands/CommandIris.java | 1 - 1 file changed, 1 deletion(-) 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 2470d0efa..3601b3f11 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,7 +72,6 @@ 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; From 1740bb0021c9544a47d465bdd664b306ed41f107 Mon Sep 17 00:00:00 2001 From: RePixelatedMC Date: Sun, 14 Jan 2024 16:35:00 +0100 Subject: [PATCH 2/8] whoop --- .../main/java/com/volmit/iris/core/safeguard/ServerBootSFG.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 46dda64d7..b2945e010 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 @@ -97,7 +97,7 @@ public class ServerBootSFG { } if (!hasPrivileges()){ - hasPrivileges = true; + hasPrivileges = false; joiner.add("Insufficient Privileges"); severityMedium++; } From bad547356c42069fe4ffd7635b2d61626f6c1167 Mon Sep 17 00:00:00 2001 From: RePixelatedMC Date: Sun, 14 Jan 2024 16:43:39 +0100 Subject: [PATCH 3/8] Disabled for now --- .../iris/core/safeguard/ServerBootSFG.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) 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 b2945e010..caa1f05ce 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 @@ -148,15 +148,16 @@ public class ServerBootSFG { } public static boolean hasPrivileges() { - 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) { - return false; - } - return false; + 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) { +// return false; +// } +// return false; } public static boolean enoughDiskSpace() { From 5a4a86aebaef66f46d499557f2c206a80716f39d Mon Sep 17 00:00:00 2001 From: RePixelatedMC <107539181+RePixelatedMC@users.noreply.github.com> Date: Fri, 19 Apr 2024 10:14:16 +0200 Subject: [PATCH 4/8] - Iris Updater Updates chunks thats it/ --- build.gradle | 2 + .../iris/core/commands/CommandIris.java | 20 ++++ .../iris/core/pregenerator/ChunkUpdater.java | 91 ++++++++++++++++--- 3 files changed, 100 insertions(+), 13 deletions(-) diff --git a/build.gradle b/build.gradle index 90fe9be65..0f7f8c7d5 100644 --- a/build.gradle +++ b/build.gradle @@ -237,6 +237,8 @@ allprojects { implementation "net.kyori:adventure-text-minimessage:4.13.1" implementation 'net.kyori:adventure-platform-bukkit:4.3.2' implementation 'net.kyori:adventure-api:4.13.1' + //implementation 'org.bytedeco:javacpp:1.5.10' + //implementation 'org.bytedeco:cuda-platform:12.3-8.9-1.5.10' compileOnly 'io.lumine:Mythic-Dist:5.2.1' // Dynamically Loaded 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 6ec02ef7f..c7f204a52 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 @@ -21,6 +21,7 @@ package com.volmit.iris.core.commands; import com.volmit.iris.Iris; import com.volmit.iris.core.IrisSettings; import com.volmit.iris.core.loader.IrisData; +import com.volmit.iris.core.pregenerator.ChunkUpdater; import com.volmit.iris.core.service.StudioSVC; import com.volmit.iris.core.tools.IrisBenchmarking; import com.volmit.iris.core.tools.IrisToolbelt; @@ -37,6 +38,7 @@ import com.volmit.iris.util.decree.annotations.Decree; import com.volmit.iris.util.decree.annotations.Param; import com.volmit.iris.util.decree.specialhandlers.NullablePlayerHandler; import com.volmit.iris.util.format.C; +import com.volmit.iris.util.format.Form; import com.volmit.iris.util.plugin.VolmitSender; import com.volmit.iris.util.scheduling.J; import lombok.Getter; @@ -317,6 +319,24 @@ public class CommandIris implements DecreeExecutor { return dir.delete(); } + @Decree(description = "Updates all chunk in the specified world") + public void updater( + @Param(description = "World to update chunks at") + World world + ) { + if (!IrisToolbelt.isIrisWorld(world)) { + sender().sendMessage(C.GOLD + "This is not an Iris world"); + return; + } + ChunkUpdater updater = new ChunkUpdater(world); + if (sender().isPlayer()) { + sender().sendMessage(C.GREEN + "Updating " + world.getName() + " Total chunks: " + Form.f(updater.getChunks())); + } else { + Iris.info(C.GREEN + "Updating " + world.getName() + " Total chunks: " + Form.f(updater.getChunks())); + } + updater.start(); + } + @Decree(description = "Set aura spins") public void aura( @Param(description = "The h color value", defaultValue = "-20") diff --git a/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java b/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java index 1e40ab566..c9c32726a 100644 --- a/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java +++ b/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java @@ -1,18 +1,27 @@ package com.volmit.iris.core.pregenerator; import com.volmit.iris.Iris; +import com.volmit.iris.core.tools.IrisToolbelt; +import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.format.Form; +import com.volmit.iris.util.math.M; import com.volmit.iris.util.math.RollingSequence; import com.volmit.iris.util.math.Spiraler; -import com.volmit.iris.util.nbt.mca.MCAFile; -import com.volmit.iris.util.nbt.mca.MCAUtil; +import io.papermc.lib.PaperLib; +import org.bukkit.Chunk; import org.bukkit.World; import java.io.File; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; public class ChunkUpdater { private AtomicBoolean cancelled; @@ -25,12 +34,19 @@ public class ChunkUpdater { private final AtomicInteger totalMaxChunks; private final AtomicInteger totalMcaregions; private final AtomicInteger position; + private AtomicInteger chunksProcessed; + private AtomicInteger chunksUpdated; + private AtomicLong startTime; + private ExecutorService executor; + private ScheduledExecutorService scheduler; private final File[] McaFiles; + private final Engine engine; private final World world; public ChunkUpdater(World world) { File cacheDir = new File("plugins" + File.separator + "iris" + File.separator + "cache"); File chunkCacheDir = new File("plugins" + File.separator + "iris" + File.separator + "cache" + File.separator + "spiral"); + this.engine = IrisToolbelt.access(world).getEngine(); this.chunksPerSecond = new RollingSequence(10); this.mcaregionsPerSecond = new RollingSequence(10); this.world = world; @@ -38,33 +54,82 @@ public class ChunkUpdater { this.McaFiles = new File(world.getWorldFolder(), "region").listFiles((dir, name) -> name.endsWith(".mca")); this.worldheightsize = new AtomicInteger(calculateWorldDimensions(new File(world.getWorldFolder(), "region"), 1)); this.worldwidthsize = new AtomicInteger(calculateWorldDimensions(new File(world.getWorldFolder(), "region"), 0)); - this.totalMaxChunks = new AtomicInteger((worldheightsize.get() / 16 ) * (worldwidthsize.get() / 16)); + int m = Math.max(worldheightsize.get(), worldwidthsize.get()); + this.executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() - 2); + this.scheduler = Executors.newScheduledThreadPool(1); + this.startTime = new AtomicLong(); + this.worldheightsize.set(m); + this.worldwidthsize.set(m); + this.totalMaxChunks = new AtomicInteger((worldheightsize.get() / 16) * (worldwidthsize.get() / 16)); + this.chunksProcessed = new AtomicInteger(); + this.chunksUpdated = new AtomicInteger(); this.position = new AtomicInteger(0); this.cancelled = new AtomicBoolean(false); this.totalChunks = new AtomicInteger(0); this.totalMcaregions = new AtomicInteger(0); } - public void start() { - Initialize(); + public int getChunks() { + return totalMaxChunks.get(); } - public void Initialize() { - Iris.info("Initializing.."); + public void start() { + update(); + } + + + private void update() { + Iris.info("Updating.."); try { - for (File mca : McaFiles) { - MCAFile MCARegion = MCAUtil.read(mca); - for (int pos = 0; pos != totalMaxChunks.get(); pos++) { - int[] coords = getChunk(pos); - if(MCARegion.hasChunk(coords[0], coords[1])) chunkMap.add(coords); + startTime.set(System.currentTimeMillis()); + scheduler.scheduleAtFixedRate(() -> { + try { + long eta = computeETA(); + long elapsedSeconds = (System.currentTimeMillis() - startTime.get()) / 1000; + int processed = chunksProcessed.get(); + double cps = elapsedSeconds > 0 ? processed / (double) elapsedSeconds : 0; + chunksPerSecond.put(cps); + double percentage = ((double) chunksProcessed.get() / (double) totalMaxChunks.get()) * 100; + Iris.info("Updated: " + Form.f(processed) + " of : " + Form.f(totalMaxChunks.get()) + " (%.0f%%) " + Form.f(chunksPerSecond.getAverage()) + "/s, ETA: " + Form.duration(eta, 2), percentage); + } catch (Exception e) { + e.printStackTrace(); } + }, 0, 3, TimeUnit.SECONDS); + + for (int i = 0; i < totalMaxChunks.get(); i++) { + executor.submit(this::processNextChunk); } - Iris.info("Finished Initializing.."); + + executor.shutdown(); + executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); + scheduler.shutdownNow(); + Iris.info("Processed: " + Form.f(chunksProcessed.get()) + " Chunks"); + Iris.info("Finished Updating: " + Form.f(chunksUpdated.get()) + " Chunks"); } catch (Exception e) { e.printStackTrace(); } } + private void processNextChunk() { + int pos = position.getAndIncrement(); + int[] coords = getChunk(pos); + if (PaperLib.isChunkGenerated(world, coords[0], coords[1])) { + Chunk chunk = world.getChunkAt(coords[0], coords[1]); + engine.updateChunk(chunk); + chunksUpdated.getAndIncrement(); + } + chunksProcessed.getAndIncrement(); + } + + private long computeETA() { + return (long) (totalMaxChunks.get() > 1024 ? // Generated chunks exceed 1/8th of total? + // If yes, use smooth function (which gets more accurate over time since its less sensitive to outliers) + ((totalMaxChunks.get() - chunksProcessed.get()) * ((double) (M.ms() - startTime.get()) / (double) chunksProcessed.get())) : + // If no, use quick function (which is less accurate over time but responds better to the initial delay) + ((totalMaxChunks.get() - chunksProcessed.get()) / chunksPerSecond.getAverage()) * 1000 + ); + } + public int calculateWorldDimensions(File regionDir, Integer o) { File[] files = regionDir.listFiles((dir, name) -> name.endsWith(".mca")); From 9175296fc6974cdc81a8062c3a6ea7f2805238be Mon Sep 17 00:00:00 2001 From: RePixelatedMC <107539181+RePixelatedMC@users.noreply.github.com> Date: Fri, 19 Apr 2024 12:43:57 +0200 Subject: [PATCH 5/8] rev2.0 --- .../iris/core/pregenerator/ChunkUpdater.java | 86 ++++++++++++++++--- 1 file changed, 75 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java b/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java index c9c32726a..0e783d4c7 100644 --- a/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java +++ b/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java @@ -4,28 +4,30 @@ import com.volmit.iris.Iris; import com.volmit.iris.core.tools.IrisToolbelt; import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.format.Form; import com.volmit.iris.util.math.M; import com.volmit.iris.util.math.RollingSequence; import com.volmit.iris.util.math.Spiraler; +import com.volmit.iris.util.reflect.V; +import com.volmit.iris.util.scheduling.J; import io.papermc.lib.PaperLib; +import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.World; import java.io.File; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; +import java.util.ArrayList; +import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; public class ChunkUpdater { private AtomicBoolean cancelled; - private KList chunkMap; + private KMap lastUse; private final RollingSequence chunksPerSecond; private final RollingSequence mcaregionsPerSecond; private final AtomicInteger worldheightsize; @@ -50,7 +52,7 @@ public class ChunkUpdater { this.chunksPerSecond = new RollingSequence(10); this.mcaregionsPerSecond = new RollingSequence(10); this.world = world; - this.chunkMap = new KList<>(); + this.lastUse = new KMap(); this.McaFiles = new File(world.getWorldFolder(), "region").listFiles((dir, name) -> name.endsWith(".mca")); this.worldheightsize = new AtomicInteger(calculateWorldDimensions(new File(world.getWorldFolder(), "region"), 1)); this.worldwidthsize = new AtomicInteger(calculateWorldDimensions(new File(world.getWorldFolder(), "region"), 0)); @@ -74,6 +76,7 @@ public class ChunkUpdater { } public void start() { + unloadAndSaveAllChunks(); update(); } @@ -90,7 +93,7 @@ public class ChunkUpdater { double cps = elapsedSeconds > 0 ? processed / (double) elapsedSeconds : 0; chunksPerSecond.put(cps); double percentage = ((double) chunksProcessed.get() / (double) totalMaxChunks.get()) * 100; - Iris.info("Updated: " + Form.f(processed) + " of : " + Form.f(totalMaxChunks.get()) + " (%.0f%%) " + Form.f(chunksPerSecond.getAverage()) + "/s, ETA: " + Form.duration(eta, 2), percentage); + Iris.info("Updated: " + Form.f(processed) + " of " + Form.f(totalMaxChunks.get()) + " (%.0f%%) " + Form.f(chunksPerSecond.getAverage()) + "/s, ETA: " + Form.duration(eta, 2), percentage); } catch (Exception e) { e.printStackTrace(); } @@ -113,14 +116,75 @@ public class ChunkUpdater { private void processNextChunk() { int pos = position.getAndIncrement(); int[] coords = getChunk(pos); - if (PaperLib.isChunkGenerated(world, coords[0], coords[1])) { - Chunk chunk = world.getChunkAt(coords[0], coords[1]); - engine.updateChunk(chunk); - chunksUpdated.getAndIncrement(); + if (areAllChunksGenerated(coords[0], coords[1])) { + CompletableFuture chunkFuture = loadChunksIfGenerated(coords[0], coords[1]); + chunkFuture.thenAccept(chunk -> { + Chunk c = world.getChunkAt(coords[0], coords[1]); + engine.updateChunk(c); + chunksUpdated.getAndIncrement(); + }); } chunksProcessed.getAndIncrement(); } + private boolean areAllChunksGenerated(int x, int z) { + for (int dx = -1; dx <= 1; dx++) { + for (int dz = -1; dz <= 1; dz++) { + if (!PaperLib.isChunkGenerated(world, x + dx, z + dz)) { + return false; + } + } + } + return true; + } + + private CompletableFuture loadChunksIfGenerated(int x, int z) { + CompletableFuture future = new CompletableFuture<>(); + if (areAllChunksGenerated(x, z)) { + Runnable task = () -> { + try { + for (int dx = -1; dx <= 1; dx++) { + for (int dz = -1; dz <= 1; dz++) { + Chunk c = world.getChunkAt(x + dx, z + dz); + world.loadChunk(c); + lastUse.put(c, M.ms()); + } + } + future.complete(null); + } catch (Exception e) { + future.completeExceptionally(e); + } + }; + Bukkit.getScheduler().runTask(Iris.instance, task); + } else { + future.completeExceptionally(new IllegalStateException("Not all chunks are generated")); + } + return future; + } + + + private void unloadAndSaveAllChunks() { + try { + J.sfut(() -> { + if (world == null) { + Iris.warn("World was null somehow..."); + return; + } + + for (Chunk i : new ArrayList<>(lastUse.keySet())) { + Long lastUseTime = lastUse.get(i); + if (lastUseTime != null && M.ms() - lastUseTime >= 5000) { + i.unload(); + lastUse.remove(i); + } + } + world.save(); + }).get(); + } catch (Throwable e) { + e.printStackTrace(); + } + } + private long computeETA() { return (long) (totalMaxChunks.get() > 1024 ? // Generated chunks exceed 1/8th of total? // If yes, use smooth function (which gets more accurate over time since its less sensitive to outliers) From 9a45e0df108ffb29e04f7a109b21f4cd065bfbcf Mon Sep 17 00:00:00 2001 From: RePixelatedMC <107539181+RePixelatedMC@users.noreply.github.com> Date: Fri, 19 Apr 2024 15:15:08 +0200 Subject: [PATCH 6/8] /iris support report ( gives server info ) and cleaned the main splash screen and fixed /iris import saying its loaded successfully even if it didnt --- core/src/main/java/com/volmit/iris/Iris.java | 31 +--- .../iris/core/commands/CommandIris.java | 2 + .../iris/core/commands/CommandSupport.java | 82 ++++++++++ .../iris/core/tools/IrisBenchmarking.java | 5 +- .../com/volmit/iris/util/misc/Hastebin.java | 135 ++++++++++++++++ .../com/volmit/iris/util/misc/Platform.java | 145 +++++++++++++++++ .../volmit/iris/util/misc/getHardware.java | 152 ++++++++++++++++-- 7 files changed, 506 insertions(+), 46 deletions(-) create mode 100644 core/src/main/java/com/volmit/iris/core/commands/CommandSupport.java create mode 100644 core/src/main/java/com/volmit/iris/util/misc/Hastebin.java create mode 100644 core/src/main/java/com/volmit/iris/util/misc/Platform.java diff --git a/core/src/main/java/com/volmit/iris/Iris.java b/core/src/main/java/com/volmit/iris/Iris.java index 9fec3b7e8..950913796 100644 --- a/core/src/main/java/com/volmit/iris/Iris.java +++ b/core/src/main/java/com/volmit/iris/Iris.java @@ -806,9 +806,6 @@ public class Iris extends VolmitPlugin implements Listener { } else { splash = splashstable; } - OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean(); - String osArch = osBean.getArch(); - String osName = osBean.getName(); if (!passedserversoftware) { Iris.info("Server type & version: " + C.RED + Bukkit.getVersion()); @@ -821,35 +818,9 @@ public class Iris extends VolmitPlugin implements Listener { Iris.info(C.YELLOW + "Purpur is recommended to use with iris."); } } - Iris.info("Server OS: " + osName + " (" + osArch + ")"); - - try { - if (warningmode){ - Iris.info("Server Cpu: " + C.GOLD + getCPUModel()); - } else { - if(unstablemode){ - Iris.info("Server Cpu: " + C.DARK_RED + getCPUModel()); - } else { - if (getCPUModel().contains("Intel")) { - Iris.info("Server Cpu: " + C.BLUE + getCPUModel()); - } - if (getCPUModel().contains("Ryzen")) { - Iris.info("Server Cpu: " + C.RED + getCPUModel()); - } - if (!getCPUModel().contains("Ryzen") && !getCPUModel().contains("Intel")) { - Iris.info("Server Cpu: " + C.GRAY + getCPUModel()); - } - } - } - } catch (Exception e){ - Iris.info("Server Cpu: " + C.DARK_RED + "Failed"); - } - - Iris.info("Process Threads: " + Runtime.getRuntime().availableProcessors()); - Iris.info("Process Memory: " + getHardware.getProcessMemory() + " MB"); - Iris.info("Free DiskSpace: " + Form.ofSize(freeSpace.getFreeSpace(), 1024)); if (getHardware.getProcessMemory() < 5999) { Iris.warn("6GB+ Ram is recommended"); + Iris.warn("Process Memory: " + getHardware.getProcessMemory() + " MB"); } Iris.info("Bukkit version: " + Bukkit.getBukkitVersion()); Iris.info("Custom Biomes: " + INMS.get().countCustomBiomes()); 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 c7f204a52..ad77d9268 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 @@ -78,6 +78,7 @@ public class CommandIris implements DecreeExecutor { private CommandWhat what; private CommandEdit edit; private CommandFind find; + private CommandSupport support; private CommandDeveloper developer; public static boolean worldCreation = false; String WorldEngine; @@ -532,6 +533,7 @@ public class CommandIris implements DecreeExecutor { } catch (IOException e) { Iris.error("Failed to update bukkit.yml!"); e.printStackTrace(); + return; } } checkForBukkitWorlds(world); diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandSupport.java b/core/src/main/java/com/volmit/iris/core/commands/CommandSupport.java new file mode 100644 index 000000000..0f7baad0d --- /dev/null +++ b/core/src/main/java/com/volmit/iris/core/commands/CommandSupport.java @@ -0,0 +1,82 @@ +/* + * 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.loader.IrisData; +import com.volmit.iris.core.pregenerator.ChunkUpdater; +import com.volmit.iris.core.service.IrisEngineSVC; +import com.volmit.iris.core.tools.IrisPackBenchmarking; +import com.volmit.iris.core.tools.IrisToolbelt; +import com.volmit.iris.engine.framework.Engine; +import com.volmit.iris.engine.object.IrisDimension; +import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.decree.DecreeExecutor; +import com.volmit.iris.util.decree.DecreeOrigin; +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.format.Form; +import com.volmit.iris.util.io.IO; +import com.volmit.iris.util.mantle.TectonicPlate; +import com.volmit.iris.util.misc.Hastebin; +import com.volmit.iris.util.misc.Platform; +import com.volmit.iris.util.misc.getHardware; +import com.volmit.iris.util.nbt.mca.MCAFile; +import com.volmit.iris.util.nbt.mca.MCAUtil; +import com.volmit.iris.util.plugin.VolmitSender; +import net.jpountz.lz4.LZ4BlockInputStream; +import net.jpountz.lz4.LZ4BlockOutputStream; +import net.jpountz.lz4.LZ4FrameInputStream; +import net.jpountz.lz4.LZ4FrameOutputStream; +import org.apache.commons.lang.RandomStringUtils; +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.World; +import oshi.SystemInfo; + +import java.io.*; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +@Decree(name = "Support", origin = DecreeOrigin.BOTH, description = "Iris World Manager", aliases = {"support"}) +public class CommandSupport implements DecreeExecutor { + + @Decree(description = "report") + public void report() { + try { + if (sender().isPlayer()) sender().sendMessage(C.GOLD + "Creating report.."); + if (!sender().isPlayer()) Iris.info(C.GOLD + "Creating report.."); + Hastebin.enviornment(sender()); + + } catch (Exception e) { + Iris.info(C.RED + "Something went wrong: "); + e.printStackTrace(); + } + } + + +} + + diff --git a/core/src/main/java/com/volmit/iris/core/tools/IrisBenchmarking.java b/core/src/main/java/com/volmit/iris/core/tools/IrisBenchmarking.java index 300a4467f..79bf1b643 100644 --- a/core/src/main/java/com/volmit/iris/core/tools/IrisBenchmarking.java +++ b/core/src/main/java/com/volmit/iris/core/tools/IrisBenchmarking.java @@ -28,7 +28,6 @@ import java.io.InputStreamReader; import static com.google.common.math.LongMath.isPrime; import static com.volmit.iris.util.misc.getHardware.getCPUModel; -import static com.volmit.iris.util.misc.getHardware.getDiskModel; public class IrisBenchmarking { static String ServerOS; static String filePath = "benchmark.dat"; @@ -180,12 +179,12 @@ public class IrisBenchmarking { Iris.info("- Data Compression: " + formatDouble(calculateDataCompression) + " MBytes/Sec"); if (WindowsDiskSpeed) { - Iris.info("Disk Model: " + getDiskModel()); + //Iris.info("Disk Model: " + getDiskModel()); Iris.info(C.BLUE + "- Running with Windows System Assessment Tool"); Iris.info("- Sequential 64.0 Write: " + C.BLUE + formatDouble(avgWriteSpeedMBps) + " Mbps"); Iris.info("- Sequential 64.0 Read: " + C.BLUE + formatDouble(avgReadSpeedMBps) + " Mbps"); } else { - Iris.info("Disk Model: " + getDiskModel()); + // Iris.info("Disk Model: " + getDiskModel()); Iris.info(C.GREEN + "- Running in Native Mode"); Iris.info("- Average Write Speed: " + C.GREEN + formatDouble(avgWriteSpeedMBps) + " Mbps"); Iris.info("- Average Read Speed: " + C.GREEN + formatDouble(avgReadSpeedMBps) + " Mbps"); diff --git a/core/src/main/java/com/volmit/iris/util/misc/Hastebin.java b/core/src/main/java/com/volmit/iris/util/misc/Hastebin.java new file mode 100644 index 000000000..11e253b31 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/util/misc/Hastebin.java @@ -0,0 +1,135 @@ +package com.volmit.iris.util.misc; + +import com.volmit.iris.Iris; +import com.volmit.iris.core.tools.IrisToolbelt; +import com.volmit.iris.engine.framework.Engine; +import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.format.C; +import com.volmit.iris.util.format.Form; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.command.CommandSender; +import oshi.SystemInfo; + +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.File; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.file.Files; +import java.util.List; + +public class Hastebin { + + public static void enviornment(CommandSender sender) { + // Construct the server information + StringBuilder sb = new StringBuilder(); + SystemInfo systemInfo = new SystemInfo(); + KList disks = new KList<>(getHardware.getDisk()); + KList interfaces = new KList<>(getHardware.getInterfaces()); + KList displays = new KList<>(getHardware.getEDID()); + KList sensors = new KList<>(getHardware.getSensors()); + KList gpus = new KList<>(getHardware.getGraphicsCards()); + KList powersources = new KList<>(getHardware.getPowerSources()); + + KList IrisWorlds = new KList<>(); + KList BukkitWorlds = new KList<>(); + + for (World w : Bukkit.getServer().getWorlds()) { + try { + Engine engine = IrisToolbelt.access(w).getEngine(); + if (engine != null) { + IrisWorlds.add(w); + } + } catch (Exception e) { + BukkitWorlds.add(w); + } + } + + sb.append(" -- == Iris Info == -- \n"); + sb.append("Iris Version Version: ").append(Iris.instance.getDescription().getVersion()).append("\n"); + sb.append("- Iris Worlds"); + for (World w : IrisWorlds.copy()) { + sb.append(" - ").append(w.getName()); + } + sb.append("- Bukkit Worlds"); + for (World w : BukkitWorlds.copy()) { + sb.append(" - ").append(w.getName()); + } + sb.append(" -- == Platform Overview == -- " + "\n"); + sb.append("Server Type: ").append(Bukkit.getVersion()).append("\n"); + sb.append("Server Uptime: ").append(Form.stampTime(systemInfo.getOperatingSystem().getSystemUptime())).append("\n"); + sb.append("Version: ").append(Platform.getVersion()).append(" - Platform: ").append(Platform.getName()).append("\n"); + sb.append("Java Vendor: ").append(Platform.ENVIRONMENT.getJavaVendor()).append(" - Java Version: ").append(Platform.ENVIRONMENT.getJavaVersion()).append("\n"); + sb.append(" -- == Processor Overview == -- " + "\n"); + sb.append("CPU Model: ").append(getHardware.getCPUModel()); + sb.append("CPU Architecture: ").append(Platform.CPU.getArchitecture()).append(" Available Processors: ").append(Platform.CPU.getAvailableProcessors()).append("\n"); + sb.append("CPU Load: ").append(Form.pc(Platform.CPU.getCPULoad())).append(" CPU Live Process Load: ").append(Form.pc(Platform.CPU.getLiveProcessCPULoad())).append("\n"); + sb.append("-=" + " Graphics " + "=- " + "\n"); + for (String gpu : gpus) { + sb.append(" ").append(gpu).append("\n"); + } + sb.append(" -- == Memory Information == -- " + "\n"); + sb.append("Physical Memory - Total: ").append(Form.memSize(Platform.MEMORY.PHYSICAL.getTotalMemory())).append(" Free: ").append(Form.memSize(Platform.MEMORY.PHYSICAL.getFreeMemory())).append(" Used: ").append(Form.memSize(Platform.MEMORY.PHYSICAL.getUsedMemory())).append("\n"); + sb.append("Virtual Memory - Total: ").append(Form.memSize(Platform.MEMORY.VIRTUAL.getTotalMemory())).append(" Free: ").append(Form.memSize(Platform.MEMORY.VIRTUAL.getFreeMemory())).append(" Used: ").append(Form.memSize(Platform.MEMORY.VIRTUAL.getUsedMemory())).append("\n"); + sb.append(" -- == Storage Information == -- " + "\n"); + for (String disk : disks) { + sb.append(" ").append(sb.append(disk)).append("\n"); + } + sb.append(" -- == Interface Information == -- "+ "\n" ); + for (String inter : interfaces) { + sb.append(" ").append(inter).append("\n"); + } + sb.append(" -- == Display Information == -- "+ "\n" ); + for (String display : displays) { + sb.append(display).append("\n"); + } + sb.append(" -- == Sensor Information == -- " + "\n"); + for (String sensor : sensors) { + sb.append(" ").append(sensor).append("\n"); + } + sb.append(" -- == Power Information == -- " + "\n"); + for (String power : powersources) { + sb.append(" ").append(power).append("\n"); + } + + try { + String hastebinUrl = uploadToHastebin(sb.toString()); + + // Create the clickable message + TextComponent message = new TextComponent("[Link]"); + TextComponent link = new TextComponent(hastebinUrl); + link.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, hastebinUrl)); + message.addExtra(link); + + // Send the clickable message to the player + sender.spigot().sendMessage(message); + } catch (Exception e) { + sender.sendMessage(C.DARK_RED + "Failed to upload server information to Hastebin."); + } + } + + private static String uploadToHastebin(String content) throws Exception { + URL url = new URL("https://paste.bytecode.ninja/documents"); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("POST"); + conn.setRequestProperty("Content-Type", "text/plain"); + conn.setDoOutput(true); + + DataOutputStream wr = new DataOutputStream(conn.getOutputStream()); + wr.writeBytes(content); + wr.flush(); + wr.close(); + + BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String response = br.readLine(); + br.close(); + + return "https://paste.bytecode.ninja/" + response.split("\"")[3]; + } + + +} \ No newline at end of file diff --git a/core/src/main/java/com/volmit/iris/util/misc/Platform.java b/core/src/main/java/com/volmit/iris/util/misc/Platform.java new file mode 100644 index 000000000..afbf7c8c3 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/util/misc/Platform.java @@ -0,0 +1,145 @@ +package com.volmit.iris.util.misc; + +import com.sun.management.OperatingSystemMXBean; + +import java.io.File; +import java.lang.management.ManagementFactory; + +@SuppressWarnings("restriction") +public class Platform { + public static String getVersion() { + return getSystem().getVersion(); + } + + public static String getName() { + return getSystem().getName(); + } + + private static OperatingSystemMXBean getSystem() { + return (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); + } + + public static class ENVIRONMENT { + public static boolean canRunBatch() { + return getSystem().getName().toLowerCase().contains("windows"); + } + + public static String getJavaHome() { + return System.getProperty("java.home"); + } + + public static String getJavaVendor() { + return System.getProperty("java.vendor"); + } + + public static String getJavaVersion() { + return System.getProperty("java.version"); + } + } + + public static class STORAGE { + public static long getAbsoluteTotalSpace() { + long t = 0; + + for (File i : getRoots()) { + t += getTotalSpace(i); + } + + return t; + } + + public static long getTotalSpace() { + return getTotalSpace(new File(".")); + } + + public static long getTotalSpace(File root) { + return root.getTotalSpace(); + } + + public static long getAbsoluteFreeSpace() { + long t = 0; + + for (File i : getRoots()) { + t += getFreeSpace(i); + } + + return t; + } + + public static long getFreeSpace() { + return getFreeSpace(new File(".")); + } + + public static long getFreeSpace(File root) { + return root.getFreeSpace(); + } + + public static long getUsedSpace() { + return getTotalSpace() - getFreeSpace(); + } + + public static long getUsedSpace(File root) { + return getTotalSpace(root) - getFreeSpace(root); + } + + public static long getAbsoluteUsedSpace() { + return getAbsoluteTotalSpace() - getAbsoluteFreeSpace(); + } + + public static File[] getRoots() { + return File.listRoots(); + } + } + + public static class MEMORY { + public static class PHYSICAL { + public static long getTotalMemory() { + return getSystem().getTotalPhysicalMemorySize(); + } + + public static long getFreeMemory() { + return getSystem().getFreePhysicalMemorySize(); + } + + public static long getUsedMemory() { + return getTotalMemory() - getFreeMemory(); + } + } + + public static class VIRTUAL { + public static long getTotalMemory() { + return getSystem().getTotalSwapSpaceSize(); + } + + public static long getFreeMemory() { + return getSystem().getFreeSwapSpaceSize(); + } + + public static long getUsedMemory() { + return getTotalMemory() - getFreeMemory(); + } + + public static long getCommittedVirtualMemory() { + return getSystem().getCommittedVirtualMemorySize(); + } + } + } + + public static class CPU { + public static int getAvailableProcessors() { + return getSystem().getAvailableProcessors(); + } + + public static double getCPULoad() { + return getSystem().getSystemCpuLoad(); + } + + public static double getLiveProcessCPULoad() { + return getSystem().getProcessCpuLoad(); + } + + public static String getArchitecture() { + return getSystem().getArch(); + } + } +} \ No newline at end of file diff --git a/core/src/main/java/com/volmit/iris/util/misc/getHardware.java b/core/src/main/java/com/volmit/iris/util/misc/getHardware.java index 0b9a52033..0e494e27c 100644 --- a/core/src/main/java/com/volmit/iris/util/misc/getHardware.java +++ b/core/src/main/java/com/volmit/iris/util/misc/getHardware.java @@ -1,11 +1,24 @@ package com.volmit.iris.util.misc; -import oshi.SystemInfo; -import oshi.hardware.CentralProcessor; -import oshi.hardware.HWDiskStore; -import oshi.software.os.OperatingSystem; +import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.format.C; +import com.volmit.iris.util.format.Form; +import org.jetbrains.annotations.Nullable; +import oshi.SystemInfo; +import oshi.hardware.*; +import oshi.software.os.FileSystem; +import oshi.software.os.OSFileStore; +import oshi.software.os.OperatingSystem; +import oshi.util.EdidUtil; + +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; import java.util.List; +import java.util.stream.Collectors; public class getHardware { public static String getServerOS() { @@ -44,14 +57,127 @@ public class getHardware { } } - public static String getDiskModel() { - SystemInfo systemInfo = new SystemInfo(); - List diskStores = systemInfo.getHardware().getDiskStores(); - if (!diskStores.isEmpty()) { - HWDiskStore firstDisk = diskStores.get(0); - return firstDisk.getModel(); - } else { - return "Unknown Disk Model"; + public static KList getSensors() { + try { + KList temps = new KList<>(); + SystemInfo systemInfo = new SystemInfo(); + temps.add("CPU Temperature: " + systemInfo.getHardware().getSensors().getCpuTemperature()); + temps.add("CPU Voltage: " + systemInfo.getHardware().getSensors().getCpuTemperature()); + temps.add("Fan Speeds: " + Arrays.toString(systemInfo.getHardware().getSensors().getFanSpeeds())); + return temps.copy(); + } catch (Exception e) { + e.printStackTrace(); } + return null; } -} + + public static KList getGraphicsCards() { + try { + KList gpus = new KList<>(); + SystemInfo systemInfo = new SystemInfo(); + for (GraphicsCard gpu : systemInfo.getHardware().getGraphicsCards()) { + gpus.add(C.BLUE + "Gpu Model: " + C.GRAY + gpu.getName()); + gpus.add("- vRam Size: " + C.GRAY + Form.memSize(gpu.getVRam())); + gpus.add("- Vendor: " + C.GRAY + gpu.getVendor()); + } + return gpus.copy(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static KList getDisk() { + try { + KList systemDisks = new KList<>(); + SystemInfo systemInfo = new SystemInfo(); + List diskStores = systemInfo.getHardware().getDiskStores(); + OperatingSystem operatingSystem = systemInfo.getOperatingSystem(); + List fileStores = operatingSystem.getFileSystem().getFileStores(); + + for (HWDiskStore disk : diskStores) { + systemDisks.add(C.BLUE + "Disk: " + disk.getName()); + systemDisks.add("- Model: " + disk.getModel()); + systemDisks.add("Partitions: " + disk.getPartitions()); + for (OSFileStore partition : fileStores) { + systemDisks.add(C.BLUE + "- Name: " + partition.getName()); + systemDisks.add(" - Description: " + partition.getDescription()); + systemDisks.add(" - Total Space: " + Form.memSize(partition.getTotalSpace())); + systemDisks.add(" - Free Space: " + Form.memSize(partition.getFreeSpace())); + systemDisks.add(" - Mount: " + partition.getMount()); + systemDisks.add(" - Label: " + partition.getLabel()); + } + systemDisks.add(C.DARK_GRAY + "-=" + C.BLUE +" Since Boot " + C.DARK_GRAY + "=- "); + systemDisks.add("- Total Reads: " + Form.memSize(disk.getReadBytes())); + systemDisks.add("- Total Writes: " + Form.memSize(disk.getWriteBytes())); + } + if (systemDisks.isEmpty()) { + systemDisks.add("Failed to get disks."); + } + return systemDisks.copy(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static KList getPowerSources() { + try { + KList systemPowerSources = new KList<>(); + SystemInfo systemInfo = new SystemInfo(); + List powerSources = systemInfo.getHardware().getPowerSources(); + for (PowerSource powersource : powerSources) { + systemPowerSources.add(C.BLUE + "- Name: " + powersource.getName()); + systemPowerSources.add("- RemainingCapacityPercent: " + powersource.getRemainingCapacityPercent()); + systemPowerSources.add("- Power Usage Rate: " + powersource.getPowerUsageRate()); + systemPowerSources.add("- Power OnLine: " + powersource.isPowerOnLine()); + systemPowerSources.add("- Capacity Units: " + powersource.getCapacityUnits()); + systemPowerSources.add("- Cycle Count: " + powersource.getCycleCount()); + } + if (systemPowerSources.isEmpty()) { + systemPowerSources.add("No PowerSources."); + } + return systemPowerSources.copy(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static KList getEDID() { + try { + KList systemEDID = new KList<>(); + SystemInfo systemInfo = new SystemInfo(); + HardwareAbstractionLayer hardware = systemInfo.getHardware(); + List displays = hardware.getDisplays(); + for (Display display : displays) { + systemEDID.add("Display: " + display.getEdid()); + } + if (!systemEDID.isEmpty()) { + systemEDID.add("No displays"); + } + return systemEDID.copy(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static KList getInterfaces() { + try { + KList interfaces = new KList<>(); + Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces(); + for (NetworkInterface ni : Collections.list(networkInterfaces)) { + interfaces.add(C.BLUE + "Display Name: %s", ni.getDisplayName()); + Enumeration inetAddresses = ni.getInetAddresses(); + for (InetAddress ia : Collections.list(inetAddresses)) { + interfaces.add("IP: %s", ia.getHostAddress()); + } + return interfaces.copy(); + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} \ No newline at end of file From 9e6963b6ce3a53875258aa0f4993a3d1a6fedabd Mon Sep 17 00:00:00 2001 From: RePixelatedMC Date: Tue, 23 Apr 2024 11:24:53 +0200 Subject: [PATCH 7/8] A lot of improvements thanks to CrazyDev! --- .../iris/core/commands/CommandIris.java | 19 +- .../iris/core/commands/CommandUpdater.java | 107 ++++++++++ .../iris/core/pregenerator/ChunkUpdater.java | 186 ++++++++++++------ 3 files changed, 237 insertions(+), 75 deletions(-) create mode 100644 core/src/main/java/com/volmit/iris/core/commands/CommandUpdater.java 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 c7f204a52..3a6206fc3 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 @@ -78,6 +78,7 @@ public class CommandIris implements DecreeExecutor { private CommandWhat what; private CommandEdit edit; private CommandFind find; + private CommandUpdater updater; private CommandDeveloper developer; public static boolean worldCreation = false; String WorldEngine; @@ -319,24 +320,6 @@ public class CommandIris implements DecreeExecutor { return dir.delete(); } - @Decree(description = "Updates all chunk in the specified world") - public void updater( - @Param(description = "World to update chunks at") - World world - ) { - if (!IrisToolbelt.isIrisWorld(world)) { - sender().sendMessage(C.GOLD + "This is not an Iris world"); - return; - } - ChunkUpdater updater = new ChunkUpdater(world); - if (sender().isPlayer()) { - sender().sendMessage(C.GREEN + "Updating " + world.getName() + " Total chunks: " + Form.f(updater.getChunks())); - } else { - Iris.info(C.GREEN + "Updating " + world.getName() + " Total chunks: " + Form.f(updater.getChunks())); - } - updater.start(); - } - @Decree(description = "Set aura spins") public void aura( @Param(description = "The h color value", defaultValue = "-20") diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandUpdater.java b/core/src/main/java/com/volmit/iris/core/commands/CommandUpdater.java new file mode 100644 index 000000000..cb1ff6eeb --- /dev/null +++ b/core/src/main/java/com/volmit/iris/core/commands/CommandUpdater.java @@ -0,0 +1,107 @@ +/* + * 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 org.bukkit.World; + +import com.volmit.iris.Iris; +import com.volmit.iris.core.pregenerator.ChunkUpdater; +import com.volmit.iris.core.tools.IrisToolbelt; +import com.volmit.iris.util.decree.DecreeExecutor; +import com.volmit.iris.util.decree.DecreeOrigin; +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.format.Form; + +@Decree(name = "Updater", origin = DecreeOrigin.BOTH, description = "Iris World Updater") +public class CommandUpdater implements DecreeExecutor { + private ChunkUpdater chunkUpdater; + + @Decree(description = "Updates all chunk in the specified world") + public void start( + @Param(description = "World to update chunks at") + World world + ) { + if (!IrisToolbelt.isIrisWorld(world)) { + sender().sendMessage(C.GOLD + "This is not an Iris world"); + return; + } + chunkUpdater = new ChunkUpdater(world); + if (sender().isPlayer()) { + sender().sendMessage(C.GREEN + "Updating " + world.getName() + C.GRAY + " Total chunks: " + Form.f(chunkUpdater.getChunks())); + } else { + Iris.info(C.GREEN + "Updating " + world.getName() + C.GRAY + " Total chunks: " + Form.f(chunkUpdater.getChunks())); + } + chunkUpdater.start(); + } + + @Decree(description = "Pause the updater") + public void pause( + @Param(description = "World to pause the Updater at") + World world + ) { + if (!IrisToolbelt.isIrisWorld(world)) { + sender().sendMessage(C.GOLD + "This is not an Iris world"); + return; + } + if (chunkUpdater == null) { + sender().sendMessage(C.GOLD + "You cant pause something that doesnt exist?"); + return; + } + boolean status = chunkUpdater.pause(); + if (sender().isPlayer()) { + if (status) { + sender().sendMessage(C.IRIS + "Paused task for: " + C.GRAY + world.getName()); + } else { + sender().sendMessage(C.IRIS + "Unpause task for: " + C.GRAY + world.getName()); + } + } else { + if (status) { + Iris.info(C.IRIS + "Paused task for: " + C.GRAY + world.getName()); + } else { + Iris.info(C.IRIS + "Unpause task for: " + C.GRAY + world.getName()); + } + } + } + + @Decree(description = "Stops the updater") + public void stop( + @Param(description = "World to stop the Updater at") + World world + ) { + if (!IrisToolbelt.isIrisWorld(world)) { + sender().sendMessage(C.GOLD + "This is not an Iris world"); + return; + } + if (chunkUpdater == null) { + sender().sendMessage(C.GOLD + "You cant stop something that doesnt exist?"); + return; + } + if (sender().isPlayer()) { + sender().sendMessage("Stopping Updater for: " + C.GRAY + world.getName()); + } else { + Iris.info("Stopping Updater for: " + C.GRAY + world.getName()); + } + chunkUpdater.stop(); + } + +} + + diff --git a/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java b/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java index 0e783d4c7..d89ad3340 100644 --- a/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java +++ b/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java @@ -9,14 +9,11 @@ import com.volmit.iris.util.format.Form; import com.volmit.iris.util.math.M; import com.volmit.iris.util.math.RollingSequence; import com.volmit.iris.util.math.Spiraler; -import com.volmit.iris.util.reflect.V; import com.volmit.iris.util.scheduling.J; import io.papermc.lib.PaperLib; -import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.World; - import java.io.File; import java.util.ArrayList; @@ -26,10 +23,10 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; public class ChunkUpdater { + private AtomicBoolean paused; private AtomicBoolean cancelled; private KMap lastUse; private final RollingSequence chunksPerSecond; - private final RollingSequence mcaregionsPerSecond; private final AtomicInteger worldheightsize; private final AtomicInteger worldwidthsize; private final AtomicInteger totalChunks; @@ -40,25 +37,26 @@ public class ChunkUpdater { private AtomicInteger chunksUpdated; private AtomicLong startTime; private ExecutorService executor; + private ExecutorService chunkExecutor; private ScheduledExecutorService scheduler; - private final File[] McaFiles; + private CompletableFuture future; + private CountDownLatch latch; + private final Object pauseLock; private final Engine engine; private final World world; public ChunkUpdater(World world) { - File cacheDir = new File("plugins" + File.separator + "iris" + File.separator + "cache"); - File chunkCacheDir = new File("plugins" + File.separator + "iris" + File.separator + "cache" + File.separator + "spiral"); this.engine = IrisToolbelt.access(world).getEngine(); - this.chunksPerSecond = new RollingSequence(10); - this.mcaregionsPerSecond = new RollingSequence(10); + this.chunksPerSecond = new RollingSequence(5); this.world = world; this.lastUse = new KMap(); - this.McaFiles = new File(world.getWorldFolder(), "region").listFiles((dir, name) -> name.endsWith(".mca")); this.worldheightsize = new AtomicInteger(calculateWorldDimensions(new File(world.getWorldFolder(), "region"), 1)); this.worldwidthsize = new AtomicInteger(calculateWorldDimensions(new File(world.getWorldFolder(), "region"), 0)); int m = Math.max(worldheightsize.get(), worldwidthsize.get()); - this.executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() - 2); + this.executor = Executors.newFixedThreadPool(Math.max(Runtime.getRuntime().availableProcessors() / 3, 1)); + this.chunkExecutor = Executors.newFixedThreadPool(Math.max(Runtime.getRuntime().availableProcessors() / 3, 1)); this.scheduler = Executors.newScheduledThreadPool(1); + this.future = new CompletableFuture<>(); this.startTime = new AtomicLong(); this.worldheightsize.set(m); this.worldwidthsize.set(m); @@ -66,6 +64,9 @@ public class ChunkUpdater { this.chunksProcessed = new AtomicInteger(); this.chunksUpdated = new AtomicInteger(); this.position = new AtomicInteger(0); + this.latch = new CountDownLatch(totalMaxChunks.get()); + this.paused = new AtomicBoolean(false); + this.pauseLock = new Object(); this.cancelled = new AtomicBoolean(false); this.totalChunks = new AtomicInteger(0); this.totalMcaregions = new AtomicInteger(0); @@ -80,6 +81,22 @@ public class ChunkUpdater { update(); } + public boolean pause() { + unloadAndSaveAllChunks(); + if (paused.get()) { + paused.set(false); + return false; + } else { + paused.set(true); + return true; + } + } + + public void stop() { + unloadAndSaveAllChunks(); + cancelled.set(true); + } + private void update() { Iris.info("Updating.."); @@ -87,47 +104,89 @@ public class ChunkUpdater { startTime.set(System.currentTimeMillis()); scheduler.scheduleAtFixedRate(() -> { try { - long eta = computeETA(); - long elapsedSeconds = (System.currentTimeMillis() - startTime.get()) / 1000; - int processed = chunksProcessed.get(); - double cps = elapsedSeconds > 0 ? processed / (double) elapsedSeconds : 0; - chunksPerSecond.put(cps); - double percentage = ((double) chunksProcessed.get() / (double) totalMaxChunks.get()) * 100; - Iris.info("Updated: " + Form.f(processed) + " of " + Form.f(totalMaxChunks.get()) + " (%.0f%%) " + Form.f(chunksPerSecond.getAverage()) + "/s, ETA: " + Form.duration(eta, 2), percentage); + if (!paused.get()) { + long eta = computeETA(); + long elapsedSeconds = (System.currentTimeMillis() - startTime.get()) / 1000; + int processed = chunksProcessed.get(); + double cps = elapsedSeconds > 0 ? processed / (double) elapsedSeconds : 0; + chunksPerSecond.put(cps); + double percentage = ((double) chunksProcessed.get() / (double) totalMaxChunks.get()) * 100; + if (!cancelled.get()) { + Iris.info("Updated: " + Form.f(processed) + " of " + Form.f(totalMaxChunks.get()) + " (%.0f%%) " + Form.f(chunksPerSecond.getAverage()) + "/s, ETA: " + Form.duration(eta, + 2), percentage); + } + } } catch (Exception e) { e.printStackTrace(); } }, 0, 3, TimeUnit.SECONDS); - for (int i = 0; i < totalMaxChunks.get(); i++) { - executor.submit(this::processNextChunk); - } + CompletableFuture.runAsync(() -> { + for (int i = 0; i < totalMaxChunks.get(); i++) { + if (paused.get()) { + synchronized (pauseLock) { + try { + pauseLock.wait(); + } catch (InterruptedException e) { + Iris.error("Interrupted while waiting for executor: "); + e.printStackTrace(); + break; + } + } + } + executor.submit(() -> { + if (!cancelled.get()) { + processNextChunk(); + } + latch.countDown(); + }); + } + }).thenRun(() -> { + try { + latch.await(); + close(); + } catch (Exception e) { + Thread.currentThread().interrupt(); + } + }); - executor.shutdown(); - executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); - scheduler.shutdownNow(); - Iris.info("Processed: " + Form.f(chunksProcessed.get()) + " Chunks"); - Iris.info("Finished Updating: " + Form.f(chunksUpdated.get()) + " Chunks"); } catch (Exception e) { e.printStackTrace(); } } + public void close() { + try { + unloadAndSaveAllChunks(); + executor.shutdown(); + executor.awaitTermination(5, TimeUnit.SECONDS); + chunkExecutor.shutdown(); + chunkExecutor.awaitTermination(5, TimeUnit.SECONDS); + scheduler.shutdownNow(); + } catch (Exception ignored) { + } + if (cancelled.get()) { + Iris.info("Updated: " + Form.f(chunksUpdated.get()) + " Chunks"); + Iris.info("Irritated: " + Form.f(chunksProcessed.get()) + " of " + Form.f(totalMaxChunks.get())); + Iris.info("Stopped updater."); + } else { + Iris.info("Processed: " + Form.f(chunksProcessed.get()) + " Chunks"); + Iris.info("Finished Updating: " + Form.f(chunksUpdated.get()) + " Chunks"); + } + } + private void processNextChunk() { int pos = position.getAndIncrement(); int[] coords = getChunk(pos); - if (areAllChunksGenerated(coords[0], coords[1])) { - CompletableFuture chunkFuture = loadChunksIfGenerated(coords[0], coords[1]); - chunkFuture.thenAccept(chunk -> { - Chunk c = world.getChunkAt(coords[0], coords[1]); - engine.updateChunk(c); - chunksUpdated.getAndIncrement(); - }); + if (loadChunksIfGenerated(coords[0], coords[1])) { + Chunk c = world.getChunkAt(coords[0], coords[1]); + engine.updateChunk(c); + chunksUpdated.incrementAndGet(); } chunksProcessed.getAndIncrement(); } - private boolean areAllChunksGenerated(int x, int z) { + private boolean loadChunksIfGenerated(int x, int z) { for (int dx = -1; dx <= 1; dx++) { for (int dz = -1; dz <= 1; dz++) { if (!PaperLib.isChunkGenerated(world, x + dx, z + dz)) { @@ -135,34 +194,47 @@ public class ChunkUpdater { } } } - return true; - } - private CompletableFuture loadChunksIfGenerated(int x, int z) { - CompletableFuture future = new CompletableFuture<>(); - if (areAllChunksGenerated(x, z)) { - Runnable task = () -> { - try { - for (int dx = -1; dx <= 1; dx++) { - for (int dz = -1; dz <= 1; dz++) { - Chunk c = world.getChunkAt(x + dx, z + dz); - world.loadChunk(c); - lastUse.put(c, M.ms()); - } + AtomicBoolean generated = new AtomicBoolean(true); + KList> futures = new KList<>(9); + for (int dx = -1; dx <= 1; dx++) { + for (int dz = -1; dz <= 1; dz++) { + int xx = x + dx; + int zz = z + dz; + futures.add(chunkExecutor.submit(() -> { + Chunk c; + try { + c = PaperLib.getChunkAtAsync(world, xx, zz, false).get(); + } catch (InterruptedException | ExecutionException e) { + generated.set(false); + return; } - future.complete(null); - } catch (Exception e) { - future.completeExceptionally(e); - } - }; - Bukkit.getScheduler().runTask(Iris.instance, task); - } else { - future.completeExceptionally(new IllegalStateException("Not all chunks are generated")); + if (!c.isLoaded()) { + CountDownLatch latch = new CountDownLatch(1); + J.s(() -> { + c.load(false); + latch.countDown(); + }); + try { + latch.await(); + } catch (InterruptedException ignored) {} + } + if (!c.isGenerated()) { + generated.set(false); + } + lastUse.put(c, M.ms()); + })); + } } - return future; + while (!futures.isEmpty()) { + futures.removeIf(Future::isDone); + try { + Thread.sleep(50); + } catch (InterruptedException ignored) {} + } + return generated.get(); } - private void unloadAndSaveAllChunks() { try { J.sfut(() -> { From 178a462a4eeba9e958f2fc76fdc997ffbec7ea42 Mon Sep 17 00:00:00 2001 From: RePixelatedMC Date: Tue, 23 Apr 2024 12:29:19 +0200 Subject: [PATCH 8/8] e --- .../com/volmit/iris/util/nbt/mca/Chunk.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/com/volmit/iris/util/nbt/mca/Chunk.java b/core/src/main/java/com/volmit/iris/util/nbt/mca/Chunk.java index fdd0b969b..f74cdcf7f 100644 --- a/core/src/main/java/com/volmit/iris/util/nbt/mca/Chunk.java +++ b/core/src/main/java/com/volmit/iris/util/nbt/mca/Chunk.java @@ -41,6 +41,7 @@ public class Chunk { private int lastMCAUpdate; private CompoundTag data; private int dataVersion; + private int nativeIrisVersion; private long lastUpdate; private long inhabitedTime; private MCABiomeContainer biomes; @@ -83,6 +84,11 @@ public class Chunk { return c; } + public static void injectIrisData(Chunk c) { + World mainWorld = getServer().getWorlds().get(0); + c.data.put("Iris", nativeIrisVersion()); + } + private static CompoundTag defaultLevel() { CompoundTag level = new CompoundTag(); level.putString("Status", "full"); @@ -90,14 +96,19 @@ public class Chunk { return level; } + private static CompoundTag nativeIrisVersion() { + CompoundTag level = new CompoundTag(); + level.putString("Generator", "Iris " + Iris.instance.getDescription().getVersion()); + return level; + } + private void initReferences(long loadFlags) { if (data == null) { throw new NullPointerException("data cannot be null"); } - CompoundTag level; - if ((level = data.getCompoundTag("Level")) == null) { - throw new IllegalArgumentException("data does not contain \"Level\" tag"); - } + + CompoundTag level = data; + World mainWorld = getServer().getWorlds().get(0); dataVersion = data.getInt("DataVersion"); inhabitedTime = level.getLong("InhabitedTime");