Compare commits

..

47 Commits

Author SHA1 Message Date
53b54d300f new event TabCompleteRequestEvent and deprecate TabCompleteEvent 2024-05-08 09:51:37 +02:00
211753cc33 Add CommandsDeclareEvent to declare commands with brigadier API 2024-05-08 09:51:36 +02:00
e1999307b1 Server branding now includes the backend server name 2024-05-08 09:51:36 +02:00
eeca3a5c56 Multi-session with same Minecraft account with specific permission
Players with permission bungeecord.multiple_connect can have multiple connections with the same Minecraft account.
The UUID and player name is altered to avoid collision with other player:
UUID : xxxxxxxx-xxxx-VIxx-xxxx-xxxxxxxxxxxx
- The UUID version (V above) is now the provided version + 8 (for online player, it is 4, so it becomes C).
- The I digit will follow the index of the duplicated player : first duplicated player is 1, second one is 2.
- The name of the player will be the real player name, followed by the character "." (dot) followed by the duplication index.

Bedrock accounts connected using the Floodgate plugin will not be able to connect multiple times due to the risk of xUID collision.
2024-05-08 09:51:36 +02:00
55c4157375 Change projet configuration and POM for Pandacube 2024-05-08 09:51:33 +02:00
70ad55b773 Remove modules and startup delay
We don’t need them for Pandacube
2024-05-08 09:46:40 +02:00
Janmm14
18eae8a1a6
#3664: Improve chat test code quality 2024-05-05 10:48:01 +10:00
Outfluencer
6e1751733f
#3608, #3676: Close connection if HAProxy 2.0 message is a health check 2024-04-29 06:56:18 +10:00
DerFrZocker
6335af840b
SPIGOT-7638: Library loader does not seem to resolve every dependency 2024-04-27 09:25:29 +10:00
Janmm14
336333acb1
#3665: Small improvements to TranslatableComponent
* Make TranslatableComponent format Pattern static
* Fix TranslatableComponent copy constructor not copying fallback
2024-04-25 07:58:27 +10:00
dependabot[bot]
d110f6629b
#3669: Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.2 to 3.5.3
Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.5.2 to 3.5.3.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.2...maven-shade-plugin-3.5.3)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-25 07:57:50 +10:00
md_5
6f70b15e2e
Minecraft 1.20.5 support 2024-04-24 01:15:00 +10:00
dependabot[bot]
b30499e2b6
#3667: Bump org.apache.maven.plugins:maven-jar-plugin from 3.4.0 to 3.4.1
Bumps [org.apache.maven.plugins:maven-jar-plugin](https://github.com/apache/maven-jar-plugin) from 3.4.0 to 3.4.1.
- [Release notes](https://github.com/apache/maven-jar-plugin/releases)
- [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.4.0...maven-jar-plugin-3.4.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-jar-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-23 08:19:33 +10:00
md_5
5079181c28
Minecraft 1.20.5-rc3 support 2024-04-23 06:16:02 +10:00
md_5
ee02d98cb2
Minecraft 1.20.5-rc2 support 2024-04-20 08:53:11 +10:00
Outfluencer
c7ff3b8a14
#3654: Update year in README.md 2024-04-20 08:46:24 +10:00
Outfluencer
de60af0d7b
#3659: Cleanup command packets for 1.20.5 2024-04-20 08:45:46 +10:00
dependabot[bot]
a9218a7aa7
#3660: Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.3 to 3.2.4
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.3 to 3.2.4.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.3...maven-gpg-plugin-3.2.4)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-gpg-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-20 08:44:38 +10:00
Outfluencer
67c65e0464
#3658: Minecraft 1.20.5-rc1 support 2024-04-19 06:58:16 +10:00
Outfluencer
1be25b6c74
#3656: Improve online mode support where IP forwarding is disabled 2024-04-17 21:05:26 +10:00
md_5
8525b44961
Minecraft 1.20.5-pre3 support 2024-04-17 07:55:07 +10:00
Jared Tiala
1fca510a08
#3655: Fix 1.20.5-pre1 view distance packet ID 2024-04-17 06:38:26 +10:00
dependabot[bot]
3384185285
#3652: Bump org.apache.maven.plugins:maven-jar-plugin from 3.3.0 to 3.4.0
Bumps [org.apache.maven.plugins:maven-jar-plugin](https://github.com/apache/maven-jar-plugin) from 3.3.0 to 3.4.0.
- [Release notes](https://github.com/apache/maven-jar-plugin/releases)
- [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.3.0...maven-jar-plugin-3.4.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-jar-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-16 21:33:01 +10:00
dependabot[bot]
3075d2c19d
#3651: Bump io.netty:netty-bom from 4.1.108.Final to 4.1.109.Final
Bumps [io.netty:netty-bom](https://github.com/netty/netty) from 4.1.108.Final to 4.1.109.Final.
- [Commits](https://github.com/netty/netty/compare/netty-4.1.108.Final...netty-4.1.109.Final)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-16 21:32:48 +10:00
md_5
bc528d5d98
Update native libraries 2024-04-14 09:15:51 +10:00
Outfluencer
25cf8d682b
#3617: Don't go further if connection is disconnected during handshake event
Also replace all isClosed with isClosing as it is more accurate for
disconnect calls in events.
2024-04-13 17:22:31 +10:00
ignPurple
17e23d5c3f
#3628: Convert PostLoginEvent to AsyncEvent and expose target server 2024-04-13 17:10:24 +10:00
dependabot[bot]
d6c5197cb9
#3599: Bump com.mysql:mysql-connector-j from 8.2.0 to 8.3.0
Bumps [com.mysql:mysql-connector-j](https://github.com/mysql/mysql-connector-j) from 8.2.0 to 8.3.0.
- [Changelog](https://github.com/mysql/mysql-connector-j/blob/release/8.x/CHANGES)
- [Commits](https://github.com/mysql/mysql-connector-j/compare/8.2.0...8.3.0)

---
updated-dependencies:
- dependency-name: com.mysql:mysql-connector-j
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-13 15:52:04 +10:00
dependabot[bot]
dd96f0f878
#3647: Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.2 to 3.2.3
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.2 to 3.2.3.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.2...maven-gpg-plugin-3.2.3)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-gpg-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-13 15:49:42 +10:00
md_5
8a9501ffe4
Minecraft 1.20.5-pre1 support 2024-04-13 10:50:38 +10:00
Outfluencer
5e25c63c5a
#3646: Add experimental io_uring support 2024-04-09 21:39:06 +10:00
dependabot[bot]
bd963501ec
#3644: Bump org.apache.maven.plugins:maven-source-plugin from 3.3.0 to 3.3.1
Bumps [org.apache.maven.plugins:maven-source-plugin](https://github.com/apache/maven-source-plugin) from 3.3.0 to 3.3.1.
- [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.3.0...maven-source-plugin-3.3.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-source-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-09 21:22:35 +10:00
md_5
da795a7094
Minecraft 24w14a support 2024-04-07 08:18:48 +10:00
md_5
84d0ea73fa
Minor formatting fixes 2024-03-31 10:09:20 +11:00
Outfluencer
0851e39197
#3614: Make glist command output hover and clickable 2024-03-31 10:09:16 +11:00
md_5
86e6fdf8a2
Fix lombok induced JavaDoc error 2024-03-31 10:02:23 +11:00
md_5
6ab0f5eba7
#3621: Warn about use of valid chat colors and add test 2024-03-31 09:53:03 +11:00
Rothes
f224787222
#3621: Only serialize valid chat colors to "color" component 2024-03-31 09:51:04 +11:00
Janmm14
82684c7b6b
#3634: Improve chat test code style.
Stop use of subclass for static method call.
Make test helper methods static.
2024-03-31 09:38:18 +11:00
Janmm14
c2f73d32b8
#3634: Micro-optimize chat deserialization 2024-03-31 09:38:17 +11:00
md_5
e642b9dde1
Minecraft 24w13a support 2024-03-29 15:03:59 +11:00
dependabot[bot]
db623d10c5
#3640: Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.1 to 3.2.2
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.1 to 3.2.2.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.1...maven-gpg-plugin-3.2.2)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-gpg-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-27 08:22:21 +11:00
dependabot[bot]
61bb9f5b93
#3637: Bump org.projectlombok:lombok from 1.18.30 to 1.18.32
Bumps [org.projectlombok:lombok](https://github.com/projectlombok/lombok) from 1.18.30 to 1.18.32.
- [Changelog](https://github.com/projectlombok/lombok/blob/master/doc/changelog.markdown)
- [Commits](https://github.com/projectlombok/lombok/compare/v1.18.30...v1.18.32)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-23 15:58:33 +11:00
dependabot[bot]
9551b45328
#3639: Bump io.netty:netty-bom from 4.1.107.Final to 4.1.108.Final
Bumps [io.netty:netty-bom](https://github.com/netty/netty) from 4.1.107.Final to 4.1.108.Final.
- [Commits](https://github.com/netty/netty/compare/netty-4.1.107.Final...netty-4.1.108.Final)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-23 15:58:14 +11:00
dependabot[bot]
dc680b87eb
#3636: Bump org.apache.maven.plugins:maven-gpg-plugin from 3.1.0 to 3.2.1
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.1.0 to 3.2.1.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.1.0...maven-gpg-plugin-3.2.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-gpg-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-23 15:57:59 +11:00
dependabot[bot]
156eda78c6
#3635: Bump org.apache.maven.plugins:maven-compiler-plugin
Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.12.1 to 3.13.0.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.12.1...maven-compiler-plugin-3.13.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-compiler-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-23 15:57:46 +11:00
md_5
31be68af51
Minecraft 24w12a support 2024-03-23 15:57:06 +11:00
51 changed files with 496 additions and 318 deletions

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-2023 SpigotMC Pty. Ltd.
(c) 2012-2024 SpigotMC Pty. Ltd.

View File

@ -3,8 +3,9 @@ package net.md_5.bungee.api.event;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import net.md_5.bungee.api.Callback;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Event;
/**
* Event called as soon as a connection has a {@link ProxiedPlayer} and is ready
@ -13,11 +14,22 @@ import net.md_5.bungee.api.plugin.Event;
@Data
@ToString(callSuper = false)
@EqualsAndHashCode(callSuper = false)
public class PostLoginEvent extends Event
public class PostLoginEvent extends AsyncEvent<PostLoginEvent>
{
/**
* The player involved with this event.
*/
private final ProxiedPlayer player;
/**
* The server to which the player will initially be connected.
*/
private ServerInfo target;
public PostLoginEvent(ProxiedPlayer player, ServerInfo target, Callback<PostLoginEvent> done)
{
super( done );
this.player = player;
this.target = target;
}
}

View File

@ -61,6 +61,11 @@ class LibraryLoader
logger.log( Level.INFO, "Downloading {0}", event.getResource().getRepositoryUrl() + event.getResource().getResourceName() );
}
} );
// SPIGOT-7638: Add system properties,
// since JdkVersionProfileActivator needs 'java.version' when a profile has the 'jdk' element
// otherwise it will silently fail and not resolves the dependencies in the affected pom.
session.setSystemProperties( System.getProperties() );
session.setReadOnly();
this.repositories = repository.newResolutionRepositories( session, Arrays.asList( new RemoteRepository.Builder( "central", "default", "https://repo.maven.apache.org/maven2" ).build() ) );

View File

@ -38,7 +38,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<version>3.4.1</version>
<configuration>
<archive>
<manifestEntries>
@ -52,7 +52,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.2</version>
<version>3.5.3</version>
<executions>
<execution>
<phase>package</phase>

View File

@ -244,7 +244,7 @@ public final class ChatColor
public static ChatColor of(String string)
{
Preconditions.checkArgument( string != null, "string cannot be null" );
if ( string.startsWith( "#" ) && string.length() == 7 )
if ( string.length() == 7 && string.charAt( 0 ) == '#' )
{
int rgb;
try

View File

@ -253,6 +253,9 @@ public abstract class BaseComponent
/**
* Set this component's color.
* <p>
* <b>Warning: This should be a color, not formatting code (ie,
* {@link ChatColor#color} should not be null).</b>
*
* @param color the component color, or null to use the default
*/

View File

@ -18,6 +18,9 @@ public final class ComponentStyle implements Cloneable
/**
* The color of this style.
* <p>
* <b>Warning: This should be a color, not formatting code (ie,
* {@link ChatColor#color} should not be null).</b>
*/
private ChatColor color;
/**

View File

@ -19,7 +19,7 @@ import net.md_5.bungee.chat.TranslationRegistry;
public final class TranslatableComponent extends BaseComponent
{
private final Pattern format = Pattern.compile( "%(?:(\\d+)\\$)?([A-Za-z%]|$)" );
private static final Pattern FORMAT = Pattern.compile( "%(?:(\\d+)\\$)?([A-Za-z%]|$)" );
/**
* The key into the Minecraft locale files to use for the translation. The
@ -44,10 +44,11 @@ public final class TranslatableComponent extends BaseComponent
{
super( original );
setTranslate( original.getTranslate() );
setFallback( original.getFallback() );
if ( original.getWith() != null )
{
List<BaseComponent> temp = new ArrayList<BaseComponent>();
List<BaseComponent> temp = new ArrayList<>();
for ( BaseComponent baseComponent : original.getWith() )
{
temp.add( baseComponent.duplicate() );
@ -177,7 +178,7 @@ public final class TranslatableComponent extends BaseComponent
trans = fallback;
}
Matcher matcher = format.matcher( trans );
Matcher matcher = FORMAT.matcher( trans );
int position = 0;
int i = 0;
while ( matcher.find( position ) )

View File

@ -23,59 +23,62 @@ public class BaseComponentSerializer
{
component.applyStyle( context.deserialize( object, ComponentStyle.class ) );
if ( object.has( "insertion" ) )
JsonElement insertion = object.get( "insertion" );
if ( insertion != null )
{
component.setInsertion( object.get( "insertion" ).getAsString() );
component.setInsertion( insertion.getAsString() );
}
//Events
if ( object.has( "clickEvent" ) )
JsonObject clickEvent = object.getAsJsonObject( "clickEvent" );
if ( clickEvent != null )
{
JsonObject event = object.getAsJsonObject( "clickEvent" );
component.setClickEvent( new ClickEvent(
ClickEvent.Action.valueOf( event.get( "action" ).getAsString().toUpperCase( Locale.ROOT ) ),
( event.has( "value" ) ) ? event.get( "value" ).getAsString() : "" ) );
ClickEvent.Action.valueOf( clickEvent.get( "action" ).getAsString().toUpperCase( Locale.ROOT ) ),
( clickEvent.has( "value" ) ) ? clickEvent.get( "value" ).getAsString() : "" ) );
}
if ( object.has( "hoverEvent" ) )
JsonObject hoverEventJson = object.getAsJsonObject( "hoverEvent" );
if ( hoverEventJson != null )
{
JsonObject event = object.getAsJsonObject( "hoverEvent" );
HoverEvent hoverEvent = null;
HoverEvent.Action action = HoverEvent.Action.valueOf( event.get( "action" ).getAsString().toUpperCase( Locale.ROOT ) );
HoverEvent.Action action = HoverEvent.Action.valueOf( hoverEventJson.get( "action" ).getAsString().toUpperCase( Locale.ROOT ) );
if ( event.has( "value" ) )
JsonElement value = hoverEventJson.get( "value" );
if ( value != null )
{
JsonElement contents = event.get( "value" );
// Plugins previously had support to pass BaseComponent[] into any action.
// If the GSON is possible to be parsed as BaseComponent, attempt to parse as so.
BaseComponent[] components;
if ( contents.isJsonArray() )
if ( value.isJsonArray() )
{
components = context.deserialize( contents, BaseComponent[].class );
components = context.deserialize( value, BaseComponent[].class );
} else
{
components = new BaseComponent[]
{
context.deserialize( contents, BaseComponent.class )
context.deserialize( value, BaseComponent.class )
};
}
hoverEvent = new HoverEvent( action, components );
} else if ( event.has( "contents" ) )
} else
{
JsonElement contents = event.get( "contents" );
Content[] list;
if ( contents.isJsonArray() )
JsonElement contents = hoverEventJson.get( "contents" );
if ( contents != null )
{
list = context.deserialize( contents, HoverEvent.getClass( action, true ) );
} else
{
list = new Content[]
Content[] list;
if ( contents.isJsonArray() )
{
context.deserialize( contents, HoverEvent.getClass( action, false ) )
};
list = context.deserialize( contents, HoverEvent.getClass( action, true ) );
} else
{
list = new Content[]
{
context.deserialize( contents, HoverEvent.getClass( action, false ) )
};
}
hoverEvent = new HoverEvent( action, new ArrayList<>( Arrays.asList( list ) ) );
}
hoverEvent = new HoverEvent( action, new ArrayList<>( Arrays.asList( list ) ) );
}
if ( hoverEvent != null )
@ -84,9 +87,10 @@ public class BaseComponentSerializer
}
}
if ( object.has( "extra" ) )
JsonElement extra = object.get( "extra" );
if ( extra != null )
{
component.setExtra( Arrays.asList( context.<BaseComponent[]>deserialize( object.get( "extra" ), BaseComponent[].class ) ) );
component.setExtra( Arrays.asList( context.deserialize( extra, BaseComponent[].class ) ) );
}
}

View File

@ -9,6 +9,7 @@ import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
import java.util.Map;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.ComponentStyle;
import net.md_5.bungee.api.chat.ComponentStyleBuilder;
@ -62,7 +63,7 @@ public class ComponentStyleSerializer implements JsonSerializer<ComponentStyle>,
{
object.addProperty( "obfuscated", style.isObfuscatedRaw() );
}
if ( style.hasColor() )
if ( style.hasColor() && style.getColor().getColor() != null )
{
object.addProperty( "color", style.getColor().getName() );
}
@ -77,33 +78,34 @@ public class ComponentStyleSerializer implements JsonSerializer<ComponentStyle>,
{
ComponentStyleBuilder builder = ComponentStyle.builder();
JsonObject object = json.getAsJsonObject();
if ( object.has( "bold" ) )
for ( Map.Entry<String, JsonElement> entry : object.entrySet() )
{
builder.bold( getAsBoolean( object.get( "bold" ) ) );
}
if ( object.has( "italic" ) )
{
builder.italic( getAsBoolean( object.get( "italic" ) ) );
}
if ( object.has( "underlined" ) )
{
builder.underlined( getAsBoolean( object.get( "underlined" ) ) );
}
if ( object.has( "strikethrough" ) )
{
builder.strikethrough( getAsBoolean( object.get( "strikethrough" ) ) );
}
if ( object.has( "obfuscated" ) )
{
builder.obfuscated( getAsBoolean( object.get( "obfuscated" ) ) );
}
if ( object.has( "color" ) )
{
builder.color( ChatColor.of( object.get( "color" ).getAsString() ) );
}
if ( object.has( "font" ) )
{
builder.font( object.get( "font" ).getAsString() );
String name = entry.getKey();
JsonElement value = entry.getValue();
switch ( name )
{
case "bold":
builder.bold( getAsBoolean( value ) );
break;
case "italic":
builder.italic( getAsBoolean( value ) );
break;
case "underlined":
builder.underlined( getAsBoolean( value ) );
break;
case "strikethrough":
builder.strikethrough( getAsBoolean( value ) );
break;
case "obfuscated":
builder.obfuscated( getAsBoolean( value ) );
break;
case "color":
builder.color( ChatColor.of( value.getAsString() ) );
break;
case "font":
builder.font( value.getAsString() );
break;
}
}
return builder.build();
}

View File

@ -17,13 +17,14 @@ public class KeybindComponentSerializer extends BaseComponentSerializer implemen
public KeybindComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
{
JsonObject object = json.getAsJsonObject();
if ( !object.has( "keybind" ) )
JsonElement keybind = object.get( "keybind" );
if ( keybind == null )
{
throw new JsonParseException( "Could not parse JSON: missing 'keybind' property" );
}
KeybindComponent component = new KeybindComponent();
deserialize( object, component, context );
component.setKeybind( object.get( "keybind" ).getAsString() );
component.setKeybind( keybind.getAsString() );
return component;
}

View File

@ -17,22 +17,29 @@ public class ScoreComponentSerializer extends BaseComponentSerializer implements
public ScoreComponent deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException
{
JsonObject json = element.getAsJsonObject();
if ( !json.has( "score" ) )
JsonObject score = json.getAsJsonObject( "score" );
if ( score == null )
{
throw new JsonParseException( "Could not parse JSON: missing 'score' property" );
}
JsonObject score = json.get( "score" ).getAsJsonObject();
if ( !score.has( "name" ) || !score.has( "objective" ) )
JsonElement nameJson = score.get( "name" );
if ( nameJson == null )
{
throw new JsonParseException( "A score component needs at least a name (and an objective)" );
}
JsonElement objectiveJson = score.get( "objective" );
if ( objectiveJson == null )
{
throw new JsonParseException( "A score component needs at least a name and an objective" );
}
String name = score.get( "name" ).getAsString();
String objective = score.get( "objective" ).getAsString();
String name = nameJson.getAsString();
String objective = objectiveJson.getAsString();
ScoreComponent component = new ScoreComponent( name, objective );
if ( score.has( "value" ) && !score.get( "value" ).getAsString().isEmpty() )
JsonElement value = score.get( "value" );
if ( value != null && !value.getAsString().isEmpty() )
{
component.setValue( score.get( "value" ).getAsString() );
component.setValue( value.getAsString() );
}
deserialize( json, component, context );

View File

@ -17,15 +17,17 @@ public class SelectorComponentSerializer extends BaseComponentSerializer impleme
public SelectorComponent deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException
{
JsonObject object = element.getAsJsonObject();
if ( !object.has( "selector" ) )
JsonElement selector = object.get( "selector" );
if ( selector == null )
{
throw new JsonParseException( "Could not parse JSON: missing 'selector' property" );
}
SelectorComponent component = new SelectorComponent( object.get( "selector" ).getAsString() );
SelectorComponent component = new SelectorComponent( selector.getAsString() );
if ( object.has( "separator" ) )
JsonElement separator = object.get( "separator" );
if ( separator != null )
{
component.setSeparator( ComponentSerializer.deserialize( object.get( "separator" ).getAsString() ) );
component.setSeparator( ComponentSerializer.deserialize( separator.getAsString() ) );
}
deserialize( object, component, context );

View File

@ -18,9 +18,10 @@ public class TextComponentSerializer extends BaseComponentSerializer implements
{
TextComponent component = new TextComponent();
JsonObject object = json.getAsJsonObject();
if ( object.has( "text" ) )
JsonElement text = object.get( "text" );
if ( text != null )
{
component.setText( object.get( "text" ).getAsString() );
component.setText( text.getAsString() );
}
deserialize( object, component, context );
return component;

View File

@ -21,18 +21,21 @@ public class TranslatableComponentSerializer extends BaseComponentSerializer imp
TranslatableComponent component = new TranslatableComponent();
JsonObject object = json.getAsJsonObject();
deserialize( object, component, context );
if ( !object.has( "translate" ) )
JsonElement translate = object.get( "translate" );
if ( translate == null )
{
throw new JsonParseException( "Could not parse JSON: missing 'translate' property" );
}
component.setTranslate( object.get( "translate" ).getAsString() );
if ( object.has( "with" ) )
component.setTranslate( translate.getAsString() );
JsonElement with = object.get( "with" );
if ( with != null )
{
component.setWith( Arrays.asList( context.deserialize( object.get( "with" ), BaseComponent[].class ) ) );
component.setWith( Arrays.asList( context.deserialize( with, BaseComponent[].class ) ) );
}
if ( object.has( "fallback" ) )
JsonElement fallback = object.get( "fallback" );
if ( fallback != null )
{
component.setFallback( object.get( "fallback" ).getAsString() );
component.setFallback( fallback.getAsString() );
}
return component;
}

View File

@ -1,5 +1,6 @@
package net.md_5.bungee.api.chat;
import static net.md_5.bungee.api.ChatColor.*;
import static org.junit.jupiter.api.Assertions.*;
import java.awt.Color;
import java.util.function.BiFunction;
@ -7,7 +8,6 @@ import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.ObjIntConsumer;
import java.util.function.Supplier;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.hover.content.Entity;
import net.md_5.bungee.api.chat.hover.content.Text;
import net.md_5.bungee.chat.ComponentSerializer;
@ -20,14 +20,14 @@ public class ComponentsTest
{
String json = ComponentSerializer.toString( components );
BaseComponent[] parsed = ComponentSerializer.parse( json );
assertEquals( TextComponent.toLegacyText( parsed ), TextComponent.toLegacyText( components ) );
assertEquals( BaseComponent.toLegacyText( parsed ), BaseComponent.toLegacyText( components ) );
}
public static void testDissembleReassemble(BaseComponent component)
{
String json = ComponentSerializer.toString( component );
BaseComponent[] parsed = ComponentSerializer.parse( json );
assertEquals( TextComponent.toLegacyText( parsed ), TextComponent.toLegacyText( component ) );
assertEquals( BaseComponent.toLegacyText( parsed ), BaseComponent.toLegacyText( component ) );
}
public static void testAssembleDissemble(String json, boolean modern)
@ -100,7 +100,7 @@ public class ComponentsTest
@Test
public void testEmptyComponentBuilderCreate()
{
this.testEmptyComponentBuilder(
testEmptyComponentBuilder(
ComponentBuilder::create,
(components) -> assertEquals( components.length, 0 ),
(components, size) -> assertEquals( size, components.length )
@ -110,14 +110,14 @@ public class ComponentsTest
@Test
public void testEmptyComponentBuilderBuild()
{
this.testEmptyComponentBuilder(
testEmptyComponentBuilder(
ComponentBuilder::build,
(component) -> assertNull( component.getExtra() ),
(component, size) -> assertEquals( component.getExtra().size(), size )
);
}
private <T> void testEmptyComponentBuilder(Function<ComponentBuilder, T> componentBuilder, Consumer<T> emptyAssertion, ObjIntConsumer<T> sizedAssertion)
private static <T> void testEmptyComponentBuilder(Function<ComponentBuilder, T> componentBuilder, Consumer<T> emptyAssertion, ObjIntConsumer<T> sizedAssertion)
{
ComponentBuilder builder = new ComponentBuilder();
@ -137,9 +137,9 @@ public class ComponentsTest
{
ComponentBuilder builder = new ComponentBuilder();
assertNotNull( builder.getCurrentComponent() );
builder.color( ChatColor.GREEN );
builder.color( GREEN );
builder.append( "test ", ComponentBuilder.FormatRetention.ALL );
assertEquals( builder.getCurrentComponent().getColor(), ChatColor.GREEN );
assertEquals( builder.getCurrentComponent().getColor(), GREEN );
}
@Test
@ -155,6 +155,17 @@ public class ComponentsTest
assertThrows( IndexOutOfBoundsException.class, () -> builder.getComponent( 1 ) );
}
@Test
public void testFormatNotColor()
{
BaseComponent[] component = new ComponentBuilder().color( BOLD ).append( "Test" ).create();
String json = ComponentSerializer.toString( component );
BaseComponent[] parsed = ComponentSerializer.parse( json );
assertNull( parsed[0].getColorRaw(), "Format should not be preserved as color" );
}
@Test
public void testComponentParting()
{
@ -176,8 +187,8 @@ public class ComponentsTest
@Test
public void testToLegacyFromLegacy()
{
String text = "§a§lHello §f§kworld§7!";
assertEquals( text, TextComponent.toLegacyText( TextComponent.fromLegacyText( text ) ) );
String text = "" + GREEN + BOLD + "Hello " + WHITE + MAGIC + "world" + GRAY + "!";
assertEquals( text, BaseComponent.toLegacyText( TextComponent.fromLegacyText( text ) ) );
}
@Test
@ -218,7 +229,7 @@ public class ComponentsTest
@Test
public void testLegacyComponentBuilderAppend()
{
String text = "§a§lHello §r§kworld§7!";
String text = "" + GREEN + BOLD + "Hello " + RESET + MAGIC + "world" + GRAY + "!";
BaseComponent[] components = TextComponent.fromLegacyText( text );
BaseComponent[] builderComponents = new ComponentBuilder().append( components ).create();
assertArrayEquals( components, builderComponents );
@ -337,20 +348,20 @@ public class ComponentsTest
@Test
public void testFormatRetentionCopyFormattingCreate()
{
this.testFormatRetentionCopyFormatting( () -> new HoverEvent( HoverEvent.Action.SHOW_TEXT, new ComponentBuilder( "Test" ).create() ) );
testFormatRetentionCopyFormatting( () -> new HoverEvent( HoverEvent.Action.SHOW_TEXT, new ComponentBuilder( "Test" ).create() ) );
}
@Test
public void testFormatRetentionCopyFormattingBuild()
{
this.testFormatRetentionCopyFormatting( () -> new HoverEvent( HoverEvent.Action.SHOW_TEXT, new Text( new ComponentBuilder( "Test" ).build() ) ) );
testFormatRetentionCopyFormatting( () -> new HoverEvent( HoverEvent.Action.SHOW_TEXT, new Text( new ComponentBuilder( "Test" ).build() ) ) );
}
private void testFormatRetentionCopyFormatting(Supplier<HoverEvent> hoverEventSupplier)
private static void testFormatRetentionCopyFormatting(Supplier<HoverEvent> hoverEventSupplier)
{
TextComponent first = new TextComponent( "Hello" );
first.setBold( true );
first.setColor( ChatColor.RED );
first.setColor( RED );
first.setClickEvent( new ClickEvent( ClickEvent.Action.RUN_COMMAND, "test" ) );
first.setHoverEvent( hoverEventSupplier.get() );
@ -365,18 +376,18 @@ public class ComponentsTest
@Test
public void testBuilderCloneCreate()
{
this.testBuilderClone( (builder) -> TextComponent.toLegacyText( builder.create() ) );
testBuilderClone( (builder) -> BaseComponent.toLegacyText( builder.create() ) );
}
@Test
public void testBuilderCloneBuild()
{
this.testBuilderClone( (builder) -> TextComponent.toLegacyText( builder.build() ) );
testBuilderClone( (builder) -> BaseComponent.toLegacyText( builder.build() ) );
}
private void testBuilderClone(Function<ComponentBuilder, String> legacyTextFunction)
private static void testBuilderClone(Function<ComponentBuilder, String> legacyTextFunction)
{
ComponentBuilder builder = new ComponentBuilder( "Hello " ).color( ChatColor.RED ).append( "world" ).color( ChatColor.DARK_RED );
ComponentBuilder builder = new ComponentBuilder( "Hello " ).color( RED ).append( "world" ).color( DARK_RED );
ComponentBuilder cloned = new ComponentBuilder( builder );
assertEquals( legacyTextFunction.apply( builder ), legacyTextFunction.apply( cloned ) );
@ -385,7 +396,7 @@ public class ComponentsTest
@Test
public void testBuilderAppendCreateMixedComponents()
{
this.testBuilderAppendMixedComponents(
testBuilderAppendMixedComponents(
ComponentBuilder::create,
(components, index) -> components[index]
);
@ -394,13 +405,13 @@ public class ComponentsTest
@Test
public void testBuilderAppendBuildMixedComponents()
{
this.testBuilderAppendMixedComponents(
testBuilderAppendMixedComponents(
ComponentBuilder::build,
(component, index) -> component.getExtra().get( index )
);
}
private <T> void testBuilderAppendMixedComponents(Function<ComponentBuilder, T> componentBuilder, BiFunction<T, Integer, BaseComponent> extraGetter)
private static <T> void testBuilderAppendMixedComponents(Function<ComponentBuilder, T> componentBuilder, BiFunction<T, Integer, BaseComponent> extraGetter)
{
ComponentBuilder builder = new ComponentBuilder( "Hello " );
TextComponent textComponent = new TextComponent( "world " );
@ -443,12 +454,12 @@ public class ComponentsTest
@Test
public void testBuilderAppendCreate()
{
this.testBuilderAppend(
testBuilderAppend(
() -> new HoverEvent( HoverEvent.Action.SHOW_TEXT, new ComponentBuilder( "Hello world" ).create() ),
ComponentBuilder::create,
(components, index) -> components[index],
BaseComponent::toPlainText,
ChatColor.YELLOW + "Hello " + ChatColor.GREEN + "world!",
YELLOW + "Hello " + GREEN + "world!",
BaseComponent::toLegacyText
);
}
@ -456,24 +467,24 @@ public class ComponentsTest
@Test
public void testBuilderAppendBuild()
{
this.testBuilderAppend(
testBuilderAppend(
() -> new HoverEvent( HoverEvent.Action.SHOW_TEXT, new Text( new ComponentBuilder( "Hello world" ).build() ) ),
ComponentBuilder::build,
(component, index) -> component.getExtra().get( index ),
(component) -> BaseComponent.toPlainText( component ),
// An extra format code is appended to the beginning because there is an empty TextComponent at the start of every component
ChatColor.WHITE.toString() + ChatColor.YELLOW + "Hello " + ChatColor.GREEN + "world!",
WHITE.toString() + YELLOW + "Hello " + GREEN + "world!",
(component) -> BaseComponent.toLegacyText( component )
);
}
private <T> void testBuilderAppend(Supplier<HoverEvent> hoverEventSupplier, Function<ComponentBuilder, T> componentBuilder, BiFunction<T, Integer, BaseComponent> extraGetter, Function<T, String> toPlainTextFunction, String expectedLegacyText, Function<T, String> toLegacyTextFunction)
private static <T> void testBuilderAppend(Supplier<HoverEvent> hoverEventSupplier, Function<ComponentBuilder, T> componentBuilder, BiFunction<T, Integer, BaseComponent> extraGetter, Function<T, String> toPlainTextFunction, String expectedLegacyText, Function<T, String> toLegacyTextFunction)
{
ClickEvent clickEvent = new ClickEvent( ClickEvent.Action.RUN_COMMAND, "/help " );
HoverEvent hoverEvent = hoverEventSupplier.get();
ComponentBuilder builder = new ComponentBuilder( "Hello " ).color( ChatColor.YELLOW );
builder.append( new ComponentBuilder( "world!" ).color( ChatColor.GREEN ).event( hoverEvent ).event( clickEvent ).create() ); // Intentionally using create() to append multiple individual components
ComponentBuilder builder = new ComponentBuilder( "Hello " ).color( YELLOW );
builder.append( new ComponentBuilder( "world!" ).color( GREEN ).event( hoverEvent ).event( clickEvent ).create() ); // Intentionally using create() to append multiple individual components
T component = componentBuilder.apply( builder );
@ -486,10 +497,10 @@ public class ComponentsTest
@Test
public void testBuilderAppendLegacyCreate()
{
this.testBuilderAppendLegacy(
testBuilderAppendLegacy(
ComponentBuilder::create,
BaseComponent::toPlainText,
ChatColor.YELLOW + "Hello " + ChatColor.GREEN + "world!",
YELLOW + "Hello " + GREEN + "world!",
BaseComponent::toLegacyText
);
}
@ -497,19 +508,19 @@ public class ComponentsTest
@Test
public void testBuilderAppendLegacyBuild()
{
this.testBuilderAppendLegacy(
testBuilderAppendLegacy(
ComponentBuilder::build,
(component) -> BaseComponent.toPlainText( component ),
// An extra format code is appended to the beginning because there is an empty TextComponent at the start of every component
ChatColor.WHITE.toString() + ChatColor.YELLOW + "Hello " + ChatColor.GREEN + "world!",
WHITE.toString() + YELLOW + "Hello " + GREEN + "world!",
(component) -> BaseComponent.toLegacyText( component )
);
}
private <T> void testBuilderAppendLegacy(Function<ComponentBuilder, T> componentBuilder, Function<T, String> toPlainTextFunction, String expectedLegacyString, Function<T, String> toLegacyTextFunction)
private static <T> void testBuilderAppendLegacy(Function<ComponentBuilder, T> componentBuilder, Function<T, String> toPlainTextFunction, String expectedLegacyString, Function<T, String> toLegacyTextFunction)
{
ComponentBuilder builder = new ComponentBuilder( "Hello " ).color( ChatColor.YELLOW );
builder.appendLegacy( "§aworld!" );
ComponentBuilder builder = new ComponentBuilder( "Hello " ).color( YELLOW );
builder.appendLegacy( GREEN + "world!" );
T component = componentBuilder.apply( builder );
@ -521,26 +532,26 @@ public class ComponentsTest
public void testBasicComponent()
{
TextComponent textComponent = new TextComponent( "Hello world" );
textComponent.setColor( ChatColor.RED );
textComponent.setColor( RED );
assertEquals( "Hello world", textComponent.toPlainText() );
assertEquals( ChatColor.RED + "Hello world", textComponent.toLegacyText() );
assertEquals( RED + "Hello world", textComponent.toLegacyText() );
}
@Test
public void testLegacyConverter()
{
BaseComponent[] test1 = TextComponent.fromLegacyText( ChatColor.AQUA + "Aqua " + ChatColor.RED + ChatColor.BOLD + "RedBold" );
BaseComponent[] test1 = TextComponent.fromLegacyText( AQUA + "Aqua " + RED + BOLD + "RedBold" );
assertEquals( "Aqua RedBold", BaseComponent.toPlainText( test1 ) );
assertEquals( ChatColor.AQUA + "Aqua " + ChatColor.RED + ChatColor.BOLD + "RedBold", BaseComponent.toLegacyText( test1 ) );
assertEquals( AQUA + "Aqua " + RED + BOLD + "RedBold", BaseComponent.toLegacyText( test1 ) );
BaseComponent[] test2 = TextComponent.fromLegacyText( "Text http://spigotmc.org " + ChatColor.GREEN + "google.com/test" );
BaseComponent[] test2 = TextComponent.fromLegacyText( "Text http://spigotmc.org " + GREEN + "google.com/test" );
assertEquals( "Text http://spigotmc.org google.com/test", BaseComponent.toPlainText( test2 ) );
//The extra ChatColor instances are sometimes inserted when not needed but it doesn't change the result
assertEquals( ChatColor.WHITE + "Text " + ChatColor.WHITE + "http://spigotmc.org" + ChatColor.WHITE
+ " " + ChatColor.GREEN + "google.com/test" + ChatColor.GREEN, BaseComponent.toLegacyText( test2 ) );
assertEquals( WHITE + "Text " + WHITE + "http://spigotmc.org" + WHITE
+ " " + GREEN + "google.com/test" + GREEN, BaseComponent.toLegacyText( test2 ) );
ClickEvent url1 = test2[1].getClickEvent();
assertNotNull( url1 );
@ -553,36 +564,13 @@ public class ComponentsTest
assertEquals( "http://google.com/test", url2.getValue() );
}
@Test
public void testTranslateComponent()
{
TranslatableComponent item = new TranslatableComponent( "item.swordGold.name" );
item.setColor( ChatColor.AQUA );
TranslatableComponent translatableComponent = new TranslatableComponent( "commands.give.success",
item, "5",
"thinkofdeath" );
assertEquals( "Given Golden Sword * 5 to thinkofdeath", translatableComponent.toPlainText() );
assertEquals( ChatColor.WHITE + "Given " + ChatColor.AQUA + "Golden Sword" + ChatColor.WHITE
+ " * " + ChatColor.WHITE + "5" + ChatColor.WHITE + " to " + ChatColor.WHITE + "thinkofdeath",
translatableComponent.toLegacyText() );
TranslatableComponent positional = new TranslatableComponent( "book.pageIndicator", "5", "50" );
assertEquals( "Page 5 of 50", positional.toPlainText() );
assertEquals( ChatColor.WHITE + "Page " + ChatColor.WHITE + "5" + ChatColor.WHITE + " of " + ChatColor.WHITE + "50", positional.toLegacyText() );
TranslatableComponent one_four_two = new TranslatableComponent( "filled_map.buried_treasure" );
assertEquals( "Buried Treasure Map", one_four_two.toPlainText() );
}
@Test
public void testBuilderCreate()
{
this.testBuilder(
testBuilder(
ComponentBuilder::create,
BaseComponent::toPlainText,
ChatColor.RED + "Hello " + ChatColor.BLUE + ChatColor.BOLD + "World" + ChatColor.YELLOW + ChatColor.BOLD + "!",
RED + "Hello " + BLUE + BOLD + "World" + YELLOW + BOLD + "!",
BaseComponent::toLegacyText
);
}
@ -590,20 +578,20 @@ public class ComponentsTest
@Test
public void testBuilderBuild()
{
this.testBuilder(
testBuilder(
ComponentBuilder::build,
(component) -> BaseComponent.toPlainText( component ),
// An extra format code is appended to the beginning because there is an empty TextComponent at the start of every component
ChatColor.WHITE.toString() + ChatColor.RED + "Hello " + ChatColor.BLUE + ChatColor.BOLD + "World" + ChatColor.YELLOW + ChatColor.BOLD + "!",
WHITE.toString() + RED + "Hello " + BLUE + BOLD + "World" + YELLOW + BOLD + "!",
(component) -> BaseComponent.toLegacyText( component )
);
}
private <T> void testBuilder(Function<ComponentBuilder, T> componentBuilder, Function<T, String> toPlainTextFunction, String expectedLegacyString, Function<T, String> toLegacyTextFunction)
private static <T> void testBuilder(Function<ComponentBuilder, T> componentBuilder, Function<T, String> toPlainTextFunction, String expectedLegacyString, Function<T, String> toLegacyTextFunction)
{
T component = componentBuilder.apply( new ComponentBuilder( "Hello " ).color( ChatColor.RED ).
append( "World" ).bold( true ).color( ChatColor.BLUE ).
append( "!" ).color( ChatColor.YELLOW ) );
T component = componentBuilder.apply( new ComponentBuilder( "Hello " ).color( RED ).
append( "World" ).bold( true ).color( BLUE ).
append( "!" ).color( YELLOW ) );
assertEquals( "Hello World!", toPlainTextFunction.apply( component ) );
assertEquals( expectedLegacyString, toLegacyTextFunction.apply( component ) );
@ -612,7 +600,7 @@ public class ComponentsTest
@Test
public void testBuilderCreateReset()
{
this.testBuilderReset(
testBuilderReset(
ComponentBuilder::create,
(components, index) -> components[index]
);
@ -621,25 +609,25 @@ public class ComponentsTest
@Test
public void testBuilderBuildReset()
{
this.testBuilderReset(
testBuilderReset(
ComponentBuilder::build,
(component, index) -> component.getExtra().get( index )
);
}
private <T> void testBuilderReset(Function<ComponentBuilder, T> componentBuilder, BiFunction<T, Integer, BaseComponent> extraGetter)
private static <T> void testBuilderReset(Function<ComponentBuilder, T> componentBuilder, BiFunction<T, Integer, BaseComponent> extraGetter)
{
T component = componentBuilder.apply( new ComponentBuilder( "Hello " ).color( ChatColor.RED )
T component = componentBuilder.apply( new ComponentBuilder( "Hello " ).color( RED )
.append( "World" ).reset() );
assertEquals( ChatColor.RED, extraGetter.apply( component, 0 ).getColor() );
assertEquals( ChatColor.WHITE, extraGetter.apply( component, 1 ).getColor() );
assertEquals( RED, extraGetter.apply( component, 0 ).getColor() );
assertEquals( WHITE, extraGetter.apply( component, 1 ).getColor() );
}
@Test
public void testBuilderCreateFormatRetention()
{
this.testBuilderFormatRetention(
testBuilderFormatRetention(
ComponentBuilder::create,
(components, index) -> components[index]
);
@ -648,39 +636,39 @@ public class ComponentsTest
@Test
public void testBuilderBuildFormatRetention()
{
this.testBuilderFormatRetention(
testBuilderFormatRetention(
ComponentBuilder::build,
(component, index) -> component.getExtra().get( index )
);
}
private <T> void testBuilderFormatRetention(Function<ComponentBuilder, T> componentBuilder, BiFunction<T, Integer, BaseComponent> extraGetter)
private static <T> void testBuilderFormatRetention(Function<ComponentBuilder, T> componentBuilder, BiFunction<T, Integer, BaseComponent> extraGetter)
{
T noneRetention = componentBuilder.apply( new ComponentBuilder( "Hello " ).color( ChatColor.RED )
T noneRetention = componentBuilder.apply( new ComponentBuilder( "Hello " ).color( RED )
.append( "World", ComponentBuilder.FormatRetention.NONE ) );
assertEquals( ChatColor.RED, extraGetter.apply( noneRetention, 0 ).getColor() );
assertEquals( ChatColor.WHITE, extraGetter.apply( noneRetention, 1 ).getColor() );
assertEquals( RED, extraGetter.apply( noneRetention, 0 ).getColor() );
assertEquals( WHITE, extraGetter.apply( noneRetention, 1 ).getColor() );
HoverEvent testEvent = new HoverEvent( HoverEvent.Action.SHOW_TEXT, new Text( new ComponentBuilder( "test" ).build() ) );
T formattingRetention = componentBuilder.apply( new ComponentBuilder( "Hello " ).color( ChatColor.RED )
T formattingRetention = componentBuilder.apply( new ComponentBuilder( "Hello " ).color( RED )
.event( testEvent ).append( "World", ComponentBuilder.FormatRetention.FORMATTING ) );
assertEquals( ChatColor.RED, extraGetter.apply( formattingRetention, 0 ).getColor() );
assertEquals( RED, extraGetter.apply( formattingRetention, 0 ).getColor() );
assertEquals( testEvent, extraGetter.apply( formattingRetention, 0 ).getHoverEvent() );
assertEquals( ChatColor.RED, extraGetter.apply( formattingRetention, 1 ).getColor() );
assertEquals( RED, extraGetter.apply( formattingRetention, 1 ).getColor() );
assertNull( extraGetter.apply( formattingRetention, 1 ).getHoverEvent() );
ClickEvent testClickEvent = new ClickEvent( ClickEvent.Action.OPEN_URL, "http://www.example.com" );
T eventRetention = componentBuilder.apply( new ComponentBuilder( "Hello " ).color( ChatColor.RED )
T eventRetention = componentBuilder.apply( new ComponentBuilder( "Hello " ).color( RED )
.event( testEvent ).event( testClickEvent ).append( "World", ComponentBuilder.FormatRetention.EVENTS ) );
assertEquals( ChatColor.RED, extraGetter.apply( eventRetention, 0 ).getColor() );
assertEquals( RED, extraGetter.apply( eventRetention, 0 ).getColor() );
assertEquals( testEvent, extraGetter.apply( eventRetention, 0 ).getHoverEvent() );
assertEquals( testClickEvent, extraGetter.apply( eventRetention, 0 ).getClickEvent() );
assertEquals( ChatColor.WHITE, extraGetter.apply( eventRetention, 1 ).getColor() );
assertEquals( WHITE, extraGetter.apply( eventRetention, 1 ).getColor() );
assertEquals( testEvent, extraGetter.apply( eventRetention, 1 ).getHoverEvent() );
assertEquals( testClickEvent, extraGetter.apply( eventRetention, 1 ).getClickEvent() );
}
@ -698,9 +686,9 @@ public class ComponentsTest
{
TextComponent a = new TextComponent( "A" );
TextComponent b = new TextComponent( "B" );
b.setColor( ChatColor.AQUA );
b.setColor( AQUA );
TextComponent c = new TextComponent( "C" );
c.setColor( ChatColor.RED );
c.setColor( RED );
a.addExtra( b );
b.addExtra( c );
c.addExtra( a );
@ -712,7 +700,7 @@ public class ComponentsTest
{
TextComponent a = new TextComponent( "A" );
TextComponent b = new TextComponent( "B" );
b.setColor( ChatColor.AQUA );
b.setColor( AQUA );
a.addExtra( b );
a.addExtra( b );
ComponentSerializer.toString( a );
@ -723,9 +711,9 @@ public class ComponentsTest
{
TextComponent a = new TextComponent( "A" );
TextComponent b = new TextComponent( "B" );
b.setColor( ChatColor.AQUA );
b.setColor( AQUA );
TextComponent c = new TextComponent( "C" );
c.setColor( ChatColor.RED );
c.setColor( RED );
a.addExtra( b );
a.addExtra( c );
c.addExtra( a );
@ -741,15 +729,15 @@ public class ComponentsTest
// collect all invalid color codes (e.g. §z, §g, ...)
for ( char alphChar : "0123456789abcdefghijklmnopqrstuvwxyz".toCharArray() )
{
if ( ChatColor.ALL_CODES.indexOf( alphChar ) == -1 )
if ( ALL_CODES.indexOf( alphChar ) == -1 )
{
allInvalidColorCodes.append( ChatColor.COLOR_CHAR );
allInvalidColorCodes.append( COLOR_CHAR );
allInvalidColorCodes.append( alphChar );
}
}
// last char is a single '§'
allInvalidColorCodes.append( ChatColor.COLOR_CHAR );
allInvalidColorCodes.append( COLOR_CHAR );
String invalidColorCodesLegacyText = fromAndToLegacyText( allInvalidColorCodes.toString() );
String emptyLegacyText = fromAndToLegacyText( "" );
@ -761,10 +749,10 @@ public class ComponentsTest
@Test
public void testFormattingOnlyTextConversion()
{
String text = "§a";
String text = "" + GREEN;
BaseComponent[] converted = TextComponent.fromLegacyText( text );
assertEquals( ChatColor.GREEN, converted[0].getColor() );
assertEquals( GREEN, converted[0].getColor() );
String roundtripLegacyText = BaseComponent.toLegacyText( converted );
@ -799,8 +787,8 @@ public class ComponentsTest
@Test
public void testLegacyHack()
{
BaseComponent[] hexColored = new ComponentBuilder().color( ChatColor.of( Color.GRAY ) ).append( "Test" ).create();
String legacy = TextComponent.toLegacyText( hexColored );
BaseComponent[] hexColored = new ComponentBuilder().color( of( Color.GRAY ) ).append( "Test" ).create();
String legacy = BaseComponent.toLegacyText( hexColored );
BaseComponent[] reColored = TextComponent.fromLegacyText( legacy );
@ -810,7 +798,7 @@ public class ComponentsTest
@Test
public void testLegacyResetInBuilderCreate()
{
this.testLegacyResetInBuilder(
testLegacyResetInBuilder(
ComponentBuilder::create,
ComponentSerializer::toString
);
@ -819,7 +807,7 @@ public class ComponentsTest
@Test
public void testLegacyResetInBuilderBuild()
{
this.testLegacyResetInBuilder(
testLegacyResetInBuilder(
ComponentBuilder::build,
ComponentSerializer::toString
);
@ -842,8 +830,8 @@ public class ComponentsTest
assertTrue( style.isEmpty() );
style = ComponentStyle.builder()
.bold( true )
.build();
.bold( true )
.build();
assertFalse( style.isEmpty() );
}
@ -851,10 +839,10 @@ public class ComponentsTest
* In legacy chat, colors and reset both reset all formatting.
* Make sure it works in combination with ComponentBuilder.
*/
private <T> void testLegacyResetInBuilder(Function<ComponentBuilder, T> componentBuilder, Function<T, String> componentSerializer)
private static <T> void testLegacyResetInBuilder(Function<ComponentBuilder, T> componentBuilder, Function<T, String> componentSerializer)
{
ComponentBuilder builder = new ComponentBuilder();
BaseComponent[] a = TextComponent.fromLegacyText( "§4§n44444§rdd§6§l6666" );
BaseComponent[] a = TextComponent.fromLegacyText( "" + DARK_RED + UNDERLINE + "44444" + RESET + "dd" + GOLD + BOLD + "6666" );
String expected = "{\"extra\":[{\"underlined\":true,\"color\":\"dark_red\",\"text\":\"44444\"},{\"color\":"
+ "\"white\",\"text\":\"dd\"},{\"bold\":true,\"color\":\"gold\",\"text\":\"6666\"}],\"text\":\"\"}";
@ -865,7 +853,7 @@ public class ComponentsTest
String test1 = componentSerializer.apply( componentBuilder.apply( builder ) );
assertEquals( expected, test1 );
BaseComponent[] b = TextComponent.fromLegacyText( "§rrrrr" );
BaseComponent[] b = TextComponent.fromLegacyText( RESET + "rrrr" );
builder.append( b );
String test2 = componentSerializer.apply( componentBuilder.apply( builder ) );

View File

@ -1,5 +1,6 @@
package net.md_5.bungee.api.chat;
import static net.md_5.bungee.api.ChatColor.*;
import static org.junit.jupiter.api.Assertions.*;
import net.md_5.bungee.chat.ComponentSerializer;
import org.junit.jupiter.api.Test;
@ -12,7 +13,7 @@ public class TranslatableComponentTest
{
TranslatableComponent testComponent = new TranslatableComponent( "Test string with %s placeholders: %s", 2, "aoeu" );
assertEquals( "Test string with 2 placeholders: aoeu", testComponent.toPlainText() );
assertEquals( "§fTest string with §f2§f placeholders: §faoeu", testComponent.toLegacyText() );
assertEquals( WHITE + "Test string with " + WHITE + "2" + WHITE + " placeholders: " + WHITE + "aoeu", testComponent.toLegacyText() );
}
@Test
@ -22,7 +23,29 @@ public class TranslatableComponentTest
String jsonString = ComponentSerializer.toString( testComponent );
BaseComponent[] baseComponents = ComponentSerializer.parse( jsonString );
assertEquals( "Test string with a placeholder", TextComponent.toPlainText( baseComponents ) );
assertEquals( "§fTest string with §fa§f placeholder", TextComponent.toLegacyText( baseComponents ) );
assertEquals( "Test string with a placeholder", BaseComponent.toPlainText( baseComponents ) );
assertEquals( WHITE + "Test string with " + WHITE + "a" + WHITE + " placeholder", BaseComponent.toLegacyText( baseComponents ) );
}
@Test
public void testTranslateComponent()
{
TranslatableComponent item = new TranslatableComponent( "item.swordGold.name" );
item.setColor( AQUA );
TranslatableComponent translatableComponent = new TranslatableComponent( "commands.give.success",
item, "5", "thinkofdeath" );
assertEquals( "Given Golden Sword * 5 to thinkofdeath", translatableComponent.toPlainText() );
assertEquals( WHITE + "Given " + AQUA + "Golden Sword" + WHITE + " * " + WHITE + "5" + WHITE + " to " + WHITE + "thinkofdeath",
translatableComponent.toLegacyText() );
TranslatableComponent positional = new TranslatableComponent( "book.pageIndicator", "5", "50" );
assertEquals( "Page 5 of 50", positional.toPlainText() );
assertEquals( WHITE + "Page " + WHITE + "5" + WHITE + " of " + WHITE + "50", positional.toLegacyText() );
TranslatableComponent one_four_two = new TranslatableComponent( "filled_map.buried_treasure" );
assertEquals( "Buried Treasure Map", one_four_two.toPlainText() );
}
}

View File

@ -8,7 +8,7 @@ echo "Compiling mbedtls"
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="g++ -shared -fPIC -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 +1 @@
Subproject commit 8c89224991adff88d53cd380f42a2baa36f91454
Subproject commit 2ca6c285a0dd3f33982dd57299012dacab1ff206

View File

@ -4,12 +4,6 @@
#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

@ -4,12 +4,6 @@
#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;

@ -1 +1 @@
Subproject commit 4e4e4c4fbdad9dd034d8f05e2312bf845f0d4d15
Subproject commit 92530568d2c128b4432467b76a3b54d93d6350bd

10
pom.xml
View File

@ -71,7 +71,7 @@
<properties>
<build.number>unknown</build.number>
<lombok.version>1.18.30</lombok.version>
<lombok.version>1.18.32</lombok.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>
@ -82,7 +82,7 @@
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-bom</artifactId>
<version>4.1.107.Final</version>
<version>4.1.109.Final</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@ -151,7 +151,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.1</version>
<version>3.13.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@ -281,7 +281,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<version>3.3.1</version>
<executions>
<execution>
<phase>package</phase>
@ -356,7 +356,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<version>3.2.4</version>
<executions>
<execution>
<phase>verify</phase>

View File

@ -51,6 +51,7 @@ 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.Transfer;
import net.md_5.bungee.protocol.packet.UnsignedClientCommand;
import net.md_5.bungee.protocol.packet.ViewDistance;
public abstract class AbstractPacketHandler
@ -104,6 +105,10 @@ public abstract class AbstractPacketHandler
{
}
public void handle(UnsignedClientCommand command) throws Exception
{
}
public void handle(Respawn respawn) throws Exception
{
}

View File

@ -57,6 +57,7 @@ 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.Transfer;
import net.md_5.bungee.protocol.packet.UnsignedClientCommand;
import net.md_5.bungee.protocol.packet.ViewDistance;
public enum Protocol
@ -444,7 +445,7 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_4, 0x4F ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x51 ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x53 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x62 )
map( ProtocolConstants.MINECRAFT_1_20_5, 0x55 )
);
TO_CLIENT.registerPacket(
ServerData.class,
@ -513,7 +514,7 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_4, 0x12 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x14 ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x15 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x17 )
map( ProtocolConstants.MINECRAFT_1_20_5, 0x18 )
);
TO_SERVER.registerPacket( Chat.class,
Chat::new,
@ -528,13 +529,20 @@ public enum Protocol
ClientCommand.class,
ClientCommand::new,
map( ProtocolConstants.MINECRAFT_1_19, 0x03 ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x04 )
map( ProtocolConstants.MINECRAFT_1_19_1, 0x04 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x05 )
);
TO_SERVER.registerPacket(
UnsignedClientCommand.class,
UnsignedClientCommand::new,
map( ProtocolConstants.MINECRAFT_1_20_5, 0x04 )
);
TO_SERVER.registerPacket(
ClientChat.class,
ClientChat::new,
map( ProtocolConstants.MINECRAFT_1_19, 0x04 ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x05 )
map( ProtocolConstants.MINECRAFT_1_19_1, 0x05 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x06 )
);
TO_SERVER.registerPacket(
TabCompleteRequest.class,
@ -549,7 +557,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_1, 0x09 ),
map( ProtocolConstants.MINECRAFT_1_19_3, 0x08 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x09 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x0A )
map( ProtocolConstants.MINECRAFT_1_20_2, 0x0A ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x0B )
);
TO_SERVER.registerPacket(
ClientSettings.class,
@ -563,7 +572,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_1, 0x08 ),
map( ProtocolConstants.MINECRAFT_1_19_3, 0x07 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x08 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x09 )
map( ProtocolConstants.MINECRAFT_1_20_2, 0x09 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x0A )
);
TO_SERVER.registerPacket(
PluginMessage.class,
@ -581,17 +591,18 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_4, 0x0D ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x0F ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x10 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x11 )
map( ProtocolConstants.MINECRAFT_1_20_5, 0x12 )
);
TO_SERVER.registerPacket(
StartConfiguration.class,
StartConfiguration::new,
map( ProtocolConstants.MINECRAFT_1_20_2, 0x0B )
map( ProtocolConstants.MINECRAFT_1_20_2, 0x0B ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x0C )
);
TO_SERVER.registerPacket(
CookieResponse.class,
CookieResponse::new,
map( ProtocolConstants.MINECRAFT_1_20_5, 0x10 )
map( ProtocolConstants.MINECRAFT_1_20_5, 0x11 )
);
}
},
@ -724,12 +735,12 @@ public enum Protocol
TO_CLIENT.registerPacket(
StoreCookie.class,
StoreCookie::new,
map( ProtocolConstants.MINECRAFT_1_20_5, 0x09 )
map( ProtocolConstants.MINECRAFT_1_20_5, 0x0A )
);
TO_CLIENT.registerPacket(
Transfer.class,
Transfer::new,
map( ProtocolConstants.MINECRAFT_1_20_5, 0x0A )
map( ProtocolConstants.MINECRAFT_1_20_5, 0x0B )
);
TO_SERVER.registerPacket(

View File

@ -45,7 +45,7 @@ public class ProtocolConstants
public static final int MINECRAFT_1_20 = 763;
public static final int MINECRAFT_1_20_2 = 764;
public static final int MINECRAFT_1_20_3 = 765;
public static final int MINECRAFT_1_20_5 = 1073742003;
public static final int MINECRAFT_1_20_5 = 766;
public static final List<String> SUPPORTED_VERSIONS;
public static final List<Integer> SUPPORTED_VERSION_IDS;
@ -104,13 +104,14 @@ public class ProtocolConstants
ProtocolConstants.MINECRAFT_1_19_4,
ProtocolConstants.MINECRAFT_1_20,
ProtocolConstants.MINECRAFT_1_20_2,
ProtocolConstants.MINECRAFT_1_20_3
ProtocolConstants.MINECRAFT_1_20_3,
ProtocolConstants.MINECRAFT_1_20_5
);
if ( SNAPSHOT_SUPPORT )
{
// supportedVersions.add( "1.20.x" );
supportedVersionIds.add( ProtocolConstants.MINECRAFT_1_20_5 );
// supportedVersionIds.add( ProtocolConstants.MINECRAFT_1_20_5 );
}
SUPPORTED_VERSIONS = supportedVersions.build();

View File

@ -922,7 +922,10 @@ public class Commands extends DefinedPacket
get( "minecraft:template_mirror", VOID ),
get( "minecraft:template_rotation", VOID ),
get( "minecraft:uuid", VOID ),
get( "minecraft:heightmap", VOID )
get( "minecraft:heightmap", VOID ),
get( "minecraft:loot_table", VOID ),
get( "minecraft:loot_predicate", VOID ),
get( "minecraft:loot_modifier", VOID )
};
}

View File

@ -37,6 +37,11 @@ public class LoginSuccess extends DefinedPacket
{
properties = readProperties( buf );
}
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_5 )
{
// Whether the client should disconnect on its own if it receives invalid data from the server
buf.readBoolean();
}
}
@Override
@ -54,6 +59,12 @@ public class LoginSuccess extends DefinedPacket
{
writeProperties( properties, buf );
}
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_5 )
{
// Whether the client should disconnect on its own if it receives invalid data from the server
// Vanilla sends true so we also send true
buf.writeBoolean( true );
}
}
@Override

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 UnsignedClientCommand extends DefinedPacket
{
private String command;
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
command = readString( buf, 256 );
}
@Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
writeString( command, buf );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@ -50,6 +50,18 @@
<classifier>linux-aarch_64</classifier>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.netty.incubator</groupId>
<artifactId>netty-incubator-transport-native-io_uring</artifactId>
<version>0.0.25.Final</version>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>io.netty.incubator</groupId>
<artifactId>netty-incubator-transport-native-io_uring</artifactId>
<version>0.0.25.Final</version>
<classifier>linux-aarch_64</classifier>
</dependency>
<dependency>
<groupId>fr.pandacube.bungeecord</groupId>
<artifactId>bungeecord-api</artifactId>
@ -95,7 +107,7 @@
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.2.0</version>
<version>8.3.0</version>
<scope>runtime</scope>
</dependency>
<!-- add these back in as they are not exposed by the API -->

View File

@ -130,7 +130,7 @@ public class ServerConnector extends PacketHandler
channel.write( copiedHandshake );
channel.setProtocol( Protocol.LOGIN );
channel.write( new LoginRequest( user.getName(), null, user.getUniqueId() ) );
channel.write( new LoginRequest( user.getName(), null, user.getRewriteId() ) );
}
@Override
@ -365,7 +365,7 @@ public class ServerConnector extends PacketHandler
} else
{
LoginResult loginProfile = user.getPendingConnection().getLoginProfile();
user.unsafe().sendPacket( new LoginSuccess( user.getUniqueId(), user.getName(), ( loginProfile == null ) ? null : loginProfile.getProperties() ) );
user.unsafe().sendPacket( new LoginSuccess( user.getRewriteId(), user.getName(), ( loginProfile == null ) ? null : loginProfile.getProperties() ) );
user.getCh().setEncodeProtocol( Protocol.CONFIGURATION );
}
}

View File

@ -642,6 +642,11 @@ public final class UserConnection implements ProxiedPlayer
return getPendingConnection().getUniqueId();
}
public UUID getRewriteId()
{
return getPendingConnection().getRewriteId();
}
public void setSettings(ClientSettings settings)
{
this.settings = settings;

View File

@ -126,6 +126,8 @@ public class InitialHandler extends PacketHandler implements PendingConnection
@Getter
private UUID offlineId;
@Getter
private UUID rewriteId;
@Getter
private LoginResult loginProfile;
@Getter
private boolean legacy;
@ -227,7 +229,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
@Override
public void done(ProxyPingEvent result, Throwable error)
{
if ( ch.isClosed() )
if ( ch.isClosing() )
{
return;
}
@ -370,6 +372,12 @@ public class InitialHandler extends PacketHandler implements PendingConnection
bungee.getPluginManager().callEvent( new PlayerHandshakeEvent( InitialHandler.this, handshake ) );
// return if the connection was closed during the event
if ( ch.isClosing() )
{
return;
}
switch ( handshake.getRequestedProtocol() )
{
case 1:
@ -470,7 +478,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
disconnect( ( reason != null ) ? reason : TextComponent.fromLegacy( bungee.getTranslation( "kick_message" ) ) );
return;
}
if ( ch.isClosed() )
if ( ch.isClosing() )
{
return;
}
@ -577,6 +585,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
duplication = true;
}
}
rewriteId = ( bungee.config.isIpForward() ) ? uniqueId : offlineId;
if ( BungeeCord.getInstance().config.isEnforceSecureProfile() )
{
@ -639,7 +648,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
disconnect( ( reason != null ) ? reason : TextComponent.fromLegacy( bungee.getTranslation( "kick_message" ) ) );
return;
}
if ( ch.isClosed() )
if ( ch.isClosing() )
{
return;
}
@ -656,7 +665,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
if ( getVersion() < ProtocolConstants.MINECRAFT_1_20_2 )
{
unsafe.sendPacket( new LoginSuccess( getUniqueId(), getName(), ( loginProfile == null ) ? null : loginProfile.getProperties() ) );
unsafe.sendPacket( new LoginSuccess( getRewriteId(), getName(), ( loginProfile == null ) ? null : loginProfile.getProperties() ) );
ch.setProtocol( Protocol.GAME );
}
finish2();
@ -679,28 +688,37 @@ public class InitialHandler extends PacketHandler implements PendingConnection
}
ch.getHandle().pipeline().get( HandlerBoss.class ).setHandler( new UpstreamBridge( bungee, userCon ) );
bungee.getPluginManager().callEvent( new PostLoginEvent( userCon ) );
// #3612: Don't progress further if disconnected during event
if ( ch.isClosed() )
{
return;
}
ServerInfo server;
ServerInfo initialServer;
if ( bungee.getReconnectHandler() != null )
{
server = bungee.getReconnectHandler().getServer( userCon );
initialServer = bungee.getReconnectHandler().getServer( userCon );
} else
{
server = AbstractReconnectHandler.getForcedHost( InitialHandler.this );
initialServer = AbstractReconnectHandler.getForcedHost( InitialHandler.this );
}
if ( server == null )
if ( initialServer == null )
{
server = bungee.getServerInfo( listener.getDefaultServer() );
initialServer = bungee.getServerInfo( listener.getDefaultServer() );
}
userCon.connect( server, null, true, ServerConnectEvent.Reason.JOIN_PROXY );
Callback<PostLoginEvent> complete = new Callback<PostLoginEvent>()
{
@Override
public void done(PostLoginEvent result, Throwable error)
{
// #3612: Don't progress further if disconnected during event
if ( ch.isClosing() )
{
return;
}
userCon.connect( result.getTarget(), null, true, ServerConnectEvent.Reason.JOIN_PROXY );
}
};
// fire post-login event
bungee.getPluginManager().callEvent( new PostLoginEvent( userCon, initialServer, complete ) );
}
@Override

View File

@ -42,6 +42,7 @@ import net.md_5.bungee.protocol.packet.PluginMessage;
import net.md_5.bungee.protocol.packet.StartConfiguration;
import net.md_5.bungee.protocol.packet.TabCompleteRequest;
import net.md_5.bungee.protocol.packet.TabCompleteResponse;
import net.md_5.bungee.protocol.packet.UnsignedClientCommand;
import net.md_5.bungee.util.AllowedCharacters;
public class UpstreamBridge extends PacketHandler
@ -84,7 +85,7 @@ public class UpstreamBridge extends PacketHandler
PlayerListItem oldPacket = new PlayerListItem();
oldPacket.setAction( PlayerListItem.Action.REMOVE_PLAYER );
PlayerListItem.Item item = new PlayerListItem.Item();
item.setUuid( con.getUniqueId() );
item.setUuid( con.getRewriteId() );
oldPacket.setItems( new PlayerListItem.Item[]
{
item
@ -93,7 +94,7 @@ public class UpstreamBridge extends PacketHandler
PlayerListItemRemove newPacket = new PlayerListItemRemove();
newPacket.setUuids( new UUID[]
{
con.getUniqueId()
con.getRewriteId()
} );
for ( ProxiedPlayer player : con.getServer().getInfo().getPlayers() )
@ -196,6 +197,12 @@ public class UpstreamBridge extends PacketHandler
handleChat( "/" + command.getCommand() );
}
@Override
public void handle(UnsignedClientCommand command) throws Exception
{
handleChat( "/" + command.getCommand() );
}
private String handleChat(String message)
{
for ( int index = 0, length = message.length(); index < length; index++ )

View File

@ -121,13 +121,13 @@ class EntityMap_1_10 extends EntityMap
DefinedPacket.readVarInt( packet ); // Entity ID
int idLength = packet.readerIndex() - readerIndex - packetIdLength;
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
UserConnection player;
if ( ( player = BungeeCord.getInstance().getPlayerByOfflineUUID( uuid ) ) != null )
{
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength + idLength );
DefinedPacket.writeUUID( player.getUniqueId(), packet );
DefinedPacket.writeUUID( player.getRewriteId(), packet );
packet.writerIndex( previous );
}
break;
@ -164,7 +164,7 @@ class EntityMap_1_10 extends EntityMap
int packetId = DefinedPacket.readVarInt( packet );
int packetIdLength = packet.readerIndex() - readerIndex;
if ( packetId == 0x1B /* Spectate : PacketPlayInSpectate */ && !BungeeCord.getInstance().getConfig().isIpForward() )
if ( packetId == 0x1B /* Spectate : PacketPlayInSpectate */ )
{
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
@ -173,7 +173,7 @@ class EntityMap_1_10 extends EntityMap
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength );
DefinedPacket.writeUUID( ( (UserConnection) player ).getPendingConnection().getOfflineId(), packet );
DefinedPacket.writeUUID( ( (UserConnection) player ).getRewriteId(), packet );
packet.writerIndex( previous );
}
}

View File

@ -121,13 +121,13 @@ class EntityMap_1_11 extends EntityMap
DefinedPacket.readVarInt( packet ); // Entity ID
int idLength = packet.readerIndex() - readerIndex - packetIdLength;
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
UserConnection player;
if ( ( player = BungeeCord.getInstance().getPlayerByOfflineUUID( uuid ) ) != null )
{
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength + idLength );
DefinedPacket.writeUUID( player.getUniqueId(), packet );
DefinedPacket.writeUUID( player.getRewriteId(), packet );
packet.writerIndex( previous );
}
break;
@ -165,7 +165,7 @@ class EntityMap_1_11 extends EntityMap
int packetId = DefinedPacket.readVarInt( packet );
int packetIdLength = packet.readerIndex() - readerIndex;
if ( packetId == 0x1B /* Spectate : PacketPlayInSpectate */ && !BungeeCord.getInstance().getConfig().isIpForward() )
if ( packetId == 0x1B /* Spectate : PacketPlayInSpectate */ )
{
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
@ -174,7 +174,7 @@ class EntityMap_1_11 extends EntityMap
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength );
DefinedPacket.writeUUID( ( (UserConnection) player ).getPendingConnection().getOfflineId(), packet );
DefinedPacket.writeUUID( ( (UserConnection) player ).getRewriteId(), packet );
packet.writerIndex( previous );
}
}

View File

@ -121,13 +121,13 @@ class EntityMap_1_12 extends EntityMap
DefinedPacket.readVarInt( packet ); // Entity ID
int idLength = packet.readerIndex() - readerIndex - packetIdLength;
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
UserConnection player;
if ( ( player = BungeeCord.getInstance().getPlayerByOfflineUUID( uuid ) ) != null )
{
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength + idLength );
DefinedPacket.writeUUID( player.getUniqueId(), packet );
DefinedPacket.writeUUID( player.getRewriteId(), packet );
packet.writerIndex( previous );
}
break;
@ -165,7 +165,7 @@ class EntityMap_1_12 extends EntityMap
int packetId = DefinedPacket.readVarInt( packet );
int packetIdLength = packet.readerIndex() - readerIndex;
if ( packetId == 0x1E /* Spectate : PacketPlayInSpectate */ && !BungeeCord.getInstance().getConfig().isIpForward() )
if ( packetId == 0x1E /* Spectate : PacketPlayInSpectate */ )
{
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
@ -174,7 +174,7 @@ class EntityMap_1_12 extends EntityMap
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength );
DefinedPacket.writeUUID( ( (UserConnection) player ).getPendingConnection().getOfflineId(), packet );
DefinedPacket.writeUUID( ( (UserConnection) player ).getRewriteId(), packet );
packet.writerIndex( previous );
}
}

View File

@ -121,13 +121,13 @@ class EntityMap_1_12_1 extends EntityMap
DefinedPacket.readVarInt( packet ); // Entity ID
int idLength = packet.readerIndex() - readerIndex - packetIdLength;
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
UserConnection player;
if ( ( player = BungeeCord.getInstance().getPlayerByOfflineUUID( uuid ) ) != null )
{
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength + idLength );
DefinedPacket.writeUUID( player.getUniqueId(), packet );
DefinedPacket.writeUUID( player.getRewriteId(), packet );
packet.writerIndex( previous );
}
break;
@ -165,7 +165,7 @@ class EntityMap_1_12_1 extends EntityMap
int packetId = DefinedPacket.readVarInt( packet );
int packetIdLength = packet.readerIndex() - readerIndex;
if ( packetId == 0x1E /* Spectate : PacketPlayInSpectate */ && !BungeeCord.getInstance().getConfig().isIpForward() )
if ( packetId == 0x1E /* Spectate : PacketPlayInSpectate */ )
{
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
@ -174,7 +174,7 @@ class EntityMap_1_12_1 extends EntityMap
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength );
DefinedPacket.writeUUID( ( (UserConnection) player ).getPendingConnection().getOfflineId(), packet );
DefinedPacket.writeUUID( ( (UserConnection) player ).getRewriteId(), packet );
packet.writerIndex( previous );
}
}

View File

@ -121,13 +121,13 @@ class EntityMap_1_13 extends EntityMap
DefinedPacket.readVarInt( packet ); // Entity ID
int idLength = packet.readerIndex() - readerIndex - packetIdLength;
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
UserConnection player;
if ( ( player = BungeeCord.getInstance().getPlayerByOfflineUUID( uuid ) ) != null )
{
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength + idLength );
DefinedPacket.writeUUID( player.getUniqueId(), packet );
DefinedPacket.writeUUID( player.getRewriteId(), packet );
packet.writerIndex( previous );
}
break;
@ -165,7 +165,7 @@ class EntityMap_1_13 extends EntityMap
int packetId = DefinedPacket.readVarInt( packet );
int packetIdLength = packet.readerIndex() - readerIndex;
if ( packetId == 0x28 /* Spectate : PacketPlayInSpectate */ && !BungeeCord.getInstance().getConfig().isIpForward() )
if ( packetId == 0x28 /* Spectate : PacketPlayInSpectate */ )
{
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
@ -174,7 +174,7 @@ class EntityMap_1_13 extends EntityMap
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength );
DefinedPacket.writeUUID( ( (UserConnection) player ).getPendingConnection().getOfflineId(), packet );
DefinedPacket.writeUUID( ( (UserConnection) player ).getRewriteId(), packet );
packet.writerIndex( previous );
}
}

View File

@ -120,13 +120,13 @@ class EntityMap_1_14 extends EntityMap
DefinedPacket.readVarInt( packet ); // Entity ID
int idLength = packet.readerIndex() - readerIndex - packetIdLength;
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
UserConnection player;
if ( ( player = BungeeCord.getInstance().getPlayerByOfflineUUID( uuid ) ) != null )
{
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength + idLength );
DefinedPacket.writeUUID( player.getUniqueId(), packet );
DefinedPacket.writeUUID( player.getRewriteId(), packet );
packet.writerIndex( previous );
}
break;
@ -169,7 +169,7 @@ class EntityMap_1_14 extends EntityMap
int packetId = DefinedPacket.readVarInt( packet );
int packetIdLength = packet.readerIndex() - readerIndex;
if ( packetId == 0x2B /* Spectate : PacketPlayInSpectate */ && !BungeeCord.getInstance().getConfig().isIpForward() )
if ( packetId == 0x2B /* Spectate : PacketPlayInSpectate */ )
{
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
@ -178,7 +178,7 @@ class EntityMap_1_14 extends EntityMap
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength );
DefinedPacket.writeUUID( ( (UserConnection) player ).getPendingConnection().getOfflineId(), packet );
DefinedPacket.writeUUID( ( (UserConnection) player ).getRewriteId(), packet );
packet.writerIndex( previous );
}
}

View File

@ -120,13 +120,13 @@ class EntityMap_1_15 extends EntityMap
DefinedPacket.readVarInt( packet ); // Entity ID
int idLength = packet.readerIndex() - readerIndex - packetIdLength;
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
UserConnection player;
if ( ( player = BungeeCord.getInstance().getPlayerByOfflineUUID( uuid ) ) != null )
{
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength + idLength );
DefinedPacket.writeUUID( player.getUniqueId(), packet );
DefinedPacket.writeUUID( player.getRewriteId(), packet );
packet.writerIndex( previous );
}
break;
@ -169,7 +169,7 @@ class EntityMap_1_15 extends EntityMap
int packetId = DefinedPacket.readVarInt( packet );
int packetIdLength = packet.readerIndex() - readerIndex;
if ( packetId == 0x2B /* Spectate : PacketPlayInSpectate */ && !BungeeCord.getInstance().getConfig().isIpForward() )
if ( packetId == 0x2B /* Spectate : PacketPlayInSpectate */ )
{
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
@ -178,7 +178,7 @@ class EntityMap_1_15 extends EntityMap
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength );
DefinedPacket.writeUUID( ( (UserConnection) player ).getPendingConnection().getOfflineId(), packet );
DefinedPacket.writeUUID( ( (UserConnection) player ).getRewriteId(), packet );
packet.writerIndex( previous );
}
}

View File

@ -120,13 +120,13 @@ class EntityMap_1_16 extends EntityMap
DefinedPacket.readVarInt( packet ); // Entity ID
int idLength = packet.readerIndex() - readerIndex - packetIdLength;
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
UserConnection player;
if ( ( player = BungeeCord.getInstance().getPlayerByOfflineUUID( uuid ) ) != null )
{
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength + idLength );
DefinedPacket.writeUUID( player.getUniqueId(), packet );
DefinedPacket.writeUUID( player.getRewriteId(), packet );
packet.writerIndex( previous );
}
break;
@ -169,7 +169,7 @@ class EntityMap_1_16 extends EntityMap
int packetId = DefinedPacket.readVarInt( packet );
int packetIdLength = packet.readerIndex() - readerIndex;
if ( packetId == 0x2C /* Spectate : PacketPlayInSpectate */ && !BungeeCord.getInstance().getConfig().isIpForward() )
if ( packetId == 0x2C /* Spectate : PacketPlayInSpectate */ )
{
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
@ -178,7 +178,7 @@ class EntityMap_1_16 extends EntityMap
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength );
DefinedPacket.writeUUID( ( (UserConnection) player ).getPendingConnection().getOfflineId(), packet );
DefinedPacket.writeUUID( ( (UserConnection) player ).getRewriteId(), packet );
packet.writerIndex( previous );
}
}

View File

@ -22,7 +22,7 @@ class EntityMap_1_16_2 extends EntityMap
static final EntityMap_1_16_2 INSTANCE_1_19_4 = new EntityMap_1_16_2( 0x03, 0x30 );
static final EntityMap_1_16_2 INSTANCE_1_20_2 = new EntityMap_1_16_2( -1, 0x33 );
static final EntityMap_1_16_2 INSTANCE_1_20_3 = new EntityMap_1_16_2( -1, 0x34 );
static final EntityMap_1_16_2 INSTANCE_1_20_5 = new EntityMap_1_16_2( -1, 0x36 );
static final EntityMap_1_16_2 INSTANCE_1_20_5 = new EntityMap_1_16_2( -1, 0x37 );
//
private final int spawnPlayerId;
private final int spectateId;
@ -41,13 +41,13 @@ class EntityMap_1_16_2 extends EntityMap
DefinedPacket.readVarInt( packet ); // Entity ID
int idLength = packet.readerIndex() - readerIndex - packetIdLength;
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
UserConnection player;
if ( ( player = BungeeCord.getInstance().getPlayerByOfflineUUID( uuid ) ) != null )
{
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength + idLength );
DefinedPacket.writeUUID( player.getUniqueId(), packet );
DefinedPacket.writeUUID( player.getRewriteId(), packet );
packet.writerIndex( previous );
}
}
@ -62,7 +62,7 @@ class EntityMap_1_16_2 extends EntityMap
int packetId = DefinedPacket.readVarInt( packet );
int packetIdLength = packet.readerIndex() - readerIndex;
if ( packetId == spectateId && !BungeeCord.getInstance().getConfig().isIpForward() )
if ( packetId == spectateId )
{
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
@ -71,7 +71,7 @@ class EntityMap_1_16_2 extends EntityMap
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength );
DefinedPacket.writeUUID( ( (UserConnection) player ).getPendingConnection().getOfflineId(), packet );
DefinedPacket.writeUUID( ( (UserConnection) player ).getRewriteId(), packet );
packet.writerIndex( previous );
}
}

View File

@ -121,13 +121,13 @@ class EntityMap_1_8 extends EntityMap
DefinedPacket.readVarInt( packet ); // Entity ID
int idLength = packet.readerIndex() - readerIndex - packetIdLength;
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
UserConnection player;
if ( ( player = BungeeCord.getInstance().getPlayerByOfflineUUID( uuid ) ) != null )
{
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength + idLength );
DefinedPacket.writeUUID( player.getUniqueId(), packet );
DefinedPacket.writeUUID( player.getRewriteId(), packet );
packet.writerIndex( previous );
}
} else if ( packetId == 0x42 /* Combat Event */ )
@ -158,7 +158,7 @@ class EntityMap_1_8 extends EntityMap
int packetId = DefinedPacket.readVarInt( packet );
int packetIdLength = packet.readerIndex() - readerIndex;
if ( packetId == 0x18 /* Spectate */ && !BungeeCord.getInstance().getConfig().isIpForward() )
if ( packetId == 0x18 /* Spectate */ )
{
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
@ -167,7 +167,7 @@ class EntityMap_1_8 extends EntityMap
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength );
DefinedPacket.writeUUID( ( (UserConnection) player ).getPendingConnection().getOfflineId(), packet );
DefinedPacket.writeUUID( ( (UserConnection) player ).getRewriteId(), packet );
packet.writerIndex( previous );
}
}

View File

@ -121,13 +121,13 @@ class EntityMap_1_9 extends EntityMap
DefinedPacket.readVarInt( packet ); // Entity ID
int idLength = packet.readerIndex() - readerIndex - packetIdLength;
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
UserConnection player;
if ( ( player = BungeeCord.getInstance().getPlayerByOfflineUUID( uuid ) ) != null )
{
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength + idLength );
DefinedPacket.writeUUID( player.getUniqueId(), packet );
DefinedPacket.writeUUID( player.getRewriteId(), packet );
packet.writerIndex( previous );
}
break;
@ -164,7 +164,7 @@ class EntityMap_1_9 extends EntityMap
int packetId = DefinedPacket.readVarInt( packet );
int packetIdLength = packet.readerIndex() - readerIndex;
if ( packetId == 0x1B /* Spectate : PacketPlayInSpectate */ && !BungeeCord.getInstance().getConfig().isIpForward() )
if ( packetId == 0x1B /* Spectate : PacketPlayInSpectate */ )
{
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
@ -173,7 +173,7 @@ class EntityMap_1_9 extends EntityMap
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength );
DefinedPacket.writeUUID( ( (UserConnection) player ).getPendingConnection().getOfflineId(), packet );
DefinedPacket.writeUUID( ( (UserConnection) player ).getRewriteId(), packet );
packet.writerIndex( previous );
}
}

View File

@ -121,13 +121,13 @@ class EntityMap_1_9_4 extends EntityMap
DefinedPacket.readVarInt( packet ); // Entity ID
int idLength = packet.readerIndex() - readerIndex - packetIdLength;
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
UserConnection player;
if ( ( player = BungeeCord.getInstance().getPlayerByOfflineUUID( uuid ) ) != null )
{
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength + idLength );
DefinedPacket.writeUUID( player.getUniqueId(), packet );
DefinedPacket.writeUUID( player.getRewriteId(), packet );
packet.writerIndex( previous );
}
break;
@ -164,7 +164,7 @@ class EntityMap_1_9_4 extends EntityMap
int packetId = DefinedPacket.readVarInt( packet );
int packetIdLength = packet.readerIndex() - readerIndex;
if ( packetId == 0x1B /* Spectate : PacketPlayInSpectate */ && !BungeeCord.getInstance().getConfig().isIpForward() )
if ( packetId == 0x1B /* Spectate : PacketPlayInSpectate */ )
{
UUID uuid = DefinedPacket.readUUID( packet );
ProxiedPlayer player;
@ -173,7 +173,7 @@ class EntityMap_1_9_4 extends EntityMap
int previous = packet.writerIndex();
packet.readerIndex( readerIndex );
packet.writerIndex( readerIndex + packetIdLength );
DefinedPacket.writeUUID( ( (UserConnection) player ).getPendingConnection().getOfflineId(), packet );
DefinedPacket.writeUUID( ( (UserConnection) player ).getRewriteId(), packet );
packet.writerIndex( previous );
}
}

View File

@ -94,6 +94,9 @@ public class HandlerBoss extends ChannelInboundHandlerAdapter
} );
channel.setRemoteAddress( newAddress );
} else
{
channel.close();
}
} finally
{

View File

@ -24,6 +24,11 @@ import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.channel.unix.DomainSocketAddress;
import io.netty.handler.codec.haproxy.HAProxyMessageDecoder;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.incubator.channel.uring.IOUring;
import io.netty.incubator.channel.uring.IOUringDatagramChannel;
import io.netty.incubator.channel.uring.IOUringEventLoopGroup;
import io.netty.incubator.channel.uring.IOUringServerSocketChannel;
import io.netty.incubator.channel.uring.IOUringSocketChannel;
import io.netty.util.AttributeKey;
import io.netty.util.internal.PlatformDependent;
import java.net.SocketAddress;
@ -102,26 +107,42 @@ public class PipelineUtils
public static final String LEGACY_KICKER = "legacy-kick";
private static boolean epoll;
private static boolean io_uring;
static
{
if ( !PlatformDependent.isWindows() && Boolean.parseBoolean( System.getProperty( "bungee.epoll", "true" ) ) )
if ( !PlatformDependent.isWindows() )
{
ProxyServer.getInstance().getLogger().info( "Not on Windows, attempting to use enhanced EpollEventLoop" );
// disable by default (experimental)
if ( Boolean.parseBoolean( System.getProperty( "bungee.io_uring", "false" ) ) )
{
ProxyServer.getInstance().getLogger().info( "Not on Windows, attempting to use enhanced IOUringEventLoopGroup" );
if ( io_uring = IOUring.isAvailable() )
{
ProxyServer.getInstance().getLogger().log( Level.WARNING, "io_uring is enabled and working, utilising it! (experimental feature)" );
} else
{
ProxyServer.getInstance().getLogger().log( Level.WARNING, "io_uring is not working: {0}", Util.exception( IOUring.unavailabilityCause() ) );
}
}
if ( epoll = Epoll.isAvailable() )
if ( !io_uring && Boolean.parseBoolean( System.getProperty( "bungee.epoll", "true" ) ) )
{
ProxyServer.getInstance().getLogger().info( "Epoll is working, utilising it!" );
} else
{
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Epoll is not working, falling back to NIO: {0}", Util.exception( Epoll.unavailabilityCause() ) );
ProxyServer.getInstance().getLogger().info( "Not on Windows, attempting to use enhanced EpollEventLoop" );
if ( epoll = Epoll.isAvailable() )
{
ProxyServer.getInstance().getLogger().info( "Epoll is working, utilising it!" );
} else
{
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Epoll is not working, falling back to NIO: {0}", Util.exception( Epoll.unavailabilityCause() ) );
}
}
}
}
public static EventLoopGroup newEventLoopGroup(int threads, ThreadFactory factory)
{
return epoll ? new EpollEventLoopGroup( threads, factory ) : new NioEventLoopGroup( threads, factory );
return io_uring ? new IOUringEventLoopGroup( threads, factory ) : epoll ? new EpollEventLoopGroup( threads, factory ) : new NioEventLoopGroup( threads, factory );
}
public static Class<? extends ServerChannel> getServerChannel(SocketAddress address)
@ -133,7 +154,7 @@ public class PipelineUtils
return EpollServerDomainSocketChannel.class;
}
return epoll ? EpollServerSocketChannel.class : NioServerSocketChannel.class;
return io_uring ? IOUringServerSocketChannel.class : epoll ? EpollServerSocketChannel.class : NioServerSocketChannel.class;
}
public static Class<? extends Channel> getChannel(SocketAddress address)
@ -145,12 +166,12 @@ public class PipelineUtils
return EpollDomainSocketChannel.class;
}
return epoll ? EpollSocketChannel.class : NioSocketChannel.class;
return io_uring ? IOUringSocketChannel.class : epoll ? EpollSocketChannel.class : NioSocketChannel.class;
}
public static Class<? extends DatagramChannel> getDatagramChannel()
{
return epoll ? EpollDatagramChannel.class : NioDatagramChannel.class;
return io_uring ? IOUringDatagramChannel.class : epoll ? EpollDatagramChannel.class : NioDatagramChannel.class;
}
private static final int LOW_MARK = Integer.getInteger( "net.md_5.bungee.low_mark", 2 << 18 ); // 0.5 mb

View File

@ -46,7 +46,7 @@ public abstract class TabList
UserConnection player = BungeeCord.getInstance().getPlayerByOfflineUUID( playerListItem.getUuids()[i] );
if ( player != null )
{
playerListItem.getUuids()[i] = player.getUniqueId();
playerListItem.getUuids()[i] = player.getRewriteId();
}
}
@ -72,7 +72,7 @@ public abstract class TabList
UserConnection player = BungeeCord.getInstance().getPlayerByOfflineUUID( item.getUuid() );
if ( player != null )
{
item.setUuid( player.getUniqueId() );
item.setUuid( player.getRewriteId() );
if ( item.getProperties() != null )
{