diff --git a/.gitignore b/.gitignore index a5b1113..b7bcba5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,10 @@ +.idea .gradle **/build/ !src/**/build/ +**/test/kotlin/pack + # Ignore Gradle GUI config gradle-app.setting diff --git a/README.md b/README.md index 0290ebd..0570682 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # solid-api ![Maven Central Version](https://img.shields.io/maven-central/v/io.github.solid-resourcepack/solid-api?style=flat) ![CodeFactor Grade](https://img.shields.io/codefactor/grade/github/solid-resourcepack/solid-api) -A library built on top of [creative](https://github.com/unnamed/creative) to make resource pack generation simpler. -Visit the [Wiki]() to learn more +A (currently) read only API for minecraft resource packs. > Documentation is still work in progress diff --git a/build.gradle.kts b/build.gradle.kts index ead7e44..c2d5ba3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,12 +4,12 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { alias(libs.plugins.shadow) alias(libs.plugins.kotlin) - alias(libs.plugins.sonatypeCentralPortalPublisher) + alias(libs.plugins.sonatype.central.portal.publisher) `maven-publish` } group = "io.github.solid-resourcepack" -version = "1.0.12" +version = "1.1.0" repositories { mavenCentral() @@ -18,11 +18,10 @@ repositories { } dependencies { - testImplementation(rootProject.libs.kotlinTest) - implementation(rootProject.libs.kotlinJvm) - compileOnly(libs.paper) - api(libs.solidMaterial) - api(libs.bundles.creative) + testImplementation(rootProject.libs.kotlin.test) + implementation(rootProject.libs.kotlin.jvm) + implementation(rootProject.libs.bundles.configurate) + api(rootProject.libs.adventure) } kotlin { @@ -40,9 +39,6 @@ tasks.named("shadowJar", ShadowJar::class) { tasks.test { useJUnitPlatform() - dependencies { - implementation(libs.paper) - } } publishing { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d1e3d61..e5064b8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,28 +2,25 @@ kotlin = "1.9.20" kotlinCoroutines = "1.4.2" shadow = "8.1.1" -paper = "1.21-R0.1-SNAPSHOT" -creative = "1.7.2" sonatypeCentralPortalPublisher = "1.2.3" -solidMaterial = "1.21-1.1.1" +configurate = "4.2.0" +adventure = "4.19.0" [libraries] -kotlinJvm = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin" } -kotlinTest = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } -kotlinCoroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinCoroutines" } -paper = { module = "io.papermc.paper:paper-api", version.ref = "paper" } - -creativeApi = { module = "team.unnamed:creative-api", version.ref = "creative" } -creativeSerializer = { module = "team.unnamed:creative-serializer-minecraft", version.ref = "creative" } -solidMaterial = { module = "io.github.solid-resourcepack:solid-material-api", version.ref = "solidMaterial" } +kotlin-jvm = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin" } +kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } +kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinCoroutines" } +configurate = { module = "org.spongepowered:configurate-gson", version.ref = "configurate" } +configurate-extra-kotlin = { module = "org.spongepowered:configurate-extra-kotlin", version.ref = "configurate" } +adventure = { module = "net.kyori:adventure-api", version.ref = "adventure" } [bundles] -creative = [ - "creativeApi", - "creativeSerializer" +configurate = [ + "configurate", + "configurate-extra-kotlin" ] [plugins] kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" } -sonatypeCentralPortalPublisher = { id = "net.thebugmc.gradle.sonatype-central-portal-publisher", version.ref = "sonatypeCentralPortalPublisher" } \ No newline at end of file +sonatype-central-portal-publisher = { id = "net.thebugmc.gradle.sonatype-central-portal-publisher", version.ref = "sonatypeCentralPortalPublisher" } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e644113 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..a441313 --- /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.8-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..b740cf1 --- /dev/null +++ b/gradlew @@ -0,0 +1,249 @@ +#!/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/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 "${APP_HOME:-./}" > /dev/null && pwd -P ) || 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, 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..25da30d --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,92 @@ +@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=. +@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/src/main/kotlin/io/github/solid/resourcepack/api/builder/AdvancedResourcePack.kt b/src/main/kotlin/io/github/solid/resourcepack/api/builder/AdvancedResourcePack.kt deleted file mode 100644 index 9e75c53..0000000 --- a/src/main/kotlin/io/github/solid/resourcepack/api/builder/AdvancedResourcePack.kt +++ /dev/null @@ -1,55 +0,0 @@ -package io.github.solid.resourcepack.api.builder - -import io.github.solid.resourcepack.api.builder.feature.* -import io.github.solid.resourcepack.api.mappings.ModelMapper -import net.kyori.adventure.key.Key -import team.unnamed.creative.BuiltResourcePack -import team.unnamed.creative.ResourcePack -import team.unnamed.creative.model.Model -import team.unnamed.creative.serialize.minecraft.MinecraftResourcePackWriter - -class AdvancedResourcePack( - val resourcePack: ResourcePack -) { - inline fun > apply(config: Config): Return { - return Feature::class.java.getDeclaredConstructor().newInstance().apply(config, resourcePack) - } - - fun apply(config: SolidModelConfig) { - apply(config) - } - - fun apply(config: ModelModifierConfig) { - return apply(config) - } - - fun apply(config: ModelVariantConfig): Key { - return apply(config) - } - - fun apply(config: PredicateConfig) { - apply(config) - } - - - fun map(mapper: ModelMapper<*>) { - map(mapper, Filters.MINECRAFT_FILTER) - } - - fun map(mapper: ModelMapper<*>, vararg filters: (Model) -> Boolean) { - resourcePack.models().filter { model -> filters.all { it(model) } }.forEach { model -> - model.overrides().forEach { - mapper.register(it.model(), it.predicate()) - } - } - } - - - fun build(): BuiltResourcePack { - return MinecraftResourcePackWriter.builder().prettyPrinting(true).build().build(resourcePack) - } - - object Filters { - val MINECRAFT_FILTER: (Model) -> Boolean = { model -> model.key().namespace() == Key.MINECRAFT_NAMESPACE } - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/builder/ResourcePackFeature.kt b/src/main/kotlin/io/github/solid/resourcepack/api/builder/ResourcePackFeature.kt deleted file mode 100644 index 733c2d9..0000000 --- a/src/main/kotlin/io/github/solid/resourcepack/api/builder/ResourcePackFeature.kt +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.solid.resourcepack.api.builder - -import team.unnamed.creative.ResourcePack - -interface ResourcePackFeature { - fun apply(config: Config, pack: ResourcePack): Return -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/builder/config/ConfigBuilder.kt b/src/main/kotlin/io/github/solid/resourcepack/api/builder/config/ConfigBuilder.kt deleted file mode 100644 index 78e36bc..0000000 --- a/src/main/kotlin/io/github/solid/resourcepack/api/builder/config/ConfigBuilder.kt +++ /dev/null @@ -1,5 +0,0 @@ -package io.github.solid.resourcepack.api.builder.config - -interface ConfigBuilder { - fun build(): Config -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/builder/config/ModelModifierBuilder.kt b/src/main/kotlin/io/github/solid/resourcepack/api/builder/config/ModelModifierBuilder.kt deleted file mode 100644 index 1a78106..0000000 --- a/src/main/kotlin/io/github/solid/resourcepack/api/builder/config/ModelModifierBuilder.kt +++ /dev/null @@ -1,49 +0,0 @@ -package io.github.solid.resourcepack.api.builder.config - -import io.github.solid.resourcepack.api.builder.feature.ModelModifierConfig -import net.kyori.adventure.key.Key -import team.unnamed.creative.base.Writable - -object ModelModifier { - fun simple(key: Key, data: Writable): ModelModifierConfig { - return ModelModifierBuilder().key(key).data(data).mapper(Mapper.GENERIC_WRAPPER).build() - } - fun abstract(key: Key, data: Writable): ModelModifierConfig { - return ModelModifierBuilder().key(key).data(data).mapper(Mapper.ABSTRACT_WRAPPER).build() - } - - fun builder(): ModelModifierBuilder { - return ModelModifierBuilder() - } - - object Mapper { - val ABSTRACT_WRAPPER: (String) -> String = { key -> "#$key" } - val GENERIC_WRAPPER: (String) -> String = { "#layer0" } - } -} - -class ModelModifierBuilder : ConfigBuilder { - - private lateinit var key: Key - private lateinit var data: Writable - private lateinit var mapper: (String) -> String - - fun key(key: Key): ModelModifierBuilder { - this.key = key - return this - } - - fun data(data: Writable): ModelModifierBuilder { - this.data = data - return this - } - - fun mapper(mapper: (String) -> String): ModelModifierBuilder { - this.mapper = mapper - return this - } - - override fun build(): ModelModifierConfig { - return ModelModifierConfig(key, data, mapper) - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/builder/config/ModelVariantBuilder.kt b/src/main/kotlin/io/github/solid/resourcepack/api/builder/config/ModelVariantBuilder.kt deleted file mode 100644 index c674e8e..0000000 --- a/src/main/kotlin/io/github/solid/resourcepack/api/builder/config/ModelVariantBuilder.kt +++ /dev/null @@ -1,67 +0,0 @@ -package io.github.solid.resourcepack.api.builder.config - -import io.github.solid.resourcepack.api.builder.feature.ModelVariantConfig -import net.kyori.adventure.key.Key -import team.unnamed.creative.base.Writable -import team.unnamed.creative.model.ModelTexture -import team.unnamed.creative.texture.Texture - - -object ModelVariant { - fun generic(target: Key, texture: Key): ModelVariantConfig { - return ModelVariantBuilder().target(target).key(texture).textures(Textures.generic(texture)).build() - } - fun generic(target: Key, texture: Texture): ModelVariantConfig { - return ModelVariantBuilder().target(target).key(texture.key()).texturesWithData(Textures.generic(texture)).build() - } - fun builder(): ModelVariantBuilder { - return ModelVariantBuilder() - } - - object Textures { - fun generic(texture: Key): Map { - return mapOf("layer0" to texture) - } - - fun generic(texture: Texture): Map { - return mapOf("layer0" to texture) - } - } -} - -class ModelVariantBuilder: ConfigBuilder { - private lateinit var target: Key - private lateinit var key: Key - - private val textures: MutableMap = mutableMapOf() - private val textureData: MutableMap = mutableMapOf() - - fun target(target: Key): ModelVariantBuilder { - this.target = target - return this - } - - fun key(key: Key): ModelVariantBuilder { - this.key = key - return this - } - - fun texture(layer: String, key: Key): ModelVariantBuilder { - this.textures[layer] = ModelTexture.ofKey(key) - return this - } - - fun textures(textures: Map): ModelVariantBuilder { - this.textures.putAll(textures.map { it.key to ModelTexture.ofKey(it.value) }) - return this - } - - fun texturesWithData(textures: Map): ModelVariantBuilder { - this.textures.putAll(textures.map { it.key to ModelTexture.ofKey(Key.key(it.value.key().namespace(), it.value.key().value().replace(".png", ""))) }) - this.textureData.putAll(textures.map { it.value.key() to it.value.data() }) - return this - } - override fun build(): ModelVariantConfig { - return ModelVariantConfig(target, key, textures, textureData) - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/builder/config/PredicateBuilder.kt b/src/main/kotlin/io/github/solid/resourcepack/api/builder/config/PredicateBuilder.kt deleted file mode 100644 index e06345a..0000000 --- a/src/main/kotlin/io/github/solid/resourcepack/api/builder/config/PredicateBuilder.kt +++ /dev/null @@ -1,102 +0,0 @@ -package io.github.solid.resourcepack.api.builder.config - -import io.github.solid.resourcepack.api.builder.feature.PredicateConfig -import io.github.solid.resourcepack.api.predicate.PredicateIncrementor -import io.github.solid.resourcepack.api.predicate.PredicateIncrementorType -import io.github.solid.resourcepack.material.SolidBlockMaterial -import io.github.solid.resourcepack.material.SolidMaterial -import net.kyori.adventure.key.Key - - -object Predicate { - fun builder(): PredicateBuilder { - return PredicateBuilder() - } - - fun mushroomBlock(): PredicateBuilder { - return builder().key(Key.key(Key.MINECRAFT_NAMESPACE, "block/mushroom_block")) - .type(PredicateIncrementorType.MUSHROOM_BLOCK).parent(Key.key(Key.MINECRAFT_NAMESPACE, "block/cube_all")) - } - - fun chorusFlower(): PredicateBuilder { - return builder().key(Key.key(Key.MINECRAFT_NAMESPACE, "block/chorus_flower")) - .type(PredicateIncrementorType.CHORUS_FLOWER) - .parent(Key.key(Key.MINECRAFT_NAMESPACE, "block/template_chorus_flower")).textures( - mapOf("texture" to Key.key(Key.MINECRAFT_NAMESPACE, "block/chorus_flower")) - ) - } - - fun customModelData(material: SolidMaterial): PredicateBuilder { - return builder().type(PredicateIncrementorType.CUSTOM_MODEL_DATA).target(material) - } - - fun customModelData(): PredicateBuilder { - return builder().type(PredicateIncrementorType.CUSTOM_MODEL_DATA) - } - - fun noteBlock(): PredicateBuilder { - return builder().type(PredicateIncrementorType.NOTE_BLOCK).target(SolidBlockMaterial.NOTE_BLOCK.toGeneric()) - } -} - -class PredicateBuilder : ConfigBuilder { - - private var target: SolidMaterial? = null - private val textures = mutableMapOf() - private var key: Key? = null - private var parent: Key? = null - private lateinit var incrementor: PredicateIncrementor - private val models: MutableList = mutableListOf() - - fun target(target: SolidMaterial): PredicateBuilder { - this.target = target - return this - } - - fun key(key: Key): PredicateBuilder { - this.key = key - return this - } - - fun textures(textures: Map): PredicateBuilder { - this.textures.putAll(textures) - return this - } - - fun parent(parent: Key): PredicateBuilder { - this.parent = parent - return this - } - - fun type(type: PredicateIncrementorType): PredicateBuilder { - this.incrementor = PredicateIncrementor(type.predicates) - return this - } - - fun incrementor(incrementor: PredicateIncrementor): PredicateBuilder { - this.incrementor = incrementor - return this - } - - fun models(vararg models: Key): PredicateBuilder { - this.models.addAll(models) - return this - } - - fun models(models: Collection): PredicateBuilder { - this.models.addAll(models) - return this - } - - override fun build(): PredicateConfig { - if (target == null) { - target = SolidMaterial(key!!, parent, textures) - } - - return PredicateConfig( - target = target!!, - models = models, - incrementor = incrementor - ) - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/builder/config/SolidModelBuilder.kt b/src/main/kotlin/io/github/solid/resourcepack/api/builder/config/SolidModelBuilder.kt deleted file mode 100644 index f42244a..0000000 --- a/src/main/kotlin/io/github/solid/resourcepack/api/builder/config/SolidModelBuilder.kt +++ /dev/null @@ -1,137 +0,0 @@ -package io.github.solid.resourcepack.api.builder.config - -import io.github.solid.resourcepack.api.builder.feature.SolidModelConfig -import io.github.solid.resourcepack.api.predicate.PredicateIncrementor -import io.github.solid.resourcepack.api.predicate.PredicateIncrementorType -import io.github.solid.resourcepack.material.SolidItemMaterial -import io.github.solid.resourcepack.material.SolidMaterial -import net.kyori.adventure.key.Key -import team.unnamed.creative.base.Writable -import team.unnamed.creative.texture.Texture - -object SolidModel { - - fun itemModel(target: SolidItemMaterial, model: Key): SolidModelBuilder { - return SolidModelBuilder().target(target.toGeneric()).key(model).incrementor(PredicateIncrementorType.CUSTOM_MODEL_DATA) - } - - fun itemModel(target: SolidItemMaterial, model: Key, writable: Writable): SolidModelBuilder { - return SolidModelBuilder().target(target.toGeneric()).key(model).data(writable) - .incrementor(PredicateIncrementorType.CUSTOM_MODEL_DATA) - } - - fun itemModel(target: SolidItemMaterial, vararg textures: Texture): SolidModelBuilder { - return SolidModelBuilder().target(target.toGeneric()).variants(*textures) - .incrementor(PredicateIncrementorType.CUSTOM_MODEL_DATA) - } - - fun builder(): SolidModelBuilder { - return SolidModelBuilder() - } - -} - -class SolidModelBuilder : ConfigBuilder { - - private lateinit var key: Key - private var writable: Writable? = null - - private var target: SolidMaterial? = null - private var targetKey: Key? = null - private var targetParent: Key? = null - private val targetTextures: MutableMap = mutableMapOf() - - private val variants = mutableMapOf>() - private var mapper: ((String) -> String)? = null - private lateinit var incrementor: PredicateIncrementor - - fun data(data: Writable): SolidModelBuilder { - this.writable = data - return this - } - - fun key(key: Key): SolidModelBuilder { - this.key = key - return this - } - - fun target(target: SolidMaterial): SolidModelBuilder { - this.target = target - return this - } - - fun targetKey(target: Key): SolidModelBuilder { - this.targetKey = target - return this - } - - fun targetParent(parent: Key): SolidModelBuilder { - this.targetParent = parent - return this - } - - fun targetTexture(layer: String, texture: Key): SolidModelBuilder { - this.targetTextures[layer] = texture - return this - } - - fun targetTextures(textures: Map): SolidModelBuilder { - this.targetTextures.putAll(textures) - return this - } - - fun variants(vararg textures: Texture): SolidModelBuilder { - - this.variants.putAll(textures.map { Key.key(it.key().namespace(), it.key().value().replace(".png", "")) to ModelVariant.Textures.generic(it) }) - return this - } - - fun variant(key: Key, textures: Map): SolidModelBuilder { - this.variants[key] = textures - return this - } - - fun variants(variants: Map>): SolidModelBuilder { - this.variants.putAll(variants) - return this - } - - fun incrementor(incrementor: PredicateIncrementor): SolidModelBuilder { - this.incrementor = incrementor - return this - } - - fun incrementor(type: PredicateIncrementorType): SolidModelBuilder { - this.incrementor = PredicateIncrementor(type.predicates) - return this - } - - fun abstract(): SolidModelBuilder { - this.mapper = ModelModifier.Mapper.ABSTRACT_WRAPPER - return this - } - - fun generic(): SolidModelBuilder { - this.mapper = ModelModifier.Mapper.GENERIC_WRAPPER - return this - } - - fun mapper(mapper: (String) -> String): SolidModelBuilder { - this.mapper = mapper - return this - } - - override fun build(): SolidModelConfig { - if (this.target == null) { - this.target = SolidMaterial(this.key, this.targetParent, this.targetTextures) - } - return SolidModelConfig( - writable = writable, - target = target!!, - key = key, - incrementor = incrementor, - mapper = mapper, - variants = variants - ) - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/builder/feature/ModelModifierFeature.kt b/src/main/kotlin/io/github/solid/resourcepack/api/builder/feature/ModelModifierFeature.kt deleted file mode 100644 index 0a096b1..0000000 --- a/src/main/kotlin/io/github/solid/resourcepack/api/builder/feature/ModelModifierFeature.kt +++ /dev/null @@ -1,34 +0,0 @@ -package io.github.solid.resourcepack.api.builder.feature - -import com.google.gson.Gson -import com.google.gson.JsonObject -import io.github.solid.resourcepack.api.builder.ResourcePackFeature -import net.kyori.adventure.key.Key -import team.unnamed.creative.ResourcePack -import team.unnamed.creative.base.Writable - -class ModelModifierFeature : ResourcePackFeature { - - private val gson = Gson() - override fun apply(config: ModelModifierConfig, pack: ResourcePack) { - if(pack.model(config.key) != null) return - val model = gson.fromJson(config.data.toUTF8String(), JsonObject::class.java) - val obj = model.get("textures").asJsonObject - val map = obj.asMap() - map.keys.forEach { obj.addProperty(it, config.mapper(it)) } - model.add("textures", obj) - val modified = Writable.stringUtf8(Gson().toJson(model)) - pack.unknownFile("assets/${config.key.namespace()}/models/${config.key.value()}.json", modified) - } - - object Mappers { - val ABSTRACT_WRAPPER: (String) -> String = { key -> "#$key" } - val SIMPLE_WRAPPER: (String) -> String = { "#layer0" } - } -} - -data class ModelModifierConfig( - val key: Key, - val data: Writable, - val mapper: (String) -> String -) diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/builder/feature/ModelVariantFeature.kt b/src/main/kotlin/io/github/solid/resourcepack/api/builder/feature/ModelVariantFeature.kt deleted file mode 100644 index 5704321..0000000 --- a/src/main/kotlin/io/github/solid/resourcepack/api/builder/feature/ModelVariantFeature.kt +++ /dev/null @@ -1,30 +0,0 @@ -package io.github.solid.resourcepack.api.builder.feature - -import io.github.solid.resourcepack.api.builder.ResourcePackFeature -import net.kyori.adventure.key.Key -import team.unnamed.creative.ResourcePack -import team.unnamed.creative.base.Writable -import team.unnamed.creative.model.Model -import team.unnamed.creative.model.ModelTexture -import team.unnamed.creative.model.ModelTextures -import team.unnamed.creative.texture.Texture - -class ModelVariantFeature : ResourcePackFeature { - override fun apply(config: ModelVariantConfig, pack: ResourcePack): Key { - config.textureData.forEach { data -> - if(pack.texture(data.key) == null) - pack.texture(Texture.texture(data.key, data.value)) - } - val model = Model.model().key(config.key).parent(config.target) - .textures(ModelTextures.builder().variables(config.textures).build()) - pack.model(model.build()) - return config.key - } -} - -data class ModelVariantConfig( - val target: Key, - val key: Key, - val textures: Map, - val textureData: Map -) \ No newline at end of file diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/builder/feature/PredicateFeature.kt b/src/main/kotlin/io/github/solid/resourcepack/api/builder/feature/PredicateFeature.kt deleted file mode 100644 index f96bf50..0000000 --- a/src/main/kotlin/io/github/solid/resourcepack/api/builder/feature/PredicateFeature.kt +++ /dev/null @@ -1,39 +0,0 @@ -package io.github.solid.resourcepack.api.builder.feature - -import io.github.solid.resourcepack.api.builder.ResourcePackFeature -import io.github.solid.resourcepack.api.predicate.PredicateGenerator -import io.github.solid.resourcepack.api.predicate.PredicateIncrementor -import io.github.solid.resourcepack.material.SolidMaterial -import net.kyori.adventure.key.Key -import team.unnamed.creative.ResourcePack -import team.unnamed.creative.model.Model -import team.unnamed.creative.model.ModelTexture -import team.unnamed.creative.model.ModelTextures - -class PredicateFeature : ResourcePackFeature { - override fun apply(config: PredicateConfig, pack: ResourcePack) { - val model = pack.model(config.target.key) ?: Model.model().parent(config.target.parent) - .key(config.target.key).textures( - ModelTextures.builder().let { - config.target.textures.forEach { texture -> - it.addVariable( - texture.key, - ModelTexture.ofKey(texture.value) - ) - }; it.build() - } - ).build() - val overrides = model.overrides().toList() - val incrementor = config.incrementor - val generator = PredicateGenerator(incrementor) - model.overrides().clear() - model.overrides().addAll(generator.generate(overrides, config.models)) - pack.model(model) - } -} - -data class PredicateConfig( - val models: List, - val target: SolidMaterial, - val incrementor: PredicateIncrementor -) \ No newline at end of file diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/builder/feature/SolidModelFeature.kt b/src/main/kotlin/io/github/solid/resourcepack/api/builder/feature/SolidModelFeature.kt deleted file mode 100644 index 0b0f05b..0000000 --- a/src/main/kotlin/io/github/solid/resourcepack/api/builder/feature/SolidModelFeature.kt +++ /dev/null @@ -1,77 +0,0 @@ -package io.github.solid.resourcepack.api.builder.feature - -import io.github.solid.resourcepack.api.builder.ResourcePackFeature -import io.github.solid.resourcepack.api.builder.config.ModelModifier -import io.github.solid.resourcepack.api.builder.config.ModelVariant -import io.github.solid.resourcepack.api.builder.config.Predicate -import io.github.solid.resourcepack.api.predicate.PredicateIncrementor -import io.github.solid.resourcepack.material.SolidMaterial -import net.kyori.adventure.key.Key -import team.unnamed.creative.ResourcePack -import team.unnamed.creative.base.Writable -import team.unnamed.creative.texture.Texture - -class SolidModelFeature : ResourcePackFeature { - override fun apply(config: SolidModelConfig, pack: ResourcePack) { - var parentKey = config.key - val models = pack.model(config.key)?.let { mutableListOf(it.key()) } ?: mutableListOf() - - if (config.mapper != null && config.writable != null) { - models.clear() - parentKey = Key.key(config.key.namespace(), config.key.value() + "_abstract") - ModelModifier.builder().key(parentKey).data(config.writable).mapper(config.mapper).build().let { - ModelModifierFeature().apply(it, pack) - } - } else if (config.writable != null) { - pack.unknownFile( - "assets/${config.key.namespace()}/models/${config.key.value()}.json", config.writable - ) - } - - if (config.variants.isNotEmpty()) { - models.clear() - config.variants.forEach { (key, variant) -> - ModelVariant.builder().key(key).target(parentKey).texturesWithData(variant).build().let { - ModelVariantFeature().apply(it, pack).let { model -> models.add(model.key()) } - } - } - } - val predicateBuilder = - Predicate.builder().target(config.target).incrementor(config.incrementor).models(models) - PredicateFeature().apply(predicateBuilder.build(), pack) - } -} - -data class SolidModelConfig( - - /** - * Data in the model to possibly add - */ - val writable: Writable?, - - /** - * The target minecraft model to apply the changes to - */ - val target: SolidMaterial, - - /** - * The key of this model - */ - val key: Key, - - /** - * The mapper mapping the textures of - */ - val mapper: ((String) -> String)?, - - /** - * The incrementor to use for the predicate of the target model - */ - val incrementor: PredicateIncrementor, - - /** - * The texture variants of this model, also applied on the target model. - * If not empty, the key will be treated as an abstract model and not be added to the target model - */ - val variants: Map> -) \ No newline at end of file diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/key/SolidKey.kt b/src/main/kotlin/io/github/solid/resourcepack/api/key/SolidKey.kt deleted file mode 100644 index e99360d..0000000 --- a/src/main/kotlin/io/github/solid/resourcepack/api/key/SolidKey.kt +++ /dev/null @@ -1,38 +0,0 @@ -package io.github.solid.resourcepack.api.key - -import net.kyori.adventure.key.Key -import org.bukkit.Material -import org.jetbrains.annotations.ApiStatus.Experimental - - -object SolidKey { - - /** - * ONLY WORKS WHEN USED IN A MINECRAFT SERVER CONTEXT - */ - @Experimental - fun from(material: Material): Key { - val keyType: KeyType = if (material.isBlock) { - KeyType.BLOCK - } else if (material.isItem) { - KeyType.ITEM - } else { - throw IllegalArgumentException("Material is not supported") - } - return from(material, keyType) - } - - fun from(material: Material, keyType: KeyType): Key { - return Key.key(Key.MINECRAFT_NAMESPACE, "${keyType.name.lowercase()}/${material.name.lowercase()}") - } - - val ITEM_GENERATED = Key.key(Key.MINECRAFT_NAMESPACE, "item/generated") - val ITEM_HANDHELD = Key.key(Key.MINECRAFT_NAMESPACE, "item/handheld") - val CUBE_ALL = Key.key(Key.MINECRAFT_NAMESPACE, "block/cube_all") -} - - -enum class KeyType { - ITEM, - BLOCK -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/link/ModelLinkCollector.kt b/src/main/kotlin/io/github/solid/resourcepack/api/link/ModelLinkCollector.kt new file mode 100644 index 0000000..4eeba95 --- /dev/null +++ b/src/main/kotlin/io/github/solid/resourcepack/api/link/ModelLinkCollector.kt @@ -0,0 +1,164 @@ +package io.github.solid.resourcepack.api.link + +import io.github.solid.resourcepack.api.link.legacy.LegacyResourcePackItemLink +import io.github.solid.resourcepack.api.link.modern.ModernResourcePackLink +import io.github.solid.resourcepack.api.meta.PackMeta +import io.github.solid.resourcepack.api.util.* +import io.leangen.geantyref.TypeToken +import net.kyori.adventure.key.Key +import org.spongepowered.configurate.gson.GsonConfigurationLoader +import org.spongepowered.configurate.kotlin.extensions.get +import org.spongepowered.configurate.kotlin.objectMapperFactory +import java.nio.file.Path +import java.nio.file.Paths +import kotlin.io.path.exists +import kotlin.io.path.isDirectory +import kotlin.io.path.listDirectoryEntries +import kotlin.io.path.relativeTo + + +class ModelLinkCollector(private val packPath: Path) : ModelLinkHolder { + + private fun toModelPath(key: Key): Path { + return Paths.get(key.namespace(), "models", key.value() + ".json") + } + + private fun toModelKey(path: Path): Key { + return Key.key( + path.subpath(0, 1).toString(), + path.subpath(2, path.nameCount).toString().replace("\\", "/").replace(".json", "") + ) + } + + override fun collect(): List { + val result = mutableListOf() + result.addAll(collectModern()) + result.combine(collectLegacy()) { first, second -> + first.key == second.key + } + result.combine(collectOverlays()) { first, second -> + first.key == second.key + } + return result + } + + private fun collectOverlays(): List { + val returned = mutableListOf() + val metaPath = packPath.resolve("pack.mcmeta") + if (!metaPath.exists()) return returned + val meta = readModel(metaPath) ?: return returned + meta.overlays.entries.forEach { overlay -> + if (overlay.formats == null || overlay.directory == null) return@forEach + val version = overlay.formats.start + val results: List = if (version >= 46) { + collectModern( + listOf( + Paths.get("assets"), + Paths.get(overlay.directory, "assets") + ) + ) + } else { + collectLegacy( + listOf(Paths.get("assets"), Paths.get(overlay.directory, "assets")), + Path.of(overlay.directory, "assets", "minecraft", "models") + ) + } + returned.addAll(results) + } + return returned + } + + private fun collectLegacy(basePaths: List, modelPath: Path, type: ModelType): List { + val result = mutableListOf() + val linkModels = packPath.resolve(Paths.get(modelPath.toString(), type.name.lowercase())) + if (!linkModels.exists()) return result + linkModels.listDirectoryEntries("*.json").forEach { definition -> + if (!definition.exists()) return@forEach + try { + val parsed = readModel(definition) + parsed?.collect()?.map { + ModelLink( + it.key, + toModelKey(definition.relativeTo(packPath.resolve(basePaths[0]))), + predicates = it.predicates + ) + }?.let { + result.addAll(it.filter { m -> + basePaths.any { path -> packPath.resolve(path).resolve(toModelPath(m.key)).exists() } + }) + } + } catch (e: Exception) { + e.printStackTrace() + } + } + return result + } + + private fun collectLegacy( + basePath: List = listOf(Paths.get("assets")), + modelPath: Path = Paths.get("assets", "minecraft", "models") + ): List { + val result = mutableListOf() + ModelType.entries.forEach { type -> result.addAll(collectLegacy(basePath, modelPath, type)) } + return result + } + + private fun collectModern(basePaths: List, path: Path): List { + val result = mutableListOf() + val items = path.resolve("items") + if (!items.exists()) return result + items.listDirectoryEntries("*.json").forEach itemForEach@{ definition -> + if (!definition.exists()) return@itemForEach + try { + val parsed = readModel(definition) + parsed?.collect()?.let { + result.addAll(it.filter { m -> + basePaths.any { path -> packPath.resolve(path).resolve(toModelPath(m.key)).exists() } + }) + } + } catch (e: Exception) { + e.printStackTrace() + } + } + return result + } + + private fun collectModern(basePaths: List = listOf(Paths.get("assets"))): List { + val result = mutableListOf() + basePaths.map { packPath.resolve(it) }.forEach { + if (!it.exists()) return@forEach + it.listDirectoryEntries().filter { it.isDirectory() }.forEach { namespace -> + result.addAll(collectModern(basePaths, namespace)) + } + } + return result + } + + + private fun MutableList.combine(other: List, check: (first: T, second: T) -> Boolean): List { + other.forEach { element -> + val found = this.find { check(element, it) }?.let { this.indexOf(it) } + if (found == null) { + this.add(element) + return@forEach + } + this.removeAt(found) + this.add(found, element) + } + return this + } + + private inline fun readModel(path: Path): T? { + val loader = GsonConfigurationLoader.builder().path(path).defaultOptions { options -> + options.serializers { serializers -> + serializers.registerAnnotatedObjects(objectMapperFactory()) + serializers.register(Enum::class.java, GenericEnumSerializer) + serializers.register(Key::class.java, KeySerializer) + serializers.register(Range::class.java, RangeSerializer) + serializers.register(object : TypeToken>() {}, MapSerializer) + } + }.build() + return loader.load().get() + } + +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/link/ModelLinkHolder.kt b/src/main/kotlin/io/github/solid/resourcepack/api/link/ModelLinkHolder.kt new file mode 100644 index 0000000..4159552 --- /dev/null +++ b/src/main/kotlin/io/github/solid/resourcepack/api/link/ModelLinkHolder.kt @@ -0,0 +1,19 @@ +package io.github.solid.resourcepack.api.link + +import net.kyori.adventure.key.Key + +interface ModelLinkHolder { + fun collect(): List +} + +data class ModelLink( + val key: Key, + val parent: Key? = null, + val predicates: Map? = null, + val modelType: ModelType = ModelType.ITEM, +) + +enum class ModelType { + ITEM, + BLOCK; +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/predicate/PredicateIncrementor.kt b/src/main/kotlin/io/github/solid/resourcepack/api/link/PredicateIncrementor.kt similarity index 87% rename from src/main/kotlin/io/github/solid/resourcepack/api/predicate/PredicateIncrementor.kt rename to src/main/kotlin/io/github/solid/resourcepack/api/link/PredicateIncrementor.kt index a1a7f7f..622560a 100644 --- a/src/main/kotlin/io/github/solid/resourcepack/api/predicate/PredicateIncrementor.kt +++ b/src/main/kotlin/io/github/solid/resourcepack/api/link/PredicateIncrementor.kt @@ -1,8 +1,7 @@ -package io.github.solid.resourcepack.api.predicate +package io.github.solid.resourcepack.api.link +import io.github.solid.resourcepack.api.link.legacy.ModelOverride import net.kyori.adventure.key.Key -import team.unnamed.creative.model.ItemOverride -import team.unnamed.creative.model.ItemPredicate enum class PredicateIncrementorType(val predicates: Map>) { NOTE_BLOCK( @@ -118,30 +117,32 @@ class PredicateGenerator(private val incrementor: PredicateIncrementor) { incrementor.setValue(1) } - fun generate(predicates: List?, items: List): List { + fun generate(predicates: List?, items: List): List { val predicateMaps = - predicates?.map { predicate -> predicate.predicate().associate { it.name() to it.value() } } ?: listOf() + predicates?.map { predicate -> predicate.predicate.toList().associate { it.first to it.second } } + ?: listOf() val realPredicates = predicates?.toMutableList() ?: mutableListOf() val iterator = items.iterator() while (iterator.hasNext()) { val item = iterator.next() - if(predicates?.any { it.model() == item } == true) continue + if (predicates?.any { it.model == item } == true) continue var predicate = incrementor.increment() while (predicateMaps.contentEquals(predicate)) { predicate = incrementor.increment() } realPredicates.add( - ItemOverride.of( - item, - predicate.map { ItemPredicate.custom(it.key, it.value) }) + ModelOverride( + predicate, + item + ) ) } return realPredicates } - private fun List>.contentEquals(other: Map): Boolean { - return this.any first@ { - val returned = it.keys.all second@ { key -> + private fun List>.contentEquals(other: Map): Boolean { + return this.any first@{ + val returned = it.keys.all second@{ key -> return@second other[key].toString() == it[key].toString() } return@first returned diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/link/legacy/LegacyResourcePackItemLink.kt b/src/main/kotlin/io/github/solid/resourcepack/api/link/legacy/LegacyResourcePackItemLink.kt new file mode 100644 index 0000000..6afd8ca --- /dev/null +++ b/src/main/kotlin/io/github/solid/resourcepack/api/link/legacy/LegacyResourcePackItemLink.kt @@ -0,0 +1,15 @@ +package io.github.solid.resourcepack.api.link.legacy + +import io.github.solid.resourcepack.api.link.ModelLink +import io.github.solid.resourcepack.api.link.ModelLinkHolder +import net.kyori.adventure.key.Key +import org.spongepowered.configurate.objectmapping.ConfigSerializable + +@ConfigSerializable +data class LegacyResourcePackItemLink( + val parent: Key, val textures: Map, val overrides: List +) : ModelLinkHolder { + override fun collect(): List { + return overrides.map { ModelLink(it.model, predicates = it.predicate) } + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/link/legacy/ModelOverride.kt b/src/main/kotlin/io/github/solid/resourcepack/api/link/legacy/ModelOverride.kt new file mode 100644 index 0000000..10408c2 --- /dev/null +++ b/src/main/kotlin/io/github/solid/resourcepack/api/link/legacy/ModelOverride.kt @@ -0,0 +1,10 @@ +package io.github.solid.resourcepack.api.link.legacy + +import net.kyori.adventure.key.Key +import org.spongepowered.configurate.objectmapping.ConfigSerializable + +@ConfigSerializable +data class ModelOverride( + val predicate: Map, + val model: Key, +) \ No newline at end of file diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/link/modern/ModernResourcePackItemLink.kt b/src/main/kotlin/io/github/solid/resourcepack/api/link/modern/ModernResourcePackItemLink.kt new file mode 100644 index 0000000..ec56268 --- /dev/null +++ b/src/main/kotlin/io/github/solid/resourcepack/api/link/modern/ModernResourcePackItemLink.kt @@ -0,0 +1,26 @@ +package io.github.solid.resourcepack.api.link.modern + +import io.github.solid.resourcepack.api.link.ModelLink +import io.github.solid.resourcepack.api.link.ModelLinkHolder +import net.kyori.adventure.key.Key +import org.spongepowered.configurate.objectmapping.ConfigSerializable + +/** + * A vanilla item model (in /items) in 1.21.4 and up + */ +@ConfigSerializable +data class ModernResourcePackLink( + val model: ModernResourcePackModel? = null +) : ModelLinkHolder { + override fun collect(): List { + if (model?.model == null) { return listOf() } + if (model.type != Key.key("minecraft", "model")) return listOf() + return listOf(ModelLink(model.model)) + } +} + +@ConfigSerializable +data class ModernResourcePackModel( + val type: Key? = null, + val model: Key? = null, +) \ No newline at end of file diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/mappings/ModelMapper.kt b/src/main/kotlin/io/github/solid/resourcepack/api/mappings/ModelMapper.kt deleted file mode 100644 index 3290d07..0000000 --- a/src/main/kotlin/io/github/solid/resourcepack/api/mappings/ModelMapper.kt +++ /dev/null @@ -1,9 +0,0 @@ -package io.github.solid.resourcepack.api.mappings - -import net.kyori.adventure.key.Key -import team.unnamed.creative.model.ItemPredicate - -interface ModelMapper { - fun register(key: Key, value: List) - fun get(key: Key): T? -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/meta/PackMeta.kt b/src/main/kotlin/io/github/solid/resourcepack/api/meta/PackMeta.kt new file mode 100644 index 0000000..abe1994 --- /dev/null +++ b/src/main/kotlin/io/github/solid/resourcepack/api/meta/PackMeta.kt @@ -0,0 +1,31 @@ +package io.github.solid.resourcepack.api.meta + +import io.github.solid.resourcepack.api.util.Range +import org.spongepowered.configurate.objectmapping.ConfigSerializable +import org.spongepowered.configurate.objectmapping.meta.Setting + +@ConfigSerializable +data class PackMeta( + val pack: PackDescription, + val overlays: Overlays, +) + +@ConfigSerializable +data class PackDescription( + @Setting("pack_format") + val format: Int = -1, + @Setting("supported_formats") + val supportedFormats: Range = Range(-1, -1), + val description: String = "", +) + +@ConfigSerializable +data class Overlays( + val entries: List = listOf(), +) + +@ConfigSerializable +data class Overlay( + val formats: Range? = null, + val directory: String? = null, +) diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/util/GenericEnumSerializer.kt b/src/main/kotlin/io/github/solid/resourcepack/api/util/GenericEnumSerializer.kt new file mode 100644 index 0000000..b90e9db --- /dev/null +++ b/src/main/kotlin/io/github/solid/resourcepack/api/util/GenericEnumSerializer.kt @@ -0,0 +1,27 @@ +package io.github.solid.resourcepack.api.util + +import org.spongepowered.configurate.ConfigurationNode +import org.spongepowered.configurate.serialize.SerializationException +import org.spongepowered.configurate.serialize.TypeSerializer +import java.lang.reflect.Type + +object GenericEnumSerializer : TypeSerializer> { + override fun deserialize(type: Type, node: ConfigurationNode): Enum<*> { + val value = node.string ?: throw SerializationException("No value present in node") + + if (type !is Class<*> || !type.isEnum) { + throw SerializationException("Type is not an enum class") + } + + @Suppress("UNCHECKED_CAST") + return try { + java.lang.Enum.valueOf(type as Class>, value.uppercase()) + } catch (e: IllegalArgumentException) { + throw SerializationException("Invalid enum constant") + } + } + + override fun serialize(type: Type, obj: Enum<*>?, node: ConfigurationNode) { + node.set(obj?.name?.lowercase()) + } +} diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/util/KeySerializer.kt b/src/main/kotlin/io/github/solid/resourcepack/api/util/KeySerializer.kt new file mode 100644 index 0000000..9cd74e6 --- /dev/null +++ b/src/main/kotlin/io/github/solid/resourcepack/api/util/KeySerializer.kt @@ -0,0 +1,23 @@ +package io.github.solid.resourcepack.api.util + +import net.kyori.adventure.key.Key +import org.spongepowered.configurate.ConfigurationNode +import org.spongepowered.configurate.serialize.SerializationException +import org.spongepowered.configurate.serialize.TypeSerializer +import java.lang.reflect.Type + +object KeySerializer : TypeSerializer { + override fun deserialize(type: Type, node: ConfigurationNode): Key { + val value = node.string ?: throw SerializationException("No value present in node") + + return try { + Key.key(value) + } catch (e: Exception) { + throw SerializationException("Invalid key syntax") + } + } + + override fun serialize(type: Type, obj: Key?, node: ConfigurationNode) { + node.set(obj?.asString()) + } +} diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/util/MapSerializer.kt b/src/main/kotlin/io/github/solid/resourcepack/api/util/MapSerializer.kt new file mode 100644 index 0000000..443a359 --- /dev/null +++ b/src/main/kotlin/io/github/solid/resourcepack/api/util/MapSerializer.kt @@ -0,0 +1,21 @@ +package io.github.solid.resourcepack.api.util + +import org.spongepowered.configurate.ConfigurationNode +import org.spongepowered.configurate.serialize.SerializationException +import org.spongepowered.configurate.serialize.TypeSerializer +import java.lang.reflect.Type + +object MapSerializer : TypeSerializer> { + override fun deserialize(type: Type?, node: ConfigurationNode?): Map { + if(node == null) throw SerializationException("Map is null!") + if(!node.isMap) throw SerializationException("Map is null!") + return node.childrenMap().map { it.key.toString() to it.value.raw()!! }.toMap() + } + + override fun serialize(type: Type?, obj: Map?, node: ConfigurationNode?) { + if (node == null) return + if (obj == null) return + obj.forEach { (k, v) -> node.node(k).set(v) } + } + +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/solid/resourcepack/api/util/Range.kt b/src/main/kotlin/io/github/solid/resourcepack/api/util/Range.kt new file mode 100644 index 0000000..2502736 --- /dev/null +++ b/src/main/kotlin/io/github/solid/resourcepack/api/util/Range.kt @@ -0,0 +1,40 @@ +package io.github.solid.resourcepack.api.util + +import org.spongepowered.configurate.ConfigurationNode +import org.spongepowered.configurate.serialize.SerializationException +import org.spongepowered.configurate.serialize.TypeSerializer +import java.lang.reflect.Type + + +data class Range( + val start: Int, + val end: Int? = null, +) + +object RangeSerializer : TypeSerializer { + override fun deserialize(type: Type, node: ConfigurationNode): Range { + if (node.isList) { + val list = node.getList(Int::class.java) ?: throw SerializationException("No int list provided") + return Range(list[0], list[1]) + } + if (!node.hasChild("min_inclusive") && !node.hasChild("max_inclusive")) { + return Range(node.int) + } + val start = node.node("min_inclusive").int + val end = node.node("max_inclusive").int + return Range(start, end) + } + + override fun serialize(type: Type, obj: Range?, node: ConfigurationNode) { + if (obj == null) return + if (obj.end == null) { + node.set(obj.start) + return + } + + node.node("min_inclusive").set(obj.start) + node.node("max_inclusive").set(obj.end) + } +} + + diff --git a/src/test/kotlin/PredicateTest.kt b/src/test/kotlin/PredicateTest.kt deleted file mode 100644 index 33615db..0000000 --- a/src/test/kotlin/PredicateTest.kt +++ /dev/null @@ -1,20 +0,0 @@ -import io.github.solid.resourcepack.api.builder.AdvancedResourcePack -import io.github.solid.resourcepack.api.builder.config.Predicate -import io.github.solid.resourcepack.material.SolidMaterial -import net.kyori.adventure.key.Key -import team.unnamed.creative.ResourcePack - -val BOOST_ARROW = Key.key("test", "item/boost_arrow") -fun main() { - val pack = AdvancedResourcePack(ResourcePack.resourcePack()) - pack.apply( - Predicate.customModelData(SolidMaterial.from(Key.key("minecraft", "item/stick"))).models(BOOST_ARROW).build() - ) - - val mapper = TestMapper() - pack.map( - mapper, - AdvancedResourcePack.Filters.MINECRAFT_FILTER, - { model -> model.key().value().startsWith("item/") }) - println(mapper.get(BOOST_ARROW)) -} \ No newline at end of file diff --git a/src/test/kotlin/TestMapper.kt b/src/test/kotlin/TestMapper.kt deleted file mode 100644 index 7309fe6..0000000 --- a/src/test/kotlin/TestMapper.kt +++ /dev/null @@ -1,15 +0,0 @@ -import io.github.solid.resourcepack.api.mappings.ModelMapper -import net.kyori.adventure.key.Key -import team.unnamed.creative.model.ItemPredicate - -class TestMapper: ModelMapper { - - private val registry = mutableMapOf() - override fun register(key: Key, value: List) { - registry[key] = value.toString() - } - - override fun get(key: Key): String? { - return registry.getOrDefault(key, null) - } -} \ No newline at end of file diff --git a/src/test/kotlin/io/github/solid/resourcepack/api/link/ModelLinkCollectorTest.kt b/src/test/kotlin/io/github/solid/resourcepack/api/link/ModelLinkCollectorTest.kt new file mode 100644 index 0000000..e6f005b --- /dev/null +++ b/src/test/kotlin/io/github/solid/resourcepack/api/link/ModelLinkCollectorTest.kt @@ -0,0 +1,17 @@ +package io.github.solid.resourcepack.api.link + +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.* +import java.nio.file.Path + +class ModelLinkCollectorTest { + + @Test + fun collect() { + val path = Path.of("src", "test", "kotlin", "pack") + println(path.toAbsolutePath().toString()) + val collector = ModelLinkCollector(path) + assert(collector.collect().isNotEmpty()) + } +} \ No newline at end of file