Compare commits

..
39 Commits
Author SHA1 Message Date
dependabot[bot] 32f3cc51b1 Bump gradle-wrapper from 9.8.1 to 9.8.2 (#650)
Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 9.8.1 to 9.8.2.
- [Release notes](https://github.com/gradle/gradle/releases)
- [Commits](https://github.com/gradle/gradle/compare/v9.8.1...v9.8.2)

---
updated-dependencies:
- dependency-name: gradle-wrapper
  dependency-version: 9.8.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-27 14:57:56 +01:00
Akkariin 76dc4f0232 fix(protocol): correct PlayerInputPacket ID on 26.1+ to fix F3+3 disconnect (#648) (#649)
In Minecraft 26.1, 26.2, and 26.3, ServerboundPlayerInputPacket is registered
at packet ID 0x2B, while 0x26 is ServerboundPingRequestPacket.

Previously, PlayerInputPacket was incorrectly mapped to 0x26 for MINECRAFT_26_1.
When a client joined with the F3+3 network chart open or toggled F3+3 during
verification, the client sent ServerboundPingRequestPacket (0x26, 8 bytes).
Sonar attempted to decode it as PlayerInputPacket (which only reads 1 byte in
1.21.2+), leaving 7 unread bytes. SonarPacketDecoder threw QuietDecoderException,
causing TailExceptionsHandler to silently close the channel, resulting in a client
disconnection with 'Disconnected' without any server-side stack trace.

This commit updates PlayerInputPacket's ID on 26.1+ to 0x2B, allowing PingRequest
(0x26) to be safely ignored by SonarPacketDecoder.
2026-10-25 17:57:46 +01:00
Jones 3497cb116c chore(release): bump version to 2.1.53 (#646) 2026-10-17 18:31:48 +02:00
Jones 4d491531bb feat(captcha): increase generation randomness 2026-10-17 18:27:38 +02:00
FeGmbHandJones 7b2d2db614 Remove adventure-platform to prevent Adventure 4.x/5.x class conflict (#642)
* Remove adventure platform dependencies

Removed adventure-platform-bukkit and adventure-platform-bungee dependencies.

* fix(bungee): remove adventure-platform to prevent Adventure 4.x/5.x class conflict

* fix(bukkit): restore missing adventure-platform-bukkit catalog entry

* Remove adventure-platform-bukkit dependency

Removed adventure-platform-bukkit dependency from libs.versions.toml

* Readd adventure-platform-bukkit dependency

* Update copyright year and refactor action bar method

Updated copyright year from 2025 to 2026 and refactored action bar message sending as commented by @jonesdevelopment

* Refactor title code as commented

* I forgot a closing bracket :(

* Change LibraryLoader to public class with state management

Refactor LibraryLoader to a public class and add loaded state management.

* Update copyright year and load libraries earlier

* Add imports for BungeeLibraryManager and SonarPlatform

* Avoid double library loading without tracking state

* Invert BungeeAudience#showTitle player check

* Now makes use of Java 17+ features

* Avoid storing extra 1.16 protocol version ID

---------

Co-authored-by: Jones <admin@jonesdev.xyz>
2026-10-13 13:45:41 +02:00
dependabot[bot] 4547b1632d Bump com.diffplug.spotless from 8.10.3 to 8.10.4 (#643)
Bumps [com.diffplug.spotless](https://github.com/diffplug/spotless) from 8.10.3 to 8.10.4.
- [Release notes](https://github.com/diffplug/spotless/releases)
- [Changelog](https://github.com/diffplug/spotless/blob/main/CHANGES.md)
- [Commits](https://github.com/diffplug/spotless/compare/gradle/8.10.3...gradle/8.10.4)

---
updated-dependencies:
- dependency-name: com.diffplug.spotless
  dependency-version: 8.10.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-12 14:18:31 +02:00
dependabot[bot] 943872ed62 Bump io.netty:netty-all from 4.2.18.Final to 4.2.19.Final (#645)
Bumps [io.netty:netty-all](https://github.com/netty/netty) from 4.2.18.Final to 4.2.19.Final.
- [Release notes](https://github.com/netty/netty/releases)
- [Commits](https://github.com/netty/netty/compare/netty-4.2.18.Final...netty-4.2.19.Final)

---
updated-dependencies:
- dependency-name: io.netty:netty-all
  dependency-version: 4.2.19.Final
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-12 14:18:14 +02:00
dependabot[bot] f1239a7412 Bump gradle-wrapper from 9.8.0 to 9.8.1 (#644)
Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 9.8.0 to 9.8.1.
- [Release notes](https://github.com/gradle/gradle/releases)
- [Commits](https://github.com/gradle/gradle/compare/v9.8.0...v9.8.1)

---
updated-dependencies:
- dependency-name: gradle-wrapper
  dependency-version: 9.8.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-12 14:18:12 +02:00
dependabot[bot] 1794a2f24e Bump com.diffplug.spotless from 8.10.2 to 8.10.3 (#640)
Bumps [com.diffplug.spotless](https://github.com/diffplug/spotless) from 8.10.2 to 8.10.3.
- [Release notes](https://github.com/diffplug/spotless/releases)
- [Changelog](https://github.com/diffplug/spotless/blob/main/CHANGES.md)
- [Commits](https://github.com/diffplug/spotless/compare/gradle/8.10.2...gradle/8.10.3)

---
updated-dependencies:
- dependency-name: com.diffplug.spotless
  dependency-version: 8.10.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-05 16:13:47 +02:00
dependabot[bot] 18f40fea3e Bump gradle-wrapper from 9.7.1 to 9.8.0 (#638)
Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 9.7.1 to 9.8.0.
- [Release notes](https://github.com/gradle/gradle/releases)
- [Commits](https://github.com/gradle/gradle/compare/v9.7.1...v9.8.0)

---
updated-dependencies:
- dependency-name: gradle-wrapper
  dependency-version: 9.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-28 21:57:19 +02:00
Jones cf865978b4 Release 2.1.52 (#637) 2026-09-27 15:40:37 +02:00
Akkariin eccfb26b30 26.3 Support (#635)
* 26.3 Support

* Add 26.3 protocol version (777)
* Add 26.3 runtime codec and tags
* Update block state IDs for 26.3
* Update item and entity IDs for 26.3
* Update packet registry mappings for 26.3
* Update ConfirmTeleportationPacket, AnimationPacket, EntityAnimationPacket, and JoinGamePacket for 26.3 wire format changes

* Fix non-compound element serialization in RegistryDataPacket

In 26.3, registry entries such as minecraft:block_transformer use ListTag rather than CompoundTag for their element data. Allow any BinaryTag in RegistryDataPacket to prevent empty compound tags from being sent to clients.

* [ci skip] Fix gamemode and previousGamemode encoding in JoinGamePacket for 26.3+

Minecraft 26.3 uses GameType.STREAM_CODEC (VarInt) for gameType and GameType.OPTIONAL_STREAM_CODEC (Optional VarInt where 0 represents none) for previousGameType in CommonPlayerSpawnInfo. Writing previousGamemode as a raw byte (-1 / 0xFF) caused VarInt decoding to consume extra bytes and desynchronize subsequent packet fields.

* Adapt GravityHandler teleport confirmation and movement checks for 26.3+

* Bypass swing arm check in ProtocolHandler for 26.3+

* [ci skip] update annotate for `canFall` field in `GravityHandler`
2026-09-20 13:41:32 +02:00
Jones edf57c280b [skip ci] Update dead wiki.vg link in README 2026-09-15 13:29:29 +02:00
dependabot[bot] 81776712c0 Bump io.netty:netty-all from 4.2.17.Final to 4.2.18.Final (#633)
Bumps [io.netty:netty-all](https://github.com/netty/netty) from 4.2.17.Final to 4.2.18.Final.
- [Release notes](https://github.com/netty/netty/releases)
- [Commits](https://github.com/netty/netty/compare/netty-4.2.17.Final...netty-4.2.18.Final)

---
updated-dependencies:
- dependency-name: io.netty:netty-all
  dependency-version: 4.2.18.Final
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-14 11:54:41 +02:00
dependabot[bot] acc3d0df3a Bump com.diffplug.spotless from 8.10.1 to 8.10.2 (#634)
Bumps com.diffplug.spotless from 8.10.1 to 8.10.2.

---
updated-dependencies:
- dependency-name: com.diffplug.spotless
  dependency-version: 8.10.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-14 11:54:34 +02:00
dependabot[bot] aafb2a22fe Bump org.projectlombok:lombok from 1.18.46 to 1.18.48 (#632)
Bumps [org.projectlombok:lombok](https://github.com/projectlombok/lombok) from 1.18.46 to 1.18.48.
- [Changelog](https://github.com/projectlombok/lombok/blob/master/doc/changelog.markdown)
- [Commits](https://github.com/projectlombok/lombok/compare/v1.18.46...v1.18.48)

---
updated-dependencies:
- dependency-name: org.projectlombok:lombok
  dependency-version: 1.18.48
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-07 20:59:59 +02:00
Jones b8bbe411e1 Release 2.1.51 (#630) 2026-09-06 14:57:18 +02:00
purpurcof 4ed63ee2dc Prevent TailExceptionsHandler from racing a graceful close (#616) 2026-08-31 23:05:20 +02:00
dependabot[bot] 7cd7f86114 Bump com.diffplug.spotless from 8.10.0 to 8.10.1 (#629)
Bumps com.diffplug.spotless from 8.10.0 to 8.10.1.

---
updated-dependencies:
- dependency-name: com.diffplug.spotless
  dependency-version: 8.10.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-31 11:44:29 +02:00
dependabot[bot] 58c9a6bc25 Bump gradle-wrapper from 9.7.0 to 9.7.1 (#627)
Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 9.7.0 to 9.7.1.
- [Release notes](https://github.com/gradle/gradle/releases)
- [Commits](https://github.com/gradle/gradle/compare/v9.7.0...v9.7.1)

---
updated-dependencies:
- dependency-name: gradle-wrapper
  dependency-version: 9.7.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-24 13:01:52 +02:00
dependabot[bot] be6fbc78ab Bump com.diffplug.spotless from 8.9.0 to 8.10.0 (#626)
Bumps com.diffplug.spotless from 8.9.0 to 8.10.0.

---
updated-dependencies:
- dependency-name: com.diffplug.spotless
  dependency-version: 8.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-24 13:01:43 +02:00
Jones cd5eb191fa Fix filled_map item type ID on 26.2 2026-08-23 14:10:56 +02:00
dependabot[bot] 449ff7a55d Bump io.netty:netty-all from 4.2.16.Final to 4.2.17.Final (#620)
Bumps [io.netty:netty-all](https://github.com/netty/netty) from 4.2.16.Final to 4.2.17.Final.
- [Release notes](https://github.com/netty/netty/releases)
- [Commits](https://github.com/netty/netty/compare/netty-4.2.16.Final...netty-4.2.17.Final)

---
updated-dependencies:
- dependency-name: io.netty:netty-all
  dependency-version: 4.2.17.Final
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 15:04:11 +02:00
dependabot[bot] 89b8033540 Bump gradle-wrapper from 9.6.1 to 9.7.0 (#621)
Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 9.6.1 to 9.7.0.
- [Release notes](https://github.com/gradle/gradle/releases)
- [Commits](https://github.com/gradle/gradle/compare/v9.6.1...v9.7.0)

---
updated-dependencies:
- dependency-name: gradle-wrapper
  dependency-version: 9.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 15:03:59 +02:00
dependabot[bot] 1b003e9872 Bump com.diffplug.spotless from 8.8.0 to 8.9.0 (#619)
Bumps com.diffplug.spotless from 8.8.0 to 8.9.0.

---
updated-dependencies:
- dependency-name: com.diffplug.spotless
  dependency-version: 8.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 16:13:07 +02:00
dependabot[bot] 59d1cd2e66 Bump com.gradleup.shadow from 9.6.0 to 9.6.1 (#617)
Bumps [com.gradleup.shadow](https://github.com/GradleUp/shadow) from 9.6.0 to 9.6.1.
- [Release notes](https://github.com/GradleUp/shadow/releases)
- [Commits](https://github.com/GradleUp/shadow/compare/9.6.0...9.6.1)

---
updated-dependencies:
- dependency-name: com.gradleup.shadow
  dependency-version: 9.6.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-27 13:53:01 +02:00
dependabot[bot] de377dbde6 Bump com.gradleup.shadow from 9.5.1 to 9.6.0 (#614)
Bumps [com.gradleup.shadow](https://github.com/GradleUp/shadow) from 9.5.1 to 9.6.0.
- [Release notes](https://github.com/GradleUp/shadow/releases)
- [Commits](https://github.com/GradleUp/shadow/compare/9.5.1...9.6.0)

---
updated-dependencies:
- dependency-name: com.gradleup.shadow
  dependency-version: 9.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-20 14:09:59 +02:00
Jones 9b5845f5af Implement missing check for blacklist scores of 0 2026-07-15 21:57:00 +02:00
dependabot[bot] 6cd1f9e5e4 Bump com.gradleup.shadow from 9.4.3 to 9.5.1 (#609)
Bumps [com.gradleup.shadow](https://github.com/GradleUp/shadow) from 9.4.3 to 9.5.1.
- [Release notes](https://github.com/GradleUp/shadow/releases)
- [Commits](https://github.com/GradleUp/shadow/compare/9.4.3...9.5.1)

---
updated-dependencies:
- dependency-name: com.gradleup.shadow
  dependency-version: 9.5.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-13 17:59:34 +02:00
dependabot[bot] 5ca053cfdd Bump io.netty:netty-all from 4.2.15.Final to 4.2.16.Final (#610)
Bumps [io.netty:netty-all](https://github.com/netty/netty) from 4.2.15.Final to 4.2.16.Final.
- [Release notes](https://github.com/netty/netty/releases)
- [Commits](https://github.com/netty/netty/compare/netty-4.2.15.Final...netty-4.2.16.Final)

---
updated-dependencies:
- dependency-name: io.netty:netty-all
  dependency-version: 4.2.16.Final
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-13 12:55:43 +02:00
Jones 95d94e467a Release 2.1.50 (#607) 2026-07-12 12:29:30 +02:00
Jones fdd54c9b34 Bump dynamic adventure from 4.21.0 to 5.2.0 2026-07-12 12:20:34 +02:00
Jones 5d09260fbc Release 2.1.49 (#606) 2026-07-11 14:03:48 +02:00
Jones b7b2d0d501 Adventure 5 and Java 17+ 2026-07-10 18:02:28 +02:00
dependabot[bot] c8bfd7431f Bump com.diffplug.spotless from 8.7.0 to 8.8.0 (#603)
Bumps com.diffplug.spotless from 8.7.0 to 8.8.0.

---
updated-dependencies:
- dependency-name: com.diffplug.spotless
  dependency-version: 8.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-06 07:25:44 +02:00
dependabot[bot] 312dcca783 Bump com.gradleup.shadow from 9.4.1 to 9.4.3 (#600)
Bumps [com.gradleup.shadow](https://github.com/GradleUp/shadow) from 9.4.1 to 9.4.3.
- [Release notes](https://github.com/GradleUp/shadow/releases)
- [Commits](https://github.com/GradleUp/shadow/compare/9.4.1...9.4.3)

---
updated-dependencies:
- dependency-name: com.gradleup.shadow
  dependency-version: 9.4.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-29 15:03:08 +02:00
dependabot[bot] e006bca937 Bump gradle-wrapper from 9.6.0 to 9.6.1 (#602)
Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 9.6.0 to 9.6.1.
- [Release notes](https://github.com/gradle/gradle/releases)
- [Commits](https://github.com/gradle/gradle/compare/v9.6.0...v9.6.1)

---
updated-dependencies:
- dependency-name: gradle-wrapper
  dependency-version: 9.6.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-29 15:02:55 +02:00
dependabot[bot] b5c406e5e1 Bump com.diffplug.spotless from 8.6.0 to 8.7.0 (#598)
Bumps com.diffplug.spotless from 8.6.0 to 8.7.0.

---
updated-dependencies:
- dependency-name: com.diffplug.spotless
  dependency-version: 8.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-22 13:04:47 +02:00
dependabot[bot] 8b9129aeae Bump gradle-wrapper from 9.5.1 to 9.6.0 (#599)
Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 9.5.1 to 9.6.0.
- [Release notes](https://github.com/gradle/gradle/releases)
- [Commits](https://github.com/gradle/gradle/compare/v9.5.1...v9.6.0)

---
updated-dependencies:
- dependency-name: gradle-wrapper
  dependency-version: 9.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-22 13:04:26 +02:00
36 changed files with 395 additions and 131 deletions

No files matched your search

+1 -1
View File
@@ -47,7 +47,7 @@ Sonar analyzes a player's behavior before joining the actual server, therefore s
1. Sonar sends the player to a lightweight fake server when they connect for the first time.
2. Sonar verifies that players obey the laws of Minecraft's physics, including gravity and proper block collision.
3. Sonar verifies that players send legitimate packets when interacting with vehicles (e.g. boats).
4. Sonar makes sure that players send legitimate packets according to the [vanilla Minecraft protocol](<https://wiki.vg/Protocol>).
4. Sonar makes sure that players send legitimate packets according to the [vanilla Minecraft protocol](<https://minecraft.wiki/w/Java_Edition_protocol/>).
Sonar also protects against spambot attacks since it queues the incoming connections, therefore making it technically impossible to have a ton of bots join the server at the same time.
@@ -77,7 +77,8 @@ public enum ProtocolVersion {
MINECRAFT_1_21_9(773, "1.21.9"),
MINECRAFT_1_21_11(774, "1.21.11"),
MINECRAFT_26_1(775, "26.1"),
MINECRAFT_26_2(776, "26.2");
MINECRAFT_26_2(776, "26.2"),
MINECRAFT_26_3(777, "26.3");
private final int protocol;
private final String name;
+6 -3
View File
@@ -75,6 +75,12 @@ allprojects {
compileJava {
options.encoding = "UTF-8"
options.release.set(17)
}
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
disableAutoTargetJvm()
}
jar {
@@ -93,9 +99,6 @@ allprojects {
attributes["Git-Commit"] = gitCommit
}
}
java.sourceCompatibility = JavaVersion.VERSION_11
java.targetCompatibility = JavaVersion.VERSION_11
}
}
@@ -83,7 +83,8 @@ public enum BukkitServerVersion {
MINECRAFT_1_21_10,
MINECRAFT_1_21_11,
MINECRAFT_26_1,
MINECRAFT_26_2;
MINECRAFT_26_2,
MINECRAFT_26_3;
static final BukkitServerVersion[] REVERSED_VALUES;
-3
View File
@@ -15,9 +15,6 @@ dependencies {
compileOnly(rootProject.libs.bungeecord)
implementation(rootProject.libs.adventure.platform.bungee) {
exclude(module = "adventure-nbt")
}
implementation(rootProject.libs.bstats.bungee)
implementation(rootProject.libs.libby.bungee)
}
@@ -0,0 +1,92 @@
/*
* Copyright (C) 2026 Sonar Contributors
*
* 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 xyz.jonesdev.sonar.bungee;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.kyori.adventure.title.Title;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.chat.ComponentSerializer;
import org.jetbrains.annotations.NotNull;
import xyz.jonesdev.sonar.api.antibot.protocol.ProtocolVersion;
import java.time.Duration;
/**
* Minimal {@link Audience} implementation backed by the native BungeeCord chat API.
* <br>
* BungeeCord does not ship Adventure, so we used to bundle adventure-platform-bungeecord (Adventure 4.x).
* That conflicted with the Adventure 5.x libraries Sonar loads at runtime, because both end up
* in the same relocated package. Converting components to JSON and passing them to BungeeCord's own
* {@link ComponentSerializer} allows us to depend on exactly one Adventure version.
*/
final class BungeeAudience implements Audience {
private final CommandSender sender;
BungeeAudience(final @NotNull CommandSender sender) {
this.sender = sender;
}
@Override
public void sendMessage(final @NotNull Component message) {
sender.sendMessage(toBungee(message));
}
@Override
public void sendActionBar(final @NotNull Component message) {
// Only players have an action bar
if (sender instanceof ProxiedPlayer player) {
player.sendMessage(ChatMessageType.ACTION_BAR, toBungee(message));
}
}
@Override
public void showTitle(final @NotNull Title title) {
// Only players can see titles
if (sender instanceof ProxiedPlayer player) {
final Title.Times times = title.times();
ProxyServer.getInstance().createTitle()
.title(toBungee(title.title()))
.subTitle(toBungee(title.subtitle()))
// Use the same defaults as Title#DEFAULT_TIMES (0.5s, 3.5s, 1s)
.fadeIn(times == null ? 10 : toTicks(times.fadeIn()))
.stay(times == null ? 70 : toTicks(times.stay()))
.fadeOut(times == null ? 20 : toTicks(times.fadeOut()))
.send(player);
}
}
private static int toTicks(final @NotNull Duration duration) {
return (int) (duration.toMillis() / 50L);
}
private @NotNull BaseComponent[] toBungee(final @NotNull Component component) {
// Downsample hex colors for clients that do not support them
final boolean legacyClient = sender instanceof ProxiedPlayer player
&& player.getPendingConnection().getVersion() < ProtocolVersion.MINECRAFT_1_16.getProtocol();
final GsonComponentSerializer serializer = legacyClient
? GsonComponentSerializer.colorDownsamplingGson()
: GsonComponentSerializer.gson();
return ComponentSerializer.parse(serializer.serialize(component));
}
}
@@ -20,8 +20,8 @@ package xyz.jonesdev.sonar.bungee;
import com.alessiodp.libby.BungeeLibraryManager;
import lombok.Getter;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.platform.bungeecord.BungeeAudiences;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import org.bstats.bungeecord.Metrics;
import org.bstats.charts.SimplePie;
import org.jetbrains.annotations.NotNull;
@@ -36,26 +36,22 @@ import java.util.UUID;
@Getter
public final class SonarBungee extends SonarBootstrap<SonarBungeePlugin> {
public SonarBungee(final @NotNull SonarBungeePlugin plugin) {
super(plugin, SonarPlatform.BUNGEE, plugin.getDataFolder(), new BungeeLibraryManager(plugin));
public SonarBungee(final @NotNull SonarBungeePlugin plugin, final @NotNull BungeeLibraryManager libraryManager) {
super(plugin, SonarPlatform.BUNGEE, plugin.getDataFolder(), libraryManager);
}
/**
* Wrapper for BungeeCord audiences
*/
private final BungeeAudiences bungeeAudiences = BungeeAudiences.create(getPlugin());
@Override
public @Nullable Audience audience(final @Nullable UUID uniqueId) {
if (uniqueId == null) {
return null;
}
return bungeeAudiences.player(uniqueId);
final ProxiedPlayer player = getPlugin().getServer().getPlayer(uniqueId);
return player == null ? null : new BungeeAudience(player);
}
@Override
public @NotNull Audience sender(final @NotNull Object object) {
return bungeeAudiences.sender((CommandSender) object);
return new BungeeAudience((CommandSender) object);
}
/**
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2025 Sonar Contributors
* Copyright (C) 2026 Sonar Contributors
*
* 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
@@ -17,9 +17,12 @@
package xyz.jonesdev.sonar.bungee;
import com.alessiodp.libby.BungeeLibraryManager;
import lombok.Getter;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Plugin;
import xyz.jonesdev.sonar.api.SonarPlatform;
import xyz.jonesdev.sonar.common.boot.LibraryLoader;
@Getter
public final class SonarBungeePlugin extends Plugin {
@@ -30,7 +33,13 @@ public final class SonarBungeePlugin extends Plugin {
public void onEnable() {
server = ProxyServer.getInstance();
bootstrap = new SonarBungee(this);
// HACK:
// Adventure is not bundled in the jar, so the libraries have to be on the classpath
// before SonarBungee is loaded. The JVM resolves its Adventure types during class verification.
final BungeeLibraryManager libraryManager = new BungeeLibraryManager(this);
LibraryLoader.loadLibraries(libraryManager, SonarPlatform.BUNGEE);
bootstrap = new SonarBungee(this, libraryManager);
bootstrap.initialize();
}
@@ -54,13 +54,13 @@ public final class StandardCaptchaGenerator implements CaptchaGenerator {
static {
FONT = TTFFontProvider.loadFont("/assets/fonts/Kingthings_Trypewriter_2.ttf");
FBM.setAmount(0.6f);
FBM.setScale(15);
FBM.setAmount(0.55f + RANDOM.nextFloat(0.15f));
FBM.setScale(10 + RANDOM.nextFloat(10));
SMEAR.setShape(SmearFilter.SQUARES);
SMEAR.setDensity(0.1f);
SMEAR.setDistance(0);
SMEAR.setMix(0.35f);
SMEAR.setMix(0.25f + RANDOM.nextFloat(0.25f));
// Create fractions based on the number of colors
for (int i = 0; i < COLOR_FRACTIONS.length; i++) {
@@ -111,7 +111,7 @@ public final class StandardCaptchaGenerator implements CaptchaGenerator {
private void applyRandomColorGradient(final @NotNull Graphics2D graphics) {
// Randomize the colors for the gradient effect
for (int i = 0; i < COLORS.length; i++) {
final float random = 0.9f + RANDOM.nextFloat() * 0.1f;
final float random = 0.8f + RANDOM.nextFloat() * 0.2f;
COLORS[i] = Color.getHSBColor(RANDOM.nextFloat(), random * 0.8f, random);
}
@@ -161,8 +161,8 @@ public final class StandardCaptchaGenerator implements CaptchaGenerator {
}
private void createGlyphOutline(final @NotNull Graphics2D graphics, final @NotNull Shape shape) {
final float txy = 1.25f + RANDOM.nextFloat();
final float width = 1 + RANDOM.nextFloat();
final float txy = RANDOM.nextFloat(0.1f, 2f);
final float width = RANDOM.nextFloat(0.5f, 2f);
// Create a randomly translated and stroked shape based on the original glyph shape
final AffineTransform translation = AffineTransform.getTranslateInstance(txy, txy);
+2 -2
View File
@@ -17,7 +17,7 @@
import lombok.experimental.UtilityClass;
import xyz.jonesdev.sonar.api.antibot.captcha.CaptchaGenerator;
import xyz.jonesdev.sonar.captcha.complex.ComplexCaptchaGenerator;
import xyz.jonesdev.sonar.captcha.StandardCaptchaGenerator;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
@@ -29,7 +29,7 @@ import java.util.Random;
public class Main {
public void main(final String... args) throws IOException {
final Random random = new Random();
final CaptchaGenerator standardCaptchaGenerator = new ComplexCaptchaGenerator(null);
final CaptchaGenerator standardCaptchaGenerator = new StandardCaptchaGenerator(null);
final long start = System.currentTimeMillis();
final char[] dictionary = {'a', 'b', 'c', 'd', 'e', 'f'/*, 'g'*/, 'h'/*, 'i'*/, 'j',
@@ -24,8 +24,8 @@ import org.jetbrains.annotations.NotNull;
import xyz.jonesdev.sonar.api.SonarPlatform;
@UtilityClass
class LibraryLoader {
void loadLibraries(final @NotNull LibraryManager libraryManager, final @NotNull SonarPlatform platform) {
public class LibraryLoader {
public void loadLibraries(final @NotNull LibraryManager libraryManager, final @NotNull SonarPlatform platform) {
libraryManager.addMavenCentral();
libraryManager.addJitPack();
libraryManager.loadLibraries(
@@ -69,25 +69,14 @@ class LibraryLoader {
// Only load adventure if not on Velocity
if (platform != SonarPlatform.VELOCITY) {
if (platform != SonarPlatform.PAPER) {
// BungeeCord does not ship Adventure, and we do not bundle adventure-platform there anymore
// (mixing Adventure 4.x and 5.x in the same relocated package causes NoSuchMethodErrors).
// Therefore, adventure-api and everything else Adventure needs has to be resolved at runtime.
final boolean resolveTransitive = platform == SonarPlatform.BUNGEE;
libraryManager.loadLibraries(
Library.builder()
.groupId("net{}kyori")
.artifactId("adventure-text-minimessage")
.version("4.21.0")
.relocate("net{}kyori", "xyz{}jonesdev{}sonar{}libs{}kyori")
.build(),
Library.builder()
.groupId("net{}kyori")
.artifactId("adventure-text-serializer-gson")
.version("4.21.0")
.relocate("net{}kyori", "xyz{}jonesdev{}sonar{}libs{}kyori")
.build(),
Library.builder()
.groupId("net{}kyori")
.artifactId("adventure-nbt")
.version("4.21.0")
.relocate("net{}kyori", "xyz{}jonesdev{}sonar{}libs{}kyori")
.build()
adventureLibrary("adventure-text-minimessage", resolveTransitive),
adventureLibrary("adventure-text-serializer-gson", resolveTransitive),
adventureLibrary("adventure-nbt", resolveTransitive)
);
} else {
// On Paper, we only relocate the nbt package since the rest of adventure is bundled with the server.
@@ -95,11 +84,25 @@ class LibraryLoader {
Library.builder()
.groupId("net{}kyori")
.artifactId("adventure-nbt")
.version("4.21.0")
.version("5.2.0")
.relocate("net{}kyori{}adventure{}nbt", "xyz{}jonesdev{}sonar{}libs{}kyori{}adventure{}nbt")
.build()
);
}
}
}
private @NotNull Library adventureLibrary(final @NotNull String artifactId, final boolean resolveTransitive) {
final Library.Builder builder = Library.builder()
.groupId("net{}kyori")
.artifactId(artifactId)
.version("5.2.0")
.relocate("net{}kyori", "xyz{}jonesdev{}sonar{}libs{}kyori");
if (resolveTransitive) {
builder.resolveTransitiveDependencies(true)
// Gson is already provided by the proxy, so we must not load another copy
.excludeTransitiveDependency("com.google.code.gson", "gson");
}
return builder.build();
}
}
@@ -68,7 +68,13 @@ public abstract class SonarBootstrap<T> implements Sonar {
final @NotNull File dataDirectory,
final @NotNull LibraryManager libraryManager) {
// Load all libraries before anything else
LibraryLoader.loadLibraries(libraryManager, platform);
// HACK:
// We manually load the libraries on BungeeCord beforehand,
// so we skip this call to avoid loading libraries twice.
// See SonarBungeePlugin.java#L40
if (platform != SonarPlatform.BUNGEE) {
LibraryLoader.loadLibraries(libraryManager, platform);
}
this.libraryManager = libraryManager;
// Check if Netty is up to date
ProtocolUtil.checkNettyVersion();
@@ -21,6 +21,7 @@ import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import org.jetbrains.annotations.NotNull;
import xyz.jonesdev.sonar.common.util.ProtocolUtil;
@ChannelHandler.Sharable
public final class TailExceptionsHandler extends ChannelDuplexHandler {
@@ -33,6 +34,20 @@ public final class TailExceptionsHandler extends ChannelDuplexHandler {
// Additionally, this will also run after our custom decoder.
@Override
public void exceptionCaught(final @NotNull ChannelHandlerContext ctx, final Throwable cause) throws Exception {
// If ProtocolUtil#closeWith(...) already queued a graceful write-then-close for
// this channel (e.g. VerificationHandler#fail() calls disconnect() and then
// throws to unwind), don't race it with a second, immediate close() here. Doing
// so can abort the still-in-flight kick/disconnect packet write before it's fully
// flushed, so the client only receives a truncated packet instead of our message.
// The scheduled close from closeWith() will still run once the write completes.
// See: https://github.com/jonesdevelopment/sonar/issues/476
if (Boolean.TRUE.equals(ctx.channel().attr(ProtocolUtil.CLOSING).get())) {
if (LOG_EXCEPTIONS) {
cause.printStackTrace(System.err);
}
return;
}
// Close the channel if we encounter any errors.
ctx.close();
if (LOG_EXCEPTIONS) {
@@ -106,8 +106,10 @@ public class SonarPacketPreparer {
public final SonarPacket[] REGISTRY_SYNC_1_21_11 = RegistryDataPacket.of(DimensionRegistry.CODEC_1_21_11);
public final SonarPacket[] REGISTRY_SYNC_26_1 = RegistryDataPacket.of(DimensionRegistry.CODEC_26_1);
public final SonarPacket[] REGISTRY_SYNC_26_2 = RegistryDataPacket.of(DimensionRegistry.CODEC_26_2);
public final SonarPacket[] REGISTRY_SYNC_26_3 = RegistryDataPacket.of(DimensionRegistry.CODEC_26_3);
public final SonarPacket TAGS_UPDATE_26_1 = UpdateTagsPacket.of(DimensionRegistry.TAGS_26_1);
public final SonarPacket TAGS_UPDATE_26_2 = UpdateTagsPacket.of(DimensionRegistry.TAGS_26_2);
public final SonarPacket TAGS_UPDATE_26_3 = UpdateTagsPacket.of(DimensionRegistry.TAGS_26_3);
public final SonarPacket START_WRITING_CHUNKS = new GameEventPacket(13, 0);
public final static SonarPacket INVALID_HELD_ITEM_SLOT = new SetHeldItemPacket(-1);
public final SonarPacket RANDOM_KEEP_ALIVE = new SonarPacketSnapshot(new KeepAlivePacket(RANDOM.nextInt()));
@@ -296,7 +298,9 @@ public class SonarPacketPreparer {
}
public static @Nullable SonarPacket getTagsPacket(final @NotNull ProtocolVersion protocolVersion) {
if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_26_2)) {
if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_26_3)) {
return TAGS_UPDATE_26_3;
} else if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_26_2)) {
return TAGS_UPDATE_26_2;
} else if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_26_1)) {
return TAGS_UPDATE_26_1;
@@ -305,7 +309,9 @@ public class SonarPacketPreparer {
}
public static SonarPacket[] getRegistryPackets(final @NotNull ProtocolVersion protocolVersion) {
if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_26_2)) {
if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_26_3)) {
return REGISTRY_SYNC_26_3;
} else if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_26_2)) {
return REGISTRY_SYNC_26_2;
} else if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_26_1)) {
return REGISTRY_SYNC_26_1;
@@ -77,7 +77,8 @@ public enum SonarPacketRegistry {
map(0x05, MINECRAFT_1_20_2, true),
map(0x07, MINECRAFT_1_20_5, true));
clientbound.register(UpdateTagsPacket.class, UpdateTagsPacket::new,
map(0x0D, MINECRAFT_1_20_5, true));
map(0x0D, MINECRAFT_1_20_5, true),
map(0x0E, MINECRAFT_26_3, true));
serverbound.register(ClientInformationPacket.class, ClientInformationPacket::new,
map(0x00, MINECRAFT_1_20_2, false));
@@ -113,7 +114,8 @@ public enum SonarPacketRegistry {
map(0x2C, MINECRAFT_1_21_2, true),
map(0x2B, MINECRAFT_1_21_5, true),
map(0x30, MINECRAFT_1_21_9, true),
map(0x31, MINECRAFT_26_1, true));
map(0x31, MINECRAFT_26_1, true),
map(0x32, MINECRAFT_26_3, true));
// minecraft:keep_alive
clientbound.register(KeepAlivePacket.class, KeepAlivePacket::new,
map(0x00, MINECRAFT_1_7_2, true),
@@ -133,7 +135,8 @@ public enum SonarPacketRegistry {
map(0x27, MINECRAFT_1_21_2, true),
map(0x26, MINECRAFT_1_21_5, true),
map(0x2B, MINECRAFT_1_21_9, true),
map(0x2C, MINECRAFT_26_1, true));
map(0x2C, MINECRAFT_26_1, true),
map(0x2D, MINECRAFT_26_3, true));
// minecraft:disconnect
clientbound.register(DisconnectPacket.class, DisconnectPacket::new,
map(0x40, MINECRAFT_1_7_2, true),
@@ -172,7 +175,8 @@ public enum SonarPacketRegistry {
map(0x42, MINECRAFT_1_21_2, true),
map(0x41, MINECRAFT_1_21_5, true),
map(0x46, MINECRAFT_1_21_9, true),
map(0x48, MINECRAFT_26_1, true));
map(0x48, MINECRAFT_26_1, true),
map(0x49, MINECRAFT_26_3, true));
// minecraft:player_abilities
clientbound.register(PlayerAbilitiesPacket.class, PlayerAbilitiesPacket::new,
map(0x39, MINECRAFT_1_7_2, true),
@@ -193,7 +197,8 @@ public enum SonarPacketRegistry {
map(0x3A, MINECRAFT_1_21_2, true),
map(0x39, MINECRAFT_1_21_5, true),
map(0x3E, MINECRAFT_1_21_9, true),
map(0x40, MINECRAFT_26_1, true));
map(0x40, MINECRAFT_26_1, true),
map(0x41, MINECRAFT_26_3, true));
// minecraft:level_chunk_with_light
clientbound.register(ChunkDataPacket.class, ChunkDataPacket::new,
map(0x21, MINECRAFT_1_7_2, true),
@@ -213,7 +218,8 @@ public enum SonarPacketRegistry {
map(0x28, MINECRAFT_1_21_2, true),
map(0x27, MINECRAFT_1_21_5, true),
map(0x2C, MINECRAFT_1_21_9, true),
map(0x2D, MINECRAFT_26_1, true));
map(0x2D, MINECRAFT_26_1, true),
map(0x2E, MINECRAFT_26_3, true));
// minecraft:remove_entities
clientbound.register(RemoveEntitiesPacket.class, RemoveEntitiesPacket::new,
map(0x13, MINECRAFT_1_7_2, true),
@@ -236,7 +242,8 @@ public enum SonarPacketRegistry {
map(0x47, MINECRAFT_1_21_2, true),
map(0x46, MINECRAFT_1_21_5, true),
map(0x4B, MINECRAFT_1_21_9, true),
map(0x4D, MINECRAFT_26_1, true));
map(0x4D, MINECRAFT_26_1, true),
map(0x4E, MINECRAFT_26_3, true));
// minecraft:set_passengers
clientbound.register(SetPassengersPacket.class, SetPassengersPacket::new,
map(0x1B, MINECRAFT_1_7_2, true),
@@ -256,7 +263,8 @@ public enum SonarPacketRegistry {
map(0x65, MINECRAFT_1_21_2, true),
map(0x64, MINECRAFT_1_21_5, true),
map(0x69, MINECRAFT_1_21_9, true),
map(0x6B, MINECRAFT_26_1, true));
map(0x6B, MINECRAFT_26_1, true),
map(0x6D, MINECRAFT_26_3, true));
// minecraft:add_entity
clientbound.register(SpawnEntityPacket.class, SpawnEntityPacket::new,
map(0x0E, MINECRAFT_1_7_2, true),
@@ -281,7 +289,8 @@ public enum SonarPacketRegistry {
map(0x4E, MINECRAFT_1_21_2, true),
map(0x4D, MINECRAFT_1_21_5, true),
map(0x52, MINECRAFT_1_21_9, true),
map(0x54, MINECRAFT_26_1, true));
map(0x54, MINECRAFT_26_1, true),
map(0x56, MINECRAFT_26_3, true));
// minecraft:ping
clientbound.register(TransactionPacket.class, TransactionPacket::new,
map(0x32, MINECRAFT_1_7_2, true),
@@ -300,7 +309,8 @@ public enum SonarPacketRegistry {
map(0x37, MINECRAFT_1_21_2, true),
map(0x36, MINECRAFT_1_21_5, true),
map(0x3B, MINECRAFT_1_21_9, true),
map(0x3D, MINECRAFT_26_1, true));
map(0x3D, MINECRAFT_26_1, true),
map(0x3E, MINECRAFT_26_3, true));
// minecraft:set_default_spawn_position
clientbound.register(SetDefaultSpawnPositionPacket.class, SetDefaultSpawnPositionPacket::new,
map(0x05, MINECRAFT_1_7_2, true),
@@ -322,7 +332,8 @@ public enum SonarPacketRegistry {
map(0x5B, MINECRAFT_1_21_2, true),
map(0x5A, MINECRAFT_1_21_5, true),
map(0x5F, MINECRAFT_1_21_9, true),
map(0x61, MINECRAFT_26_1, true));
map(0x61, MINECRAFT_26_1, true),
map(0x63, MINECRAFT_26_3, true));
// minecraft:map_item_data
clientbound.register(MapDataPacket.class, MapDataPacket::new,
map(0x34, MINECRAFT_1_7_2, true),
@@ -341,7 +352,8 @@ public enum SonarPacketRegistry {
map(0x2D, MINECRAFT_1_21_2, true),
map(0x2C, MINECRAFT_1_21_5, true),
map(0x31, MINECRAFT_1_21_9, true),
map(0x33, MINECRAFT_26_1, true));
map(0x33, MINECRAFT_26_1, true),
map(0x34, MINECRAFT_26_3, true));
// minecraft:container_set_slot
clientbound.register(SetContainerSlotPacket.class, SetContainerSlotPacket::new,
map(0x2F, MINECRAFT_1_7_2, true),
@@ -376,7 +388,8 @@ public enum SonarPacketRegistry {
map(0x61, MINECRAFT_1_21_2, true),
map(0x60, MINECRAFT_1_21_5, true),
map(0x65, MINECRAFT_1_21_9, true),
map(0x67, MINECRAFT_26_1, true));
map(0x67, MINECRAFT_26_1, true),
map(0x69, MINECRAFT_26_3, true));
// minecraft:system_chat
clientbound.register(SystemChatPacket.class, SystemChatPacket::new,
map(0x02, MINECRAFT_1_7_2, true),
@@ -395,20 +408,23 @@ public enum SonarPacketRegistry {
map(0x73, MINECRAFT_1_21_2, true),
map(0x72, MINECRAFT_1_21_5, true),
map(0x77, MINECRAFT_1_21_9, true),
map(0x79, MINECRAFT_26_1, true));
map(0x79, MINECRAFT_26_1, true),
map(0x7C, MINECRAFT_26_3, true));
// minecraft:game_event
clientbound.register(GameEventPacket.class, GameEventPacket::new,
map(0x20, MINECRAFT_1_20_3, true),
map(0x22, MINECRAFT_1_20_5, true),
map(0x23, MINECRAFT_1_21_2, true),
map(0x22, MINECRAFT_1_21_5, true),
map(0x26, MINECRAFT_1_21_9, true));
map(0x26, MINECRAFT_1_21_9, true),
map(0x27, MINECRAFT_26_3, true));
// minecraft:transfer
clientbound.register(TransferPacket.class, TransferPacket::new,
map(0x73, MINECRAFT_1_20_5, true),
map(0x7A, MINECRAFT_1_21_2, true),
map(0x7F, MINECRAFT_1_21_9, true),
map(0x81, MINECRAFT_26_1, true));
map(0x81, MINECRAFT_26_1, true),
map(0x84, MINECRAFT_26_3, true));
// minecraft:set_held_slot
clientbound.register(SetHeldItemPacket.class, SetHeldItemPacket::new,
map(0x09, MINECRAFT_1_7_2, true),
@@ -430,7 +446,8 @@ public enum SonarPacketRegistry {
map(0x63, MINECRAFT_1_21_2, true),
map(0x62, MINECRAFT_1_21_5, true),
map(0x67, MINECRAFT_1_21_9, true),
map(0x69, MINECRAFT_26_1, true));
map(0x69, MINECRAFT_26_1, true),
map(0x6B, MINECRAFT_26_3, true));
// minecraft:animate
clientbound.register(EntityAnimationPacket.class, EntityAnimationPacket::new,
map(0x0B, MINECRAFT_1_7_2, true),
@@ -462,7 +479,8 @@ public enum SonarPacketRegistry {
map(0x6B, MINECRAFT_1_21_2, true),
map(0x6A, MINECRAFT_1_21_5, true),
map(0x6F, MINECRAFT_1_21_9, true),
map(0x71, MINECRAFT_26_1, true));
map(0x71, MINECRAFT_26_1, true),
map(0x73, MINECRAFT_26_3, true));
// minecraft:client_tick_end
serverbound.register(ClientTickEndPacket.class, ClientTickEndPacket::new,
@@ -486,7 +504,8 @@ public enum SonarPacketRegistry {
map(0x31, MINECRAFT_1_21_2, false),
map(0x33, MINECRAFT_1_21_4, false),
map(0x34, MINECRAFT_1_21_6, false),
map(0x35, MINECRAFT_26_1, false));
map(0x35, MINECRAFT_26_1, false),
map(0x36, MINECRAFT_26_3, false));
// minecraft:paddle_boat
serverbound.register(PaddleBoatPacket.class, PaddleBoatPacket::new,
map(0x11, MINECRAFT_1_9, false),
@@ -525,7 +544,7 @@ public enum SonarPacketRegistry {
map(0x28, MINECRAFT_1_21_2, false),
map(0x29, MINECRAFT_1_21_4, false),
map(0x2A, MINECRAFT_1_21_6, false),
map(0x26, MINECRAFT_26_1, false));
map(0x2B, MINECRAFT_26_1, false));
// minecraft:move_vehicle
serverbound.register(VehicleMovePacket.class, VehicleMovePacket::new,
map(0x10, MINECRAFT_1_9, false),
@@ -734,7 +753,8 @@ public enum SonarPacketRegistry {
map(0x3A, MINECRAFT_1_21_4, false),
map(0x3B, MINECRAFT_1_21_5, false),
map(0x3C, MINECRAFT_1_21_6, false),
map(0x3F, MINECRAFT_26_1, false));
map(0x3F, MINECRAFT_26_1, false),
map(0x2E, MINECRAFT_26_3, false));
}
};
@@ -80,7 +80,10 @@ public enum BlockType {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_11)) {
return 9250;
}
return 9451;
if (protocolVersion.lessThanOrEquals(MINECRAFT_26_2)) {
return 9451;
}
return 11185;
}, protocolVersion -> (double) 0.75f),
TRAPDOOR(protocolVersion -> {
// We have to use wooden trapdoors for 1.7 since 1.7 doesn't have iron trapdoors
@@ -135,7 +138,10 @@ public enum BlockType {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_11)) {
return 12380;
}
return 12582;
if (protocolVersion.lessThanOrEquals(MINECRAFT_26_2)) {
return 12582;
}
return 14429;
}, protocolVersion -> 0.1875),
END_PORTAL_FRAME(protocolVersion -> {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_12_2)) {
@@ -183,7 +189,10 @@ public enum BlockType {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_11)) {
return 9272;
}
return 9473;
if (protocolVersion.lessThanOrEquals(MINECRAFT_26_2)) {
return 9473;
}
return 11207;
}, protocolVersion -> 0.8125),
DAYLIGHT_SENSOR(protocolVersion -> {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_12_2)) {
@@ -234,7 +243,10 @@ public enum BlockType {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_11)) {
return 11093;
}
return 11295;
if (protocolVersion.lessThanOrEquals(MINECRAFT_26_2)) {
return 11295;
}
return 13062;
}, protocolVersion -> 0.375),
COBBLESTONE_WALL(protocolVersion -> {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_12_2)) {
@@ -282,7 +294,10 @@ public enum BlockType {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_11)) {
return 9783;
}
return 9984;
if (protocolVersion.lessThanOrEquals(MINECRAFT_26_2)) {
return 9984;
}
return 11726;
}, protocolVersion -> 1.5),
STONE_SLABS(protocolVersion -> {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_12_2)) {
@@ -333,7 +348,10 @@ public enum BlockType {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_11)) {
return 13197;
}
return 13399;
if (protocolVersion.lessThanOrEquals(MINECRAFT_26_2)) {
return 13399;
}
return 15252;
}, protocolVersion -> 0.5),
WHITE_CARPET(protocolVersion -> {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_12_2)) {
@@ -384,7 +402,10 @@ public enum BlockType {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_11)) {
return 12694;
}
return 12896;
if (protocolVersion.lessThanOrEquals(MINECRAFT_26_2)) {
return 12896;
}
return 14743;
}, protocolVersion -> protocolVersion.compareTo(MINECRAFT_1_8) < 0 ? 0 : 0.0625);
private final Function<ProtocolVersion, Integer> id;
@@ -43,8 +43,10 @@ public final class DimensionRegistry {
public final CompoundBinaryTag CODEC_1_21_11;
public final CompoundBinaryTag CODEC_26_1;
public final CompoundBinaryTag CODEC_26_2;
public final CompoundBinaryTag CODEC_26_3;
public final CompoundBinaryTag TAGS_26_1;
public final CompoundBinaryTag TAGS_26_2;
public final CompoundBinaryTag TAGS_26_3;
static {
CODEC_1_16 = getCodec("codec_1_16.nbt");
@@ -62,8 +64,10 @@ public final class DimensionRegistry {
CODEC_1_21_11 = getCodec("codec_1_21_11.nbt");
CODEC_26_1 = getCodec("codec_26_1.nbt");
CODEC_26_2 = getCodec("codec_26_2.nbt");
CODEC_26_3 = getCodec("codec_26_3.nbt");
TAGS_26_1 = getCodec("tags_26_1.nbt");
TAGS_26_2 = getCodec("tags_26_2.nbt");
TAGS_26_3 = getCodec("tags_26_3.nbt");
}
private @NotNull CompoundBinaryTag getCodec(final @NotNull String fileName) {
@@ -67,7 +67,10 @@ public enum EntityType {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_9)) {
return 87;
}
return 89;
if (protocolVersion.lessThanOrEquals(MINECRAFT_26_2)) {
return 89;
}
return 90;
}),
MINECART(protocolVersion -> {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_13_2)) {
@@ -112,7 +115,10 @@ public enum EntityType {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_9)) {
return 84;
}
return 85;
if (protocolVersion.lessThanOrEquals(MINECRAFT_26_2)) {
return 85;
}
return 86;
});
private final Function<ProtocolVersion, Integer> id;
@@ -85,7 +85,13 @@ public enum ItemType {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_11)) {
return 1104;
}
return 1105;
if (protocolVersion.lessThanOrEquals(MINECRAFT_26_1)) {
return 1105;
}
if (protocolVersion.lessThanOrEquals(MINECRAFT_26_2)) {
return 1133;
}
return 1238;
}, protocolVersion -> {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21)) {
return 26;
@@ -99,7 +105,10 @@ public enum ItemType {
if (protocolVersion.lessThanOrEquals(MINECRAFT_1_21_11)) {
return 44;
}
return 46;
if (protocolVersion.lessThanOrEquals(MINECRAFT_26_2)) {
return 46;
}
return 48;
});
private final Function<ProtocolVersion, Integer> id;
@@ -50,7 +50,7 @@ public final class RegistryDataPacket implements SonarPacket {
for (final RegistryDataPacket.Bundle bundle : bundles) {
ProtocolUtil.writeString(byteBuf, bundle.getName());
// Write the bundle tag
final CompoundBinaryTag tag = bundle.getTag();
final BinaryTag tag = bundle.getTag();
if (tag != null) {
byteBuf.writeBoolean(true);
ProtocolUtil.writeBinaryTag(byteBuf, protocolVersion, tag);
@@ -73,8 +73,7 @@ public final class RegistryDataPacket implements SonarPacket {
final ArrayList<RegistryDataPacket.Bundle> bundles = new ArrayList<>();
for (final BinaryTag binaryTag : rootTag.getCompound(type).getList("value")) {
final CompoundBinaryTag tag = (CompoundBinaryTag) binaryTag;
// CompoundBinaryTag#getCompound(String) will return an empty compound tag when not exist.
bundles.add(new Bundle(tag.getString("name"), tag.get("element") == null ? null : tag.getCompound("element")));
bundles.add(new Bundle(tag.getString("name"), tag.get("element")));
}
packets[index++] = new SonarPacketSnapshot(new RegistryDataPacket(rootTag, type, bundles));
}
@@ -86,6 +85,6 @@ public final class RegistryDataPacket implements SonarPacket {
public static class Bundle {
@NotNull String name;
// In the protocol, it is able to be null
@Nullable CompoundBinaryTag tag;
@Nullable BinaryTag tag;
}
}
@@ -46,6 +46,8 @@ public final class AnimationPacket implements SonarPacket {
if (protocolVersion.lessThan(ProtocolVersion.MINECRAFT_1_8)) {
entityId = byteBuf.readInt();
type = LegacyAnimationType.getById(byteBuf.readByte());
} else if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_26_3)) {
hand = MAIN_HAND;
} else if (protocolVersion.greaterThan(ProtocolVersion.MINECRAFT_1_8)) {
// Only 1.9+ clients have an offhand
hand = ProtocolUtil.readVarInt(byteBuf);
@@ -32,6 +32,15 @@ import xyz.jonesdev.sonar.common.util.ProtocolUtil;
@AllArgsConstructor
public final class ConfirmTeleportationPacket implements SonarPacket {
private int teleportId;
private double x;
private double y;
private double z;
private float yaw;
private float pitch;
public ConfirmTeleportationPacket(final int teleportId) {
this.teleportId = teleportId;
}
@Override
public void encode(final ByteBuf byteBuf, final ProtocolVersion protocolVersion) {
@@ -41,5 +50,12 @@ public final class ConfirmTeleportationPacket implements SonarPacket {
@Override
public void decode(final ByteBuf byteBuf, final ProtocolVersion protocolVersion) throws Exception {
teleportId = ProtocolUtil.readVarInt(byteBuf);
if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_26_3)) {
x = byteBuf.readDouble();
y = byteBuf.readDouble();
z = byteBuf.readDouble();
yaw = byteBuf.readFloat();
pitch = byteBuf.readFloat();
}
}
}
@@ -148,8 +148,14 @@ public final class JoinGamePacket implements SonarPacket {
ProtocolUtil.writeString(byteBuf, levelName);
byteBuf.writeLong(partialHashedSeed);
byteBuf.writeByte(gamemode);
byteBuf.writeByte(previousGamemode);
if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_26_3)) {
ProtocolUtil.writeVarInt(byteBuf, gamemode);
// ByteBufCodecs#OPTIONAL_VAR_INT: 0 for empty, (value + 1) if present
ProtocolUtil.writeVarInt(byteBuf, previousGamemode == -1 ? 0 : previousGamemode + 1);
} else {
byteBuf.writeByte(gamemode);
byteBuf.writeByte(previousGamemode);
}
}
if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_1_16)) {
@@ -169,12 +175,11 @@ public final class JoinGamePacket implements SonarPacket {
ProtocolUtil.writeVarInt(byteBuf, seaLevel);
}
if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_1_20_5)) {
byteBuf.writeBoolean(secureProfile);
}
if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_26_2)) {
byteBuf.writeBoolean(onlineMode);
byteBuf.writeBoolean(secureProfile);
} else if (protocolVersion.greaterThanOrEquals(ProtocolVersion.MINECRAFT_1_20_5)) {
byteBuf.writeBoolean(secureProfile);
}
}
@@ -24,6 +24,7 @@ import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.handler.codec.DecoderException;
import io.netty.handler.codec.EncoderException;
import io.netty.util.AttributeKey;
import io.netty.util.Version;
import lombok.experimental.UtilityClass;
import net.kyori.adventure.nbt.BinaryTag;
@@ -217,9 +218,20 @@ public class ProtocolUtil {
}
}
public static final AttributeKey<Boolean> CLOSING = AttributeKey.valueOf("sonar-graceful-close-in-progress");
public static void closeWith(final @NotNull Channel channel,
final @NotNull ProtocolVersion protocolVersion,
final @NotNull Object msg) {
// Mark this channel as already undergoing a graceful close *before* we queue the
// write. If something downstream (e.g. an exception thrown right after this call,
// such as VerificationHandler#fail()'s QuietDecoderException) reaches
// TailExceptionsHandler while our writeAndFlush(...).addListener(CLOSE) is still
// in flight, that handler must not call ctx.close() a second time - doing so can
// abort the still-pending write and deliver only a truncated packet to the client
// (which then sees a bare disconnect/reset instead of our kick message).
// See: https://github.com/jonesdevelopment/sonar/issues/476
channel.attr(CLOSING).set(true);
if (protocolVersion.lessThan(ProtocolVersion.MINECRAFT_1_8)) {
channel.eventLoop().execute(() -> {
channel.config().setAutoRead(false);
@@ -36,8 +36,9 @@ public final class GravityHandler extends VerificationHandler {
super(user);
this.preJoinHandler = preJoinHandler;
// Bedrock users start falling immediately
this.canFall = user.isGeyser();
// Client can send movement packet without first position-and-rot packet (usually caused by teleport, < 26.3 Java)
// 26.3+ client will no longer send movement packet for teleports. (positions included in teleport confirm)
this.canFall = user.isGeyser() || user.getProtocolVersion().greaterThanOrEquals(ProtocolVersion.MINECRAFT_26_3);
// We don't want to check Geyser players for valid gravity, as this might cause issues because of the protocol
this.enableGravityCheck = !user.isGeyser() && AntiBot.shouldPerform(
Sonar.get0().getConfig().getVerification().getGravity().getTiming());
@@ -108,6 +109,8 @@ public final class GravityHandler extends VerificationHandler {
final SetPlayerPositionRotationPacket position = (SetPlayerPositionRotationPacket) packet;
if (teleported) {
handleMovement(position.getX(), position.getY(), position.getZ(), position.isOnGround(), true);
} else if (user.getProtocolVersion().greaterThanOrEquals(ProtocolVersion.MINECRAFT_26_3)) {
return;
} else if (user.getProtocolVersion().equals(ProtocolVersion.MINECRAFT_1_21_2)) {
lastPositionPacket = position;
return;
@@ -122,6 +125,8 @@ public final class GravityHandler extends VerificationHandler {
if (teleported) {
final SetPlayerPositionPacket position = (SetPlayerPositionPacket) packet;
handleMovement(position.getX(), position.getY(), position.getZ(), position.isOnGround(), false);
} else if (user.getProtocolVersion().greaterThanOrEquals(ProtocolVersion.MINECRAFT_26_3)) {
return;
}
checkClientTick();
} else if (packet instanceof ConfirmTeleportationPacket) {
@@ -133,11 +138,15 @@ public final class GravityHandler extends VerificationHandler {
checkState(confirmTeleport.getTeleportId() == expectedTeleportId,
"expected TP ID " + expectedTeleportId + ", but got " + confirmTeleport.getTeleportId());
final boolean v26_3 = user.getProtocolVersion().greaterThanOrEquals(ProtocolVersion.MINECRAFT_26_3);
final boolean sendPosRotBefore = user.getProtocolVersion().equals(ProtocolVersion.MINECRAFT_1_21_2);
checkState(sendPosRotBefore ? lastPositionPacket != null : !expectTeleportPosRot,
"expected position rotation but got teleport confirm.");
if (!sendPosRotBefore) {
expectTeleportPosRot = true;
if (!v26_3) {
checkState(sendPosRotBefore ? lastPositionPacket != null : !expectTeleportPosRot,
"expected position rotation but got teleport confirm.");
if (!sendPosRotBefore) {
expectTeleportPosRot = true;
}
}
// The first teleport ID is not useful for us in this context, skip it
@@ -147,7 +156,11 @@ public final class GravityHandler extends VerificationHandler {
// Enable the movement checks
teleported = true;
if (sendPosRotBefore) {
if (v26_3) {
handleMovement(
confirmTeleport.getX(), confirmTeleport.getY(), confirmTeleport.getZ(),
false, true);
} else if (sendPosRotBefore) {
handleMovement(
lastPositionPacket.getX(), lastPositionPacket.getY(), lastPositionPacket.getZ(),
lastPositionPacket.isOnGround(), true);
@@ -248,7 +261,8 @@ public final class GravityHandler extends VerificationHandler {
// The deltaY is 0 whenever the player sends their first position packet.
// We have to account for this or the player will falsely fail the verification.
if (deltaY == 0) {
checkState(rotated, "illegal movement packet order: " + deltaY);
checkState(user.getProtocolVersion().greaterThanOrEquals(ProtocolVersion.MINECRAFT_26_3) || rotated,
"illegal movement packet order: " + deltaY);
checkState(movementTick == 0, "illegal y motion: " + movementTick);
// 1.7 clients immediately start falling after this packet
if (user.getProtocolVersion().lessThan(ProtocolVersion.MINECRAFT_1_8)) {
@@ -71,7 +71,8 @@ public final class ProtocolHandler extends VerificationHandler {
waitingSlotConfirm = false;
expectedSlotId = -1;
// The player did not send duplicate packets, so they pass this check
if (user.isGeyser()) {
// 26.3+ removed client-side swing packet echo, so exempt 26.3+ from the arm animation check
if (user.isGeyser() || user.getProtocolVersion().greaterThanOrEquals(ProtocolVersion.MINECRAFT_26_3)) {
markSuccess();
} else {
sendArmAnimation();
@@ -121,7 +121,7 @@ public abstract class VerificationHandler implements SonarPacketListener {
// The user is allowed to disable the blacklist entirely by setting the threshold to 0
final int limit = Sonar.get0().getConfig().getVerification().getBlacklistThreshold();
// The player hasn't been blacklisted yet, so skip this iteration
if (newScore < limit) break blacklist;
if (limit <= 0 || newScore < limit) break blacklist;
GlobalSonarStatistics.totalBlacklistedPlayers++;
+1 -1
View File
@@ -1,3 +1,3 @@
group=xyz.jonesdev
version=2.1.48
version=2.1.53
description=A lightweight, effective, and easy-to-use anti-bot plugin for Velocity, BungeeCord, and Bukkit.
+5 -6
View File
@@ -1,6 +1,6 @@
[versions]
netty = "4.2.15.Final"
adventure = "4.24.0"
netty = "4.2.19.Final"
adventure = "5.2.0"
adventure-platform = "4.4.1"
bstats = "3.2.1"
libby = "2.0.0-SNAPSHOT"
@@ -8,8 +8,8 @@ pluginyml = "0.6.0"
[plugins]
indra-git = "net.kyori.indra.git:3.2.0"
shadow = "com.gradleup.shadow:9.4.1"
spotless = "com.diffplug.spotless:8.6.0"
shadow = "com.gradleup.shadow:9.6.1"
spotless = "com.diffplug.spotless:8.10.4"
pluginyml-bungee = { id = "net.minecrell.plugin-yml.bungee", version.ref = "pluginyml" }
pluginyml-bukkit = { id = "net.minecrell.plugin-yml.bukkit", version.ref = "pluginyml" }
pluginyml-paper = { id = "net.minecrell.plugin-yml.paper", version.ref = "pluginyml" }
@@ -20,7 +20,6 @@ adventure-minimessage = { module = "net.kyori:adventure-text-minimessage", versi
adventure-serializer = { module = "net.kyori:adventure-text-serializer-gson", version.ref = "adventure" }
adventure-nbt = { module = "net.kyori:adventure-nbt", version.ref = "adventure" }
adventure-platform-bukkit = { module = "net.kyori:adventure-platform-bukkit", version.ref = "adventure-platform" }
adventure-platform-bungee = { module = "net.kyori:adventure-platform-bungeecord", version.ref = "adventure-platform" }
libby-core = { module = "com.alessiodp.libby:libby-core", version.ref = "libby" }
libby-bungee = { module = "com.alessiodp.libby:libby-bungee", version.ref = "libby" }
libby-bukkit = { module = "com.alessiodp.libby:libby-bukkit", version.ref = "libby" }
@@ -34,7 +33,7 @@ caffeine = "com.github.ben-manes.caffeine:caffeine:3.2.4"
annotations = "org.jetbrains:annotations:26.1.0"
simpleyaml = "com.github.Carleslc.Simple-YAML:Simple-Yaml:1.8.4"
ormlite = "com.j256.ormlite:ormlite-jdbc:6.1"
lombok = "org.projectlombok:lombok:1.18.46"
lombok = "org.projectlombok:lombok:1.18.48"
bungeecord = "net.md-5:bungeecord-proxy:26.1-R0.1-SNAPSHOT"
velocity = "io.papermc.velocity:velocity-proxy:3.5.0-SNAPSHOT"
paper = "io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT"
Binary file not shown.
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.2-bin.zip
networkTimeout=10000
retries=0
retryBackOffMs=500
Vendored
+2 -2
View File
@@ -20,7 +20,7 @@
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
# gradlew start up script for POSIX generated by Gradle.
#
# Important for running:
#
@@ -29,7 +29,7 @@
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
# ksh gradlew
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
Vendored
+43 -13
View File
@@ -19,13 +19,40 @@
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem gradlew startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables, and ensure extensions are enabled
setlocal EnableExtensions
@rem Catch executions from older scripts and ensure they exit cleanly.
@rem This can be removed once we can be reasonably confident that few people
@rem will be migrating directly to this new wrapper.
goto afterSafetyNet
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
goto exitWithErrorLevel
:afterSafetyNet
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
@@ -45,13 +72,14 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
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
1>&2 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.
"%COMSPEC%" /c exit 1
goto exitWithErrorLevel
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
@@ -59,24 +87,26 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
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
1>&2 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.
"%COMSPEC%" /c exit 1
goto exitWithErrorLevel
:execute
@rem Setup the command line
@rem Execute Gradle
@rem Execute gradlew
@rem endlocal doesn't take effect until after the line is parsed and variables are expanded
@rem which allows us to clear the local environment before executing the java command
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel & goto exitWithErrorLevel
@rem This label must not be changed. We rely on old scripts being able to jump to this point.
:exitWithErrorLevel
@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
"%COMSPEC%" /c exit %ERRORLEVEL%
-3
View File
@@ -22,6 +22,3 @@ tasks {
}
}
}
java.sourceCompatibility = JavaVersion.VERSION_17
java.targetCompatibility = JavaVersion.VERSION_17