From 468c5d5f2b44d58bcd2ddfd90c7844d13ec4f049 Mon Sep 17 00:00:00 2001 From: hookan Date: Mon, 7 Feb 2022 23:56:16 +0800 Subject: [PATCH] port to 1.18.1 --- build.gradle | 23 +- gradle/wrapper/gradle-wrapper.jar | Bin 56177 -> 59536 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 282 +++++++++++------- gradlew.bat | 43 +-- src/main/java/org/teacon/signin/SignMeUp.java | 74 +++-- .../signin/client/ClientGuideMapManager.java | 25 +- .../teacon/signin/client/GuideMapScreen.java | 124 ++++---- .../java/org/teacon/signin/client/Hotkey.java | 14 +- .../teacon/signin/client/SignMeUpClient.java | 13 +- .../teacon/signin/command/CommandImpl.java | 234 +++++++-------- .../signin/data/DynamicLocationStorage.java | 71 ++--- .../java/org/teacon/signin/data/GuideMap.java | 36 +-- .../teacon/signin/data/GuideMapManager.java | 54 ++-- .../org/teacon/signin/data/PlayerTracker.java | 11 +- .../java/org/teacon/signin/data/Trigger.java | 36 +-- .../teacon/signin/data/Vector3iAdapter.java | 12 +- .../java/org/teacon/signin/data/Waypoint.java | 52 ++-- .../signin/network/MapScreenPacket.java | 30 +- .../signin/network/PartialUpdatePacket.java | 35 ++- .../signin/network/SyncGuideMapPacket.java | 15 +- .../signin/network/TriggerFromMapPacket.java | 10 +- .../network/TriggerFromWaypointPacket.java | 10 +- 23 files changed, 639 insertions(+), 567 deletions(-) diff --git a/build.gradle b/build.gradle index b3c381d..7dd0f60 100644 --- a/build.gradle +++ b/build.gradle @@ -4,29 +4,28 @@ import java.time.temporal.ChronoUnit buildscript { repositories { - maven { url = 'https://files.minecraftforge.net/maven' } + maven { url = 'https://maven.minecraftforge.net' } + maven { url = 'https://maven.parchmentmc.org' } mavenCentral() } dependencies { - classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '4.+', changing: true + classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true + classpath 'org.parchmentmc:librarian:1.+' } } apply plugin: 'net.minecraftforge.gradle' +apply plugin: 'org.parchmentmc.librarian.forgegradle' apply plugin: 'eclipse' apply plugin: 'maven-publish' version = '0.1.6' group = 'org.teacon' -archivesBaseName = 'SignMeUp-Forge-1.16' +archivesBaseName = 'SignMeUp-Forge-1.18' -sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8 - -compileJava { - sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8 -} +java.toolchain.languageVersion = JavaLanguageVersion.of(17) minecraft { - mappings channel: 'snapshot', version: '20210309-1.16.4' + mappings channel: 'parchment', version: '2022.01.23-1.18.1' accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') runs { @@ -70,7 +69,7 @@ minecraft { } dependencies { - minecraft 'net.minecraftforge:forge:1.16.4-35.1.0' + minecraft 'net.minecraftforge:forge:1.18.1-39.0.40' } jar { @@ -94,11 +93,11 @@ publishing { publications { release(MavenPublication) { groupId = "org.teacon" - artifactId = "SignMeUp-Forge-1.16" + artifactId = "SignMeUp-Forge-1.18" artifact jar pom { - name = 'SignMeUp for Minecraft 1.16' + name = 'SignMeUp for Minecraft 1.18' description = 'In-game sign-up, sign-in system and more' url = 'https://github.com/teaconmc/SignMeUp' licenses { diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 94336fcae912db8a11d55634156fa011f4686124..7454180f2ae8848c63b8b4dea2cb829da983f2fa 100644 GIT binary patch delta 51385 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

8j~^e*5P?UYQ`^~!nLb#D_{DdBU_KYFbP>Bi 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%0A}15$O#mvChbGF@eh4Ar%3syAIE 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�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 dG1? zP@yAg1BG=MS7;ilsI~}*_;g$UVrM1 zF`;r%mx}`2rXPQTtybVGJQ23eO|Yy^;KmoMla+cweE`UXcfm`~;~S6A{H%O;i?*7X zXxmTl6%CuP&yojDR01a73YFSzvX}B(^051yNv#4aLZBGH=A=+oiYw@YJ5?cKmeasz z7J(B}E%Y~$G(=x#D&*iY%`|jqq^fsY$~xmu;4|m|jD~Y^XKSoUl%iUcI}1mmqPP;%@YINd zwQp6Q;lLIEXDNJk86Hkiu^x9o6H;)~-B5FiN*<2L^z!1aB2MhZ+F78+df&0<*x_8C zU!O~lQV~ea5Y!pIf$q0Vxg3<9L06+JcmOH9jfW&)h@&sk&S=WY$q95NVax(tjM z^!bmv0fUjX1u)%>$aaU8c9d>#M6Tg44M8wi*#C%=SIzp!qr&*vH}aEi4f8SL%u~;IA;i zFygW?fwFV(eE+p9C#L$2K}uen>96bml?DSt7A)};2B9?m;{TTb1_q3qBYXvh0j!=Q zM*sC|2I%ukwc(!>$U(c_|2R7T0{rL3|G)v6K`K(efJeV{s_Fin1yXJ~I!@4aCU}qr z`yci|#R&X3Ps_?^WNqN&^lz3rQBiLm2t5n>kiB4KLjxV?F@g4ruPV37Tn zg*EpEL}L0M0_A2uC{itG;UUPkX#Yt9be2X2BH#lzmau+h8I=bYl#l-&D~!K$Ai#tC zKL+`hsrUh)UNRR77#Qh)@xQYoqbMO3#JHZtUYm5{7=F!LWaE{6)65i0!0vm{vY1o z0a8G6LCi0BV4A;qe5QoJtkoAD@=rv8e?K3_4?q@M0^r^%&Yw5*LdN|?8u0ocJS|Xh z?S=in^+-Y3mu?TR0D7;{f(j5+_o6_C0dT5XvzaH9q2VhPK0k92#4T?4MyCDJ+`{4q;H(-A~QODmGt@crA ze_#5$R{bqR_$#E_pGklzIsc~IZ@h4V7cx{Y@Hw6!JQ+xp>VLiOh4#}6Qk2(kQu!wF zpEv$*!J2<4T!7#B=qR-R@t7BSApbBxXY~HRNv>OO{!HX=F#u5Uh`+!`1^>oxY|;LS z|9dkxDj1l+3%p1ekY!u+Pwb0rYcH^kvA=D1Y`@6MKU;+UZMz-_!qb2@4B`K2|L=_# zpeBs#h5e2spu;!8Ke2zWVF!tCalgRMrvA45{0-|*{NJmkL9c~hYC-=T(`g_)$Nv=k zKkHHdo%!iZ5P=CevV-|&0xuQ;{$m|<)|&&ulL4!$P=WT_FRI>)WnnKk1o^)?5xZo6 zrt!z(nSZ&pb`c0q`hUFG{vL$@btGQa29eJ|zj0Ea%pSt88mGDUtHuR(fqrBByS7D7 z{aKxhdx7(N?|y;t_J4uB`+-9H0-P^v-@p4U|J<3v;EP^ND9S*A`~|e~67;7B^5O>&77XnF0kYsizyJUM diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7665b0f..e750102 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index cccdd3d..c53aefa 100755 --- a/gradlew +++ b/gradlew @@ -1,78 +1,129 @@ -#!/usr/bin/env sh +#!/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 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/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 -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_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +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="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # 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 @@ -81,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + 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 @@ -89,84 +140,95 @@ location of your Java installation." 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 +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 -# 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 +# 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" ) -# 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\"" + 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 - i=$((i+1)) + # 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 - 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" ;; - 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, 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" - -# 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")" -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" "$@" diff --git a/gradlew.bat b/gradlew.bat index e95643d..ac1b06f 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@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 @@ -13,15 +29,18 @@ 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= +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 init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +54,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% @@ -45,28 +64,14 @@ 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 diff --git a/src/main/java/org/teacon/signin/SignMeUp.java b/src/main/java/org/teacon/signin/SignMeUp.java index 268f17b..47f5107 100644 --- a/src/main/java/org/teacon/signin/SignMeUp.java +++ b/src/main/java/org/teacon/signin/SignMeUp.java @@ -1,20 +1,18 @@ package org.teacon.signin; -import net.minecraft.command.CommandSource; -import net.minecraft.command.Commands; -import net.minecraft.command.ISuggestionProvider; -import net.minecraft.command.arguments.BlockPosArgument; -import net.minecraft.command.arguments.ResourceLocationArgument; -import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.minecraft.commands.arguments.ResourceLocationArgument; +import net.minecraft.commands.arguments.coordinates.BlockPosArgument; +import net.minecraft.core.Vec3i; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.util.math.vector.Vector3i; -import net.minecraft.util.text.StringTextComponent; -import net.minecraft.world.World; -import net.minecraftforge.api.distmarker.Dist; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.common.capabilities.CapabilityManager; +import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent; import net.minecraftforge.event.AddReloadListenerEvent; import net.minecraftforge.event.AttachCapabilitiesEvent; import net.minecraftforge.event.RegisterCommandsEvent; @@ -23,8 +21,9 @@ import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.loading.FMLEnvironment; -import net.minecraftforge.fml.network.NetworkRegistry; -import net.minecraftforge.fml.network.simple.SimpleChannel; +import net.minecraftforge.network.NetworkRegistry; +import net.minecraftforge.network.simple.SimpleChannel; + import org.teacon.signin.client.SignMeUpClient; import org.teacon.signin.command.CommandImpl; import org.teacon.signin.data.DynamicLocationStorage; @@ -50,7 +49,7 @@ public SignMeUp() { } public static void setup(FMLCommonSetupEvent event) { - CapabilityManager.INSTANCE.register(DynamicLocationStorage.class, new DynamicLocationStorage.Serializer(), DynamicLocationStorage::new); + //CapabilityManager.INSTANCE.register(DynamicLocationStorage.class, new DynamicLocationStorage.Serializer(), DynamicLocationStorage::new); channel.registerMessage(0, SyncGuideMapPacket.class, SyncGuideMapPacket::write, SyncGuideMapPacket::new, SyncGuideMapPacket::handle); channel.registerMessage(1, PartialUpdatePacket.class, PartialUpdatePacket::write, PartialUpdatePacket::new, PartialUpdatePacket::handle); channel.registerMessage(2, MapScreenPacket.class, MapScreenPacket::write, MapScreenPacket::new, MapScreenPacket::handle); @@ -58,6 +57,11 @@ public static void setup(FMLCommonSetupEvent event) { channel.registerMessage(4, TriggerFromWaypointPacket.class, TriggerFromWaypointPacket::write, TriggerFromWaypointPacket::new, TriggerFromWaypointPacket::handle); } + @SubscribeEvent + public void registerCaps(RegisterCapabilitiesEvent event) { + event.register(DynamicLocationStorage.class); + } + @SubscribeEvent public static void dataLoading(AddReloadListenerEvent event) { event.addListener(MANAGER); @@ -69,11 +73,11 @@ public static void command(RegisterCommandsEvent event) { .then(Commands.literal("map") .then(Commands.literal("list").executes(CommandImpl::listMaps)) .then(Commands.literal("close") - .then(Commands.argument("id", ResourceLocationArgument.resourceLocation()) + .then(Commands.argument("id", ResourceLocationArgument.id()) .executes(CommandImpl::closeSpecificMap)) .executes(CommandImpl::closeAnyMap)) .then(Commands.literal("open") - .then(Commands.argument("id", ResourceLocationArgument.resourceLocation()) + .then(Commands.argument("id", ResourceLocationArgument.id()) .executes(CommandImpl::openSpecificMap)) .executes(CommandImpl::openNearestMap))) .then(Commands.literal("point") @@ -82,44 +86,48 @@ public static void command(RegisterCommandsEvent event) { .executes(CommandImpl::listWaypointPos)) .executes(CommandImpl::listWaypoints)) .then(Commands.literal("get") - .then(Commands.argument("id", ResourceLocationArgument.resourceLocation()) + .then(Commands.argument("id", ResourceLocationArgument.id()) .then(Commands.literal("location") .executes(CommandImpl::getWaypointPos)))) .then(Commands.literal("set") - .then(Commands.argument("id", ResourceLocationArgument.resourceLocation()) + .then(Commands.argument("id", ResourceLocationArgument.id()) .then(Commands.literal("actual") .then(Commands.argument("pos", BlockPosArgument.blockPos()).executes(CommandImpl::setWaypointActualPos))) .then(Commands.literal("render") .then(Commands.argument("pos", BlockPosArgument.blockPos()).executes(CommandImpl::setWaypointRenderPos)))))) .then(Commands.literal("trigger") - .then(Commands.argument("id", ResourceLocationArgument.resourceLocation()) - .suggests((src, builder) -> ISuggestionProvider.suggest(FMLEnvironment.dist.isClient() - ? SignMeUpClient.MANAGER.getAllTriggers().stream().map(ResourceLocation::toString) - : SignMeUp.MANAGER.getAllTriggers().stream().map(ResourceLocation::toString), builder)) - .executes(CommandImpl::trigger)))); + .then(Commands.argument("id", ResourceLocationArgument.id()) + .suggests((src, builder) -> { + if(FMLEnvironment.dist.isClient()) { + SignMeUpClient.MANAGER.getAllTriggers().stream().forEach(location -> builder.suggest(location.toString())); + } else { + SignMeUp.MANAGER.getAllTriggers().stream().forEach(location -> builder.suggest(location.toString())); + } + return builder.buildFuture(); + }).executes(CommandImpl::trigger)))); } @SubscribeEvent - public static void attachCap(AttachCapabilitiesEvent event) { + public static void attachCap(AttachCapabilitiesEvent event) { event.addCapability(new ResourceLocation("sign_up"), new DynamicLocationStorage.Holder()); } - public static boolean trigger(ServerPlayerEntity player, Vector3i pos, ResourceLocation triggerId, boolean isCommand) { + public static boolean trigger(ServerPlayer player, Vec3i pos, ResourceLocation triggerId, boolean isCommand) { final Trigger trigger = MANAGER.findTrigger(triggerId); if (trigger != null && trigger.isVisibleTo(player)) { final MinecraftServer server = player.getServer(); if (server != null) { - final Vector3d pos3d = Vector3d.copy(pos); - final CommandSource source = isCommand - ? player.getCommandSource().withPos(pos3d).withPermissionLevel(2) - : player.getCommandSource().withPos(pos3d).withFeedbackDisabled().withMinPermissionLevel(2); + final Vec3 pos3d = Vec3.atLowerCornerOf(pos); + final CommandSourceStack source = isCommand + ? player.createCommandSourceStack().withPosition(pos3d).withPermission(2) + : player.createCommandSourceStack().withPosition(pos3d).withSuppressedOutput().withMaximumPermission(2); for (String command : trigger.executes) { - server.getCommandManager().handleCommand(source, command); + server.getCommands().performCommand(source, command); } } return true; } else { - player.sendStatusMessage(new StringTextComponent("You seemed to click the void just now..."), true); + player.displayClientMessage(new TextComponent("You seemed to click the void just now..."), true); return false; } } diff --git a/src/main/java/org/teacon/signin/client/ClientGuideMapManager.java b/src/main/java/org/teacon/signin/client/ClientGuideMapManager.java index 5726e22..9974f08 100644 --- a/src/main/java/org/teacon/signin/client/ClientGuideMapManager.java +++ b/src/main/java/org/teacon/signin/client/ClientGuideMapManager.java @@ -1,10 +1,9 @@ package org.teacon.signin.client; import net.minecraft.client.Minecraft; -import net.minecraft.client.entity.player.ClientPlayerEntity; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.util.math.vector.Vector3i; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.phys.Vec3; + import org.teacon.signin.data.GuideMap; import org.teacon.signin.data.Trigger; import org.teacon.signin.data.Waypoint; @@ -18,17 +17,17 @@ public final class ClientGuideMapManager { private final Map availableWaypoints = new HashMap<>(); private final Map availableTriggers = new HashMap<>(); - public void openMapByPacket(MapScreenPacket.Action action, ResourceLocation mapId, Vector3d position) { + public void openMapByPacket(MapScreenPacket.Action action, ResourceLocation mapId, Vec3 position) { Minecraft mc = Minecraft.getInstance(); - mc.runAsync(() -> { + mc.submitAsync(() -> { if (action == MapScreenPacket.Action.OPEN_SPECIFIC) { Objects.requireNonNull(mapId); GuideMap map = SignMeUpClient.MANAGER.findMap(mapId); - mc.displayGuiScreen(new GuideMapScreen(mapId, map, position)); - } else if (mc.currentScreen instanceof GuideMapScreen) { - final GuideMapScreen screen = (GuideMapScreen) mc.currentScreen; + mc.setScreen(new GuideMapScreen(mapId, map, position)); + } else if (mc.screen instanceof GuideMapScreen) { + final GuideMapScreen screen = (GuideMapScreen) mc.screen; if (action != MapScreenPacket.Action.CLOSE_SPECIFIC || screen.mapId.equals(mapId)) { - mc.displayGuiScreen(null); + mc.setScreen(null); } } }); @@ -38,15 +37,15 @@ public synchronized void acceptUpdateFromServer(SortedMap nearestTo(Vector3d pos) { + public Map.Entry nearestTo(Vec3 pos) { double minDistanceSq = Double.MAX_VALUE; Map.Entry result = null; for (Map.Entry entry : this.availableMaps.entrySet()) { // Skip the dimension check because the client manager only knows // guide maps that are for the current dimension. final GuideMap guideMap = entry.getValue(); - final double dx = pos.getX() - guideMap.center.getX(); - final double dz = pos.getZ() - guideMap.center.getZ(); + final double dx = pos.x() - guideMap.center.getX(); + final double dz = pos.z() - guideMap.center.getZ(); if (Math.min(Math.abs(dx), Math.abs(dz)) <= guideMap.radius) { final double distanceSq = dx * dx + dz * dz; if (distanceSq < minDistanceSq) { diff --git a/src/main/java/org/teacon/signin/client/GuideMapScreen.java b/src/main/java/org/teacon/signin/client/GuideMapScreen.java index e1f8e68..692e190 100644 --- a/src/main/java/org/teacon/signin/client/GuideMapScreen.java +++ b/src/main/java/org/teacon/signin/client/GuideMapScreen.java @@ -4,20 +4,20 @@ import com.google.common.collect.ListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Queues; -import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.systems.RenderSystem; -import mcp.MethodsReturnNonnullByDefault; +import com.mojang.blaze3d.vertex.*; +import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.FontRenderer; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.widget.button.Button; -import net.minecraft.client.gui.widget.button.ImageButton; -import net.minecraft.util.IReorderingProcessor; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.util.math.vector.Vector3i; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.TranslationTextComponent; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.components.ImageButton; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.core.Vec3i; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.FormattedCharSequence; +import net.minecraft.world.phys.Vec3; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Marker; @@ -34,7 +34,8 @@ @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public final class GuideMapScreen extends Screen { +public final class GuideMapScreen extends Screen +{ private static final Logger LOGGER = LogManager.getLogger("SignMeUp"); private static final Marker MARKER = MarkerManager.getMarker("GuideMapScreen"); @@ -58,7 +59,7 @@ public final class GuideMapScreen extends Screen { private boolean hasWaypointTrigger = false; private final GuideMap map; - private final Vector3d playerLocation; + private final Vec3 playerLocation; private final List waypointIds; private PolynomialMapping mapping; @@ -71,7 +72,7 @@ public final class GuideMapScreen extends Screen { private boolean needRefresh = false; - public GuideMapScreen(ResourceLocation mapId, GuideMap map, Vector3d location) { + public GuideMapScreen(ResourceLocation mapId, GuideMap map, Vec3 location) { super(map.getTitle()); this.map = map; this.mapId = mapId; @@ -90,12 +91,12 @@ protected void init() { int x0 = (this.width - X_SIZE) / 2, y0 = (this.height - Y_SIZE) / 2, x1 = x0 + 206; // Left and Right Image Flip Button - this.leftFlip = this.addButton(new ImageButton(x1 + 7, y0 + 20, 10, 54, 155, 163, 0, GUIDE_MAP_RIGHT, new FlipHandler(1))); - this.rightFlip = this.addButton(new ImageButton(x1 + 93, y0 + 20, 10, 54, 167, 163, 0, GUIDE_MAP_RIGHT, new FlipHandler(-1))); + this.leftFlip = this.addRenderableWidget(new ImageButton(x1 + 7, y0 + 20, 10, 54, 155, 163, 0, GUIDE_MAP_RIGHT, new FlipHandler(1))); + this.rightFlip = this.addRenderableWidget(new ImageButton(x1 + 93, y0 + 20, 10, 54, 167, 163, 0, GUIDE_MAP_RIGHT, new FlipHandler(-1))); // Prev and next page for map triggers - this.mapTriggerPrev = this.addButton(new ImageButton(x0 + 6, y0 + 138, 33, 17, 66, 163, 19, GUIDE_MAP_LEFT, (btn) -> --this.mapTriggerPage)); - this.mapTriggerNext = this.addButton(new ImageButton(x0 + 39, y0 + 138, 33, 17, 99, 163, 19, GUIDE_MAP_LEFT, (btn) -> ++this.mapTriggerPage)); + this.mapTriggerPrev = this.addRenderableWidget(new ImageButton(x0 + 6, y0 + 138, 33, 17, 66, 163, 19, GUIDE_MAP_LEFT, (btn) -> --this.mapTriggerPage)); + this.mapTriggerNext = this.addRenderableWidget(new ImageButton(x0 + 39, y0 + 138, 33, 17, 99, 163, 19, GUIDE_MAP_LEFT, (btn) -> ++this.mapTriggerPage)); // Setup trigger buttons from GuideMap this.mapTriggers.clear(); @@ -107,7 +108,7 @@ protected void init() { continue; } this.mapTriggerPageSize = Math.max(this.mapTriggerPageSize, 1 + j / 6); - final TriggerButton btn = this.addButton(new TriggerButton(x0 + 8, y0 + 21 + (j % 6) * 19, 62, 18, + final TriggerButton btn = this.addRenderableWidget(new TriggerButton(x0 + 8, y0 + 21 + (j % 6) * 19, 62, 18, 2, trigger.disabled ? 203 : 163, trigger.disabled ? 0 : 20, GUIDE_MAP_LEFT, trigger, (b) -> SignMeUp.channel.sendToServer(new TriggerFromMapPacket(this.mapId, triggerId)))); this.mapTriggers.add(btn); @@ -132,11 +133,11 @@ protected void init() { final int waypointSize = waypoints.size(); final double[] inputX = new double[waypointSize], inputY = new double[waypointSize]; final double[] outputX = new double[waypointSize], outputY = new double[waypointSize]; - final Vector3i center = this.map.center; + final Vec3i center = this.map.center; for (int i = 0; i < waypointSize; ++i) { final Waypoint wp = waypoints.get(i); - final Vector3i actualLocation = wp.getActualLocation(); - final Vector3i renderLocation = wp.getRenderLocation(); + final Vec3i actualLocation = wp.getActualLocation(); + final Vec3i renderLocation = wp.getRenderLocation(); inputX[i] = actualLocation.getX() - center.getX(); inputY[i] = actualLocation.getZ() - center.getZ(); outputX[i] = renderLocation.getX() - center.getX(); @@ -158,13 +159,13 @@ protected void init() { final int wpY = Math.round((float) outputY[i] / this.map.radius * 64) + 64; if (wpX >= 1 && wpX <= 127 && wpY >= 1 && wpY <= 127) { // Setup Waypoints as ImageButtons - this.addButton(new ImageButton(mapCanvasX + wpX - 2, mapCanvasY + wpY - 2, 4, 4, 58, 2, 0, MAP_ICONS, + this.addRenderableWidget(new ImageButton(mapCanvasX + wpX - 2, mapCanvasY + wpY - 2, 4, 4, 58, 2, 0, MAP_ICONS, 128, 128, (btn) -> this.selectedWaypoint = wpId, (btn, transform, mouseX, mouseY) -> { - double distance = Math.sqrt(wp.getActualLocation().distanceSq(this.playerLocation, true)); - this.renderTooltip(transform, Arrays.asList( - wp.getTitle().func_241878_f(), - new TranslationTextComponent("sign_up.waypoint.distance", - Math.round(distance * 10.0) / 10.0).func_241878_f() + double distance = Math.sqrt(wp.getActualLocation().distSqr(this.playerLocation, true)); + this.renderComponentTooltip(transform, Arrays.asList( + wp.getTitle(), + new TranslatableComponent("sign_up.waypoint.distance", + Math.round(distance * 10.0) / 10.0) ), mouseX, mouseY); }, wp.getTitle())); // Setup trigger buttons from Waypoints @@ -175,7 +176,7 @@ protected void init() { if (trigger == null) { continue; } - TriggerButton btn = this.addButton(new TriggerButton(x1 + 109, y0 + 21 + j * 19, 62, 18, + TriggerButton btn = this.addRenderableWidget(new TriggerButton(x1 + 109, y0 + 21 + j * 19, 62, 18, 2, trigger.disabled ? 203 : 163, trigger.disabled ? 0 : 20, GUIDE_MAP_RIGHT, trigger, (b) -> SignMeUp.channel.sendToServer(new TriggerFromWaypointPacket(wpId, triggerId)))); this.waypointTriggers.put(wpId, btn); @@ -214,7 +215,7 @@ public void tick() { } @Override - public void render(MatrixStack transforms, int mouseX, int mouseY, float partialTicks) { + public void render(PoseStack transforms, int mouseX, int mouseY, float partialTicks) { final Minecraft mc = Objects.requireNonNull(this.minecraft); int x0 = (this.width - X_SIZE) / 2, y0 = (this.height - Y_SIZE) / 2, x1 = x0 + 206; @@ -226,12 +227,12 @@ public void render(MatrixStack transforms, int mouseX, int mouseY, float partial super.render(transforms, mouseX, mouseY, partialTicks); - this.renderTextCollection(this.font, transforms, x0, y0, x1); + this.renderTextCollection(transforms, x0, y0, x1); } - private void renderTextCollection(FontRenderer font, MatrixStack transforms, int x0, int y0, int x1) { + private void renderTextCollection(PoseStack transforms, int x0, int y0, int x1) { // Display the subtitle/desc of the map if no waypoint is selected - ITextComponent title = this.map.getTitle(), subtitle = this.map.getSubtitle(), desc = this.map.getDesc(); + Component title = this.map.getTitle(), subtitle = this.map.getSubtitle(), desc = this.map.getDesc(); if (this.selectedWaypoint != null) { Waypoint wp = SignMeUpClient.MANAGER.findWaypoint(this.selectedWaypoint); if (wp != null) { @@ -240,37 +241,37 @@ private void renderTextCollection(FontRenderer font, MatrixStack transforms, int } } // Draw title and subtitle depending on whether a waypoint is selected - final int xTitle = x0 + 142 - font.getStringPropertyWidth(title) / 2; - font.drawText(transforms, title, xTitle, y0 + 7F, 0x404040); - final int xSubtitle = x1 + 56 - font.getStringPropertyWidth(subtitle) / 2; - font.drawText(transforms, subtitle, xSubtitle, y0 + 7F, 0x404040); + final int xTitle = x0 + 142 - font.width(title) / 2; + font.draw(transforms, title, xTitle, y0 + 7F, 0x404040); + final int xSubtitle = x1 + 56 - font.width(subtitle) / 2; + font.draw(transforms, subtitle, xSubtitle, y0 + 7F, 0x404040); // I DISLIKE THIS METHOD BECAUSE IT FAILS TO HANDLE LINE BREAKING // A proper line breaking algorithm should comply with UAX #14, link below: // http://www.unicode.org/reports/tr14/ // However it at least get things work for now. So it is the status quo. - List displayedDescList = font.trimStringToWidth(desc, 90); + List displayedDescList = font.split(desc, 90); // Draw desc text for (int i = 0, size = Math.min(8, displayedDescList.size()); i < size; ++i) { - font.func_238422_b_(transforms, displayedDescList.get(i), x1 + 10F, y0 + 81F + 9 * i, 0x404040); + font.draw(transforms, displayedDescList.get(i), x1 + 10F, y0 + 81F + 9 * i, 0x404040); } } @SuppressWarnings("deprecation") - private void renderMapTexture(Minecraft mc, MatrixStack transforms, int x0, int y0, int x1) { + private void renderMapTexture(Minecraft mc, PoseStack transforms, int x0, int y0, int x1) { RenderSystem.enableBlend(); RenderSystem.defaultBlendFunc(); - RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); // corner of the in-game window - mc.textureManager.bindTexture(this.map.texture); + RenderSystem.setShaderTexture(0, this.map.texture); // Who said we have to use 128 * 128 texture? blit(transforms, x0 + 78, y0 + 23, 0, 0, 128, 128, 128, 128); } @SuppressWarnings("deprecation") - private void renderWaypointTexture(Minecraft mc, MatrixStack transforms, int x0, int y0, int x1, float partialTicks) { + private void renderWaypointTexture(Minecraft mc, PoseStack transforms, int x0, int y0, int x1, float partialTicks) { RenderSystem.enableBlend(); RenderSystem.defaultBlendFunc(); - RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); ResourceLocation image = this.map.getDisplayingImageId(); if (this.selectedWaypoint != null) { Waypoint wp = SignMeUpClient.MANAGER.findWaypoint(this.selectedWaypoint); @@ -295,25 +296,25 @@ private void renderWaypointTexture(Minecraft mc, MatrixStack transforms, int x0, if (this.lastWaypointTextures.isEmpty()) { this.ticksAfterWaypointTextureChanged = 0; } else { - mc.textureManager.bindTexture(head); + RenderSystem.setShaderTexture(0, head); blit(transforms, x1 + 7, y0 + 20, 0, 0, 96, 54, 96, 54); - RenderSystem.color4f(1.0F, 1.0F, 1.0F, alpha); - mc.textureManager.bindTexture(GUIDE_MAP_RIGHT); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, alpha); + RenderSystem.setShaderTexture(0, GUIDE_MAP_RIGHT); blit(transforms, x1 + 7, y0 + 20, 7, 20, 96, 54); image = this.lastWaypointTextures.getFirst(); } this.lastWaypointTextures.addFirst(head); - mc.textureManager.bindTexture(image); + RenderSystem.setShaderTexture(0, image); blit(transforms, x1 + 7, y0 + 20, 0, 0, 96, 54, 96, 54); } @SuppressWarnings("deprecation") - private void renderBackgroundTexture(Minecraft mc, MatrixStack transforms, int x0, int y0, int x1) { - RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); - mc.textureManager.bindTexture(GUIDE_MAP_LEFT); + private void renderBackgroundTexture(Minecraft mc, PoseStack transforms, int x0, int y0, int x1) { + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderTexture(0, GUIDE_MAP_LEFT); blit(transforms, x0, y0, 0, 0, 211, 161); blit(transforms, x0 + 6, y0 + 138, 66, 201, 66, 17); - mc.textureManager.bindTexture(GUIDE_MAP_RIGHT); + RenderSystem.setShaderTexture(0, GUIDE_MAP_RIGHT); blit(transforms, x1 + 5, y0, 5, 0, 174, 161); if (!this.hasWaypointTrigger) { blit(transforms, x1 + 108, y0 + 20, 181, 20, 64, 134); @@ -341,7 +342,8 @@ public boolean isPauseScreen() { return false; } - private final class FlipHandler implements Button.IPressable { + private final class FlipHandler implements Button.OnPress + { private final int diff; private FlipHandler(int diff) { @@ -365,19 +367,19 @@ private final class TriggerButton extends ImageButton { private final Trigger trigger; private TriggerButton(int x, int y, int width, int height, int uOffset, int vOffset, int vDiff, - ResourceLocation image, Trigger trigger, IPressable pressable) { + ResourceLocation image, Trigger trigger, OnPress pressable) { super(x, y, width, height, uOffset, vOffset, vDiff, image, pressable); this.trigger = trigger; } @Override - public void renderWidget(MatrixStack transforms, int mouseX, int mouseY, float partialTicks) { - super.renderWidget(transforms, mouseX, mouseY, partialTicks); - final FontRenderer font = Minecraft.getInstance().fontRenderer; - final int stringWidth = font.getStringPropertyWidth(this.trigger.getTitle()); + public void renderButton(PoseStack transforms, int mouseX, int mouseY, float partialTicks) { + super.renderButton(transforms, mouseX, mouseY, partialTicks); + //final Font font = Minecraft.getInstance().font; + final int stringWidth = font.width(this.trigger.getTitle()); final int x0 = this.x + this.width / 2 - stringWidth / 2, y0 = this.y + (this.height - 8) / 2; - font.drawText(transforms, this.trigger.getTitle(), x0, y0, this.trigger.disabled ? 0xFFFFFF : 0x404040); - if (this.isHovered()) { + font.draw(transforms, this.trigger.getTitle(), x0, y0, this.trigger.disabled ? 0xFFFFFF : 0x404040); + if (this.isHovered) { GuideMapScreen.this.renderTooltip(transforms, this.trigger.getDesc(), mouseX, mouseY); } } diff --git a/src/main/java/org/teacon/signin/client/Hotkey.java b/src/main/java/org/teacon/signin/client/Hotkey.java index 442e781..8aede6f 100644 --- a/src/main/java/org/teacon/signin/client/Hotkey.java +++ b/src/main/java/org/teacon/signin/client/Hotkey.java @@ -1,9 +1,9 @@ package org.teacon.signin.client; import net.minecraft.client.Minecraft; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.util.text.TranslationTextComponent; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.phys.Vec3; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.event.InputEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; @@ -17,15 +17,15 @@ public final class Hotkey { @SubscribeEvent public static void keyTyped(InputEvent.KeyInputEvent event) { - if (SignMeUpClient.keyOpenMap != null && SignMeUpClient.keyOpenMap.isPressed()) { + if (SignMeUpClient.keyOpenMap != null && SignMeUpClient.keyOpenMap.isDown()) { Minecraft mc = Minecraft.getInstance(); if (mc.player != null) { - final Vector3d position = mc.player.getPositionVec(); + final Vec3 position = mc.player.position(); final Map.Entry entry = SignMeUpClient.MANAGER.nearestTo(position); if (entry != null) { - mc.displayGuiScreen(new GuideMapScreen(entry.getKey(), entry.getValue(), position)); + mc.setScreen(new GuideMapScreen(entry.getKey(), entry.getValue(), position)); } else { - mc.player.sendStatusMessage(new TranslationTextComponent("sign_up.status.no_map_available"), true); + mc.player.displayClientMessage(new TranslatableComponent("sign_up.status.no_map_available"), true); } } } diff --git a/src/main/java/org/teacon/signin/client/SignMeUpClient.java b/src/main/java/org/teacon/signin/client/SignMeUpClient.java index cf318e4..cbebea8 100644 --- a/src/main/java/org/teacon/signin/client/SignMeUpClient.java +++ b/src/main/java/org/teacon/signin/client/SignMeUpClient.java @@ -1,27 +1,28 @@ package org.teacon.signin.client; -import net.minecraft.client.settings.KeyBinding; -import net.minecraft.client.util.InputMappings; +import com.mojang.blaze3d.platform.InputConstants; +import net.minecraft.client.KeyMapping; import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.ClientRegistry; import net.minecraftforge.client.settings.KeyConflictContext; import net.minecraftforge.client.settings.KeyModifier; import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.client.registry.ClientRegistry; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import org.lwjgl.glfw.GLFW; + @Mod.EventBusSubscriber(modid = "sign_up", bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) public final class SignMeUpClient { public static final ClientGuideMapManager MANAGER = new ClientGuideMapManager(); - static KeyBinding keyOpenMap; + static KeyMapping keyOpenMap; @SubscribeEvent public static void setup(FMLClientSetupEvent event) { - ClientRegistry.registerKeyBinding(keyOpenMap = new KeyBinding("sign_up.keybinding.open_map", + ClientRegistry.registerKeyBinding(keyOpenMap = new KeyMapping("sign_up.keybinding.open_map", KeyConflictContext.IN_GAME, KeyModifier.NONE, - InputMappings.Type.KEYSYM, GLFW.GLFW_KEY_M, "sign_up.keybinding")); + InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_M, "sign_up.keybinding")); } } diff --git a/src/main/java/org/teacon/signin/command/CommandImpl.java b/src/main/java/org/teacon/signin/command/CommandImpl.java index 304eac0..1ac10a0 100644 --- a/src/main/java/org/teacon/signin/command/CommandImpl.java +++ b/src/main/java/org/teacon/signin/command/CommandImpl.java @@ -4,22 +4,22 @@ import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.datafixers.util.Function4; -import net.minecraft.command.CommandSource; -import net.minecraft.command.arguments.ResourceLocationArgument; -import net.minecraft.entity.player.ServerPlayerEntity; -import net.minecraft.util.RegistryKey; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.util.math.vector.Vector3i; -import net.minecraft.util.text.StringTextComponent; -import net.minecraft.util.text.TranslationTextComponent; -import net.minecraft.world.World; -import net.minecraftforge.fml.network.NetworkDirection; + +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.arguments.ResourceLocationArgument; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.network.NetworkDirection; + import org.teacon.signin.SignMeUp; import org.teacon.signin.data.DynamicLocationStorage; import org.teacon.signin.data.GuideMap; -import org.teacon.signin.data.Trigger; import org.teacon.signin.data.Waypoint; import org.teacon.signin.network.MapScreenPacket; @@ -30,99 +30,99 @@ * This class contains command execution implementations */ public final class CommandImpl { - public static final TranslationTextComponent ERROR = new TranslationTextComponent("sign_up.text.error"); + public static final TranslatableComponent ERROR = new TranslatableComponent("sign_up.text.error"); - public static int trigger(CommandContext context) throws CommandSyntaxException { - final ResourceLocation triggerId = ResourceLocationArgument.getResourceLocation(context, "id"); - final BlockPos pos = new BlockPos(context.getSource().getPos()); - final ServerPlayerEntity src = context.getSource().asPlayer(); + public static int trigger(CommandContext context) throws CommandSyntaxException { + final ResourceLocation triggerId = ResourceLocationArgument.getId(context, "id"); + final BlockPos pos = new BlockPos(context.getSource().getPosition()); + final ServerPlayer src = context.getSource().getPlayerOrException(); return SignMeUp.trigger(src, pos, triggerId, true) ? 1 : 0; } - public static int listMaps(CommandContext context) { - CommandSource src = context.getSource(); + public static int listMaps(CommandContext context) { + CommandSourceStack src = context.getSource(); if (SignMeUp.MANAGER.getAllMaps().size() != 0) { - src.sendFeedback(new TranslationTextComponent("sign_up.text.list_maps") - .appendString(": ") + src.sendSuccess(new TranslatableComponent("sign_up.text.list_maps") + .append(": ") , false); for (GuideMap map : SignMeUp.MANAGER.getAllMaps()) { - src.sendFeedback(map.getTitle(), false); + src.sendSuccess(map.getTitle(), false); } return Command.SINGLE_SUCCESS; } else { - src.sendErrorMessage(ERROR - .appendString(": ") - .appendSibling(new TranslationTextComponent("sign_up.text.no_map_exists")) + src.sendFailure(ERROR + .append(": ") + .append(new TranslatableComponent("sign_up.text.no_map_exists")) ); return -1; } } - public static int closeSpecificMap(CommandContext context) throws CommandSyntaxException { - CommandSource src = context.getSource(); - ServerPlayerEntity player = context.getSource().asPlayer(); + public static int closeSpecificMap(CommandContext context) throws CommandSyntaxException { + CommandSourceStack src = context.getSource(); + ServerPlayer player = context.getSource().getPlayerOrException(); final ResourceLocation id = context.getArgument("id", ResourceLocation.class); GuideMap map = SignMeUp.MANAGER.findMap(id); if (map != null) { // Here we have to send a packet to client side // for rendering the map GUI - MapScreenPacket packet = new MapScreenPacket(MapScreenPacket.Action.CLOSE_SPECIFIC, src.getPos(), id); - SignMeUp.channel.sendTo(packet, player.connection.netManager, NetworkDirection.PLAY_TO_CLIENT); + MapScreenPacket packet = new MapScreenPacket(MapScreenPacket.Action.CLOSE_SPECIFIC, src.getPosition(), id); + SignMeUp.channel.sendTo(packet, player.connection.getConnection(), NetworkDirection.PLAY_TO_CLIENT); return Command.SINGLE_SUCCESS; } else { - src.sendErrorMessage(ERROR - .appendString(": ") - .appendSibling(new TranslationTextComponent("sign_up.text.map")) - .appendString(" " + id.toString() + " ") - .appendSibling(new TranslationTextComponent("sign_up.text.does_not_exist")) + src.sendFailure(ERROR + .append(": ") + .append(new TranslatableComponent("sign_up.text.map")) + .append(" " + id.toString() + " ") + .append(new TranslatableComponent("sign_up.text.does_not_exist")) ); return -1; } } - public static int closeAnyMap(CommandContext context) throws CommandSyntaxException { - ServerPlayerEntity player = context.getSource().asPlayer(); - MapScreenPacket packet = new MapScreenPacket(MapScreenPacket.Action.CLOSE_ANY, Vector3d.ZERO, null); - SignMeUp.channel.sendTo(packet, player.connection.netManager, NetworkDirection.PLAY_TO_CLIENT); + public static int closeAnyMap(CommandContext context) throws CommandSyntaxException { + ServerPlayer player = context.getSource().getPlayerOrException(); + MapScreenPacket packet = new MapScreenPacket(MapScreenPacket.Action.CLOSE_ANY, Vec3.ZERO, null); + SignMeUp.channel.sendTo(packet, player.connection.getConnection(), NetworkDirection.PLAY_TO_CLIENT); return Command.SINGLE_SUCCESS; } - public static int openSpecificMap(CommandContext context) throws CommandSyntaxException { - CommandSource src = context.getSource(); - ServerPlayerEntity player = context.getSource().asPlayer(); + public static int openSpecificMap(CommandContext context) throws CommandSyntaxException { + CommandSourceStack src = context.getSource(); + ServerPlayer player = context.getSource().getPlayerOrException(); final ResourceLocation id = context.getArgument("id", ResourceLocation.class); GuideMap map = SignMeUp.MANAGER.findMap(id); if (map != null) { // Here we have to send a packet to client side // for rendering the map GUI - final MapScreenPacket packet = new MapScreenPacket(MapScreenPacket.Action.OPEN_SPECIFIC, src.getPos(), id); - SignMeUp.channel.sendTo(packet, player.connection.netManager, NetworkDirection.PLAY_TO_CLIENT); + final MapScreenPacket packet = new MapScreenPacket(MapScreenPacket.Action.OPEN_SPECIFIC, src.getPosition(), id); + SignMeUp.channel.sendTo(packet, player.connection.getConnection(), NetworkDirection.PLAY_TO_CLIENT); return Command.SINGLE_SUCCESS; } else { - src.sendErrorMessage(ERROR - .appendString(": ") - .appendSibling(new TranslationTextComponent("sign_up.text.map")) - .appendString(" " + id.toString() + " ") - .appendSibling(new TranslationTextComponent("sign_up.text.does_not_exist")) + src.sendFailure(ERROR + .append(": ") + .append(new TranslatableComponent("sign_up.text.map")) + .append(" " + id.toString() + " ") + .append(new TranslatableComponent("sign_up.text.does_not_exist")) ); return -1; } } - public static int openNearestMap(CommandContext context) throws CommandSyntaxException { - CommandSource src = context.getSource(); - ServerPlayerEntity player = src.asPlayer(); - RegistryKey worldKey = src.getWorld().getDimensionKey(); + public static int openNearestMap(CommandContext context) throws CommandSyntaxException { + CommandSourceStack src = context.getSource(); + ServerPlayer player = src.getPlayerOrException(); + ResourceKey worldKey = src.getLevel().dimension(); GuideMap map = null; double minDistanceSq = Double.MAX_VALUE; // We first check the dimension - if (src.asPlayer().world.getDimensionKey() == worldKey) { + if (src.getPlayerOrException().getLevel().dimension() == worldKey) { // Then we look for the nearest in-range map for (GuideMap guideMap : SignMeUp.MANAGER.getAllMaps()) { - final double dx = src.getPos().getX() - guideMap.center.getX(); - final double dz = src.getPos().getZ() - guideMap.center.getZ(); + final double dx = src.getPosition().x() - guideMap.center.getX(); + final double dz = src.getPosition().z() - guideMap.center.getZ(); if (Math.min(Math.abs(dx), Math.abs(dz)) <= guideMap.radius) { final double distanceSq = dx * dx + dz * dz; if (distanceSq < minDistanceSq) { @@ -135,128 +135,128 @@ public static int openNearestMap(CommandContext context) throws C if (map != null) { // Same packet as above - final MapScreenPacket packet = new MapScreenPacket(MapScreenPacket.Action.OPEN_SPECIFIC, src.getPos(), SignMeUp.MANAGER.findMapId(map)); - SignMeUp.channel.sendTo(packet, player.connection.netManager, NetworkDirection.PLAY_TO_CLIENT); + final MapScreenPacket packet = new MapScreenPacket(MapScreenPacket.Action.OPEN_SPECIFIC, src.getPosition(), SignMeUp.MANAGER.findMapId(map)); + SignMeUp.channel.sendTo(packet, player.connection.getConnection(), NetworkDirection.PLAY_TO_CLIENT); return Command.SINGLE_SUCCESS; } else { - src.sendErrorMessage(ERROR - .appendString(": ") - .appendSibling(new TranslationTextComponent("sign_up.status.no_map_available")) + src.sendFailure(ERROR + .append(": ") + .append(new TranslatableComponent("sign_up.status.no_map_available")) ); return -1; } } - public static int listWaypoints(CommandContext context) throws CommandSyntaxException { - CommandSource src = context.getSource(); - ServerPlayerEntity player = src.asPlayer(); + public static int listWaypoints(CommandContext context) throws CommandSyntaxException { + CommandSourceStack src = context.getSource(); + ServerPlayer player = src.getPlayerOrException(); if (SignMeUp.MANAGER.getAllWaypoints().size() != 0) { - src.sendFeedback(new TranslationTextComponent("sign_up.text.list_points") - .appendString(": ") + src.sendSuccess(new TranslatableComponent("sign_up.text.list_points") + .append(": ") , false); for (Waypoint waypoint : SignMeUp.MANAGER.getAllWaypoints()) { DecimalFormat df = new DecimalFormat("0.00"); df.setRoundingMode(RoundingMode.HALF_UP); - src.sendFeedback(new StringTextComponent(" - ") - .appendSibling(waypoint.getTitle()).appendString("\n ") - .appendSibling(new TranslationTextComponent("sign_up.text.distance")) - .appendString(": " + df.format(Vector3d.copy(waypoint.getActualLocation()).distanceTo(src.getPos())) + " ") - .appendSibling(new TranslationTextComponent("sign_up.text.blocks_away")) + src.sendSuccess(new TextComponent(" - ") + .append(waypoint.getTitle()).append("\n ") + .append(new TranslatableComponent("sign_up.text.distance")) + .append(": " + df.format(Vec3.atLowerCornerOf(waypoint.getActualLocation()).distanceTo(src.getPosition())) + " ") + .append(new TranslatableComponent("sign_up.text.blocks_away")) , false ); } return Command.SINGLE_SUCCESS; } else { - src.sendErrorMessage(ERROR.appendString(": ").appendSibling(new TranslationTextComponent("sign_up.text.no_waypoint_exists"))); + src.sendFailure(ERROR.append(": ").append(new TranslatableComponent("sign_up.text.no_waypoint_exists"))); return -1; } } - public static int listWaypointPos(CommandContext context) { - CommandSource src = context.getSource(); + public static int listWaypointPos(CommandContext context) { + CommandSourceStack src = context.getSource(); if (SignMeUp.MANAGER.getAllWaypoints().size() != 0) { - src.sendFeedback(new TranslationTextComponent("sign_up.text.list_points"), false); + src.sendSuccess(new TranslatableComponent("sign_up.text.list_points"), false); for (Waypoint waypoint : SignMeUp.MANAGER.getAllWaypoints()) { - src.sendFeedback(new StringTextComponent(" - ") - .appendSibling(waypoint.getTitle()) - .appendString("\n ") - .appendSibling(new TranslationTextComponent("sign_up.text.render_location")) - .appendString(": ") - .appendString(waypoint.getRenderLocation().getCoordinatesAsString()) - .appendString("\n ") - .appendSibling(new TranslationTextComponent("sign_up.text.actual_location")) - .appendString(": ") - .appendString(waypoint.getActualLocation().getCoordinatesAsString()) + src.sendSuccess(new TextComponent(" - ") + .append(waypoint.getTitle()) + .append("\n ") + .append(new TranslatableComponent("sign_up.text.render_location")) + .append(": ") + .append(waypoint.getRenderLocation().toShortString()) + .append("\n ") + .append(new TranslatableComponent("sign_up.text.actual_location")) + .append(": ") + .append(waypoint.getActualLocation().toShortString()) , false ); } return Command.SINGLE_SUCCESS; } else { - src.sendErrorMessage(ERROR.appendString(": ").appendSibling(new TranslationTextComponent("sign_up.text.no_waypoint_exists"))); + src.sendFailure(ERROR.append(": ").append(new TranslatableComponent("sign_up.text.no_waypoint_exists"))); return -1; } } - public static int getWaypointPos(CommandContext context) { - CommandSource src = context.getSource(); + public static int getWaypointPos(CommandContext context) { + CommandSourceStack src = context.getSource(); final ResourceLocation id = context.getArgument("id", ResourceLocation.class); Waypoint waypoint = SignMeUp.MANAGER.findWaypoint(id); if (waypoint != null) { - src.sendFeedback(new StringTextComponent(" - ") - .appendSibling(waypoint.getTitle()) - .appendString("\n ") - .appendSibling(new TranslationTextComponent("sign_up.text.render_location")) - .appendString(": ") - .appendString(waypoint.getRenderLocation().getCoordinatesAsString()) - .appendString("\n ") - .appendSibling(new TranslationTextComponent("sign_up.text.actual_location")) - .appendString(": ") - .appendString(waypoint.getActualLocation().getCoordinatesAsString()) + src.sendSuccess(new TextComponent(" - ") + .append(waypoint.getTitle()) + .append("\n ") + .append(new TranslatableComponent("sign_up.text.render_location")) + .append(": ") + .append(waypoint.getRenderLocation().toShortString()) + .append("\n ") + .append(new TranslatableComponent("sign_up.text.actual_location")) + .append(": ") + .append(waypoint.getActualLocation().toShortString()) , false ); return Command.SINGLE_SUCCESS; } else { - src.sendErrorMessage(new StringTextComponent("Error: waypoint " + id + " does not exist")); - src.sendErrorMessage(ERROR - .appendString(": ") - .appendSibling(new TranslationTextComponent("sign_up.text.waypoint") - .appendString(" " + id.toString() + " ") - .appendSibling(new TranslationTextComponent("sign_up.text.does_not_exist"))) + src.sendFailure(new TextComponent("Error: waypoint " + id + " does not exist")); + src.sendFailure(ERROR + .append(": ") + .append(new TranslatableComponent("sign_up.text.waypoint") + .append(" " + id.toString() + " ") + .append(new TranslatableComponent("sign_up.text.does_not_exist"))) ); return -1; } } - public static int setWaypointActualPos(CommandContext context) { - return setDynamicWaypointPosImpl(context, (store, id, world, pos) -> { - store.setActual(id, world, pos); + public static int setWaypointActualPos(CommandContext context) { + return setDynamicWaypointPosImpl(context, (store, id, level, pos) -> { + store.setActual(id, level, pos); return Command.SINGLE_SUCCESS; }); } - public static int setWaypointRenderPos(CommandContext context) { - return setDynamicWaypointPosImpl(context, (store, id, world, pos) -> { - store.setRendering(id, world, pos); + public static int setWaypointRenderPos(CommandContext context) { + return setDynamicWaypointPosImpl(context, (store, id, level, pos) -> { + store.setRendering(id, level, pos); return Command.SINGLE_SUCCESS; }); } - public static int setDynamicWaypointPosImpl(CommandContext context, Function4 handler) { - final CommandSource src = context.getSource(); - final World world = src.getWorld(); + public static int setDynamicWaypointPosImpl(CommandContext context, Function4 handler) { + final CommandSourceStack src = context.getSource(); + final Level level = src.getLevel(); final BlockPos pos = context.getArgument("pos", BlockPos.class); final ResourceLocation id = context.getArgument("id", ResourceLocation.class); final Waypoint wp = SignMeUp.MANAGER.findWaypoint(id); if (wp != null) { if (wp.hasDynamicLocation()) { - return world.getCapability(DynamicLocationStorage.CAP).map(store -> handler.apply(store, id, world, pos)).orElse(-1); + return level.getCapability(DynamicLocationStorage.CAP).map(store -> handler.apply(store, id, level, pos)).orElse(-1); } else { - src.sendErrorMessage(new StringTextComponent("Error: waypoint " + id + " is static")); + src.sendFailure(new TextComponent("Error: waypoint " + id + " is static")); return -1; } } else { - src.sendErrorMessage(new StringTextComponent("Error: waypoint " + id + " does not exist")); + src.sendFailure(new TextComponent("Error: waypoint " + id + " does not exist")); return -1; } } diff --git a/src/main/java/org/teacon/signin/data/DynamicLocationStorage.java b/src/main/java/org/teacon/signin/data/DynamicLocationStorage.java index 3959b8a..e69b3d9 100644 --- a/src/main/java/org/teacon/signin/data/DynamicLocationStorage.java +++ b/src/main/java/org/teacon/signin/data/DynamicLocationStorage.java @@ -1,15 +1,14 @@ package org.teacon.signin.data; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.nbt.INBT; -import net.minecraft.nbt.NBTDynamicOps; -import net.minecraft.util.Direction; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.GlobalPos; -import net.minecraft.world.World; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.GlobalPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.Level; import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.capabilities.CapabilityInject; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.util.INBTSerializable; import net.minecraftforge.common.util.LazyOptional; @@ -25,7 +24,6 @@ public final class DynamicLocationStorage { private static final Logger LOGGER = LogManager.getLogger("SignMeUp"); - @CapabilityInject(DynamicLocationStorage.class) public static Capability CAP; final Map pos = new HashMap<>(); @@ -39,30 +37,27 @@ public GlobalPos getRendering(ResourceLocation id) { return renderPos.get(id); } - public void setActual(ResourceLocation id, World world, BlockPos pos) { - this.pos.put(id, GlobalPos.getPosition(world.getDimensionKey(), pos)); + public void setActual(ResourceLocation id, Level level, BlockPos pos) { + this.pos.put(id, GlobalPos.of(level.dimension(), pos)); } - public void setRendering(ResourceLocation id, World world, BlockPos pos) { - this.renderPos.put(id, GlobalPos.getPosition(world.getDimensionKey(), pos)); + public void setRendering(ResourceLocation id, Level level, BlockPos pos) { + this.renderPos.put(id, GlobalPos.of(level.dimension(), pos)); } - public static final class Serializer implements Capability.IStorage { - - @Override - public INBT writeNBT(Capability capability, DynamicLocationStorage instance, Direction side) { + public static final class Serializer { + public Tag writeNBT(Capability capability, DynamicLocationStorage instance, Direction side) { return writeNBTImpl(instance); } - @Override - public void readNBT(Capability capability, DynamicLocationStorage instance, Direction side, INBT nbt) { + public void readNBT(Capability capability, DynamicLocationStorage instance, Direction side, Tag nbt) { readNBTImpl(instance, nbt); } - public static CompoundNBT writeNBTImpl(DynamicLocationStorage instance) { - final CompoundNBT data = new CompoundNBT(); - final CompoundNBT actualPoses = new CompoundNBT(); - final CompoundNBT renderPoses = new CompoundNBT(); + public static CompoundTag writeNBTImpl(DynamicLocationStorage instance) { + final CompoundTag data = new CompoundTag(); + final CompoundTag actualPoses = new CompoundTag(); + final CompoundTag renderPoses = new CompoundTag(); instance.pos.forEach((id, pos) -> collect(id, pos, actualPoses)); instance.renderPos.forEach((id, pos) -> collect(id, pos, renderPoses)); data.put("actual", actualPoses); @@ -70,26 +65,26 @@ public static CompoundNBT writeNBTImpl(DynamicLocationStorage instance) { return data; } - public static void readNBTImpl(DynamicLocationStorage instance, INBT nbt) { - if (nbt instanceof CompoundNBT) { - final CompoundNBT data = (CompoundNBT) nbt; - final CompoundNBT actualPoses = data.getCompound("actual"); - final CompoundNBT renderPoses = data.getCompound("render"); - actualPoses.keySet().forEach(id -> parse(actualPoses, id, instance.pos)); - renderPoses.keySet().forEach(id -> parse(renderPoses, id, instance.renderPos)); + public static void readNBTImpl(DynamicLocationStorage instance, Tag nbt) { + if (nbt instanceof CompoundTag) { + final CompoundTag data = (CompoundTag) nbt; + final CompoundTag actualPoses = data.getCompound("actual"); + final CompoundTag renderPoses = data.getCompound("render"); + actualPoses.getAllKeys().forEach(id -> parse(actualPoses, id, instance.pos)); + renderPoses.getAllKeys().forEach(id -> parse(renderPoses, id, instance.renderPos)); } } - private static void collect(ResourceLocation id, GlobalPos pos, CompoundNBT dst) { - dst.put(id.toString(), GlobalPos.CODEC.encodeStart(NBTDynamicOps.INSTANCE, pos).getOrThrow(false, LOGGER::warn)); + private static void collect(ResourceLocation id, GlobalPos pos, CompoundTag dst) { + dst.put(id.toString(), GlobalPos.CODEC.encodeStart(NbtOps.INSTANCE, pos).getOrThrow(false, LOGGER::warn)); } - private static void parse(CompoundNBT src, String id, Map dst) { - dst.put(new ResourceLocation(id), GlobalPos.CODEC.parse(NBTDynamicOps.INSTANCE, src.get(id)).getOrThrow(false, LOGGER::warn)); + private static void parse(CompoundTag src, String id, Map dst) { + dst.put(new ResourceLocation(id), GlobalPos.CODEC.parse(NbtOps.INSTANCE, src.get(id)).getOrThrow(false, LOGGER::warn)); } } - public static final class Holder implements ICapabilityProvider, INBTSerializable { + public static final class Holder implements ICapabilityProvider, INBTSerializable { private final DynamicLocationStorage storage = new DynamicLocationStorage(); private final LazyOptional wrapped = LazyOptional.of(() -> this.storage); @@ -101,12 +96,12 @@ public LazyOptional getCapability(@Nonnull Capability cap, @Nullable D } @Override - public CompoundNBT serializeNBT() { + public CompoundTag serializeNBT() { return Serializer.writeNBTImpl(this.storage); } @Override - public void deserializeNBT(CompoundNBT nbt) { + public void deserializeNBT(CompoundTag nbt) { Serializer.readNBTImpl(this.storage, nbt); } } diff --git a/src/main/java/org/teacon/signin/data/GuideMap.java b/src/main/java/org/teacon/signin/data/GuideMap.java index 70b55e9..e4971b1 100644 --- a/src/main/java/org/teacon/signin/data/GuideMap.java +++ b/src/main/java/org/teacon/signin/data/GuideMap.java @@ -10,11 +10,11 @@ import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; import com.google.gson.JsonSyntaxException; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.vector.Vector3i; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.StringTextComponent; -import net.minecraft.util.text.TranslationTextComponent; +import net.minecraft.core.Vec3i; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.resources.ResourceLocation; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Marker; @@ -29,11 +29,11 @@ public final class GuideMap { public static final ResourceLocation DEFAULT_IMAGE = new ResourceLocation("sign_up:textures/map_default.png"); - ITextComponent title; - ITextComponent subtitle; - ITextComponent desc; + Component title; + Component subtitle; + Component desc; - public Vector3i center; + public Vec3i center; public float radius = 128F; public ResourceLocation dim = null; @@ -47,16 +47,16 @@ public final class GuideMap { List waypointIds = Collections.emptyList(); List triggerIds = Collections.emptyList(); - public ITextComponent getTitle() { - return this.title != null ? this.title : new TranslationTextComponent("sign_up.map.unnamed"); + public Component getTitle() { + return this.title != null ? this.title : new TranslatableComponent("sign_up.map.unnamed"); } - public ITextComponent getSubtitle() { + public Component getSubtitle() { return this.subtitle != null ? this.subtitle : this.getTitle(); } - public ITextComponent getDesc() { - return this.desc != null ? this.desc : StringTextComponent.EMPTY; + public Component getDesc() { + return this.desc != null ? this.desc : TextComponent.EMPTY; } public boolean hasMoreThanOneImage() { @@ -94,16 +94,16 @@ public GuideMap deserialize(JsonElement src, Type type, JsonDeserializationConte } final JsonObject json = src.getAsJsonObject(); if (json.has("title")) { - map.title = context.deserialize(json.get("title"), ITextComponent.class); + map.title = context.deserialize(json.get("title"), Component.class); } if (json.has("subtitle")) { - map.subtitle = context.deserialize(json.get("subtitle"), ITextComponent.class); + map.subtitle = context.deserialize(json.get("subtitle"), Component.class); } if (json.has("description")) { - map.desc = context.deserialize(json.get("description"), ITextComponent.class); + map.desc = context.deserialize(json.get("description"), Component.class); } if (json.has("center")) { - map.center = context.deserialize(json.get("center"), Vector3i.class); + map.center = context.deserialize(json.get("center"), Vec3i.class); } else { LOGGER.warn(MARKER, "Center coordinate missing, falling back to [0, 0]."); } diff --git a/src/main/java/org/teacon/signin/data/GuideMapManager.java b/src/main/java/org/teacon/signin/data/GuideMapManager.java index a1cee7a..ecc644d 100644 --- a/src/main/java/org/teacon/signin/data/GuideMapManager.java +++ b/src/main/java/org/teacon/signin/data/GuideMapManager.java @@ -5,19 +5,19 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.minecraft.client.resources.JsonReloadListener; // To anyone who are shocked: yes this class exists on both side! -import net.minecraft.entity.player.ServerPlayerEntity; -import net.minecraft.profiler.IProfiler; -import net.minecraft.resources.IResourceManager; +import net.minecraft.core.Vec3i; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.vector.Vector3i; -import net.minecraft.util.text.ITextComponent; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; +import net.minecraft.util.profiling.ProfilerFiller; import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.entity.EntityJoinWorldEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.network.NetworkDirection; -import net.minecraftforge.fml.server.ServerLifecycleHooks; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.server.ServerLifecycleHooks; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Marker; @@ -35,18 +35,18 @@ import java.util.TreeMap; import java.util.WeakHashMap; -public final class GuideMapManager extends JsonReloadListener { +public final class GuideMapManager extends SimpleJsonResourceReloadListener { private static final Logger LOGGER = LogManager.getLogger("SignMeUp"); private static final Marker MARKER = MarkerManager.getMarker("GuideMapManager"); private static final Gson GSON = new GsonBuilder().setLenient() - .registerTypeHierarchyAdapter(ITextComponent.class, new ITextComponent.Serializer()) + .registerTypeHierarchyAdapter(Component.class, new Component.Serializer()) .registerTypeAdapter(GuideMap.class, new GuideMap.Serializer()) .registerTypeAdapter(Waypoint.class, new Waypoint.Serializer()) .registerTypeAdapter(Waypoint.Location.class, new Waypoint.Location.Serializer()) .registerTypeAdapter(Trigger.class, new Trigger.Serializer()) - .registerTypeAdapter(Vector3i.class, new Vector3iAdapter()) + .registerTypeAdapter(Vec3i.class, new Vector3iAdapter()) .create(); private static void setDiff(Set a, Set b, Set aMinusB, Set bMinusA) { @@ -74,15 +74,15 @@ public GuideMapManager() { @SubscribeEvent public void sync(EntityJoinWorldEvent event) { // Being a ServerPlayerEntity implies a logical server, thus no isRemote check. - if (event.getEntity() instanceof ServerPlayerEntity) { - final ServerPlayerEntity p = (ServerPlayerEntity) event.getEntity(); + if (event.getEntity() instanceof ServerPlayer) { + final ServerPlayer p = (ServerPlayer) event.getEntity(); final SortedMap mapsToSend = new TreeMap<>(); this.maps.forEach((id, map) -> { - if (p.world.getDimensionKey().getLocation().equals(map.dim)) { + if (p.level.dimension().location().equals(map.dim)) { mapsToSend.put(id, map); } }); - SignMeUp.channel.sendTo(new SyncGuideMapPacket(mapsToSend), p.connection.netManager, NetworkDirection.PLAY_TO_CLIENT); + SignMeUp.channel.sendTo(new SyncGuideMapPacket(mapsToSend), p.connection.getConnection(), NetworkDirection.PLAY_TO_CLIENT); } } @@ -110,32 +110,32 @@ private static void tickOne(ResourceLocation id, PlayerTracker trackingComponent * packet so the client manager will receive that waypoint. * These players form the set diff 2 - 1. */ - final Set matched = Collections.newSetFromMap(new WeakHashMap<>()); + final Set matched = Collections.newSetFromMap(new WeakHashMap<>()); try { - matched.addAll(trackingComponent.getSelector().selectPlayers(server.getCommandSource())); + matched.addAll(trackingComponent.getSelector().findPlayers(server.createCommandSourceStack())); } catch (CommandSyntaxException e) { return; } - final Set update = Collections.newSetFromMap(new IdentityHashMap<>()); - final Set removal = Collections.newSetFromMap(new IdentityHashMap<>()); + final Set update = Collections.newSetFromMap(new IdentityHashMap<>()); + final Set removal = Collections.newSetFromMap(new IdentityHashMap<>()); setDiff(trackingComponent.getTracking(), matched, removal, update); - for (ServerPlayerEntity p : update) { - SignMeUp.channel.sendTo(trackingComponent.getNotifyPacket(false, id), p.connection.netManager, NetworkDirection.PLAY_TO_CLIENT); + for (ServerPlayer p : update) { + SignMeUp.channel.sendTo(trackingComponent.getNotifyPacket(false, id), p.connection.getConnection(), NetworkDirection.PLAY_TO_CLIENT); } - for (ServerPlayerEntity p : removal) { - SignMeUp.channel.sendTo(trackingComponent.getNotifyPacket(true, id), p.connection.netManager, NetworkDirection.PLAY_TO_CLIENT); + for (ServerPlayer p : removal) { + SignMeUp.channel.sendTo(trackingComponent.getNotifyPacket(true, id), p.connection.getConnection(), NetworkDirection.PLAY_TO_CLIENT); } trackingComponent.setTracking(matched); } @Override - protected void apply(Map objects, IResourceManager manager, IProfiler profiler) { + protected void apply(Map objects, ResourceManager manager, ProfilerFiller profiler) { this.maps.clear(); this.points.clear(); this.triggers.clear(); - profiler.startSection("SignInGuides"); + profiler.push("SignInGuides"); objects.forEach(this::process); - profiler.endSection(); + profiler.pop(); } private void process(ResourceLocation id, JsonElement json) { diff --git a/src/main/java/org/teacon/signin/data/PlayerTracker.java b/src/main/java/org/teacon/signin/data/PlayerTracker.java index 03e8840..d03fa38 100644 --- a/src/main/java/org/teacon/signin/data/PlayerTracker.java +++ b/src/main/java/org/teacon/signin/data/PlayerTracker.java @@ -1,8 +1,9 @@ package org.teacon.signin.data; -import net.minecraft.command.arguments.EntitySelector; -import net.minecraft.entity.player.ServerPlayerEntity; -import net.minecraft.util.ResourceLocation; +import net.minecraft.commands.arguments.selector.EntitySelector; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; + import org.teacon.signin.network.PartialUpdatePacket; import java.util.Set; @@ -11,9 +12,9 @@ public interface PlayerTracker { EntitySelector getSelector(); - Set getTracking(); + Set getTracking(); - void setTracking(Set players); + void setTracking(Set players); PartialUpdatePacket getNotifyPacket(boolean remove, ResourceLocation id); } diff --git a/src/main/java/org/teacon/signin/data/Trigger.java b/src/main/java/org/teacon/signin/data/Trigger.java index f0d4d12..ed7f4ad 100644 --- a/src/main/java/org/teacon/signin/data/Trigger.java +++ b/src/main/java/org/teacon/signin/data/Trigger.java @@ -4,13 +4,13 @@ import com.google.gson.*; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.minecraft.command.arguments.EntitySelector; -import net.minecraft.command.arguments.EntitySelectorParser; -import net.minecraft.entity.player.ServerPlayerEntity; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.Util; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.TranslationTextComponent; +import net.minecraft.Util; +import net.minecraft.commands.arguments.selector.EntitySelector; +import net.minecraft.commands.arguments.selector.EntitySelectorParser; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; import org.teacon.signin.network.PartialUpdatePacket; import java.lang.reflect.Type; @@ -20,8 +20,8 @@ public final class Trigger implements PlayerTracker { - ITextComponent title; - ITextComponent desc; + Component title; + Component desc; public volatile boolean disabled = false; @@ -30,13 +30,13 @@ public final class Trigger implements PlayerTracker { public ImmutableList executes = ImmutableList.of(); - transient Set visiblePlayers = Collections.newSetFromMap(new WeakHashMap<>()); + transient Set visiblePlayers = Collections.newSetFromMap(new WeakHashMap<>()); - public ITextComponent getTitle() { - return this.title == null ? new TranslationTextComponent("sign_up.trigger.unnamed") : this.title; + public Component getTitle() { + return this.title == null ? new TranslatableComponent("sign_up.trigger.unnamed") : this.title; } - public ITextComponent getDesc() { + public Component getDesc() { return this.desc == null ? this.getTitle() : this.desc; } @@ -52,17 +52,17 @@ public EntitySelector getSelector() { return parsedSelector; } - public boolean isVisibleTo(ServerPlayerEntity p) { + public boolean isVisibleTo(ServerPlayer p) { return this.visiblePlayers.contains(p); } @Override - public Set getTracking() { + public Set getTracking() { return this.visiblePlayers; } @Override - public void setTracking(Set players) { + public void setTracking(Set players) { this.visiblePlayers = players; } @@ -79,10 +79,10 @@ public Trigger deserialize(JsonElement json, Type typeOfT, JsonDeserializationCo final JsonObject obj = json.getAsJsonObject(); final Trigger t = new Trigger(); if (obj.has("title")) { - t.title = context.deserialize(obj.get("title"), ITextComponent.class); + t.title = context.deserialize(obj.get("title"), Component.class); } if (obj.has("description")) { - t.desc = context.deserialize(obj.get("description"), ITextComponent.class); + t.desc = context.deserialize(obj.get("description"), Component.class); } if (obj.has("disabled")) { t.disabled = obj.get("disabled").getAsBoolean(); diff --git a/src/main/java/org/teacon/signin/data/Vector3iAdapter.java b/src/main/java/org/teacon/signin/data/Vector3iAdapter.java index 92ca6ae..94cd2aa 100644 --- a/src/main/java/org/teacon/signin/data/Vector3iAdapter.java +++ b/src/main/java/org/teacon/signin/data/Vector3iAdapter.java @@ -1,28 +1,28 @@ package org.teacon.signin.data; import com.google.gson.*; -import net.minecraft.util.math.vector.Vector3i; +import net.minecraft.core.Vec3i; import java.lang.reflect.Type; public final class Vector3iAdapter - implements JsonSerializer, JsonDeserializer { + implements JsonSerializer, JsonDeserializer { @Override - public Vector3i deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + public Vec3i deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { if (json.isJsonArray()) { JsonArray arr = json.getAsJsonArray(); if (arr.size() == 3) { - return new Vector3i(arr.get(0).getAsInt(), arr.get(1).getAsInt(), arr.get(2).getAsInt()); + return new Vec3i(arr.get(0).getAsInt(), arr.get(1).getAsInt(), arr.get(2).getAsInt()); } else if (arr.size() == 2) { - return new Vector3i(arr.get(0).getAsInt(), 0, arr.get(1).getAsInt()); + return new Vec3i(arr.get(0).getAsInt(), 0, arr.get(1).getAsInt()); } } throw new JsonSyntaxException("Coordinates must be array of 2 or 3 integers"); } @Override - public JsonElement serialize(Vector3i src, Type typeOfSrc, JsonSerializationContext context) { + public JsonElement serialize(Vec3i src, Type typeOfSrc, JsonSerializationContext context) { JsonArray arr = new JsonArray(); arr.add(src.getX()); arr.add(src.getY()); diff --git a/src/main/java/org/teacon/signin/data/Waypoint.java b/src/main/java/org/teacon/signin/data/Waypoint.java index 38d0453..72c5ce7 100644 --- a/src/main/java/org/teacon/signin/data/Waypoint.java +++ b/src/main/java/org/teacon/signin/data/Waypoint.java @@ -10,14 +10,14 @@ import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; import com.mojang.brigadier.StringReader; -import net.minecraft.command.arguments.EntitySelector; -import net.minecraft.command.arguments.EntitySelectorParser; -import net.minecraft.entity.player.ServerPlayerEntity; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.vector.Vector3i; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.StringTextComponent; -import net.minecraft.util.text.TranslationTextComponent; +import net.minecraft.commands.arguments.selector.EntitySelector; +import net.minecraft.commands.arguments.selector.EntitySelectorParser; +import net.minecraft.core.Vec3i; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; import org.teacon.signin.network.PartialUpdatePacket; import java.lang.reflect.Type; @@ -31,11 +31,11 @@ public final class Waypoint implements PlayerTracker { public static final class Location { - Vector3i actualLocation; - private Vector3i renderLocation; + Vec3i actualLocation; + private Vec3i renderLocation; boolean isDynamic = false; - public Vector3i getRenderLocation() { + public Vec3i getRenderLocation() { return this.renderLocation == null ? this.actualLocation : this.renderLocation; } @@ -50,9 +50,9 @@ public Location deserialize(JsonElement json, Type type, JsonDeserializationCont return loc; } else if (json.isJsonObject()) { final JsonObject locations = json.getAsJsonObject(); - loc.actualLocation = context.deserialize(locations.get("actual"), Vector3i.class); + loc.actualLocation = context.deserialize(locations.get("actual"), Vec3i.class); if (locations.has("render")) { - loc.renderLocation = context.deserialize(locations.get("render"), Vector3i.class); + loc.renderLocation = context.deserialize(locations.get("render"), Vec3i.class); } return loc; } else { @@ -76,8 +76,8 @@ public JsonElement serialize(Location src, Type typeOfSrc, JsonSerializationCont } } - private ITextComponent title; - private ITextComponent desc; + private Component title; + private Component desc; private String selector = "@e"; private transient EntitySelector parsedSelector; @@ -90,25 +90,25 @@ public JsonElement serialize(Location src, Type typeOfSrc, JsonSerializationCont private int displayingImageIndex; - transient Set visiblePlayers = Collections.newSetFromMap(new WeakHashMap<>()); + transient Set visiblePlayers = Collections.newSetFromMap(new WeakHashMap<>()); - public ITextComponent getTitle() { - return title == null ? new TranslationTextComponent("sign_up.waypoint.unnamed") : this.title; + public Component getTitle() { + return title == null ? new TranslatableComponent("sign_up.waypoint.unnamed") : this.title; } - public ITextComponent getDesc() { - return this.desc == null ? StringTextComponent.EMPTY : this.desc; + public Component getDesc() { + return this.desc == null ? TextComponent.EMPTY : this.desc; } public boolean hasDynamicLocation() { return location.isDynamic; } - public Vector3i getRenderLocation() { + public Vec3i getRenderLocation() { return location.getRenderLocation(); } - public Vector3i getActualLocation() { + public Vec3i getActualLocation() { return location.actualLocation; } @@ -143,12 +143,12 @@ public EntitySelector getSelector() { } @Override - public Set getTracking() { + public Set getTracking() { return this.visiblePlayers; } @Override - public void setTracking(Set players) { + public void setTracking(Set players) { this.visiblePlayers = players; } @@ -165,10 +165,10 @@ public Waypoint deserialize(JsonElement json, Type typeOfT, JsonDeserializationC final JsonObject obj = json.getAsJsonObject(); final Waypoint wp = new Waypoint(); if (obj.has("title")) { - wp.title = context.deserialize(obj.get("title"), ITextComponent.class); + wp.title = context.deserialize(obj.get("title"), Component.class); } if (obj.has("description")) { - wp.desc = context.deserialize(obj.get("description"), ITextComponent.class); + wp.desc = context.deserialize(obj.get("description"), Component.class); } if (obj.has("selector")) { wp.selector = obj.get("selector").getAsString(); diff --git a/src/main/java/org/teacon/signin/network/MapScreenPacket.java b/src/main/java/org/teacon/signin/network/MapScreenPacket.java index 317f9ad..7ae6853 100644 --- a/src/main/java/org/teacon/signin/network/MapScreenPacket.java +++ b/src/main/java/org/teacon/signin/network/MapScreenPacket.java @@ -1,41 +1,41 @@ package org.teacon.signin.network; -import net.minecraft.network.PacketBuffer; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.vector.Vector3d; -import net.minecraftforge.fml.network.NetworkEvent; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.network.NetworkEvent; import org.teacon.signin.client.SignMeUpClient; import java.util.function.Supplier; public final class MapScreenPacket { private final Action action; - private final Vector3d position; + private final Vec3 position; private final ResourceLocation mapId; - public MapScreenPacket(Action action, Vector3d position, ResourceLocation id) { + public MapScreenPacket(Action action, Vec3 position, ResourceLocation id) { this.position = position; this.action = action; this.mapId = id; } - public MapScreenPacket(PacketBuffer buf) { - this.action = buf.readEnumValue(Action.class); + public MapScreenPacket(FriendlyByteBuf buf) { + this.action = buf.readEnum(Action.class); if (this.action != Action.CLOSE_ANY) { - this.position = new Vector3d(buf.readDouble(), buf.readDouble(), buf.readDouble()); + this.position = new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble()); this.mapId = buf.readResourceLocation(); } else { - this.position = Vector3d.ZERO; + this.position = Vec3.ZERO; this.mapId = null; } } - public void write(PacketBuffer buf) { - buf.writeEnumValue(this.action); + public void write(FriendlyByteBuf buf) { + buf.writeEnum(this.action); if (this.action != Action.CLOSE_ANY) { - buf.writeDouble(this.position.getX()); - buf.writeDouble(this.position.getY()); - buf.writeDouble(this.position.getZ()); + buf.writeDouble(this.position.x()); + buf.writeDouble(this.position.y()); + buf.writeDouble(this.position.z()); buf.writeResourceLocation(this.mapId); } } diff --git a/src/main/java/org/teacon/signin/network/PartialUpdatePacket.java b/src/main/java/org/teacon/signin/network/PartialUpdatePacket.java index 0461ae5..d9d78ce 100644 --- a/src/main/java/org/teacon/signin/network/PartialUpdatePacket.java +++ b/src/main/java/org/teacon/signin/network/PartialUpdatePacket.java @@ -3,12 +3,11 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.network.PacketBuffer; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.vector.Vector3i; -import net.minecraft.util.text.ITextComponent; -import net.minecraftforge.fml.network.NetworkEvent; +import net.minecraft.core.Vec3i; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.network.NetworkEvent; import org.teacon.signin.client.GuideMapScreen; import org.teacon.signin.client.SignMeUpClient; import org.teacon.signin.data.*; @@ -24,9 +23,9 @@ public enum Mode { private static final Gson GSON = new GsonBuilder().setLenient() .registerTypeAdapter(Waypoint.class, new Waypoint.Serializer()) .registerTypeAdapter(Waypoint.Location.class, new Waypoint.Location.Serializer()) - .registerTypeAdapter(Vector3i.class, new Vector3iAdapter()) + .registerTypeAdapter(Vec3i.class, new Vector3iAdapter()) .registerTypeAdapter(Trigger.class, new Trigger.Serializer()) - .registerTypeHierarchyAdapter(ITextComponent.class, new ITextComponent.Serializer()) + .registerTypeHierarchyAdapter(Component.class, new Component.Serializer()) .create(); private Mode mode; @@ -35,18 +34,18 @@ public enum Mode { private ResourceLocation triggerId; private Trigger trigger; - public PartialUpdatePacket(PacketBuffer buf) { - switch (this.mode = buf.readEnumValue(Mode.class)) { + public PartialUpdatePacket(FriendlyByteBuf buf) { + switch (this.mode = buf.readEnum(Mode.class)) { case ADD_WAYPOINT: this.waypointId = buf.readResourceLocation(); - this.waypoint = GSON.fromJson(buf.readString(Short.MAX_VALUE), Waypoint.class); + this.waypoint = GSON.fromJson(buf.readUtf(Short.MAX_VALUE), Waypoint.class); break; case REMOVE_WAYPOINT: this.waypointId = buf.readResourceLocation(); break; case ADD_TRIGGER: this.triggerId = buf.readResourceLocation(); - this.trigger = GSON.fromJson(buf.readString(Short.MAX_VALUE), Trigger.class); + this.trigger = GSON.fromJson(buf.readUtf(Short.MAX_VALUE), Trigger.class); break; case REMOVE_TRIGGER: this.triggerId = buf.readResourceLocation(); @@ -65,22 +64,22 @@ public PartialUpdatePacket(Mode mode, ResourceLocation id, Trigger trigger) { this.trigger = trigger; } - public void write(PacketBuffer buf) { - buf.writeEnumValue(this.mode); + public void write(FriendlyByteBuf buf) { + buf.writeEnum(this.mode); switch (this.mode) { case REMOVE_WAYPOINT: buf.writeResourceLocation(this.waypointId); break; case ADD_WAYPOINT: buf.writeResourceLocation(this.waypointId); - buf.writeString(GSON.toJson(this.waypoint)); + buf.writeUtf(GSON.toJson(this.waypoint)); break; case REMOVE_TRIGGER: buf.writeResourceLocation(this.triggerId); break; case ADD_TRIGGER: buf.writeResourceLocation(this.triggerId); - buf.writeString(GSON.toJson(this.trigger)); + buf.writeUtf(GSON.toJson(this.trigger)); break; } } @@ -102,8 +101,8 @@ public void handle(Supplier contextGetter) { break; } final Minecraft mc = Minecraft.getInstance(); - if (mc.currentScreen instanceof GuideMapScreen) { - ((GuideMapScreen) mc.currentScreen).refresh(); + if (mc.screen instanceof GuideMapScreen) { + ((GuideMapScreen) mc.screen).refresh(); } }); contextGetter.get().setPacketHandled(true); diff --git a/src/main/java/org/teacon/signin/network/SyncGuideMapPacket.java b/src/main/java/org/teacon/signin/network/SyncGuideMapPacket.java index 9ec7ffc..4887334 100644 --- a/src/main/java/org/teacon/signin/network/SyncGuideMapPacket.java +++ b/src/main/java/org/teacon/signin/network/SyncGuideMapPacket.java @@ -4,10 +4,11 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import net.minecraft.network.PacketBuffer; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.text.ITextComponent; -import net.minecraftforge.fml.network.NetworkEvent; +import net.minecraft.network.FriendlyByteBuf; + +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.network.NetworkEvent; import org.teacon.signin.client.SignMeUpClient; import org.teacon.signin.data.GuideMap; @@ -21,7 +22,7 @@ public final class SyncGuideMapPacket { private static final Gson GSON = new GsonBuilder().setLenient() .registerTypeAdapter(GuideMap.class, new GuideMap.Serializer()) - .registerTypeHierarchyAdapter(ITextComponent.class, new ITextComponent.Serializer()) + .registerTypeHierarchyAdapter(Component.class, new Component.Serializer()) .create(); private final SortedMap maps; @@ -30,7 +31,7 @@ public SyncGuideMapPacket(SortedMap mapsToSend) { this.maps = mapsToSend; } - public SyncGuideMapPacket(PacketBuffer buf) { + public SyncGuideMapPacket(FriendlyByteBuf buf) { this.maps = new TreeMap<>(); // We want all guide maps to be sorted by key. try { final String src = new String(buf.readByteArray(), StandardCharsets.UTF_8); @@ -45,7 +46,7 @@ private static void accept(Map.Entry entry, Class ty dst.put(new ResourceLocation(entry.getKey()), GSON.fromJson(entry.getValue(), type)); } - public void write(PacketBuffer buf) { + public void write(FriendlyByteBuf buf) { buf.writeByteArray(GSON.toJson(this.maps).getBytes(StandardCharsets.UTF_8)); } diff --git a/src/main/java/org/teacon/signin/network/TriggerFromMapPacket.java b/src/main/java/org/teacon/signin/network/TriggerFromMapPacket.java index 4c3e47d..8f35976 100644 --- a/src/main/java/org/teacon/signin/network/TriggerFromMapPacket.java +++ b/src/main/java/org/teacon/signin/network/TriggerFromMapPacket.java @@ -1,8 +1,8 @@ package org.teacon.signin.network; -import net.minecraft.network.PacketBuffer; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fml.network.NetworkEvent; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.network.NetworkEvent; import org.teacon.signin.SignMeUp; import org.teacon.signin.data.GuideMap; @@ -14,7 +14,7 @@ public final class TriggerFromMapPacket { private final ResourceLocation trigger; // Used for deserialization - public TriggerFromMapPacket(PacketBuffer buf) { + public TriggerFromMapPacket(FriendlyByteBuf buf) { this.map = buf.readResourceLocation(); this.trigger = buf.readResourceLocation(); } @@ -24,7 +24,7 @@ public TriggerFromMapPacket(ResourceLocation map, ResourceLocation trigger) { this.trigger = trigger; } - public void write(PacketBuffer buf) { + public void write(FriendlyByteBuf buf) { buf.writeResourceLocation(this.map); buf.writeResourceLocation(this.trigger); } diff --git a/src/main/java/org/teacon/signin/network/TriggerFromWaypointPacket.java b/src/main/java/org/teacon/signin/network/TriggerFromWaypointPacket.java index c0ac124..b357479 100644 --- a/src/main/java/org/teacon/signin/network/TriggerFromWaypointPacket.java +++ b/src/main/java/org/teacon/signin/network/TriggerFromWaypointPacket.java @@ -1,8 +1,8 @@ package org.teacon.signin.network; -import net.minecraft.network.PacketBuffer; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fml.network.NetworkEvent; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.network.NetworkEvent; import org.teacon.signin.SignMeUp; import org.teacon.signin.data.Waypoint; @@ -14,7 +14,7 @@ public final class TriggerFromWaypointPacket { private final ResourceLocation trigger; // Used for deserialization - public TriggerFromWaypointPacket(PacketBuffer buf) { + public TriggerFromWaypointPacket(FriendlyByteBuf buf) { this.waypoint = buf.readResourceLocation(); this.trigger = buf.readResourceLocation(); } @@ -24,7 +24,7 @@ public TriggerFromWaypointPacket(ResourceLocation waypoint, ResourceLocation tri this.trigger = trigger; } - public void write(PacketBuffer buf) { + public void write(FriendlyByteBuf buf) { buf.writeResourceLocation(this.waypoint); buf.writeResourceLocation(this.trigger); }