This commit is contained in:
Intege-rs
2026-01-24 07:55:36 -05:00
commit 7a77188758
5298 changed files with 723645 additions and 0 deletions

43
.gitignore vendored Normal file
View File

@@ -0,0 +1,43 @@
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
.kotlin
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

8
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

1
.idea/.name generated Normal file
View File

@@ -0,0 +1 @@
Hytale-Server

6
.idea/AndroidProjectSystem.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AndroidProjectSystem">
<option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
</component>
</project>

16
.idea/gradle.xml generated Normal file
View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

10
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="corretto-21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

0
_decomp/decomp.ps1 Normal file
View File

Binary file not shown.

22
build.gradle.kts Normal file
View File

@@ -0,0 +1,22 @@
plugins {
id("java")
}
group = "hytale-server.kotlin"
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
}
dependencies {
testImplementation(platform("org.junit:junit-bom:5.10.0"))
testImplementation("org.junit.jupiter:junit-jupiter")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}
sourceSets {
getByName("main") {
java.setSrcDirs(listOf("src"))
}
}

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,6 @@
#Sat Jan 24 07:48:30 EST 2026
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

234
gradlew vendored Normal file
View File

@@ -0,0 +1,234 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/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
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
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${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"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || 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
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# 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" "$@"

89
gradlew.bat vendored Normal file
View File

@@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="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
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

1
settings.gradle.kts Normal file
View File

@@ -0,0 +1 @@
rootProject.name = "Hytale-Server"

View File

@@ -0,0 +1,82 @@
package com.hypixel.fastutil;
import java.util.Collection;
public interface FastCollection<E> extends Collection<E> {
void forEachWithFloat(FastCollection.FastConsumerF<? super E> var1, float var2);
void forEachWithInt(FastCollection.FastConsumerI<? super E> var1, int var2);
void forEachWithLong(FastCollection.FastConsumerL<? super E> var1, long var2);
<A, B, C, D> void forEach(
FastCollection.FastConsumerD9<? super E, A, B, C, D> var1,
A var2,
double var3,
double var5,
double var7,
double var9,
double var11,
double var13,
double var15,
double var17,
double var19,
B var21,
C var22,
D var23
);
<A, B, C, D> void forEach(
FastCollection.FastConsumerD6<? super E, A, B, C, D> var1,
A var2,
double var3,
double var5,
double var7,
double var9,
double var11,
double var13,
B var15,
C var16,
D var17
);
@FunctionalInterface
public interface FastConsumerD6<A, B, C, D, E> {
void accept(A var1, B var2, double var3, double var5, double var7, double var9, double var11, double var13, C var15, D var16, E var17);
}
@FunctionalInterface
public interface FastConsumerD9<A, B, C, D, E> {
void accept(
A var1,
B var2,
double var3,
double var5,
double var7,
double var9,
double var11,
double var13,
double var15,
double var17,
double var19,
C var21,
D var22,
E var23
);
}
@FunctionalInterface
public interface FastConsumerF<A> {
void accept(A var1, float var2);
}
@FunctionalInterface
public interface FastConsumerI<A> {
void accept(A var1, int var2);
}
@FunctionalInterface
public interface FastConsumerL<A> {
void accept(A var1, long var2);
}
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.bytes;
@FunctionalInterface
public interface Byte2ByteOperator {
byte apply(byte var1, byte var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.bytes;
@FunctionalInterface
public interface Byte2CharOperator {
char apply(byte var1, char var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.bytes;
@FunctionalInterface
public interface Byte2DoubleOperator {
double apply(byte var1, double var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.bytes;
@FunctionalInterface
public interface Byte2FloatOperator {
float apply(byte var1, float var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.bytes;
@FunctionalInterface
public interface Byte2IntOperator {
int apply(byte var1, int var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.bytes;
@FunctionalInterface
public interface Byte2LongOperator {
long apply(byte var1, long var2);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.bytes;
@FunctionalInterface
public interface Byte2ObjectOperator<V> {
V apply(byte var1, V var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.bytes;
@FunctionalInterface
public interface Byte2ShortOperator {
short apply(byte var1, short var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.chars;
@FunctionalInterface
public interface Char2ByteOperator {
byte apply(char var1, byte var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.chars;
@FunctionalInterface
public interface Char2CharOperator {
char apply(char var1, char var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.chars;
@FunctionalInterface
public interface Char2DoubleOperator {
double apply(char var1, double var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.chars;
@FunctionalInterface
public interface Char2FloatOperator {
float apply(char var1, float var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.chars;
@FunctionalInterface
public interface Char2IntOperator {
int apply(char var1, int var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.chars;
@FunctionalInterface
public interface Char2LongOperator {
long apply(char var1, long var2);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.chars;
@FunctionalInterface
public interface Char2ObjectOperator<V> {
V apply(char var1, V var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.chars;
@FunctionalInterface
public interface Char2ShortOperator {
short apply(char var1, short var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.doubles;
@FunctionalInterface
public interface Double2ByteOperator {
byte apply(double var1, byte var3);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.doubles;
@FunctionalInterface
public interface Double2CharOperator {
char apply(double var1, char var3);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.doubles;
@FunctionalInterface
public interface Double2DoubleOperator {
double apply(double var1, double var3);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.doubles;
@FunctionalInterface
public interface Double2FloatOperator {
float apply(double var1, float var3);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.doubles;
@FunctionalInterface
public interface Double2IntOperator {
int apply(double var1, int var3);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.doubles;
@FunctionalInterface
public interface Double2LongOperator {
long apply(double var1, long var3);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.doubles;
@FunctionalInterface
public interface Double2ObjectOperator<V> {
V apply(double var1, V var3);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.doubles;
@FunctionalInterface
public interface Double2ShortOperator {
short apply(double var1, short var3);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.floats;
@FunctionalInterface
public interface Float2ByteOperator {
byte apply(float var1, byte var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.floats;
@FunctionalInterface
public interface Float2CharOperator {
char apply(float var1, char var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.floats;
@FunctionalInterface
public interface Float2DoubleOperator {
double apply(float var1, double var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.floats;
@FunctionalInterface
public interface Float2FloatOperator {
float apply(float var1, float var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.floats;
@FunctionalInterface
public interface Float2IntOperator {
int apply(float var1, int var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.floats;
@FunctionalInterface
public interface Float2LongOperator {
long apply(float var1, long var2);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.floats;
@FunctionalInterface
public interface Float2ObjectOperator<V> {
V apply(float var1, V var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.floats;
@FunctionalInterface
public interface Float2ShortOperator {
short apply(float var1, short var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.ints;
@FunctionalInterface
public interface Int2ByteOperator {
byte apply(int var1, byte var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.ints;
@FunctionalInterface
public interface Int2CharOperator {
char apply(int var1, char var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.ints;
@FunctionalInterface
public interface Int2DoubleOperator {
double apply(int var1, double var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.ints;
@FunctionalInterface
public interface Int2FloatOperator {
float apply(int var1, float var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.ints;
@FunctionalInterface
public interface Int2IntOperator {
int apply(int var1, int var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.ints;
@FunctionalInterface
public interface Int2LongOperator {
long apply(int var1, long var2);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.ints;
@FunctionalInterface
public interface Int2ObjectOperator<V> {
V apply(int var1, V var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.ints;
@FunctionalInterface
public interface Int2ShortOperator {
short apply(int var1, short var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.longs;
@FunctionalInterface
public interface Long2ByteOperator {
byte apply(long var1, byte var3);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.longs;
@FunctionalInterface
public interface Long2CharOperator {
char apply(long var1, char var3);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.longs;
@FunctionalInterface
public interface Long2DoubleOperator {
double apply(long var1, double var3);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.longs;
@FunctionalInterface
public interface Long2FloatOperator {
float apply(long var1, float var3);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.longs;
@FunctionalInterface
public interface Long2IntOperator {
int apply(long var1, int var3);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.longs;
@FunctionalInterface
public interface Long2LongOperator {
long apply(long var1, long var3);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.longs;
@FunctionalInterface
public interface Long2ObjectOperator<V> {
V apply(long var1, V var3);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.longs;
@FunctionalInterface
public interface Long2ShortOperator {
short apply(long var1, short var3);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.shorts;
@FunctionalInterface
public interface Short2ByteOperator {
byte apply(short var1, byte var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.shorts;
@FunctionalInterface
public interface Short2CharOperator {
char apply(short var1, char var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.shorts;
@FunctionalInterface
public interface Short2DoubleOperator {
double apply(short var1, double var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.shorts;
@FunctionalInterface
public interface Short2FloatOperator {
float apply(short var1, float var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.shorts;
@FunctionalInterface
public interface Short2IntOperator {
int apply(short var1, int var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.shorts;
@FunctionalInterface
public interface Short2LongOperator {
long apply(short var1, long var2);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.shorts;
@FunctionalInterface
public interface Short2ObjectOperator<V> {
V apply(short var1, V var2);
}

View File

@@ -0,0 +1,6 @@
package com.hypixel.fastutil.shorts;
@FunctionalInterface
public interface Short2ShortOperator {
short apply(short var1, short var2);
}

View File

@@ -0,0 +1,18 @@
package com.hypixel.fastutil.util;
public class SneakyThrow {
public SneakyThrow() {
}
public static RuntimeException sneakyThrow(Throwable t) {
if (t == null) {
throw new NullPointerException("t");
} else {
return sneakyThrow0(t);
}
}
private static <T extends Throwable> T sneakyThrow0(Throwable t) throws T {
throw t;
}
}

View File

@@ -0,0 +1,55 @@
package com.hypixel.fastutil.util;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.concurrent.ThreadLocalRandom;
import sun.misc.Unsafe;
public class TLRUtil {
private static final Unsafe UNSAFE;
private static final long PROBE;
public TLRUtil() {
}
public static void localInit() {
ThreadLocalRandom.current();
}
public static int getProbe() {
return UNSAFE.getInt(Thread.currentThread(), PROBE);
}
public static int advanceProbe(int probe) {
probe ^= probe << 13;
probe ^= probe >>> 17;
probe ^= probe << 5;
UNSAFE.putInt(Thread.currentThread(), PROBE, probe);
return probe;
}
static {
Unsafe instance;
try {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
instance = (Unsafe)field.get(null);
} catch (Exception var5) {
try {
Constructor<Unsafe> c = Unsafe.class.getDeclaredConstructor();
c.setAccessible(true);
instance = c.newInstance();
} catch (Exception var4) {
throw SneakyThrow.sneakyThrow(var4);
}
}
UNSAFE = instance;
try {
PROBE = UNSAFE.objectFieldOffset(Thread.class.getDeclaredField("threadLocalRandomProbe"));
} catch (NoSuchFieldException var3) {
throw SneakyThrow.sneakyThrow(var3);
}
}
}

View File

@@ -0,0 +1,59 @@
package com.hypixel.hytale;
import com.hypixel.hytale.logger.HytaleLogger;
import com.hypixel.hytale.logger.backend.HytaleFileHandler;
import com.hypixel.hytale.logger.backend.HytaleLoggerBackend;
import com.hypixel.hytale.logger.sentry.SkipSentryException;
import com.hypixel.hytale.server.core.HytaleServer;
import com.hypixel.hytale.server.core.HytaleServerConfig;
import com.hypixel.hytale.server.core.Options;
import io.sentry.Sentry;
import java.util.Map.Entry;
import java.util.logging.Level;
public class LateMain {
public LateMain() {
}
public static void lateMain(String[] args) {
try {
if (!Options.parse(args)) {
HytaleLogger.init();
HytaleFileHandler.INSTANCE.enable();
HytaleLogger.replaceStd();
HytaleLoggerBackend.LOG_LEVEL_LOADER = name -> {
for (Entry<String, Level> e : Options.getOptionSet().valuesOf(Options.LOG_LEVELS)) {
if (name.equals(e.getKey())) {
return e.getValue();
}
}
HytaleServer hytaleServer = HytaleServer.get();
if (hytaleServer != null) {
HytaleServerConfig config = hytaleServer.getConfig();
if (config != null) {
Level configLevel = config.getLogLevels().get(name);
if (configLevel != null) {
return configLevel;
}
}
}
return Options.getOptionSet().has(Options.SHUTDOWN_AFTER_VALIDATE) ? Level.WARNING : null;
};
if (Options.getOptionSet().has(Options.SHUTDOWN_AFTER_VALIDATE)) {
HytaleLoggerBackend.reloadLogLevels();
}
new HytaleServer();
}
} catch (Throwable var2) {
if (!SkipSentryException.hasSkipSentry(var2)) {
Sentry.captureException(var2);
}
var2.printStackTrace();
throw new RuntimeException("Failed to create HytaleServer", var2);
}
}
}

View File

@@ -0,0 +1,78 @@
package com.hypixel.hytale;
import com.hypixel.hytale.plugin.early.EarlyPluginLoader;
import com.hypixel.hytale.plugin.early.TransformingClassLoader;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Locale;
import javax.annotation.Nonnull;
public final class Main {
public Main() {
}
public static void main(String[] args) {
Locale.setDefault(Locale.ENGLISH);
System.setProperty("java.awt.headless", "true");
System.setProperty("file.encoding", "UTF-8");
EarlyPluginLoader.loadEarlyPlugins(args);
if (EarlyPluginLoader.hasTransformers()) {
launchWithTransformingClassLoader(args);
} else {
LateMain.lateMain(args);
}
}
private static void launchWithTransformingClassLoader(@Nonnull String[] args) {
try {
URL[] urls = getClasspathUrls();
ClassLoader appClassLoader = Main.class.getClassLoader();
TransformingClassLoader transformingClassLoader = new TransformingClassLoader(
urls, EarlyPluginLoader.getTransformers(), appClassLoader.getParent(), appClassLoader
);
Thread.currentThread().setContextClassLoader(transformingClassLoader);
Class<?> lateMainClass = transformingClassLoader.loadClass("com.hypixel.hytale.LateMain");
Method mainMethod = lateMainClass.getMethod("lateMain", String[].class);
mainMethod.invoke(null, args);
} catch (NoSuchMethodException | IllegalAccessException | ClassNotFoundException var6) {
throw new RuntimeException("Failed to launch with transforming classloader", var6);
} catch (InvocationTargetException var7) {
Throwable cause = var7.getCause();
if (cause instanceof RuntimeException re) {
throw re;
} else if (cause instanceof Error err) {
throw err;
} else {
throw new RuntimeException("LateMain.lateMain() threw an exception", cause);
}
}
}
private static URL[] getClasspathUrls() {
if (Main.class.getClassLoader() instanceof URLClassLoader urlClassLoader) {
return urlClassLoader.getURLs();
} else {
ObjectArrayList<URL> urls = new ObjectArrayList<>();
String classpath = System.getProperty("java.class.path");
if (classpath != null && !classpath.isEmpty()) {
for (String pathStr : classpath.split(System.getProperty("path.separator"))) {
try {
Path path = Path.of(pathStr);
if (Files.exists(path)) {
urls.add(path.toUri().toURL());
}
} catch (Exception var8) {
System.err.println("[EarlyPlugin] Failed to parse classpath entry: " + pathStr);
}
}
}
return urls.toArray(URL[]::new);
}
}
}

View File

@@ -0,0 +1,11 @@
package com.hypixel.hytale.assetstore;
public class AssetConstants {
public static final int EXPECTED_CHILDREN_PER_ASSET = 3;
public static final int EXPECTED_ASSETS_PER_PATH = 1;
public static final int EXPECTED_VALUES_PER_TAG = 3;
public static final int EXPECTED_ASSETS_PER_TAG = 3;
public AssetConstants() {
}
}

View File

@@ -0,0 +1,279 @@
package com.hypixel.hytale.assetstore;
import com.hypixel.hytale.assetstore.map.JsonAssetWithMap;
import com.hypixel.hytale.codec.ExtraInfo;
import com.hypixel.hytale.common.util.ArrayUtil;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.ints.IntSets;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Function;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class AssetExtraInfo<K> extends ExtraInfo {
@Nullable
private final Path assetPath;
private final AssetExtraInfo.Data data;
public AssetExtraInfo(AssetExtraInfo.Data data) {
super(Integer.MAX_VALUE, AssetValidationResults::new);
this.assetPath = null;
this.data = data;
}
public AssetExtraInfo(Path assetPath, AssetExtraInfo.Data data) {
super(Integer.MAX_VALUE, AssetValidationResults::new);
this.assetPath = assetPath;
this.data = data;
}
@Nonnull
public String generateKey() {
return "*" + this.getKey() + "_" + this.peekKey('_');
}
public K getKey() {
return (K)this.getData().getKey();
}
@Nullable
public Path getAssetPath() {
return this.assetPath;
}
public AssetExtraInfo.Data getData() {
return this.data;
}
@Override
public void appendDetailsTo(@Nonnull StringBuilder sb) {
sb.append("Id: ").append(this.getKey()).append("\n");
if (this.assetPath != null) {
sb.append("Path: ").append(this.assetPath).append("\n");
}
}
public AssetValidationResults getValidationResults() {
return (AssetValidationResults)super.getValidationResults();
}
@Nonnull
@Override
public String toString() {
return "AssetExtraInfo{assetPath=" + this.assetPath + ", data=" + this.data + "} " + super.toString();
}
public static class Data {
public static final char TAG_VALUE_SEPARATOR = '=';
private Map<Class<? extends JsonAssetWithMap>, List<Object>> containedAssets;
private Map<Class<? extends JsonAssetWithMap>, List<RawAsset<Object>>> containedRawAssets;
@Nullable
private AssetExtraInfo.Data containerData;
private Class<? extends JsonAsset<?>> assetClass;
private Object key;
private Object parentKey;
private final Map<String, String[]> rawTags = new HashMap<>(0);
private final Int2ObjectMap<IntSet> tagStorage = new Int2ObjectOpenHashMap<>(0);
private final Int2ObjectMap<IntSet> unmodifiableTagStorage = new Int2ObjectOpenHashMap<>(0);
private final IntSet expandedTagStorage = new IntOpenHashSet(0);
private final IntSet unmodifiableExpandedTagStorage = IntSets.unmodifiable(this.expandedTagStorage);
public <K> Data(Class<? extends JsonAsset<K>> assetClass, K key, K parentKey) {
this.assetClass = assetClass;
this.key = key;
this.parentKey = parentKey;
}
public <K> Data(@Nullable AssetExtraInfo.Data containerData, Class<? extends JsonAsset<K>> aClass, K key, K parentKey, boolean inheritContainerTags) {
this(aClass, key, parentKey);
this.containerData = containerData;
if (containerData != null && inheritContainerTags) {
this.putTags(containerData.rawTags);
}
}
public Class<? extends JsonAsset<?>> getAssetClass() {
return this.assetClass;
}
public Object getKey() {
return this.key;
}
public Object getParentKey() {
return this.parentKey;
}
@Nonnull
public AssetExtraInfo.Data getRootContainerData() {
AssetExtraInfo.Data temp = this;
while (temp.containerData != null) {
temp = temp.containerData;
}
return temp;
}
@Nullable
public AssetExtraInfo.Data getContainerData() {
return this.containerData;
}
@Nullable
public <K> K getContainerKey(Class<? extends JsonAsset<K>> aClass) {
if (this.containerData == null) {
return null;
} else {
return (K)(this.containerData.assetClass.equals(aClass) ? this.containerData.key : this.containerData.getContainerKey(aClass));
}
}
public void putTags(@Nonnull Map<String, String[]> tags) {
for (Entry<String, String[]> entry : tags.entrySet()) {
String tag = entry.getKey().intern();
this.rawTags.merge(tag, entry.getValue(), ArrayUtil::combine);
IntSet tagIndexes = this.ensureTag(tag);
for (String value : entry.getValue()) {
tagIndexes.add(AssetRegistry.getOrCreateTagIndex(value));
this.ensureTag(value);
this.rawTags.putIfAbsent(value, ArrayUtil.EMPTY_STRING_ARRAY);
String valueTag = (tag + "=" + value).intern();
this.rawTags.putIfAbsent(valueTag, ArrayUtil.EMPTY_STRING_ARRAY);
this.ensureTag(valueTag);
}
}
}
@Nonnull
public Map<String, String[]> getRawTags() {
return Collections.unmodifiableMap(this.rawTags);
}
@Nonnull
public Int2ObjectMap<IntSet> getTags() {
return Int2ObjectMaps.unmodifiable(this.unmodifiableTagStorage);
}
@Nonnull
public IntSet getExpandedTagIndexes() {
return this.unmodifiableExpandedTagStorage;
}
public IntSet getTag(int tagIndex) {
return this.unmodifiableTagStorage.getOrDefault(tagIndex, IntSets.EMPTY_SET);
}
public <K, T extends JsonAssetWithMap<K, M>, M extends AssetMap<K, T>> void addContainedAsset(Class<T> assetClass, T asset) {
if (this.containedAssets == null) {
this.containedAssets = new HashMap<>();
}
this.containedAssets.computeIfAbsent(assetClass, k -> new ArrayList<>()).add(asset);
}
public <K, T extends JsonAssetWithMap<K, M>, M extends AssetMap<K, T>> void addContainedAsset(Class<T> assetClass, RawAsset<K> rawAsset) {
if (this.containedRawAssets == null) {
this.containedRawAssets = new HashMap<>();
}
this.containedRawAssets.computeIfAbsent(assetClass, k -> new ArrayList<>()).add(rawAsset);
}
public <K> void fetchContainedAssets(K key, @Nonnull Map<Class<? extends JsonAssetWithMap>, Map<K, List<Object>>> containedAssets) {
if (this.containedAssets != null) {
for (Entry<Class<? extends JsonAssetWithMap>, List<Object>> entry : this.containedAssets.entrySet()) {
containedAssets.computeIfAbsent(entry.getKey(), k -> new HashMap<>()).computeIfAbsent(key, k -> new ArrayList<>(3)).addAll(entry.getValue());
}
}
}
public <K> void fetchContainedRawAssets(K key, @Nonnull Map<Class<? extends JsonAssetWithMap>, Map<K, List<RawAsset<Object>>>> containedAssets) {
if (this.containedRawAssets != null) {
for (Entry<Class<? extends JsonAssetWithMap>, List<RawAsset<Object>>> entry : this.containedRawAssets.entrySet()) {
containedAssets.computeIfAbsent(entry.getKey(), k -> new HashMap<>()).computeIfAbsent(key, k -> new ArrayList<>(3)).addAll(entry.getValue());
}
}
}
public <K, T extends JsonAssetWithMap<K, M>, M extends AssetMap<K, T>> boolean containsAsset(Class<T> tClass, K key) {
if (this.containedAssets != null) {
List<T> assets = (List<T>)this.containedAssets.get(tClass);
if (assets != null) {
Function<T, K> keyFunction = AssetRegistry.<K, T, M>getAssetStore(tClass).getKeyFunction();
for (T asset : assets) {
if (key.equals(keyFunction.apply(asset))) {
return true;
}
}
}
}
if (this.containedRawAssets != null) {
List<RawAsset<T>> rawAssets = (List<RawAsset<T>>)this.containedRawAssets.get(tClass);
if (rawAssets != null) {
for (RawAsset<T> rawAsset : rawAssets) {
if (key.equals(rawAsset.getKey())) {
return true;
}
}
}
}
return false;
}
public void loadContainedAssets(boolean reloading) {
if (this.containedAssets != null) {
for (Entry<Class<? extends JsonAssetWithMap>, List<Object>> entry : this.containedAssets.entrySet()) {
AssetRegistry.getAssetStore(entry.getKey()).loadAssets("Hytale:Hytale", entry.getValue(), AssetUpdateQuery.DEFAULT, reloading);
}
}
if (this.containedRawAssets != null) {
for (Entry<Class<? extends JsonAssetWithMap>, List<RawAsset<Object>>> entry : this.containedRawAssets.entrySet()) {
AssetRegistry.getAssetStore(entry.getKey()).loadBuffersWithKeys("Hytale:Hytale", entry.getValue(), AssetUpdateQuery.DEFAULT, reloading);
}
}
}
@Nonnull
private IntSet ensureTag(@Nonnull String tag) {
int idx = AssetRegistry.getOrCreateTagIndex(tag);
this.expandedTagStorage.add(idx);
return this.tagStorage.computeIfAbsent(idx, k -> {
IntSet set = new IntOpenHashSet(3);
this.unmodifiableTagStorage.put(k, IntSets.unmodifiable(set));
return set;
});
}
@Nonnull
@Override
public String toString() {
return "Data{containedAssets="
+ this.containedRawAssets
+ ", rawTags="
+ this.rawTags
+ ", parent="
+ this.containerData
+ ", assetClass="
+ this.assetClass
+ ", key="
+ this.key
+ "}";
}
}
}

View File

@@ -0,0 +1,4 @@
package com.hypixel.hytale.assetstore;
public interface AssetHolder<K> {
}

View File

@@ -0,0 +1,30 @@
package com.hypixel.hytale.assetstore;
import com.hypixel.hytale.codec.schema.SchemaContext;
import com.hypixel.hytale.codec.schema.config.Schema;
import com.hypixel.hytale.codec.validation.ValidationResults;
import com.hypixel.hytale.codec.validation.Validator;
import java.util.function.Supplier;
import javax.annotation.Nonnull;
public class AssetKeyValidator<K> implements Validator<K> {
private final Supplier<AssetStore<K, ?, ?>> store;
public AssetKeyValidator(Supplier<AssetStore<K, ?, ?>> store) {
this.store = store;
}
public AssetStore<K, ?, ?> getStore() {
return this.store.get();
}
@Override
public void accept(K k, @Nonnull ValidationResults results) {
this.store.get().validate(k, results, results.getExtraInfo());
}
@Override
public void updateSchema(SchemaContext context, @Nonnull Schema target) {
target.setHytaleAssetRef(this.store.get().getAssetClass().getSimpleName());
}
}

View File

@@ -0,0 +1,58 @@
package com.hypixel.hytale.assetstore;
import com.hypixel.hytale.assetstore.map.JsonAssetWithMap;
import java.nio.file.Path;
import java.util.Map;
import java.util.Set;
public class AssetLoadResult<K, T> {
private final Map<K, T> loadedAssets;
private final Map<K, Path> loadedKeyToPathMap;
private final Set<K> failedToLoadKeys;
private final Set<Path> failedToLoadPaths;
private final Map<Class<? extends JsonAssetWithMap>, AssetLoadResult> childAssetResults;
public AssetLoadResult(
Map<K, T> loadedAssets,
Map<K, Path> loadedKeyToPathMap,
Set<K> failedToLoadKeys,
Set<Path> failedToLoadPaths,
Map<Class<? extends JsonAssetWithMap>, AssetLoadResult> childAssetResults
) {
this.loadedAssets = loadedAssets;
this.loadedKeyToPathMap = loadedKeyToPathMap;
this.failedToLoadKeys = failedToLoadKeys;
this.failedToLoadPaths = failedToLoadPaths;
this.childAssetResults = childAssetResults;
}
public Map<K, T> getLoadedAssets() {
return this.loadedAssets;
}
public Map<K, Path> getLoadedKeyToPathMap() {
return this.loadedKeyToPathMap;
}
public Set<K> getFailedToLoadKeys() {
return this.failedToLoadKeys;
}
public Set<Path> getFailedToLoadPaths() {
return this.failedToLoadPaths;
}
public boolean hasFailed() {
if (this.failedToLoadKeys.isEmpty() && this.failedToLoadPaths.isEmpty()) {
for (AssetLoadResult result : this.childAssetResults.values()) {
if (result.hasFailed()) {
return true;
}
}
return false;
} else {
return true;
}
}
}

View File

@@ -0,0 +1,58 @@
package com.hypixel.hytale.assetstore;
import com.hypixel.hytale.assetstore.codec.AssetCodec;
import it.unimi.dsi.fastutil.ints.IntSet;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public abstract class AssetMap<K, T extends JsonAsset<K>> {
public AssetMap() {
}
@Nullable
public abstract T getAsset(K var1);
@Nullable
public abstract T getAsset(@Nonnull String var1, K var2);
@Nullable
public abstract Path getPath(K var1);
@Nullable
public abstract String getAssetPack(K var1);
public abstract Set<K> getKeys(Path var1);
public abstract Set<K> getChildren(K var1);
public abstract int getAssetCount();
public abstract Map<K, T> getAssetMap();
public abstract Map<K, Path> getPathMap(@Nonnull String var1);
public abstract Set<K> getKeysForTag(int var1);
public abstract IntSet getTagIndexes();
public abstract int getTagCount();
protected abstract void clear();
protected abstract void putAll(@Nonnull String var1, AssetCodec<K, T> var2, Map<K, T> var3, Map<K, Path> var4, Map<K, Set<K>> var5);
protected abstract Set<K> remove(Set<K> var1);
protected abstract Set<K> remove(@Nonnull String var1, Set<K> var2, List<Entry<String, Object>> var3);
public boolean requireReplaceOnRemove() {
return false;
}
public abstract Set<K> getKeysForPack(@Nonnull String var1);
}

View File

@@ -0,0 +1,79 @@
package com.hypixel.hytale.assetstore;
import com.hypixel.hytale.common.plugin.PluginManifest;
import java.nio.file.FileSystem;
import java.nio.file.Path;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class AssetPack {
@Nonnull
private final String name;
@Nonnull
private final Path root;
@Nullable
private final FileSystem fileSystem;
private final boolean isImmutable;
private final PluginManifest manifest;
private final Path packLocation;
public AssetPack(Path packLocation, @Nonnull String name, @Nonnull Path root, @Nullable FileSystem fileSystem, boolean isImmutable, PluginManifest manifest) {
this.name = name;
this.root = root;
this.fileSystem = fileSystem;
this.isImmutable = isImmutable;
this.manifest = manifest;
this.packLocation = packLocation;
}
@Nonnull
public String getName() {
return this.name;
}
@Nonnull
public Path getRoot() {
return this.root;
}
@Nullable
public FileSystem getFileSystem() {
return this.fileSystem;
}
public PluginManifest getManifest() {
return this.manifest;
}
public boolean isImmutable() {
return this.isImmutable;
}
public Path getPackLocation() {
return this.packLocation;
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
AssetPack assetPack = (AssetPack)o;
return !this.name.equals(assetPack.name) ? false : this.root.equals(assetPack.root);
} else {
return false;
}
}
@Override
public int hashCode() {
int result = this.name.hashCode();
return 31 * result + this.root.hashCode();
}
@Nonnull
@Override
public String toString() {
return "AssetPack{name='" + this.name + "', root=" + this.root + ", fileSystem=" + this.fileSystem + "}";
}
}

View File

@@ -0,0 +1,39 @@
package com.hypixel.hytale.assetstore;
import com.hypixel.hytale.assetstore.map.JsonAssetWithMap;
import java.util.Collections;
import java.util.Set;
import javax.annotation.Nonnull;
public class AssetReferences<CK, C extends JsonAssetWithMap<CK, ?>> {
private final Class<C> parentAssetClass;
private final Set<CK> parentKeys;
public AssetReferences(Class<C> parentAssetClass, Set<CK> parentKeys) {
this.parentAssetClass = parentAssetClass;
this.parentKeys = parentKeys;
}
public Class<C> getParentAssetClass() {
return this.parentAssetClass;
}
public Set<CK> getParentKeys() {
return this.parentKeys;
}
public <T extends JsonAssetWithMap<K, ?>, K> void addChildAssetReferences(Class<T> tClass, K childKey) {
Class parentAssetClass = this.parentAssetClass;
AssetStore<CK, C, ?> assetStore = AssetRegistry.getAssetStore(parentAssetClass);
for (CK parentKey : this.parentKeys) {
assetStore.addChildAssetReferences(parentKey, tClass, Collections.singleton(childKey));
}
}
@Nonnull
@Override
public String toString() {
return "AssetReferences{parentAssetClass=" + this.parentAssetClass + ", parentKeys=" + this.parentKeys + "}";
}
}

View File

@@ -0,0 +1,145 @@
package com.hypixel.hytale.assetstore;
import com.hypixel.hytale.assetstore.event.RegisterAssetStoreEvent;
import com.hypixel.hytale.assetstore.event.RemoveAssetStoreEvent;
import com.hypixel.hytale.assetstore.map.JsonAssetWithMap;
import com.hypixel.hytale.event.IEventDispatcher;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.StampedLock;
import javax.annotation.Nonnull;
public class AssetRegistry {
public static final ReadWriteLock ASSET_LOCK = new ReentrantReadWriteLock();
public static boolean HAS_INIT = false;
public static final int TAG_NOT_FOUND = Integer.MIN_VALUE;
private static final Map<Class<? extends JsonAssetWithMap>, AssetStore<?, ?, ?>> storeMap = new HashMap<>();
private static final Map<Class<? extends JsonAssetWithMap>, AssetStore<?, ?, ?>> storeMapUnmodifiable = Collections.unmodifiableMap(storeMap);
private static final AtomicInteger NEXT_TAG_INDEX = new AtomicInteger();
private static final StampedLock TAG_LOCK = new StampedLock();
private static final Object2IntMap<String> TAG_MAP = new Object2IntOpenHashMap<>();
private static final Object2IntMap<String> CLIENT_TAG_MAP = new Object2IntOpenHashMap<>();
public AssetRegistry() {
}
@Nonnull
public static Map<Class<? extends JsonAssetWithMap>, AssetStore<?, ?, ?>> getStoreMap() {
return storeMapUnmodifiable;
}
public static <K, T extends JsonAssetWithMap<K, M>, M extends AssetMap<K, T>> AssetStore<K, T, M> getAssetStore(Class<T> tClass) {
return (AssetStore<K, T, M>)storeMap.get(tClass);
}
@Nonnull
public static <K, T extends JsonAssetWithMap<K, M>, M extends AssetMap<K, T>, S extends AssetStore<K, T, M>> S register(@Nonnull S assetStore) {
ASSET_LOCK.writeLock().lock();
try {
if (storeMap.putIfAbsent(assetStore.getAssetClass(), assetStore) != null) {
throw new IllegalArgumentException("Asset Store already exists for " + assetStore.getAssetClass());
}
} finally {
ASSET_LOCK.writeLock().unlock();
}
IEventDispatcher<RegisterAssetStoreEvent, RegisterAssetStoreEvent> dispatch = assetStore.getEventBus().dispatchFor(RegisterAssetStoreEvent.class);
if (dispatch.hasListener()) {
dispatch.dispatch(new RegisterAssetStoreEvent(assetStore));
}
return assetStore;
}
public static <K, T extends JsonAssetWithMap<K, M>, M extends AssetMap<K, T>, S extends AssetStore<K, T, M>> void unregister(@Nonnull S assetStore) {
ASSET_LOCK.writeLock().lock();
try {
storeMap.remove(assetStore.getAssetClass());
} finally {
ASSET_LOCK.writeLock().unlock();
}
IEventDispatcher<RemoveAssetStoreEvent, RemoveAssetStoreEvent> dispatch = assetStore.getEventBus().dispatchFor(RemoveAssetStoreEvent.class);
if (dispatch.hasListener()) {
dispatch.dispatch(new RemoveAssetStoreEvent(assetStore));
}
}
public static int getTagIndex(@Nonnull String tag) {
if (tag == null) {
throw new IllegalArgumentException("tag can't be null!");
} else {
long stamp = TAG_LOCK.readLock();
int var3;
try {
var3 = TAG_MAP.getInt(tag);
} finally {
TAG_LOCK.unlockRead(stamp);
}
return var3;
}
}
public static int getOrCreateTagIndex(@Nonnull String tag) {
if (tag == null) {
throw new IllegalArgumentException("tag can't be null!");
} else {
long stamp = TAG_LOCK.writeLock();
int var3;
try {
var3 = TAG_MAP.computeIfAbsent(tag.intern(), k -> NEXT_TAG_INDEX.getAndIncrement());
} finally {
TAG_LOCK.unlockWrite(stamp);
}
return var3;
}
}
public static boolean registerClientTag(@Nonnull String tag) {
if (tag == null) {
throw new IllegalArgumentException("tag can't be null!");
} else {
long stamp = TAG_LOCK.writeLock();
boolean var3;
try {
var3 = CLIENT_TAG_MAP.put(tag, TAG_MAP.computeIfAbsent(tag, k -> NEXT_TAG_INDEX.getAndIncrement())) == Integer.MIN_VALUE;
} finally {
TAG_LOCK.unlockWrite(stamp);
}
return var3;
}
}
@Nonnull
public static Object2IntMap<String> getClientTags() {
long stamp = TAG_LOCK.readLock();
Object2IntOpenHashMap var2;
try {
var2 = new Object2IntOpenHashMap<>(CLIENT_TAG_MAP);
} finally {
TAG_LOCK.unlockRead(stamp);
}
return var2;
}
static {
TAG_MAP.defaultReturnValue(Integer.MIN_VALUE);
CLIENT_TAG_MAP.defaultReturnValue(Integer.MIN_VALUE);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,178 @@
package com.hypixel.hytale.assetstore;
import javax.annotation.Nonnull;
public class AssetUpdateQuery {
public static final AssetUpdateQuery DEFAULT = new AssetUpdateQuery(AssetUpdateQuery.RebuildCache.DEFAULT);
public static final AssetUpdateQuery DEFAULT_NO_REBUILD = new AssetUpdateQuery(AssetUpdateQuery.RebuildCache.NO_REBUILD);
private final boolean disableAssetCompare;
private final AssetUpdateQuery.RebuildCache rebuildCache;
public AssetUpdateQuery(boolean disableAssetCompare, AssetUpdateQuery.RebuildCache rebuildCache) {
this.disableAssetCompare = disableAssetCompare;
this.rebuildCache = rebuildCache;
}
public AssetUpdateQuery(AssetUpdateQuery.RebuildCache rebuildCache) {
this(AssetStore.DISABLE_ASSET_COMPARE, rebuildCache);
}
public boolean isDisableAssetCompare() {
return this.disableAssetCompare;
}
@Nonnull
public AssetUpdateQuery.RebuildCache getRebuildCache() {
return this.rebuildCache;
}
@Nonnull
@Override
public String toString() {
return "AssetUpdateQuery{rebuildCache=" + this.rebuildCache + "}";
}
public static class RebuildCache {
public static final AssetUpdateQuery.RebuildCache DEFAULT = new AssetUpdateQuery.RebuildCache(true, true, true, true, true, true);
public static final AssetUpdateQuery.RebuildCache NO_REBUILD = new AssetUpdateQuery.RebuildCache(false, false, false, false, false, false);
private final boolean blockTextures;
private final boolean models;
private final boolean modelTextures;
private final boolean mapGeometry;
private final boolean itemIcons;
private final boolean commonAssetsRebuild;
public RebuildCache(boolean blockTextures, boolean models, boolean modelTextures, boolean mapGeometry, boolean itemIcons, boolean commonAssetsRebuild) {
this.blockTextures = blockTextures;
this.models = models;
this.modelTextures = modelTextures;
this.mapGeometry = mapGeometry;
this.itemIcons = itemIcons;
this.commonAssetsRebuild = commonAssetsRebuild;
}
public boolean isBlockTextures() {
return this.blockTextures;
}
public boolean isModels() {
return this.models;
}
public boolean isModelTextures() {
return this.modelTextures;
}
public boolean isMapGeometry() {
return this.mapGeometry;
}
public boolean isItemIcons() {
return this.itemIcons;
}
public boolean isCommonAssetsRebuild() {
return this.commonAssetsRebuild;
}
@Nonnull
public AssetUpdateQuery.RebuildCacheBuilder toBuilder() {
return new AssetUpdateQuery.RebuildCacheBuilder(
this.blockTextures, this.models, this.modelTextures, this.mapGeometry, this.itemIcons, this.commonAssetsRebuild
);
}
@Nonnull
public static AssetUpdateQuery.RebuildCacheBuilder builder() {
return new AssetUpdateQuery.RebuildCacheBuilder();
}
@Nonnull
@Override
public String toString() {
return "RebuildCache{blockTextures="
+ this.blockTextures
+ ", models="
+ this.models
+ ", modelTextures="
+ this.modelTextures
+ ", mapGeometry="
+ this.mapGeometry
+ ", icons="
+ this.itemIcons
+ ", commonAssetsRebuild="
+ this.commonAssetsRebuild
+ "}";
}
}
public static class RebuildCacheBuilder {
private boolean blockTextures;
private boolean models;
private boolean modelTextures;
private boolean mapGeometry;
private boolean itemIcons;
private boolean commonAssetsRebuild;
RebuildCacheBuilder() {
}
RebuildCacheBuilder(boolean blockTextures, boolean models, boolean modelTextures, boolean mapGeometry, boolean itemIcons, boolean commonAssetsRebuild) {
this.blockTextures = blockTextures;
this.models = models;
this.modelTextures = modelTextures;
this.mapGeometry = mapGeometry;
this.itemIcons = itemIcons;
this.commonAssetsRebuild = commonAssetsRebuild;
}
public void setBlockTextures(boolean blockTextures) {
this.blockTextures = blockTextures;
}
public void setModels(boolean models) {
this.models = models;
}
public void setModelTextures(boolean modelTextures) {
this.modelTextures = modelTextures;
}
public void setMapGeometry(boolean mapGeometry) {
this.mapGeometry = mapGeometry;
}
public void setItemIcons(boolean itemIcons) {
this.itemIcons = itemIcons;
}
public void setCommonAssetsRebuild(boolean commonAssetsRebuild) {
this.commonAssetsRebuild = commonAssetsRebuild;
}
@Nonnull
public AssetUpdateQuery.RebuildCache build() {
return new AssetUpdateQuery.RebuildCache(
this.blockTextures, this.models, this.modelTextures, this.mapGeometry, this.itemIcons, this.commonAssetsRebuild
);
}
@Nonnull
@Override
public String toString() {
return "RebuildCache{blockTextures="
+ this.blockTextures
+ ", models="
+ this.models
+ ", modelTextures="
+ this.modelTextures
+ ", mapGeometry="
+ this.mapGeometry
+ ", icons="
+ this.itemIcons
+ ", commonAssetsRebuild="
+ this.commonAssetsRebuild
+ "}";
}
}
}

View File

@@ -0,0 +1,77 @@
package com.hypixel.hytale.assetstore;
import com.hypixel.hytale.codec.ExtraInfo;
import com.hypixel.hytale.codec.validation.ValidationResults;
import com.hypixel.hytale.logger.HytaleLogger;
import com.hypixel.hytale.logger.backend.HytaleLoggerBackend;
import com.hypixel.hytale.logger.util.GithubMessageUtil;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.checkerframework.checker.nullness.compatqual.NonNullDecl;
public class AssetValidationResults extends ValidationResults {
private Set<Class<? extends JsonAsset>> disabledMissingAssetClasses;
public AssetValidationResults(ExtraInfo extraInfo) {
super(extraInfo);
}
public void handleMissingAsset(String field, @Nonnull Class<? extends JsonAsset> assetType, Object assetId) {
if (this.disabledMissingAssetClasses == null || !this.disabledMissingAssetClasses.contains(assetType)) {
throw new MissingAssetException(field, assetType, assetId);
}
}
public void handleMissingAsset(String field, @Nonnull Class<? extends JsonAsset> assetType, Object assetId, String extra) {
if (this.disabledMissingAssetClasses == null || !this.disabledMissingAssetClasses.contains(assetType)) {
throw new MissingAssetException(field, assetType, assetId, extra);
}
}
public void disableMissingAssetFor(Class<? extends JsonAsset> assetType) {
if (this.disabledMissingAssetClasses == null) {
this.disabledMissingAssetClasses = new HashSet<>();
}
this.disabledMissingAssetClasses.add(assetType);
}
@Override
public void logOrThrowValidatorExceptions(@NonNullDecl HytaleLogger logger, @NonNullDecl String msg) {
this.logOrThrowValidatorExceptions(logger, msg, null, 0);
}
public void logOrThrowValidatorExceptions(@NonNullDecl HytaleLogger logger, @NonNullDecl String msg, @Nullable Path path, int lineOffset) {
if (GithubMessageUtil.isGithub() && this.validatorExceptions != null && !this.validatorExceptions.isEmpty()) {
for (ValidationResults.ValidatorResultsHolder holder : this.validatorExceptions) {
String file = "unknown";
if (path == null && this.extraInfo instanceof AssetExtraInfo<?> assetExtraInfo) {
path = assetExtraInfo.getAssetPath();
}
if (path != null) {
file = path.toString();
}
for (ValidationResults.ValidationResult result : holder.results()) {
HytaleLoggerBackend.rawLog(
switch (result.result()) {
case SUCCESS -> "";
case WARNING -> holder.line() == -1
? GithubMessageUtil.messageWarning(file, result.reason())
: GithubMessageUtil.messageWarning(file, holder.line() + lineOffset, holder.column(), result.reason());
case FAIL -> holder.line() == -1
? GithubMessageUtil.messageError(file, result.reason())
: GithubMessageUtil.messageError(file, holder.line() + lineOffset, holder.column(), result.reason());
}
);
}
}
}
super.logOrThrowValidatorExceptions(logger, msg);
}
}

View File

@@ -0,0 +1,50 @@
package com.hypixel.hytale.assetstore;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class DecodedAsset<K, T extends JsonAsset<K>> implements AssetHolder<K> {
private final K key;
private final T asset;
public DecodedAsset(K key, T asset) {
this.key = key;
this.asset = asset;
}
public K getKey() {
return this.key;
}
public T getAsset() {
return this.asset;
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
DecodedAsset<?, ?> that = (DecodedAsset<?, ?>)o;
if (this.key != null ? this.key.equals(that.key) : that.key == null) {
return this.asset != null ? this.asset.equals(that.asset) : that.asset == null;
} else {
return false;
}
} else {
return false;
}
}
@Override
public int hashCode() {
int result = this.key != null ? this.key.hashCode() : 0;
return 31 * result + (this.asset != null ? this.asset.hashCode() : 0);
}
@Nonnull
@Override
public String toString() {
return "DecodedAsset{key=" + this.key + ", asset=" + this.asset + "}";
}
}

View File

@@ -0,0 +1,5 @@
package com.hypixel.hytale.assetstore;
public interface JsonAsset<K> {
K getId();
}

View File

@@ -0,0 +1,55 @@
package com.hypixel.hytale.assetstore;
import com.hypixel.hytale.codec.ExtraInfo;
import com.hypixel.hytale.codec.validation.ValidationResults;
import javax.annotation.Nonnull;
public class MissingAssetException extends RuntimeException {
private String field;
private Class<? extends JsonAsset> assetType;
private Object assetId;
public MissingAssetException(String field, @Nonnull Class<? extends JsonAsset> assetType, Object assetId) {
super("Missing asset '" + assetId + "' of type " + assetType.getSimpleName() + " for field '" + field + "'!");
this.field = field;
this.assetType = assetType;
this.assetId = assetId;
}
public MissingAssetException(String field, @Nonnull Class<? extends JsonAsset> assetType, Object assetId, String extra) {
super("Missing asset '" + assetId + "' of type " + assetType.getSimpleName() + " for field '" + field + "'! " + extra);
this.field = field;
this.assetType = assetType;
this.assetId = assetId;
}
public String getField() {
return this.field;
}
public Class<? extends JsonAsset> getAssetType() {
return this.assetType;
}
public Object getAssetId() {
return this.assetId;
}
public static void handle(@Nonnull ExtraInfo extraInfo, String field, @Nonnull Class<? extends JsonAsset> assetType, Object assetId) {
ValidationResults validationResults = extraInfo.getValidationResults();
if (validationResults instanceof AssetValidationResults) {
((AssetValidationResults)validationResults).handleMissingAsset(field, assetType, assetId);
} else {
throw new MissingAssetException(field, assetType, assetId);
}
}
public static void handle(@Nonnull ExtraInfo extraInfo, String field, @Nonnull Class<? extends JsonAsset> assetType, Object assetId, String extra) {
ValidationResults validationResults = extraInfo.getValidationResults();
if (validationResults instanceof AssetValidationResults) {
((AssetValidationResults)validationResults).handleMissingAsset(field, assetType, assetId, extra);
} else {
throw new MissingAssetException(field, assetType, assetId, extra);
}
}
}

View File

@@ -0,0 +1,153 @@
package com.hypixel.hytale.assetstore;
import com.hypixel.hytale.assetstore.codec.ContainedAssetCodec;
import com.hypixel.hytale.assetstore.map.JsonAssetWithMap;
import com.hypixel.hytale.codec.util.RawJsonReader;
import java.io.IOException;
import java.nio.file.Path;
import java.util.function.Supplier;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNullableByDefault;
@ParametersAreNullableByDefault
public class RawAsset<K> implements AssetHolder<K> {
private final Path parentPath;
@Nullable
private final K key;
private final int lineOffset;
private final boolean parentKeyResolved;
@Nullable
private final K parentKey;
@Nullable
private final Path path;
@Nullable
private final char[] buffer;
@Nullable
private final AssetExtraInfo.Data containerData;
@Nonnull
private final ContainedAssetCodec.Mode containedAssetMode;
public RawAsset(K key, Path path) {
this.key = key;
this.lineOffset = 0;
this.parentKeyResolved = false;
this.parentKey = null;
this.path = path;
this.parentPath = null;
this.buffer = null;
this.containerData = null;
this.containedAssetMode = ContainedAssetCodec.Mode.NONE;
}
public RawAsset(
Path parentPath,
K key,
K parentKey,
int lineOffset,
char[] buffer,
AssetExtraInfo.Data containerData,
@Nonnull ContainedAssetCodec.Mode containedAssetMode
) {
this.key = key;
this.lineOffset = lineOffset;
this.parentKeyResolved = true;
this.parentKey = parentKey;
this.path = null;
this.parentPath = parentPath;
this.buffer = buffer;
this.containerData = containerData;
this.containedAssetMode = containedAssetMode;
}
private RawAsset(
K key,
boolean parentKeyResolved,
K parentKey,
Path path,
char[] buffer,
AssetExtraInfo.Data containerData,
@Nonnull ContainedAssetCodec.Mode containedAssetMode
) {
this.key = key;
this.lineOffset = 0;
this.parentKeyResolved = parentKeyResolved;
this.parentKey = parentKey;
this.path = path;
this.parentPath = null;
this.buffer = buffer;
this.containerData = containerData;
this.containedAssetMode = containedAssetMode;
}
@Nullable
public K getKey() {
return this.key;
}
public boolean isParentKeyResolved() {
return this.parentKeyResolved;
}
@Nullable
public K getParentKey() {
return this.parentKey;
}
@Nullable
public Path getPath() {
return this.path;
}
public Path getParentPath() {
return this.parentPath;
}
public int getLineOffset() {
return this.lineOffset;
}
public char[] getBuffer() {
return this.buffer;
}
@Nonnull
public ContainedAssetCodec.Mode getContainedAssetMode() {
return this.containedAssetMode;
}
@Nonnull
public RawJsonReader toRawJsonReader(@Nonnull Supplier<char[]> bufferSupplier) throws IOException {
return this.path != null ? RawJsonReader.fromPath(this.path, bufferSupplier.get()) : RawJsonReader.fromBuffer(this.buffer);
}
@Nonnull
public AssetExtraInfo.Data makeData(Class<? extends JsonAssetWithMap<K, ?>> aClass, K key, K parentKey) {
boolean inheritTags = switch (this.containedAssetMode) {
case INHERIT_ID, INHERIT_ID_AND_PARENT, INJECT_PARENT -> true;
case NONE, GENERATE_ID -> false;
};
return new AssetExtraInfo.Data(this.containerData, aClass, key, parentKey, inheritTags);
}
@Nonnull
public RawAsset<K> withResolveKeys(K key, K parentKey) {
return new RawAsset<>(key, true, parentKey, this.path, this.buffer, this.containerData, this.containedAssetMode);
}
@Nonnull
@Override
public String toString() {
return "RawAsset{key="
+ this.key
+ ", parentKeyResolved="
+ this.parentKeyResolved
+ ", parentKey="
+ this.parentKey
+ ", path="
+ this.path
+ ", buffer.length="
+ (this.buffer != null ? this.buffer.length : -1)
+ "}";
}
}

View File

@@ -0,0 +1,225 @@
package com.hypixel.hytale.assetstore.codec;
import com.hypixel.hytale.assetstore.AssetExtraInfo;
import com.hypixel.hytale.assetstore.JsonAsset;
import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.codec.KeyedCodec;
import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.codec.codecs.map.MapCodec;
import com.hypixel.hytale.codec.schema.SchemaContext;
import com.hypixel.hytale.codec.schema.config.ObjectSchema;
import com.hypixel.hytale.codec.schema.config.Schema;
import com.hypixel.hytale.codec.util.RawJsonReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class AssetBuilderCodec<K, T extends JsonAsset<K>> extends BuilderCodec<T> implements AssetCodec<K, T> {
public static final KeyedCodec<Map<String, String[]>> TAGS_CODEC = new KeyedCodec<>("Tags", new MapCodec<>(Codec.STRING_ARRAY, HashMap::new));
private static final String TAG_DOCUMENTATION = "Tags are a general way to describe an asset that can be interpreted by other systems in a way they see fit.\n\nFor example you could tag something with a **Material** tag with the values **Solid** and **Stone**, And another single tag **Ore**.\n\nTags will be expanded into a single list of tags automatically. Using the above example with **Material** and **Ore** the end result would be the following list of tags: **Ore**, **Material**, **Solid**, **Stone**, **Material=Solid** and **Material=Stone**.";
@Nonnull
protected final KeyedCodec<K> idCodec;
@Nonnull
protected final KeyedCodec<K> parentCodec;
protected final BiConsumer<T, K> idSetter;
protected final BiConsumer<T, AssetExtraInfo.Data> dataSetter;
@Nonnull
protected final Function<T, AssetExtraInfo.Data> dataGetter;
protected AssetBuilderCodec(@Nonnull AssetBuilderCodec.Builder<K, T> builder) {
super(builder);
this.idCodec = builder.idCodec;
this.parentCodec = new KeyedCodec<>("Parent", this.idCodec.getChildCodec());
this.idSetter = builder.idSetter;
this.dataSetter = builder.dataSetter;
this.dataGetter = builder.dataGetter;
}
@Nonnull
@Override
public KeyedCodec<K> getKeyCodec() {
return this.idCodec;
}
@Nonnull
@Override
public KeyedCodec<K> getParentCodec() {
return this.parentCodec;
}
@Override
public AssetExtraInfo.Data getData(T t) {
return this.dataGetter.apply(t);
}
@Override
public T decodeJsonAsset(@Nonnull RawJsonReader reader, @Nonnull AssetExtraInfo<K> extraInfo) throws IOException {
return this.decodeAndInheritJsonAsset(reader, null, extraInfo);
}
@Override
public T decodeAndInheritJsonAsset(@Nonnull RawJsonReader reader, @Nullable T parent, @Nonnull AssetExtraInfo<K> extraInfo) throws IOException {
T t = this.supplier.get();
this.dataSetter.accept(t, extraInfo.getData());
if (parent != null) {
this.inherit(t, parent, extraInfo);
}
this.decodeAndInheritJson0(reader, t, parent, extraInfo);
this.idSetter.accept(t, extraInfo.getKey());
this.afterDecodeAndValidate(t, extraInfo);
return t;
}
@Nonnull
@Override
public ObjectSchema toSchema(@Nonnull SchemaContext context) {
return this.toSchema(context, this.supplier.get());
}
@Nonnull
public ObjectSchema toSchema(@Nonnull SchemaContext context, @Nullable T def) {
ObjectSchema schema = super.toSchema(context, def);
KeyedCodec<K> parent = this.getParentCodec();
Schema parentSchema = parent.getChildCodec().toSchema(context);
parentSchema.setMarkdownDescription(
"When set this asset will inherit properties from the named asset.\n\nWhen inheriting from another **"
+ this.tClass.getSimpleName()
+ "** most properties will simply be copied from the parent asset to this asset. In the case where both child and parent provide a field the child field will simply replace the value provided by the parent, in the case of nested structures this will apply to the fields within the structure. In some cases the field may decide to act differently, for example: by merging the parent and child fields together."
);
Class<? super T> rootClass = this.tClass;
for (BuilderCodec<? super T> rootCodec = this; rootCodec.getParent() != null; rootClass = rootCodec.getInnerClass()) {
rootCodec = rootCodec.getParent();
}
parentSchema.setHytaleParent(new Schema.InheritSettings(rootClass.getSimpleName()));
LinkedHashMap<String, Schema> props = new LinkedHashMap<>();
props.put(parent.getKey(), parentSchema);
props.putAll(schema.getProperties());
schema.setProperties(props);
return schema;
}
@Nonnull
public static <K, T extends JsonAsset<K>> AssetBuilderCodec.Builder<K, T> builder(
Class<T> tClass,
Supplier<T> supplier,
Codec<K> idCodec,
BiConsumer<T, K> idSetter,
Function<T, K> idGetter,
BiConsumer<T, AssetExtraInfo.Data> dataSetter,
@Nonnull Function<T, AssetExtraInfo.Data> dataGetter
) {
return new AssetBuilderCodec.Builder<>(tClass, supplier, idCodec, idSetter, idGetter, dataSetter, dataGetter);
}
@Nonnull
public static <K, T extends JsonAsset<K>> AssetBuilderCodec.Builder<K, T> builder(
Class<T> tClass,
Supplier<T> supplier,
BuilderCodec<? super T> parentCodec,
Codec<K> idCodec,
BiConsumer<T, K> idSetter,
Function<T, K> idGetter,
BiConsumer<T, AssetExtraInfo.Data> dataSetter,
@Nonnull Function<T, AssetExtraInfo.Data> dataGetter
) {
return new AssetBuilderCodec.Builder<>(tClass, supplier, parentCodec, idCodec, idSetter, idGetter, dataSetter, dataGetter);
}
@Nonnull
public static <K, T extends JsonAsset<K>> AssetBuilderCodec<K, T> wrap(
@Nonnull BuilderCodec<T> codec,
Codec<K> idCodec,
BiConsumer<T, K> idSetter,
Function<T, K> idGetter,
BiConsumer<T, AssetExtraInfo.Data> dataSetter,
@Nonnull Function<T, AssetExtraInfo.Data> dataGetter
) {
return builder(codec.getInnerClass(), codec.getSupplier(), codec, idCodec, idSetter, idGetter, dataSetter, dataGetter)
.documentation(codec.getDocumentation())
.build();
}
public static class Builder<K, T extends JsonAsset<K>> extends BuilderCodec.BuilderBase<T, AssetBuilderCodec.Builder<K, T>> {
@Nonnull
protected final KeyedCodec<K> idCodec;
protected final BiConsumer<T, K> idSetter;
protected final BiConsumer<T, AssetExtraInfo.Data> dataSetter;
@Nonnull
protected final Function<T, AssetExtraInfo.Data> dataGetter;
public Builder(
Class<T> tClass,
Supplier<T> supplier,
Codec<K> idCodec,
BiConsumer<T, K> idSetter,
Function<T, K> idGetter,
BiConsumer<T, AssetExtraInfo.Data> dataSetter,
@Nonnull Function<T, AssetExtraInfo.Data> dataGetter
) {
super(tClass, supplier);
this.idCodec = new KeyedCodec<>("Id", idCodec);
this.idSetter = idSetter;
this.dataSetter = dataSetter;
this.dataGetter = dataGetter;
this.<Map<String, String[]>>appendInherited(AssetBuilderCodec.TAGS_CODEC, (t, tags) -> dataGetter.apply(t).putTags(tags), t -> {
AssetExtraInfo.Data data = dataGetter.apply(t);
return data != null ? data.getRawTags() : null;
}, (t, parent) -> {
AssetExtraInfo.Data data = dataGetter.apply(t);
AssetExtraInfo.Data parentData = dataGetter.apply(parent);
if (data != null && parentData != null) {
data.putTags(parentData.getRawTags());
}
})
.documentation(
"Tags are a general way to describe an asset that can be interpreted by other systems in a way they see fit.\n\nFor example you could tag something with a **Material** tag with the values **Solid** and **Stone**, And another single tag **Ore**.\n\nTags will be expanded into a single list of tags automatically. Using the above example with **Material** and **Ore** the end result would be the following list of tags: **Ore**, **Material**, **Solid**, **Stone**, **Material=Solid** and **Material=Stone**."
)
.add();
}
public Builder(
Class<T> tClass,
Supplier<T> supplier,
BuilderCodec<? super T> parentCodec,
Codec<K> idCodec,
BiConsumer<T, K> idSetter,
Function<T, K> idGetter,
BiConsumer<T, AssetExtraInfo.Data> dataSetter,
@Nonnull Function<T, AssetExtraInfo.Data> dataGetter
) {
super(tClass, supplier, parentCodec);
this.idCodec = new KeyedCodec<>("Id", idCodec);
this.idSetter = idSetter;
this.dataSetter = dataSetter;
this.dataGetter = dataGetter;
this.<Map<String, String[]>>appendInherited(AssetBuilderCodec.TAGS_CODEC, (t, tags) -> dataGetter.apply(t).putTags(tags), t -> {
AssetExtraInfo.Data data = dataGetter.apply(t);
return data != null ? data.getRawTags() : null;
}, (t, parent) -> {
AssetExtraInfo.Data data = dataGetter.apply(t);
AssetExtraInfo.Data parentData = dataGetter.apply(parent);
if (data != null && parentData != null) {
data.putTags(parentData.getRawTags());
}
})
.documentation(
"Tags are a general way to describe an asset that can be interpreted by other systems in a way they see fit.\n\nFor example you could tag something with a **Material** tag with the values **Solid** and **Stone**, And another single tag **Ore**.\n\nTags will be expanded into a single list of tags automatically. Using the above example with **Material** and **Ore** the end result would be the following list of tags: **Ore**, **Material**, **Solid**, **Stone**, **Material=Solid** and **Material=Stone**."
)
.add();
}
@Nonnull
public AssetBuilderCodec<K, T> build() {
return new AssetBuilderCodec<>(this);
}
}
}

View File

@@ -0,0 +1,23 @@
package com.hypixel.hytale.assetstore.codec;
import com.hypixel.hytale.assetstore.AssetExtraInfo;
import com.hypixel.hytale.assetstore.JsonAsset;
import com.hypixel.hytale.codec.InheritCodec;
import com.hypixel.hytale.codec.KeyedCodec;
import com.hypixel.hytale.codec.util.RawJsonReader;
import com.hypixel.hytale.codec.validation.ValidatableCodec;
import java.io.IOException;
import javax.annotation.Nullable;
public interface AssetCodec<K, T extends JsonAsset<K>> extends InheritCodec<T>, ValidatableCodec<T> {
KeyedCodec<K> getKeyCodec();
KeyedCodec<K> getParentCodec();
@Nullable
AssetExtraInfo.Data getData(T var1);
T decodeJsonAsset(RawJsonReader var1, AssetExtraInfo<K> var2) throws IOException;
T decodeAndInheritJsonAsset(RawJsonReader var1, T var2, AssetExtraInfo<K> var3) throws IOException;
}

Some files were not shown because too many files have changed in this diff Show More