1 Commits

Author SHA1 Message Date
6949470e3b Code extracted from useless for loop. Closes #2872 2020-12-28 19:17:06 +01:00
193 changed files with 3122 additions and 7278 deletions

View File

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

View File

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

View File

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

View File

@@ -1,28 +0,0 @@
version: 2
updates:
- package-ecosystem: "maven"
directory: "/"
schedule:
interval: "daily"
open-pull-requests-limit: 50
ignore:
# Synchronised with Minecraft
- dependency-name: "com.google.code.gson:gson"
# 9.x has performance issues (see, eg, checkstyle/checkstyle#10934) and 10.x is incompatible
- dependency-name: "com.puppycrawl.tools:checkstyle"
# Newer versions have issues, see #1909 and #2050
- dependency-name: "jline:jline"
# Later versions of these Maven dependencies are incompatible and require careful management - see SPIGOT-7400
- dependency-name: "org.apache.maven.resolver:maven-resolver-connector-basic"
- dependency-name: "org.apache.maven.resolver:maven-resolver-transport-http"
- dependency-name: "org.apache.maven:maven-resolver-provider"
# Used with maven-resolver dependencies; 2.0 update breaks other providers
- dependency-name: "org.slf4j:slf4j-api"
update-types: ["version-update:semver-major"]
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
open-pull-requests-limit: 50

View File

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

6
.gitmodules vendored
View File

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

View File

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

View File

@@ -4,14 +4,15 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>fr.pandacube.bungeecord</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.16-R0.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId> <artifactId>bungeecord-api</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.16-R0.4-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>BungeeCord-API</name> <name>BungeeCord-API</name>
@@ -19,25 +20,25 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>fr.pandacube.bungeecord</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-chat</artifactId> <artifactId>bungeecord-chat</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>fr.pandacube.bungeecord</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-config</artifactId> <artifactId>bungeecord-config</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>fr.pandacube.bungeecord</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-event</artifactId> <artifactId>bungeecord-event</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>fr.pandacube.bungeecord</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-protocol</artifactId> <artifactId>bungeecord-protocol</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>
@@ -45,33 +46,13 @@
<dependency> <dependency>
<groupId>io.netty</groupId> <groupId>io.netty</groupId>
<artifactId>netty-transport-native-unix-common</artifactId> <artifactId>netty-transport-native-unix-common</artifactId>
<version>${netty.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-resolver-provider</artifactId>
<version>3.8.5</version>
<!-- not part of the API proper -->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-connector-basic</artifactId>
<version>1.7.3</version>
<!-- not part of the API proper -->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-transport-http</artifactId>
<version>1.7.3</version>
<!-- not part of the API proper -->
<scope>provided</scope>
</dependency>
<dependency> <dependency>
<groupId>org.yaml</groupId> <groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId> <artifactId>snakeyaml</artifactId>
<version>2.2</version> <version>1.26</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

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

View File

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

View File

@@ -1,10 +1,9 @@
package net.md_5.bungee.api; package net.md_5.bungee.api;
import com.google.common.base.Preconditions;
import com.google.common.io.BaseEncoding; import com.google.common.io.BaseEncoding;
import com.google.gson.TypeAdapter; import com.google.gson.TypeAdapter;
import com.google.gson.internal.bind.TypeAdapters;
import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter; import com.google.gson.stream.JsonWriter;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
@@ -27,26 +26,13 @@ public class Favicon
@Override @Override
public void write(JsonWriter out, Favicon value) throws IOException public void write(JsonWriter out, Favicon value) throws IOException
{ {
if ( value == null ) TypeAdapters.STRING.write( out, value == null ? null : value.getEncoded() );
{
out.nullValue();
} else
{
out.value( value.getEncoded() );
}
} }
@Override @Override
public Favicon read(JsonReader in) throws IOException public Favicon read(JsonReader in) throws IOException
{ {
JsonToken peek = in.peek(); String enc = TypeAdapters.STRING.read( in );
if ( peek == JsonToken.NULL )
{
in.nextNull();
return null;
}
String enc = in.nextString();
return enc == null ? null : create( enc ); return enc == null ? null : create( enc );
} }
}; };
@@ -73,7 +59,6 @@ public class Favicon
*/ */
public static Favicon create(BufferedImage image) public static Favicon create(BufferedImage image)
{ {
Preconditions.checkArgument( image != null, "image is null" );
// check size // check size
if ( image.getWidth() != 64 || image.getHeight() != 64 ) if ( image.getWidth() != 64 || image.getHeight() != 64 )
{ {

View File

@@ -15,7 +15,7 @@ import net.md_5.bungee.api.event.ServerConnectEvent;
import net.md_5.bungee.api.score.Scoreboard; import net.md_5.bungee.api.score.Scoreboard;
/** /**
* Represents a player whose connection is being connected to somewhere else, * Represents a player who's connection is being connected to somewhere else,
* whether it be a remote or embedded server. * whether it be a remote or embedded server.
*/ */
public interface ProxiedPlayer extends Connection, CommandSender public interface ProxiedPlayer extends Connection, CommandSender
@@ -57,7 +57,8 @@ public interface ProxiedPlayer extends Connection, CommandSender
String getDisplayName(); String getDisplayName();
/** /**
* Sets this player's display name to be used by proxy commands and plugins. * Sets this players display name to be used as their nametag and tab list
* name.
* *
* @param name the name to set * @param name the name to set
*/ */

View File

@@ -1,157 +0,0 @@
package net.md_5.bungee.api.event;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.RootCommandNode;
import lombok.AccessLevel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Setter;
import lombok.ToString;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.connection.Connection;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.plugin.PluginManager;
import net.md_5.bungee.api.plugin.TabExecutor;
/**
* Event called when a downstream server (on 1.13+) sends the command structure
* to a player, but before BungeeCord adds the dummy command nodes of
* registered commands.
* <p>
* BungeeCord will not overwrite the modifications made by the listeners.
*
* <h2>Usage example</h2>
* Here is a usage example of this event, to declare a command structure.
* This illustrates the commands /server and /send of Bungee.
* <pre>
* event.getRoot().addChild( LiteralArgumentBuilder.&lt;CommandSender&gt;literal( "server" )
* .requires( sender -&gt; sender.hasPermission( "bungeecord.command.server" ) )
* .executes( a -&gt; 0 )
* .then( RequiredArgumentBuilder.argument( "serverName", StringArgumentType.greedyString() )
* .suggests( SuggestionRegistry.ASK_SERVER )
* )
* .build()
* );
* event.getRoot().addChild( LiteralArgumentBuilder.&lt;CommandSender&gt;literal( "send" )
* .requires( sender -&gt; sender.hasPermission( "bungeecord.command.send" ) )
* .then( RequiredArgumentBuilder.argument( "playerName", StringArgumentType.word() )
* .suggests( SuggestionRegistry.ASK_SERVER )
* .then( RequiredArgumentBuilder.argument( "serverName", StringArgumentType.greedyString() )
* .suggests( SuggestionRegistry.ASK_SERVER )
* )
* )
* .build()
* );
* </pre>
*
* <h2>Flag a {@link CommandNode} as executable or not</h2>
* The implementation of a {@link com.mojang.brigadier.Command Command} used in
* {@link ArgumentBuilder#executes(com.mojang.brigadier.Command)} will never be
* executed. This will only tell to the client if the current node is
* executable or not.
* <ul>
* <li>
* {@code builder.executes(null)} (default) to mark the node as not
* executable.
* </li>
* <li>
* {@code builder.executes(a -> 0)}, or any non null argument, to mark
* the node as executable (the child arguments are displayed as
* optional).
* </li>
* </ul>
*
* <h2>{@link CommandNode}s suggestions management</h2>
* The implementation of a SuggestionProvider used in
* {@link RequiredArgumentBuilder#suggests(SuggestionProvider)} will never be
* executed. This will only tell to the client how to deal with the
* auto-completion of the argument.
* <ul>
* <li>
* {@code builder.suggests(null)} (default) to disable auto-completion
* for this argument.
* </li>
* <li>
* {@code builder.suggests(SuggestionRegistry.ALL_RECIPES)} to suggest
* Minecrafts recipes.
* </li>
* <li>
* {@code builder.suggests(SuggestionRegistry.AVAILABLE_SOUNDS)} to
* suggest Minecrafts default sound identifiers.
* </li>
* <li>
* {@code builder.suggests(SuggestionRegistry.SUMMONABLE_ENTITIES)} to
* suggest Minecrafts default summonable entities identifiers.
* </li>
* <li>
* {@code builder.suggests(SuggestionRegistry.ASK_SERVER)}, or any
* other non null argument, to make the Minecraft client ask
* auto-completion to the server. Any specified implementation of
* {@link SuggestionProvider} will never be executed.
* </li>
* </ul>
*
* <h2>Argument types</h2>
* When building a new argument command node using
* {@link RequiredArgumentBuilder#argument(String, ArgumentType)}, you have to
* specify an {@link ArgumentType}. You can use all subclasses of
* {@link ArgumentType} provided with brigadier (for instance,
* {@link StringArgumentType} or {@link IntegerArgumentType}), or call any
* {@code ArgumentRegistry.minecraft*()} methods to use a {@code minecraft:*}
* argument type.
*
* <h2>Limitations with brigadier API</h2>
* This event is only used for the client to show command syntax, suggest
* sub-commands and color the arguments in the chat box. The command execution
* needs to be implemented using {@link PluginManager#registerCommand(Plugin,
* Command)} and the server-side tab-completion using {@link TabCompleteEvent}
* or {@link TabExecutor}.
*/
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class CommandsDeclareEvent extends TargetedEvent
{
/**
* Wether or not the command tree is modified by this event.
*
* If this value is set to true, BungeeCord will ensure that the
* modifications made in the command tree, will be sent to the player.
* If this is false, the modifications may not be taken into account.
*
* When calling {@link #getRoot()}, this value is automatically set
* to true.
*/
@Setter(value = AccessLevel.NONE)
private boolean modified = false;
/**
* The root command node of the command structure that will be send to the
* player.
*/
private final RootCommandNode<CommandSender> root;
public CommandsDeclareEvent(Connection sender, Connection receiver, RootCommandNode<CommandSender> root)
{
super( sender, receiver );
this.root = root;
}
/**
* The root command node of the command structure that will be send to the
* player.
* @return The root command node
*/
public RootCommandNode<CommandSender> getRoot()
{
modified = true;
return root;
}
}

View File

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

View File

@@ -9,13 +9,6 @@ import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Event; import net.md_5.bungee.api.plugin.Event;
/**
* Called when the player is disconnected from a server, for example during
* server switching.
*
* If the player is kicked from a server, {@link ServerKickEvent} will be called
* instead.
*/
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@ToString(callSuper = false) @ToString(callSuper = false)

View File

@@ -9,9 +9,7 @@ import net.md_5.bungee.api.plugin.Cancellable;
/** /**
* Event called when a player uses tab completion. * Event called when a player uses tab completion.
* @deprecated please use {@link TabCompleteRequestEvent} to support 1.13+ suggestions.
*/ */
@Deprecated
@Data @Data
@ToString(callSuper = true) @ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)

View File

@@ -1,85 +0,0 @@
package net.md_5.bungee.api.event;
import com.google.common.base.Preconditions;
import com.mojang.brigadier.context.StringRange;
import com.mojang.brigadier.suggestion.Suggestions;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import net.md_5.bungee.api.connection.Connection;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Cancellable;
import net.md_5.bungee.protocol.ProtocolConstants;
/**
* Event called when a player uses tab completion.
*/
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class TabCompleteRequestEvent extends TargetedEvent implements Cancellable
{
/**
* Cancelled state.
*/
private boolean cancelled;
/**
* The message the player has already entered.
*/
private final String cursor;
/**
* Range corresponding to the last word of {@link #getCursor()}.
* If you want your suggestions to be compatible with 1.12 and older
* clients, you need to {@link #setSuggestions(Suggestions)} with
* a range equals to this one.
* For 1.13 and newer clients, any other range that cover any part of
* {@link #getCursor()} is fine.<br>
* To check if the client supports custom ranges, use
* {@link #supportsCustomRange()}.
*/
private final StringRange legacyCompatibleRange;
/**
* The suggestions that will be sent to the client. If this list is empty,
* the request will be forwarded to the server.
*/
private Suggestions suggestions;
public TabCompleteRequestEvent(Connection sender, Connection receiver, String cursor, StringRange legacyCompatibleRange, Suggestions suggestions)
{
super( sender, receiver );
this.cursor = cursor;
this.legacyCompatibleRange = legacyCompatibleRange;
this.suggestions = suggestions;
}
/**
* Sets the suggestions that will be sent to the client.
* If this list is empty, the request will be forwarded to the server.
* @param suggestions the new Suggestions. Cannot be null.
* @throws IllegalArgumentException if the client is on 1.12 or lower and
* {@code suggestions.getRange()} is not equals to {@link #legacyCompatibleRange}.
*/
public void setSuggestions(Suggestions suggestions)
{
Preconditions.checkNotNull( suggestions );
Preconditions.checkArgument( supportsCustomRange() || legacyCompatibleRange.equals( suggestions.getRange() ),
"Clients on 1.12 or lower versions don't support the provided range for tab-completion: " + suggestions.getRange()
+ ". Please use TabCompleteRequestEvent.getLegacyCompatibleRange() for legacy clients." );
this.suggestions = suggestions;
}
/**
* Convenient method to tell if the client supports custom range for
* suggestions.
* If the client is on 1.13 or above, this methods returns true, and any
* range can be used for {@link #setSuggestions(Suggestions)}. Otherwise,
* it returns false and the defined range must be equals to
* {@link #legacyCompatibleRange}.
* @return true if the client is on 1.13 or newer version, false otherwise.
*/
public boolean supportsCustomRange()
{
return ( (ProxiedPlayer) getSender() ).getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_13;
}
}

View File

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

View File

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

View File

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

View File

@@ -4,12 +4,10 @@ import com.google.common.base.Preconditions;
import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.eventbus.Subscribe; import com.google.common.eventbus.Subscribe;
import com.google.common.graph.GraphBuilder;
import com.google.common.graph.Graphs;
import com.google.common.graph.MutableGraph;
import java.io.File; import java.io.File;
import java.io.InputStream; import java.io.InputStream;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@@ -33,7 +31,6 @@ import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.event.EventBus; import net.md_5.bungee.event.EventBus;
import net.md_5.bungee.event.EventHandler; import net.md_5.bungee.event.EventHandler;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor; import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.introspector.PropertyUtils; import org.yaml.snakeyaml.introspector.PropertyUtils;
@@ -52,8 +49,6 @@ public final class PluginManager
private final Yaml yaml; private final Yaml yaml;
private final EventBus eventBus; private final EventBus eventBus;
private final Map<String, Plugin> plugins = new LinkedHashMap<>(); private final Map<String, Plugin> plugins = new LinkedHashMap<>();
private final MutableGraph<String> dependencyGraph = GraphBuilder.directed().build();
private final LibraryLoader libraryLoader;
private final Map<String, Command> commandMap = new HashMap<>(); private final Map<String, Command> commandMap = new HashMap<>();
private Map<String, PluginDescription> toLoad = new HashMap<>(); private Map<String, PluginDescription> toLoad = new HashMap<>();
private final Multimap<Plugin, Command> commandsByPlugin = ArrayListMultimap.create(); private final Multimap<Plugin, Command> commandsByPlugin = ArrayListMultimap.create();
@@ -65,24 +60,13 @@ public final class PluginManager
this.proxy = proxy; this.proxy = proxy;
// Ignore unknown entries in the plugin descriptions // Ignore unknown entries in the plugin descriptions
Constructor yamlConstructor = new Constructor( new LoaderOptions() ); Constructor yamlConstructor = new Constructor();
PropertyUtils propertyUtils = yamlConstructor.getPropertyUtils(); PropertyUtils propertyUtils = yamlConstructor.getPropertyUtils();
propertyUtils.setSkipMissingProperties( true ); propertyUtils.setSkipMissingProperties( true );
yamlConstructor.setPropertyUtils( propertyUtils ); yamlConstructor.setPropertyUtils( propertyUtils );
yaml = new Yaml( yamlConstructor ); yaml = new Yaml( yamlConstructor );
eventBus = new EventBus( proxy.getLogger() ); eventBus = new EventBus( proxy.getLogger() );
LibraryLoader libraryLoader = null;
try
{
libraryLoader = new LibraryLoader( proxy.getLogger() );
} catch ( NoClassDefFoundError ex )
{
// Provided depends were not added back
proxy.getLogger().warning( "Could not initialize LibraryLoader (missing dependencies?)" );
}
this.libraryLoader = libraryLoader;
} }
/** /**
@@ -325,7 +309,6 @@ public final class PluginManager
status = false; status = false;
} }
dependencyGraph.putEdge( plugin.getName(), dependName );
if ( !status ) if ( !status )
{ {
break; break;
@@ -337,7 +320,10 @@ public final class PluginManager
{ {
try try
{ {
URLClassLoader loader = new PluginClassloader( proxy, plugin, plugin.getFile(), ( libraryLoader != null ) ? libraryLoader.createLoader( plugin ) : null ); URLClassLoader loader = new PluginClassloader( proxy, plugin, new URL[]
{
plugin.getFile().toURI().toURL()
} );
Class<?> main = loader.loadClass( plugin.getMain() ); Class<?> main = loader.loadClass( plugin.getMain() );
Plugin clazz = (Plugin) main.getDeclaredConstructor().newInstance(); Plugin clazz = (Plugin) main.getDeclaredConstructor().newInstance();
@@ -349,7 +335,7 @@ public final class PluginManager
} ); } );
} catch ( Throwable t ) } catch ( Throwable t )
{ {
proxy.getLogger().log( Level.WARNING, "Error loading plugin " + plugin.getName(), t ); proxy.getLogger().log( Level.WARNING, "Error enabling plugin " + plugin.getName(), t );
} }
} }
@@ -477,19 +463,4 @@ public final class PluginManager
{ {
return Collections.unmodifiableCollection( commandMap.entrySet() ); return Collections.unmodifiableCollection( commandMap.entrySet() );
} }
boolean isTransitiveDepend(PluginDescription plugin, PluginDescription depend)
{
Preconditions.checkArgument( plugin != null, "plugin" );
Preconditions.checkArgument( depend != null, "depend" );
if ( dependencyGraph.nodes().contains( plugin.getName() ) )
{
if ( Graphs.reachableNodes( dependencyGraph, plugin.getName() ).contains( depend.getName() ) )
{
return true;
}
}
return false;
}
} }

View File

@@ -1,13 +1,12 @@
package net.md_5.bungee.api; package net.md_5.bungee.api;
import static org.junit.jupiter.api.Assertions.*;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.util.Collection; import java.util.Collection;
import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.ServerConnectEvent; import net.md_5.bungee.api.event.ServerConnectEvent;
import org.junit.jupiter.api.Test; import org.junit.Test;
public class ServerConnectRequestTest public class ServerConnectRequestTest
{ {
@@ -79,15 +78,15 @@ public class ServerConnectRequestTest
} }
}; };
@Test @Test(expected = NullPointerException.class)
public void testNullTarget() public void testNullTarget()
{ {
assertThrows( NullPointerException.class, () -> ServerConnectRequest.builder().target( null ).reason( ServerConnectEvent.Reason.JOIN_PROXY ).build() ); ServerConnectRequest.builder().target( null ).reason( ServerConnectEvent.Reason.JOIN_PROXY ).build();
} }
@Test @Test(expected = NullPointerException.class)
public void testNullReason() public void testNullReason()
{ {
assertThrows( NullPointerException.class, () -> ServerConnectRequest.builder().target( DUMMY_INFO ).reason( null ).build() ); ServerConnectRequest.builder().target( DUMMY_INFO ).reason( null ).build();
} }
} }

View File

@@ -1,38 +1,63 @@
package net.md_5.bungee.util; package net.md_5.bungee.util;
import static org.junit.jupiter.api.Assertions.*;
import io.netty.channel.unix.DomainSocketAddress; import io.netty.channel.unix.DomainSocketAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.util.stream.Stream; import java.util.Arrays;
import java.util.Collection;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import net.md_5.bungee.Util; import net.md_5.bungee.Util;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.Assert;
import org.junit.jupiter.params.provider.Arguments; import org.junit.Test;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RequiredArgsConstructor @RequiredArgsConstructor
@RunWith(Parameterized.class)
public class AddressParseTest public class AddressParseTest
{ {
public static Stream<Arguments> data() @Parameters
public static Collection<Object[]> data()
{ {
return Stream.of( return Arrays.asList( new Object[][]
Arguments.of( "127.0.0.1", "127.0.0.1", Util.DEFAULT_PORT ), {
Arguments.of( "127.0.0.1:1337", "127.0.0.1", 1337 ), {
Arguments.of( "[::1]", "0:0:0:0:0:0:0:1", Util.DEFAULT_PORT ), "127.0.0.1", "127.0.0.1", Util.DEFAULT_PORT
Arguments.of( "[0:0:0:0::1]", "0:0:0:0:0:0:0:1", Util.DEFAULT_PORT ), },
Arguments.of( "[0:0:0:0:0:0:0:1]", "0:0:0:0:0:0:0:1", Util.DEFAULT_PORT ), {
Arguments.of( "[::1]:1337", "0:0:0:0:0:0:0:1", 1337 ), "127.0.0.1:1337", "127.0.0.1", 1337
Arguments.of( "[0:0:0:0::1]:1337", "0:0:0:0:0:0:0:1", 1337 ), },
Arguments.of( "[0:0:0:0:0:0:0:1]:1337", "0:0:0:0:0:0:0:1", 1337 ), {
Arguments.of( "unix:///var/run/bungee.sock", "/var/run/bungee.sock", -1 ) "[::1]", "0:0:0:0:0:0:0:1", Util.DEFAULT_PORT
); },
{
"[0:0:0:0::1]", "0:0:0:0:0:0:0:1", Util.DEFAULT_PORT
},
{
"[0:0:0:0:0:0:0:1]", "0:0:0:0:0:0:0:1", Util.DEFAULT_PORT
},
{
"[::1]:1337", "0:0:0:0:0:0:0:1", 1337
},
{
"[0:0:0:0::1]:1337", "0:0:0:0:0:0:0:1", 1337
},
{
"[0:0:0:0:0:0:0:1]:1337", "0:0:0:0:0:0:0:1", 1337
},
{
"unix:///var/run/bungee.sock", "/var/run/bungee.sock", -1
} }
} );
}
private final String line;
private final String host;
private final int port;
@ParameterizedTest @Test
@MethodSource("data") public void test()
public void test(String line, String host, int port)
{ {
SocketAddress parsed = Util.getAddr( line ); SocketAddress parsed = Util.getAddr( line );
@@ -40,14 +65,14 @@ public class AddressParseTest
{ {
InetSocketAddress tcp = (InetSocketAddress) parsed; InetSocketAddress tcp = (InetSocketAddress) parsed;
assertEquals( host, tcp.getHostString() ); Assert.assertEquals( host, tcp.getHostString() );
assertEquals( port, tcp.getPort() ); Assert.assertEquals( port, tcp.getPort() );
} else if ( parsed instanceof DomainSocketAddress ) } else if ( parsed instanceof DomainSocketAddress )
{ {
DomainSocketAddress unix = (DomainSocketAddress) parsed; DomainSocketAddress unix = (DomainSocketAddress) parsed;
assertEquals( host, unix.path() ); Assert.assertEquals( host, unix.path() );
assertEquals( -1, port ); Assert.assertEquals( -1, port );
} else } else
{ {
throw new AssertionError( "Unknown socket " + parsed ); throw new AssertionError( "Unknown socket " + parsed );

View File

@@ -1,7 +1,7 @@
package net.md_5.bungee.util; package net.md_5.bungee.util;
import static org.junit.jupiter.api.Assertions.*; import org.junit.Assert;
import org.junit.jupiter.api.Test; import org.junit.Test;
public class CaseInsensitiveTest public class CaseInsensitiveTest
{ {
@@ -13,12 +13,12 @@ public class CaseInsensitiveTest
CaseInsensitiveMap<Object> map = new CaseInsensitiveMap<>(); CaseInsensitiveMap<Object> map = new CaseInsensitiveMap<>();
map.put( "FOO", obj ); map.put( "FOO", obj );
assertTrue( map.contains( "foo" ) ); // Assert that contains is case insensitive Assert.assertTrue( map.contains( "foo" ) ); // Assert that contains is case insensitive
assertTrue( map.entrySet().iterator().next().getKey().equals( "FOO" ) ); // Assert that case is preserved Assert.assertTrue( map.entrySet().iterator().next().getKey().equals( "FOO" ) ); // Assert that case is preserved
// Assert that remove is case insensitive // Assert that remove is case insensitive
map.remove( "FoO" ); map.remove( "FoO" );
assertFalse( map.contains( "foo" ) ); Assert.assertFalse( map.contains( "foo" ) );
} }
@Test @Test
@@ -27,8 +27,8 @@ public class CaseInsensitiveTest
CaseInsensitiveSet set = new CaseInsensitiveSet(); CaseInsensitiveSet set = new CaseInsensitiveSet();
set.add( "FOO" ); set.add( "FOO" );
assertTrue( set.contains( "foo" ) ); // Assert that contains is case insensitive Assert.assertTrue( set.contains( "foo" ) ); // Assert that contains is case insensitive
set.remove( "FoO" ); set.remove( "FoO" );
assertFalse( set.contains( "foo" ) ); // Assert that remove is case insensitive Assert.assertFalse( set.contains( "foo" ) ); // Assert that remove is case insensitive
} }
} }

View File

@@ -1,9 +1,9 @@
package net.md_5.bungee.util; package net.md_5.bungee.util;
import static org.junit.jupiter.api.Assertions.*;
import java.util.UUID; import java.util.UUID;
import net.md_5.bungee.Util; import net.md_5.bungee.Util;
import org.junit.jupiter.api.Test; import org.junit.Assert;
import org.junit.Test;
public class UUIDTest public class UUIDTest
{ {
@@ -13,7 +13,7 @@ public class UUIDTest
{ {
UUID uuid = UUID.fromString( "af74a02d-19cb-445b-b07f-6866a861f783" ); UUID uuid = UUID.fromString( "af74a02d-19cb-445b-b07f-6866a861f783" );
UUID uuid1 = Util.getUUID( "af74a02d19cb445bb07f6866a861f783" ); UUID uuid1 = Util.getUUID( "af74a02d19cb445bb07f6866a861f783" );
assertEquals( uuid, uuid1 ); Assert.assertEquals( uuid, uuid1 );
} }
@Test @Test
@@ -23,7 +23,7 @@ public class UUIDTest
{ {
UUID expected = UUID.randomUUID(); UUID expected = UUID.randomUUID();
UUID actual = Util.getUUID( expected.toString().replace( "-", "" ) ); UUID actual = Util.getUUID( expected.toString().replace( "-", "" ) );
assertEquals( expected, actual, "Could not parse UUID " + expected ); Assert.assertEquals( "Could not parse UUID " + expected, expected, actual );
} }
} }
} }

View File

@@ -4,14 +4,15 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>fr.pandacube.bungeecord</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.16-R0.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-bootstrap</artifactId> <artifactId>bungeecord-bootstrap</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.16-R0.4-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>BungeeCord-Bootstrap</name> <name>BungeeCord-Bootstrap</name>
@@ -20,12 +21,14 @@
<properties> <properties>
<maven.deploy.skip>true</maven.deploy.skip> <maven.deploy.skip>true</maven.deploy.skip>
<maven.javadoc.skip>true</maven.javadoc.skip> <maven.javadoc.skip>true</maven.javadoc.skip>
<maven.compiler.source>1.6</maven.compiler.source>
<maven.compiler.target>1.6</maven.compiler.target>
<maven.build.timestamp.format>yyyyMMdd</maven.build.timestamp.format> <maven.build.timestamp.format>yyyyMMdd</maven.build.timestamp.format>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>fr.pandacube.bungeecord</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-proxy</artifactId> <artifactId>bungeecord-proxy</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>
@@ -38,7 +41,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId> <artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version> <version>3.2.0</version>
<configuration> <configuration>
<archive> <archive>
<manifestEntries> <manifestEntries>
@@ -52,7 +55,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId> <artifactId>maven-shade-plugin</artifactId>
<version>3.5.0</version> <version>3.2.3</version>
<executions> <executions>
<execution> <execution>
<phase>package</phase> <phase>package</phase>
@@ -76,34 +79,4 @@
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
<profiles>
<profile>
<id>jdk-9-release</id>
<activation>
<jdk>[9,)</jdk>
</activation>
<properties>
<maven.compiler.release>6</maven.compiler.release>
</properties>
</profile>
<profile>
<id>jdk-12-release</id>
<activation>
<jdk>[12,)</jdk>
</activation>
<properties>
<maven.compiler.release>7</maven.compiler.release>
</properties>
</profile>
<profile>
<id>jdk-20-release</id>
<activation>
<jdk>[20,)</jdk>
</activation>
<properties>
<maven.compiler.release>8</maven.compiler.release>
</properties>
</profile>
</profiles>
</project> </project>

View File

@@ -4,14 +4,15 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>fr.pandacube.bungeecord</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.16-R0.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-chat</artifactId> <artifactId>bungeecord-chat</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.16-R0.4-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>BungeeCord-Chat</name> <name>BungeeCord-Chat</name>
@@ -21,7 +22,7 @@
<dependency> <dependency>
<groupId>com.google.code.gson</groupId> <groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId> <artifactId>gson</artifactId>
<version>2.10.1</version> <version>2.8.0</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

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

View File

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

View File

@@ -57,7 +57,7 @@ public final class ComponentBuilder
*/ */
public ComponentBuilder(ComponentBuilder original) public ComponentBuilder(ComponentBuilder original)
{ {
this( original.parts.toArray( new BaseComponent[ 0 ] ) ); this( original.parts.toArray( new BaseComponent[ original.parts.size() ] ) );
} }
/** /**
@@ -161,7 +161,7 @@ public final class ComponentBuilder
previous = dummy; previous = dummy;
dummy = null; dummy = null;
} }
if ( previous != null && !component.isReset() ) if ( previous != null )
{ {
component.copyFormatting( previous, retention, false ); component.copyFormatting( previous, retention, false );
} }
@@ -454,32 +454,9 @@ public final class ComponentBuilder
return this; return this;
} }
/**
* Returns the component built by this builder. If this builder is
* empty, an empty text component will be returned.
*
* @return the component
*/
public BaseComponent build()
{
TextComponent base = new TextComponent();
if ( !parts.isEmpty() )
{
List<BaseComponent> cloned = new ArrayList<>( parts );
cloned.replaceAll( BaseComponent::duplicate );
base.setExtra( cloned );
}
return base;
}
/** /**
* Returns the components needed to display the message created by this * Returns the components needed to display the message created by this
* builder.git * builder.git
* <p>
* <strong>NOTE:</strong> {@link #build()} is preferred as it will
* consolidate all components into a single BaseComponent with extra
* contents as opposed to an array of components which is non-standard
* and may result in unexpected behavior.
* *
* @return the created components * @return the created components
*/ */

View File

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

View File

@@ -30,10 +30,6 @@ public final class TranslatableComponent extends BaseComponent
* The components to substitute into the translation * The components to substitute into the translation
*/ */
private List<BaseComponent> with; private List<BaseComponent> with;
/**
* The fallback, if the translation is not found
*/
private String fallback;
/** /**
* Creates a translatable component from the original to clone it. * Creates a translatable component from the original to clone it.
@@ -157,11 +153,6 @@ public final class TranslatableComponent extends BaseComponent
{ {
String trans = TranslationRegistry.INSTANCE.translate( translate ); String trans = TranslationRegistry.INSTANCE.translate( translate );
if ( trans.equals( translate ) && fallback != null )
{
trans = fallback;
}
Matcher matcher = format.matcher( trans ); Matcher matcher = format.matcher( trans );
int position = 0; int position = 0;
int i = 0; int i = 0;

View File

@@ -23,12 +23,6 @@ public class Text extends Content
this.value = value; this.value = value;
} }
public Text(BaseComponent value)
{
// For legacy serialization reasons, this has to be an array of components
this( new BaseComponent[]{value} );
}
public Text(String value) public Text(String value)
{ {
this.value = value; this.value = value;

View File

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

View File

@@ -27,6 +27,7 @@ import net.md_5.bungee.api.chat.hover.content.TextSerializer;
public class ComponentSerializer implements JsonDeserializer<BaseComponent> public class ComponentSerializer implements JsonDeserializer<BaseComponent>
{ {
private static final JsonParser JSON_PARSER = new JsonParser();
private static final Gson gson = new GsonBuilder(). private static final Gson gson = new GsonBuilder().
registerTypeAdapter( BaseComponent.class, new ComponentSerializer() ). registerTypeAdapter( BaseComponent.class, new ComponentSerializer() ).
registerTypeAdapter( TextComponent.class, new TextComponentSerializer() ). registerTypeAdapter( TextComponent.class, new TextComponentSerializer() ).
@@ -42,25 +43,9 @@ public class ComponentSerializer implements JsonDeserializer<BaseComponent>
public static final ThreadLocal<Set<BaseComponent>> serializedComponents = new ThreadLocal<Set<BaseComponent>>(); public static final ThreadLocal<Set<BaseComponent>> serializedComponents = new ThreadLocal<Set<BaseComponent>>();
/**
* Parse a JSON-compliant String as an array of base components. The input
* can be one of either an array of components, or a single component object.
* If the input is an array, each component will be parsed individually and
* returned in the order that they were parsed. If the input is a single
* component object, a single-valued array with the component will be returned.
* <p>
* <strong>NOTE:</strong> {@link #deserialize(String)} is preferred as it will
* parse only one component as opposed to an array of components which is non-
* standard behavior. This method is still appropriate for parsing multiple
* components at once, although such use case is rarely (if at all) exhibited
* in vanilla Minecraft.
*
* @param json the component json to parse
* @return an array of all parsed components
*/
public static BaseComponent[] parse(String json) public static BaseComponent[] parse(String json)
{ {
JsonElement jsonElement = JsonParser.parseString( json ); JsonElement jsonElement = JSON_PARSER.parse( json );
if ( jsonElement.isJsonArray() ) if ( jsonElement.isJsonArray() )
{ {
@@ -74,26 +59,6 @@ public class ComponentSerializer implements JsonDeserializer<BaseComponent>
} }
} }
/**
* Deserialize a JSON-compliant String as a single component. The input is
* expected to be a JSON object that represents only one component.
*
* @param json the component json to parse
* @return the deserialized component
* @throws IllegalArgumentException if anything other than a JSON object is
* passed as input
*/
public static BaseComponent deserialize(String json)
{
JsonElement jsonElement = JsonParser.parseString( json );
if ( !jsonElement.isJsonObject() )
{
throw new IllegalArgumentException( "Malformatted JSON. Expected object, got array for input \"" + json + "\"." );
}
return gson.fromJson( jsonElement, BaseComponent.class );
}
public static String toString(Object object) public static String toString(Object object)
{ {
return gson.toJson( object ); return gson.toJson( object );

View File

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

View File

@@ -28,11 +28,7 @@ public class TranslatableComponentSerializer extends BaseComponentSerializer imp
component.setTranslate( object.get( "translate" ).getAsString() ); component.setTranslate( object.get( "translate" ).getAsString() );
if ( object.has( "with" ) ) if ( object.has( "with" ) )
{ {
component.setWith( Arrays.asList( context.deserialize( object.get( "with" ), BaseComponent[].class ) ) ); component.setWith( Arrays.asList( context.<BaseComponent[]>deserialize( object.get( "with" ), BaseComponent[].class ) ) );
}
if ( object.has( "fallback" ) )
{
component.setFallback( object.get( "fallback" ).getAsString() );
} }
return component; return component;
} }
@@ -47,10 +43,6 @@ public class TranslatableComponentSerializer extends BaseComponentSerializer imp
{ {
object.add( "with", context.serialize( src.getWith() ) ); object.add( "with", context.serialize( src.getWith() ) );
} }
if ( src.getFallback() != null )
{
object.addProperty( "fallback", src.getFallback() );
}
return object; return object;
} }
} }

View File

@@ -1,17 +1,12 @@
package net.md_5.bungee.api.chat; package net.md_5.bungee.api.chat;
import static org.junit.jupiter.api.Assertions.*;
import java.awt.Color; import java.awt.Color;
import java.util.function.BiFunction;
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.ChatColor;
import net.md_5.bungee.api.chat.hover.content.Item; import net.md_5.bungee.api.chat.hover.content.Item;
import net.md_5.bungee.api.chat.hover.content.Text; import net.md_5.bungee.api.chat.hover.content.Text;
import net.md_5.bungee.chat.ComponentSerializer; import net.md_5.bungee.chat.ComponentSerializer;
import org.junit.jupiter.api.Test; import org.junit.Assert;
import org.junit.Test;
public class ComponentsTest public class ComponentsTest
{ {
@@ -20,27 +15,13 @@ public class ComponentsTest
{ {
String json = ComponentSerializer.toString( components ); String json = ComponentSerializer.toString( components );
BaseComponent[] parsed = ComponentSerializer.parse( json ); BaseComponent[] parsed = ComponentSerializer.parse( json );
assertEquals( TextComponent.toLegacyText( parsed ), TextComponent.toLegacyText( components ) ); Assert.assertEquals( TextComponent.toLegacyText( parsed ), TextComponent.toLegacyText( components ) );
} }
public static void testDissembleReassemble(BaseComponent component) public static void testDissembleReassemble(String json)
{
String json = ComponentSerializer.toString( component );
BaseComponent[] parsed = ComponentSerializer.parse( json );
assertEquals( TextComponent.toLegacyText( parsed ), TextComponent.toLegacyText( component ) );
}
public static void testAssembleDissemble(String json, boolean modern)
{
if ( modern )
{
BaseComponent deserialized = ComponentSerializer.deserialize( json );
assertEquals( json, ComponentSerializer.toString( deserialized ) );
} else
{ {
BaseComponent[] parsed = ComponentSerializer.parse( json ); BaseComponent[] parsed = ComponentSerializer.parse( json );
assertEquals( json, ComponentSerializer.toString( parsed ) ); Assert.assertEquals( json, ComponentSerializer.toString( parsed ) );
}
} }
@Test @Test
@@ -60,16 +41,14 @@ public class ComponentsTest
{ {
textComponent textComponent
} ); } );
testDissembleReassemble( textComponent ); json = "{\"text\":\"Test\",\"hoverEvent\":{\"action\":\"show_item\",\"value\":[{\"text\":\"{id:\\\"minecraft:netherrack\\\",Count:47b}\"}]}}";
json = "{\"hoverEvent\":{\"action\":\"show_item\",\"value\":[{\"text\":\"{id:\\\"minecraft:netherrack\\\",Count:47b}\"}]},\"text\":\"Test\"}"; testDissembleReassemble( json );
testAssembleDissemble( json, false );
testAssembleDissemble( json, true );
////////// //////////
String hoverVal = "{\"text\":\"{id:\\\"minecraft:dirt\\\",Count:1b}\"}"; String hoverVal = "{\"text\":\"{id:\\\"minecraft:dirt\\\",Count:1b}\"}";
json = "{\"extra\":[{\"text\":\"[\"},{\"extra\":[{\"translate\":\"block.minecraft.dirt\"}],\"text\":\"\"},{\"text\":\"]\"}],\"hoverEvent\":{\"action\":\"show_item\",\"value\":[" + hoverVal + "]},\"text\":\"\"}"; json = "{\"extra\":[{\"text\":\"[\"},{\"extra\":[{\"translate\":\"block.minecraft.dirt\"}],\"text\":\"\"},{\"text\":\"]\"}],\"hoverEvent\":{\"action\":\"show_item\",\"value\":[" + hoverVal + "]},\"text\":\"\"}";
components = ComponentSerializer.parse( json ); components = ComponentSerializer.parse( json );
Text contentText = ( (Text) components[0].getHoverEvent().getContents().get( 0 ) ); Text contentText = ( (Text) components[0].getHoverEvent().getContents().get( 0 ) );
assertEquals( hoverVal, ComponentSerializer.toString( (BaseComponent[]) contentText.getValue() ) ); Assert.assertEquals( hoverVal, ComponentSerializer.toString( (BaseComponent[]) contentText.getValue() ) );
testDissembleReassemble( components ); testDissembleReassemble( components );
////////// //////////
TextComponent component1 = new TextComponent( "HoverableText" ); TextComponent component1 = new TextComponent( "HoverableText" );
@@ -80,44 +59,25 @@ public class ComponentsTest
json = ComponentSerializer.toString( component1 ); json = ComponentSerializer.toString( component1 );
components = ComponentSerializer.parse( json ); components = ComponentSerializer.parse( json );
Item parsedContentItem = ( (Item) components[0].getHoverEvent().getContents().get( 0 ) ); Item parsedContentItem = ( (Item) components[0].getHoverEvent().getContents().get( 0 ) );
assertEquals( contentItem, parsedContentItem ); Assert.assertEquals( contentItem, parsedContentItem );
assertEquals( contentItem.getCount(), parsedContentItem.getCount() ); Assert.assertEquals( contentItem.getCount(), parsedContentItem.getCount() );
assertEquals( contentItem.getId(), parsedContentItem.getId() ); Assert.assertEquals( contentItem.getId(), parsedContentItem.getId() );
assertEquals( nbt, parsedContentItem.getTag().getNbt() ); Assert.assertEquals( nbt, parsedContentItem.getTag().getNbt() );
} }
@Test @Test
public void testEmptyComponentBuilderCreate() public void testEmptyComponentBuilder()
{
this.testEmptyComponentBuilder(
ComponentBuilder::create,
(components) -> assertEquals( components.length, 0 ),
(components, size) -> assertEquals( size, components.length )
);
}
@Test
public void testEmptyComponentBuilderBuild()
{
this.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)
{ {
ComponentBuilder builder = new ComponentBuilder(); ComponentBuilder builder = new ComponentBuilder();
T component = componentBuilder.apply( builder ); BaseComponent[] parts = builder.create();
emptyAssertion.accept( component ); Assert.assertEquals( parts.length, 0 );
for ( int i = 0; i < 3; i++ ) for ( int i = 0; i < 3; i++ )
{ {
builder.append( "part:" + i ); builder.append( "part:" + i );
component = componentBuilder.apply( builder ); parts = builder.create();
sizedAssertion.accept( component, i + 1 ); Assert.assertEquals( parts.length, i + 1 );
} }
} }
@@ -125,23 +85,23 @@ public class ComponentsTest
public void testDummyRetaining() public void testDummyRetaining()
{ {
ComponentBuilder builder = new ComponentBuilder(); ComponentBuilder builder = new ComponentBuilder();
assertNotNull( builder.getCurrentComponent() ); Assert.assertNotNull( builder.getCurrentComponent() );
builder.color( ChatColor.GREEN ); builder.color( ChatColor.GREEN );
builder.append( "test ", ComponentBuilder.FormatRetention.ALL ); builder.append( "test ", ComponentBuilder.FormatRetention.ALL );
assertEquals( builder.getCurrentComponent().getColor(), ChatColor.GREEN ); Assert.assertEquals( builder.getCurrentComponent().getColor(), ChatColor.GREEN );
} }
@Test @Test(expected = IndexOutOfBoundsException.class)
public void testComponentGettingExceptions() public void testComponentGettingExceptions()
{ {
ComponentBuilder builder = new ComponentBuilder(); ComponentBuilder builder = new ComponentBuilder();
assertThrows( IndexOutOfBoundsException.class, () -> builder.getComponent( -1 ) ); builder.getComponent( -1 );
assertThrows( IndexOutOfBoundsException.class, () -> builder.getComponent( 0 ) ); builder.getComponent( 0 );
assertThrows( IndexOutOfBoundsException.class, () -> builder.getComponent( 1 ) ); builder.getComponent( 1 );
BaseComponent component = new TextComponent( "Hello" ); BaseComponent component = new TextComponent( "Hello" );
builder.append( component ); builder.append( component );
assertEquals( builder.getComponent( 0 ), component ); Assert.assertEquals( builder.getComponent( 0 ), component );
assertThrows( IndexOutOfBoundsException.class, () -> builder.getComponent( 1 ) ); builder.getComponent( 1 );
} }
@Test @Test
@@ -150,33 +110,33 @@ public class ComponentsTest
ComponentBuilder builder = new ComponentBuilder(); ComponentBuilder builder = new ComponentBuilder();
TextComponent apple = new TextComponent( "apple" ); TextComponent apple = new TextComponent( "apple" );
builder.append( apple ); builder.append( apple );
assertEquals( builder.getCurrentComponent(), apple ); Assert.assertEquals( builder.getCurrentComponent(), apple );
assertEquals( builder.getComponent( 0 ), apple ); Assert.assertEquals( builder.getComponent( 0 ), apple );
TextComponent mango = new TextComponent( "mango" ); TextComponent mango = new TextComponent( "mango" );
TextComponent orange = new TextComponent( "orange" ); TextComponent orange = new TextComponent( "orange" );
builder.append( mango ); builder.append( mango );
builder.append( orange ); builder.append( orange );
builder.removeComponent( 1 ); // Removing mango builder.removeComponent( 1 ); // Removing mango
assertEquals( builder.getComponent( 0 ), apple ); Assert.assertEquals( builder.getComponent( 0 ), apple );
assertEquals( builder.getComponent( 1 ), orange ); Assert.assertEquals( builder.getComponent( 1 ), orange );
} }
@Test @Test
public void testToLegacyFromLegacy() public void testToLegacyFromLegacy()
{ {
String text = "§a§lHello §f§kworld§7!"; String text = "§a§lHello §f§kworld§7!";
assertEquals( text, TextComponent.toLegacyText( TextComponent.fromLegacyText( text ) ) ); Assert.assertEquals( text, TextComponent.toLegacyText( TextComponent.fromLegacyText( text ) ) );
} }
@Test @Test(expected = IndexOutOfBoundsException.class)
public void testComponentBuilderCursorInvalidPos() public void testComponentBuilderCursorInvalidPos()
{ {
ComponentBuilder builder = new ComponentBuilder(); ComponentBuilder builder = new ComponentBuilder();
builder.append( new TextComponent( "Apple, " ) ); builder.append( new TextComponent( "Apple, " ) );
builder.append( new TextComponent( "Orange, " ) ); builder.append( new TextComponent( "Orange, " ) );
assertThrows( IndexOutOfBoundsException.class, () -> builder.setCursor( -1 ) ); builder.setCursor( -1 );
assertThrows( IndexOutOfBoundsException.class, () -> builder.setCursor( 2 ) ); builder.setCursor( 2 );
} }
@Test @Test
@@ -184,24 +144,24 @@ public class ComponentsTest
{ {
TextComponent t1, t2, t3; TextComponent t1, t2, t3;
ComponentBuilder builder = new ComponentBuilder(); ComponentBuilder builder = new ComponentBuilder();
assertEquals( builder.getCursor(), -1 ); Assert.assertEquals( builder.getCursor(), -1 );
builder.append( t1 = new TextComponent( "Apple, " ) ); builder.append( t1 = new TextComponent( "Apple, " ) );
assertEquals( builder.getCursor(), 0 ); Assert.assertEquals( builder.getCursor(), 0 );
builder.append( t2 = new TextComponent( "Orange, " ) ); builder.append( t2 = new TextComponent( "Orange, " ) );
builder.append( t3 = new TextComponent( "Mango, " ) ); builder.append( t3 = new TextComponent( "Mango, " ) );
assertEquals( builder.getCursor(), 2 ); Assert.assertEquals( builder.getCursor(), 2 );
builder.setCursor( 0 ); builder.setCursor( 0 );
assertEquals( builder.getCurrentComponent(), t1 ); Assert.assertEquals( builder.getCurrentComponent(), t1 );
// Test that appending new components updates the position to the new list size // Test that appending new components updates the position to the new list size
// after having previously set it to 0 (first component) // after having previously set it to 0 (first component)
builder.append( new TextComponent( "and Grapefruit" ) ); builder.append( new TextComponent( "and Grapefruit" ) );
assertEquals( builder.getCursor(), 3 ); Assert.assertEquals( builder.getCursor(), 3 );
builder.setCursor( 0 ); builder.setCursor( 0 );
builder.resetCursor(); builder.resetCursor();
assertEquals( builder.getCursor(), 3 ); Assert.assertEquals( builder.getCursor(), 3 );
} }
@Test @Test
@@ -210,7 +170,7 @@ public class ComponentsTest
String text = "§a§lHello §r§kworld§7!"; String text = "§a§lHello §r§kworld§7!";
BaseComponent[] components = TextComponent.fromLegacyText( text ); BaseComponent[] components = TextComponent.fromLegacyText( text );
BaseComponent[] builderComponents = new ComponentBuilder().append( components ).create(); BaseComponent[] builderComponents = new ComponentBuilder().append( components ).create();
assertArrayEquals( components, builderComponents ); Assert.assertArrayEquals( components, builderComponents );
} }
/* /*
@@ -232,7 +192,7 @@ public class ComponentsTest
component.setHoverEvent( event ); component.setHoverEvent( event );
String serialised = ComponentSerializer.toString( component ); String serialised = ComponentSerializer.toString( component );
BaseComponent[] deserialised = ComponentSerializer.parse( serialised ); BaseComponent[] deserialised = ComponentSerializer.parse( serialised );
assertEquals( TextComponent.toLegacyText( deserialised ), TextComponent.toLegacyText( component ) ); Assert.assertEquals( TextComponent.toLegacyText( deserialised ), TextComponent.toLegacyText( component ) );
} }
*/ */
@@ -247,13 +207,13 @@ public class ComponentsTest
); );
TextComponent component = new TextComponent( "test" ); TextComponent component = new TextComponent( "test" );
component.setHoverEvent( hoverEvent ); component.setHoverEvent( hoverEvent );
assertEquals( component.getHoverEvent().getContents().size(), 1 ); Assert.assertEquals( component.getHoverEvent().getContents().size(), 1 );
assertTrue( component.getHoverEvent().getContents().get( 0 ) instanceof Text ); Assert.assertTrue( component.getHoverEvent().getContents().get( 0 ) instanceof Text );
assertEquals( ( (Text) component.getHoverEvent().getContents().get( 0 ) ).getValue(), advancement ); Assert.assertEquals( ( (Text) component.getHoverEvent().getContents().get( 0 ) ).getValue(), advancement );
} }
@Test @Test
public void testHoverEventContentsCreate() public void testHoverEventContents()
{ {
// First do the text using the newer contents system // First do the text using the newer contents system
HoverEvent hoverEvent = new HoverEvent( HoverEvent hoverEvent = new HoverEvent(
@@ -262,53 +222,21 @@ public class ComponentsTest
new Text( new ComponentBuilder( "Second" ).create() ) new Text( new ComponentBuilder( "Second" ).create() )
); );
this.testHoverEventContents( TextComponent component = new TextComponent( "Sample text" );
hoverEvent, component.setHoverEvent( hoverEvent );
ComponentSerializer::parse, Assert.assertEquals( hoverEvent.getContents().size(), 2 );
(components) -> components[0].getHoverEvent(), Assert.assertFalse( hoverEvent.isLegacy() );
ComponentsTest::testDissembleReassemble // BaseComponent String serialized = ComponentSerializer.toString( component );
); BaseComponent[] deserialized = ComponentSerializer.parse( serialized );
Assert.assertEquals( component.getHoverEvent(), deserialized[0].getHoverEvent() );
// check the test still works with the value method // check the test still works with the value method
hoverEvent = new HoverEvent( HoverEvent.Action.SHOW_TEXT, new ComponentBuilder( "Sample text" ).create() ); hoverEvent = new HoverEvent( HoverEvent.Action.SHOW_TEXT, new ComponentBuilder( "Sample text" ).create() );
TextComponent component = new TextComponent( "Sample text" ); Assert.assertEquals( hoverEvent.getContents().size(), 1 );
component.setHoverEvent( hoverEvent ); Assert.assertTrue( hoverEvent.isLegacy() );
serialized = ComponentSerializer.toString( component );
assertEquals( hoverEvent.getContents().size(), 1 ); deserialized = ComponentSerializer.parse( serialized );
assertTrue( hoverEvent.isLegacy() ); Assert.assertEquals( component.getHoverEvent(), deserialized[0].getHoverEvent() );
String serialized = ComponentSerializer.toString( component );
BaseComponent[] deserialized = ComponentSerializer.parse( serialized );
assertEquals( component.getHoverEvent(), deserialized[0].getHoverEvent() );
}
@Test
public void testHoverEventContentsBuild()
{
// First do the text using the newer contents system
HoverEvent hoverEvent = new HoverEvent(
HoverEvent.Action.SHOW_TEXT,
new Text( new ComponentBuilder( "First" ).build() ),
new Text( new ComponentBuilder( "Second" ).build() )
);
this.testHoverEventContents(
hoverEvent,
ComponentSerializer::deserialize,
BaseComponent::getHoverEvent,
ComponentsTest::testDissembleReassemble // BaseComponent
);
}
private <T> void testHoverEventContents(HoverEvent hoverEvent, Function<String, T> deserializer, Function<T, HoverEvent> hoverEventGetter, Consumer<T> dissembleReassembleTest)
{
TextComponent component = new TextComponent( "Sample text" );
component.setHoverEvent( hoverEvent );
assertEquals( hoverEvent.getContents().size(), 2 );
assertFalse( hoverEvent.isLegacy() );
String serialized = ComponentSerializer.toString( component );
T deserialized = deserializer.apply( serialized );
assertEquals( component.getHoverEvent(), hoverEventGetter.apply( deserialized ) );
// Test single content: // Test single content:
String json = "{\"italic\":true,\"color\":\"gray\",\"translate\":\"chat.type.admin\",\"with\":[{\"text\":\"@\"}" String json = "{\"italic\":true,\"color\":\"gray\",\"translate\":\"chat.type.admin\",\"with\":[{\"text\":\"@\"}"
@@ -320,76 +248,37 @@ public class ComponentsTest
+ "\"/tell Name \"},\"hoverEvent\":{\"action\":\"show_entity\",\"contents\":" + "\"/tell Name \"},\"hoverEvent\":{\"action\":\"show_entity\",\"contents\":"
+ "{\"type\":\"minecraft:player\",\"id\":\"00000000-0000-0000-0000-00000000000000\",\"name\":" + "{\"type\":\"minecraft:player\",\"id\":\"00000000-0000-0000-0000-00000000000000\",\"name\":"
+ "{\"text\":\"Name\"}}},\"text\":\"Name\"}]}]}"; + "{\"text\":\"Name\"}}},\"text\":\"Name\"}]}]}";
dissembleReassembleTest.accept( deserializer.apply( json ) ); testDissembleReassemble( ComponentSerializer.parse( json ) );
} }
@Test @Test
public void testFormatRetentionCopyFormattingCreate() public void testFormatRetentionCopyFormatting()
{
this.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() ) ) );
}
private void testFormatRetentionCopyFormatting(Supplier<HoverEvent> hoverEventSupplier)
{ {
TextComponent first = new TextComponent( "Hello" ); TextComponent first = new TextComponent( "Hello" );
first.setBold( true ); first.setBold( true );
first.setColor( ChatColor.RED ); first.setColor( ChatColor.RED );
first.setClickEvent( new ClickEvent( ClickEvent.Action.RUN_COMMAND, "test" ) ); first.setClickEvent( new ClickEvent( ClickEvent.Action.RUN_COMMAND, "test" ) );
first.setHoverEvent( hoverEventSupplier.get() ); first.setHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, new ComponentBuilder( "Test" ).create() ) );
TextComponent second = new TextComponent( " world" ); TextComponent second = new TextComponent( " world" );
second.copyFormatting( first, ComponentBuilder.FormatRetention.ALL, true ); second.copyFormatting( first, ComponentBuilder.FormatRetention.ALL, true );
assertEquals( first.isBold(), second.isBold() ); Assert.assertEquals( first.isBold(), second.isBold() );
assertEquals( first.getColor(), second.getColor() ); Assert.assertEquals( first.getColor(), second.getColor() );
assertEquals( first.getClickEvent(), second.getClickEvent() ); Assert.assertEquals( first.getClickEvent(), second.getClickEvent() );
assertEquals( first.getHoverEvent(), second.getHoverEvent() ); Assert.assertEquals( first.getHoverEvent(), second.getHoverEvent() );
} }
@Test @Test
public void testBuilderCloneCreate() public void testBuilderClone()
{
this.testBuilderClone( (builder) -> TextComponent.toLegacyText( builder.create() ) );
}
@Test
public void testBuilderCloneBuild()
{
this.testBuilderClone( (builder) -> TextComponent.toLegacyText( builder.build() ) );
}
private 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( ChatColor.RED ).append( "world" ).color( ChatColor.DARK_RED );
ComponentBuilder cloned = new ComponentBuilder( builder ); ComponentBuilder cloned = new ComponentBuilder( builder );
assertEquals( legacyTextFunction.apply( builder ), legacyTextFunction.apply( cloned ) ); Assert.assertEquals( TextComponent.toLegacyText( builder.create() ), TextComponent.toLegacyText( cloned.create() ) );
} }
@Test @Test
public void testBuilderAppendCreateMixedComponents() public void testBuilderAppendMixedComponents()
{
this.testBuilderAppendMixedComponents(
ComponentBuilder::create,
(components, index) -> components[index]
);
}
@Test
public void testBuilderAppendBuildMixedComponents()
{
this.testBuilderAppendMixedComponents(
ComponentBuilder::build,
(component, index) -> component.getExtra().get( index )
);
}
private <T> void testBuilderAppendMixedComponents(Function<ComponentBuilder, T> componentBuilder, BiFunction<T, Integer, BaseComponent> extraGetter)
{ {
ComponentBuilder builder = new ComponentBuilder( "Hello " ); ComponentBuilder builder = new ComponentBuilder( "Hello " );
TextComponent textComponent = new TextComponent( "world " ); TextComponent textComponent = new TextComponent( "world " );
@@ -402,11 +291,11 @@ public class ComponentsTest
} ); } );
ScoreComponent scoreComponent = new ScoreComponent( "myscore", "myobjective" ); ScoreComponent scoreComponent = new ScoreComponent( "myscore", "myobjective" );
builder.append( scoreComponent ); // non array based BaseComponent append builder.append( scoreComponent ); // non array based BaseComponent append
T component = componentBuilder.apply( builder ); BaseComponent[] components = builder.create();
assertEquals( "Hello ", extraGetter.apply( component, 0 ).toPlainText() ); Assert.assertEquals( "Hello ", components[0].toPlainText() );
assertEquals( textComponent.toPlainText(), extraGetter.apply( component, 1 ).toPlainText() ); Assert.assertEquals( textComponent.toPlainText(), components[1].toPlainText() );
assertEquals( translatableComponent.toPlainText(), extraGetter.apply( component, 2 ).toPlainText() ); Assert.assertEquals( translatableComponent.toPlainText(), components[2].toPlainText() );
assertEquals( scoreComponent.toPlainText(), extraGetter.apply( component, 3 ).toPlainText() ); Assert.assertEquals( scoreComponent.toPlainText(), components[3].toPlainText() );
} }
@Test @Test
@@ -416,84 +305,36 @@ public class ComponentsTest
String text = ComponentSerializer.toString( component ); String text = ComponentSerializer.toString( component );
BaseComponent[] reparsed = ComponentSerializer.parse( text ); BaseComponent[] reparsed = ComponentSerializer.parse( text );
assertArrayEquals( component, reparsed ); Assert.assertArrayEquals( component, reparsed );
} }
@Test @Test
public void testBuilderAppendCreate() public void testBuilderAppend()
{
this.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!",
BaseComponent::toLegacyText
);
}
@Test
public void testBuilderAppendBuild()
{
this.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!",
(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)
{ {
ClickEvent clickEvent = new ClickEvent( ClickEvent.Action.RUN_COMMAND, "/help " ); ClickEvent clickEvent = new ClickEvent( ClickEvent.Action.RUN_COMMAND, "/help " );
HoverEvent hoverEvent = hoverEventSupplier.get(); HoverEvent hoverEvent = new HoverEvent( HoverEvent.Action.SHOW_TEXT, new ComponentBuilder( "Hello world" ).create() );
ComponentBuilder builder = new ComponentBuilder( "Hello " ).color( ChatColor.YELLOW ); 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 builder.append( new ComponentBuilder( "world!" ).color( ChatColor.GREEN ).event( hoverEvent ).event( clickEvent ).create() );
T component = componentBuilder.apply( builder ); BaseComponent[] components = builder.create();
assertEquals( extraGetter.apply( component, 1 ).getHoverEvent(), hoverEvent ); Assert.assertEquals( components[1].getHoverEvent(), hoverEvent );
assertEquals( extraGetter.apply( component, 1 ).getClickEvent(), clickEvent ); Assert.assertEquals( components[1].getClickEvent(), clickEvent );
assertEquals( "Hello world!", toPlainTextFunction.apply( component ) ); Assert.assertEquals( "Hello world!", BaseComponent.toPlainText( components ) );
assertEquals( expectedLegacyText, toLegacyTextFunction.apply( component ) ); Assert.assertEquals( ChatColor.YELLOW + "Hello " + ChatColor.GREEN + "world!", BaseComponent.toLegacyText( components ) );
} }
@Test @Test
public void testBuilderAppendLegacyCreate() public void testBuilderAppendLegacy()
{
this.testBuilderAppendLegacy(
ComponentBuilder::create,
BaseComponent::toPlainText,
ChatColor.YELLOW + "Hello " + ChatColor.GREEN + "world!",
BaseComponent::toLegacyText
);
}
@Test
public void testBuilderAppendLegacyBuild()
{
this.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!",
(component) -> BaseComponent.toLegacyText( component )
);
}
private <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 ); ComponentBuilder builder = new ComponentBuilder( "Hello " ).color( ChatColor.YELLOW );
builder.appendLegacy( "§aworld!" ); builder.appendLegacy( "§aworld!" );
T component = componentBuilder.apply( builder ); BaseComponent[] components = builder.create();
assertEquals( "Hello world!", toPlainTextFunction.apply( component ) ); Assert.assertEquals( "Hello world!", BaseComponent.toPlainText( components ) );
assertEquals( expectedLegacyString, toLegacyTextFunction.apply( component ) ); Assert.assertEquals( ChatColor.YELLOW + "Hello " + ChatColor.GREEN + "world!", BaseComponent.toLegacyText( components ) );
} }
@Test @Test
@@ -502,8 +343,8 @@ public class ComponentsTest
TextComponent textComponent = new TextComponent( "Hello world" ); TextComponent textComponent = new TextComponent( "Hello world" );
textComponent.setColor( ChatColor.RED ); textComponent.setColor( ChatColor.RED );
assertEquals( "Hello world", textComponent.toPlainText() ); Assert.assertEquals( "Hello world", textComponent.toPlainText() );
assertEquals( ChatColor.RED + "Hello world", textComponent.toLegacyText() ); Assert.assertEquals( ChatColor.RED + "Hello world", textComponent.toLegacyText() );
} }
@Test @Test
@@ -511,25 +352,25 @@ public class ComponentsTest
{ {
BaseComponent[] test1 = TextComponent.fromLegacyText( ChatColor.AQUA + "Aqua " + ChatColor.RED + ChatColor.BOLD + "RedBold" ); BaseComponent[] test1 = TextComponent.fromLegacyText( ChatColor.AQUA + "Aqua " + ChatColor.RED + ChatColor.BOLD + "RedBold" );
assertEquals( "Aqua RedBold", BaseComponent.toPlainText( test1 ) ); Assert.assertEquals( "Aqua RedBold", BaseComponent.toPlainText( test1 ) );
assertEquals( ChatColor.AQUA + "Aqua " + ChatColor.RED + ChatColor.BOLD + "RedBold", BaseComponent.toLegacyText( test1 ) ); Assert.assertEquals( ChatColor.AQUA + "Aqua " + ChatColor.RED + ChatColor.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 " + ChatColor.GREEN + "google.com/test" );
assertEquals( "Text http://spigotmc.org google.com/test", BaseComponent.toPlainText( test2 ) ); Assert.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 //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 Assert.assertEquals( ChatColor.WHITE + "Text " + ChatColor.WHITE + "http://spigotmc.org" + ChatColor.WHITE
+ " " + ChatColor.GREEN + "google.com/test" + ChatColor.GREEN, BaseComponent.toLegacyText( test2 ) ); + " " + ChatColor.GREEN + "google.com/test" + ChatColor.GREEN, BaseComponent.toLegacyText( test2 ) );
ClickEvent url1 = test2[1].getClickEvent(); ClickEvent url1 = test2[1].getClickEvent();
assertNotNull( url1 ); Assert.assertNotNull( url1 );
assertTrue( url1.getAction() == ClickEvent.Action.OPEN_URL ); Assert.assertTrue( url1.getAction() == ClickEvent.Action.OPEN_URL );
assertEquals( "http://spigotmc.org", url1.getValue() ); Assert.assertEquals( "http://spigotmc.org", url1.getValue() );
ClickEvent url2 = test2[3].getClickEvent(); ClickEvent url2 = test2[3].getClickEvent();
assertNotNull( url2 ); Assert.assertNotNull( url2 );
assertTrue( url2.getAction() == ClickEvent.Action.OPEN_URL ); Assert.assertTrue( url2.getAction() == ClickEvent.Action.OPEN_URL );
assertEquals( "http://google.com/test", url2.getValue() ); Assert.assertEquals( "http://google.com/test", url2.getValue() );
} }
@Test @Test
@@ -541,140 +382,83 @@ public class ComponentsTest
item, "5", item, "5",
"thinkofdeath" ); "thinkofdeath" );
assertEquals( "Given Golden Sword * 5 to thinkofdeath", translatableComponent.toPlainText() ); Assert.assertEquals( "Given Golden Sword * 5 to thinkofdeath", translatableComponent.toPlainText() );
assertEquals( ChatColor.WHITE + "Given " + ChatColor.AQUA + "Golden Sword" + ChatColor.WHITE Assert.assertEquals( ChatColor.WHITE + "Given " + ChatColor.AQUA + "Golden Sword" + ChatColor.WHITE
+ " * " + ChatColor.WHITE + "5" + ChatColor.WHITE + " to " + ChatColor.WHITE + "thinkofdeath", + " * " + ChatColor.WHITE + "5" + ChatColor.WHITE + " to " + ChatColor.WHITE + "thinkofdeath",
translatableComponent.toLegacyText() ); translatableComponent.toLegacyText() );
TranslatableComponent positional = new TranslatableComponent( "book.pageIndicator", "5", "50" ); TranslatableComponent positional = new TranslatableComponent( "book.pageIndicator", "5", "50" );
assertEquals( "Page 5 of 50", positional.toPlainText() ); Assert.assertEquals( "Page 5 of 50", positional.toPlainText() );
assertEquals( ChatColor.WHITE + "Page " + ChatColor.WHITE + "5" + ChatColor.WHITE + " of " + ChatColor.WHITE + "50", positional.toLegacyText() ); Assert.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" ); TranslatableComponent one_four_two = new TranslatableComponent( "filled_map.buried_treasure" );
assertEquals( "Buried Treasure Map", one_four_two.toPlainText() ); Assert.assertEquals( "Buried Treasure Map", one_four_two.toPlainText() );
} }
@Test @Test
public void testBuilderCreate() public void testBuilder()
{ {
this.testBuilder( BaseComponent[] components = new ComponentBuilder( "Hello " ).color( ChatColor.RED ).
ComponentBuilder::create,
BaseComponent::toPlainText,
ChatColor.RED + "Hello " + ChatColor.BLUE + ChatColor.BOLD
+ "World" + ChatColor.YELLOW + ChatColor.BOLD + "!",
BaseComponent::toLegacyText
);
}
@Test
public void testBuilderBuild()
{
this.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 + "!",
(component) -> BaseComponent.toLegacyText( component )
);
}
private <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( "World" ).bold( true ).color( ChatColor.BLUE ).
append( "!" ).color( ChatColor.YELLOW ) ); append( "!" ).color( ChatColor.YELLOW ).create();
assertEquals( "Hello World!", toPlainTextFunction.apply( component ) ); Assert.assertEquals( "Hello World!", BaseComponent.toPlainText( components ) );
assertEquals( expectedLegacyString, toLegacyTextFunction.apply( component ) ); Assert.assertEquals( ChatColor.RED + "Hello " + ChatColor.BLUE + ChatColor.BOLD
+ "World" + ChatColor.YELLOW + ChatColor.BOLD + "!", BaseComponent.toLegacyText( components ) );
} }
@Test @Test
public void testBuilderCreateReset() public void testBuilderReset()
{ {
this.testBuilderReset( BaseComponent[] components = new ComponentBuilder( "Hello " ).color( ChatColor.RED )
ComponentBuilder::create, .append( "World" ).reset().create();
(components, index) -> components[index]
); Assert.assertEquals( components[0].getColor(), ChatColor.RED );
Assert.assertEquals( components[1].getColor(), ChatColor.WHITE );
} }
@Test @Test
public void testBuilderBuildReset() public void testBuilderFormatRetention()
{ {
this.testBuilderReset( BaseComponent[] noneRetention = new ComponentBuilder( "Hello " ).color( ChatColor.RED )
ComponentBuilder::build, .append( "World", ComponentBuilder.FormatRetention.NONE ).create();
(component, index) -> component.getExtra().get( index )
);
}
private <T> void testBuilderReset(Function<ComponentBuilder, T> componentBuilder, BiFunction<T, Integer, BaseComponent> extraGetter) Assert.assertEquals( noneRetention[0].getColor(), ChatColor.RED );
{ Assert.assertEquals( noneRetention[1].getColor(), ChatColor.WHITE );
T component = componentBuilder.apply( new ComponentBuilder( "Hello " ).color( ChatColor.RED )
.append( "World" ).reset() );
assertEquals( ChatColor.RED, extraGetter.apply( component, 0 ).getColor() ); HoverEvent testEvent = new HoverEvent( HoverEvent.Action.SHOW_TEXT, new ComponentBuilder( "test" ).create() );
assertEquals( ChatColor.WHITE, extraGetter.apply( component, 1 ).getColor() );
}
@Test BaseComponent[] formattingRetention = new ComponentBuilder( "Hello " ).color( ChatColor.RED )
public void testBuilderCreateFormatRetention() .event( testEvent ).append( "World", ComponentBuilder.FormatRetention.FORMATTING ).create();
{
this.testBuilderFormatRetention(
ComponentBuilder::create,
(components, index) -> components[index]
);
}
@Test Assert.assertEquals( formattingRetention[0].getColor(), ChatColor.RED );
public void testBuilderBuildFormatRetention() Assert.assertEquals( formattingRetention[0].getHoverEvent(), testEvent );
{ Assert.assertEquals( formattingRetention[1].getColor(), ChatColor.RED );
this.testBuilderFormatRetention( Assert.assertNull( formattingRetention[1].getHoverEvent() );
ComponentBuilder::build,
(component, index) -> component.getExtra().get( index )
);
}
private <T> void testBuilderFormatRetention(Function<ComponentBuilder, T> componentBuilder, BiFunction<T, Integer, BaseComponent> extraGetter)
{
T noneRetention = componentBuilder.apply( new ComponentBuilder( "Hello " ).color( ChatColor.RED )
.append( "World", ComponentBuilder.FormatRetention.NONE ) );
assertEquals( ChatColor.RED, extraGetter.apply( noneRetention, 0 ).getColor() );
assertEquals( ChatColor.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 )
.event( testEvent ).append( "World", ComponentBuilder.FormatRetention.FORMATTING ) );
assertEquals( ChatColor.RED, extraGetter.apply( formattingRetention, 0 ).getColor() );
assertEquals( testEvent, extraGetter.apply( formattingRetention, 0 ).getHoverEvent() );
assertEquals( ChatColor.RED, extraGetter.apply( formattingRetention, 1 ).getColor() );
assertNull( extraGetter.apply( formattingRetention, 1 ).getHoverEvent() );
ClickEvent testClickEvent = new ClickEvent( ClickEvent.Action.OPEN_URL, "http://www.example.com" ); ClickEvent testClickEvent = new ClickEvent( ClickEvent.Action.OPEN_URL, "http://www.example.com" );
T eventRetention = componentBuilder.apply( new ComponentBuilder( "Hello " ).color( ChatColor.RED ) BaseComponent[] eventRetention = new ComponentBuilder( "Hello " ).color( ChatColor.RED )
.event( testEvent ).event( testClickEvent ).append( "World", ComponentBuilder.FormatRetention.EVENTS ) ); .event( testEvent ).event( testClickEvent ).append( "World", ComponentBuilder.FormatRetention.EVENTS ).create();
assertEquals( ChatColor.RED, extraGetter.apply( eventRetention, 0 ).getColor() ); Assert.assertEquals( eventRetention[0].getColor(), ChatColor.RED );
assertEquals( testEvent, extraGetter.apply( eventRetention, 0 ).getHoverEvent() ); Assert.assertEquals( eventRetention[0].getHoverEvent(), testEvent );
assertEquals( testClickEvent, extraGetter.apply( eventRetention, 0 ).getClickEvent() ); Assert.assertEquals( eventRetention[0].getClickEvent(), testClickEvent );
assertEquals( ChatColor.WHITE, extraGetter.apply( eventRetention, 1 ).getColor() ); Assert.assertEquals( eventRetention[1].getColor(), ChatColor.WHITE );
assertEquals( testEvent, extraGetter.apply( eventRetention, 1 ).getHoverEvent() ); Assert.assertEquals( eventRetention[1].getHoverEvent(), testEvent );
assertEquals( testClickEvent, extraGetter.apply( eventRetention, 1 ).getClickEvent() ); Assert.assertEquals( eventRetention[1].getClickEvent(), testClickEvent );
} }
@Test @Test(expected = IllegalArgumentException.class)
public void testLoopSimple() public void testLoopSimple()
{ {
TextComponent component = new TextComponent( "Testing" ); TextComponent component = new TextComponent( "Testing" );
component.addExtra( component ); component.addExtra( component );
assertThrows( IllegalArgumentException.class, () -> ComponentSerializer.toString( component ) ); ComponentSerializer.toString( component );
} }
@Test @Test(expected = IllegalArgumentException.class)
public void testLoopComplex() public void testLoopComplex()
{ {
TextComponent a = new TextComponent( "A" ); TextComponent a = new TextComponent( "A" );
@@ -685,7 +469,7 @@ public class ComponentsTest
a.addExtra( b ); a.addExtra( b );
b.addExtra( c ); b.addExtra( c );
c.addExtra( a ); c.addExtra( a );
assertThrows( IllegalArgumentException.class, () -> ComponentSerializer.toString( a ) ); ComponentSerializer.toString( a );
} }
@Test @Test
@@ -699,7 +483,7 @@ public class ComponentsTest
ComponentSerializer.toString( a ); ComponentSerializer.toString( a );
} }
@Test @Test(expected = IllegalArgumentException.class)
public void testRepeatedError() public void testRepeatedError()
{ {
TextComponent a = new TextComponent( "A" ); TextComponent a = new TextComponent( "A" );
@@ -711,7 +495,7 @@ public class ComponentsTest
a.addExtra( c ); a.addExtra( c );
c.addExtra( a ); c.addExtra( a );
a.addExtra( b ); a.addExtra( b );
assertThrows( IllegalArgumentException.class, () -> ComponentSerializer.toString( a ) ); ComponentSerializer.toString( a );
} }
@Test @Test
@@ -736,7 +520,7 @@ public class ComponentsTest
String emptyLegacyText = fromAndToLegacyText( "" ); String emptyLegacyText = fromAndToLegacyText( "" );
// all invalid color codes and the trailing '§' should be ignored // all invalid color codes and the trailing '§' should be ignored
assertEquals( emptyLegacyText, invalidColorCodesLegacyText ); Assert.assertEquals( emptyLegacyText, invalidColorCodesLegacyText );
} }
@Test @Test
@@ -745,12 +529,12 @@ public class ComponentsTest
String text = "§a"; String text = "§a";
BaseComponent[] converted = TextComponent.fromLegacyText( text ); BaseComponent[] converted = TextComponent.fromLegacyText( text );
assertEquals( ChatColor.GREEN, converted[0].getColor() ); Assert.assertEquals( ChatColor.GREEN, converted[0].getColor() );
String roundtripLegacyText = BaseComponent.toLegacyText( converted ); String roundtripLegacyText = BaseComponent.toLegacyText( converted );
// color code should not be lost during conversion // color code should not be lost during conversion
assertEquals( text, roundtripLegacyText ); Assert.assertEquals( text, roundtripLegacyText );
} }
@Test @Test
@@ -762,7 +546,7 @@ public class ComponentsTest
TextComponent second = new TextComponent( "Hello, " ); TextComponent second = new TextComponent( "Hello, " );
second.addExtra( new TextComponent( "World!" ) ); second.addExtra( new TextComponent( "World!" ) );
assertEquals( first, second ); Assert.assertEquals( first, second );
} }
@Test @Test
@@ -774,7 +558,7 @@ public class ComponentsTest
TextComponent second = new TextComponent( "Hello, " ); TextComponent second = new TextComponent( "Hello, " );
second.addExtra( new TextComponent( "World!" ) ); second.addExtra( new TextComponent( "World!" ) );
assertNotEquals( first, second ); Assert.assertNotEquals( first, second );
} }
@Test @Test
@@ -785,57 +569,10 @@ public class ComponentsTest
BaseComponent[] reColored = TextComponent.fromLegacyText( legacy ); BaseComponent[] reColored = TextComponent.fromLegacyText( legacy );
assertArrayEquals( hexColored, reColored ); Assert.assertArrayEquals( hexColored, reColored );
} }
@Test private String fromAndToLegacyText(String legacyText)
public void testLegacyResetInBuilderCreate()
{
this.testLegacyResetInBuilder(
ComponentBuilder::create,
ComponentSerializer::toString
);
}
@Test
public void testLegacyResetInBuilderBuild()
{
this.testLegacyResetInBuilder(
ComponentBuilder::build,
ComponentSerializer::toString
);
}
/*
* 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)
{
ComponentBuilder builder = new ComponentBuilder();
BaseComponent[] a = TextComponent.fromLegacyText( "§4§n44444§rdd§6§l6666" );
String expected = "{\"extra\":[{\"underlined\":true,\"color\":\"dark_red\",\"text\":\"44444\"},{\"color\":"
+ "\"white\",\"text\":\"dd\"},{\"bold\":true,\"color\":\"gold\",\"text\":\"6666\"}],\"text\":\"\"}";
assertEquals( expected, ComponentSerializer.toString( a ) );
builder.append( a );
String test1 = componentSerializer.apply( componentBuilder.apply( builder ) );
assertEquals( expected, test1 );
BaseComponent[] b = TextComponent.fromLegacyText( "§rrrrr" );
builder.append( b );
String test2 = componentSerializer.apply( componentBuilder.apply( builder ) );
assertEquals(
"{\"extra\":[{\"underlined\":true,\"color\":\"dark_red\",\"text\":\"44444\"},"
+ "{\"color\":\"white\",\"text\":\"dd\"},{\"bold\":true,\"color\":\"gold\",\"text\":\"6666\"},"
+ "{\"color\":\"white\",\"text\":\"rrrr\"}],\"text\":\"\"}",
test2 );
}
private static String fromAndToLegacyText(String legacyText)
{ {
return BaseComponent.toLegacyText( TextComponent.fromLegacyText( legacyText ) ); return BaseComponent.toLegacyText( TextComponent.fromLegacyText( legacyText ) );
} }

View File

@@ -1,8 +1,8 @@
package net.md_5.bungee.api.chat; package net.md_5.bungee.api.chat;
import static org.junit.jupiter.api.Assertions.*;
import net.md_5.bungee.chat.ComponentSerializer; import net.md_5.bungee.chat.ComponentSerializer;
import org.junit.jupiter.api.Test; import org.junit.Assert;
import org.junit.Test;
public class TranslatableComponentTest public class TranslatableComponentTest
{ {
@@ -11,8 +11,8 @@ public class TranslatableComponentTest
public void testMissingPlaceholdersAdded() public void testMissingPlaceholdersAdded()
{ {
TranslatableComponent testComponent = new TranslatableComponent( "Test string with %s placeholders: %s", 2, "aoeu" ); TranslatableComponent testComponent = new TranslatableComponent( "Test string with %s placeholders: %s", 2, "aoeu" );
assertEquals( "Test string with 2 placeholders: aoeu", testComponent.toPlainText() ); Assert.assertEquals( "Test string with 2 placeholders: aoeu", testComponent.toPlainText() );
assertEquals( "§fTest string with §f2§f placeholders: §faoeu", testComponent.toLegacyText() ); Assert.assertEquals( "§fTest string with §f2§f placeholders: §faoeu", testComponent.toLegacyText() );
} }
@Test @Test
@@ -22,7 +22,7 @@ public class TranslatableComponentTest
String jsonString = ComponentSerializer.toString( testComponent ); String jsonString = ComponentSerializer.toString( testComponent );
BaseComponent[] baseComponents = ComponentSerializer.parse( jsonString ); BaseComponent[] baseComponents = ComponentSerializer.parse( jsonString );
assertEquals( "Test string with a placeholder", TextComponent.toPlainText( baseComponents ) ); Assert.assertEquals( "Test string with a placeholder", TextComponent.toPlainText( baseComponents ) );
assertEquals( "§fTest string with §fa§f placeholder", TextComponent.toLegacyText( baseComponents ) ); Assert.assertEquals( "§fTest string with §fa§f placeholder", TextComponent.toLegacyText( baseComponents ) );
} }
} }

View File

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

View File

@@ -4,14 +4,15 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>fr.pandacube.bungeecord</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.16-R0.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-config</artifactId> <artifactId>bungeecord-config</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.16-R0.4-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>BungeeCord-Config</name> <name>BungeeCord-Config</name>
@@ -21,14 +22,14 @@
<dependency> <dependency>
<groupId>com.google.code.gson</groupId> <groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId> <artifactId>gson</artifactId>
<version>2.10.1</version> <version>2.8.0</version>
<scope>compile</scope> <scope>compile</scope>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.yaml</groupId> <groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId> <artifactId>snakeyaml</artifactId>
<version>2.2</version> <version>1.26</version>
<scope>compile</scope> <scope>compile</scope>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>

View File

@@ -14,7 +14,6 @@ import java.util.Map;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor; import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.nodes.Node; import org.yaml.snakeyaml.nodes.Node;
@@ -30,10 +29,7 @@ public class YamlConfiguration extends ConfigurationProvider
@Override @Override
protected Yaml initialValue() protected Yaml initialValue()
{ {
DumperOptions options = new DumperOptions(); Representer representer = new Representer()
options.setDefaultFlowStyle( DumperOptions.FlowStyle.BLOCK );
Representer representer = new Representer( options )
{ {
{ {
representers.put( Configuration.class, new Represent() representers.put( Configuration.class, new Represent()
@@ -47,7 +43,10 @@ public class YamlConfiguration extends ConfigurationProvider
} }
}; };
return new Yaml( new Constructor( new LoaderOptions() ), representer, options ); DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle( DumperOptions.FlowStyle.BLOCK );
return new Yaml( new Constructor(), representer, options );
} }
}; };

View File

@@ -1,25 +1,30 @@
package net.md_5.bungee.config; package net.md_5.bungee.config;
import static org.junit.jupiter.api.Assertions.*;
import java.io.StringReader; import java.io.StringReader;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Stream;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.Assert;
import org.junit.jupiter.params.provider.Arguments; import org.junit.Test;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RequiredArgsConstructor @RequiredArgsConstructor
@RunWith(Parameterized.class)
public class CompoundConfigurationTest public class CompoundConfigurationTest
{ {
public static Stream<Arguments> data() @Parameters(name = "{0}")
public static Iterable<Object[]> data()
{
// CHECKSTYLE:OFF
return Arrays.asList( new Object[][]
{
{ {
return Stream.of(
Arguments.of(
// provider // provider
YamlConfiguration.class, YamlConfiguration.class,
// testDocument // testDocument
@@ -68,8 +73,8 @@ public class CompoundConfigurationTest
+ "null:\n" + "null:\n"
+ " null: object\n" + " null: object\n"
+ " object: null\n" + " object: null\n"
), },
Arguments.of( {
// provider // provider
JsonConfiguration.class, JsonConfiguration.class,
// testDocument // testDocument
@@ -126,13 +131,18 @@ public class CompoundConfigurationTest
+ " \"object\": null\n" + " \"object\": null\n"
+ " }\n" + " }\n"
+ "}" + "}"
)
);
} }
} );
// CHECKSTYLE:ON
}
//
private final Class<? extends ConfigurationProvider> provider;
private final String testDocument;
private final String numberTest;
private final String nullTest;
@ParameterizedTest @Test
@MethodSource("data") public void testConfig() throws Exception
public void testConfig(Class<? extends ConfigurationProvider> provider, String testDocument, String numberTest, String nullTest) throws Exception
{ {
Configuration conf = ConfigurationProvider.getProvider( provider ).load( testDocument ); Configuration conf = ConfigurationProvider.getProvider( provider ).load( testDocument );
testSection( conf ); testSection( conf );
@@ -141,7 +151,7 @@ public class CompoundConfigurationTest
ConfigurationProvider.getProvider( provider ).save( conf, sw ); ConfigurationProvider.getProvider( provider ).save( conf, sw );
// Check nulls were saved, see #1094 // Check nulls were saved, see #1094
assertFalse( sw.toString().contains( "null" ), "Config contains null" ); Assert.assertFalse( "Config contains null", sw.toString().contains( "null" ) );
conf = ConfigurationProvider.getProvider( provider ).load( new StringReader( sw.toString() ) ); conf = ConfigurationProvider.getProvider( provider ).load( new StringReader( sw.toString() ) );
conf.set( "receipt", "Oz-Ware Purchase Invoice" ); // Add it back conf.set( "receipt", "Oz-Ware Purchase Invoice" ); // Add it back
@@ -150,38 +160,37 @@ public class CompoundConfigurationTest
private void testSection(Configuration conf) private void testSection(Configuration conf)
{ {
assertEquals( "Oz-Ware Purchase Invoice", conf.getString( "receipt" ), "receipt" ); Assert.assertEquals( "receipt", "Oz-Ware Purchase Invoice", conf.getString( "receipt" ) );
// assertEquals( "2012-08-06", conf.get( "date" ).toString(), "date" ); // Assert.assertEquals( "date", "2012-08-06", conf.get( "date" ).toString() );
Configuration customer = conf.getSection( "customer" ); Configuration customer = conf.getSection( "customer" );
assertEquals( "Dorothy", customer.getString( "given" ), "customer.given" ); Assert.assertEquals( "customer.given", "Dorothy", customer.getString( "given" ) );
assertEquals( "Dorothy", conf.getString( "customer.given" ), "customer.given" ); Assert.assertEquals( "customer.given", "Dorothy", conf.getString( "customer.given" ) );
List items = conf.getList( "items" ); List items = conf.getList( "items" );
Map item = (Map) items.get( 0 ); Map item = (Map) items.get( 0 );
assertEquals( "A4786", item.get( "part_no" ), "items[0].part_no" ); Assert.assertEquals( "items[0].part_no", "A4786", item.get( "part_no" ) );
conf.set( "receipt", null ); conf.set( "receipt", null );
assertEquals( null, conf.get( "receipt" ) ); Assert.assertEquals( null, conf.get( "receipt" ) );
assertEquals( "foo", conf.get( "receipt", "foo" ) ); Assert.assertEquals( "foo", conf.get( "receipt", "foo" ) );
Configuration newSection = conf.getSection( "new.section" ); Configuration newSection = conf.getSection( "new.section" );
newSection.set( "value", "foo" ); newSection.set( "value", "foo" );
assertEquals( "foo", conf.get( "new.section.value" ) ); Assert.assertEquals( "foo", conf.get( "new.section.value" ) );
conf.set( "other.new.section", "bar" ); conf.set( "other.new.section", "bar" );
assertEquals( "bar", conf.get( "other.new.section" ) ); Assert.assertEquals( "bar", conf.get( "other.new.section" ) );
assertTrue( conf.contains( "customer.given" ) ); Assert.assertTrue( conf.contains( "customer.given" ) );
assertTrue( customer.contains( "given" ) ); Assert.assertTrue( customer.contains( "given" ) );
assertFalse( conf.contains( "customer.foo" ) ); Assert.assertFalse( conf.contains( "customer.foo" ) );
assertFalse( customer.contains( "foo" ) ); Assert.assertFalse( customer.contains( "foo" ) );
} }
@ParameterizedTest @Test
@MethodSource("data") public void testNumberedKeys()
public void testNumberedKeys(Class<? extends ConfigurationProvider> provider, String testDocument, String numberTest, String nullTest)
{ {
Configuration conf = ConfigurationProvider.getProvider( provider ).load( numberTest ); Configuration conf = ConfigurationProvider.getProvider( provider ).load( numberTest );
@@ -192,31 +201,29 @@ public class CompoundConfigurationTest
} }
} }
@ParameterizedTest @Test
@MethodSource("data") public void testNull()
public void testNull(Class<? extends ConfigurationProvider> provider, String testDocument, String numberTest, String nullTest)
{ {
Configuration conf = ConfigurationProvider.getProvider( provider ).load( nullTest ); Configuration conf = ConfigurationProvider.getProvider( provider ).load( nullTest );
assertEquals( "object", conf.get( "null.null" ) ); Assert.assertEquals( "object", conf.get( "null.null" ) );
assertEquals( "object", conf.getSection( "null" ).get( "null" ) ); Assert.assertEquals( "object", conf.getSection( "null" ).get( "null" ) );
assertEquals( null, conf.get( "null.object" ) ); Assert.assertEquals( null, conf.get( "null.object" ) );
assertEquals( "", conf.getString( "null.object" ) ); Assert.assertEquals( "", conf.getString( "null.object" ) );
} }
@ParameterizedTest @Test
@MethodSource("data") public void testMapAddition()
public void testMapAddition(Class<? extends ConfigurationProvider> provider, String testDocument, String numberTest, String nullTest)
{ {
Configuration conf = ConfigurationProvider.getProvider( provider ).load( testDocument ); Configuration conf = ConfigurationProvider.getProvider( provider ).load( testDocument );
conf.set( "addition", Collections.singletonMap( "foo", "bar" ) ); conf.set( "addition", Collections.singletonMap( "foo", "bar" ) );
// Order matters // Order matters
assertEquals( "bar", conf.getSection( "addition" ).getString( "foo" ) ); Assert.assertEquals( "bar", conf.getSection( "addition" ).getString( "foo" ) );
assertEquals( "bar", conf.getString( "addition.foo" ) ); Assert.assertEquals( "bar", conf.getString( "addition.foo" ) );
assertTrue( conf.get( "addition" ) instanceof Configuration ); Assert.assertTrue( conf.get( "addition" ) instanceof Configuration );
} }
} }

View File

@@ -1,7 +1,7 @@
package net.md_5.bungee.config; package net.md_5.bungee.config;
import static org.junit.jupiter.api.Assertions.*; import org.junit.Assert;
import org.junit.jupiter.api.Test; import org.junit.Test;
public class DefaultConfigurationTest public class DefaultConfigurationTest
{ {
@@ -16,8 +16,8 @@ public class DefaultConfigurationTest
Configuration actualConfig = new Configuration( defaultConfig ); Configuration actualConfig = new Configuration( defaultConfig );
assertEquals( 10, actualConfig.getInt( "setting" ) ); Assert.assertEquals( 10, actualConfig.getInt( "setting" ) );
assertEquals( 11, actualConfig.getInt( "nested.setting" ) ); Assert.assertEquals( 11, actualConfig.getInt( "nested.setting" ) );
assertEquals( 12, actualConfig.getInt( "double.nested.setting" ) ); Assert.assertEquals( 12, actualConfig.getInt( "double.nested.setting" ) );
} }
} }

View File

@@ -4,14 +4,15 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>fr.pandacube.bungeecord</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.16-R0.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-event</artifactId> <artifactId>bungeecord-event</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.16-R0.4-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>BungeeCord-Event</name> <name>BungeeCord-Event</name>

View File

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

View File

@@ -1,8 +1,8 @@
package net.md_5.bungee.event; package net.md_5.bungee.event;
import static org.junit.jupiter.api.Assertions.*;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import org.junit.jupiter.api.Test; import org.junit.Assert;
import org.junit.Test;
public class EventBusTest public class EventBusTest
{ {
@@ -15,14 +15,14 @@ public class EventBusTest
{ {
bus.register( this ); bus.register( this );
bus.post( new FirstEvent() ); bus.post( new FirstEvent() );
assertEquals( 0, latch.getCount() ); Assert.assertEquals( 0, latch.getCount() );
} }
@EventHandler @EventHandler
public void firstListener(FirstEvent event) public void firstListener(FirstEvent event)
{ {
bus.post( new SecondEvent() ); bus.post( new SecondEvent() );
assertEquals( 1, latch.getCount() ); Assert.assertEquals( 1, latch.getCount() );
latch.countDown(); latch.countDown();
} }

View File

@@ -1,8 +1,8 @@
package net.md_5.bungee.event; package net.md_5.bungee.event;
import static org.junit.jupiter.api.Assertions.*;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import org.junit.jupiter.api.Test; import org.junit.Assert;
import org.junit.Test;
public class EventPriorityTest public class EventPriorityTest
{ {
@@ -16,41 +16,41 @@ public class EventPriorityTest
bus.register( this ); bus.register( this );
bus.register( new EventPriorityListenerPartner() ); bus.register( new EventPriorityListenerPartner() );
bus.post( new PriorityTestEvent() ); bus.post( new PriorityTestEvent() );
assertEquals( 0, latch.getCount() ); Assert.assertEquals( 0, latch.getCount() );
} }
@EventHandler(priority = Byte.MIN_VALUE) @EventHandler(priority = Byte.MIN_VALUE)
public void onMinPriority(PriorityTestEvent event) public void onMinPriority(PriorityTestEvent event)
{ {
assertEquals( 7, latch.getCount() ); Assert.assertEquals( 7, latch.getCount() );
latch.countDown(); latch.countDown();
} }
@EventHandler(priority = EventPriority.LOWEST) @EventHandler(priority = EventPriority.LOWEST)
public void onLowestPriority(PriorityTestEvent event) public void onLowestPriority(PriorityTestEvent event)
{ {
assertEquals( 6, latch.getCount() ); Assert.assertEquals( 6, latch.getCount() );
latch.countDown(); latch.countDown();
} }
@EventHandler @EventHandler
public void onNormalPriority(PriorityTestEvent event) public void onNormalPriority(PriorityTestEvent event)
{ {
assertEquals( 4, latch.getCount() ); Assert.assertEquals( 4, latch.getCount() );
latch.countDown(); latch.countDown();
} }
@EventHandler(priority = EventPriority.HIGHEST) @EventHandler(priority = EventPriority.HIGHEST)
public void onHighestPriority(PriorityTestEvent event) public void onHighestPriority(PriorityTestEvent event)
{ {
assertEquals( 2, latch.getCount() ); Assert.assertEquals( 2, latch.getCount() );
latch.countDown(); latch.countDown();
} }
@EventHandler(priority = Byte.MAX_VALUE) @EventHandler(priority = Byte.MAX_VALUE)
public void onMaxPriority(PriorityTestEvent event) public void onMaxPriority(PriorityTestEvent event)
{ {
assertEquals( 1, latch.getCount() ); Assert.assertEquals( 1, latch.getCount() );
latch.countDown(); latch.countDown();
} }
@@ -64,14 +64,14 @@ public class EventPriorityTest
@EventHandler(priority = EventPriority.HIGH) @EventHandler(priority = EventPriority.HIGH)
public void onHighPriority(PriorityTestEvent event) public void onHighPriority(PriorityTestEvent event)
{ {
assertEquals( 3, latch.getCount() ); Assert.assertEquals( 3, latch.getCount() );
latch.countDown(); latch.countDown();
} }
@EventHandler(priority = EventPriority.LOW) @EventHandler(priority = EventPriority.LOW)
public void onLowPriority(PriorityTestEvent event) public void onLowPriority(PriorityTestEvent event)
{ {
assertEquals( 5, latch.getCount() ); Assert.assertEquals( 5, latch.getCount() );
latch.countDown(); latch.countDown();
} }
} }

View File

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

View File

@@ -1,7 +1,7 @@
package net.md_5.bungee.event; package net.md_5.bungee.event;
import static org.junit.jupiter.api.Assertions.fail; import org.junit.Assert;
import org.junit.jupiter.api.Test; import org.junit.Test;
public class UnregisteringListenerTest public class UnregisteringListenerTest
{ {
@@ -19,7 +19,7 @@ public class UnregisteringListenerTest
@EventHandler @EventHandler
public void onEvent(TestEvent evt) public void onEvent(TestEvent evt)
{ {
fail( "Event listener wasn't unregistered" ); Assert.fail( "Event listener wasn't unregistered" );
} }
public static class TestEvent public static class TestEvent

View File

@@ -4,14 +4,15 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>fr.pandacube.bungeecord</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.16-R0.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-log</artifactId> <artifactId>bungeecord-log</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.16-R0.4-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>BungeeCord-Log</name> <name>BungeeCord-Log</name>
@@ -25,7 +26,7 @@
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>fr.pandacube.bungeecord</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-chat</artifactId> <artifactId>bungeecord-chat</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>

View File

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

View File

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

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

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

View File

@@ -0,0 +1,46 @@
package net.md_5.bungee.module.cmd.alert;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.plugin.Command;
public class CommandAlert extends Command
{
public CommandAlert()
{
super( "alert", "bungeecord.command.alert" );
}
@Override
public void execute(CommandSender sender, String[] args)
{
if ( args.length == 0 )
{
sender.sendMessage( ProxyServer.getInstance().getTranslation( "message_needed" ) );
} else
{
StringBuilder builder = new StringBuilder();
if ( args[0].startsWith( "&h" ) )
{
// Remove &h
args[0] = args[0].substring( 2, args[0].length() );
} else
{
builder.append( ProxyServer.getInstance().getTranslation( "alert" ) );
}
for ( String s : args )
{
builder.append( ChatColor.translateAlternateColorCodes( '&', s ) );
builder.append( " " );
}
String message = builder.substring( 0, builder.length() - 1 );
ProxyServer.getInstance().broadcast( TextComponent.fromLegacyText( message ) );
}
}
}

View File

@@ -0,0 +1,56 @@
package net.md_5.bungee.module.cmd.alert;
import com.google.common.base.Joiner;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.chat.ComponentSerializer;
public class CommandAlertRaw extends Command
{
public CommandAlertRaw()
{
super( "alertraw", "bungeecord.command.alert" );
}
@Override
public void execute(CommandSender sender, String[] args)
{
if ( args.length == 0 )
{
sender.sendMessage( ProxyServer.getInstance().getTranslation( "message_needed" ) );
} else
{
String message = Joiner.on( ' ' ).join( args );
try
{
ProxyServer.getInstance().broadcast( ComponentSerializer.parse( message ) );
} catch ( Exception e )
{
Throwable error = e;
while ( error.getCause() != null )
{
error = error.getCause();
}
if ( sender instanceof ProxiedPlayer )
{
sender.sendMessage( new ComponentBuilder( ProxyServer.getInstance().getTranslation( "error_occurred_player" ) )
.event( new HoverEvent( HoverEvent.Action.SHOW_TEXT, new ComponentBuilder( error.getMessage() )
.color( ChatColor.RED )
.create() ) )
.create()
);
} else
{
sender.sendMessage( ProxyServer.getInstance().getTranslation( "error_occurred_console", error.getMessage() ) );
}
}
}
}
}

View File

@@ -0,0 +1,14 @@
package net.md_5.bungee.module.cmd.alert;
import net.md_5.bungee.api.plugin.Plugin;
public class PluginAlert extends Plugin
{
@Override
public void onEnable()
{
getProxy().getPluginManager().registerCommand( this, new CommandAlert() );
getProxy().getPluginManager().registerCommand( this, new CommandAlertRaw() );
}
}

View File

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

View File

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

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

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

View File

@@ -0,0 +1,34 @@
package net.md_5.bungee.module.cmd.find;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.command.PlayerCommand;
public class CommandFind extends PlayerCommand
{
public CommandFind()
{
super( "find", "bungeecord.command.find" );
}
@Override
public void execute(CommandSender sender, String[] args)
{
if ( args.length != 1 )
{
sender.sendMessage( ProxyServer.getInstance().getTranslation( "username_needed" ) );
} else
{
ProxiedPlayer player = ProxyServer.getInstance().getPlayer( args[0] );
if ( player == null || player.getServer() == null )
{
sender.sendMessage( ProxyServer.getInstance().getTranslation( "user_not_online" ) );
} else
{
sender.sendMessage( ProxyServer.getInstance().getTranslation( "user_online_at", player.getName(), player.getServer().getInfo().getName() ) );
}
}
}
}

View File

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

View File

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

View File

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

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

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

View File

@@ -0,0 +1,47 @@
package net.md_5.bungee.module.cmd.list;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import net.md_5.bungee.Util;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Command;
/**
* Command to list all players connected to the proxy.
*/
public class CommandList extends Command
{
public CommandList()
{
super( "glist", "bungeecord.command.list" );
}
@Override
public void execute(CommandSender sender, String[] args)
{
for ( ServerInfo server : ProxyServer.getInstance().getServers().values() )
{
if ( !server.canAccess( sender ) )
{
continue;
}
List<String> players = new ArrayList<>();
for ( ProxiedPlayer player : server.getPlayers() )
{
players.add( player.getDisplayName() );
}
Collections.sort( players, String.CASE_INSENSITIVE_ORDER );
sender.sendMessage( ProxyServer.getInstance().getTranslation( "command_list", server.getName(), server.getPlayers().size(), Util.format( players, ChatColor.RESET + ", " ) ) );
}
sender.sendMessage( ProxyServer.getInstance().getTranslation( "total_players", ProxyServer.getInstance().getOnlineCount() ) );
}
}

View File

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

View File

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

View File

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

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

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

View File

@@ -0,0 +1,200 @@
package net.md_5.bungee.module.cmd.send;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import net.md_5.bungee.api.Callback;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.ServerConnectRequest;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.ServerConnectEvent;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.api.plugin.TabExecutor;
public class CommandSend extends Command implements TabExecutor
{
protected static class SendCallback
{
private final Map<ServerConnectRequest.Result, List<String>> results = new HashMap<>();
private final CommandSender sender;
private int count = 0;
public SendCallback(CommandSender sender)
{
this.sender = sender;
for ( ServerConnectRequest.Result result : ServerConnectRequest.Result.values() )
{
results.put( result, new ArrayList<String>() );
}
}
public void lastEntryDone()
{
sender.sendMessage( ChatColor.GREEN.toString() + ChatColor.BOLD + "Send Results:" );
for ( Map.Entry<ServerConnectRequest.Result, List<String>> entry : results.entrySet() )
{
ComponentBuilder builder = new ComponentBuilder( "" );
if ( !entry.getValue().isEmpty() )
{
builder.event( new HoverEvent( HoverEvent.Action.SHOW_TEXT,
new ComponentBuilder( Joiner.on( ", " ).join( entry.getValue() ) ).color( ChatColor.YELLOW ).create() ) );
}
builder.append( entry.getKey().name() + ": " ).color( ChatColor.GREEN );
builder.append( "" + entry.getValue().size() ).bold( true );
sender.sendMessage( builder.create() );
}
}
public static class Entry implements Callback<ServerConnectRequest.Result>
{
private final SendCallback callback;
private final ProxiedPlayer player;
private final ServerInfo target;
public Entry(SendCallback callback, ProxiedPlayer player, ServerInfo target)
{
this.callback = callback;
this.player = player;
this.target = target;
this.callback.count++;
}
@Override
public void done(ServerConnectRequest.Result result, Throwable error)
{
callback.results.get( result ).add( player.getName() );
if ( result == ServerConnectRequest.Result.SUCCESS )
{
player.sendMessage( ProxyServer.getInstance().getTranslation( "you_got_summoned", target.getName(), callback.sender.getName() ) );
}
if ( --callback.count == 0 )
{
callback.lastEntryDone();
}
}
}
}
public CommandSend()
{
super( "send", "bungeecord.command.send" );
}
@Override
public void execute(CommandSender sender, String[] args)
{
if ( args.length != 2 )
{
sender.sendMessage( ProxyServer.getInstance().getTranslation( "send_cmd_usage" ) );
return;
}
ServerInfo server = ProxyServer.getInstance().getServerInfo( args[1] );
if ( server == null )
{
sender.sendMessage( ProxyServer.getInstance().getTranslation( "no_server" ) );
return;
}
List<ProxiedPlayer> targets;
if ( args[0].equalsIgnoreCase( "all" ) )
{
targets = new ArrayList<>( ProxyServer.getInstance().getPlayers() );
} else if ( args[0].equalsIgnoreCase( "current" ) )
{
if ( !( sender instanceof ProxiedPlayer ) )
{
sender.sendMessage( ProxyServer.getInstance().getTranslation( "player_only" ) );
return;
}
ProxiedPlayer player = (ProxiedPlayer) sender;
targets = new ArrayList<>( player.getServer().getInfo().getPlayers() );
} else
{
// If we use a server name, send the entire server. This takes priority over players.
ServerInfo serverTarget = ProxyServer.getInstance().getServerInfo( args[0] );
if ( serverTarget != null )
{
targets = new ArrayList<>( serverTarget.getPlayers() );
} else
{
ProxiedPlayer player = ProxyServer.getInstance().getPlayer( args[0] );
if ( player == null )
{
sender.sendMessage( ProxyServer.getInstance().getTranslation( "user_not_online" ) );
return;
}
targets = Collections.singletonList( player );
}
}
final SendCallback callback = new SendCallback( sender );
for ( ProxiedPlayer player : targets )
{
ServerConnectRequest request = ServerConnectRequest.builder()
.target( server )
.reason( ServerConnectEvent.Reason.COMMAND )
.callback( new SendCallback.Entry( callback, player, server ) )
.build();
player.connect( request );
}
sender.sendMessage( ChatColor.DARK_GREEN + "Attempting to send " + targets.size() + " players to " + server.getName() );
}
@Override
public Iterable<String> onTabComplete(CommandSender sender, String[] args)
{
if ( args.length > 2 || args.length == 0 )
{
return ImmutableSet.of();
}
Set<String> matches = new HashSet<>();
if ( args.length == 1 )
{
String search = args[0].toLowerCase( Locale.ROOT );
for ( ProxiedPlayer player : ProxyServer.getInstance().getPlayers() )
{
if ( player.getName().toLowerCase( Locale.ROOT ).startsWith( search ) )
{
matches.add( player.getName() );
}
}
if ( "all".startsWith( search ) )
{
matches.add( "all" );
}
if ( "current".startsWith( search ) )
{
matches.add( "current" );
}
} else
{
String search = args[1].toLowerCase( Locale.ROOT );
for ( String server : ProxyServer.getInstance().getServers().keySet() )
{
if ( server.toLowerCase( Locale.ROOT ).startsWith( search ) )
{
matches.add( server );
}
}
}
return matches;
}
}

View File

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

View File

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

View File

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

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

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

View File

@@ -0,0 +1,104 @@
package net.md_5.bungee.module.cmd.server;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import java.util.Collections;
import java.util.Locale;
import java.util.Map;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.ServerConnectEvent;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.api.plugin.TabExecutor;
/**
* Command to list and switch a player between available servers.
*/
public class CommandServer extends Command implements TabExecutor
{
public CommandServer()
{
super( "server", "bungeecord.command.server" );
}
@Override
public void execute(CommandSender sender, String[] args)
{
Map<String, ServerInfo> servers = ProxyServer.getInstance().getServers();
if ( args.length == 0 )
{
if ( sender instanceof ProxiedPlayer )
{
sender.sendMessage( ProxyServer.getInstance().getTranslation( "current_server", ( (ProxiedPlayer) sender ).getServer().getInfo().getName() ) );
}
ComponentBuilder serverList = new ComponentBuilder().appendLegacy( ProxyServer.getInstance().getTranslation( "server_list" ) );
boolean first = true;
for ( ServerInfo server : servers.values() )
{
if ( server.canAccess( sender ) )
{
TextComponent serverTextComponent = new TextComponent( first ? server.getName() : ", " + server.getName() );
int count = server.getPlayers().size();
serverTextComponent.setHoverEvent( new HoverEvent(
HoverEvent.Action.SHOW_TEXT,
new ComponentBuilder( count + ( count == 1 ? " player" : " players" ) + "\n" ).appendLegacy( ProxyServer.getInstance().getTranslation( "click_to_connect" ) ).create() )
);
serverTextComponent.setClickEvent( new ClickEvent( ClickEvent.Action.RUN_COMMAND, "/server " + server.getName() ) );
serverList.append( serverTextComponent );
first = false;
}
}
sender.sendMessage( serverList.create() );
} else
{
if ( !( sender instanceof ProxiedPlayer ) )
{
return;
}
ProxiedPlayer player = (ProxiedPlayer) sender;
ServerInfo server = servers.get( args[0] );
if ( server == null )
{
player.sendMessage( ProxyServer.getInstance().getTranslation( "no_server" ) );
} else if ( !server.canAccess( player ) )
{
player.sendMessage( ProxyServer.getInstance().getTranslation( "no_server_permission" ) );
} else
{
player.connect( server, ServerConnectEvent.Reason.COMMAND );
}
}
}
@Override
public Iterable<String> onTabComplete(final CommandSender sender, final String[] args)
{
return ( args.length > 1 ) ? Collections.EMPTY_LIST : Iterables.transform( Iterables.filter( ProxyServer.getInstance().getServers().values(), new Predicate<ServerInfo>()
{
private final String lower = ( args.length == 0 ) ? "" : args[0].toLowerCase( Locale.ROOT );
@Override
public boolean apply(ServerInfo input)
{
return input.getName().toLowerCase( Locale.ROOT ).startsWith( lower ) && input.canAccess( sender );
}
} ), new Function<ServerInfo, String>()
{
@Override
public String apply(ServerInfo input)
{
return input.getName();
}
} );
}
}

View File

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

View File

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

54
module/pom.xml Normal file
View File

@@ -0,0 +1,54 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<packaging>pom</packaging>
<name>BungeeCord Modules</name>
<description>Parent project for all BungeeCord modules.</description>
<modules>
<module>cmd-alert</module>
<module>cmd-find</module>
<module>cmd-list</module>
<module>cmd-send</module>
<module>cmd-server</module>
<module>reconnect-yaml</module>
</modules>
<properties>
<module.author>SpigotMC</module.author>
<maven.deploy.skip>true</maven.deploy.skip>
<maven.javadoc.skip>true</maven.javadoc.skip>
</properties>
<dependencies>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.name}</finalName>
<resources>
<resource>
<filtering>true</filtering>
<directory>${basedir}/src/main/resources</directory>
</resource>
</resources>
</build>
</project>

View File

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

View File

@@ -0,0 +1,20 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module-reconnect-yaml</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<packaging>jar</packaging>
<name>reconnect_yaml</name>
<description>Provides reconnect location functionality in locations.yml</description>
</project>

View File

@@ -0,0 +1,22 @@
package net.md_5.bungee.module.reconnect.yaml;
import net.md_5.bungee.api.config.ListenerInfo;
import net.md_5.bungee.api.plugin.Plugin;
public class PluginYaml extends Plugin
{
@Override
public void onEnable()
{
// TODO: Abstract this for other reconnect modules
for ( ListenerInfo info : getProxy().getConfig().getListeners() )
{
if ( !info.isForceDefault() && getProxy().getReconnectHandler() == null )
{
getProxy().setReconnectHandler( new YamlReconnectHandler() );
break;
}
}
}
}

View File

@@ -0,0 +1,115 @@
package net.md_5.bungee.module.reconnect.yaml;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.Level;
import net.md_5.bungee.api.AbstractReconnectHandler;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.util.CaseInsensitiveMap;
import org.yaml.snakeyaml.Yaml;
public class YamlReconnectHandler extends AbstractReconnectHandler
{
private final Yaml yaml = new Yaml();
private final File file = new File( "locations.yml" );
private final ReadWriteLock lock = new ReentrantReadWriteLock();
/*========================================================================*/
private CaseInsensitiveMap<String> data;
@SuppressWarnings("unchecked")
public YamlReconnectHandler()
{
try
{
file.createNewFile();
try ( FileReader rd = new FileReader( file ) )
{
Map map = yaml.loadAs( rd, Map.class );
if ( map != null )
{
data = new CaseInsensitiveMap<>( map );
}
}
} catch ( Exception ex )
{
file.renameTo( new File( "locations.yml.old" ) );
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Could not load reconnect locations, resetting them" );
}
if ( data == null )
{
data = new CaseInsensitiveMap<>();
}
}
@Override
protected ServerInfo getStoredServer(ProxiedPlayer player)
{
ServerInfo server = null;
lock.readLock().lock();
try
{
server = ProxyServer.getInstance().getServerInfo( data.get( key( player ) ) );
} finally
{
lock.readLock().unlock();
}
return server;
}
@Override
public void setServer(ProxiedPlayer player)
{
lock.writeLock().lock();
try
{
data.put( key( player ), ( player.getReconnectServer() != null ) ? player.getReconnectServer().getName() : player.getServer().getInfo().getName() );
} finally
{
lock.writeLock().unlock();
}
}
private String key(ProxiedPlayer player)
{
InetSocketAddress host = player.getPendingConnection().getVirtualHost();
return player.getName() + ";" + host.getHostString() + ":" + host.getPort();
}
@Override
public void save()
{
Map<String, String> copy = new HashMap<>();
lock.readLock().lock();
try
{
copy.putAll( data );
} finally
{
lock.readLock().unlock();
}
try ( FileWriter wr = new FileWriter( file ) )
{
yaml.dump( copy, wr );
} catch ( IOException ex )
{
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Could not save reconnect locations", ex );
}
}
@Override
public void close()
{
}
}

View File

@@ -0,0 +1,5 @@
name: ${project.name}
main: net.md_5.bungee.module.reconnect.yaml.PluginYaml
version: ${describe}
description: ${project.description}
author: ${module.author}

View File

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

Submodule native/mbedtls deleted from 8c89224991

View File

@@ -4,14 +4,15 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>fr.pandacube.bungeecord</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.16-R0.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-native</artifactId> <artifactId>bungeecord-native</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.16-R0.4-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>BungeeCord-Native</name> <name>BungeeCord-Native</name>
@@ -21,6 +22,7 @@
<dependency> <dependency>
<groupId>io.netty</groupId> <groupId>io.netty</groupId>
<artifactId>netty-transport</artifactId> <artifactId>netty-transport</artifactId>
<version>${netty.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -1,15 +1,12 @@
// Support for CentOS 6
__asm__(".symver memcpy,memcpy@GLIBC_2.2.5");
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <mbedtls/aes.h> #include <mbedtls/aes.h>
#include "net_md_5_bungee_jni_cipher_NativeCipherImpl.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; typedef unsigned char byte;
struct crypto_context { struct crypto_context {

View File

@@ -1,15 +1,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <zlib.h> #include <zlib.h>
#include "net_md_5_bungee_jni_zlib_NativeCompressImpl.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; typedef unsigned char byte;
static jfieldID consumedID; static jfieldID consumedID;

View File

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

View File

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

View File

@@ -1,6 +1,5 @@
package net.md_5.bungee; package net.md_5.bungee;
import static org.junit.jupiter.api.Assertions.*;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import java.util.Random; import java.util.Random;
@@ -10,11 +9,12 @@ import net.md_5.bungee.jni.NativeCode;
import net.md_5.bungee.jni.cipher.BungeeCipher; import net.md_5.bungee.jni.cipher.BungeeCipher;
import net.md_5.bungee.jni.cipher.JavaCipher; import net.md_5.bungee.jni.cipher.JavaCipher;
import net.md_5.bungee.jni.cipher.NativeCipher; import net.md_5.bungee.jni.cipher.NativeCipher;
import org.junit.jupiter.api.MethodOrderer; import org.junit.Assert;
import org.junit.jupiter.api.Test; import org.junit.FixMethodOrder;
import org.junit.jupiter.api.TestMethodOrder; import org.junit.Test;
import org.junit.runners.MethodSorters;
@TestMethodOrder(MethodOrderer.MethodName.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class NativeCipherTest public class NativeCipherTest
{ {
@@ -26,7 +26,7 @@ public class NativeCipherTest
private final SecretKey secret = new SecretKeySpec( new byte[ 16 ], "AES" ); private final SecretKey secret = new SecretKeySpec( new byte[ 16 ], "AES" );
private static final int BENCHMARK_COUNT = 4096; private static final int BENCHMARK_COUNT = 4096;
// //
private static final NativeCode<BungeeCipher> factory = new NativeCode<>( "native-cipher", JavaCipher::new, NativeCipher::new ); private static final NativeCode<BungeeCipher> factory = new NativeCode<>( "native-cipher", JavaCipher.class, NativeCipher.class );
@Test @Test
public void testNative() throws Exception public void testNative() throws Exception
@@ -34,7 +34,7 @@ public class NativeCipherTest
if ( NativeCode.isSupported() ) if ( NativeCode.isSupported() )
{ {
boolean loaded = factory.load(); boolean loaded = factory.load();
assertTrue( loaded, "Native cipher failed to load!" ); Assert.assertTrue( "Native cipher failed to load!", loaded );
NativeCipher cipher = new NativeCipher(); NativeCipher cipher = new NativeCipher();
System.out.println( "Testing native cipher..." ); System.out.println( "Testing native cipher..." );
@@ -48,7 +48,7 @@ public class NativeCipherTest
if ( NativeCode.isSupported() ) if ( NativeCode.isSupported() )
{ {
boolean loaded = factory.load(); boolean loaded = factory.load();
assertTrue( loaded, "Native cipher failed to load!" ); Assert.assertTrue( "Native cipher failed to load!", loaded );
NativeCipher cipher = new NativeCipher(); NativeCipher cipher = new NativeCipher();
@@ -98,7 +98,7 @@ public class NativeCipherTest
// Encrypt // Encrypt
cipher.init( true, secret ); cipher.init( true, secret );
cipher.cipher( nativePlain, out ); cipher.cipher( nativePlain, out );
assertEquals( nativeCiphered, out ); Assert.assertEquals( nativeCiphered, out );
out.clear(); out.clear();
@@ -106,7 +106,7 @@ public class NativeCipherTest
cipher.init( false, secret ); cipher.init( false, secret );
cipher.cipher( nativeCiphered, out ); cipher.cipher( nativeCiphered, out );
nativePlain.resetReaderIndex(); nativePlain.resetReaderIndex();
assertEquals( nativePlain, out ); Assert.assertEquals( nativePlain, out );
System.out.println( "This cipher works correctly!" ); System.out.println( "This cipher works correctly!" );
} }

View File

@@ -1,6 +1,5 @@
package net.md_5.bungee; package net.md_5.bungee;
import static org.junit.jupiter.api.Assertions.*;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import java.util.Arrays; import java.util.Arrays;
@@ -10,19 +9,20 @@ import net.md_5.bungee.jni.NativeCode;
import net.md_5.bungee.jni.zlib.BungeeZlib; import net.md_5.bungee.jni.zlib.BungeeZlib;
import net.md_5.bungee.jni.zlib.JavaZlib; import net.md_5.bungee.jni.zlib.JavaZlib;
import net.md_5.bungee.jni.zlib.NativeZlib; import net.md_5.bungee.jni.zlib.NativeZlib;
import org.junit.jupiter.api.Test; import org.junit.Assert;
import org.junit.Test;
public class NativeZlibTest public class NativeZlibTest
{ {
private final NativeCode<BungeeZlib> factory = new NativeCode<>( "native-compress", JavaZlib::new, NativeZlib::new ); private final NativeCode<BungeeZlib> factory = new NativeCode<>( "native-compress", JavaZlib.class, NativeZlib.class );
@Test @Test
public void doTest() throws DataFormatException public void doTest() throws DataFormatException
{ {
if ( NativeCode.isSupported() ) if ( NativeCode.isSupported() )
{ {
assertTrue( factory.load(), "Native code failed to load!" ); Assert.assertTrue( "Native code failed to load!", factory.load() );
test( factory.newInstance() ); test( factory.newInstance() );
} }
test( new JavaZlib() ); test( new JavaZlib() );
@@ -64,6 +64,6 @@ public class NativeZlibTest
long elapsed = System.currentTimeMillis() - start; long elapsed = System.currentTimeMillis() - start;
System.out.println( "Took: " + elapsed + "ms" ); System.out.println( "Took: " + elapsed + "ms" );
assertTrue( Arrays.equals( dataBuf, check ), "Results do not match" ); Assert.assertTrue( "Results do not match", Arrays.equals( dataBuf, check ) );
} }
} }

Submodule native/zlib deleted from 4e4e4c4fbd

139
pom.xml
View File

@@ -3,9 +3,9 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>fr.pandacube.bungeecord</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.16-R0.4-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>BungeeCord-Parent</name> <name>BungeeCord-Parent</name>
@@ -37,10 +37,10 @@
<module>config</module> <module>config</module>
<module>event</module> <module>event</module>
<module>log</module> <module>log</module>
<module>module</module>
<module>protocol</module> <module>protocol</module>
<module>proxy</module> <module>proxy</module>
<module>query</module> <module>query</module>
<module>slf4j</module>
<module>native</module> <module>native</module>
</modules> </modules>
@@ -71,34 +71,23 @@
<properties> <properties>
<build.number>unknown</build.number> <build.number>unknown</build.number>
<lombok.version>1.18.30</lombok.version> <netty.version>4.1.53.Final</netty.version>
<maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
<dependencyManagement>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>io.netty</groupId> <groupId>junit</groupId>
<artifactId>netty-bom</artifactId> <artifactId>junit</artifactId>
<version>4.1.97.Final</version> <version>4.13.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
<version>32.1.2-jre</version> <version>21.0</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
@@ -110,28 +99,19 @@
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>${lombok.version}</version> <version>1.18.10</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.0</version>
</plugin>
</plugins>
</pluginManagement>
<plugins> <plugins>
<plugin> <plugin>
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>scriptus</artifactId> <artifactId>scriptus</artifactId>
<version>0.5.0</version> <version>0.4.1</version>
<configuration> <configuration>
<format>git:${project.name}-Pandacube:${project.version}:%s:${build.number}</format> <format>git:${project.name}:${project.version}:%s:${build.number}</format>
</configuration> </configuration>
<executions> <executions>
<execution> <execution>
@@ -142,15 +122,10 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId> <artifactId>maven-checkstyle-plugin</artifactId>
<version>3.3.0</version> <version>3.1.1</version>
<executions> <executions>
<execution> <execution>
<phase>process-classes</phase> <phase>process-classes</phase>
@@ -168,14 +143,14 @@
<dependency> <dependency>
<groupId>com.puppycrawl.tools</groupId> <groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId> <artifactId>checkstyle</artifactId>
<version>8.45.1</version> <version>8.36.2</version>
</dependency> </dependency>
</dependencies> </dependencies>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.codehaus.mojo</groupId> <groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId> <artifactId>animal-sniffer-maven-plugin</artifactId>
<version>1.23</version> <version>1.19</version>
<executions> <executions>
<execution> <execution>
<phase>process-classes</phase> <phase>process-classes</phase>
@@ -192,82 +167,10 @@
</signature> </signature>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.4.1</version>
<executions>
<execution>
<id>enforce</id>
<configuration>
<rules>
<dependencyConvergence>
<excludes>
<!-- org.apache.maven:maven-resolver-provider is inconsistent -->
<exclude>org.apache.commons:commons-lang3</exclude>
<!-- org.apache.maven:maven-resolver-transport-http is inconsistent -->
<exclude>org.apache.httpcomponents:httpcore</exclude>
</excludes>
</dependencyConvergence>
</rules>
</configuration>
<goals>
<!--<goal>enforce</goal>--> <!-- Disabled until maven-resolver is upgraded again. -->
</goals>
</execution>
</executions>
</plugin>
</plugins> </plugins>
</build> </build>
<profiles> <profiles>
<profile>
<id>jdk-9-release</id>
<activation>
<jdk>[9,)</jdk>
</activation>
<properties>
<maven.compiler.release>8</maven.compiler.release>
</properties>
</profile>
<profile>
<id>jdk-9-javadoc</id>
<activation>
<jdk>[9,)</jdk>
</activation>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<additionalOptions>-html5</additionalOptions>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
<profile>
<id>jdk-15-javadoc</id>
<activation>
<jdk>[15,)</jdk>
</activation>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<doclint>none</doclint>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
<profile> <profile>
<id>dist</id> <id>dist</id>
<build> <build>
@@ -275,7 +178,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId> <artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version> <version>3.2.1</version>
<executions> <executions>
<execution> <execution>
<phase>package</phase> <phase>package</phase>
@@ -288,7 +191,7 @@
<plugin> <plugin>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId> <artifactId>lombok-maven-plugin</artifactId>
<version>1.18.20.0</version> <version>1.18.10.0</version>
<executions> <executions>
<execution> <execution>
<phase>package</phase> <phase>package</phase>
@@ -302,17 +205,11 @@
<outputDirectory>${project.build.directory}/delombok</outputDirectory> <outputDirectory>${project.build.directory}/delombok</outputDirectory>
<sourceDirectory>${project.build.sourceDirectory}</sourceDirectory> <sourceDirectory>${project.build.sourceDirectory}</sourceDirectory>
</configuration> </configuration>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<executions> <executions>
<!-- Execute Javadoc once normally to catch any warnings --> <!-- Execute Javadoc once normally to catch any warnings -->
<execution> <execution>
@@ -350,7 +247,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId> <artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version> <version>1.6</version>
<executions> <executions>
<execution> <execution>
<phase>verify</phase> <phase>verify</phase>

View File

@@ -4,14 +4,15 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>fr.pandacube.bungeecord</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.16-R0.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-protocol</artifactId> <artifactId>bungeecord-protocol</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.16-R0.4-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>BungeeCord-Protocol</name> <name>BungeeCord-Protocol</name>
@@ -40,7 +41,7 @@
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>fr.pandacube.bungeecord</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-chat</artifactId> <artifactId>bungeecord-chat</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>
@@ -48,6 +49,7 @@
<dependency> <dependency>
<groupId>io.netty</groupId> <groupId>io.netty</groupId>
<artifactId>netty-codec</artifactId> <artifactId>netty-codec</artifactId>
<version>${netty.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>

View File

@@ -2,16 +2,12 @@ package net.md_5.bungee.protocol;
import net.md_5.bungee.protocol.packet.BossBar; import net.md_5.bungee.protocol.packet.BossBar;
import net.md_5.bungee.protocol.packet.Chat; import net.md_5.bungee.protocol.packet.Chat;
import net.md_5.bungee.protocol.packet.ClearTitles;
import net.md_5.bungee.protocol.packet.ClientChat;
import net.md_5.bungee.protocol.packet.ClientCommand;
import net.md_5.bungee.protocol.packet.ClientSettings; import net.md_5.bungee.protocol.packet.ClientSettings;
import net.md_5.bungee.protocol.packet.ClientStatus; import net.md_5.bungee.protocol.packet.ClientStatus;
import net.md_5.bungee.protocol.packet.Commands; import net.md_5.bungee.protocol.packet.Commands;
import net.md_5.bungee.protocol.packet.EncryptionRequest; import net.md_5.bungee.protocol.packet.EncryptionRequest;
import net.md_5.bungee.protocol.packet.EncryptionResponse; import net.md_5.bungee.protocol.packet.EncryptionResponse;
import net.md_5.bungee.protocol.packet.EntityStatus; import net.md_5.bungee.protocol.packet.EntityStatus;
import net.md_5.bungee.protocol.packet.FinishConfiguration;
import net.md_5.bungee.protocol.packet.GameState; import net.md_5.bungee.protocol.packet.GameState;
import net.md_5.bungee.protocol.packet.Handshake; import net.md_5.bungee.protocol.packet.Handshake;
import net.md_5.bungee.protocol.packet.KeepAlive; import net.md_5.bungee.protocol.packet.KeepAlive;
@@ -19,7 +15,6 @@ import net.md_5.bungee.protocol.packet.Kick;
import net.md_5.bungee.protocol.packet.LegacyHandshake; import net.md_5.bungee.protocol.packet.LegacyHandshake;
import net.md_5.bungee.protocol.packet.LegacyPing; import net.md_5.bungee.protocol.packet.LegacyPing;
import net.md_5.bungee.protocol.packet.Login; import net.md_5.bungee.protocol.packet.Login;
import net.md_5.bungee.protocol.packet.LoginAcknowledged;
import net.md_5.bungee.protocol.packet.LoginPayloadRequest; import net.md_5.bungee.protocol.packet.LoginPayloadRequest;
import net.md_5.bungee.protocol.packet.LoginPayloadResponse; import net.md_5.bungee.protocol.packet.LoginPayloadResponse;
import net.md_5.bungee.protocol.packet.LoginRequest; import net.md_5.bungee.protocol.packet.LoginRequest;
@@ -27,25 +22,18 @@ import net.md_5.bungee.protocol.packet.LoginSuccess;
import net.md_5.bungee.protocol.packet.PingPacket; import net.md_5.bungee.protocol.packet.PingPacket;
import net.md_5.bungee.protocol.packet.PlayerListHeaderFooter; import net.md_5.bungee.protocol.packet.PlayerListHeaderFooter;
import net.md_5.bungee.protocol.packet.PlayerListItem; import net.md_5.bungee.protocol.packet.PlayerListItem;
import net.md_5.bungee.protocol.packet.PlayerListItemRemove;
import net.md_5.bungee.protocol.packet.PlayerListItemUpdate;
import net.md_5.bungee.protocol.packet.PluginMessage; import net.md_5.bungee.protocol.packet.PluginMessage;
import net.md_5.bungee.protocol.packet.Respawn; import net.md_5.bungee.protocol.packet.Respawn;
import net.md_5.bungee.protocol.packet.ScoreboardDisplay; import net.md_5.bungee.protocol.packet.ScoreboardDisplay;
import net.md_5.bungee.protocol.packet.ScoreboardObjective; import net.md_5.bungee.protocol.packet.ScoreboardObjective;
import net.md_5.bungee.protocol.packet.ScoreboardScore; import net.md_5.bungee.protocol.packet.ScoreboardScore;
import net.md_5.bungee.protocol.packet.ServerData;
import net.md_5.bungee.protocol.packet.SetCompression; import net.md_5.bungee.protocol.packet.SetCompression;
import net.md_5.bungee.protocol.packet.StartConfiguration;
import net.md_5.bungee.protocol.packet.StatusRequest; import net.md_5.bungee.protocol.packet.StatusRequest;
import net.md_5.bungee.protocol.packet.StatusResponse; import net.md_5.bungee.protocol.packet.StatusResponse;
import net.md_5.bungee.protocol.packet.Subtitle;
import net.md_5.bungee.protocol.packet.SystemChat;
import net.md_5.bungee.protocol.packet.TabCompleteRequest; import net.md_5.bungee.protocol.packet.TabCompleteRequest;
import net.md_5.bungee.protocol.packet.TabCompleteResponse; import net.md_5.bungee.protocol.packet.TabCompleteResponse;
import net.md_5.bungee.protocol.packet.Team; import net.md_5.bungee.protocol.packet.Team;
import net.md_5.bungee.protocol.packet.Title; import net.md_5.bungee.protocol.packet.Title;
import net.md_5.bungee.protocol.packet.TitleTimes;
import net.md_5.bungee.protocol.packet.ViewDistance; import net.md_5.bungee.protocol.packet.ViewDistance;
public abstract class AbstractPacketHandler public abstract class AbstractPacketHandler
@@ -87,18 +75,6 @@ public abstract class AbstractPacketHandler
{ {
} }
public void handle(ClientChat chat) throws Exception
{
}
public void handle(SystemChat chat) throws Exception
{
}
public void handle(ClientCommand command) throws Exception
{
}
public void handle(Respawn respawn) throws Exception public void handle(Respawn respawn) throws Exception
{ {
} }
@@ -119,14 +95,6 @@ public abstract class AbstractPacketHandler
{ {
} }
public void handle(PlayerListItemRemove playerListItem) throws Exception
{
}
public void handle(PlayerListItemUpdate playerListItem) throws Exception
{
}
public void handle(PlayerListHeaderFooter playerListHeaderFooter) throws Exception public void handle(PlayerListHeaderFooter playerListHeaderFooter) throws Exception
{ {
} }
@@ -159,18 +127,6 @@ public abstract class AbstractPacketHandler
{ {
} }
public void handle(Subtitle title) throws Exception
{
}
public void handle(TitleTimes title) throws Exception
{
}
public void handle(ClearTitles title) throws Exception
{
}
public void handle(PluginMessage pluginMessage) throws Exception public void handle(PluginMessage pluginMessage) throws Exception
{ {
} }
@@ -222,20 +178,4 @@ public abstract class AbstractPacketHandler
public void handle(GameState gameState) throws Exception public void handle(GameState gameState) throws Exception
{ {
} }
public void handle(ServerData serverData) throws Exception
{
}
public void handle(LoginAcknowledged loginAcknowledged) throws Exception
{
}
public void handle(StartConfiguration startConfiguration) throws Exception
{
}
public void handle(FinishConfiguration finishConfiguration) throws Exception
{
}
} }

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