diff --git a/.gitignore b/.gitignore index 869b9b1..be6836c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,9 @@ +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + target/ !.mvn/wrapper/maven-wrapper.jar !**/src/main/**/target/ diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..86509a4 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,40 @@ +plugins { + id("java") + id("io.github.goooler.shadow") version "8.1.7" +} + +group = "me.zimzaza4" +version = "1.0-SNAPSHOT" + +repositories { + mavenCentral() + + maven("https://repo.opencollab.dev/main/") +} + +dependencies { + compileOnly("org.geysermc.geyser:api:2.8.3-SNAPSHOT") + + compileOnly(files("libs/geyserutils-geyser-1.0-SNAPSHOT.jar")) + + implementation("org.spongepowered:configurate-yaml:4.2.0-GeyserMC-SNAPSHOT") + implementation("com.google.code.gson:gson:2.13.1") +} + +java { + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) +} + +tasks.compileJava { + options.encoding = "UTF-8" +} + +tasks.shadowJar { + archiveFileName.set("${rootProject.name}-${version}.jar") + + relocate("org.spongepowered.configurate", "me.zimzaza4.geysermodelenginepackgenerator.libs.configurate") +} + +tasks.build { + dependsOn("shadowJar") +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..9bbc975 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..37f853b --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..faf9300 --- /dev/null +++ b/gradlew @@ -0,0 +1,251 @@ +#!/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. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# 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/HEAD/platforms/jvm/plugins-application/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 + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# 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 + if ! command -v java >/dev/null 2>&1 + then + 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 +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + 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 + + +# 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"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# 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/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..9d21a21 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,94 @@ +@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 +@rem SPDX-License-Identifier: Apache-2.0 +@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=. +@rem This is normally unused +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% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +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% equ 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! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/pom.xml b/pom.xml deleted file mode 100644 index e274fde..0000000 --- a/pom.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - 4.0.0 - - re.imc - GeyserModelEnginePackGenerator - 1.0-SNAPSHOT - - - 17 - 17 - UTF-8 - - - - - opencollab-release-repo - https://repo.opencollab.dev/maven-releases/ - - true - - - true - - - - opencollab-snapshot-repo - https://repo.opencollab.dev/maven-snapshots/ - - false - - - true - - - - jitpack.io - https://jitpack.io - - - - - - com.google.code.gson - gson - 2.8.9 - - - org.projectlombok - lombok - 1.18.28 - compile - - - org.geysermc.geyser - api - 2.5.0-SNAPSHOT - provided - - - me.zimzaza4 - geyserutils-geyser - 1.0.0 - system - ${project.basedir}/libs/geyserutils-geyser-1.0-SNAPSHOT.jar - - - me.rochblondiaux - blockbenchmodelreader - 1.2 - - - com.github.GeyserMC.PackConverter - bedrock-pack-schema - 3d8150474d - - - com.github.GeyserMC.PackConverter - pack-schema-api - 3d8150474d - - - \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..2e98e3f --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "GeyserModelEnginePackGenerator" diff --git a/src/main/java/re/imc/geysermodelenginepackgenerator/GeneratorMain.java b/src/main/java/re/imc/geysermodelenginepackgenerator/GeneratorMain.java index 5ce6077..d645e47 100644 --- a/src/main/java/re/imc/geysermodelenginepackgenerator/GeneratorMain.java +++ b/src/main/java/re/imc/geysermodelenginepackgenerator/GeneratorMain.java @@ -17,13 +17,12 @@ import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; public class GeneratorMain { + public static final Map entityMap = new HashMap<>(); public static final Map animationMap = new HashMap<>(); public static final Map geometryMap = new HashMap<>(); public static final Map> textureMap = new HashMap<>(); - public static final Gson GSON = new GsonBuilder().setPrettyPrinting() - .create(); - + public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); public static void main(String[] args) { File source = new File(args.length > 0 ? args[0] : "input"); @@ -36,11 +35,11 @@ public class GeneratorMain { public static void generateFromZip(String currentPath, String modelId, ZipFile zip) { Entity entity = new Entity(modelId); - if (entityMap.containsKey(modelId)) { - return; - } + if (entityMap.containsKey(modelId)) return; + ModelConfig modelConfig = new ModelConfig(); ZipEntry textureConfigFile = null; + for (Iterator it = zip.entries().asIterator(); it.hasNext(); ) { ZipEntry entry = it.next(); if (entry.getName().endsWith("config.json")) { @@ -69,8 +68,8 @@ public class GeneratorMain { Map map = textureMap.computeIfAbsent(modelId, s -> new HashMap<>()); try { map.put(textureName, new Texture(modelId, currentPath, bindingBones, zip.getInputStream(e).readAllBytes())); - } catch (IOException ex) { - ex.printStackTrace(); + } catch (IOException err) { + throw new RuntimeException(err); } entity.setTextureMap(map); if (modelConfig.getBingingBones().isEmpty()) { @@ -106,6 +105,7 @@ public class GeneratorMain { } } } + if (canAdd) { entity.setModelConfig(modelConfig); entity.setPath(currentPath); @@ -116,20 +116,20 @@ public class GeneratorMain { public static void generateFromFolder(String currentPath, File folder, boolean root) { - if (folder.listFiles() == null) { - return; - } + if (folder.listFiles() == null) return; + String modelId = root ? "" : folder.getName().toLowerCase(); Entity entity = new Entity(modelId); ModelConfig modelConfig = new ModelConfig(); boolean shouldOverrideConfig = false; File textureConfigFile = new File(folder, "config.json"); + if (textureConfigFile.exists()) { try { modelConfig = GSON.fromJson(Files.readString(textureConfigFile.toPath()), ModelConfig.class); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException err) { + throw new RuntimeException(err); } } boolean canAdd = false; @@ -140,33 +140,33 @@ public class GeneratorMain { if (e.getName().endsWith(".zip")) { try { generateFromZip(currentPath, e.getName().replace(".zip", "").toLowerCase(Locale.ROOT), new ZipFile(e)); - } catch (IOException ex) { - ex.printStackTrace(); + } catch (IOException err) { + throw new RuntimeException(err); } } - if (entityMap.containsKey(modelId)) { - continue; - } + + if (entityMap.containsKey(modelId)) continue; + if (e.getName().endsWith(".png")) { String textureName = e.getName().replace(".png", ""); Set bindingBones = new HashSet<>(); bindingBones.add("*"); - if (modelConfig.getBingingBones().containsKey(textureName)) { - bindingBones = modelConfig.getBingingBones().get(textureName); - } + if (modelConfig.getBingingBones().containsKey(textureName)) bindingBones = modelConfig.getBingingBones().get(textureName); + Map map = textureMap.computeIfAbsent(modelId, s -> new HashMap<>()); try { map.put(textureName, new Texture(modelId, currentPath, bindingBones, Files.readAllBytes(e.toPath()))); - } catch (IOException ex) { - ex.printStackTrace(); + } catch (IOException err) { + throw new RuntimeException(err); } + entity.setTextureMap(map); if (modelConfig.getBingingBones().isEmpty()) { modelConfig.getBingingBones().put(textureName, Set.of("*")); shouldOverrideConfig = true; } - } + if (e.getName().endsWith(".json")) { try { String json = Files.readString(e.toPath()); @@ -189,11 +189,12 @@ public class GeneratorMain { entity.setGeometry(geometry); canAdd = true; } - } catch (IOException ex) { - ex.printStackTrace(); + } catch (IOException err) { + throw new RuntimeException(err); } } } + if (canAdd) { // old config File oldConfig = new File(folder, "config.properties"); @@ -208,16 +209,18 @@ public class GeneratorMain { oldConfig.delete(); } - } catch (IOException ex) { - ex.printStackTrace(); + } catch (IOException err) { + throw new RuntimeException(err); } + if (shouldOverrideConfig) { try { Files.writeString(textureConfigFile.toPath(), GSON.toJson(modelConfig)); - } catch (IOException ex) { - ex.printStackTrace(); + } catch (IOException err) { + throw new RuntimeException(err); } } + entity.setModelConfig(modelConfig); entity.setPath(currentPath); entityMap.put(modelId, entity); @@ -237,14 +240,13 @@ public class GeneratorMain { File manifestFile = new File(output, "manifest.json"); - output.mkdirs(); if (!manifestFile.exists()) { try { Files.writeString(manifestFile.toPath(), PackManifest.generate(), StandardCharsets.UTF_8); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException err) { + throw new RuntimeException(err); } } @@ -263,8 +265,8 @@ public class GeneratorMain { try { Files.writeString(materialFile.toPath(), Material.TEMPLATE, StandardCharsets.UTF_8); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException err) { + throw new RuntimeException(err); } } @@ -280,9 +282,7 @@ public class GeneratorMain { pathController.toFile().getParentFile().mkdirs(); path.toFile().getParentFile().mkdirs(); - if (path.toFile().exists()) { - continue; - } + if (path.toFile().exists()) continue; AnimationController controller = new AnimationController(); controller.load(entry.getValue(), entity); @@ -290,8 +290,8 @@ public class GeneratorMain { try { Files.writeString(path, GSON.toJson(entry.getValue().getJson()), StandardCharsets.UTF_8); Files.writeString(pathController, controller.getJson().toString(), StandardCharsets.UTF_8); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException err) { + throw new RuntimeException(err); } } @@ -322,22 +322,20 @@ public class GeneratorMain { try { Files.writeString(path, GSON.toJson(entry.getValue().getJson()), StandardCharsets.UTF_8); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException err) { + throw new RuntimeException(err); } } } } - if (path.toFile().exists()) { - continue; - } + if (path.toFile().exists()) continue; try { Files.writeString(path, GSON.toJson(entry.getValue().getJson()), StandardCharsets.UTF_8); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException err) { + throw new RuntimeException(err); } } @@ -354,8 +352,8 @@ public class GeneratorMain { if (entry.getValue().getImage() != null) { Files.write(path, entry.getValue().getImage()); } - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException err) { + throw new RuntimeException(err); } } } @@ -366,13 +364,13 @@ public class GeneratorMain { Path entityPath = entityFolder.toPath().resolve(entity.getPath() + entry.getKey() + ".entity.json"); entityPath.toFile().getParentFile().mkdirs(); - if (entityPath.toFile().exists()) { - continue; - } + + if (entityPath.toFile().exists()) continue; + try { Files.writeString(entityPath, entity.getJson().toString(), StandardCharsets.UTF_8); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException err) { + throw new RuntimeException(err); } // render controller part @@ -387,8 +385,8 @@ public class GeneratorMain { } try { Files.writeString(renderPath, controller.generate(), StandardCharsets.UTF_8); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException err) { + throw new RuntimeException(err); } } @@ -407,18 +405,17 @@ public class GeneratorMain { private static boolean isGeometryFile(String json) { try { - return new JsonParser().parse(json).getAsJsonObject().has("minecraft:geometry"); - } catch (Throwable e) { + return JsonParser.parseString(json).getAsJsonObject().has("minecraft:geometry"); + } catch (Throwable ignored) { return false; } } private static boolean isAnimationFile(String json) { try { - return new JsonParser().parse(json).getAsJsonObject().has("animations"); - } catch (Throwable e) { + return JsonParser.parseString(json).getAsJsonObject().has("animations"); + } catch (Throwable ignored) { return false; } } - } \ No newline at end of file diff --git a/src/main/java/re/imc/geysermodelenginepackgenerator/ExtensionMain.java b/src/main/java/re/imc/geysermodelenginepackgenerator/GeyserModelEnginePackGenerator.java similarity index 64% rename from src/main/java/re/imc/geysermodelenginepackgenerator/ExtensionMain.java rename to src/main/java/re/imc/geysermodelenginepackgenerator/GeyserModelEnginePackGenerator.java index 64f38c9..3d5d9de 100644 --- a/src/main/java/re/imc/geysermodelenginepackgenerator/ExtensionMain.java +++ b/src/main/java/re/imc/geysermodelenginepackgenerator/GeyserModelEnginePackGenerator.java @@ -1,43 +1,43 @@ package re.imc.geysermodelenginepackgenerator; -import me.zimzaza4.geyserutils.geyser.GeyserUtils; -import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.event.subscribe.Subscribe; import org.geysermc.geyser.api.command.Command; -import org.geysermc.geyser.api.command.CommandExecutor; import org.geysermc.geyser.api.command.CommandSource; import org.geysermc.geyser.api.event.lifecycle.GeyserDefineCommandsEvent; -import org.geysermc.geyser.api.event.lifecycle.GeyserLoadResourcePacksEvent; +import org.geysermc.geyser.api.event.lifecycle.GeyserDefineResourcePacksEvent; import org.geysermc.geyser.api.event.lifecycle.GeyserPreInitializeEvent; import org.geysermc.geyser.api.extension.Extension; -import org.geysermc.geyser.api.extension.ExtensionLogger; +import org.geysermc.geyser.api.pack.PackCodec; +import org.geysermc.geyser.api.pack.ResourcePack; +import re.imc.geysermodelenginepackgenerator.managers.ConfigManager; import re.imc.geysermodelenginepackgenerator.generator.Entity; -import re.imc.geysermodelenginepackgenerator.generator.Geometry; import re.imc.geysermodelenginepackgenerator.util.ZipUtil; import java.io.File; import java.io.IOException; -import java.nio.channels.FileChannel; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.StandardCopyOption; -import java.util.List; import java.util.zip.ZipOutputStream; -public class ExtensionMain implements Extension { +public class GeyserModelEnginePackGenerator implements Extension { + + private static GeyserModelEnginePackGenerator extension; private File source; - public static ExtensionLogger logger; - Path generatedPackZip; + private Path generatedPackZip; + + private ConfigManager configManager; @Subscribe public void onLoad(GeyserPreInitializeEvent event) { + extension = this; + + loadManagers(); + source = dataFolder().resolve("input").toFile(); source.mkdirs(); - logger = logger(); loadConfig(); - } @Subscribe @@ -45,9 +45,8 @@ public class ExtensionMain implements Extension { event.register(Command.builder(this) .name("reload") .source(CommandSource.class) - .executableOnConsole(true) + .playerOnly(false) .description("GeyserModelPackGenerator Reload Command") - .suggestedOpOnly(true) .permission("geysermodelenginepackgenerator.admin") .executor((source, command, args) -> { loadConfig(); @@ -57,7 +56,6 @@ public class ExtensionMain implements Extension { } public void loadConfig() { - File generatedPack = dataFolder().resolve("generated_pack").toFile(); GeneratorMain.startGenerate(source, generatedPack); @@ -66,23 +64,28 @@ public class ExtensionMain implements Extension { try (ZipOutputStream zipOutputStream = new ZipOutputStream(Files.newOutputStream(generatedPackZip))) { ZipUtil.compressFolder(generatedPack, null, zipOutputStream); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException err) { + throw new RuntimeException(err); } for (Entity entity : GeneratorMain.entityMap.values()) { entity.register(); } - } + private void loadManagers() { + this.configManager = new ConfigManager(); + } @Subscribe - public void onPackLoad(GeyserLoadResourcePacksEvent event) { - if (Boolean.parseBoolean(System.getProperty("geyser-model-engine-auto-load-pack", "true"))) { - event.resourcePacks().add(generatedPackZip); - } + public void onPackLoad(GeyserDefineResourcePacksEvent event) { + if (!configManager.getConfig().getBoolean("options.resource-pack.auto-load")) return; + + ResourcePack resourcePack = ResourcePack.builder(PackCodec.path(generatedPackZip)).build(); + event.register(resourcePack); } - + public static GeyserModelEnginePackGenerator getExtension() { + return extension; + } } diff --git a/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Animation.java b/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Animation.java index d1b6946..7dbc8dc 100644 --- a/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Animation.java +++ b/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Animation.java @@ -4,20 +4,12 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; import re.imc.geysermodelenginepackgenerator.GeneratorMain; import java.util.HashSet; import java.util.Map; import java.util.Set; -@Getter -@Setter -@AllArgsConstructor -@NoArgsConstructor public class Animation { public static final String HEAD_TEMPLATE = """ @@ -29,16 +21,16 @@ public class Animation { } """; - String modelId; - JsonObject json; - @Getter - Set animationIds = new HashSet<>(); + private String modelId; + private JsonObject json; + private Set animationIds = new HashSet<>(); - String path; + private String path; public void load(String string) { - this.json = new JsonParser().parse(string).getAsJsonObject(); + this.json = JsonParser.parseString(string).getAsJsonObject(); JsonObject newAnimations = new JsonObject(); + for (Map.Entry element : json.get("animations").getAsJsonObject().entrySet()) { animationIds.add(element.getKey()); JsonObject animation = element.getValue().getAsJsonObject(); @@ -77,7 +69,7 @@ public class Animation { } } } - } catch (Throwable t) {} + } catch (Throwable ignored) {} if (end != null && end.has("lerp_mode") && end.get("lerp_mode").getAsString().equals("catmullrom")) { end.addProperty("lerp_mode", "linear"); } @@ -98,31 +90,61 @@ public class Animation { object.addProperty("loop", true); JsonObject bones = new JsonObject(); JsonArray array = geometry.getInternal().get("bones").getAsJsonArray(); + int i = 0; + for (JsonElement element : array) { if (element.isJsonObject()) { String name = element.getAsJsonObject().get("name").getAsString(); String parent = ""; - if (element.getAsJsonObject().has("parent")) { - parent = element.getAsJsonObject().get("parent").getAsString(); - } - if (parent.startsWith("h_") || parent.startsWith("hi_")) { - continue; - } + if (element.getAsJsonObject().has("parent")) parent = element.getAsJsonObject().get("parent").getAsString(); + if (parent.startsWith("h_") || parent.startsWith("hi_")) continue; + if (name.startsWith("h_") || name.startsWith("hi_")) { - bones.add(name, new JsonParser().parse(HEAD_TEMPLATE)); + bones.add(name, JsonParser.parseString(HEAD_TEMPLATE)); i++; } } } - if (i == 0) { - return; - } - GeneratorMain.entityMap - .get(modelId).setHasHeadAnimation(true); + + if (i == 0) return; + + GeneratorMain.entityMap.get(modelId).setHasHeadAnimation(true); object.add("bones", bones); json.get("animations").getAsJsonObject().add("animation." + modelId + ".look_at_target", object); } + + public void setModelId(String modelId) { + this.modelId = modelId; + } + + public void setJson(JsonObject json) { + this.json = json; + } + + public void setAnimationIds(Set animationIds) { + this.animationIds = animationIds; + } + + public String getModelId() { + return modelId; + } + + public void setPath(String path) { + this.path = path; + } + + public JsonObject getJson() { + return json; + } + + public Set getAnimationIds() { + return animationIds; + } + + public String getPath() { + return path; + } } diff --git a/src/main/java/re/imc/geysermodelenginepackgenerator/generator/AnimationController.java b/src/main/java/re/imc/geysermodelenginepackgenerator/generator/AnimationController.java index d49ffd9..0fb66d7 100644 --- a/src/main/java/re/imc/geysermodelenginepackgenerator/generator/AnimationController.java +++ b/src/main/java/re/imc/geysermodelenginepackgenerator/generator/AnimationController.java @@ -30,13 +30,11 @@ public class AnimationController { "transitions": [{ "play": "%query% != 0"}] } } - }"""; + } + """; - @Getter - JsonObject json; - @Setter - @Getter - Entity entity; + private JsonObject json; + private Entity entity; public void load(Animation animation, Entity entity) { JsonObject root = new JsonObject(); @@ -46,18 +44,19 @@ public class AnimationController { JsonObject animationControllers = new JsonObject(); root.add("animation_controllers", animationControllers); - List sorted = new ArrayList<>(animation.animationIds); + List sorted = new ArrayList<>(animation.getAnimationIds()); int i = 0; Collections.sort(sorted); for (String id : sorted) { id = id.replace(" ", "_"); int n = (int) Math.pow(2, (i % 24)); - JsonObject controller = new JsonParser().parse(CONTROLLER_TEMPLATE.replace("%anim%", id).replace("%query%", "math.mod(math.floor(query.property('modelengine:anim" + i / 24 + "') / " + n + "), 2)")).getAsJsonObject(); - animationControllers.add("controller.animation." + animation.modelId + "." + id, controller); + JsonObject controller = JsonParser.parseString(CONTROLLER_TEMPLATE.replace("%anim%", id).replace("%query%", "math.mod(math.floor(query.property('modelengine:anim" + i / 24 + "') / " + n + "), 2)")).getAsJsonObject(); + animationControllers.add("controller.animation." + animation.getModelId() + "." + id, controller); i++; if (entity != null) { boolean blend = entity.getModelConfig().isEnableBlendTransition(); + if (!blend) { for (Map.Entry states : controller.get("states").getAsJsonObject().entrySet()) { states.getValue().getAsJsonObject().remove("blend_transition"); @@ -137,4 +136,20 @@ public class AnimationController { }"""; */ + + public void setJson(JsonObject json) { + this.json = json; + } + + public void setEntity(Entity entity) { + this.entity = entity; + } + + public JsonObject getJson() { + return json; + } + + public Entity getEntity() { + return entity; + } } diff --git a/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Bone.java b/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Bone.java index c31535d..73942b2 100644 --- a/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Bone.java +++ b/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Bone.java @@ -1,23 +1,34 @@ package re.imc.geysermodelenginepackgenerator.generator; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; import java.util.Set; -@AllArgsConstructor -@NoArgsConstructor -@Getter -@Setter public class Bone { - String name; - String parent; - Set children = new HashSet<>(); - Set allChildren = new HashSet<>(); + + private final String name; + private final String parent; + private final Set children; + private final Set allChildren; + + public Bone(String name, String parent, Set children, Set allChildren) { + this.name = name; + this.parent = parent; + this.children = children; + this.allChildren = allChildren; + } + + public String getName() { + return name; + } + + public String getParent() { + return parent; + } + + public Set getChildren() { + return children; + } + + public Set getAllChildren() { + return allChildren; + } } diff --git a/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Entity.java b/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Entity.java index 34d8f3e..9708e4f 100644 --- a/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Entity.java +++ b/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Entity.java @@ -11,14 +11,20 @@ import me.zimzaza4.geyserutils.geyser.GeyserUtils; import java.util.*; -@Getter -@Setter -@AllArgsConstructor -@NoArgsConstructor public class Entity { public static final Set REGISTERED_ENTITIES = new HashSet<>(); + private String modelId; + private JsonObject json; + private boolean hasHeadAnimation = false; + private Animation animation; + private Geometry geometry; + private RenderController renderController; + private String path; + private Map textureMap = new HashMap<>(); + private ModelConfig modelConfig; + public static final String TEMPLATE = """ { "format_version": "1.10.0", @@ -32,7 +38,7 @@ public class Entity { "textures": { }, "geometry": { - + }, "animations": { "look_at_target": "%look_at_target%" @@ -49,31 +55,15 @@ public class Entity { } """; - - String modelId; - JsonObject json; - boolean hasHeadAnimation = false; - Animation animation; - Geometry geometry; - RenderController renderController; - String path; - Map textureMap = new HashMap<>(); - ModelConfig modelConfig; - - - - - public Entity(String modelId) { this.modelId = modelId; } public void modify() { - - json = new JsonParser().parse(TEMPLATE.replace("%entity_id%", modelId) + this.json = JsonParser.parseString(TEMPLATE.replace("%entity_id%", modelId) .replace("%geometry%", "geometry.meg_" + modelId) .replace("%texture%", "textures/entity/" + path + modelId) - .replace("%look_at_target%", modelConfig.isEnableHeadRotation() ? "animation." + modelId + ".look_at_target" : "animation.none") + .replace("%look_at_target%", modelConfig.isEnableHeadRotation() ? "animation." + modelId + ".look_at_target" : "animation.none") .replace("%material%", modelConfig.getMaterial())).getAsJsonObject(); JsonObject description = json.get("minecraft:client_entity").getAsJsonObject().get("description").getAsJsonObject(); @@ -84,7 +74,7 @@ public class Entity { JsonArray jsonRenderControllers = description.get("render_controllers").getAsJsonArray(); - Map materials = getModelConfig().getTextureMaterials(); + Map materials = modelConfig.getTextureMaterials(); materials.forEach(jsonMaterials::addProperty); if (modelConfig.getPerTextureUvSize().isEmpty()) { @@ -93,9 +83,8 @@ public class Entity { } for (String name : textureMap.keySet()) { - if (name.endsWith("_e")) { - continue; - } + if (name.endsWith("_e")) continue; + if (modelConfig.getPerTextureUvSize().containsKey(name)) { Integer[] size = modelConfig.getPerTextureUvSize().getOrDefault(name, new Integer[]{16, 16}); String suffix = size[0] + "_" + size[1]; @@ -104,14 +93,14 @@ public class Entity { jsonTextures.addProperty(name, "textures/entity/" + path + modelId + "/" + name); } - jsonRenderControllers.add("controller.render." + modelId + "_" + name); + jsonRenderControllers.add("controller.render." + modelId + "_" + name); } JsonArray animate = description.get("scripts").getAsJsonObject().get("animate").getAsJsonArray(); if (animation != null) { - for (String animation : animation.animationIds) { + for (String animation : animation.getAnimationIds()) { animation = animation.replace(" ", "_"); String controller = "controller.animation." + modelId + "." + animation; animate.add(animation + "_control"); @@ -122,19 +111,14 @@ public class Entity { } public void register() { - - - String id = "modelengine:" + modelId; boolean registered = REGISTERED_ENTITIES.contains(id); - if (registered) { - return; - } + if (registered) return; + REGISTERED_ENTITIES.add(id); GeyserUtils.addCustomEntity(id); - if (geometry == null) { - return; - } + if (geometry == null) return; + if (!modelConfig.isDisablePartVisibility()) { for (int i = 0; i < Math.ceil(geometry.getBones().size() / 24f); i++) { GeyserUtils.addProperty(id, "modelengine:bone" + i, Integer.class); @@ -142,10 +126,83 @@ public class Entity { } if (animation != null) { - for (int i = 0; i < Math.ceil(animation.animationIds.size() / 24f); i++) { + for (int i = 0; i < Math.ceil(animation.getAnimationIds().size() / 24f); i++) { GeyserUtils.addProperty(id, "modelengine:anim" + i, Integer.class); } } + GeyserUtils.registerProperties(id); } + + public void setModelId(String modelId) { + this.modelId = modelId; + } + + public void setJson(JsonObject json) { + this.json = json; + } + + public void setHasHeadAnimation(boolean hasHeadAnimation) { + this.hasHeadAnimation = hasHeadAnimation; + } + + public void setAnimation(Animation animation) { + this.animation = animation; + } + + public void setGeometry(Geometry geometry) { + this.geometry = geometry; + } + + public void setRenderController(RenderController renderController) { + this.renderController = renderController; + } + + public void setPath(String path) { + this.path = path; + } + + public void setTextureMap(Map textureMap) { + this.textureMap = textureMap; + } + + public void setModelConfig(ModelConfig modelConfig) { + this.modelConfig = modelConfig; + } + + public String getModelId() { + return modelId; + } + + public JsonObject getJson() { + return json; + } + + public boolean isHasHeadAnimation() { + return hasHeadAnimation; + } + + public Animation getAnimation() { + return animation; + } + + public Geometry getGeometry() { + return geometry; + } + + public RenderController getRenderController() { + return renderController; + } + + public String getPath() { + return path; + } + + public Map getTextureMap() { + return textureMap; + } + + public ModelConfig getModelConfig() { + return modelConfig; + } } diff --git a/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Geometry.java b/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Geometry.java index c7fd0a0..a31f074 100644 --- a/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Geometry.java +++ b/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Geometry.java @@ -5,26 +5,20 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import org.geysermc.geyser.api.extension.ExtensionLogger; -import re.imc.geysermodelenginepackgenerator.ExtensionMain; import java.util.*; -@Getter -@Setter -@AllArgsConstructor -@NoArgsConstructor public class Geometry { + private String modelId; + private String geometryId; + private JsonObject json; + private Map bones = new HashMap<>(); - String modelId; - String geometryId; - JsonObject json; - Map bones = new HashMap<>(); + private String path; - String path; public void load(String json) { - this.json = new JsonParser().parse(json).getAsJsonObject(); + this.json = JsonParser.parseString(json).getAsJsonObject(); } public void setId(String id) { geometryId = id; @@ -45,7 +39,6 @@ public class Geometry { } public void modify() { - JsonArray array = getInternal().get("bones").getAsJsonArray(); Iterator iterator = array.iterator(); while (iterator.hasNext()) { @@ -55,23 +48,20 @@ public class Geometry { String parent = element.getAsJsonObject().has("parent") ? element.getAsJsonObject().get("parent").getAsString().toLowerCase() : null; element.getAsJsonObject().remove("name"); - element.getAsJsonObject().addProperty("name", name); - if (name.equals("hitbox") || - name.equals("shadow") || - name.equals("mount") || - name.startsWith("b_") || - name.startsWith("ob_")) { + if (name.equals("hitbox") || name.equals("shadow") || name.equals("mount") || name.startsWith("b_") || name.startsWith("ob_")) { iterator.remove(); - } else bones.put(name, new Bone(name, parent, new HashSet<>(), new HashSet<>())); + } else { + bones.put(name, new Bone(name, parent, new HashSet<>(), new HashSet<>())); + } } for (Bone bone : bones.values()) { - if (bone.parent != null) { - Bone parent = bones.get(bone.parent); + if (bone.getParent() != null) { + Bone parent = bones.get(bone.getParent()); if (parent != null) { - parent.children.add(bone); + parent.getChildren().add(bone); addAllChildren(parent, bone); } } @@ -81,10 +71,46 @@ public class Geometry { } public void addAllChildren(Bone p, Bone c) { - p.allChildren.add(c); - Bone parent = bones.get(p.parent); + p.getAllChildren().add(c); + Bone parent = bones.get(p.getParent()); if (parent != null) { addAllChildren(parent, c); } } + + public void setModelId(String modelId) { + this.modelId = modelId; + } + + public void setGeometryId(String geometryId) { + this.geometryId = geometryId; + } + + public void setJson(JsonObject json) { + this.json = json; + } + + public void setPath(String path) { + this.path = path; + } + + public String getModelId() { + return modelId; + } + + public String getGeometryId() { + return geometryId; + } + + public JsonObject getJson() { + return json; + } + + public String getPath() { + return path; + } + + public Map getBones() { + return bones; + } } diff --git a/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Material.java b/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Material.java index 04df3ba..5043885 100644 --- a/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Material.java +++ b/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Material.java @@ -26,7 +26,7 @@ public class Material { ], "msaaSupport": "Both" }, - + "entity_alphatest_anim_change_color_one_sided:entity_alphatest_change_color_one_sided":{ "+defines":[ "USE_UV_ANIM" diff --git a/src/main/java/re/imc/geysermodelenginepackgenerator/generator/ModelConfig.java b/src/main/java/re/imc/geysermodelenginepackgenerator/generator/ModelConfig.java index 0a0f878..bfdee89 100644 --- a/src/main/java/re/imc/geysermodelenginepackgenerator/generator/ModelConfig.java +++ b/src/main/java/re/imc/geysermodelenginepackgenerator/generator/ModelConfig.java @@ -9,8 +9,6 @@ import java.util.Set; @AllArgsConstructor @NoArgsConstructor -@Getter -@Setter @ToString public class ModelConfig { @@ -31,6 +29,38 @@ public class ModelConfig { @SerializedName("disable_part_visibility") boolean disablePartVisibility = true; + public void setEnableHeadRotation(boolean enableHeadRotation) { + this.enableHeadRotation = enableHeadRotation; + } + + public void setMaterial(String material) { + this.material = material; + } + + public void setEnableBlendTransition(boolean enableBlendTransition) { + this.enableBlendTransition = enableBlendTransition; + } + + public void setBingingBones(Map> bingingBones) { + this.bingingBones = bingingBones; + } + + public void setAnimTextures(Map animTextures) { + this.animTextures = animTextures; + } + + public void setTextureMaterials(Map textureMaterials) { + this.textureMaterials = textureMaterials; + } + + public void setPerTextureUvSize(Map perTextureUvSize) { + this.perTextureUvSize = perTextureUvSize; + } + + public void setDisablePartVisibility(boolean disablePartVisibility) { + this.disablePartVisibility = disablePartVisibility; + } + public Map getTextureMaterials() { return textureMaterials != null ? textureMaterials : Map.of(); } @@ -39,6 +69,30 @@ public class ModelConfig { return perTextureUvSize != null ? perTextureUvSize : Map.of(); } + public boolean isEnableHeadRotation() { + return enableHeadRotation; + } + + public String getMaterial() { + return material; + } + + public boolean isEnableBlendTransition() { + return enableBlendTransition; + } + + public Map> getBingingBones() { + return bingingBones; + } + + public Map getAnimTextures() { + return animTextures; + } + + public boolean isDisablePartVisibility() { + return disablePartVisibility; + } + @NoArgsConstructor @AllArgsConstructor @Getter diff --git a/src/main/java/re/imc/geysermodelenginepackgenerator/generator/PackManifest.java b/src/main/java/re/imc/geysermodelenginepackgenerator/generator/PackManifest.java index 4924699..a3c55c9 100644 --- a/src/main/java/re/imc/geysermodelenginepackgenerator/generator/PackManifest.java +++ b/src/main/java/re/imc/geysermodelenginepackgenerator/generator/PackManifest.java @@ -3,6 +3,7 @@ package re.imc.geysermodelenginepackgenerator.generator; import java.util.UUID; public class PackManifest { + public static final String TEMPLATE = """ { "format_version": 1, diff --git a/src/main/java/re/imc/geysermodelenginepackgenerator/generator/RenderController.java b/src/main/java/re/imc/geysermodelenginepackgenerator/generator/RenderController.java index d7b5ef3..59cf40f 100644 --- a/src/main/java/re/imc/geysermodelenginepackgenerator/generator/RenderController.java +++ b/src/main/java/re/imc/geysermodelenginepackgenerator/generator/RenderController.java @@ -29,11 +29,10 @@ public class RenderController { root.add("render_controllers", renderControllers); Set processedBones = new HashSet<>(); - boolean singleTexture = entity.textureMap.size() == 1 && entity.modelConfig.getPerTextureUvSize().isEmpty(); - for (String key : entity.textureMap.keySet()) { - if (key.endsWith("_e")) { - continue; - } + boolean singleTexture = entity.getTextureMap().size() == 1 && entity.getModelConfig().getPerTextureUvSize().isEmpty(); + for (String key : entity.getTextureMap().keySet()) { + if (key.endsWith("_e")) continue; + // Texture texture = entity.textureMap.get(key); Set uvBonesId = entity.getModelConfig().bingingBones.get(key); @@ -149,11 +148,11 @@ public class RenderController { if (!processedBones.contains(bone) && (uvParent || uvAllBones.contains(boneName) || uvBonesId.contains("*"))) { int index = i; if (boneName.startsWith("uv_")) { - index = sorted.indexOf(bone.parent); + index = sorted.indexOf(bone.getParent()); } int n = (int) Math.pow(2, (index % 24)); - if (entity.modelConfig.isDisablePartVisibility()) { + if (entity.getModelConfig().isDisablePartVisibility()) { visibilityItem.addProperty(boneName, true); } else { visibilityItem.addProperty(boneName, "math.mod(math.floor(query.property('modelengine:bone" + index / 24 + "') / " + n + "), 2) == 1"); diff --git a/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Texture.java b/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Texture.java index c45e38e..35edb5b 100644 --- a/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Texture.java +++ b/src/main/java/re/imc/geysermodelenginepackgenerator/generator/Texture.java @@ -1,22 +1,34 @@ package re.imc.geysermodelenginepackgenerator.generator; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; - -import java.awt.*; -import java.awt.image.BufferedImage; -import java.nio.file.Path; import java.util.Set; -@Getter -@Setter -@AllArgsConstructor public class Texture { - String modelId; - String path; - Set bindingBones; - byte[] image; + private final String modelId; + private final String path; + private final Set bindingBones; + private final byte[] image; + public Texture(String modelId, String path, Set bindingBones, byte[] image) { + this.modelId = modelId; + this.path = path; + this.bindingBones = bindingBones; + this.image = image; + } + + public String getModelId() { + return modelId; + } + + public String getPath() { + return path; + } + + public Set getBindingBones() { + return bindingBones; + } + + public byte[] getImage() { + return image; + } } diff --git a/src/main/java/re/imc/geysermodelenginepackgenerator/managers/ConfigManager.java b/src/main/java/re/imc/geysermodelenginepackgenerator/managers/ConfigManager.java new file mode 100644 index 0000000..7018235 --- /dev/null +++ b/src/main/java/re/imc/geysermodelenginepackgenerator/managers/ConfigManager.java @@ -0,0 +1,20 @@ +package re.imc.geysermodelenginepackgenerator.managers; + +import re.imc.geysermodelenginepackgenerator.util.FileConfiguration; + +public class ConfigManager { + + private FileConfiguration config; + + public ConfigManager() { + load(); + } + + public void load() { + this.config = new FileConfiguration("config.yml"); + } + + public FileConfiguration getConfig() { + return config; + } +} diff --git a/src/main/java/re/imc/geysermodelenginepackgenerator/util/FileConfiguration.java b/src/main/java/re/imc/geysermodelenginepackgenerator/util/FileConfiguration.java new file mode 100644 index 0000000..0c0d05f --- /dev/null +++ b/src/main/java/re/imc/geysermodelenginepackgenerator/util/FileConfiguration.java @@ -0,0 +1,148 @@ +package re.imc.geysermodelenginepackgenerator.util; + +import org.spongepowered.configurate.CommentedConfigurationNode; +import org.spongepowered.configurate.serialize.SerializationException; +import org.spongepowered.configurate.yaml.YamlConfigurationLoader; +import re.imc.geysermodelenginepackgenerator.GeyserModelEnginePackGenerator; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +public class FileConfiguration { + + private final GeyserModelEnginePackGenerator extension = GeyserModelEnginePackGenerator.getExtension(); + + private final Path dataDirectory = extension.dataFolder(); + + protected final String configFile; + private final CommentedConfigurationNode configurationNode; + + public FileConfiguration(String configFile) { + this.configFile = configFile; + this.configurationNode = load(configFile); + } + + public FileConfiguration(CommentedConfigurationNode configurationNode, String configFile) { + this.configFile = configFile; + this.configurationNode = configurationNode; + } + + private CommentedConfigurationNode load(String fileName) { + try { + if (!Files.exists(this.dataDirectory)) Files.createDirectories(this.dataDirectory); + + Path config = this.dataDirectory.resolve(fileName); + + if (!Files.exists(config)) { + try (InputStream resourceAsStream = this.extension.getClass().getClassLoader().getResourceAsStream("Extension/" + fileName)) { + Files.copy(resourceAsStream, config); + } catch (IOException err) { + throw new RuntimeException(err); + } + } + + YamlConfigurationLoader loader = YamlConfigurationLoader.builder().path(config).build(); + + return loader.load(); + } catch (IOException err) { + throw new RuntimeException(err); + } + } + + public FileConfiguration getConfigurationSection(String path) { + CommentedConfigurationNode sectionNode = getConfigurationSectionNode(path); + if (sectionNode == null || sectionNode.virtual()) return null; + return new FileConfiguration(sectionNode, this.configFile); + } + + public String getString(String path) { + CommentedConfigurationNode node = getInternal(path); + if (node == null) return null; + return node.getString(); + } + + public List getStringList(String path) { + CommentedConfigurationNode node = getInternal(path); + if (node == null || node.virtual()) return List.of(); + + try { + return node.getList(String.class, List.of()); + } catch (SerializationException err) { + throw new RuntimeException(err); + } + } + + public int getInt(String path) { + CommentedConfigurationNode node = getInternal(path); + if (node == null) return 0; + return node.getInt(); + } + + public List getIntegerList(String path) { + CommentedConfigurationNode node = getInternal(path); + if (node == null || node.virtual()) return List.of(); + + try { + return node.getList(Integer.class, List.of()); + } catch (SerializationException err) { + throw new RuntimeException(err); + } + } + + public double getDouble(String path) { + CommentedConfigurationNode node = getInternal(path); + if (node == null) return 0; + return node.getDouble(); + } + + public double getLong(String path) { + CommentedConfigurationNode node = getInternal(path); + if (node == null) return 0; + return node.getLong(); + } + + public List getLongList(String path) { + CommentedConfigurationNode node = getInternal(path); + if (node == null || node.virtual()) return List.of(); + + try { + return node.getList(Long.class, List.of()); + } catch (SerializationException err) { + throw new RuntimeException(err); + } + } + + public boolean getBoolean(String path) { + CommentedConfigurationNode node = getInternal(path); + if (node == null) return false; + return node.getBoolean(); + } + + public boolean isBoolean(String path) { + CommentedConfigurationNode node = getInternal(path); + return node != null && node.raw() instanceof Boolean; + } + + private CommentedConfigurationNode getInternal(String path) { + CommentedConfigurationNode node = toSplitRoot(path, this.configurationNode); + if (node.virtual()) return null; + return node; + } + + private CommentedConfigurationNode toSplitRoot(String path, CommentedConfigurationNode node) { + if (path == null) return node; + path = path.startsWith(".") ? path.substring(1) : path; + return node.node(path.contains(".") ? path.split("\\.") : new Object[]{path}); + } + + private CommentedConfigurationNode getConfigurationSectionNode(String path) { + return getInternal(path); + } + + public CommentedConfigurationNode getRootNode() { + return configurationNode; + } +} diff --git a/src/main/resources/Extension/config.yml b/src/main/resources/Extension/config.yml new file mode 100644 index 0000000..6d7b1e0 --- /dev/null +++ b/src/main/resources/Extension/config.yml @@ -0,0 +1,4 @@ + +options: + resource-pack: + auto-load: true \ No newline at end of file diff --git a/src/main/resources/extension.yml b/src/main/resources/extension.yml index a3de91a..cdb398c 100644 --- a/src/main/resources/extension.yml +++ b/src/main/resources/extension.yml @@ -1,6 +1,6 @@ name: GeyserModelEnginePackGenerator id: geysermodelenginepackgenerator -main: re.imc.geysermodelenginepackgenerator.ExtensionMain -api: 1.0.0 +main: re.imc.geysermodelenginepackgenerator.GeyserModelEnginePackGenerator +api: 2.7.0 version: 1.0.0 authors: [zimzaza4] \ No newline at end of file