mirror of
https://github.com/Nan1t/NanoLimbo.git
synced 2025-07-16 14:10:13 +02:00
Compare commits
86 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
a5b9e3510d | ||
|
155e6cc6c3 | ||
|
b99a533e1a | ||
|
94edb65dac | ||
|
48346762bf | ||
|
402484c838 | ||
|
32b75fb9d8 | ||
|
3f7c8bb1df | ||
|
e9b6c888bc | ||
|
6bbde1f578 | ||
|
f36f8dac6c | ||
|
f137495c4e | ||
|
04a646b271 | ||
|
cd42e91cd1 | ||
|
e3e12db006 | ||
|
a750bc50d2 | ||
|
e54d8d6ed3 | ||
|
f5684107c8 | ||
|
ebe9c19a05 | ||
|
72774fbff9 | ||
|
0489f883d1 | ||
|
6919420916 | ||
|
dfa6cf3862 | ||
|
93ad159833 | ||
|
f257426173 | ||
|
4fd0389356 | ||
|
23bcfc7b20 | ||
|
9dc7027a22 | ||
|
145d57679e | ||
|
ff84c8f564 | ||
|
b5605f8d12 | ||
|
5615ec2321 | ||
|
9490dc3ef2 | ||
|
7309ca3b41 | ||
|
dceb977a75 | ||
|
9ce3146045 | ||
|
fb15336b42 | ||
|
ddb27d421b | ||
|
b301617f99 | ||
|
e77a42ebc9 | ||
|
3ef5683222 | ||
|
064150a171 | ||
|
6c1f7e4e2f | ||
|
ab1844131b | ||
|
9558c2357b | ||
|
8d135c0804 | ||
|
0ddac89204 | ||
|
97e4b44920 | ||
|
dbeb7cc037 | ||
|
c96668f4d7 | ||
|
37813a1fed | ||
|
bbafbcc959 | ||
|
593e137b57 | ||
|
21b74e8093 | ||
|
2fdbd3e63a | ||
|
77a68efdc8 | ||
|
8210e61989 | ||
|
0af7a4c63d | ||
|
3c9bb88e19 | ||
|
05ef0435e5 | ||
|
04c1730da0 | ||
|
8fee9a4426 | ||
|
d5c61e8a8d | ||
|
f5003b1126 | ||
|
353533a72a | ||
|
68846b0e0d | ||
|
68ea7c020c | ||
|
b36decb3dd | ||
|
a327f7bc98 | ||
|
714ef11fa8 | ||
|
bc22bdd4ed | ||
|
5d08856bca | ||
|
af304da0f0 | ||
|
747da18b72 | ||
|
4c8668f222 | ||
|
699996e267 | ||
|
e7257894e3 | ||
|
b19fa9db37 | ||
|
d474498ef6 | ||
|
b221d88d67 | ||
|
90364e4f6b | ||
|
fa63d3fff9 | ||
|
b4daf6aa60 | ||
|
59d264d9b8 | ||
|
87debafbad | ||
|
613f6e75b2 |
63
README.md
63
README.md
@ -1,20 +1,20 @@
|
|||||||
## NanoLimbo
|
## NanoLimbo
|
||||||
|
|
||||||
This is lightweight minecraft limbo server, written on Java with Netty.
|
This is a lightweight Minecraft limbo server, written in Java with Netty.
|
||||||
The main goal of the project is maximum simplicity with a minimum number of sent and processed packets.
|
The main goal of this project is maximum simplicity with a minimum number of sent and processed packets.
|
||||||
This limbo is empty, there are no ability to set schematic building since
|
The limbo is empty; there is no ability to set a schematic building since this is not necessary.
|
||||||
this is not necessary. You can send useful information in chat or BossBar.
|
You can send useful information via chat or boss bar.
|
||||||
|
|
||||||
No plugins, no logs. The server is fully clear. It only able keep a lot of players while the main server is down.
|
The server is fully clear. It is only able to keep a lot of players while the main server is down.
|
||||||
|
|
||||||
The general features:
|
General features:
|
||||||
* High performance. The server not saves and not cached any useless (for limbo) data.
|
* High performance. The server doesn't save or cache any useless (for limbo) data.
|
||||||
* Doesn't spawn threads per player. Uses fixed threads pool.
|
* Doesn't spawn threads per player. Use a fixed thread pool.
|
||||||
* Support for **BungeeCord** and **Velocity** info forwarding.
|
* Support for **BungeeCord** and **Velocity** info forwarding.
|
||||||
* Support for [BungeeGuard](https://www.spigotmc.org/resources/79601/) handshake format.
|
* Support for [BungeeGuard](https://www.spigotmc.org/resources/79601/) handshake format.
|
||||||
* Multiple versions support.
|
* Multiple versions support.
|
||||||
* Fully configurable.
|
* Fully configurable.
|
||||||
* Lightweight. App size around **2MB.**
|
* Lightweight. App size around **3MB**.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@ -22,6 +22,7 @@ The general features:
|
|||||||
|
|
||||||
Symbol `X` means all minor versions.
|
Symbol `X` means all minor versions.
|
||||||
|
|
||||||
|
- [x] 1.7.X
|
||||||
- [x] 1.8.X
|
- [x] 1.8.X
|
||||||
- [x] 1.9.X
|
- [x] 1.9.X
|
||||||
- [x] 1.10.X
|
- [x] 1.10.X
|
||||||
@ -33,31 +34,35 @@ Symbol `X` means all minor versions.
|
|||||||
- [x] 1.16.X
|
- [x] 1.16.X
|
||||||
- [x] 1.17.X
|
- [x] 1.17.X
|
||||||
- [x] 1.18.X
|
- [x] 1.18.X
|
||||||
- [x] 1.19
|
- [x] 1.19.X
|
||||||
|
- [x] 1.20.X
|
||||||
|
- [x] 1.21
|
||||||
|
|
||||||
The server **doesn't** support snapshots.
|
The server **doesn't** support snapshots.
|
||||||
|
|
||||||
### Commands
|
### Commands
|
||||||
|
|
||||||
* `help` - Show help message
|
* `help` - Show help message
|
||||||
* `conn` - Display amount of connections
|
* `conn` - Display number of connections
|
||||||
* `mem` - Display memory usage stats
|
* `mem` - Display memory usage stats
|
||||||
* `stop` - Stop the server
|
* `stop` - Stop the server
|
||||||
|
|
||||||
Note, that it also will be closed correctly if you just press `Ctrl+C`.
|
Note that the server also will be closed correctly if you just press `Ctrl+C`.
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
|
Required software: JRE 11+
|
||||||
|
|
||||||
The installation process is simple.
|
The installation process is simple.
|
||||||
|
|
||||||
1. Download the latest version of program **[here](https://github.com/Nan1t/NanoLimbo/releases)**
|
1. Download the latest version of the program [**here**](https://github.com/Nan1t/NanoLimbo/releases).
|
||||||
2. Put jar file in the folder you want.
|
2. Put the jar file in the folder you want.
|
||||||
3. Create a start script as you did it for Bukkit or BungeeCord with command like this:
|
3. Create a start script as you did for Bukkit or BungeeCord, with a command like this:
|
||||||
`java -jar NanoLimbo-<version>.jar`
|
`java -jar NanoLimbo-<version>.jar`
|
||||||
4. The server will create `settings.yml` file. It's a server configuration.
|
4. The server will create `settings.yml` file, which is the server configuration.
|
||||||
5. Configure it as you want and restart server.
|
5. Configure it as you want and restart the server.
|
||||||
|
|
||||||
### About player info forwarding
|
### Player info forwarding
|
||||||
|
|
||||||
The server supports player info forwarding from the proxy. There are several types of info forwarding:
|
The server supports player info forwarding from the proxy. There are several types of info forwarding:
|
||||||
|
|
||||||
@ -66,29 +71,29 @@ The server supports player info forwarding from the proxy. There are several typ
|
|||||||
* `BUNGEE_GUARD` - **BungeeGuard** forwarding type.
|
* `BUNGEE_GUARD` - **BungeeGuard** forwarding type.
|
||||||
|
|
||||||
If you use BungeeCord, or Velocity with `LEGACY` forwarding, just set this type in the config.
|
If you use BungeeCord, or Velocity with `LEGACY` forwarding, just set this type in the config.
|
||||||
If you use Velocity with `MODERN` info forwarding, set this type and paste secret key from Velocity
|
If you use Velocity with `MODERN` info forwarding, set this type and paste the secret key from
|
||||||
config into `secret` field.
|
Velocity config into `secret` field.
|
||||||
If you installed BungeeGuard on your proxy, then use `BUNGEE_GUARD` forwarding type.
|
If you installed BungeeGuard on your proxy, then use `BUNGEE_GUARD` forwarding type.
|
||||||
Then add your tokens to `tokens` list.
|
Then add your tokens to `tokens` list.
|
||||||
|
|
||||||
### Contributing
|
### Contributing
|
||||||
|
|
||||||
You can create pull request, if you found some bug, optimization ability, or you want to add some functional,
|
Feel free to create a pull request if you find some bug or optimization opportunity, or if you want
|
||||||
which is suitable for limbo server and won't significantly load the server.
|
to add some functionality that is suitable for a limbo server and won't significantly load the server.
|
||||||
|
|
||||||
### Building
|
### Building
|
||||||
|
|
||||||
Required software:
|
Required software:
|
||||||
|
|
||||||
* JDK 1.8+
|
* JDK 11+
|
||||||
* Gradle 7+
|
* Gradle 7+ (optional)
|
||||||
|
|
||||||
To build minimized .jar, go to project root and write in terminal:
|
To build a minimized jar, go to the project root directory and run in the terminal:
|
||||||
|
|
||||||
```
|
```
|
||||||
gradlew shadowJar
|
./gradlew shadowJar
|
||||||
```
|
```
|
||||||
|
|
||||||
### Contacts
|
### Contacts
|
||||||
|
|
||||||
If you have any question or suggestion, join to [Discord server](https://discord.gg/4VGP3Gv)
|
If you have any questions or suggestions, join our [Discord server](https://discord.gg/4VGP3Gv)!
|
||||||
|
35
build.gradle
35
build.gradle
@ -1,16 +1,17 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
id 'java'
|
||||||
id 'com.github.johnrengelman.shadow' version '7.0.0'
|
id 'com.github.johnrengelman.shadow' version '7.1.2'
|
||||||
|
id 'com.github.gmazzo.buildconfig' version '3.1.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
group 'ru.nanit'
|
group 'ua.nanit'
|
||||||
version '1.4'
|
version '1.8.1'
|
||||||
|
|
||||||
compileJava {
|
compileJava {
|
||||||
options.encoding = "UTF-8"
|
options.encoding = "UTF-8"
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(JavaCompile) {
|
tasks.withType(JavaCompile).configureEach {
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
}
|
}
|
||||||
@ -20,25 +21,35 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
|
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.3'
|
||||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
|
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.3'
|
||||||
|
|
||||||
|
implementation 'ch.qos.logback:logback-classic:1.5.6'
|
||||||
implementation 'org.spongepowered:configurate-yaml:4.1.2'
|
implementation 'org.spongepowered:configurate-yaml:4.1.2'
|
||||||
implementation 'io.netty:netty-all:4.1.77.Final'
|
implementation 'io.netty:netty-all:4.1.101.Final'
|
||||||
implementation 'net.kyori:adventure-nbt:4.10.1'
|
implementation 'net.kyori:adventure-nbt:4.14.0'
|
||||||
implementation 'com.grack:nanojson:1.7'
|
implementation 'com.grack:nanojson:1.8'
|
||||||
|
implementation 'com.google.code.gson:gson:2.10.1'
|
||||||
|
}
|
||||||
|
|
||||||
|
buildConfig {
|
||||||
|
className("BuildConfig")
|
||||||
|
packageName("ua.nanit.limbo")
|
||||||
|
buildConfigField('String', 'LIMBO_VERSION', "\"${project.version}\"")
|
||||||
}
|
}
|
||||||
|
|
||||||
shadowJar {
|
shadowJar {
|
||||||
from 'LICENSE'
|
from 'LICENSE'
|
||||||
|
|
||||||
manifest {
|
manifest {
|
||||||
attributes('Main-Class': 'ru.nanit.limbo.NanoLimbo')
|
attributes('Main-Class': 'ua.nanit.limbo.NanoLimbo')
|
||||||
}
|
}
|
||||||
|
|
||||||
minimize()
|
minimize {
|
||||||
|
exclude(dependency('ch.qos.logback:logback-classic:.*:.*'))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
}
|
}
|
||||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
269
gradlew
vendored
Normal file → Executable file
269
gradlew
vendored
Normal file → Executable file
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env sh
|
#!/bin/sh
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright 2015 the original author or authors.
|
# Copyright © 2015-2021 the original authors.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -17,67 +17,101 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
##
|
#
|
||||||
## 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
|
# Attempt to set APP_HOME
|
||||||
|
|
||||||
# Resolve links: $0 may be a link
|
# Resolve links: $0 may be a link
|
||||||
PRG="$0"
|
app_path=$0
|
||||||
# Need this for relative symlinks.
|
|
||||||
while [ -h "$PRG" ] ; do
|
# Need this for daisy-chained symlinks.
|
||||||
ls=`ls -ld "$PRG"`
|
while
|
||||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||||
if expr "$link" : '/.*' > /dev/null; then
|
[ -h "$app_path" ]
|
||||||
PRG="$link"
|
do
|
||||||
else
|
ls=$( ls -ld "$app_path" )
|
||||||
PRG=`dirname "$PRG"`"/$link"
|
link=${ls#*' -> '}
|
||||||
fi
|
case $link in #(
|
||||||
|
/*) app_path=$link ;; #(
|
||||||
|
*) app_path=$APP_HOME$link ;;
|
||||||
|
esac
|
||||||
done
|
done
|
||||||
SAVED="`pwd`"
|
|
||||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||||
APP_HOME="`pwd -P`"
|
|
||||||
cd "$SAVED" >/dev/null
|
|
||||||
|
|
||||||
APP_NAME="Gradle"
|
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.
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD="maximum"
|
MAX_FD=maximum
|
||||||
|
|
||||||
warn () {
|
warn () {
|
||||||
echo "$*"
|
echo "$*"
|
||||||
}
|
} >&2
|
||||||
|
|
||||||
die () {
|
die () {
|
||||||
echo
|
echo
|
||||||
echo "$*"
|
echo "$*"
|
||||||
echo
|
echo
|
||||||
exit 1
|
exit 1
|
||||||
}
|
} >&2
|
||||||
|
|
||||||
# OS specific support (must be 'true' or 'false').
|
# OS specific support (must be 'true' or 'false').
|
||||||
cygwin=false
|
cygwin=false
|
||||||
msys=false
|
msys=false
|
||||||
darwin=false
|
darwin=false
|
||||||
nonstop=false
|
nonstop=false
|
||||||
case "`uname`" in
|
case "$( uname )" in #(
|
||||||
CYGWIN* )
|
CYGWIN* ) cygwin=true ;; #(
|
||||||
cygwin=true
|
Darwin* ) darwin=true ;; #(
|
||||||
;;
|
MSYS* | MINGW* ) msys=true ;; #(
|
||||||
Darwin* )
|
NONSTOP* ) nonstop=true ;;
|
||||||
darwin=true
|
|
||||||
;;
|
|
||||||
MSYS* | MINGW* )
|
|
||||||
msys=true
|
|
||||||
;;
|
|
||||||
NONSTOP* )
|
|
||||||
nonstop=true
|
|
||||||
;;
|
|
||||||
esac
|
esac
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
|||||||
if [ -n "$JAVA_HOME" ] ; then
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
# IBM's JDK on AIX uses strange locations for the executables
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||||
else
|
else
|
||||||
JAVACMD="$JAVA_HOME/bin/java"
|
JAVACMD=$JAVA_HOME/bin/java
|
||||||
fi
|
fi
|
||||||
if [ ! -x "$JAVACMD" ] ; then
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
|
|||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
fi
|
fi
|
||||||
else
|
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.
|
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
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
@ -106,80 +140,95 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
MAX_FD_LIMIT=`ulimit -H -n`
|
case $MAX_FD in #(
|
||||||
if [ $? -eq 0 ] ; then
|
max*)
|
||||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
MAX_FD="$MAX_FD_LIMIT"
|
warn "Could not query maximum file descriptor limit"
|
||||||
fi
|
esac
|
||||||
ulimit -n $MAX_FD
|
case $MAX_FD in #(
|
||||||
if [ $? -ne 0 ] ; then
|
'' | soft) :;; #(
|
||||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
*)
|
||||||
fi
|
ulimit -n "$MAX_FD" ||
|
||||||
else
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# For Darwin, add options to specify how the application appears in the dock
|
|
||||||
if $darwin; then
|
|
||||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
|
||||||
fi
|
|
||||||
|
|
||||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
|
||||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
|
||||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
|
||||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
|
||||||
|
|
||||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
|
||||||
|
|
||||||
# We build the pattern for arguments to be converted via cygpath
|
|
||||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
|
||||||
SEP=""
|
|
||||||
for dir in $ROOTDIRSRAW ; do
|
|
||||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
|
||||||
SEP="|"
|
|
||||||
done
|
|
||||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
|
||||||
# Add a user-defined pattern to the cygpath arguments
|
|
||||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
|
||||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
|
||||||
fi
|
|
||||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
|
||||||
i=0
|
|
||||||
for arg in "$@" ; do
|
|
||||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
|
||||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
|
||||||
|
|
||||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
|
||||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
|
||||||
else
|
|
||||||
eval `echo args$i`="\"$arg\""
|
|
||||||
fi
|
|
||||||
i=`expr $i + 1`
|
|
||||||
done
|
|
||||||
case $i in
|
|
||||||
0) set -- ;;
|
|
||||||
1) set -- "$args0" ;;
|
|
||||||
2) set -- "$args0" "$args1" ;;
|
|
||||||
3) set -- "$args0" "$args1" "$args2" ;;
|
|
||||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
|
||||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
|
||||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
|
||||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
|
||||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
|
||||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Escape application args
|
# Collect all arguments for the java command, stacking in reverse order:
|
||||||
save () {
|
# * args from the command line
|
||||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
# * the main class name
|
||||||
echo " "
|
# * -classpath
|
||||||
}
|
# * -D...appname settings
|
||||||
APP_ARGS=`save "$@"`
|
# * --module-path (only if needed)
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||||
|
|
||||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
if "$cygwin" || "$msys" ; then
|
||||||
|
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||||
|
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||||
|
|
||||||
|
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||||
|
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
for arg do
|
||||||
|
if
|
||||||
|
case $arg in #(
|
||||||
|
-*) false ;; # don't mess with options #(
|
||||||
|
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||||
|
[ -e "$t" ] ;; #(
|
||||||
|
*) false ;;
|
||||||
|
esac
|
||||||
|
then
|
||||||
|
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||||
|
fi
|
||||||
|
# Roll the args list around exactly as many times as the number of
|
||||||
|
# args, so each arg winds up back in the position where it started, but
|
||||||
|
# possibly modified.
|
||||||
|
#
|
||||||
|
# NB: a `for` loop captures its iteration list before it begins, so
|
||||||
|
# changing the positional parameters here affects neither the number of
|
||||||
|
# iterations, nor the values presented in `arg`.
|
||||||
|
shift # remove old arg
|
||||||
|
set -- "$@" "$arg" # push replacement arg
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Collect all arguments for the java command;
|
||||||
|
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||||
|
# shell script including quotes and variable substitutions, so put them in
|
||||||
|
# double quotes to make sure that they get re-expanded; and
|
||||||
|
# * put everything else in single quotes, so that it's not re-expanded.
|
||||||
|
|
||||||
|
set -- \
|
||||||
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
-classpath "$CLASSPATH" \
|
||||||
|
org.gradle.wrapper.GradleWrapperMain \
|
||||||
|
"$@"
|
||||||
|
|
||||||
|
# Use "xargs" to parse quoted args.
|
||||||
|
#
|
||||||
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
#
|
||||||
|
# In Bash we could simply go:
|
||||||
|
#
|
||||||
|
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||||
|
# set -- "${ARGS[@]}" "$@"
|
||||||
|
#
|
||||||
|
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||||
|
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||||
|
# character that might be a shell metacharacter, then use eval to reverse
|
||||||
|
# that process (while maintaining the separation between arguments), and wrap
|
||||||
|
# the whole thing up as a single "set" statement.
|
||||||
|
#
|
||||||
|
# This will of course break if any of these variables contains a newline or
|
||||||
|
# an unmatched quote.
|
||||||
|
#
|
||||||
|
|
||||||
|
eval "set -- $(
|
||||||
|
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||||
|
xargs -n1 |
|
||||||
|
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||||
|
tr '\n' ' '
|
||||||
|
)" '"$@"'
|
||||||
|
|
||||||
exec "$JAVACMD" "$@"
|
exec "$JAVACMD" "$@"
|
||||||
|
178
gradlew.bat
vendored
178
gradlew.bat
vendored
@ -1,89 +1,89 @@
|
|||||||
@rem
|
@rem
|
||||||
@rem Copyright 2015 the original author or authors.
|
@rem Copyright 2015 the original author or authors.
|
||||||
@rem
|
@rem
|
||||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
@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 not use this file except in compliance with the License.
|
||||||
@rem You may obtain a copy of the License at
|
@rem You may obtain a copy of the License at
|
||||||
@rem
|
@rem
|
||||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
@rem
|
@rem
|
||||||
@rem Unless required by applicable law or agreed to in writing, software
|
@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 distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@rem See the License for the specific language governing permissions and
|
@rem See the License for the specific language governing permissions and
|
||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%" == "" @echo off
|
@if "%DEBUG%" == "" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
@rem Gradle startup script for Windows
|
@rem Gradle startup script for Windows
|
||||||
@rem
|
@rem
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
|
|
||||||
@rem Set local scope for the variables with windows NT shell
|
@rem Set local scope for the variables with windows NT shell
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
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.
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
@rem Find java.exe
|
@rem Find java.exe
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if "%ERRORLEVEL%" == "0" goto execute
|
if "%ERRORLEVEL%" == "0" goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
echo.
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation.
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:findJavaFromJavaHome
|
:findJavaFromJavaHome
|
||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
echo.
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation.
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute Gradle
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
rem the _cmd.exe /c_ return code!
|
rem the _cmd.exe /c_ return code!
|
||||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
exit /b 1
|
exit /b 1
|
||||||
|
|
||||||
:mainEnd
|
:mainEnd
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
:omega
|
:omega
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2020 Nan1t
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets.play;
|
|
||||||
|
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
|
||||||
import ru.nanit.limbo.protocol.PacketOut;
|
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This packet was very simplified and using only for ADD_PLAYER action
|
|
||||||
*/
|
|
||||||
public class PacketPlayerInfo implements PacketOut {
|
|
||||||
|
|
||||||
private int gameMode = 3;
|
|
||||||
private String username = "";
|
|
||||||
private UUID uuid;
|
|
||||||
|
|
||||||
public void setGameMode(int gameMode) {
|
|
||||||
this.gameMode = gameMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUsername(String username) {
|
|
||||||
this.username = username;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUuid(UUID uuid) {
|
|
||||||
this.uuid = uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void encode(ByteMessage msg, Version version) {
|
|
||||||
msg.writeVarInt(0); // Add player action
|
|
||||||
msg.writeVarInt(1);
|
|
||||||
msg.writeUuid(uuid);
|
|
||||||
msg.writeString(username);
|
|
||||||
msg.writeVarInt(0);
|
|
||||||
msg.writeVarInt(gameMode);
|
|
||||||
msg.writeVarInt(60);
|
|
||||||
msg.writeBoolean(false);
|
|
||||||
if (version.moreOrEqual(Version.V1_19)) {
|
|
||||||
msg.writeBoolean(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,106 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2020 Nan1t
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package ru.nanit.limbo.world;
|
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
|
||||||
import org.spongepowered.configurate.ConfigurationNode;
|
|
||||||
import org.spongepowered.configurate.serialize.TypeSerializer;
|
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
public class Location {
|
|
||||||
|
|
||||||
private final double x;
|
|
||||||
private final double y;
|
|
||||||
private final double z;
|
|
||||||
private final float yaw;
|
|
||||||
private final float pitch;
|
|
||||||
|
|
||||||
Location(double x, double y, double z, float yaw, float pitch) {
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.z = z;
|
|
||||||
this.yaw = yaw;
|
|
||||||
this.pitch = pitch;
|
|
||||||
}
|
|
||||||
|
|
||||||
Location(double x, double y, double z) {
|
|
||||||
this(x, y, z, 0.0F, 0.0F);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getX() {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getBlockX() {
|
|
||||||
return (int) x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getY() {
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getBlockY() {
|
|
||||||
return (int) y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getZ() {
|
|
||||||
return z;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getBlockZ() {
|
|
||||||
return (int) z;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getYaw() {
|
|
||||||
return yaw;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getPitch() {
|
|
||||||
return pitch;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Location of(double x, double y, double z) {
|
|
||||||
return new Location(x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Location of(double x, double y, double z, float yaw, float pitch) {
|
|
||||||
return new Location(x, y, z, yaw, pitch);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Location pos(int x, int y, int z) {
|
|
||||||
return new Location(x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Serializer implements TypeSerializer<Location> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Location deserialize(Type type, ConfigurationNode node) {
|
|
||||||
double x = node.node("x").getDouble(0);
|
|
||||||
double y = node.node("y").getDouble(0);
|
|
||||||
double z = node.node("z").getDouble(0);
|
|
||||||
float yaw = node.node("yaw").getFloat(0.0F);
|
|
||||||
float pitch = node.node("pitch").getFloat(0.0F);
|
|
||||||
|
|
||||||
return new Location(x, y, z, yaw, pitch);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void serialize(Type type, @Nullable Location obj, ConfigurationNode node) { }
|
|
||||||
}
|
|
||||||
}
|
|
@ -15,7 +15,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo;
|
package ua.nanit.limbo;
|
||||||
|
|
||||||
public final class LimboConstants {
|
public final class LimboConstants {
|
||||||
|
|
@ -15,10 +15,10 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo;
|
package ua.nanit.limbo;
|
||||||
|
|
||||||
import ru.nanit.limbo.server.LimboServer;
|
import ua.nanit.limbo.server.LimboServer;
|
||||||
import ru.nanit.limbo.server.Logger;
|
import ua.nanit.limbo.server.Log;
|
||||||
|
|
||||||
public final class NanoLimbo {
|
public final class NanoLimbo {
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ public final class NanoLimbo {
|
|||||||
try {
|
try {
|
||||||
new LimboServer().start();
|
new LimboServer().start();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Logger.error("Cannot start server: ", e);
|
Log.error("Cannot start server: ", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -15,15 +15,17 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.configuration;
|
package ua.nanit.limbo.configuration;
|
||||||
|
|
||||||
import org.spongepowered.configurate.ConfigurationNode;
|
import org.spongepowered.configurate.ConfigurationNode;
|
||||||
import org.spongepowered.configurate.ConfigurationOptions;
|
import org.spongepowered.configurate.ConfigurationOptions;
|
||||||
import org.spongepowered.configurate.serialize.TypeSerializerCollection;
|
import org.spongepowered.configurate.serialize.TypeSerializerCollection;
|
||||||
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
|
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
|
||||||
import ru.nanit.limbo.server.data.*;
|
import ua.nanit.limbo.util.Colors;
|
||||||
import ru.nanit.limbo.util.Colors;
|
import ua.nanit.limbo.server.data.BossBar;
|
||||||
import ru.nanit.limbo.world.Location;
|
import ua.nanit.limbo.server.data.InfoForwarding;
|
||||||
|
import ua.nanit.limbo.server.data.PingData;
|
||||||
|
import ua.nanit.limbo.server.data.Title;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
@ -43,7 +45,6 @@ public final class LimboConfig {
|
|||||||
private PingData pingData;
|
private PingData pingData;
|
||||||
|
|
||||||
private String dimensionType;
|
private String dimensionType;
|
||||||
private Location spawnPosition;
|
|
||||||
private int gameMode;
|
private int gameMode;
|
||||||
|
|
||||||
private boolean useBrandName;
|
private boolean useBrandName;
|
||||||
@ -70,6 +71,11 @@ public final class LimboConfig {
|
|||||||
private int bossGroupSize;
|
private int bossGroupSize;
|
||||||
private int workerGroupSize;
|
private int workerGroupSize;
|
||||||
|
|
||||||
|
private boolean useTrafficLimits;
|
||||||
|
private int maxPacketSize;
|
||||||
|
private double interval;
|
||||||
|
private double maxPacketRate;
|
||||||
|
|
||||||
public LimboConfig(Path root) {
|
public LimboConfig(Path root) {
|
||||||
this.root = root;
|
this.root = root;
|
||||||
}
|
}
|
||||||
@ -86,14 +92,13 @@ public final class LimboConfig {
|
|||||||
address = conf.node("bind").get(SocketAddress.class);
|
address = conf.node("bind").get(SocketAddress.class);
|
||||||
maxPlayers = conf.node("maxPlayers").getInt();
|
maxPlayers = conf.node("maxPlayers").getInt();
|
||||||
pingData = conf.node("ping").get(PingData.class);
|
pingData = conf.node("ping").get(PingData.class);
|
||||||
dimensionType = conf.node("dimension").getString();
|
dimensionType = conf.node("dimension").getString("the_end");
|
||||||
if (dimensionType.equalsIgnoreCase("nether")) {
|
if (dimensionType.equalsIgnoreCase("nether")) {
|
||||||
dimensionType = "the_nether";
|
dimensionType = "the_nether";
|
||||||
}
|
}
|
||||||
if (dimensionType.equalsIgnoreCase("end")) {
|
if (dimensionType.equalsIgnoreCase("end")) {
|
||||||
dimensionType = "the_end";
|
dimensionType = "the_end";
|
||||||
}
|
}
|
||||||
spawnPosition = conf.node("spawnPosition").get(Location.class);
|
|
||||||
gameMode = conf.node("gameMode").getInt();
|
gameMode = conf.node("gameMode").getInt();
|
||||||
useBrandName = conf.node("brandName", "enable").getBoolean();
|
useBrandName = conf.node("brandName", "enable").getBoolean();
|
||||||
useJoinMessage = conf.node("joinMessage", "enable").getBoolean();
|
useJoinMessage = conf.node("joinMessage", "enable").getBoolean();
|
||||||
@ -127,6 +132,11 @@ public final class LimboConfig {
|
|||||||
useEpoll = conf.node("netty", "useEpoll").getBoolean(true);
|
useEpoll = conf.node("netty", "useEpoll").getBoolean(true);
|
||||||
bossGroupSize = conf.node("netty", "threads", "bossGroup").getInt(1);
|
bossGroupSize = conf.node("netty", "threads", "bossGroup").getInt(1);
|
||||||
workerGroupSize = conf.node("netty", "threads", "workerGroup").getInt(4);
|
workerGroupSize = conf.node("netty", "threads", "workerGroup").getInt(4);
|
||||||
|
|
||||||
|
useTrafficLimits = conf.node("traffic", "enable").getBoolean(false);
|
||||||
|
maxPacketSize = conf.node("traffic", "maxPacketSize").getInt(-1);
|
||||||
|
interval = conf.node("traffic", "interval").getDouble(-1.0);
|
||||||
|
maxPacketRate = conf.node("traffic", "maxPacketRate").getDouble(-1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BufferedReader getReader() throws IOException {
|
private BufferedReader getReader() throws IOException {
|
||||||
@ -152,7 +162,6 @@ public final class LimboConfig {
|
|||||||
.register(PingData.class, new PingData.Serializer())
|
.register(PingData.class, new PingData.Serializer())
|
||||||
.register(BossBar.class, new BossBar.Serializer())
|
.register(BossBar.class, new BossBar.Serializer())
|
||||||
.register(Title.class, new Title.Serializer())
|
.register(Title.class, new Title.Serializer())
|
||||||
.register(Location.class, new Location.Serializer())
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,10 +181,6 @@ public final class LimboConfig {
|
|||||||
return dimensionType;
|
return dimensionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Location getSpawnPosition() {
|
|
||||||
return spawnPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getGameMode() {
|
public int getGameMode() {
|
||||||
return gameMode;
|
return gameMode;
|
||||||
}
|
}
|
||||||
@ -255,4 +260,20 @@ public final class LimboConfig {
|
|||||||
public int getWorkerGroupSize() {
|
public int getWorkerGroupSize() {
|
||||||
return workerGroupSize;
|
return workerGroupSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isUseTrafficLimits() {
|
||||||
|
return useTrafficLimits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxPacketSize() {
|
||||||
|
return maxPacketSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getInterval() {
|
||||||
|
return interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getMaxPacketRate() {
|
||||||
|
return maxPacketRate;
|
||||||
|
}
|
||||||
}
|
}
|
@ -15,7 +15,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.configuration;
|
package ua.nanit.limbo.configuration;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.spongepowered.configurate.ConfigurationNode;
|
import org.spongepowered.configurate.ConfigurationNode;
|
@ -15,17 +15,14 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.connection;
|
package ua.nanit.limbo.connection;
|
||||||
|
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelInitializer;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.handler.timeout.ReadTimeoutHandler;
|
import io.netty.handler.timeout.ReadTimeoutHandler;
|
||||||
import ru.nanit.limbo.connection.pipeline.PacketDecoder;
|
import ua.nanit.limbo.connection.pipeline.*;
|
||||||
import ru.nanit.limbo.connection.pipeline.PacketEncoder;
|
import ua.nanit.limbo.server.LimboServer;
|
||||||
import ru.nanit.limbo.connection.pipeline.VarIntFrameDecoder;
|
|
||||||
import ru.nanit.limbo.connection.pipeline.VarIntLengthEncoder;
|
|
||||||
import ru.nanit.limbo.server.LimboServer;
|
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@ -49,6 +46,15 @@ public class ClientChannelInitializer extends ChannelInitializer<Channel> {
|
|||||||
TimeUnit.MILLISECONDS));
|
TimeUnit.MILLISECONDS));
|
||||||
pipeline.addLast("frame_decoder", new VarIntFrameDecoder());
|
pipeline.addLast("frame_decoder", new VarIntFrameDecoder());
|
||||||
pipeline.addLast("frame_encoder", new VarIntLengthEncoder());
|
pipeline.addLast("frame_encoder", new VarIntLengthEncoder());
|
||||||
|
|
||||||
|
if (server.getConfig().isUseTrafficLimits()) {
|
||||||
|
pipeline.addLast("traffic_limit", new ChannelTrafficHandler(
|
||||||
|
server.getConfig().getMaxPacketSize(),
|
||||||
|
server.getConfig().getInterval(),
|
||||||
|
server.getConfig().getMaxPacketRate()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
pipeline.addLast("decoder", decoder);
|
pipeline.addLast("decoder", decoder);
|
||||||
pipeline.addLast("encoder", encoder);
|
pipeline.addLast("encoder", encoder);
|
||||||
pipeline.addLast("handler", connection);
|
pipeline.addLast("handler", connection);
|
@ -15,7 +15,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.connection;
|
package ua.nanit.limbo.connection;
|
||||||
|
|
||||||
import com.grack.nanojson.JsonArray;
|
import com.grack.nanojson.JsonArray;
|
||||||
import com.grack.nanojson.JsonObject;
|
import com.grack.nanojson.JsonObject;
|
||||||
@ -26,17 +26,18 @@ import io.netty.channel.ChannelFutureListener;
|
|||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import ru.nanit.limbo.connection.pipeline.PacketDecoder;
|
import ua.nanit.limbo.connection.pipeline.PacketDecoder;
|
||||||
import ru.nanit.limbo.connection.pipeline.PacketEncoder;
|
import ua.nanit.limbo.connection.pipeline.PacketEncoder;
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.Packet;
|
import ua.nanit.limbo.protocol.Packet;
|
||||||
import ru.nanit.limbo.protocol.packets.login.*;
|
import ua.nanit.limbo.protocol.PacketSnapshot;
|
||||||
import ru.nanit.limbo.protocol.packets.play.*;
|
import ua.nanit.limbo.protocol.packets.login.PacketDisconnect;
|
||||||
import ru.nanit.limbo.protocol.registry.State;
|
import ua.nanit.limbo.protocol.packets.play.PacketKeepAlive;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.State;
|
||||||
import ru.nanit.limbo.server.LimboServer;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
import ru.nanit.limbo.server.Logger;
|
import ua.nanit.limbo.server.LimboServer;
|
||||||
import ru.nanit.limbo.util.UuidUtil;
|
import ua.nanit.limbo.server.Log;
|
||||||
|
import ua.nanit.limbo.util.UuidUtil;
|
||||||
|
|
||||||
import javax.crypto.Mac;
|
import javax.crypto.Mac;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
@ -46,6 +47,7 @@ import java.security.InvalidKeyException;
|
|||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class ClientConnection extends ChannelInboundHandlerAdapter {
|
public class ClientConnection extends ChannelInboundHandlerAdapter {
|
||||||
|
|
||||||
@ -93,7 +95,7 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void channelInactive(@NotNull ChannelHandlerContext ctx) throws Exception {
|
public void channelInactive(@NotNull ChannelHandlerContext ctx) throws Exception {
|
||||||
if (state.equals(State.PLAY)) {
|
if (state.equals(State.PLAY) || state.equals(State.CONFIGURATION)) {
|
||||||
server.getConnections().removeConnection(this);
|
server.getConnections().removeConnection(this);
|
||||||
}
|
}
|
||||||
super.channelInactive(ctx);
|
super.channelInactive(ctx);
|
||||||
@ -102,7 +104,7 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
|
|||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||||
if (channel.isActive()) {
|
if (channel.isActive()) {
|
||||||
Logger.error("Unhandled exception: ", cause);
|
Log.error("Unhandled exception: ", cause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +115,7 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
|
|||||||
|
|
||||||
public void handlePacket(Object packet) {
|
public void handlePacket(Object packet) {
|
||||||
if (packet instanceof Packet) {
|
if (packet instanceof Packet) {
|
||||||
((Packet)packet).handle(this, server);
|
((Packet) packet).handle(this, server);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,38 +125,90 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
writePacket(PacketSnapshots.PACKET_LOGIN_SUCCESS);
|
sendPacket(PacketSnapshots.PACKET_LOGIN_SUCCESS);
|
||||||
updateState(State.PLAY);
|
|
||||||
|
|
||||||
server.getConnections().addConnection(this);
|
server.getConnections().addConnection(this);
|
||||||
|
|
||||||
writePacket(PacketSnapshots.PACKET_JOIN_GAME);
|
// Preparing for configuration mode
|
||||||
writePacket(PacketSnapshots.PACKET_PLAYER_ABILITIES);
|
if (clientVersion.moreOrEqual(Version.V1_20_2)) {
|
||||||
writePacket(PacketSnapshots.PACKET_PLAYER_POS);
|
updateEncoderState(State.CONFIGURATION);
|
||||||
|
return;
|
||||||
if (server.getConfig().isUsePlayerList() || clientVersion.equals(Version.V1_16_4))
|
|
||||||
writePacket(PacketSnapshots.PACKET_PLAYER_INFO);
|
|
||||||
|
|
||||||
if (clientVersion.moreOrEqual(Version.V1_13)) {
|
|
||||||
writePacket(PacketSnapshots.PACKET_DECLARE_COMMANDS);
|
|
||||||
|
|
||||||
if (PacketSnapshots.PACKET_PLUGIN_MESSAGE != null)
|
|
||||||
writePacket(PacketSnapshots.PACKET_PLUGIN_MESSAGE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PacketSnapshots.PACKET_BOSS_BAR != null && clientVersion.moreOrEqual(Version.V1_9))
|
spawnPlayer();
|
||||||
writePacket(PacketSnapshots.PACKET_BOSS_BAR);
|
}
|
||||||
|
|
||||||
if (PacketSnapshots.PACKET_JOIN_MESSAGE != null)
|
public void spawnPlayer() {
|
||||||
writePacket(PacketSnapshots.PACKET_JOIN_MESSAGE);
|
updateState(State.PLAY);
|
||||||
|
|
||||||
if (PacketSnapshots.PACKET_TITLE_TITLE != null)
|
Runnable sendPlayPackets = () -> {
|
||||||
writeTitle();
|
writePacket(PacketSnapshots.PACKET_JOIN_GAME);
|
||||||
|
writePacket(PacketSnapshots.PACKET_PLAYER_ABILITIES);
|
||||||
|
|
||||||
if (PacketSnapshots.PACKET_HEADER_AND_FOOTER != null)
|
if (clientVersion.less(Version.V1_9)) {
|
||||||
writePacket(PacketSnapshots.PACKET_HEADER_AND_FOOTER);
|
writePacket(PacketSnapshots.PACKET_PLAYER_POS_AND_LOOK_LEGACY);
|
||||||
|
} else {
|
||||||
|
writePacket(PacketSnapshots.PACKET_PLAYER_POS_AND_LOOK);
|
||||||
|
}
|
||||||
|
|
||||||
sendKeepAlive();
|
if (clientVersion.moreOrEqual(Version.V1_19_3))
|
||||||
|
writePacket(PacketSnapshots.PACKET_SPAWN_POSITION);
|
||||||
|
|
||||||
|
if (server.getConfig().isUsePlayerList() || clientVersion.equals(Version.V1_16_4))
|
||||||
|
writePacket(PacketSnapshots.PACKET_PLAYER_INFO);
|
||||||
|
|
||||||
|
if (clientVersion.moreOrEqual(Version.V1_13)) {
|
||||||
|
writePacket(PacketSnapshots.PACKET_DECLARE_COMMANDS);
|
||||||
|
|
||||||
|
if (PacketSnapshots.PACKET_PLUGIN_MESSAGE != null)
|
||||||
|
writePacket(PacketSnapshots.PACKET_PLUGIN_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PacketSnapshots.PACKET_BOSS_BAR != null && clientVersion.moreOrEqual(Version.V1_9))
|
||||||
|
writePacket(PacketSnapshots.PACKET_BOSS_BAR);
|
||||||
|
|
||||||
|
if (PacketSnapshots.PACKET_JOIN_MESSAGE != null)
|
||||||
|
writePacket(PacketSnapshots.PACKET_JOIN_MESSAGE);
|
||||||
|
|
||||||
|
if (PacketSnapshots.PACKET_TITLE_TITLE != null && clientVersion.moreOrEqual(Version.V1_8))
|
||||||
|
writeTitle();
|
||||||
|
|
||||||
|
if (PacketSnapshots.PACKET_HEADER_AND_FOOTER != null && clientVersion.moreOrEqual(Version.V1_8))
|
||||||
|
writePacket(PacketSnapshots.PACKET_HEADER_AND_FOOTER);
|
||||||
|
|
||||||
|
if (clientVersion.moreOrEqual(Version.V1_20_3)) {
|
||||||
|
writePacket(PacketSnapshots.PACKET_START_WAITING_CHUNKS);
|
||||||
|
|
||||||
|
for (PacketSnapshot chunk : PacketSnapshots.PACKETS_EMPTY_CHUNKS) {
|
||||||
|
writePacket(chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sendKeepAlive();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (clientVersion.lessOrEqual(Version.V1_7_6)) {
|
||||||
|
this.channel.eventLoop().schedule(sendPlayPackets, 100, TimeUnit.MILLISECONDS);
|
||||||
|
} else {
|
||||||
|
sendPlayPackets.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onLoginAcknowledgedReceived() {
|
||||||
|
updateState(State.CONFIGURATION);
|
||||||
|
|
||||||
|
if (PacketSnapshots.PACKET_PLUGIN_MESSAGE != null)
|
||||||
|
writePacket(PacketSnapshots.PACKET_PLUGIN_MESSAGE);
|
||||||
|
|
||||||
|
if (clientVersion.moreOrEqual(Version.V1_20_5)) {
|
||||||
|
for (PacketSnapshot packet : PacketSnapshots.PACKETS_REGISTRY_DATA) {
|
||||||
|
writePacket(packet);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
writePacket(PacketSnapshots.PACKET_REGISTRY_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendPacket(PacketSnapshots.PACKET_FINISH_CONFIGURATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disconnectLogin(String reason) {
|
public void disconnectLogin(String reason) {
|
||||||
@ -210,6 +264,10 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
|
|||||||
encoder.updateState(state);
|
encoder.updateState(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateEncoderState(State state) {
|
||||||
|
encoder.updateState(state);
|
||||||
|
}
|
||||||
|
|
||||||
public void updateVersion(Version version) {
|
public void updateVersion(Version version) {
|
||||||
clientVersion = version;
|
clientVersion = version;
|
||||||
decoder.updateVersion(version);
|
decoder.updateVersion(version);
|
||||||
@ -217,7 +275,7 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setAddress(String host) {
|
public void setAddress(String host) {
|
||||||
this.address = new InetSocketAddress(host, ((InetSocketAddress)this.address).getPort());
|
this.address = new InetSocketAddress(host, ((InetSocketAddress) this.address).getPort());
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean checkBungeeGuardHandshake(String handshake) {
|
boolean checkBungeeGuardHandshake(String handshake) {
|
||||||
@ -254,7 +312,7 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
|
|||||||
setAddress(socketAddressHostname);
|
setAddress(socketAddressHostname);
|
||||||
gameProfile.setUuid(uuid);
|
gameProfile.setUuid(uuid);
|
||||||
|
|
||||||
Logger.debug("Successfully verified BungeeGuard token");
|
Log.debug("Successfully verified BungeeGuard token");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -278,7 +336,7 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
|
|||||||
byte[] mySignature = mac.doFinal(data);
|
byte[] mySignature = mac.doFinal(data);
|
||||||
if (!MessageDigest.isEqual(signature, mySignature))
|
if (!MessageDigest.isEqual(signature, mySignature))
|
||||||
return false;
|
return false;
|
||||||
} catch (InvalidKeyException |java.security.NoSuchAlgorithmException e) {
|
} catch (InvalidKeyException | java.security.NoSuchAlgorithmException e) {
|
||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
}
|
}
|
||||||
int version = buf.readVarInt();
|
int version = buf.readVarInt();
|
@ -1,42 +1,42 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2020 Nan1t
|
* Copyright (C) 2020 Nan1t
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.connection;
|
package ua.nanit.limbo.connection;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class GameProfile {
|
public class GameProfile {
|
||||||
|
|
||||||
private UUID uuid;
|
private UUID uuid;
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
public UUID getUuid() {
|
public UUID getUuid() {
|
||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUuid(UUID uuid) {
|
public void setUuid(UUID uuid) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUsername() {
|
public String getUsername() {
|
||||||
return username;
|
return username;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUsername(String username) {
|
public void setUsername(String username) {
|
||||||
this.username = username;
|
this.username = username;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,20 +15,22 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.connection;
|
package ua.nanit.limbo.connection;
|
||||||
|
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import ru.nanit.limbo.LimboConstants;
|
import ua.nanit.limbo.LimboConstants;
|
||||||
import ru.nanit.limbo.protocol.packets.PacketHandshake;
|
import ua.nanit.limbo.protocol.packets.PacketHandshake;
|
||||||
import ru.nanit.limbo.protocol.packets.login.PacketLoginPluginRequest;
|
import ua.nanit.limbo.protocol.packets.configuration.PacketFinishConfiguration;
|
||||||
import ru.nanit.limbo.protocol.packets.login.PacketLoginPluginResponse;
|
import ua.nanit.limbo.protocol.packets.login.PacketLoginAcknowledged;
|
||||||
import ru.nanit.limbo.protocol.packets.login.PacketLoginStart;
|
import ua.nanit.limbo.protocol.packets.login.PacketLoginPluginRequest;
|
||||||
import ru.nanit.limbo.protocol.packets.status.PacketStatusPing;
|
import ua.nanit.limbo.protocol.packets.login.PacketLoginPluginResponse;
|
||||||
import ru.nanit.limbo.protocol.packets.status.PacketStatusRequest;
|
import ua.nanit.limbo.protocol.packets.login.PacketLoginStart;
|
||||||
import ru.nanit.limbo.protocol.packets.status.PacketStatusResponse;
|
import ua.nanit.limbo.protocol.packets.status.PacketStatusPing;
|
||||||
import ru.nanit.limbo.server.LimboServer;
|
import ua.nanit.limbo.protocol.packets.status.PacketStatusRequest;
|
||||||
import ru.nanit.limbo.server.Logger;
|
import ua.nanit.limbo.protocol.packets.status.PacketStatusResponse;
|
||||||
import ru.nanit.limbo.util.UuidUtil;
|
import ua.nanit.limbo.server.LimboServer;
|
||||||
|
import ua.nanit.limbo.server.Log;
|
||||||
|
import ua.nanit.limbo.util.UuidUtil;
|
||||||
|
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
@ -44,7 +46,7 @@ public class PacketHandler {
|
|||||||
conn.updateVersion(packet.getVersion());
|
conn.updateVersion(packet.getVersion());
|
||||||
conn.updateState(packet.getNextState());
|
conn.updateState(packet.getNextState());
|
||||||
|
|
||||||
Logger.debug("Pinged from %s [%s]", conn.getAddress(),
|
Log.debug("Pinged from %s [%s]", conn.getAddress(),
|
||||||
conn.getClientVersion().toString());
|
conn.getClientVersion().toString());
|
||||||
|
|
||||||
if (server.getConfig().getInfoForwarding().isLegacy()) {
|
if (server.getConfig().getInfoForwarding().isLegacy()) {
|
||||||
@ -127,4 +129,12 @@ public class PacketHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void handle(ClientConnection conn, PacketLoginAcknowledged packet) {
|
||||||
|
conn.onLoginAcknowledgedReceived();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handle(ClientConnection conn, PacketFinishConfiguration packet) {
|
||||||
|
conn.spawnPlayer();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -15,17 +15,26 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.connection;
|
package ua.nanit.limbo.connection;
|
||||||
|
|
||||||
import ru.nanit.limbo.LimboConstants;
|
import net.kyori.adventure.nbt.BinaryTag;
|
||||||
import ru.nanit.limbo.protocol.PacketSnapshot;
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import ru.nanit.limbo.protocol.packets.login.PacketLoginSuccess;
|
import net.kyori.adventure.nbt.ListBinaryTag;
|
||||||
import ru.nanit.limbo.protocol.packets.play.*;
|
import ua.nanit.limbo.LimboConstants;
|
||||||
import ru.nanit.limbo.server.LimboServer;
|
import ua.nanit.limbo.protocol.PacketSnapshot;
|
||||||
import ru.nanit.limbo.server.data.Title;
|
import ua.nanit.limbo.protocol.packets.configuration.PacketFinishConfiguration;
|
||||||
import ru.nanit.limbo.util.UuidUtil;
|
import ua.nanit.limbo.protocol.packets.configuration.PacketRegistryData;
|
||||||
|
import ua.nanit.limbo.protocol.packets.login.PacketLoginSuccess;
|
||||||
|
import ua.nanit.limbo.protocol.packets.play.*;
|
||||||
|
import ua.nanit.limbo.server.LimboServer;
|
||||||
|
import ua.nanit.limbo.server.data.Title;
|
||||||
|
import ua.nanit.limbo.util.NbtMessageUtil;
|
||||||
|
import ua.nanit.limbo.util.UuidUtil;
|
||||||
|
import ua.nanit.limbo.world.Dimension;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
@ -33,15 +42,19 @@ public final class PacketSnapshots {
|
|||||||
|
|
||||||
public static PacketSnapshot PACKET_LOGIN_SUCCESS;
|
public static PacketSnapshot PACKET_LOGIN_SUCCESS;
|
||||||
public static PacketSnapshot PACKET_JOIN_GAME;
|
public static PacketSnapshot PACKET_JOIN_GAME;
|
||||||
|
public static PacketSnapshot PACKET_SPAWN_POSITION;
|
||||||
public static PacketSnapshot PACKET_PLUGIN_MESSAGE;
|
public static PacketSnapshot PACKET_PLUGIN_MESSAGE;
|
||||||
public static PacketSnapshot PACKET_PLAYER_ABILITIES;
|
public static PacketSnapshot PACKET_PLAYER_ABILITIES;
|
||||||
public static PacketSnapshot PACKET_PLAYER_INFO;
|
public static PacketSnapshot PACKET_PLAYER_INFO;
|
||||||
public static PacketSnapshot PACKET_DECLARE_COMMANDS;
|
public static PacketSnapshot PACKET_DECLARE_COMMANDS;
|
||||||
public static PacketSnapshot PACKET_PLAYER_POS;
|
|
||||||
public static PacketSnapshot PACKET_JOIN_MESSAGE;
|
public static PacketSnapshot PACKET_JOIN_MESSAGE;
|
||||||
public static PacketSnapshot PACKET_BOSS_BAR;
|
public static PacketSnapshot PACKET_BOSS_BAR;
|
||||||
public static PacketSnapshot PACKET_HEADER_AND_FOOTER;
|
public static PacketSnapshot PACKET_HEADER_AND_FOOTER;
|
||||||
|
|
||||||
|
public static PacketSnapshot PACKET_PLAYER_POS_AND_LOOK_LEGACY;
|
||||||
|
// For 1.19 we need to spawn player outside the world to avoid stuck in terrain loading
|
||||||
|
public static PacketSnapshot PACKET_PLAYER_POS_AND_LOOK;
|
||||||
|
|
||||||
public static PacketSnapshot PACKET_TITLE_TITLE;
|
public static PacketSnapshot PACKET_TITLE_TITLE;
|
||||||
public static PacketSnapshot PACKET_TITLE_SUBTITLE;
|
public static PacketSnapshot PACKET_TITLE_SUBTITLE;
|
||||||
public static PacketSnapshot PACKET_TITLE_TIMES;
|
public static PacketSnapshot PACKET_TITLE_TIMES;
|
||||||
@ -50,6 +63,12 @@ public final class PacketSnapshots {
|
|||||||
public static PacketSnapshot PACKET_TITLE_LEGACY_SUBTITLE;
|
public static PacketSnapshot PACKET_TITLE_LEGACY_SUBTITLE;
|
||||||
public static PacketSnapshot PACKET_TITLE_LEGACY_TIMES;
|
public static PacketSnapshot PACKET_TITLE_LEGACY_TIMES;
|
||||||
|
|
||||||
|
public static PacketSnapshot PACKET_REGISTRY_DATA;
|
||||||
|
public static List<PacketSnapshot> PACKETS_REGISTRY_DATA;
|
||||||
|
public static PacketSnapshot PACKET_FINISH_CONFIGURATION;
|
||||||
|
|
||||||
|
public static List<PacketSnapshot> PACKETS_EMPTY_CHUNKS;
|
||||||
|
public static PacketSnapshot PACKET_START_WAITING_CHUNKS;
|
||||||
|
|
||||||
private PacketSnapshots() { }
|
private PacketSnapshots() { }
|
||||||
|
|
||||||
@ -62,6 +81,7 @@ public final class PacketSnapshots {
|
|||||||
loginSuccess.setUuid(uuid);
|
loginSuccess.setUuid(uuid);
|
||||||
|
|
||||||
PacketJoinGame joinGame = new PacketJoinGame();
|
PacketJoinGame joinGame = new PacketJoinGame();
|
||||||
|
String worldName = "minecraft:" + server.getConfig().getDimensionType().toLowerCase();
|
||||||
joinGame.setEntityId(0);
|
joinGame.setEntityId(0);
|
||||||
joinGame.setEnableRespawnScreen(true);
|
joinGame.setEnableRespawnScreen(true);
|
||||||
joinGame.setFlat(false);
|
joinGame.setFlat(false);
|
||||||
@ -72,7 +92,6 @@ public final class PacketSnapshots {
|
|||||||
joinGame.setReducedDebugInfo(true);
|
joinGame.setReducedDebugInfo(true);
|
||||||
joinGame.setDebug(false);
|
joinGame.setDebug(false);
|
||||||
joinGame.setViewDistance(0);
|
joinGame.setViewDistance(0);
|
||||||
String worldName = "minecraft:" + server.getConfig().getDimensionType().toLowerCase();
|
|
||||||
joinGame.setWorldName(worldName);
|
joinGame.setWorldName(worldName);
|
||||||
joinGame.setWorldNames(worldName);
|
joinGame.setWorldNames(worldName);
|
||||||
joinGame.setHashedSeed(0);
|
joinGame.setHashedSeed(0);
|
||||||
@ -83,13 +102,15 @@ public final class PacketSnapshots {
|
|||||||
playerAbilities.setFlags(0x02);
|
playerAbilities.setFlags(0x02);
|
||||||
playerAbilities.setFieldOfView(0.1F);
|
playerAbilities.setFieldOfView(0.1F);
|
||||||
|
|
||||||
PacketPlayerPositionAndLook positionAndLook = new PacketPlayerPositionAndLook();
|
int teleportId = ThreadLocalRandom.current().nextInt();
|
||||||
positionAndLook.setX(server.getConfig().getSpawnPosition().getX());
|
|
||||||
positionAndLook.setY(server.getConfig().getSpawnPosition().getY());
|
PacketPlayerPositionAndLook positionAndLookLegacy
|
||||||
positionAndLook.setZ(server.getConfig().getSpawnPosition().getZ());
|
= new PacketPlayerPositionAndLook(0, 64, 0, 0, 0, teleportId);
|
||||||
positionAndLook.setYaw(server.getConfig().getSpawnPosition().getYaw());
|
|
||||||
positionAndLook.setPitch(server.getConfig().getSpawnPosition().getPitch());
|
PacketPlayerPositionAndLook positionAndLook
|
||||||
positionAndLook.setTeleportId(ThreadLocalRandom.current().nextInt());
|
= new PacketPlayerPositionAndLook(0, 400, 0, 0, 0, teleportId);
|
||||||
|
|
||||||
|
PacketSpawnPosition packetSpawnPosition = new PacketSpawnPosition(0, 400, 0);
|
||||||
|
|
||||||
PacketDeclareCommands declareCommands = new PacketDeclareCommands();
|
PacketDeclareCommands declareCommands = new PacketDeclareCommands();
|
||||||
declareCommands.setCommands(Collections.emptyList());
|
declareCommands.setCommands(Collections.emptyList());
|
||||||
@ -101,16 +122,18 @@ public final class PacketSnapshots {
|
|||||||
|
|
||||||
PACKET_LOGIN_SUCCESS = PacketSnapshot.of(loginSuccess);
|
PACKET_LOGIN_SUCCESS = PacketSnapshot.of(loginSuccess);
|
||||||
PACKET_JOIN_GAME = PacketSnapshot.of(joinGame);
|
PACKET_JOIN_GAME = PacketSnapshot.of(joinGame);
|
||||||
|
PACKET_PLAYER_POS_AND_LOOK_LEGACY = PacketSnapshot.of(positionAndLookLegacy);
|
||||||
|
PACKET_PLAYER_POS_AND_LOOK = PacketSnapshot.of(positionAndLook);
|
||||||
|
PACKET_SPAWN_POSITION = PacketSnapshot.of(packetSpawnPosition);
|
||||||
PACKET_PLAYER_ABILITIES = PacketSnapshot.of(playerAbilities);
|
PACKET_PLAYER_ABILITIES = PacketSnapshot.of(playerAbilities);
|
||||||
PACKET_PLAYER_POS = PacketSnapshot.of(positionAndLook);
|
|
||||||
PACKET_PLAYER_INFO = PacketSnapshot.of(info);
|
PACKET_PLAYER_INFO = PacketSnapshot.of(info);
|
||||||
|
|
||||||
PACKET_DECLARE_COMMANDS = PacketSnapshot.of(declareCommands);
|
PACKET_DECLARE_COMMANDS = PacketSnapshot.of(declareCommands);
|
||||||
|
|
||||||
if (server.getConfig().isUseHeaderAndFooter()) {
|
if (server.getConfig().isUseHeaderAndFooter()) {
|
||||||
PacketPlayerListHeader header = new PacketPlayerListHeader();
|
PacketPlayerListHeader header = new PacketPlayerListHeader();
|
||||||
header.setHeader(server.getConfig().getPlayerListHeader());
|
header.setHeader(NbtMessageUtil.create(server.getConfig().getPlayerListHeader()));
|
||||||
header.setFooter(server.getConfig().getPlayerListFooter());
|
header.setFooter(NbtMessageUtil.create(server.getConfig().getPlayerListFooter()));
|
||||||
PACKET_HEADER_AND_FOOTER = PacketSnapshot.of(header);
|
PACKET_HEADER_AND_FOOTER = PacketSnapshot.of(header);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +146,7 @@ public final class PacketSnapshots {
|
|||||||
|
|
||||||
if (server.getConfig().isUseJoinMessage()) {
|
if (server.getConfig().isUseJoinMessage()) {
|
||||||
PacketChatMessage joinMessage = new PacketChatMessage();
|
PacketChatMessage joinMessage = new PacketChatMessage();
|
||||||
joinMessage.setJsonData(server.getConfig().getJoinMessage());
|
joinMessage.setMessage(NbtMessageUtil.create(server.getConfig().getJoinMessage()));
|
||||||
joinMessage.setPosition(PacketChatMessage.PositionLegacy.SYSTEM_MESSAGE);
|
joinMessage.setPosition(PacketChatMessage.PositionLegacy.SYSTEM_MESSAGE);
|
||||||
joinMessage.setSender(UUID.randomUUID());
|
joinMessage.setSender(UUID.randomUUID());
|
||||||
PACKET_JOIN_MESSAGE = PacketSnapshot.of(joinMessage);
|
PACKET_JOIN_MESSAGE = PacketSnapshot.of(joinMessage);
|
||||||
@ -170,5 +193,65 @@ public final class PacketSnapshots {
|
|||||||
PACKET_TITLE_LEGACY_SUBTITLE = PacketSnapshot.of(legacySubtitle);
|
PACKET_TITLE_LEGACY_SUBTITLE = PacketSnapshot.of(legacySubtitle);
|
||||||
PACKET_TITLE_LEGACY_TIMES = PacketSnapshot.of(legacyTimes);
|
PACKET_TITLE_LEGACY_TIMES = PacketSnapshot.of(legacyTimes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PacketRegistryData packetRegistryData = new PacketRegistryData();
|
||||||
|
packetRegistryData.setDimensionRegistry(server.getDimensionRegistry());
|
||||||
|
|
||||||
|
PACKET_REGISTRY_DATA = PacketSnapshot.of(packetRegistryData);
|
||||||
|
|
||||||
|
Dimension dimension1_21 = server.getDimensionRegistry().getDimension_1_21();
|
||||||
|
List<PacketSnapshot> packetRegistries = new ArrayList<>();
|
||||||
|
CompoundBinaryTag dimensionTag = dimension1_21.getData();
|
||||||
|
for (String registryType : dimensionTag.keySet()) {
|
||||||
|
CompoundBinaryTag compoundRegistryType = dimensionTag.getCompound(registryType);
|
||||||
|
|
||||||
|
PacketRegistryData registryData = new PacketRegistryData();
|
||||||
|
registryData.setDimensionRegistry(server.getDimensionRegistry());
|
||||||
|
|
||||||
|
ListBinaryTag values = compoundRegistryType.getList("value");
|
||||||
|
registryData.setMetadataWriter((message, version) -> {
|
||||||
|
message.writeString(registryType);
|
||||||
|
|
||||||
|
message.writeVarInt(values.size());
|
||||||
|
for (BinaryTag entry : values) {
|
||||||
|
CompoundBinaryTag entryTag = (CompoundBinaryTag) entry;
|
||||||
|
|
||||||
|
String name = entryTag.getString("name");
|
||||||
|
CompoundBinaryTag element = entryTag.getCompound("element");
|
||||||
|
|
||||||
|
message.writeString(name);
|
||||||
|
message.writeBoolean(true);
|
||||||
|
message.writeNamelessCompoundTag(element);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
packetRegistries.add(PacketSnapshot.of(registryData));
|
||||||
|
}
|
||||||
|
|
||||||
|
PACKETS_REGISTRY_DATA = packetRegistries;
|
||||||
|
|
||||||
|
PACKET_FINISH_CONFIGURATION = PacketSnapshot.of(new PacketFinishConfiguration());
|
||||||
|
|
||||||
|
PacketGameEvent packetGameEvent = new PacketGameEvent();
|
||||||
|
packetGameEvent.setType((byte) 13); // Waiting for chunks type
|
||||||
|
packetGameEvent.setValue(0);
|
||||||
|
PACKET_START_WAITING_CHUNKS = PacketSnapshot.of(packetGameEvent);
|
||||||
|
|
||||||
|
int chunkXOffset = (int) 0 >> 4; // Default x position is 0
|
||||||
|
int chunkZOffset = (int) 0 >> 4; // Default z position is 0
|
||||||
|
int chunkEdgeSize = 1; // TODO Make configurable?
|
||||||
|
|
||||||
|
List<PacketSnapshot> emptyChunks = new ArrayList<>();
|
||||||
|
// Make multiple chunks for edges
|
||||||
|
for (int chunkX = chunkXOffset - chunkEdgeSize; chunkX <= chunkXOffset + chunkEdgeSize; ++chunkX) {
|
||||||
|
for (int chunkZ = chunkZOffset - chunkEdgeSize; chunkZ <= chunkZOffset + chunkEdgeSize; ++chunkZ) {
|
||||||
|
PacketEmptyChunk packetEmptyChunk = new PacketEmptyChunk();
|
||||||
|
packetEmptyChunk.setX(chunkX);
|
||||||
|
packetEmptyChunk.setZ(chunkZ);
|
||||||
|
|
||||||
|
emptyChunks.add(PacketSnapshot.of(packetEmptyChunk));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PACKETS_EMPTY_CHUNKS = emptyChunks;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,111 @@
|
|||||||
|
package ua.nanit.limbo.connection.pipeline;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import ua.nanit.limbo.server.Log;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class ChannelTrafficHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
|
||||||
|
private final int maxPacketSize;
|
||||||
|
private final double maxPacketRate;
|
||||||
|
private final PacketBucket packetBucket;
|
||||||
|
|
||||||
|
public ChannelTrafficHandler(int maxPacketSize, double interval, double maxPacketRate) {
|
||||||
|
this.maxPacketSize = maxPacketSize;
|
||||||
|
this.maxPacketRate = maxPacketRate;
|
||||||
|
this.packetBucket = (interval > 0.0 && maxPacketRate > 0.0) ? new PacketBucket(interval * 1000.0, 150) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelRead(@NotNull ChannelHandlerContext ctx, @NotNull Object msg) throws Exception {
|
||||||
|
if (msg instanceof ByteBuf) {
|
||||||
|
ByteBuf in = (ByteBuf) msg;
|
||||||
|
int bytes = in.readableBytes();
|
||||||
|
|
||||||
|
if (maxPacketSize > 0 && bytes > maxPacketSize) {
|
||||||
|
closeConnection(ctx, "Closed %s due to large packet size (%d bytes)", ctx.channel().remoteAddress(), bytes);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packetBucket != null) {
|
||||||
|
packetBucket.incrementPackets(1);
|
||||||
|
if (packetBucket.getCurrentPacketRate() > maxPacketRate) {
|
||||||
|
closeConnection(ctx, "Closed %s due to many packets sent (%d in the last %.1f seconds)", ctx.channel().remoteAddress(), packetBucket.sum, (packetBucket.intervalTime / 1000.0));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.channelRead(ctx, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void closeConnection(ChannelHandlerContext ctx, String reason, Object... args) {
|
||||||
|
ctx.close();
|
||||||
|
Log.info(reason, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class PacketBucket {
|
||||||
|
private static final double NANOSECONDS_TO_MILLISECONDS = 1.0e-6;
|
||||||
|
private static final int MILLISECONDS_TO_SECONDS = 1000;
|
||||||
|
|
||||||
|
private final double intervalTime;
|
||||||
|
private final double intervalResolution;
|
||||||
|
private final int[] data;
|
||||||
|
private int newestData;
|
||||||
|
private double lastBucketTime;
|
||||||
|
private int sum;
|
||||||
|
|
||||||
|
public PacketBucket(final double intervalTime, final int totalBuckets) {
|
||||||
|
this.intervalTime = intervalTime;
|
||||||
|
this.intervalResolution = intervalTime / totalBuckets;
|
||||||
|
this.data = new int[totalBuckets];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void incrementPackets(final int packets) {
|
||||||
|
double timeMs = System.nanoTime() * NANOSECONDS_TO_MILLISECONDS;
|
||||||
|
double timeDelta = timeMs - this.lastBucketTime;
|
||||||
|
|
||||||
|
if (timeDelta < 0.0) {
|
||||||
|
timeDelta = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeDelta < this.intervalResolution) {
|
||||||
|
this.data[this.newestData] += packets;
|
||||||
|
this.sum += packets;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bucketsToMove = (int)(timeDelta / this.intervalResolution);
|
||||||
|
double nextBucketTime = this.lastBucketTime + bucketsToMove * this.intervalResolution;
|
||||||
|
|
||||||
|
if (bucketsToMove >= this.data.length) {
|
||||||
|
Arrays.fill(this.data, 0);
|
||||||
|
this.data[0] = packets;
|
||||||
|
this.sum = packets;
|
||||||
|
this.newestData = 0;
|
||||||
|
this.lastBucketTime = timeMs;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < bucketsToMove; ++i) {
|
||||||
|
int index = (this.newestData + i) % this.data.length;
|
||||||
|
this.sum -= this.data[index];
|
||||||
|
this.data[index] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int newestDataIndex = (this.newestData + bucketsToMove) % this.data.length;
|
||||||
|
this.sum += packets - this.data[newestDataIndex];
|
||||||
|
this.data[newestDataIndex] = packets;
|
||||||
|
this.newestData = newestDataIndex;
|
||||||
|
this.lastBucketTime = nextBucketTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getCurrentPacketRate() {
|
||||||
|
return this.sum / (this.intervalTime / MILLISECONDS_TO_SECONDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,16 +15,16 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.connection.pipeline;
|
package ua.nanit.limbo.connection.pipeline;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.Packet;
|
import ua.nanit.limbo.protocol.Packet;
|
||||||
import ru.nanit.limbo.protocol.registry.State;
|
import ua.nanit.limbo.protocol.registry.State;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
import ru.nanit.limbo.server.Logger;
|
import ua.nanit.limbo.server.Log;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -47,16 +47,20 @@ public class PacketDecoder extends MessageToMessageDecoder<ByteBuf> {
|
|||||||
Packet packet = mappings.getPacket(packetId);
|
Packet packet = mappings.getPacket(packetId);
|
||||||
|
|
||||||
if (packet != null) {
|
if (packet != null) {
|
||||||
Logger.debug("Received packet %s[0x%s]", packet.toString(), Integer.toHexString(packetId));
|
Log.debug("Received packet %s[0x%s] (%d bytes)", packet.toString(), Integer.toHexString(packetId), msg.readableBytes());
|
||||||
try {
|
try {
|
||||||
packet.decode(msg, version);
|
packet.decode(msg, version);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Logger.warning("Cannot decode packet 0x%s: %s", Integer.toHexString(packetId), e.getMessage());
|
if (Log.isDebug()) {
|
||||||
|
Log.warning("Cannot decode packet 0x%s", e, Integer.toHexString(packetId));
|
||||||
|
} else {
|
||||||
|
Log.warning("Cannot decode packet 0x%s: %s", Integer.toHexString(packetId), e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.fireChannelRead(packet);
|
ctx.fireChannelRead(packet);
|
||||||
} else {
|
} else {
|
||||||
Logger.debug("Undefined incoming packet: 0x" + Integer.toHexString(packetId));
|
Log.debug("Undefined incoming packet: 0x" + Integer.toHexString(packetId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -15,17 +15,17 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.connection.pipeline;
|
package ua.nanit.limbo.connection.pipeline;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.handler.codec.MessageToByteEncoder;
|
import io.netty.handler.codec.MessageToByteEncoder;
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.Packet;
|
import ua.nanit.limbo.protocol.Packet;
|
||||||
import ru.nanit.limbo.protocol.PacketSnapshot;
|
import ua.nanit.limbo.protocol.PacketSnapshot;
|
||||||
import ru.nanit.limbo.protocol.registry.State;
|
import ua.nanit.limbo.protocol.registry.State;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
import ru.nanit.limbo.server.Logger;
|
import ua.nanit.limbo.server.Log;
|
||||||
|
|
||||||
public class PacketEncoder extends MessageToByteEncoder<Packet> {
|
public class PacketEncoder extends MessageToByteEncoder<Packet> {
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ public class PacketEncoder extends MessageToByteEncoder<Packet> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (packetId == -1) {
|
if (packetId == -1) {
|
||||||
Logger.warning("Undefined packet class: %s[0x%s]", packet.getClass().getName(), Integer.toHexString(packetId));
|
Log.warning("Undefined packet class: %s[0x%s] (%d bytes)", packet.getClass().getName(), Integer.toHexString(packetId), msg.readableBytes());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,11 +60,11 @@ public class PacketEncoder extends MessageToByteEncoder<Packet> {
|
|||||||
try {
|
try {
|
||||||
packet.encode(msg, version);
|
packet.encode(msg, version);
|
||||||
|
|
||||||
if (Logger.getLevel() >= Logger.Level.DEBUG.getIndex()) {
|
if (Log.isDebug()) {
|
||||||
Logger.debug("Sending %s[0x%s] packet (%d bytes)", packet.toString(), Integer.toHexString(packetId), msg.readableBytes());
|
Log.debug("Sending %s[0x%s] packet (%d bytes)", packet.toString(), Integer.toHexString(packetId), msg.readableBytes());
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Logger.error("Cannot encode packet 0x%s: %s", Integer.toHexString(packetId), e.getMessage());
|
Log.error("Cannot encode packet 0x%s: %s", Integer.toHexString(packetId), e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -15,7 +15,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.connection.pipeline;
|
package ua.nanit.limbo.connection.pipeline;
|
||||||
|
|
||||||
import io.netty.util.ByteProcessor;
|
import io.netty.util.ByteProcessor;
|
||||||
|
|
@ -15,12 +15,12 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.connection.pipeline;
|
package ua.nanit.limbo.connection.pipeline;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||||
import ru.nanit.limbo.server.Logger;
|
import ua.nanit.limbo.server.Log;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -42,18 +42,19 @@ public class VarIntFrameDecoder extends ByteToMessageDecoder {
|
|||||||
int readVarInt = reader.getReadVarInt();
|
int readVarInt = reader.getReadVarInt();
|
||||||
int bytesRead = reader.getBytesRead();
|
int bytesRead = reader.getBytesRead();
|
||||||
if (readVarInt < 0) {
|
if (readVarInt < 0) {
|
||||||
Logger.error("[VarIntFrameDecoder] Bad data length");
|
Log.error("[VarIntFrameDecoder] Bad data length");
|
||||||
} else if (readVarInt == 0) {
|
} else if (readVarInt == 0) {
|
||||||
in.readerIndex(varIntEnd + 1);
|
in.readerIndex(varIntEnd + 1);
|
||||||
} else {
|
} else {
|
||||||
int minimumRead = bytesRead + readVarInt;
|
int minimumRead = bytesRead + readVarInt;
|
||||||
|
|
||||||
if (in.isReadable(minimumRead)) {
|
if (in.isReadable(minimumRead)) {
|
||||||
out.add(in.retainedSlice(varIntEnd + 1, readVarInt));
|
out.add(in.retainedSlice(varIntEnd + 1, readVarInt));
|
||||||
in.skipBytes(minimumRead);
|
in.skipBytes(minimumRead);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (reader.getResult() == VarIntByteDecoder.DecodeResult.TOO_BIG) {
|
} else if (reader.getResult() == VarIntByteDecoder.DecodeResult.TOO_BIG) {
|
||||||
Logger.error("[VarIntFrameDecoder] Too big data");
|
Log.error("[VarIntFrameDecoder] Too big data");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,13 +15,13 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.connection.pipeline;
|
package ua.nanit.limbo.connection.pipeline;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.channel.ChannelHandler;
|
import io.netty.channel.ChannelHandler;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.handler.codec.MessageToByteEncoder;
|
import io.netty.handler.codec.MessageToByteEncoder;
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
|
|
||||||
@ChannelHandler.Sharable
|
@ChannelHandler.Sharable
|
||||||
public class VarIntLengthEncoder extends MessageToByteEncoder<ByteBuf> {
|
public class VarIntLengthEncoder extends MessageToByteEncoder<ByteBuf> {
|
@ -15,14 +15,14 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol;
|
package ua.nanit.limbo.protocol;
|
||||||
|
|
||||||
import io.netty.buffer.*;
|
import io.netty.buffer.*;
|
||||||
import io.netty.handler.codec.DecoderException;
|
import io.netty.handler.codec.DecoderException;
|
||||||
import io.netty.handler.codec.EncoderException;
|
import io.netty.handler.codec.EncoderException;
|
||||||
import io.netty.util.ByteProcessor;
|
import io.netty.util.ByteProcessor;
|
||||||
import net.kyori.adventure.nbt.BinaryTagIO;
|
import net.kyori.adventure.nbt.*;
|
||||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -34,6 +34,9 @@ import java.nio.channels.GatheringByteChannel;
|
|||||||
import java.nio.channels.ScatteringByteChannel;
|
import java.nio.channels.ScatteringByteChannel;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.BitSet;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class ByteMessage extends ByteBuf {
|
public class ByteMessage extends ByteBuf {
|
||||||
@ -70,14 +73,37 @@ public class ByteMessage extends ByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void writeVarInt(int value) {
|
public void writeVarInt(int value) {
|
||||||
while (true) {
|
// Peel the one and two byte count cases explicitly as they are the most common VarInt sizes
|
||||||
if ((value & 0xFFFFFF80) == 0) {
|
// that the proxy will write, to improve inlining.
|
||||||
buf.writeByte(value);
|
if ((value & (0xFFFFFFFF << 7)) == 0) {
|
||||||
return;
|
buf.writeByte(value);
|
||||||
}
|
} else if ((value & (0xFFFFFFFF << 14)) == 0) {
|
||||||
|
int w = (value & 0x7F | 0x80) << 8 | (value >>> 7);
|
||||||
|
buf.writeShort(w);
|
||||||
|
} else {
|
||||||
|
writeVarIntFull(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buf.writeByte(value & 0x7F | 0x80);
|
private void writeVarIntFull(final int value) {
|
||||||
value >>>= 7;
|
// See https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/
|
||||||
|
if ((value & (0xFFFFFFFF << 7)) == 0) {
|
||||||
|
buf.writeByte(value);
|
||||||
|
} else if ((value & (0xFFFFFFFF << 14)) == 0) {
|
||||||
|
int w = (value & 0x7F | 0x80) << 8 | (value >>> 7);
|
||||||
|
buf.writeShort(w);
|
||||||
|
} else if ((value & (0xFFFFFFFF << 21)) == 0) {
|
||||||
|
int w = (value & 0x7F | 0x80) << 16 | ((value >>> 7) & 0x7F | 0x80) << 8 | (value >>> 14);
|
||||||
|
buf.writeMedium(w);
|
||||||
|
} else if ((value & (0xFFFFFFFF << 28)) == 0) {
|
||||||
|
int w = (value & 0x7F | 0x80) << 24 | (((value >>> 7) & 0x7F | 0x80) << 16)
|
||||||
|
| ((value >>> 14) & 0x7F | 0x80) << 8 | (value >>> 21);
|
||||||
|
buf.writeInt(w);
|
||||||
|
} else {
|
||||||
|
int w = (value & 0x7F | 0x80) << 24 | ((value >>> 7) & 0x7F | 0x80) << 16
|
||||||
|
| ((value >>> 14) & 0x7F | 0x80) << 8 | ((value >>> 21) & 0x7F | 0x80);
|
||||||
|
buf.writeInt(w);
|
||||||
|
buf.writeByte(value >>> 28);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,6 +216,81 @@ public class ByteMessage extends ByteBuf {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void writeNamelessCompoundTag(BinaryTag binaryTag) {
|
||||||
|
try (ByteBufOutputStream stream = new ByteBufOutputStream(buf)) {
|
||||||
|
stream.writeByte(binaryTag.type().id());
|
||||||
|
|
||||||
|
// TODO Find a way to improve this...
|
||||||
|
if (binaryTag instanceof CompoundBinaryTag) {
|
||||||
|
CompoundBinaryTag tag = (CompoundBinaryTag) binaryTag;
|
||||||
|
tag.type().write(tag, stream);
|
||||||
|
}
|
||||||
|
else if (binaryTag instanceof ByteBinaryTag) {
|
||||||
|
ByteBinaryTag tag = (ByteBinaryTag) binaryTag;
|
||||||
|
tag.type().write(tag, stream);
|
||||||
|
}
|
||||||
|
else if (binaryTag instanceof ShortBinaryTag) {
|
||||||
|
ShortBinaryTag tag = (ShortBinaryTag) binaryTag;
|
||||||
|
tag.type().write(tag, stream);
|
||||||
|
}
|
||||||
|
else if (binaryTag instanceof IntBinaryTag) {
|
||||||
|
IntBinaryTag tag = (IntBinaryTag) binaryTag;
|
||||||
|
tag.type().write(tag, stream);
|
||||||
|
}
|
||||||
|
else if (binaryTag instanceof LongBinaryTag) {
|
||||||
|
LongBinaryTag tag = (LongBinaryTag) binaryTag;
|
||||||
|
tag.type().write(tag, stream);
|
||||||
|
}
|
||||||
|
else if (binaryTag instanceof DoubleBinaryTag) {
|
||||||
|
DoubleBinaryTag tag = (DoubleBinaryTag) binaryTag;
|
||||||
|
tag.type().write(tag, stream);
|
||||||
|
}
|
||||||
|
else if (binaryTag instanceof StringBinaryTag) {
|
||||||
|
StringBinaryTag tag = (StringBinaryTag) binaryTag;
|
||||||
|
tag.type().write(tag, stream);
|
||||||
|
}
|
||||||
|
else if (binaryTag instanceof ListBinaryTag) {
|
||||||
|
ListBinaryTag tag = (ListBinaryTag) binaryTag;
|
||||||
|
tag.type().write(tag, stream);
|
||||||
|
}
|
||||||
|
else if (binaryTag instanceof EndBinaryTag) {
|
||||||
|
EndBinaryTag tag = (EndBinaryTag) binaryTag;
|
||||||
|
tag.type().write(tag, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
throw new EncoderException("Cannot write NBT CompoundTag");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeNbtMessage(NbtMessage nbtMessage, Version version) {
|
||||||
|
if (version.moreOrEqual(Version.V1_20_3)) {
|
||||||
|
writeNamelessCompoundTag(nbtMessage.getTag());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
writeString(nbtMessage.getJson());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public <E extends Enum<E>> void writeEnumSet(EnumSet<E> enumset, Class<E> oclass) {
|
||||||
|
E[] enums = oclass.getEnumConstants();
|
||||||
|
BitSet bits = new BitSet(enums.length);
|
||||||
|
|
||||||
|
for (int i = 0; i < enums.length; ++i) {
|
||||||
|
bits.set(i, enumset.contains(enums[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
writeFixedBitSet(bits, enums.length, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void writeFixedBitSet(BitSet bits, int size, ByteBuf buf) {
|
||||||
|
if (bits.length() > size) {
|
||||||
|
throw new StackOverflowError("BitSet too large (expected " + size + " got " + bits.size() + ")");
|
||||||
|
}
|
||||||
|
buf.writeBytes(Arrays.copyOf(bits.toByteArray(), (size + 8) >> 3));
|
||||||
|
}
|
||||||
|
|
||||||
/* Delegated methods */
|
/* Delegated methods */
|
||||||
|
|
||||||
@Override
|
@Override
|
10
src/main/java/ua/nanit/limbo/protocol/MetadataWriter.java
Normal file
10
src/main/java/ua/nanit/limbo/protocol/MetadataWriter.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package ua.nanit.limbo.protocol;
|
||||||
|
|
||||||
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface MetadataWriter {
|
||||||
|
|
||||||
|
void writeData(ByteMessage message, Version version);
|
||||||
|
|
||||||
|
}
|
30
src/main/java/ua/nanit/limbo/protocol/NbtMessage.java
Normal file
30
src/main/java/ua/nanit/limbo/protocol/NbtMessage.java
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package ua.nanit.limbo.protocol;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.BinaryTag;
|
||||||
|
|
||||||
|
public class NbtMessage {
|
||||||
|
|
||||||
|
private String json;
|
||||||
|
private BinaryTag tag;
|
||||||
|
|
||||||
|
public NbtMessage(String json, BinaryTag tag) {
|
||||||
|
this.json = json;
|
||||||
|
this.tag = tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getJson() {
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setJson(String json) {
|
||||||
|
this.json = json;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BinaryTag getTag() {
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTag(BinaryTag tag) {
|
||||||
|
this.tag = tag;
|
||||||
|
}
|
||||||
|
}
|
@ -15,11 +15,11 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol;
|
package ua.nanit.limbo.protocol;
|
||||||
|
|
||||||
import ru.nanit.limbo.connection.ClientConnection;
|
import ua.nanit.limbo.connection.ClientConnection;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
import ru.nanit.limbo.server.LimboServer;
|
import ua.nanit.limbo.server.LimboServer;
|
||||||
|
|
||||||
public interface Packet {
|
public interface Packet {
|
||||||
|
|
@ -15,9 +15,9 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol;
|
package ua.nanit.limbo.protocol;
|
||||||
|
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
|
||||||
public interface PacketIn extends Packet {
|
public interface PacketIn extends Packet {
|
||||||
|
|
@ -15,9 +15,9 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol;
|
package ua.nanit.limbo.protocol;
|
||||||
|
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
|
||||||
public interface PacketOut extends Packet {
|
public interface PacketOut extends Packet {
|
||||||
|
|
@ -15,16 +15,16 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol;
|
package ua.nanit.limbo.protocol;
|
||||||
|
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PacketSnapshot encodes packet to byte array for each MC version.
|
* PacketSnapshot encodes a packet to byte array for each MC version.
|
||||||
* Some versions have same snapshot, so there are mappings to avoid data copying
|
* Some versions have the same snapshot, so there are mappings to avoid data copying
|
||||||
*/
|
*/
|
||||||
public class PacketSnapshot implements PacketOut {
|
public class PacketSnapshot implements PacketOut {
|
||||||
|
|
@ -15,16 +15,14 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets;
|
package ua.nanit.limbo.protocol.packets;
|
||||||
|
|
||||||
import ru.nanit.limbo.connection.ClientConnection;
|
import ua.nanit.limbo.connection.ClientConnection;
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.PacketIn;
|
import ua.nanit.limbo.protocol.PacketIn;
|
||||||
import ru.nanit.limbo.protocol.registry.State;
|
import ua.nanit.limbo.protocol.registry.State;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
import ru.nanit.limbo.server.LimboServer;
|
import ua.nanit.limbo.server.LimboServer;
|
||||||
import ru.nanit.limbo.server.Logger;
|
|
||||||
import ru.nanit.limbo.util.UuidUtil;
|
|
||||||
|
|
||||||
public class PacketHandshake implements PacketIn {
|
public class PacketHandshake implements PacketIn {
|
||||||
|
|
@ -0,0 +1,19 @@
|
|||||||
|
package ua.nanit.limbo.protocol.packets.configuration;
|
||||||
|
|
||||||
|
import ua.nanit.limbo.connection.ClientConnection;
|
||||||
|
import ua.nanit.limbo.protocol.PacketIn;
|
||||||
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
|
import ua.nanit.limbo.server.LimboServer;
|
||||||
|
|
||||||
|
public class PacketFinishConfiguration implements PacketIn, PacketOut {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(ClientConnection conn, LimboServer server) {
|
||||||
|
server.getPacketHandler().handle(conn, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getClass().getSimpleName();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package ua.nanit.limbo.protocol.packets.configuration;
|
||||||
|
|
||||||
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
|
import ua.nanit.limbo.protocol.MetadataWriter;
|
||||||
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
import ua.nanit.limbo.world.DimensionRegistry;
|
||||||
|
|
||||||
|
public class PacketRegistryData implements PacketOut {
|
||||||
|
|
||||||
|
private DimensionRegistry dimensionRegistry;
|
||||||
|
private MetadataWriter metadataWriter;
|
||||||
|
|
||||||
|
public void setDimensionRegistry(DimensionRegistry dimensionRegistry) {
|
||||||
|
this.dimensionRegistry = dimensionRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMetadataWriter(MetadataWriter metadataWriter) {
|
||||||
|
this.metadataWriter = metadataWriter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void encode(ByteMessage msg, Version version) {
|
||||||
|
if (metadataWriter != null) {
|
||||||
|
if (version.moreOrEqual(Version.V1_20_5)) {
|
||||||
|
metadataWriter.writeData(msg, version);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msg.writeNamelessCompoundTag(dimensionRegistry.getCodec_1_20());
|
||||||
|
}
|
||||||
|
}
|
@ -15,11 +15,11 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets.login;
|
package ua.nanit.limbo.protocol.packets.login;
|
||||||
|
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.PacketOut;
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
|
||||||
public class PacketDisconnect implements PacketOut {
|
public class PacketDisconnect implements PacketOut {
|
||||||
|
|
@ -0,0 +1,19 @@
|
|||||||
|
package ua.nanit.limbo.protocol.packets.login;
|
||||||
|
|
||||||
|
import ua.nanit.limbo.connection.ClientConnection;
|
||||||
|
import ua.nanit.limbo.protocol.PacketIn;
|
||||||
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
|
import ua.nanit.limbo.server.LimboServer;
|
||||||
|
|
||||||
|
public class PacketLoginAcknowledged implements PacketIn, PacketOut {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(ClientConnection conn, LimboServer server) {
|
||||||
|
server.getPacketHandler().handle(conn, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getClass().getSimpleName();
|
||||||
|
}
|
||||||
|
}
|
@ -15,12 +15,12 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets.login;
|
package ua.nanit.limbo.protocol.packets.login;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.PacketOut;
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
|
||||||
public class PacketLoginPluginRequest implements PacketOut {
|
public class PacketLoginPluginRequest implements PacketOut {
|
||||||
|
|
@ -15,13 +15,13 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets.login;
|
package ua.nanit.limbo.protocol.packets.login;
|
||||||
|
|
||||||
import ru.nanit.limbo.connection.ClientConnection;
|
import ua.nanit.limbo.connection.ClientConnection;
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.PacketIn;
|
import ua.nanit.limbo.protocol.PacketIn;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
import ru.nanit.limbo.server.LimboServer;
|
import ua.nanit.limbo.server.LimboServer;
|
||||||
|
|
||||||
public class PacketLoginPluginResponse implements PacketIn {
|
public class PacketLoginPluginResponse implements PacketIn {
|
||||||
|
|
@ -15,13 +15,13 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets.login;
|
package ua.nanit.limbo.protocol.packets.login;
|
||||||
|
|
||||||
import ru.nanit.limbo.connection.ClientConnection;
|
import ua.nanit.limbo.connection.ClientConnection;
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.PacketIn;
|
import ua.nanit.limbo.protocol.PacketIn;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
import ru.nanit.limbo.server.LimboServer;
|
import ua.nanit.limbo.server.LimboServer;
|
||||||
|
|
||||||
public class PacketLoginStart implements PacketIn {
|
public class PacketLoginStart implements PacketIn {
|
||||||
|
|
@ -15,11 +15,11 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets.login;
|
package ua.nanit.limbo.protocol.packets.login;
|
||||||
|
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.PacketOut;
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@ -40,13 +40,18 @@ public class PacketLoginSuccess implements PacketOut {
|
|||||||
public void encode(ByteMessage msg, Version version) {
|
public void encode(ByteMessage msg, Version version) {
|
||||||
if (version.moreOrEqual(Version.V1_16)) {
|
if (version.moreOrEqual(Version.V1_16)) {
|
||||||
msg.writeUuid(uuid);
|
msg.writeUuid(uuid);
|
||||||
} else {
|
} else if (version.moreOrEqual(Version.V1_7_6)) {
|
||||||
msg.writeString(uuid.toString());
|
msg.writeString(uuid.toString());
|
||||||
|
} else {
|
||||||
|
msg.writeString(uuid.toString().replace("-", ""));
|
||||||
}
|
}
|
||||||
msg.writeString(username);
|
msg.writeString(username);
|
||||||
if (version.moreOrEqual(Version.V1_19)) {
|
if (version.moreOrEqual(Version.V1_19)) {
|
||||||
msg.writeVarInt(0);
|
msg.writeVarInt(0);
|
||||||
}
|
}
|
||||||
|
if (version.moreOrEqual(Version.V1_20_5)) {
|
||||||
|
msg.writeBoolean(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -15,12 +15,12 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets.play;
|
package ua.nanit.limbo.protocol.packets.play;
|
||||||
|
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.PacketOut;
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
import ru.nanit.limbo.server.data.BossBar;
|
import ua.nanit.limbo.server.data.BossBar;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ public class PacketBossBar implements PacketOut {
|
|||||||
public void encode(ByteMessage msg, Version version) {
|
public void encode(ByteMessage msg, Version version) {
|
||||||
msg.writeUuid(uuid);
|
msg.writeUuid(uuid);
|
||||||
msg.writeVarInt(0); // Create bossbar
|
msg.writeVarInt(0); // Create bossbar
|
||||||
msg.writeString(bossBar.getText());
|
msg.writeNbtMessage(bossBar.getText(), version);
|
||||||
msg.writeFloat(bossBar.getHealth());
|
msg.writeFloat(bossBar.getHealth());
|
||||||
msg.writeVarInt(bossBar.getColor().getIndex());
|
msg.writeVarInt(bossBar.getColor().getIndex());
|
||||||
msg.writeVarInt(bossBar.getDivision().getIndex());
|
msg.writeVarInt(bossBar.getDivision().getIndex());
|
@ -15,22 +15,23 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets.play;
|
package ua.nanit.limbo.protocol.packets.play;
|
||||||
|
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.PacketOut;
|
import ua.nanit.limbo.protocol.NbtMessage;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class PacketChatMessage implements PacketOut {
|
public class PacketChatMessage implements PacketOut {
|
||||||
|
|
||||||
private String jsonData;
|
private NbtMessage message;
|
||||||
private PositionLegacy position;
|
private PositionLegacy position;
|
||||||
private UUID sender;
|
private UUID sender;
|
||||||
|
|
||||||
public void setJsonData(String jsonData) {
|
public void setMessage(NbtMessage message) {
|
||||||
this.jsonData = jsonData;
|
this.message = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPosition(PositionLegacy position) {
|
public void setPosition(PositionLegacy position) {
|
||||||
@ -43,11 +44,12 @@ public class PacketChatMessage implements PacketOut {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void encode(ByteMessage msg, Version version) {
|
public void encode(ByteMessage msg, Version version) {
|
||||||
msg.writeString(jsonData);
|
msg.writeNbtMessage(message, version);
|
||||||
if (version.moreOrEqual(Version.V1_19)) {
|
if (version.moreOrEqual(Version.V1_19_1)) {
|
||||||
|
msg.writeBoolean(position.index == PositionLegacy.ACTION_BAR.index);
|
||||||
|
} else if (version.moreOrEqual(Version.V1_19)) {
|
||||||
msg.writeVarInt(position.index);
|
msg.writeVarInt(position.index);
|
||||||
}
|
} else if (version.moreOrEqual(Version.V1_8)) {
|
||||||
else {
|
|
||||||
msg.writeByte(position.index);
|
msg.writeByte(position.index);
|
||||||
}
|
}
|
||||||
|
|
@ -15,11 +15,11 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets.play;
|
package ua.nanit.limbo.protocol.packets.play;
|
||||||
|
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.PacketOut;
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -0,0 +1,47 @@
|
|||||||
|
package ua.nanit.limbo.protocol.packets.play;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
|
import net.kyori.adventure.nbt.LongArrayBinaryTag;
|
||||||
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
|
||||||
|
public class PacketEmptyChunk implements PacketOut {
|
||||||
|
|
||||||
|
private int x;
|
||||||
|
private int z;
|
||||||
|
|
||||||
|
public void setX(int x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setZ(int z) {
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void encode(ByteMessage msg, Version version) {
|
||||||
|
msg.writeInt(x);
|
||||||
|
msg.writeInt(z);
|
||||||
|
|
||||||
|
LongArrayBinaryTag longArrayTag = LongArrayBinaryTag.longArrayBinaryTag(new long[37]);
|
||||||
|
CompoundBinaryTag tag = CompoundBinaryTag.builder()
|
||||||
|
.put("MOTION_BLOCKING", longArrayTag).build();
|
||||||
|
CompoundBinaryTag rootTag = CompoundBinaryTag.builder()
|
||||||
|
.put("root", tag).build();
|
||||||
|
msg.writeNamelessCompoundTag(rootTag);
|
||||||
|
|
||||||
|
byte[] sectionData = new byte[]{0, 0, 0, 0, 0, 0, 1, 0};
|
||||||
|
msg.writeVarInt(sectionData.length * 16);
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
msg.writeBytes(sectionData);
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.writeVarInt(0);
|
||||||
|
|
||||||
|
byte[] lightData = new byte[]{1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, -1, -1, 0, 0};
|
||||||
|
msg.ensureWritable(lightData.length);
|
||||||
|
msg.writeBytes(lightData, 1, lightData.length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package ua.nanit.limbo.protocol.packets.play;
|
||||||
|
|
||||||
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
|
||||||
|
public class PacketGameEvent implements PacketOut {
|
||||||
|
|
||||||
|
private byte type;
|
||||||
|
private float value;
|
||||||
|
|
||||||
|
public void setType(byte type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(float value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void encode(ByteMessage msg, Version version) {
|
||||||
|
msg.writeByte(type);
|
||||||
|
msg.writeFloat(value);
|
||||||
|
}
|
||||||
|
}
|
@ -15,12 +15,12 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets.play;
|
package ua.nanit.limbo.protocol.packets.play;
|
||||||
|
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.PacketOut;
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
import ru.nanit.limbo.world.dimension.DimensionRegistry;
|
import ua.nanit.limbo.world.DimensionRegistry;
|
||||||
|
|
||||||
public class PacketJoinGame implements PacketOut {
|
public class PacketJoinGame implements PacketOut {
|
||||||
|
|
||||||
@ -38,6 +38,8 @@ public class PacketJoinGame implements PacketOut {
|
|||||||
private boolean enableRespawnScreen;
|
private boolean enableRespawnScreen;
|
||||||
private boolean isDebug;
|
private boolean isDebug;
|
||||||
private boolean isFlat;
|
private boolean isFlat;
|
||||||
|
private boolean limitedCrafting;
|
||||||
|
private boolean secureProfile;
|
||||||
|
|
||||||
public void setEntityId(int entityId) {
|
public void setEntityId(int entityId) {
|
||||||
this.entityId = entityId;
|
this.entityId = entityId;
|
||||||
@ -95,11 +97,27 @@ public class PacketJoinGame implements PacketOut {
|
|||||||
isFlat = flat;
|
isFlat = flat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setLimitedCrafting(boolean limitedCrafting) {
|
||||||
|
this.limitedCrafting = limitedCrafting;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSecureProfile(boolean secureProfile) {
|
||||||
|
this.secureProfile = secureProfile;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void encode(ByteMessage msg, Version version) {
|
public void encode(ByteMessage msg, Version version) {
|
||||||
msg.writeInt(entityId);
|
msg.writeInt(entityId);
|
||||||
|
|
||||||
if (version.fromTo(Version.V1_8, Version.V1_9_1)) {
|
if (version.fromTo(Version.V1_7_2, Version.V1_7_6)) {
|
||||||
|
msg.writeByte(gameMode == 3 ? 1 : gameMode);
|
||||||
|
msg.writeByte(dimensionRegistry.getDefaultDimension_1_16().getId());
|
||||||
|
msg.writeByte(0); // Difficulty
|
||||||
|
msg.writeByte(maxPlayers);
|
||||||
|
msg.writeString("flat"); // Level type
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version.fromTo(Version.V1_8, Version.V1_9)) {
|
||||||
msg.writeByte(gameMode);
|
msg.writeByte(gameMode);
|
||||||
msg.writeByte(dimensionRegistry.getDefaultDimension_1_16().getId());
|
msg.writeByte(dimensionRegistry.getDefaultDimension_1_16().getId());
|
||||||
msg.writeByte(0); // Difficulty
|
msg.writeByte(0); // Difficulty
|
||||||
@ -108,7 +126,7 @@ public class PacketJoinGame implements PacketOut {
|
|||||||
msg.writeBoolean(reducedDebugInfo);
|
msg.writeBoolean(reducedDebugInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version.fromTo(Version.V1_9_2, Version.V1_13_2)) {
|
if (version.fromTo(Version.V1_9_1, Version.V1_13_2)) {
|
||||||
msg.writeByte(gameMode);
|
msg.writeByte(gameMode);
|
||||||
msg.writeInt(dimensionRegistry.getDefaultDimension_1_16().getId());
|
msg.writeInt(dimensionRegistry.getDefaultDimension_1_16().getId());
|
||||||
msg.writeByte(0); // Difficulty
|
msg.writeByte(0); // Difficulty
|
||||||
@ -193,12 +211,22 @@ public class PacketJoinGame implements PacketOut {
|
|||||||
msg.writeBoolean(isFlat);
|
msg.writeBoolean(isFlat);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version.moreOrEqual(Version.V1_19)) {
|
if (version.fromTo(Version.V1_19, Version.V1_19_4)) {
|
||||||
msg.writeBoolean(isHardcore);
|
msg.writeBoolean(isHardcore);
|
||||||
msg.writeByte(gameMode);
|
msg.writeByte(gameMode);
|
||||||
msg.writeByte(previousGameMode);
|
msg.writeByte(previousGameMode);
|
||||||
msg.writeStringsArray(worldNames);
|
msg.writeStringsArray(worldNames);
|
||||||
msg.writeCompoundTag(dimensionRegistry.getCodec_1_19());
|
if (version.moreOrEqual(Version.V1_19_1)) {
|
||||||
|
if (version.moreOrEqual(Version.V1_19_4)) {
|
||||||
|
msg.writeCompoundTag(dimensionRegistry.getCodec_1_19_4());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
msg.writeCompoundTag(dimensionRegistry.getCodec_1_19_1());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
msg.writeCompoundTag(dimensionRegistry.getCodec_1_19());
|
||||||
|
}
|
||||||
msg.writeString(worldName); // World type
|
msg.writeString(worldName); // World type
|
||||||
msg.writeString(worldName);
|
msg.writeString(worldName);
|
||||||
msg.writeLong(hashedSeed);
|
msg.writeLong(hashedSeed);
|
||||||
@ -211,6 +239,67 @@ public class PacketJoinGame implements PacketOut {
|
|||||||
msg.writeBoolean(isFlat);
|
msg.writeBoolean(isFlat);
|
||||||
msg.writeBoolean(false);
|
msg.writeBoolean(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (version.equals(Version.V1_20)) {
|
||||||
|
msg.writeBoolean(isHardcore);
|
||||||
|
msg.writeByte(gameMode);
|
||||||
|
msg.writeByte(previousGameMode);
|
||||||
|
msg.writeStringsArray(worldNames);
|
||||||
|
msg.writeCompoundTag(dimensionRegistry.getCodec_1_20());
|
||||||
|
msg.writeString(worldName); // World type
|
||||||
|
msg.writeString(worldName);
|
||||||
|
msg.writeLong(hashedSeed);
|
||||||
|
msg.writeVarInt(maxPlayers);
|
||||||
|
msg.writeVarInt(viewDistance);
|
||||||
|
msg.writeVarInt(viewDistance); // Simulation Distance
|
||||||
|
msg.writeBoolean(reducedDebugInfo);
|
||||||
|
msg.writeBoolean(enableRespawnScreen);
|
||||||
|
msg.writeBoolean(isDebug);
|
||||||
|
msg.writeBoolean(isFlat);
|
||||||
|
msg.writeBoolean(false);
|
||||||
|
msg.writeVarInt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version.fromTo(Version.V1_20_2, Version.V1_20_3)) {
|
||||||
|
msg.writeBoolean(isHardcore);
|
||||||
|
msg.writeStringsArray(worldNames);
|
||||||
|
msg.writeVarInt(maxPlayers);
|
||||||
|
msg.writeVarInt(viewDistance);
|
||||||
|
msg.writeVarInt(viewDistance); // Simulation Distance
|
||||||
|
msg.writeBoolean(reducedDebugInfo);
|
||||||
|
msg.writeBoolean(enableRespawnScreen);
|
||||||
|
msg.writeBoolean(limitedCrafting);
|
||||||
|
msg.writeString(worldName);
|
||||||
|
msg.writeString(worldName);
|
||||||
|
msg.writeLong(hashedSeed);
|
||||||
|
msg.writeByte(gameMode);
|
||||||
|
msg.writeByte(previousGameMode);
|
||||||
|
msg.writeBoolean(isDebug);
|
||||||
|
msg.writeBoolean(isFlat);
|
||||||
|
msg.writeBoolean(false);
|
||||||
|
msg.writeVarInt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version.moreOrEqual(Version.V1_20_5)) {
|
||||||
|
msg.writeBoolean(isHardcore);
|
||||||
|
msg.writeStringsArray(worldNames);
|
||||||
|
msg.writeVarInt(maxPlayers);
|
||||||
|
msg.writeVarInt(viewDistance);
|
||||||
|
msg.writeVarInt(viewDistance); // Simulation Distance
|
||||||
|
msg.writeBoolean(reducedDebugInfo);
|
||||||
|
msg.writeBoolean(enableRespawnScreen);
|
||||||
|
msg.writeBoolean(limitedCrafting);
|
||||||
|
msg.writeVarInt(dimensionRegistry.getDimension_1_20_5().getId());
|
||||||
|
msg.writeString(worldName);
|
||||||
|
msg.writeLong(hashedSeed);
|
||||||
|
msg.writeByte(gameMode);
|
||||||
|
msg.writeByte(previousGameMode);
|
||||||
|
msg.writeBoolean(isDebug);
|
||||||
|
msg.writeBoolean(isFlat);
|
||||||
|
msg.writeBoolean(false);
|
||||||
|
msg.writeVarInt(0);
|
||||||
|
msg.writeBoolean(secureProfile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -15,11 +15,11 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets.play;
|
package ua.nanit.limbo.protocol.packets.play;
|
||||||
|
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.Packet;
|
import ua.nanit.limbo.protocol.Packet;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
|
||||||
public class PacketKeepAlive implements Packet {
|
public class PacketKeepAlive implements Packet {
|
||||||
|
|
||||||
@ -37,8 +37,10 @@ public class PacketKeepAlive implements Packet {
|
|||||||
public void encode(ByteMessage msg, Version version) {
|
public void encode(ByteMessage msg, Version version) {
|
||||||
if (version.moreOrEqual(Version.V1_12_2)) {
|
if (version.moreOrEqual(Version.V1_12_2)) {
|
||||||
msg.writeLong(id);
|
msg.writeLong(id);
|
||||||
} else {
|
} else if (version.moreOrEqual(Version.V1_8)) {
|
||||||
msg.writeVarInt((int) id);
|
msg.writeVarInt((int) id);
|
||||||
|
} else {
|
||||||
|
msg.writeInt((int) id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,8 +48,10 @@ public class PacketKeepAlive implements Packet {
|
|||||||
public void decode(ByteMessage msg, Version version) {
|
public void decode(ByteMessage msg, Version version) {
|
||||||
if (version.moreOrEqual(Version.V1_12_2)) {
|
if (version.moreOrEqual(Version.V1_12_2)) {
|
||||||
this.id = msg.readLong();
|
this.id = msg.readLong();
|
||||||
} else {
|
} else if (version.moreOrEqual(Version.V1_8)) {
|
||||||
this.id = msg.readVarInt();
|
this.id = msg.readVarInt();
|
||||||
|
} else {
|
||||||
|
this.id = msg.readInt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,49 +1,49 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2020 Nan1t
|
* Copyright (C) 2020 Nan1t
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets.play;
|
package ua.nanit.limbo.protocol.packets.play;
|
||||||
|
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.PacketOut;
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
|
||||||
public class PacketPlayerAbilities implements PacketOut {
|
public class PacketPlayerAbilities implements PacketOut {
|
||||||
|
|
||||||
private int flags = 0x02;
|
private int flags = 0x02;
|
||||||
private float flyingSpeed = 0.0F;
|
private float flyingSpeed = 0.0F;
|
||||||
private float fieldOfView = 0.1F;
|
private float fieldOfView = 0.1F;
|
||||||
|
|
||||||
public void setFlags(int flags) {
|
public void setFlags(int flags) {
|
||||||
this.flags = flags;
|
this.flags = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFlyingSpeed(float flyingSpeed) {
|
public void setFlyingSpeed(float flyingSpeed) {
|
||||||
this.flyingSpeed = flyingSpeed;
|
this.flyingSpeed = flyingSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFieldOfView(float fieldOfView) {
|
public void setFieldOfView(float fieldOfView) {
|
||||||
this.fieldOfView = fieldOfView;
|
this.fieldOfView = fieldOfView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void encode(ByteMessage msg, Version version) {
|
public void encode(ByteMessage msg, Version version) {
|
||||||
msg.writeByte(flags);
|
msg.writeByte(flags);
|
||||||
msg.writeFloat(flyingSpeed);
|
msg.writeFloat(flyingSpeed);
|
||||||
msg.writeFloat(fieldOfView);
|
msg.writeFloat(fieldOfView);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Nan1t
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ua.nanit.limbo.protocol.packets.play;
|
||||||
|
|
||||||
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This packet was very simplified and using only for ADD_PLAYER action
|
||||||
|
*/
|
||||||
|
public class PacketPlayerInfo implements PacketOut {
|
||||||
|
|
||||||
|
private int gameMode = 3;
|
||||||
|
private String username = "";
|
||||||
|
private UUID uuid;
|
||||||
|
|
||||||
|
public void setGameMode(int gameMode) {
|
||||||
|
this.gameMode = gameMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUuid(UUID uuid) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void encode(ByteMessage msg, Version version) {
|
||||||
|
if (version.less(Version.V1_8)) {
|
||||||
|
msg.writeString(username);
|
||||||
|
msg.writeBoolean(true); // Is online
|
||||||
|
msg.writeShort(0);
|
||||||
|
} else {
|
||||||
|
if (version.moreOrEqual(Version.V1_19_3)) {
|
||||||
|
EnumSet<Action> actions = EnumSet.noneOf(Action.class);
|
||||||
|
actions.add(Action.ADD_PLAYER);
|
||||||
|
actions.add(Action.UPDATE_LISTED);
|
||||||
|
actions.add(Action.UPDATE_GAMEMODE);
|
||||||
|
msg.writeEnumSet(actions, Action.class);
|
||||||
|
|
||||||
|
msg.writeVarInt(1); // Array length (1 element)
|
||||||
|
msg.writeUuid(uuid); // UUID
|
||||||
|
msg.writeString(username); //Username
|
||||||
|
msg.writeVarInt(0); //Properties (0 is empty)
|
||||||
|
|
||||||
|
msg.writeBoolean(true); //Update listed
|
||||||
|
msg.writeVarInt(gameMode); //Gamemode
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.writeVarInt(0); // Add player action
|
||||||
|
msg.writeVarInt(1);
|
||||||
|
msg.writeUuid(uuid);
|
||||||
|
msg.writeString(username);
|
||||||
|
msg.writeVarInt(0);
|
||||||
|
msg.writeVarInt(gameMode);
|
||||||
|
msg.writeVarInt(60);
|
||||||
|
msg.writeBoolean(false);
|
||||||
|
|
||||||
|
if (version.moreOrEqual(Version.V1_19)) {
|
||||||
|
msg.writeBoolean(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum Action {
|
||||||
|
ADD_PLAYER,
|
||||||
|
INITIALIZE_CHAT,
|
||||||
|
UPDATE_GAMEMODE,
|
||||||
|
UPDATE_LISTED,
|
||||||
|
UPDATE_LATENCY,
|
||||||
|
UPDATE_DISPLAY_NAME;
|
||||||
|
}
|
||||||
|
}
|
@ -15,28 +15,29 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets.play;
|
package ua.nanit.limbo.protocol.packets.play;
|
||||||
|
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.PacketOut;
|
import ua.nanit.limbo.protocol.NbtMessage;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
|
||||||
public class PacketPlayerListHeader implements PacketOut {
|
public class PacketPlayerListHeader implements PacketOut {
|
||||||
|
|
||||||
private String header;
|
private NbtMessage header;
|
||||||
private String footer;
|
private NbtMessage footer;
|
||||||
|
|
||||||
public void setHeader(String header) {
|
public void setHeader(NbtMessage header) {
|
||||||
this.header = header;
|
this.header = header;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFooter(String footer) {
|
public void setFooter(NbtMessage footer) {
|
||||||
this.footer = footer;
|
this.footer = footer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void encode(ByteMessage msg, Version version) {
|
public void encode(ByteMessage msg, Version version) {
|
||||||
msg.writeString(header);
|
msg.writeNbtMessage(header, version);
|
||||||
msg.writeString(footer);
|
msg.writeNbtMessage(footer, version);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,11 +15,11 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets.play;
|
package ua.nanit.limbo.protocol.packets.play;
|
||||||
|
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.PacketOut;
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
|
||||||
public class PacketPlayerPositionAndLook implements PacketOut {
|
public class PacketPlayerPositionAndLook implements PacketOut {
|
||||||
|
|
||||||
@ -28,53 +28,38 @@ public class PacketPlayerPositionAndLook implements PacketOut {
|
|||||||
private double z;
|
private double z;
|
||||||
private float yaw;
|
private float yaw;
|
||||||
private float pitch;
|
private float pitch;
|
||||||
private byte flags = 0x08;
|
|
||||||
private int teleportId;
|
private int teleportId;
|
||||||
|
|
||||||
public void setX(double x) {
|
public PacketPlayerPositionAndLook() {}
|
||||||
|
|
||||||
|
public PacketPlayerPositionAndLook(double x, double y, double z, float yaw, float pitch, int teleportId) {
|
||||||
this.x = x;
|
this.x = x;
|
||||||
}
|
|
||||||
|
|
||||||
public void setY(double y) {
|
|
||||||
this.y = y;
|
this.y = y;
|
||||||
}
|
|
||||||
|
|
||||||
public void setZ(double z) {
|
|
||||||
this.z = z;
|
this.z = z;
|
||||||
}
|
|
||||||
|
|
||||||
public void setYaw(float yaw) {
|
|
||||||
this.yaw = yaw;
|
this.yaw = yaw;
|
||||||
}
|
|
||||||
|
|
||||||
public void setPitch(float pitch) {
|
|
||||||
this.pitch = pitch;
|
this.pitch = pitch;
|
||||||
}
|
|
||||||
|
|
||||||
public void setFlags(byte flags) {
|
|
||||||
this.flags = flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTeleportId(int teleportId) {
|
|
||||||
this.teleportId = teleportId;
|
this.teleportId = teleportId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void encode(ByteMessage msg, Version version) {
|
public void encode(ByteMessage msg, Version version) {
|
||||||
msg.writeDouble(x);
|
msg.writeDouble(x);
|
||||||
msg.writeDouble(y);
|
msg.writeDouble(y + (version.less(Version.V1_8) ? 1.62F : 0));
|
||||||
msg.writeDouble(z);
|
msg.writeDouble(z);
|
||||||
msg.writeFloat(yaw);
|
msg.writeFloat(yaw);
|
||||||
msg.writeFloat(pitch);
|
msg.writeFloat(pitch);
|
||||||
|
|
||||||
if (version.less(Version.V1_9)) {
|
if (version.moreOrEqual(Version.V1_8)) {
|
||||||
msg.writeBoolean(true); // On ground
|
msg.writeByte(0x08);
|
||||||
} else {
|
} else {
|
||||||
msg.writeByte(flags);
|
msg.writeBoolean(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version.moreOrEqual(Version.V1_9)) {
|
||||||
msg.writeVarInt(teleportId);
|
msg.writeVarInt(teleportId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version.moreOrEqual(Version.V1_17)) {
|
if (version.fromTo(Version.V1_17, Version.V1_19_3)) {
|
||||||
msg.writeBoolean(false); // Dismount vehicle
|
msg.writeBoolean(false); // Dismount vehicle
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,11 +15,11 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets.play;
|
package ua.nanit.limbo.protocol.packets.play;
|
||||||
|
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.PacketOut;
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
|
||||||
public class PacketPluginMessage implements PacketOut {
|
public class PacketPluginMessage implements PacketOut {
|
||||||
|
|
||||||
@ -39,4 +39,5 @@ public class PacketPluginMessage implements PacketOut {
|
|||||||
msg.writeString(channel);
|
msg.writeString(channel);
|
||||||
msg.writeString(message);
|
msg.writeString(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package ua.nanit.limbo.protocol.packets.play;
|
||||||
|
|
||||||
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
|
||||||
|
public class PacketSpawnPosition implements PacketOut {
|
||||||
|
|
||||||
|
private long x;
|
||||||
|
private long y;
|
||||||
|
private long z;
|
||||||
|
|
||||||
|
public PacketSpawnPosition() { }
|
||||||
|
|
||||||
|
public PacketSpawnPosition(long x, long y, long z) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void encode(ByteMessage msg, Version version) {
|
||||||
|
msg.writeLong(encodePosition(x, y ,z));
|
||||||
|
msg.writeFloat(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long encodePosition(long x, long y, long z) {
|
||||||
|
return ((x & 0x3FFFFFF) << 38) | ((z & 0x3FFFFFF) << 12) | (y & 0xFFF);
|
||||||
|
}
|
||||||
|
}
|
@ -15,12 +15,12 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets.play;
|
package ua.nanit.limbo.protocol.packets.play;
|
||||||
|
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.PacketOut;
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
import ru.nanit.limbo.server.data.Title;
|
import ua.nanit.limbo.server.data.Title;
|
||||||
|
|
||||||
public class PacketTitleLegacy implements PacketOut {
|
public class PacketTitleLegacy implements PacketOut {
|
||||||
|
|
@ -15,23 +15,24 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets.play;
|
package ua.nanit.limbo.protocol.packets.play;
|
||||||
|
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.PacketOut;
|
import ua.nanit.limbo.protocol.NbtMessage;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
|
||||||
public class PacketTitleSetSubTitle implements PacketOut {
|
public class PacketTitleSetSubTitle implements PacketOut {
|
||||||
|
|
||||||
private String subtitle;
|
private NbtMessage subtitle;
|
||||||
|
|
||||||
public void setSubtitle(String subtitle) {
|
public void setSubtitle(NbtMessage subtitle) {
|
||||||
this.subtitle = subtitle;
|
this.subtitle = subtitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void encode(ByteMessage msg, Version version) {
|
public void encode(ByteMessage msg, Version version) {
|
||||||
msg.writeString(subtitle);
|
msg.writeNbtMessage(subtitle, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -15,23 +15,24 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets.play;
|
package ua.nanit.limbo.protocol.packets.play;
|
||||||
|
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.PacketOut;
|
import ua.nanit.limbo.protocol.NbtMessage;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
|
||||||
public class PacketTitleSetTitle implements PacketOut {
|
public class PacketTitleSetTitle implements PacketOut {
|
||||||
|
|
||||||
private String title;
|
private NbtMessage title;
|
||||||
|
|
||||||
public void setTitle(String title) {
|
public void setTitle(NbtMessage title) {
|
||||||
this.title = title;
|
this.title = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void encode(ByteMessage msg, Version version) {
|
public void encode(ByteMessage msg, Version version) {
|
||||||
msg.writeString(title);
|
msg.writeNbtMessage(title, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -15,11 +15,11 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets.play;
|
package ua.nanit.limbo.protocol.packets.play;
|
||||||
|
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.PacketOut;
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
|
|
||||||
public class PacketTitleTimes implements PacketOut {
|
public class PacketTitleTimes implements PacketOut {
|
||||||
|
|
@ -15,13 +15,13 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets.status;
|
package ua.nanit.limbo.protocol.packets.status;
|
||||||
|
|
||||||
import ru.nanit.limbo.connection.ClientConnection;
|
import ua.nanit.limbo.connection.ClientConnection;
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.Packet;
|
import ua.nanit.limbo.protocol.Packet;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
import ru.nanit.limbo.server.LimboServer;
|
import ua.nanit.limbo.server.LimboServer;
|
||||||
|
|
||||||
public class PacketStatusPing implements Packet {
|
public class PacketStatusPing implements Packet {
|
||||||
|
|
@ -15,13 +15,13 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets.status;
|
package ua.nanit.limbo.protocol.packets.status;
|
||||||
|
|
||||||
import ru.nanit.limbo.connection.ClientConnection;
|
import ua.nanit.limbo.connection.ClientConnection;
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.PacketIn;
|
import ua.nanit.limbo.protocol.PacketIn;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
import ru.nanit.limbo.server.LimboServer;
|
import ua.nanit.limbo.server.LimboServer;
|
||||||
|
|
||||||
public class PacketStatusRequest implements PacketIn {
|
public class PacketStatusRequest implements PacketIn {
|
||||||
|
|
@ -15,12 +15,12 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.packets.status;
|
package ua.nanit.limbo.protocol.packets.status;
|
||||||
|
|
||||||
import ru.nanit.limbo.protocol.ByteMessage;
|
import ua.nanit.limbo.protocol.ByteMessage;
|
||||||
import ru.nanit.limbo.protocol.PacketOut;
|
import ua.nanit.limbo.protocol.PacketOut;
|
||||||
import ru.nanit.limbo.protocol.registry.Version;
|
import ua.nanit.limbo.protocol.registry.Version;
|
||||||
import ru.nanit.limbo.server.LimboServer;
|
import ua.nanit.limbo.server.LimboServer;
|
||||||
|
|
||||||
public class PacketStatusResponse implements PacketOut {
|
public class PacketStatusResponse implements PacketOut {
|
||||||
|
|
||||||
@ -36,9 +36,16 @@ public class PacketStatusResponse implements PacketOut {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void encode(ByteMessage msg, Version version) {
|
public void encode(ByteMessage msg, Version version) {
|
||||||
int protocol = server.getConfig().getInfoForwarding().isNone()
|
int protocol;
|
||||||
? version.getProtocolNumber()
|
int staticProtocol = server.getConfig().getPingData().getProtocol();
|
||||||
: Version.getMax().getProtocolNumber();
|
|
||||||
|
if (staticProtocol > 0) {
|
||||||
|
protocol = staticProtocol;
|
||||||
|
} else {
|
||||||
|
protocol = server.getConfig().getInfoForwarding().isNone()
|
||||||
|
? version.getProtocolNumber()
|
||||||
|
: Version.getMax().getProtocolNumber();
|
||||||
|
}
|
||||||
|
|
||||||
String ver = server.getConfig().getPingData().getVersion();
|
String ver = server.getConfig().getPingData().getVersion();
|
||||||
String desc = server.getConfig().getPingData().getDescription();
|
String desc = server.getConfig().getPingData().getDescription();
|
@ -15,20 +15,21 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.registry;
|
package ua.nanit.limbo.protocol.registry;
|
||||||
|
|
||||||
import ru.nanit.limbo.protocol.Packet;
|
import ua.nanit.limbo.protocol.Packet;
|
||||||
import ru.nanit.limbo.protocol.packets.PacketHandshake;
|
import ua.nanit.limbo.protocol.packets.PacketHandshake;
|
||||||
import ru.nanit.limbo.protocol.packets.login.*;
|
import ua.nanit.limbo.protocol.packets.login.*;
|
||||||
import ru.nanit.limbo.protocol.packets.play.*;
|
import ua.nanit.limbo.protocol.packets.play.*;
|
||||||
import ru.nanit.limbo.protocol.packets.status.PacketStatusPing;
|
import ua.nanit.limbo.protocol.packets.configuration.*;
|
||||||
import ru.nanit.limbo.protocol.packets.status.PacketStatusRequest;
|
import ua.nanit.limbo.protocol.packets.status.PacketStatusPing;
|
||||||
import ru.nanit.limbo.protocol.packets.status.PacketStatusResponse;
|
import ua.nanit.limbo.protocol.packets.status.PacketStatusRequest;
|
||||||
|
import ua.nanit.limbo.protocol.packets.status.PacketStatusResponse;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import static ru.nanit.limbo.protocol.registry.Version.*;
|
import static ua.nanit.limbo.protocol.registry.Version.*;
|
||||||
|
|
||||||
public enum State {
|
public enum State {
|
||||||
|
|
||||||
@ -63,6 +64,10 @@ public enum State {
|
|||||||
serverBound.register(PacketLoginPluginResponse::new,
|
serverBound.register(PacketLoginPluginResponse::new,
|
||||||
map(0x02, Version.getMin(), Version.getMax())
|
map(0x02, Version.getMin(), Version.getMax())
|
||||||
);
|
);
|
||||||
|
serverBound.register(
|
||||||
|
PacketLoginAcknowledged::new,
|
||||||
|
map(0x03, V1_20_2, Version.getMax())
|
||||||
|
);
|
||||||
clientBound.register(PacketDisconnect::new,
|
clientBound.register(PacketDisconnect::new,
|
||||||
map(0x00, Version.getMin(), Version.getMax())
|
map(0x00, Version.getMin(), Version.getMax())
|
||||||
);
|
);
|
||||||
@ -74,10 +79,55 @@ public enum State {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
PLAY(3) {
|
CONFIGURATION(3) {
|
||||||
|
{
|
||||||
|
clientBound.register(
|
||||||
|
PacketPluginMessage::new,
|
||||||
|
map(0x00, V1_20_2, V1_20_3),
|
||||||
|
map(0x01, V1_20_5, V1_21)
|
||||||
|
);
|
||||||
|
clientBound.register(
|
||||||
|
PacketDisconnect::new,
|
||||||
|
map(0x01, V1_20_2, V1_20_3),
|
||||||
|
map(0x02, V1_20_5, V1_21)
|
||||||
|
);
|
||||||
|
clientBound.register(
|
||||||
|
PacketFinishConfiguration::new,
|
||||||
|
map(0x02, V1_20_2, V1_20_3),
|
||||||
|
map(0x03, V1_20_5, V1_21)
|
||||||
|
);
|
||||||
|
clientBound.register(
|
||||||
|
PacketKeepAlive::new,
|
||||||
|
map(0x03, V1_20_2, V1_20_3),
|
||||||
|
map(0x04, V1_20_5, V1_21)
|
||||||
|
);
|
||||||
|
clientBound.register(
|
||||||
|
PacketRegistryData::new,
|
||||||
|
map(0x05, V1_20_2, V1_20_3),
|
||||||
|
map(0x07, V1_20_5, V1_21)
|
||||||
|
);
|
||||||
|
|
||||||
|
serverBound.register(
|
||||||
|
PacketPluginMessage::new,
|
||||||
|
map(0x01, V1_20_2, V1_20_3),
|
||||||
|
map(0x02, V1_20_2, V1_21)
|
||||||
|
);
|
||||||
|
serverBound.register(
|
||||||
|
PacketFinishConfiguration::new,
|
||||||
|
map(0x02, V1_20_2, V1_20_3),
|
||||||
|
map(0x03, V1_20_5, V1_21)
|
||||||
|
);
|
||||||
|
serverBound.register(
|
||||||
|
PacketKeepAlive::new,
|
||||||
|
map(0x03, V1_20_2, V1_20_3),
|
||||||
|
map(0x04, V1_20_5, V1_21)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
PLAY(4) {
|
||||||
{
|
{
|
||||||
serverBound.register(PacketKeepAlive::new,
|
serverBound.register(PacketKeepAlive::new,
|
||||||
map(0x00, V1_8, V1_8),
|
map(0x00, V1_7_2, V1_8),
|
||||||
map(0x0B, V1_9, V1_11_1),
|
map(0x0B, V1_9, V1_11_1),
|
||||||
map(0x0C, V1_12, V1_12),
|
map(0x0C, V1_12, V1_12),
|
||||||
map(0x0B, V1_12_1, V1_12_2),
|
map(0x0B, V1_12_1, V1_12_2),
|
||||||
@ -85,7 +135,13 @@ public enum State {
|
|||||||
map(0x0F, V1_14, V1_15_2),
|
map(0x0F, V1_14, V1_15_2),
|
||||||
map(0x10, V1_16, V1_16_4),
|
map(0x10, V1_16, V1_16_4),
|
||||||
map(0x0F, V1_17, V1_18_2),
|
map(0x0F, V1_17, V1_18_2),
|
||||||
map(0x11, V1_19, V1_19)
|
map(0x11, V1_19, V1_19),
|
||||||
|
map(0x12, V1_19_1, V1_19_1),
|
||||||
|
map(0x11, V1_19_3, V1_19_3),
|
||||||
|
map(0x12, V1_19_4, V1_20),
|
||||||
|
map(0x14, V1_20_2, V1_20_2),
|
||||||
|
map(0x15, V1_20_3, V1_20_3),
|
||||||
|
map(0x18, V1_20_5, V1_21)
|
||||||
);
|
);
|
||||||
|
|
||||||
clientBound.register(PacketDeclareCommands::new,
|
clientBound.register(PacketDeclareCommands::new,
|
||||||
@ -94,17 +150,25 @@ public enum State {
|
|||||||
map(0x11, V1_16, V1_16_1),
|
map(0x11, V1_16, V1_16_1),
|
||||||
map(0x10, V1_16_2, V1_16_4),
|
map(0x10, V1_16_2, V1_16_4),
|
||||||
map(0x12, V1_17, V1_18_2),
|
map(0x12, V1_17, V1_18_2),
|
||||||
map(0x0F, V1_19, V1_19)
|
map(0x0F, V1_19, V1_19_1),
|
||||||
|
map(0x0E, V1_19_3, V1_19_3),
|
||||||
|
map(0x10, V1_19_4, V1_20),
|
||||||
|
map(0x11, V1_20_2, V1_21)
|
||||||
);
|
);
|
||||||
clientBound.register(PacketJoinGame::new,
|
clientBound.register(PacketJoinGame::new,
|
||||||
map(0x01, V1_8, V1_8),
|
map(0x01, V1_7_2, V1_8),
|
||||||
map(0x23, V1_9, V1_12_2),
|
map(0x23, V1_9, V1_12_2),
|
||||||
map(0x25, V1_13, V1_14_4),
|
map(0x25, V1_13, V1_14_4),
|
||||||
map(0x26, V1_15, V1_15_2),
|
map(0x26, V1_15, V1_15_2),
|
||||||
map(0x25, V1_16, V1_16_1),
|
map(0x25, V1_16, V1_16_1),
|
||||||
map(0x24, V1_16_2, V1_16_4),
|
map(0x24, V1_16_2, V1_16_4),
|
||||||
map(0x26, V1_17, V1_18_2),
|
map(0x26, V1_17, V1_18_2),
|
||||||
map(0x23, V1_19, V1_19)
|
map(0x23, V1_19, V1_19),
|
||||||
|
map(0x25, V1_19_1, V1_19_1),
|
||||||
|
map(0x24, V1_19_3, V1_19_3),
|
||||||
|
map(0x28, V1_19_4, V1_20),
|
||||||
|
map(0x29, V1_20_2, V1_20_3),
|
||||||
|
map(0x2B, V1_20_5, V1_21)
|
||||||
);
|
);
|
||||||
clientBound.register(PacketPluginMessage::new,
|
clientBound.register(PacketPluginMessage::new,
|
||||||
map(0x19, V1_13, V1_13_2),
|
map(0x19, V1_13, V1_13_2),
|
||||||
@ -113,10 +177,15 @@ public enum State {
|
|||||||
map(0x18, V1_16, V1_16_1),
|
map(0x18, V1_16, V1_16_1),
|
||||||
map(0x17, V1_16_2, V1_16_4),
|
map(0x17, V1_16_2, V1_16_4),
|
||||||
map(0x18, V1_17, V1_18_2),
|
map(0x18, V1_17, V1_18_2),
|
||||||
map(0x15, V1_19, V1_19)
|
map(0x15, V1_19, V1_19),
|
||||||
|
map(0x16, V1_19_1, V1_19_1),
|
||||||
|
map(0x15, V1_19_3, V1_19_3),
|
||||||
|
map(0x17, V1_19_4, V1_20),
|
||||||
|
map(0x18, V1_20_2, V1_20_3),
|
||||||
|
map(0x19, V1_20_5, V1_21)
|
||||||
);
|
);
|
||||||
clientBound.register(PacketPlayerAbilities::new,
|
clientBound.register(PacketPlayerAbilities::new,
|
||||||
map(0x39, V1_8, V1_8),
|
map(0x39, V1_7_2, V1_8),
|
||||||
map(0x2B, V1_9, V1_12),
|
map(0x2B, V1_9, V1_12),
|
||||||
map(0x2C, V1_12_1, V1_12_2),
|
map(0x2C, V1_12_1, V1_12_2),
|
||||||
map(0x2E, V1_13, V1_13_2),
|
map(0x2E, V1_13, V1_13_2),
|
||||||
@ -125,10 +194,15 @@ public enum State {
|
|||||||
map(0x31, V1_16, V1_16_1),
|
map(0x31, V1_16, V1_16_1),
|
||||||
map(0x30, V1_16_2, V1_16_4),
|
map(0x30, V1_16_2, V1_16_4),
|
||||||
map(0x32, V1_17, V1_18_2),
|
map(0x32, V1_17, V1_18_2),
|
||||||
map(0x2F, V1_19, V1_19)
|
map(0x2F, V1_19, V1_19),
|
||||||
|
map(0x31, V1_19_1, V1_19_1),
|
||||||
|
map(0x30, V1_19_3, V1_19_3),
|
||||||
|
map(0x34, V1_19_4, V1_20),
|
||||||
|
map(0x36, V1_20_2, V1_20_3),
|
||||||
|
map(0x38, V1_20_5, V1_21)
|
||||||
);
|
);
|
||||||
clientBound.register(PacketPlayerPositionAndLook::new,
|
clientBound.register(PacketPlayerPositionAndLook::new,
|
||||||
map(0x08, V1_8, V1_8),
|
map(0x08, V1_7_2, V1_8),
|
||||||
map(0x2E, V1_9, V1_12),
|
map(0x2E, V1_9, V1_12),
|
||||||
map(0x2F, V1_12_1, V1_12_2),
|
map(0x2F, V1_12_1, V1_12_2),
|
||||||
map(0x32, V1_13, V1_13_2),
|
map(0x32, V1_13, V1_13_2),
|
||||||
@ -137,10 +211,15 @@ public enum State {
|
|||||||
map(0x35, V1_16, V1_16_1),
|
map(0x35, V1_16, V1_16_1),
|
||||||
map(0x34, V1_16_2, V1_16_4),
|
map(0x34, V1_16_2, V1_16_4),
|
||||||
map(0x38, V1_17, V1_18_2),
|
map(0x38, V1_17, V1_18_2),
|
||||||
map(0x36, V1_19, V1_19)
|
map(0x36, V1_19, V1_19),
|
||||||
|
map(0x39, V1_19_1, V1_19_1),
|
||||||
|
map(0x38, V1_19_3, V1_19_3),
|
||||||
|
map(0x3C, V1_19_4, V1_20),
|
||||||
|
map(0x3E, V1_20_2, V1_20_3),
|
||||||
|
map(0x40, V1_20_5, V1_21)
|
||||||
);
|
);
|
||||||
clientBound.register(PacketKeepAlive::new,
|
clientBound.register(PacketKeepAlive::new,
|
||||||
map(0x00, V1_8, V1_8),
|
map(0x00, V1_7_2, V1_8),
|
||||||
map(0x1F, V1_9, V1_12_2),
|
map(0x1F, V1_9, V1_12_2),
|
||||||
map(0x21, V1_13, V1_13_2),
|
map(0x21, V1_13, V1_13_2),
|
||||||
map(0x20, V1_14, V1_14_4),
|
map(0x20, V1_14, V1_14_4),
|
||||||
@ -148,26 +227,39 @@ public enum State {
|
|||||||
map(0x20, V1_16, V1_16_1),
|
map(0x20, V1_16, V1_16_1),
|
||||||
map(0x1F, V1_16_2, V1_16_4),
|
map(0x1F, V1_16_2, V1_16_4),
|
||||||
map(0x21, V1_17, V1_18_2),
|
map(0x21, V1_17, V1_18_2),
|
||||||
map(0x1E, V1_19, V1_19)
|
map(0x1E, V1_19, V1_19),
|
||||||
|
map(0x20, V1_19_1, V1_19_1),
|
||||||
|
map(0x1F, V1_19_3, V1_19_3),
|
||||||
|
map(0x23, V1_19_4, V1_20),
|
||||||
|
map(0x24, V1_20_2, V1_20_3),
|
||||||
|
map(0x26, V1_20_5, V1_21)
|
||||||
);
|
);
|
||||||
clientBound.register(PacketChatMessage::new,
|
clientBound.register(PacketChatMessage::new,
|
||||||
map(0x02, V1_8, V1_8),
|
map(0x02, V1_7_2, V1_8),
|
||||||
map(0x0F, V1_9, V1_12_2),
|
map(0x0F, V1_9, V1_12_2),
|
||||||
map(0x0E, V1_13, V1_14_4),
|
map(0x0E, V1_13, V1_14_4),
|
||||||
map(0x0F, V1_15, V1_15_2),
|
map(0x0F, V1_15, V1_15_2),
|
||||||
map(0x0E, V1_16, V1_16_4),
|
map(0x0E, V1_16, V1_16_4),
|
||||||
map(0x0F, V1_17, V1_18_2),
|
map(0x0F, V1_17, V1_18_2),
|
||||||
map(0x5F, V1_19, V1_19)
|
map(0x5F, V1_19, V1_19),
|
||||||
|
map(0x62, V1_19_1, V1_19_1),
|
||||||
|
map(0x60, V1_19_3, V1_19_3),
|
||||||
|
map(0x64, V1_19_4, V1_20),
|
||||||
|
map(0x67, V1_20_2, V1_20_2),
|
||||||
|
map(0x69, V1_20_3, V1_20_3),
|
||||||
|
map(0x6C, V1_20_5, V1_21)
|
||||||
);
|
);
|
||||||
clientBound.register(PacketBossBar::new,
|
clientBound.register(PacketBossBar::new,
|
||||||
map(0x0C, V1_9, V1_14_4),
|
map(0x0C, V1_9, V1_14_4),
|
||||||
map(0x0D, V1_15, V1_15_2),
|
map(0x0D, V1_15, V1_15_2),
|
||||||
map(0x0C, V1_16, V1_16_4),
|
map(0x0C, V1_16, V1_16_4),
|
||||||
map(0x0D, V1_17, V1_18_2),
|
map(0x0D, V1_17, V1_18_2),
|
||||||
map(0x0A, V1_19, V1_19)
|
map(0x0A, V1_19, V1_19_3),
|
||||||
|
map(0x0B, V1_19_4, V1_20),
|
||||||
|
map(0x0A, V1_20_2, V1_21)
|
||||||
);
|
);
|
||||||
clientBound.register(PacketPlayerInfo::new,
|
clientBound.register(PacketPlayerInfo::new,
|
||||||
map(0x38, V1_8, V1_8),
|
map(0x38, V1_7_2, V1_8),
|
||||||
map(0x2D, V1_9, V1_12),
|
map(0x2D, V1_9, V1_12),
|
||||||
map(0x2E, V1_12_1, V1_12_2),
|
map(0x2E, V1_12_1, V1_12_2),
|
||||||
map(0x30, V1_13, V1_13_2),
|
map(0x30, V1_13, V1_13_2),
|
||||||
@ -176,7 +268,12 @@ public enum State {
|
|||||||
map(0x33, V1_16, V1_16_1),
|
map(0x33, V1_16, V1_16_1),
|
||||||
map(0x32, V1_16_2, V1_16_4),
|
map(0x32, V1_16_2, V1_16_4),
|
||||||
map(0x36, V1_17, V1_18_2),
|
map(0x36, V1_17, V1_18_2),
|
||||||
map(0x34, V1_19, V1_19)
|
map(0x34, V1_19, V1_19),
|
||||||
|
map(0x37, V1_19_1, V1_19_1),
|
||||||
|
map(0x36, V1_19_3, V1_19_3),
|
||||||
|
map(0x3A, V1_19_4, V1_20),
|
||||||
|
map(0x3C, V1_20_2, V1_20_3),
|
||||||
|
map(0x3E, V1_20_5, V1_21)
|
||||||
);
|
);
|
||||||
clientBound.register(PacketTitleLegacy::new,
|
clientBound.register(PacketTitleLegacy::new,
|
||||||
map(0x45, V1_8, V1_11_1),
|
map(0x45, V1_8, V1_11_1),
|
||||||
@ -189,15 +286,33 @@ public enum State {
|
|||||||
);
|
);
|
||||||
clientBound.register(PacketTitleSetTitle::new,
|
clientBound.register(PacketTitleSetTitle::new,
|
||||||
map(0x59, V1_17, V1_17_1),
|
map(0x59, V1_17, V1_17_1),
|
||||||
map(0x5A, V1_18, V1_19)
|
map(0x5A, V1_18, V1_19),
|
||||||
|
map(0x5D, V1_19_1, V1_19_1),
|
||||||
|
map(0x5B, V1_19_3, V1_19_3),
|
||||||
|
map(0x5F, V1_19_4, V1_20),
|
||||||
|
map(0x61, V1_20_2, V1_20_2),
|
||||||
|
map(0x63, V1_20_3, V1_20_3),
|
||||||
|
map(0x65, V1_20_5, V1_21)
|
||||||
);
|
);
|
||||||
clientBound.register(PacketTitleSetSubTitle::new,
|
clientBound.register(PacketTitleSetSubTitle::new,
|
||||||
map(0x57, V1_17, V1_17_1),
|
map(0x57, V1_17, V1_17_1),
|
||||||
map(0x58, V1_18, V1_19)
|
map(0x58, V1_18, V1_19),
|
||||||
|
map(0x5B, V1_19_1, V1_19_1),
|
||||||
|
map(0x59, V1_19_3, V1_19_3),
|
||||||
|
map(0x5D, V1_19_4, V1_20),
|
||||||
|
map(0x5F, V1_20_2, V1_20_2),
|
||||||
|
map(0x61, V1_20_3, V1_20_3),
|
||||||
|
map(0x63, V1_20_5, V1_21)
|
||||||
);
|
);
|
||||||
clientBound.register(PacketTitleTimes::new,
|
clientBound.register(PacketTitleTimes::new,
|
||||||
map(0x5A, V1_17, V1_17_1),
|
map(0x5A, V1_17, V1_17_1),
|
||||||
map(0x5B, V1_18, V1_19)
|
map(0x5B, V1_18, V1_19),
|
||||||
|
map(0x5E, V1_19_1, V1_19_1),
|
||||||
|
map(0x5C, V1_19_3, V1_19_3),
|
||||||
|
map(0x60, V1_19_4, V1_20),
|
||||||
|
map(0x62, V1_20_2, V1_20_2),
|
||||||
|
map(0x64, V1_20_3, V1_20_3),
|
||||||
|
map(0x66, V1_20_5, V1_21)
|
||||||
);
|
);
|
||||||
clientBound.register(PacketPlayerListHeader::new,
|
clientBound.register(PacketPlayerListHeader::new,
|
||||||
map(0x47, V1_8, V1_8),
|
map(0x47, V1_8, V1_8),
|
||||||
@ -211,7 +326,28 @@ public enum State {
|
|||||||
map(0x53, V1_16, V1_16_4),
|
map(0x53, V1_16, V1_16_4),
|
||||||
map(0x5E, V1_17, V1_17_1),
|
map(0x5E, V1_17, V1_17_1),
|
||||||
map(0x5F, V1_18, V1_18_2),
|
map(0x5F, V1_18, V1_18_2),
|
||||||
map(0x60, V1_19, V1_19)
|
map(0x60, V1_19, V1_19),
|
||||||
|
map(0x63, V1_19_1, V1_19_1),
|
||||||
|
map(0x61, V1_19_3, V1_19_3),
|
||||||
|
map(0x65, V1_19_4, V1_20),
|
||||||
|
map(0x68, V1_20_2, V1_20_2),
|
||||||
|
map(0x6A, V1_20_3, V1_20_3),
|
||||||
|
map(0x6D, V1_20_5, V1_21)
|
||||||
|
);
|
||||||
|
clientBound.register(PacketSpawnPosition::new,
|
||||||
|
map(0x4C, V1_19_3, V1_19_3),
|
||||||
|
map(0x50, V1_19_4, V1_20),
|
||||||
|
map(0x52, V1_20_2, V1_20_2),
|
||||||
|
map(0x54, V1_20_3, V1_20_3),
|
||||||
|
map(0x56, V1_20_5, V1_21)
|
||||||
|
);
|
||||||
|
clientBound.register(PacketGameEvent::new,
|
||||||
|
map(0x20, V1_20_3, V1_20_3),
|
||||||
|
map(0x22, V1_20_5, V1_21)
|
||||||
|
);
|
||||||
|
clientBound.register(PacketEmptyChunk::new,
|
||||||
|
map(0x25, V1_20_3, V1_20_3),
|
||||||
|
map(0x27, V1_20_5, V1_21)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
@ -15,7 +15,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.protocol.registry;
|
package ua.nanit.limbo.protocol.registry;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -23,6 +23,10 @@ import java.util.Map;
|
|||||||
public enum Version {
|
public enum Version {
|
||||||
|
|
||||||
UNDEFINED(-1),
|
UNDEFINED(-1),
|
||||||
|
V1_7_2(4),
|
||||||
|
// 1.7.2-1.7.5 has same protocol numbers
|
||||||
|
V1_7_6(5),
|
||||||
|
// 1.7.6-1.7.10 has same protocol numbers
|
||||||
V1_8(47),
|
V1_8(47),
|
||||||
// 1.8-1.8.8 has same protocol numbers
|
// 1.8-1.8.8 has same protocol numbers
|
||||||
V1_9(107),
|
V1_9(107),
|
||||||
@ -59,7 +63,18 @@ public enum Version {
|
|||||||
V1_18(757),
|
V1_18(757),
|
||||||
// 1.18.1 has same protocol number
|
// 1.18.1 has same protocol number
|
||||||
V1_18_2(758),
|
V1_18_2(758),
|
||||||
V1_19(759);
|
V1_19(759),
|
||||||
|
V1_19_1(760),
|
||||||
|
// 1.19.2 has same protocol number
|
||||||
|
V1_19_3(761),
|
||||||
|
V1_19_4(762),
|
||||||
|
V1_20(763),
|
||||||
|
// 1.20.1 has same protocol number
|
||||||
|
V1_20_2(764),
|
||||||
|
V1_20_3(765),
|
||||||
|
V1_20_5(766),
|
||||||
|
// 1.20.6 has same protocol number
|
||||||
|
V1_21(767);
|
||||||
|
|
||||||
private static final Map<Integer, Version> VERSION_MAP;
|
private static final Map<Integer, Version> VERSION_MAP;
|
||||||
private static final Version MAX;
|
private static final Version MAX;
|
||||||
@ -118,7 +133,7 @@ public enum Version {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Version getMin() {
|
public static Version getMin() {
|
||||||
return V1_8;
|
return V1_7_2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Version getMax() {
|
public static Version getMax() {
|
@ -1,4 +1,4 @@
|
|||||||
package ru.nanit.limbo.server;
|
package ua.nanit.limbo.server;
|
||||||
|
|
||||||
public interface Command {
|
public interface Command {
|
||||||
|
|
@ -1,9 +1,6 @@
|
|||||||
package ru.nanit.limbo.server;
|
package ua.nanit.limbo.server;
|
||||||
|
|
||||||
import ru.nanit.limbo.server.commands.CmdConn;
|
import ua.nanit.limbo.server.commands.*;
|
||||||
import ru.nanit.limbo.server.commands.CmdHelp;
|
|
||||||
import ru.nanit.limbo.server.commands.CmdMem;
|
|
||||||
import ru.nanit.limbo.server.commands.CmdStop;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@ -19,8 +16,10 @@ public final class CommandManager extends Thread {
|
|||||||
return commands.get(name.toLowerCase());
|
return commands.get(name.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void register(String name, Command cmd) {
|
public void register(Command cmd, String... aliases) {
|
||||||
commands.put(name.toLowerCase(), cmd);
|
for (String alias : aliases) {
|
||||||
|
commands.put(alias.toLowerCase(), cmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -41,19 +40,20 @@ public final class CommandManager extends Thread {
|
|||||||
try {
|
try {
|
||||||
handler.execute();
|
handler.execute();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
Logger.error("Cannot execute command:", t);
|
Log.error("Cannot execute command:", t);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.info("Unknown command. Type \"help\" to get commands list");
|
Log.info("Unknown command. Type \"help\" to get commands list");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerAll(LimboServer server) {
|
public void registerAll(LimboServer server) {
|
||||||
register("help", new CmdHelp(server));
|
register(new CmdHelp(server), "help");
|
||||||
register("conn", new CmdConn(server));
|
register(new CmdConn(server), "conn");
|
||||||
register("mem", new CmdMem());
|
register(new CmdMem(), "mem");
|
||||||
register("stop", new CmdStop());
|
register(new CmdStop(), "stop");
|
||||||
|
register(new CmdVersion(), "version", "ver");
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,9 +15,9 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.server;
|
package ua.nanit.limbo.server;
|
||||||
|
|
||||||
import ru.nanit.limbo.connection.ClientConnection;
|
import ua.nanit.limbo.connection.ClientConnection;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -43,12 +43,12 @@ public final class Connections {
|
|||||||
|
|
||||||
public void addConnection(ClientConnection connection) {
|
public void addConnection(ClientConnection connection) {
|
||||||
connections.put(connection.getUuid(), connection);
|
connections.put(connection.getUuid(), connection);
|
||||||
Logger.info("Player %s connected (%s) [%s]", connection.getUsername(),
|
Log.info("Player %s connected (%s) [%s]", connection.getUsername(),
|
||||||
connection.getAddress(), connection.getClientVersion());
|
connection.getAddress(), connection.getClientVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeConnection(ClientConnection connection) {
|
public void removeConnection(ClientConnection connection) {
|
||||||
connections.remove(connection.getUuid());
|
connections.remove(connection.getUuid());
|
||||||
Logger.info("Player %s disconnected", connection.getUsername());
|
Log.info("Player %s disconnected", connection.getUsername());
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,7 +15,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.server;
|
package ua.nanit.limbo.server;
|
||||||
|
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.ChannelOption;
|
import io.netty.channel.ChannelOption;
|
||||||
@ -27,12 +27,12 @@ import io.netty.channel.epoll.EpollServerSocketChannel;
|
|||||||
import io.netty.channel.nio.NioEventLoopGroup;
|
import io.netty.channel.nio.NioEventLoopGroup;
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
import io.netty.util.ResourceLeakDetector;
|
import io.netty.util.ResourceLeakDetector;
|
||||||
import ru.nanit.limbo.configuration.LimboConfig;
|
import ua.nanit.limbo.configuration.LimboConfig;
|
||||||
import ru.nanit.limbo.connection.ClientChannelInitializer;
|
import ua.nanit.limbo.connection.ClientChannelInitializer;
|
||||||
import ru.nanit.limbo.connection.ClientConnection;
|
import ua.nanit.limbo.connection.ClientConnection;
|
||||||
import ru.nanit.limbo.connection.PacketHandler;
|
import ua.nanit.limbo.connection.PacketHandler;
|
||||||
import ru.nanit.limbo.connection.PacketSnapshots;
|
import ua.nanit.limbo.connection.PacketSnapshots;
|
||||||
import ru.nanit.limbo.world.dimension.DimensionRegistry;
|
import ua.nanit.limbo.world.DimensionRegistry;
|
||||||
|
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
@ -72,13 +72,14 @@ public final class LimboServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void start() throws Exception {
|
public void start() throws Exception {
|
||||||
Logger.info("Starting server...");
|
|
||||||
|
|
||||||
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED);
|
|
||||||
|
|
||||||
config = new LimboConfig(Paths.get("./"));
|
config = new LimboConfig(Paths.get("./"));
|
||||||
config.load();
|
config.load();
|
||||||
|
|
||||||
|
Log.setLevel(config.getDebugLevel());
|
||||||
|
Log.info("Starting server...");
|
||||||
|
|
||||||
|
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED);
|
||||||
|
|
||||||
packetHandler = new PacketHandler(this);
|
packetHandler = new PacketHandler(this);
|
||||||
dimensionRegistry = new DimensionRegistry(this);
|
dimensionRegistry = new DimensionRegistry(this);
|
||||||
dimensionRegistry.load(config.getDimensionType());
|
dimensionRegistry.load(config.getDimensionType());
|
||||||
@ -92,9 +93,7 @@ public final class LimboServer {
|
|||||||
|
|
||||||
Runtime.getRuntime().addShutdownHook(new Thread(this::stop, "NanoLimbo shutdown thread"));
|
Runtime.getRuntime().addShutdownHook(new Thread(this::stop, "NanoLimbo shutdown thread"));
|
||||||
|
|
||||||
Logger.info("Server started on %s", config.getAddress());
|
Log.info("Server started on %s", config.getAddress());
|
||||||
|
|
||||||
Logger.setLevel(config.getDebugLevel());
|
|
||||||
|
|
||||||
commandManager = new CommandManager();
|
commandManager = new CommandManager();
|
||||||
commandManager.registerAll(this);
|
commandManager.registerAll(this);
|
||||||
@ -110,12 +109,12 @@ public final class LimboServer {
|
|||||||
bossGroup = new EpollEventLoopGroup(config.getBossGroupSize());
|
bossGroup = new EpollEventLoopGroup(config.getBossGroupSize());
|
||||||
workerGroup = new EpollEventLoopGroup(config.getWorkerGroupSize());
|
workerGroup = new EpollEventLoopGroup(config.getWorkerGroupSize());
|
||||||
channelClass = EpollServerSocketChannel.class;
|
channelClass = EpollServerSocketChannel.class;
|
||||||
Logger.debug("Using Epoll transport type");
|
Log.debug("Using Epoll transport type");
|
||||||
} else {
|
} else {
|
||||||
bossGroup = new NioEventLoopGroup(config.getBossGroupSize());
|
bossGroup = new NioEventLoopGroup(config.getBossGroupSize());
|
||||||
workerGroup = new NioEventLoopGroup(config.getWorkerGroupSize());
|
workerGroup = new NioEventLoopGroup(config.getWorkerGroupSize());
|
||||||
channelClass = NioServerSocketChannel.class;
|
channelClass = NioServerSocketChannel.class;
|
||||||
Logger.debug("Using Java NIO transport type");
|
Log.debug("Using Java NIO transport type");
|
||||||
}
|
}
|
||||||
|
|
||||||
new ServerBootstrap()
|
new ServerBootstrap()
|
||||||
@ -132,7 +131,7 @@ public final class LimboServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void stop() {
|
private void stop() {
|
||||||
Logger.info("Stopping server...");
|
Log.info("Stopping server...");
|
||||||
|
|
||||||
if (keepAliveTask != null) {
|
if (keepAliveTask != null) {
|
||||||
keepAliveTask.cancel(true);
|
keepAliveTask.cancel(true);
|
||||||
@ -146,7 +145,7 @@ public final class LimboServer {
|
|||||||
workerGroup.shutdownGracefully();
|
workerGroup.shutdownGracefully();
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.info("Server stopped, Goodbye!");
|
Log.info("Server stopped, Goodbye!");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -15,63 +15,73 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.server;
|
package ua.nanit.limbo.server;
|
||||||
|
|
||||||
import java.time.LocalTime;
|
import ch.qos.logback.classic.Logger;
|
||||||
import java.time.format.DateTimeFormatter;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public final class Logger {
|
public final class Log {
|
||||||
|
|
||||||
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("hh:mm:ss");
|
private static final Logger LOGGER = (Logger) LoggerFactory.getLogger("Limbo");
|
||||||
private static int debugLevel = Level.INFO.getIndex();
|
private static int debugLevel = Level.INFO.getIndex();
|
||||||
|
|
||||||
private Logger() {}
|
private Log() {}
|
||||||
|
|
||||||
public static int getLevel() {
|
|
||||||
return debugLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void info(Object msg, Object... args) {
|
public static void info(Object msg, Object... args) {
|
||||||
print(Level.INFO, msg, null, args);
|
LOGGER.info(String.format(msg.toString(), args));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void debug(Object msg, Object... args) {
|
public static void debug(Object msg, Object... args) {
|
||||||
print(Level.DEBUG, msg, null, args);
|
LOGGER.debug(String.format(msg.toString(), args));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void warning(Object msg, Object... args) {
|
public static void warning(Object msg, Object... args) {
|
||||||
print(Level.WARNING, msg, null, args);
|
LOGGER.warn(String.format(msg.toString(), args));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void warning(Object msg, Throwable t, Object... args) {
|
public static void warning(Object msg, Throwable t, Object... args) {
|
||||||
print(Level.WARNING, msg, t, args);
|
LOGGER.warn(String.format(msg.toString(), args), t);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void error(Object msg, Object... args) {
|
public static void error(Object msg, Object... args) {
|
||||||
print(Level.ERROR, msg, null, args);
|
LOGGER.error(msg.toString(), args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void error(Object msg, Throwable t, Object... args) {
|
public static void error(Object msg, Throwable t, Object... args) {
|
||||||
print(Level.ERROR, msg, t, args);
|
LOGGER.error(String.format(msg.toString(), args), t);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void print(Level level, Object msg, Throwable t, Object... args) {
|
public static boolean isDebug() {
|
||||||
if (debugLevel >= level.getIndex()) {
|
return debugLevel >= Level.DEBUG.getIndex();
|
||||||
System.out.printf("%s: %s%n", getPrefix(level), String.format(msg.toString(), args));
|
|
||||||
if (t != null) t.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getPrefix(Level level) {
|
|
||||||
return String.format("[%s] [%s]", getTime(), level.getDisplay());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getTime() {
|
|
||||||
return LocalTime.now().format(FORMATTER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setLevel(int level) {
|
static void setLevel(int level) {
|
||||||
debugLevel = level;
|
debugLevel = level;
|
||||||
|
|
||||||
|
Logger logback = getRootLogger();
|
||||||
|
|
||||||
|
if (logback != null) {
|
||||||
|
logback.setLevel(convertLevel(level));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Logger getRootLogger() {
|
||||||
|
return (Logger) LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ch.qos.logback.classic.Level convertLevel(int level) {
|
||||||
|
switch (level) {
|
||||||
|
case 0:
|
||||||
|
return ch.qos.logback.classic.Level.ERROR;
|
||||||
|
case 1:
|
||||||
|
return ch.qos.logback.classic.Level.WARN;
|
||||||
|
case 2:
|
||||||
|
return ch.qos.logback.classic.Level.INFO;
|
||||||
|
case 3:
|
||||||
|
return ch.qos.logback.classic.Level.DEBUG;
|
||||||
|
default:
|
||||||
|
throw new IllegalStateException("Undefined log level: " + level);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Level {
|
public enum Level {
|
@ -1,8 +1,8 @@
|
|||||||
package ru.nanit.limbo.server.commands;
|
package ua.nanit.limbo.server.commands;
|
||||||
|
|
||||||
import ru.nanit.limbo.server.Command;
|
import ua.nanit.limbo.server.Command;
|
||||||
import ru.nanit.limbo.server.LimboServer;
|
import ua.nanit.limbo.server.LimboServer;
|
||||||
import ru.nanit.limbo.server.Logger;
|
import ua.nanit.limbo.server.Log;
|
||||||
|
|
||||||
public class CmdConn implements Command {
|
public class CmdConn implements Command {
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ public class CmdConn implements Command {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() {
|
public void execute() {
|
||||||
Logger.info("Connections: %d", server.getConnections().getCount());
|
Log.info("Connections: %d", server.getConnections().getCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -1,8 +1,8 @@
|
|||||||
package ru.nanit.limbo.server.commands;
|
package ua.nanit.limbo.server.commands;
|
||||||
|
|
||||||
import ru.nanit.limbo.server.Command;
|
import ua.nanit.limbo.server.Command;
|
||||||
import ru.nanit.limbo.server.LimboServer;
|
import ua.nanit.limbo.server.LimboServer;
|
||||||
import ru.nanit.limbo.server.Logger;
|
import ua.nanit.limbo.server.Log;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -18,10 +18,10 @@ public class CmdHelp implements Command {
|
|||||||
public void execute() {
|
public void execute() {
|
||||||
Map<String, Command> commands = server.getCommandManager().getCommands();
|
Map<String, Command> commands = server.getCommandManager().getCommands();
|
||||||
|
|
||||||
Logger.info("Available commands:");
|
Log.info("Available commands:");
|
||||||
|
|
||||||
for (Map.Entry<String, Command> entry : commands.entrySet()) {
|
for (Map.Entry<String, Command> entry : commands.entrySet()) {
|
||||||
Logger.info("%s - %s", entry.getKey(), entry.getValue().description());
|
Log.info("%s - %s", entry.getKey(), entry.getValue().description());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
package ru.nanit.limbo.server.commands;
|
package ua.nanit.limbo.server.commands;
|
||||||
|
|
||||||
import ru.nanit.limbo.server.Command;
|
import ua.nanit.limbo.server.Command;
|
||||||
import ru.nanit.limbo.server.Logger;
|
import ua.nanit.limbo.server.Log;
|
||||||
|
|
||||||
public class CmdMem implements Command {
|
public class CmdMem implements Command {
|
||||||
|
|
||||||
@ -14,11 +14,11 @@ public class CmdMem implements Command {
|
|||||||
long free = runtime.freeMemory() / mb;
|
long free = runtime.freeMemory() / mb;
|
||||||
long max = runtime.maxMemory() / mb;
|
long max = runtime.maxMemory() / mb;
|
||||||
|
|
||||||
Logger.info("Memory usage:");
|
Log.info("Memory usage:");
|
||||||
Logger.info("Used: %d MB", used);
|
Log.info("Used: %d MB", used);
|
||||||
Logger.info("Total: %d MB", total);
|
Log.info("Total: %d MB", total);
|
||||||
Logger.info("Free: %d MB", free);
|
Log.info("Free: %d MB", free);
|
||||||
Logger.info("Max: %d MB", max);
|
Log.info("Max: %d MB", max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -1,6 +1,6 @@
|
|||||||
package ru.nanit.limbo.server.commands;
|
package ua.nanit.limbo.server.commands;
|
||||||
|
|
||||||
import ru.nanit.limbo.server.Command;
|
import ua.nanit.limbo.server.Command;
|
||||||
|
|
||||||
public class CmdStop implements Command {
|
public class CmdStop implements Command {
|
||||||
|
|
18
src/main/java/ua/nanit/limbo/server/commands/CmdVersion.java
Normal file
18
src/main/java/ua/nanit/limbo/server/commands/CmdVersion.java
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package ua.nanit.limbo.server.commands;
|
||||||
|
|
||||||
|
import ua.nanit.limbo.server.Command;
|
||||||
|
import ua.nanit.limbo.server.Log;
|
||||||
|
import ua.nanit.limbo.BuildConfig;
|
||||||
|
|
||||||
|
public class CmdVersion implements Command {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() {
|
||||||
|
Log.info("Version: %s", BuildConfig.LIMBO_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String description() {
|
||||||
|
return "Display limbo version";
|
||||||
|
}
|
||||||
|
}
|
@ -15,24 +15,26 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.server.data;
|
package ua.nanit.limbo.server.data;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.spongepowered.configurate.ConfigurationNode;
|
import org.spongepowered.configurate.ConfigurationNode;
|
||||||
import org.spongepowered.configurate.serialize.SerializationException;
|
import org.spongepowered.configurate.serialize.SerializationException;
|
||||||
import org.spongepowered.configurate.serialize.TypeSerializer;
|
import org.spongepowered.configurate.serialize.TypeSerializer;
|
||||||
import ru.nanit.limbo.util.Colors;
|
import ua.nanit.limbo.protocol.NbtMessage;
|
||||||
|
import ua.nanit.limbo.util.Colors;
|
||||||
|
import ua.nanit.limbo.util.NbtMessageUtil;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
public class BossBar {
|
public class BossBar {
|
||||||
|
|
||||||
private String text;
|
private NbtMessage text;
|
||||||
private float health;
|
private float health;
|
||||||
private Color color;
|
private Color color;
|
||||||
private Division division;
|
private Division division;
|
||||||
|
|
||||||
public String getText() {
|
public NbtMessage getText() {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +50,7 @@ public class BossBar {
|
|||||||
return division;
|
return division;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setText(String text) {
|
public void setText(NbtMessage text) {
|
||||||
this.text = text;
|
this.text = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +112,7 @@ public class BossBar {
|
|||||||
public BossBar deserialize(Type type, ConfigurationNode node) throws SerializationException {
|
public BossBar deserialize(Type type, ConfigurationNode node) throws SerializationException {
|
||||||
BossBar bossBar = new BossBar();
|
BossBar bossBar = new BossBar();
|
||||||
|
|
||||||
bossBar.setText(Colors.of(node.node("text").getString("")));
|
bossBar.setText(NbtMessageUtil.create(Colors.of(node.node("text").getString(""))));
|
||||||
bossBar.setHealth(node.node("health").getFloat());
|
bossBar.setHealth(node.node("health").getFloat());
|
||||||
|
|
||||||
if (bossBar.getHealth() < 0 || bossBar.getHealth() > 1)
|
if (bossBar.getHealth() < 0 || bossBar.getHealth() > 1)
|
@ -15,7 +15,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.server.data;
|
package ua.nanit.limbo.server.data;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.spongepowered.configurate.ConfigurationNode;
|
import org.spongepowered.configurate.ConfigurationNode;
|
@ -15,12 +15,12 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.server.data;
|
package ua.nanit.limbo.server.data;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.spongepowered.configurate.ConfigurationNode;
|
import org.spongepowered.configurate.ConfigurationNode;
|
||||||
import org.spongepowered.configurate.serialize.TypeSerializer;
|
import org.spongepowered.configurate.serialize.TypeSerializer;
|
||||||
import ru.nanit.limbo.util.Colors;
|
import ua.nanit.limbo.util.Colors;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
@ -28,6 +28,7 @@ public class PingData {
|
|||||||
|
|
||||||
private String version;
|
private String version;
|
||||||
private String description;
|
private String description;
|
||||||
|
private int protocol;
|
||||||
|
|
||||||
public String getVersion() {
|
public String getVersion() {
|
||||||
return version;
|
return version;
|
||||||
@ -45,6 +46,14 @@ public class PingData {
|
|||||||
this.description = description;
|
this.description = description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getProtocol() {
|
||||||
|
return protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProtocol(int protocol) {
|
||||||
|
this.protocol = protocol;
|
||||||
|
}
|
||||||
|
|
||||||
public static class Serializer implements TypeSerializer<PingData> {
|
public static class Serializer implements TypeSerializer<PingData> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -52,6 +61,7 @@ public class PingData {
|
|||||||
PingData pingData = new PingData();
|
PingData pingData = new PingData();
|
||||||
pingData.setDescription(Colors.of(node.node("description").getString("")));
|
pingData.setDescription(Colors.of(node.node("description").getString("")));
|
||||||
pingData.setVersion(Colors.of(node.node("version").getString("")));
|
pingData.setVersion(Colors.of(node.node("version").getString("")));
|
||||||
|
pingData.setProtocol(node.node("protocol").getInt(-1));
|
||||||
return pingData;
|
return pingData;
|
||||||
}
|
}
|
||||||
|
|
@ -15,28 +15,30 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.server.data;
|
package ua.nanit.limbo.server.data;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.spongepowered.configurate.ConfigurationNode;
|
import org.spongepowered.configurate.ConfigurationNode;
|
||||||
import org.spongepowered.configurate.serialize.TypeSerializer;
|
import org.spongepowered.configurate.serialize.TypeSerializer;
|
||||||
import ru.nanit.limbo.util.Colors;
|
import ua.nanit.limbo.protocol.NbtMessage;
|
||||||
|
import ua.nanit.limbo.util.Colors;
|
||||||
|
import ua.nanit.limbo.util.NbtMessageUtil;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
public class Title {
|
public class Title {
|
||||||
|
|
||||||
private String title;
|
private NbtMessage title;
|
||||||
private String subtitle;
|
private NbtMessage subtitle;
|
||||||
private int fadeIn;
|
private int fadeIn;
|
||||||
private int stay;
|
private int stay;
|
||||||
private int fadeOut;
|
private int fadeOut;
|
||||||
|
|
||||||
public String getTitle() {
|
public NbtMessage getTitle() {
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSubtitle() {
|
public NbtMessage getSubtitle() {
|
||||||
return subtitle;
|
return subtitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,11 +54,11 @@ public class Title {
|
|||||||
return fadeOut;
|
return fadeOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTitle(String title) {
|
public void setTitle(NbtMessage title) {
|
||||||
this.title = title;
|
this.title = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSubtitle(String subtitle) {
|
public void setSubtitle(NbtMessage subtitle) {
|
||||||
this.subtitle = subtitle;
|
this.subtitle = subtitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,8 +79,8 @@ public class Title {
|
|||||||
@Override
|
@Override
|
||||||
public Title deserialize(Type type, ConfigurationNode node) {
|
public Title deserialize(Type type, ConfigurationNode node) {
|
||||||
Title title = new Title();
|
Title title = new Title();
|
||||||
title.setTitle(Colors.of(node.node("title").getString("")));
|
title.setTitle(NbtMessageUtil.create(Colors.of(node.node("title").getString(""))));
|
||||||
title.setSubtitle(Colors.of(node.node("subtitle").getString("")));
|
title.setSubtitle(NbtMessageUtil.create(Colors.of(node.node("subtitle").getString(""))));
|
||||||
title.setFadeIn(node.node("fadeIn").getInt(10));
|
title.setFadeIn(node.node("fadeIn").getInt(10));
|
||||||
title.setStay(node.node("stay").getInt(100));
|
title.setStay(node.node("stay").getInt(100));
|
||||||
title.setFadeOut(node.node("fadeOut").getInt(10));
|
title.setFadeOut(node.node("fadeOut").getInt(10));
|
@ -15,7 +15,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.util;
|
package ua.nanit.limbo.util;
|
||||||
|
|
||||||
public final class Colors {
|
public final class Colors {
|
||||||
|
|
110
src/main/java/ua/nanit/limbo/util/NbtMessageUtil.java
Normal file
110
src/main/java/ua/nanit/limbo/util/NbtMessageUtil.java
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
package ua.nanit.limbo.util;
|
||||||
|
|
||||||
|
import com.google.gson.*;
|
||||||
|
import net.kyori.adventure.nbt.*;
|
||||||
|
import ua.nanit.limbo.protocol.NbtMessage;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class NbtMessageUtil {
|
||||||
|
|
||||||
|
public static NbtMessage create(String json) {
|
||||||
|
BinaryTag compoundBinaryTag = fromJson(JsonParser.parseString(json));
|
||||||
|
|
||||||
|
return new NbtMessage(json, compoundBinaryTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BinaryTag fromJson(JsonElement json) {
|
||||||
|
if (json instanceof JsonPrimitive) {
|
||||||
|
JsonPrimitive jsonPrimitive = (JsonPrimitive) json;
|
||||||
|
if (jsonPrimitive.isNumber()) {
|
||||||
|
Number number = json.getAsNumber();
|
||||||
|
|
||||||
|
if (number instanceof Byte) {
|
||||||
|
return ByteBinaryTag.byteBinaryTag((Byte) number);
|
||||||
|
} else if (number instanceof Short) {
|
||||||
|
return ShortBinaryTag.shortBinaryTag((Short) number);
|
||||||
|
} else if (number instanceof Integer) {
|
||||||
|
return IntBinaryTag.intBinaryTag((Integer) number);
|
||||||
|
} else if (number instanceof Long) {
|
||||||
|
return LongBinaryTag.longBinaryTag((Long) number);
|
||||||
|
} else if (number instanceof Float) {
|
||||||
|
return FloatBinaryTag.floatBinaryTag((Float) number);
|
||||||
|
} else if (number instanceof Double) {
|
||||||
|
return DoubleBinaryTag.doubleBinaryTag((Double) number);
|
||||||
|
}
|
||||||
|
} else if (jsonPrimitive.isString()) {
|
||||||
|
return StringBinaryTag.stringBinaryTag(jsonPrimitive.getAsString());
|
||||||
|
} else if (jsonPrimitive.isBoolean()) {
|
||||||
|
return ByteBinaryTag.byteBinaryTag(jsonPrimitive.getAsBoolean() ? (byte) 1 : (byte) 0);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Unknown JSON primitive: " + jsonPrimitive);
|
||||||
|
}
|
||||||
|
} else if (json instanceof JsonObject) {
|
||||||
|
CompoundBinaryTag.Builder builder = CompoundBinaryTag.builder();
|
||||||
|
for (Map.Entry<String, JsonElement> property : ((JsonObject) json).entrySet()) {
|
||||||
|
builder.put(property.getKey(), fromJson(property.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
} else if (json instanceof JsonArray) {
|
||||||
|
List<JsonElement> jsonArray = ((JsonArray) json).asList();
|
||||||
|
|
||||||
|
if (jsonArray.isEmpty()) {
|
||||||
|
return ListBinaryTag.listBinaryTag(EndBinaryTag.endBinaryTag().type(), Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
BinaryTagType tagByteType = ByteBinaryTag.ZERO.type();
|
||||||
|
BinaryTagType tagIntType = IntBinaryTag.intBinaryTag(0).type();
|
||||||
|
BinaryTagType tagLongType = LongBinaryTag.longBinaryTag(0).type();
|
||||||
|
|
||||||
|
BinaryTag listTag;
|
||||||
|
BinaryTagType listType = fromJson(jsonArray.get(0)).type();
|
||||||
|
if (listType.equals(tagByteType)) {
|
||||||
|
byte[] bytes = new byte[jsonArray.size()];
|
||||||
|
for (int i = 0; i < bytes.length; i++) {
|
||||||
|
bytes[i] = (Byte) ((JsonPrimitive) jsonArray.get(i)).getAsNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
listTag = ByteArrayBinaryTag.byteArrayBinaryTag(bytes);
|
||||||
|
} else if (listType.equals(tagIntType)) {
|
||||||
|
int[] ints = new int[jsonArray.size()];
|
||||||
|
for (int i = 0; i < ints.length; i++) {
|
||||||
|
ints[i] = (Integer) ((JsonPrimitive) jsonArray.get(i)).getAsNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
listTag = IntArrayBinaryTag.intArrayBinaryTag(ints);
|
||||||
|
} else if (listType.equals(tagLongType)) {
|
||||||
|
long[] longs = new long[jsonArray.size()];
|
||||||
|
for (int i = 0; i < longs.length; i++) {
|
||||||
|
longs[i] = (Long) ((JsonPrimitive) jsonArray.get(i)).getAsNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
listTag = LongArrayBinaryTag.longArrayBinaryTag(longs);
|
||||||
|
} else {
|
||||||
|
List<BinaryTag> tagItems = new ArrayList<>(jsonArray.size());
|
||||||
|
|
||||||
|
for (JsonElement jsonEl : jsonArray) {
|
||||||
|
BinaryTag subTag = fromJson(jsonEl);
|
||||||
|
if (subTag.type() != listType) {
|
||||||
|
throw new IllegalArgumentException("Cannot convert mixed JsonArray to Tag");
|
||||||
|
}
|
||||||
|
|
||||||
|
tagItems.add(subTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
listTag = ListBinaryTag.listBinaryTag(listType, tagItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
return listTag;
|
||||||
|
} else if (json instanceof JsonNull) {
|
||||||
|
return EndBinaryTag.endBinaryTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalArgumentException("Unknown JSON element: " + json);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -15,7 +15,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.util;
|
package ua.nanit.limbo.util;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
@ -15,7 +15,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.world.dimension;
|
package ua.nanit.limbo.world;
|
||||||
|
|
||||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
|
|
@ -15,13 +15,13 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.nanit.limbo.world.dimension;
|
package ua.nanit.limbo.world;
|
||||||
|
|
||||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.kyori.adventure.nbt.ListBinaryTag;
|
import net.kyori.adventure.nbt.ListBinaryTag;
|
||||||
import net.kyori.adventure.nbt.TagStringIO;
|
import net.kyori.adventure.nbt.TagStringIO;
|
||||||
import ru.nanit.limbo.server.LimboServer;
|
import ua.nanit.limbo.server.LimboServer;
|
||||||
import ru.nanit.limbo.server.Logger;
|
import ua.nanit.limbo.server.Log;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
@ -33,10 +33,16 @@ public final class DimensionRegistry {
|
|||||||
|
|
||||||
private Dimension defaultDimension_1_16;
|
private Dimension defaultDimension_1_16;
|
||||||
private Dimension defaultDimension_1_18_2;
|
private Dimension defaultDimension_1_18_2;
|
||||||
|
private Dimension dimension_1_20_5;
|
||||||
|
private Dimension dimension_1_21;
|
||||||
|
|
||||||
private CompoundBinaryTag codec_1_16;
|
private CompoundBinaryTag codec_1_16;
|
||||||
private CompoundBinaryTag codec_1_18_2;
|
private CompoundBinaryTag codec_1_18_2;
|
||||||
private CompoundBinaryTag codec_1_19;
|
private CompoundBinaryTag codec_1_19;
|
||||||
|
private CompoundBinaryTag codec_1_19_1;
|
||||||
|
private CompoundBinaryTag codec_1_19_4;
|
||||||
|
private CompoundBinaryTag codec_1_20;
|
||||||
|
private CompoundBinaryTag codec_1_21;
|
||||||
private CompoundBinaryTag oldCodec;
|
private CompoundBinaryTag oldCodec;
|
||||||
|
|
||||||
public DimensionRegistry(LimboServer server) {
|
public DimensionRegistry(LimboServer server) {
|
||||||
@ -55,6 +61,22 @@ public final class DimensionRegistry {
|
|||||||
return codec_1_19;
|
return codec_1_19;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CompoundBinaryTag getCodec_1_19_1() {
|
||||||
|
return codec_1_19_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompoundBinaryTag getCodec_1_19_4() {
|
||||||
|
return codec_1_19_4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompoundBinaryTag getCodec_1_20() {
|
||||||
|
return codec_1_20;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompoundBinaryTag getCodec_1_21() {
|
||||||
|
return codec_1_21;
|
||||||
|
}
|
||||||
|
|
||||||
public CompoundBinaryTag getOldCodec() {
|
public CompoundBinaryTag getOldCodec() {
|
||||||
return oldCodec;
|
return oldCodec;
|
||||||
}
|
}
|
||||||
@ -67,15 +89,30 @@ public final class DimensionRegistry {
|
|||||||
return defaultDimension_1_18_2;
|
return defaultDimension_1_18_2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Dimension getDimension_1_20_5() {
|
||||||
|
return dimension_1_20_5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dimension getDimension_1_21() {
|
||||||
|
return dimension_1_21;
|
||||||
|
}
|
||||||
|
|
||||||
public void load(String def) throws IOException {
|
public void load(String def) throws IOException {
|
||||||
|
// On 1.16-1.16.1 different codec format
|
||||||
|
oldCodec = readCodecFile("/dimension/codec_old.snbt");
|
||||||
codec_1_16 = readCodecFile("/dimension/codec_1_16.snbt");
|
codec_1_16 = readCodecFile("/dimension/codec_1_16.snbt");
|
||||||
codec_1_18_2 = readCodecFile("/dimension/codec_1_18_2.snbt");
|
codec_1_18_2 = readCodecFile("/dimension/codec_1_18_2.snbt");
|
||||||
codec_1_19 = readCodecFile("/dimension/codec_1_19.snbt");
|
codec_1_19 = readCodecFile("/dimension/codec_1_19.snbt");
|
||||||
// On 1.16-1.16.1 different codec format
|
codec_1_19_1 = readCodecFile("/dimension/codec_1_19_1.snbt");
|
||||||
oldCodec = readCodecFile("/dimension/codec_old.snbt");
|
codec_1_19_4 = readCodecFile("/dimension/codec_1_19_4.snbt");
|
||||||
|
codec_1_20 = readCodecFile("/dimension/codec_1_20.snbt");
|
||||||
|
codec_1_21 = readCodecFile("/dimension/codec_1_21.snbt");
|
||||||
|
|
||||||
defaultDimension_1_16 = getDefaultDimension(def, codec_1_16);
|
defaultDimension_1_16 = getDefaultDimension(def, codec_1_16);
|
||||||
defaultDimension_1_18_2 = getDefaultDimension(def, codec_1_18_2);
|
defaultDimension_1_18_2 = getDefaultDimension(def, codec_1_18_2);
|
||||||
|
|
||||||
|
dimension_1_20_5 = getModernDimension(def, codec_1_20);
|
||||||
|
dimension_1_21 = getModernDimension(def, codec_1_21);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dimension getDefaultDimension(String def, CompoundBinaryTag tag) {
|
private Dimension getDefaultDimension(String def, CompoundBinaryTag tag) {
|
||||||
@ -93,29 +130,37 @@ public final class DimensionRegistry {
|
|||||||
case "the_end":
|
case "the_end":
|
||||||
return new Dimension(1, "minecraft:the_end", theEnd);
|
return new Dimension(1, "minecraft:the_end", theEnd);
|
||||||
default:
|
default:
|
||||||
Logger.warning("Undefined dimension type: '%s'. Using THE_END as default", def);
|
Log.warning("Undefined dimension type: '%s'. Using THE_END as default", def);
|
||||||
return new Dimension(1, "minecraft:the_end", theEnd);
|
return new Dimension(1, "minecraft:the_end", theEnd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Dimension getModernDimension(String def, CompoundBinaryTag tag) {
|
||||||
|
switch (def.toLowerCase()) {
|
||||||
|
case "overworld":
|
||||||
|
return new Dimension(0, "minecraft:overworld", tag);
|
||||||
|
case "the_nether":
|
||||||
|
return new Dimension(2, "minecraft:nether", tag);
|
||||||
|
case "the_end":
|
||||||
|
return new Dimension(3, "minecraft:the_end", tag);
|
||||||
|
default:
|
||||||
|
Log.warning("Undefined dimension type: '%s'. Using THE_END as default", def);
|
||||||
|
return new Dimension(3, "minecraft:the_end", tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private CompoundBinaryTag readCodecFile(String resPath) throws IOException {
|
private CompoundBinaryTag readCodecFile(String resPath) throws IOException {
|
||||||
InputStream in = server.getClass().getResourceAsStream(resPath);
|
InputStream in = server.getClass().getResourceAsStream(resPath);
|
||||||
|
|
||||||
if(in == null)
|
if (in == null)
|
||||||
throw new FileNotFoundException("Cannot find dimension registry file");
|
throw new FileNotFoundException("Cannot find dimension registry file");
|
||||||
|
|
||||||
return TagStringIO.get().asCompound(streamToString(in));
|
return TagStringIO.get().asCompound(streamToString(in));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String streamToString(InputStream in) throws IOException {
|
private String streamToString(InputStream in) throws IOException {
|
||||||
InputStreamReader isReader = new InputStreamReader(in, StandardCharsets.UTF_8);
|
try (BufferedReader bufReader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
|
||||||
BufferedReader bufReader = new BufferedReader(isReader);
|
return bufReader.lines().collect(Collectors.joining("\n"));
|
||||||
String content = bufReader.lines()
|
}
|
||||||
.collect(Collectors.joining("\n"));
|
|
||||||
|
|
||||||
isReader.close();
|
|
||||||
bufReader.close();
|
|
||||||
|
|
||||||
return content;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
2286
src/main/resources/dimension/codec_1_19_1.snbt
Normal file
2286
src/main/resources/dimension/codec_1_19_1.snbt
Normal file
File diff suppressed because it is too large
Load Diff
2760
src/main/resources/dimension/codec_1_19_4.snbt
Normal file
2760
src/main/resources/dimension/codec_1_19_4.snbt
Normal file
File diff suppressed because it is too large
Load Diff
2778
src/main/resources/dimension/codec_1_20.snbt
Normal file
2778
src/main/resources/dimension/codec_1_20.snbt
Normal file
File diff suppressed because it is too large
Load Diff
2816
src/main/resources/dimension/codec_1_21.snbt
Normal file
2816
src/main/resources/dimension/codec_1_21.snbt
Normal file
File diff suppressed because it is too large
Load Diff
30
src/main/resources/logback.xml
Normal file
30
src/main/resources/logback.xml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE configuration>
|
||||||
|
|
||||||
|
<configuration>
|
||||||
|
<import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
|
||||||
|
<import class="ch.qos.logback.core.ConsoleAppender"/>
|
||||||
|
<import class="ch.qos.logback.core.FileAppender"/>
|
||||||
|
|
||||||
|
<timestamp key="bySecond" datePattern="yyyy-MM-dd"/>
|
||||||
|
|
||||||
|
<appender name="STDOUT" class="ConsoleAppender">
|
||||||
|
<encoder class="PatternLayoutEncoder">
|
||||||
|
<pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} -%kvp- %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="FILE" class="FileAppender">
|
||||||
|
<file>logs/log-${bySecond}.txt</file>
|
||||||
|
<immediateFlush>true</immediateFlush>
|
||||||
|
|
||||||
|
<encoder class="PatternLayoutEncoder">
|
||||||
|
<pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} -%kvp- %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root level="info">
|
||||||
|
<appender-ref ref="FILE"/>
|
||||||
|
<appender-ref ref="STDOUT"/>
|
||||||
|
</root>
|
||||||
|
</configuration>
|
@ -7,7 +7,7 @@ bind:
|
|||||||
ip: 'localhost'
|
ip: 'localhost'
|
||||||
port: 65535
|
port: 65535
|
||||||
|
|
||||||
# Max amount of players can join to server
|
# Max number of players can join to server
|
||||||
# Set -1 to make it infinite
|
# Set -1 to make it infinite
|
||||||
maxPlayers: 100
|
maxPlayers: 100
|
||||||
|
|
||||||
@ -15,49 +15,48 @@ maxPlayers: 100
|
|||||||
ping:
|
ping:
|
||||||
description: '{"text": "&9NanoLimbo"}'
|
description: '{"text": "&9NanoLimbo"}'
|
||||||
version: 'NanoLimbo'
|
version: 'NanoLimbo'
|
||||||
|
# Return static protocol version number in ping result
|
||||||
|
# By default, its -1 to return the client version if it supported
|
||||||
|
# https://wiki.vg/Protocol_version_numbers
|
||||||
|
protocol: -1
|
||||||
|
|
||||||
# Available dimensions: OVERWORLD, NETHER, THE_END
|
# Available dimensions: OVERWORLD, NETHER, THE_END
|
||||||
dimension: THE_END
|
dimension: THE_END
|
||||||
|
|
||||||
# Whether to display the player in the player list
|
# Whether to display the player in the player list
|
||||||
# For 1.16.5 clients player list will be sent even if disabled, to avoid crash
|
# For 1.16.5 clients, the player list will be sent even if disabled, to avoid crash
|
||||||
playerList:
|
playerList:
|
||||||
enable: false
|
enable: false
|
||||||
username: 'NanoLimbo'
|
username: 'NanoLimbo'
|
||||||
|
|
||||||
# Whether to display header and footer in player list
|
# Whether to display header and footer in player list
|
||||||
|
# For 1.8+ clients
|
||||||
headerAndFooter:
|
headerAndFooter:
|
||||||
enable: false
|
enable: false
|
||||||
header: '{"text": "&eWelcome!"}'
|
header: '{"text": "&eWelcome!"}'
|
||||||
footer: '{"text": "&9NanoLimbo"}'
|
footer: '{"text": "&9NanoLimbo"}'
|
||||||
|
|
||||||
# Spawn position in the world
|
|
||||||
spawnPosition:
|
|
||||||
x: 0.0
|
|
||||||
y: 400.0
|
|
||||||
z: 0.0
|
|
||||||
yaw: 0.0
|
|
||||||
pitch: 0.0
|
|
||||||
|
|
||||||
# Setup player's game mode
|
# Setup player's game mode
|
||||||
# 0 - Survival
|
# 0 - Survival
|
||||||
# 1 - Creative (hide HP and food bar)
|
# 1 - Creative (hide HP and food bar)
|
||||||
# 2 - Adventure
|
# 2 - Adventure
|
||||||
# 3 - Spectator (hide all UI bars)
|
# 3 - Spectator (hide all UI bars)
|
||||||
|
# Spectator works on 1.8+ clients
|
||||||
gameMode: 3
|
gameMode: 3
|
||||||
|
|
||||||
# Server name which is shown under F3
|
# Server name which is shown under F3
|
||||||
|
# For 1.13+ clients
|
||||||
brandName:
|
brandName:
|
||||||
enable: true
|
enable: true
|
||||||
content: 'NanoLimbo'
|
content: 'NanoLimbo'
|
||||||
|
|
||||||
# Message sends when player join to server
|
# Message sends when player joins to the server
|
||||||
joinMessage:
|
joinMessage:
|
||||||
enable: true
|
enable: true
|
||||||
text: '{"text": "&eWelcome to the Limbo!"}'
|
text: '{"text": "&eWelcome to the Limbo!"}'
|
||||||
|
|
||||||
# BossBar displays when player join to server
|
# BossBar displays when player joins to the server
|
||||||
# Works on 1.9+ clients only
|
# For 1.9+ clients
|
||||||
bossBar:
|
bossBar:
|
||||||
enable: true
|
enable: true
|
||||||
text: '{"text": "Welcome to the Limbo!"}'
|
text: '{"text": "Welcome to the Limbo!"}'
|
||||||
@ -68,6 +67,7 @@ bossBar:
|
|||||||
division: SOLID
|
division: SOLID
|
||||||
|
|
||||||
# Display title and subtitle
|
# Display title and subtitle
|
||||||
|
# For 1.8+ clients
|
||||||
title:
|
title:
|
||||||
enable: true
|
enable: true
|
||||||
# Set title text value empty, if you need only subtitle
|
# Set title text value empty, if you need only subtitle
|
||||||
@ -87,7 +87,7 @@ title:
|
|||||||
# - LEGACY
|
# - LEGACY
|
||||||
# - MODERN
|
# - MODERN
|
||||||
# - BUNGEE_GUARD
|
# - BUNGEE_GUARD
|
||||||
# Don't use secret if you not use MODERN type
|
# Don't use secret if you do not use MODERN type
|
||||||
infoForwarding:
|
infoForwarding:
|
||||||
type: NONE
|
type: NONE
|
||||||
secret: '<YOUR_SECRET_HERE>'
|
secret: '<YOUR_SECRET_HERE>'
|
||||||
@ -105,11 +105,29 @@ readTimeout: 30000
|
|||||||
# 3 - Display errors, warnings, info, debug
|
# 3 - Display errors, warnings, info, debug
|
||||||
debugLevel: 2
|
debugLevel: 2
|
||||||
|
|
||||||
# Warning! Do not touch params of this block, if you not completely sure what is this!
|
# Warning! Do not touch params of this block if you are not completely sure what is this!
|
||||||
netty:
|
netty:
|
||||||
# Use Linux native transport type, if it possible
|
# Use a Linux native transport type, if it possible
|
||||||
useEpoll: true
|
useEpoll: true
|
||||||
# EventLoopGroup threads count
|
# EventLoopGroup threads count
|
||||||
threads:
|
threads:
|
||||||
bossGroup: 1
|
bossGroup: 1
|
||||||
workerGroup: 4
|
workerGroup: 4
|
||||||
|
|
||||||
|
# Options to check incoming traffic and kick potentially malicious connections.
|
||||||
|
# Take into account that player can send many small packets, for example, just moving mouse.
|
||||||
|
traffic:
|
||||||
|
# If true, then additional handler will be added to the channel pipeline
|
||||||
|
enable: true
|
||||||
|
# Max packet size in bytes
|
||||||
|
# Unlimited if -1
|
||||||
|
maxPacketSize: 8192
|
||||||
|
# The interval to measure packets over
|
||||||
|
# Lowering this value will limit peak packets from players which would target people with bad connections
|
||||||
|
# Raising this value will allow higher peak packet rates, which will help with people who have poor connections
|
||||||
|
# Ignored if -1.0
|
||||||
|
interval: 7.0
|
||||||
|
# The maximum packets per second for players
|
||||||
|
# It is measured over the configured interval
|
||||||
|
# Ignored if -1.0
|
||||||
|
maxPacketRate: 500.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user