diff --git a/build.gradle b/build.gradle
index 2484924d8..77c48256c 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/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 6ec02ef7f..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
@@ -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;
@@ -76,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;
@@ -317,6 +320,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")
@@ -512,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/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 1e40ab566..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
@@ -1,70 +1,271 @@
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.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.nbt.mca.MCAFile;
-import com.volmit.iris.util.nbt.mca.MCAUtil;
+import com.volmit.iris.util.scheduling.J;
+import io.papermc.lib.PaperLib;
+import org.bukkit.Chunk;
import org.bukkit.World;
-
import java.io.File;
+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 paused;
private AtomicBoolean cancelled;
- private KList chunkMap;
+ private KMap lastUse;
private final RollingSequence chunksPerSecond;
- private final RollingSequence mcaregionsPerSecond;
private final AtomicInteger worldheightsize;
private final AtomicInteger worldwidthsize;
private final AtomicInteger totalChunks;
private final AtomicInteger totalMaxChunks;
private final AtomicInteger totalMcaregions;
private final AtomicInteger position;
- private final File[] McaFiles;
+ private AtomicInteger chunksProcessed;
+ private AtomicInteger chunksUpdated;
+ private AtomicLong startTime;
+ private ExecutorService executor;
+ private ExecutorService chunkExecutor;
+ private ScheduledExecutorService scheduler;
+ 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.chunksPerSecond = new RollingSequence(10);
- this.mcaregionsPerSecond = new RollingSequence(10);
+ this.engine = IrisToolbelt.access(world).getEngine();
+ this.chunksPerSecond = new RollingSequence(5);
this.world = world;
- this.chunkMap = new KList<>();
- this.McaFiles = new File(world.getWorldFolder(), "region").listFiles((dir, name) -> name.endsWith(".mca"));
+ this.lastUse = new KMap();
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(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);
+ this.totalMaxChunks = new AtomicInteger((worldheightsize.get() / 16) * (worldwidthsize.get() / 16));
+ 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);
}
- public void start() {
- Initialize();
+ public int getChunks() {
+ return totalMaxChunks.get();
}
- public void Initialize() {
- Iris.info("Initializing..");
+ public void start() {
+ unloadAndSaveAllChunks();
+ 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..");
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 {
+ 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();
}
- }
- Iris.info("Finished Initializing..");
+ }, 0, 3, TimeUnit.SECONDS);
+
+ 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();
+ }
+ });
+
} 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 (loadChunksIfGenerated(coords[0], coords[1])) {
+ Chunk c = world.getChunkAt(coords[0], coords[1]);
+ engine.updateChunk(c);
+ chunksUpdated.incrementAndGet();
+ }
+ chunksProcessed.getAndIncrement();
+ }
+
+ 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)) {
+ return false;
+ }
+ }
+ }
+
+ 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;
+ }
+ 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());
+ }));
+ }
+ }
+ while (!futures.isEmpty()) {
+ futures.removeIf(Future::isDone);
+ try {
+ Thread.sleep(50);
+ } catch (InterruptedException ignored) {}
+ }
+ return generated.get();
+ }
+
+ 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)
+ ((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"));
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
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");