aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build.yml2
-rw-r--r--.gitignore4
-rw-r--r--build-logic/build.gradle.kts (renamed from buildSrc/build.gradle.kts)11
l---------build-logic/gradle/wrapper1
-rwxr-xr-xbuild-logic/gradlew251
-rw-r--r--build-logic/gradlew.bat94
-rw-r--r--build-logic/settings.gradle.kts8
-rw-r--r--build-logic/src/main/kotlin/EnvFile.kt (renamed from buildSrc/src/EnvFile.kt)0
-rw-r--r--build-logic/src/main/kotlin/FabricModTransform.kt (renamed from buildSrc/src/FabricModTransform.kt)0
-rw-r--r--build-logic/src/main/kotlin/InnerJarsUnpacker.kt (renamed from buildSrc/src/InnerJarsUnpacker.kt)0
-rw-r--r--build-logic/src/main/kotlin/RepoDownload.kt (renamed from buildSrc/src/RepoDownload.kt)0
-rw-r--r--build-logic/src/main/kotlin/firmament.base.gradle.kts1
-rw-r--r--build-logic/src/main/kotlin/firmament.common.gradle.kts2
-rw-r--r--build-logic/src/main/kotlin/firmament.license-management.gradle.kts5
-rw-r--r--build-logic/src/main/kotlin/firmament.repositories.gradle.kts46
-rw-r--r--build-logic/src/main/kotlin/licenseinfo.kt (renamed from buildSrc/src/licenseinfo.kt)0
-rw-r--r--build-logic/src/main/kotlin/lookupversion.kt (renamed from buildSrc/src/lookupversion.kt)0
-rw-r--r--build.gradle.kts56
-rw-r--r--gradle/libs.versions.toml3
-rw-r--r--javaplugin/build.gradle.kts1
-rw-r--r--settings.gradle.kts1
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiCommonPlugin.kt2
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiPlugin.kt28
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntryRenderer.kt4
-rw-r--r--src/compat/rei/java/moe/nea/firmament/compat/rei/SBItemEntryDefinition.kt2
-rw-r--r--src/main/kotlin/features/debug/PowerUserTools.kt4
-rw-r--r--src/main/kotlin/features/debug/itemeditor/ItemExporter.kt2
-rw-r--r--src/main/kotlin/features/debug/itemeditor/LegacyItemExporter.kt9
-rw-r--r--src/main/kotlin/features/inventory/SlotLocking.kt68
-rw-r--r--src/main/kotlin/features/inventory/TimerInLore.kt1
-rw-r--r--src/main/kotlin/features/items/EtherwarpOverlay.kt3
-rw-r--r--src/main/kotlin/features/macros/RadialMenu.kt6
-rw-r--r--src/main/kotlin/repo/RepoManager.kt32
-rw-r--r--src/main/kotlin/util/render/LerpUtils.kt6
-rw-r--r--src/main/kotlin/util/skyblock/SkyBlockItems.kt1
-rw-r--r--src/main/resources/firmament.accesswidener5
-rw-r--r--src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomBlockTextures.kt121
-rw-r--r--src/texturePacks/java/moe/nea/firmament/mixins/custommodels/LoadExtraBlockStates.java34
-rw-r--r--symbols/build.gradle.kts5
-rw-r--r--testagent/build.gradle.kts1
-rw-r--r--translations/en_us.json21
-rw-r--r--web/src/pages/docs/_texture-pack-format.md5
42 files changed, 723 insertions, 123 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index b1daf9d..3393d05 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -24,7 +24,7 @@ jobs:
- uses: ./.github/composite/gradle
- name: Build with gradle
run: |
- ./gradlew remapJar --scan
+ ./gradlew assemble --scan
- name: Move build artifact around and print check sum
run: |
rm -f build/libs/*sources*.jar
diff --git a/.gitignore b/.gitignore
index b41569e..c5e4a9e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,8 +6,8 @@
.properties
/.gradle
/build/
-/buildSrc/.gradle
-/buildSrc/build/
+/build-logic/.gradle
+/build-logic/build/
/*/build
.kotlin
diff --git a/buildSrc/build.gradle.kts b/build-logic/build.gradle.kts
index 1b2542b..431a04e 100644
--- a/buildSrc/build.gradle.kts
+++ b/build-logic/build.gradle.kts
@@ -3,11 +3,12 @@
// SPDX-License-Identifier: CC0-1.0
plugins {
- kotlin("jvm") version "2.1.0"
`kotlin-dsl`
+ kotlin("jvm") version "2.0.21"
}
repositories {
mavenCentral()
+ gradlePluginPortal()
maven {
name = "jitpack"
url = uri("https://jitpack.io")
@@ -19,11 +20,3 @@ dependencies {
implementation("net.fabricmc:access-widener:2.1.0")
implementation("com.google.code.gson:gson:2.10.1")
}
-
-sourceSets {
- main {
- kotlin {
- srcDir(file("src"))
- }
- }
-}
diff --git a/build-logic/gradle/wrapper b/build-logic/gradle/wrapper
new file mode 120000
index 0000000..3232fe4
--- /dev/null
+++ b/build-logic/gradle/wrapper
@@ -0,0 +1 @@
+../../gradle/wrapper \ No newline at end of file
diff --git a/build-logic/gradlew b/build-logic/gradlew
new file mode 100755
index 0000000..faf9300
--- /dev/null
+++ b/build-logic/gradlew
@@ -0,0 +1,251 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/build-logic/gradlew.bat b/build-logic/gradlew.bat
new file mode 100644
index 0000000..9d21a21
--- /dev/null
+++ b/build-logic/gradlew.bat
@@ -0,0 +1,94 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+@rem SPDX-License-Identifier: Apache-2.0
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo. 1>&2
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo. 1>&2
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts
new file mode 100644
index 0000000..0108b7a
--- /dev/null
+++ b/build-logic/settings.gradle.kts
@@ -0,0 +1,8 @@
+dependencyResolutionManagement {
+ versionCatalogs {
+ create("libs") {
+ from(files("../gradle/libs.versions.toml"))
+ }
+ }
+}
+rootProject.name = "firm-build-logic"
diff --git a/buildSrc/src/EnvFile.kt b/build-logic/src/main/kotlin/EnvFile.kt
index ceec763..ceec763 100644
--- a/buildSrc/src/EnvFile.kt
+++ b/build-logic/src/main/kotlin/EnvFile.kt
diff --git a/buildSrc/src/FabricModTransform.kt b/build-logic/src/main/kotlin/FabricModTransform.kt
index 53affbe..53affbe 100644
--- a/buildSrc/src/FabricModTransform.kt
+++ b/build-logic/src/main/kotlin/FabricModTransform.kt
diff --git a/buildSrc/src/InnerJarsUnpacker.kt b/build-logic/src/main/kotlin/InnerJarsUnpacker.kt
index de06467..de06467 100644
--- a/buildSrc/src/InnerJarsUnpacker.kt
+++ b/build-logic/src/main/kotlin/InnerJarsUnpacker.kt
diff --git a/buildSrc/src/RepoDownload.kt b/build-logic/src/main/kotlin/RepoDownload.kt
index 42a09b3..42a09b3 100644
--- a/buildSrc/src/RepoDownload.kt
+++ b/build-logic/src/main/kotlin/RepoDownload.kt
diff --git a/build-logic/src/main/kotlin/firmament.base.gradle.kts b/build-logic/src/main/kotlin/firmament.base.gradle.kts
new file mode 100644
index 0000000..8c512a4
--- /dev/null
+++ b/build-logic/src/main/kotlin/firmament.base.gradle.kts
@@ -0,0 +1 @@
+group = "moe.nea.firmament"
diff --git a/build-logic/src/main/kotlin/firmament.common.gradle.kts b/build-logic/src/main/kotlin/firmament.common.gradle.kts
new file mode 100644
index 0000000..a359b3d
--- /dev/null
+++ b/build-logic/src/main/kotlin/firmament.common.gradle.kts
@@ -0,0 +1,2 @@
+apply(plugin = "firmament.base")
+apply(plugin = "firmament.repositories")
diff --git a/build-logic/src/main/kotlin/firmament.license-management.gradle.kts b/build-logic/src/main/kotlin/firmament.license-management.gradle.kts
new file mode 100644
index 0000000..0a2626b
--- /dev/null
+++ b/build-logic/src/main/kotlin/firmament.license-management.gradle.kts
@@ -0,0 +1,5 @@
+apply(plugin = "moe.nea.licenseextractificator")
+
+configure<moe.nea.licenseextractificator.LicenseExtension> {
+ addExtraLicenseMatchers()
+}
diff --git a/build-logic/src/main/kotlin/firmament.repositories.gradle.kts b/build-logic/src/main/kotlin/firmament.repositories.gradle.kts
new file mode 100644
index 0000000..07a5709
--- /dev/null
+++ b/build-logic/src/main/kotlin/firmament.repositories.gradle.kts
@@ -0,0 +1,46 @@
+repositories {
+ mavenCentral()
+ maven("https://maven.terraformersmc.com/releases/")
+ maven("https://maven.shedaniel.me")
+ maven("https://maven.fabricmc.net")
+ maven("https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1")
+ maven("https://api.modrinth.com/maven") {
+ content {
+ includeGroup("maven.modrinth")
+ }
+ }
+ maven("https://repo.sleeping.town") {
+ content {
+ includeGroup("com.unascribed")
+ }
+ }
+ ivy("https://github.com/HotswapProjects/HotswapAgent/releases/download") {
+ patternLayout {
+ artifact("[revision]/[artifact]-[revision].[ext]")
+ }
+ content {
+ includeGroup("virtual.github.hotswapagent")
+ }
+ metadataSources {
+ artifact()
+ }
+ }
+ maven("https://server.bbkr.space/artifactory/libs-release")
+ maven("https://repo.nea.moe/releases")
+ maven("https://maven.notenoughupdates.org/releases")
+ maven("https://repo.nea.moe/mirror")
+ maven("https://jitpack.io/") {
+ content {
+ includeGroupByRegex("(com|io)\\.github\\..+")
+ excludeModule("io.github.cottonmc", "LibGui")
+ }
+ }
+ maven("https://repo.hypixel.net/repository/Hypixel/")
+ maven("https://maven.azureaaron.net/snapshots")
+ maven("https://maven.azureaaron.net/releases")
+ maven("https://www.cursemaven.com")
+ maven("https://maven.isxander.dev/releases") {
+ name = "Xander Maven"
+ }
+ mavenLocal()
+}
diff --git a/buildSrc/src/licenseinfo.kt b/build-logic/src/main/kotlin/licenseinfo.kt
index 50e4593..50e4593 100644
--- a/buildSrc/src/licenseinfo.kt
+++ b/build-logic/src/main/kotlin/licenseinfo.kt
diff --git a/buildSrc/src/lookupversion.kt b/build-logic/src/main/kotlin/lookupversion.kt
index 8a7c2de..8a7c2de 100644
--- a/buildSrc/src/lookupversion.kt
+++ b/build-logic/src/main/kotlin/lookupversion.kt
diff --git a/build.gradle.kts b/build.gradle.kts
index 065925a..c8bdfdb 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -28,14 +28,15 @@ plugins {
alias(libs.plugins.kotlin.plugin.powerassert)
alias(libs.plugins.kotlin.plugin.ksp)
// alias(libs.plugins.loom)
+ alias(libs.plugins.shadow) apply false
// TODO: use arch loom once they update to 1.8
id("fabric-loom") version "1.10.1"
- id("moe.nea.licenseextractificator")
+ id("firmament.common")
+ id("firmament.license-management")
alias(libs.plugins.mcAutoTranslations)
}
version = getGitTagInfo(libs.versions.minecraft.get())
-group = rootProject.property("maven_group").toString()
java {
withSourcesJar()
@@ -43,6 +44,7 @@ java {
languageVersion.set(JavaLanguageVersion.of(21))
}
}
+
loom {
mixin.useLegacyMixinAp.set(false)
}
@@ -53,54 +55,6 @@ tasks.withType(KotlinCompile::class) {
}
}
-allprojects {
- repositories {
- mavenCentral()
- maven("https://maven.terraformersmc.com/releases/")
- maven("https://maven.shedaniel.me")
- maven("https://maven.fabricmc.net")
- maven("https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1")
- maven("https://api.modrinth.com/maven") {
- content {
- includeGroup("maven.modrinth")
- }
- }
- maven("https://repo.sleeping.town") {
- content {
- includeGroup("com.unascribed")
- }
- }
- ivy("https://github.com/HotswapProjects/HotswapAgent/releases/download") {
- patternLayout {
- artifact("[revision]/[artifact]-[revision].[ext]")
- }
- content {
- includeGroup("virtual.github.hotswapagent")
- }
- metadataSources {
- artifact()
- }
- }
- maven("https://server.bbkr.space/artifactory/libs-release")
- maven("https://repo.nea.moe/releases")
- maven("https://maven.notenoughupdates.org/releases")
- maven("https://repo.nea.moe/mirror")
- maven("https://jitpack.io/") {
- content {
- includeGroupByRegex("(com|io)\\.github\\..+")
- excludeModule("io.github.cottonmc", "LibGui")
- }
- }
- maven("https://repo.hypixel.net/repository/Hypixel/")
- maven("https://maven.azureaaron.net/snapshots")
- maven("https://maven.azureaaron.net/releases")
- maven("https://www.cursemaven.com")
- maven("https://maven.isxander.dev/releases") {
- name = "Xander Maven"
- }
- mavenLocal()
- }
-}
kotlin {
sourceSets.all {
languageSettings {
@@ -565,5 +519,3 @@ tasks.withType<AbstractArchiveTask>().configureEach {
isPreserveFileTimestamps = false
isReproducibleFileOrder = true
}
-
-licensing.addExtraLicenseMatchers()
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index f536faf..d4ff2c4 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -73,7 +73,7 @@ jarvis = "1.1.4"
nealisp = "1.1.0"
# Update from https://github.com/NotEnoughUpdates/MoulConfig/tags
-moulconfig = "4.0.0-beta"
+moulconfig = "4.0.1-beta"
# Update from https://repo.nea.moe/#/releases/moe/nea/mc-auto-translations/moe.nea.mc-auto-translations.gradle.plugin
mcAutoTranslations = "0.3.0"
@@ -163,5 +163,6 @@ kotlin_jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin_plugin_serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
kotlin_plugin_powerassert = { id = "org.jetbrains.kotlin.plugin.power-assert", version.ref = "kotlin" }
kotlin_plugin_ksp = { id = "com.google.devtools.ksp", version.ref = "kotlin_ksp" }
+shadow = { id = "com.gradleup.shadow", version.ref = "shadow" }
loom = { id = "dev.architectury.loom", version.ref = "loom" }
mcAutoTranslations = { id = "moe.nea.mc-auto-translations", version.ref = "mcAutoTranslations" }
diff --git a/javaplugin/build.gradle.kts b/javaplugin/build.gradle.kts
index 6982a5a..dc461bc 100644
--- a/javaplugin/build.gradle.kts
+++ b/javaplugin/build.gradle.kts
@@ -1,6 +1,7 @@
plugins {
java
idea
+ id("firmament.common")
}
dependencies {
implementation("net.fabricmc:stitch:0.6.2")
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 8a5dc47..7b298b6 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -39,3 +39,4 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
include("symbols")
include("javaplugin")
include("testagent")
+includeBuild("build-logic")
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiCommonPlugin.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiCommonPlugin.kt
index 98ac276..71e867a 100644
--- a/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiCommonPlugin.kt
+++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiCommonPlugin.kt
@@ -2,9 +2,11 @@ package moe.nea.firmament.compat.rei
import me.shedaniel.rei.api.common.entry.type.EntryTypeRegistry
import me.shedaniel.rei.api.common.plugins.REICommonPlugin
+import moe.nea.firmament.repo.RepoManager
class FirmamentReiCommonPlugin : REICommonPlugin {
override fun registerEntryTypes(registry: EntryTypeRegistry) {
+ if (!RepoManager.shouldLoadREI()) return
registry.register(FirmamentReiPlugin.SKYBLOCK_ITEM_TYPE_ID, SBItemEntryDefinition)
}
}
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiPlugin.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiPlugin.kt
index 89c3e19..3a494b9 100644
--- a/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiPlugin.kt
+++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiPlugin.kt
@@ -55,6 +55,7 @@ class FirmamentReiPlugin : REIClientPlugin {
@OptIn(ExpensiveItemCacheApi::class)
override fun registerTransferHandlers(registry: TransferHandlerRegistry) {
+ if (!RepoManager.shouldLoadREI()) return
registry.register(TransferHandler { context ->
val screen = context.containerScreen
val display = context.display
@@ -64,8 +65,11 @@ class FirmamentReiPlugin : REIClientPlugin {
val neuItem = RepoManager.getNEUItem(SkyblockId(recipe.output.itemId))
?: error("Could not find neu item ${recipe.output.itemId} which is used in a recipe output")
val useSuperCraft = context.isStackedCrafting || RepoManager.Config.alwaysSuperCraft
- if (neuItem.isVanilla && useSuperCraft) return@TransferHandler TransferHandler.Result.createFailed(Text.translatable(
- "firmament.recipe.novanilla"))
+ if (neuItem.isVanilla && useSuperCraft) return@TransferHandler TransferHandler.Result.createFailed(
+ Text.translatable(
+ "firmament.recipe.novanilla"
+ )
+ )
var shouldReturn = true
if (context.isActuallyCrafting && !useSuperCraft) {
val craftingScreen = (screen as? GenericContainerScreen)
@@ -85,13 +89,16 @@ class FirmamentReiPlugin : REIClientPlugin {
}
- val generics = listOf<GenericREIRecipeCategory<*>>( // Order matters: The order in here is the order in which they show up in REI
+ val generics = listOf<GenericREIRecipeCategory<*>>(
+ // Order matters: The order in here is the order in which they show up in REI
GenericREIRecipeCategory(SBCraftingRecipeRenderer),
GenericREIRecipeCategory(SBForgeRecipeRenderer),
GenericREIRecipeCategory(SBEssenceUpgradeRecipeRenderer),
)
override fun registerCategories(registry: CategoryRegistry) {
+ if (!RepoManager.shouldLoadREI()) return
+
registry.add(generics)
registry.add(SBMobDropRecipe.Category)
registry.add(SBKatRecipe.Category)
@@ -105,6 +112,8 @@ class FirmamentReiPlugin : REIClientPlugin {
}
override fun registerDisplays(registry: DisplayRegistry) {
+ if (!RepoManager.shouldLoadREI()) return
+
generics.forEach {
it.registerDynamicGenerator(registry)
}
@@ -114,16 +123,21 @@ class FirmamentReiPlugin : REIClientPlugin {
)
registry.registerDisplayGenerator(
SBMobDropRecipe.Category.categoryIdentifier,
- SkyblockMobDropRecipeDynamicGenerator)
+ SkyblockMobDropRecipeDynamicGenerator
+ )
registry.registerDisplayGenerator(
SBShopRecipe.Category.categoryIdentifier,
- SkyblockShopRecipeDynamicGenerator)
+ SkyblockShopRecipeDynamicGenerator
+ )
registry.registerDisplayGenerator(
SBKatRecipe.Category.categoryIdentifier,
- SkyblockKatRecipeDynamicGenerator)
+ SkyblockKatRecipeDynamicGenerator
+ )
}
override fun registerCollapsibleEntries(registry: CollapsibleEntryRegistry) {
+ if (!RepoManager.shouldLoadREI()) return
+
if (!RepoManager.Config.disableItemGroups)
RepoManager.neuRepo.constants.parents.parents
.forEach { (parent, children) ->
@@ -148,6 +162,8 @@ class FirmamentReiPlugin : REIClientPlugin {
}
override fun registerEntries(registry: EntryRegistry) {
+ if (!RepoManager.shouldLoadREI()) return
+
registry.removeEntryIf { true }
RepoManager.neuRepo.items?.items?.values?.forEach { neuItem ->
registry.addEntry(SBItemEntryDefinition.getEntry(neuItem.skyblockId))
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntryRenderer.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntryRenderer.kt
index d73500a..5e4eee3 100644
--- a/src/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntryRenderer.kt
+++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntryRenderer.kt
@@ -45,7 +45,7 @@ object NEUItemEntryRenderer : EntryRenderer<SBItemStack> {
delta: Float
) {
val neuItem = entry.value.neuItem
- val itemToRender = if(RepoManager.Config.perfectRenders < RepoManager.PerfectRender.RENDER && !entry.value.isWarm() && neuItem != null) {
+ val itemToRender = if(!RepoManager.Config.perfectRenders.rendersPerfectVisuals() && !entry.value.isWarm() && neuItem != null) {
ItemCache.recacheSoon(neuItem)
ItemStack(Items.PAINTING)
} else {
@@ -72,7 +72,7 @@ object NEUItemEntryRenderer : EntryRenderer<SBItemStack> {
@OptIn(ExpensiveItemCacheApi::class)
override fun getTooltip(entry: EntryStack<SBItemStack>, tooltipContext: TooltipContext): Tooltip? {
- if (!entry.value.isWarm() && RepoManager.Config.perfectRenders < RepoManager.PerfectRender.RENDER_AND_TEXT) {
+ if (!entry.value.isWarm() && !RepoManager.Config.perfectRenders.rendersPerfectText()) {
val neuItem = entry.value.neuItem
if (neuItem != null) {
val lore = mutableListOf<Text>()
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/SBItemEntryDefinition.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/SBItemEntryDefinition.kt
index 1d0a611..740eeeb 100644
--- a/src/compat/rei/java/moe/nea/firmament/compat/rei/SBItemEntryDefinition.kt
+++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/SBItemEntryDefinition.kt
@@ -46,7 +46,7 @@ object SBItemEntryDefinition : EntryDefinition<SBItemStack> {
@OptIn(ExpensiveItemCacheApi::class)
override fun asFormattedText(entry: EntryStack<SBItemStack>, value: SBItemStack): Text {
val neuItem = entry.value.neuItem
- return if (RepoManager.Config.perfectRenders < RepoManager.PerfectRender.RENDER_AND_TEXT || entry.value.isWarm() || neuItem == null) {
+ return if (!RepoManager.Config.perfectRenders.rendersPerfectText() || entry.value.isWarm() || neuItem == null) {
VanillaEntryTypes.ITEM.definition.asFormattedText(entry.asItemEntry(), value.asImmutableItemStack())
} else {
Text.literal(neuItem.displayName)
diff --git a/src/main/kotlin/features/debug/PowerUserTools.kt b/src/main/kotlin/features/debug/PowerUserTools.kt
index 1a7b2cf..0800a4f 100644
--- a/src/main/kotlin/features/debug/PowerUserTools.kt
+++ b/src/main/kotlin/features/debug/PowerUserTools.kt
@@ -41,6 +41,7 @@ import moe.nea.firmament.util.mc.iterableArmorItems
import moe.nea.firmament.util.mc.loreAccordingToNbt
import moe.nea.firmament.util.skyBlockId
import moe.nea.firmament.util.tr
+import moe.nea.firmament.util.grey
object PowerUserTools : FirmamentFeature {
override val identifier: String
@@ -60,6 +61,7 @@ object PowerUserTools : FirmamentFeature {
val exportUIRecipes by keyBindingWithDefaultUnbound("export-recipe")
val exportNpcLocation by keyBindingWithDefaultUnbound("export-npc-location")
val highlightNonOverlayItems by toggle("highlight-non-overlay") { false }
+ val dontHighlightSemicolonItems by toggle("dont-highlight-semicolon-items") { false }
}
override val config
@@ -228,7 +230,7 @@ object PowerUserTools : FirmamentFeature {
fun addItemId(it: ItemTooltipEvent) {
if (TConfig.showItemIds) {
val id = it.stack.skyBlockId ?: return
- it.lines.add(Text.stringifiedTranslatable("firmament.tooltip.skyblockid", id.neuItem))
+ it.lines.add(Text.stringifiedTranslatable("firmament.tooltip.skyblockid", id.neuItem).grey())
}
val (item, text) = lastCopiedStack ?: return
if (!ItemStack.areEqual(item, it.stack)) {
diff --git a/src/main/kotlin/features/debug/itemeditor/ItemExporter.kt b/src/main/kotlin/features/debug/itemeditor/ItemExporter.kt
index c521b5a..2a56204 100644
--- a/src/main/kotlin/features/debug/itemeditor/ItemExporter.kt
+++ b/src/main/kotlin/features/debug/itemeditor/ItemExporter.kt
@@ -215,6 +215,8 @@ object ItemExporter {
return
}
val stack = event.slot.stack ?: return
+ val id = event.slot.stack.skyBlockId?.neuItem
+ if (PowerUserTools.TConfig.dontHighlightSemicolonItems && id != null && id.contains(";")) return
val isExported = nonOverlayCache.getOrPut(stack.skyBlockId ?: return) {
RepoDownloadManager.repoSavedLocation.resolve("itemsOverlay")
.resolve(ExportedTestConstantMeta.current.dataVersion.toString())
diff --git a/src/main/kotlin/features/debug/itemeditor/LegacyItemExporter.kt b/src/main/kotlin/features/debug/itemeditor/LegacyItemExporter.kt
index ad03b16..ecf3d2c 100644
--- a/src/main/kotlin/features/debug/itemeditor/LegacyItemExporter.kt
+++ b/src/main/kotlin/features/debug/itemeditor/LegacyItemExporter.kt
@@ -5,6 +5,7 @@ import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put
import kotlin.concurrent.thread
+import kotlin.jvm.optionals.getOrNull
import net.minecraft.component.DataComponentTypes
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NbtByte
@@ -14,6 +15,7 @@ import net.minecraft.nbt.NbtInt
import net.minecraft.nbt.NbtList
import net.minecraft.nbt.NbtOps
import net.minecraft.nbt.NbtString
+import net.minecraft.registry.tag.ItemTags
import net.minecraft.text.Text
import net.minecraft.util.Unit
import moe.nea.firmament.Firmament
@@ -39,6 +41,7 @@ import moe.nea.firmament.util.unformattedString
class LegacyItemExporter private constructor(var itemStack: ItemStack) {
init {
require(!itemStack.isEmpty)
+ itemStack.count = 1
}
var lore = itemStack.loreAccordingToNbt
@@ -171,7 +174,11 @@ class LegacyItemExporter private constructor(var itemStack: ItemStack) {
}
private fun copyColour() {
- val leatherTint = itemStack.get(DataComponentTypes.DYED_COLOR) ?: return
+ if (!itemStack.isIn(ItemTags.DYEABLE)) {
+ itemStack.remove(DataComponentTypes.DYED_COLOR)
+ return
+ }
+ val leatherTint = itemStack.componentChanges.get(DataComponentTypes.DYED_COLOR)?.getOrNull() ?: return
legacyNbt.getOrPutCompound("display").put("color", NbtInt.of(leatherTint.rgb))
}
diff --git a/src/main/kotlin/features/inventory/SlotLocking.kt b/src/main/kotlin/features/inventory/SlotLocking.kt
index d3348a2..0a3f01b 100644
--- a/src/main/kotlin/features/inventory/SlotLocking.kt
+++ b/src/main/kotlin/features/inventory/SlotLocking.kt
@@ -4,7 +4,6 @@ package moe.nea.firmament.features.inventory
import java.util.UUID
import org.lwjgl.glfw.GLFW
-import util.render.CustomRenderLayers
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers
@@ -19,9 +18,8 @@ import kotlinx.serialization.json.int
import kotlinx.serialization.serializer
import net.minecraft.client.gui.screen.ingame.HandledScreen
import net.minecraft.client.render.RenderLayer
-import net.minecraft.client.render.RenderLayers
-import net.minecraft.client.render.TexturedRenderLayers
import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.item.ItemStack
import net.minecraft.screen.GenericContainerScreenHandler
import net.minecraft.screen.slot.Slot
import net.minecraft.screen.slot.SlotActionType
@@ -44,14 +42,20 @@ import moe.nea.firmament.util.MC
import moe.nea.firmament.util.SBData
import moe.nea.firmament.util.SkyBlockIsland
import moe.nea.firmament.util.data.ProfileSpecificDataHolder
+import moe.nea.firmament.util.extraAttributes
import moe.nea.firmament.util.json.DashlessUUIDSerializer
+import moe.nea.firmament.util.lime
import moe.nea.firmament.util.mc.ScreenUtil.getSlotByIndex
import moe.nea.firmament.util.mc.SlotUtils.swapWithHotBar
import moe.nea.firmament.util.mc.displayNameAccordingToNbt
import moe.nea.firmament.util.mc.loreAccordingToNbt
+import moe.nea.firmament.util.red
import moe.nea.firmament.util.render.drawLine
+import moe.nea.firmament.util.skyBlockId
import moe.nea.firmament.util.skyblock.DungeonUtil
+import moe.nea.firmament.util.skyblock.SkyBlockItems
import moe.nea.firmament.util.skyblockUUID
+import moe.nea.firmament.util.tr
import moe.nea.firmament.util.unformattedString
object SlotLocking : FirmamentFeature {
@@ -132,6 +136,7 @@ object SlotLocking : FirmamentFeature {
val slotBindRequireShift by toggle("require-quick-move") { true }
val slotRenderLines by choice("bind-render") { SlotRenderLinesMode.ONLY_BOXES }
val allowMultiBinding by toggle("multi-bind") { true } // TODO: filter based on this option
+ val protectAllHuntingBoxes by toggle("hunting-box") { false }
val allowDroppingInDungeons by toggle("drop-in-dungeons") { true }
}
@@ -193,10 +198,12 @@ object SlotLocking : FirmamentFeature {
var anyBlocked = false
for (i in 0 until event.slot.index) {
val stack = inv.getStack(i)
- if (IsSlotProtectedEvent.shouldBlockInteraction(null,
- SlotActionType.THROW,
- IsSlotProtectedEvent.MoveOrigin.SALVAGE,
- stack)
+ if (IsSlotProtectedEvent.shouldBlockInteraction(
+ null,
+ SlotActionType.THROW,
+ IsSlotProtectedEvent.MoveOrigin.SALVAGE,
+ stack
+ )
)
anyBlocked = true
}
@@ -219,12 +226,20 @@ object SlotLocking : FirmamentFeature {
&& doesNotDeleteItem
) return
val stack = event.itemStack ?: return
+ if (TConfig.protectAllHuntingBoxes && (stack.isHuntingBox())) {
+ event.protect()
+ return
+ }
val uuid = stack.skyblockUUID ?: return
if (uuid in (lockedUUIDs ?: return)) {
event.protect()
}
}
+ fun ItemStack.isHuntingBox(): Boolean {
+ return skyBlockId == SkyBlockItems.HUNTING_TOOLKIT || extraAttributes.get("tool_kit") != null
+ }
+
@Subscribe
fun onProtectSlot(it: IsSlotProtectedEvent) {
if (it.slot != null && it.slot.inventory is PlayerInventory && it.slot.index in (lockedSlots ?: setOf())) {
@@ -271,6 +286,21 @@ object SlotLocking : FirmamentFeature {
val slot = inventory.focusedSlot_Firmament ?: return
val stack = slot.stack ?: return
+ if (stack.isHuntingBox()) {
+ MC.sendChat(
+ tr(
+ "firmament.slot-locking.hunting-box-unbindable-hint",
+ "The hunting box cannot be UUID bound reliably. It changes its own UUID frequently when switching tools. "
+ ).red().append(
+ tr(
+ "firmament.slot-locking.hunting-box-unbindable-hint.solution",
+ "Use the Firmament config option for locking all hunting boxes instead."
+ ).lime()
+ )
+ )
+ CommonSoundEffects.playFailure()
+ return
+ }
val uuid = stack.skyblockUUID ?: return
val lockedUUIDs = lockedUUIDs ?: return
if (uuid in lockedUUIDs) {
@@ -350,12 +380,16 @@ object SlotLocking : FirmamentFeature {
hotX + sx, hotY + sy,
color(anyHovered)
)
- event.context.drawBorder(hotbarSlot.x + sx,
- hotbarSlot.y + sy,
- 16, 16, color(hotbarSlot in highlitSlots).color)
- event.context.drawBorder(inventorySlot.x + sx,
- inventorySlot.y + sy,
- 16, 16, color(inventorySlot in highlitSlots).color)
+ event.context.drawBorder(
+ hotbarSlot.x + sx,
+ hotbarSlot.y + sy,
+ 16, 16, color(hotbarSlot in highlitSlots).color
+ )
+ event.context.drawBorder(
+ inventorySlot.x + sx,
+ inventorySlot.y + sy,
+ 16, 16, color(inventorySlot in highlitSlots).color
+ )
}
}
@@ -383,9 +417,11 @@ object SlotLocking : FirmamentFeature {
hovX + sx, hovY + sy,
me.shedaniel.math.Color.ofOpaque(0x00FF00)
)
- event.context.drawBorder(hoveredSlot.x + sx,
- hoveredSlot.y + sy,
- 16, 16, 0xFF00FF00u.toInt())
+ event.context.drawBorder(
+ hoveredSlot.x + sx,
+ hoveredSlot.y + sy,
+ 16, 16, 0xFF00FF00u.toInt()
+ )
}
}
diff --git a/src/main/kotlin/features/inventory/TimerInLore.kt b/src/main/kotlin/features/inventory/TimerInLore.kt
index cc1df9a..e939404 100644
--- a/src/main/kotlin/features/inventory/TimerInLore.kt
+++ b/src/main/kotlin/features/inventory/TimerInLore.kt
@@ -47,6 +47,7 @@ object TimerInLore {
appendValue(ChronoField.SECOND_OF_MINUTE, 2)
}),
AMERICAN("EEEE, MMM d h:mm a yyyy"),
+ RFCPrecise(DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss.SSS Z")),
;
constructor(block: DateTimeFormatterBuilder.() -> Unit)
diff --git a/src/main/kotlin/features/items/EtherwarpOverlay.kt b/src/main/kotlin/features/items/EtherwarpOverlay.kt
index b1f695a..f6ab1a2 100644
--- a/src/main/kotlin/features/items/EtherwarpOverlay.kt
+++ b/src/main/kotlin/features/items/EtherwarpOverlay.kt
@@ -19,6 +19,7 @@ object EtherwarpOverlay : FirmamentFeature {
object TConfig : ManagedConfig(identifier, Category.ITEMS) {
var etherwarpOverlay by toggle("etherwarp-overlay") { false }
+ var onlyShowWhileSneaking by toggle("only-show-while-sneaking") { true }
var cube by toggle("cube") { true }
val cubeColour by colour("cube-colour") { ChromaColour.fromStaticRGB(172, 0, 255, 60) }
var wireframe by toggle("wireframe") { false }
@@ -32,7 +33,7 @@ object EtherwarpOverlay : FirmamentFeature {
fun renderEtherwarpOverlay(event: WorldRenderLastEvent) {
if (!TConfig.etherwarpOverlay) return
val player = MC.player ?: return
- if (!player.isSneaking) return
+ if (TConfig.onlyShowWhileSneaking && !player.isSneaking) return
val world = player.world
val camera = MC.camera ?: return
val heldItem = MC.stackInHand
diff --git a/src/main/kotlin/features/macros/RadialMenu.kt b/src/main/kotlin/features/macros/RadialMenu.kt
index 2e09c44..9e5222f 100644
--- a/src/main/kotlin/features/macros/RadialMenu.kt
+++ b/src/main/kotlin/features/macros/RadialMenu.kt
@@ -36,7 +36,11 @@ object RadialMenuViewer {
var activeMenu: RadialMenu? = null
set(value) {
- field = value
+ if (value?.options.isNullOrEmpty()) {
+ field = null
+ } else {
+ field = value
+ }
delta = Vector2f(0F, 0F)
}
var delta = Vector2f(0F, 0F)
diff --git a/src/main/kotlin/repo/RepoManager.kt b/src/main/kotlin/repo/RepoManager.kt
index df89092..c3d1c52 100644
--- a/src/main/kotlin/repo/RepoManager.kt
+++ b/src/main/kotlin/repo/RepoManager.kt
@@ -7,7 +7,9 @@ import io.github.moulberry.repo.data.NEURecipe
import io.github.moulberry.repo.data.Rarity
import java.nio.file.Path
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents
+import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
import net.minecraft.client.MinecraftClient
import net.minecraft.network.packet.s2c.play.SynchronizeRecipesS2CPacket
import net.minecraft.recipe.display.CuttingRecipeDisplay
@@ -35,11 +37,13 @@ object RepoManager {
branch = "master"
save()
}
-
+ val enableREI by toggle("enable-rei") { true }
val disableItemGroups by toggle("disable-item-groups") { true }
val reload by button("reload") {
save()
- RepoManager.reload()
+ Firmament.coroutineScope.launch {
+ RepoManager.reload()
+ }
}
val redownload by button("redownload") {
save()
@@ -56,6 +60,9 @@ object RepoManager {
RENDER_AND_TEXT("text"),
;
+ fun rendersPerfectText() = this == RENDER_AND_TEXT
+ fun rendersPerfectVisuals() = this == RENDER || this == RENDER_AND_TEXT
+
override fun asString(): String? = label
}
@@ -131,16 +138,17 @@ object RepoManager {
fun reloadForTest(from: Path) {
neuRepo = makeNEURepository(from)
- reload()
+ reloadSync()
}
- fun reload() {
- if (!TestUtil.isInTest && !MC.instance.isOnThread) {
- MC.instance.send {
- reload()
- }
- return
+
+ suspend fun reload() {
+ withContext(Dispatchers.IO) {
+ reloadSync()
}
+ }
+
+ fun reloadSync() {
try {
logger.info("Repo reload started.")
neuRepo.reload()
@@ -168,7 +176,9 @@ object RepoManager {
if (Config.autoUpdate) {
launchAsyncUpdate()
} else {
- reload()
+ Firmament.coroutineScope.launch {
+ reload()
+ }
}
}
@@ -196,4 +206,6 @@ object RepoManager {
fun getRepoRef(): String {
return "${Config.username}/${Config.reponame}#${Config.branch}"
}
+
+ fun shouldLoadREI(): Boolean = Config.enableREI
}
diff --git a/src/main/kotlin/util/render/LerpUtils.kt b/src/main/kotlin/util/render/LerpUtils.kt
index 63a13ec..e7f226c 100644
--- a/src/main/kotlin/util/render/LerpUtils.kt
+++ b/src/main/kotlin/util/render/LerpUtils.kt
@@ -1,11 +1,15 @@
package moe.nea.firmament.util.render
import me.shedaniel.math.Color
+import kotlin.math.absoluteValue
val π = Math.PI
val τ = Math.PI * 2
-fun lerpAngle(a: Float, b: Float, progress: Float): Float {
+fun lerpAngle(a: Float, b: Float, progress: Float): Float {
// TODO: there is at least 10 mods to many in here lol
+ if (((b - a).absoluteValue - π).absoluteValue < 0.0001) {
+ return lerp(a, b, progress)
+ }
val shortestAngle = ((((b.mod(τ) - a.mod(τ)).mod(τ)) + τ + π).mod(τ)) - π
return ((a + (shortestAngle) * progress).mod(τ)).toFloat()
}
diff --git a/src/main/kotlin/util/skyblock/SkyBlockItems.kt b/src/main/kotlin/util/skyblock/SkyBlockItems.kt
index 4f208dd..d552fd7 100644
--- a/src/main/kotlin/util/skyblock/SkyBlockItems.kt
+++ b/src/main/kotlin/util/skyblock/SkyBlockItems.kt
@@ -19,4 +19,5 @@ object SkyBlockItems {
val BONE_BOOMERANG = SkyblockId("BONE_BOOMERANG")
val STARRED_BONE_BOOMERANG = SkyblockId("STARRED_BONE_BOOMERANG")
val TRIBAL_SPEAR = SkyblockId("TRIBAL_SPEAR")
+ val HUNTING_TOOLKIT = SkyblockId("HUNTING_TOOLKIT")
}
diff --git a/src/main/resources/firmament.accesswidener b/src/main/resources/firmament.accesswidener
index 71f63ac..0b7b830 100644
--- a/src/main/resources/firmament.accesswidener
+++ b/src/main/resources/firmament.accesswidener
@@ -16,6 +16,11 @@ accessible method net/minecraft/entity/decoration/ArmorStandEntity setSmall (Z)V
accessible method net/minecraft/resource/NamespaceResourceManager loadMetadata (Lnet/minecraft/resource/InputSupplier;)Lnet/minecraft/resource/metadata/ResourceMetadata;
accessible method net/minecraft/client/gui/DrawContext drawTexturedQuad (Ljava/util/function/Function;Lnet/minecraft/util/Identifier;IIIIFFFFI)V
+accessible class net/minecraft/client/render/model/BlockStatesLoader$LoadedBlockStateDefinition
+accessible field net/minecraft/client/render/model/BlockStatesLoader FINDER Lnet/minecraft/resource/ResourceFinder;
+accessible method net/minecraft/client/render/model/BlockStatesLoader$LoadedBlockStateDefinition <init> (Ljava/lang/String;Lnet/minecraft/client/render/model/json/BlockModelDefinition;)V
+accessible method net/minecraft/client/render/model/BlockStatesLoader combine (Lnet/minecraft/util/Identifier;Lnet/minecraft/state/StateManager;Ljava/util/List;)Lnet/minecraft/client/render/model/BlockStatesLoader$LoadedModels;
+
mutable field net/minecraft/screen/slot/Slot x I
mutable field net/minecraft/screen/slot/Slot y I
diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomBlockTextures.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomBlockTextures.kt
index 462b1e1..2d7a978 100644
--- a/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomBlockTextures.kt
+++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomBlockTextures.kt
@@ -2,6 +2,9 @@
package moe.nea.firmament.features.texturepack
+import com.google.gson.JsonParseException
+import com.google.gson.JsonParser
+import com.mojang.serialization.JsonOps
import java.util.concurrent.CompletableFuture
import java.util.concurrent.Executor
import java.util.function.Function
@@ -21,15 +24,21 @@ import kotlinx.serialization.serializer
import kotlin.jvm.optionals.getOrNull
import net.minecraft.block.Block
import net.minecraft.block.BlockState
+import net.minecraft.block.Blocks
import net.minecraft.client.render.model.Baker
import net.minecraft.client.render.model.BlockStateModel
+import net.minecraft.client.render.model.BlockStatesLoader
import net.minecraft.client.render.model.ReferencedModelsCollector
import net.minecraft.client.render.model.SimpleBlockStateModel
+import net.minecraft.client.render.model.json.BlockModelDefinition
import net.minecraft.client.render.model.json.ModelVariant
+import net.minecraft.registry.Registries
import net.minecraft.registry.RegistryKey
import net.minecraft.registry.RegistryKeys
+import net.minecraft.resource.Resource
import net.minecraft.resource.ResourceManager
import net.minecraft.resource.SinglePreparationResourceReloader
+import net.minecraft.state.StateManager
import net.minecraft.util.Identifier
import net.minecraft.util.math.BlockPos
import net.minecraft.util.profiler.Profiler
@@ -41,6 +50,7 @@ import moe.nea.firmament.events.FinalizeResourceManagerEvent
import moe.nea.firmament.events.SkyblockServerUpdateEvent
import moe.nea.firmament.features.texturepack.CustomBlockTextures.createBakedModels
import moe.nea.firmament.features.texturepack.CustomGlobalTextures.logger
+import moe.nea.firmament.util.ErrorUtil
import moe.nea.firmament.util.IdentifierSerializer
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.SBData
@@ -62,12 +72,28 @@ object CustomBlockTextures {
val block: Identifier,
val sound: Identifier?,
) {
+ fun replace(block: BlockState): BlockStateModel? {
+ blockStateMap?.let { return it[block] }
+ return blockModel
+ }
+
+ @Transient
+ lateinit var overridingBlock: Block
@Transient
val blockModelIdentifier get() = block.withPrefixedPath("block/")
/**
- * Guaranteed to be set after [BakedReplacements.modelBakingFuture] is complete.
+ * Guaranteed to be set after [BakedReplacements.modelBakingFuture] is complete, if [unbakedBlockStateMap] is set.
+ */
+ @Transient
+ var blockStateMap: Map<BlockState, BlockStateModel>? = null
+
+ @Transient
+ var unbakedBlockStateMap: Map<BlockState, BlockStateModel.UnbakedGrouped>? = null
+
+ /**
+ * Guaranteed to be set after [BakedReplacements.modelBakingFuture] is complete. Prefer [blockStateMap] if present.
*/
@Transient
lateinit var blockModel: BlockStateModel
@@ -139,7 +165,15 @@ object CustomBlockTextures {
data class LocationReplacements(
val lookup: Map<Block, List<BlockReplacement>>
- )
+ ) {
+ init {
+ lookup.forEach { (block, replacements) ->
+ for (replacement in replacements) {
+ replacement.replacement.overridingBlock = block
+ }
+ }
+ }
+ }
data class BlockReplacement(
val checks: List<Area>?,
@@ -213,7 +247,7 @@ object CustomBlockTextures {
@JvmStatic
fun getReplacementModel(block: BlockState, blockPos: BlockPos?): BlockStateModel? {
- return getReplacement(block, blockPos)?.blockModel
+ return getReplacement(block, blockPos)?.replace(block)
}
@JvmStatic
@@ -236,8 +270,12 @@ object CustomBlockTextures {
}
@Volatile
- var preparationFuture: CompletableFuture<BakedReplacements> = CompletableFuture.completedFuture(BakedReplacements(
- mapOf()))
+ @get:JvmStatic
+ var preparationFuture: CompletableFuture<BakedReplacements> = CompletableFuture.completedFuture(
+ BakedReplacements(
+ mapOf()
+ )
+ )
val insideFallbackCall = ThreadLocal.withInitial { 0 }
@@ -257,7 +295,8 @@ object CustomBlockTextures {
fun onEarlyReload(event: EarlyResourceReloadEvent) {
preparationFuture = CompletableFuture
.supplyAsync(
- { prepare(event.resourceManager) }, event.preparationExecutor)
+ { prepare(event.resourceManager) }, event.preparationExecutor
+ )
}
private fun prepare(manager: ResourceManager): BakedReplacements {
@@ -295,7 +334,7 @@ object CustomBlockTextures {
@Subscribe
fun onStart(event: FinalizeResourceManagerEvent) {
event.resourceManager.registerReloader(object :
- SinglePreparationResourceReloader<BakedReplacements>() {
+ SinglePreparationResourceReloader<BakedReplacements>() {
override fun prepare(manager: ResourceManager, profiler: Profiler): BakedReplacements {
return preparationFuture.join().also {
it.modelBakingFuture.join()
@@ -328,12 +367,28 @@ object CustomBlockTextures {
@JvmStatic
fun collectExtraModels(modelsCollector: ReferencedModelsCollector) {
preparationFuture.join().collectAllReplacements()
- .forEach { modelsCollector.resolve(simpleBlockModel(it.blockModelIdentifier)) }
+ .forEach {
+ modelsCollector.resolve(simpleBlockModel(it.blockModelIdentifier))
+ it.unbakedBlockStateMap?.values?.forEach {
+ modelsCollector.resolve(it)
+ }
+ }
}
@JvmStatic
fun createBakedModels(baker: Baker, executor: Executor): CompletableFuture<Void?> {
return preparationFuture.thenComposeAsync(Function { replacements ->
+ val allBlockStates = CompletableFuture.allOf(
+ *replacements.collectAllReplacements().filter { it.unbakedBlockStateMap != null }.map {
+ CompletableFuture.supplyAsync({
+ it.blockStateMap = it.unbakedBlockStateMap
+ ?.map {
+ it.key to it.value.bake(it.key, baker)
+ }
+ ?.toMap()
+ }, executor)
+ }.toList().toTypedArray()
+ )
val byModel = replacements.collectAllReplacements().groupBy { it.blockModelIdentifier }
val modelBakingTask = AsyncHelper.mapValues(byModel, { blockId, replacements ->
val unbakedModel = SimpleBlockStateModel.Unbaked(
@@ -344,7 +399,55 @@ object CustomBlockTextures {
it.blockModel = baked
}
}, executor)
- modelBakingTask.thenAcceptAsync { replacements.modelBakingFuture.complete(Unit) }
+ modelBakingTask.thenComposeAsync {
+ allBlockStates
+ }.thenAcceptAsync {
+ replacements.modelBakingFuture.complete(Unit)
+ }
}, executor)
}
+
+ @JvmStatic
+ fun collectExtraBlockStateMaps(
+ extra: BakedReplacements,
+ original: Map<Identifier, List<Resource>>,
+ stateManagers: Function<Identifier, StateManager<Block, BlockState>?>
+ ) {
+ extra.collectAllReplacements().forEach {
+ val blockId = Registries.BLOCK.getKey(it.overridingBlock).getOrNull()?.value ?: return@forEach
+ val allModels = mutableListOf<BlockStatesLoader.LoadedBlockStateDefinition>()
+ val stateManager = stateManagers.apply(blockId) ?: return@forEach
+ for (resource in original[BlockStatesLoader.FINDER.toResourcePath(it.block)] ?: return@forEach) {
+ try {
+ resource.reader.use { reader ->
+ val jsonElement = JsonParser.parseReader(reader)
+ val blockModelDefinition =
+ BlockModelDefinition.CODEC.parse(JsonOps.INSTANCE, jsonElement)
+ .getOrThrow { msg: String? -> JsonParseException(msg) }
+ allModels.add(
+ BlockStatesLoader.LoadedBlockStateDefinition(
+ resource.getPackId(),
+ blockModelDefinition
+ )
+ )
+ }
+ } catch (exception: Exception) {
+ ErrorUtil.softError(
+ "Failed to load custom blockstate definition ${it.block} from pack ${resource.packId}",
+ exception
+ )
+ }
+ }
+
+ try {
+ it.unbakedBlockStateMap = BlockStatesLoader.combine(
+ blockId,
+ stateManager,
+ allModels
+ ).models
+ } catch (exception: Exception) {
+ ErrorUtil.softError("Failed to combine custom blockstate definitions for ${it.block}", exception)
+ }
+ }
+ }
}
diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/LoadExtraBlockStates.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/LoadExtraBlockStates.java
new file mode 100644
index 0000000..c33fd04
--- /dev/null
+++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/LoadExtraBlockStates.java
@@ -0,0 +1,34 @@
+package moe.nea.firmament.mixins.custommodels;
+
+import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
+import com.llamalad7.mixinextras.sugar.Local;
+import moe.nea.firmament.features.texturepack.CustomBlockTextures;
+import net.minecraft.block.Block;
+import net.minecraft.block.BlockState;
+import net.minecraft.client.render.model.BlockStatesLoader;
+import net.minecraft.resource.Resource;
+import net.minecraft.state.StateManager;
+import net.minecraft.util.Identifier;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.function.Function;
+
+@Mixin(BlockStatesLoader.class)
+public class LoadExtraBlockStates {
+ @ModifyExpressionValue(method = "load", at = @At(value = "INVOKE", target = "Ljava/util/concurrent/CompletableFuture;supplyAsync(Ljava/util/function/Supplier;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"))
+ private static CompletableFuture<Map<Identifier, List<Resource>>> loadExtraModels(
+ CompletableFuture<Map<Identifier, List<Resource>>> x,
+ @Local(argsOnly = true) Executor executor,
+ @Local Function<Identifier, StateManager<Block, BlockState>> stateManagers
+ ) {
+ return x.thenCombineAsync(CustomBlockTextures.getPreparationFuture(), (original, extra) -> {
+ CustomBlockTextures.collectExtraBlockStateMaps(extra, original, stateManagers);
+ return original;
+ }, executor);
+ }
+}
diff --git a/symbols/build.gradle.kts b/symbols/build.gradle.kts
index 2a7bcc8..2084af4 100644
--- a/symbols/build.gradle.kts
+++ b/symbols/build.gradle.kts
@@ -1,12 +1,9 @@
-
plugins {
kotlin("jvm")
id("com.google.devtools.ksp")
+ id("firmament.common")
}
-repositories {
- mavenCentral()
-}
dependencies {
ksp("dev.zacsweers.autoservice:auto-service-ksp:1.1.0")
implementation("com.google.auto.service:auto-service-annotations:1.1.1")
diff --git a/testagent/build.gradle.kts b/testagent/build.gradle.kts
index 73eb583..cf7c15b 100644
--- a/testagent/build.gradle.kts
+++ b/testagent/build.gradle.kts
@@ -1,5 +1,6 @@
plugins {
java
+ id("firmament.common")
id("com.gradleup.shadow")
}
dependencies {
diff --git a/translations/en_us.json b/translations/en_us.json
index 6299181..95b43f1 100644
--- a/translations/en_us.json
+++ b/translations/en_us.json
@@ -135,6 +135,8 @@
"firmament.config.etherwarp-overlay.cube.description": "Displays a full cube on the block",
"firmament.config.etherwarp-overlay.etherwarp-overlay": "Etherwarp Overlay",
"firmament.config.etherwarp-overlay.etherwarp-overlay.description": "Display an overlay that tells you what block you will warp to.",
+ "firmament.config.etherwarp-overlay.only-show-while-sneaking": "Only show while sneaking",
+ "firmament.config.etherwarp-overlay.only-show-while-sneaking.description": "Displays the Etherwarp overlay only while sneaking.",
"firmament.config.etherwarp-overlay.wireframe": "Outline",
"firmament.config.etherwarp-overlay.wireframe.description": "Displays a full outline on the block",
"firmament.config.fairy-souls": "Fairy Souls",
@@ -159,7 +161,7 @@
"firmament.config.fixes.hide-mob-effects": "Hide Potion Effects",
"firmament.config.fixes.hide-mob-effects.description": "Hide Potion effects on the right side of your player inventory.",
"firmament.config.fixes.hide-potion-effects-hud": "Hide Potion Effects HUD",
- "firmament.config.fixes.hide-potion-effects-hud.description": "Hides the potion effects HUd in the top right.",
+ "firmament.config.fixes.hide-potion-effects-hud.description": "Hides the potion effects HUD in the top right.",
"firmament.config.fixes.hide-recipe-book": "No Recipe Book",
"firmament.config.fixes.hide-recipe-book.description": "Remove the recipe book from your inventory",
"firmament.config.fixes.hide-slot-highlights": "Hide Slot Highlights",
@@ -168,19 +170,19 @@
"firmament.config.fixes.peek-chat.description": "Hold this keybinding to view the chat as if you have it opened, but while still being able to control your character.",
"firmament.config.fixes.player-skins": "Fix unsigned Player Skins",
"firmament.config.fixes.player-skins.description": "Mark all player skins as signed, preventing console spam, and some rendering issues.",
- "firmament.config.hud": "Hud",
+ "firmament.config.hud": "HUD",
"firmament.config.hud.day-count": "Day Count",
- "firmament.config.hud.day-count-hud": "Day Count Hud",
+ "firmament.config.hud.day-count-hud": "Day Count HUD",
"firmament.config.hud.day-count-hud.description": "Shows day.",
"firmament.config.hud.day-count-hud.display": "Day: %s",
"firmament.config.hud.day-count.description": "A HUD showing current day.",
"firmament.config.hud.fps-count": "FPS Count",
- "firmament.config.hud.fps-count-hud": "FPS Count Hud",
+ "firmament.config.hud.fps-count-hud": "FPS Count HUD",
"firmament.config.hud.fps-count-hud.description": "Shows FPS.",
"firmament.config.hud.fps-count-hud.display": "FPS: %s",
"firmament.config.hud.fps-count.description": "A HUD showing current FPS.",
"firmament.config.hud.ping-count": "Ping Count",
- "firmament.config.hud.ping-count-hud": "Ping Count Hud",
+ "firmament.config.hud.ping-count-hud": "Ping Count HUD",
"firmament.config.hud.ping-count-hud.description": "Shows Ping.",
"firmament.config.hud.ping-count-hud.display": "Ping %s",
"firmament.config.hud.ping-count.description": "A HUD showing current Ping.",
@@ -209,6 +211,7 @@
"firmament.config.lore-timers.format.choice.american": "§9Ame§cri§fcan",
"firmament.config.lore-timers.format.choice.local": "System Time Format",
"firmament.config.lore-timers.format.choice.rfc": "RFC",
+ "firmament.config.lore-timers.format.choice.rfcprecise": "RFC (Milliseconds)",
"firmament.config.lore-timers.format.choice.socialist": "European-ish",
"firmament.config.lore-timers.format.description": "Choose the time format in which resolved timers are displayed.",
"firmament.config.lore-timers.show": "Show Lore Timers",
@@ -258,6 +261,8 @@
"firmament.config.power-user.copy-texture-pack-id.description": "Copy the texture pack id that is used for the item stack under your cursor.",
"firmament.config.power-user.copy-title": "Copy Inventory Title",
"firmament.config.power-user.copy-title.description": "Copies Inventory and Screen Titles",
+ "firmament.config.power-user.dont-highlight-semicolon-items": "Remove Semicolon Highlight",
+ "firmament.config.power-user.dont-highlight-semicolon-items.description": "Removes the highlight from items that contain a semicolon e.g Pets or Enchanted Books.",
"firmament.config.power-user.entity-data": "Show Entity Data",
"firmament.config.power-user.entity-data.description": "Print out information about the entity under your cross-hair.",
"firmament.config.power-user.export-item-stack": "Export Item Stack",
@@ -266,6 +271,8 @@
"firmament.config.power-user.export-npc-location.description": "Export the NPC's location to the repo data",
"firmament.config.power-user.export-recipe": "Export Recipe Data",
"firmament.config.power-user.export-recipe.description": "Export Recipe Data to the repo data",
+ "firmament.config.power-user.highlight-non-overlay": "Highlight Missing Items",
+ "firmament.config.power-user.highlight-non-overlay.description": "Highlights items that don't exist in the repo.",
"firmament.config.power-user.show-item-id": "Show SkyBlock Ids",
"firmament.config.power-user.show-item-id.description": "Show the SkyBlock id of items underneath them.",
"firmament.config.price-data": "Price Data",
@@ -301,6 +308,8 @@
"firmament.config.repo.branch.hint": "dangerous",
"firmament.config.repo.disable-item-groups": "Disable Item Groups",
"firmament.config.repo.disable-item-groups.description": "Disabling item groups can increase performance, but will no longer collect similar items (like minions, enchantments) together.",
+ "firmament.config.repo.enable-rei": "Enable REI",
+ "firmament.config.repo.enable-rei.description": "REI is required for viewing Firmaments item list. If you want to use another item list provider like SkyBlockers, you can turn it off here. Without other mods this will make you revert back to the vanilla item list.",
"firmament.config.repo.enable-super-craft": "Always use Super Craft",
"firmament.config.repo.enable-super-craft.description": "Always use super craft when clicking the craft button in REI, instead of just when holding shift.",
"firmament.config.repo.perfect-renders": "Perfect Render",
@@ -337,6 +346,8 @@
"firmament.config.slot-locking.bind.description": "Bind a hotbar slot to another slot. This allows quick switching between the slots by shift clicking on either slot.",
"firmament.config.slot-locking.drop-in-dungeons": "Allow Dungeon Abilities",
"firmament.config.slot-locking.drop-in-dungeons.description": "Allow dropping items in dungeons, to use your dungeon ultimate abilities.",
+ "firmament.config.slot-locking.hunting-box": "Protect Hunting Box",
+ "firmament.config.slot-locking.hunting-box.description": "The Hunting Box frequently changes its UUID, and as such cannot be reliably protected using UUID locking. Instead this option can be used to block from dropping any Hunting Box.",
"firmament.config.slot-locking.lock": "Lock Slot",
"firmament.config.slot-locking.lock-uuid": "Lock UUID (Lock Item)",
"firmament.config.slot-locking.lock-uuid.description": "Lock a SkyBlock item by it's UUID. This blocks a specific item from being dropped/sold, but still allows moving it around.",
diff --git a/web/src/pages/docs/_texture-pack-format.md b/web/src/pages/docs/_texture-pack-format.md
index 2f84777..3575cfc 100644
--- a/web/src/pages/docs/_texture-pack-format.md
+++ b/web/src/pages/docs/_texture-pack-format.md
@@ -809,6 +809,11 @@ which block models are replaced under which conditions:
}
```
+The referenced `block` can either be a regular json block model (like the ones in `assets/minecraft/blocks/`), or it can
+reference a blockstates json like in `assets/<namespace>/blockstates/<path>.json`. The blockstates.json is prefered and
+needs to match the vanilla format, so it is best to copy over the vanilla blockstates.json for the block you are editing
+and replace all block model paths with your own custom block models.
+
| Field | Required | Description |
|-------------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `modes` | yes | A list of `/locraw` mode names. |