diff --git a/build-logic/src/main/groovy/kit_tunes.base_mod_conventions.gradle b/build-logic/src/main/groovy/kit_tunes.base_mod_conventions.gradle index b39bcc3..637c3ef 100644 --- a/build-logic/src/main/groovy/kit_tunes.base_mod_conventions.gradle +++ b/build-logic/src/main/groovy/kit_tunes.base_mod_conventions.gradle @@ -27,23 +27,3 @@ processResources { expand 'version': project.mod_version } } - -tasks.withType(JavaCompile).configureEach { - it.options.encoding = 'UTF-8' - // Minecraft 1.18 until Minecraft 1.20.5 requires Java 17. - it.options.release = 17 -} - -java { - // Still required by IDEs such as Eclipse and Visual Studio Code - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - - // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task if it is present. - // If you remove this line, sources will not be generated. - withSourcesJar() - - // If this mod is going to be a library, then it should also generate Javadocs in order to aid with development. - // Uncomment this line to generate them. - // withJavadocJar() -} diff --git a/build-logic/src/main/groovy/kit_tunes.java.17.gradle b/build-logic/src/main/groovy/kit_tunes.java.17.gradle new file mode 100644 index 0000000..c088290 --- /dev/null +++ b/build-logic/src/main/groovy/kit_tunes.java.17.gradle @@ -0,0 +1,19 @@ +plugins { + id 'java' +} + +java { + withSourcesJar() + + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } +} + +tasks.withType(JavaCompile).configureEach { + it.options.encoding = "UTF-8" + + javaCompiler = javaToolchains.compilerFor { + languageVersion = JavaLanguageVersion.of(17) + } +} diff --git a/build-logic/src/main/groovy/kit_tunes.java.21.gradle b/build-logic/src/main/groovy/kit_tunes.java.21.gradle new file mode 100644 index 0000000..2dd436d --- /dev/null +++ b/build-logic/src/main/groovy/kit_tunes.java.21.gradle @@ -0,0 +1,19 @@ +plugins { + id 'java' +} + +java { + withSourcesJar() + + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } +} + +tasks.withType(JavaCompile).configureEach { + it.options.encoding = "UTF-8" + + javaCompiler = javaToolchains.compilerFor { + languageVersion = JavaLanguageVersion.of(21) + } +} diff --git a/build-logic/src/main/groovy/kit_tunes.java.8.gradle b/build-logic/src/main/groovy/kit_tunes.java.8.gradle new file mode 100644 index 0000000..173236a --- /dev/null +++ b/build-logic/src/main/groovy/kit_tunes.java.8.gradle @@ -0,0 +1,19 @@ +plugins { + id 'java' +} + +java { + withSourcesJar() + + toolchain { + languageVersion = JavaLanguageVersion.of(8) + } +} + +tasks.withType(JavaCompile).configureEach { + it.options.encoding = "UTF-8" + + javaCompiler = javaToolchains.compilerFor { + languageVersion = JavaLanguageVersion.of(8) + } +} diff --git a/build.gradle b/build.gradle index 2be6132..8157d67 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'maven-publish' + id 'kit_tunes.java.17' id 'kit_tunes.base_mod_conventions' } @@ -21,9 +21,11 @@ dependencies { include project(':subprojects:api') include project(':subprojects:core') + include project(':subprojects:sound_events:r1.20.4') + include project(':subprojects:ui:r1.20.4') + include project(':subprojects:ui:r1.21.0') - include project(':subprojects:sound_events:r1.20.4') } // If you plan to use a different file for the license, don't forget to change the file name here! @@ -32,20 +34,3 @@ jar { rename { "${it}_${base.archivesName.get()}" } } } - -// Configure the maven publication -publishing { - publications { - mavenJava(MavenPublication) { - from components.java - } - } - - // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. - repositories { - // Add repositories to publish to here. - // Notice: This block does NOT have the same function as the block in the top level. - // The repositories here will be used for publishing your artifact, not for - // retrieving dependencies. - } -} diff --git a/gradle.properties b/gradle.properties index dd36bfc..cfd3e8d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # Gradle Properties -org.gradle.jvmargs = -Xmx2G +org.gradle.jvmargs = -Xmx4G org.gradle.parallel = true # Mod Properties diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f5c4c78..00d34f1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,8 +3,8 @@ minecraft = "1.20.4" quilt_mappings = "1.20.4+build.3" -quilt_loom = "1.4.1" -quilt_loader = "0.23.1" +quilt_loom = "1.7.3" +quilt_loader = "0.26.0" qsl = "8.0.0-alpha.11+1.20.4" @@ -15,7 +15,6 @@ quilt_loom = { module = "org.quiltmc:loom", version.ref = "quilt_loom" } quilt_loader = { module = "org.quiltmc:quilt-loader", version.ref = "quilt_loader" } qsl_resource_loader = { module = "org.quiltmc.qsl.core:resource_loader", version.ref = "qsl"} -qsl_client_command = { module = "org.quiltmc.qsl.management:client_command", version.ref = "qsl"} # If you have multiple similar dependencies, you can declare a dependency bundle and reference it on the build script with "libs.bundles.example". [bundles] diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7f93135..e644113 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ac72c34..a441313 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 0adc8e1..b740cf1 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# 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/. @@ -145,7 +145,7 @@ 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=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -153,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -202,11 +202,11 @@ 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 $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# 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" \ diff --git a/gradlew.bat b/gradlew.bat index 93e3f59..25da30d 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +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 @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +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 diff --git a/settings.gradle b/settings.gradle index 8abc8f9..41c7289 100644 --- a/settings.gradle +++ b/settings.gradle @@ -13,11 +13,16 @@ pluginManagement { } } +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0" +} + includeBuild 'build-logic' include('subprojects:api') include('subprojects:core') -include('subprojects:ui:r1.20.4') - include('subprojects:sound_events:r1.20.4') + +include('subprojects:ui:r1.20.4') +include('subprojects:ui:r1.21.0') diff --git a/src/main/resources/albums/tricky_trials.json b/src/main/resources/albums/tricky_trials.json new file mode 100644 index 0000000..8c9d1ca --- /dev/null +++ b/src/main/resources/albums/tricky_trials.json @@ -0,0 +1,87 @@ +{ + "name": "Minecraft: Tricky Trials (Original Game Soundtrack)", + "tracks": [ + { + "matches": [ + "featherfall" + ], + "name": "Featherfall", + "artist": "kit_tunes.artists.aaron_cherof" + }, + { + "matches": [ + "watcher" + ], + "name": "Watcher", + "artist": "kit_tunes.artists.aaron_cherof" + }, + { + "matches": [ + "puzzlebox" + ], + "name": "Puzzlebox", + "artist": "kit_tunes.artists.aaron_cherof" + }, + { + "matches": [ + "komorebi" + ], + "name": "komorebi", + "artist": "kit_tunes.artists.kumi_tanioka" + }, + { + "matches": [ + "pokopoko" + ], + "name": "pokopoko", + "artist": "kit_tunes.artists.kumi_tanioka" + }, + { + "matches": [ + "yakusoku" + ], + "name": "yakusoku", + "artist": "kit_tunes.artists.kumi_tanioka" + }, + { + "matches": [ + "deeper" + ], + "name": "Deeper", + "artist": "kit_tunes.artists.lena_raine" + }, + { + "matches": [ + "eld_unknown" + ], + "name": "Eld Unknown", + "artist": "kit_tunes.artists.lena_raine" + }, + { + "matches": [ + "endless" + ], + "name": "Endless", + "artist": "kit_tunes.artists.lena_raine" + }, + { + "matches": [], + "name": "Creator", + "artist": "kit_tunes.artists.lena_raine" + }, + { + "matches": [ + "creator" + ], + "name": "Creator (Music Box Version)", + "artist": "kit_tunes.artists.lena_raine" + }, + { + "matches": [ + "precipice" + ], + "name": "Precipice", + "artist": "kit_tunes.artists.aaron_cherof" + } + ] +} diff --git a/subprojects/api/build.gradle b/subprojects/api/build.gradle index f654842..31570b1 100644 --- a/subprojects/api/build.gradle +++ b/subprojects/api/build.gradle @@ -1,3 +1,4 @@ plugins { + id 'kit_tunes.java.17' id 'kit_tunes.library_mod_conventions' } diff --git a/subprojects/core/build.gradle b/subprojects/core/build.gradle index dc6f6f4..fb38c21 100644 --- a/subprojects/core/build.gradle +++ b/subprojects/core/build.gradle @@ -1,4 +1,5 @@ plugins { + id 'kit_tunes.java.17' id 'kit_tunes.library_mod_conventions' } diff --git a/subprojects/sound_events/r1.20.4/build.gradle b/subprojects/sound_events/r1.20.4/build.gradle index bf9394f..f41a726 100644 --- a/subprojects/sound_events/r1.20.4/build.gradle +++ b/subprojects/sound_events/r1.20.4/build.gradle @@ -1,4 +1,5 @@ plugins { + id 'kit_tunes.java.17' id 'kit_tunes.game_mod_conventions' } diff --git a/subprojects/sound_events/r1.20.4/src/main/resources/quilt.mod.json b/subprojects/sound_events/r1.20.4/src/main/resources/quilt.mod.json index e2f5826..a77b740 100644 --- a/subprojects/sound_events/r1.20.4/src/main/resources/quilt.mod.json +++ b/subprojects/sound_events/r1.20.4/src/main/resources/quilt.mod.json @@ -20,18 +20,16 @@ "depends": [ { "id": "quilt_loader", - "versions": ">=0.19.1" + "versions": ">=0.26.0" }, { "id": "minecraft", - "versions": "=1.20.4" + "versions": { + "all": [">=1.20.4", "<=1.21.0"] + } }, { - "id": "quilt_client_command", - "versions": { "all": [">=8.0.0-", "<9.0.0"] } - }, - { - "id": "quilt_resource_loader", + "id": "quilted_fabric_resource_loader_v0", "versions": "*" } ] diff --git a/subprojects/ui/r1.20.4/build.gradle b/subprojects/ui/r1.20.4/build.gradle index 2c2c505..86bae40 100644 --- a/subprojects/ui/r1.20.4/build.gradle +++ b/subprojects/ui/r1.20.4/build.gradle @@ -1,4 +1,5 @@ plugins { + id 'kit_tunes.java.17' id 'kit_tunes.game_mod_conventions' } @@ -13,7 +14,6 @@ dependencies { implementation project(':subprojects:api') implementation project(':subprojects:core') - modImplementation libs.qsl.client.command modImplementation libs.qsl.resource.loader modImplementation "com.terraformersmc:modmenu:${project.modmenu_version}" diff --git a/subprojects/ui/r1.20.4/src/main/java/net/pixaurora/kit_tunes/impl/KitTunesUIImpl.java b/subprojects/ui/r1.20.4/src/main/java/net/pixaurora/kit_tunes/impl/KitTunesUIImpl.java index b759c2b..320ca54 100644 --- a/subprojects/ui/r1.20.4/src/main/java/net/pixaurora/kit_tunes/impl/KitTunesUIImpl.java +++ b/subprojects/ui/r1.20.4/src/main/java/net/pixaurora/kit_tunes/impl/KitTunesUIImpl.java @@ -17,7 +17,7 @@ import net.pixaurora.kit_tunes.impl.ui.toast.KitTunesToastData; public class KitTunesUIImpl implements KitTunesMinecraftUICompat { - private Minecraft client = Minecraft.getInstance(); + private final Minecraft client = Minecraft.getInstance(); public static ResourceLocation resourceToMinecraftType(ResourcePath path) { return new ResourceLocation(path.namespace(), path.path()); diff --git a/subprojects/ui/r1.20.4/src/main/resources/quilt.mod.json b/subprojects/ui/r1.20.4/src/main/resources/quilt.mod.json index d874c5e..ee62beb 100644 --- a/subprojects/ui/r1.20.4/src/main/resources/quilt.mod.json +++ b/subprojects/ui/r1.20.4/src/main/resources/quilt.mod.json @@ -25,16 +25,12 @@ "depends": [ { "id": "quilt_loader", - "versions": ">=0.19.1" + "versions": ">=0.26.0" }, { "id": "minecraft", "versions": "=1.20.4" }, - { - "id": "quilt_client_command", - "versions": { "all": [">=8.0.0-", "<9.0.0"] } - }, { "id": "quilt_resource_loader", "versions": "*" diff --git a/subprojects/ui/r1.21.0/build.gradle b/subprojects/ui/r1.21.0/build.gradle new file mode 100644 index 0000000..16d5740 --- /dev/null +++ b/subprojects/ui/r1.21.0/build.gradle @@ -0,0 +1,20 @@ +plugins { + id 'kit_tunes.java.21' + id 'kit_tunes.game_mod_conventions' +} + +repositories { + maven { + name = "Terraformers" + url = "https://maven.terraformersmc.com/" + } +} + +dependencies { + implementation project(':subprojects:api') + implementation project(':subprojects:core') + + modImplementation fabricApi.module("fabric-resource-loader-v0", project.fabric_api_version) + + modImplementation "com.terraformersmc:modmenu:${project.modmenu_version}" +} diff --git a/subprojects/ui/r1.21.0/gradle.properties b/subprojects/ui/r1.21.0/gradle.properties new file mode 100644 index 0000000..8f4d77e --- /dev/null +++ b/subprojects/ui/r1.21.0/gradle.properties @@ -0,0 +1,8 @@ +# Mod properties +sub_mod_name = ui + +minecraft_version = 1.21 +quilt_mappings_version = 1.21+build.2 + +modmenu_version=9.2.0-beta.2 +fabric_api_version = 0.100.1+1.21 diff --git a/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/FakeComponent.java b/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/FakeComponent.java new file mode 100644 index 0000000..ea88dfe --- /dev/null +++ b/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/FakeComponent.java @@ -0,0 +1,21 @@ +package net.pixaurora.kit_tunes.impl; + +import net.minecraft.network.chat.MutableComponent; +import net.pixaurora.kit_tunes.impl.ui.text.Component; + +public class FakeComponent implements Component { + protected final MutableComponent parent; + + public FakeComponent(MutableComponent component) { + this.parent = component; + } + + public MutableComponent gameVer() { + return this.parent; + } + + @Override + public Component concat(Component component) { + return new FakeComponent(this.parent.copy().append(KitTunesUIImpl.componentToMinecraftType(component))); + } +} diff --git a/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/KitTunesUIImpl.java b/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/KitTunesUIImpl.java new file mode 100644 index 0000000..50aeb3e --- /dev/null +++ b/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/KitTunesUIImpl.java @@ -0,0 +1,103 @@ +package net.pixaurora.kit_tunes.impl; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.components.toasts.Toast; +import net.minecraft.client.gui.screens.ConfirmLinkScreen; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; +import net.pixaurora.kit_tunes.api.resource.ResourcePath; +import net.pixaurora.kit_tunes.impl.gui.KitTunesScreenImpl; +import net.pixaurora.kit_tunes.impl.gui.KitTunesToastImpl; +import net.pixaurora.kit_tunes.impl.gui.MinecraftScreen; +import net.pixaurora.kit_tunes.impl.resource.ResourcePathUtils; +import net.pixaurora.kit_tunes.impl.service.KitTunesMinecraftUICompat; +import net.pixaurora.kit_tunes.impl.ui.screen.Screen; +import net.pixaurora.kit_tunes.impl.ui.sound.Sound; +import net.pixaurora.kit_tunes.impl.ui.text.Component; +import net.pixaurora.kit_tunes.impl.ui.toast.KitTunesToastData; + +public class KitTunesUIImpl implements KitTunesMinecraftUICompat { + private final Minecraft client = Minecraft.getInstance(); + + public static ResourceLocation resourceToMinecraftType(ResourcePath path) { + return ResourceLocation.fromNamespaceAndPath(path.namespace(), path.path()); + } + + public static ResourceLocation resourceToMinecraftGuiSprite(ResourcePath path) { + return resourceToMinecraftType( + ResourcePathUtils.stripSuffixAndPrefix("textures/gui/sprites/", ".png", path).get()); + } + + public static MutableComponent componentToMinecraftType(Component component) { + if (component instanceof FakeComponent) { + return ((FakeComponent) component).parent; + } else { + throw new RuntimeException( + "Internal component is of an unconvertable type `" + component.getClass().getName() + "`!"); + } + } + + @Override + public void sendToast(KitTunesToastData toastData) { + Minecraft client = Minecraft.getInstance(); + Toast toast = new KitTunesToastImpl(client.font, toastData); + + client.getToasts().addToast(toast); + } + + @Override + public ResourcePath convertToRegularAsset(ResourcePath path) { + return path; + } + + @Override + public ResourcePath convertToGuiAsset(ResourcePath path) { + return ResourcePathUtils.stripSuffixAndPrefix("textures/gui/sprites/", ".png", path).get(); + } + + @Override + public Component translatable(String key) { + return new FakeComponent(net.minecraft.network.chat.Component.translatable(key)); + } + + @Override + public Component translatableWithFallback(String key, String defaultText) { + return new FakeComponent(net.minecraft.network.chat.Component.translatableWithFallback(key, defaultText)); + } + + @Override + public Component literal(String text) { + return new FakeComponent(net.minecraft.network.chat.Component.literal(text)); + } + + @Override + public int textHeight() { + return this.client.font.lineHeight; + } + + @Override + public int textWidth(Component text) { + return this.client.font.width(componentToMinecraftType(text)); + } + + @Override + public void playSound(Sound sound) { + this.client.getSoundManager().play(SoundUtil.soundFromInternalID(sound)); + } + + @Override + public void setScreen(Screen screen) { + net.minecraft.client.gui.screens.Screen mcScreen; + if (screen instanceof MinecraftScreen) { + mcScreen = ((MinecraftScreen) screen).parent(); + } else { + mcScreen = new KitTunesScreenImpl(screen); + } + this.client.setScreen(mcScreen); + } + + @Override + public void confirmURL(String url) { + ConfirmLinkScreen.confirmLinkNow(this.client.screen, url); + } +} diff --git a/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/SoundUtil.java b/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/SoundUtil.java new file mode 100644 index 0000000..624e823 --- /dev/null +++ b/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/SoundUtil.java @@ -0,0 +1,17 @@ +package net.pixaurora.kit_tunes.impl; + +import net.minecraft.client.resources.sounds.SimpleSoundInstance; +import net.minecraft.client.resources.sounds.SoundInstance; +import net.minecraft.sounds.SoundEvents; +import net.pixaurora.kit_tunes.impl.ui.sound.Sound; + +public class SoundUtil { + public static SoundInstance soundFromInternalID(Sound sound) { + switch (sound) { + case BUTTON_CLICK: + return SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F); + default: + throw new RuntimeException("Sound " + sound.name() + " was not mapped!"); + } + } +} diff --git a/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/compat/ModMenuIntegration.java b/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/compat/ModMenuIntegration.java new file mode 100644 index 0000000..839fea8 --- /dev/null +++ b/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/compat/ModMenuIntegration.java @@ -0,0 +1,23 @@ +package net.pixaurora.kit_tunes.impl.compat; + +import java.util.Map; + +import com.terraformersmc.modmenu.api.ConfigScreenFactory; +import com.terraformersmc.modmenu.api.ModMenuApi; + +import net.minecraft.client.gui.screens.Screen; +import net.pixaurora.kit_tunes.impl.Constants; +import net.pixaurora.kit_tunes.impl.gui.KitTunesScreenImpl; +import net.pixaurora.kit_tunes.impl.gui.MinecraftScreen; +import net.pixaurora.kit_tunes.impl.ui.screen.KitTunesHomeScreen; + +public class ModMenuIntegration implements ModMenuApi { + public KitTunesScreenImpl modHomeScreen(Screen parent) { + return new KitTunesScreenImpl(new KitTunesHomeScreen(new MinecraftScreen(parent))); + } + + @Override + public Map> getProvidedConfigScreenFactories() { + return Map.of(Constants.MOD_ID, this::modHomeScreen); + } +} diff --git a/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/gui/ConversionCacheImpl.java b/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/gui/ConversionCacheImpl.java new file mode 100644 index 0000000..9559256 --- /dev/null +++ b/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/gui/ConversionCacheImpl.java @@ -0,0 +1,20 @@ +package net.pixaurora.kit_tunes.impl.gui; + +import net.minecraft.resources.ResourceLocation; +import net.pixaurora.kit_tunes.api.resource.ResourcePath; +import net.pixaurora.kit_tunes.impl.KitTunesUIImpl; +import net.pixaurora.kit_tunes.impl.ui.ConversionCache; + +public class ConversionCacheImpl extends ConversionCache { + @Override + protected ResourceLocation resourceToMinecraftType(ResourcePath path) { + return KitTunesUIImpl.resourceToMinecraftType(path); + } + + @Override + protected net.minecraft.network.chat.Component componentToMinecraftType( + net.pixaurora.kit_tunes.impl.ui.text.Component component) { + return KitTunesUIImpl.componentToMinecraftType(component); + } + +} diff --git a/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/gui/GuiDisplayImpl.java b/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/gui/GuiDisplayImpl.java new file mode 100644 index 0000000..0a1db86 --- /dev/null +++ b/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/gui/GuiDisplayImpl.java @@ -0,0 +1,41 @@ +package net.pixaurora.kit_tunes.impl.gui; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.pixaurora.kit_tunes.api.resource.ResourcePath; +import net.pixaurora.kit_tunes.impl.ui.GuiDisplay; +import net.pixaurora.kit_tunes.impl.ui.math.Point; +import net.pixaurora.kit_tunes.impl.ui.math.Size; +import net.pixaurora.kit_tunes.impl.ui.text.Color; +import net.pixaurora.kit_tunes.impl.ui.text.Component; + +public class GuiDisplayImpl implements GuiDisplay { + private final GuiGraphics graphics; + + private final ConversionCacheImpl conversions; + + public GuiDisplayImpl(GuiGraphics graphics, ConversionCacheImpl conversions) { + this.graphics = graphics; + this.conversions = conversions; + } + + @Override + public void drawTexture(ResourcePath path, Size size, Point pos) { + int width = size.width(); + int height = size.height(); + + this.graphics.blit(conversions.convert(path), pos.x(), pos.y(), 0, 0.0F, 0.0F, width, height, width, height); + } + + @Override + public void drawGuiTexture(ResourcePath path, Size size, Point pos) { + this.graphics.blitSprite(conversions.convert(path), pos.x(), pos.y(), size.width(), size.height()); + } + + @SuppressWarnings("resource") + @Override + public void drawText(Component text, Color color, Point pos) { + this.graphics.drawString(Minecraft.getInstance().font, conversions.convert(text), pos.x(), pos.y(), + color.hex()); + } +} diff --git a/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/gui/KitTunesScreenImpl.java b/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/gui/KitTunesScreenImpl.java new file mode 100644 index 0000000..977e5c1 --- /dev/null +++ b/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/gui/KitTunesScreenImpl.java @@ -0,0 +1,63 @@ +package net.pixaurora.kit_tunes.impl.gui; + +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; +import net.pixaurora.kit_tunes.impl.ui.GuiDisplay; +import net.pixaurora.kit_tunes.impl.ui.math.Point; +import net.pixaurora.kit_tunes.impl.ui.math.Size; +import net.pixaurora.kit_tunes.impl.ui.screen.Screen; + +public class KitTunesScreenImpl extends net.minecraft.client.gui.screens.Screen { + private final Screen screen; + + private final ConversionCacheImpl conversions; + + public KitTunesScreenImpl(Screen screen) { + super(Component.empty()); + + this.screen = screen; + + this.conversions = new ConversionCacheImpl(); + } + + // "Minecraft Screen" functions + + @Override + public void init() { + this.screen.init(Size.of(this.width, this.height)); + } + + @Override + public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) { + super.render(graphics, mouseX, mouseY, delta); + + GuiDisplay display = new GuiDisplayImpl(graphics, this.conversions); + Point mousePos = Point.of(mouseX, mouseY); + + this.screen.draw(display, mousePos); + } + + @Override + public void onClose() { + this.screen.onExit(); + } + + @Override + public boolean shouldCloseOnEsc() { + return true; + } + + @Override + public boolean mouseClicked(double x, double y, int button) { + Point mousePos = Point.of((int) x, (int) y); + + this.screen.handleClick(mousePos, button); + + return false; + } + + @Override + public void tick() { + this.screen.tick(); + } +} diff --git a/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/gui/KitTunesToastImpl.java b/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/gui/KitTunesToastImpl.java new file mode 100644 index 0000000..60733ec --- /dev/null +++ b/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/gui/KitTunesToastImpl.java @@ -0,0 +1,137 @@ +package net.pixaurora.kit_tunes.impl.gui; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.toasts.Toast; +import net.minecraft.client.gui.components.toasts.ToastComponent; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.FormattedCharSequence; +import net.pixaurora.kit_tunes.impl.KitTunesUIImpl; +import net.pixaurora.kit_tunes.impl.ui.math.Point; +import net.pixaurora.kit_tunes.impl.ui.math.Size; +import net.pixaurora.kit_tunes.impl.ui.toast.ToastBackground; +import net.pixaurora.kit_tunes.impl.ui.toast.ToastBackgroundAppearance; +import net.pixaurora.kit_tunes.impl.ui.toast.ToastBackgroundTile; +import net.pixaurora.kit_tunes.impl.util.Pair; +import net.pixaurora.kit_tunes.impl.ui.toast.KitTunesToastData; + +public class KitTunesToastImpl implements Toast { + private final KitTunesToastData toastData; + + private final ResourceLocation icon; + + private final ResourceLocation background; + private final List tiles; + + private final Component title; + private final List bodyLines; + private final Size toastSize; + + private boolean hasRendered = false; + private long firstRenderedTime; + + public KitTunesToastImpl(Font font, KitTunesToastData toastData) { + this.toastData = toastData; + + this.icon = KitTunesUIImpl.resourceToMinecraftType(this.toastData.icon()); + + ToastBackground background = toastData.background(); + + this.background = KitTunesUIImpl.resourceToMinecraftGuiSprite(background.appearance().texture()); + + List lines = toastData.messageLines().stream().map(KitTunesUIImpl::componentToMinecraftType) + .toList(); + + this.title = KitTunesUIImpl.componentToMinecraftType(toastData.title()); + this.bodyLines = new ArrayList<>(); + + for (Component line : lines) { + this.bodyLines.addAll(font.split(line, background.maxLineLength())); + } + + int textWidth = font.width(this.title); + + for (FormattedCharSequence line : this.bodyLines) { + textWidth = Math.max(font.width(line), textWidth); + } + + Size textBox = Size.of(textWidth, this.bodyLines.size() * font.lineHeight); + + Pair, Size> tilesAndSize = background.tilesAndSize(textBox); + + this.tiles = tilesAndSize.first(); + this.toastSize = tilesAndSize.second(); + } + + @Override + public int width() { + return this.toastSize.width(); + } + + @Override + public int height() { + return this.toastSize.height(); + } + + @Override + public Toast.Visibility render(GuiGraphics graphics, ToastComponent manager, long frameTime) { + if (!this.hasRendered) { + this.hasRendered = true; + this.firstRenderedTime = frameTime; + } + + Point offset = Point.ZERO; + + this.drawToastBackground(graphics, offset); + + ToastBackground background = this.toastData.background(); + + this.drawTexture(graphics, this.icon, background.iconPos().offset(offset), this.toastData.iconSize()); + + Minecraft client = manager.getMinecraft(); + + Point titlePos = background.titlePos().offset(offset); + graphics.drawString(client.font, title, titlePos.x(), titlePos.y(), ChatFormatting.AQUA.getColor(), false); + + Point bodyTextStart = background.bodyTextStartPos().offset(offset); + int currentLineY = bodyTextStart.y(); + + for (FormattedCharSequence line : this.bodyLines) { + graphics.drawString(client.font, line, bodyTextStart.x(), currentLineY, ChatFormatting.BLACK.getColor(), + false); + currentLineY += client.font.lineHeight; + } + + return frameTime - this.firstRenderedTime < 5000 ? Toast.Visibility.SHOW : Toast.Visibility.HIDE; + } + + public void drawTexture(GuiGraphics graphics, ResourceLocation texture, Point pos, Size size) { + int width = size.width(); + int height = size.height(); + + graphics.blit(texture, pos.x(), pos.y(), 0, 0.0F, 0.0F, width, height, width, height); + } + + private void drawToastBackground(GuiGraphics graphics, Point offset) { + ToastBackgroundAppearance appearance = this.toastData.background().appearance(); + + Size texture = appearance.size(); + + for (ToastBackgroundTile tile : this.tiles) { + Size tileSize = tile.size(); + Point textureOffset = tile.textureOffset(); + + Point tilePos = tile.pos().offset(offset); + + graphics.blitSprite(this.background, texture.width(), texture.height(), textureOffset.x(), + textureOffset.y(), tilePos.x(), tilePos.y(), tileSize.width(), tileSize.height()); + } + } +} diff --git a/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/gui/MinecraftScreen.java b/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/gui/MinecraftScreen.java new file mode 100644 index 0000000..286baa4 --- /dev/null +++ b/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/gui/MinecraftScreen.java @@ -0,0 +1,31 @@ +package net.pixaurora.kit_tunes.impl.gui; + +import net.pixaurora.kit_tunes.impl.ui.GuiDisplay; +import net.pixaurora.kit_tunes.impl.ui.math.Point; +import net.pixaurora.kit_tunes.impl.ui.math.Size; +import net.pixaurora.kit_tunes.impl.ui.screen.Screen; + +public class MinecraftScreen implements Screen { + private final net.minecraft.client.gui.screens.Screen parent; + + public MinecraftScreen(net.minecraft.client.gui.screens.Screen parent) { + this.parent = parent; + } + + @Override + public void draw(GuiDisplay gui, Point mousePos) { + } + + @Override + public void init(Size window) { + throw new RuntimeException("This isn't a real Kit Tunes screen!"); + } + + @Override + public void handleClick(Point mousePos, int button) { + } + + public net.minecraft.client.gui.screens.Screen parent() { + return this.parent; + } +} diff --git a/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/mixin/ui/GuiMixin.java b/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/mixin/ui/GuiMixin.java new file mode 100644 index 0000000..595c2fd --- /dev/null +++ b/subprojects/ui/r1.21.0/src/main/java/net/pixaurora/kit_tunes/impl/mixin/ui/GuiMixin.java @@ -0,0 +1,19 @@ +package net.pixaurora.kit_tunes.impl.mixin.ui; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.gui.Gui; +import net.minecraft.network.chat.Component; + +@Mixin(Gui.class) +public class GuiMixin { + // Because we want to show our own notification, we cancel this one so it + // doesn't show twice. + @Inject(method = "setNowPlaying", at = @At("HEAD"), cancellable = true) + private void cancelNowPlayingNotification(Component description, CallbackInfo cInfo) { + cInfo.cancel(); + } +} diff --git a/subprojects/ui/r1.21.0/src/main/resources/META-INF/services/net.pixaurora.kit_tunes.impl.service.KitTunesMinecraftUICompat b/subprojects/ui/r1.21.0/src/main/resources/META-INF/services/net.pixaurora.kit_tunes.impl.service.KitTunesMinecraftUICompat new file mode 100644 index 0000000..e627ce1 --- /dev/null +++ b/subprojects/ui/r1.21.0/src/main/resources/META-INF/services/net.pixaurora.kit_tunes.impl.service.KitTunesMinecraftUICompat @@ -0,0 +1 @@ +net.pixaurora.kit_tunes.impl.KitTunesUIImpl diff --git a/subprojects/ui/r1.21.0/src/main/resources/kit_tunes_ui.mixins.json b/subprojects/ui/r1.21.0/src/main/resources/kit_tunes_ui.mixins.json new file mode 100644 index 0000000..372e274 --- /dev/null +++ b/subprojects/ui/r1.21.0/src/main/resources/kit_tunes_ui.mixins.json @@ -0,0 +1,13 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.pixaurora.kit_tunes.impl.mixin.ui", + "compatibilityLevel": "JAVA_21", + "mixins": [], + "client": [ + "GuiMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/subprojects/ui/r1.21.0/src/main/resources/quilt.mod.json b/subprojects/ui/r1.21.0/src/main/resources/quilt.mod.json new file mode 100644 index 0000000..f775307 --- /dev/null +++ b/subprojects/ui/r1.21.0/src/main/resources/quilt.mod.json @@ -0,0 +1,47 @@ +{ + "schema_version": 1, + "quilt_loader": { + "group": "net.pixaurora", + "id": "kit_tunes_ui", + "version": "${version}", + "metadata": { + "name": "Kit Tunes UI", + "description": "The things you see!", + "contributors": { + "Pixaurora": "Owner" + }, + "contact": { + "homepage": "https://github.com/Pixaurora/Kit-Tunes", + "issues": "https://github.com/Pixaurora/Kit-Tunes/issues", + "sources": "https://github.com/Pixaurora/Kit-Tunes" + } + }, + "intermediate_mappings": "net.fabricmc:intermediary", + "entrypoints": { + "modmenu": [ + "net.pixaurora.kit_tunes.impl.compat.ModMenuIntegration" + ] + }, + "depends": [ + { + "id": "quilt_loader", + "versions": ">=0.26.0" + }, + { + "id": "minecraft", + "versions": "=1.21.0" + }, + { + "id": "quilted_fabric_resource_loader_v0", + "versions": "*" + } + ] + }, + "mixin": "kit_tunes_ui.mixins.json", + "modmenu": { + "parent": "kit_tunes", + "badges": [ + "library" + ] + } +}