diff --git a/Gui/build.gradle b/Gui/build.gradle
new file mode 100644
index 000000000..19bdf442c
--- /dev/null
+++ b/Gui/build.gradle
@@ -0,0 +1,71 @@
+plugins {
+ id 'java'
+ id 'application'
+ id 'org.javamodularity.moduleplugin' version '1.8.12'
+ id 'org.openjfx.javafxplugin' version '0.0.13'
+ id 'org.beryx.jlink' version '2.25.0'
+}
+
+group 'com.volmit'
+version '1.0'
+
+repositories {
+ mavenCentral()
+}
+
+ext {
+ junitVersion = '5.10.0'
+}
+
+sourceCompatibility = '17'
+targetCompatibility = '17'
+
+tasks.withType(JavaCompile) {
+ options.encoding = 'UTF-8'
+}
+
+application {
+ mainModule = 'com.volmit.gui'
+ mainClass = 'com.volmit.gui.HelloApplication'
+}
+
+javafx {
+ version = '17.0.6'
+ modules = ['javafx.controls', 'javafx.fxml', 'javafx.web', 'javafx.swing' , 'javafx.media']
+}
+
+dependencies {
+ implementation('org.controlsfx:controlsfx:11.1.2')
+ implementation('com.dlsc.formsfx:formsfx-core:11.6.0') {
+ exclude(group: 'org.openjfx')
+ }
+ implementation('net.synedra:validatorfx:0.4.0') {
+ exclude(group: 'org.openjfx')
+ }
+ implementation('org.kordamp.ikonli:ikonli-javafx:12.3.1')
+ implementation('org.kordamp.bootstrapfx:bootstrapfx-core:0.4.0')
+ implementation('eu.hansolo:tilesfx:11.48') {
+ exclude(group: 'org.openjfx')
+ }
+ implementation('com.github.almasb:fxgl:17.3') {
+ exclude(group: 'org.openjfx')
+ }
+
+ testImplementation("org.junit.jupiter:junit-jupiter-api:${junitVersion}")
+ testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junitVersion}")
+}
+
+test {
+useJUnitPlatform()}
+
+jlink {
+ imageZip = project.file("${buildDir}/distributions/app-${javafx.platform.classifier}.zip")
+ options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
+ launcher {
+ name = 'app'
+ }
+}
+
+jlinkZip {
+ group = 'distribution'
+}
\ No newline at end of file
diff --git a/Gui/gradle/wrapper/gradle-wrapper.jar b/Gui/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000..249e5832f
Binary files /dev/null and b/Gui/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/Gui/gradle/wrapper/gradle-wrapper.properties b/Gui/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000..15de90249
--- /dev/null
+++ b/Gui/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/Gui/gradlew b/Gui/gradlew
new file mode 100644
index 000000000..1b6c78733
--- /dev/null
+++ b/Gui/gradlew
@@ -0,0 +1,234 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+APP_NAME="Gradle"
+APP_BASE_NAME=${0##*/}
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/Gui/gradlew.bat b/Gui/gradlew.bat
new file mode 100644
index 000000000..107acd32c
--- /dev/null
+++ b/Gui/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/Gui/settings.gradle b/Gui/settings.gradle
new file mode 100644
index 000000000..6ba600e55
--- /dev/null
+++ b/Gui/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = "Gui"
diff --git a/Gui/src/main/java/com/volmit/gui/HelloApplication.java b/Gui/src/main/java/com/volmit/gui/HelloApplication.java
new file mode 100644
index 000000000..19f51abce
--- /dev/null
+++ b/Gui/src/main/java/com/volmit/gui/HelloApplication.java
@@ -0,0 +1,23 @@
+package com.volmit.gui;
+
+import javafx.application.Application;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Scene;
+import javafx.stage.Stage;
+
+import java.io.IOException;
+
+public class HelloApplication extends Application {
+ @Override
+ public void start(Stage stage) throws IOException {
+ FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
+ Scene scene = new Scene(fxmlLoader.load(), 320, 240);
+ stage.setTitle("Hello!");
+ stage.setScene(scene);
+ stage.show();
+ }
+
+ public static void main(String[] args) {
+ launch();
+ }
+}
\ No newline at end of file
diff --git a/Gui/src/main/java/com/volmit/gui/HelloController.java b/Gui/src/main/java/com/volmit/gui/HelloController.java
new file mode 100644
index 000000000..2a8358167
--- /dev/null
+++ b/Gui/src/main/java/com/volmit/gui/HelloController.java
@@ -0,0 +1,14 @@
+package com.volmit.gui;
+
+import javafx.fxml.FXML;
+import javafx.scene.control.Label;
+
+public class HelloController {
+ @FXML
+ private Label welcomeText;
+
+ @FXML
+ protected void onHelloButtonClick() {
+ welcomeText.setText("Welcome to JavaFX Application!");
+ }
+}
\ No newline at end of file
diff --git a/Gui/src/main/java/module-info.java b/Gui/src/main/java/module-info.java
new file mode 100644
index 000000000..d17d5585d
--- /dev/null
+++ b/Gui/src/main/java/module-info.java
@@ -0,0 +1,16 @@
+module org.repix.gui {
+ requires javafx.controls;
+ requires javafx.fxml;
+ requires javafx.web;
+
+ requires org.controlsfx.controls;
+ requires com.dlsc.formsfx;
+ requires net.synedra.validatorfx;
+ requires org.kordamp.ikonli.javafx;
+ requires org.kordamp.bootstrapfx.core;
+ requires eu.hansolo.tilesfx;
+ requires com.almasb.fxgl.all;
+
+ opens com.volmit.gui to javafx.fxml;
+ exports com.volmit.gui;
+}
\ No newline at end of file
diff --git a/Gui/src/main/resources/com/volmit/gui/hello-view.fxml b/Gui/src/main/resources/com/volmit/gui/hello-view.fxml
new file mode 100644
index 000000000..fa37b1043
--- /dev/null
+++ b/Gui/src/main/resources/com/volmit/gui/hello-view.fxml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build.gradle b/build.gradle
index 434a1ccad..b138ddbbc 100644
--- a/build.gradle
+++ b/build.gradle
@@ -43,6 +43,7 @@ registerCustomOutputTaskUnix('CyberpwnLT', '/Users/danielmills/development/serve
registerCustomOutputTaskUnix('PsychoLT', '/Volumes/PRO-G40/Minecraft/MinecraftDevelopment/Server/plugins')
// ==============================================================
+
def NMS_BINDINGS = Map.of(
"v1_20_R3", "1.20.4-R0.1-SNAPSHOT",
"v1_20_R2", "1.20.2-R0.1-SNAPSHOT",
@@ -182,6 +183,7 @@ NMS_BINDINGS.each {
shadowJar {
NMS_BINDINGS.each {dependsOn(":nms:${it.key}:build")}
+ dependsOn(':com.volmit.gui:build')
//minimize()
append("plugin.yml")
@@ -228,6 +230,7 @@ allprojects {
dependencies {
// Provided or Classpath
+ // implementation project(':com.volmit.gui')
compileOnly 'org.projectlombok:lombok:1.18.24'
annotationProcessor 'org.projectlombok:lombok:1.18.24'
diff --git a/core/src/main/java/com/volmit/iris/core/IrisSettings.java b/core/src/main/java/com/volmit/iris/core/IrisSettings.java
index 335207de5..a736407a4 100644
--- a/core/src/main/java/com/volmit/iris/core/IrisSettings.java
+++ b/core/src/main/java/com/volmit/iris/core/IrisSettings.java
@@ -42,6 +42,7 @@ public class IrisSettings {
private IrisSettingsConcurrency concurrency = new IrisSettingsConcurrency();
private IrisSettingsStudio studio = new IrisSettingsStudio();
private IrisSettingsPerformance performance = new IrisSettingsPerformance();
+ private IrisWorldDump worldDump = new IrisWorldDump();
public static int getThreadCount(int c) {
return switch (c) {
@@ -187,4 +188,8 @@ public class IrisSettings {
public boolean disableTimeAndWeather = true;
public boolean autoStartDefaultStudio = false;
}
+ @Data
+ public static class IrisWorldDump {
+ public int mcaCacheSize = 3;
+ }
}
diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandDeveloper.java b/core/src/main/java/com/volmit/iris/core/commands/CommandDeveloper.java
index fb1e3c405..6e556391d 100644
--- a/core/src/main/java/com/volmit/iris/core/commands/CommandDeveloper.java
+++ b/core/src/main/java/com/volmit/iris/core/commands/CommandDeveloper.java
@@ -28,6 +28,7 @@ import com.volmit.iris.core.tools.IrisPackBenchmarking;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.core.tools.IrisWorldDump;
import com.volmit.iris.engine.framework.Engine;
+import com.volmit.iris.engine.jvm.VMJavaFX;
import com.volmit.iris.engine.mantle.components.MantleObjectComponent;
import com.volmit.iris.engine.object.IrisBiome;
import com.volmit.iris.engine.object.IrisCave;
@@ -172,11 +173,20 @@ public class CommandDeveloper implements DecreeExecutor {
public void mca (
@Param(description = "String") World world) {
try {
- File[] McaFiles = new File(world.getName(), "region").listFiles((dir, name) -> name.endsWith(".mca"));
- for (File mca : McaFiles) {
- IrisWorldDump dump = new IrisWorldDump(world, sender(), IrisWorldDump.mode.RAW);
- dump.dump();
- }
+ IrisWorldDump dump = new IrisWorldDump(world, sender(), IrisWorldDump.mode.PACKED);
+ dump.start();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ @Decree(description = "test")
+ public void javafx () {
+ try {
+ VMJavaFX javaFX = new VMJavaFX(sender());
+ javaFX.start();
} catch (Exception e) {
e.printStackTrace();
}
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 d89ad3340..29c590fa2 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
@@ -106,7 +106,7 @@ public class ChunkUpdater {
try {
if (!paused.get()) {
long eta = computeETA();
- long elapsedSeconds = (System.currentTimeMillis() - startTime.get()) / 1000;
+ long elapsedSeconds = (System.currentTimeMillis() - startTime.get()) / 3000;
int processed = chunksProcessed.get();
double cps = elapsedSeconds > 0 ? processed / (double) elapsedSeconds : 0;
chunksPerSecond.put(cps);
diff --git a/core/src/main/java/com/volmit/iris/core/tools/IrisWorldDump.java b/core/src/main/java/com/volmit/iris/core/tools/IrisWorldDump.java
index f8cf1f8c4..566a645f8 100644
--- a/core/src/main/java/com/volmit/iris/core/tools/IrisWorldDump.java
+++ b/core/src/main/java/com/volmit/iris/core/tools/IrisWorldDump.java
@@ -1,50 +1,77 @@
package com.volmit.iris.core.tools;
import com.volmit.iris.Iris;
+import com.volmit.iris.core.IrisSettings;
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.C;
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.nbt.mca.Chunk;
import com.volmit.iris.util.nbt.mca.MCAFile;
import com.volmit.iris.util.nbt.mca.MCAUtil;
import com.volmit.iris.util.nbt.tag.CompoundTag;
+import com.volmit.iris.util.nbt.tag.StringTag;
import com.volmit.iris.util.plugin.VolmitSender;
import org.bukkit.World;
import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReferenceArray;
public class IrisWorldDump {
private KList mcaList;
+ private KMap storage;
+ private AtomicLong airStorage;
private World world;
private File MCADirectory;
- private AtomicInteger processed;
+ private AtomicInteger regionsProcessed;
+ private AtomicInteger chunksProcessed;
private AtomicInteger totalToProcess;
+ private AtomicInteger totalMaxChunks;
+ private AtomicInteger totalMCAFiles;
+ private RollingSequence chunksPerSecond;
private Engine engine = null;
private Boolean IrisWorld;
private VolmitSender sender;
+ private ExecutorService executor;
+ private ScheduledExecutorService scheduler;
+ private AtomicLong startTime;
private mode mode;
+ private File dumps;
+ private File worldDump;
+ private int mcaCacheSize;
+ private File temp;
+ private File blocks;
+ private File structures;
public IrisWorldDump(World world, VolmitSender sender, mode mode) {
+ sender.sendMessage("Initializing IrisWorldDump...");
this.world = world;
this.sender = sender;
this.MCADirectory = new File(world.getWorldFolder(), "region");
- if (Runtime.getRuntime().maxMemory() < 1.5 * estimateMemoryUsage()) {
- sender.sendMessage(C.YELLOW + "Not enough memory!");
- sender.sendMessage(C.YELLOW + "- Process amount: " + Form.memSize(Runtime.getRuntime().maxMemory()));
- sender.sendMessage(C.YELLOW + "- Required amount: " + Form.memSize(estimateMemoryUsage()));
- //return;
- }
- sender.sendMessage("Initializing IrisWorldDump...");
-
- this.mcaList = new KList<>(getMcaFiles());
- this.processed = new AtomicInteger(0);
+ this.totalMCAFiles = new AtomicInteger(MCACount());
+ this.dumps = new File("plugins" + File.separator + "iris", "dumps");
+ this.worldDump = new File(dumps, world.getName());
+ this.mcaCacheSize = IrisSettings.get().getWorldDump().mcaCacheSize;
+ this.regionsProcessed = new AtomicInteger(0);
+ this.chunksProcessed = new AtomicInteger(0);
this.totalToProcess = new AtomicInteger(0);
-
+ this.totalMaxChunks = new AtomicInteger(totalMCAFiles.get() * 1024);
+ this.chunksPerSecond = new RollingSequence(10);
+ this.temp = new File(worldDump, "temp");
+ this.executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() - 1);
+ this.scheduler = Executors.newSingleThreadScheduledExecutor();
+ this.startTime = new AtomicLong();
+ this.storage = new KMap<>();
+ this.airStorage = new AtomicLong(0);
+ this.blocks = new File(worldDump, "blocks");
+ this.structures = new File(worldDump, "structures");
+ initialize();
try {
this.engine = IrisToolbelt.access(world).getEngine();
this.IrisWorld = true;
@@ -53,6 +80,45 @@ public class IrisWorldDump {
}
}
+ private void initialize() {
+ if (!dumps.exists()) {
+ if (!dumps.mkdirs()) {
+ System.err.println("Failed to create dump directory.");
+ return;
+ }
+ }
+
+ if (worldDump.exists() && !worldDump.delete()) {
+ System.err.println("Failed to delete existing world dump directory.");
+ return;
+ }
+
+ if (!worldDump.mkdir()) {
+ System.err.println("Failed to create world dump directory.");
+ return;
+ }
+
+ if (!blocks.mkdir()) {
+ System.err.println("Failed to create blocks directory.");
+ return;
+ }
+
+ if (!structures.mkdir()) {
+ System.err.println("Failed to create structures directory.");
+ return;
+ }
+ for (File mcaFile : MCADirectory.listFiles()) {
+ if (mcaFile.getName().endsWith(".mca")) {
+ totalToProcess.getAndIncrement();
+ }
+ }
+ }
+
+ public void start() {
+ dump();
+ updater();
+ }
+
public enum mode {
RAW {
@Override
@@ -64,69 +130,102 @@ public class IrisWorldDump {
@Override
public void methodDump() {
+ }
+ },
+ PACKED {
+ @Override
+ public void methodDump() {
+
}
};
public abstract void methodDump();
}
+
+ private void updater() {
+ startTime.set(System.currentTimeMillis());
+ scheduler.scheduleAtFixedRate(() -> {
+ long eta = computeETA();
+ long elapsedSeconds = (System.currentTimeMillis() - startTime.get()) / 3000;
+ 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("Processed: " + Form.f(processed) + " of " + Form.f(totalMaxChunks.get()) + " (%.0f%%) " + Form.f(chunksPerSecond.getAverage()) + "/s, ETA: " + Form.duration(eta, 2), percentage);
- public void dump() {
- for (MCAFile mca : mcaList) {
- AtomicReferenceArray chunks = new AtomicReferenceArray<>(1024);
- for (int i = 0; i < chunks.length(); i++) {
- chunks.set(i, mca.getChunks().get(i));
+ }, 1, 3, TimeUnit.SECONDS);
+
+ }
+
+
+ private void dump() {
+ Iris.info("Starting the dump process.");
+ int threads = Runtime.getRuntime().availableProcessors();
+ AtomicInteger f = new AtomicInteger();
+ for (File mcaFile : MCADirectory.listFiles()) {
+ if (mcaFile.getName().endsWith(".mca")) {
+ executor.submit(() -> {
+ try {
+ processMCARegion( MCAUtil.read(mcaFile));
+ } catch (Exception e) {
+ f.getAndIncrement();
+ Iris.error("Failed to read mca file");
+ e.printStackTrace();
+ }
+ });
+ }
}
- for (int i = 0; i < chunks.length(); i++) {
- Chunk chunk = chunks.get(i);
- if (chunk != null) {
- int CHUNK_HEIGHT = (world.getMaxHeight() - world.getMinHeight());
- for (int x = 0; x < 16; x++) {
- for (int z = 0; z < 16; z++) {
- for (int y = 0; y < CHUNK_HEIGHT; y++) {
- // CompoundTag tag = chunk.getBlockStateAt(x,y,z);
- //net.minecraft.world.level.chunk.PalettedContainer;
- //net.minecraft.world.level.chunk.storage.ChunkSerializer;
+ }
+
+ private void processMCARegion(MCAFile mca) {
+ AtomicReferenceArray chunks = new AtomicReferenceArray<>(1024);
+ for (int i = 0; i < chunks.length(); i++) {
+ chunks.set(i, mca.getChunks().get(i));
+ }
+ for (int i = 0; i < chunks.length(); i++) {
+ Chunk chunk = chunks.get(i);
+ if (chunk != null) {
+ int CHUNK_HEIGHT = (world.getMaxHeight() - world.getMinHeight());
+ for (int x = 0; x < 16; x++) {
+ for (int z = 0; z < 16; z++) {
+ for (int y = 0; y < CHUNK_HEIGHT; y++) {
+ CompoundTag tag = chunk.getBlockStateAt(x, y, z);
+ if (tag == null) {
+ String blockName = "minecraft:air";
+ //storage.compute(blockName, (key, count) -> (count == null) ? 1 : count + 1);
+ airStorage.getAndIncrement();
+ int ii = 0;
+ } else {
+ StringTag nameTag = tag.getStringTag("Name");
+ String blockName = nameTag.getValue();
+ storage.compute(blockName, (key, count) -> (count == null) ? 1 : count + 1);
+ int ii = 0;
}
}
}
}
+ chunksProcessed.getAndIncrement();
}
}
+ regionsProcessed.getAndIncrement();
}
-
- private long estimateMemoryUsage() {
- long size = 0;
+ private int MCACount() {
+ int size = 0;
for (File mca : MCADirectory.listFiles()) {
- size =+ mca.length();
+ if (mca.getName().endsWith(".mca")) {
+ size++;
+ }
}
return size;
}
- private List getMcaFiles() {
- List mcaFiles = new ArrayList<>();
- int l = 0;
- int f = 0;
- for (File mca : MCADirectory.listFiles()) {
- // net.minecraft.world.level.chunk.PalettedContainer
- // take a look at the classes `net.minecraft.world.level.chunk.PalettedContainer` and `net.minecraft.world.level.chunk.storage.ChunkSerializer`
- if (mca.getName().endsWith(".mca")) {
- try {
- mcaFiles.add(MCAUtil.read(mca));
- l++;
- } catch (Exception e) {
- f++;
- Iris.error("Failed to read mca file: " + mca.getName(), e);
- e.printStackTrace(); // todo: debug line
- }
- }
- }
- sender.sendMessage("Loaded: " + l + " MCA Regions");
- if (f > 0) {
- sender.sendMessage(C.RED +"Failed " + C.GRAY + "to load: " + f + " MCA Regions");
- }
- Iris.info("Successfull: " + Form.f(l));
- Iris.info("Failed: " + Form.f(f));
- return mcaFiles;
+ 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
+ );
}
}
diff --git a/core/src/main/java/com/volmit/iris/engine/jvm/VMJavaFX.java b/core/src/main/java/com/volmit/iris/engine/jvm/VMJavaFX.java
new file mode 100644
index 000000000..d187c333b
--- /dev/null
+++ b/core/src/main/java/com/volmit/iris/engine/jvm/VMJavaFX.java
@@ -0,0 +1,32 @@
+package com.volmit.iris.engine.jvm;
+
+import com.volmit.iris.util.plugin.VolmitSender;
+
+public class VMJavaFX {
+ private VolmitSender sender;
+ public VMJavaFX(VolmitSender user) {
+ this.sender = user;
+
+ }
+
+ public void start() {
+ try {
+ // Start JavaFX in a new JVM
+ ProcessBuilder processBuilder = new ProcessBuilder(
+ "java",
+ "--module-path", "path/to/javafx-sdk/lib", // Set path to JavaFX SDK
+ "--add-modules", "javafx.controls,javafx.fxml",
+ "-jar", "path/to/javafx-application.jar"
+ );
+ processBuilder.inheritIO();
+ processBuilder.start();
+ sender.sendMessage("JavaFX application is launched!");
+ } catch (Exception e) {
+ sender.sendMessage("Failed to launch JavaFX application.");
+ e.printStackTrace();
+ }
+ }
+
+
+
+}
diff --git a/settings.gradle b/settings.gradle
index ba41bb67e..e100bba88 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -23,7 +23,7 @@ pluginManagement {
}
}
rootProject.name = 'Iris'
-
+include 'app', 'com.volmit.gui'
include(':core')
include(
':nms:v1_20_R3',