diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..b175ed5 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +max_line_length = 120 +tab_width = 4 diff --git a/.gitignore b/.gitignore index 87a217a..0180d34 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,10 @@ -## IDEA ## -.idea/ -out/ -*.iml -*.ipr -*.iws -*.ids +# Java +/hs_err_pid* -## GRADLE ## -.gradle/ +# Gradle +/.gradle/ build/ -publish.gradle + +# IDEA +/.idea/ +/*.iml diff --git a/README.MD b/README.MD index d904346..049eeb8 100644 --- a/README.MD +++ b/README.MD @@ -1,97 +1,42 @@ # NBT Lib -![version: v1.1-RC](https://img.shields.io/badge/version-v1.1--RC-a0a.svg?style=flat) -![coverage: 93%](https://img.shields.io/badge/coverage-93%25-darkgreen.svg?style=flat) +![version: 2.0-SNAPSHOT](https://img.shields.io/badge/version-2.0--SNAPSHOT-a0a.svg?style=flat) Библиотека для работы с NBT (Named Binary Tag). -Начиная с версии `1.1-RC` разделена на две составляющие: теги и кодеки. Последние занимаются (де)сериализацией тегов. - -## Примеры работы с NBT +## Примеры работы **Создание тега типа String:** ```java -TagString tagString = new TagString(); -tagString.setValue("hello!"); +StringTag tag = new StringTag("Hello World!"); ``` -или в одну строчку +**Создание тега типа Compound:** ```java -TagString tagString = new TagString("hello!"); +CompoundTag tag = new CompoundTag() + .append("Seed", new LongTag(1234567890)); ``` -**Создание тега типа Compound:** - -```java -TagCompound tagCompound = new TagCompound(); -tagCompound.getValue().add(new TagLong("Seed", 1234567890)); -``` - -## Сериализация NBT - -Сериализация в бинарный формат Minecraft Vanilla выполняется библиотекой `nbt-vanilla-codec`. +## Сериализация Пример сериализации тега типа String в файл ```java -NbtOutputStream nbtOutputStream = new NbtOutputStream(new FileOutputStream("somefile.bin")); -nbtOutputStream.writeTag(new TagString("hello!")); -nbtOutputStream.close(); +try (NbtOutputStream nbtOutputStream = new NbtOutputStream(new FileOutputStream("somefile.bin"))) { + nbtOutputStream.writeTag(new StringTag("hello!")); +} ``` По такому же принципу происходит и десериализация ```java -NbtInputStream nbtInputStream = new NbtInputStream(new FileInputStream("somefile.bin")); -Tag tag = nbtInputStream.readTag(); -nbtInputStream.close(); - -if (tag.getType() == TypeTag.STRING) { - TagString tagString = tag.asTagString(); -} -``` - -## Подключение к проекту - -### Maven - -```xml - - - mc-project-repository - https://dmx-mc-project.gitlab.io/maven-repository/ - - - - - - mc-project.nbt - nbt - 1.1-RC - - - - mc-project.nbt.codec - nbt-vanilla-codec - 1.1-RC - - -``` - -### Gradle - -```groovy -repositories { - maven { - name 'mc-project' - url 'https://dmx-mc-project.gitlab.io/maven-repository/' +try (NbtInputStream nbtInputStream = new NbtInputStream(new FileInputStream("somefile.bin"))) { + TagValue tag = nbtInputStream.readTag(); + if (tag.isString()) { + StringTag stringTag = tag.asString(); + // ... } } - -dependencies { - implementation (group: 'mc-project.nbt', name: 'nbt', version: '1.1-RC') - implementation (group: 'mc-project.nbt.codec', name: 'nbt-vanilla-codec', version: '1.1-RC') -} ``` diff --git a/build.gradle b/build.gradle index 2fbeb98..b1b742b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,59 +1,49 @@ -/* Gradle 5.3 */ +plugins { + id 'java' + id 'jacoco' +} wrapper { - gradleVersion = '5.3' - distributionType = Wrapper.DistributionType.ALL + gradleVersion = '8.5' + distributionType = Wrapper.DistributionType.BIN } -subprojects { - apply plugin: 'java' - apply plugin: 'jacoco' +group = 'mc.nbt' +version = '2.0-SNAPSHOT' - def publishScript = file(rootProject.getProjectDir().getPath() + '/publish.gradle') - if (publishScript.exists()) { - apply from: publishScript.path - } +compileJava { + targetCompatibility = sourceCompatibility = JavaVersion.VERSION_17 + options.encoding = 'UTF-8' +} - project.group = projectGroup - project.version = projectVersion +repositories { + mavenLocal() + mavenCentral() +} - compileJava { - sourceCompatibility = 1.8 - targetCompatibility = 1.8 - options.encoding = 'UTF-8' - } +dependencies { + def junit5_version = '5.9.2' + testImplementation("org.junit.jupiter:junit-jupiter-api:${junit5_version}") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junit5_version}") + testImplementation("org.junit.jupiter:junit-jupiter-params:${junit5_version}") - repositories { - mavenLocal() - mavenCentral() - } + testImplementation('org.apache.commons:commons-lang3:3.12.0') +} - ext { - slf4j_version = '1.7.25' - lombok_version = '1.18.2' - junit_version = '5.3.1' - } +test { + useJUnitPlatform() +} - dependencies { - /* LOGGER */ - implementation (group: 'org.slf4j', name: 'slf4j-api', version: slf4j_version) +jacoco { + toolVersion = '0.8.7' +} - /* LOMBOK */ - annotationProcessor (group: 'org.projectlombok', name: 'lombok', version: lombok_version) - compileOnly (group: 'org.projectlombok', name: 'lombok', version: lombok_version) - - /* TESTING */ - testImplementation (group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: junit_version) - testImplementation (group: 'org.junit.jupiter', name: 'junit-jupiter-params', version: junit_version) - testRuntimeOnly (group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: junit_version) - testImplementation (group: 'org.apache.commons', name: 'commons-lang3', version: '3.9') - } - - test { - useJUnitPlatform() - } - - jacoco { - toolVersion = '0.8.5' +jacocoTestReport { + afterEvaluate { + classDirectories.setFrom(files(classDirectories.files.collect { + fileTree(dir: it, + exclude: ['mc/network/api/io/**'] + ) + })) } } diff --git a/gradle.properties b/gradle.properties deleted file mode 100644 index a8acd06..0000000 --- a/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -projectGroup=mc-project.nbt -projectVersion=1.1-RC \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 5c2d1cf..d64cd49 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4de6ed6..1af9e09 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ -#Mon Apr 27 14:14:33 MSK 2020 -distributionUrl=https\://services.gradle.org/distributions/gradle-5.3-all.zip distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 index b0d6d0a..1aa94a4 --- a/gradlew +++ b/gradlew @@ -1,13 +1,13 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# 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 # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, @@ -17,78 +17,111 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# 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/subprojects/plugins/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 -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +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 -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# 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"' +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +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 - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +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" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -97,92 +130,120 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + 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" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; +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 -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") +# 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. -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +# 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" ) -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done fi + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 9991c50..93e3f59 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -5,7 +5,7 @@ @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 http://www.apache.org/licenses/LICENSE-2.0 +@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, @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,10 +25,14 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +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" @@ -37,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -51,7 +55,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -61,38 +65,26 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :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 %CMD_LINE_ARGS% +"%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%"=="0" goto mainEnd +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! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +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 diff --git a/lombok.config b/lombok.config deleted file mode 100644 index 48a65c1..0000000 --- a/lombok.config +++ /dev/null @@ -1,2 +0,0 @@ -# Добавить runtime аннотацию @lombok.Generated ко всем генерируемым методам "ломбока" -lombok.addLombokGeneratedAnnotation = true \ No newline at end of file diff --git a/nbt/src/main/java/mc/nbt/TypeTag.java b/nbt/src/main/java/mc/nbt/TypeTag.java deleted file mode 100644 index 788270c..0000000 --- a/nbt/src/main/java/mc/nbt/TypeTag.java +++ /dev/null @@ -1,45 +0,0 @@ -package mc.nbt; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import mc.nbt.tag.*; - -@RequiredArgsConstructor -@Getter -public enum TypeTag { - END(0, TagEnd.class), - BYTE(1, TagByte.class), - SHORT(2,TagShort.class), - INT(3, TagInt.class), - LONG(4, TagLong.class), - FLOAT(5, TagFloat.class), - DOUBLE(6, TagDouble.class), - BYTE_ARRAY(7, TagByteArray.class), - STRING(8, TagString.class), - LIST(9, TagList.class), - COMPOUND(10, TagCompound.class), - INT_ARRAY(11, TagIntArray.class), - LONG_ARRAY(12, TagLongArray.class); - - public static Tag getTagById(int id) { - TypeTag type = valueOfTypeId(id); - try { - return type.classTag.newInstance(); - } catch (InstantiationException | IllegalAccessException e) { - throw new RuntimeException(e); //FIXME - } - } - - public static TypeTag valueOfTypeId(int id) { - for (TypeTag type : TypeTag.values()) { - if (type.id == id) { - return type; - } - } - - throw new RuntimeException("Unknown tag id: " + id); //FIXME - } - - private final int id; - private final Class classTag; -} diff --git a/nbt/src/main/java/mc/nbt/tag/Tag.java b/nbt/src/main/java/mc/nbt/tag/Tag.java deleted file mode 100644 index 31d122d..0000000 --- a/nbt/src/main/java/mc/nbt/tag/Tag.java +++ /dev/null @@ -1,70 +0,0 @@ -package mc.nbt.tag; - -import lombok.Getter; -import lombok.Setter; -import mc.nbt.TypeTag; - -public abstract class Tag { - - @Getter - @Setter - private String name; - - public abstract TypeTag getType(); - - public TagByte asTagByte() { - return (TagByte) this; - } - - public TagShort asTagShort() { - return (TagShort) this; - } - - public TagInt asTagInt() { - return (TagInt) this; - } - - public TagLong asTagLong() { - return (TagLong) this; - } - - public TagFloat asTagFloat() { - return (TagFloat) this; - } - - public TagDouble asTagDouble() { - return (TagDouble) this; - } - - public TagByteArray asTagByteArray() { - return (TagByteArray) this; - } - - public TagString asTagString() { - return (TagString) this; - } - - public TagList asTagList() { - return (TagList) this; - } - - public TagCompound asTagCompound() { - return (TagCompound) this; - } - - public TagIntArray asTagIntArray() { - return (TagIntArray) this; - } - - public TagLongArray asTagLongArray() { - return (TagLongArray) this; - } - - public String toString() { - if (name != null && !name.isEmpty()) { - return "Tag(name=" + this.name + ")"; - } else { - return "Tag"; - } - } -} diff --git a/nbt/src/main/java/mc/nbt/tag/TagByte.java b/nbt/src/main/java/mc/nbt/tag/TagByte.java deleted file mode 100644 index b19c677..0000000 --- a/nbt/src/main/java/mc/nbt/tag/TagByte.java +++ /dev/null @@ -1,30 +0,0 @@ -package mc.nbt.tag; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import mc.nbt.TypeTag; - -@NoArgsConstructor -@ToString(callSuper = true) -public class TagByte extends Tag { - - @Getter - @Setter - private byte value; - - public TagByte(byte value) { - setValue(value); - } - - public TagByte(String name, byte value) { - this(value); - setName(name); - } - - @Override - public TypeTag getType() { - return TypeTag.BYTE; - } -} diff --git a/nbt/src/main/java/mc/nbt/tag/TagByteArray.java b/nbt/src/main/java/mc/nbt/tag/TagByteArray.java deleted file mode 100644 index c416ebe..0000000 --- a/nbt/src/main/java/mc/nbt/tag/TagByteArray.java +++ /dev/null @@ -1,30 +0,0 @@ -package mc.nbt.tag; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import mc.nbt.TypeTag; - -@NoArgsConstructor -@ToString(callSuper = true) -public class TagByteArray extends Tag { - - @Getter - @Setter - private byte[] value; - - public TagByteArray(byte[] value) { - setValue(value); - } - - public TagByteArray(String name, byte[] value) { - this(value); - setName(name); - } - - @Override - public TypeTag getType() { - return TypeTag.BYTE_ARRAY; - } -} diff --git a/nbt/src/main/java/mc/nbt/tag/TagCompound.java b/nbt/src/main/java/mc/nbt/tag/TagCompound.java deleted file mode 100644 index 9897fd5..0000000 --- a/nbt/src/main/java/mc/nbt/tag/TagCompound.java +++ /dev/null @@ -1,32 +0,0 @@ -package mc.nbt.tag; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import mc.nbt.TypeTag; - -import java.util.List; - -@NoArgsConstructor -@ToString(callSuper = true) -public class TagCompound extends Tag { - - @Getter - @Setter - private List value; - - public TagCompound(List value) { - setValue(value); - } - - public TagCompound(String name, List value) { - this(value); - setName(name); - } - - @Override - public TypeTag getType() { - return TypeTag.COMPOUND; - } -} diff --git a/nbt/src/main/java/mc/nbt/tag/TagDouble.java b/nbt/src/main/java/mc/nbt/tag/TagDouble.java deleted file mode 100644 index 9bc7f2b..0000000 --- a/nbt/src/main/java/mc/nbt/tag/TagDouble.java +++ /dev/null @@ -1,30 +0,0 @@ -package mc.nbt.tag; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import mc.nbt.TypeTag; - -@NoArgsConstructor -@ToString(callSuper = true) -public class TagDouble extends Tag { - - @Getter - @Setter - private double value; - - public TagDouble(double value) { - setValue(value); - } - - public TagDouble(String name, double value) { - this(value); - setName(name); - } - - @Override - public TypeTag getType() { - return TypeTag.DOUBLE; - } -} diff --git a/nbt/src/main/java/mc/nbt/tag/TagEnd.java b/nbt/src/main/java/mc/nbt/tag/TagEnd.java deleted file mode 100644 index b497f3f..0000000 --- a/nbt/src/main/java/mc/nbt/tag/TagEnd.java +++ /dev/null @@ -1,26 +0,0 @@ -package mc.nbt.tag; - -import mc.nbt.TypeTag; - -public class TagEnd extends Tag { - - public static final TagEnd INSTANCE = new TagEnd(); - - TagEnd() { - } - - @Override - public void setName(String name) { - throw new UnsupportedOperationException(); - } - - @Override - public String getName() { - return null; - } - - @Override - public TypeTag getType() { - return TypeTag.END; - } -} diff --git a/nbt/src/main/java/mc/nbt/tag/TagFloat.java b/nbt/src/main/java/mc/nbt/tag/TagFloat.java deleted file mode 100644 index 981d68f..0000000 --- a/nbt/src/main/java/mc/nbt/tag/TagFloat.java +++ /dev/null @@ -1,30 +0,0 @@ -package mc.nbt.tag; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import mc.nbt.TypeTag; - -@NoArgsConstructor -@ToString(callSuper = true) -public class TagFloat extends Tag { - - @Getter - @Setter - private float value; - - public TagFloat(float value) { - setValue(value); - } - - public TagFloat(String name, float value) { - this(value); - setName(name); - } - - @Override - public TypeTag getType() { - return TypeTag.FLOAT; - } -} diff --git a/nbt/src/main/java/mc/nbt/tag/TagInt.java b/nbt/src/main/java/mc/nbt/tag/TagInt.java deleted file mode 100644 index cd5e34e..0000000 --- a/nbt/src/main/java/mc/nbt/tag/TagInt.java +++ /dev/null @@ -1,30 +0,0 @@ -package mc.nbt.tag; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import mc.nbt.TypeTag; - -@NoArgsConstructor -@ToString(callSuper = true) -public class TagInt extends Tag { - - @Getter - @Setter - private int value; - - public TagInt(int value) { - setValue(value); - } - - public TagInt(String name, int value) { - this(value); - setName(name); - } - - @Override - public TypeTag getType() { - return TypeTag.INT; - } -} diff --git a/nbt/src/main/java/mc/nbt/tag/TagIntArray.java b/nbt/src/main/java/mc/nbt/tag/TagIntArray.java deleted file mode 100644 index c430526..0000000 --- a/nbt/src/main/java/mc/nbt/tag/TagIntArray.java +++ /dev/null @@ -1,30 +0,0 @@ -package mc.nbt.tag; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import mc.nbt.TypeTag; - -@NoArgsConstructor -@ToString(callSuper = true) -public class TagIntArray extends Tag { - - @Getter - @Setter - private int[] value; - - public TagIntArray(int[] value) { - setValue(value); - } - - public TagIntArray(String name, int[] value) { - this(value); - setName(name); - } - - @Override - public TypeTag getType() { - return TypeTag.INT_ARRAY; - } -} diff --git a/nbt/src/main/java/mc/nbt/tag/TagList.java b/nbt/src/main/java/mc/nbt/tag/TagList.java deleted file mode 100644 index 10cf1f4..0000000 --- a/nbt/src/main/java/mc/nbt/tag/TagList.java +++ /dev/null @@ -1,51 +0,0 @@ -package mc.nbt.tag; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import mc.nbt.TypeTag; - -import java.util.List; -import java.util.Objects; - -@NoArgsConstructor -@ToString(callSuper = true) -public class TagList extends Tag { - - @Getter - @Setter - private List value; //FIXME - - @Getter - private TypeTag typeList; - - public TagList(List value) { - Objects.requireNonNull(value); - - setValue(value); - if (!value.isEmpty()) { - setTypeList(value.get(0).getType()); - } - } - - public TagList(String name, List value) { - this(value); - setName(name); - } - - public void setTypeList(TypeTag typeList) { - if (value != null && !value.isEmpty()) { - if (value.get(0).getType() != typeList) { - throw new IllegalArgumentException("Incorrect type"); //FIXME - } - } - - this.typeList = typeList; - } - - @Override - public TypeTag getType() { - return TypeTag.LIST; - } -} diff --git a/nbt/src/main/java/mc/nbt/tag/TagLong.java b/nbt/src/main/java/mc/nbt/tag/TagLong.java deleted file mode 100644 index 3db4eb7..0000000 --- a/nbt/src/main/java/mc/nbt/tag/TagLong.java +++ /dev/null @@ -1,30 +0,0 @@ -package mc.nbt.tag; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import mc.nbt.TypeTag; - -@NoArgsConstructor -@ToString(callSuper = true) -public class TagLong extends Tag { - - @Getter - @Setter - private long value; - - public TagLong(long value) { - setValue(value); - } - - public TagLong(String name, long value) { - this(value); - setName(name); - } - - @Override - public TypeTag getType() { - return TypeTag.LONG; - } -} diff --git a/nbt/src/main/java/mc/nbt/tag/TagLongArray.java b/nbt/src/main/java/mc/nbt/tag/TagLongArray.java deleted file mode 100644 index 382865e..0000000 --- a/nbt/src/main/java/mc/nbt/tag/TagLongArray.java +++ /dev/null @@ -1,30 +0,0 @@ -package mc.nbt.tag; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import mc.nbt.TypeTag; - -@NoArgsConstructor -@ToString(callSuper = true) -public class TagLongArray extends Tag { - - @Getter - @Setter - private long[] value; - - public TagLongArray(long[] value) { - setValue(value); - } - - public TagLongArray(String name, long[] value) { - this(value); - setName(name); - } - - @Override - public TypeTag getType() { - return TypeTag.LONG_ARRAY; - } -} diff --git a/nbt/src/main/java/mc/nbt/tag/TagShort.java b/nbt/src/main/java/mc/nbt/tag/TagShort.java deleted file mode 100644 index 235a320..0000000 --- a/nbt/src/main/java/mc/nbt/tag/TagShort.java +++ /dev/null @@ -1,30 +0,0 @@ -package mc.nbt.tag; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import mc.nbt.TypeTag; - -@NoArgsConstructor -@ToString(callSuper = true) -public class TagShort extends Tag { - - @Getter - @Setter - private short value; - - public TagShort(short value) { - setValue(value); - } - - public TagShort(String name, short value) { - this(value); - setName(name); - } - - @Override - public TypeTag getType() { - return TypeTag.SHORT; - } -} diff --git a/nbt/src/main/java/mc/nbt/tag/TagString.java b/nbt/src/main/java/mc/nbt/tag/TagString.java deleted file mode 100644 index 3223bef..0000000 --- a/nbt/src/main/java/mc/nbt/tag/TagString.java +++ /dev/null @@ -1,30 +0,0 @@ -package mc.nbt.tag; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import mc.nbt.TypeTag; - -@NoArgsConstructor -@ToString(callSuper = true) -public class TagString extends Tag { - - @Getter - @Setter - private String value; - - public TagString(String value) { - setValue(value); - } - - public TagString(String name, String value) { - this(value); - setName(name); - } - - @Override - public TypeTag getType() { - return TypeTag.STRING; - } -} diff --git a/nbt/src/test/java/mc/nbt/tag/TagEndTest.java b/nbt/src/test/java/mc/nbt/tag/TagEndTest.java deleted file mode 100644 index c40a3d5..0000000 --- a/nbt/src/test/java/mc/nbt/tag/TagEndTest.java +++ /dev/null @@ -1,30 +0,0 @@ -package mc.nbt.tag; - -import mc.nbt.TypeTag; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -class TagEndTest { - - @Test - void testUnsupportSetName() { - TagEnd tagEnd = new TagEnd(); - - assertThrows(UnsupportedOperationException.class, () -> tagEnd.setName("any")); - } - - @Test - void testGetName() { - TagEnd tagEnd = new TagEnd(); - - assertNull(tagEnd.getName()); - } - - @Test - void testGetType() { - TagEnd tagEnd = new TagEnd(); - - assertEquals(TypeTag.END, tagEnd.getType()); - } -} diff --git a/settings.gradle b/settings.gradle index a63d74b..26a333e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1 @@ rootProject.name = 'nbt-lib' - -include('nbt') -include('vanilla-codec') diff --git a/src/main/java/mc/nbt/ByteArrayTag.java b/src/main/java/mc/nbt/ByteArrayTag.java new file mode 100644 index 0000000..79dc2d9 --- /dev/null +++ b/src/main/java/mc/nbt/ByteArrayTag.java @@ -0,0 +1,46 @@ +package mc.nbt; + +import mc.nbt.internal.JacocoExcludeGeneratedReport; + +import java.util.Arrays; +import java.util.Objects; + +public class ByteArrayTag extends TagValue { + private final byte[] value; + + public ByteArrayTag(byte[] value) { + this.value = Objects.requireNonNull(value); + } + + @Override + public TagType getType() { + return TagType.BYTE_ARRAY; + } + + public byte[] getValue() { + return value; + } + + @JacocoExcludeGeneratedReport + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ByteArrayTag that = (ByteArrayTag) o; + return Arrays.equals(getValue(), that.getValue()); + } + + @JacocoExcludeGeneratedReport + @Override + public int hashCode() { + return Arrays.hashCode(getValue()); + } + + @JacocoExcludeGeneratedReport + @Override + public String toString() { + return "ByteArrayTag{" + + "value.length=" + value.length + + '}'; + } +} diff --git a/src/main/java/mc/nbt/ByteTag.java b/src/main/java/mc/nbt/ByteTag.java new file mode 100644 index 0000000..ceb4831 --- /dev/null +++ b/src/main/java/mc/nbt/ByteTag.java @@ -0,0 +1,45 @@ +package mc.nbt; + +import mc.nbt.internal.JacocoExcludeGeneratedReport; + +import java.util.Objects; + +public class ByteTag extends TagValue { + private final byte value; + + public ByteTag(byte value) { + this.value = value; + } + + @Override + public TagType getType() { + return TagType.BYTE; + } + + public byte getValue() { + return value; + } + + @JacocoExcludeGeneratedReport + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ByteTag byteTag = (ByteTag) o; + return getValue() == byteTag.getValue(); + } + + @JacocoExcludeGeneratedReport + @Override + public int hashCode() { + return Objects.hash(getValue()); + } + + @JacocoExcludeGeneratedReport + @Override + public String toString() { + return "ByteTag{" + + "value=" + value + + '}'; + } +} diff --git a/src/main/java/mc/nbt/CompoundTag.java b/src/main/java/mc/nbt/CompoundTag.java new file mode 100644 index 0000000..871c9e1 --- /dev/null +++ b/src/main/java/mc/nbt/CompoundTag.java @@ -0,0 +1,118 @@ +package mc.nbt; + +import mc.nbt.internal.JacocoExcludeGeneratedReport; + +import java.io.Serializable; +import java.util.*; + +public class CompoundTag extends TagValue implements Map, Serializable { + private final LinkedHashMap map; + + public CompoundTag() { + this.map = new LinkedHashMap<>(); + } + + public CompoundTag(String key, TagValue value) { + this.map = new LinkedHashMap<>(); + this.map.put(key, value); + } + + public CompoundTag(Map map) { + this.map = new LinkedHashMap<>(map); + } + + @Override + public TagType getType() { + return TagType.COMPOUND; + } + + public CompoundTag append(String key, TagValue value) { + this.map.put(key, value); + return this; + } + + // Map methods + + @Override + public int size() { + return map.size(); + } + + @Override + public boolean isEmpty() { + return map.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + return map.containsKey(key); + } + + @Override + public boolean containsValue(Object value) { + return map.containsValue(value); + } + + @Override + public TagValue get(Object key) { + return map.get(key); + } + + @Override + public TagValue put(String key, TagValue value) { + return map.put(key, value); + } + + @Override + public TagValue remove(Object value) { + return map.remove(value); + } + + @Override + public void putAll(Map map) { + this.map.putAll(map); + } + + @Override + public void clear() { + map.clear(); + } + + @Override + public Set keySet() { + return map.keySet(); + } + + @Override + public Collection values() { + return map.values(); + } + + @Override + public Set> entrySet() { + return map.entrySet(); + } + + @JacocoExcludeGeneratedReport + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CompoundTag that = (CompoundTag) o; + return map.equals(that.map); + } + + @JacocoExcludeGeneratedReport + @Override + public int hashCode() { + return Objects.hash(map); + } + + @JacocoExcludeGeneratedReport + @Override + public String toString() { + return "CompoundTag{" + + map + + '}'; + } +} diff --git a/src/main/java/mc/nbt/DoubleTag.java b/src/main/java/mc/nbt/DoubleTag.java new file mode 100644 index 0000000..8ba82e6 --- /dev/null +++ b/src/main/java/mc/nbt/DoubleTag.java @@ -0,0 +1,45 @@ +package mc.nbt; + +import mc.nbt.internal.JacocoExcludeGeneratedReport; + +import java.util.Objects; + +public class DoubleTag extends TagValue { + private final double value; + + public DoubleTag(double value) { + this.value = value; + } + + @Override + public TagType getType() { + return TagType.DOUBLE; + } + + public double getValue() { + return value; + } + + @JacocoExcludeGeneratedReport + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DoubleTag doubleTag = (DoubleTag) o; + return Double.compare(doubleTag.getValue(), getValue()) == 0; + } + + @JacocoExcludeGeneratedReport + @Override + public int hashCode() { + return Objects.hash(getValue()); + } + + @JacocoExcludeGeneratedReport + @Override + public String toString() { + return "DoubleTag{" + + "value=" + value + + '}'; + } +} diff --git a/src/main/java/mc/nbt/EndTag.java b/src/main/java/mc/nbt/EndTag.java new file mode 100644 index 0000000..999c193 --- /dev/null +++ b/src/main/java/mc/nbt/EndTag.java @@ -0,0 +1,30 @@ +package mc.nbt; + +import mc.nbt.internal.JacocoExcludeGeneratedReport; + +@JacocoExcludeGeneratedReport +public class EndTag extends TagValue { + private static final EndTag INSTANCE = new EndTag(); + + private EndTag() { + } + + @Override + public TagType getType() { + return TagType.END; + } + + @Override + public String getName() { + return null; + } + + @Override + public void setName(String name) { + throw new UnsupportedOperationException(); + } + + public static EndTag getInstance() { + return INSTANCE; + } +} diff --git a/src/main/java/mc/nbt/FloatTag.java b/src/main/java/mc/nbt/FloatTag.java new file mode 100644 index 0000000..3cddb1f --- /dev/null +++ b/src/main/java/mc/nbt/FloatTag.java @@ -0,0 +1,45 @@ +package mc.nbt; + +import mc.nbt.internal.JacocoExcludeGeneratedReport; + +import java.util.Objects; + +public class FloatTag extends TagValue { + private final float value; + + public FloatTag(float value) { + this.value = value; + } + + @Override + public TagType getType() { + return TagType.FLOAT; + } + + public float getValue() { + return value; + } + + @JacocoExcludeGeneratedReport + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + FloatTag floatTag = (FloatTag) o; + return Float.compare(floatTag.getValue(), getValue()) == 0; + } + + @JacocoExcludeGeneratedReport + @Override + public int hashCode() { + return Objects.hash(getValue()); + } + + @JacocoExcludeGeneratedReport + @Override + public String toString() { + return "FloatTag{" + + "value=" + value + + '}'; + } +} diff --git a/src/main/java/mc/nbt/IntegerArrayTag.java b/src/main/java/mc/nbt/IntegerArrayTag.java new file mode 100644 index 0000000..5e77623 --- /dev/null +++ b/src/main/java/mc/nbt/IntegerArrayTag.java @@ -0,0 +1,46 @@ +package mc.nbt; + +import mc.nbt.internal.JacocoExcludeGeneratedReport; + +import java.util.Arrays; +import java.util.Objects; + +public class IntegerArrayTag extends TagValue { + private final int[] value; + + public IntegerArrayTag(int[] value) { + this.value = Objects.requireNonNull(value); + } + + @Override + public TagType getType() { + return TagType.INTEGER_ARRAY; + } + + public int[] getValue() { + return value; + } + + @JacocoExcludeGeneratedReport + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + IntegerArrayTag that = (IntegerArrayTag) o; + return Arrays.equals(getValue(), that.getValue()); + } + + @JacocoExcludeGeneratedReport + @Override + public int hashCode() { + return Arrays.hashCode(getValue()); + } + + @JacocoExcludeGeneratedReport + @Override + public String toString() { + return "IntegerArrayTag{" + + "value.length=" + value.length + + '}'; + } +} diff --git a/src/main/java/mc/nbt/IntegerTag.java b/src/main/java/mc/nbt/IntegerTag.java new file mode 100644 index 0000000..7535cae --- /dev/null +++ b/src/main/java/mc/nbt/IntegerTag.java @@ -0,0 +1,45 @@ +package mc.nbt; + +import mc.nbt.internal.JacocoExcludeGeneratedReport; + +import java.util.Objects; + +public class IntegerTag extends TagValue { + private final int value; + + public IntegerTag(int value) { + this.value = value; + } + + @Override + public TagType getType() { + return TagType.INTEGER; + } + + public int getValue() { + return value; + } + + @JacocoExcludeGeneratedReport + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + IntegerTag that = (IntegerTag) o; + return getValue() == that.getValue(); + } + + @JacocoExcludeGeneratedReport + @Override + public int hashCode() { + return Objects.hash(getValue()); + } + + @JacocoExcludeGeneratedReport + @Override + public String toString() { + return "IntegerTag{" + + "value=" + value + + '}'; + } +} diff --git a/src/main/java/mc/nbt/ListTag.java b/src/main/java/mc/nbt/ListTag.java new file mode 100644 index 0000000..a9d82ae --- /dev/null +++ b/src/main/java/mc/nbt/ListTag.java @@ -0,0 +1,178 @@ +package mc.nbt; + +import mc.nbt.internal.JacocoExcludeGeneratedReport; + +import java.util.*; + +public class ListTag extends TagValue implements List { + + private final TagType listType; + private final List list; + + public ListTag(TagType listType, int initialCapacity) { + this.listType = Objects.requireNonNull(listType); + this.list = new ArrayList<>(initialCapacity); + } + + public ListTag(TagType listType) { + this.listType = Objects.requireNonNull(listType); + this.list = new ArrayList<>(); + } + + @Override + public TagType getType() { + return TagType.LIST; + } + + public TagType getListType() { + return listType; + } + + public ListTag append(TagValue tag) { + list.add(tag); + return this; + } + + // List methods + + @Override + public int size() { + return list.size(); + } + + @Override + public boolean isEmpty() { + return list.isEmpty(); + } + + @Override + public boolean contains(Object o) { + return list.contains(o); + } + + @Override + public Iterator iterator() { + return list.iterator(); + } + + @Override + public Object[] toArray() { + return list.toArray(); + } + + @SuppressWarnings("SuspiciousToArrayCall") + @Override + public A[] toArray(A[] array) { + return list.toArray(array); + } + + @Override + public boolean add(TagValue tag) { + return list.add(tag); + } + + @Override + public boolean remove(Object o) { + return list.remove(o); + } + + @SuppressWarnings("SlowListContainsAll") + @Override + public boolean containsAll(Collection collection) { + return list.containsAll(collection); + } + + @Override + public boolean addAll(Collection collection) { + return list.addAll(collection); + } + + @Override + public boolean addAll(int index, Collection collection) { + return list.addAll(index, collection); + } + + @Override + public boolean removeAll(Collection collection) { + return list.removeAll(collection); + } + + @Override + public boolean retainAll(Collection collection) { + return list.retainAll(collection); + } + + @Override + public void clear() { + list.clear(); + } + + @Override + public TagValue get(int index) { + return list.get(index); + } + + @Override + public TagValue set(int index, TagValue element) { + return list.set(index, element); + } + + @Override + public void add(int index, TagValue element) { + list.add(index, element); + } + + @Override + public TagValue remove(int index) { + return list.remove(index); + } + + @Override + public int indexOf(Object o) { + return list.indexOf(o); + } + + @Override + public int lastIndexOf(Object o) { + return list.lastIndexOf(o); + } + + @Override + public ListIterator listIterator() { + return list.listIterator(); + } + + @Override + public ListIterator listIterator(int index) { + return list.listIterator(index); + } + + @Override + public List subList(int fromIndex, int toIndex) { + return list.subList(fromIndex, toIndex); + } + + @JacocoExcludeGeneratedReport + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ListTag listTag = (ListTag) o; + return list.equals(listTag.list) && getListType() == listTag.getListType(); + } + + @JacocoExcludeGeneratedReport + @Override + public int hashCode() { + return Objects.hash(list, getListType()); + } + + @JacocoExcludeGeneratedReport + @Override + public String toString() { + return "ListTag{" + + "listType=" + listType + + ", list=" + list + + '}'; + } +} diff --git a/src/main/java/mc/nbt/LongArrayTag.java b/src/main/java/mc/nbt/LongArrayTag.java new file mode 100644 index 0000000..185d6f4 --- /dev/null +++ b/src/main/java/mc/nbt/LongArrayTag.java @@ -0,0 +1,46 @@ +package mc.nbt; + +import mc.nbt.internal.JacocoExcludeGeneratedReport; + +import java.util.Arrays; +import java.util.Objects; + +public class LongArrayTag extends TagValue { + private final long[] value; + + public LongArrayTag(long[] value) { + this.value = Objects.requireNonNull(value); + } + + @Override + public TagType getType() { + return TagType.LONG_ARRAY; + } + + public long[] getValue() { + return value; + } + + @JacocoExcludeGeneratedReport + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + LongArrayTag that = (LongArrayTag) o; + return Arrays.equals(getValue(), that.getValue()); + } + + @JacocoExcludeGeneratedReport + @Override + public int hashCode() { + return Arrays.hashCode(getValue()); + } + + @JacocoExcludeGeneratedReport + @Override + public String toString() { + return "LongArrayTag{" + + "value.length=" + value.length + + '}'; + } +} diff --git a/src/main/java/mc/nbt/LongTag.java b/src/main/java/mc/nbt/LongTag.java new file mode 100644 index 0000000..772b162 --- /dev/null +++ b/src/main/java/mc/nbt/LongTag.java @@ -0,0 +1,45 @@ +package mc.nbt; + +import mc.nbt.internal.JacocoExcludeGeneratedReport; + +import java.util.Objects; + +public class LongTag extends TagValue { + private final long value; + + public LongTag(long value) { + this.value = value; + } + + @Override + public TagType getType() { + return TagType.LONG; + } + + public long getValue() { + return value; + } + + @JacocoExcludeGeneratedReport + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + LongTag longTag = (LongTag) o; + return getValue() == longTag.getValue(); + } + + @JacocoExcludeGeneratedReport + @Override + public int hashCode() { + return Objects.hash(getValue()); + } + + @JacocoExcludeGeneratedReport + @Override + public String toString() { + return "LongTag{" + + "value=" + value + + '}'; + } +} diff --git a/src/main/java/mc/nbt/ShortTag.java b/src/main/java/mc/nbt/ShortTag.java new file mode 100644 index 0000000..56f37b8 --- /dev/null +++ b/src/main/java/mc/nbt/ShortTag.java @@ -0,0 +1,45 @@ +package mc.nbt; + +import mc.nbt.internal.JacocoExcludeGeneratedReport; + +import java.util.Objects; + +public class ShortTag extends TagValue { + private final short value; + + public ShortTag(short value) { + this.value = value; + } + + @Override + public TagType getType() { + return TagType.SHORT; + } + + public short getValue() { + return value; + } + + @JacocoExcludeGeneratedReport + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ShortTag shortTag = (ShortTag) o; + return getValue() == shortTag.getValue(); + } + + @JacocoExcludeGeneratedReport + @Override + public int hashCode() { + return Objects.hash(getValue()); + } + + @JacocoExcludeGeneratedReport + @Override + public String toString() { + return "ShortTag{" + + "value=" + value + + '}'; + } +} diff --git a/src/main/java/mc/nbt/StringTag.java b/src/main/java/mc/nbt/StringTag.java new file mode 100644 index 0000000..59440c1 --- /dev/null +++ b/src/main/java/mc/nbt/StringTag.java @@ -0,0 +1,46 @@ +package mc.nbt; + +import mc.nbt.internal.JacocoExcludeGeneratedReport; + +import java.util.Objects; + +public class StringTag extends TagValue { + + private final String value; + + public StringTag(String value) { + this.value = Objects.requireNonNull(value); + } + + @Override + public TagType getType() { + return TagType.STRING; + } + + public String getValue() { + return this.value; + } + + @JacocoExcludeGeneratedReport + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + StringTag stringTag = (StringTag) o; + return getValue().equals(stringTag.getValue()); + } + + @JacocoExcludeGeneratedReport + @Override + public int hashCode() { + return Objects.hash(getValue()); + } + + @JacocoExcludeGeneratedReport + @Override + public String toString() { + return "StringTag{" + + "value='" + value + '\'' + + '}'; + } +} diff --git a/src/main/java/mc/nbt/TagType.java b/src/main/java/mc/nbt/TagType.java new file mode 100644 index 0000000..c1ad06f --- /dev/null +++ b/src/main/java/mc/nbt/TagType.java @@ -0,0 +1,40 @@ +package mc.nbt; + +public enum TagType { + BYTE(1), + SHORT(2), + INTEGER(3), + LONG(4), + FLOAT(5), + DOUBLE(6), + + BYTE_ARRAY(7), + INTEGER_ARRAY(11), + LONG_ARRAY(12), + + STRING(8), + LIST(9), + COMPOUND(10), + + END(0); + + private final int id; + + TagType(int id) { + this.id = id; + } + + public int getId() { + return id; + } + + public static TagType valueOfId(int id) { + for (TagType type : TagType.values()) { + if (type.id == id) { + return type; + } + } + + throw new RuntimeException("Unknown tag id: " + id); //TODO семантический exception + } +} diff --git a/src/main/java/mc/nbt/TagValue.java b/src/main/java/mc/nbt/TagValue.java new file mode 100644 index 0000000..cc33c66 --- /dev/null +++ b/src/main/java/mc/nbt/TagValue.java @@ -0,0 +1,135 @@ +package mc.nbt; + +public abstract class TagValue { + protected String name; + + TagValue() { + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public abstract TagType getType(); + + public ByteTag asByte() { + throwIfInvalidType(TagType.BYTE); + return (ByteTag) this; + } + + public ByteArrayTag asByteArray() { + throwIfInvalidType(TagType.BYTE_ARRAY); + return (ByteArrayTag) this; + } + + public ShortTag asShort() { + throwIfInvalidType(TagType.SHORT); + return (ShortTag) this; + } + + public IntegerTag asInteger() { + throwIfInvalidType(TagType.INTEGER); + return (IntegerTag) this; + } + + public IntegerArrayTag asIntegerArray() { + throwIfInvalidType(TagType.INTEGER_ARRAY); + return (IntegerArrayTag) this; + } + + public LongTag asLong() { + throwIfInvalidType(TagType.LONG); + return (LongTag) this; + } + + public LongArrayTag asLongArray() { + throwIfInvalidType(TagType.LONG_ARRAY); + return (LongArrayTag) this; + } + + public FloatTag asFloat() { + throwIfInvalidType(TagType.FLOAT); + return (FloatTag) this; + } + + public DoubleTag asDouble() { + throwIfInvalidType(TagType.DOUBLE); + return (DoubleTag) this; + } + + public StringTag asString() { + throwIfInvalidType(TagType.STRING); + return (StringTag) this; + } + + public ListTag asList() { + throwIfInvalidType(TagType.LIST); + return (ListTag) this; + } + + public CompoundTag asCompound() { + throwIfInvalidType(TagType.COMPOUND); + return (CompoundTag) this; + } + + public boolean isByte() { + return getType() == TagType.BYTE; + } + + public boolean isByteArray() { + return getType() == TagType.BYTE_ARRAY; + } + + public boolean isShort() { + return getType() == TagType.SHORT; + } + + public boolean isInteger() { + return getType() == TagType.INTEGER; + } + + public boolean isIntegerArray() { + return getType() == TagType.INTEGER_ARRAY; + } + + public boolean isLong() { + return getType() == TagType.LONG; + } + + public boolean isLongArray() { + return getType() == TagType.LONG_ARRAY; + } + + public boolean isFloat() { + return getType() == TagType.FLOAT; + } + + public boolean isDouble() { + return getType() == TagType.DOUBLE; + } + + public boolean isString() { + return getType() == TagType.STRING; + } + + public boolean isCompound() { + return getType() == TagType.COMPOUND; + } + + public boolean isEnd() { + return getType() == TagType.END; + } + + private void throwIfInvalidType(TagType expectedType) { + if (getType() != expectedType) { + //TODO семантический exception + throw new RuntimeException( + "Value expected to be type %s is of unexpected type %s" + .formatted(expectedType, getType())); + } + } +} diff --git a/src/main/java/mc/nbt/codec/ByteArrayTagCodec.java b/src/main/java/mc/nbt/codec/ByteArrayTagCodec.java new file mode 100644 index 0000000..4278389 --- /dev/null +++ b/src/main/java/mc/nbt/codec/ByteArrayTagCodec.java @@ -0,0 +1,26 @@ +package mc.nbt.codec; + +import mc.nbt.ByteArrayTag; +import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; + +import java.io.IOException; + +public class ByteArrayTagCodec implements Codec { + + @Override + public void encode(ByteArrayTag tag, NbtOutputStream outputStream) throws IOException { + outputStream.writeInt(tag.getValue().length); + outputStream.write(tag.getValue()); + } + + @SuppressWarnings("ResultOfMethodCallIgnored") + @Override + public ByteArrayTag decode(NbtInputStream inputStream) throws IOException { + int len = inputStream.readInt(); + byte[] bytes = new byte[len]; + inputStream.read(bytes); + + return new ByteArrayTag(bytes); + } +} diff --git a/src/main/java/mc/nbt/codec/ByteTagCodec.java b/src/main/java/mc/nbt/codec/ByteTagCodec.java new file mode 100644 index 0000000..64db2f5 --- /dev/null +++ b/src/main/java/mc/nbt/codec/ByteTagCodec.java @@ -0,0 +1,20 @@ +package mc.nbt.codec; + +import mc.nbt.ByteTag; +import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; + +import java.io.IOException; + +public class ByteTagCodec implements Codec { + + @Override + public void encode(ByteTag tag, NbtOutputStream outputStream) throws IOException { + outputStream.writeByte(tag.getValue()); + } + + @Override + public ByteTag decode(NbtInputStream inputStream) throws IOException { + return new ByteTag(inputStream.readByte()); + } +} diff --git a/src/main/java/mc/nbt/codec/Codec.java b/src/main/java/mc/nbt/codec/Codec.java new file mode 100644 index 0000000..8208e1d --- /dev/null +++ b/src/main/java/mc/nbt/codec/Codec.java @@ -0,0 +1,14 @@ +package mc.nbt.codec; + +import mc.nbt.TagValue; +import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; + +import java.io.IOException; + +public interface Codec { + + void encode(T tag, NbtOutputStream outputStream) throws IOException; + + T decode(NbtInputStream inputStream) throws IOException; +} diff --git a/src/main/java/mc/nbt/codec/CodecRegistry.java b/src/main/java/mc/nbt/codec/CodecRegistry.java new file mode 100644 index 0000000..a620c5f --- /dev/null +++ b/src/main/java/mc/nbt/codec/CodecRegistry.java @@ -0,0 +1,39 @@ +package mc.nbt.codec; + +import mc.nbt.TagType; +import mc.nbt.TagValue; + +import java.util.Map; +import java.util.Objects; + +public class CodecRegistry { + private static final CodecRegistry INSTANCE = new CodecRegistry(); + + private final Map> codecs; + + private CodecRegistry() { + codecs = Map.ofEntries( + Map.entry(TagType.BYTE, new ByteTagCodec()), + Map.entry(TagType.SHORT, new ShortTagCodec()), + Map.entry(TagType.INTEGER, new IntegerTagCodec()), + Map.entry(TagType.LONG, new LongTagCodec()), + Map.entry(TagType.FLOAT, new FloatTagCodec()), + Map.entry(TagType.DOUBLE, new DoubleTagCodec()), + Map.entry(TagType.BYTE_ARRAY, new ByteArrayTagCodec()), + Map.entry(TagType.INTEGER_ARRAY, new IntegerArrayTagCodec()), + Map.entry(TagType.LONG_ARRAY, new LongArrayTagCodec()), + Map.entry(TagType.STRING, new StringTagCodec()), + Map.entry(TagType.LIST, new ListTagCodec()), + Map.entry(TagType.COMPOUND, new CompoundTagCodec()), + Map.entry(TagType.END, new EndTagCodec()) + ); + } + + public Codec get(TagType tagType) { + return codecs.get(Objects.requireNonNull(tagType)); + } + + public static CodecRegistry getInstance() { + return INSTANCE; + } +} diff --git a/src/main/java/mc/nbt/codec/CompoundTagCodec.java b/src/main/java/mc/nbt/codec/CompoundTagCodec.java new file mode 100644 index 0000000..9cc4c40 --- /dev/null +++ b/src/main/java/mc/nbt/codec/CompoundTagCodec.java @@ -0,0 +1,40 @@ +package mc.nbt.codec; + +import mc.nbt.CompoundTag; +import mc.nbt.EndTag; +import mc.nbt.TagValue; +import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; + +import java.io.IOException; +import java.util.Map; + +public class CompoundTagCodec implements Codec { + + @Override + public void encode(CompoundTag tag, NbtOutputStream outputStream) throws IOException { + for (Map.Entry entry : tag.entrySet()) { + if (entry.getValue() == null) //TODO по-хорошему, пользователю нужно запретить вставлять null-теги + continue; + + outputStream.writeTag(entry.getKey(), entry.getValue()); + } + + outputStream.writeTag(EndTag.getInstance()); + } + + @Override + public CompoundTag decode(NbtInputStream inputStream) throws IOException { + var compoundTag = new CompoundTag(); + + do { + var tagValue = inputStream.readTag(); + if (tagValue.isEnd()) + break; + + compoundTag.append(tagValue.getName(), tagValue); + } while (true); + + return compoundTag; + } +} diff --git a/src/main/java/mc/nbt/codec/DoubleTagCodec.java b/src/main/java/mc/nbt/codec/DoubleTagCodec.java new file mode 100644 index 0000000..8928aa8 --- /dev/null +++ b/src/main/java/mc/nbt/codec/DoubleTagCodec.java @@ -0,0 +1,20 @@ +package mc.nbt.codec; + +import mc.nbt.DoubleTag; +import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; + +import java.io.IOException; + +public class DoubleTagCodec implements Codec { + + @Override + public void encode(DoubleTag tag, NbtOutputStream outputStream) throws IOException { + outputStream.writeDouble(tag.getValue()); + } + + @Override + public DoubleTag decode(NbtInputStream inputStream) throws IOException { + return new DoubleTag(inputStream.readDouble()); + } +} diff --git a/src/main/java/mc/nbt/codec/EndTagCodec.java b/src/main/java/mc/nbt/codec/EndTagCodec.java new file mode 100644 index 0000000..0a12bc7 --- /dev/null +++ b/src/main/java/mc/nbt/codec/EndTagCodec.java @@ -0,0 +1,20 @@ +package mc.nbt.codec; + +import mc.nbt.EndTag; +import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; + +import java.io.IOException; + +public class EndTagCodec implements Codec { + + @Override + public void encode(EndTag tag, NbtOutputStream outputStream) throws IOException { + // nothing + } + + @Override + public EndTag decode(NbtInputStream inputStream) throws IOException { + return EndTag.getInstance(); + } +} diff --git a/src/main/java/mc/nbt/codec/FloatTagCodec.java b/src/main/java/mc/nbt/codec/FloatTagCodec.java new file mode 100644 index 0000000..e674abf --- /dev/null +++ b/src/main/java/mc/nbt/codec/FloatTagCodec.java @@ -0,0 +1,20 @@ +package mc.nbt.codec; + +import mc.nbt.FloatTag; +import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; + +import java.io.IOException; + +public class FloatTagCodec implements Codec { + + @Override + public void encode(FloatTag tag, NbtOutputStream outputStream) throws IOException { + outputStream.writeFloat(tag.getValue()); + } + + @Override + public FloatTag decode(NbtInputStream inputStream) throws IOException { + return new FloatTag(inputStream.readFloat()); + } +} diff --git a/src/main/java/mc/nbt/codec/IntegerArrayTagCodec.java b/src/main/java/mc/nbt/codec/IntegerArrayTagCodec.java new file mode 100644 index 0000000..8977305 --- /dev/null +++ b/src/main/java/mc/nbt/codec/IntegerArrayTagCodec.java @@ -0,0 +1,30 @@ +package mc.nbt.codec; + +import mc.nbt.IntegerArrayTag; +import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; + +import java.io.IOException; + +public class IntegerArrayTagCodec implements Codec { + + @Override + public void encode(IntegerArrayTag tag, NbtOutputStream outputStream) throws IOException { + outputStream.writeInt(tag.getValue().length); + for (int item : tag.getValue()) { + outputStream.writeInt(item); + } + } + + @Override + public IntegerArrayTag decode(NbtInputStream inputStream) throws IOException { + int len = inputStream.readInt(); + int[] ints = new int[len]; + + for (int i = 0; i < len; i++) { + ints[i] = inputStream.readInt(); + } + + return new IntegerArrayTag(ints); + } +} diff --git a/src/main/java/mc/nbt/codec/IntegerTagCodec.java b/src/main/java/mc/nbt/codec/IntegerTagCodec.java new file mode 100644 index 0000000..b3d9885 --- /dev/null +++ b/src/main/java/mc/nbt/codec/IntegerTagCodec.java @@ -0,0 +1,20 @@ +package mc.nbt.codec; + +import mc.nbt.IntegerTag; +import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; + +import java.io.IOException; + +public class IntegerTagCodec implements Codec { + + @Override + public void encode(IntegerTag tag, NbtOutputStream outputStream) throws IOException { + outputStream.writeInt(tag.getValue()); + } + + @Override + public IntegerTag decode(NbtInputStream inputStream) throws IOException { + return new IntegerTag(inputStream.readInt()); + } +} diff --git a/src/main/java/mc/nbt/codec/ListTagCodec.java b/src/main/java/mc/nbt/codec/ListTagCodec.java new file mode 100644 index 0000000..23254c9 --- /dev/null +++ b/src/main/java/mc/nbt/codec/ListTagCodec.java @@ -0,0 +1,45 @@ +package mc.nbt.codec; + +import mc.nbt.ListTag; +import mc.nbt.TagType; +import mc.nbt.TagValue; +import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; + +import java.io.IOException; + +public class ListTagCodec implements Codec { + + @SuppressWarnings({"rawtypes", "unchecked"}) + @Override + public void encode(ListTag tag, NbtOutputStream outputStream) throws IOException { + outputStream.writeByte(tag.getListType().getId()); + outputStream.writeInt(tag.size()); + + Codec codec = CodecRegistry.getInstance().get(tag.getListType()); + for (TagValue tagValue : tag) { + codec.encode(tagValue, outputStream); + } + } + + @SuppressWarnings("rawtypes") + @Override + public ListTag decode(NbtInputStream inputStream) throws IOException { + int listTypeId = inputStream.readByte(); + TagType listType = TagType.valueOfId(listTypeId); + + int size = inputStream.readInt(); + ListTag list = new ListTag(listType, size); + + Codec codec = CodecRegistry.getInstance().get(listType); + + if (size > 0) { + for (int i = 0; i < size; i++) { + var tagValue = codec.decode(inputStream); + list.add(tagValue); + } + } + + return list; + } +} diff --git a/src/main/java/mc/nbt/codec/LongArrayTagCodec.java b/src/main/java/mc/nbt/codec/LongArrayTagCodec.java new file mode 100644 index 0000000..ac155d2 --- /dev/null +++ b/src/main/java/mc/nbt/codec/LongArrayTagCodec.java @@ -0,0 +1,30 @@ +package mc.nbt.codec; + +import mc.nbt.LongArrayTag; +import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; + +import java.io.IOException; + +public class LongArrayTagCodec implements Codec { + + @Override + public void encode(LongArrayTag tag, NbtOutputStream outputStream) throws IOException { + outputStream.writeInt(tag.getValue().length); + for (long value : tag.getValue()) { + outputStream.writeLong(value); + } + } + + @Override + public LongArrayTag decode(NbtInputStream inputStream) throws IOException { + int len = inputStream.readInt(); + long[] longs = new long[len]; + + for (int i = 0; i < len; i++) { + longs[i] = inputStream.readLong(); + } + + return new LongArrayTag(longs); + } +} diff --git a/src/main/java/mc/nbt/codec/LongTagCodec.java b/src/main/java/mc/nbt/codec/LongTagCodec.java new file mode 100644 index 0000000..d9f6dbb --- /dev/null +++ b/src/main/java/mc/nbt/codec/LongTagCodec.java @@ -0,0 +1,20 @@ +package mc.nbt.codec; + +import mc.nbt.LongTag; +import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; + +import java.io.IOException; + +public class LongTagCodec implements Codec { + + @Override + public void encode(LongTag tag, NbtOutputStream outputStream) throws IOException { + outputStream.writeLong(tag.getValue()); + } + + @Override + public LongTag decode(NbtInputStream inputStream) throws IOException { + return new LongTag(inputStream.readLong()); + } +} diff --git a/src/main/java/mc/nbt/codec/ShortTagCodec.java b/src/main/java/mc/nbt/codec/ShortTagCodec.java new file mode 100644 index 0000000..9cc3548 --- /dev/null +++ b/src/main/java/mc/nbt/codec/ShortTagCodec.java @@ -0,0 +1,20 @@ +package mc.nbt.codec; + +import mc.nbt.ShortTag; +import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; + +import java.io.IOException; + +public class ShortTagCodec implements Codec { + + @Override + public void encode(ShortTag tag, NbtOutputStream outputStream) throws IOException { + outputStream.writeShort(tag.getValue()); + } + + @Override + public ShortTag decode(NbtInputStream inputStream) throws IOException { + return new ShortTag(inputStream.readShort()); + } +} diff --git a/src/main/java/mc/nbt/codec/StringTagCodec.java b/src/main/java/mc/nbt/codec/StringTagCodec.java new file mode 100644 index 0000000..24ddeea --- /dev/null +++ b/src/main/java/mc/nbt/codec/StringTagCodec.java @@ -0,0 +1,19 @@ +package mc.nbt.codec; + +import mc.nbt.StringTag; +import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; + +import java.io.IOException; + +public class StringTagCodec implements Codec { + @Override + public void encode(StringTag tag, NbtOutputStream outputStream) throws IOException { + outputStream.writeString(tag.getValue()); + } + + @Override + public StringTag decode(NbtInputStream inputStream) throws IOException { + return new StringTag(inputStream.readString()); + } +} diff --git a/src/main/java/mc/nbt/internal/JacocoExcludeGeneratedReport.java b/src/main/java/mc/nbt/internal/JacocoExcludeGeneratedReport.java new file mode 100644 index 0000000..a669436 --- /dev/null +++ b/src/main/java/mc/nbt/internal/JacocoExcludeGeneratedReport.java @@ -0,0 +1,15 @@ +package mc.nbt.internal; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@Documented +@Retention(RUNTIME) +@Target({TYPE, METHOD}) +public @interface JacocoExcludeGeneratedReport { +} diff --git a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/io/NbtInputStream.java b/src/main/java/mc/nbt/io/NbtInputStream.java similarity index 58% rename from vanilla-codec/src/main/java/mc/nbt/codec/vanilla/io/NbtInputStream.java rename to src/main/java/mc/nbt/io/NbtInputStream.java index eec932f..0198b80 100644 --- a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/io/NbtInputStream.java +++ b/src/main/java/mc/nbt/io/NbtInputStream.java @@ -1,10 +1,10 @@ -package mc.nbt.codec.vanilla.io; +package mc.nbt.io; -import mc.nbt.TypeTag; -import mc.nbt.codec.vanilla.Codec; -import mc.nbt.codec.vanilla.CodecEnum; -import mc.nbt.tag.Tag; -import mc.nbt.tag.TagEnd; +import mc.nbt.EndTag; +import mc.nbt.TagType; +import mc.nbt.TagValue; +import mc.nbt.codec.Codec; +import mc.nbt.codec.CodecRegistry; import java.io.DataInputStream; import java.io.IOException; @@ -17,8 +17,7 @@ public class NbtInputStream extends InputStream { private final DataInputStream dataInputStream; public NbtInputStream(InputStream inputStream, boolean compressed) throws IOException { - this.dataInputStream = new DataInputStream( - compressed + this.dataInputStream = new DataInputStream(compressed ? new GZIPInputStream(inputStream) : inputStream); } @@ -27,19 +26,19 @@ public class NbtInputStream extends InputStream { this(inputStream, false); } - public Tag readTag() throws IOException { - final TypeTag typeTag = TypeTag.valueOfTypeId(read()); - if (typeTag == TypeTag.END) { - return TagEnd.INSTANCE; - } else { - final CodecEnum codecEnum = CodecEnum.valueOfTypeTag(typeTag); - final Codec codec = codecEnum.getCodec(); - final String name = readString(); - final Tag tag = codec.decode(this); - - tag.setName(name); - return tag; + @SuppressWarnings("rawtypes") + public TagValue readTag() throws IOException { + var tagType = TagType.valueOfId(read()); + if (tagType == TagType.END) { + return EndTag.getInstance(); } + + Codec codec = CodecRegistry.getInstance().get(tagType); + String name = readString(); + var tagValue = codec.decode(this); + + tagValue.setName(name); + return tagValue; } public byte readByte() throws IOException { @@ -58,20 +57,6 @@ public class NbtInputStream extends InputStream { return dataInputStream.readLong(); } - public String readString() throws IOException { - int length = readShort(); - if (length > 0) { - byte[] buff = new byte[length]; - if (read(buff, 0, length) < length) { - throw new IOException("Unexpected end of stream"); - } - - return new String(buff, StandardCharsets.UTF_8); - } else { - return ""; - } - } - public float readFloat() throws IOException { return dataInputStream.readFloat(); } @@ -80,6 +65,20 @@ public class NbtInputStream extends InputStream { return dataInputStream.readDouble(); } + public String readString() throws IOException { + int length = readShort(); + if (length <= 0) { + return ""; + } + + byte[] buff = new byte[length]; + if (read(buff, 0, length) < length) { + throw new IOException("Unexpected end of stream"); + } + + return new String(buff, StandardCharsets.UTF_8); + } + @Override public int read() throws IOException { return dataInputStream.read(); @@ -87,6 +86,6 @@ public class NbtInputStream extends InputStream { @Override public void close() throws IOException { - this.dataInputStream.close(); + dataInputStream.close(); } } diff --git a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/io/NbtOutputStream.java b/src/main/java/mc/nbt/io/NbtOutputStream.java similarity index 74% rename from vanilla-codec/src/main/java/mc/nbt/codec/vanilla/io/NbtOutputStream.java rename to src/main/java/mc/nbt/io/NbtOutputStream.java index f9b2bf6..1ea890d 100644 --- a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/io/NbtOutputStream.java +++ b/src/main/java/mc/nbt/io/NbtOutputStream.java @@ -1,9 +1,8 @@ -package mc.nbt.codec.vanilla.io; +package mc.nbt.io; -import mc.nbt.TypeTag; -import mc.nbt.codec.vanilla.Codec; -import mc.nbt.codec.vanilla.CodecEnum; -import mc.nbt.tag.Tag; +import mc.nbt.TagValue; +import mc.nbt.codec.Codec; +import mc.nbt.codec.CodecRegistry; import java.io.DataOutputStream; import java.io.IOException; @@ -16,8 +15,7 @@ public class NbtOutputStream extends OutputStream { private final DataOutputStream dataOutputStream; public NbtOutputStream(OutputStream outputStream, boolean compressed) throws IOException { - this.dataOutputStream = new DataOutputStream( - compressed + this.dataOutputStream = new DataOutputStream(compressed ? new GZIPOutputStream(outputStream) : outputStream); } @@ -26,16 +24,19 @@ public class NbtOutputStream extends OutputStream { this(outputStream, false); } - @SuppressWarnings("unchecked") - public void writeTag(Tag tag) throws IOException { - final TypeTag typeTag = tag.getType(); - final CodecEnum codecEnum = CodecEnum.valueOfTypeTag(typeTag); - final Codec codec = codecEnum.getCodec(); - writeByte(typeTag.getId()); - writeString(tag.getName()); + @SuppressWarnings({"unchecked", "rawtypes"}) + public void writeTag(String name, TagValue tagValue) throws IOException { + Codec codec = CodecRegistry.getInstance().get(tagValue.getType()); - codec.encode(tag, this); + writeByte(tagValue.getType().getId()); + writeString(name); + + codec.encode(tagValue, this); + } + + public void writeTag(TagValue tagValue) throws IOException { + writeTag(tagValue.getName(), tagValue); } public void writeByte(int value) throws IOException { @@ -54,6 +55,14 @@ public class NbtOutputStream extends OutputStream { dataOutputStream.writeLong(value); } + public void writeFloat(float value) throws IOException { + dataOutputStream.writeFloat(value); + } + + public void writeDouble(double value) throws IOException { + dataOutputStream.writeDouble(value); + } + public void writeString(String value) throws IOException { if (value == null || value.isEmpty()) { writeShort(0); @@ -63,14 +72,6 @@ public class NbtOutputStream extends OutputStream { } } - public void writeFloat(float value) throws IOException { - dataOutputStream.writeFloat(value); - } - - public void writeDouble(double value) throws IOException { - dataOutputStream.writeDouble(value); - } - @Override public void write(int b) throws IOException { dataOutputStream.write(b); diff --git a/src/test/java/mc/nbt/io/NbtInputStreamTest.java b/src/test/java/mc/nbt/io/NbtInputStreamTest.java new file mode 100644 index 0000000..08a578f --- /dev/null +++ b/src/test/java/mc/nbt/io/NbtInputStreamTest.java @@ -0,0 +1,38 @@ +package mc.nbt.io; + +import mc.nbt.CompoundTag; +import mc.nbt.StringTag; +import mc.nbt.TagType; +import mc.nbt.TagValue; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.Objects; + +import static org.junit.jupiter.api.Assertions.*; + +class NbtInputStreamTest { + + @Test + void testSimple() throws IOException { + try (var stream = Objects.requireNonNull(NbtInputStreamTest.class.getResourceAsStream("/hello_world.nbt")); + NbtInputStream nbtInputStream = new NbtInputStream(stream)) { + + TagValue tag = nbtInputStream.readTag(); + assertNotNull(tag); + assertEquals(TagType.COMPOUND, tag.getType()); + + CompoundTag compoundTag = tag.asCompound(); + assertEquals("hello world", compoundTag.getName()); + assertEquals(1, compoundTag.size()); + + assertTrue(compoundTag.containsKey("name")); + tag = compoundTag.get("name"); + assertEquals(TagType.STRING, tag.getType()); + + StringTag stringTag = tag.asString(); + assertEquals("name", stringTag.getName()); + assertEquals("Bananrama", stringTag.getValue()); + } + } +} \ No newline at end of file diff --git a/src/test/java/mc/nbt/io/NbtOutputStreamTest.java b/src/test/java/mc/nbt/io/NbtOutputStreamTest.java new file mode 100644 index 0000000..48c436d --- /dev/null +++ b/src/test/java/mc/nbt/io/NbtOutputStreamTest.java @@ -0,0 +1,381 @@ +package mc.nbt.io; + +import mc.nbt.*; +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.RandomUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.*; + +class NbtOutputStreamTest { + + ByteArrayOutputStream baos; + NbtOutputStream nbtOutputStream; + + @BeforeEach + void before() throws IOException { + baos = new ByteArrayOutputStream(); + nbtOutputStream = new NbtOutputStream(baos); + } + + @Test + void writeEndTag() throws IOException { + nbtOutputStream.writeTag(EndTag.getInstance()); + + try (var nbtInputStream = createNbtInputStream()) { + TagValue tag = nbtInputStream.readTag(); + assertEquals(TagType.END, tag.getType()); + assertNull(tag.getName()); + } + } + + @ParameterizedTest + @MethodSource("streamOfTagByte") + void writeByteTag(ByteTag byteTag) throws IOException { + nbtOutputStream.writeTag(byteTag); + + try (var nbtInputStream = createNbtInputStream()) { + TagValue tag = nbtInputStream.readTag(); + assertEquals(TagType.BYTE, tag.getType()); + assertEquals(byteTag.getValue(), tag.asByte().getValue()); + assertName(byteTag, tag); + } + } + + @ParameterizedTest + @MethodSource("streamOfTagShort") + void writeShortTag(ShortTag shortTag) throws IOException { + nbtOutputStream.writeTag(shortTag); + + try (var nbtInputStream = createNbtInputStream()) { + TagValue tag = nbtInputStream.readTag(); + assertEquals(TagType.SHORT, tag.getType()); + assertEquals(shortTag.getValue(), tag.asShort().getValue()); + assertName(shortTag, tag); + } + } + + @ParameterizedTest + @MethodSource("streamOfTagInt") + void writeIntegerTag(IntegerTag integerTag) throws IOException { + nbtOutputStream.writeTag(integerTag); + + try (var nbtInputStream = createNbtInputStream()) { + TagValue tag = nbtInputStream.readTag(); + assertEquals(TagType.INTEGER, tag.getType()); + assertEquals(integerTag.getValue(), tag.asInteger().getValue()); + assertName(integerTag, tag); + } + } + + @ParameterizedTest + @MethodSource("streamOfTagLong") + void writeLongTag(LongTag longTag) throws IOException { + nbtOutputStream.writeTag(longTag); + + try (var nbtInputStream = createNbtInputStream()) { + TagValue tag = nbtInputStream.readTag(); + assertEquals(TagType.LONG, tag.getType()); + assertEquals(longTag.getValue(), tag.asLong().getValue()); + assertName(longTag, tag); + } + } + + @ParameterizedTest + @MethodSource("streamOfTagFloat") + void writeFloatTag(FloatTag floatTag) throws IOException { + nbtOutputStream.writeTag(floatTag); + + try (var nbtInputStream = createNbtInputStream()) { + TagValue tag = nbtInputStream.readTag(); + assertEquals(TagType.FLOAT, tag.getType()); + assertEquals(floatTag.getValue(), tag.asFloat().getValue()); + assertName(floatTag, tag); + } + } + + @ParameterizedTest + @MethodSource("streamOfTagDouble") + void writeDoubleTag(DoubleTag doubleTag) throws IOException { + nbtOutputStream.writeTag(doubleTag); + + try (var nbtInputStream = createNbtInputStream()) { + TagValue tag = nbtInputStream.readTag(); + assertEquals(TagType.DOUBLE, tag.getType()); + assertEquals(doubleTag.getValue(), tag.asDouble().getValue()); + assertName(doubleTag, tag); + } + } + + @ParameterizedTest + @MethodSource("streamOfTagByteArray") + void writeByteArrayTag(ByteArrayTag byteArrayTag) throws IOException { + nbtOutputStream.writeTag(byteArrayTag); + + try (var nbtInputStream = createNbtInputStream()) { + TagValue tag = nbtInputStream.readTag(); + assertEquals(TagType.BYTE_ARRAY, tag.getType()); + assertArrayEquals(byteArrayTag.getValue(), tag.asByteArray().getValue()); + assertName(byteArrayTag, tag); + } + } + + @ParameterizedTest + @MethodSource("streamOfTagString") + void writeStringTag(StringTag stringTag) throws IOException { + nbtOutputStream.writeTag(stringTag); + + try (var nbtInputStream = createNbtInputStream()) { + TagValue tag = nbtInputStream.readTag(); + assertEquals(TagType.STRING, tag.getType()); + assertEquals(stringTag.getValue(), tag.asString().getValue()); + assertName(stringTag, tag); + } + } + + @ParameterizedTest + @MethodSource("streamOfTagList") + void writeListTag(ListTag listTag) throws IOException { + nbtOutputStream.writeTag(listTag); + + try (var nbtInputStream = createNbtInputStream()) { + TagValue tag = nbtInputStream.readTag(); + assertEquals(TagType.LIST, tag.getType()); + assertEquals(listTag.size(), tag.asList().size()); + assertEquals(listTag.getListType(), tag.asList().getListType()); + assertName(listTag, tag); + + for (int i = 0; i < listTag.size(); i++) { + LongTag longTag1 = listTag.get(i).asLong(); + LongTag longTag2 = tag.asList().get(i).asLong(); + + assertNull(longTag2.getName()); + assertEquals(longTag1.getValue(), longTag2.getValue()); + } + } + } + + @ParameterizedTest + @MethodSource("streamOfTagCompound") + void writeCompoundTag(CompoundTag compoundTag) throws IOException { + nbtOutputStream.writeTag(compoundTag); + + try (var nbtInputStream = createNbtInputStream()) { + TagValue tag = nbtInputStream.readTag(); + assertEquals(TagType.COMPOUND, tag.getType()); + assertEquals(compoundTag.size(), tag.asCompound().size()); + assertName(compoundTag, tag); + + for (int i = 0; i < compoundTag.size(); i++) { + compoundTag.forEach((key, tagValue) -> { + assertTrue(tag.asCompound().containsKey(key)); + + LongTag longTag1 = tagValue.asLong(); + LongTag longTag2 = tag.asCompound().get(key).asLong(); + + assertNotNull(longTag2.getName()); + assertEquals(longTag1.getValue(), longTag2.getValue()); + }); + } + } + } + + @ParameterizedTest + @MethodSource("streamOfTagIntArray") + void writeIntegerArrayTag(IntegerArrayTag integerArrayTag) throws IOException { + nbtOutputStream.writeTag(integerArrayTag); + + try (var nbtInputStream = createNbtInputStream()) { + TagValue tag = nbtInputStream.readTag(); + assertEquals(TagType.INTEGER_ARRAY, tag.getType()); + assertArrayEquals(integerArrayTag.getValue(), tag.asIntegerArray().getValue()); + assertName(integerArrayTag, tag); + } + } + + @ParameterizedTest + @MethodSource("streamOfTagLongArray") + void writeLongArrayTag(LongArrayTag longArrayTag) throws IOException { + nbtOutputStream.writeTag(longArrayTag); + + try (var nbtInputStream = createNbtInputStream()) { + TagValue tag = nbtInputStream.readTag(); + assertEquals(TagType.LONG_ARRAY, tag.getType()); + assertArrayEquals(longArrayTag.getValue(), tag.asLongArray().getValue()); + assertName(longArrayTag, tag); + } + } + + // region Methods for ParameterizedTest + // ------------------------------------------------------------------------------------------------------------- + + private static Stream streamOfTagByte() { + final byte value = RandomUtils.nextBytes(1)[0]; + + return Stream.of( + Arguments.of(new ByteTag(value)), + Arguments.of(new ByteTag(value) {{ + this.setName(randomString()); + }}) + ); + } + + private static Stream streamOfTagShort() { + final short value = (short) RandomUtils.nextInt(0, Short.MAX_VALUE); + + return Stream.of( + Arguments.of(new ShortTag(value)), + Arguments.of(new ShortTag(value) {{ + this.setName(randomString()); + }}) + ); + } + + private static Stream streamOfTagInt() { + final int value = RandomUtils.nextInt(); + + return Stream.of( + Arguments.of(new IntegerTag(value)), + Arguments.of(new IntegerTag(value) {{ + this.setName(randomString()); + }}) + ); + } + + private static Stream streamOfTagLong() { + final long value = RandomUtils.nextLong(); + + return Stream.of( + Arguments.of(new LongTag(value)), + Arguments.of(new LongTag(value) {{ + this.setName(randomString()); + }}) + ); + } + + private static Stream streamOfTagFloat() { + final float value = RandomUtils.nextFloat(); + + return Stream.of( + Arguments.of(new FloatTag(value)), + Arguments.of(new FloatTag(value) {{ + this.setName(randomString()); + }}) + ); + } + + private static Stream streamOfTagDouble() { + final double value = RandomUtils.nextDouble(); + + return Stream.of( + Arguments.of(new DoubleTag(value)), + Arguments.of(new DoubleTag(value) {{ + this.setName(randomString()); + }}) + ); + } + + private static Stream streamOfTagByteArray() { + final byte[] value = RandomUtils.nextBytes(RandomUtils.nextInt(1, 1000)); + + return Stream.of( + Arguments.of(new ByteArrayTag(value)), + Arguments.of(new ByteArrayTag(value) {{ + this.setName(randomString()); + }}) + ); + } + + private static Stream streamOfTagString() { + final String value = randomString(); + + return Stream.of( + Arguments.of(new StringTag(value)), + Arguments.of(new StringTag(value) {{ + this.setName(randomString()); + }}) + ); + } + + private static Stream streamOfTagList() { + return Stream.of( + Arguments.of(new ListTag(TagType.LONG).append(new LongTag(1L))), + Arguments.of(new ListTag(TagType.LONG) {{ + this.setName(randomString()); + }}.append(new LongTag(1L))) + ); + } + + private static Stream streamOfTagCompound() { + return Stream.of( + Arguments.of(new CompoundTag() + .append("TestName1", new LongTag(RandomUtils.nextLong())) + .append("TestName2", new LongTag(RandomUtils.nextLong())) + .append("TestName3", new LongTag(RandomUtils.nextLong()))), + Arguments.of(new CompoundTag() {{ + this.setName(randomString()); + }} + .append("TestName1", new LongTag(RandomUtils.nextLong())) + .append("TestName2", new LongTag(RandomUtils.nextLong())) + .append("TestName3", new LongTag(RandomUtils.nextLong()))) + ); + } + + private static Stream streamOfTagIntArray() { + final int[] value = new int[RandomUtils.nextInt(1, 1000)]; + + for (int i = 0; i < value.length; i++) { + value[i] = RandomUtils.nextInt(); + } + + return Stream.of( + Arguments.of(new IntegerArrayTag(value)), + Arguments.of(new IntegerArrayTag(value) {{ + this.setName(randomString()); + }}) + ); + } + + private static Stream streamOfTagLongArray() { + final long[] value = new long[RandomUtils.nextInt(1, 1000)]; + + for (int i = 0; i < value.length; i++) { + value[i] = RandomUtils.nextLong(); + } + + return Stream.of( + Arguments.of(new LongArrayTag(value)), + Arguments.of(new LongArrayTag(value) {{ + this.setName(randomString()); + }}) + ); + } + + // ------------------------------------------------------------------------------------------------------------- + // endregion + + private NbtInputStream createNbtInputStream() throws IOException { + return new NbtInputStream(new ByteArrayInputStream(baos.toByteArray())); + } + + private static String randomString() { + return RandomStringUtils.randomAscii(RandomUtils.nextInt(1, Short.MAX_VALUE)); + } + + private void assertName(TagValue expectedTag, TagValue actualTag) { + if (expectedTag.getName() == null) { + assertTrue(actualTag.getName().isEmpty()); + } else { + assertEquals(expectedTag.getName(), actualTag.getName()); + } + } +} \ No newline at end of file diff --git a/vanilla-codec/src/test/resources/hello_world.nbt b/src/test/resources/hello_world.nbt similarity index 100% rename from vanilla-codec/src/test/resources/hello_world.nbt rename to src/test/resources/hello_world.nbt diff --git a/vanilla-codec/build.gradle b/vanilla-codec/build.gradle deleted file mode 100644 index 957954f..0000000 --- a/vanilla-codec/build.gradle +++ /dev/null @@ -1,3 +0,0 @@ -dependencies { - compile project(':nbt') -} \ No newline at end of file diff --git a/vanilla-codec/gradle.properties b/vanilla-codec/gradle.properties deleted file mode 100644 index 20f8291..0000000 --- a/vanilla-codec/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -projectGroup=mc-project.nbt.codec -projectName=nbt-vanilla-codec \ No newline at end of file diff --git a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/Codec.java b/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/Codec.java deleted file mode 100644 index a149cf6..0000000 --- a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/Codec.java +++ /dev/null @@ -1,13 +0,0 @@ -package mc.nbt.codec.vanilla; - -import mc.nbt.codec.vanilla.io.NbtInputStream; -import mc.nbt.codec.vanilla.io.NbtOutputStream; -import mc.nbt.tag.Tag; - -import java.io.IOException; - -public interface Codec { - - T decode(NbtInputStream in) throws IOException; - void encode(T tag, NbtOutputStream out) throws IOException; -} diff --git a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/CodecEnum.java b/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/CodecEnum.java deleted file mode 100644 index 7057d8e..0000000 --- a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/CodecEnum.java +++ /dev/null @@ -1,36 +0,0 @@ -package mc.nbt.codec.vanilla; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import mc.nbt.TypeTag; - -import java.util.stream.Stream; - -@RequiredArgsConstructor -@Getter -public enum CodecEnum { - - END(TypeTag.END, new TagEndCodec()), - BYTE(TypeTag.BYTE, new TagByteCodec()), - SHORT(TypeTag.SHORT, new TagShortCodec()), - INT(TypeTag.INT, new TagIntCodec()), - LONG(TypeTag.LONG, new TagLongCodec()), - FLOAT(TypeTag.FLOAT, new TagFloatCodec()), - DOUBLE(TypeTag.DOUBLE, new TagDoubleCodec()), - BYTE_ARRAY(TypeTag.BYTE_ARRAY, new TagByteArrayCodec()), - STRING(TypeTag.STRING, new TagStringCodec()), - LIST(TypeTag.LIST, new TagListCodec()), - COMPOUND(TypeTag.COMPOUND, new TagCompoundCodec()), - INT_ARRAY(TypeTag.INT_ARRAY, new TagIntArrayCodec()), - LONG_ARRAY(TypeTag.LONG_ARRAY, new TagLongArrayCodec()); - - public static CodecEnum valueOfTypeTag(TypeTag typeTag) { - return Stream.of(CodecEnum.values()) - .filter(codecEnum -> codecEnum.getTypeTag() == typeTag) - .findFirst() - .orElseThrow(() -> new RuntimeException("Codec for " + typeTag.name() + " not found")); - } - - private final TypeTag typeTag; - private final Codec codec; -} diff --git a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagByteArrayCodec.java b/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagByteArrayCodec.java deleted file mode 100644 index f1db556..0000000 --- a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagByteArrayCodec.java +++ /dev/null @@ -1,23 +0,0 @@ -package mc.nbt.codec.vanilla; - -import mc.nbt.codec.vanilla.io.NbtInputStream; -import mc.nbt.codec.vanilla.io.NbtOutputStream; -import mc.nbt.tag.TagByteArray; - -import java.io.IOException; - -class TagByteArrayCodec implements Codec { - - @Override - public TagByteArray decode(NbtInputStream in) throws IOException { - byte[] value = new byte[in.readInt()]; - in.read(value); - return new TagByteArray(value); - } - - @Override - public void encode(TagByteArray tag, NbtOutputStream out) throws IOException { - out.writeInt(tag.getValue().length); - out.write(tag.getValue()); - } -} diff --git a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagByteCodec.java b/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagByteCodec.java deleted file mode 100644 index fd3dd0c..0000000 --- a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagByteCodec.java +++ /dev/null @@ -1,20 +0,0 @@ -package mc.nbt.codec.vanilla; - -import mc.nbt.codec.vanilla.io.NbtInputStream; -import mc.nbt.codec.vanilla.io.NbtOutputStream; -import mc.nbt.tag.TagByte; - -import java.io.IOException; - -class TagByteCodec implements Codec { - - @Override - public TagByte decode(NbtInputStream in) throws IOException { - return new TagByte(in.readByte()); - } - - @Override - public void encode(TagByte tag, NbtOutputStream out) throws IOException { - out.writeByte(tag.getValue()); - } -} diff --git a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagCompoundCodec.java b/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagCompoundCodec.java deleted file mode 100644 index 23347cb..0000000 --- a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagCompoundCodec.java +++ /dev/null @@ -1,42 +0,0 @@ -package mc.nbt.codec.vanilla; - -import mc.nbt.TypeTag; -import mc.nbt.codec.vanilla.io.NbtInputStream; -import mc.nbt.codec.vanilla.io.NbtOutputStream; -import mc.nbt.tag.Tag; -import mc.nbt.tag.TagCompound; -import mc.nbt.tag.TagEnd; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -class TagCompoundCodec implements Codec { - - @Override - public TagCompound decode(NbtInputStream in) throws IOException { - List tagList = new ArrayList<>(); - - while (true) { - Tag tag = in.readTag(); - if (tag.getType() == TypeTag.END) { - break; - } - - tagList.add(tag); - } - - TagCompound tagCompound = new TagCompound(); - tagCompound.setValue(tagList); - return tagCompound; - } - - @Override - public void encode(TagCompound tag, NbtOutputStream out) throws IOException { - for (Tag itemTag : tag.getValue()) { - out.writeTag(itemTag); - } - - out.writeTag(TagEnd.INSTANCE); - } -} diff --git a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagDoubleCodec.java b/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagDoubleCodec.java deleted file mode 100644 index 590da4b..0000000 --- a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagDoubleCodec.java +++ /dev/null @@ -1,20 +0,0 @@ -package mc.nbt.codec.vanilla; - -import mc.nbt.codec.vanilla.io.NbtInputStream; -import mc.nbt.codec.vanilla.io.NbtOutputStream; -import mc.nbt.tag.TagDouble; - -import java.io.IOException; - -public class TagDoubleCodec implements Codec { - - @Override - public TagDouble decode(NbtInputStream in) throws IOException { - return new TagDouble(in.readDouble()); - } - - @Override - public void encode(TagDouble tag, NbtOutputStream out) throws IOException { - out.writeDouble(tag.getValue()); - } -} diff --git a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagEndCodec.java b/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagEndCodec.java deleted file mode 100644 index 2e7cf5b..0000000 --- a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagEndCodec.java +++ /dev/null @@ -1,18 +0,0 @@ -package mc.nbt.codec.vanilla; - -import mc.nbt.codec.vanilla.io.NbtInputStream; -import mc.nbt.codec.vanilla.io.NbtOutputStream; -import mc.nbt.tag.TagEnd; - -class TagEndCodec implements Codec { - - @Override - public TagEnd decode(NbtInputStream in) { - return TagEnd.INSTANCE; - } - - @Override - public void encode(TagEnd tag, NbtOutputStream out) { - //nothing - } -} diff --git a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagFloatCodec.java b/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagFloatCodec.java deleted file mode 100644 index dc35195..0000000 --- a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagFloatCodec.java +++ /dev/null @@ -1,20 +0,0 @@ -package mc.nbt.codec.vanilla; - -import mc.nbt.codec.vanilla.io.NbtInputStream; -import mc.nbt.codec.vanilla.io.NbtOutputStream; -import mc.nbt.tag.TagFloat; - -import java.io.IOException; - -public class TagFloatCodec implements Codec { - - @Override - public TagFloat decode(NbtInputStream in) throws IOException { - return new TagFloat(in.readFloat()); - } - - @Override - public void encode(TagFloat tag, NbtOutputStream out) throws IOException { - out.writeFloat(tag.getValue()); - } -} diff --git a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagIntArrayCodec.java b/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagIntArrayCodec.java deleted file mode 100644 index adccd4b..0000000 --- a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagIntArrayCodec.java +++ /dev/null @@ -1,29 +0,0 @@ -package mc.nbt.codec.vanilla; - -import mc.nbt.codec.vanilla.io.NbtInputStream; -import mc.nbt.codec.vanilla.io.NbtOutputStream; -import mc.nbt.tag.TagIntArray; - -import java.io.IOException; - -public class TagIntArrayCodec implements Codec { - - @Override - public TagIntArray decode(NbtInputStream in) throws IOException { - final int[] value = new int[in.readInt()]; - - for (int i = 0; i < value.length; i++) { - value[i] = in.readInt(); - } - - return new TagIntArray(value); - } - - @Override - public void encode(TagIntArray tag, NbtOutputStream out) throws IOException { - out.writeInt(tag.getValue().length); - for (int item : tag.getValue()) { - out.writeInt(item); - } - } -} diff --git a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagIntCodec.java b/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagIntCodec.java deleted file mode 100644 index ee4ad29..0000000 --- a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagIntCodec.java +++ /dev/null @@ -1,20 +0,0 @@ -package mc.nbt.codec.vanilla; - -import mc.nbt.codec.vanilla.io.NbtInputStream; -import mc.nbt.codec.vanilla.io.NbtOutputStream; -import mc.nbt.tag.TagInt; - -import java.io.IOException; - -class TagIntCodec implements Codec { - - @Override - public TagInt decode(NbtInputStream in) throws IOException { - return new TagInt(in.readInt()); - } - - @Override - public void encode(TagInt tag, NbtOutputStream out) throws IOException { - out.writeInt(tag.getValue()); - } -} diff --git a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagListCodec.java b/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagListCodec.java deleted file mode 100644 index 5b952cb..0000000 --- a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagListCodec.java +++ /dev/null @@ -1,46 +0,0 @@ -package mc.nbt.codec.vanilla; - -import mc.nbt.TypeTag; -import mc.nbt.codec.vanilla.io.NbtInputStream; -import mc.nbt.codec.vanilla.io.NbtOutputStream; -import mc.nbt.tag.Tag; -import mc.nbt.tag.TagList; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class TagListCodec implements Codec { - - @Override - public TagList decode(NbtInputStream in) throws IOException { - final Codec typeCodec = CodecEnum.valueOfTypeTag(TypeTag.valueOfTypeId(in.readByte())).getCodec(); - final int size = in.readInt(); - - List tagList; - if (size > 0) { - tagList = new ArrayList<>(size); - - for (int i = 0; i < size; i++) { - tagList.add(typeCodec.decode(in)); - } - } else { - tagList = Collections.emptyList(); - } - - return new TagList(tagList); - } - - @SuppressWarnings("unchecked") - @Override - public void encode(TagList tag, NbtOutputStream out) throws IOException { - out.writeByte(tag.getTypeList().getId()); - out.writeInt(tag.getValue().size()); - - final Codec typeCodec = CodecEnum.valueOfTypeTag(tag.getTypeList()).getCodec(); - for (Tag item : tag.getValue()) { - typeCodec.encode(item, out); - } - } -} diff --git a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagLongArrayCodec.java b/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagLongArrayCodec.java deleted file mode 100644 index 4354cf4..0000000 --- a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagLongArrayCodec.java +++ /dev/null @@ -1,29 +0,0 @@ -package mc.nbt.codec.vanilla; - -import mc.nbt.codec.vanilla.io.NbtInputStream; -import mc.nbt.codec.vanilla.io.NbtOutputStream; -import mc.nbt.tag.TagLongArray; - -import java.io.IOException; - -public class TagLongArrayCodec implements Codec { - - @Override - public TagLongArray decode(NbtInputStream in) throws IOException { - final long[] value = new long[in.readInt()]; - - for (int i = 0; i < value.length; i++) { - value[i] = in.readLong(); - } - - return new TagLongArray(value); - } - - @Override - public void encode(TagLongArray tag, NbtOutputStream out) throws IOException { - out.writeInt(tag.getValue().length); - for (long item : tag.getValue()) { - out.writeLong(item); - } - } -} diff --git a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagLongCodec.java b/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagLongCodec.java deleted file mode 100644 index af62964..0000000 --- a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagLongCodec.java +++ /dev/null @@ -1,21 +0,0 @@ -package mc.nbt.codec.vanilla; - -import mc.nbt.codec.vanilla.io.NbtInputStream; -import mc.nbt.codec.vanilla.io.NbtOutputStream; -import mc.nbt.tag.TagLong; - -import java.io.IOException; - -public class TagLongCodec implements Codec { - - @Override - public TagLong decode(NbtInputStream in) throws IOException { - long value = in.readLong(); - return new TagLong(value); - } - - @Override - public void encode(TagLong tag, NbtOutputStream out) throws IOException { - out.writeLong(tag.getValue()); - } -} diff --git a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagShortCodec.java b/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagShortCodec.java deleted file mode 100644 index 93adbdf..0000000 --- a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagShortCodec.java +++ /dev/null @@ -1,20 +0,0 @@ -package mc.nbt.codec.vanilla; - -import mc.nbt.codec.vanilla.io.NbtInputStream; -import mc.nbt.codec.vanilla.io.NbtOutputStream; -import mc.nbt.tag.TagShort; - -import java.io.IOException; - -class TagShortCodec implements Codec { - - @Override - public TagShort decode(NbtInputStream in) throws IOException { - return new TagShort(in.readShort()); - } - - @Override - public void encode(TagShort tag, NbtOutputStream out) throws IOException { - out.writeShort(tag.getValue()); - } -} diff --git a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagStringCodec.java b/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagStringCodec.java deleted file mode 100644 index 87897c4..0000000 --- a/vanilla-codec/src/main/java/mc/nbt/codec/vanilla/TagStringCodec.java +++ /dev/null @@ -1,20 +0,0 @@ -package mc.nbt.codec.vanilla; - -import mc.nbt.codec.vanilla.io.NbtInputStream; -import mc.nbt.codec.vanilla.io.NbtOutputStream; -import mc.nbt.tag.TagString; - -import java.io.IOException; - -public class TagStringCodec implements Codec { - - @Override - public TagString decode(NbtInputStream in) throws IOException { - return new TagString(in.readString()); - } - - @Override - public void encode(TagString tag, NbtOutputStream out) throws IOException { - out.writeString(tag.getValue()); - } -} diff --git a/vanilla-codec/src/test/java/mc/nbt/codec/vanilla/io/NbtInputStreamTest.java b/vanilla-codec/src/test/java/mc/nbt/codec/vanilla/io/NbtInputStreamTest.java deleted file mode 100644 index c31b2cf..0000000 --- a/vanilla-codec/src/test/java/mc/nbt/codec/vanilla/io/NbtInputStreamTest.java +++ /dev/null @@ -1,203 +0,0 @@ -package mc.nbt.codec.vanilla.io; - -import mc.nbt.TypeTag; -import mc.nbt.tag.*; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Iterator; - -import static org.junit.jupiter.api.Assertions.*; - -//TODO необходимо добавить тесты для INT_ARRAY и LONG_ARRAY -class NbtInputStreamTest { - - @Test - void testSimple() throws IOException { - InputStream stream = NbtInputStreamTest.class.getResourceAsStream("/hello_world.nbt"); - assertNotNull(stream); - - NbtInputStream nbtInputStream = new NbtInputStream(stream); - Tag tag = nbtInputStream.readTag(); - assertNotNull(tag); - assertEquals(TypeTag.COMPOUND, tag.getType()); - - TagCompound tagCompound = tag.asTagCompound(); - assertEquals("hello world", tagCompound.getName()); - assertEquals(1, tagCompound.getValue().size()); - - tag = tagCompound.getValue().get(0); - assertEquals(TypeTag.STRING, tag.getType()); - - TagString tagString = tag.asTagString(); - assertEquals("name", tagString.getName()); - assertEquals("Bananrama", tagString.getValue()); - } - - @Test - void testGZipped() throws IOException { - InputStream stream = NbtInputStreamTest.class.getResourceAsStream("/bigtest.nbt"); - assertNotNull(stream); - - NbtInputStream nbtInputStream = new NbtInputStream(stream, true); - Tag tag = nbtInputStream.readTag(); - assertNotNull(tag); - assertEquals(TypeTag.COMPOUND, tag.getType()); - - TagCompound tagCompound = tag.asTagCompound(); - assertEquals("Level", tagCompound.getName()); - assertEquals(11, tagCompound.getValue().size()); - - tagCompound.getValue().forEach(tag1 -> { - switch (tag1.getType()) { - case BYTE: testTagByte(tag1.asTagByte()); break; - case SHORT: testTagShort(tag1.asTagShort()); break; - case INT: testTagInt(tag1.asTagInt()); break; - case LONG: testTagLong(tag1.asTagLong()); break; - case FLOAT: testTagFloat(tag1.asTagFloat()); break; - case DOUBLE: testTagDouble(tag1.asTagDouble()); break; - case BYTE_ARRAY: testTagByteArray(tag1.asTagByteArray()); break; - case STRING: testTagString(tag1.asTagString()); break; - case LIST: testTagList(tag1.asTagList()); break; - case COMPOUND: testTagCompound(tag1.asTagCompound()); break; - } - }); - } - - private void testTagByte(TagByte tag) { - assertEquals("byteTest", tag.getName()); - assertEquals(Byte.MAX_VALUE, tag.getValue()); - } - - private void testTagShort(TagShort tag) { - assertEquals("shortTest", tag.getName()); - assertEquals(Short.MAX_VALUE, tag.getValue()); - } - - private void testTagInt(TagInt tag) { - assertEquals("intTest", tag.getName()); - assertEquals(Integer.MAX_VALUE, tag.getValue()); - } - - private void testTagLong(TagLong tag) { - assertEquals("longTest", tag.getName()); - assertEquals(Long.MAX_VALUE, tag.getValue()); - } - - private void testTagFloat(TagFloat tag) { - assertEquals("floatTest", tag.getName()); - assertEquals(0.49823147058486938f, tag.getValue()); - } - - private void testTagDouble(TagDouble tag) { - assertEquals("doubleTest", tag.getName()); - assertEquals(0.49312871321823148d, tag.getValue()); - } - - private void testTagByteArray(TagByteArray tag) { - assertEquals("byteArrayTest " + - "(the first 1000 values of (n*n*255+n*7)%100, " + - "starting with n=0 (0, 62, 34, 16, 8, ...))", tag.getName()); - assertEquals(1000, tag.getValue().length); - - for (int n = 0; n < tag.getValue().length; n++) { - assertEquals((n * n * 255 + n * 7) % 100, tag.getValue()[n]); - } - } - - private void testTagString(TagString tag) { - assertEquals("stringTest", tag.getName()); - assertEquals("HELLO WORLD THIS IS A TEST STRING \305\304\326!", tag.getValue()); - } - - private void testTagList(TagList tag) { - if (tag.getName().equals("listTest (long)")) { - testTagListLong(tag); - } else if (tag.getName().equals("listTest (compound)")) { - testTagListCompound(tag); - } else { - fail("Unknown TagList(name=" + tag.getName() + ")"); - } - } - - private void testTagListLong(TagList tag) { - assertEquals(TypeTag.LONG, tag.getTypeList()); - assertEquals(5, tag.getValue().size()); - - Iterator iterator = tag.getValue().iterator(); - for(int n = 11; n <= 15 && iterator.hasNext(); n++) { - assertEquals(n, iterator.next().asTagLong().getValue()); - } - } - - private void testTagListCompound(TagList tag) { - assertEquals(TypeTag.COMPOUND, tag.getTypeList()); - assertEquals(2, tag.getValue().size()); - - { - TagCompound tagCompound = tag.getValue().get(0).asTagCompound(); - assertNull(tagCompound.getName()); - assertEquals(2, tagCompound.getValue().size()); - - TagString tagString = tagCompound.getValue().get(0).asTagString(); - assertEquals("name", tagString.getName()); - assertEquals("Compound tag #0", tagString.getValue()); - - TagLong tagLong = tagCompound.getValue().get(1).asTagLong(); - assertEquals("created-on", tagLong.getName()); - assertEquals(1264099775885L, tagLong.getValue()); - } - - { - TagCompound tagCompound = tag.getValue().get(1).asTagCompound(); - assertNull(tagCompound.getName()); - assertEquals(2, tagCompound.getValue().size()); - - TagString tagString = tagCompound.getValue().get(0).asTagString(); - assertEquals("name", tagString.getName()); - assertEquals("Compound tag #1", tagString.getValue()); - - TagLong tagLong = tagCompound.getValue().get(1).asTagLong(); - assertEquals("created-on", tagLong.getName()); - assertEquals(1264099775885L, tagLong.getValue()); - } - } - - private void testTagCompound(TagCompound tag) { - assertEquals("nested compound test", tag.getName()); - assertEquals(2, tag.getValue().size()); - - { - TagCompound tagCompound = tag.getValue().get(0).asTagCompound(); - assertEquals("ham", tagCompound.getName()); - assertEquals(2, tagCompound.getValue().size()); - - { - TagString tagString = tagCompound.getValue().get(0).asTagString(); - assertEquals("name", tagString.getName()); - assertEquals("Hampus", tagString.getValue()); - - TagFloat tagFloat = tagCompound.getValue().get(1).asTagFloat(); - assertEquals("value", tagFloat.getName()); - assertEquals(0.75f, tagFloat.getValue()); - } - } - - { - TagCompound tagCompound = tag.getValue().get(1).asTagCompound(); - assertEquals("egg", tagCompound.getName()); - assertEquals(2, tagCompound.getValue().size()); - - { - TagString tagString = tagCompound.getValue().get(0).asTagString(); - assertEquals("name", tagString.getName()); - assertEquals("Eggbert", tagString.getValue()); - - TagFloat tagFloat = tagCompound.getValue().get(1).asTagFloat(); - assertEquals("value", tagFloat.getName()); - assertEquals(0.5f, tagFloat.getValue()); - } - } - } -} diff --git a/vanilla-codec/src/test/java/mc/nbt/codec/vanilla/io/NbtOutputStreamCompressedTest.java b/vanilla-codec/src/test/java/mc/nbt/codec/vanilla/io/NbtOutputStreamCompressedTest.java deleted file mode 100644 index c616833..0000000 --- a/vanilla-codec/src/test/java/mc/nbt/codec/vanilla/io/NbtOutputStreamCompressedTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package mc.nbt.codec.vanilla.io; - -import mc.nbt.TypeTag; -import mc.nbt.tag.Tag; -import mc.nbt.tag.TagLong; -import org.apache.commons.lang3.RandomUtils; -import org.junit.jupiter.api.Test; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -class NbtOutputStreamCompressedTest { - - @Test - void testWriteCompressed() throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - NbtOutputStream nbtOutputStream = new NbtOutputStream(baos, true); - - TagLong tagLong = new TagLong("Test compressed stream", RandomUtils.nextLong()); - nbtOutputStream.writeTag(tagLong); - nbtOutputStream.close(); - - NbtInputStream nbtInputStream = new NbtInputStream(new ByteArrayInputStream(baos.toByteArray()), true); - Tag tag = nbtInputStream.readTag(); - - assertEquals(TypeTag.LONG, tag.getType()); - assertEquals(tagLong.getName(), tag.getName()); - assertEquals(tagLong.getValue(), tag.asTagLong().getValue()); - } -} diff --git a/vanilla-codec/src/test/java/mc/nbt/codec/vanilla/io/NbtOutputStreamTest.java b/vanilla-codec/src/test/java/mc/nbt/codec/vanilla/io/NbtOutputStreamTest.java deleted file mode 100644 index ab408ab..0000000 --- a/vanilla-codec/src/test/java/mc/nbt/codec/vanilla/io/NbtOutputStreamTest.java +++ /dev/null @@ -1,332 +0,0 @@ -package mc.nbt.codec.vanilla.io; - -import mc.nbt.TypeTag; -import mc.nbt.tag.*; -import org.apache.commons.lang3.RandomStringUtils; -import org.apache.commons.lang3.RandomUtils; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.*; - -class NbtOutputStreamTest { - - private ByteArrayOutputStream baos; - private NbtOutputStream nbtOutputStream; - - @BeforeEach - void before() throws IOException { - baos = new ByteArrayOutputStream(); - nbtOutputStream = new NbtOutputStream(baos); - } - - @Test - void testWriteTagEnd() throws IOException { - nbtOutputStream.writeTag(TagEnd.INSTANCE); - - Tag tag = createNbtInputStream().readTag(); - assertEquals(TypeTag.END, tag.getType()); - assertNull(tag.getName()); - } - - private static Stream streamOfTagByte() { - final byte value = RandomUtils.nextBytes(1)[0]; - - return Stream.of( - Arguments.of(new TagByte(value)), - Arguments.of(new TagByte(randomString(), value)) - ); - } - - @ParameterizedTest - @MethodSource("streamOfTagByte") - void testWriteTagByte(TagByte tagByte) throws IOException { - nbtOutputStream.writeTag(tagByte); - - Tag tag = createNbtInputStream().readTag(); - assertEquals(TypeTag.BYTE, tag.getType()); - assertEquals(tagByte.getValue(), tag.asTagByte().getValue()); - assertName(tagByte, tag); - } - - private static Stream streamOfTagShort() { - final short value = (short) RandomUtils.nextInt(0, Short.MAX_VALUE); - - return Stream.of( - Arguments.of(new TagShort(value)), - Arguments.of(new TagShort(randomString(), value)) - ); - } - - @ParameterizedTest - @MethodSource("streamOfTagShort") - void testWriteTagShort(TagShort tagShort) throws IOException { - nbtOutputStream.writeTag(tagShort); - - Tag tag = createNbtInputStream().readTag(); - assertEquals(TypeTag.SHORT, tag.getType()); - assertEquals(tagShort.getValue(), tag.asTagShort().getValue()); - assertName(tagShort, tag); - } - - private static Stream streamOfTagInt() { - final int value = RandomUtils.nextInt(); - - return Stream.of( - Arguments.of(new TagInt(value)), - Arguments.of(new TagInt(randomString(), value)) - ); - } - - @ParameterizedTest - @MethodSource("streamOfTagInt") - void testWriteTagInt(TagInt tagInt) throws IOException { - nbtOutputStream.writeTag(tagInt); - - Tag tag = createNbtInputStream().readTag(); - assertEquals(TypeTag.INT, tag.getType()); - assertEquals(tagInt.getValue(), tag.asTagInt().getValue()); - assertName(tagInt, tag); - } - - private static Stream streamOfTagLong() { - final long value = RandomUtils.nextLong(); - - return Stream.of( - Arguments.of(new TagLong(value)), - Arguments.of(new TagLong(randomString(), value)) - ); - } - - @ParameterizedTest - @MethodSource("streamOfTagLong") - void testWriteTagLong(TagLong tagLong) throws IOException { - nbtOutputStream.writeTag(tagLong); - - Tag tag = createNbtInputStream().readTag(); - assertEquals(TypeTag.LONG, tag.getType()); - assertEquals(tagLong.getValue(), tag.asTagLong().getValue()); - assertName(tagLong, tag); - } - - private static Stream streamOfTagFloat() { - final float value = RandomUtils.nextFloat(); - - return Stream.of( - Arguments.of(new TagFloat(value)), - Arguments.of(new TagFloat(randomString(), value)) - ); - } - - @ParameterizedTest - @MethodSource("streamOfTagFloat") - void testWriteTagFloat(TagFloat tagFloat) throws IOException { - nbtOutputStream.writeTag(tagFloat); - - Tag tag = createNbtInputStream().readTag(); - assertEquals(TypeTag.FLOAT, tag.getType()); - assertEquals(tagFloat.getValue(), tag.asTagFloat().getValue()); - assertName(tagFloat, tag); - } - - private static Stream streamOfTagDouble() { - final double value = RandomUtils.nextDouble(); - - return Stream.of( - Arguments.of(new TagDouble(value)), - Arguments.of(new TagDouble(randomString(), value)) - ); - } - - @ParameterizedTest - @MethodSource("streamOfTagDouble") - void testWriteTagDouble(TagDouble tagDouble) throws IOException { - nbtOutputStream.writeTag(tagDouble); - - Tag tag = createNbtInputStream().readTag(); - assertEquals(TypeTag.DOUBLE, tag.getType()); - assertEquals(tagDouble.getValue(), tag.asTagDouble().getValue()); - assertName(tagDouble, tag); - } - - private static Stream streamOfTagByteArray() { - final byte[] value = RandomUtils.nextBytes(RandomUtils.nextInt(1, 1000)); - - return Stream.of( - Arguments.of(new TagByteArray(value)), - Arguments.of(new TagByteArray(randomString(), value)) - ); - } - - @ParameterizedTest - @MethodSource("streamOfTagByteArray") - void testWriteTagByteArray(TagByteArray tagByteArray) throws IOException { - nbtOutputStream.writeTag(tagByteArray); - - Tag tag = createNbtInputStream().readTag(); - assertEquals(TypeTag.BYTE_ARRAY, tag.getType()); - assertArrayEquals(tagByteArray.getValue(), tag.asTagByteArray().getValue()); - assertName(tagByteArray, tag); - } - - private static Stream streamOfTagString() { - final String value = randomString(); - - return Stream.of( - Arguments.of(new TagString(value)), - Arguments.of(new TagString(randomString(), value)) - ); - } - - @ParameterizedTest - @MethodSource("streamOfTagString") - void testWriteTagString(TagString tagString) throws IOException { - nbtOutputStream.writeTag(tagString); - - Tag tag = createNbtInputStream().readTag(); - assertEquals(TypeTag.STRING, tag.getType()); - assertEquals(tagString.getValue(), tag.asTagString().getValue()); - assertName(tagString, tag); - } - - private static Stream streamOfTagList() { - final List value = new ArrayList<>(); -// value.add(new TagLong("TestName", RandomUtils.nextLong())); -// value.add(new TagLong(RandomUtils.nextLong())); -// value.add(new TagLong(RandomUtils.nextLong())); -// value.add(new TagLong(RandomUtils.nextLong())); - value.add(new TagLong(1L)); - - return Stream.of( - Arguments.of(new TagList(value)), - Arguments.of(new TagList(randomString(), value)) - ); - } - - @ParameterizedTest - @MethodSource("streamOfTagList") - void testWriteTagList(TagList tagList) throws IOException { - nbtOutputStream.writeTag(tagList); - - Tag tag = createNbtInputStream().readTag(); - assertEquals(TypeTag.LIST, tag.getType()); - assertEquals(tagList.getValue().size(), tag.asTagList().getValue().size()); - assertEquals(tagList.getTypeList(), tag.asTagList().getTypeList()); - assertName(tagList, tag); - - for (int i = 0; i < tagList.getValue().size(); i++) { - TagLong tagLong1 = tagList.getValue().get(i).asTagLong(); - TagLong tagLong2 = tag.asTagList().getValue().get(i).asTagLong(); - - assertNull(tagLong2.getName()); - assertEquals(tagLong1.getValue(), tagLong2.getValue()); - } - } - - private static Stream streamOfTagCompound() { - final List value = new ArrayList<>(); - value.add(new TagLong("TestName1", RandomUtils.nextLong())); - value.add(new TagLong(RandomUtils.nextLong())); - value.add(new TagLong("TestName3",RandomUtils.nextLong())); - value.add(new TagLong(RandomUtils.nextLong())); - - return Stream.of( - Arguments.of(new TagCompound(value)), - Arguments.of(new TagCompound(randomString(), value)) - ); - } - - @ParameterizedTest - @MethodSource("streamOfTagCompound") - void testWriteTagCompound(TagCompound tagCompound) throws IOException { - nbtOutputStream.writeTag(tagCompound); - - Tag tag = createNbtInputStream().readTag(); - assertEquals(TypeTag.COMPOUND, tag.getType()); - assertEquals(tagCompound.getValue().size(), tag.asTagCompound().getValue().size()); - assertName(tagCompound, tag); - - for (int i = 0; i < tagCompound.getValue().size(); i++) { - TagLong tagLong1 = tagCompound.getValue().get(i).asTagLong(); - TagLong tagLong2 = tag.asTagCompound().getValue().get(i).asTagLong(); - - assertNotNull(tagLong2.getName()); - assertName(tagLong1, tagLong2); - assertEquals(tagLong1.getValue(), tagLong2.getValue()); - } - } - - private static Stream streamOfTagIntArray() { - final int[] value = new int[RandomUtils.nextInt(1, 1000)]; - - for (int i = 0; i < value.length; i++) { - value[i] = RandomUtils.nextInt(); - } - - return Stream.of( - Arguments.of(new TagIntArray(value)), - Arguments.of(new TagIntArray(randomString(), value)) - ); - } - - @ParameterizedTest - @MethodSource("streamOfTagIntArray") - void testWriteTagIntArray(TagIntArray tagIntArray) throws IOException { - nbtOutputStream.writeTag(tagIntArray); - - Tag tag = createNbtInputStream().readTag(); - assertEquals(TypeTag.INT_ARRAY, tag.getType()); - assertArrayEquals(tagIntArray.getValue(), tag.asTagIntArray().getValue()); - assertName(tagIntArray, tag); - } - - private static Stream streamOfTagLongArray() { - final long[] value = new long[RandomUtils.nextInt(1, 1000)]; - - for (int i = 0; i < value.length; i++) { - value[i] = RandomUtils.nextLong(); - } - - return Stream.of( - Arguments.of(new TagLongArray(value)), - Arguments.of(new TagLongArray(randomString(), value)) - ); - } - - @ParameterizedTest - @MethodSource("streamOfTagLongArray") - void testWriteTagLongArray(TagLongArray tagLongArray) throws IOException { - nbtOutputStream.writeTag(tagLongArray); - - Tag tag = createNbtInputStream().readTag(); - assertEquals(TypeTag.LONG_ARRAY, tag.getType()); - assertArrayEquals(tagLongArray.getValue(), tag.asTagLongArray().getValue()); - assertName(tagLongArray, tag); - } - - private void assertName(Tag expectedTag, Tag actualTag) { - if (expectedTag.getName() == null) { - assertTrue(actualTag.getName().isEmpty()); - } else { - assertEquals(expectedTag.getName(), actualTag.getName()); - } - } - - private static String randomString() { - return RandomStringUtils.randomAscii(RandomUtils.nextInt(1, Short.MAX_VALUE)); - } - - private NbtInputStream createNbtInputStream() throws IOException { - return new NbtInputStream(new ByteArrayInputStream(baos.toByteArray())); - } -} \ No newline at end of file diff --git a/vanilla-codec/src/test/resources/bigtest.nbt b/vanilla-codec/src/test/resources/bigtest.nbt deleted file mode 100644 index dc3769b..0000000 Binary files a/vanilla-codec/src/test/resources/bigtest.nbt and /dev/null differ