Compare commits
33 Commits
0106df2fba
...
ba212a8a61
Author | SHA1 | Date | |
---|---|---|---|
ba212a8a61 | |||
bf44147805 | |||
e47394e10d | |||
3ba71310b8 | |||
fe2baa08b5 | |||
fb1c808d0e | |||
|
5a1e342e0d | ||
|
d9bbdc3281 | ||
|
cfe00fa47c | ||
|
d68ebd1eaf | ||
|
a7cd79eb41 | ||
|
9e83ee6f0c | ||
|
7c81d91740 | ||
|
5b126b7f4d | ||
|
9fe7d21f4b | ||
|
94ea0271ba | ||
|
3af672d2f2 | ||
|
0dd7b98428 | ||
|
a793692a2c | ||
|
23fb838227 | ||
|
2d6d89d668 | ||
|
0199cb90ff | ||
|
958cef5084 | ||
|
9f5ace9025 | ||
|
3a6e2631bf | ||
|
c7adcf9fdf | ||
|
da3616e636 | ||
|
b371fe67a5 | ||
|
6324c7d527 | ||
|
6263fe283b | ||
|
9a7617f9b8 | ||
|
9a71358dfa | ||
|
a96a2e80a1 |
3
.github/dependabot.yml
vendored
3
.github/dependabot.yml
vendored
@ -13,9 +13,10 @@ updates:
|
||||
- dependency-name: "com.puppycrawl.tools:checkstyle"
|
||||
# Newer versions have issues, see #1909 and #2050
|
||||
- dependency-name: "jline:jline"
|
||||
# Needs to be synchronised with maven-resolver-provider dependencies
|
||||
# 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"]
|
||||
|
4
.github/workflows/maven.yml
vendored
4
.github/workflows/maven.yml
vendored
@ -9,12 +9,12 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
java: [8, 11, 17]
|
||||
java: [8, 11, 17, 21]
|
||||
|
||||
name: Java ${{ matrix.java }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: zulu
|
||||
|
23
api/pom.xml
23
api/pom.xml
@ -4,15 +4,14 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-api</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-API</name>
|
||||
@ -20,25 +19,25 @@
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-chat</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-config</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-event</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-protocol</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
@ -51,28 +50,28 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-resolver-provider</artifactId>
|
||||
<version>3.9.2</version>
|
||||
<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.9.10</version>
|
||||
<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.9.10</version>
|
||||
<version>1.7.3</version>
|
||||
<!-- not part of the API proper -->
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>2.0</version>
|
||||
<version>2.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
@ -0,0 +1,157 @@
|
||||
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.<CommandSender>literal( "server" )
|
||||
* .requires( sender -> sender.hasPermission( "bungeecord.command.server" ) )
|
||||
* .executes( a -> 0 )
|
||||
* .then( RequiredArgumentBuilder.argument( "serverName", StringArgumentType.greedyString() )
|
||||
* .suggests( SuggestionRegistry.ASK_SERVER )
|
||||
* )
|
||||
* .build()
|
||||
* );
|
||||
* event.getRoot().addChild( LiteralArgumentBuilder.<CommandSender>literal( "send" )
|
||||
* .requires( sender -> 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
|
||||
* Minecraft’s recipes.
|
||||
* </li>
|
||||
* <li>
|
||||
* {@code builder.suggests(SuggestionRegistry.AVAILABLE_SOUNDS)} to
|
||||
* suggest Minecraft’s default sound identifiers.
|
||||
* </li>
|
||||
* <li>
|
||||
* {@code builder.suggests(SuggestionRegistry.SUMMONABLE_ENTITIES)} to
|
||||
* suggest Minecraft’s 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;
|
||||
}
|
||||
}
|
@ -9,7 +9,9 @@ import net.md_5.bungee.api.plugin.Cancellable;
|
||||
|
||||
/**
|
||||
* Event called when a player uses tab completion.
|
||||
* @deprecated please use {@link TabCompleteRequestEvent} to support 1.13+ suggestions.
|
||||
*/
|
||||
@Deprecated
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
|
@ -0,0 +1,85 @@
|
||||
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;
|
||||
}
|
||||
}
|
@ -4,15 +4,14 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-bootstrap</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-Bootstrap</name>
|
||||
@ -21,14 +20,12 @@
|
||||
<properties>
|
||||
<maven.deploy.skip>true</maven.deploy.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>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-proxy</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
@ -55,7 +52,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.4.1</version>
|
||||
<version>3.5.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
|
@ -4,15 +4,14 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-chat</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-Chat</name>
|
||||
@ -22,7 +21,7 @@
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.10</version>
|
||||
<version>2.10.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
@ -454,9 +454,32 @@ public final class ComponentBuilder
|
||||
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
|
||||
* 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
|
||||
*/
|
||||
|
@ -23,6 +23,12 @@ public class Text extends Content
|
||||
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)
|
||||
{
|
||||
this.value = value;
|
||||
|
@ -27,7 +27,6 @@ import net.md_5.bungee.api.chat.hover.content.TextSerializer;
|
||||
public class ComponentSerializer implements JsonDeserializer<BaseComponent>
|
||||
{
|
||||
|
||||
private static final JsonParser JSON_PARSER = new JsonParser();
|
||||
private static final Gson gson = new GsonBuilder().
|
||||
registerTypeAdapter( BaseComponent.class, new ComponentSerializer() ).
|
||||
registerTypeAdapter( TextComponent.class, new TextComponentSerializer() ).
|
||||
@ -43,9 +42,25 @@ public class ComponentSerializer implements JsonDeserializer<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)
|
||||
{
|
||||
JsonElement jsonElement = JSON_PARSER.parse( json );
|
||||
JsonElement jsonElement = JsonParser.parseString( json );
|
||||
|
||||
if ( jsonElement.isJsonArray() )
|
||||
{
|
||||
@ -59,6 +74,26 @@ 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)
|
||||
{
|
||||
return gson.toJson( object );
|
||||
|
@ -1,6 +1,11 @@
|
||||
package net.md_5.bungee.api.chat;
|
||||
|
||||
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.chat.hover.content.Item;
|
||||
import net.md_5.bungee.api.chat.hover.content.Text;
|
||||
@ -18,11 +23,25 @@ public class ComponentsTest
|
||||
Assert.assertEquals( TextComponent.toLegacyText( parsed ), TextComponent.toLegacyText( components ) );
|
||||
}
|
||||
|
||||
public static void testDissembleReassemble(String json)
|
||||
public static void testDissembleReassemble(BaseComponent component)
|
||||
{
|
||||
String json = ComponentSerializer.toString( component );
|
||||
BaseComponent[] parsed = ComponentSerializer.parse( json );
|
||||
Assert.assertEquals( TextComponent.toLegacyText( parsed ), TextComponent.toLegacyText( component ) );
|
||||
}
|
||||
|
||||
public static void testAssembleDissemble(String json, boolean modern)
|
||||
{
|
||||
if ( modern )
|
||||
{
|
||||
BaseComponent deserialized = ComponentSerializer.deserialize( json );
|
||||
Assert.assertEquals( json, ComponentSerializer.toString( deserialized ) );
|
||||
} else
|
||||
{
|
||||
BaseComponent[] parsed = ComponentSerializer.parse( json );
|
||||
Assert.assertEquals( json, ComponentSerializer.toString( parsed ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testItemParse()
|
||||
@ -41,8 +60,10 @@ public class ComponentsTest
|
||||
{
|
||||
textComponent
|
||||
} );
|
||||
testDissembleReassemble( textComponent );
|
||||
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}\"}";
|
||||
json = "{\"extra\":[{\"text\":\"[\"},{\"extra\":[{\"translate\":\"block.minecraft.dirt\"}],\"text\":\"\"},{\"text\":\"]\"}],\"hoverEvent\":{\"action\":\"show_item\",\"value\":[" + hoverVal + "]},\"text\":\"\"}";
|
||||
@ -66,18 +87,37 @@ public class ComponentsTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyComponentBuilder()
|
||||
public void testEmptyComponentBuilderCreate()
|
||||
{
|
||||
this.testEmptyComponentBuilder(
|
||||
ComponentBuilder::create,
|
||||
(components) -> Assert.assertEquals( components.length, 0 ),
|
||||
(components, size) -> Assert.assertEquals( size, components.length )
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyComponentBuilderBuild()
|
||||
{
|
||||
this.testEmptyComponentBuilder(
|
||||
ComponentBuilder::build,
|
||||
(component) -> Assert.assertNull( component.getExtra() ),
|
||||
(component, size) -> Assert.assertEquals( component.getExtra().size(), size )
|
||||
);
|
||||
}
|
||||
|
||||
private <T> void testEmptyComponentBuilder(Function<ComponentBuilder, T> componentBuilder, Consumer<T> emptyAssertion, ObjIntConsumer<T> sizedAssertion)
|
||||
{
|
||||
ComponentBuilder builder = new ComponentBuilder();
|
||||
|
||||
BaseComponent[] parts = builder.create();
|
||||
Assert.assertEquals( parts.length, 0 );
|
||||
T component = componentBuilder.apply( builder );
|
||||
emptyAssertion.accept( component );
|
||||
|
||||
for ( int i = 0; i < 3; i++ )
|
||||
{
|
||||
builder.append( "part:" + i );
|
||||
parts = builder.create();
|
||||
Assert.assertEquals( parts.length, i + 1 );
|
||||
component = componentBuilder.apply( builder );
|
||||
sizedAssertion.accept( component, i + 1 );
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,7 +253,7 @@ public class ComponentsTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHoverEventContents()
|
||||
public void testHoverEventContentsCreate()
|
||||
{
|
||||
// First do the text using the newer contents system
|
||||
HoverEvent hoverEvent = new HoverEvent(
|
||||
@ -222,21 +262,53 @@ public class ComponentsTest
|
||||
new Text( new ComponentBuilder( "Second" ).create() )
|
||||
);
|
||||
|
||||
this.testHoverEventContents(
|
||||
hoverEvent,
|
||||
ComponentSerializer::parse,
|
||||
(components) -> components[0].getHoverEvent(),
|
||||
ComponentsTest::testDissembleReassemble // BaseComponent
|
||||
);
|
||||
|
||||
// check the test still works with the value method
|
||||
hoverEvent = new HoverEvent( HoverEvent.Action.SHOW_TEXT, new ComponentBuilder( "Sample text" ).create() );
|
||||
TextComponent component = new TextComponent( "Sample text" );
|
||||
component.setHoverEvent( hoverEvent );
|
||||
|
||||
Assert.assertEquals( hoverEvent.getContents().size(), 1 );
|
||||
Assert.assertTrue( hoverEvent.isLegacy() );
|
||||
String serialized = ComponentSerializer.toString( component );
|
||||
BaseComponent[] deserialized = ComponentSerializer.parse( serialized );
|
||||
Assert.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 );
|
||||
Assert.assertEquals( hoverEvent.getContents().size(), 2 );
|
||||
Assert.assertFalse( hoverEvent.isLegacy() );
|
||||
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
|
||||
hoverEvent = new HoverEvent( HoverEvent.Action.SHOW_TEXT, new ComponentBuilder( "Sample text" ).create() );
|
||||
Assert.assertEquals( hoverEvent.getContents().size(), 1 );
|
||||
Assert.assertTrue( hoverEvent.isLegacy() );
|
||||
serialized = ComponentSerializer.toString( component );
|
||||
deserialized = ComponentSerializer.parse( serialized );
|
||||
Assert.assertEquals( component.getHoverEvent(), deserialized[0].getHoverEvent() );
|
||||
String serialized = ComponentSerializer.toString( component );
|
||||
T deserialized = deserializer.apply( serialized );
|
||||
Assert.assertEquals( component.getHoverEvent(), hoverEventGetter.apply( deserialized ) );
|
||||
|
||||
// Test single content:
|
||||
String json = "{\"italic\":true,\"color\":\"gray\",\"translate\":\"chat.type.admin\",\"with\":[{\"text\":\"@\"}"
|
||||
@ -248,17 +320,28 @@ public class ComponentsTest
|
||||
+ "\"/tell Name \"},\"hoverEvent\":{\"action\":\"show_entity\",\"contents\":"
|
||||
+ "{\"type\":\"minecraft:player\",\"id\":\"00000000-0000-0000-0000-00000000000000\",\"name\":"
|
||||
+ "{\"text\":\"Name\"}}},\"text\":\"Name\"}]}]}";
|
||||
testDissembleReassemble( ComponentSerializer.parse( json ) );
|
||||
dissembleReassembleTest.accept( deserializer.apply( json ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFormatRetentionCopyFormatting()
|
||||
public void testFormatRetentionCopyFormattingCreate()
|
||||
{
|
||||
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" );
|
||||
first.setBold( true );
|
||||
first.setColor( ChatColor.RED );
|
||||
first.setClickEvent( new ClickEvent( ClickEvent.Action.RUN_COMMAND, "test" ) );
|
||||
first.setHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, new ComponentBuilder( "Test" ).create() ) );
|
||||
first.setHoverEvent( hoverEventSupplier.get() );
|
||||
|
||||
TextComponent second = new TextComponent( " world" );
|
||||
second.copyFormatting( first, ComponentBuilder.FormatRetention.ALL, true );
|
||||
@ -269,16 +352,44 @@ public class ComponentsTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuilderClone()
|
||||
public void testBuilderCloneCreate()
|
||||
{
|
||||
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 cloned = new ComponentBuilder( builder );
|
||||
|
||||
Assert.assertEquals( TextComponent.toLegacyText( builder.create() ), TextComponent.toLegacyText( cloned.create() ) );
|
||||
Assert.assertEquals( legacyTextFunction.apply( builder ), legacyTextFunction.apply( cloned ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuilderAppendMixedComponents()
|
||||
public void testBuilderAppendCreateMixedComponents()
|
||||
{
|
||||
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 " );
|
||||
TextComponent textComponent = new TextComponent( "world " );
|
||||
@ -291,11 +402,11 @@ public class ComponentsTest
|
||||
} );
|
||||
ScoreComponent scoreComponent = new ScoreComponent( "myscore", "myobjective" );
|
||||
builder.append( scoreComponent ); // non array based BaseComponent append
|
||||
BaseComponent[] components = builder.create();
|
||||
Assert.assertEquals( "Hello ", components[0].toPlainText() );
|
||||
Assert.assertEquals( textComponent.toPlainText(), components[1].toPlainText() );
|
||||
Assert.assertEquals( translatableComponent.toPlainText(), components[2].toPlainText() );
|
||||
Assert.assertEquals( scoreComponent.toPlainText(), components[3].toPlainText() );
|
||||
T component = componentBuilder.apply( builder );
|
||||
Assert.assertEquals( "Hello ", extraGetter.apply( component, 0 ).toPlainText() );
|
||||
Assert.assertEquals( textComponent.toPlainText(), extraGetter.apply( component, 1 ).toPlainText() );
|
||||
Assert.assertEquals( translatableComponent.toPlainText(), extraGetter.apply( component, 2 ).toPlainText() );
|
||||
Assert.assertEquals( scoreComponent.toPlainText(), extraGetter.apply( component, 3 ).toPlainText() );
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -309,32 +420,80 @@ public class ComponentsTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuilderAppend()
|
||||
public void testBuilderAppendCreate()
|
||||
{
|
||||
ClickEvent clickEvent = new ClickEvent( ClickEvent.Action.RUN_COMMAND, "/help " );
|
||||
HoverEvent hoverEvent = new HoverEvent( HoverEvent.Action.SHOW_TEXT, new ComponentBuilder( "Hello world" ).create() );
|
||||
|
||||
ComponentBuilder builder = new ComponentBuilder( "Hello " ).color( ChatColor.YELLOW );
|
||||
builder.append( new ComponentBuilder( "world!" ).color( ChatColor.GREEN ).event( hoverEvent ).event( clickEvent ).create() );
|
||||
|
||||
BaseComponent[] components = builder.create();
|
||||
|
||||
Assert.assertEquals( components[1].getHoverEvent(), hoverEvent );
|
||||
Assert.assertEquals( components[1].getClickEvent(), clickEvent );
|
||||
Assert.assertEquals( "Hello world!", BaseComponent.toPlainText( components ) );
|
||||
Assert.assertEquals( ChatColor.YELLOW + "Hello " + ChatColor.GREEN + "world!", BaseComponent.toLegacyText( components ) );
|
||||
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 testBuilderAppendLegacy()
|
||||
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 " );
|
||||
HoverEvent hoverEvent = hoverEventSupplier.get();
|
||||
|
||||
ComponentBuilder builder = new ComponentBuilder( "Hello " ).color( ChatColor.YELLOW );
|
||||
builder.append( new ComponentBuilder( "world!" ).color( ChatColor.GREEN ).event( hoverEvent ).event( clickEvent ).create() ); // Intentionally using create() to append multiple individual components
|
||||
|
||||
T component = componentBuilder.apply( builder );
|
||||
|
||||
Assert.assertEquals( extraGetter.apply( component, 1 ).getHoverEvent(), hoverEvent );
|
||||
Assert.assertEquals( extraGetter.apply( component, 1 ).getClickEvent(), clickEvent );
|
||||
Assert.assertEquals( "Hello world!", toPlainTextFunction.apply( component ) );
|
||||
Assert.assertEquals( expectedLegacyText, toLegacyTextFunction.apply( component ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuilderAppendLegacyCreate()
|
||||
{
|
||||
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 );
|
||||
builder.appendLegacy( "§aworld!" );
|
||||
|
||||
BaseComponent[] components = builder.create();
|
||||
T component = componentBuilder.apply( builder );
|
||||
|
||||
Assert.assertEquals( "Hello world!", BaseComponent.toPlainText( components ) );
|
||||
Assert.assertEquals( ChatColor.YELLOW + "Hello " + ChatColor.GREEN + "world!", BaseComponent.toLegacyText( components ) );
|
||||
Assert.assertEquals( "Hello world!", toPlainTextFunction.apply( component ) );
|
||||
Assert.assertEquals( expectedLegacyString, toLegacyTextFunction.apply( component ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -397,57 +556,114 @@ public class ComponentsTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuilder()
|
||||
public void testBuilderCreate()
|
||||
{
|
||||
BaseComponent[] components = new ComponentBuilder( "Hello " ).color( ChatColor.RED ).
|
||||
this.testBuilder(
|
||||
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( "!" ).color( ChatColor.YELLOW ).create();
|
||||
append( "!" ).color( ChatColor.YELLOW ) );
|
||||
|
||||
Assert.assertEquals( "Hello World!", BaseComponent.toPlainText( components ) );
|
||||
Assert.assertEquals( ChatColor.RED + "Hello " + ChatColor.BLUE + ChatColor.BOLD
|
||||
+ "World" + ChatColor.YELLOW + ChatColor.BOLD + "!", BaseComponent.toLegacyText( components ) );
|
||||
Assert.assertEquals( "Hello World!", toPlainTextFunction.apply( component ) );
|
||||
Assert.assertEquals( expectedLegacyString, toLegacyTextFunction.apply( component ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuilderReset()
|
||||
public void testBuilderCreateReset()
|
||||
{
|
||||
BaseComponent[] components = new ComponentBuilder( "Hello " ).color( ChatColor.RED )
|
||||
.append( "World" ).reset().create();
|
||||
|
||||
Assert.assertEquals( components[0].getColor(), ChatColor.RED );
|
||||
Assert.assertEquals( components[1].getColor(), ChatColor.WHITE );
|
||||
this.testBuilderReset(
|
||||
ComponentBuilder::create,
|
||||
(components, index) -> components[index]
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuilderFormatRetention()
|
||||
public void testBuilderBuildReset()
|
||||
{
|
||||
BaseComponent[] noneRetention = new ComponentBuilder( "Hello " ).color( ChatColor.RED )
|
||||
.append( "World", ComponentBuilder.FormatRetention.NONE ).create();
|
||||
this.testBuilderReset(
|
||||
ComponentBuilder::build,
|
||||
(component, index) -> component.getExtra().get( index )
|
||||
);
|
||||
}
|
||||
|
||||
Assert.assertEquals( noneRetention[0].getColor(), ChatColor.RED );
|
||||
Assert.assertEquals( noneRetention[1].getColor(), ChatColor.WHITE );
|
||||
private <T> void testBuilderReset(Function<ComponentBuilder, T> componentBuilder, BiFunction<T, Integer, BaseComponent> extraGetter)
|
||||
{
|
||||
T component = componentBuilder.apply( new ComponentBuilder( "Hello " ).color( ChatColor.RED )
|
||||
.append( "World" ).reset() );
|
||||
|
||||
HoverEvent testEvent = new HoverEvent( HoverEvent.Action.SHOW_TEXT, new ComponentBuilder( "test" ).create() );
|
||||
Assert.assertEquals( ChatColor.RED, extraGetter.apply( component, 0 ).getColor() );
|
||||
Assert.assertEquals( ChatColor.WHITE, extraGetter.apply( component, 1 ).getColor() );
|
||||
}
|
||||
|
||||
BaseComponent[] formattingRetention = new ComponentBuilder( "Hello " ).color( ChatColor.RED )
|
||||
.event( testEvent ).append( "World", ComponentBuilder.FormatRetention.FORMATTING ).create();
|
||||
@Test
|
||||
public void testBuilderCreateFormatRetention()
|
||||
{
|
||||
this.testBuilderFormatRetention(
|
||||
ComponentBuilder::create,
|
||||
(components, index) -> components[index]
|
||||
);
|
||||
}
|
||||
|
||||
Assert.assertEquals( formattingRetention[0].getColor(), ChatColor.RED );
|
||||
Assert.assertEquals( formattingRetention[0].getHoverEvent(), testEvent );
|
||||
Assert.assertEquals( formattingRetention[1].getColor(), ChatColor.RED );
|
||||
Assert.assertNull( formattingRetention[1].getHoverEvent() );
|
||||
@Test
|
||||
public void testBuilderBuildFormatRetention()
|
||||
{
|
||||
this.testBuilderFormatRetention(
|
||||
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 ) );
|
||||
|
||||
Assert.assertEquals( ChatColor.RED, extraGetter.apply( noneRetention, 0 ).getColor() );
|
||||
Assert.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 ) );
|
||||
|
||||
Assert.assertEquals( ChatColor.RED, extraGetter.apply( formattingRetention, 0 ).getColor() );
|
||||
Assert.assertEquals( testEvent, extraGetter.apply( formattingRetention, 0 ).getHoverEvent() );
|
||||
Assert.assertEquals( ChatColor.RED, extraGetter.apply( formattingRetention, 1 ).getColor() );
|
||||
Assert.assertNull( extraGetter.apply( formattingRetention, 1 ).getHoverEvent() );
|
||||
|
||||
ClickEvent testClickEvent = new ClickEvent( ClickEvent.Action.OPEN_URL, "http://www.example.com" );
|
||||
|
||||
BaseComponent[] eventRetention = new ComponentBuilder( "Hello " ).color( ChatColor.RED )
|
||||
.event( testEvent ).event( testClickEvent ).append( "World", ComponentBuilder.FormatRetention.EVENTS ).create();
|
||||
T eventRetention = componentBuilder.apply( new ComponentBuilder( "Hello " ).color( ChatColor.RED )
|
||||
.event( testEvent ).event( testClickEvent ).append( "World", ComponentBuilder.FormatRetention.EVENTS ) );
|
||||
|
||||
Assert.assertEquals( eventRetention[0].getColor(), ChatColor.RED );
|
||||
Assert.assertEquals( eventRetention[0].getHoverEvent(), testEvent );
|
||||
Assert.assertEquals( eventRetention[0].getClickEvent(), testClickEvent );
|
||||
Assert.assertEquals( eventRetention[1].getColor(), ChatColor.WHITE );
|
||||
Assert.assertEquals( eventRetention[1].getHoverEvent(), testEvent );
|
||||
Assert.assertEquals( eventRetention[1].getClickEvent(), testClickEvent );
|
||||
Assert.assertEquals( ChatColor.RED, extraGetter.apply( eventRetention, 0 ).getColor() );
|
||||
Assert.assertEquals( testEvent, extraGetter.apply( eventRetention, 0 ).getHoverEvent() );
|
||||
Assert.assertEquals( testClickEvent, extraGetter.apply( eventRetention, 0 ).getClickEvent() );
|
||||
Assert.assertEquals( ChatColor.WHITE, extraGetter.apply( eventRetention, 1 ).getColor() );
|
||||
Assert.assertEquals( testEvent, extraGetter.apply( eventRetention, 1 ).getHoverEvent() );
|
||||
Assert.assertEquals( testClickEvent, extraGetter.apply( eventRetention, 1 ).getClickEvent() );
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@ -572,12 +788,29 @@ public class ComponentsTest
|
||||
Assert.assertArrayEquals( hexColored, reColored );
|
||||
}
|
||||
|
||||
/**
|
||||
@Test
|
||||
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.
|
||||
*/
|
||||
@Test
|
||||
public void testLegacyResetInBuilder()
|
||||
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" );
|
||||
@ -588,13 +821,13 @@ public class ComponentsTest
|
||||
|
||||
builder.append( a );
|
||||
|
||||
String test1 = ComponentSerializer.toString( builder.create() );
|
||||
String test1 = componentSerializer.apply( componentBuilder.apply( builder ) );
|
||||
Assert.assertEquals( expected, test1 );
|
||||
|
||||
BaseComponent[] b = TextComponent.fromLegacyText( "§rrrrr" );
|
||||
builder.append( b );
|
||||
|
||||
String test2 = ComponentSerializer.toString( builder.create() );
|
||||
String test2 = componentSerializer.apply( componentBuilder.apply( builder ) );
|
||||
Assert.assertEquals(
|
||||
"{\"extra\":[{\"underlined\":true,\"color\":\"dark_red\",\"text\":\"44444\"},"
|
||||
+ "{\"color\":\"white\",\"text\":\"dd\"},{\"bold\":true,\"color\":\"gold\",\"text\":\"6666\"},"
|
||||
|
@ -4,15 +4,14 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-config</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-Config</name>
|
||||
@ -22,14 +21,14 @@
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.10</version>
|
||||
<version>2.10.1</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>2.0</version>
|
||||
<version>2.2</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
@ -4,15 +4,14 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-event</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-Event</name>
|
||||
|
@ -4,15 +4,14 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-log</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-Log</name>
|
||||
@ -26,7 +25,7 @@
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-chat</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
|
@ -1,31 +0,0 @@
|
||||
<?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>
|
@ -1,20 +0,0 @@
|
||||
|
||||
<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.20-R0.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-module-cmd-alert</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>cmd_alert</name>
|
||||
<description>Provides the alert and alertraw commands</description>
|
||||
</project>
|
@ -1,47 +0,0 @@
|
||||
package net.md_5.bungee.module.cmd.alert;
|
||||
|
||||
import java.util.Locale;
|
||||
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].toLowerCase( Locale.ROOT ).startsWith( "&h" ) )
|
||||
{
|
||||
// Remove &h
|
||||
args[0] = args[0].substring( 2 );
|
||||
} 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 ) );
|
||||
}
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
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() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
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() );
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
name: ${project.name}
|
||||
main: net.md_5.bungee.module.cmd.alert.PluginAlert
|
||||
version: ${describe}
|
||||
description: ${project.description}
|
||||
author: ${module.author}
|
@ -1,31 +0,0 @@
|
||||
<?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>
|
@ -1,20 +0,0 @@
|
||||
|
||||
<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.20-R0.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-module-cmd-find</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>cmd_find</name>
|
||||
<description>Provides the find command</description>
|
||||
</project>
|
@ -1,34 +0,0 @@
|
||||
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() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
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() );
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
name: ${project.name}
|
||||
main: net.md_5.bungee.module.cmd.find.PluginFind
|
||||
version: ${describe}
|
||||
description: ${project.description}
|
||||
author: ${module.author}
|
@ -1,31 +0,0 @@
|
||||
<?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>
|
@ -1,20 +0,0 @@
|
||||
|
||||
<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.20-R0.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-module-cmd-kick</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>cmd_kick</name>
|
||||
<description>Provides the gkick command</description>
|
||||
</project>
|
@ -1,72 +0,0 @@
|
||||
package net.md_5.bungee.module.cmd.kick;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
import net.md_5.bungee.api.plugin.TabExecutor;
|
||||
|
||||
public class CommandKick extends Command implements TabExecutor
|
||||
{
|
||||
|
||||
public CommandKick()
|
||||
{
|
||||
super( "gkick", "bungeecord.command.kick" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, String[] args)
|
||||
{
|
||||
if ( args.length == 0 )
|
||||
{
|
||||
sender.sendMessage( ProxyServer.getInstance().getTranslation( "username_needed" ) );
|
||||
} else
|
||||
{
|
||||
ProxiedPlayer player = ProxyServer.getInstance().getPlayer( args[0] );
|
||||
|
||||
if ( player == null )
|
||||
{
|
||||
sender.sendMessage( TextComponent.fromLegacyText( ProxyServer.getInstance().getTranslation( "user_not_online" ) ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( args.length == 1 )
|
||||
{
|
||||
player.disconnect( TextComponent.fromLegacyText( ProxyServer.getInstance().getTranslation( "kick_message" ) ) );
|
||||
} else
|
||||
{
|
||||
String[] reason = new String[ args.length - 1 ];
|
||||
System.arraycopy( args, 1, reason, 0, reason.length );
|
||||
player.disconnect( TextComponent.fromLegacyText( ChatColor.translateAlternateColorCodes( '&', Joiner.on( ' ' ).join( reason ) ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<String> onTabComplete(CommandSender sender, String[] args)
|
||||
{
|
||||
if ( args.length == 1 )
|
||||
{
|
||||
Set<String> matches = new HashSet<>();
|
||||
String search = args[0].toLowerCase( Locale.ROOT );
|
||||
for ( ProxiedPlayer player : ProxyServer.getInstance().getPlayers() )
|
||||
{
|
||||
if ( player.getName().toLowerCase( Locale.ROOT ).startsWith( search ) )
|
||||
{
|
||||
matches.add( player.getName() );
|
||||
}
|
||||
}
|
||||
return matches;
|
||||
} else
|
||||
{
|
||||
return ImmutableSet.of();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
package net.md_5.bungee.module.cmd.kick;
|
||||
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
|
||||
public class PluginKick extends Plugin
|
||||
{
|
||||
|
||||
@Override
|
||||
public void onEnable()
|
||||
{
|
||||
getProxy().getPluginManager().registerCommand( this, new CommandKick() );
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
name: ${project.name}
|
||||
main: net.md_5.bungee.module.cmd.kick.PluginKick
|
||||
version: ${describe}
|
||||
description: ${project.description}
|
||||
author: ${module.author}
|
@ -1,31 +0,0 @@
|
||||
<?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>
|
@ -1,20 +0,0 @@
|
||||
|
||||
<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.20-R0.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-module-cmd-list</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>cmd_list</name>
|
||||
<description>Provides the glist command</description>
|
||||
</project>
|
@ -1,62 +0,0 @@
|
||||
package net.md_5.bungee.module.cmd.list;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
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;
|
||||
import net.md_5.bungee.api.plugin.TabExecutor;
|
||||
|
||||
/**
|
||||
* Command to list all players connected to the proxy.
|
||||
*/
|
||||
public class CommandList extends Command implements TabExecutor
|
||||
{
|
||||
|
||||
public CommandList()
|
||||
{
|
||||
super( "glist", "bungeecord.command.list" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, String[] args)
|
||||
{
|
||||
boolean hideEmptyServers = ( args.length == 0 ) || !args[0].equalsIgnoreCase( "all" );
|
||||
|
||||
for ( ServerInfo server : ProxyServer.getInstance().getServers().values() )
|
||||
{
|
||||
if ( !server.canAccess( sender ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Collection<ProxiedPlayer> serverPlayers = server.getPlayers();
|
||||
if ( hideEmptyServers && serverPlayers.isEmpty() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
List<String> players = new ArrayList<>();
|
||||
for ( ProxiedPlayer player : serverPlayers )
|
||||
{
|
||||
players.add( player.getDisplayName() );
|
||||
}
|
||||
Collections.sort( players, String.CASE_INSENSITIVE_ORDER );
|
||||
|
||||
sender.sendMessage( ProxyServer.getInstance().getTranslation( "command_list", server.getName(), players.size(), String.join( ChatColor.RESET + ", ", players ) ) );
|
||||
}
|
||||
|
||||
sender.sendMessage( ProxyServer.getInstance().getTranslation( "total_players", ProxyServer.getInstance().getOnlineCount() ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<String> onTabComplete(CommandSender sender, String[] args)
|
||||
{
|
||||
return ( args.length > 1 ) ? Collections.emptyList() : Collections.singletonList( "all" );
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
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() );
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
name: ${project.name}
|
||||
main: net.md_5.bungee.module.cmd.list.PluginList
|
||||
version: ${describe}
|
||||
description: ${project.description}
|
||||
author: ${module.author}
|
@ -1,31 +0,0 @@
|
||||
<?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>
|
@ -1,20 +0,0 @@
|
||||
|
||||
<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.20-R0.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-module-cmd-send</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>cmd_send</name>
|
||||
<description>Provides the gsend command</description>
|
||||
</project>
|
@ -1,200 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
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() );
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
name: ${project.name}
|
||||
main: net.md_5.bungee.module.cmd.send.PluginSend
|
||||
version: ${describe}
|
||||
description: ${project.description}
|
||||
author: ${module.author}
|
@ -1,31 +0,0 @@
|
||||
<?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>
|
@ -1,20 +0,0 @@
|
||||
|
||||
<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.20-R0.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-module-cmd-server</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>cmd_server</name>
|
||||
<description>Provides the server command</description>
|
||||
</project>
|
@ -1,104 +0,0 @@
|
||||
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();
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
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() );
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
name: ${project.name}
|
||||
main: net.md_5.bungee.module.cmd.server.PluginServer
|
||||
version: ${describe}
|
||||
description: ${project.description}
|
||||
author: ${module.author}
|
@ -1,55 +0,0 @@
|
||||
|
||||
<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.20-R0.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-module</artifactId>
|
||||
<version>1.20-R0.1-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-kick</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>
|
@ -1,31 +0,0 @@
|
||||
<?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>
|
@ -1,20 +0,0 @@
|
||||
|
||||
<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.20-R0.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-module-reconnect-yaml</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>reconnect_yaml</name>
|
||||
<description>Provides reconnect location functionality in locations.yml</description>
|
||||
</project>
|
@ -1,22 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
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()
|
||||
{
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
name: ${project.name}
|
||||
main: net.md_5.bungee.module.reconnect.yaml.PluginYaml
|
||||
version: ${describe}
|
||||
description: ${project.description}
|
||||
author: ${module.author}
|
@ -4,15 +4,14 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-native</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-Native</name>
|
||||
|
29
pom.xml
29
pom.xml
@ -3,9 +3,9 @@
|
||||
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>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>BungeeCord-Parent</name>
|
||||
@ -37,7 +37,6 @@
|
||||
<module>config</module>
|
||||
<module>event</module>
|
||||
<module>log</module>
|
||||
<module>module</module>
|
||||
<module>protocol</module>
|
||||
<module>proxy</module>
|
||||
<module>query</module>
|
||||
@ -72,7 +71,7 @@
|
||||
|
||||
<properties>
|
||||
<build.number>unknown</build.number>
|
||||
<lombok.version>1.18.28</lombok.version>
|
||||
<lombok.version>1.18.30</lombok.version>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
@ -83,7 +82,7 @@
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-bom</artifactId>
|
||||
<version>4.1.93.Final</version>
|
||||
<version>4.1.97.Final</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@ -99,7 +98,7 @@
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>31.1-jre</version>
|
||||
<version>32.1.2-jre</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -117,13 +116,22 @@
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>scriptus</artifactId>
|
||||
<version>0.4.1</version>
|
||||
<version>0.5.0</version>
|
||||
<configuration>
|
||||
<format>git:${project.name}:${project.version}:%s:${build.number}</format>
|
||||
<format>git:${project.name}-Pandacube:${project.version}:%s:${build.number}</format>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
@ -187,7 +195,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<version>3.4.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>enforce</id>
|
||||
@ -204,7 +212,7 @@
|
||||
</rules>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>enforce</goal>
|
||||
<!--<goal>enforce</goal>--> <!-- Disabled until maven-resolver is upgraded again. -->
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
@ -305,7 +313,6 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.5.0</version>
|
||||
<executions>
|
||||
<!-- Execute Javadoc once normally to catch any warnings -->
|
||||
<execution>
|
||||
|
@ -4,15 +4,14 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-protocol</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-Protocol</name>
|
||||
@ -41,7 +40,7 @@
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-chat</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
|
@ -11,6 +11,7 @@ import net.md_5.bungee.protocol.packet.Commands;
|
||||
import net.md_5.bungee.protocol.packet.EncryptionRequest;
|
||||
import net.md_5.bungee.protocol.packet.EncryptionResponse;
|
||||
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.Handshake;
|
||||
import net.md_5.bungee.protocol.packet.KeepAlive;
|
||||
@ -18,6 +19,7 @@ import net.md_5.bungee.protocol.packet.Kick;
|
||||
import net.md_5.bungee.protocol.packet.LegacyHandshake;
|
||||
import net.md_5.bungee.protocol.packet.LegacyPing;
|
||||
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.LoginPayloadResponse;
|
||||
import net.md_5.bungee.protocol.packet.LoginRequest;
|
||||
@ -34,6 +36,7 @@ import net.md_5.bungee.protocol.packet.ScoreboardObjective;
|
||||
import net.md_5.bungee.protocol.packet.ScoreboardScore;
|
||||
import net.md_5.bungee.protocol.packet.ServerData;
|
||||
import net.md_5.bungee.protocol.packet.SetCompression;
|
||||
import net.md_5.bungee.protocol.packet.StartConfiguration;
|
||||
import net.md_5.bungee.protocol.packet.StatusRequest;
|
||||
import net.md_5.bungee.protocol.packet.StatusResponse;
|
||||
import net.md_5.bungee.protocol.packet.Subtitle;
|
||||
@ -223,4 +226,16 @@ public abstract class AbstractPacketHandler
|
||||
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
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,9 @@ import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import se.llbit.nbt.ErrorTag;
|
||||
import se.llbit.nbt.NamedTag;
|
||||
import se.llbit.nbt.SpecificTag;
|
||||
import se.llbit.nbt.Tag;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@ -293,14 +295,35 @@ public abstract class DefinedPacket
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Tag readTag(ByteBuf input)
|
||||
public static Tag readTag(ByteBuf input, int protocolVersion)
|
||||
{
|
||||
Tag tag = NamedTag.read( new DataInputStream( new ByteBufInputStream( input ) ) );
|
||||
DataInputStream in = new DataInputStream( new ByteBufInputStream( input ) );
|
||||
Tag tag;
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
try
|
||||
{
|
||||
byte type = in.readByte();
|
||||
if ( type == 0 )
|
||||
{
|
||||
return Tag.END;
|
||||
} else
|
||||
{
|
||||
tag = SpecificTag.read( type, in );
|
||||
}
|
||||
} catch ( IOException ex )
|
||||
{
|
||||
tag = new ErrorTag( "IOException while reading tag type:\n" + ex.getMessage() );
|
||||
}
|
||||
} else
|
||||
{
|
||||
tag = NamedTag.read( in );
|
||||
}
|
||||
Preconditions.checkArgument( !tag.isError(), "Error reading tag: %s", tag.error() );
|
||||
return tag;
|
||||
}
|
||||
|
||||
public static void writeTag(Tag tag, ByteBuf output)
|
||||
public static void writeTag(Tag tag, ByteBuf output, int protocolVersion)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -378,6 +401,11 @@ public abstract class DefinedPacket
|
||||
write( buf );
|
||||
}
|
||||
|
||||
public Protocol nextProtocol()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract void handle(AbstractPacketHandler handler) throws Exception;
|
||||
|
||||
@Override
|
||||
|
@ -5,12 +5,14 @@ import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
import java.util.List;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class MinecraftDecoder extends MessageToMessageDecoder<ByteBuf>
|
||||
{
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private Protocol protocol;
|
||||
private final boolean server;
|
||||
|
@ -4,12 +4,14 @@ import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class MinecraftEncoder extends MessageToByteEncoder<DefinedPacket>
|
||||
{
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private Protocol protocol;
|
||||
private boolean server;
|
||||
|
@ -19,11 +19,13 @@ import net.md_5.bungee.protocol.packet.Commands;
|
||||
import net.md_5.bungee.protocol.packet.EncryptionRequest;
|
||||
import net.md_5.bungee.protocol.packet.EncryptionResponse;
|
||||
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.Handshake;
|
||||
import net.md_5.bungee.protocol.packet.KeepAlive;
|
||||
import net.md_5.bungee.protocol.packet.Kick;
|
||||
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.LoginPayloadResponse;
|
||||
import net.md_5.bungee.protocol.packet.LoginRequest;
|
||||
@ -40,6 +42,7 @@ import net.md_5.bungee.protocol.packet.ScoreboardObjective;
|
||||
import net.md_5.bungee.protocol.packet.ScoreboardScore;
|
||||
import net.md_5.bungee.protocol.packet.ServerData;
|
||||
import net.md_5.bungee.protocol.packet.SetCompression;
|
||||
import net.md_5.bungee.protocol.packet.StartConfiguration;
|
||||
import net.md_5.bungee.protocol.packet.StatusRequest;
|
||||
import net.md_5.bungee.protocol.packet.StatusResponse;
|
||||
import net.md_5.bungee.protocol.packet.Subtitle;
|
||||
@ -85,7 +88,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x1E ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_1, 0x20 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x1F ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x23 )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x23 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x24 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
Login.class,
|
||||
@ -100,7 +104,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x23 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_1, 0x25 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x24 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x28 )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x28 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x29 )
|
||||
);
|
||||
TO_CLIENT.registerPacket( Chat.class,
|
||||
Chat::new,
|
||||
@ -128,7 +133,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x3B ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_1, 0x3E ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x3D ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x41 )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x41 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x43 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
BossBar.class,
|
||||
@ -138,7 +144,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_16, 0x0C ),
|
||||
map( ProtocolConstants.MINECRAFT_1_17, 0x0D ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x0A ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0xB )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x0B ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x0A )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
PlayerListItem.class, // PlayerInfo
|
||||
@ -168,7 +175,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_17, 0x11 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x0E ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x0D ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0xF )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x0F ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x10 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
ScoreboardObjective.class,
|
||||
@ -183,7 +191,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_17, 0x53 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_1, 0x56 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x54 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x58 )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x58 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x5A )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
ScoreboardScore.class,
|
||||
@ -198,7 +207,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_17, 0x56 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_1, 0x59 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x57 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x5B )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x5B ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x5D )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
ScoreboardDisplay.class,
|
||||
@ -213,7 +223,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_17, 0x4C ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_1, 0x4F ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x4D ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x51 )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x51 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x53 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
Team.class,
|
||||
@ -228,7 +239,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_17, 0x55 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_1, 0x58 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x56 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x5A )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x5A ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x5C )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
PluginMessage.class,
|
||||
@ -244,7 +256,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x15 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_1, 0x16 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x15 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x17 )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x17 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x18 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
Kick.class,
|
||||
@ -260,7 +273,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x17 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_1, 0x19 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x17 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x1A )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x1A ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x1B )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
Title.class,
|
||||
@ -276,7 +290,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_18, 0x5A ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_1, 0x5D ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x5B ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x5F )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x5F ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x61 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
ClearTitles.class,
|
||||
@ -284,7 +299,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_17, 0x10 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x0D ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x0C ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0xE )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x0E ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x0F )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
Subtitle.class,
|
||||
@ -293,7 +309,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_18, 0x58 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_1, 0x5B ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x59 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x5D )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x5D ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x5F )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
TitleTimes.class,
|
||||
@ -302,7 +319,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_18, 0x5B ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_1, 0x5E ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x5C ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x60 )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x60 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x62 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
SystemChat.class,
|
||||
@ -310,7 +328,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x5F ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_1, 0x62 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x60 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x64 )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x64 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x67 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
PlayerListHeaderFooter.class,
|
||||
@ -329,7 +348,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x60 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_1, 0x63 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x61 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x65 )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x65 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x68 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
EntityStatus.class,
|
||||
@ -345,7 +365,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x18 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_1, 0x1A ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x19 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x1C )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x1C ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x1D )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
Commands.class,
|
||||
@ -357,7 +378,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_17, 0x12 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x0F ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x0E ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x10 )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x10 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x11 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
GameState.class,
|
||||
@ -369,7 +391,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x1B ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_1, 0x1D ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x1C ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x1F )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x1F ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x20 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
ViewDistance.class,
|
||||
@ -381,7 +404,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x49 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_1, 0x4C ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x4B ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x4F )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x4F ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x51 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
ServerData.class,
|
||||
@ -389,19 +413,27 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x3F ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_1, 0x42 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x41 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x45 )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x45 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x47 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
PlayerListItemRemove.class,
|
||||
PlayerListItemRemove::new,
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x35 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x39 )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x39 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x3B )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
PlayerListItemUpdate.class,
|
||||
PlayerListItemUpdate::new,
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x36 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x3A )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x3A ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x3C )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
StartConfiguration.class,
|
||||
StartConfiguration::new,
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x65 )
|
||||
);
|
||||
|
||||
TO_SERVER.registerPacket(
|
||||
@ -418,7 +450,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x11 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_1, 0x12 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x11 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x12 )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x12 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x14 )
|
||||
);
|
||||
TO_SERVER.registerPacket( Chat.class,
|
||||
Chat::new,
|
||||
@ -453,7 +486,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x08 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_1, 0x09 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x08 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x09 )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x09 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x0A )
|
||||
);
|
||||
TO_SERVER.registerPacket(
|
||||
ClientSettings.class,
|
||||
@ -466,7 +500,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x07 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_1, 0x08 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x07 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x08 )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x08 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x09 )
|
||||
);
|
||||
TO_SERVER.registerPacket(
|
||||
PluginMessage.class,
|
||||
@ -481,7 +516,13 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x0C ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_1, 0x0D ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x0C ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x0D )
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x0D ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x0F )
|
||||
);
|
||||
TO_SERVER.registerPacket(
|
||||
StartConfiguration.class,
|
||||
StartConfiguration::new,
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x0B )
|
||||
);
|
||||
}
|
||||
},
|
||||
@ -559,6 +600,59 @@ public enum Protocol
|
||||
LoginPayloadResponse::new,
|
||||
map( ProtocolConstants.MINECRAFT_1_13, 0x02 )
|
||||
);
|
||||
TO_SERVER.registerPacket(
|
||||
LoginAcknowledged.class,
|
||||
LoginAcknowledged::new,
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x03 )
|
||||
);
|
||||
}
|
||||
},
|
||||
// 3
|
||||
CONFIGURATION
|
||||
{
|
||||
|
||||
{
|
||||
TO_CLIENT.registerPacket(
|
||||
PluginMessage.class,
|
||||
PluginMessage::new,
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x00 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
Kick.class,
|
||||
Kick::new,
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x01 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
FinishConfiguration.class,
|
||||
FinishConfiguration::new,
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x02 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
KeepAlive.class,
|
||||
KeepAlive::new,
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x03 )
|
||||
);
|
||||
|
||||
TO_SERVER.registerPacket(
|
||||
ClientSettings.class,
|
||||
ClientSettings::new,
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x00 )
|
||||
);
|
||||
TO_SERVER.registerPacket(
|
||||
PluginMessage.class,
|
||||
PluginMessage::new,
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x01 )
|
||||
);
|
||||
TO_SERVER.registerPacket(
|
||||
FinishConfiguration.class,
|
||||
FinishConfiguration::new,
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x02 )
|
||||
);
|
||||
TO_SERVER.registerPacket(
|
||||
KeepAlive.class,
|
||||
KeepAlive::new,
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x03 )
|
||||
);
|
||||
}
|
||||
};
|
||||
/*========================================================================*/
|
||||
|
@ -43,6 +43,7 @@ public class ProtocolConstants
|
||||
public static final int MINECRAFT_1_19_3 = 761;
|
||||
public static final int MINECRAFT_1_19_4 = 762;
|
||||
public static final int MINECRAFT_1_20 = 763;
|
||||
public static final int MINECRAFT_1_20_2 = 764;
|
||||
public static final List<String> SUPPORTED_VERSIONS;
|
||||
public static final List<Integer> SUPPORTED_VERSION_IDS;
|
||||
|
||||
@ -99,13 +100,14 @@ public class ProtocolConstants
|
||||
ProtocolConstants.MINECRAFT_1_19_1,
|
||||
ProtocolConstants.MINECRAFT_1_19_3,
|
||||
ProtocolConstants.MINECRAFT_1_19_4,
|
||||
ProtocolConstants.MINECRAFT_1_20
|
||||
ProtocolConstants.MINECRAFT_1_20,
|
||||
ProtocolConstants.MINECRAFT_1_20_2
|
||||
);
|
||||
|
||||
if ( SNAPSHOT_SUPPORT )
|
||||
{
|
||||
// supportedVersions.add( "1.20.x" );
|
||||
// supportedVersionIds.add( ProtocolConstants.MINECRAFT_1_20 );
|
||||
// supportedVersionIds.add( ProtocolConstants.MINECRAFT_1_20_2 );
|
||||
}
|
||||
|
||||
SUPPORTED_VERSIONS = supportedVersions.build();
|
||||
|
@ -32,7 +32,7 @@ public class ClientCommand extends DefinedPacket
|
||||
@Override
|
||||
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
|
||||
{
|
||||
command = readString( buf );
|
||||
command = readString( buf, 256 );
|
||||
timestamp = buf.readLong();
|
||||
salt = buf.readLong();
|
||||
|
||||
|
@ -4,6 +4,7 @@ import com.google.common.base.Preconditions;
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.StringReader;
|
||||
import com.mojang.brigadier.arguments.ArgumentType;
|
||||
import com.mojang.brigadier.arguments.BoolArgumentType;
|
||||
import com.mojang.brigadier.arguments.DoubleArgumentType;
|
||||
import com.mojang.brigadier.arguments.FloatArgumentType;
|
||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||
@ -303,7 +304,7 @@ public class Commands extends DefinedPacket
|
||||
}
|
||||
|
||||
@Data
|
||||
private static class ArgumentRegistry
|
||||
public static class ArgumentRegistry
|
||||
{
|
||||
|
||||
private static final Map<String, ArgumentSerializer> PROVIDERS = new HashMap<>();
|
||||
@ -325,18 +326,29 @@ public class Commands extends DefinedPacket
|
||||
{
|
||||
}
|
||||
};
|
||||
private static final ArgumentSerializer<Boolean> BOOLEAN = new ArgumentSerializer<Boolean>()
|
||||
private static final ProperArgumentSerializer<BoolArgumentType> BOOLEAN = new ProperArgumentSerializer<BoolArgumentType>()
|
||||
{
|
||||
@Override
|
||||
protected Boolean read(ByteBuf buf)
|
||||
protected BoolArgumentType read(ByteBuf buf)
|
||||
{
|
||||
return buf.readBoolean();
|
||||
return BoolArgumentType.bool();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write(ByteBuf buf, Boolean t)
|
||||
protected void write(ByteBuf buf, BoolArgumentType t)
|
||||
{
|
||||
buf.writeBoolean( t );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getIntKey()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getKey()
|
||||
{
|
||||
return "brigadier:bool";
|
||||
}
|
||||
};
|
||||
private static final ArgumentSerializer<Byte> BYTE = new ArgumentSerializer<Byte>()
|
||||
@ -353,7 +365,7 @@ public class Commands extends DefinedPacket
|
||||
buf.writeByte( t );
|
||||
}
|
||||
};
|
||||
private static final ArgumentSerializer<FloatArgumentType> FLOAT_RANGE = new ArgumentSerializer<FloatArgumentType>()
|
||||
private static final ProperArgumentSerializer<FloatArgumentType> FLOAT_RANGE = new ProperArgumentSerializer<FloatArgumentType>()
|
||||
{
|
||||
@Override
|
||||
protected FloatArgumentType read(ByteBuf buf)
|
||||
@ -381,8 +393,20 @@ public class Commands extends DefinedPacket
|
||||
buf.writeFloat( t.getMaximum() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getIntKey()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getKey()
|
||||
{
|
||||
return "brigadier:float";
|
||||
}
|
||||
};
|
||||
private static final ArgumentSerializer<DoubleArgumentType> DOUBLE_RANGE = new ArgumentSerializer<DoubleArgumentType>()
|
||||
private static final ProperArgumentSerializer<DoubleArgumentType> DOUBLE_RANGE = new ProperArgumentSerializer<DoubleArgumentType>()
|
||||
{
|
||||
@Override
|
||||
protected DoubleArgumentType read(ByteBuf buf)
|
||||
@ -410,8 +434,20 @@ public class Commands extends DefinedPacket
|
||||
buf.writeDouble( t.getMaximum() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getIntKey()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getKey()
|
||||
{
|
||||
return "brigadier:double";
|
||||
}
|
||||
};
|
||||
private static final ArgumentSerializer<IntegerArgumentType> INTEGER_RANGE = new ArgumentSerializer<IntegerArgumentType>()
|
||||
private static final ProperArgumentSerializer<IntegerArgumentType> INTEGER_RANGE = new ProperArgumentSerializer<IntegerArgumentType>()
|
||||
{
|
||||
@Override
|
||||
protected IntegerArgumentType read(ByteBuf buf)
|
||||
@ -439,6 +475,18 @@ public class Commands extends DefinedPacket
|
||||
buf.writeInt( t.getMaximum() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getIntKey()
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getKey()
|
||||
{
|
||||
return "brigadier:integer";
|
||||
}
|
||||
};
|
||||
private static final ArgumentSerializer<Integer> INTEGER = new ArgumentSerializer<Integer>()
|
||||
{
|
||||
@ -454,7 +502,7 @@ public class Commands extends DefinedPacket
|
||||
buf.writeInt( t );
|
||||
}
|
||||
};
|
||||
private static final ArgumentSerializer<LongArgumentType> LONG_RANGE = new ArgumentSerializer<LongArgumentType>()
|
||||
private static final ProperArgumentSerializer<LongArgumentType> LONG_RANGE = new ProperArgumentSerializer<LongArgumentType>()
|
||||
{
|
||||
@Override
|
||||
protected LongArgumentType read(ByteBuf buf)
|
||||
@ -482,6 +530,18 @@ public class Commands extends DefinedPacket
|
||||
buf.writeLong( t.getMaximum() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getIntKey()
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getKey()
|
||||
{
|
||||
return "brigadier:long";
|
||||
}
|
||||
};
|
||||
private static final ProperArgumentSerializer<StringArgumentType> STRING = new ProperArgumentSerializer<StringArgumentType>()
|
||||
{
|
||||
@ -537,11 +597,20 @@ public class Commands extends DefinedPacket
|
||||
|
||||
static
|
||||
{
|
||||
register( "brigadier:bool", VOID );
|
||||
register( "brigadier:bool", BOOLEAN );
|
||||
PROPER_PROVIDERS.put( BoolArgumentType.class, BOOLEAN );
|
||||
|
||||
register( "brigadier:float", FLOAT_RANGE );
|
||||
PROPER_PROVIDERS.put( FloatArgumentType.class, FLOAT_RANGE );
|
||||
|
||||
register( "brigadier:double", DOUBLE_RANGE );
|
||||
PROPER_PROVIDERS.put( DoubleArgumentType.class, DOUBLE_RANGE );
|
||||
|
||||
register( "brigadier:integer", INTEGER_RANGE );
|
||||
register( "brigadier:long", LONG_RANGE );
|
||||
PROPER_PROVIDERS.put( IntegerArgumentType.class, INTEGER_RANGE );
|
||||
|
||||
register( "brigadier:long", LONG_RANGE ); // 1.14+
|
||||
PROPER_PROVIDERS.put( LongArgumentType.class, LONG_RANGE );
|
||||
|
||||
register( "brigadier:string", STRING );
|
||||
PROPER_PROVIDERS.put( StringArgumentType.class, STRING );
|
||||
@ -756,6 +825,404 @@ public class Commands extends DefinedPacket
|
||||
return serializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:entity}.
|
||||
* @param singleEntity if the argument restrict to only one entity
|
||||
* @param onlyPlayers if the argument restrict to players only
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftEntity(boolean singleEntity, boolean onlyPlayers)
|
||||
{
|
||||
byte flags = 0;
|
||||
if ( singleEntity )
|
||||
{
|
||||
flags |= 1;
|
||||
}
|
||||
if ( onlyPlayers )
|
||||
{
|
||||
flags |= 2;
|
||||
}
|
||||
|
||||
return minecraftArgumentType( "minecraft:entity", flags );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:game_profile}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftGameProfile()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:game_profile", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:block_pos}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftBlockPos()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:block_pos", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:column_pos}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftColumnPos()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:column_pos", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:vec3}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftVec3()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:vec3", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:vec2}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftVec2()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:vec2", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:block_state}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftBlockState()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:block_state", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:block_predicate}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftBlockPredicate()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:block_predicate", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:item_stack}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftItemStack()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:item_stack", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:item_predicate}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftItemPredicate()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:item_predicate", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:color}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftColor()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:color", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:component}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftComponent()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:component", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:message}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftMessage()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:message", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:nbt_compound_tag}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftNBTCompoundTag()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:nbt_compound_tag", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:nbt_tag}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftNBTTag()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:nbt_tag", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:nbt}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftNBT()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:nbt", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:nbt_path}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftNBTPath()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:nbt_path", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:objective}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftObjective()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:objective", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:objective_criteria}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftObjectiveCriteria()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:objective_criteria", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:operation}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftOperation()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:operation", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:particle}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftParticle()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:particle", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:rotation}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftRotation()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:rotation", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:scoreboard_slot}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftScoreboardSlot()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:scoreboard_slot", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:score_holder}.
|
||||
* @param allowMultiple if the argument allows multiple entities
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftScoreHolder(boolean allowMultiple)
|
||||
{
|
||||
byte flags = 0;
|
||||
if ( allowMultiple )
|
||||
{
|
||||
flags |= 1;
|
||||
}
|
||||
|
||||
return minecraftArgumentType( "minecraft:score_holder", flags );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:swizzle}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftSwizzle()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:swizzle", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:team}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftTeam()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:team", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:item_slot}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftItemSlot()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:item_slot", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:resource_location}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftResourceLocation()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:resource_location", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:mob_effect}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftMobEffect()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:mob_effect", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:function}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftFunction()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:function", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:entity_anchor}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftEntityAnchor()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:entity_anchor", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:int_range}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftIntRange()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:int_range", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:float_range}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftFloatRange()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:float_range", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:item_enchantment}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftItemEnchantment()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:item_enchantment", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:entity_summon}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftEntitySummon()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:entity_summon", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:dimension}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftDimension()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:dimension", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:time}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftTime()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:time", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:uuid}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftUUID()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:uuid", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:angle}.
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftAngle()
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:angle", null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:resource}.
|
||||
* @param rawString the raw string for the argument
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftResource(String rawString)
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:resource", rawString );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Minecraft ArgumentType {@code minecraft:resource_or_tag}.
|
||||
* @param rawString the raw string for the argument
|
||||
* @return an ArgumentType instance
|
||||
*/
|
||||
public static ArgumentType<?> minecraftResourceOrTag(String rawString)
|
||||
{
|
||||
return minecraftArgumentType( "minecraft:resource_or_tag", rawString );
|
||||
}
|
||||
|
||||
private static ArgumentType<?> minecraftArgumentType(String key, Object rawValue)
|
||||
{
|
||||
ArgumentSerializer reader = PROVIDERS.get( key );
|
||||
Preconditions.checkArgument( reader != null, "No provider for argument " + key );
|
||||
|
||||
return new DummyType( key, reader, rawValue );
|
||||
}
|
||||
|
||||
private static ArgumentType<?> read(ByteBuf buf, int protocolVersion)
|
||||
{
|
||||
Object key;
|
||||
@ -879,11 +1346,15 @@ public class Commands extends DefinedPacket
|
||||
|
||||
private static String getKey(SuggestionProvider<DummyProvider> provider)
|
||||
{
|
||||
Preconditions.checkArgument( provider instanceof DummyProvider, "Non dummy provider " + provider );
|
||||
|
||||
Preconditions.checkNotNull( provider );
|
||||
if ( provider instanceof DummyProvider )
|
||||
{
|
||||
return ( (DummyProvider) provider ).key;
|
||||
}
|
||||
|
||||
return ( (DummyProvider) ASK_SERVER ).key;
|
||||
}
|
||||
|
||||
@Data
|
||||
private static final class DummyProvider implements SuggestionProvider<DummyProvider>
|
||||
{
|
||||
|
@ -0,0 +1,37 @@
|
||||
package net.md_5.bungee.protocol.packet;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import net.md_5.bungee.protocol.AbstractPacketHandler;
|
||||
import net.md_5.bungee.protocol.DefinedPacket;
|
||||
import net.md_5.bungee.protocol.Protocol;
|
||||
import net.md_5.bungee.protocol.ProtocolConstants;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class FinishConfiguration extends DefinedPacket
|
||||
{
|
||||
|
||||
@Override
|
||||
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public Protocol nextProtocol()
|
||||
{
|
||||
return Protocol.GAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(AbstractPacketHandler handler) throws Exception
|
||||
{
|
||||
handler.handle( this );
|
||||
}
|
||||
}
|
@ -36,6 +36,7 @@ public class Login extends DefinedPacket
|
||||
private int simulationDistance;
|
||||
private boolean reducedDebugInfo;
|
||||
private boolean normalRespawn;
|
||||
private boolean limitedCrafting;
|
||||
private boolean debug;
|
||||
private boolean flat;
|
||||
private Location deathLocation;
|
||||
@ -49,10 +50,16 @@ public class Login extends DefinedPacket
|
||||
{
|
||||
hardcore = buf.readBoolean();
|
||||
}
|
||||
if ( protocolVersion < ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
gameMode = buf.readUnsignedByte();
|
||||
}
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16 )
|
||||
{
|
||||
if ( protocolVersion < ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
previousGameMode = buf.readUnsignedByte();
|
||||
}
|
||||
|
||||
worldNames = new HashSet<>();
|
||||
int worldCount = readVarInt( buf );
|
||||
@ -61,19 +68,25 @@ public class Login extends DefinedPacket
|
||||
worldNames.add( readString( buf ) );
|
||||
}
|
||||
|
||||
dimensions = readTag( buf );
|
||||
if ( protocolVersion < ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
dimensions = readTag( buf, protocolVersion );
|
||||
}
|
||||
}
|
||||
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16 )
|
||||
{
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16_2 && protocolVersion < ProtocolConstants.MINECRAFT_1_19 )
|
||||
{
|
||||
dimension = readTag( buf );
|
||||
} else
|
||||
dimension = readTag( buf, protocolVersion );
|
||||
} else if ( protocolVersion < ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
dimension = readString( buf );
|
||||
}
|
||||
if ( protocolVersion < ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
worldName = readString( buf );
|
||||
}
|
||||
} else if ( protocolVersion > ProtocolConstants.MINECRAFT_1_9 )
|
||||
{
|
||||
dimension = buf.readInt();
|
||||
@ -81,7 +94,7 @@ public class Login extends DefinedPacket
|
||||
{
|
||||
dimension = (int) buf.readByte();
|
||||
}
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_15 )
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_15 && protocolVersion < ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
seed = buf.readLong();
|
||||
}
|
||||
@ -116,6 +129,15 @@ public class Login extends DefinedPacket
|
||||
{
|
||||
normalRespawn = buf.readBoolean();
|
||||
}
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
limitedCrafting = buf.readBoolean();
|
||||
dimension = readString( buf );
|
||||
worldName = readString( buf );
|
||||
seed = buf.readLong();
|
||||
gameMode = buf.readUnsignedByte();
|
||||
previousGameMode = buf.readByte();
|
||||
}
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16 )
|
||||
{
|
||||
debug = buf.readBoolean();
|
||||
@ -142,10 +164,16 @@ public class Login extends DefinedPacket
|
||||
{
|
||||
buf.writeBoolean( hardcore );
|
||||
}
|
||||
if ( protocolVersion < ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
buf.writeByte( gameMode );
|
||||
}
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16 )
|
||||
{
|
||||
if ( protocolVersion < ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
buf.writeByte( previousGameMode );
|
||||
}
|
||||
|
||||
writeVarInt( worldNames.size(), buf );
|
||||
for ( String world : worldNames )
|
||||
@ -153,19 +181,25 @@ public class Login extends DefinedPacket
|
||||
writeString( world, buf );
|
||||
}
|
||||
|
||||
writeTag( dimensions, buf );
|
||||
if ( protocolVersion < ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
writeTag( dimensions, buf, protocolVersion );
|
||||
}
|
||||
}
|
||||
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16 )
|
||||
{
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16_2 && protocolVersion < ProtocolConstants.MINECRAFT_1_19 )
|
||||
{
|
||||
writeTag( (Tag) dimension, buf );
|
||||
} else
|
||||
writeTag( (Tag) dimension, buf, protocolVersion );
|
||||
} else if ( protocolVersion < ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
writeString( (String) dimension, buf );
|
||||
}
|
||||
if ( protocolVersion < ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
writeString( worldName, buf );
|
||||
}
|
||||
} else if ( protocolVersion > ProtocolConstants.MINECRAFT_1_9 )
|
||||
{
|
||||
buf.writeInt( (Integer) dimension );
|
||||
@ -174,9 +208,12 @@ public class Login extends DefinedPacket
|
||||
buf.writeByte( (Integer) dimension );
|
||||
}
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_15 )
|
||||
{
|
||||
if ( protocolVersion < ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
buf.writeLong( seed );
|
||||
}
|
||||
}
|
||||
if ( protocolVersion < ProtocolConstants.MINECRAFT_1_14 )
|
||||
{
|
||||
buf.writeByte( difficulty );
|
||||
@ -208,6 +245,15 @@ public class Login extends DefinedPacket
|
||||
{
|
||||
buf.writeBoolean( normalRespawn );
|
||||
}
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
buf.writeBoolean( limitedCrafting );
|
||||
writeString( (String) dimension, buf );
|
||||
writeString( worldName, buf );
|
||||
buf.writeLong( seed );
|
||||
buf.writeByte( gameMode );
|
||||
buf.writeByte( previousGameMode );
|
||||
}
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16 )
|
||||
{
|
||||
buf.writeBoolean( debug );
|
||||
|
@ -0,0 +1,37 @@
|
||||
package net.md_5.bungee.protocol.packet;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import net.md_5.bungee.protocol.AbstractPacketHandler;
|
||||
import net.md_5.bungee.protocol.DefinedPacket;
|
||||
import net.md_5.bungee.protocol.Protocol;
|
||||
import net.md_5.bungee.protocol.ProtocolConstants;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class LoginAcknowledged extends DefinedPacket
|
||||
{
|
||||
|
||||
@Override
|
||||
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public Protocol nextProtocol()
|
||||
{
|
||||
return Protocol.CONFIGURATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(AbstractPacketHandler handler) throws Exception
|
||||
{
|
||||
handler.handle( this );
|
||||
}
|
||||
}
|
@ -32,7 +32,7 @@ public class LoginRequest extends DefinedPacket
|
||||
}
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 )
|
||||
{
|
||||
if ( buf.readBoolean() )
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_2 || buf.readBoolean() )
|
||||
{
|
||||
uuid = readUUID( buf );
|
||||
}
|
||||
@ -48,6 +48,11 @@ public class LoginRequest extends DefinedPacket
|
||||
writePublicKey( publicKey, buf );
|
||||
}
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 )
|
||||
{
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
writeUUID( uuid, buf );
|
||||
} else
|
||||
{
|
||||
if ( uuid != null )
|
||||
{
|
||||
@ -59,6 +64,7 @@ public class LoginRequest extends DefinedPacket
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(AbstractPacketHandler handler) throws Exception
|
||||
|
@ -27,7 +27,7 @@ public class Respawn extends DefinedPacket
|
||||
private String levelType;
|
||||
private boolean debug;
|
||||
private boolean flat;
|
||||
private boolean copyMeta;
|
||||
private byte copyMeta;
|
||||
private Location deathLocation;
|
||||
private int portalCooldown;
|
||||
|
||||
@ -38,7 +38,7 @@ public class Respawn extends DefinedPacket
|
||||
{
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16_2 && protocolVersion < ProtocolConstants.MINECRAFT_1_19 )
|
||||
{
|
||||
dimension = readTag( buf );
|
||||
dimension = readTag( buf, protocolVersion );
|
||||
} else
|
||||
{
|
||||
dimension = readString( buf );
|
||||
@ -62,7 +62,10 @@ public class Respawn extends DefinedPacket
|
||||
previousGameMode = buf.readUnsignedByte();
|
||||
debug = buf.readBoolean();
|
||||
flat = buf.readBoolean();
|
||||
copyMeta = buf.readBoolean();
|
||||
if ( protocolVersion < ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
copyMeta = buf.readByte();
|
||||
}
|
||||
} else
|
||||
{
|
||||
levelType = readString( buf );
|
||||
@ -78,6 +81,10 @@ public class Respawn extends DefinedPacket
|
||||
{
|
||||
portalCooldown = readVarInt( buf );
|
||||
}
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
copyMeta = buf.readByte();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -87,7 +94,7 @@ public class Respawn extends DefinedPacket
|
||||
{
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16_2 && protocolVersion < ProtocolConstants.MINECRAFT_1_19 )
|
||||
{
|
||||
writeTag( (Tag) dimension, buf );
|
||||
writeTag( (Tag) dimension, buf, protocolVersion );
|
||||
} else
|
||||
{
|
||||
writeString( (String) dimension, buf );
|
||||
@ -111,7 +118,10 @@ public class Respawn extends DefinedPacket
|
||||
buf.writeByte( previousGameMode );
|
||||
buf.writeBoolean( debug );
|
||||
buf.writeBoolean( flat );
|
||||
buf.writeBoolean( copyMeta );
|
||||
if ( protocolVersion < ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
buf.writeByte( copyMeta );
|
||||
}
|
||||
} else
|
||||
{
|
||||
writeString( levelType, buf );
|
||||
@ -132,6 +142,10 @@ public class Respawn extends DefinedPacket
|
||||
{
|
||||
writeVarInt( portalCooldown, buf );
|
||||
}
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
buf.writeByte( copyMeta );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -7,6 +7,7 @@ import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import net.md_5.bungee.protocol.AbstractPacketHandler;
|
||||
import net.md_5.bungee.protocol.DefinedPacket;
|
||||
import net.md_5.bungee.protocol.ProtocolConstants;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@ -18,20 +19,32 @@ public class ScoreboardDisplay extends DefinedPacket
|
||||
/**
|
||||
* 0 = list, 1 = side, 2 = below.
|
||||
*/
|
||||
private byte position;
|
||||
private int position;
|
||||
private String name;
|
||||
|
||||
@Override
|
||||
public void read(ByteBuf buf)
|
||||
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
|
||||
{
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
position = readVarInt( buf );
|
||||
} else
|
||||
{
|
||||
position = buf.readByte();
|
||||
}
|
||||
name = readString( buf );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buf)
|
||||
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
|
||||
{
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
writeVarInt( position, buf );
|
||||
} else
|
||||
{
|
||||
buf.writeByte( position );
|
||||
}
|
||||
writeString( name, buf );
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,37 @@
|
||||
package net.md_5.bungee.protocol.packet;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import net.md_5.bungee.protocol.AbstractPacketHandler;
|
||||
import net.md_5.bungee.protocol.DefinedPacket;
|
||||
import net.md_5.bungee.protocol.Protocol;
|
||||
import net.md_5.bungee.protocol.ProtocolConstants;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class StartConfiguration extends DefinedPacket
|
||||
{
|
||||
|
||||
@Override
|
||||
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public Protocol nextProtocol()
|
||||
{
|
||||
return Protocol.CONFIGURATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(AbstractPacketHandler handler) throws Exception
|
||||
{
|
||||
handler.handle( this );
|
||||
}
|
||||
}
|
@ -4,15 +4,14 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-proxy</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-Proxy</name>
|
||||
@ -52,37 +51,37 @@
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-log</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-native</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-protocol</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-query</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-slf4j</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
@ -96,26 +95,26 @@
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
<version>8.0.33</version>
|
||||
<version>8.1.0</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<!-- add these back in as they are not exposed by the API -->
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-resolver-provider</artifactId>
|
||||
<version>3.9.2</version>
|
||||
<version>3.8.5</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.resolver</groupId>
|
||||
<artifactId>maven-resolver-connector-basic</artifactId>
|
||||
<version>1.9.10</version>
|
||||
<version>1.7.3</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.resolver</groupId>
|
||||
<artifactId>maven-resolver-transport-http</artifactId>
|
||||
<version>1.9.10</version>
|
||||
<version>1.7.3</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
@ -89,7 +89,6 @@ import net.md_5.bungee.forge.ForgeConstants;
|
||||
import net.md_5.bungee.log.BungeeLogger;
|
||||
import net.md_5.bungee.log.LoggingForwardHandler;
|
||||
import net.md_5.bungee.log.LoggingOutputStream;
|
||||
import net.md_5.bungee.module.ModuleManager;
|
||||
import net.md_5.bungee.netty.PipelineUtils;
|
||||
import net.md_5.bungee.protocol.DefinedPacket;
|
||||
import net.md_5.bungee.protocol.ProtocolConstants;
|
||||
@ -173,7 +172,6 @@ public class BungeeCord extends ProxyServer
|
||||
.registerTypeAdapter( Favicon.class, Favicon.getFaviconTypeAdapter() ).create();
|
||||
@Getter
|
||||
private ConnectionThrottle connectionThrottle;
|
||||
private final ModuleManager moduleManager = new ModuleManager();
|
||||
|
||||
{
|
||||
// TODO: Proper fallback when we interface the manager
|
||||
@ -271,10 +269,6 @@ public class BungeeCord extends ProxyServer
|
||||
|
||||
eventLoops = PipelineUtils.newEventLoopGroup( 0, new ThreadFactoryBuilder().setNameFormat( "Netty IO Thread #%1$d" ).build() );
|
||||
|
||||
File moduleDirectory = new File( "modules" );
|
||||
moduleManager.load( this, moduleDirectory );
|
||||
pluginManager.detectPlugins( moduleDirectory );
|
||||
|
||||
pluginsFolder.mkdir();
|
||||
pluginManager.detectPlugins( pluginsFolder );
|
||||
|
||||
|
@ -5,7 +5,6 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import joptsimple.OptionParser;
|
||||
import joptsimple.OptionSet;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
@ -56,8 +55,7 @@ public class BungeeCordLauncher
|
||||
System.err.println( "*** Warning, this build is outdated ***" );
|
||||
System.err.println( "*** Please download a new build from http://ci.md-5.net/job/BungeeCord ***" );
|
||||
System.err.println( "*** You will get NO support regarding this build ***" );
|
||||
System.err.println( "*** Server will start in 10 seconds ***" );
|
||||
Thread.sleep( TimeUnit.SECONDS.toMillis( 10 ) );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,26 +103,30 @@ public class BungeeServerInfo implements ServerInfo
|
||||
sendData( channel, data, true );
|
||||
}
|
||||
|
||||
// TODO: Don't like this method
|
||||
@Override
|
||||
public boolean sendData(String channel, byte[] data, boolean queue)
|
||||
{
|
||||
Preconditions.checkNotNull( channel, "channel" );
|
||||
Preconditions.checkNotNull( data, "data" );
|
||||
|
||||
synchronized ( packetQueue )
|
||||
Server server;
|
||||
synchronized ( players )
|
||||
{
|
||||
Server server = ( players.isEmpty() ) ? null : players.iterator().next().getServer();
|
||||
server = ( players.isEmpty() ) ? null : players.iterator().next().getServer();
|
||||
}
|
||||
|
||||
if ( server != null )
|
||||
{
|
||||
server.sendData( channel, data );
|
||||
return true;
|
||||
} else if ( queue )
|
||||
{
|
||||
synchronized ( packetQueue )
|
||||
{
|
||||
packetQueue.add( new PluginMessage( channel, data, false ) );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private long lastPing;
|
||||
|
@ -43,6 +43,7 @@ import net.md_5.bungee.protocol.packet.GameState;
|
||||
import net.md_5.bungee.protocol.packet.Handshake;
|
||||
import net.md_5.bungee.protocol.packet.Kick;
|
||||
import net.md_5.bungee.protocol.packet.Login;
|
||||
import net.md_5.bungee.protocol.packet.LoginAcknowledged;
|
||||
import net.md_5.bungee.protocol.packet.LoginPayloadRequest;
|
||||
import net.md_5.bungee.protocol.packet.LoginPayloadResponse;
|
||||
import net.md_5.bungee.protocol.packet.LoginRequest;
|
||||
@ -52,6 +53,7 @@ import net.md_5.bungee.protocol.packet.Respawn;
|
||||
import net.md_5.bungee.protocol.packet.ScoreboardObjective;
|
||||
import net.md_5.bungee.protocol.packet.ScoreboardScore;
|
||||
import net.md_5.bungee.protocol.packet.SetCompression;
|
||||
import net.md_5.bungee.protocol.packet.StartConfiguration;
|
||||
import net.md_5.bungee.protocol.packet.ViewDistance;
|
||||
import net.md_5.bungee.util.AddressUtil;
|
||||
import net.md_5.bungee.util.BufUtil;
|
||||
@ -73,7 +75,7 @@ public class ServerConnector extends PacketHandler
|
||||
private enum State
|
||||
{
|
||||
|
||||
LOGIN_SUCCESS, ENCRYPT_RESPONSE, LOGIN, FINISHED;
|
||||
LOGIN_SUCCESS, LOGIN, FINISHED;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -84,13 +86,13 @@ public class ServerConnector extends PacketHandler
|
||||
return;
|
||||
}
|
||||
|
||||
String message = "Exception Connecting:" + Util.exception( t );
|
||||
String message = ChatColor.RED + "Exception Connecting: " + Util.exception( t );
|
||||
if ( user.getServer() == null )
|
||||
{
|
||||
user.disconnect( message );
|
||||
} else
|
||||
{
|
||||
user.sendMessage( ChatColor.RED + message );
|
||||
user.sendMessage( message );
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,8 +147,15 @@ public class ServerConnector extends PacketHandler
|
||||
public void handle(LoginSuccess loginSuccess) throws Exception
|
||||
{
|
||||
Preconditions.checkState( thisState == State.LOGIN_SUCCESS, "Not expecting LOGIN_SUCCESS" );
|
||||
if ( user.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
ServerConnection server = new ServerConnection( ch, target );
|
||||
cutThrough( server );
|
||||
} else
|
||||
{
|
||||
ch.setProtocol( Protocol.GAME );
|
||||
thisState = State.LOGIN;
|
||||
}
|
||||
|
||||
// Only reset the Forge client when:
|
||||
// 1) The user is switching servers (so has a current server)
|
||||
@ -182,6 +191,12 @@ public class ServerConnector extends PacketHandler
|
||||
Preconditions.checkState( thisState == State.LOGIN, "Not expecting LOGIN" );
|
||||
|
||||
ServerConnection server = new ServerConnection( ch, target );
|
||||
handleLogin( bungee, ch, user, target, handshakeHandler, server, login );
|
||||
cutThrough( server );
|
||||
}
|
||||
|
||||
public static void handleLogin(ProxyServer bungee, ChannelWrapper ch, UserConnection user, BungeeServerInfo target, ForgeServerHandler handshakeHandler, ServerConnection server, Login login) throws Exception
|
||||
{
|
||||
ServerConnectedEvent event = new ServerConnectedEvent( user, server );
|
||||
bungee.getPluginManager().callEvent( event );
|
||||
|
||||
@ -225,14 +240,13 @@ public class ServerConnector extends PacketHandler
|
||||
|
||||
// Set tab list size, TODO: what shall we do about packet mutability
|
||||
Login modLogin = new Login( login.getEntityId(), login.isHardcore(), login.getGameMode(), login.getPreviousGameMode(), login.getWorldNames(), login.getDimensions(), login.getDimension(), login.getWorldName(), login.getSeed(), login.getDifficulty(),
|
||||
(byte) user.getPendingConnection().getListener().getTabListSize(), login.getLevelType(), login.getViewDistance(), login.getSimulationDistance(), login.isReducedDebugInfo(), login.isNormalRespawn(), login.isDebug(), login.isFlat(), login.getDeathLocation(),
|
||||
(byte) user.getPendingConnection().getListener().getTabListSize(), login.getLevelType(), login.getViewDistance(), login.getSimulationDistance(), login.isReducedDebugInfo(), login.isNormalRespawn(), login.isLimitedCrafting(), login.isDebug(), login.isFlat(), login.getDeathLocation(),
|
||||
login.getPortalCooldown() );
|
||||
|
||||
user.unsafe().sendPacket( modLogin );
|
||||
|
||||
if ( user.getServer() != null )
|
||||
if ( user.getDimension() != null )
|
||||
{
|
||||
user.getServer().setObsolete( true );
|
||||
user.getTabListHandler().onServerChange();
|
||||
|
||||
user.getServerSentScoreboard().clear();
|
||||
@ -244,14 +258,15 @@ public class ServerConnector extends PacketHandler
|
||||
}
|
||||
user.getSentBossBars().clear();
|
||||
|
||||
user.unsafe().sendPacket( new Respawn( login.getDimension(), login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(), false, login.getDeathLocation(),
|
||||
user.unsafe().sendPacket( new Respawn( login.getDimension(), login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(), (byte) 0, login.getDeathLocation(),
|
||||
login.getPortalCooldown() ) );
|
||||
user.getServer().disconnect( "Quitting" );
|
||||
} else
|
||||
{
|
||||
user.unsafe().sendPacket( BungeeCord.getInstance().registerChannels( user.getPendingConnection().getVersion() ) );
|
||||
|
||||
ByteBuf brand = ByteBufAllocator.DEFAULT.heapBuffer();
|
||||
DefinedPacket.writeString( bungee.getName() + " (" + bungee.getVersion() + ")", brand );
|
||||
user.unsafe().sendPacket( new PluginMessage( user.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_13 ? "minecraft:brand" : "MC|Brand", DefinedPacket.toArray( brand ), handshakeHandler.isServerForge() ) );
|
||||
user.unsafe().sendPacket( new PluginMessage( user.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_13 ? "minecraft:brand" : "MC|Brand", DefinedPacket.toArray( brand ), handshakeHandler != null && handshakeHandler.isServerForge() ) );
|
||||
brand.release();
|
||||
}
|
||||
|
||||
@ -295,19 +310,40 @@ public class ServerConnector extends PacketHandler
|
||||
if ( login.getDimension() == user.getDimension() )
|
||||
{
|
||||
user.unsafe().sendPacket( new Respawn( (Integer) login.getDimension() >= 0 ? -1 : 0, login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(),
|
||||
false, login.getDeathLocation(), login.getPortalCooldown() ) );
|
||||
(byte) 0, login.getDeathLocation(), login.getPortalCooldown() ) );
|
||||
}
|
||||
|
||||
user.setServerEntityId( login.getEntityId() );
|
||||
user.unsafe().sendPacket( new Respawn( login.getDimension(), login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(),
|
||||
false, login.getDeathLocation(), login.getPortalCooldown() ) );
|
||||
(byte) 0, login.getDeathLocation(), login.getPortalCooldown() ) );
|
||||
if ( user.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_14 )
|
||||
{
|
||||
user.unsafe().sendPacket( new ViewDistance( login.getViewDistance() ) );
|
||||
}
|
||||
user.setDimension( login.getDimension() );
|
||||
}
|
||||
}
|
||||
|
||||
private void cutThrough(ServerConnection server)
|
||||
{
|
||||
if ( user.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
if ( user.getServer() != null )
|
||||
{
|
||||
// Begin config mode
|
||||
user.unsafe().sendPacket( new StartConfiguration() );
|
||||
} else
|
||||
{
|
||||
ch.setDecodeProtocol( Protocol.CONFIGURATION );
|
||||
ch.write( new LoginAcknowledged() );
|
||||
ch.setEncodeProtocol( Protocol.CONFIGURATION );
|
||||
}
|
||||
}
|
||||
|
||||
// Remove from old servers
|
||||
if ( user.getServer() != null )
|
||||
{
|
||||
user.getServer().setObsolete( true );
|
||||
user.getServer().disconnect( "Quitting" );
|
||||
}
|
||||
|
||||
|
@ -72,6 +72,7 @@ public final class UserConnection implements ProxiedPlayer
|
||||
/*========================================================================*/
|
||||
@NonNull
|
||||
private final ProxyServer bungee;
|
||||
@Getter
|
||||
@NonNull
|
||||
private final ChannelWrapper ch;
|
||||
@Getter
|
||||
@ -124,6 +125,9 @@ public final class UserConnection implements ProxiedPlayer
|
||||
private final Scoreboard serverSentScoreboard = new Scoreboard();
|
||||
@Getter
|
||||
private final Collection<UUID> sentBossBars = new HashSet<>();
|
||||
@Getter
|
||||
@Setter
|
||||
private String lastCommandTabbed;
|
||||
/*========================================================================*/
|
||||
@Getter
|
||||
private String displayName;
|
||||
|
@ -6,6 +6,7 @@ import com.google.common.collect.Lists;
|
||||
import com.google.common.io.ByteArrayDataOutput;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||
import com.mojang.brigadier.context.StringRange;
|
||||
@ -19,11 +20,17 @@ import io.netty.channel.unix.DomainSocketAddress;
|
||||
import java.io.DataInput;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.logging.Level;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.md_5.bungee.ServerConnection;
|
||||
import net.md_5.bungee.ServerConnection.KeepAliveData;
|
||||
import net.md_5.bungee.ServerConnector;
|
||||
import net.md_5.bungee.UserConnection;
|
||||
import net.md_5.bungee.Util;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
@ -31,6 +38,8 @@ import net.md_5.bungee.api.chat.BaseComponent;
|
||||
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.connection.Server;
|
||||
import net.md_5.bungee.api.event.CommandsDeclareEvent;
|
||||
import net.md_5.bungee.api.event.PluginMessageEvent;
|
||||
import net.md_5.bungee.api.event.ServerConnectEvent;
|
||||
import net.md_5.bungee.api.event.ServerDisconnectEvent;
|
||||
@ -48,11 +57,13 @@ import net.md_5.bungee.netty.ChannelWrapper;
|
||||
import net.md_5.bungee.netty.PacketHandler;
|
||||
import net.md_5.bungee.protocol.DefinedPacket;
|
||||
import net.md_5.bungee.protocol.PacketWrapper;
|
||||
import net.md_5.bungee.protocol.Protocol;
|
||||
import net.md_5.bungee.protocol.ProtocolConstants;
|
||||
import net.md_5.bungee.protocol.packet.BossBar;
|
||||
import net.md_5.bungee.protocol.packet.Commands;
|
||||
import net.md_5.bungee.protocol.packet.KeepAlive;
|
||||
import net.md_5.bungee.protocol.packet.Kick;
|
||||
import net.md_5.bungee.protocol.packet.Login;
|
||||
import net.md_5.bungee.protocol.packet.PlayerListItem;
|
||||
import net.md_5.bungee.protocol.packet.PlayerListItemRemove;
|
||||
import net.md_5.bungee.protocol.packet.PlayerListItemUpdate;
|
||||
@ -80,6 +91,7 @@ public class DownstreamBridge extends PacketHandler
|
||||
private final ProxyServer bungee;
|
||||
private final UserConnection con;
|
||||
private final ServerConnection server;
|
||||
private boolean receivedLogin;
|
||||
|
||||
@Override
|
||||
public void exception(Throwable t) throws Exception
|
||||
@ -131,7 +143,7 @@ public class DownstreamBridge extends PacketHandler
|
||||
public void handle(PacketWrapper packet) throws Exception
|
||||
{
|
||||
EntityMap rewrite = con.getEntityRewrite();
|
||||
if ( rewrite != null )
|
||||
if ( rewrite != null && con.getCh().getEncodeProtocol() == Protocol.GAME )
|
||||
{
|
||||
rewrite.rewriteClientbound( packet.buf, con.getServerEntityId(), con.getClientEntityId(), con.getPendingConnection().getVersion() );
|
||||
}
|
||||
@ -292,7 +304,7 @@ public class DownstreamBridge extends PacketHandler
|
||||
Preconditions.checkState( !serverBrand.contains( bungee.getName() ), "Cannot connect proxy to itself!" );
|
||||
|
||||
brand = ByteBufAllocator.DEFAULT.heapBuffer();
|
||||
DefinedPacket.writeString( bungee.getName() + " (" + bungee.getVersion() + ")" + " <- " + serverBrand, brand );
|
||||
DefinedPacket.writeString( bungee.getName() + " (" + bungee.getVersion() + ")" + " <- " + server.getInfo().getName() + " (" + serverBrand + ")", brand );
|
||||
pluginMessage.setData( DefinedPacket.toArray( brand ) );
|
||||
brand.release();
|
||||
// changes in the packet are ignored so we need to send it manually
|
||||
@ -401,6 +413,27 @@ public class DownstreamBridge extends PacketHandler
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "GetPlayerServer":
|
||||
{
|
||||
String name = in.readUTF();
|
||||
ProxiedPlayer player = bungee.getPlayer( name );
|
||||
out.writeUTF( "GetPlayerServer" );
|
||||
out.writeUTF( name );
|
||||
if ( player == null )
|
||||
{
|
||||
out.writeUTF( "" );
|
||||
break;
|
||||
}
|
||||
Server srv = player.getServer();
|
||||
if ( srv == null )
|
||||
{
|
||||
out.writeUTF( "" );
|
||||
} else
|
||||
{
|
||||
out.writeUTF( srv.getInfo().getName() );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "IP":
|
||||
out.writeUTF( "IP" );
|
||||
if ( con.getSocketAddress() instanceof InetSocketAddress )
|
||||
@ -562,6 +595,16 @@ public class DownstreamBridge extends PacketHandler
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "KickPlayerRaw":
|
||||
{
|
||||
ProxiedPlayer player = bungee.getPlayer( in.readUTF() );
|
||||
if ( player != null )
|
||||
{
|
||||
BaseComponent[] kickReason = ComponentSerializer.parse( in.readUTF() );
|
||||
player.disconnect( kickReason );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check we haven't set out to null, and we have written data, if so reply back back along the BungeeCord channel
|
||||
@ -614,6 +657,23 @@ public class DownstreamBridge extends PacketHandler
|
||||
return input.getText();
|
||||
}
|
||||
} );
|
||||
} else
|
||||
{
|
||||
String last = con.getLastCommandTabbed();
|
||||
if ( last != null )
|
||||
{
|
||||
String commandName = last.toLowerCase( Locale.ROOT );
|
||||
commands.addAll( bungee.getPluginManager().getCommands().stream()
|
||||
.filter( (entry) ->
|
||||
{
|
||||
String lowerCase = entry.getKey().toLowerCase( Locale.ROOT );
|
||||
return lowerCase.startsWith( commandName ) && entry.getValue().hasPermission( con ) && !bungee.getDisabledCommands().contains( lowerCase );
|
||||
} )
|
||||
.map( (stringCommandEntry) -> '/' + stringCommandEntry.getKey() )
|
||||
.collect( Collectors.toList() ) );
|
||||
commands.sort( null );
|
||||
con.setLastCommandTabbed( null );
|
||||
}
|
||||
}
|
||||
|
||||
TabCompleteResponseEvent tabCompleteResponseEvent = new TabCompleteResponseEvent( server, con, new ArrayList<>( commands ) );
|
||||
@ -674,6 +734,11 @@ public class DownstreamBridge extends PacketHandler
|
||||
{
|
||||
boolean modified = false;
|
||||
|
||||
CommandsDeclareEvent commandsDeclareEvent = new CommandsDeclareEvent( server, con, commands.getRoot() );
|
||||
bungee.getPluginManager().callEvent( commandsDeclareEvent );
|
||||
|
||||
modified = commandsDeclareEvent.isModified();
|
||||
|
||||
for ( Map.Entry<String, Command> command : bungee.getPluginManager().getCommands() )
|
||||
{
|
||||
if ( !bungee.getDisabledCommands().contains( command.getKey() ) && commands.getRoot().getChild( command.getKey() ) == null && command.getValue().hasPermission( con ) )
|
||||
@ -690,11 +755,65 @@ public class DownstreamBridge extends PacketHandler
|
||||
|
||||
if ( modified )
|
||||
{
|
||||
commands.setRoot( (com.mojang.brigadier.tree.RootCommandNode) filterCommandNode( commands.getRoot(), new IdentityHashMap<>() ) );
|
||||
con.unsafe().sendPacket( commands );
|
||||
throw CancelSendSignal.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a deep copy of the provided command node but removes any node that are not accessible by the player
|
||||
* (using {@link CommandNode#getRequirement()})
|
||||
*/
|
||||
private CommandNode filterCommandNode(CommandNode source, IdentityHashMap<CommandNode, CommandNode> commandNodeMapping)
|
||||
{
|
||||
CommandNode dest;
|
||||
if ( source instanceof com.mojang.brigadier.tree.RootCommandNode )
|
||||
{
|
||||
dest = new com.mojang.brigadier.tree.RootCommandNode();
|
||||
} else
|
||||
{
|
||||
if ( source.getRequirement() != null )
|
||||
{
|
||||
try
|
||||
{
|
||||
if ( !source.getRequirement().test( con ) )
|
||||
{
|
||||
commandNodeMapping.put( source, null );
|
||||
return null;
|
||||
}
|
||||
} catch ( Throwable t )
|
||||
{
|
||||
ProxyServer.getInstance().getLogger().log( Level.SEVERE, "Requirement test for command node " + source + " encountered an exception", t );
|
||||
}
|
||||
}
|
||||
|
||||
ArgumentBuilder destChildBuilder = source.createBuilder();
|
||||
destChildBuilder.requires( sender -> true );
|
||||
if ( destChildBuilder.getRedirect() != null )
|
||||
{
|
||||
if ( commandNodeMapping.containsKey( destChildBuilder.getRedirect() ) )
|
||||
destChildBuilder.redirect( commandNodeMapping.get( destChildBuilder.getRedirect() ) );
|
||||
else
|
||||
destChildBuilder.redirect( filterCommandNode( destChildBuilder.getRedirect(), commandNodeMapping ) );
|
||||
}
|
||||
|
||||
dest = destChildBuilder.build();
|
||||
}
|
||||
|
||||
commandNodeMapping.put( source, dest );
|
||||
|
||||
for ( CommandNode sourceChild : (Collection<CommandNode>) source.getChildren() )
|
||||
{
|
||||
CommandNode destChild = filterCommandNode( sourceChild, commandNodeMapping );
|
||||
if ( destChild == null )
|
||||
continue;
|
||||
dest.addChild( destChild );
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(ServerData serverData) throws Exception
|
||||
{
|
||||
@ -705,6 +824,17 @@ public class DownstreamBridge extends PacketHandler
|
||||
throw CancelSendSignal.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Login login) throws Exception
|
||||
{
|
||||
Preconditions.checkState( !receivedLogin, "Not expecting login" );
|
||||
|
||||
receivedLogin = true;
|
||||
ServerConnector.handleLogin( bungee, server.getCh(), con, server.getInfo(), null, server, login );
|
||||
|
||||
throw CancelSendSignal.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
|
@ -59,6 +59,7 @@ import net.md_5.bungee.protocol.packet.Handshake;
|
||||
import net.md_5.bungee.protocol.packet.Kick;
|
||||
import net.md_5.bungee.protocol.packet.LegacyHandshake;
|
||||
import net.md_5.bungee.protocol.packet.LegacyPing;
|
||||
import net.md_5.bungee.protocol.packet.LoginAcknowledged;
|
||||
import net.md_5.bungee.protocol.packet.LoginPayloadResponse;
|
||||
import net.md_5.bungee.protocol.packet.LoginRequest;
|
||||
import net.md_5.bungee.protocol.packet.LoginSuccess;
|
||||
@ -111,6 +112,16 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
private boolean legacy;
|
||||
@Getter
|
||||
private String extraDataInHandshake = "";
|
||||
private UserConnection userCon;
|
||||
|
||||
@Getter
|
||||
private boolean duplication = false;
|
||||
|
||||
@Getter
|
||||
private String realName = null;
|
||||
|
||||
@Getter
|
||||
private UUID realId = null;
|
||||
|
||||
@Override
|
||||
public boolean shouldHandle(PacketWrapper packet) throws Exception
|
||||
@ -121,12 +132,12 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
private enum State
|
||||
{
|
||||
|
||||
HANDSHAKE, STATUS, PING, USERNAME, ENCRYPT, FINISHING;
|
||||
HANDSHAKE, STATUS, PING, USERNAME, ENCRYPT, FINISHING, CONFIGURING;
|
||||
}
|
||||
|
||||
private boolean canSendKickMessage()
|
||||
{
|
||||
return thisState == State.USERNAME || thisState == State.ENCRYPT || thisState == State.FINISHING;
|
||||
return thisState == State.USERNAME || thisState == State.ENCRYPT || thisState == State.FINISHING || thisState == State.CONFIGURING;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -409,6 +420,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
}
|
||||
|
||||
this.loginRequest = loginRequest;
|
||||
setName( realName = loginRequest.getData() );
|
||||
|
||||
int limit = BungeeCord.getInstance().config.getPlayerLimit();
|
||||
if ( limit > 0 && bungee.getOnlineCount() >= limit )
|
||||
@ -417,14 +429,6 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
return;
|
||||
}
|
||||
|
||||
// If offline mode and they are already on, don't allow connect
|
||||
// We can just check by UUID here as names are based on UUID
|
||||
if ( !isOnlineMode() && bungee.getPlayer( getUniqueId() ) != null )
|
||||
{
|
||||
disconnect( bungee.getTranslation( "already_connected_proxy" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
Callback<PreLoginEvent> callback = new Callback<PreLoginEvent>()
|
||||
{
|
||||
|
||||
@ -441,6 +445,16 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
{
|
||||
return;
|
||||
}
|
||||
if ( !realName.equals( name ) )
|
||||
{
|
||||
// Floodgate changes the name attribute with reflexion
|
||||
setName( realName = name );
|
||||
}
|
||||
if ( uniqueId != null )
|
||||
{
|
||||
// if plugin called setUniqueId()
|
||||
realId = uniqueId;
|
||||
}
|
||||
if ( onlineMode )
|
||||
{
|
||||
thisState = State.ENCRYPT;
|
||||
@ -495,8 +509,8 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
if ( obj != null && obj.getId() != null )
|
||||
{
|
||||
loginProfile = obj;
|
||||
name = obj.getName();
|
||||
uniqueId = Util.getUUID( obj.getId() );
|
||||
setName( realName = obj.getName() );
|
||||
uniqueId = realId = Util.getUUID( obj.getId() );
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
@ -514,10 +528,25 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
|
||||
private void finish()
|
||||
{
|
||||
offlineId = UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + getName() ).getBytes( Charsets.UTF_8 ) );
|
||||
if ( uniqueId == null )
|
||||
if ( uniqueId == null ) // offline mode and no plugin used setUniqueId()
|
||||
{
|
||||
uniqueId = offlineId;
|
||||
uniqueId = realId = offlineId;
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point, player is either authenticated by Mojang (online mode),
|
||||
* by a plugin (Floodgate ?) or the offline id is set.
|
||||
*/
|
||||
ProxiedPlayer existingPlayer = bungee.getPlayer( uniqueId );
|
||||
if ( existingPlayer != null && existingPlayer.hasPermission( "bungeecord.multiple_connect" ) )
|
||||
{
|
||||
UUID newId = generateDuplicatedId( uniqueId );
|
||||
if ( !uniqueId.equals( newId ) )
|
||||
{
|
||||
uniqueId = newId;
|
||||
setName( name + "." + getDuplicationIndex( newId ) );
|
||||
duplication = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( BungeeCord.getInstance().config.isEnforceSecureProfile() )
|
||||
@ -593,12 +622,40 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
{
|
||||
if ( !ch.isClosing() )
|
||||
{
|
||||
UserConnection userCon = new UserConnection( bungee, ch, getName(), InitialHandler.this );
|
||||
userCon = new UserConnection( bungee, ch, getName(), InitialHandler.this );
|
||||
userCon.setCompressionThreshold( BungeeCord.getInstance().config.getCompressionThreshold() );
|
||||
userCon.init();
|
||||
|
||||
unsafe.sendPacket( new LoginSuccess( getUniqueId(), getName(), ( loginProfile == null ) ? null : loginProfile.getProperties() ) );
|
||||
if ( getVersion() >= ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
thisState = State.CONFIGURING;
|
||||
} else
|
||||
{
|
||||
ch.setProtocol( Protocol.GAME );
|
||||
finish2();
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
};
|
||||
|
||||
// fire login event
|
||||
bungee.getPluginManager().callEvent( new LoginEvent( InitialHandler.this, complete ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(LoginAcknowledged loginAcknowledged) throws Exception
|
||||
{
|
||||
Preconditions.checkState( thisState == State.CONFIGURING, "Not expecting CONFIGURING" );
|
||||
|
||||
finish2();
|
||||
ch.setEncodeProtocol( Protocol.CONFIGURATION );
|
||||
}
|
||||
|
||||
private void finish2()
|
||||
{
|
||||
userCon.init();
|
||||
|
||||
ch.getHandle().pipeline().get( HandlerBoss.class ).setHandler( new UpstreamBridge( bungee, userCon ) );
|
||||
bungee.getPluginManager().callEvent( new PostLoginEvent( userCon ) );
|
||||
@ -617,14 +674,6 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
|
||||
userCon.connect( server, null, true, ServerConnectEvent.Reason.JOIN_PROXY );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
};
|
||||
|
||||
// fire login event
|
||||
bungee.getPluginManager().callEvent( new LoginEvent( InitialHandler.this, complete ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(LoginPayloadResponse response) throws Exception
|
||||
@ -671,6 +720,54 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
return ( name != null ) ? name : ( loginRequest == null ) ? null : loginRequest.getData();
|
||||
}
|
||||
|
||||
private void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
if ( loginRequest != null )
|
||||
{
|
||||
loginRequest.setData( name ); // name transmitted to Spigot server
|
||||
}
|
||||
updateOfflineId();
|
||||
}
|
||||
|
||||
private UUID generateDuplicatedId(UUID base)
|
||||
{
|
||||
// UUID version: offline = 3 ; Java online mode = 4 ; Floodgate xUID = 0 (and must be kept 0)
|
||||
// UUID variant: offline = 0xx ; Java online mode = 10x ; Floodgate xUID = xxx
|
||||
if ( base.version() == 0 )
|
||||
{
|
||||
/*
|
||||
* Floodgate’s xUID converted to UUID are not supported
|
||||
* because it requires the 64 MSBs to be 0 (or Floodgate API would not
|
||||
* recognize a Bedrock account) and we cannot modify the 64 LSBs
|
||||
* without risking a collision with the xUID of another Bedrock account
|
||||
*/
|
||||
return base;
|
||||
}
|
||||
long MSB = base.getMostSignificantBits();
|
||||
long LSB = base.getLeastSignificantBits();
|
||||
|
||||
MSB &= 0xFFFFFFFF_FFFF_70FFL; // reset bits we need
|
||||
MSB |= 0x00000000_0000_8000L; // set version to + 8 the current version
|
||||
|
||||
for ( int i = 1; i <= 9; i++ )
|
||||
{
|
||||
long newMSB = MSB | i << 8;
|
||||
UUID newUUID = new UUID( newMSB, LSB );
|
||||
if ( bungee.getPlayer( newUUID ) != null )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return newUUID;
|
||||
}
|
||||
return base; // there are too many duplicated connections for this player
|
||||
}
|
||||
|
||||
private static int getDuplicationIndex(UUID duplicatedId)
|
||||
{
|
||||
return (int) ( duplicatedId.getMostSignificantBits() >> 8 ) & 0xF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVersion()
|
||||
{
|
||||
@ -710,6 +807,11 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
this.uniqueId = uuid;
|
||||
}
|
||||
|
||||
private void updateOfflineId()
|
||||
{
|
||||
offlineId = UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + getName() ).getBytes( Charsets.UTF_8 ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUUID()
|
||||
{
|
||||
|
@ -6,7 +6,6 @@ import com.mojang.brigadier.suggestion.Suggestion;
|
||||
import com.mojang.brigadier.suggestion.Suggestions;
|
||||
import io.netty.channel.Channel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import net.md_5.bungee.BungeeCord;
|
||||
@ -20,20 +19,24 @@ import net.md_5.bungee.api.event.PlayerDisconnectEvent;
|
||||
import net.md_5.bungee.api.event.PluginMessageEvent;
|
||||
import net.md_5.bungee.api.event.SettingsChangedEvent;
|
||||
import net.md_5.bungee.api.event.TabCompleteEvent;
|
||||
import net.md_5.bungee.api.event.TabCompleteRequestEvent;
|
||||
import net.md_5.bungee.entitymap.EntityMap;
|
||||
import net.md_5.bungee.forge.ForgeConstants;
|
||||
import net.md_5.bungee.netty.ChannelWrapper;
|
||||
import net.md_5.bungee.netty.PacketHandler;
|
||||
import net.md_5.bungee.protocol.PacketWrapper;
|
||||
import net.md_5.bungee.protocol.Protocol;
|
||||
import net.md_5.bungee.protocol.ProtocolConstants;
|
||||
import net.md_5.bungee.protocol.packet.Chat;
|
||||
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.KeepAlive;
|
||||
import net.md_5.bungee.protocol.packet.LoginAcknowledged;
|
||||
import net.md_5.bungee.protocol.packet.PlayerListItem;
|
||||
import net.md_5.bungee.protocol.packet.PlayerListItemRemove;
|
||||
import net.md_5.bungee.protocol.packet.PluginMessage;
|
||||
import net.md_5.bungee.protocol.packet.StartConfiguration;
|
||||
import net.md_5.bungee.protocol.packet.TabCompleteRequest;
|
||||
import net.md_5.bungee.protocol.packet.TabCompleteResponse;
|
||||
import net.md_5.bungee.util.AllowedCharacters;
|
||||
@ -51,7 +54,6 @@ public class UpstreamBridge extends PacketHandler
|
||||
|
||||
BungeeCord.getInstance().addConnection( con );
|
||||
con.getTabListHandler().onConnect();
|
||||
con.unsafe().sendPacket( BungeeCord.getInstance().registerChannels( con.getPendingConnection().getVersion() ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -134,7 +136,7 @@ public class UpstreamBridge extends PacketHandler
|
||||
if ( con.getServer() != null )
|
||||
{
|
||||
EntityMap rewrite = con.getEntityRewrite();
|
||||
if ( rewrite != null )
|
||||
if ( rewrite != null && con.getServer().getCh().getEncodeProtocol() == Protocol.GAME )
|
||||
{
|
||||
rewrite.rewriteServerbound( packet.buf, con.getClientEntityId(), con.getServerEntityId(), con.getPendingConnection().getVersion() );
|
||||
}
|
||||
@ -213,8 +215,9 @@ public class UpstreamBridge extends PacketHandler
|
||||
{
|
||||
List<String> suggestions = new ArrayList<>();
|
||||
boolean isRegisteredCommand = false;
|
||||
boolean isCommand = tabComplete.getCursor().startsWith( "/" );
|
||||
|
||||
if ( tabComplete.getCursor().startsWith( "/" ) )
|
||||
if ( isCommand )
|
||||
{
|
||||
isRegisteredCommand = bungee.getPluginManager().dispatchCommand( con, tabComplete.getCursor().substring( 1 ), suggestions );
|
||||
}
|
||||
@ -222,32 +225,42 @@ public class UpstreamBridge extends PacketHandler
|
||||
TabCompleteEvent tabCompleteEvent = new TabCompleteEvent( con, con.getServer(), tabComplete.getCursor(), suggestions );
|
||||
bungee.getPluginManager().callEvent( tabCompleteEvent );
|
||||
|
||||
if ( tabCompleteEvent.isCancelled() )
|
||||
List<String> legacyResults = tabCompleteEvent.getSuggestions();
|
||||
|
||||
int start = tabComplete.getCursor().lastIndexOf( ' ' ) + 1;
|
||||
int end = tabComplete.getCursor().length();
|
||||
StringRange lastArgumentRange = StringRange.between( start, end );
|
||||
|
||||
List<Suggestion> brigadier = new ArrayList<>( legacyResults.size() );
|
||||
for ( String s : legacyResults )
|
||||
{
|
||||
brigadier.add( new Suggestion( lastArgumentRange, s ) );
|
||||
}
|
||||
|
||||
TabCompleteRequestEvent tabCompleteRequestEvent = new TabCompleteRequestEvent( con, con.getServer(), tabComplete.getCursor(), lastArgumentRange, new Suggestions( lastArgumentRange, brigadier ) );
|
||||
tabCompleteRequestEvent.setCancelled( tabCompleteEvent.isCancelled() );
|
||||
bungee.getPluginManager().callEvent( tabCompleteRequestEvent );
|
||||
|
||||
if ( tabCompleteRequestEvent.isCancelled() )
|
||||
{
|
||||
throw CancelSendSignal.INSTANCE;
|
||||
}
|
||||
|
||||
List<String> results = tabCompleteEvent.getSuggestions();
|
||||
if ( !results.isEmpty() )
|
||||
Suggestions brigadierResults = tabCompleteRequestEvent.getSuggestions();
|
||||
|
||||
if ( !brigadierResults.isEmpty() )
|
||||
{
|
||||
// Unclear how to handle 1.13 commands at this point. Because we don't inject into the command packets we are unlikely to get this far unless
|
||||
// Bungee plugins are adding results for commands they don't own anyway
|
||||
if ( con.getPendingConnection().getVersion() < ProtocolConstants.MINECRAFT_1_13 )
|
||||
{
|
||||
List<String> results = new ArrayList<>( brigadierResults.getList().size() );
|
||||
for ( Suggestion s : brigadierResults.getList() )
|
||||
{
|
||||
results.add( s.getText() );
|
||||
}
|
||||
con.unsafe().sendPacket( new TabCompleteResponse( results ) );
|
||||
} else
|
||||
{
|
||||
int start = tabComplete.getCursor().lastIndexOf( ' ' ) + 1;
|
||||
int end = tabComplete.getCursor().length();
|
||||
StringRange range = StringRange.between( start, end );
|
||||
|
||||
List<Suggestion> brigadier = new LinkedList<>();
|
||||
for ( String s : results )
|
||||
{
|
||||
brigadier.add( new Suggestion( range, s ) );
|
||||
}
|
||||
|
||||
con.unsafe().sendPacket( new TabCompleteResponse( tabComplete.getTransactionId(), new Suggestions( range, brigadier ) ) );
|
||||
con.unsafe().sendPacket( new TabCompleteResponse( tabComplete.getTransactionId(), brigadierResults ) );
|
||||
}
|
||||
throw CancelSendSignal.INSTANCE;
|
||||
}
|
||||
@ -257,6 +270,15 @@ public class UpstreamBridge extends PacketHandler
|
||||
{
|
||||
throw CancelSendSignal.INSTANCE;
|
||||
}
|
||||
|
||||
if ( isCommand && con.getPendingConnection().getVersion() < ProtocolConstants.MINECRAFT_1_13 )
|
||||
{
|
||||
int lastSpace = tabComplete.getCursor().lastIndexOf( ' ' );
|
||||
if ( lastSpace == -1 )
|
||||
{
|
||||
con.setLastCommandTabbed( tabComplete.getCursor().substring( 1 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -309,6 +331,19 @@ public class UpstreamBridge extends PacketHandler
|
||||
con.getPendingConnection().relayMessage( pluginMessage );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(StartConfiguration startConfiguration) throws Exception
|
||||
{
|
||||
ChannelWrapper ch = con.getServer().getCh();
|
||||
if ( ch.getDecodeProtocol() == Protocol.LOGIN )
|
||||
{
|
||||
ch.setDecodeProtocol( Protocol.CONFIGURATION );
|
||||
ch.write( new LoginAcknowledged() );
|
||||
ch.setEncodeProtocol( Protocol.CONFIGURATION );
|
||||
throw CancelSendSignal.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
|
@ -82,6 +82,8 @@ public abstract class EntityMap
|
||||
case ProtocolConstants.MINECRAFT_1_19_4:
|
||||
case ProtocolConstants.MINECRAFT_1_20:
|
||||
return EntityMap_1_16_2.INSTANCE_1_19_4;
|
||||
case ProtocolConstants.MINECRAFT_1_20_2:
|
||||
return EntityMap_1_16_2.INSTANCE_1_20_2;
|
||||
}
|
||||
throw new RuntimeException( "Version " + version + " has no entity map" );
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ class EntityMap_1_16_2 extends EntityMap
|
||||
static final EntityMap_1_16_2 INSTANCE_1_19 = new EntityMap_1_16_2( 0x02, 0x2F );
|
||||
static final EntityMap_1_16_2 INSTANCE_1_19_1 = new EntityMap_1_16_2( 0x02, 0x30 );
|
||||
static final EntityMap_1_16_2 INSTANCE_1_19_4 = new EntityMap_1_16_2( 0x03, 0x30 );
|
||||
static final EntityMap_1_16_2 INSTANCE_1_20_2 = new EntityMap_1_16_2( -1, 0x33 );
|
||||
//
|
||||
private final int spawnPlayerId;
|
||||
private final int spectateId;
|
||||
|
@ -1,34 +0,0 @@
|
||||
package net.md_5.bungee.module;
|
||||
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.common.io.Files;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import lombok.Data;
|
||||
import net.md_5.bungee.Util;
|
||||
|
||||
@Data
|
||||
public class JenkinsModuleSource implements ModuleSource
|
||||
{
|
||||
|
||||
@Override
|
||||
public void retrieve(ModuleSpec module, ModuleVersion version)
|
||||
{
|
||||
System.out.println( "Attempting to Jenkins download module " + module.getName() + " v" + version.getBuild() );
|
||||
try
|
||||
{
|
||||
URL website = new URL( "https://ci.md-5.net/job/BungeeCord/" + version.getBuild() + "/artifact/module/" + module.getName().replace( '_', '-' ) + "/target/" + module.getName() + ".jar" );
|
||||
URLConnection con = website.openConnection();
|
||||
// 15 second timeout at various stages
|
||||
con.setConnectTimeout( 15000 );
|
||||
con.setReadTimeout( 15000 );
|
||||
|
||||
Files.write( ByteStreams.toByteArray( con.getInputStream() ), module.getFile() );
|
||||
System.out.println( "Download complete" );
|
||||
} catch ( IOException ex )
|
||||
{
|
||||
System.out.println( "Failed to download: " + Util.exception( ex ) );
|
||||
}
|
||||
}
|
||||
}
|
@ -1,155 +0,0 @@
|
||||
package net.md_5.bungee.module;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.logging.Level;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.plugin.PluginDescription;
|
||||
import net.md_5.bungee.util.CaseInsensitiveMap;
|
||||
import org.yaml.snakeyaml.DumperOptions;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
public class ModuleManager
|
||||
{
|
||||
|
||||
private final Map<String, ModuleSource> knownSources = new HashMap<>();
|
||||
|
||||
public ModuleManager()
|
||||
{
|
||||
knownSources.put( "jenkins", new JenkinsModuleSource() );
|
||||
}
|
||||
|
||||
// CHECKSTYLE:OFF
|
||||
@SuppressFBWarnings(
|
||||
{
|
||||
"SF_SWITCH_FALLTHROUGH", "SF_SWITCH_NO_DEFAULT"
|
||||
})
|
||||
// CHECKSTYLE:ON
|
||||
public void load(ProxyServer proxy, File moduleDirectory) throws Exception
|
||||
{
|
||||
moduleDirectory.mkdir();
|
||||
|
||||
ModuleVersion bungeeVersion = ModuleVersion.parse( proxy.getVersion() );
|
||||
if ( bungeeVersion == null )
|
||||
{
|
||||
System.out.println( "Couldn't detect bungee version. Custom build?" );
|
||||
return;
|
||||
}
|
||||
|
||||
List<ModuleSpec> modules = new ArrayList<>();
|
||||
File configFile = new File( "modules.yml" );
|
||||
// Start Yaml
|
||||
DumperOptions options = new DumperOptions();
|
||||
options.setDefaultFlowStyle( DumperOptions.FlowStyle.BLOCK );
|
||||
Yaml yaml = new Yaml( options );
|
||||
|
||||
Map<String, Object> config;
|
||||
|
||||
configFile.createNewFile();
|
||||
try ( InputStream is = new FileInputStream( configFile ) )
|
||||
{
|
||||
config = (Map) yaml.load( is );
|
||||
}
|
||||
|
||||
if ( config == null )
|
||||
{
|
||||
config = new CaseInsensitiveMap<>();
|
||||
} else
|
||||
{
|
||||
config = new CaseInsensitiveMap<>( config );
|
||||
}
|
||||
// End yaml
|
||||
|
||||
List<String> defaults = new ArrayList<>();
|
||||
Object readModules = config.get( "modules" );
|
||||
if ( readModules != null )
|
||||
{
|
||||
defaults.addAll( (Collection) readModules );
|
||||
}
|
||||
int version = ( config.containsKey( "version" ) ) ? (int) config.get( "version" ) : 0;
|
||||
switch ( version )
|
||||
{
|
||||
case 0:
|
||||
defaults.add( "jenkins://cmd_alert" );
|
||||
defaults.add( "jenkins://cmd_find" );
|
||||
defaults.add( "jenkins://cmd_list" );
|
||||
defaults.add( "jenkins://cmd_send" );
|
||||
defaults.add( "jenkins://cmd_server" );
|
||||
case 1:
|
||||
defaults.add( "jenkins://reconnect_yaml" );
|
||||
}
|
||||
config.put( "modules", defaults );
|
||||
config.put( "version", 2 );
|
||||
|
||||
try ( FileWriter wr = new FileWriter( configFile ) )
|
||||
{
|
||||
yaml.dump( config, wr );
|
||||
}
|
||||
|
||||
for ( String s : (List<String>) config.get( "modules" ) )
|
||||
{
|
||||
URI uri = new URI( s );
|
||||
|
||||
ModuleSource source = knownSources.get( uri.getScheme() );
|
||||
if ( source == null )
|
||||
{
|
||||
System.out.println( "Unknown module source: " + s );
|
||||
continue;
|
||||
}
|
||||
String name = uri.getAuthority();
|
||||
if ( name == null )
|
||||
{
|
||||
System.out.println( "Unknown module host: " + s );
|
||||
continue;
|
||||
}
|
||||
|
||||
ModuleSpec spec = new ModuleSpec( name, new File( moduleDirectory, name + ".jar" ), source );
|
||||
modules.add( spec );
|
||||
System.out.println( "Discovered module: " + spec );
|
||||
}
|
||||
|
||||
for ( ModuleSpec module : modules )
|
||||
{
|
||||
ModuleVersion moduleVersion = ( module.getFile().exists() ) ? getVersion( module.getFile() ) : null;
|
||||
|
||||
if ( !bungeeVersion.equals( moduleVersion ) )
|
||||
{
|
||||
System.out.println( "Attempting to update plugin from " + moduleVersion + " to " + bungeeVersion );
|
||||
module.getProvider().retrieve( module, bungeeVersion );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressFBWarnings("REC_CATCH_EXCEPTION")
|
||||
private ModuleVersion getVersion(File file)
|
||||
{
|
||||
try ( JarFile jar = new JarFile( file ) )
|
||||
{
|
||||
JarEntry pdf = jar.getJarEntry( "plugin.yml" );
|
||||
Preconditions.checkNotNull( pdf, "Plugin must have a plugin.yml" );
|
||||
|
||||
try ( InputStream in = jar.getInputStream( pdf ) )
|
||||
{
|
||||
PluginDescription desc = new Yaml().loadAs( in, PluginDescription.class );
|
||||
return ModuleVersion.parse( desc.getVersion() );
|
||||
}
|
||||
} catch ( Exception ex )
|
||||
{
|
||||
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Could not check module from file " + file, ex );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
package net.md_5.bungee.module;
|
||||
|
||||
interface ModuleSource
|
||||
{
|
||||
|
||||
void retrieve(ModuleSpec module, ModuleVersion version);
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
package net.md_5.bungee.module;
|
||||
|
||||
import java.io.File;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ModuleSpec
|
||||
{
|
||||
|
||||
private final String name;
|
||||
private final File file;
|
||||
private final ModuleSource provider;
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
package net.md_5.bungee.module;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Data
|
||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class ModuleVersion
|
||||
{
|
||||
|
||||
private final String build;
|
||||
private final String git;
|
||||
|
||||
public static ModuleVersion parse(String version)
|
||||
{
|
||||
int lastColon = version.lastIndexOf( ':' );
|
||||
int secondLastColon = version.lastIndexOf( ':', lastColon - 1 );
|
||||
|
||||
if ( lastColon == -1 || secondLastColon == -1 )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
String buildNumber = version.substring( lastColon + 1, version.length() );
|
||||
String gitCommit = version.substring( secondLastColon + 1, lastColon ).replaceAll( "\"", "" );
|
||||
|
||||
if ( "unknown".equals( buildNumber ) || "unknown".equals( gitCommit ) )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ModuleVersion( buildNumber, gitCommit );
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.md_5.bungee.compress.PacketCompressor;
|
||||
import net.md_5.bungee.compress.PacketDecompressor;
|
||||
import net.md_5.bungee.protocol.DefinedPacket;
|
||||
import net.md_5.bungee.protocol.MinecraftDecoder;
|
||||
import net.md_5.bungee.protocol.MinecraftEncoder;
|
||||
import net.md_5.bungee.protocol.PacketWrapper;
|
||||
@ -35,12 +36,33 @@ public class ChannelWrapper
|
||||
this.remoteAddress = ( this.ch.remoteAddress() == null ) ? this.ch.parent().localAddress() : this.ch.remoteAddress();
|
||||
}
|
||||
|
||||
public void setProtocol(Protocol protocol)
|
||||
public Protocol getDecodeProtocol()
|
||||
{
|
||||
return ch.pipeline().get( MinecraftDecoder.class ).getProtocol();
|
||||
}
|
||||
|
||||
public void setDecodeProtocol(Protocol protocol)
|
||||
{
|
||||
ch.pipeline().get( MinecraftDecoder.class ).setProtocol( protocol );
|
||||
}
|
||||
|
||||
public Protocol getEncodeProtocol()
|
||||
{
|
||||
return ch.pipeline().get( MinecraftEncoder.class ).getProtocol();
|
||||
|
||||
}
|
||||
|
||||
public void setEncodeProtocol(Protocol protocol)
|
||||
{
|
||||
ch.pipeline().get( MinecraftEncoder.class ).setProtocol( protocol );
|
||||
}
|
||||
|
||||
public void setProtocol(Protocol protocol)
|
||||
{
|
||||
setDecodeProtocol( protocol );
|
||||
setEncodeProtocol( protocol );
|
||||
}
|
||||
|
||||
public void setVersion(int protocol)
|
||||
{
|
||||
ch.pipeline().get( MinecraftDecoder.class ).setProtocolVersion( protocol );
|
||||
@ -51,13 +73,29 @@ public class ChannelWrapper
|
||||
{
|
||||
if ( !closed )
|
||||
{
|
||||
DefinedPacket defined = null;
|
||||
if ( packet instanceof PacketWrapper )
|
||||
{
|
||||
( (PacketWrapper) packet ).setReleased( true );
|
||||
ch.writeAndFlush( ( (PacketWrapper) packet ).buf, ch.voidPromise() );
|
||||
PacketWrapper wrapper = (PacketWrapper) packet;
|
||||
wrapper.setReleased( true );
|
||||
ch.writeAndFlush( wrapper.buf, ch.voidPromise() );
|
||||
defined = wrapper.packet;
|
||||
} else
|
||||
{
|
||||
ch.writeAndFlush( packet, ch.voidPromise() );
|
||||
if ( packet instanceof DefinedPacket )
|
||||
{
|
||||
defined = (DefinedPacket) packet;
|
||||
}
|
||||
}
|
||||
|
||||
if ( defined != null )
|
||||
{
|
||||
Protocol nextProtocol = defined.nextProtocol();
|
||||
if ( nextProtocol != null )
|
||||
{
|
||||
setEncodeProtocol( nextProtocol );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -124,11 +162,11 @@ public class ChannelWrapper
|
||||
|
||||
public void setCompressionThreshold(int compressionThreshold)
|
||||
{
|
||||
if ( ch.pipeline().get( PacketCompressor.class ) == null && compressionThreshold != -1 )
|
||||
if ( ch.pipeline().get( PacketCompressor.class ) == null && compressionThreshold >= 0 )
|
||||
{
|
||||
addBefore( PipelineUtils.PACKET_ENCODER, "compress", new PacketCompressor() );
|
||||
}
|
||||
if ( compressionThreshold != -1 )
|
||||
if ( compressionThreshold >= 0 )
|
||||
{
|
||||
ch.pipeline().get( PacketCompressor.class ).setThreshold( compressionThreshold );
|
||||
} else
|
||||
@ -136,11 +174,11 @@ public class ChannelWrapper
|
||||
ch.pipeline().remove( "compress" );
|
||||
}
|
||||
|
||||
if ( ch.pipeline().get( PacketDecompressor.class ) == null && compressionThreshold != -1 )
|
||||
if ( ch.pipeline().get( PacketDecompressor.class ) == null && compressionThreshold >= 0 )
|
||||
{
|
||||
addBefore( PipelineUtils.PACKET_DECODER, "decompress", new PacketDecompressor() );
|
||||
}
|
||||
if ( compressionThreshold == -1 )
|
||||
if ( compressionThreshold < 0 )
|
||||
{
|
||||
ch.pipeline().remove( "decompress" );
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import net.md_5.bungee.connection.PingHandler;
|
||||
import net.md_5.bungee.protocol.BadPacketException;
|
||||
import net.md_5.bungee.protocol.OverflowPacketException;
|
||||
import net.md_5.bungee.protocol.PacketWrapper;
|
||||
import net.md_5.bungee.protocol.Protocol;
|
||||
import net.md_5.bungee.util.QuietException;
|
||||
|
||||
/**
|
||||
@ -101,9 +102,18 @@ public class HandlerBoss extends ChannelInboundHandlerAdapter
|
||||
return;
|
||||
}
|
||||
|
||||
PacketWrapper packet = (PacketWrapper) msg;
|
||||
if ( packet.packet != null )
|
||||
{
|
||||
Protocol nextProtocol = packet.packet.nextProtocol();
|
||||
if ( nextProtocol != null )
|
||||
{
|
||||
channel.setDecodeProtocol( nextProtocol );
|
||||
}
|
||||
}
|
||||
|
||||
if ( handler != null )
|
||||
{
|
||||
PacketWrapper packet = (PacketWrapper) msg;
|
||||
boolean sendPacket = handler.shouldHandle( packet );
|
||||
try
|
||||
{
|
||||
|
@ -4,15 +4,14 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-query</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-Query</name>
|
||||
@ -25,7 +24,7 @@
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
|
@ -4,15 +4,14 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>net.md-5</groupId>
|
||||
<groupId>fr.pandacube.bungeecord</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-slf4j</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.2-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-SLF4J</name>
|
||||
|
Loading…
Reference in New Issue
Block a user