Skip to content
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
c3e8c28
Support 1.21.2
BoomEaro Oct 23, 2024
529b1b9
Support 1.21.4, update dependencies and minor improvements
BoomEaro Dec 9, 2024
a4b5886
Fix missing 1.21.1 display name
BoomEaro Dec 9, 2024
8ce14bf
Add github actions
BoomEaro Dec 9, 2024
ea7b15e
Fix wrong codec for 1.20.5
BoomEaro Dec 9, 2024
7ca2e4b
Support 1.21.5
BoomEaro Mar 25, 2025
b61c08d
Bump netty 4.1.119.Final
BoomEaro Mar 25, 2025
d90a6e3
Bump gradle 8.13
BoomEaro Mar 25, 2025
ad525a6
Fix typo
BoomEaro Mar 28, 2025
d0679ce
Bump 1.9
BoomEaro Mar 28, 2025
6a50f6e
Update readme
BoomEaro Mar 28, 2025
e594a38
Bump netty 4.2.0
BoomEaro Apr 5, 2025
ac2d934
Update other dependencies
BoomEaro Apr 5, 2025
c4a0cd0
Reorganize and improve registry encoding and sending
BoomEaro Apr 5, 2025
1956c0c
More correctly decode packets and add simple packet limit check
BoomEaro Apr 5, 2025
e2c68e8
Bump 1.9.1
BoomEaro Apr 5, 2025
d0b364d
More correctly write CompoundBinaryTag
BoomEaro May 31, 2025
bcf40d4
Bump gradle 8.14.1
BoomEaro May 31, 2025
7ea65dc
Bump 1.9.2
BoomEaro May 31, 2025
de85541
Fix PacketLoginStart decoding for 1.19.3 and bump 1.9.3
BoomEaro Jun 8, 2025
4a3bd7b
Support 1.21.6
BoomEaro Jun 18, 2025
9d0eb38
Bump gradle 8.14.2
BoomEaro Jun 18, 2025
3ecc20e
Update dependencies
BoomEaro Jun 18, 2025
4523dd6
Bump 1.9.4
BoomEaro Jun 18, 2025
be44eaf
Support 1.21.7
BoomEaro Jun 30, 2025
4fb7e7d
Bump 1.9.5
BoomEaro Jun 30, 2025
b4136a7
Add ability to enable secure profile
BoomEaro Jul 5, 2025
6dbcfa9
Optimize varint reading
BoomEaro Jul 5, 2025
b811784
Bump gradle 8.14.3
BoomEaro Jul 5, 2025
82b21bb
Bump 1.9.6
BoomEaro Jul 5, 2025
6a832a1
Ignore empty packets
BoomEaro Jul 20, 2025
f791bce
Bump netty 4.2.3
BoomEaro Jul 20, 2025
bc272e5
Update buildconfig and gradle shadow dependencies
BoomEaro Jul 20, 2025
4dae86d
1.21.8 has the same protocol
BoomEaro Jul 20, 2025
d1c5e1a
Bump 1.9.7
BoomEaro Jul 20, 2025
ef4e4e4
Packet Limiter - maxPacketBytesRate
Pantera07 Aug 10, 2025
823be08
Merge pull request #3 from Pantera07/packet-limiter_bps
BoomEaro Aug 16, 2025
e70ef2b
Rise minimum java version to 17 and use new java features
BoomEaro Aug 16, 2025
ea9674c
Bump gradle 9.0.0
BoomEaro Aug 16, 2025
f77a715
Update dependencies
BoomEaro Aug 16, 2025
97d28db
Remove archive classifier
BoomEaro Aug 16, 2025
bc49fbf
Update readme
BoomEaro Aug 16, 2025
e8fe64e
Bump 1.9.8
BoomEaro Aug 16, 2025
962dda0
Trim nickname to 16 characters for PacketPlayerInfo
BoomEaro Sep 12, 2025
bc48266
Update dependencies
BoomEaro Sep 12, 2025
425c8f8
Remove unused test framework
BoomEaro Sep 12, 2025
f0ce3a2
Little improve NanoLimbo build
BoomEaro Sep 12, 2025
a4a195e
Bump 1.9.9
BoomEaro Sep 12, 2025
7243601
Print current protocol state, version and packet type
BoomEaro Sep 13, 2025
0f88aaa
Add build workflow
BoomEaro Sep 13, 2025
0eb056e
Limit max username length to 16 characters and use netty's readString…
BoomEaro Sep 14, 2025
9e233af
Update README.md
BoomEaro Sep 14, 2025
24d32a9
Limit max host length name
BoomEaro Sep 14, 2025
6196e9f
Revert "Limit max host length name"
BoomEaro Sep 14, 2025
c0dc0d9
Bump gradle 9.1.0
BoomEaro Sep 23, 2025
d9c1af4
Lombok & cleanup
eliasfalch Sep 25, 2025
d81d2f3
Merge pull request #8 from eliasfalch/feature/1.21.2
BoomEaro Sep 30, 2025
b1c39db
Use a bit more lombok features
BoomEaro Sep 30, 2025
d89c09b
Support 1.21.9
BoomEaro Oct 1, 2025
8271183
Bump 1.9.10
BoomEaro Oct 1, 2025
d6c1713
Add missing copyright headers
BoomEaro Nov 29, 2025
227ef44
Update dependencies
BoomEaro Nov 29, 2025
d4dfe95
Use gson for bungee guard token parsing
BoomEaro Nov 29, 2025
38e1f4f
Migrate to kotlin dsl
BoomEaro Nov 29, 2025
5d553d0
Bump 1.10.0
BoomEaro Nov 29, 2025
3feb8fa
Just cleanup
BoomEaro Nov 29, 2025
336a43e
Fix chunks encoding
BoomEaro Nov 29, 2025
4354d62
Little cleanup
BoomEaro Nov 29, 2025
c6da1d9
Actualize readme
BoomEaro Nov 29, 2025
c8a6f64
Add support for io_uring and kqueue
BoomEaro Dec 6, 2025
1086ddf
Bump 1.10.1
BoomEaro Dec 6, 2025
5b65d83
Support for 1.21.11
BoomEaro Dec 9, 2025
7a73bf4
Bump 1.10.2
BoomEaro Dec 9, 2025
3e188a1
Update readme
BoomEaro Dec 26, 2025
376365a
Fix handshake intention handling
BoomEaro Jan 2, 2026
ea587fa
Update readme
BoomEaro Jan 2, 2026
037fb39
Update dependencies
BoomEaro Jan 2, 2026
6405ce2
Bump 1.10.3
BoomEaro Jan 2, 2026
7e38ad8
Implement full minimessage support
BoomEaro Jan 3, 2026
8f327e4
More correctly serialize config data and cleanup
BoomEaro Jan 3, 2026
ecd0cea
More correctly disable leak detector
BoomEaro Jan 3, 2026
ffbcaa9
More correctly encode login packet and little cleanup
BoomEaro Jan 3, 2026
03fa7f6
Simplify registry creation
BoomEaro Jan 3, 2026
58ead7b
Simplify update tags creation and little improve packet registry encode
BoomEaro Jan 3, 2026
fd91e43
Add missing copyright headers
BoomEaro Jan 3, 2026
82b83d3
Just little cleanup
BoomEaro Jan 3, 2026
f16ef84
Actualize velocity forwarding
BoomEaro Jan 4, 2026
71cf094
Refactor forwarding a bit
BoomEaro Jan 4, 2026
b2f7cd4
Actualize default config
BoomEaro Jan 4, 2026
a00bcb5
Update readme
BoomEaro Jan 4, 2026
15d85ee
Bump 1.11.0
BoomEaro Jan 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .github/workflows/releases.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Java CI with Gradle
on:
release:
types: [ published ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 11
uses: actions/setup-java@v4
with:
java-version: "11"
distribution: "temurin"
cache: gradle
- name: Current Java version
run: java -version
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
- name: Build with Gradle
run: gradle shadowJar
- name: Find correct JAR
id: find-jar
run: |
output="$(find build/libs/ ! -name "*-javadoc.jar" ! -name "*-sources.jar" -type f -printf "%f\n")"
echo "::set-output name=jarname::$output"
- name: Upload to the GitHub release
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: build/libs/${{ steps.find-jar.outputs.jarname }}
asset_name: ${{ steps.find-jar.outputs.jarname }}
asset_content_type: application/java-archive
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Symbol `X` means all minor versions.
- [x] 1.18.X
- [x] 1.19.X
- [x] 1.20.X
- [x] 1.21
- [x] 1.21.X

The server **doesn't** support snapshots.

Expand Down
30 changes: 17 additions & 13 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,35 +1,39 @@
plugins {
id 'java'
id 'com.github.johnrengelman.shadow' version '7.1.2'
id 'com.gradleup.shadow' version '8.3.6'
id 'com.github.gmazzo.buildconfig' version '3.1.0'
}

group 'ua.nanit'
version '1.8.1'
version '1.9.4'

compileJava {
options.encoding = "UTF-8"
}

tasks.withType(JavaCompile).configureEach {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}

repositories {
mavenCentral()
}

dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.3'
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 'io.netty:netty-all:4.1.101.Final'
implementation 'net.kyori:adventure-nbt:4.14.0'
implementation 'com.grack:nanojson:1.8'
implementation 'com.google.code.gson:gson:2.10.1'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.13.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.13.1'

implementation 'ch.qos.logback:logback-classic:1.5.18'
implementation 'org.spongepowered:configurate-yaml:4.2.0'

implementation "io.netty:netty-handler:4.2.2.Final"
implementation "io.netty:netty-transport-native-epoll:4.2.2.Final:linux-x86_64"
implementation "io.netty:netty-transport-native-epoll:4.2.2.Final:linux-aarch_64"

implementation 'net.kyori:adventure-nbt:4.22.0'
implementation 'com.grack:nanojson:1.10'
implementation 'com.google.code.gson:gson:2.13.1'
}

buildConfig {
Expand Down
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
4 changes: 3 additions & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
47 changes: 32 additions & 15 deletions gradlew
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#

##############################################################################
#
Expand Down Expand Up @@ -55,7 +57,7 @@
# 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
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
Expand All @@ -80,13 +82,11 @@ do
esac
done

APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit

APP_NAME="Gradle"
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
Expand Down Expand Up @@ -114,7 +114,7 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;;
esac

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
CLASSPATH="\\\"\\\""


# Determine the Java command to use to start the JVM.
Expand All @@ -133,22 +133,29 @@ location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi

# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
Expand Down Expand Up @@ -193,18 +200,28 @@ if "$cygwin" || "$msys" ; then
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.

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'

# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.

set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@"

# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi

# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
Expand Down
41 changes: 23 additions & 18 deletions gradlew.bat
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem

@if "%DEBUG%" == "" @echo off
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
Expand All @@ -25,7 +27,8 @@
if "%OS%"=="Windows_NT" setlocal

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

Expand All @@ -40,13 +43,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
if %ERRORLEVEL% equ 0 goto execute

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2

goto fail

Expand All @@ -56,32 +59,34 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto execute

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2

goto fail

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
set CLASSPATH=


@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%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
if %ERRORLEVEL% equ 0 goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%

:mainEnd
if "%OS%"=="Windows_NT" endlocal
Expand Down
47 changes: 37 additions & 10 deletions src/main/java/ua/nanit/limbo/connection/ClientConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import java.net.SocketAddress;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -104,7 +105,9 @@ public void channelInactive(@NotNull ChannelHandlerContext ctx) throws Exception
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
if (channel.isActive()) {
Log.error("Unhandled exception: ", cause);
Log.error("Encountered exception", cause);

ctx.close();
}
}

Expand Down Expand Up @@ -179,9 +182,7 @@ public void spawnPlayer() {
if (clientVersion.moreOrEqual(Version.V1_20_3)) {
writePacket(PacketSnapshots.PACKET_START_WAITING_CHUNKS);

for (PacketSnapshot chunk : PacketSnapshots.PACKETS_EMPTY_CHUNKS) {
writePacket(chunk);
}
writePackets(PacketSnapshots.PACKETS_EMPTY_CHUNKS);
}

sendKeepAlive();
Expand All @@ -197,20 +198,46 @@ public void spawnPlayer() {
public void onLoginAcknowledgedReceived() {
updateState(State.CONFIGURATION);

if (PacketSnapshots.PACKET_PLUGIN_MESSAGE != null)
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_KNOWN_PACKS);
return;
}

writePacket(PacketSnapshots.PACKET_REGISTRY_DATA);

sendPacket(PacketSnapshots.PACKET_FINISH_CONFIGURATION);
}

public void onKnownPacksReceived() {
if (clientVersion.moreOrEqual(Version.V1_21_6)) {
writePackets(PacketSnapshots.PACKETS_REGISTRY_DATA_1_21_6);
} else if (clientVersion.moreOrEqual(Version.V1_21_5)) {
writePackets(PacketSnapshots.PACKETS_REGISTRY_DATA_1_21_5);
} else if (clientVersion.moreOrEqual(Version.V1_21_4)) {
writePackets(PacketSnapshots.PACKETS_REGISTRY_DATA_1_21_4);
} else if (clientVersion.moreOrEqual(Version.V1_21_2)) {
writePackets(PacketSnapshots.PACKETS_REGISTRY_DATA_1_21_2);
} else if (clientVersion.moreOrEqual(Version.V1_21)) {
writePackets(PacketSnapshots.PACKETS_REGISTRY_DATA_1_21);
} else if (clientVersion.moreOrEqual(Version.V1_20_5)) {
writePackets(PacketSnapshots.PACKETS_REGISTRY_DATA_1_20_5);
}

writePacket(PacketSnapshots.PACKET_UPDATE_TAGS);

sendPacket(PacketSnapshots.PACKET_FINISH_CONFIGURATION);
}

private void writePackets(List<PacketSnapshot> packets) {
for (PacketSnapshot packet : packets) {
writePacket(packet);
}
}

public void disconnectLogin(String reason) {
if (isConnected() && state == State.LOGIN) {
PacketDisconnect disconnect = new PacketDisconnect();
Expand Down
Loading