129 Commits

Author SHA1 Message Date
Ismael Hanbel
511017ab35 #3396: Update Netty version 2022-11-12 11:52:30 +11:00
floge07
c3e8cfac79 #3374, #3389: Improve log handling of normal java.util Logger usage by forwarding the LogRecords directly to the BungeeLogger instead of the fallback err stream. 2022-11-12 11:51:14 +11:00
rgnter
bf2b3c68f8 #3384: Update documentation of ProxyPingEvent 2022-11-12 11:43:29 +11:00
Outfluencer
68e74a8c03 #3378: Remove KickStringWriter from the pipeline after handshake arrives 2022-11-12 11:41:10 +11:00
Outfluencer
5b4a540440 #3361: Cache MessageFormats for translations 2022-11-12 11:39:31 +11:00
osfanbuff63
88da5c05c7 #3353: Update GitHub actions
Updates `actions/checkout` and `actions/setup-java` to v3.
2022-11-12 11:34:17 +11:00
md_5
2d369e8945 Update SnakeYAML version 2022-10-02 09:18:42 +11:00
md_5
02548c4b9b Update Netty/SnakeYAML version 2022-09-22 10:16:27 +10:00
Outfluencer
71990e3ccc #3387: Use the correct write method for ChatChain in ClientCommand 2022-08-27 07:40:18 +10:00
Outfluencer
5e7dcc48b9 #3382: Use the correct write method for ChatChain in ClientChat packet 2022-08-20 16:22:14 +10:00
Outfluencer
5cdba87b87 #3377: Add additional checks for protocol length limits 2022-08-16 19:26:33 +10:00
Outfluencer
696315615d #3366: Improve consistency and appearance of default translations 2022-08-14 11:34:00 +10:00
Outfluencer
dd3f820040 #3363, #3369: Implement new ServerData packet to stop MOTD data from servers 2022-08-14 11:32:35 +10:00
md_5
78ca16dfe3 Minecraft 1.19.1 support 2022-07-28 04:00:00 +10:00
Noah
adc32d5a5c #3367: Add linux aarch64 native epoll support 2022-07-23 18:53:52 +10:00
Outfluencer
12e4514813 #3355,#3357: Fix possible NPE's in LoginEvent & PreLoginEvent 2022-07-12 21:47:57 +10:00
Ivan Pekov
587fb37bdf #3192, #3210: Handle null ServerPing#getPlayers upon a legacy ping 2022-07-02 10:35:54 +10:00
Kevin Ludwig
d221e52929 #3241: Support ping passthrough for legacy pings 2022-07-02 10:27:36 +10:00
FlorianMichael
e151a6cf92 #3156: Add kick module 2022-07-02 10:11:09 +10:00
Outfluencer
9ced5ce131 #3287: Fix HttpHandler calls done method twice 2022-07-02 10:02:16 +10:00
tsuoihito
c8e876bfe2 #3342: Fix sanitized address being not IP but hostname after InetSocketAddress#getHostName() 2022-06-30 21:28:37 +10:00
Janmm14
2a716bbc7f #3344: Fix legacy chat conversion losing format reset information.
In legacy chat format, colors and reset do not retain any formatting.

In order to prevent this behaviour from creating unnecessary long json containing many redundant `formatting: false`, the original `fromLegacyText(...)` idea was to just override the color to white and handle the format reset just internally.

However eventual previous format rejection (aka reset) information was lost when appending multiple legacy format strings to a `ComponentBuilder`.

With this change we save the "reset wish" in the `BaseComponent` and update `ComponentBuilder`'s append function to not copy over formatting if the component has the reset flag set.
2022-06-30 21:22:16 +10:00
Janmm14
00590b6c0d #3343: Create GitHub issue templates 2022-06-30 21:18:12 +10:00
md_5
2ff4be7846 Update gson to 2.8.9 2022-06-28 21:40:53 +10:00
md_5
ff5727c5ef Revert broken chat PR and align with Spigot 2022-06-08 19:37:15 +10:00
Brokkonaut
e46bc343e4 #3319: Do not forward cancelled messages or handled commands 2022-06-08 17:44:08 +10:00
Lukas Alt
5972fd2353 #3318: Fixed system messages shown in action bar for MC 1.19 clients 2022-06-08 11:23:41 +10:00
bob7l
8c0e4b1d33 #3315: Further fix for offline mode support 2022-06-08 10:05:06 +10:00
md_5
a737a754d1 Downgrade dependency version 2022-06-08 09:01:05 +10:00
md_5
fc8685a042 #3311: Fix chat handling on older versions 2022-06-08 08:30:37 +10:00
md_5
cc4765b4fe #3313: Fix offline mode support 2022-06-08 08:22:46 +10:00
md_5
eccdf87f22 Minecraft 1.19 support 2022-06-08 02:00:00 +10:00
md_5
862bb2ac72 #3258: Only show detailed connect exception to admins 2022-04-09 08:59:01 +10:00
Outfluencer
34d416a4e8 #3261: Remove unused AttributeKeys
These attribute keys are not used so we can remove them
2022-03-19 10:05:23 +11:00
Outfluencer
410f64bc9f #3268: Correct plugin message size check 2022-03-19 10:04:45 +11:00
Outfluencer
978e68fc74 #3265: Print all thrown exception
DecoderExceptions that are not a CorruptedFrameException and dont have BadPacketException or OverflowPacketException as cause are not printed.
I also removed the ID message in BadPacketException because bad packet does not mean it has a invalid id the protocol version can also be not valid or the packet was not read to the end and more details are in the message of the exception
2022-03-19 10:04:40 +11:00
Outfluencer
a17d8f8a66 #3264: Negative packet ids are also outside of range 2022-03-09 11:21:07 +11:00
md_5
7e47490e70 Minecraft 1.18.2 support 2022-03-01 02:00:00 +11:00
nnnnt21
f4f94d3b56 #3256: Allow - and . in online mode as some accounts still have these usernames 2022-02-24 08:06:10 +11:00
md_5
eae9d45c8a Provide more information in connect errors 2022-02-06 08:44:55 +11:00
md_5
d2d157c1fe #3246: Fix commands not working due to MinecraftForge changes 2022-02-06 08:26:09 +11:00
Outfluencer
9c95d4ba43 #3226: Add console command name tab completion 2022-01-02 10:13:48 +11:00
md_5
6cbd7404f4 Fix checkstyle paren pad settings 2022-01-02 10:13:48 +11:00
md_5
ad8a8ef5a9 Increase per-listener event bus warning time 2022-01-01 09:22:26 +11:00
md_5
e6766a1ee2 Update README date 2022-01-01 08:50:50 +11:00
Janmm14
b4ccdaa51c #2715: Improve BadPacketException message in MinecraftDecoder 2021-12-19 09:54:37 +11:00
Janmm14
3a11656909 #3116: Do not fill in LogRecord caller data by default in slf4j wrapper 2021-12-19 09:53:13 +11:00
Janmm14
2479fab632 #3221: Use computeIfAbsent method in EventBus 2021-12-19 09:50:48 +11:00
md_5
51eb1ac623 Dependency upgrades 2021-12-18 12:18:21 +11:00
md_5
879f37f046 Upgrade to SnakeYAML 1.30 release 2021-12-18 11:36:05 +11:00
md_5
f2aadd6014 #3223: Only rewrite spectate packet if no IP forwarding 2021-12-13 08:25:54 +11:00
md_5
1ad81504ca Update native cipher 2021-12-10 15:54:39 +11:00
Janmm14
425ee4e142 #3215: Add time measurement per event listener method 2021-12-05 08:51:33 +11:00
Valtn
42d8300bb7 #3220: Fix server list info being cached permanently 2021-12-05 08:04:26 +11:00
md_5
a9d75c5255 Minecraft 1.18 support 2021-12-01 03:00:00 +11:00
md_5
98afd548d1 Minecraft 1.18-rc3 support 2021-11-27 08:00:00 +11:00
md_5
7fc256dba7 Minecraft 1.18-pre8 support 2021-11-25 08:00:00 +11:00
md_5
21b23624ad #3159: Account for the (broken) configuration when ip forward is enabled on bungee but not the server 2021-11-23 15:27:31 +11:00
md_5
1ace5c0c8b Trial snapshot SnakeYAML version 2021-11-23 08:30:38 +11:00
md_5
bee99beab1 Downgrade to Checkstyle 8.x as 9.x series has much larger memory usage 2021-11-22 15:27:24 +11:00
md_5
8b363d3d1f Minecraft 1.18-pre5 support 2021-11-22 09:00:00 +11:00
PSNRigner
c7b0c3cd48 #3207: Rework the plugin message relaying system to allow unregistering channels 2021-11-12 19:38:47 +11:00
md_5
c0c9b28582 Update snapshot support to 1.18-pre1 2021-11-12 19:37:57 +11:00
Frank van der Heijden
c3fffbc919 #3205: Don't forward tab completions if the root command is a bungee command 2021-11-04 18:45:11 +11:00
md_5
6613aaea95 Add test fix for library classes being visible to non-dependent plugins 2021-10-09 18:02:58 +11:00
riku6460
53ce6b93a2 #3200: Fix protocol for 21w40a 2021-10-09 18:00:36 +11:00
Janmm14
d8e293842f #2466: Use switch in "BungeeCord" plugin message handling 2021-10-09 09:25:29 +11:00
MrMicky
5cf869df1a #3198: Remove terminally deprecated SecurityManager
See https://openjdk.java.net/jeps/411
2021-10-09 09:25:29 +11:00
md_5
f26f7d8809 Add optional 1.18 (21w40a) snapshot protocol support
Accessible via the net.md_5.bungee.protocol.snapshot JVM property.
2021-10-09 09:25:28 +11:00
Outfluencer
c5a90475af #3195: Remove unused translations
Both translations are not used in BungeeCord or any modules.
2021-09-25 08:10:28 +10:00
Outfluencer
3008d7ef2f #3189: Improve username validation 2021-09-25 08:09:47 +10:00
Outfluencer
1823f86dbb #3190: Improve login protocol state machine
Prevents repetition of packets
2021-09-17 18:16:01 +10:00
Janmm14
06bf088d27 #3186: Replace String.format calls in exceptions with simple string concats 2021-09-17 18:14:21 +10:00
md_5
9953698a7c Add GitHub Java 17 build 2021-09-16 07:43:13 +10:00
md_5
bda1605627 Minor formatting fixes 2021-07-22 11:46:41 +10:00
Outfluencer
2e0e88db0d #3158: Remove redundant protocol version check in the TabCompleteResponse packet
No need for the second if in the read and write method use a else instead
2021-07-22 11:43:03 +10:00
Outfluencer
96482cc0cf #3157: Read only 20 chars for clients below 1.13 in PluginMessages
20 chars is the vanilla limit for all clients below 1.13. We should use this value.
2021-07-22 11:42:48 +10:00
Outfluencer
a283aaf724 #3153: Add color support to the end command 2021-07-18 10:22:17 +10:00
Adrian Antkowiak
5db276eb52 #3147: HAProxyMessage.sourceAddress() can be null
.sourceAddress() is null when send-proxy-v2 & check option is used
2021-07-11 09:06:51 +10:00
md_5
c866619f56 Minecraft 1.17.1 support 2021-07-07 00:00:00 +10:00
Outfluencer
b9da505efe #3142: Remove redundant name length check in InitialHandler
This check is not needed anymore as the player gets kicked while reading the LoginRequest packet if the name length is longer than 16
2021-07-04 09:40:47 +10:00
md_5
061a7c67bd Update checkstyle 2021-07-03 11:17:12 +10:00
Ivan Pekov
6f7331e852 #3138, 3140: Check for the new leak detector netty flag 2021-06-30 19:00:22 +10:00
md_5
1b489bcc11 Attempt to fix java 8 native crash 2021-06-26 11:39:53 +10:00
md_5
da27924a49 #3115, #3125: Update natives build script, switch to Cloudflare zlib 2021-06-26 11:31:05 +10:00
Outfluencer
15b39887c5 #3133: Directly disconnect on illegal chars 2021-06-26 10:09:17 +10:00
Janmm14
f9583a7652 #3129: Replace ConnectTimeoutException with a more user-friendly string. 2021-06-26 10:06:12 +10:00
Janmm14
cb738188de #3126: Use suppliers instead of reflection for native impl generation. 2021-06-26 10:01:30 +10:00
Outfluencer
a8b2f5268d #3123: Apply exact vanilla string length limits for tab completion 2021-06-20 08:51:55 +10:00
Outfluencer
ad50fc9ad3 #3111: Check chat for illegal chars & moved length check into the packet class 2021-06-15 09:07:20 +10:00
md_5
a25c2b325b Fix typo in previous commit 2021-06-13 11:26:18 +10:00
md_5
c57bf61114 #3113: Remove unnecessary slice in PacketDecompressor
Thanks @lokha for the profiling and suggestion.
2021-06-13 08:32:25 +10:00
md_5
b7935d4b14 Downgrade SnakeYAML due to issues with comments parsing 2021-06-11 21:13:42 +10:00
Janmm14
00982f3620 #3104: Use lambdas rather than reflection to create packets 2021-06-11 16:55:02 +10:00
Lukas Alt
088b2045d0 #3109: Made file log level configurable 2021-06-10 08:42:48 +10:00
Antoine L
633ff1cfc8 #3107: Fix action bar messages in 1.17 2021-06-09 18:58:20 +10:00
md_5
6cda6b6c10 Update SnakeYAML and Netty 2021-06-09 18:56:38 +10:00
md_5
90573625f1 Minecraft 1.17 support 2021-06-09 09:00:00 +10:00
Janmm14
d49e97c423 #3099: Improve toArray calls by using an empty array as parameter.
From Intellij IDEA inspections: Since late updates of OpenJDK 6 this call was intrinsified, making the performance of the empty array version the same and sometimes even better, compared to the pre-sized version.
2021-05-28 08:23:43 +10:00
md_5
39a80e414e #3093: Support names with '.', block names with ' ' 2021-05-26 10:31:37 +10:00
md_5
ab9153ddc3 Further increase length limit for TO_CLIENT chat packets 2021-05-26 10:31:26 +10:00
md_5
7ec1f487c1 Remove ipv6 scope from forwarded addresses
Affects forwarding when epoll enabled
2021-05-25 18:42:10 +10:00
md_5
c96628b72e #3094: Fix TO_CLIENT max Chat string length 2021-05-21 17:45:55 +10:00
md_5
e5ded9a2fb Apply stricter length limits to client strings
Also bump snapshot version and remove redundant file header
2021-05-21 08:16:55 +10:00
md_5
5823f47467 #3090: Register events in parent classes 2021-05-19 18:41:09 +10:00
Janmm14
a0b7f09252 #3087: Force-enable multi-release jar file support for JDK9+ via System property 2021-05-18 20:34:53 +10:00
md_5
b60a30c705 Move additional dependencies to runtime scope 2021-05-16 18:09:04 +10:00
md_5
4fc1a9e770 Dependency bump 2021-05-15 17:22:35 +10:00
md_5
f0908b663f Add optional 1.17 (21w19a) snapshot protocol support
Accessible via the net.md_5.bungee.protocol.snapshot JVM property.
2021-05-15 09:31:07 +10:00
md_5
5fa596fee9 #3084: (Regrettably) add a full SLF4J wrapper 2021-05-14 08:51:09 +10:00
md_5
ada1b95ffc Remove redundant entity rewriting code on > 1.16.2 2021-05-12 07:59:50 +10:00
Luck
72b3bdf676 #3077: Fix regression preventing child classloaders delegating to a PluginClassloader
Bug was introduced in 425dd45109
2021-05-01 08:32:51 +10:00
Janmm14
71d1246374 #3066: Put ReadTimeoutHandler after frame decoder.
This reduces the impact of attacks that send a large packet size first and then send data very slowly but frequently enough to not trigger a timeout (as the timeout handler was before the Varint21FrameDecoder). This causes connections to stay open for a long time without much effort from an attacker, while the packet never leaves the Varint21FrameDecpder stage of the netty pipeline (causing no additional checks to happen and no logs of the connection to be created).

This will not have an impact on bad connections as without recieving full packets the underlying spigot server would timeout instead.
2021-04-28 16:52:00 +10:00
_tomcraft
ac371bb596 #3073: Release HAProxyMessage after read 2021-04-28 08:07:17 +10:00
md_5
830ee8f27d #3061: Continue to fallback to underlying URLClassLoader 2021-04-10 07:30:17 +10:00
md_5
425dd45109 Override classloader close method for completeness 2021-04-09 15:38:21 +10:00
md_5
6a039de8db Add preview of automatic library support
Example plugin.yml usage:
```
    libraries:
      - com.squareup.okhttp3:okhttp:4.9.0
```

Libraries will only be accessible to plugins and their transitive depends, allowing for multiple versions of the same library to be used by different plugins.

This is a preview feature. Feedback is welcome so that it may be refined before being made widely available.
2021-04-09 13:13:55 +10:00
md_5
8d783aa172 #3058: Remove world limit 2021-04-06 08:18:58 +10:00
md_5
a4e5f5005b Add full support for building on JDK [15,) 2021-04-04 17:24:23 +10:00
Zach Levis
a7c6edeb63 #3041: Respond to login query requests in a way that matches the Vanilla client 2021-02-26 11:28:05 +11:00
Janmm14
4f23b49fef #3037: Update ProxiedPlayer#setDisplayName javadoc to current behaviour 2021-02-14 09:37:07 +11:00
md_5
cfcc8b1a6f Pin GitHub workflow build to ubuntu-20.04 2021-02-14 09:35:07 +11:00
md_5
ebec582ce2 Add full support for building on JDK [8, 14] 2021-02-14 09:29:55 +11:00
md_5
3d701fbe0e #3028: Add protocol level string length limits 2021-01-25 15:54:27 +11:00
md_5
e95da11115 Bump Netty/SnakeYAML/MySQL versions 2021-01-24 08:56:07 +11:00
md_5
9f6a798ea6 Bump version to 1.16-R0.5-SNAPSHOT 2021-01-15 10:19:24 +11:00
md_5
36c8df4d2f Release 1.16-R0.4 2021-01-15 09:49:36 +11:00
blablubbabc
baf2f60850 #3018: Serialize text component properties in the same order as Minecraft 2021-01-13 10:17:16 +11:00
md_5
9ac39005f8 Update README date 2021-01-12 09:06:25 +11:00
131 changed files with 4116 additions and 1170 deletions

63
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -0,0 +1,63 @@
name: Bug inside BungeeCord
description: Create a bug report about a problem inside BungeeCord.
body:
- type: markdown
attributes:
value: |
#### Report a bug inside bungeecord
Issues happening with forks of BungeeCord should **not** be reported here.
- type: input
id: bungee-version
attributes:
label: Bungeecord version
description: The output of the /bungee command (or just the bungee build number) (execute in bungeecord console for easy text copy)
placeholder: e.g. git:BungeeCord-Bootstrap:1.xx-SNAPSHOT:xxxxxxx:xxxx
validations:
required: true
- type: input
id: server-version
attributes:
label: Server version
description: The output of the /version command (execute in server console for easy text copy)
placeholder: "e.g. git-Spigot-xxxxxxx-xxxxxxx (MC: 1.x.x)"
- type: input
id: client-version
attributes:
label: Client version
description: Minecraft Client Version
placeholder: e.g. 1.18.2
- type: textarea
id: bungee-plugins
attributes:
label: Bungeecord plugins
description: Please list all BungeeCord plugins you are using.
validations:
required: true
- type: textarea
id: the-bug
attributes:
label: The bug
description: Please describe the bug. Include **details** you find neccessary. If you just have a question, please ask it in [SpigotMC Forums](https://www.spigotmc.org) and not here.
validations:
required: true
- type: textarea
id: logs
attributes:
label: Log output (links)
description: Please put your log output inbetween three backticks (```` ``` ````). Upload your log files to [gist.github.com](https://gist.github.com) and put them in here.
placeholder: |
```
log output
```
- type: checkboxes
id: checkboxes
attributes:
label: Checking
options:
- label: I am using BungeeCord and **not a fork**. Issues with forks should not be reported here.
required: true
- label: I think this is **not** an issue with a bungeecord plugin.
required: true
- label: I have not read these checkboxes and therefore I just ticked them all.
- label: This is not a question or plugin creation help request.
required: true

14
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,14 @@
blank_issues_enabled: false
contact_links:
- name: Configuration help
url: https://www.spigotmc.org/forums/bungeecord-help.70/create-thread
about: Help for configuring bungeecord will only be answered in spigotmc.org forums.
- name: I have a problem with a bungee plugin
url: https://www.spigotmc.org/forums/bungeecord-plugin-help.71/create-thread
about: Help about plugins can be recieved in spigotmc.org forums.
- name: Questions and discussions
url: https://www.spigotmc.org/forums/bungeecord-discussion.21/create-thread
about: spigotmc.org forums are the best place to ask your questions regarding bungeecord.
- name: Plugin creation help
url: https://www.spigotmc.org/forums/bungeecord-plugin-development.23/create-thread
about: Plugin creation help for bungee plugins can be recieved in spigotmc.org forums.

View File

@@ -0,0 +1,36 @@
name: Feature request
description: Suggest a feature which bungeecord should include.
body:
- type: textarea
id: the-feature
attributes:
label: Feature description
description: Please describe your feature or improvement. Please include **details**.
validations:
required: true
- type: textarea
id: goal
attributes:
label: Goal of the feature
description: What is the goal of your feature?
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Unfitting alternatives
description: What alternatives have you considered and why are they not sufficient for your use case?
validations:
required: true
- type: checkboxes
id: checkboxes
attributes:
label: Checking
options:
- label: This is not a question or plugin creation help request.
required: true
- label: This is a **feature or improvement request**.
required: true
- label: I have not read these checkboxes and therefore I just ticked them all.
- label: I did not use this form to report a bug.
required: true

View File

@@ -4,18 +4,20 @@ on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
strategy:
fail-fast: false
matrix:
java: [8, 11]
java: [8, 11, 17]
name: Java ${{ matrix.java }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
distribution: zulu
java-version: ${{ matrix.java }}
- run: java -version && mvn --version
- run: mvn --activate-profiles dist --no-transfer-progress package

6
.gitmodules vendored Normal file
View File

@@ -0,0 +1,6 @@
[submodule "native/mbedtls"]
path = native/mbedtls
url = https://github.com/ARMmbed/mbedtls.git
[submodule "native/zlib"]
path = native/zlib
url = https://github.com/cloudflare/zlib.git

View File

@@ -23,4 +23,4 @@ Binaries
--------
Precompiled binaries are available for end users on [Jenkins](https://www.spigotmc.org/go/bungeecord-dl).
(c) 2012-2020 SpigotMC Pty. Ltd.
(c) 2012-2022 SpigotMC Pty. Ltd.

View File

@@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-API</name>
@@ -49,10 +49,31 @@
<version>${netty.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-resolver-provider</artifactId>
<version>3.8.5</version>
<!-- not part of the API proper -->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-connector-basic</artifactId>
<version>1.7.3</version>
<!-- not part of the API proper -->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-transport-http</artifactId>
<version>1.7.3</version>
<!-- not part of the API proper -->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.26</version>
<version>1.33</version>
<scope>compile</scope>
</dependency>
</dependencies>

View File

@@ -7,6 +7,7 @@ import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Locale;
import java.util.UUID;
/**
@@ -68,6 +69,17 @@ public class Util
return String.format( "0x%02X", i );
}
/**
* Formats an char as a unicode value.
*
* @param c the character to format
* @return the unicode representation of the character
*/
public static String unicode(char c)
{
return "\\u" + String.format( "%04x", (int) c ).toUpperCase( Locale.ROOT );
}
/**
* Constructs a pretty one line version of a {@link Throwable}. Useful for
* debugging.
@@ -76,11 +88,24 @@ public class Util
* @return a string representing information about the {@link Throwable}
*/
public static String exception(Throwable t)
{
return exception( t, true );
}
/**
* Constructs a pretty one line version of a {@link Throwable}. Useful for
* debugging.
*
* @param t the {@link Throwable} to format.
* @param includeLineNumbers whether to include line numbers
* @return a string representing information about the {@link Throwable}
*/
public static String exception(Throwable t, boolean includeLineNumbers)
{
// TODO: We should use clear manually written exceptions
StackTraceElement[] trace = t.getStackTrace();
return t.getClass().getSimpleName() + " : " + t.getMessage()
+ ( ( trace.length > 0 ) ? " @ " + t.getStackTrace()[0].getClassName() + ":" + t.getStackTrace()[0].getLineNumber() : "" );
+ ( ( includeLineNumbers && trace.length > 0 ) ? " @ " + t.getStackTrace()[0].getClassName() + ":" + t.getStackTrace()[0].getLineNumber() : "" );
}
public static String csv(Iterable<?> objects)

View File

@@ -28,18 +28,13 @@ public abstract class AbstractReconnectHandler implements ReconnectHandler
public static ServerInfo getForcedHost(PendingConnection con)
{
if ( con.getVirtualHost() == null )
{
return null;
}
String forced = con.getListener().getForcedHosts().get( con.getVirtualHost().getHostString() );
String forced = ( con.getVirtualHost() == null ) ? null : con.getListener().getForcedHosts().get( con.getVirtualHost().getHostString() );
if ( forced == null && con.getListener().isForceDefault() )
{
forced = con.getListener().getDefaultServer();
}
return ProxyServer.getInstance().getServerInfo( forced );
return ( forced == null ) ? null : ProxyServer.getInstance().getServerInfo( forced );
}
protected abstract ServerInfo getStoredServer(ProxiedPlayer player);

View File

@@ -57,8 +57,7 @@ public interface ProxiedPlayer extends Connection, CommandSender
String getDisplayName();
/**
* Sets this players display name to be used as their nametag and tab list
* name.
* Sets this player's display name to be used by proxy commands and plugins.
*
* @param name the name to set
*/

View File

@@ -8,7 +8,7 @@ import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.connection.PendingConnection;
/**
* Called when the proxy is pinged with packet 0xFE from the server list.
* Called when the proxy is queried for status from the server list.
*/
@Data
@ToString(callSuper = false)

View File

@@ -0,0 +1,123 @@
package net.md_5.bungee.api.plugin;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.collection.CollectRequest;
import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.impl.DefaultServiceLocator;
import org.eclipse.aether.repository.LocalRepository;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.repository.RepositoryPolicy;
import org.eclipse.aether.resolution.ArtifactResult;
import org.eclipse.aether.resolution.DependencyRequest;
import org.eclipse.aether.resolution.DependencyResolutionException;
import org.eclipse.aether.resolution.DependencyResult;
import org.eclipse.aether.spi.connector.RepositoryConnectorFactory;
import org.eclipse.aether.spi.connector.transport.TransporterFactory;
import org.eclipse.aether.transfer.AbstractTransferListener;
import org.eclipse.aether.transfer.TransferCancelledException;
import org.eclipse.aether.transfer.TransferEvent;
import org.eclipse.aether.transport.http.HttpTransporterFactory;
class LibraryLoader
{
private final Logger logger;
private final RepositorySystem repository;
private final DefaultRepositorySystemSession session;
private final List<RemoteRepository> repositories;
public LibraryLoader(Logger logger)
{
this.logger = logger;
DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator();
locator.addService( RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class );
locator.addService( TransporterFactory.class, HttpTransporterFactory.class );
this.repository = locator.getService( RepositorySystem.class );
this.session = MavenRepositorySystemUtils.newSession();
session.setChecksumPolicy( RepositoryPolicy.CHECKSUM_POLICY_FAIL );
session.setLocalRepositoryManager( repository.newLocalRepositoryManager( session, new LocalRepository( "libraries" ) ) );
session.setTransferListener( new AbstractTransferListener()
{
@Override
public void transferStarted(TransferEvent event) throws TransferCancelledException
{
logger.log( Level.INFO, "Downloading {0}", event.getResource().getRepositoryUrl() + event.getResource().getResourceName() );
}
} );
session.setReadOnly();
this.repositories = repository.newResolutionRepositories( session, Arrays.asList( new RemoteRepository.Builder( "central", "default", "https://repo.maven.apache.org/maven2" ).build() ) );
}
public ClassLoader createLoader(PluginDescription desc)
{
if ( desc.getLibraries().isEmpty() )
{
return null;
}
logger.log( Level.INFO, "[{0}] Loading {1} libraries... please wait", new Object[]
{
desc.getName(), desc.getLibraries().size()
} );
List<Dependency> dependencies = new ArrayList<>();
for ( String library : desc.getLibraries() )
{
Artifact artifact = new DefaultArtifact( library );
Dependency dependency = new Dependency( artifact, null );
dependencies.add( dependency );
}
DependencyResult result;
try
{
result = repository.resolveDependencies( session, new DependencyRequest( new CollectRequest( (Dependency) null, dependencies, repositories ), null ) );
} catch ( DependencyResolutionException ex )
{
throw new RuntimeException( "Error resolving libraries", ex );
}
List<URL> jarFiles = new ArrayList<>();
for ( ArtifactResult artifact : result.getArtifactResults() )
{
File file = artifact.getArtifact().getFile();
URL url;
try
{
url = file.toURI().toURL();
} catch ( MalformedURLException ex )
{
throw new AssertionError( ex );
}
jarFiles.add( url );
logger.log( Level.INFO, "[{0}] Loaded library {1}", new Object[]
{
desc.getName(), file
} );
}
URLClassLoader loader = new URLClassLoader( jarFiles.toArray( new URL[ 0 ] ) );
return loader;
}
}

View File

@@ -1,12 +1,23 @@
package net.md_5.bungee.api.plugin;
import com.google.common.base.Preconditions;
import com.google.common.io.ByteStreams;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.CodeSigner;
import java.security.CodeSource;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import lombok.ToString;
import net.md_5.bungee.api.ProxyServer;
@ToString(of = "desc")
final class PluginClassloader extends URLClassLoader
{
@@ -14,6 +25,10 @@ final class PluginClassloader extends URLClassLoader
//
private final ProxyServer proxy;
private final PluginDescription desc;
private final JarFile jar;
private final Manifest manifest;
private final URL url;
private final ClassLoader libraryLoader;
//
private Plugin plugin;
@@ -22,11 +37,18 @@ final class PluginClassloader extends URLClassLoader
ClassLoader.registerAsParallelCapable();
}
public PluginClassloader(ProxyServer proxy, PluginDescription desc, URL[] urls)
public PluginClassloader(ProxyServer proxy, PluginDescription desc, File file, ClassLoader libraryLoader) throws IOException
{
super( urls );
super( new URL[]
{
file.toURI().toURL()
} );
this.proxy = proxy;
this.desc = desc;
this.jar = new JarFile( file );
this.manifest = jar.getManifest();
this.url = file.toURI().toURL();
this.libraryLoader = libraryLoader;
allLoaders.add( this );
}
@@ -34,17 +56,34 @@ final class PluginClassloader extends URLClassLoader
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
{
return loadClass0( name, resolve, true );
return loadClass0( name, resolve, true, true );
}
private Class<?> loadClass0(String name, boolean resolve, boolean checkOther) throws ClassNotFoundException
private Class<?> loadClass0(String name, boolean resolve, boolean checkOther, boolean checkLibraries) throws ClassNotFoundException
{
try
{
return super.loadClass( name, resolve );
Class<?> result = super.loadClass( name, resolve );
// SPIGOT-6749: Library classes will appear in the above, but we don't want to return them to other plugins
if ( checkOther || result.getClassLoader() == this )
{
return result;
}
} catch ( ClassNotFoundException ex )
{
}
if ( checkLibraries && libraryLoader != null )
{
try
{
return libraryLoader.loadClass( name );
} catch ( ClassNotFoundException ex )
{
}
}
if ( checkOther )
{
for ( PluginClassloader loader : allLoaders )
@@ -53,16 +92,81 @@ final class PluginClassloader extends URLClassLoader
{
try
{
return loader.loadClass0( name, resolve, false );
return loader.loadClass0( name, resolve, false, proxy.getPluginManager().isTransitiveDepend( desc, loader.desc ) );
} catch ( ClassNotFoundException ex )
{
}
}
}
}
throw new ClassNotFoundException( name );
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException
{
String path = name.replace( '.', '/' ).concat( ".class" );
JarEntry entry = jar.getJarEntry( path );
if ( entry != null )
{
byte[] classBytes;
try ( InputStream is = jar.getInputStream( entry ) )
{
classBytes = ByteStreams.toByteArray( is );
} catch ( IOException ex )
{
throw new ClassNotFoundException( name, ex );
}
int dot = name.lastIndexOf( '.' );
if ( dot != -1 )
{
String pkgName = name.substring( 0, dot );
if ( getPackage( pkgName ) == null )
{
try
{
if ( manifest != null )
{
definePackage( pkgName, manifest, url );
} else
{
definePackage( pkgName, null, null, null, null, null, null, null );
}
} catch ( IllegalArgumentException ex )
{
if ( getPackage( pkgName ) == null )
{
throw new IllegalStateException( "Cannot find package " + pkgName );
}
}
}
}
CodeSigner[] signers = entry.getCodeSigners();
CodeSource source = new CodeSource( url, signers );
return defineClass( name, classBytes, 0, classBytes.length, source );
}
return super.findClass( name );
}
@Override
public void close() throws IOException
{
try
{
super.close();
} finally
{
jar.close();
}
}
void init(Plugin plugin)
{
Preconditions.checkArgument( plugin != null, "plugin" );

View File

@@ -2,6 +2,8 @@ package net.md_5.bungee.api.plugin;
import java.io.File;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import lombok.AllArgsConstructor;
import lombok.Data;
@@ -48,4 +50,8 @@ public class PluginDescription
* Optional description.
*/
private String description = null;
/**
* Optional libraries.
*/
private List<String> libraries = new LinkedList<>();
}

View File

@@ -4,10 +4,12 @@ import com.google.common.base.Preconditions;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.google.common.eventbus.Subscribe;
import com.google.common.graph.GraphBuilder;
import com.google.common.graph.Graphs;
import com.google.common.graph.MutableGraph;
import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Collection;
@@ -49,6 +51,8 @@ public final class PluginManager
private final Yaml yaml;
private final EventBus eventBus;
private final Map<String, Plugin> plugins = new LinkedHashMap<>();
private final MutableGraph<String> dependencyGraph = GraphBuilder.directed().build();
private final LibraryLoader libraryLoader;
private final Map<String, Command> commandMap = new HashMap<>();
private Map<String, PluginDescription> toLoad = new HashMap<>();
private final Multimap<Plugin, Command> commandsByPlugin = ArrayListMultimap.create();
@@ -67,6 +71,17 @@ public final class PluginManager
yaml = new Yaml( yamlConstructor );
eventBus = new EventBus( proxy.getLogger() );
LibraryLoader libraryLoader = null;
try
{
libraryLoader = new LibraryLoader( proxy.getLogger() );
} catch ( NoClassDefFoundError ex )
{
// Provided depends were not added back
proxy.getLogger().warning( "Could not initialize LibraryLoader (missing dependencies?)" );
}
this.libraryLoader = libraryLoader;
}
/**
@@ -309,6 +324,7 @@ public final class PluginManager
status = false;
}
dependencyGraph.putEdge( plugin.getName(), dependName );
if ( !status )
{
break;
@@ -320,10 +336,7 @@ public final class PluginManager
{
try
{
URLClassLoader loader = new PluginClassloader( proxy, plugin, new URL[]
{
plugin.getFile().toURI().toURL()
} );
URLClassLoader loader = new PluginClassloader( proxy, plugin, plugin.getFile(), ( libraryLoader != null ) ? libraryLoader.createLoader( plugin ) : null );
Class<?> main = loader.loadClass( plugin.getMain() );
Plugin clazz = (Plugin) main.getDeclaredConstructor().newInstance();
@@ -335,7 +348,7 @@ public final class PluginManager
} );
} catch ( Throwable t )
{
proxy.getLogger().log( Level.WARNING, "Error enabling plugin " + plugin.getName(), t );
proxy.getLogger().log( Level.WARNING, "Error loading plugin " + plugin.getName(), t );
}
}
@@ -463,4 +476,19 @@ public final class PluginManager
{
return Collections.unmodifiableCollection( commandMap.entrySet() );
}
boolean isTransitiveDepend(PluginDescription plugin, PluginDescription depend)
{
Preconditions.checkArgument( plugin != null, "plugin" );
Preconditions.checkArgument( depend != null, "depend" );
if ( dependencyGraph.nodes().contains( plugin.getName() ) )
{
if ( Graphs.reachableNodes( dependencyGraph, plugin.getName() ).contains( depend.getName() ) )
{
return true;
}
}
return false;
}
}

View File

@@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-bootstrap</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Bootstrap</name>
@@ -79,4 +79,25 @@
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>jdk-9-release</id>
<activation>
<jdk>[9,)</jdk>
</activation>
<properties>
<maven.compiler.release>6</maven.compiler.release>
</properties>
</profile>
<profile>
<id>jdk-12-release</id>
<activation>
<jdk>[12,)</jdk>
</activation>
<properties>
<maven.compiler.release>7</maven.compiler.release>
</properties>
</profile>
</profiles>
</project>

View File

@@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-chat</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Chat</name>
@@ -22,7 +22,7 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.0</version>
<version>2.8.9</version>
<scope>compile</scope>
</dependency>
</dependencies>

View File

@@ -300,7 +300,7 @@ public final class ChatColor
@Deprecated
public static ChatColor[] values()
{
return BY_CHAR.values().toArray( new ChatColor[ BY_CHAR.values().size() ] );
return BY_CHAR.values().toArray( new ChatColor[ 0 ] );
}
/**

View File

@@ -78,6 +78,12 @@ public abstract class BaseComponent
@Getter
private HoverEvent hoverEvent;
/**
* Whether this component rejects previous formatting
*/
@Getter
private transient boolean reset;
/**
* Default constructor.
*

View File

@@ -57,7 +57,7 @@ public final class ComponentBuilder
*/
public ComponentBuilder(ComponentBuilder original)
{
this( original.parts.toArray( new BaseComponent[ original.parts.size() ] ) );
this( original.parts.toArray( new BaseComponent[ 0 ] ) );
}
/**
@@ -161,7 +161,7 @@ public final class ComponentBuilder
previous = dummy;
dummy = null;
}
if ( previous != null )
if ( previous != null && !component.isReset() )
{
component.copyFormatting( previous, retention, false );
}

View File

@@ -44,7 +44,7 @@ public final class TextComponent extends BaseComponent
*/
public static BaseComponent[] fromLegacyText(String message, ChatColor defaultColor)
{
ArrayList<BaseComponent> components = new ArrayList<BaseComponent>();
ArrayList<BaseComponent> components = new ArrayList<>();
StringBuilder builder = new StringBuilder();
TextComponent component = new TextComponent();
Matcher matcher = url.matcher( message );
@@ -111,15 +111,15 @@ public final class TextComponent extends BaseComponent
} else if ( format == ChatColor.MAGIC )
{
component.setObfuscated( true );
} else if ( format == ChatColor.RESET )
{
format = defaultColor;
component = new TextComponent();
component.setColor( format );
} else
{
if ( format == ChatColor.RESET )
{
format = defaultColor;
}
component = new TextComponent();
component.setColor( format );
component.setReset( true );
}
continue;
}
@@ -157,7 +157,7 @@ public final class TextComponent extends BaseComponent
component.setText( builder.toString() );
components.add( component );
return components.toArray( new BaseComponent[ components.size() ] );
return components.toArray( new BaseComponent[ 0 ] );
}
/**
@@ -230,6 +230,6 @@ public final class TextComponent extends BaseComponent
@Override
public String toString()
{
return String.format( "TextComponent{text=%s, %s}", text, super.toString() );
return "TextComponent{text=" + text + ", " + super.toString() + '}';
}
}

View File

@@ -22,14 +22,6 @@ public class BaseComponentSerializer
protected void deserialize(JsonObject object, BaseComponent component, JsonDeserializationContext context)
{
if ( object.has( "color" ) )
{
component.setColor( ChatColor.of( object.get( "color" ).getAsString() ) );
}
if ( object.has( "font" ) )
{
component.setFont( object.get( "font" ).getAsString() );
}
if ( object.has( "bold" ) )
{
component.setBold( object.get( "bold" ).getAsBoolean() );
@@ -50,14 +42,14 @@ public class BaseComponentSerializer
{
component.setObfuscated( object.get( "obfuscated" ).getAsBoolean() );
}
if ( object.has( "color" ) )
{
component.setColor( ChatColor.of( object.get( "color" ).getAsString() ) );
}
if ( object.has( "insertion" ) )
{
component.setInsertion( object.get( "insertion" ).getAsString() );
}
if ( object.has( "extra" ) )
{
component.setExtra( Arrays.asList( context.<BaseComponent[]>deserialize( object.get( "extra" ), BaseComponent[].class ) ) );
}
//Events
if ( object.has( "clickEvent" ) )
@@ -93,7 +85,7 @@ public class BaseComponentSerializer
{
components = new BaseComponent[]
{
context.deserialize( contents, BaseComponent.class )
context.deserialize( contents, BaseComponent.class )
};
}
hoverEvent = new HoverEvent( action, components );
@@ -121,6 +113,15 @@ public class BaseComponentSerializer
component.setHoverEvent( hoverEvent );
}
}
if ( object.has( "font" ) )
{
component.setFont( object.get( "font" ).getAsString() );
}
if ( object.has( "extra" ) )
{
component.setExtra( Arrays.asList( context.<BaseComponent[]>deserialize( object.get( "extra" ), BaseComponent[].class ) ) );
}
}
protected void serialize(JsonObject object, BaseComponent component, JsonSerializationContext context)
@@ -135,14 +136,6 @@ public class BaseComponentSerializer
{
Preconditions.checkArgument( !ComponentSerializer.serializedComponents.get().contains( component ), "Component loop" );
ComponentSerializer.serializedComponents.get().add( component );
if ( component.getColorRaw() != null )
{
object.addProperty( "color", component.getColorRaw().getName() );
}
if ( component.getFontRaw() != null )
{
object.addProperty( "font", component.getFontRaw() );
}
if ( component.isBoldRaw() != null )
{
object.addProperty( "bold", component.isBoldRaw() );
@@ -163,16 +156,15 @@ public class BaseComponentSerializer
{
object.addProperty( "obfuscated", component.isObfuscatedRaw() );
}
if ( component.getColorRaw() != null )
{
object.addProperty( "color", component.getColorRaw().getName() );
}
if ( component.getInsertion() != null )
{
object.addProperty( "insertion", component.getInsertion() );
}
if ( component.getExtra() != null )
{
object.add( "extra", context.serialize( component.getExtra() ) );
}
//Events
if ( component.getClickEvent() != null )
{
@@ -195,6 +187,15 @@ public class BaseComponentSerializer
}
object.add( "hoverEvent", hoverEvent );
}
if ( component.getFontRaw() != null )
{
object.addProperty( "font", component.getFontRaw() );
}
if ( component.getExtra() != null )
{
object.add( "extra", context.serialize( component.getExtra() ) );
}
} finally
{
ComponentSerializer.serializedComponents.get().remove( component );

View File

@@ -8,8 +8,6 @@ import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
import java.util.List;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TextComponent;
public class TextComponentSerializer extends BaseComponentSerializer implements JsonSerializer<TextComponent>, JsonDeserializer<TextComponent>
@@ -32,13 +30,9 @@ public class TextComponentSerializer extends BaseComponentSerializer implements
@Override
public JsonElement serialize(TextComponent src, Type typeOfSrc, JsonSerializationContext context)
{
List<BaseComponent> extra = src.getExtra();
JsonObject object = new JsonObject();
serialize( object, src, context );
object.addProperty( "text", src.getText() );
if ( src.hasFormatting() || ( extra != null && !extra.isEmpty() ) )
{
serialize( object, src, context );
}
return object;
}
}

View File

@@ -41,7 +41,7 @@ public class ComponentsTest
{
textComponent
} );
json = "{\"text\":\"Test\",\"hoverEvent\":{\"action\":\"show_item\",\"value\":[{\"text\":\"{id:\\\"minecraft:netherrack\\\",Count:47b}\"}]}}";
json = "{\"hoverEvent\":{\"action\":\"show_item\",\"value\":[{\"text\":\"{id:\\\"minecraft:netherrack\\\",Count:47b}\"}]},\"text\":\"Test\"}";
testDissembleReassemble( json );
//////////
String hoverVal = "{\"text\":\"{id:\\\"minecraft:dirt\\\",Count:1b}\"}";
@@ -572,7 +572,37 @@ public class ComponentsTest
Assert.assertArrayEquals( hexColored, reColored );
}
private String fromAndToLegacyText(String legacyText)
/**
* In legacy chat, colors and reset both reset all formatting.
* Make sure it works in combination with ComponentBuilder.
*/
@Test
public void testLegacyResetInBuilder()
{
ComponentBuilder builder = new ComponentBuilder();
BaseComponent[] a = TextComponent.fromLegacyText( "§4§n44444§rdd§6§l6666" );
String expected = "{\"extra\":[{\"underlined\":true,\"color\":\"dark_red\",\"text\":\"44444\"},{\"color\":"
+ "\"white\",\"text\":\"dd\"},{\"bold\":true,\"color\":\"gold\",\"text\":\"6666\"}],\"text\":\"\"}";
Assert.assertEquals( expected, ComponentSerializer.toString( a ) );
builder.append( a );
String test1 = ComponentSerializer.toString( builder.create() );
Assert.assertEquals( expected, test1 );
BaseComponent[] b = TextComponent.fromLegacyText( "§rrrrr" );
builder.append( b );
String test2 = ComponentSerializer.toString( builder.create() );
Assert.assertEquals(
"{\"extra\":[{\"underlined\":true,\"color\":\"dark_red\",\"text\":\"44444\"},"
+ "{\"color\":\"white\",\"text\":\"dd\"},{\"bold\":true,\"color\":\"gold\",\"text\":\"6666\"},"
+ "{\"color\":\"white\",\"text\":\"rrrr\"}],\"text\":\"\"}",
test2 );
}
private static String fromAndToLegacyText(String legacyText)
{
return BaseComponent.toLegacyText( TextComponent.fromLegacyText( legacyText ) );
}

View File

@@ -33,6 +33,7 @@
<!-- See http://checkstyle.sourceforge.net/config_filters.html -->
<module name="SuppressionCommentFilter"/>
<module name="SuppressWarningsHolder"/>
<!-- See http://checkstyle.sourceforge.net/config_imports.html -->
<module name="AvoidStarImport"/>
@@ -54,11 +55,11 @@
<module name="OperatorWrap"/>
<module name="ParenPad">
<property name="option" value="nospace"/>
<property name="tokens" value="ANNOTATION, CTOR_DEF, METHOD_DEF"/>
<property name="tokens" value="ANNOTATION, CTOR_DEF, METHOD_DEF, LAMBDA"/>
</module>
<module name="ParenPad">
<property name="option" value="space"/>
<property name="tokens" value="ANNOTATION_FIELD_DEF, CTOR_CALL, DOT, ENUM_CONSTANT_DEF, EXPR, LITERAL_CATCH, LITERAL_DO, LITERAL_FOR, LITERAL_IF, LITERAL_NEW, LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_WHILE, METHOD_CALL, QUESTION, RESOURCE_SPECIFICATION, SUPER_CTOR_CALL, LAMBDA"/>
<property name="tokens" value="ANNOTATION_FIELD_DEF, CTOR_CALL, DOT, ENUM_CONSTANT_DEF, EXPR, LITERAL_CATCH, LITERAL_DO, LITERAL_FOR, LITERAL_IF, LITERAL_NEW, LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_WHILE, METHOD_CALL, QUESTION, RESOURCE_SPECIFICATION, SUPER_CTOR_CALL, RECORD_DEF"/>
</module>
<module name="SingleSpaceSeparator"/>
<module name="TypecastParenPad"/>
@@ -84,4 +85,6 @@
<module name="Indentation"/>
<module name="UpperEll"/>
</module>
<module name="SuppressWarningsFilter"/>
</module>

View File

@@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-config</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Config</name>
@@ -22,14 +22,14 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.0</version>
<version>2.8.9</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.26</version>
<version>1.33</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>

View File

@@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-event</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Event</name>

View File

@@ -1,5 +1,6 @@
package net.md_5.bungee.event;
import com.google.common.collect.ImmutableSet;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.MessageFormat;
@@ -41,6 +42,8 @@ public class EventBus
{
for ( EventHandlerMethod method : handlers )
{
long start = System.nanoTime();
try
{
method.invoke( event );
@@ -54,6 +57,15 @@ public class EventBus
{
logger.log( Level.WARNING, MessageFormat.format( "Error dispatching event {0} to listener {1}", event, method.getListener() ), ex.getCause() );
}
long elapsed = System.nanoTime() - start;
if ( elapsed > 50000000 )
{
logger.log( Level.WARNING, "Plugin listener {0} took {1}ms to process event {2}!", new Object[]
{
method.getListener().getClass().getName(), elapsed / 1000000, event
} );
}
}
}
}
@@ -61,7 +73,8 @@ public class EventBus
private Map<Class<?>, Map<Byte, Set<Method>>> findHandlers(Object listener)
{
Map<Class<?>, Map<Byte, Set<Method>>> handler = new HashMap<>();
for ( Method m : listener.getClass().getDeclaredMethods() )
Set<Method> methods = ImmutableSet.<Method>builder().add( listener.getClass().getMethods() ).add( listener.getClass().getDeclaredMethods() ).build();
for ( final Method m : methods )
{
EventHandler annotation = m.getAnnotation( EventHandler.class );
if ( annotation != null )
@@ -75,18 +88,8 @@ public class EventBus
} );
continue;
}
Map<Byte, Set<Method>> prioritiesMap = handler.get( params[0] );
if ( prioritiesMap == null )
{
prioritiesMap = new HashMap<>();
handler.put( params[0], prioritiesMap );
}
Set<Method> priority = prioritiesMap.get( annotation.priority() );
if ( priority == null )
{
priority = new HashSet<>();
prioritiesMap.put( annotation.priority(), priority );
}
Map<Byte, Set<Method>> prioritiesMap = handler.computeIfAbsent( params[0], k -> new HashMap<>() );
Set<Method> priority = prioritiesMap.computeIfAbsent( annotation.priority(), k -> new HashSet<>() );
priority.add( m );
}
}
@@ -101,22 +104,11 @@ public class EventBus
{
for ( Map.Entry<Class<?>, Map<Byte, Set<Method>>> e : handler.entrySet() )
{
Map<Byte, Map<Object, Method[]>> prioritiesMap = byListenerAndPriority.get( e.getKey() );
if ( prioritiesMap == null )
{
prioritiesMap = new HashMap<>();
byListenerAndPriority.put( e.getKey(), prioritiesMap );
}
Map<Byte, Map<Object, Method[]>> prioritiesMap = byListenerAndPriority.computeIfAbsent( e.getKey(), k -> new HashMap<>() );
for ( Map.Entry<Byte, Set<Method>> entry : e.getValue().entrySet() )
{
Map<Object, Method[]> currentPriorityMap = prioritiesMap.get( entry.getKey() );
if ( currentPriorityMap == null )
{
currentPriorityMap = new HashMap<>();
prioritiesMap.put( entry.getKey(), currentPriorityMap );
}
Method[] baked = new Method[ entry.getValue().size() ];
currentPriorityMap.put( listener, entry.getValue().toArray( baked ) );
Map<Object, Method[]> currentPriorityMap = prioritiesMap.computeIfAbsent( entry.getKey(), k -> new HashMap<>() );
currentPriorityMap.put( listener, entry.getValue().toArray( new Method[ 0 ] ) );
}
bakeHandlers( e.getKey() );
}
@@ -194,7 +186,7 @@ public class EventBus
}
}
} while ( value++ < Byte.MAX_VALUE );
byEventBaked.put( eventClass, handlersList.toArray( new EventHandlerMethod[ handlersList.size() ] ) );
byEventBaked.put( eventClass, handlersList.toArray( new EventHandlerMethod[ 0 ] ) );
} else
{
byEventBaked.remove( eventClass );

View File

@@ -0,0 +1,26 @@
package net.md_5.bungee.event;
import java.util.concurrent.CountDownLatch;
import org.junit.Assert;
import org.junit.Test;
public class SubclassTest extends EventBusTest
{
private final CountDownLatch latch = new CountDownLatch( 1 );
@Test
@Override
public void testNestedEvents()
{
super.testNestedEvents();
Assert.assertEquals( 0, latch.getCount() );
}
@EventHandler
protected void extraListener(FirstEvent event)
{
Assert.assertEquals( 1, latch.getCount() );
latch.countDown();
}
}

View File

@@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-log</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Log</name>

View File

@@ -13,19 +13,23 @@ public class BungeeLogger extends Logger
private final LogDispatcher dispatcher = new LogDispatcher( this );
// CHECKSTYLE:OFF
@SuppressWarnings(
{
"CallToPrintStackTrace", "CallToThreadStartDuringObjectConstruction"
})
// CHECKSTYLE:ON
@SuppressFBWarnings("SC_START_IN_CTOR")
public BungeeLogger(String loggerName, String filePattern, ConsoleReader reader)
{
super( loggerName, null );
setLevel( Level.ALL );
setUseParentHandlers( false );
try
{
FileHandler fileHandler = new FileHandler( filePattern, 1 << 24, 8, true );
fileHandler.setLevel( Level.parse( System.getProperty( "net.md_5.bungee.file-log-level", "INFO" ) ) );
fileHandler.setFormatter( new ConciseFormatter( false ) );
addHandler( fileHandler );

View File

@@ -0,0 +1,29 @@
package net.md_5.bungee.log;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class LoggingForwardHandler extends Handler
{
private final Logger logger;
@Override
public void publish(LogRecord record)
{
logger.log( record );
}
@Override
public void flush()
{
}
@Override
public void close() throws SecurityException
{
}
}

View File

@@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module-cmd-alert</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>cmd_alert</name>

View File

@@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module-cmd-find</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>cmd_find</name>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-shared-configuration>
<!--
This file contains additional configuration written by modules in the NetBeans IDE.
The configuration is intended to be shared among all the users of project and
therefore it is assumed to be part of version control checkout.
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
-->
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
<!--
Properties that influence various parts of the IDE, especially code formatting and the like.
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
That way multiple projects can share the same settings (useful for formatting rules for example).
Any value defined here will override the pom.xml file value but is only applicable to the current project.
-->
<org-netbeans-modules-editor-indent.CodeStyle.usedProfile>project</org-netbeans-modules-editor-indent.CodeStyle.usedProfile>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>
</properties>
</project-shared-configuration>

20
module/cmd-kick/pom.xml Normal file
View File

@@ -0,0 +1,20 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module</artifactId>
<version>1.19-R0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module-cmd-kick</artifactId>
<version>1.19-R0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>cmd_kick</name>
<description>Provides the gkick command</description>
</project>

View File

@@ -0,0 +1,72 @@
package net.md_5.bungee.module.cmd.kick;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.api.plugin.TabExecutor;
public class CommandKick extends Command implements TabExecutor
{
public CommandKick()
{
super( "gkick", "bungeecord.command.kick" );
}
@Override
public void execute(CommandSender sender, String[] args)
{
if ( args.length == 0 )
{
sender.sendMessage( ProxyServer.getInstance().getTranslation( "username_needed" ) );
} else
{
ProxiedPlayer player = ProxyServer.getInstance().getPlayer( args[0] );
if ( player == null )
{
sender.sendMessage( TextComponent.fromLegacyText( ProxyServer.getInstance().getTranslation( "user_not_online" ) ) );
return;
}
if ( args.length == 1 )
{
player.disconnect( TextComponent.fromLegacyText( ProxyServer.getInstance().getTranslation( "kick_message" ) ) );
} else
{
String[] reason = new String[ args.length - 1 ];
System.arraycopy( args, 1, reason, 0, reason.length );
player.disconnect( TextComponent.fromLegacyText( ChatColor.translateAlternateColorCodes( '&', Joiner.on( ' ' ).join( reason ) ) ) );
}
}
}
@Override
public Iterable<String> onTabComplete(CommandSender sender, String[] args)
{
if ( args.length == 1 )
{
Set<String> matches = new HashSet<>();
String search = args[0].toLowerCase( Locale.ROOT );
for ( ProxiedPlayer player : ProxyServer.getInstance().getPlayers() )
{
if ( player.getName().toLowerCase( Locale.ROOT ).startsWith( search ) )
{
matches.add( player.getName() );
}
}
return matches;
} else
{
return ImmutableSet.of();
}
}
}

View File

@@ -0,0 +1,13 @@
package net.md_5.bungee.module.cmd.kick;
import net.md_5.bungee.api.plugin.Plugin;
public class PluginKick extends Plugin
{
@Override
public void onEnable()
{
getProxy().getPluginManager().registerCommand( this, new CommandKick() );
}
}

View File

@@ -0,0 +1,5 @@
name: ${project.name}
main: net.md_5.bungee.module.cmd.kick.PluginKick
version: ${describe}
description: ${project.description}
author: ${module.author}

View File

@@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module-cmd-list</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>cmd_list</name>

View File

@@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module-cmd-send</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>cmd_send</name>

View File

@@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module-cmd-server</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>cmd_server</name>

View File

@@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>BungeeCord Modules</name>
@@ -21,6 +21,7 @@
<modules>
<module>cmd-alert</module>
<module>cmd-find</module>
<module>cmd-kick</module>
<module>cmd-list</module>
<module>cmd-send</module>
<module>cmd-server</module>

View File

@@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module-reconnect-yaml</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>reconnect_yaml</name>

View File

@@ -1,6 +1,14 @@
#!/bin/sh
CXX="g++ -shared -fPIC -O3 -Wall -Werror -I$JAVA_HOME/include/ -I$JAVA_HOME/include/linux/"
set -eu
$CXX src/main/c/NativeCipherImpl.cpp -o src/main/resources/native-cipher.so -lcrypto
$CXX src/main/c/NativeCompressImpl.cpp -o src/main/resources/native-compress.so -lz
echo "Compiling mbedtls"
(cd mbedtls && make no_test)
echo "Compiling zlib"
(cd zlib && CFLAGS=-fPIC ./configure --static && make)
CXX="g++ -shared -fPIC -Wl,--wrap=memcpy -O3 -Wall -Werror -I$JAVA_HOME/include/ -I$JAVA_HOME/include/linux/"
$CXX -Imbedtls/include src/main/c/NativeCipherImpl.cpp -o src/main/resources/native-cipher.so mbedtls/library/libmbedcrypto.a
$CXX -Izlib src/main/c/NativeCompressImpl.cpp -o src/main/resources/native-compress.so zlib/libz.a

1
native/mbedtls Submodule

Submodule native/mbedtls added at 8df2f8e7b9

View File

@@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-native</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Native</name>

View File

@@ -1,12 +1,15 @@
// Support for CentOS 6
__asm__(".symver memcpy,memcpy@GLIBC_2.2.5");
#include <stdlib.h>
#include <string.h>
#include <mbedtls/aes.h>
#include "net_md_5_bungee_jni_cipher_NativeCipherImpl.h"
// Support for CentOS 6
__asm__(".symver memcpy,memcpy@GLIBC_2.2.5");
extern "C" void *__wrap_memcpy(void *dest, const void *src, size_t n) {
return memcpy(dest, src, n);
}
typedef unsigned char byte;
struct crypto_context {

View File

@@ -1,7 +1,15 @@
#include <stdlib.h>
#include <string.h>
#include <zlib.h>
#include "net_md_5_bungee_jni_zlib_NativeCompressImpl.h"
// Support for CentOS 6
__asm__(".symver memcpy,memcpy@GLIBC_2.2.5");
extern "C" void *__wrap_memcpy(void *dest, const void *src, size_t n) {
return memcpy(dest, src, n);
}
typedef unsigned char byte;
static jfieldID consumedID;

View File

@@ -6,18 +6,19 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.function.Supplier;
import net.md_5.bungee.jni.cipher.BungeeCipher;
public final class NativeCode<T>
{
private final String name;
private final Class<? extends T> javaImpl;
private final Class<? extends T> nativeImpl;
private final Supplier<? extends T> javaImpl;
private final Supplier<? extends T> nativeImpl;
//
private boolean loaded;
public NativeCode(String name, Class<? extends T> javaImpl, Class<? extends T> nativeImpl)
public NativeCode(String name, Supplier<? extends T> javaImpl, Supplier<? extends T> nativeImpl)
{
this.name = name;
this.javaImpl = javaImpl;
@@ -26,13 +27,7 @@ public final class NativeCode<T>
public T newInstance()
{
try
{
return ( loaded ) ? nativeImpl.getDeclaredConstructor().newInstance() : javaImpl.getDeclaredConstructor().newInstance();
} catch ( ReflectiveOperationException ex )
{
throw new RuntimeException( "Error getting instance", ex );
}
return ( loaded ) ? nativeImpl.get() : javaImpl.get();
}
public boolean load()

View File

@@ -25,9 +25,15 @@ public class JavaCipher implements BungeeCipher
}
}
public JavaCipher() throws GeneralSecurityException
public JavaCipher()
{
this.cipher = Cipher.getInstance( "AES/CFB8/NoPadding" );
try
{
this.cipher = Cipher.getInstance( "AES/CFB8/NoPadding" );
} catch ( GeneralSecurityException ex )
{
throw new RuntimeException( ex );
}
}
@Override

View File

@@ -26,7 +26,7 @@ public class NativeCipherTest
private final SecretKey secret = new SecretKeySpec( new byte[ 16 ], "AES" );
private static final int BENCHMARK_COUNT = 4096;
//
private static final NativeCode<BungeeCipher> factory = new NativeCode<>( "native-cipher", JavaCipher.class, NativeCipher.class );
private static final NativeCode<BungeeCipher> factory = new NativeCode<>( "native-cipher", JavaCipher::new, NativeCipher::new );
@Test
public void testNative() throws Exception

View File

@@ -15,7 +15,7 @@ import org.junit.Test;
public class NativeZlibTest
{
private final NativeCode<BungeeZlib> factory = new NativeCode<>( "native-compress", JavaZlib.class, NativeZlib.class );
private final NativeCode<BungeeZlib> factory = new NativeCode<>( "native-compress", JavaZlib::new, NativeZlib::new );
@Test
public void doTest() throws DataFormatException

1
native/zlib Submodule

Submodule native/zlib added at 959b4ea305

79
pom.xml
View File

@@ -5,7 +5,7 @@
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>BungeeCord-Parent</name>
@@ -41,6 +41,7 @@
<module>protocol</module>
<module>proxy</module>
<module>query</module>
<module>slf4j</module>
<module>native</module>
</modules>
@@ -71,7 +72,8 @@
<properties>
<build.number>unknown</build.number>
<netty.version>4.1.53.Final</netty.version>
<lombok.version>1.18.22</lombok.version>
<netty.version>4.1.85.Final</netty.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -81,13 +83,13 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>21.0</version>
<version>31.0.1-jre</version>
<scope>compile</scope>
</dependency>
<dependency>
@@ -99,7 +101,7 @@
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
@@ -122,10 +124,15 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.1.1</version>
<version>3.1.2</version>
<executions>
<execution>
<phase>process-classes</phase>
@@ -143,14 +150,14 @@
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>8.36.2</version>
<version>8.45.1</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
<version>1.19</version>
<version>1.20</version>
<executions>
<execution>
<phase>process-classes</phase>
@@ -171,6 +178,53 @@
</build>
<profiles>
<profile>
<id>jdk-9-release</id>
<activation>
<jdk>[9,)</jdk>
</activation>
<properties>
<maven.compiler.release>8</maven.compiler.release>
</properties>
</profile>
<profile>
<id>jdk-9-javadoc</id>
<activation>
<jdk>[9,)</jdk>
</activation>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<additionalOptions>-html5</additionalOptions>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
<profile>
<id>jdk-15-javadoc</id>
<activation>
<jdk>[15,)</jdk>
</activation>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<doclint>none</doclint>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
<profile>
<id>dist</id>
<build>
@@ -191,7 +245,7 @@
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>1.18.10.0</version>
<version>1.18.20.0</version>
<executions>
<execution>
<phase>package</phase>
@@ -205,6 +259,13 @@
<outputDirectory>${project.build.directory}/delombok</outputDirectory>
<sourceDirectory>${project.build.sourceDirectory}</sourceDirectory>
</configuration>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>

View File

@@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-protocol</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Protocol</name>

View File

@@ -2,6 +2,9 @@ package net.md_5.bungee.protocol;
import net.md_5.bungee.protocol.packet.BossBar;
import net.md_5.bungee.protocol.packet.Chat;
import net.md_5.bungee.protocol.packet.ClearTitles;
import net.md_5.bungee.protocol.packet.ClientChat;
import net.md_5.bungee.protocol.packet.ClientCommand;
import net.md_5.bungee.protocol.packet.ClientSettings;
import net.md_5.bungee.protocol.packet.ClientStatus;
import net.md_5.bungee.protocol.packet.Commands;
@@ -27,13 +30,17 @@ import net.md_5.bungee.protocol.packet.Respawn;
import net.md_5.bungee.protocol.packet.ScoreboardDisplay;
import net.md_5.bungee.protocol.packet.ScoreboardObjective;
import net.md_5.bungee.protocol.packet.ScoreboardScore;
import net.md_5.bungee.protocol.packet.ServerData;
import net.md_5.bungee.protocol.packet.SetCompression;
import net.md_5.bungee.protocol.packet.StatusRequest;
import net.md_5.bungee.protocol.packet.StatusResponse;
import net.md_5.bungee.protocol.packet.Subtitle;
import net.md_5.bungee.protocol.packet.SystemChat;
import net.md_5.bungee.protocol.packet.TabCompleteRequest;
import net.md_5.bungee.protocol.packet.TabCompleteResponse;
import net.md_5.bungee.protocol.packet.Team;
import net.md_5.bungee.protocol.packet.Title;
import net.md_5.bungee.protocol.packet.TitleTimes;
import net.md_5.bungee.protocol.packet.ViewDistance;
public abstract class AbstractPacketHandler
@@ -75,6 +82,18 @@ public abstract class AbstractPacketHandler
{
}
public void handle(ClientChat chat) throws Exception
{
}
public void handle(SystemChat chat) throws Exception
{
}
public void handle(ClientCommand command) throws Exception
{
}
public void handle(Respawn respawn) throws Exception
{
}
@@ -127,6 +146,18 @@ public abstract class AbstractPacketHandler
{
}
public void handle(Subtitle title) throws Exception
{
}
public void handle(TitleTimes title) throws Exception
{
}
public void handle(ClearTitles title) throws Exception
{
}
public void handle(PluginMessage pluginMessage) throws Exception
{
}
@@ -178,4 +209,8 @@ public abstract class AbstractPacketHandler
public void handle(GameState gameState) throws Exception
{
}
public void handle(ServerData serverData) throws Exception
{
}
}

View File

@@ -0,0 +1,82 @@
package net.md_5.bungee.protocol;
import com.google.common.base.Preconditions;
import io.netty.buffer.ByteBuf;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class ChatChain extends DefinedPacket
{
private List<ChainLink> seen;
private List<ChainLink> received;
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
seen = readLinks( buf );
if ( buf.readBoolean() )
{
received = readLinks( buf );
}
}
private static List<ChainLink> readLinks(ByteBuf buf)
{
int cnt = readVarInt( buf );
Preconditions.checkArgument( cnt <= 5, "Too many entries" );
List<ChainLink> chain = new LinkedList<>();
for ( int i = 0; i < cnt; i++ )
{
chain.add( new ChainLink( readUUID( buf ), readArray( buf ) ) );
}
return chain;
}
@Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
writeLinks( seen, buf );
if ( received != null )
{
buf.writeBoolean( true );
writeLinks( received, buf );
} else
{
buf.writeBoolean( false );
}
}
private static void writeLinks(List<ChainLink> links, ByteBuf buf)
{
writeVarInt( links.size(), buf );
for ( ChainLink link : links )
{
writeUUID( link.sender, buf );
writeArray( link.signature, buf );
}
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
throw new UnsupportedOperationException( "Not supported." );
}
@Data
public static class ChainLink
{
private final UUID sender;
private final byte[] signature;
}
}

View File

@@ -21,35 +21,55 @@ public abstract class DefinedPacket
public static void writeString(String s, ByteBuf buf)
{
if ( s.length() > Short.MAX_VALUE )
writeString( s, buf, Short.MAX_VALUE );
}
public static void writeString(String s, ByteBuf buf, int maxLength)
{
if ( s.length() > maxLength )
{
throw new OverflowPacketException( String.format( "Cannot send string longer than Short.MAX_VALUE (got %s characters)", s.length() ) );
throw new OverflowPacketException( "Cannot send string longer than " + maxLength + " (got " + s.length() + " characters)" );
}
byte[] b = s.getBytes( Charsets.UTF_8 );
if ( b.length > maxLength * 3 )
{
throw new OverflowPacketException( "Cannot send string longer than " + ( maxLength * 3 ) + " (got " + b.length + " bytes)" );
}
writeVarInt( b.length, buf );
buf.writeBytes( b );
}
public static String readString(ByteBuf buf)
{
return readString( buf, Short.MAX_VALUE );
}
public static String readString(ByteBuf buf, int maxLen)
{
int len = readVarInt( buf );
if ( len > Short.MAX_VALUE )
if ( len > maxLen * 3 )
{
throw new OverflowPacketException( String.format( "Cannot receive string longer than Short.MAX_VALUE (got %s characters)", len ) );
throw new OverflowPacketException( "Cannot receive string longer than " + maxLen * 3 + " (got " + len + " bytes)" );
}
byte[] b = new byte[ len ];
buf.readBytes( b );
String s = buf.toString( buf.readerIndex(), len, Charsets.UTF_8 );
buf.readerIndex( buf.readerIndex() + len );
return new String( b, Charsets.UTF_8 );
if ( s.length() > maxLen )
{
throw new OverflowPacketException( "Cannot receive string longer than " + maxLen + " (got " + s.length() + " characters)" );
}
return s;
}
public static void writeArray(byte[] b, ByteBuf buf)
{
if ( b.length > Short.MAX_VALUE )
{
throw new OverflowPacketException( String.format( "Cannot send byte array longer than Short.MAX_VALUE (got %s bytes)", b.length ) );
throw new OverflowPacketException( "Cannot send byte array longer than Short.MAX_VALUE (got " + b.length + " bytes)" );
}
writeVarInt( b.length, buf );
buf.writeBytes( b );
@@ -73,7 +93,7 @@ public abstract class DefinedPacket
int len = readVarInt( buf );
if ( len > limit )
{
throw new OverflowPacketException( String.format( "Cannot receive byte array longer than %s (got %s bytes)", limit, len ) );
throw new OverflowPacketException( "Cannot receive byte array longer than " + limit + " (got " + len + " bytes)" );
}
byte[] ret = new byte[ len ];
buf.readBytes( ret );
@@ -203,6 +223,73 @@ public abstract class DefinedPacket
return new UUID( input.readLong(), input.readLong() );
}
public static void writeProperties(Property[] properties, ByteBuf buf)
{
if ( properties == null )
{
writeVarInt( 0, buf );
return;
}
writeVarInt( properties.length, buf );
for ( Property prop : properties )
{
writeString( prop.getName(), buf );
writeString( prop.getValue(), buf );
if ( prop.getSignature() != null )
{
buf.writeBoolean( true );
writeString( prop.getSignature(), buf );
} else
{
buf.writeBoolean( false );
}
}
}
public static Property[] readProperties(ByteBuf buf)
{
Property[] properties = new Property[ DefinedPacket.readVarInt( buf ) ];
for ( int j = 0; j < properties.length; j++ )
{
String name = readString( buf );
String value = readString( buf );
if ( buf.readBoolean() )
{
properties[j] = new Property( name, value, DefinedPacket.readString( buf ) );
} else
{
properties[j] = new Property( name, value );
}
}
return properties;
}
public static void writePublicKey(PlayerPublicKey publicKey, ByteBuf buf)
{
if ( publicKey != null )
{
buf.writeBoolean( true );
buf.writeLong( publicKey.getExpiry() );
writeArray( publicKey.getKey(), buf );
writeArray( publicKey.getSignature(), buf );
} else
{
buf.writeBoolean( false );
}
}
public static PlayerPublicKey readPublicKey(ByteBuf buf)
{
if ( buf.readBoolean() )
{
return new PlayerPublicKey( buf.readLong(), readArray( buf, 512 ), readArray( buf, 4096 ) );
}
return null;
}
public static Tag readTag(ByteBuf input)
{
Tag tag = NamedTag.read( new DataInputStream( new ByteBufInputStream( input ) ) );

View File

@@ -0,0 +1,11 @@
package net.md_5.bungee.protocol;
import lombok.Data;
@Data
public class Location
{
private final String dimension;
private final long pos;
}

View File

@@ -41,7 +41,7 @@ public class MinecraftDecoder extends MessageToMessageDecoder<ByteBuf>
if ( in.isReadable() )
{
throw new BadPacketException( "Did not read all bytes from packet " + packet.getClass() + " " + packetId + " Protocol " + protocol + " Direction " + prot.getDirection() );
throw new BadPacketException( "Packet " + protocol + ":" + prot.getDirection() + "/" + packetId + " (" + packet.getClass().getSimpleName() + ") larger than expected, extra bytes: " + in.readableBytes() );
}
} else
{

View File

@@ -0,0 +1,12 @@
package net.md_5.bungee.protocol;
import lombok.Data;
@Data
public class PlayerPublicKey
{
private final long expiry;
private final byte[] key;
private final byte[] signature;
}

View File

@@ -0,0 +1,19 @@
package net.md_5.bungee.protocol;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class Property
{
private String name;
private String value;
private String signature;
public Property(String name, String value)
{
this( name, value, null );
}
}

View File

@@ -6,11 +6,14 @@ import gnu.trove.map.TIntObjectMap;
import gnu.trove.map.TObjectIntMap;
import gnu.trove.map.hash.TIntObjectHashMap;
import gnu.trove.map.hash.TObjectIntHashMap;
import java.lang.reflect.Constructor;
import java.util.function.Supplier;
import lombok.Data;
import lombok.Getter;
import net.md_5.bungee.protocol.packet.BossBar;
import net.md_5.bungee.protocol.packet.Chat;
import net.md_5.bungee.protocol.packet.ClearTitles;
import net.md_5.bungee.protocol.packet.ClientChat;
import net.md_5.bungee.protocol.packet.ClientCommand;
import net.md_5.bungee.protocol.packet.ClientSettings;
import net.md_5.bungee.protocol.packet.Commands;
import net.md_5.bungee.protocol.packet.EncryptionRequest;
@@ -33,13 +36,17 @@ import net.md_5.bungee.protocol.packet.Respawn;
import net.md_5.bungee.protocol.packet.ScoreboardDisplay;
import net.md_5.bungee.protocol.packet.ScoreboardObjective;
import net.md_5.bungee.protocol.packet.ScoreboardScore;
import net.md_5.bungee.protocol.packet.ServerData;
import net.md_5.bungee.protocol.packet.SetCompression;
import net.md_5.bungee.protocol.packet.StatusRequest;
import net.md_5.bungee.protocol.packet.StatusResponse;
import net.md_5.bungee.protocol.packet.Subtitle;
import net.md_5.bungee.protocol.packet.SystemChat;
import net.md_5.bungee.protocol.packet.TabCompleteRequest;
import net.md_5.bungee.protocol.packet.TabCompleteResponse;
import net.md_5.bungee.protocol.packet.Team;
import net.md_5.bungee.protocol.packet.Title;
import net.md_5.bungee.protocol.packet.TitleTimes;
import net.md_5.bungee.protocol.packet.ViewDistance;
public enum Protocol
@@ -52,6 +59,7 @@ public enum Protocol
{
TO_SERVER.registerPacket(
Handshake.class,
Handshake::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x00 )
);
}
@@ -63,33 +71,44 @@ public enum Protocol
{
TO_CLIENT.registerPacket(
KeepAlive.class,
KeepAlive::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x00 ),
map( ProtocolConstants.MINECRAFT_1_9, 0x1F ),
map( ProtocolConstants.MINECRAFT_1_13, 0x21 ),
map( ProtocolConstants.MINECRAFT_1_14, 0x20 ),
map( ProtocolConstants.MINECRAFT_1_15, 0x21 ),
map( ProtocolConstants.MINECRAFT_1_16, 0x20 ),
map( ProtocolConstants.MINECRAFT_1_16_2, 0x1F )
map( ProtocolConstants.MINECRAFT_1_16_2, 0x1F ),
map( ProtocolConstants.MINECRAFT_1_17, 0x21 ),
map( ProtocolConstants.MINECRAFT_1_19, 0x1E ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x20 )
);
TO_CLIENT.registerPacket(
Login.class,
Login::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x01 ),
map( ProtocolConstants.MINECRAFT_1_9, 0x23 ),
map( ProtocolConstants.MINECRAFT_1_13, 0x25 ),
map( ProtocolConstants.MINECRAFT_1_15, 0x26 ),
map( ProtocolConstants.MINECRAFT_1_16, 0x25 ),
map( ProtocolConstants.MINECRAFT_1_16_2, 0x24 )
map( ProtocolConstants.MINECRAFT_1_16_2, 0x24 ),
map( ProtocolConstants.MINECRAFT_1_17, 0x26 ),
map( ProtocolConstants.MINECRAFT_1_19, 0x23 ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x25 )
);
TO_CLIENT.registerPacket(
Chat.class,
TO_CLIENT.registerPacket( Chat.class,
Chat::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x02 ),
map( ProtocolConstants.MINECRAFT_1_9, 0x0F ),
map( ProtocolConstants.MINECRAFT_1_13, 0x0E ),
map( ProtocolConstants.MINECRAFT_1_15, 0x0F ),
map( ProtocolConstants.MINECRAFT_1_16, 0x0E )
map( ProtocolConstants.MINECRAFT_1_16, 0x0E ),
map( ProtocolConstants.MINECRAFT_1_17, 0x0F ),
map( ProtocolConstants.MINECRAFT_1_19, -1 )
);
TO_CLIENT.registerPacket(
Respawn.class,
Respawn::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x07 ),
map( ProtocolConstants.MINECRAFT_1_9, 0x33 ),
map( ProtocolConstants.MINECRAFT_1_12, 0x34 ),
@@ -98,16 +117,23 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_14, 0x3A ),
map( ProtocolConstants.MINECRAFT_1_15, 0x3B ),
map( ProtocolConstants.MINECRAFT_1_16, 0x3A ),
map( ProtocolConstants.MINECRAFT_1_16_2, 0x39 )
map( ProtocolConstants.MINECRAFT_1_16_2, 0x39 ),
map( ProtocolConstants.MINECRAFT_1_17, 0x3D ),
map( ProtocolConstants.MINECRAFT_1_19, 0x3B ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x3E )
);
TO_CLIENT.registerPacket(
BossBar.class,
BossBar::new,
map( ProtocolConstants.MINECRAFT_1_9, 0x0C ),
map( ProtocolConstants.MINECRAFT_1_15, 0x0D ),
map( ProtocolConstants.MINECRAFT_1_16, 0x0C )
map( ProtocolConstants.MINECRAFT_1_16, 0x0C ),
map( ProtocolConstants.MINECRAFT_1_17, 0x0D ),
map( ProtocolConstants.MINECRAFT_1_19, 0x0A )
);
TO_CLIENT.registerPacket(
PlayerListItem.class, // PlayerInfo
PlayerListItem::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x38 ),
map( ProtocolConstants.MINECRAFT_1_9, 0x2D ),
map( ProtocolConstants.MINECRAFT_1_12_1, 0x2E ),
@@ -115,89 +141,146 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_14, 0x33 ),
map( ProtocolConstants.MINECRAFT_1_15, 0x34 ),
map( ProtocolConstants.MINECRAFT_1_16, 0x33 ),
map( ProtocolConstants.MINECRAFT_1_16_2, 0x32 )
map( ProtocolConstants.MINECRAFT_1_16_2, 0x32 ),
map( ProtocolConstants.MINECRAFT_1_17, 0x36 ),
map( ProtocolConstants.MINECRAFT_1_19, 0x34 ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x37 )
);
TO_CLIENT.registerPacket(
TabCompleteResponse.class,
TabCompleteResponse::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x3A ),
map( ProtocolConstants.MINECRAFT_1_9, 0x0E ),
map( ProtocolConstants.MINECRAFT_1_13, 0x10 ),
map( ProtocolConstants.MINECRAFT_1_15, 0x11 ),
map( ProtocolConstants.MINECRAFT_1_16, 0x10 ),
map( ProtocolConstants.MINECRAFT_1_16_2, 0x0F )
map( ProtocolConstants.MINECRAFT_1_16_2, 0x0F ),
map( ProtocolConstants.MINECRAFT_1_17, 0x11 ),
map( ProtocolConstants.MINECRAFT_1_19, 0x0E )
);
TO_CLIENT.registerPacket(
ScoreboardObjective.class,
ScoreboardObjective::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x3B ),
map( ProtocolConstants.MINECRAFT_1_9, 0x3F ),
map( ProtocolConstants.MINECRAFT_1_12, 0x41 ),
map( ProtocolConstants.MINECRAFT_1_12_1, 0x42 ),
map( ProtocolConstants.MINECRAFT_1_13, 0x45 ),
map( ProtocolConstants.MINECRAFT_1_14, 0x49 ),
map( ProtocolConstants.MINECRAFT_1_15, 0x4A )
map( ProtocolConstants.MINECRAFT_1_15, 0x4A ),
map( ProtocolConstants.MINECRAFT_1_17, 0x53 ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x56 )
);
TO_CLIENT.registerPacket(
ScoreboardScore.class,
ScoreboardScore::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x3C ),
map( ProtocolConstants.MINECRAFT_1_9, 0x42 ),
map( ProtocolConstants.MINECRAFT_1_12, 0x44 ),
map( ProtocolConstants.MINECRAFT_1_12_1, 0x45 ),
map( ProtocolConstants.MINECRAFT_1_13, 0x48 ),
map( ProtocolConstants.MINECRAFT_1_14, 0x4C ),
map( ProtocolConstants.MINECRAFT_1_15, 0x4D )
map( ProtocolConstants.MINECRAFT_1_15, 0x4D ),
map( ProtocolConstants.MINECRAFT_1_17, 0x56 ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x59 )
);
TO_CLIENT.registerPacket(
ScoreboardDisplay.class,
ScoreboardDisplay::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x3D ),
map( ProtocolConstants.MINECRAFT_1_9, 0x38 ),
map( ProtocolConstants.MINECRAFT_1_12, 0x3A ),
map( ProtocolConstants.MINECRAFT_1_12_1, 0x3B ),
map( ProtocolConstants.MINECRAFT_1_13, 0x3E ),
map( ProtocolConstants.MINECRAFT_1_14, 0x42 ),
map( ProtocolConstants.MINECRAFT_1_15, 0x43 )
map( ProtocolConstants.MINECRAFT_1_15, 0x43 ),
map( ProtocolConstants.MINECRAFT_1_17, 0x4C ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x4F )
);
TO_CLIENT.registerPacket(
Team.class,
Team::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x3E ),
map( ProtocolConstants.MINECRAFT_1_9, 0x41 ),
map( ProtocolConstants.MINECRAFT_1_12, 0x43 ),
map( ProtocolConstants.MINECRAFT_1_12_1, 0x44 ),
map( ProtocolConstants.MINECRAFT_1_13, 0x47 ),
map( ProtocolConstants.MINECRAFT_1_14, 0x4B ),
map( ProtocolConstants.MINECRAFT_1_15, 0x4C )
map( ProtocolConstants.MINECRAFT_1_15, 0x4C ),
map( ProtocolConstants.MINECRAFT_1_17, 0x55 ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x58 )
);
TO_CLIENT.registerPacket(
PluginMessage.class,
PluginMessage::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x3F ),
map( ProtocolConstants.MINECRAFT_1_9, 0x18 ),
map( ProtocolConstants.MINECRAFT_1_13, 0x19 ),
map( ProtocolConstants.MINECRAFT_1_14, 0x18 ),
map( ProtocolConstants.MINECRAFT_1_15, 0x19 ),
map( ProtocolConstants.MINECRAFT_1_16, 0x18 ),
map( ProtocolConstants.MINECRAFT_1_16_2, 0x17 )
map( ProtocolConstants.MINECRAFT_1_16_2, 0x17 ),
map( ProtocolConstants.MINECRAFT_1_17, 0x18 ),
map( ProtocolConstants.MINECRAFT_1_19, 0x15 ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x16 )
);
TO_CLIENT.registerPacket(
Kick.class,
Kick::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x40 ),
map( ProtocolConstants.MINECRAFT_1_9, 0x1A ),
map( ProtocolConstants.MINECRAFT_1_13, 0x1B ),
map( ProtocolConstants.MINECRAFT_1_14, 0x1A ),
map( ProtocolConstants.MINECRAFT_1_15, 0x1B ),
map( ProtocolConstants.MINECRAFT_1_16, 0x1A ),
map( ProtocolConstants.MINECRAFT_1_16_2, 0x19 )
map( ProtocolConstants.MINECRAFT_1_16_2, 0x19 ),
map( ProtocolConstants.MINECRAFT_1_17, 0x1A ),
map( ProtocolConstants.MINECRAFT_1_19, 0x17 ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x19 )
);
TO_CLIENT.registerPacket(
Title.class,
Title::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x45 ),
map( ProtocolConstants.MINECRAFT_1_12, 0x47 ),
map( ProtocolConstants.MINECRAFT_1_12_1, 0x48 ),
map( ProtocolConstants.MINECRAFT_1_13, 0x4B ),
map( ProtocolConstants.MINECRAFT_1_14, 0x4F ),
map( ProtocolConstants.MINECRAFT_1_15, 0x50 ),
map( ProtocolConstants.MINECRAFT_1_16, 0x4F )
map( ProtocolConstants.MINECRAFT_1_16, 0x4F ),
map( ProtocolConstants.MINECRAFT_1_17, 0x59 ),
map( ProtocolConstants.MINECRAFT_1_18, 0x5A ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x5D )
);
TO_CLIENT.registerPacket(
ClearTitles.class,
ClearTitles::new,
map( ProtocolConstants.MINECRAFT_1_17, 0x10 ),
map( ProtocolConstants.MINECRAFT_1_19, 0x0D )
);
TO_CLIENT.registerPacket(
Subtitle.class,
Subtitle::new,
map( ProtocolConstants.MINECRAFT_1_17, 0x57 ),
map( ProtocolConstants.MINECRAFT_1_18, 0x58 ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x5B )
);
TO_CLIENT.registerPacket(
TitleTimes.class,
TitleTimes::new,
map( ProtocolConstants.MINECRAFT_1_17, 0x5A ),
map( ProtocolConstants.MINECRAFT_1_18, 0x5B ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x5E )
);
TO_CLIENT.registerPacket(
SystemChat.class,
SystemChat::new,
map( ProtocolConstants.MINECRAFT_1_19, 0x5F ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x62 )
);
TO_CLIENT.registerPacket(
PlayerListHeaderFooter.class,
PlayerListHeaderFooter::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x47 ),
map( ProtocolConstants.MINECRAFT_1_9, 0x48 ),
map( ProtocolConstants.MINECRAFT_1_9_4, 0x47 ),
@@ -206,81 +289,133 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_13, 0x4E ),
map( ProtocolConstants.MINECRAFT_1_14, 0x53 ),
map( ProtocolConstants.MINECRAFT_1_15, 0x54 ),
map( ProtocolConstants.MINECRAFT_1_16, 0x53 )
map( ProtocolConstants.MINECRAFT_1_16, 0x53 ),
map( ProtocolConstants.MINECRAFT_1_17, 0x5E ),
map( ProtocolConstants.MINECRAFT_1_18, 0x5F ),
map( ProtocolConstants.MINECRAFT_1_19, 0x60 ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x63 )
);
TO_CLIENT.registerPacket(
EntityStatus.class,
EntityStatus::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x1A ),
map( ProtocolConstants.MINECRAFT_1_9, 0x1B ),
map( ProtocolConstants.MINECRAFT_1_13, 0x1C ),
map( ProtocolConstants.MINECRAFT_1_14, 0x1B ),
map( ProtocolConstants.MINECRAFT_1_15, 0x1C ),
map( ProtocolConstants.MINECRAFT_1_16, 0x1B ),
map( ProtocolConstants.MINECRAFT_1_16_2, 0x1A )
map( ProtocolConstants.MINECRAFT_1_16_2, 0x1A ),
map( ProtocolConstants.MINECRAFT_1_17, 0x1B ),
map( ProtocolConstants.MINECRAFT_1_19, 0x18 ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x1A )
);
TO_CLIENT.registerPacket(
Commands.class,
Commands::new,
map( ProtocolConstants.MINECRAFT_1_13, 0x11 ),
map( ProtocolConstants.MINECRAFT_1_15, 0x12 ),
map( ProtocolConstants.MINECRAFT_1_16, 0x11 ),
map( ProtocolConstants.MINECRAFT_1_16_2, 0x10 )
map( ProtocolConstants.MINECRAFT_1_16_2, 0x10 ),
map( ProtocolConstants.MINECRAFT_1_17, 0x12 ),
map( ProtocolConstants.MINECRAFT_1_19, 0x0F )
);
TO_CLIENT.registerPacket(
GameState.class,
GameState::new,
map( ProtocolConstants.MINECRAFT_1_15, 0x1F ),
map( ProtocolConstants.MINECRAFT_1_16, 0x1E ),
map( ProtocolConstants.MINECRAFT_1_16_2, 0x1D )
map( ProtocolConstants.MINECRAFT_1_16_2, 0x1D ),
map( ProtocolConstants.MINECRAFT_1_17, 0x1E ),
map( ProtocolConstants.MINECRAFT_1_19, 0x1B ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x1D )
);
TO_CLIENT.registerPacket(
ViewDistance.class,
ViewDistance::new,
map( ProtocolConstants.MINECRAFT_1_14, 0x41 ),
map( ProtocolConstants.MINECRAFT_1_15, 0x42 ),
map( ProtocolConstants.MINECRAFT_1_16, 0x41 )
map( ProtocolConstants.MINECRAFT_1_16, 0x41 ),
map( ProtocolConstants.MINECRAFT_1_17, 0x4A ),
map( ProtocolConstants.MINECRAFT_1_19, 0x49 ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x4C )
);
TO_CLIENT.registerPacket(
ServerData.class,
ServerData::new,
map( ProtocolConstants.MINECRAFT_1_19, 0x3F ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x42 )
);
TO_SERVER.registerPacket(
KeepAlive.class,
KeepAlive::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x00 ),
map( ProtocolConstants.MINECRAFT_1_9, 0x0B ),
map( ProtocolConstants.MINECRAFT_1_12, 0x0C ),
map( ProtocolConstants.MINECRAFT_1_12_1, 0x0B ),
map( ProtocolConstants.MINECRAFT_1_13, 0x0E ),
map( ProtocolConstants.MINECRAFT_1_14, 0x0F ),
map( ProtocolConstants.MINECRAFT_1_16, 0x10 )
map( ProtocolConstants.MINECRAFT_1_16, 0x10 ),
map( ProtocolConstants.MINECRAFT_1_17, 0x0F ),
map( ProtocolConstants.MINECRAFT_1_19, 0x11 ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x12 )
);
TO_SERVER.registerPacket(
Chat.class,
TO_SERVER.registerPacket( Chat.class,
Chat::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x01 ),
map( ProtocolConstants.MINECRAFT_1_9, 0x02 ),
map( ProtocolConstants.MINECRAFT_1_12, 0x03 ),
map( ProtocolConstants.MINECRAFT_1_12_1, 0x02 ),
map( ProtocolConstants.MINECRAFT_1_14, 0x03 )
map( ProtocolConstants.MINECRAFT_1_14, 0x03 ),
map( ProtocolConstants.MINECRAFT_1_19, -1 )
);
TO_SERVER.registerPacket(
ClientCommand.class,
ClientCommand::new,
map( ProtocolConstants.MINECRAFT_1_19, 0x03 ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x04 )
);
TO_SERVER.registerPacket(
ClientChat.class,
ClientChat::new,
map( ProtocolConstants.MINECRAFT_1_19, 0x04 ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x05 )
);
TO_SERVER.registerPacket(
TabCompleteRequest.class,
TabCompleteRequest::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x14 ),
map( ProtocolConstants.MINECRAFT_1_9, 0x01 ),
map( ProtocolConstants.MINECRAFT_1_12, 0x02 ),
map( ProtocolConstants.MINECRAFT_1_12_1, 0x01 ),
map( ProtocolConstants.MINECRAFT_1_13, 0x05 ),
map( ProtocolConstants.MINECRAFT_1_14, 0x06 )
map( ProtocolConstants.MINECRAFT_1_14, 0x06 ),
map( ProtocolConstants.MINECRAFT_1_19, 0x08 ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x09 )
);
TO_SERVER.registerPacket(
ClientSettings.class,
ClientSettings::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x15 ),
map( ProtocolConstants.MINECRAFT_1_9, 0x04 ),
map( ProtocolConstants.MINECRAFT_1_12, 0x05 ),
map( ProtocolConstants.MINECRAFT_1_12_1, 0x04 ),
map( ProtocolConstants.MINECRAFT_1_14, 0x05 )
map( ProtocolConstants.MINECRAFT_1_14, 0x05 ),
map( ProtocolConstants.MINECRAFT_1_19, 0x07 ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x08 )
);
TO_SERVER.registerPacket(
PluginMessage.class,
PluginMessage::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x17 ),
map( ProtocolConstants.MINECRAFT_1_9, 0x09 ),
map( ProtocolConstants.MINECRAFT_1_12, 0x0A ),
map( ProtocolConstants.MINECRAFT_1_12_1, 0x09 ),
map( ProtocolConstants.MINECRAFT_1_13, 0x0A ),
map( ProtocolConstants.MINECRAFT_1_14, 0x0B )
map( ProtocolConstants.MINECRAFT_1_14, 0x0B ),
map( ProtocolConstants.MINECRAFT_1_17, 0x0A ),
map( ProtocolConstants.MINECRAFT_1_19, 0x0C ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x0D )
);
}
},
@@ -291,19 +426,23 @@ public enum Protocol
{
TO_CLIENT.registerPacket(
StatusResponse.class,
StatusResponse::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x00 )
);
TO_CLIENT.registerPacket(
PingPacket.class,
PingPacket::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x01 )
);
TO_SERVER.registerPacket(
StatusRequest.class,
StatusRequest::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x00 )
);
TO_SERVER.registerPacket(
PingPacket.class,
PingPacket::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x01 )
);
}
@@ -315,35 +454,43 @@ public enum Protocol
{
TO_CLIENT.registerPacket(
Kick.class,
Kick::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x00 )
);
TO_CLIENT.registerPacket(
EncryptionRequest.class,
EncryptionRequest::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x01 )
);
TO_CLIENT.registerPacket(
LoginSuccess.class,
LoginSuccess::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x02 )
);
TO_CLIENT.registerPacket(
SetCompression.class,
SetCompression::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x03 )
);
TO_CLIENT.registerPacket(
LoginPayloadRequest.class,
LoginPayloadRequest::new,
map( ProtocolConstants.MINECRAFT_1_13, 0x04 )
);
TO_SERVER.registerPacket(
LoginRequest.class,
LoginRequest::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x00 )
);
TO_SERVER.registerPacket(
EncryptionResponse.class,
EncryptionResponse::new,
map( ProtocolConstants.MINECRAFT_1_8, 0x01 )
);
TO_SERVER.registerPacket(
LoginPayloadResponse.class,
LoginPayloadResponse::new,
map( ProtocolConstants.MINECRAFT_1_13, 0x02 )
);
}
@@ -394,7 +541,8 @@ public enum Protocol
private final int protocolVersion;
private final TObjectIntMap<Class<? extends DefinedPacket>> packetMap = new TObjectIntHashMap<>( MAX_PACKET_ID );
private final Constructor<? extends DefinedPacket>[] packetConstructors = new Constructor[ MAX_PACKET_ID ];
@SuppressWarnings("unchecked")
private final Supplier<? extends DefinedPacket>[] packetConstructors = new Supplier[ MAX_PACKET_ID ];
}
@Data
@@ -448,57 +596,49 @@ public enum Protocol
{
throw new BadPacketException( "Unsupported protocol version " + version );
}
if ( id > MAX_PACKET_ID )
if ( id > MAX_PACKET_ID || id < 0 )
{
throw new BadPacketException( "Packet with id " + id + " outside of range " );
throw new BadPacketException( "Packet with id " + id + " outside of range" );
}
Constructor<? extends DefinedPacket> constructor = protocolData.packetConstructors[id];
try
{
return ( constructor == null ) ? null : constructor.newInstance();
} catch ( ReflectiveOperationException ex )
{
throw new BadPacketException( "Could not construct packet with id " + id, ex );
}
Supplier<? extends DefinedPacket> constructor = protocolData.packetConstructors[id];
return ( constructor == null ) ? null : constructor.get();
}
private void registerPacket(Class<? extends DefinedPacket> packetClass, ProtocolMapping... mappings)
private void registerPacket(Class<? extends DefinedPacket> packetClass, Supplier<? extends DefinedPacket> constructor, ProtocolMapping... mappings)
{
try
int mappingIndex = 0;
ProtocolMapping mapping = mappings[mappingIndex];
for ( int protocol : ProtocolConstants.SUPPORTED_VERSION_IDS )
{
Constructor<? extends DefinedPacket> constructor = packetClass.getDeclaredConstructor();
int mappingIndex = 0;
ProtocolMapping mapping = mappings[mappingIndex];
for ( int protocol : ProtocolConstants.SUPPORTED_VERSION_IDS )
if ( protocol < mapping.protocolVersion )
{
if ( protocol < mapping.protocolVersion )
{
// This is a new packet, skip it till we reach the next protocol
continue;
}
if ( mapping.protocolVersion < protocol && mappingIndex + 1 < mappings.length )
{
// Mapping is non current, but the next one may be ok
ProtocolMapping nextMapping = mappings[mappingIndex + 1];
if ( nextMapping.protocolVersion == protocol )
{
Preconditions.checkState( nextMapping.packetID != mapping.packetID, "Duplicate packet mapping (%s, %s)", mapping.protocolVersion, nextMapping.protocolVersion );
mapping = nextMapping;
mappingIndex++;
}
}
ProtocolData data = protocols.get( protocol );
data.packetMap.put( packetClass, mapping.packetID );
data.packetConstructors[mapping.packetID] = constructor;
// This is a new packet, skip it till we reach the next protocol
continue;
}
} catch ( NoSuchMethodException ex )
{
throw new BadPacketException( "No NoArgsConstructor for packet class " + packetClass );
if ( mapping.protocolVersion < protocol && mappingIndex + 1 < mappings.length )
{
// Mapping is non current, but the next one may be ok
ProtocolMapping nextMapping = mappings[mappingIndex + 1];
if ( nextMapping.protocolVersion == protocol )
{
Preconditions.checkState( nextMapping.packetID != mapping.packetID, "Duplicate packet mapping (%s, %s)", mapping.protocolVersion, nextMapping.protocolVersion );
mapping = nextMapping;
mappingIndex++;
}
}
if ( mapping.packetID < 0 )
{
break;
}
ProtocolData data = protocols.get( protocol );
data.packetMap.put( packetClass, mapping.packetID );
data.packetConstructors[mapping.packetID] = constructor;
}
}

View File

@@ -1,11 +1,12 @@
package net.md_5.bungee.protocol;
import java.util.Arrays;
import com.google.common.collect.ImmutableList;
import java.util.List;
public class ProtocolConstants
{
private static final boolean SNAPSHOT_SUPPORT = Boolean.getBoolean( "net.md_5.bungee.protocol.snapshot" );
public static final int MINECRAFT_1_8 = 47;
public static final int MINECRAFT_1_9 = 107;
public static final int MINECRAFT_1_9_1 = 108;
@@ -33,46 +34,76 @@ public class ProtocolConstants
public static final int MINECRAFT_1_16_2 = 751;
public static final int MINECRAFT_1_16_3 = 753;
public static final int MINECRAFT_1_16_4 = 754;
public static final List<String> SUPPORTED_VERSIONS = Arrays.asList(
"1.8.x",
"1.9.x",
"1.10.x",
"1.11.x",
"1.12.x",
"1.13.x",
"1.14.x",
"1.15.x",
"1.16.x"
);
public static final List<Integer> SUPPORTED_VERSION_IDS = Arrays.asList(
ProtocolConstants.MINECRAFT_1_8,
ProtocolConstants.MINECRAFT_1_9,
ProtocolConstants.MINECRAFT_1_9_1,
ProtocolConstants.MINECRAFT_1_9_2,
ProtocolConstants.MINECRAFT_1_9_4,
ProtocolConstants.MINECRAFT_1_10,
ProtocolConstants.MINECRAFT_1_11,
ProtocolConstants.MINECRAFT_1_11_1,
ProtocolConstants.MINECRAFT_1_12,
ProtocolConstants.MINECRAFT_1_12_1,
ProtocolConstants.MINECRAFT_1_12_2,
ProtocolConstants.MINECRAFT_1_13,
ProtocolConstants.MINECRAFT_1_13_1,
ProtocolConstants.MINECRAFT_1_13_2,
ProtocolConstants.MINECRAFT_1_14,
ProtocolConstants.MINECRAFT_1_14_1,
ProtocolConstants.MINECRAFT_1_14_2,
ProtocolConstants.MINECRAFT_1_14_3,
ProtocolConstants.MINECRAFT_1_14_4,
ProtocolConstants.MINECRAFT_1_15,
ProtocolConstants.MINECRAFT_1_15_1,
ProtocolConstants.MINECRAFT_1_15_2,
ProtocolConstants.MINECRAFT_1_16,
ProtocolConstants.MINECRAFT_1_16_1,
ProtocolConstants.MINECRAFT_1_16_2,
ProtocolConstants.MINECRAFT_1_16_3,
ProtocolConstants.MINECRAFT_1_16_4
);
public static final int MINECRAFT_1_17 = 755;
public static final int MINECRAFT_1_17_1 = 756;
public static final int MINECRAFT_1_18 = 757;
public static final int MINECRAFT_1_18_2 = 758;
public static final int MINECRAFT_1_19 = 759;
public static final int MINECRAFT_1_19_1 = 760;
public static final List<String> SUPPORTED_VERSIONS;
public static final List<Integer> SUPPORTED_VERSION_IDS;
static
{
ImmutableList.Builder<String> supportedVersions = ImmutableList.<String>builder().add(
"1.8.x",
"1.9.x",
"1.10.x",
"1.11.x",
"1.12.x",
"1.13.x",
"1.14.x",
"1.15.x",
"1.16.x",
"1.17.x",
"1.18.x",
"1.19.x"
);
ImmutableList.Builder<Integer> supportedVersionIds = ImmutableList.<Integer>builder().add(
ProtocolConstants.MINECRAFT_1_8,
ProtocolConstants.MINECRAFT_1_9,
ProtocolConstants.MINECRAFT_1_9_1,
ProtocolConstants.MINECRAFT_1_9_2,
ProtocolConstants.MINECRAFT_1_9_4,
ProtocolConstants.MINECRAFT_1_10,
ProtocolConstants.MINECRAFT_1_11,
ProtocolConstants.MINECRAFT_1_11_1,
ProtocolConstants.MINECRAFT_1_12,
ProtocolConstants.MINECRAFT_1_12_1,
ProtocolConstants.MINECRAFT_1_12_2,
ProtocolConstants.MINECRAFT_1_13,
ProtocolConstants.MINECRAFT_1_13_1,
ProtocolConstants.MINECRAFT_1_13_2,
ProtocolConstants.MINECRAFT_1_14,
ProtocolConstants.MINECRAFT_1_14_1,
ProtocolConstants.MINECRAFT_1_14_2,
ProtocolConstants.MINECRAFT_1_14_3,
ProtocolConstants.MINECRAFT_1_14_4,
ProtocolConstants.MINECRAFT_1_15,
ProtocolConstants.MINECRAFT_1_15_1,
ProtocolConstants.MINECRAFT_1_15_2,
ProtocolConstants.MINECRAFT_1_16,
ProtocolConstants.MINECRAFT_1_16_1,
ProtocolConstants.MINECRAFT_1_16_2,
ProtocolConstants.MINECRAFT_1_16_3,
ProtocolConstants.MINECRAFT_1_16_4,
ProtocolConstants.MINECRAFT_1_17,
ProtocolConstants.MINECRAFT_1_17_1,
ProtocolConstants.MINECRAFT_1_18,
ProtocolConstants.MINECRAFT_1_18_2,
ProtocolConstants.MINECRAFT_1_19,
ProtocolConstants.MINECRAFT_1_19_1
);
if ( SNAPSHOT_SUPPORT )
{
// supportedVersions.add( "1.19.x" );
// supportedVersionIds.add( ProtocolConstants.MINECRAFT_1_19 );
}
SUPPORTED_VERSIONS = supportedVersions.build();
SUPPORTED_VERSION_IDS = supportedVersionIds.build();
}
public enum Direction
{

View File

@@ -40,7 +40,7 @@ public class Chat extends DefinedPacket
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
message = readString( buf );
message = readString( buf, ( direction == ProtocolConstants.Direction.TO_CLIENT ) ? 262144 : ( protocolVersion >= ProtocolConstants.MINECRAFT_1_11 ? 256 : 100 ) );
if ( direction == ProtocolConstants.Direction.TO_CLIENT )
{
position = buf.readByte();
@@ -54,7 +54,7 @@ public class Chat extends DefinedPacket
@Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
writeString( message, buf );
writeString( message, buf, ( direction == ProtocolConstants.Direction.TO_CLIENT ) ? 262144 : ( protocolVersion >= ProtocolConstants.MINECRAFT_1_11 ? 256 : 100 ) );
if ( direction == ProtocolConstants.Direction.TO_CLIENT )
{
buf.writeByte( position );

View File

@@ -0,0 +1,38 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.ProtocolConstants;
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class ClearTitles extends DefinedPacket
{
private boolean reset;
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
reset = buf.readBoolean();
}
@Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
buf.writeBoolean( reset );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,61 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.ChatChain;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.ProtocolConstants;
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class ClientChat extends DefinedPacket
{
private String message;
private long timestamp;
private long salt;
private byte[] signature;
private boolean signedPreview;
private ChatChain chain;
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
message = readString( buf, 256 );
timestamp = buf.readLong();
salt = buf.readLong();
signature = readArray( buf );
signedPreview = buf.readBoolean();
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 )
{
chain = new ChatChain();
chain.read( buf, direction, protocolVersion );
}
}
@Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
writeString( message, buf );
buf.writeLong( timestamp );
buf.writeLong( salt );
writeArray( signature, buf );
buf.writeBoolean( signedPreview );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 )
{
chain.write( buf, direction, protocolVersion );
}
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,79 @@
package net.md_5.bungee.protocol.packet;
import com.google.common.base.Preconditions;
import io.netty.buffer.ByteBuf;
import java.util.HashMap;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.ChatChain;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.ProtocolConstants;
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class ClientCommand extends DefinedPacket
{
private String command;
private long timestamp;
private long salt;
private Map<String, byte[]> signatures;
private boolean signedPreview;
private ChatChain chain;
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
command = readString( buf );
timestamp = buf.readLong();
salt = buf.readLong();
int cnt = readVarInt( buf );
Preconditions.checkArgument( cnt <= 8, "Too many signatures" );
signatures = new HashMap<>( cnt );
for ( int i = 0; i < cnt; i++ )
{
signatures.put( readString( buf, 16 ), readArray( buf ) );
}
signedPreview = buf.readBoolean();
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 )
{
chain = new ChatChain();
chain.read( buf, direction, protocolVersion );
}
}
@Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
writeString( command, buf );
buf.writeLong( timestamp );
buf.writeLong( salt );
writeVarInt( signatures.size(), buf );
for ( Map.Entry<String, byte[]> entry : signatures.entrySet() )
{
writeString( entry.getKey(), buf );
writeArray( entry.getValue(), buf );
}
buf.writeBoolean( signedPreview );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 )
{
chain.write( buf, direction, protocolVersion );
}
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -23,11 +23,13 @@ public class ClientSettings extends DefinedPacket
private byte difficulty;
private byte skinParts;
private int mainHand;
private boolean disableTextFiltering;
private boolean allowServerListing;
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
locale = readString( buf );
locale = readString( buf, 16 );
viewDistance = buf.readByte();
chatFlags = protocolVersion >= ProtocolConstants.MINECRAFT_1_9 ? DefinedPacket.readVarInt( buf ) : buf.readUnsignedByte();
chatColours = buf.readBoolean();
@@ -36,6 +38,14 @@ public class ClientSettings extends DefinedPacket
{
mainHand = DefinedPacket.readVarInt( buf );
}
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_17 )
{
disableTextFiltering = buf.readBoolean();
}
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_18 )
{
allowServerListing = buf.readBoolean();
}
}
@Override
@@ -56,6 +66,14 @@ public class ClientSettings extends DefinedPacket
{
DefinedPacket.writeVarInt( mainHand, buf );
}
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_17 )
{
buf.writeBoolean( disableTextFiltering );
}
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_18 )
{
buf.writeBoolean( allowServerListing );
}
}
@Override

View File

@@ -23,11 +23,13 @@ import com.mojang.brigadier.tree.LiteralCommandNode;
import com.mojang.brigadier.tree.RootCommandNode;
import io.netty.buffer.ByteBuf;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Deque;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import lombok.AllArgsConstructor;
@@ -36,6 +38,7 @@ import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.ProtocolConstants;
@Data
@NoArgsConstructor
@@ -56,7 +59,7 @@ public class Commands extends DefinedPacket
private RootCommandNode root;
@Override
public void read(ByteBuf buf)
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
int nodeCount = readVarInt( buf );
NetworkNode[] nodes = new NetworkNode[ nodeCount ];
@@ -79,9 +82,7 @@ public class Commands extends DefinedPacket
break;
case NODE_ARGUMENT:
String name = readString( buf );
String parser = readString( buf );
argumentBuilder = RequiredArgumentBuilder.argument( name, ArgumentRegistry.read( parser, buf ) );
argumentBuilder = RequiredArgumentBuilder.argument( name, ArgumentRegistry.read( buf, protocolVersion ) );
if ( ( flags & FLAG_SUGGESTIONS ) != 0 )
{
@@ -126,7 +127,7 @@ public class Commands extends DefinedPacket
}
@Override
public void write(ByteBuf buf)
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
Map<CommandNode, Integer> indexMap = new LinkedHashMap<>();
Deque<CommandNode> nodeQueue = new ArrayDeque<>();
@@ -210,7 +211,7 @@ public class Commands extends DefinedPacket
ArgumentCommandNode argumentNode = (ArgumentCommandNode) node;
writeString( argumentNode.getName(), buf );
ArgumentRegistry.write( argumentNode.getType(), buf );
ArgumentRegistry.write( argumentNode.getType(), buf, protocolVersion );
if ( argumentNode.getCustomSuggestions() != null )
{
@@ -308,6 +309,7 @@ public class Commands extends DefinedPacket
{
private static final Map<String, ArgumentSerializer> PROVIDERS = new HashMap<>();
private static final List<ArgumentSerializer> PROVIDER_LIST = new ArrayList<>();
private static final Map<Class<?>, ProperArgumentSerializer<?>> PROPER_PROVIDERS = new HashMap<>();
//
private static final ArgumentSerializer<Void> VOID = new ArgumentSerializer<Void>()
@@ -492,89 +494,142 @@ public class Commands extends DefinedPacket
writeVarInt( t.getType().ordinal(), buf );
}
@Override
protected int getIntKey()
{
return 5;
}
@Override
protected String getKey()
{
return "brigadier:string";
}
};
private static final ArgumentSerializer<String> RAW_STRING = new ArgumentSerializer<String>()
{
@Override
protected String read(ByteBuf buf)
{
return DefinedPacket.readString( buf );
}
@Override
protected void write(ByteBuf buf, String t)
{
DefinedPacket.writeString( t, buf );
}
};
static
{
PROVIDERS.put( "brigadier:bool", VOID );
PROVIDERS.put( "brigadier:float", FLOAT );
PROVIDERS.put( "brigadier:double", DOUBLE );
PROVIDERS.put( "brigadier:integer", INTEGER );
PROVIDERS.put( "brigadier:long", LONG );
register( "brigadier:bool", VOID );
register( "brigadier:float", FLOAT );
register( "brigadier:double", DOUBLE );
register( "brigadier:integer", INTEGER );
register( "brigadier:long", LONG );
PROVIDERS.put( "brigadier:string", STRING );
register( "brigadier:string", STRING );
PROPER_PROVIDERS.put( StringArgumentType.class, STRING );
PROVIDERS.put( "minecraft:entity", BYTE );
PROVIDERS.put( "minecraft:game_profile", VOID );
PROVIDERS.put( "minecraft:block_pos", VOID );
PROVIDERS.put( "minecraft:column_pos", VOID );
PROVIDERS.put( "minecraft:vec3", VOID );
PROVIDERS.put( "minecraft:vec2", VOID );
PROVIDERS.put( "minecraft:block_state", VOID );
PROVIDERS.put( "minecraft:block_predicate", VOID );
PROVIDERS.put( "minecraft:item_stack", VOID );
PROVIDERS.put( "minecraft:item_predicate", VOID );
PROVIDERS.put( "minecraft:color", VOID );
PROVIDERS.put( "minecraft:component", VOID );
PROVIDERS.put( "minecraft:message", VOID );
PROVIDERS.put( "minecraft:nbt_compound_tag", VOID ); // 1.14
PROVIDERS.put( "minecraft:nbt_tag", VOID ); // 1.14
PROVIDERS.put( "minecraft:nbt", VOID ); // 1.13
PROVIDERS.put( "minecraft:nbt_path", VOID );
PROVIDERS.put( "minecraft:objective", VOID );
PROVIDERS.put( "minecraft:objective_criteria", VOID );
PROVIDERS.put( "minecraft:operation", VOID );
PROVIDERS.put( "minecraft:particle", VOID );
PROVIDERS.put( "minecraft:rotation", VOID );
PROVIDERS.put( "minecraft:scoreboard_slot", VOID );
PROVIDERS.put( "minecraft:score_holder", BYTE );
PROVIDERS.put( "minecraft:swizzle", VOID );
PROVIDERS.put( "minecraft:team", VOID );
PROVIDERS.put( "minecraft:item_slot", VOID );
PROVIDERS.put( "minecraft:resource_location", VOID );
PROVIDERS.put( "minecraft:mob_effect", VOID );
PROVIDERS.put( "minecraft:function", VOID );
PROVIDERS.put( "minecraft:entity_anchor", VOID );
PROVIDERS.put( "minecraft:int_range", VOID );
PROVIDERS.put( "minecraft:float_range", VOID );
PROVIDERS.put( "minecraft:item_enchantment", VOID );
PROVIDERS.put( "minecraft:entity_summon", VOID );
PROVIDERS.put( "minecraft:dimension", VOID );
PROVIDERS.put( "minecraft:time", VOID ); // 1.14
PROVIDERS.put( "minecraft:uuid", VOID ); // 1.16
PROVIDERS.put( "minecraft:test_argument", VOID ); // 1.16, debug
PROVIDERS.put( "minecraft:test_class", VOID ); // 1.16, debug
PROVIDERS.put( "minecraft:angle", VOID ); // 1.16.2
register( "minecraft:entity", BYTE );
register( "minecraft:game_profile", VOID );
register( "minecraft:block_pos", VOID );
register( "minecraft:column_pos", VOID );
register( "minecraft:vec3", VOID );
register( "minecraft:vec2", VOID );
register( "minecraft:block_state", VOID );
register( "minecraft:block_predicate", VOID );
register( "minecraft:item_stack", VOID );
register( "minecraft:item_predicate", VOID );
register( "minecraft:color", VOID );
register( "minecraft:component", VOID );
register( "minecraft:message", VOID );
register( "minecraft:nbt_compound_tag", VOID ); // 1.14
register( "minecraft:nbt_tag", VOID ); // 1.14
register( "minecraft:nbt_path", VOID );
register( "minecraft:objective", VOID );
register( "minecraft:objective_criteria", VOID );
register( "minecraft:operation", VOID );
register( "minecraft:particle", VOID );
register( "minecraft:angle", VOID ); // 1.16.2
register( "minecraft:rotation", VOID );
register( "minecraft:scoreboard_slot", VOID );
register( "minecraft:score_holder", BYTE );
register( "minecraft:swizzle", VOID );
register( "minecraft:team", VOID );
register( "minecraft:item_slot", VOID );
register( "minecraft:resource_location", VOID );
register( "minecraft:mob_effect", VOID );
register( "minecraft:function", VOID );
register( "minecraft:entity_anchor", VOID );
register( "minecraft:int_range", VOID );
register( "minecraft:float_range", VOID );
register( "minecraft:item_enchantment", VOID );
register( "minecraft:entity_summon", VOID );
register( "minecraft:dimension", VOID );
register( "minecraft:time", VOID ); // 1.14
register( "minecraft:resource_or_tag", RAW_STRING ); // 1.18.2
register( "minecraft:resource", RAW_STRING ); // 1.18.2
register( "minecraft:template_mirror", VOID ); // 1.19
register( "minecraft:template_rotation", VOID ); // 1.19
register( "minecraft:uuid", VOID ); // 1.16
register( "minecraft:nbt", VOID ); // 1.13 // removed
}
private static ArgumentType<?> read(String key, ByteBuf buf)
private static void register(String name, ArgumentSerializer serializer)
{
ArgumentSerializer reader = PROVIDERS.get( key );
PROVIDERS.put( name, serializer );
PROVIDER_LIST.add( serializer );
}
private static ArgumentType<?> read(ByteBuf buf, int protocolVersion)
{
Object key;
ArgumentSerializer reader;
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 )
{
key = readVarInt( buf );
reader = PROVIDER_LIST.get( (Integer) key );
} else
{
key = readString( buf );
reader = PROVIDERS.get( (String) key );
}
Preconditions.checkArgument( reader != null, "No provider for argument " + key );
Object val = reader.read( buf );
return val != null && PROPER_PROVIDERS.containsKey( val.getClass() ) ? (ArgumentType<?>) val : new DummyType( key, reader, val );
}
private static void write(ArgumentType<?> arg, ByteBuf buf)
private static void write(ArgumentType<?> arg, ByteBuf buf, int protocolVersion)
{
ProperArgumentSerializer proper = PROPER_PROVIDERS.get( arg.getClass() );
if ( proper != null )
{
writeString( proper.getKey(), buf );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 )
{
writeVarInt( proper.getIntKey(), buf );
} else
{
writeString( proper.getKey(), buf );
}
proper.write( buf, arg );
} else
{
Preconditions.checkArgument( arg instanceof DummyType, "Non dummy arg " + arg.getClass() );
DummyType dummy = (DummyType) arg;
writeString( dummy.key, buf );
if ( dummy.key instanceof Integer )
{
writeVarInt( (Integer) dummy.key, buf );
} else
{
writeString( (String) dummy.key, buf );
}
dummy.serializer.write( buf, dummy.value );
}
}
@@ -583,7 +638,7 @@ public class Commands extends DefinedPacket
private static class DummyType<T> implements ArgumentType<T>
{
private final String key;
private final Object key;
private final ArgumentSerializer<T> serializer;
private final T value;
@@ -605,6 +660,8 @@ public class Commands extends DefinedPacket
private abstract static class ProperArgumentSerializer<T> extends ArgumentSerializer<T>
{
protected abstract int getIntKey();
protected abstract String getKey();
}
}

View File

@@ -18,19 +18,36 @@ public class EncryptionResponse extends DefinedPacket
private byte[] sharedSecret;
private byte[] verifyToken;
private EncryptionData encryptionData;
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
sharedSecret = readArray( buf, 128 );
verifyToken = readArray( buf, 128 );
if ( protocolVersion < ProtocolConstants.MINECRAFT_1_19 || buf.readBoolean() )
{
verifyToken = readArray( buf, 128 );
} else
{
encryptionData = new EncryptionData( buf.readLong(), readArray( buf ) );
}
}
@Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
writeArray( sharedSecret, buf );
writeArray( verifyToken, buf );
if ( verifyToken != null )
{
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 )
{
buf.writeBoolean( true );
}
writeArray( verifyToken, buf );
} else
{
buf.writeLong( encryptionData.getSalt() );
writeArray( encryptionData.getSignature(), buf );
}
}
@Override
@@ -38,4 +55,12 @@ public class EncryptionResponse extends DefinedPacket
{
handler.handle( this );
}
@Data
public static class EncryptionData
{
private final long salt;
private final byte[] signature;
}
}

View File

@@ -24,7 +24,7 @@ public class Handshake extends DefinedPacket
public void read(ByteBuf buf)
{
protocolVersion = readVarInt( buf );
host = readString( buf );
host = readString( buf, 255 );
port = buf.readUnsignedShort();
requestedProtocol = readVarInt( buf );
}

View File

@@ -1,6 +1,5 @@
package net.md_5.bungee.protocol.packet;
import com.google.common.base.Preconditions;
import io.netty.buffer.ByteBuf;
import java.util.HashSet;
import java.util.Set;
@@ -10,6 +9,7 @@ import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.Location;
import net.md_5.bungee.protocol.ProtocolConstants;
import se.llbit.nbt.Tag;
@@ -33,10 +33,12 @@ public class Login extends DefinedPacket
private int maxPlayers;
private String levelType;
private int viewDistance;
private int simulationDistance;
private boolean reducedDebugInfo;
private boolean normalRespawn;
private boolean debug;
private boolean flat;
private Location deathLocation;
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
@@ -53,8 +55,6 @@ public class Login extends DefinedPacket
worldNames = new HashSet<>();
int worldCount = readVarInt( buf );
Preconditions.checkArgument( worldCount < 128, "Too many worlds %s", worldCount );
for ( int i = 0; i < worldCount; i++ )
{
worldNames.add( readString( buf ) );
@@ -65,7 +65,7 @@ public class Login extends DefinedPacket
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16 )
{
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16_2 )
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16_2 && protocolVersion < ProtocolConstants.MINECRAFT_1_19 )
{
dimension = readTag( buf );
} else
@@ -103,6 +103,10 @@ public class Login extends DefinedPacket
{
viewDistance = readVarInt( buf );
}
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_18 )
{
simulationDistance = readVarInt( buf );
}
if ( protocolVersion >= 29 )
{
reducedDebugInfo = buf.readBoolean();
@@ -116,6 +120,13 @@ public class Login extends DefinedPacket
debug = buf.readBoolean();
flat = buf.readBoolean();
}
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 )
{
if ( buf.readBoolean() )
{
deathLocation = new Location( readString( buf ), buf.readLong() );
}
}
}
@Override
@@ -142,7 +153,7 @@ public class Login extends DefinedPacket
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16 )
{
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16_2 )
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16_2 && protocolVersion < ProtocolConstants.MINECRAFT_1_19 )
{
writeTag( (Tag) dimension, buf );
} else
@@ -180,6 +191,10 @@ public class Login extends DefinedPacket
{
writeVarInt( viewDistance, buf );
}
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_18 )
{
writeVarInt( simulationDistance, buf );
}
if ( protocolVersion >= 29 )
{
buf.writeBoolean( reducedDebugInfo );
@@ -193,6 +208,18 @@ public class Login extends DefinedPacket
buf.writeBoolean( debug );
buf.writeBoolean( flat );
}
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 )
{
if ( deathLocation != null )
{
buf.writeBoolean( true );
writeString( deathLocation.getDimension(), buf );
buf.writeLong( deathLocation.getPos() );
} else
{
buf.writeBoolean( false );
}
}
}
@Override

View File

@@ -1,16 +1,15 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.PlayerPublicKey;
import net.md_5.bungee.protocol.ProtocolConstants;
@Data
@NoArgsConstructor
@@ -20,17 +19,45 @@ public class LoginRequest extends DefinedPacket
{
private String data;
private PlayerPublicKey publicKey;
private UUID uuid;
@Override
public void read(ByteBuf buf)
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
data = readString( buf );
data = readString( buf, 16 );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 )
{
publicKey = readPublicKey( buf );
}
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 )
{
if ( buf.readBoolean() )
{
uuid = readUUID( buf );
}
}
}
@Override
public void write(ByteBuf buf)
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
writeString( data, buf );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 )
{
writePublicKey( publicKey, buf );
}
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 )
{
if ( uuid != null )
{
buf.writeBoolean( true );
writeUUID( uuid, buf );
} else
{
buf.writeBoolean( false );
}
}
}
@Override

View File

@@ -8,6 +8,7 @@ import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.Property;
import net.md_5.bungee.protocol.ProtocolConstants;
@Data
@@ -19,6 +20,7 @@ public class LoginSuccess extends DefinedPacket
private UUID uuid;
private String username;
private Property[] properties;
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
@@ -31,6 +33,10 @@ public class LoginSuccess extends DefinedPacket
uuid = UUID.fromString( readString( buf ) );
}
username = readString( buf );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 )
{
properties = readProperties( buf );
}
}
@Override
@@ -44,6 +50,10 @@ public class LoginSuccess extends DefinedPacket
writeString( uuid.toString(), buf );
}
writeString( username, buf );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 )
{
writeProperties( properties, buf );
}
}
@Override

View File

@@ -7,6 +7,8 @@ import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.PlayerPublicKey;
import net.md_5.bungee.protocol.Property;
import net.md_5.bungee.protocol.ProtocolConstants;
@Data
@@ -31,31 +33,17 @@ public class PlayerListItem extends DefinedPacket
{
case ADD_PLAYER:
item.username = DefinedPacket.readString( buf );
item.properties = new String[ DefinedPacket.readVarInt( buf ) ][];
for ( int j = 0; j < item.properties.length; j++ )
{
String name = DefinedPacket.readString( buf );
String value = DefinedPacket.readString( buf );
if ( buf.readBoolean() )
{
item.properties[j] = new String[]
{
name, value, DefinedPacket.readString( buf )
};
} else
{
item.properties[j] = new String[]
{
name, value
};
}
}
item.properties = DefinedPacket.readProperties( buf );
item.gamemode = DefinedPacket.readVarInt( buf );
item.ping = DefinedPacket.readVarInt( buf );
if ( buf.readBoolean() )
{
item.displayName = DefinedPacket.readString( buf );
}
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 )
{
item.publicKey = readPublicKey( buf );
}
break;
case UPDATE_GAMEMODE:
item.gamemode = DefinedPacket.readVarInt( buf );
@@ -84,20 +72,7 @@ public class PlayerListItem extends DefinedPacket
{
case ADD_PLAYER:
DefinedPacket.writeString( item.username, buf );
DefinedPacket.writeVarInt( item.properties.length, buf );
for ( String[] prop : item.properties )
{
DefinedPacket.writeString( prop[0], buf );
DefinedPacket.writeString( prop[1], buf );
if ( prop.length >= 3 )
{
buf.writeBoolean( true );
DefinedPacket.writeString( prop[2], buf );
} else
{
buf.writeBoolean( false );
}
}
DefinedPacket.writeProperties( item.properties, buf );
DefinedPacket.writeVarInt( item.gamemode, buf );
DefinedPacket.writeVarInt( item.ping, buf );
buf.writeBoolean( item.displayName != null );
@@ -105,6 +80,10 @@ public class PlayerListItem extends DefinedPacket
{
DefinedPacket.writeString( item.displayName, buf );
}
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 )
{
writePublicKey( item.publicKey, buf );
}
break;
case UPDATE_GAMEMODE:
DefinedPacket.writeVarInt( item.gamemode, buf );
@@ -148,7 +127,8 @@ public class PlayerListItem extends DefinedPacket
// ADD_PLAYER
private String username;
private String[][] properties;
private Property[] properties;
private PlayerPublicKey publicKey;
// ADD_PLAYER & UPDATE_GAMEMODE
private int gamemode;

View File

@@ -2,7 +2,6 @@ package net.md_5.bungee.protocol.packet;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import io.netty.buffer.ByteBuf;
import java.io.ByteArrayInputStream;
import java.io.DataInput;
@@ -48,14 +47,6 @@ public class PluginMessage extends DefinedPacket
return "legacy:" + tag.toLowerCase( Locale.ROOT );
}
};
public static final Predicate<PluginMessage> SHOULD_RELAY = new Predicate<PluginMessage>()
{
@Override
public boolean apply(PluginMessage input)
{
return ( input.getTag().equals( "REGISTER" ) || input.getTag().equals( "minecraft:register" ) || input.getTag().equals( "MC|Brand" ) || input.getTag().equals( "minecraft:brand" ) ) && input.getData().length < Byte.MAX_VALUE;
}
};
//
private String tag;
private byte[] data;
@@ -68,9 +59,9 @@ public class PluginMessage extends DefinedPacket
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
tag = ( protocolVersion >= ProtocolConstants.MINECRAFT_1_13 ) ? MODERNISE.apply( readString( buf ) ) : readString( buf );
int maxSize = direction == ProtocolConstants.Direction.TO_SERVER ? Short.MAX_VALUE : 0x100000;
Preconditions.checkArgument( buf.readableBytes() < maxSize );
tag = ( protocolVersion >= ProtocolConstants.MINECRAFT_1_13 ) ? MODERNISE.apply( readString( buf ) ) : readString( buf, 20 );
int maxSize = ( direction == ProtocolConstants.Direction.TO_SERVER ) ? Short.MAX_VALUE : 0x100000;
Preconditions.checkArgument( buf.readableBytes() <= maxSize, "Payload too large" );
data = new byte[ buf.readableBytes() ];
buf.readBytes( data );
}

View File

@@ -7,6 +7,7 @@ import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.Location;
import net.md_5.bungee.protocol.ProtocolConstants;
import se.llbit.nbt.Tag;
@@ -27,13 +28,14 @@ public class Respawn extends DefinedPacket
private boolean debug;
private boolean flat;
private boolean copyMeta;
private Location deathLocation;
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16 )
{
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16_2 )
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16_2 && protocolVersion < ProtocolConstants.MINECRAFT_1_19 )
{
dimension = readTag( buf );
} else
@@ -64,6 +66,13 @@ public class Respawn extends DefinedPacket
{
levelType = readString( buf );
}
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 )
{
if ( buf.readBoolean() )
{
deathLocation = new Location( readString( buf ), buf.readLong() );
}
}
}
@Override
@@ -71,7 +80,7 @@ public class Respawn extends DefinedPacket
{
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16 )
{
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16_2 )
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16_2 && protocolVersion < ProtocolConstants.MINECRAFT_1_19 )
{
writeTag( (Tag) dimension, buf );
} else
@@ -102,6 +111,18 @@ public class Respawn extends DefinedPacket
{
writeString( levelType, buf );
}
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 )
{
if ( deathLocation != null )
{
buf.writeBoolean( true );
writeString( deathLocation.getDimension(), buf );
buf.writeLong( deathLocation.getPos() );
} else
{
buf.writeBoolean( false );
}
}
}
@Override

View File

@@ -0,0 +1,78 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.ProtocolConstants;
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class ServerData extends DefinedPacket
{
private String motd;
private String icon;
private boolean preview;
private boolean enforceSecure;
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
if ( buf.readBoolean() )
{
motd = readString( buf, 262144 );
}
if ( buf.readBoolean() )
{
icon = readString( buf );
}
preview = buf.readBoolean();
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 )
{
enforceSecure = buf.readBoolean();
}
}
@Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
if ( motd != null )
{
buf.writeBoolean( true );
writeString( motd, buf, 262144 );
} else
{
buf.writeBoolean( false );
}
if ( icon != null )
{
buf.writeBoolean( true );
writeString( icon, buf );
} else
{
buf.writeBoolean( false );
}
buf.writeBoolean( preview );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 )
{
buf.writeBoolean( enforceSecure );
}
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,36 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.ProtocolConstants;
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class Subtitle extends DefinedPacket
{
private String text;
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
text = readString( buf );
}
@Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
writeString( text, buf );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,48 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.ProtocolConstants;
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class SystemChat extends DefinedPacket
{
private String message;
private int position;
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
message = readString( buf, 262144 );
position = ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 ) ? ( ( buf.readBoolean() ) ? ChatMessageType.ACTION_BAR.ordinal() : 0 ) : readVarInt( buf );
}
@Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
writeString( message, buf, 262144 );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 )
{
buf.writeBoolean( position == ChatMessageType.ACTION_BAR.ordinal() );
} else
{
writeVarInt( position, buf );
}
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -41,7 +41,7 @@ public class TabCompleteRequest extends DefinedPacket
{
transactionId = readVarInt( buf );
}
cursor = readString( buf );
cursor = readString( buf, ( protocolVersion > ProtocolConstants.MINECRAFT_1_13 ? 32500 : ( protocolVersion == ProtocolConstants.MINECRAFT_1_13 ? 256 : 32767 ) ) );
if ( protocolVersion < ProtocolConstants.MINECRAFT_1_13 )
{

View File

@@ -57,9 +57,7 @@ public class TabCompleteResponse extends DefinedPacket
}
suggestions = new Suggestions( range, matches );
}
if ( protocolVersion < ProtocolConstants.MINECRAFT_1_13 )
} else
{
commands = readStringArray( buf );
}
@@ -84,9 +82,7 @@ public class TabCompleteResponse extends DefinedPacket
writeString( suggestion.getTooltip().getString(), buf );
}
}
}
if ( protocolVersion < ProtocolConstants.MINECRAFT_1_13 )
} else
{
writeStringArray( commands, buf );
}

View File

@@ -24,9 +24,20 @@ public class Title extends DefinedPacket
private int stay;
private int fadeOut;
public Title(Action action)
{
this.action = action;
}
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_17 )
{
text = readString( buf );
return;
}
int index = readVarInt( buf );
// If we're working on 1.10 or lower, increment the value of the index so we pull out the correct value.
@@ -54,6 +65,12 @@ public class Title extends DefinedPacket
@Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_17 )
{
writeString( text, buf );
return;
}
int index = action.ordinal();
// If we're working on 1.10 or lower, increment the value of the index so we pull out the correct value.

View File

@@ -0,0 +1,42 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.ProtocolConstants;
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class TitleTimes extends DefinedPacket
{
private int fadeIn;
private int stay;
private int fadeOut;
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
fadeIn = buf.readInt();
stay = buf.readInt();
fadeOut = buf.readInt();
}
@Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
buf.writeInt( fadeIn );
buf.writeInt( stay );
buf.writeInt( fadeOut );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-proxy</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<version>1.19-R0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Proxy</name>
@@ -49,6 +49,13 @@
<classifier>linux-x86_64</classifier>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
<version>${netty.version}</version>
<classifier>linux-aarch_64</classifier>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
@@ -79,6 +86,12 @@
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-slf4j</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.sf.jopt-simple</groupId>
<artifactId>jopt-simple</artifactId>
@@ -88,17 +101,27 @@
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
<version>8.0.29</version>
<scope>runtime</scope>
</dependency>
<!-- add these back in as they are not exposed by the API -->
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-resolver-provider</artifactId>
<version>3.8.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-connector-basic</artifactId>
<version>1.7.3</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-transport-http</artifactId>
<version>1.7.3</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>

View File

@@ -24,10 +24,12 @@ import java.io.IOException;
import java.io.PrintStream;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.text.Format;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
@@ -85,6 +87,7 @@ import net.md_5.bungee.conf.Configuration;
import net.md_5.bungee.conf.YamlConfig;
import net.md_5.bungee.forge.ForgeConstants;
import net.md_5.bungee.log.BungeeLogger;
import net.md_5.bungee.log.LoggingForwardHandler;
import net.md_5.bungee.log.LoggingOutputStream;
import net.md_5.bungee.module.ModuleManager;
import net.md_5.bungee.netty.PipelineUtils;
@@ -95,6 +98,7 @@ import net.md_5.bungee.query.RemoteQuery;
import net.md_5.bungee.scheduler.BungeeScheduler;
import net.md_5.bungee.util.CaseInsensitiveMap;
import org.fusesource.jansi.AnsiConsole;
import org.slf4j.impl.JDK14LoggerFactory;
/**
* Main BungeeCord proxy class.
@@ -112,10 +116,9 @@ public class BungeeCord extends ProxyServer
@Getter
public final Configuration config = new Configuration();
/**
* Localization bundle.
* Localization formats.
*/
private ResourceBundle baseBundle;
private ResourceBundle customBundle;
private Map<String, Format> messageFormats;
public EventLoopGroup eventLoops;
/**
* locations.yml save thread.
@@ -188,15 +191,6 @@ public class BungeeCord extends ProxyServer
// Java uses ! to indicate a resource inside of a jar/zip/other container. Running Bungee from within a directory that has a ! will cause this to muck up.
Preconditions.checkState( new File( "." ).getAbsolutePath().indexOf( '!' ) == -1, "Cannot use BungeeCord in directory with ! in path." );
System.setSecurityManager( new BungeeSecurityManager() );
try
{
baseBundle = ResourceBundle.getBundle( "messages" );
} catch ( MissingResourceException ex )
{
baseBundle = ResourceBundle.getBundle( "messages", Locale.ENGLISH );
}
reloadMessages();
// This is a workaround for quite possibly the weirdest bug I have ever encountered in my life!
@@ -215,6 +209,22 @@ public class BungeeCord extends ProxyServer
consoleReader.addCompleter( new ConsoleCommandCompleter( this ) );
logger = new BungeeLogger( "BungeeCord", "proxy.log", consoleReader );
JDK14LoggerFactory.LOGGER = logger;
// Before we can set the Err and Out streams to our LoggingOutputStream we also have to remove
// the default ConsoleHandler from the root logger, which writes to the err stream.
// But we still want to log these records, so we add our own handler which forwards the LogRecord to the BungeeLogger.
// This way we skip the err stream and the problem of only getting a string without context, and can handle the LogRecord itself.
// Thus improving the default bahavior for projects that log on other Logger instances not created by BungeeCord.
Logger rootLogger = Logger.getLogger( "" );
for ( Handler handler : rootLogger.getHandlers() )
{
rootLogger.removeHandler( handler );
}
rootLogger.addHandler( new LoggingForwardHandler( logger ) );
// We want everything that reaches these output streams to be handled by our logger
// since it applies a nice looking format and also writes to the logfile.
System.setErr( new PrintStream( new LoggingOutputStream( logger, Level.SEVERE ), true ) );
System.setOut( new PrintStream( new LoggingOutputStream( logger, Level.INFO ), true ) );
@@ -254,7 +264,7 @@ public class BungeeCord extends ProxyServer
public void start() throws Exception
{
System.setProperty( "io.netty.selectorAutoRebuildThreshold", "0" ); // Seems to cause Bungee to stop accepting connections
if ( System.getProperty( "io.netty.leakDetectionLevel" ) == null )
if ( System.getProperty( "io.netty.leakDetectionLevel" ) == null && System.getProperty( "io.netty.leakDetection.level" ) == null )
{
ResourceLeakDetector.setLevel( ResourceLeakDetector.Level.DISABLED ); // Eats performance
}
@@ -537,32 +547,49 @@ public class BungeeCord extends ProxyServer
return ( BungeeCord.class.getPackage().getImplementationVersion() == null ) ? "unknown" : BungeeCord.class.getPackage().getImplementationVersion();
}
public void reloadMessages()
public final void reloadMessages()
{
Map<String, Format> cachedFormats = new HashMap<>();
File file = new File( "messages.properties" );
if ( file.isFile() )
{
try ( FileReader rd = new FileReader( file ) )
{
customBundle = new PropertyResourceBundle( rd );
cacheResourceBundle( cachedFormats, new PropertyResourceBundle( rd ) );
} catch ( IOException ex )
{
getLogger().log( Level.SEVERE, "Could not load custom messages.properties", ex );
}
}
ResourceBundle baseBundle;
try
{
baseBundle = ResourceBundle.getBundle( "messages" );
} catch ( MissingResourceException ex )
{
baseBundle = ResourceBundle.getBundle( "messages", Locale.ENGLISH );
}
cacheResourceBundle( cachedFormats, baseBundle );
messageFormats = Collections.unmodifiableMap( cachedFormats );
}
private void cacheResourceBundle(Map<String, Format> map, ResourceBundle resourceBundle)
{
Enumeration<String> keys = resourceBundle.getKeys();
while ( keys.hasMoreElements() )
{
map.computeIfAbsent( keys.nextElement(), (key) -> new MessageFormat( resourceBundle.getString( key ) ) );
}
}
@Override
public String getTranslation(String name, Object... args)
{
String translation = "<translation '" + name + "' missing>";
try
{
translation = MessageFormat.format( customBundle != null && customBundle.containsKey( name ) ? customBundle.getString( name ) : baseBundle.getString( name ), args );
} catch ( MissingResourceException ex )
{
}
return translation;
Format format = messageFormats.get( name );
return ( format != null ) ? format.format( args ) : "<translation '" + name + "' missing>";
}
@Override

View File

@@ -20,6 +20,11 @@ public class BungeeCordLauncher
{
Security.setProperty( "networkaddress.cache.ttl", "30" );
Security.setProperty( "networkaddress.cache.negative.ttl", "10" );
// For JDK9+ we force-enable multi-release jar file support #3087
if ( System.getProperty( "jdk.util.jar.enableMultiRelease" ) == null )
{
System.setProperty( "jdk.util.jar.enableMultiRelease", "force" );
}
OptionParser parser = new OptionParser();
parser.allowsUnrecognizedOptions();

View File

@@ -1,78 +0,0 @@
package net.md_5.bungee;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.security.AccessControlException;
import java.security.Permission;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.scheduler.GroupedThreadFactory;
public class BungeeSecurityManager extends SecurityManager
{
private static final boolean ENFORCE = false;
private final Set<String> seen = new HashSet<>();
private void checkRestricted(String text)
{
Class[] context = getClassContext();
for ( int i = 2; i < context.length; i++ )
{
ClassLoader loader = context[i].getClassLoader();
// Bungee / system can do everything
if ( loader == ClassLoader.getSystemClassLoader() || loader == null )
{
break;
}
AccessControlException ex = new AccessControlException( "Plugin violation: " + text );
if ( ENFORCE )
{
throw ex;
}
StringWriter stack = new StringWriter();
ex.printStackTrace( new PrintWriter( stack ) );
if ( seen.add( stack.toString() ) )
{
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Plugin performed restricted action, please inform them to use proper API methods: " + text, ex );
}
break;
}
}
@Override
public void checkExit(int status)
{
checkRestricted( "Exit: Cannot close VM" );
}
@Override
public void checkAccess(ThreadGroup g)
{
if ( !( g instanceof GroupedThreadFactory.BungeeGroup ) )
{
checkRestricted( "Illegal thread group access" );
}
}
@Override
public void checkPermission(Permission perm, Object context)
{
checkPermission( perm );
}
@Override
public void checkPermission(Permission perm)
{
switch ( perm.getName() )
{
case "setSecurityManager":
throw new AccessControlException( "Restricted Action", perm );
}
}
}

View File

@@ -154,7 +154,7 @@ public class BungeeServerInfo implements ServerInfo
Preconditions.checkNotNull( callback, "callback" );
int pingCache = ProxyServer.getInstance().getConfig().getRemotePingCache();
if ( pingCache > 0 && cachedPing != null && ( lastPing - System.currentTimeMillis() ) > pingCache )
if ( pingCache > 0 && cachedPing != null && ( System.currentTimeMillis() - lastPing ) > pingCache )
{
cachedPing = null;
}

View File

@@ -1,29 +1,46 @@
package net.md_5.bungee;
import lombok.Data;
import net.md_5.bungee.api.Title;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.chat.ComponentSerializer;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.ProtocolConstants;
import net.md_5.bungee.protocol.packet.ClearTitles;
import net.md_5.bungee.protocol.packet.Subtitle;
import net.md_5.bungee.protocol.packet.Title.Action;
import net.md_5.bungee.protocol.packet.TitleTimes;
public class BungeeTitle implements Title
{
private net.md_5.bungee.protocol.packet.Title title, subtitle, times, clear, reset;
private TitlePacketHolder<net.md_5.bungee.protocol.packet.Title> title;
private TitlePacketHolder<Subtitle> subtitle;
private TitlePacketHolder<TitleTimes> times;
private TitlePacketHolder<ClearTitles> clear;
private TitlePacketHolder<ClearTitles> reset;
private static net.md_5.bungee.protocol.packet.Title createPacket(Action action)
@Data
private static class TitlePacketHolder<T extends DefinedPacket>
{
net.md_5.bungee.protocol.packet.Title title = new net.md_5.bungee.protocol.packet.Title();
title.setAction( action );
if ( action == Action.TIMES )
{
// Set packet to default values first
title.setFadeIn( 20 );
title.setStay( 60 );
title.setFadeOut( 20 );
}
private final net.md_5.bungee.protocol.packet.Title oldPacket;
private final T newPacket;
}
private static TitlePacketHolder<TitleTimes> createAnimationPacket()
{
TitlePacketHolder<TitleTimes> title = new TitlePacketHolder<>( new net.md_5.bungee.protocol.packet.Title( Action.TIMES ), new TitleTimes() );
title.oldPacket.setFadeIn( 20 );
title.oldPacket.setStay( 60 );
title.oldPacket.setFadeOut( 20 );
title.newPacket.setFadeIn( 20 );
title.newPacket.setStay( 60 );
title.newPacket.setFadeOut( 20 );
return title;
}
@@ -32,10 +49,11 @@ public class BungeeTitle implements Title
{
if ( title == null )
{
title = createPacket( Action.TITLE );
net.md_5.bungee.protocol.packet.Title packet = new net.md_5.bungee.protocol.packet.Title( Action.TITLE );
title = new TitlePacketHolder<>( packet, packet );
}
title.setText( ComponentSerializer.toString( text ) );
title.oldPacket.setText( ComponentSerializer.toString( text ) ); // = newPacket
return this;
}
@@ -44,10 +62,11 @@ public class BungeeTitle implements Title
{
if ( title == null )
{
title = createPacket( Action.TITLE );
net.md_5.bungee.protocol.packet.Title packet = new net.md_5.bungee.protocol.packet.Title( Action.TITLE );
title = new TitlePacketHolder<>( packet, packet );
}
title.setText( ComponentSerializer.toString( text ) );
title.oldPacket.setText( ComponentSerializer.toString( text ) ); // = newPacket
return this;
}
@@ -56,10 +75,12 @@ public class BungeeTitle implements Title
{
if ( subtitle == null )
{
subtitle = createPacket( Action.SUBTITLE );
subtitle = new TitlePacketHolder<>( new net.md_5.bungee.protocol.packet.Title( Action.SUBTITLE ), new Subtitle() );
}
subtitle.setText( ComponentSerializer.toString( text ) );
String serialized = ComponentSerializer.toString( text );
subtitle.oldPacket.setText( serialized );
subtitle.newPacket.setText( serialized );
return this;
}
@@ -68,10 +89,12 @@ public class BungeeTitle implements Title
{
if ( subtitle == null )
{
subtitle = createPacket( Action.SUBTITLE );
subtitle = new TitlePacketHolder<>( new net.md_5.bungee.protocol.packet.Title( Action.SUBTITLE ), new Subtitle() );
}
subtitle.setText( ComponentSerializer.toString( text ) );
String serialized = ComponentSerializer.toString( text );
subtitle.oldPacket.setText( serialized );
subtitle.newPacket.setText( serialized );
return this;
}
@@ -80,10 +103,11 @@ public class BungeeTitle implements Title
{
if ( times == null )
{
times = createPacket( Action.TIMES );
times = createAnimationPacket();
}
times.setFadeIn( ticks );
times.oldPacket.setFadeIn( ticks );
times.newPacket.setFadeIn( ticks );
return this;
}
@@ -92,10 +116,11 @@ public class BungeeTitle implements Title
{
if ( times == null )
{
times = createPacket( Action.TIMES );
times = createAnimationPacket();
}
times.setStay( ticks );
times.oldPacket.setStay( ticks );
times.newPacket.setStay( ticks );
return this;
}
@@ -104,10 +129,11 @@ public class BungeeTitle implements Title
{
if ( times == null )
{
times = createPacket( Action.TIMES );
times = createAnimationPacket();
}
times.setFadeOut( ticks );
times.oldPacket.setFadeOut( ticks );
times.newPacket.setFadeOut( ticks );
return this;
}
@@ -116,7 +142,7 @@ public class BungeeTitle implements Title
{
if ( clear == null )
{
clear = createPacket( Action.CLEAR );
clear = new TitlePacketHolder<>( new net.md_5.bungee.protocol.packet.Title( Action.CLEAR ), new ClearTitles() );
}
title = null; // No need to send title if we clear it after that again
@@ -129,7 +155,7 @@ public class BungeeTitle implements Title
{
if ( reset == null )
{
reset = createPacket( Action.RESET );
reset = new TitlePacketHolder<>( new net.md_5.bungee.protocol.packet.Title( Action.RESET ), new ClearTitles( true ) );
}
// No need to send these packets if we reset them later
@@ -140,11 +166,17 @@ public class BungeeTitle implements Title
return this;
}
private static void sendPacket(ProxiedPlayer player, DefinedPacket packet)
private static void sendPacket(ProxiedPlayer player, TitlePacketHolder packet)
{
if ( packet != null )
{
player.unsafe().sendPacket( packet );
if ( player.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_17 )
{
player.unsafe().sendPacket( packet.newPacket );
} else
{
player.unsafe().sendPacket( packet.oldPacket );
}
}
}

View File

@@ -1,5 +1,11 @@
package net.md_5.bungee;
import com.google.common.io.ByteStreams;
import com.google.common.primitives.Longs;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyFactory;
@@ -7,9 +13,13 @@ import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Base64;
import java.util.Random;
import java.util.UUID;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
@@ -18,6 +28,7 @@ import net.md_5.bungee.jni.NativeCode;
import net.md_5.bungee.jni.cipher.BungeeCipher;
import net.md_5.bungee.jni.cipher.JavaCipher;
import net.md_5.bungee.jni.cipher.NativeCipher;
import net.md_5.bungee.protocol.PlayerPublicKey;
import net.md_5.bungee.protocol.packet.EncryptionRequest;
import net.md_5.bungee.protocol.packet.EncryptionResponse;
@@ -28,10 +39,12 @@ public class EncryptionUtil
{
private static final Random random = new Random();
private static final Base64.Encoder MIME_ENCODER = Base64.getMimeEncoder( 76, "\n".getBytes( StandardCharsets.UTF_8 ) );
public static final KeyPair keys;
@Getter
private static final SecretKey secret = new SecretKeySpec( new byte[ 16 ], "AES" );
public static final NativeCode<BungeeCipher> nativeFactory = new NativeCode<>( "native-cipher", JavaCipher.class, NativeCipher.class );
public static final NativeCode<BungeeCipher> nativeFactory = new NativeCode<>( "native-cipher", JavaCipher::new, NativeCipher::new );
private static final PublicKey MOJANG_KEY;
static
{
@@ -44,6 +57,14 @@ public class EncryptionUtil
{
throw new ExceptionInInitializerError( ex );
}
try
{
MOJANG_KEY = KeyFactory.getInstance( "RSA" ).generatePublic( new X509EncodedKeySpec( ByteStreams.toByteArray( EncryptionUtil.class.getResourceAsStream( "/yggdrasil_session_pubkey.der" ) ) ) );
} catch ( IOException | NoSuchAlgorithmException | InvalidKeySpecException ex )
{
throw new ExceptionInInitializerError( ex );
}
}
public static EncryptionRequest encryptRequest()
@@ -55,17 +76,51 @@ public class EncryptionUtil
return new EncryptionRequest( hash, pubKey, verify );
}
public static boolean check(PlayerPublicKey publicKey, UUID uuid) throws GeneralSecurityException
{
Signature signature = Signature.getInstance( "SHA1withRSA" );
signature.initVerify( MOJANG_KEY );
byte[] check;
if ( uuid != null )
{
byte[] encoded = getPubkey( publicKey.getKey() ).getEncoded();
check = new byte[ 24 + encoded.length ];
ByteBuffer.wrap( check ).order( ByteOrder.BIG_ENDIAN ).putLong( uuid.getMostSignificantBits() ).putLong( uuid.getLeastSignificantBits() ).putLong( publicKey.getExpiry() ).put( encoded );
} else
{
check = ( publicKey.getExpiry() + "-----BEGIN RSA PUBLIC KEY-----\n" + MIME_ENCODER.encodeToString( getPubkey( publicKey.getKey() ).getEncoded() ) + "\n-----END RSA PUBLIC KEY-----\n" ).getBytes( StandardCharsets.US_ASCII );
}
signature.update( check );
return signature.verify( publicKey.getSignature() );
}
public static boolean check(PlayerPublicKey publicKey, EncryptionResponse resp, EncryptionRequest request) throws GeneralSecurityException
{
if ( publicKey != null )
{
Signature signature = Signature.getInstance( "SHA256withRSA" );
signature.initVerify( getPubkey( publicKey.getKey() ) );
signature.update( request.getVerifyToken() );
signature.update( Longs.toByteArray( resp.getEncryptionData().getSalt() ) );
return signature.verify( resp.getEncryptionData().getSignature() );
} else
{
Cipher cipher = Cipher.getInstance( "RSA" );
cipher.init( Cipher.DECRYPT_MODE, keys.getPrivate() );
byte[] decrypted = cipher.doFinal( resp.getVerifyToken() );
return Arrays.equals( request.getVerifyToken(), decrypted );
}
}
public static SecretKey getSecret(EncryptionResponse resp, EncryptionRequest request) throws GeneralSecurityException
{
Cipher cipher = Cipher.getInstance( "RSA" );
cipher.init( Cipher.DECRYPT_MODE, keys.getPrivate() );
byte[] decrypted = cipher.doFinal( resp.getVerifyToken() );
if ( !Arrays.equals( request.getVerifyToken(), decrypted ) )
{
throw new IllegalStateException( "Key pairs do not match!" );
}
cipher.init( Cipher.DECRYPT_MODE, keys.getPrivate() );
return new SecretKeySpec( cipher.doFinal( resp.getSharedSecret() ), "AES" );
}
@@ -80,7 +135,12 @@ public class EncryptionUtil
public static PublicKey getPubkey(EncryptionRequest request) throws GeneralSecurityException
{
return KeyFactory.getInstance( "RSA" ).generatePublic( new X509EncodedKeySpec( request.getPublicKey() ) );
return getPubkey( request.getPublicKey() );
}
private static PublicKey getPubkey(byte[] b) throws GeneralSecurityException
{
return KeyFactory.getInstance( "RSA" ).generatePublic( new X509EncodedKeySpec( b ) );
}
public static byte[] encrypt(Key key, byte[] b) throws GeneralSecurityException

View File

@@ -1,9 +1,11 @@
package net.md_5.bungee;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.util.Queue;
import java.util.Set;
@@ -41,6 +43,8 @@ import net.md_5.bungee.protocol.packet.GameState;
import net.md_5.bungee.protocol.packet.Handshake;
import net.md_5.bungee.protocol.packet.Kick;
import net.md_5.bungee.protocol.packet.Login;
import net.md_5.bungee.protocol.packet.LoginPayloadRequest;
import net.md_5.bungee.protocol.packet.LoginPayloadResponse;
import net.md_5.bungee.protocol.packet.LoginRequest;
import net.md_5.bungee.protocol.packet.LoginSuccess;
import net.md_5.bungee.protocol.packet.PluginMessage;
@@ -49,6 +53,7 @@ import net.md_5.bungee.protocol.packet.ScoreboardObjective;
import net.md_5.bungee.protocol.packet.ScoreboardScore;
import net.md_5.bungee.protocol.packet.SetCompression;
import net.md_5.bungee.protocol.packet.ViewDistance;
import net.md_5.bungee.util.AddressUtil;
import net.md_5.bungee.util.BufUtil;
import net.md_5.bungee.util.QuietException;
@@ -100,7 +105,7 @@ public class ServerConnector extends PacketHandler
if ( BungeeCord.getInstance().config.isIpForward() && user.getSocketAddress() instanceof InetSocketAddress )
{
String newHost = copiedHandshake.getHost() + "\00" + user.getAddress().getHostString() + "\00" + user.getUUID();
String newHost = copiedHandshake.getHost() + "\00" + AddressUtil.sanitizeAddress( user.getAddress() ) + "\00" + user.getUUID();
LoginResult profile = user.getPendingConnection().getLoginProfile();
if ( profile != null && profile.getProperties() != null && profile.getProperties().length > 0 )
@@ -118,7 +123,7 @@ public class ServerConnector extends PacketHandler
channel.write( copiedHandshake );
channel.setProtocol( Protocol.LOGIN );
channel.write( new LoginRequest( user.getName() ) );
channel.write( new LoginRequest( user.getName(), null, user.getUniqueId() ) );
}
@Override
@@ -190,9 +195,16 @@ public class ServerConnector extends PacketHandler
}
}
for ( PluginMessage message : user.getPendingConnection().getRelayMessages() )
PluginMessage brandMessage = user.getPendingConnection().getBrandMessage();
if ( brandMessage != null )
{
ch.write( message );
ch.write( brandMessage );
}
Set<String> registeredChannels = user.getPendingConnection().getRegisteredChannels();
if ( !registeredChannels.isEmpty() )
{
ch.write( new PluginMessage( user.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_13 ? "minecraft:register" : "REGISTER", Joiner.on( "\0" ).join( registeredChannels ).getBytes( StandardCharsets.UTF_8 ), false ) );
}
if ( user.getSettings() != null )
@@ -213,7 +225,7 @@ public class ServerConnector extends PacketHandler
// Set tab list size, TODO: what shall we do about packet mutability
Login modLogin = new Login( login.getEntityId(), login.isHardcore(), login.getGameMode(), login.getPreviousGameMode(), login.getWorldNames(), login.getDimensions(), login.getDimension(), login.getWorldName(), login.getSeed(), login.getDifficulty(),
(byte) user.getPendingConnection().getListener().getTabListSize(), login.getLevelType(), login.getViewDistance(), login.isReducedDebugInfo(), login.isNormalRespawn(), login.isDebug(), login.isFlat() );
(byte) user.getPendingConnection().getListener().getTabListSize(), login.getLevelType(), login.getViewDistance(), login.getSimulationDistance(), login.isReducedDebugInfo(), login.isNormalRespawn(), login.isDebug(), login.isFlat(), login.getDeathLocation() );
user.unsafe().sendPacket( modLogin );
@@ -231,7 +243,7 @@ public class ServerConnector extends PacketHandler
}
user.getSentBossBars().clear();
user.unsafe().sendPacket( new Respawn( login.getDimension(), login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(), false ) );
user.unsafe().sendPacket( new Respawn( login.getDimension(), login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(), false, login.getDeathLocation() ) );
user.getServer().disconnect( "Quitting" );
} else
{
@@ -280,11 +292,11 @@ public class ServerConnector extends PacketHandler
user.setDimensionChange( true );
if ( login.getDimension() == user.getDimension() )
{
user.unsafe().sendPacket( new Respawn( (Integer) login.getDimension() >= 0 ? -1 : 0, login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(), false ) );
user.unsafe().sendPacket( new Respawn( (Integer) login.getDimension() >= 0 ? -1 : 0, login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(), false, login.getDeathLocation() ) );
}
user.setServerEntityId( login.getEntityId() );
user.unsafe().sendPacket( new Respawn( login.getDimension(), login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(), false ) );
user.unsafe().sendPacket( new Respawn( login.getDimension(), login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(), false, login.getDeathLocation() ) );
if ( user.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_14 )
{
user.unsafe().sendPacket( new ViewDistance( login.getViewDistance() ) );
@@ -406,6 +418,12 @@ public class ServerConnector extends PacketHandler
user.unsafe().sendPacket( pluginMessage );
}
@Override
public void handle(LoginPayloadRequest loginPayloadRequest)
{
ch.write( new LoginPayloadResponse( loginPayloadRequest.getId(), null ) );
}
@Override
public String toString()
{

View File

@@ -59,6 +59,7 @@ import net.md_5.bungee.protocol.packet.Kick;
import net.md_5.bungee.protocol.packet.PlayerListHeaderFooter;
import net.md_5.bungee.protocol.packet.PluginMessage;
import net.md_5.bungee.protocol.packet.SetCompression;
import net.md_5.bungee.protocol.packet.SystemChat;
import net.md_5.bungee.tab.ServerUnique;
import net.md_5.bungee.tab.TabList;
import net.md_5.bungee.util.CaseInsensitiveSet;
@@ -348,10 +349,10 @@ public final class UserConnection implements ProxiedPlayer
connect( def, null, true, ServerConnectEvent.Reason.LOBBY_FALLBACK );
} else if ( dimensionChange )
{
disconnect( bungee.getTranslation( "fallback_kick", future.cause().getClass().getName() ) );
disconnect( bungee.getTranslation( "fallback_kick", connectionFailMessage( future.cause() ) ) );
} else
{
sendMessage( bungee.getTranslation( "fallback_kick", future.cause().getClass().getName() ) );
sendMessage( bungee.getTranslation( "fallback_kick", connectionFailMessage( future.cause() ) ) );
}
}
}
@@ -370,6 +371,11 @@ public final class UserConnection implements ProxiedPlayer
b.connect().addListener( listener );
}
private String connectionFailMessage(Throwable cause)
{
return groups.contains( "admin" ) ? Util.exception( cause, false ) : cause.getClass().getName();
}
@Override
public void disconnect(String reason)
{
@@ -411,6 +417,10 @@ public final class UserConnection implements ProxiedPlayer
public void chat(String message)
{
Preconditions.checkState( server != null, "Not connected to server" );
if ( getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_19 )
{
throw new UnsupportedOperationException( "Cannot spoof chat on this client version!" );
}
server.getCh().write( new Chat( message ) );
}
@@ -467,7 +477,19 @@ public final class UserConnection implements ProxiedPlayer
private void sendMessage(ChatMessageType position, UUID sender, String message)
{
unsafe().sendPacket( new Chat( message, (byte) position.ordinal(), sender ) );
if ( getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_19 )
{
// Align with Spigot and remove client side formatting for now
if ( position == ChatMessageType.CHAT )
{
position = ChatMessageType.SYSTEM;
}
unsafe().sendPacket( new SystemChat( message, position.ordinal() ) );
} else
{
unsafe().sendPacket( new Chat( message, (byte) position.ordinal(), sender ) );
}
}
private void sendMessage(ChatMessageType position, UUID sender, BaseComponent... message)
@@ -475,7 +497,7 @@ public final class UserConnection implements ProxiedPlayer
// transform score components
message = ChatComponentTransformer.getInstance().transform( this, true, message );
if ( position == ChatMessageType.ACTION_BAR )
if ( position == ChatMessageType.ACTION_BAR && getPendingConnection().getVersion() < ProtocolConstants.MINECRAFT_1_17 )
{
// Versions older than 1.11 cannot send the Action bar with the new JSON formattings
// Fix by converting to a legacy message, see https://bugs.mojang.com/browse/MC-119145

View File

@@ -2,6 +2,7 @@ package net.md_5.bungee.command;
import com.google.common.base.Joiner;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.plugin.Command;
@@ -25,7 +26,7 @@ public class CommandEnd extends Command
BungeeCord.getInstance().stop();
} else
{
BungeeCord.getInstance().stop( Joiner.on( ' ' ).join( args ) );
BungeeCord.getInstance().stop( ChatColor.translateAlternateColorCodes( '&', Joiner.on( ' ' ).join( args ) ) );
}
}
}

View File

@@ -2,6 +2,9 @@ package net.md_5.bungee.command;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import jline.console.completer.Completer;
import lombok.RequiredArgsConstructor;
import net.md_5.bungee.api.ProxyServer;
@@ -15,11 +18,21 @@ public class ConsoleCommandCompleter implements Completer
@Override
public int complete(String buffer, int cursor, List<CharSequence> candidates)
{
List<String> suggestions = new ArrayList<>();
proxy.getPluginManager().dispatchCommand( proxy.getConsole(), buffer, suggestions );
candidates.addAll( suggestions );
int lastSpace = buffer.lastIndexOf( ' ' );
if ( lastSpace == -1 )
{
String lowerCase = buffer.toLowerCase( Locale.ROOT );
candidates.addAll( proxy.getPluginManager().getCommands().stream()
.map( Map.Entry::getKey )
.filter( (name) -> name.toLowerCase( Locale.ROOT ).startsWith( lowerCase ) )
.collect( Collectors.toList() ) );
} else
{
List<String> suggestions = new ArrayList<>();
proxy.getPluginManager().dispatchCommand( proxy.getConsole(), buffer, suggestions );
candidates.addAll( suggestions );
}
return ( lastSpace == -1 ) ? cursor - buffer.length() : cursor - ( buffer.length() - lastSpace - 1 );
}
}

View File

@@ -8,5 +8,5 @@ import net.md_5.bungee.jni.zlib.NativeZlib;
public class CompressFactory
{
public static final NativeCode<BungeeZlib> zlib = new NativeCode<>( "native-compress", JavaZlib.class, NativeZlib.class );
public static final NativeCode<BungeeZlib> zlib = new NativeCode<>( "native-compress", JavaZlib::new, NativeZlib::new );
}

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