├── .directory ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug-report.md │ ├── crash-report.md │ └── feature-request.md └── workflows │ └── build.yml ├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src └── main ├── java └── zabi │ └── minecraft │ └── nbttooltip │ ├── NBTTooltip.java │ ├── config │ ├── ConfigInstance.java │ ├── ConfigScreenProvider.java │ ├── ModConfig.java │ └── TriggerType.java │ └── parse_engine │ ├── BWHumanReadableParser.java │ ├── ColoredHumanReadableParser.java │ ├── JsonParser.java │ ├── NativeParser.java │ └── NbtTagParser.java └── resources ├── assets └── nbttooltip │ ├── icon.png │ └── lang │ ├── en_us.json │ ├── it_it.json │ ├── ru_ru.json │ ├── zh_cn.json │ └── zh_tw.json └── fabric.mod.json /.directory: -------------------------------------------------------------------------------- 1 | [Dolphin] 2 | Timestamp=2022,4,30,15,6,34.74 3 | Version=4 4 | 5 | [Settings] 6 | HiddenFilesShown=true 7 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Report an abnormal behaviour that does **not** crash the game. 4 | title: '' 5 | labels: Fabric, bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See bug 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Pastebin links** 27 | Don't paste the whole lists here, use **pastebin** 28 | - latest.log: 29 | - Modpack link (preferred) or Mod List: 30 | - Custom changes to modpack (if using a modpack): 31 | - NBTTooltips Config: 32 | 33 | **Environment (please complete the following information):** 34 | - Mod Version: [e.g. 1.2.0] 35 | - MC Version: [e.g. 1.16.1] 36 | - Fabric Version: [e.g. 0.6.1.45] 37 | - Fabric API version: [e.g. Fabric API 0.16.2 build 385] 38 | - System: [e.g. Windows 10, Mac OS Big Sur, Manjaro Linux] 39 | - Installation type: [e.g. SinglePlayer, DedicatedServer, Lan] 40 | 41 | **Additional context** 42 | Add any other context about the problem here, like other mods that you think might be involved in the problem. 43 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/crash-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Crash report 3 | about: 'Report a crash in the game. ' 4 | title: '' 5 | labels: Fabric, Urgent 6 | assignees: '' 7 | 8 | --- 9 | 10 | #### Please install [Not Enough Crashes](https://www.curseforge.com/minecraft/mc-mods/not-enough-crashes) to allow me to read the stack trace 11 | 12 | **To Reproduce** 13 | Steps to reproduce the crash: 14 | 1. Go to '...' 15 | 2. Click on '....' 16 | 3. Crash 17 | 18 | **Pastebin links** 19 | Don't paste the whole lists here, use **pastebin** 20 | - Crash Log: 21 | - Modpack link (preferred) or Mod List: 22 | - Custom changes to modpack (if using a modpack): 23 | - NBTTooltip Config: 24 | 25 | **Environment (please complete the following information):** 26 | - Mod Version: [e.g. 1.2.0] 27 | - MC Version: [e.g. 1.16.1] 28 | - Fabric Version: [e.g. 0.6.1.45] 29 | - Fabric API version: [e.g. Fabric API 0.16.2 build 385] 30 | - System: [e.g. Windows 10, Mac OS Big Sur, Manjaro Linux] 31 | - Installation type: [e.g. SinglePlayer, DedicatedServer, Lan] 32 | 33 | **Additional context** 34 | Add any other context about the problem here, like other mods that you think might be involved in the problem. 35 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Suggest changes to the mod (latest version only). 4 | title: '' 5 | labels: Fabric, feature-request 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # Automatically build the project and run any configured tests for every push 2 | # and submitted pull request. This can help catch issues that only occur on 3 | # certain platforms or Java versions, and provides a first line of defence 4 | # against bad commits. 5 | 6 | name: build 7 | on: [pull_request, push] 8 | 9 | jobs: 10 | build: 11 | strategy: 12 | matrix: 13 | # Use these Java versions 14 | java: [ 15 | 21, # Current Java LTS & minimum supported by Minecraft 16 | ] 17 | # and run on Linux 18 | os: [ubuntu-20.04] 19 | runs-on: ${{ matrix.os }} 20 | steps: 21 | - name: checkout repository 22 | uses: actions/checkout@v2 23 | - name: validate gradle wrapper 24 | uses: gradle/wrapper-validation-action@v1 25 | - name: setup jdk ${{ matrix.java }} 26 | uses: actions/setup-java@v1 27 | with: 28 | java-version: ${{ matrix.java }} 29 | - name: make gradle wrapper executable 30 | if: ${{ runner.os != 'Windows' }} 31 | run: chmod +x ./gradlew 32 | - name: build 33 | run: ./gradlew build 34 | - name: capture build artifacts 35 | if: ${{ runner.os == 'Linux' && matrix.java == '21' }} # Only upload artifacts built from latest java on one OS 36 | uses: actions/upload-artifact@v4 37 | with: 38 | name: Artifacts 39 | path: build/libs/ 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #ant stuff 2 | /bin/ 3 | /download/ 4 | #Remove OS generated garbage 5 | */.DS_Store 6 | .DS_Store 7 | .DS_Store? 8 | .Spotlight-V100 9 | .Trashes 10 | Icon? 11 | ehthumbs.db 12 | Thumbs.db 13 | #gradle stuff 14 | /.gradle 15 | /build/ 16 | /run*/ 17 | /ui/ 18 | gradle-app.setting 19 | #IDEA files from Gradle 20 | .idea/ 21 | /*.iml 22 | /*.ipr 23 | /*.iws 24 | #Vim backups 25 | *~ 26 | #manual version override 27 | version.properties 28 | #eclipse stuffs 29 | /.classpath 30 | /.project 31 | /.settings/ 32 | /eclipse/ 33 | /minecraft/ 34 | /debug/ 35 | /.metadata/ 36 | /config/ 37 | /logs/ 38 | options.txt 39 | /saves/ 40 | /out 41 | /tmp 42 | .iws 43 | **/.idea/workspace.xml 44 | **/.idea/tasks.xml 45 | *.iml 46 | /classes/ 47 | .metadata 48 | *.rej 49 | bin/ 50 | tmp/ 51 | *.tmp 52 | *.bak 53 | *.swp 54 | *~.nib 55 | local.properties 56 | .settings/ 57 | .loadpath 58 | .recommenders 59 | 60 | # External tool builders 61 | .externalToolBuilders/ 62 | 63 | # Locally stored "Eclipse launch configurations" 64 | *.launch 65 | 66 | # PyDev specific (Python IDE for Eclipse) 67 | *.pydevproject 68 | 69 | # CDT-specific (C/C++ Development Tooling) 70 | .cproject 71 | 72 | # Java annotation processor (APT) 73 | .factorypath 74 | 75 | # PDT-specific (PHP Development Tools) 76 | .buildpath 77 | 78 | # sbteclipse plugin 79 | .target 80 | 81 | # Tern plugin 82 | .tern-project 83 | 84 | # TeXlipse plugin 85 | .texlipse 86 | 87 | # STS (Spring Tool Suite) 88 | .springBeans 89 | 90 | # Code Recommenders 91 | .recommenders/ 92 | 93 | # Scala IDE specific (Scala & Java development for Eclipse) 94 | .cache-main 95 | .scala_dependencies 96 | .worksheet 97 | nbproject/private/ 98 | build/ 99 | nbbuild/ 100 | dist/ 101 | nbdist/ 102 | nbactions.xml 103 | nb-configuration.xml 104 | - 105 | sources/Baubles-1.12-1.5.1-api.jar 106 | sources/Baubles-1.12-1.5.2-api.jar 107 | /sources/ 108 | /libs/ 109 | .vscode 110 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 zabi94 2 | 3 | All rights reserved. 4 | Distribution of the software in any form is only allowed with explicit, prior permission from the owner. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NBTTooltip 2 | 3 | A Minecraft mod to show the Item NBT tag on their tooltip. 4 | 5 | This code is **very** messy. Don't look into this while learning! I will refactor to something more decent when I get some time, promised. 6 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'fabric-loom' version '1.9-SNAPSHOT' 3 | id 'maven-publish' 4 | } 5 | 6 | version = project.mod_version 7 | group = project.maven_group 8 | 9 | base { 10 | archivesName = project.archives_base_name 11 | } 12 | 13 | repositories { 14 | mavenLocal() 15 | maven { 16 | name = "CurseForge" 17 | url = "https://minecraft.curseforge.com/api/maven/" 18 | } 19 | maven { 20 | name = "ModMenu" 21 | url = "https://maven.terraformersmc.com/releases/" 22 | } 23 | maven { 24 | name = "Cloth+REI" 25 | url = "https://maven.shedaniel.me/" 26 | } 27 | } 28 | 29 | dependencies { 30 | minecraft "com.mojang:minecraft:${project.minecraft_version}" 31 | mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" 32 | 33 | //Fabric 34 | modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" 35 | modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" 36 | 37 | 38 | // Deps 39 | modApi("com.terraformersmc:modmenu:${project.modmenu_version}") { 40 | exclude module: 'fabric-api' 41 | exclude module: 'config-2' 42 | exclude module: 'cloth-config-fabric' 43 | exclude module: 'roughlyenoughitems-api' 44 | } 45 | 46 | modApi("me.shedaniel.cloth:cloth-config-fabric:${project.clothconfig_version}") { 47 | exclude module: 'fabric-api' 48 | exclude module: 'config-2' 49 | exclude module: 'cloth-config-fabric' 50 | exclude module: 'roughlyenoughitems-api' 51 | } 52 | 53 | // //Bundling 54 | include "me.shedaniel.cloth:cloth-config-fabric:${project.clothconfig_version}" 55 | } 56 | 57 | processResources { 58 | inputs.property "version", project.version 59 | 60 | filesMatching("fabric.mod.json") { 61 | expand "version": project.version 62 | } 63 | } 64 | 65 | tasks.withType(JavaCompile).configureEach { 66 | it.options.release = 21 67 | } 68 | 69 | 70 | java { 71 | withSourcesJar() 72 | 73 | sourceCompatibility = JavaVersion.VERSION_21 74 | targetCompatibility = JavaVersion.VERSION_21 75 | } 76 | 77 | jar { 78 | from("LICENSE") { 79 | rename { "${it}_${project.archivesBaseName}"} 80 | } 81 | } 82 | 83 | publishing { 84 | publications { 85 | mavenJava(MavenPublication) { 86 | artifact(remapJar) { 87 | builtBy remapJar 88 | } 89 | artifact(sourcesJar) { 90 | builtBy remapSourcesJar 91 | } 92 | } 93 | } 94 | 95 | repositories { 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1G 2 | 3 | minecraft_version=1.21.2 4 | yarn_mappings=1.21.2+build.1 5 | loader_version=0.16.9 6 | 7 | # Fabric API 8 | fabric_version=0.106.1+1.21.2 9 | 10 | modmenu_version=12.0.0 11 | clothconfig_version=16.0.141 12 | rei_version=17.0.790 13 | 14 | mod_version = 1.2.1 15 | maven_group = zabi.minecraft.nbttooltip 16 | archives_base_name = nbttooltip -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zabi94/NBTTooltip/76922cae323df6174f22cdeca52facfae699f6ff/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 165 | if [[ "$(uname)" == "Darwin" ]] && [[ "$HOME" == "$PWD" ]]; then 166 | cd "$(dirname "$0")" 167 | fi 168 | 169 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 170 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | maven { 4 | name = 'Fabric' 5 | url = 'https://maven.fabricmc.net/' 6 | } 7 | mavenCentral() 8 | gradlePluginPortal() 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/zabi/minecraft/nbttooltip/NBTTooltip.java: -------------------------------------------------------------------------------- 1 | package zabi.minecraft.nbttooltip; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.lwjgl.glfw.GLFW; 7 | 8 | import com.mojang.serialization.DataResult; 9 | import com.mojang.serialization.DynamicOps; 10 | 11 | import net.fabricmc.api.ClientModInitializer; 12 | import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; 13 | import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback; 14 | import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; 15 | import net.minecraft.client.MinecraftClient; 16 | import net.minecraft.client.gui.screen.Screen; 17 | import net.minecraft.client.option.KeyBinding; 18 | import net.minecraft.client.resource.language.I18n; 19 | import net.minecraft.client.toast.SystemToast; 20 | import net.minecraft.client.toast.SystemToast.Type; 21 | import net.minecraft.client.util.InputUtil; 22 | import net.minecraft.component.ComponentChanges; 23 | import net.minecraft.item.Item; 24 | import net.minecraft.item.ItemStack; 25 | import net.minecraft.item.tooltip.TooltipType; 26 | import net.minecraft.nbt.NbtCompound; 27 | import net.minecraft.nbt.NbtElement; 28 | import net.minecraft.nbt.NbtOps; 29 | import net.minecraft.text.Text; 30 | import net.minecraft.util.Formatting; 31 | import zabi.minecraft.nbttooltip.config.ModConfig; 32 | import zabi.minecraft.nbttooltip.parse_engine.NbtTagParser; 33 | 34 | public class NBTTooltip implements ClientModInitializer { 35 | 36 | public static int ticks = 0; 37 | public static int line_scrolled = 0; 38 | 39 | public static final String FORMAT = Formatting.ITALIC.toString() + Formatting.DARK_GRAY; 40 | 41 | public static final int WAITTIME_BEFORE_FAST_SCROLL = 10; 42 | 43 | public static KeyBinding COPY_TO_CLIPBOARD = new KeyBinding("key.nbttooltip.copy", InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_RIGHT, "key.category.nbttooltip"); 44 | public static KeyBinding TOGGLE_NBT = new KeyBinding("key.nbttooltip.toggle", InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_LEFT, "key.category.nbttooltip"); 45 | public static KeyBinding SCROLL_UP = new KeyBinding("key.nbttooltip.scroll_up", InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_UP, "key.category.nbttooltip"); 46 | public static KeyBinding SCROLL_DOWN = new KeyBinding("key.nbttooltip.scroll_down", InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_DOWN, "key.category.nbttooltip"); 47 | 48 | public static boolean flipflop_key_copy = false; 49 | public static boolean flipflop_key_toggle = false; 50 | 51 | public static boolean nbtKeyToggled = false; 52 | public static boolean nbtKeyPressed = false; 53 | 54 | public static int fast_scroll_warmup = 0; 55 | public static int autoscroll_locks = 0; 56 | 57 | @Override 58 | public void onInitializeClient() { 59 | ModConfig.init(); 60 | ClientTickEvents.END_CLIENT_TICK.register(NBTTooltip::clientTick); 61 | ItemTooltipCallback.EVENT.register(NBTTooltip::onInjectTooltip); 62 | KeyBindingHelper.registerKeyBinding(COPY_TO_CLIPBOARD); 63 | KeyBindingHelper.registerKeyBinding(TOGGLE_NBT); 64 | KeyBindingHelper.registerKeyBinding(SCROLL_DOWN); 65 | KeyBindingHelper.registerKeyBinding(SCROLL_UP); 66 | } 67 | 68 | public static void clientTick(MinecraftClient mc) { 69 | 70 | if (mc.world == null) return; 71 | 72 | if (autoscroll_locks > 0) autoscroll_locks--; 73 | 74 | if (!Screen.hasShiftDown() && !isPressed(mc, SCROLL_DOWN) && !isPressed(mc, SCROLL_UP) && autoscroll_locks == 0) { 75 | NBTTooltip.ticks++; 76 | int factor = 1; 77 | if (Screen.hasAltDown()) { 78 | factor = 4; 79 | } 80 | if (NBTTooltip.ticks >= ModConfig.INSTANCE.ticksBeforeScroll / factor) { 81 | NBTTooltip.ticks = 0; 82 | if (ModConfig.INSTANCE.ticksBeforeScroll > 0) { 83 | NBTTooltip.line_scrolled++; 84 | } 85 | } 86 | } 87 | 88 | if (isPressed(mc, TOGGLE_NBT)) { 89 | if (!flipflop_key_toggle) { 90 | nbtKeyToggled = !nbtKeyToggled; 91 | } 92 | flipflop_key_toggle = true; 93 | nbtKeyPressed = true; 94 | } else { 95 | flipflop_key_toggle = false; 96 | nbtKeyPressed = false; 97 | } 98 | 99 | 100 | if (!isPressed(mc, SCROLL_DOWN) && isPressed(mc, SCROLL_UP) && line_scrolled > 0 && cooldownTimeAcceptable()) { 101 | line_scrolled--; 102 | } 103 | 104 | if (isPressed(mc, SCROLL_DOWN) && !isPressed(mc, SCROLL_UP) && cooldownTimeAcceptable()) { 105 | line_scrolled++; 106 | } 107 | 108 | if (isPressed(mc, SCROLL_DOWN) || isPressed(mc, SCROLL_UP)) { 109 | if (fast_scroll_warmup < WAITTIME_BEFORE_FAST_SCROLL) fast_scroll_warmup++; 110 | autoscroll_locks = 2; 111 | } else { 112 | fast_scroll_warmup = 0; 113 | } 114 | } 115 | 116 | private static boolean cooldownTimeAcceptable() { 117 | return fast_scroll_warmup == 0 || fast_scroll_warmup >= WAITTIME_BEFORE_FAST_SCROLL; 118 | } 119 | 120 | private static boolean isPressed(MinecraftClient mc, KeyBinding key) { 121 | return !key.isUnbound() && InputUtil.isKeyPressed(mc.getWindow().getHandle(), InputUtil.fromTranslationKey(key.getBoundKeyTranslationKey()).getCode()); 122 | } 123 | 124 | public static ArrayList transformTtip(ArrayList ttip, int lines) { 125 | ArrayList newttip = new ArrayList<>(lines); 126 | if (ModConfig.INSTANCE.showSeparator) { 127 | newttip.add(Text.literal("- NBTTooltip -")); 128 | } 129 | if (ttip.size() > lines) { 130 | if (lines + line_scrolled > ttip.size()) { 131 | if (isPressed(MinecraftClient.getInstance(), SCROLL_DOWN)) { 132 | line_scrolled = ttip.size() - lines; 133 | } else { 134 | line_scrolled = 0; 135 | } 136 | } 137 | for (int i = 0; i < lines; i++) { 138 | newttip.add(ttip.get(i + line_scrolled)); 139 | } 140 | } else { 141 | line_scrolled = 0; 142 | newttip.addAll(ttip); 143 | } 144 | return newttip; 145 | } 146 | 147 | public static void onInjectTooltip(ItemStack stack, Item.TooltipContext context, TooltipType type, List list) { 148 | handleClipboardCopy(stack); 149 | if (ModConfig.INSTANCE.triggerType.shouldShowTooltip(context, type)) { 150 | if (autoscroll_locks > 0) autoscroll_locks = 2; 151 | int lines = ModConfig.INSTANCE.maxLinesShown; 152 | if (ModConfig.INSTANCE.ctrlSuppressesRest && Screen.hasControlDown()) { 153 | lines += list.size(); 154 | list.clear(); 155 | } else { 156 | list.add(Text.literal("")); 157 | } 158 | 159 | ArrayList ttip = new ArrayList<>(lines); 160 | NbtCompound tag = encodeStack(stack, context.getRegistryLookup().getOps(NbtOps.INSTANCE)); 161 | if (!tag.isEmpty()) { 162 | if (ModConfig.INSTANCE.showDelimiters) { 163 | ttip.add(Text.literal(Formatting.DARK_PURPLE + " - nbt start -")); 164 | } 165 | if (ModConfig.INSTANCE.compress) { 166 | ttip.add(Text.literal(FORMAT + tag)); 167 | } else { 168 | getRenderingEngine().parseTagToList(ttip, tag, ModConfig.INSTANCE.splitLongLines); 169 | } 170 | if (ModConfig.INSTANCE.showDelimiters) { 171 | ttip.add(Text.literal(Formatting.DARK_PURPLE + " - nbt end -")); 172 | } 173 | ttip = NBTTooltip.transformTtip(ttip, lines); 174 | list.addAll(ttip); 175 | } else { 176 | list.add(Text.literal(FORMAT + "No NBT data")); 177 | } 178 | } 179 | } 180 | 181 | private static NbtCompound encodeStack(ItemStack stack, DynamicOps ops) { 182 | DataResult result = ComponentChanges.CODEC.encodeStart(ops, stack.getComponentChanges()); 183 | result.ifError(e->{ 184 | 185 | }); 186 | NbtElement nbtElement = result.getOrThrow(); 187 | // cast here, as soon as this breaks, the mod will need to update anyway 188 | return (NbtCompound) nbtElement; 189 | } 190 | 191 | private static void handleClipboardCopy(ItemStack stack) { 192 | MinecraftClient mc = MinecraftClient.getInstance(); 193 | if (mc.currentScreen != null) { 194 | if (isPressed(mc, COPY_TO_CLIPBOARD)) { 195 | if (!flipflop_key_copy) { 196 | flipflop_key_copy = true; 197 | copyToClipboard(stack, mc); 198 | } 199 | } else { 200 | flipflop_key_copy = false; 201 | } 202 | } 203 | } 204 | 205 | private static void copyToClipboard(ItemStack stack, MinecraftClient mc) { 206 | StringBuilder sb = new StringBuilder(); 207 | String name = I18n.translate(stack.getItem().getTranslationKey()); 208 | ArrayList nbtData = new ArrayList<>(); 209 | getCopyingEngine().parseTagToList(nbtData, encodeStack(stack, mc.player.getRegistryManager().getOps(NbtOps.INSTANCE)), false); 210 | nbtData.forEach(t -> { 211 | sb.append(t.getString().replaceAll("§[0-9a-gk-or]", "")); 212 | sb.append("\n"); 213 | }); 214 | try { 215 | mc.keyboard.setClipboard(sb.toString()); 216 | mc.getToastManager().add(new SystemToast(Type.PERIODIC_NOTIFICATION, Text.translatable("nbttooltip.copied_to_clipboard"), Text.translatable("nbttooltip.object_details", name))); 217 | } catch (Exception e) { 218 | mc.getToastManager().add(new SystemToast(Type.PERIODIC_NOTIFICATION, Text.translatable("nbttooltip.copy_failed"), Text.literal(e.getMessage()))); 219 | e.printStackTrace(); 220 | } 221 | } 222 | 223 | private static NbtTagParser getRenderingEngine() { 224 | return ModConfig.INSTANCE.tooltipEngine.getEngine(); 225 | } 226 | 227 | private static NbtTagParser getCopyingEngine() { 228 | return ModConfig.INSTANCE.copyingEngine.getEngine(); 229 | } 230 | 231 | } 232 | -------------------------------------------------------------------------------- /src/main/java/zabi/minecraft/nbttooltip/config/ConfigInstance.java: -------------------------------------------------------------------------------- 1 | package zabi.minecraft.nbttooltip.config; 2 | 3 | import zabi.minecraft.nbttooltip.parse_engine.BWHumanReadableParser; 4 | import zabi.minecraft.nbttooltip.parse_engine.ColoredHumanReadableParser; 5 | import zabi.minecraft.nbttooltip.parse_engine.JsonParser; 6 | import zabi.minecraft.nbttooltip.parse_engine.NativeParser; 7 | import zabi.minecraft.nbttooltip.parse_engine.NbtTagParser; 8 | 9 | public class ConfigInstance { 10 | 11 | public TriggerType triggerType; 12 | public boolean showSeparator; 13 | public int maxLinesShown; 14 | public boolean showDelimiters; 15 | public boolean compress; 16 | public int ticksBeforeScroll; 17 | public boolean ctrlSuppressesRest; 18 | public boolean splitLongLines; 19 | 20 | public TooltipEngine tooltipEngine; 21 | public CopyingEngine copyingEngine; 22 | 23 | public ConfigInstance() { 24 | maxLinesShown = 10; 25 | compress = false; 26 | triggerType = TriggerType.F3H; 27 | showDelimiters = true; 28 | showSeparator = true; 29 | ticksBeforeScroll = 20; 30 | ctrlSuppressesRest = true; 31 | splitLongLines = true; 32 | tooltipEngine = TooltipEngine.FRIENDLY; 33 | copyingEngine = CopyingEngine.JSON; 34 | } 35 | 36 | public static enum TooltipEngine { 37 | 38 | FRIENDLY(new ColoredHumanReadableParser()), 39 | FRIENDLY_NO_COLOR(new BWHumanReadableParser()), 40 | JSON(new JsonParser()); 41 | 42 | private NbtTagParser parser; 43 | 44 | TooltipEngine(NbtTagParser parser) { 45 | this.parser = parser; 46 | } 47 | 48 | public NbtTagParser getEngine() { 49 | return parser; 50 | } 51 | } 52 | 53 | public static enum CopyingEngine { 54 | 55 | FRIENDLY(new BWHumanReadableParser()), 56 | MC_GIVE_CMD(new NativeParser()), 57 | JSON(new JsonParser()); 58 | 59 | private NbtTagParser parser; 60 | 61 | CopyingEngine(NbtTagParser parser) { 62 | this.parser = parser; 63 | } 64 | 65 | public NbtTagParser getEngine() { 66 | return parser; 67 | } 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/zabi/minecraft/nbttooltip/config/ConfigScreenProvider.java: -------------------------------------------------------------------------------- 1 | package zabi.minecraft.nbttooltip.config; 2 | 3 | import com.terraformersmc.modmenu.api.ConfigScreenFactory; 4 | import com.terraformersmc.modmenu.api.ModMenuApi; 5 | 6 | import me.shedaniel.clothconfig2.api.ConfigBuilder; 7 | import me.shedaniel.clothconfig2.api.ConfigCategory; 8 | import net.minecraft.text.Text; 9 | import zabi.minecraft.nbttooltip.config.ConfigInstance.CopyingEngine; 10 | import zabi.minecraft.nbttooltip.config.ConfigInstance.TooltipEngine; 11 | 12 | public class ConfigScreenProvider implements ModMenuApi { 13 | 14 | 15 | public static ConfigBuilder builder() { 16 | 17 | ConfigBuilder configBuilder = ConfigBuilder.create() 18 | .setTitle(Text.translatable("key.category.nbttooltip")) 19 | .setEditable(true) 20 | .setSavingRunnable(ModConfig::writeJson); 21 | 22 | ConfigCategory general = configBuilder.getOrCreateCategory(Text.translatable("nbttooltip.config.general")); 23 | 24 | general.addEntry(configBuilder.entryBuilder() 25 | .startBooleanToggle(Text.translatable("nbttooltip.config.showseparator") , ModConfig.INSTANCE.showSeparator) 26 | .setDefaultValue(true) 27 | .setTooltip( 28 | Text.translatable("nbttooltip.config.showseparator.line1"), 29 | Text.translatable("nbttooltip.config.showseparator.line2") 30 | ) 31 | .setSaveConsumer(val -> ModConfig.INSTANCE.showSeparator = val) 32 | .build() 33 | ); 34 | 35 | general.addEntry(configBuilder.entryBuilder() 36 | .startBooleanToggle(Text.translatable("nbttooltip.config.compress") , ModConfig.INSTANCE.compress) 37 | .setDefaultValue(false) 38 | .setTooltip( 39 | Text.translatable("nbttooltip.config.compress.line1"), 40 | Text.translatable("nbttooltip.config.compress.line2") 41 | ) 42 | .setSaveConsumer(val -> ModConfig.INSTANCE.compress = val) 43 | .build() 44 | ); 45 | 46 | general.addEntry(configBuilder.entryBuilder() 47 | .startEnumSelector(Text.translatable("nbttooltip.config.triggerType"), TriggerType.class, ModConfig.INSTANCE.triggerType) 48 | .setDefaultValue(TriggerType.F3H) 49 | .setTooltip( 50 | Text.translatable("nbttooltip.config.triggerType.line1"), 51 | Text.translatable("nbttooltip.config.triggerType.line2") 52 | ) 53 | .setSaveConsumer(val -> ModConfig.INSTANCE.triggerType = val) 54 | .build() 55 | ); 56 | 57 | general.addEntry(configBuilder.entryBuilder() 58 | .startBooleanToggle(Text.translatable("nbttooltip.config.showDelimiters") , ModConfig.INSTANCE.showDelimiters) 59 | .setDefaultValue(true) 60 | .setTooltip( 61 | Text.translatable("nbttooltip.config.showDelimiters.line1"), 62 | Text.translatable("nbttooltip.config.showDelimiters.line2") 63 | ) 64 | .setSaveConsumer(val -> ModConfig.INSTANCE.showDelimiters = val) 65 | .build() 66 | ); 67 | 68 | general.addEntry(configBuilder.entryBuilder() 69 | .startBooleanToggle(Text.translatable("nbttooltip.config.ctrlSuppressesRest") , ModConfig.INSTANCE.ctrlSuppressesRest) 70 | .setDefaultValue(true) 71 | .setTooltip( 72 | Text.translatable("nbttooltip.config.ctrlSuppressesRest.line1"), 73 | Text.translatable("nbttooltip.config.ctrlSuppressesRest.line2") 74 | ) 75 | .setSaveConsumer(val -> ModConfig.INSTANCE.ctrlSuppressesRest = val) 76 | .build() 77 | ); 78 | 79 | general.addEntry(configBuilder.entryBuilder() 80 | .startBooleanToggle(Text.translatable("nbttooltip.config.splitLongLines") , ModConfig.INSTANCE.splitLongLines) 81 | .setDefaultValue(true) 82 | .setTooltip( 83 | Text.translatable("nbttooltip.config.splitLongLines.line1"), 84 | Text.translatable("nbttooltip.config.splitLongLines.line2") 85 | ) 86 | .setSaveConsumer(val -> ModConfig.INSTANCE.splitLongLines = val) 87 | .build() 88 | ); 89 | 90 | general.addEntry(configBuilder.entryBuilder() 91 | .startIntField(Text.translatable("nbttooltip.config.maxLinesShown"), ModConfig.INSTANCE.maxLinesShown) 92 | .setDefaultValue(10) 93 | .setTooltip( 94 | Text.translatable("nbttooltip.config.maxLinesShown.line1"), 95 | Text.translatable("nbttooltip.config.maxLinesShown.line2") 96 | ) 97 | .setSaveConsumer(val -> ModConfig.INSTANCE.maxLinesShown = val) 98 | .build() 99 | ); 100 | 101 | 102 | 103 | general.addEntry(configBuilder.entryBuilder() 104 | .startIntField(Text.translatable("nbttooltip.config.ticksBeforeScroll"), ModConfig.INSTANCE.ticksBeforeScroll) 105 | .setDefaultValue(20) 106 | .setTooltip( 107 | Text.translatable("nbttooltip.config.ticksBeforeScroll.line1"), 108 | Text.translatable("nbttooltip.config.ticksBeforeScroll.line2") 109 | ) 110 | .setSaveConsumer(val -> ModConfig.INSTANCE.ticksBeforeScroll = val) 111 | .build() 112 | ); 113 | 114 | general.addEntry(configBuilder.entryBuilder() 115 | .startEnumSelector(Text.translatable("nbttooltip.config.tooltipEngine"), TooltipEngine.class, ModConfig.INSTANCE.tooltipEngine) 116 | .setDefaultValue(TooltipEngine.FRIENDLY) 117 | .setTooltip( 118 | Text.translatable("nbttooltip.config.tooltipEngine.line1"), 119 | Text.translatable("nbttooltip.config.tooltipEngine.line2") 120 | ) 121 | .setSaveConsumer(val -> ModConfig.INSTANCE.tooltipEngine = val) 122 | .build() 123 | ); 124 | 125 | general.addEntry(configBuilder.entryBuilder() 126 | .startEnumSelector(Text.translatable("nbttooltip.config.copyingEngine"), CopyingEngine.class, ModConfig.INSTANCE.copyingEngine) 127 | .setDefaultValue(CopyingEngine.JSON) 128 | .setTooltip( 129 | Text.translatable("nbttooltip.config.copyingEngine.line1"), 130 | Text.translatable("nbttooltip.config.copyingEngine.line2") 131 | ) 132 | .setSaveConsumer(val -> ModConfig.INSTANCE.copyingEngine = val) 133 | .build() 134 | ); 135 | 136 | return configBuilder; 137 | } 138 | 139 | @Override 140 | public ConfigScreenFactory getModConfigScreenFactory() { 141 | return parent -> builder().setParentScreen(parent).build(); 142 | } 143 | 144 | } 145 | -------------------------------------------------------------------------------- /src/main/java/zabi/minecraft/nbttooltip/config/ModConfig.java: -------------------------------------------------------------------------------- 1 | package zabi.minecraft.nbttooltip.config; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.io.FileReader; 6 | import java.io.FileWriter; 7 | import java.io.IOException; 8 | 9 | import com.google.gson.Gson; 10 | import com.google.gson.GsonBuilder; 11 | import com.google.gson.JsonIOException; 12 | import com.google.gson.JsonSyntaxException; 13 | 14 | import zabi.minecraft.nbttooltip.config.ConfigInstance.CopyingEngine; 15 | import zabi.minecraft.nbttooltip.config.ConfigInstance.TooltipEngine; 16 | 17 | 18 | public class ModConfig { 19 | 20 | private static final File folder = new File("config"); 21 | private static File configFile; 22 | private static final Gson config = new GsonBuilder().setPrettyPrinting().create(); 23 | public static ConfigInstance INSTANCE; 24 | 25 | public static void init() { 26 | loadDefaults(); 27 | generateFoldersAndFiles(); 28 | readJson(); 29 | if (INSTANCE.triggerType == null) { 30 | INSTANCE.triggerType = TriggerType.F3H; 31 | } 32 | if (INSTANCE.tooltipEngine == null) { 33 | INSTANCE.tooltipEngine = TooltipEngine.FRIENDLY; 34 | } 35 | if (INSTANCE.copyingEngine == null) { 36 | INSTANCE.copyingEngine = CopyingEngine.FRIENDLY; 37 | } 38 | writeJson(); //Write to file new config options 39 | } 40 | 41 | public static void loadDefaults() { 42 | INSTANCE = new ConfigInstance(); 43 | } 44 | 45 | private static void generateFoldersAndFiles() { 46 | if (!folder.exists()) { 47 | folder.mkdir(); 48 | } 49 | if (folder.isDirectory()) { 50 | configFile = new File(folder, "nbttooltip.json"); 51 | 52 | File legacyConfigFile = new File(folder, "nbttooltip.config"); 53 | if (legacyConfigFile.exists() && legacyConfigFile.isFile() && ! configFile.exists()) { 54 | if (!legacyConfigFile.renameTo(configFile)) { 55 | System.err.format("Could not rename legacy config file %s to %s\n", legacyConfigFile.getAbsolutePath(), configFile.getAbsolutePath()); 56 | } else { 57 | System.out.println("Successfully converted legacy config file"); 58 | } 59 | } 60 | 61 | 62 | if (!configFile.exists()) { 63 | System.out.println("Creating new config file"); 64 | try { 65 | configFile.createNewFile(); 66 | loadDefaults(); 67 | String json = config.toJson(INSTANCE); 68 | FileWriter writer = new FileWriter(configFile); 69 | writer.write(json); 70 | writer.close(); 71 | } catch (IOException e) { 72 | throw new IllegalStateException("Can't create config file", e); 73 | } 74 | } else if (configFile.isDirectory()) { 75 | throw new IllegalStateException("'nbttooltip.json' must be a file!"); 76 | } 77 | } else { 78 | throw new IllegalStateException("'config' must be a folder!"); 79 | } 80 | } 81 | 82 | public static void readJson() { 83 | try { 84 | INSTANCE = config.fromJson(new FileReader(configFile), ConfigInstance.class); 85 | if (INSTANCE == null) { 86 | throw new IllegalStateException("Null configuration"); 87 | } 88 | } catch (JsonSyntaxException e) { 89 | System.err.println("Invalid configuration!"); 90 | e.printStackTrace(); 91 | } catch (JsonIOException e) { 92 | e.printStackTrace(); 93 | } catch (FileNotFoundException e) { 94 | // No op 95 | } 96 | } 97 | 98 | public static void writeJson() { 99 | try { 100 | String json = config.toJson(INSTANCE); 101 | FileWriter writer = new FileWriter(configFile, false); 102 | writer.write(json); 103 | writer.close(); 104 | } catch (IOException e) { 105 | throw new IllegalStateException("Can't update config file", e); 106 | } 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/zabi/minecraft/nbttooltip/config/TriggerType.java: -------------------------------------------------------------------------------- 1 | package zabi.minecraft.nbttooltip.config; 2 | 3 | import java.util.function.BiFunction; 4 | 5 | import net.minecraft.item.Item; 6 | import net.minecraft.item.tooltip.TooltipType; 7 | import zabi.minecraft.nbttooltip.NBTTooltip; 8 | 9 | public enum TriggerType { 10 | 11 | F3H((ctx, type) -> type.isAdvanced()), 12 | ALWAYS_ON((ctx, type) -> true), 13 | TOGGLE_ON_KEY((ctx, type) -> NBTTooltip.nbtKeyToggled), 14 | SHOW_ON_KEY((ctx, type) -> NBTTooltip.nbtKeyPressed); 15 | 16 | private BiFunction test; 17 | 18 | TriggerType(BiFunction check) { 19 | this.test = check; 20 | } 21 | 22 | public boolean shouldShowTooltip(Item.TooltipContext context, TooltipType type) { 23 | return this.test.apply(context, type); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/zabi/minecraft/nbttooltip/parse_engine/BWHumanReadableParser.java: -------------------------------------------------------------------------------- 1 | package zabi.minecraft.nbttooltip.parse_engine; 2 | 3 | import java.util.List; 4 | 5 | import org.jetbrains.annotations.Nullable; 6 | 7 | import net.minecraft.nbt.AbstractNbtList; 8 | import net.minecraft.nbt.NbtCompound; 9 | import net.minecraft.nbt.NbtElement; 10 | import net.minecraft.text.Text; 11 | import net.minecraft.util.Formatting; 12 | import zabi.minecraft.nbttooltip.NBTTooltip; 13 | import zabi.minecraft.nbttooltip.config.ModConfig; 14 | 15 | public class BWHumanReadableParser implements NbtTagParser { 16 | 17 | private static final int line_split_threshold = 30; 18 | 19 | @Override 20 | public void parseTagToList(List list, @Nullable NbtElement tag, boolean split) { 21 | if (tag == null) { 22 | list.add(Text.literal("No NBT tag")); 23 | } else { 24 | unwrapTag(list, tag, NBTTooltip.FORMAT, "", ModConfig.INSTANCE.compress?"":" ", split); 25 | } 26 | } 27 | 28 | private void unwrapTag(List tooltip, NbtElement base, String pad, String tagName, String padIncrement, boolean splitLongStrings) { 29 | if (base instanceof NbtCompound) { 30 | addCompoundToTooltip(tooltip, base, pad, padIncrement, splitLongStrings); 31 | } else if (base instanceof AbstractNbtList) { 32 | addListToTooltip(tooltip, base, pad, padIncrement, splitLongStrings); 33 | } else { 34 | addValueToTooltip(tooltip, base, tagName, pad, splitLongStrings); 35 | } 36 | } 37 | 38 | private void addCompoundToTooltip(List tooltip, NbtElement base, String pad, String padIncrement, boolean splitLongStrings) { 39 | NbtCompound tag = (NbtCompound) base; 40 | tag.getKeys().forEach(s -> { 41 | boolean nested = (tag.get(s) instanceof AbstractNbtList) || (tag.get(s) instanceof NbtCompound); 42 | if (nested) { 43 | tooltip.add(Text.literal(pad+s+": {")); 44 | unwrapTag(tooltip, tag.get(s), pad+padIncrement, s, padIncrement, splitLongStrings); 45 | tooltip.add(Text.literal(pad+"}")); 46 | } else { 47 | addValueToTooltip(tooltip, tag.get(s), s, pad, splitLongStrings); 48 | } 49 | }); 50 | } 51 | 52 | private void addListToTooltip(List tooltip, NbtElement base, String pad, String padIncrement, boolean splitLongStrings) { 53 | AbstractNbtList tag = (AbstractNbtList) base; 54 | int index = 0; 55 | for (NbtElement nbtnext : tag) { 56 | if (nbtnext instanceof AbstractNbtList || nbtnext instanceof NbtCompound) { 57 | tooltip.add(Text.literal(pad + "[" + index + "]: {")); 58 | unwrapTag(tooltip, nbtnext, pad + padIncrement, "", padIncrement, splitLongStrings); 59 | tooltip.add(Text.literal(pad + "}")); 60 | } else { 61 | addValueToTooltip(tooltip, nbtnext, "[" + index + "]", pad, splitLongStrings); 62 | } 63 | index++; 64 | } 65 | } 66 | 67 | private static void addValueToTooltip(List tooltip, NbtElement nbt, String name, String pad, boolean splitLongStrings) { 68 | String toBeAdded = nbt.toString(); 69 | if (!splitLongStrings || toBeAdded.length() < line_split_threshold) { 70 | tooltip.add(Text.literal(pad+name+": "+ nbt)); 71 | } else { 72 | int added = 0; 73 | tooltip.add(Text.literal(pad+name+":")); 74 | while (added < toBeAdded.length()) { 75 | int nextChunk = Math.min(line_split_threshold, toBeAdded.length() - added); 76 | String sb = new StringBuilder() 77 | .append(Formatting.AQUA).append("|") 78 | .append(Formatting.RESET).append(pad) 79 | .append(" ") 80 | .append(toBeAdded, added, added + nextChunk).toString(); 81 | tooltip.add(Text.literal(sb)); 82 | added += nextChunk; 83 | } 84 | } 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/zabi/minecraft/nbttooltip/parse_engine/ColoredHumanReadableParser.java: -------------------------------------------------------------------------------- 1 | package zabi.minecraft.nbttooltip.parse_engine; 2 | 3 | import java.util.List; 4 | 5 | import org.jetbrains.annotations.Nullable; 6 | 7 | import net.minecraft.nbt.AbstractNbtList; 8 | import net.minecraft.nbt.NbtCompound; 9 | import net.minecraft.nbt.NbtElement; 10 | import net.minecraft.text.Text; 11 | import net.minecraft.util.Formatting; 12 | import zabi.minecraft.nbttooltip.config.ModConfig; 13 | 14 | public class ColoredHumanReadableParser implements NbtTagParser { 15 | 16 | private static final int line_split_threshold = 30; 17 | 18 | private static final Formatting LISTINDEX = Formatting.GREEN; 19 | private static final Formatting STRING = Formatting.LIGHT_PURPLE; 20 | private static final Formatting STRUCTURE = Formatting.GRAY; 21 | private static final Formatting TAGNAME = Formatting.GOLD; 22 | 23 | @Override 24 | public void parseTagToList(List list, @Nullable NbtElement tag, boolean split) { 25 | if (tag == null) { 26 | list.add(Text.literal("No NBT tag").formatted(Formatting.DARK_GRAY)); 27 | } else { 28 | unwrapTag(list, tag, "", "", ModConfig.INSTANCE.compress?"":" ", split); 29 | } 30 | } 31 | 32 | private void unwrapTag(List tooltip, NbtElement base, String pad, String tagName, String padIncrement, boolean splitLongStrings) { 33 | if (base instanceof NbtCompound) { 34 | addCompoundToTooltip(tooltip, base, pad, padIncrement, splitLongStrings); 35 | } else if (base instanceof AbstractNbtList) { 36 | addListToTooltip(tooltip, base, pad, padIncrement, splitLongStrings); 37 | } else { 38 | addValueToTooltip(tooltip, base, Text.literal(tagName).formatted(TAGNAME), pad, splitLongStrings); 39 | } 40 | } 41 | 42 | private void addCompoundToTooltip(List tooltip, NbtElement base, String pad, String padIncrement, boolean splitLongStrings) { 43 | NbtCompound tag = (NbtCompound) base; 44 | tag.getKeys().forEach(s -> { 45 | boolean nested = (tag.get(s) instanceof AbstractNbtList) || (tag.get(s) instanceof NbtCompound); 46 | if (nested) { 47 | Text subtreeName = Text.literal(s).formatted(TAGNAME); 48 | Text intro = Text.translatable("%s%s%s", pad, subtreeName, Text.literal(": {").formatted(STRUCTURE)); 49 | tooltip.add(intro); 50 | unwrapTag(tooltip, tag.get(s), pad+padIncrement, s, padIncrement, splitLongStrings); 51 | tooltip.add(Text.literal(pad+"}").formatted(STRUCTURE)); 52 | } else { 53 | addValueToTooltip(tooltip, tag.get(s), Text.literal(s).formatted(TAGNAME), pad, splitLongStrings); 54 | } 55 | }); 56 | } 57 | 58 | private void addListToTooltip(List tooltip, NbtElement base, String pad, String padIncrement, boolean splitLongStrings) { 59 | AbstractNbtList tag = (AbstractNbtList) base; 60 | int index = 0; 61 | for (NbtElement nbtnext : tag) { 62 | if (nbtnext instanceof AbstractNbtList || nbtnext instanceof NbtCompound) { 63 | tooltip.add(Text.translatable("%s [%s]: {", pad, Text.literal("" + index).formatted(LISTINDEX)).formatted(STRUCTURE)); 64 | unwrapTag(tooltip, nbtnext, pad + padIncrement, "", padIncrement, splitLongStrings); 65 | tooltip.add(Text.literal(pad + "}").formatted(STRUCTURE)); 66 | } else { 67 | addValueToTooltip(tooltip, nbtnext, Text.translatable("[%s]", Text.literal("" + index).formatted(LISTINDEX)) 68 | .formatted(STRUCTURE), pad, splitLongStrings); 69 | } 70 | index++; 71 | } 72 | } 73 | 74 | private static void addValueToTooltip(List tooltip, NbtElement nbt, Text name, String pad, boolean splitLongStrings) { 75 | String toBeAdded = nbt.toString(); 76 | if (!splitLongStrings || toBeAdded.length() < line_split_threshold) { 77 | tooltip.add(Text.translatable(pad+"%s: %s", name, Text.literal(nbt.toString()).formatted(STRING))); 78 | } else { 79 | Text separator = Text.literal("|").formatted(Formatting.AQUA); 80 | int added = 0; 81 | tooltip.add(Text.translatable(pad+"%s:", name)); 82 | while (added < toBeAdded.length()) { 83 | int nextChunk = Math.min(line_split_threshold, toBeAdded.length() - added); 84 | Text chunk = Text.literal(toBeAdded.substring(added, added+nextChunk)).formatted(STRING); 85 | tooltip.add(Text.translatable("%s"+pad+" %s", separator, chunk)); 86 | added += nextChunk; 87 | } 88 | } 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/zabi/minecraft/nbttooltip/parse_engine/JsonParser.java: -------------------------------------------------------------------------------- 1 | package zabi.minecraft.nbttooltip.parse_engine; 2 | 3 | import java.util.Iterator; 4 | import java.util.List; 5 | 6 | import org.jetbrains.annotations.Nullable; 7 | 8 | import net.minecraft.nbt.AbstractNbtList; 9 | import net.minecraft.nbt.NbtCompound; 10 | import net.minecraft.nbt.NbtElement; 11 | import net.minecraft.nbt.NbtString; 12 | import net.minecraft.text.Text; 13 | import zabi.minecraft.nbttooltip.config.ModConfig; 14 | 15 | public class JsonParser implements NbtTagParser { 16 | 17 | @Override 18 | public void parseTagToList(List list, @Nullable NbtElement tag, boolean split) { 19 | if (tag == null) { 20 | list.add(Text.literal("{}")); 21 | } else { 22 | list.add(Text.literal("{")); 23 | unwrapTag(list, tag, ModConfig.INSTANCE.compress?"":" ", "", ModConfig.INSTANCE.compress?"":" "); 24 | list.add(Text.literal("}")); 25 | } 26 | } 27 | 28 | private void unwrapTag(List tooltip, NbtElement base, String pad, String tagName, String padIncrement) { 29 | if (base instanceof NbtCompound) { 30 | addCompoundToTooltip(tooltip, base, pad, padIncrement); 31 | } else if (base instanceof AbstractNbtList) { 32 | addListToTooltip(tooltip, base, pad, padIncrement); 33 | } else { 34 | addValueToTooltip(tooltip, base, tagName, pad, false); 35 | } 36 | } 37 | 38 | private void addCompoundToTooltip(List tooltip, NbtElement base, String pad, String padIncrement) { 39 | NbtCompound tag = (NbtCompound) base; 40 | Iterator iter = tag.getKeys().iterator(); 41 | while (iter.hasNext()) { 42 | String s = iter.next(); 43 | if (tag.get(s) instanceof NbtCompound) { 44 | tooltip.add(Text.literal(pad+'"'+s+"\": {")); 45 | unwrapTag(tooltip, tag.get(s), pad+padIncrement, s, padIncrement); 46 | tooltip.add(Text.literal(pad+"}"+(iter.hasNext()?",":""))); 47 | } else if (tag.get(s) instanceof AbstractNbtList) { 48 | tooltip.add(Text.literal(pad+'"'+s+"\": [")); 49 | unwrapTag(tooltip, tag.get(s), pad+padIncrement, s, padIncrement); 50 | tooltip.add(Text.literal(pad+"]"+(iter.hasNext()?",":""))); 51 | } else { 52 | addNamedValueToTooltip(tooltip, tag.get(s), s, pad, iter.hasNext()); 53 | } 54 | } 55 | } 56 | 57 | private void addListToTooltip(List tooltip, NbtElement base, String pad, String padIncrement) { 58 | AbstractNbtList tag = (AbstractNbtList) base; 59 | Iterator iter = tag.iterator(); 60 | while (iter.hasNext()) { 61 | NbtElement nbtnext = iter.next(); 62 | if (nbtnext instanceof NbtCompound) { 63 | tooltip.add(Text.literal(pad + "{")); 64 | unwrapTag(tooltip, nbtnext, pad+padIncrement, "", padIncrement); 65 | tooltip.add(Text.literal(pad+"}"+(iter.hasNext()?",":""))); 66 | } else if (nbtnext instanceof AbstractNbtList) { 67 | tooltip.add(Text.literal(pad + "[")); 68 | unwrapTag(tooltip, nbtnext, pad+padIncrement, "", padIncrement); 69 | tooltip.add(Text.literal(pad+"]"+(iter.hasNext()?",":""))); 70 | } else { 71 | addValueToTooltip(tooltip, nbtnext, "", pad, iter.hasNext()); 72 | } 73 | } 74 | } 75 | 76 | private static void addNamedValueToTooltip(List tooltip, NbtElement nbt, String name, String pad, boolean addComma) { 77 | String cleanString = nbt instanceof NbtString ? escapeChars(nbt.toString()) : stripTypeIdentifiers(nbt.toString()); 78 | tooltip.add(Text.literal(pad+'"'+name+"\": "+cleanString+(addComma ? "," : ""))); 79 | } 80 | 81 | private static void addValueToTooltip(List tooltip, NbtElement nbt, String name, String pad, boolean addComma) { 82 | String cleanString = nbt instanceof NbtString ? escapeChars(nbt.toString()) : stripTypeIdentifiers(nbt.toString()); 83 | tooltip.add(Text.literal(pad+cleanString+(addComma ? "," : ""))); 84 | } 85 | 86 | private static String stripTypeIdentifiers(String string) { 87 | char last = string.charAt(string.length() - 1); 88 | if (last >= '0' && last <= '9') return string; 89 | return string.substring(0, string.length() - 1); 90 | } 91 | 92 | private static String escapeChars(String in) { 93 | if ((in.charAt(0) == '"' && in.charAt(in.length()-1) == '"') || (in.charAt(0) == '\'' && in.charAt(in.length()-1) == '\'')) { 94 | in = in.substring(1, in.length() - 1); 95 | } 96 | StringBuilder sb = new StringBuilder(); 97 | sb.append('"'); 98 | for (int i = 0; i < in.length(); i++) { 99 | char c = in.charAt(i); 100 | if (c == '"') { 101 | sb.append('\\'); 102 | sb.append('"'); 103 | } else { 104 | sb.append(c); 105 | } 106 | } 107 | sb.append('"'); 108 | return sb.toString(); 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/zabi/minecraft/nbttooltip/parse_engine/NativeParser.java: -------------------------------------------------------------------------------- 1 | package zabi.minecraft.nbttooltip.parse_engine; 2 | 3 | import java.util.List; 4 | 5 | import org.jetbrains.annotations.Nullable; 6 | 7 | import net.minecraft.nbt.AbstractNbtList; 8 | import net.minecraft.nbt.AbstractNbtNumber; 9 | import net.minecraft.nbt.NbtByteArray; 10 | import net.minecraft.nbt.NbtCompound; 11 | import net.minecraft.nbt.NbtElement; 12 | import net.minecraft.nbt.NbtIntArray; 13 | import net.minecraft.nbt.NbtLongArray; 14 | import net.minecraft.nbt.NbtString; 15 | import net.minecraft.text.Text; 16 | 17 | public class NativeParser implements NbtTagParser { 18 | 19 | @Override 20 | public void parseTagToList(List list, @Nullable NbtElement tag, boolean split) { 21 | if (tag == null) { 22 | list.add(Text.literal("{}")); 23 | } else { 24 | list.add(Text.literal(unwrap(tag))); 25 | } 26 | } 27 | 28 | public String unwrap(NbtElement tag) { 29 | if (tag instanceof AbstractNbtNumber) { 30 | return stripTypeIdentifier(tag.toString()); 31 | } else if (tag instanceof NbtString) { 32 | return tag.toString(); 33 | } else if (tag instanceof AbstractNbtList) { 34 | return String.format("[%s%s]", listIdentifier((AbstractNbtList) tag), unwrapList((AbstractNbtList) tag)); 35 | } else if (tag instanceof NbtCompound) { 36 | return String.format("{%s}", unwrapCompound((NbtCompound) tag)); 37 | } 38 | return ""; 39 | } 40 | 41 | private String unwrapCompound(NbtCompound tag) { 42 | if (tag.getKeys().size() == 0) { 43 | return ""; 44 | } 45 | StringBuilder sb = new StringBuilder(); 46 | for (String s:tag.getKeys()) { 47 | sb.append(s); 48 | sb.append(":"); 49 | sb.append(unwrap(tag.get(s))); 50 | sb.append(","); 51 | } 52 | return sb.substring(0, sb.toString().length() - 1); //Remove last comma 53 | } 54 | 55 | private String unwrapList(AbstractNbtList tag) { 56 | if (tag.size() == 0) { 57 | return ""; 58 | } 59 | StringBuilder sb = new StringBuilder(); 60 | for (int i = 0; i < tag.size() - 1; i++) { 61 | sb.append(unwrap(tag.get(i))); 62 | sb.append(','); 63 | } 64 | sb.append(unwrap(tag.get(tag.size() - 1))); 65 | return sb.toString(); 66 | } 67 | 68 | private String listIdentifier(AbstractNbtList tag) { 69 | if (tag instanceof NbtByteArray) { 70 | return "B;"; 71 | } else if (tag instanceof NbtIntArray) { 72 | return "I;"; 73 | } else if (tag instanceof NbtLongArray) { 74 | return "L;"; 75 | } else return ""; 76 | } 77 | 78 | private String stripTypeIdentifier(String string) { 79 | char last = string.charAt(string.length() - 1); 80 | if (last >= '0' && last <= '9') return string; 81 | return string.substring(0, string.length() - 1); 82 | } 83 | 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/zabi/minecraft/nbttooltip/parse_engine/NbtTagParser.java: -------------------------------------------------------------------------------- 1 | package zabi.minecraft.nbttooltip.parse_engine; 2 | 3 | import net.minecraft.nbt.NbtElement; 4 | import net.minecraft.text.Text; 5 | import org.jetbrains.annotations.Nullable; 6 | 7 | import java.util.List; 8 | 9 | public interface NbtTagParser { 10 | 11 | void parseTagToList(List list, @Nullable NbtElement tag, boolean splitlines); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/resources/assets/nbttooltip/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zabi94/NBTTooltip/76922cae323df6174f22cdeca52facfae699f6ff/src/main/resources/assets/nbttooltip/icon.png -------------------------------------------------------------------------------- /src/main/resources/assets/nbttooltip/lang/en_us.json: -------------------------------------------------------------------------------- 1 | { 2 | "nbttooltip.copied_to_clipboard": "Data copied to clipboard", 3 | "nbttooltip.object_details": "Item: %s", 4 | "nbttooltip.copy_failed": "Copy failed", 5 | "key.nbttooltip.copy": "Copy NBT", 6 | "key.nbttooltip.toggle": "Toggle NBT", 7 | "key.category.nbttooltip": "NBT Tooltip", 8 | "key.nbttooltip.scroll_down": "Scroll NBT down", 9 | "key.nbttooltip.scroll_up": "Scroll NBT up", 10 | 11 | "nbttooltip.config.showseparator": "Show separator", 12 | "nbttooltip.config.showseparator.line1": "Prints '- NBTTooltip -' before the NBT tag.", 13 | "nbttooltip.config.showseparator.line2": "This tag doesn't scroll with the text.", 14 | 15 | "nbttooltip.config.compress": "Compress text horizontally", 16 | "nbttooltip.config.compress.line1": "The text won't have indentation and will", 17 | "nbttooltip.config.compress.line2": "all align to the left margin.", 18 | 19 | "nbttooltip.config.triggerType": "Trigger Type", 20 | "nbttooltip.config.triggerType.line1": "Determines when the tooltip should be shown. The key used for", 21 | "nbttooltip.config.triggerType.line2": "key-based triggers is configurable through the controls menu.", 22 | 23 | "nbttooltip.config.showDelimiters": "Show delimiters", 24 | "nbttooltip.config.showDelimiters.line1": "Prints '- NBT start -' and '- NBT end -'.", 25 | "nbttooltip.config.showDelimiters.line2": "inside the tag, scrolling with the rest.", 26 | 27 | "nbttooltip.config.ctrlSuppressesRest": "Just NBT with CTRL", 28 | "nbttooltip.config.ctrlSuppressesRest.line1": "Allows to show just the NBT part of a tooltip", 29 | "nbttooltip.config.ctrlSuppressesRest.line2": "when holding CTRL down, hiding the rest.", 30 | 31 | "nbttooltip.config.splitLongLines": "Split long lines", 32 | "nbttooltip.config.splitLongLines.line1": "Divides long lines into multiple ones and", 33 | "nbttooltip.config.splitLongLines.line2": "places a sign at the beginning of each part.", 34 | 35 | "nbttooltip.config.maxLinesShown": "Maximum NBT lines", 36 | "nbttooltip.config.maxLinesShown.line1": "The maximum amount of lines shown in a", 37 | "nbttooltip.config.maxLinesShown.line2": "tooltip before it starts scrolling.", 38 | 39 | "nbttooltip.config.ticksBeforeScroll": "Scroll delay", 40 | "nbttooltip.config.ticksBeforeScroll.line1": "The amount of ticks after which a new line", 41 | "nbttooltip.config.ticksBeforeScroll.line2": "is shown when the tooltip is too long.", 42 | 43 | "nbttooltip.config.tooltipEngine": "Tooltip presentation", 44 | "nbttooltip.config.tooltipEngine.line1": "FRIENDLY uses a human-readable format for tooltips.", 45 | "nbttooltip.config.tooltipEngine.line2": "JSON uses the standard JSON format for files.", 46 | 47 | "nbttooltip.config.copyingEngine": "Copy format", 48 | "nbttooltip.config.copyingEngine.line1": "FRIENDLY uses a human-readable format to copy nbt.", 49 | "nbttooltip.config.copyingEngine.line2": "JSON uses the standard JSON format for files." 50 | 51 | } -------------------------------------------------------------------------------- /src/main/resources/assets/nbttooltip/lang/it_it.json: -------------------------------------------------------------------------------- 1 | { 2 | "nbttooltip.copied_to_clipboard": "Dati copiati", 3 | "nbttooltip.object_details": "Oggetto: %s", 4 | "nbttooltip.copy_failed": "Copia fallita", 5 | "key.nbttooltip.copy": "Copia NBT", 6 | "key.nbttooltip.toggle": "(Dis)Attiva NBT", 7 | "key.category.nbttooltip": "NBT Tooltip", 8 | "key.nbttooltip.scroll_down": "Scorri giù NBT", 9 | "key.nbttooltip.scroll_up": "Scorri su NBT", 10 | 11 | "nbttooltip.config.showseparator": "Mostra separatore", 12 | "nbttooltip.config.showseparator.line1": "Stampa '- NBTTooltip -' prima del tag NBT.", 13 | "nbttooltip.config.showseparator.line2": "Questa linea non scorre con il resto del testo.", 14 | 15 | "nbttooltip.config.compress": "Comprimi testo orizzontalmente", 16 | "nbttooltip.config.compress.line1": "Il testo non sarà indentato e verrà", 17 | "nbttooltip.config.compress.line2": "allineato invece al margine sinistro.", 18 | 19 | "nbttooltip.config.triggerType": "Attivazione", 20 | "nbttooltip.config.triggerType.line1": "Determina quando il tooltip deve essere mostrato. Il tasto da usare", 21 | "nbttooltip.config.triggerType.line2": "per le attivazioni è configurabile nel menu di associazione tasti.", 22 | 23 | "nbttooltip.config.showDelimiters": "Mostra delimitatori", 24 | "nbttooltip.config.showDelimiters.line1": "Stampa '- NBT start -' e '- NBT end -'.", 25 | "nbttooltip.config.showDelimiters.line2": "dentro il tag, che scorrono con il testo.", 26 | 27 | "nbttooltip.config.ctrlSuppressesRest": "Isola NBT con CTRL", 28 | "nbttooltip.config.ctrlSuppressesRest.line1": "Ti permette di nascondere il resto del tooltip", 29 | "nbttooltip.config.ctrlSuppressesRest.line2": "quando si tiene premuto il tasto CTRL.", 30 | 31 | "nbttooltip.config.splitLongLines": "Dividi linee lunghe", 32 | "nbttooltip.config.splitLongLines.line1": "Divide le linee di testo troppo lunghe in linee", 33 | "nbttooltip.config.splitLongLines.line2": "multiple e piazza un segno per riconoscerle.", 34 | 35 | "nbttooltip.config.maxLinesShown": "Numero righe massimo", 36 | "nbttooltip.config.maxLinesShown.line1": "Il numero massimo di righe da stampare in un tooltip", 37 | "nbttooltip.config.maxLinesShown.line2": "prima che il testo cominci a scorrere.", 38 | 39 | "nbttooltip.config.ticksBeforeScroll": "Lentezza scorrimento", 40 | "nbttooltip.config.ticksBeforeScroll.line1": "Il numero di tick del gioco dopo i quali il tooltip", 41 | "nbttooltip.config.ticksBeforeScroll.line2": "scorre di una riga quando non rientra nei limiti.", 42 | 43 | "nbttooltip.config.tooltipEngine": "Formato per presentazione", 44 | "nbttooltip.config.tooltipEngine.line1": "FRIENDLY mostra i tooltip in un formato comprensibile da umani.", 45 | "nbttooltip.config.tooltipEngine.line2": "JSON usa il formato standard JSON per file.", 46 | 47 | "nbttooltip.config.copyingEngine": "Formato per copia", 48 | "nbttooltip.config.copyingEngine.line1": "FRIENDLY copia i tooltip in un formato comprensibile da umani.", 49 | "nbttooltip.config.copyingEngine.line2": "JSON usa il formato standard JSON per file." 50 | 51 | } -------------------------------------------------------------------------------- /src/main/resources/assets/nbttooltip/lang/ru_ru.json: -------------------------------------------------------------------------------- 1 | { 2 | "nbttooltip.copied_to_clipboard": "Данные скопированы", 3 | "nbttooltip.object_details": "Предмет: %s", 4 | "nbttooltip.copy_failed": "Ошибка копирования", 5 | "key.nbttooltip.copy": "Копировать nbt", 6 | "key.nbttooltip.toggle": "Переключить nbt", 7 | "key.category.nbttooltip": "NBT Tooltip", 8 | "key.nbttooltip.scroll_down": "Прокрутить nbt вниз", 9 | "key.nbttooltip.scroll_up": "Прокрутить nbt вверх", 10 | 11 | "nbttooltip.config.showseparator": "Отображать разделитель", 12 | "nbttooltip.config.showseparator.line1": "Выводит '- NBTTooltip -' перед nbt-тегами.", 13 | "nbttooltip.config.showseparator.line2": "Эта надпись не прокручивается вместе с nbt.", 14 | 15 | "nbttooltip.config.compress": "Отображать данные горизонтально", 16 | "nbttooltip.config.compress.line1": "Данные не будут иметь отступов", 17 | "nbttooltip.config.compress.line2": "и будут выравнены по левому краю.", 18 | 19 | "nbttooltip.config.triggerType": "Тип переключения", 20 | "nbttooltip.config.triggerType.line1": "Определяет, когда должна отображаться всплывающая подсказка.", 21 | "nbttooltip.config.triggerType.line2": "Кнопка для отображения по нажатию настраивается в меню управления.", 22 | 23 | "nbttooltip.config.showDelimiters": "Отображать ограничители", 24 | "nbttooltip.config.showDelimiters.line1": "Выводит '- NBT start -' и '- NBT end -' на границах тегов.", 25 | "nbttooltip.config.showDelimiters.line2": "Надписи прокручиваются вместе с основными данными.", 26 | 27 | "nbttooltip.config.ctrlSuppressesRest": "Только nbt по Ctrl", 28 | "nbttooltip.config.ctrlSuppressesRest.line1": "Позволяет отображать только nbt при нажатой Ctrl,", 29 | "nbttooltip.config.ctrlSuppressesRest.line2": "скрывая остальные данные из подсказки.", 30 | 31 | "nbttooltip.config.splitLongLines": "Разделение длинных строк", 32 | "nbttooltip.config.splitLongLines.line1": "Разделяет длинные строки на несколько,", 33 | "nbttooltip.config.splitLongLines.line2": "размещая пометку перед началом каждой.", 34 | 35 | "nbttooltip.config.maxLinesShown": "Максимум строк nbt", 36 | "nbttooltip.config.maxLinesShown.line1": "Предельное число строк, отображаемых в подсказке,", 37 | "nbttooltip.config.maxLinesShown.line2": "при которых данные не прокручиваются.", 38 | 39 | "nbttooltip.config.ticksBeforeScroll": "Задержка прокрутки", 40 | "nbttooltip.config.ticksBeforeScroll.line1": "Интервал времени (в тиках), после которого активируется", 41 | "nbttooltip.config.ticksBeforeScroll.line2": "прокрутка, если всплывающая подсказка слишком длинная. ", 42 | 43 | "nbttooltip.config.tooltipEngine": "Представление данных", 44 | "nbttooltip.config.tooltipEngine.line1": "FRIENDLY использует удобочитаемый формат подсказок.", 45 | "nbttooltip.config.tooltipEngine.line2": "JSON использует обычный формат JSON для файлов.", 46 | 47 | "nbttooltip.config.copyingEngine": "Формат копирования", 48 | "nbttooltip.config.copyingEngine.line1": "FRIENDLY копирует удобочитаемый формат nbt.", 49 | "nbttooltip.config.copyingEngine.line2": "JSON копирует обычный формат JSON для файлов." 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/resources/assets/nbttooltip/lang/zh_cn.json: -------------------------------------------------------------------------------- 1 | { 2 | "nbttooltip.copied_to_clipboard": "复制数据到剪切板", 3 | "nbttooltip.object_details": "物品: %s", 4 | "nbttooltip.copy_failed": "复制失败", 5 | "key.nbttooltip.copy": "复制 NBT", 6 | "key.nbttooltip.toggle": "切换 NBT", 7 | "key.category.nbttooltip": "NBT 工具提示(NBT Tooltip)", 8 | "key.nbttooltip.scroll_down": "向下滚动 NBT", 9 | "key.nbttooltip.scroll_up": "向上滚动 NBT", 10 | 11 | "nbttooltip.config.showseparator": "显示分隔符", 12 | "nbttooltip.config.showseparator.line1": "在NBT标签前显示 '-NBTTooltip -'.", 13 | "nbttooltip.config.showseparator.line2": "此标签不随文本滚动.", 14 | 15 | "nbttooltip.config.compress": "水平压缩文本", 16 | "nbttooltip.config.compress.line1": "该文本不会有缩进.", 17 | "nbttooltip.config.compress.line2": "并且将全部向左对齐.", 18 | 19 | "nbttooltip.config.triggerType": "触发器类型", 20 | "nbttooltip.config.triggerType.line1": "决定何时显示工具提示.", 21 | "nbttooltip.config.triggerType.line2": "用于基于键的触发器,键可通过控制菜单进行配置.", 22 | 23 | "nbttooltip.config.showDelimiters": "显示分隔线", 24 | "nbttooltip.config.showDelimiters.line1": "显示 '- NBT start -' 和 '- NBT end -'.", 25 | "nbttooltip.config.showDelimiters.line2": "标签内,与其他部分一起滚动.", 26 | 27 | "nbttooltip.config.ctrlSuppressesRest": "按住CTRL时只显示NBT", 28 | "nbttooltip.config.ctrlSuppressesRest.line1": "允许只显示工具提示的NBT部分", 29 | "nbttooltip.config.ctrlSuppressesRest.line2": "当按住CTRL时,隐藏其他的内容.", 30 | 31 | "nbttooltip.config.splitLongLines": "分割长行", 32 | "nbttooltip.config.splitLongLines.line1": "将长行分成多行", 33 | "nbttooltip.config.splitLongLines.line2": "并在每一部分的开头显示一个小竖线.", 34 | 35 | "nbttooltip.config.maxLinesShown": "最多NBT行", 36 | "nbttooltip.config.maxLinesShown.line1": "在开始滚动之前,", 37 | "nbttooltip.config.maxLinesShown.line2": "工具提示中最多显示的行数.", 38 | 39 | "nbttooltip.config.ticksBeforeScroll": "滚动延迟", 40 | "nbttooltip.config.ticksBeforeScroll.line1": "当工具提示过长时,", 41 | "nbttooltip.config.ticksBeforeScroll.line2": "显示新行的延迟.", 42 | 43 | "nbttooltip.config.tooltipEngine": "工具提示呈现方式", 44 | "nbttooltip.config.tooltipEngine.line1": "FRIENDLY 使用人类可读的工具提示格式", 45 | "nbttooltip.config.tooltipEngine.line2": "JSON 使用标准的JSON文件格式.", 46 | 47 | "nbttooltip.config.copyingEngine": "复制格式", 48 | "nbttooltip.config.copyingEngine.line1": "FRIENDLY 使用人类可读的格式来复制 NBT", 49 | "nbttooltip.config.copyingEngine.line2": "JSON 使用标准的JSON文件格式." 50 | 51 | } -------------------------------------------------------------------------------- /src/main/resources/assets/nbttooltip/lang/zh_tw.json: -------------------------------------------------------------------------------- 1 | { 2 | "nbttooltip.copied_to_clipboard": "資料已複製到剪貼簿", 3 | "nbttooltip.object_details": "物品: %s", 4 | "nbttooltip.copy_failed": "複製失敗", 5 | "key.nbttooltip.copy": "複製 NBT", 6 | "key.nbttooltip.toggle": "切換 NBT", 7 | "key.category.nbttooltip": "NBT 工具提示", 8 | "key.nbttooltip.scroll_down": "向下捲動 NBT", 9 | "key.nbttooltip.scroll_up": "向上捲動 NBT", 10 | 11 | "nbttooltip.config.showseparator": "顯示分隔線", 12 | "nbttooltip.config.showseparator.line1": "在 NBT 標籤前列印「- NBTTooltip -」。", 13 | "nbttooltip.config.showseparator.line2": "此標籤不會隨文字捲動。", 14 | 15 | "nbttooltip.config.compress": "水平壓縮文字", 16 | "nbttooltip.config.compress.line1": "文字將沒有縮排,並且", 17 | "nbttooltip.config.compress.line2": "全部對齊到左邊界。", 18 | 19 | "nbttooltip.config.triggerType": "觸發類型", 20 | "nbttooltip.config.triggerType.line1": "決定何時顯示工具提示。用於", 21 | "nbttooltip.config.triggerType.line2": "基於按鍵的觸發器的按鍵可透過控制選單設定。", 22 | 23 | "nbttooltip.config.showDelimiters": "顯示分隔符", 24 | "nbttooltip.config.showDelimiters.line1": "列印「- NBT start -」和「- NBT end -」。", 25 | "nbttooltip.config.showDelimiters.line2": "在標籤內,隨其他部分一起捲動。", 26 | 27 | "nbttooltip.config.ctrlSuppressesRest": "按住 CTRL 僅顯示 NBT", 28 | "nbttooltip.config.ctrlSuppressesRest.line1": "允許僅在", 29 | "nbttooltip.config.ctrlSuppressesRest.line2": "按住 CTRL 時顯示工具提示的 NBT 部分,隱藏其餘部分。", 30 | 31 | "nbttooltip.config.splitLongLines": "分割長行", 32 | "nbttooltip.config.splitLongLines.line1": "將長行分成多行,並", 33 | "nbttooltip.config.splitLongLines.line2": "在每個部分的開頭放置一個標誌。", 34 | 35 | "nbttooltip.config.maxLinesShown": "最大 NBT 行數", 36 | "nbttooltip.config.maxLinesShown.line1": "工具提示中顯示的最大行數,超過此行數後", 37 | "nbttooltip.config.maxLinesShown.line2": "將開始捲動。", 38 | 39 | "nbttooltip.config.ticksBeforeScroll": "捲動延遲", 40 | "nbttooltip.config.ticksBeforeScroll.line1": "顯示新行之前的刻數,當工具提示", 41 | "nbttooltip.config.ticksBeforeScroll.line2": "過長時。", 42 | 43 | "nbttooltip.config.tooltipEngine": "工具提示呈現方式", 44 | "nbttooltip.config.tooltipEngine.line1": "FRIENDLY 對工具提示使用人類可讀的格式。", 45 | "nbttooltip.config.tooltipEngine.line2": "JSON 對檔案使用標準的 JSON 格式。", 46 | 47 | "nbttooltip.config.copyingEngine": "複製格式", 48 | "nbttooltip.config.copyingEngine.line1": "FRIENDLY 使用人類可讀的格式來複製 nbt。", 49 | "nbttooltip.config.copyingEngine.line2": "JSON 對檔案使用標準的 JSON 格式。" 50 | 51 | } -------------------------------------------------------------------------------- /src/main/resources/fabric.mod.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemaVersion": 1, 3 | "id": "nbttooltip", 4 | "version": "${version}", 5 | "name": "NBT Tooltip", 6 | "description": "Add a handy tooltip to items, showing NBT data", 7 | "authors": [ 8 | "Zabi94" 9 | ], 10 | "contact": { 11 | }, 12 | "license": "MIT", 13 | "icon": "assets/nbttooltip/icon.png", 14 | "environment": "client", 15 | "entrypoints": { 16 | "client": [ 17 | "zabi.minecraft.nbttooltip.NBTTooltip" 18 | ], 19 | "modmenu": [ 20 | "zabi.minecraft.nbttooltip.config.ConfigScreenProvider" 21 | ] 22 | }, 23 | "depends": { 24 | "fabricloader": "*", 25 | "fabric": "*", 26 | "minecraft": ">=1.21.2", 27 | "java": ">=21" 28 | } 29 | } 30 | --------------------------------------------------------------------------------