Compare commits
50 Commits
93cbdab1f6
...
2a19bfb6d3
Author | SHA1 | Date | |
---|---|---|---|
2a19bfb6d3 | |||
451068694a | |||
e7e77e2731 | |||
d6bf6a13f4 | |||
8dd77af343 | |||
fb9e1b0499 | |||
![]() |
f6151dce56 | ||
![]() |
9667743735 | ||
![]() |
7587f03306 | ||
![]() |
77b81f2612 | ||
![]() |
fa6d47732d | ||
![]() |
252e7b0027 | ||
![]() |
c820b3a062 | ||
![]() |
687c302610 | ||
![]() |
4b0262312e | ||
![]() |
6f13c2d6b6 | ||
![]() |
cd186999e5 | ||
![]() |
e3c7fd8cc5 | ||
![]() |
9476ffccdb | ||
![]() |
47f8c29a7c | ||
![]() |
458246505f | ||
![]() |
362bd0f4c4 | ||
![]() |
598d73e6f0 | ||
![]() |
f797bd488f | ||
![]() |
0d153feee7 | ||
![]() |
2a78233cc2 | ||
![]() |
591e18753d | ||
![]() |
556a15a6f8 | ||
![]() |
774a6fd68c | ||
![]() |
0070421549 | ||
![]() |
4dad940a2f | ||
![]() |
ed4a80eb0b | ||
![]() |
dd2033bf1a | ||
![]() |
cceebdad2a | ||
![]() |
05bdf5d3c1 | ||
![]() |
c3e4a6ef5b | ||
![]() |
2337acfcc1 | ||
![]() |
69861e5334 | ||
![]() |
22aa6f5faf | ||
![]() |
508c2f7ac3 | ||
![]() |
9dd5fb626d | ||
![]() |
b5ae0196fc | ||
![]() |
80bb237289 | ||
![]() |
4fded9828f | ||
![]() |
6b22690971 | ||
![]() |
60a3bf082f | ||
![]() |
0aa2871b26 | ||
![]() |
1265a9927b | ||
![]() |
d99570214a | ||
![]() |
15bd33b25b |
@ -23,4 +23,4 @@ Binaries
|
||||
--------
|
||||
Precompiled binaries are available for end users on [Jenkins](https://www.spigotmc.org/go/bungeecord-dl).
|
||||
|
||||
(c) 2012-2024 SpigotMC Pty. Ltd.
|
||||
(c) 2012-2025 SpigotMC Pty. Ltd.
|
||||
|
15
api/pom.xml
15
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.21-R0.1-SNAPSHOT</version>
|
||||
<version>1.21-R0.3-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-api</artifactId>
|
||||
<version>1.21-R0.1-SNAPSHOT</version>
|
||||
<version>1.21-R0.3-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>
|
||||
|
@ -16,6 +16,7 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import net.md_5.bungee.api.plugin.PluginManager;
|
||||
import net.md_5.bungee.api.scheduler.TaskScheduler;
|
||||
import net.md_5.bungee.protocol.channel.BungeeChannelInitializer;
|
||||
|
||||
public abstract class ProxyServer
|
||||
{
|
||||
@ -311,4 +312,56 @@ public abstract class ProxyServer
|
||||
*/
|
||||
public abstract Title createTitle();
|
||||
|
||||
/**
|
||||
* Get the unsafe methods of this class.
|
||||
*
|
||||
* @return the unsafe method interface
|
||||
*/
|
||||
public abstract Unsafe unsafe();
|
||||
|
||||
public interface Unsafe
|
||||
{
|
||||
|
||||
/**
|
||||
* Gets the frontend channel initializer
|
||||
*
|
||||
* @return the frontend channel initializer
|
||||
*/
|
||||
BungeeChannelInitializer getFrontendChannelInitializer();
|
||||
|
||||
/**
|
||||
* Set the frontend channel initializer of this proxy
|
||||
*
|
||||
* @param channelInitializer the frontend channelInitializer to set
|
||||
*/
|
||||
void setFrontendChannelInitializer(BungeeChannelInitializer channelInitializer);
|
||||
|
||||
/**
|
||||
* Gets the backend channel initializer
|
||||
*
|
||||
* @return the backend channel initializer
|
||||
*/
|
||||
BungeeChannelInitializer getBackendChannelInitializer();
|
||||
|
||||
/**
|
||||
* Set the backend channel initializer of this proxy
|
||||
*
|
||||
* @param channelInitializer the backend channelInitializer to set
|
||||
*/
|
||||
void setBackendChannelInitializer(BungeeChannelInitializer channelInitializer);
|
||||
|
||||
/**
|
||||
* Gets the server info channel initializer
|
||||
*
|
||||
* @return the server info channel initializer
|
||||
*/
|
||||
BungeeChannelInitializer getServerInfoChannelInitializer();
|
||||
|
||||
/**
|
||||
* Set the server info channel initializer of this proxy
|
||||
*
|
||||
* @param channelInitializer the server info channelInitializer to set
|
||||
*/
|
||||
void setServerInfoChannelInitializer(BungeeChannelInitializer channelInitializer);
|
||||
}
|
||||
}
|
||||
|
@ -84,5 +84,15 @@ public interface Connection
|
||||
* @param packet the packet to send
|
||||
*/
|
||||
void sendPacket(DefinedPacket packet);
|
||||
|
||||
/**
|
||||
* Queue a packet to this connection.
|
||||
* If the packet is not registered for the connections current encoder protocol, it will be queued until it is,
|
||||
* otherwise it will be sent immediately.
|
||||
*
|
||||
* @param packet the packet to be queued
|
||||
* @throws UnsupportedOperationException if used for a PendingConnection
|
||||
*/
|
||||
void sendPacketQueued(DefinedPacket packet);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package net.md_5.bungee.api.event;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.plugin.Event;
|
||||
|
||||
@ -10,6 +11,7 @@ import net.md_5.bungee.api.plugin.Event;
|
||||
* Called when somebody reloads BungeeCord
|
||||
*/
|
||||
@Getter
|
||||
@ToString(callSuper = false)
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class ProxyReloadEvent extends Event
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -23,6 +23,10 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.logging.Level;
|
||||
@ -59,6 +63,9 @@ public final class PluginManager
|
||||
private final Multimap<Plugin, Command> commandsByPlugin = ArrayListMultimap.create();
|
||||
private final Multimap<Plugin, Listener> listenersByPlugin = ArrayListMultimap.create();
|
||||
|
||||
private final ReadWriteLock commandsLock = new ReentrantReadWriteLock();
|
||||
private final Lock listenersLock = new ReentrantLock();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public PluginManager(ProxyServer proxy)
|
||||
{
|
||||
@ -92,6 +99,9 @@ public final class PluginManager
|
||||
* @param command the command to register
|
||||
*/
|
||||
public void registerCommand(Plugin plugin, Command command)
|
||||
{
|
||||
commandsLock.writeLock().lock();
|
||||
try
|
||||
{
|
||||
commandMap.put( command.getName().toLowerCase( Locale.ROOT ), command );
|
||||
for ( String alias : command.getAliases() )
|
||||
@ -99,6 +109,10 @@ public final class PluginManager
|
||||
commandMap.put( alias.toLowerCase( Locale.ROOT ), command );
|
||||
}
|
||||
commandsByPlugin.put( plugin, command );
|
||||
} finally
|
||||
{
|
||||
commandsLock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,9 +121,16 @@ public final class PluginManager
|
||||
* @param command the command to unregister
|
||||
*/
|
||||
public void unregisterCommand(Command command)
|
||||
{
|
||||
commandsLock.writeLock().lock();
|
||||
try
|
||||
{
|
||||
while ( commandMap.values().remove( command ) );
|
||||
commandsByPlugin.values().remove( command );
|
||||
} finally
|
||||
{
|
||||
commandsLock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -118,6 +139,9 @@ public final class PluginManager
|
||||
* @param plugin the plugin to register the commands of
|
||||
*/
|
||||
public void unregisterCommands(Plugin plugin)
|
||||
{
|
||||
commandsLock.writeLock().lock();
|
||||
try
|
||||
{
|
||||
for ( Iterator<Command> it = commandsByPlugin.get( plugin ).iterator(); it.hasNext(); )
|
||||
{
|
||||
@ -125,6 +149,10 @@ public final class PluginManager
|
||||
while ( commandMap.values().remove( command ) );
|
||||
it.remove();
|
||||
}
|
||||
} finally
|
||||
{
|
||||
commandsLock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private Command getCommandIfEnabled(String commandName, CommandSender sender)
|
||||
@ -137,7 +165,14 @@ public final class PluginManager
|
||||
return null;
|
||||
}
|
||||
|
||||
commandsLock.readLock().lock();
|
||||
try
|
||||
{
|
||||
return commandMap.get( commandLower );
|
||||
} finally
|
||||
{
|
||||
commandsLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -433,6 +468,9 @@ public final class PluginManager
|
||||
* @param listener the listener to register events for
|
||||
*/
|
||||
public void registerListener(Plugin plugin, Listener listener)
|
||||
{
|
||||
listenersLock.lock();
|
||||
try
|
||||
{
|
||||
for ( Method method : listener.getClass().getDeclaredMethods() )
|
||||
{
|
||||
@ -441,6 +479,10 @@ public final class PluginManager
|
||||
}
|
||||
eventBus.register( listener );
|
||||
listenersByPlugin.put( plugin, listener );
|
||||
} finally
|
||||
{
|
||||
listenersLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -449,9 +491,16 @@ public final class PluginManager
|
||||
* @param listener the listener to unregister
|
||||
*/
|
||||
public void unregisterListener(Listener listener)
|
||||
{
|
||||
listenersLock.lock();
|
||||
try
|
||||
{
|
||||
eventBus.unregister( listener );
|
||||
listenersByPlugin.values().remove( listener );
|
||||
} finally
|
||||
{
|
||||
listenersLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -460,12 +509,19 @@ public final class PluginManager
|
||||
* @param plugin target plugin
|
||||
*/
|
||||
public void unregisterListeners(Plugin plugin)
|
||||
{
|
||||
listenersLock.lock();
|
||||
try
|
||||
{
|
||||
for ( Iterator<Listener> it = listenersByPlugin.get( plugin ).iterator(); it.hasNext(); )
|
||||
{
|
||||
eventBus.unregister( it.next() );
|
||||
it.remove();
|
||||
}
|
||||
} finally
|
||||
{
|
||||
listenersLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -474,8 +530,15 @@ public final class PluginManager
|
||||
* @return commands
|
||||
*/
|
||||
public Collection<Map.Entry<String, Command>> getCommands()
|
||||
{
|
||||
commandsLock.readLock().lock();
|
||||
try
|
||||
{
|
||||
return Collections.unmodifiableCollection( commandMap.entrySet() );
|
||||
} finally
|
||||
{
|
||||
commandsLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
boolean isTransitiveDepend(PluginDescription plugin, PluginDescription depend)
|
||||
|
@ -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.21-R0.1-SNAPSHOT</version>
|
||||
<version>1.21-R0.3-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-bootstrap</artifactId>
|
||||
<version>1.21-R0.1-SNAPSHOT</version>
|
||||
<version>1.21-R0.3-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>
|
||||
@ -36,7 +33,7 @@
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>BungeeCord</finalName>
|
||||
<finalName>BungeeCord-${project.version}-${build.number}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
@ -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.21-R0.1-SNAPSHOT</version>
|
||||
<version>1.21-R0.3-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-chat</artifactId>
|
||||
<version>1.21-R0.1-SNAPSHOT</version>
|
||||
<version>1.21-R0.3-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-Chat</name>
|
||||
|
@ -13,7 +13,8 @@ import net.md_5.bungee.api.chat.hover.content.Content;
|
||||
import net.md_5.bungee.api.chat.hover.content.Entity;
|
||||
import net.md_5.bungee.api.chat.hover.content.Item;
|
||||
import net.md_5.bungee.api.chat.hover.content.Text;
|
||||
import net.md_5.bungee.chat.ComponentSerializer;
|
||||
import net.md_5.bungee.chat.VersionedComponentSerializer;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@ -34,6 +35,7 @@ public final class HoverEvent
|
||||
* Returns whether this hover event is prior to 1.16
|
||||
*/
|
||||
@Setter
|
||||
@ApiStatus.Internal
|
||||
private boolean legacy = false;
|
||||
|
||||
/**
|
||||
@ -80,7 +82,7 @@ public final class HoverEvent
|
||||
return (BaseComponent[]) ( (Text) content ).getValue();
|
||||
}
|
||||
|
||||
TextComponent component = new TextComponent( ComponentSerializer.toString( content ) );
|
||||
TextComponent component = new TextComponent( VersionedComponentSerializer.getDefault().toString( content ) );
|
||||
return new BaseComponent[]
|
||||
{
|
||||
component
|
||||
|
@ -10,27 +10,36 @@ import com.google.gson.JsonSerializer;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.UUID;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.chat.BaseComponentSerializer;
|
||||
import net.md_5.bungee.chat.VersionedComponentSerializer;
|
||||
|
||||
public class EntitySerializer implements JsonSerializer<Entity>, JsonDeserializer<Entity>
|
||||
public class EntitySerializer extends BaseComponentSerializer implements JsonSerializer<Entity>, JsonDeserializer<Entity>
|
||||
{
|
||||
|
||||
public EntitySerializer(VersionedComponentSerializer serializer)
|
||||
{
|
||||
super( serializer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException
|
||||
{
|
||||
JsonObject value = element.getAsJsonObject();
|
||||
|
||||
boolean newEntity = value.has( "uuid" );
|
||||
|
||||
String idString;
|
||||
JsonElement id = value.get( "id" );
|
||||
if ( id.isJsonArray() )
|
||||
JsonElement uuid = value.get( newEntity ? "uuid" : "id" );
|
||||
if ( uuid.isJsonArray() )
|
||||
{
|
||||
idString = parseUUID( context.deserialize( id, int[].class ) ).toString();
|
||||
idString = parseUUID( context.deserialize( uuid, int[].class ) ).toString();
|
||||
} else
|
||||
{
|
||||
idString = id.getAsString();
|
||||
idString = uuid.getAsString();
|
||||
}
|
||||
|
||||
return new Entity(
|
||||
( value.has( "type" ) ) ? value.get( "type" ).getAsString() : null,
|
||||
( value.has( newEntity ? "id" : "type" ) ) ? value.get( newEntity ? "id" : "type" ).getAsString() : null,
|
||||
idString,
|
||||
( value.has( "name" ) ) ? context.deserialize( value.get( "name" ), BaseComponent.class ) : null
|
||||
);
|
||||
@ -40,8 +49,21 @@ public class EntitySerializer implements JsonSerializer<Entity>, JsonDeserialize
|
||||
public JsonElement serialize(Entity content, Type type, JsonSerializationContext context)
|
||||
{
|
||||
JsonObject object = new JsonObject();
|
||||
|
||||
switch ( serializer.getVersion() )
|
||||
{
|
||||
case V1_21_5:
|
||||
object.addProperty( "id", ( content.getType() != null ) ? content.getType() : "minecraft:pig" );
|
||||
object.addProperty( "uuid", content.getId() );
|
||||
break;
|
||||
case V1_16:
|
||||
object.addProperty( "type", ( content.getType() != null ) ? content.getType() : "minecraft:pig" );
|
||||
object.addProperty( "id", content.getId() );
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException( "Unknown version " + serializer.getVersion() );
|
||||
}
|
||||
|
||||
if ( content.getName() != null )
|
||||
{
|
||||
object.add( "name", context.serialize( content.getName() ) );
|
||||
|
@ -10,15 +10,19 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Locale;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.ClickEvent;
|
||||
import net.md_5.bungee.api.chat.ComponentStyle;
|
||||
import net.md_5.bungee.api.chat.HoverEvent;
|
||||
import net.md_5.bungee.api.chat.hover.content.Content;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class BaseComponentSerializer
|
||||
{
|
||||
|
||||
protected final VersionedComponentSerializer serializer;
|
||||
|
||||
protected void deserialize(JsonObject object, BaseComponent component, JsonDeserializationContext context)
|
||||
{
|
||||
component.applyStyle( context.deserialize( object, ComponentStyle.class ) );
|
||||
@ -30,23 +34,82 @@ public class BaseComponentSerializer
|
||||
}
|
||||
|
||||
//Events
|
||||
JsonObject clickEvent = object.getAsJsonObject( "clickEvent" );
|
||||
JsonObject clickEvent;
|
||||
boolean newClickEvent = ( clickEvent = object.getAsJsonObject( "click_event" ) ) != null;
|
||||
if ( !newClickEvent )
|
||||
{
|
||||
clickEvent = object.getAsJsonObject( "clickEvent" );
|
||||
}
|
||||
if ( clickEvent != null )
|
||||
{
|
||||
component.setClickEvent( new ClickEvent(
|
||||
ClickEvent.Action.valueOf( clickEvent.get( "action" ).getAsString().toUpperCase( Locale.ROOT ) ),
|
||||
( clickEvent.has( "value" ) ) ? clickEvent.get( "value" ).getAsString() : "" ) );
|
||||
ClickEvent.Action action = ClickEvent.Action.valueOf( clickEvent.get( "action" ).getAsString().toUpperCase( Locale.ROOT ) );
|
||||
if ( newClickEvent )
|
||||
{
|
||||
switch ( action )
|
||||
{
|
||||
case OPEN_URL:
|
||||
component.setClickEvent( new ClickEvent( action, clickEvent.get( "url" ).getAsString() ) );
|
||||
break;
|
||||
case RUN_COMMAND:
|
||||
case SUGGEST_COMMAND:
|
||||
component.setClickEvent( new ClickEvent( action, clickEvent.get( "command" ).getAsString() ) );
|
||||
break;
|
||||
case CHANGE_PAGE:
|
||||
int page = clickEvent.get( "page" ).getAsInt();
|
||||
Preconditions.checkArgument( page >= 0, "Page number has to be positive" );
|
||||
component.setClickEvent( new ClickEvent( action, Integer.toString( page ) ) );
|
||||
break;
|
||||
default:
|
||||
component.setClickEvent( new ClickEvent( action, ( clickEvent.has( "value" ) ) ? clickEvent.get( "value" ).getAsString() : "" ) );
|
||||
break;
|
||||
}
|
||||
JsonObject hoverEventJson = object.getAsJsonObject( "hoverEvent" );
|
||||
} else
|
||||
{
|
||||
component.setClickEvent( new ClickEvent( action, ( clickEvent.has( "value" ) ) ? clickEvent.get( "value" ).getAsString() : "" ) );
|
||||
}
|
||||
}
|
||||
|
||||
JsonObject hoverEventJson;
|
||||
boolean newHoverEvent = ( hoverEventJson = object.getAsJsonObject( "hover_event" ) ) != null;
|
||||
if ( !newHoverEvent )
|
||||
{
|
||||
hoverEventJson = object.getAsJsonObject( "hoverEvent" );
|
||||
}
|
||||
|
||||
if ( hoverEventJson != null )
|
||||
{
|
||||
HoverEvent hoverEvent = null;
|
||||
HoverEvent.Action action = HoverEvent.Action.valueOf( hoverEventJson.get( "action" ).getAsString().toUpperCase( Locale.ROOT ) );
|
||||
|
||||
if ( newHoverEvent || hoverEventJson.has( "contents" ) )
|
||||
{
|
||||
// value is only used for text in >= 1.21.5 (its inlined now)
|
||||
JsonElement contents = hoverEventJson.get( newHoverEvent ? "value" : "contents" );
|
||||
if ( contents != null || ( newHoverEvent && ( action == HoverEvent.Action.SHOW_ITEM || action == HoverEvent.Action.SHOW_ENTITY ) ) )
|
||||
{
|
||||
if ( contents == null )
|
||||
{
|
||||
// this is the new inline for SHOW_ITEM and SHOW_ENTITY
|
||||
contents = hoverEventJson;
|
||||
}
|
||||
Content[] list;
|
||||
if ( contents.isJsonArray() )
|
||||
{
|
||||
list = context.deserialize( contents, HoverEvent.getClass( action, true ) );
|
||||
} else
|
||||
{
|
||||
list = new Content[]
|
||||
{
|
||||
context.deserialize( contents, HoverEvent.getClass( action, false ) )
|
||||
};
|
||||
}
|
||||
hoverEvent = new HoverEvent( action, new ArrayList<>( Arrays.asList( list ) ) );
|
||||
}
|
||||
} else
|
||||
{
|
||||
JsonElement value = hoverEventJson.get( "value" );
|
||||
if ( value != null )
|
||||
{
|
||||
|
||||
// Plugins previously had support to pass BaseComponent[] into any action.
|
||||
// If the GSON is possible to be parsed as BaseComponent, attempt to parse as so.
|
||||
BaseComponent[] components;
|
||||
@ -61,23 +124,6 @@ public class BaseComponentSerializer
|
||||
};
|
||||
}
|
||||
hoverEvent = new HoverEvent( action, components );
|
||||
} else
|
||||
{
|
||||
JsonElement contents = hoverEventJson.get( "contents" );
|
||||
if ( contents != null )
|
||||
{
|
||||
Content[] list;
|
||||
if ( contents.isJsonArray() )
|
||||
{
|
||||
list = context.deserialize( contents, HoverEvent.getClass( action, true ) );
|
||||
} else
|
||||
{
|
||||
list = new Content[]
|
||||
{
|
||||
context.deserialize( contents, HoverEvent.getClass( action, false ) )
|
||||
};
|
||||
}
|
||||
hoverEvent = new HoverEvent( action, new ArrayList<>( Arrays.asList( list ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,15 +143,15 @@ public class BaseComponentSerializer
|
||||
protected void serialize(JsonObject object, BaseComponent component, JsonSerializationContext context)
|
||||
{
|
||||
boolean first = false;
|
||||
if ( ComponentSerializer.serializedComponents.get() == null )
|
||||
if ( VersionedComponentSerializer.serializedComponents.get() == null )
|
||||
{
|
||||
first = true;
|
||||
ComponentSerializer.serializedComponents.set( Collections.newSetFromMap( new IdentityHashMap<BaseComponent, Boolean>() ) );
|
||||
VersionedComponentSerializer.serializedComponents.set( Collections.newSetFromMap( new IdentityHashMap<BaseComponent, Boolean>() ) );
|
||||
}
|
||||
try
|
||||
{
|
||||
Preconditions.checkArgument( !ComponentSerializer.serializedComponents.get().contains( component ), "Component loop" );
|
||||
ComponentSerializer.serializedComponents.get().add( component );
|
||||
Preconditions.checkArgument( !VersionedComponentSerializer.serializedComponents.get().contains( component ), "Component loop" );
|
||||
VersionedComponentSerializer.serializedComponents.get().add( component );
|
||||
|
||||
ComponentStyleSerializer.serializeTo( component.getStyle(), object );
|
||||
|
||||
@ -118,9 +164,38 @@ public class BaseComponentSerializer
|
||||
if ( component.getClickEvent() != null )
|
||||
{
|
||||
JsonObject clickEvent = new JsonObject();
|
||||
clickEvent.addProperty( "action", component.getClickEvent().getAction().toString().toLowerCase( Locale.ROOT ) );
|
||||
String actionName = component.getClickEvent().getAction().toString().toLowerCase( Locale.ROOT );
|
||||
clickEvent.addProperty( "action", actionName.toLowerCase( Locale.ROOT ) );
|
||||
switch ( serializer.getVersion() )
|
||||
{
|
||||
case V1_21_5:
|
||||
ClickEvent.Action action = ClickEvent.Action.valueOf( actionName.toUpperCase( Locale.ROOT ) );
|
||||
switch ( action )
|
||||
{
|
||||
case OPEN_URL:
|
||||
clickEvent.addProperty( "url", component.getClickEvent().getValue() );
|
||||
break;
|
||||
case RUN_COMMAND:
|
||||
case SUGGEST_COMMAND:
|
||||
clickEvent.addProperty( "command", component.getClickEvent().getValue() );
|
||||
break;
|
||||
case CHANGE_PAGE:
|
||||
clickEvent.addProperty( "page", Integer.parseInt( component.getClickEvent().getValue() ) );
|
||||
break;
|
||||
default:
|
||||
clickEvent.addProperty( "value", component.getClickEvent().getValue() );
|
||||
break;
|
||||
}
|
||||
object.add( "click_event", clickEvent );
|
||||
break;
|
||||
case V1_16:
|
||||
clickEvent.addProperty( "value", component.getClickEvent().getValue() );
|
||||
object.add( "clickEvent", clickEvent );
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException( "Unknown version " + serializer.getVersion() );
|
||||
}
|
||||
|
||||
}
|
||||
if ( component.getHoverEvent() != null )
|
||||
{
|
||||
@ -131,10 +206,39 @@ public class BaseComponentSerializer
|
||||
hoverEvent.add( "value", context.serialize( component.getHoverEvent().getContents().get( 0 ) ) );
|
||||
} else
|
||||
{
|
||||
hoverEvent.add( "contents", context.serialize( ( component.getHoverEvent().getContents().size() == 1 )
|
||||
switch ( serializer.getVersion() )
|
||||
{
|
||||
case V1_21_5:
|
||||
if ( component.getHoverEvent().getAction() == HoverEvent.Action.SHOW_ITEM || component.getHoverEvent().getAction() == HoverEvent.Action.SHOW_ENTITY )
|
||||
{
|
||||
JsonObject inlined = context.serialize( ( component.getHoverEvent().getContents().size() == 1 )
|
||||
? component.getHoverEvent().getContents().get( 0 ) : component.getHoverEvent().getContents() ).getAsJsonObject();
|
||||
inlined.entrySet().forEach( entry -> hoverEvent.add( entry.getKey(), entry.getValue() ) );
|
||||
} else
|
||||
{
|
||||
hoverEvent.add( "value", context.serialize( ( component.getHoverEvent().getContents().size() == 1 )
|
||||
? component.getHoverEvent().getContents().get( 0 ) : component.getHoverEvent().getContents() ) );
|
||||
}
|
||||
break;
|
||||
case V1_16:
|
||||
hoverEvent.add( "contents", context.serialize( ( component.getHoverEvent().getContents().size() == 1 )
|
||||
? component.getHoverEvent().getContents().get( 0 ) : component.getHoverEvent().getContents() ) );
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException( "Unknown version " + serializer.getVersion() );
|
||||
}
|
||||
}
|
||||
switch ( serializer.getVersion() )
|
||||
{
|
||||
case V1_21_5:
|
||||
object.add( "hover_event", hoverEvent );
|
||||
break;
|
||||
case V1_16:
|
||||
object.add( "hoverEvent", hoverEvent );
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException( "Unknown version " + serializer.getVersion() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( component.getExtra() != null )
|
||||
@ -143,10 +247,10 @@ public class BaseComponentSerializer
|
||||
}
|
||||
} finally
|
||||
{
|
||||
ComponentSerializer.serializedComponents.get().remove( component );
|
||||
VersionedComponentSerializer.serializedComponents.get().remove( component );
|
||||
if ( first )
|
||||
{
|
||||
ComponentSerializer.serializedComponents.set( null );
|
||||
VersionedComponentSerializer.serializedComponents.set( null );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
10
chat/src/main/java/net/md_5/bungee/chat/ChatVersion.java
Normal file
10
chat/src/main/java/net/md_5/bungee/chat/ChatVersion.java
Normal file
@ -0,0 +1,10 @@
|
||||
package net.md_5.bungee.chat;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public enum ChatVersion
|
||||
{
|
||||
V1_16,
|
||||
V1_21_5;
|
||||
}
|
@ -1,52 +1,17 @@
|
||||
package net.md_5.bungee.chat;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Set;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.ComponentStyle;
|
||||
import net.md_5.bungee.api.chat.ItemTag;
|
||||
import net.md_5.bungee.api.chat.KeybindComponent;
|
||||
import net.md_5.bungee.api.chat.ScoreComponent;
|
||||
import net.md_5.bungee.api.chat.SelectorComponent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.chat.TranslatableComponent;
|
||||
import net.md_5.bungee.api.chat.hover.content.Content;
|
||||
import net.md_5.bungee.api.chat.hover.content.Entity;
|
||||
import net.md_5.bungee.api.chat.hover.content.EntitySerializer;
|
||||
import net.md_5.bungee.api.chat.hover.content.Item;
|
||||
import net.md_5.bungee.api.chat.hover.content.ItemSerializer;
|
||||
import net.md_5.bungee.api.chat.hover.content.Text;
|
||||
import net.md_5.bungee.api.chat.hover.content.TextSerializer;
|
||||
|
||||
public class ComponentSerializer implements JsonDeserializer<BaseComponent>
|
||||
{
|
||||
|
||||
private static final Gson gson = new GsonBuilder().
|
||||
registerTypeAdapter( BaseComponent.class, new ComponentSerializer() ).
|
||||
registerTypeAdapter( TextComponent.class, new TextComponentSerializer() ).
|
||||
registerTypeAdapter( TranslatableComponent.class, new TranslatableComponentSerializer() ).
|
||||
registerTypeAdapter( KeybindComponent.class, new KeybindComponentSerializer() ).
|
||||
registerTypeAdapter( ScoreComponent.class, new ScoreComponentSerializer() ).
|
||||
registerTypeAdapter( SelectorComponent.class, new SelectorComponentSerializer() ).
|
||||
registerTypeAdapter( ComponentStyle.class, new ComponentStyleSerializer() ).
|
||||
registerTypeAdapter( Entity.class, new EntitySerializer() ).
|
||||
registerTypeAdapter( Text.class, new TextSerializer() ).
|
||||
registerTypeAdapter( Item.class, new ItemSerializer() ).
|
||||
registerTypeAdapter( ItemTag.class, new ItemTag.Serializer() ).
|
||||
create();
|
||||
|
||||
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
|
||||
@ -66,18 +31,7 @@ public class ComponentSerializer implements JsonDeserializer<BaseComponent>
|
||||
*/
|
||||
public static BaseComponent[] parse(String json)
|
||||
{
|
||||
JsonElement jsonElement = JsonParser.parseString( json );
|
||||
|
||||
if ( jsonElement.isJsonArray() )
|
||||
{
|
||||
return gson.fromJson( jsonElement, BaseComponent[].class );
|
||||
} else
|
||||
{
|
||||
return new BaseComponent[]
|
||||
{
|
||||
gson.fromJson( jsonElement, BaseComponent.class )
|
||||
};
|
||||
}
|
||||
return VersionedComponentSerializer.getDefault().parse( json );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,9 +44,7 @@ public class ComponentSerializer implements JsonDeserializer<BaseComponent>
|
||||
*/
|
||||
public static BaseComponent deserialize(String json)
|
||||
{
|
||||
JsonElement jsonElement = JsonParser.parseString( json );
|
||||
|
||||
return deserialize( jsonElement );
|
||||
return VersionedComponentSerializer.getDefault().deserialize( json );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -105,20 +57,7 @@ public class ComponentSerializer implements JsonDeserializer<BaseComponent>
|
||||
*/
|
||||
public static BaseComponent deserialize(JsonElement jsonElement)
|
||||
{
|
||||
if ( jsonElement instanceof JsonPrimitive )
|
||||
{
|
||||
JsonPrimitive primitive = (JsonPrimitive) jsonElement;
|
||||
if ( primitive.isString() )
|
||||
{
|
||||
return new TextComponent( primitive.getAsString() );
|
||||
}
|
||||
} else if ( jsonElement instanceof JsonArray )
|
||||
{
|
||||
BaseComponent[] array = gson.fromJson( jsonElement, BaseComponent[].class );
|
||||
return TextComponent.fromArray( array );
|
||||
}
|
||||
|
||||
return gson.fromJson( jsonElement, BaseComponent.class );
|
||||
return VersionedComponentSerializer.getDefault().deserialize( jsonElement );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -131,9 +70,7 @@ public class ComponentSerializer implements JsonDeserializer<BaseComponent>
|
||||
*/
|
||||
public static ComponentStyle deserializeStyle(String json)
|
||||
{
|
||||
JsonElement jsonElement = JsonParser.parseString( json );
|
||||
|
||||
return deserializeStyle( jsonElement );
|
||||
return VersionedComponentSerializer.getDefault().deserializeStyle( json );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -146,17 +83,17 @@ public class ComponentSerializer implements JsonDeserializer<BaseComponent>
|
||||
*/
|
||||
public static ComponentStyle deserializeStyle(JsonElement jsonElement)
|
||||
{
|
||||
return gson.fromJson( jsonElement, ComponentStyle.class );
|
||||
return VersionedComponentSerializer.getDefault().deserializeStyle( jsonElement );
|
||||
}
|
||||
|
||||
public static JsonElement toJson(BaseComponent component)
|
||||
{
|
||||
return gson.toJsonTree( component );
|
||||
return VersionedComponentSerializer.getDefault().toJson( component );
|
||||
}
|
||||
|
||||
public static JsonElement toJson(ComponentStyle style)
|
||||
{
|
||||
return gson.toJsonTree( style );
|
||||
return VersionedComponentSerializer.getDefault().toJson( style );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -167,7 +104,7 @@ public class ComponentSerializer implements JsonDeserializer<BaseComponent>
|
||||
@Deprecated
|
||||
public static String toString(Object object)
|
||||
{
|
||||
return gson.toJson( object );
|
||||
return VersionedComponentSerializer.getDefault().toString( object );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -178,54 +115,27 @@ public class ComponentSerializer implements JsonDeserializer<BaseComponent>
|
||||
@Deprecated
|
||||
public static String toString(Content content)
|
||||
{
|
||||
return gson.toJson( content );
|
||||
return VersionedComponentSerializer.getDefault().toString( content );
|
||||
}
|
||||
|
||||
public static String toString(BaseComponent component)
|
||||
{
|
||||
return gson.toJson( component );
|
||||
return VersionedComponentSerializer.getDefault().toString( component );
|
||||
}
|
||||
|
||||
public static String toString(BaseComponent... components)
|
||||
{
|
||||
if ( components.length == 1 )
|
||||
{
|
||||
return gson.toJson( components[0] );
|
||||
} else
|
||||
{
|
||||
return gson.toJson( new TextComponent( components ) );
|
||||
}
|
||||
return VersionedComponentSerializer.getDefault().toString( components );
|
||||
}
|
||||
|
||||
public static String toString(ComponentStyle style)
|
||||
{
|
||||
return gson.toJson( style );
|
||||
return VersionedComponentSerializer.getDefault().toString( style );
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
||||
{
|
||||
if ( json.isJsonPrimitive() )
|
||||
{
|
||||
return new TextComponent( json.getAsString() );
|
||||
}
|
||||
JsonObject object = json.getAsJsonObject();
|
||||
if ( object.has( "translate" ) )
|
||||
{
|
||||
return context.deserialize( json, TranslatableComponent.class );
|
||||
}
|
||||
if ( object.has( "keybind" ) )
|
||||
{
|
||||
return context.deserialize( json, KeybindComponent.class );
|
||||
}
|
||||
if ( object.has( "score" ) )
|
||||
{
|
||||
return context.deserialize( json, ScoreComponent.class );
|
||||
}
|
||||
if ( object.has( "selector" ) )
|
||||
{
|
||||
return context.deserialize( json, SelectorComponent.class );
|
||||
}
|
||||
return context.deserialize( json, TextComponent.class );
|
||||
return VersionedComponentSerializer.getDefault().deserialize( json, typeOfT, context );
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,11 @@ import net.md_5.bungee.api.chat.KeybindComponent;
|
||||
public class KeybindComponentSerializer extends BaseComponentSerializer implements JsonSerializer<KeybindComponent>, JsonDeserializer<KeybindComponent>
|
||||
{
|
||||
|
||||
public KeybindComponentSerializer(VersionedComponentSerializer serializer)
|
||||
{
|
||||
super( serializer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeybindComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
||||
{
|
||||
|
@ -13,6 +13,11 @@ import net.md_5.bungee.api.chat.ScoreComponent;
|
||||
public class ScoreComponentSerializer extends BaseComponentSerializer implements JsonSerializer<ScoreComponent>, JsonDeserializer<ScoreComponent>
|
||||
{
|
||||
|
||||
public ScoreComponentSerializer(VersionedComponentSerializer serializer)
|
||||
{
|
||||
super( serializer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScoreComponent deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException
|
||||
{
|
||||
|
@ -13,6 +13,11 @@ import net.md_5.bungee.api.chat.SelectorComponent;
|
||||
public class SelectorComponentSerializer extends BaseComponentSerializer implements JsonSerializer<SelectorComponent>, JsonDeserializer<SelectorComponent>
|
||||
{
|
||||
|
||||
public SelectorComponentSerializer(VersionedComponentSerializer serializer)
|
||||
{
|
||||
super( serializer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SelectorComponent deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException
|
||||
{
|
||||
@ -27,7 +32,7 @@ public class SelectorComponentSerializer extends BaseComponentSerializer impleme
|
||||
JsonElement separator = object.get( "separator" );
|
||||
if ( separator != null )
|
||||
{
|
||||
component.setSeparator( ComponentSerializer.deserialize( separator.getAsString() ) );
|
||||
component.setSeparator( serializer.deserialize( separator.getAsString() ) );
|
||||
}
|
||||
|
||||
deserialize( object, component, context );
|
||||
@ -43,7 +48,7 @@ public class SelectorComponentSerializer extends BaseComponentSerializer impleme
|
||||
|
||||
if ( component.getSeparator() != null )
|
||||
{
|
||||
object.addProperty( "separator", ComponentSerializer.toString( component.getSeparator() ) );
|
||||
object.addProperty( "separator", serializer.toString( component.getSeparator() ) );
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
@ -13,6 +13,11 @@ import net.md_5.bungee.api.chat.TextComponent;
|
||||
public class TextComponentSerializer extends BaseComponentSerializer implements JsonSerializer<TextComponent>, JsonDeserializer<TextComponent>
|
||||
{
|
||||
|
||||
public TextComponentSerializer(VersionedComponentSerializer serializer)
|
||||
{
|
||||
super( serializer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
||||
{
|
||||
|
@ -15,6 +15,11 @@ import net.md_5.bungee.api.chat.TranslatableComponent;
|
||||
public class TranslatableComponentSerializer extends BaseComponentSerializer implements JsonSerializer<TranslatableComponent>, JsonDeserializer<TranslatableComponent>
|
||||
{
|
||||
|
||||
public TranslatableComponentSerializer(VersionedComponentSerializer serializer)
|
||||
{
|
||||
super( serializer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TranslatableComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
||||
{
|
||||
|
@ -0,0 +1,269 @@
|
||||
package net.md_5.bungee.chat;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Set;
|
||||
import lombok.Getter;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.ComponentStyle;
|
||||
import net.md_5.bungee.api.chat.ItemTag;
|
||||
import net.md_5.bungee.api.chat.KeybindComponent;
|
||||
import net.md_5.bungee.api.chat.ScoreComponent;
|
||||
import net.md_5.bungee.api.chat.SelectorComponent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.chat.TranslatableComponent;
|
||||
import net.md_5.bungee.api.chat.hover.content.Content;
|
||||
import net.md_5.bungee.api.chat.hover.content.Entity;
|
||||
import net.md_5.bungee.api.chat.hover.content.EntitySerializer;
|
||||
import net.md_5.bungee.api.chat.hover.content.Item;
|
||||
import net.md_5.bungee.api.chat.hover.content.ItemSerializer;
|
||||
import net.md_5.bungee.api.chat.hover.content.Text;
|
||||
import net.md_5.bungee.api.chat.hover.content.TextSerializer;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
@ApiStatus.Experimental
|
||||
public class VersionedComponentSerializer implements JsonDeserializer<BaseComponent>
|
||||
{
|
||||
|
||||
@Getter
|
||||
@ApiStatus.Internal
|
||||
private final Gson gson;
|
||||
@Getter
|
||||
@ApiStatus.Internal
|
||||
private final ChatVersion version;
|
||||
|
||||
public VersionedComponentSerializer(ChatVersion version)
|
||||
{
|
||||
this.version = version;
|
||||
this.gson = new GsonBuilder().
|
||||
registerTypeAdapter( BaseComponent.class, this ).
|
||||
registerTypeAdapter( TextComponent.class, new TextComponentSerializer( this ) ).
|
||||
registerTypeAdapter( TranslatableComponent.class, new TranslatableComponentSerializer( this ) ).
|
||||
registerTypeAdapter( KeybindComponent.class, new KeybindComponentSerializer( this ) ).
|
||||
registerTypeAdapter( ScoreComponent.class, new ScoreComponentSerializer( this ) ).
|
||||
registerTypeAdapter( SelectorComponent.class, new SelectorComponentSerializer( this ) ).
|
||||
registerTypeAdapter( ComponentStyle.class, new ComponentStyleSerializer() ).
|
||||
registerTypeAdapter( Entity.class, new EntitySerializer( this ) ).
|
||||
registerTypeAdapter( Text.class, new TextSerializer() ).
|
||||
registerTypeAdapter( Item.class, new ItemSerializer() ).
|
||||
registerTypeAdapter( ItemTag.class, new ItemTag.Serializer() ).
|
||||
create();
|
||||
}
|
||||
|
||||
private static final VersionedComponentSerializer v1_16 = new VersionedComponentSerializer( ChatVersion.V1_16 );
|
||||
private static final VersionedComponentSerializer v1_21_5 = new VersionedComponentSerializer( ChatVersion.V1_21_5 );
|
||||
|
||||
public static VersionedComponentSerializer forVersion(ChatVersion version)
|
||||
{
|
||||
switch ( version )
|
||||
{
|
||||
case V1_16:
|
||||
return v1_16;
|
||||
case V1_21_5:
|
||||
return v1_21_5;
|
||||
default:
|
||||
throw new IllegalArgumentException( "Unknown version " + version );
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@ApiStatus.Internal
|
||||
public static VersionedComponentSerializer getDefault()
|
||||
{
|
||||
return v1_16;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
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 BaseComponent[] parse(String json)
|
||||
{
|
||||
JsonElement jsonElement = JsonParser.parseString( json );
|
||||
|
||||
if ( jsonElement.isJsonArray() )
|
||||
{
|
||||
return gson.fromJson( jsonElement, BaseComponent[].class );
|
||||
} else
|
||||
{
|
||||
return new BaseComponent[]
|
||||
{
|
||||
gson.fromJson( jsonElement, BaseComponent.class )
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a JSON-compliant String as a single component.
|
||||
*
|
||||
* @param json the component json to parse
|
||||
* @return the deserialized component
|
||||
* @throws IllegalArgumentException if anything other than a valid JSON
|
||||
* component string is passed as input
|
||||
*/
|
||||
public BaseComponent deserialize(String json)
|
||||
{
|
||||
JsonElement jsonElement = JsonParser.parseString( json );
|
||||
|
||||
return deserialize( jsonElement );
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a JSON element as a single component.
|
||||
*
|
||||
* @param jsonElement the component json to parse
|
||||
* @return the deserialized component
|
||||
* @throws IllegalArgumentException if anything other than a valid JSON
|
||||
* component is passed as input
|
||||
*/
|
||||
public BaseComponent deserialize(JsonElement jsonElement)
|
||||
{
|
||||
if ( jsonElement instanceof JsonPrimitive )
|
||||
{
|
||||
JsonPrimitive primitive = (JsonPrimitive) jsonElement;
|
||||
if ( primitive.isString() )
|
||||
{
|
||||
return new TextComponent( primitive.getAsString() );
|
||||
}
|
||||
} else if ( jsonElement instanceof JsonArray )
|
||||
{
|
||||
BaseComponent[] array = gson.fromJson( jsonElement, BaseComponent[].class );
|
||||
return TextComponent.fromArray( array );
|
||||
}
|
||||
|
||||
return gson.fromJson( jsonElement, BaseComponent.class );
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a JSON-compliant String as a component style.
|
||||
*
|
||||
* @param json the component style json to parse
|
||||
* @return the deserialized component style
|
||||
* @throws IllegalArgumentException if anything other than a valid JSON
|
||||
* component style string is passed as input
|
||||
*/
|
||||
public ComponentStyle deserializeStyle(String json)
|
||||
{
|
||||
JsonElement jsonElement = JsonParser.parseString( json );
|
||||
|
||||
return deserializeStyle( jsonElement );
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a JSON element as a component style.
|
||||
*
|
||||
* @param jsonElement the component style json to parse
|
||||
* @return the deserialized component style
|
||||
* @throws IllegalArgumentException if anything other than a valid JSON
|
||||
* component style is passed as input
|
||||
*/
|
||||
public ComponentStyle deserializeStyle(JsonElement jsonElement)
|
||||
{
|
||||
return gson.fromJson( jsonElement, ComponentStyle.class );
|
||||
}
|
||||
|
||||
public JsonElement toJson(BaseComponent component)
|
||||
{
|
||||
return gson.toJsonTree( component );
|
||||
}
|
||||
|
||||
public JsonElement toJson(ComponentStyle style)
|
||||
{
|
||||
return gson.toJsonTree( style );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object the object to serialize
|
||||
* @return the JSON string representation of the object
|
||||
* @deprecated Error-prone, be careful which object you input here
|
||||
*/
|
||||
@Deprecated
|
||||
public String toString(Object object)
|
||||
{
|
||||
return gson.toJson( object );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param content the content to serialize
|
||||
* @return the JSON string representation of the object
|
||||
* @deprecated for legacy internal use only
|
||||
*/
|
||||
@Deprecated
|
||||
public String toString(Content content)
|
||||
{
|
||||
return gson.toJson( content );
|
||||
}
|
||||
|
||||
public String toString(BaseComponent component)
|
||||
{
|
||||
return gson.toJson( component );
|
||||
}
|
||||
|
||||
public String toString(BaseComponent... components)
|
||||
{
|
||||
if ( components.length == 1 )
|
||||
{
|
||||
return gson.toJson( components[0] );
|
||||
} else
|
||||
{
|
||||
return gson.toJson( new TextComponent( components ) );
|
||||
}
|
||||
}
|
||||
|
||||
public String toString(ComponentStyle style)
|
||||
{
|
||||
return gson.toJson( style );
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
||||
{
|
||||
if ( json.isJsonPrimitive() )
|
||||
{
|
||||
return new TextComponent( json.getAsString() );
|
||||
}
|
||||
JsonObject object = json.getAsJsonObject();
|
||||
if ( object.has( "translate" ) )
|
||||
{
|
||||
return context.deserialize( json, TranslatableComponent.class );
|
||||
}
|
||||
if ( object.has( "keybind" ) )
|
||||
{
|
||||
return context.deserialize( json, KeybindComponent.class );
|
||||
}
|
||||
if ( object.has( "score" ) )
|
||||
{
|
||||
return context.deserialize( json, ScoreComponent.class );
|
||||
}
|
||||
if ( object.has( "selector" ) )
|
||||
{
|
||||
return context.deserialize( json, SelectorComponent.class );
|
||||
}
|
||||
return context.deserialize( json, TextComponent.class );
|
||||
}
|
||||
}
|
@ -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.21-R0.1-SNAPSHOT</version>
|
||||
<version>1.21-R0.3-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-config</artifactId>
|
||||
<version>1.21-R0.1-SNAPSHOT</version>
|
||||
<version>1.21-R0.3-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-Config</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.21-R0.1-SNAPSHOT</version>
|
||||
<version>1.21-R0.3-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-event</artifactId>
|
||||
<version>1.21-R0.1-SNAPSHOT</version>
|
||||
<version>1.21-R0.3-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.21-R0.1-SNAPSHOT</version>
|
||||
<version>1.21-R0.3-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-log</artifactId>
|
||||
<version>1.21-R0.1-SNAPSHOT</version>
|
||||
<version>1.21-R0.3-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.21-R0.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-module-cmd-alert</artifactId>
|
||||
<version>1.21-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.fromLegacy( 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.21-R0.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-module-cmd-find</artifactId>
|
||||
<version>1.21-R0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>cmd_find</name>
|
||||
<description>Provides the find command</description>
|
||||
</project>
|
@ -1,58 +0,0 @@
|
||||
package net.md_5.bungee.module.cmd.find;
|
||||
|
||||
import java.util.Collections;
|
||||
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.config.ServerInfo;
|
||||
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
|
||||
{
|
||||
boolean moduleLoaded = ProxyServer.getInstance().getPluginManager().getPlugin( "cmd_server" ) != null;
|
||||
ServerInfo server = player.getServer().getInfo();
|
||||
ComponentBuilder componentBuilder = new ComponentBuilder().appendLegacy( ProxyServer.getInstance().getTranslation( "user_online_at", player.getName(), server.getName() ) );
|
||||
|
||||
if ( moduleLoaded && server.canAccess( sender ) )
|
||||
{
|
||||
componentBuilder.event( new HoverEvent(
|
||||
HoverEvent.Action.SHOW_TEXT,
|
||||
new ComponentBuilder().appendLegacy( ProxyServer.getInstance().getTranslation( "click_to_connect" ) ).create() )
|
||||
);
|
||||
componentBuilder.event( new ClickEvent( ClickEvent.Action.RUN_COMMAND, "/server " + server.getName() ) );
|
||||
}
|
||||
|
||||
sender.sendMessage( componentBuilder.create() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<String> onTabComplete(CommandSender sender, String[] args)
|
||||
{
|
||||
return args.length == 1 ? super.onTabComplete( sender, args ) : Collections.emptyList();
|
||||
}
|
||||
}
|
@ -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.21-R0.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-module-cmd-kick</artifactId>
|
||||
<version>1.21-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.fromLegacy( ProxyServer.getInstance().getTranslation( "user_not_online" ) ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( args.length == 1 )
|
||||
{
|
||||
player.disconnect( TextComponent.fromLegacy( ProxyServer.getInstance().getTranslation( "kick_message" ) ) );
|
||||
} else
|
||||
{
|
||||
String[] reason = new String[ args.length - 1 ];
|
||||
System.arraycopy( args, 1, reason, 0, reason.length );
|
||||
player.disconnect( TextComponent.fromLegacy( 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.21-R0.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-module-cmd-list</artifactId>
|
||||
<version>1.21-R0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>cmd_list</name>
|
||||
<description>Provides the glist command</description>
|
||||
</project>
|
@ -1,79 +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.chat.BaseComponent;
|
||||
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.hover.content.Text;
|
||||
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" );
|
||||
boolean moduleLoaded = ProxyServer.getInstance().getPluginManager().getPlugin( "cmd_server" ) != null;
|
||||
|
||||
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 );
|
||||
|
||||
BaseComponent baseComponent = new ComponentBuilder().appendLegacy( ProxyServer.getInstance().getTranslation( "command_list", server.getName(), players.size(), String.join( ChatColor.RESET + ", ", players ) ) ).build();
|
||||
|
||||
if ( moduleLoaded )
|
||||
{
|
||||
baseComponent.setHoverEvent( new HoverEvent(
|
||||
HoverEvent.Action.SHOW_TEXT,
|
||||
new Text( new ComponentBuilder().appendLegacy( ProxyServer.getInstance().getTranslation( "click_to_connect" ) ).create() ) )
|
||||
);
|
||||
baseComponent.setClickEvent( new ClickEvent( ClickEvent.Action.RUN_COMMAND, "/server " + server.getName() ) );
|
||||
}
|
||||
|
||||
sender.sendMessage( baseComponent );
|
||||
}
|
||||
|
||||
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.21-R0.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-module-cmd-send</artifactId>
|
||||
<version>1.21-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, Collections.synchronizedList( new ArrayList<>() ) );
|
||||
}
|
||||
}
|
||||
|
||||
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.21-R0.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-module-cmd-server</artifactId>
|
||||
<version>1.21-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.21-R0.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-module</artifactId>
|
||||
<version>1.21-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.21-R0.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-module-reconnect-yaml</artifactId>
|
||||
<version>1.21-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.21-R0.1-SNAPSHOT</version>
|
||||
<version>1.21-R0.3-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-native</artifactId>
|
||||
<version>1.21-R0.1-SNAPSHOT</version>
|
||||
<version>1.21-R0.3-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-Native</name>
|
||||
|
@ -37,9 +37,6 @@ public class NativeCipher implements BungeeCipher
|
||||
@Override
|
||||
public void cipher(ByteBuf in, ByteBuf out) throws GeneralSecurityException
|
||||
{
|
||||
// Smoke tests
|
||||
in.memoryAddress();
|
||||
out.memoryAddress();
|
||||
Preconditions.checkState( ctx != 0, "Invalid pointer to AES key!" );
|
||||
|
||||
// Store how many bytes we can cipher
|
||||
|
@ -48,14 +48,17 @@ public class NativeZlib implements BungeeZlib
|
||||
@Override
|
||||
public void process(ByteBuf in, ByteBuf out) throws DataFormatException
|
||||
{
|
||||
// Smoke tests
|
||||
in.memoryAddress();
|
||||
out.memoryAddress();
|
||||
Preconditions.checkState( ctx != 0, "Invalid pointer to compress!" );
|
||||
|
||||
while ( !nativeCompress.finished && ( compress || in.isReadable() ) )
|
||||
{
|
||||
if ( compress )
|
||||
{
|
||||
out.ensureWritable( OUTPUT_BUFFER_SIZE );
|
||||
} else
|
||||
{
|
||||
Preconditions.checkArgument( out.isWritable(), "Output buffer overrun" );
|
||||
}
|
||||
|
||||
int processed;
|
||||
try
|
||||
|
@ -64,7 +64,7 @@ public class NativeZlibTest
|
||||
|
||||
zlib.process( originalBuf, compressed );
|
||||
|
||||
ByteBuf uncompressed = Unpooled.directBuffer();
|
||||
ByteBuf uncompressed = Unpooled.directBuffer( dataBuf.length, dataBuf.length );
|
||||
|
||||
zlib.init( false, 0 );
|
||||
zlib.process( compressed, uncompressed );
|
||||
|
22
pom.xml
22
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.21-R0.1-SNAPSHOT</version>
|
||||
<version>1.21-R0.3-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.32</lombok.version>
|
||||
<lombok.version>1.18.36</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.115.Final</version>
|
||||
<version>4.1.119.Final</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@ -138,7 +137,7 @@
|
||||
<artifactId>scriptus</artifactId>
|
||||
<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>
|
||||
@ -157,7 +156,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>3.3.1</version>
|
||||
<version>3.6.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>process-classes</phase>
|
||||
@ -275,6 +274,15 @@
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>jdk-21-proc</id>
|
||||
<activation>
|
||||
<jdk>[21,)</jdk>
|
||||
</activation>
|
||||
<properties>
|
||||
<maven.compiler.proc>full</maven.compiler.proc>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>dist</id>
|
||||
<build>
|
||||
|
@ -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.21-R0.1-SNAPSHOT</version>
|
||||
<version>1.21-R0.3-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-protocol</artifactId>
|
||||
<version>1.21-R0.1-SNAPSHOT</version>
|
||||
<version>1.21-R0.3-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-Protocol</name>
|
||||
@ -35,7 +34,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>
|
||||
|
@ -0,0 +1,19 @@
|
||||
package net.md_5.bungee.protocol;
|
||||
|
||||
import net.md_5.bungee.chat.ChatVersion;
|
||||
import net.md_5.bungee.chat.VersionedComponentSerializer;
|
||||
|
||||
public class ChatSerializer
|
||||
{
|
||||
|
||||
public static VersionedComponentSerializer forVersion(int protocolVersion)
|
||||
{
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_21_5 )
|
||||
{
|
||||
return VersionedComponentSerializer.forVersion( ChatVersion.V1_21_5 );
|
||||
} else
|
||||
{
|
||||
return VersionedComponentSerializer.forVersion( ChatVersion.V1_16 );
|
||||
}
|
||||
}
|
||||
}
|
@ -15,12 +15,12 @@ import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.function.BiConsumer;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.ComponentStyle;
|
||||
import net.md_5.bungee.chat.ComponentSerializer;
|
||||
import se.llbit.nbt.ErrorTag;
|
||||
import se.llbit.nbt.NamedTag;
|
||||
import se.llbit.nbt.SpecificTag;
|
||||
@ -69,6 +69,15 @@ public abstract class DefinedPacket
|
||||
buf.writeBytes( b );
|
||||
}
|
||||
|
||||
public static <T> T readStringMapKey(ByteBuf buf, Map<String, T> map)
|
||||
{
|
||||
String string = readString( buf );
|
||||
T result = map.get( string );
|
||||
Preconditions.checkArgument( result != null, "Unknown string key %s", string );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String readString(ByteBuf buf)
|
||||
{
|
||||
return readString( buf, Short.MAX_VALUE );
|
||||
@ -110,12 +119,12 @@ public abstract class DefinedPacket
|
||||
SpecificTag nbt = (SpecificTag) readTag( buf, protocolVersion );
|
||||
JsonElement json = TagUtil.toJson( nbt );
|
||||
|
||||
return ComponentSerializer.deserialize( json );
|
||||
return ChatSerializer.forVersion( protocolVersion ).deserialize( json );
|
||||
} else
|
||||
{
|
||||
String string = readString( buf, maxStringLength );
|
||||
|
||||
return ComponentSerializer.deserialize( string );
|
||||
return ChatSerializer.forVersion( protocolVersion ).deserialize( string );
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,7 +133,7 @@ public abstract class DefinedPacket
|
||||
SpecificTag nbt = (SpecificTag) readTag( buf, protocolVersion );
|
||||
JsonElement json = TagUtil.toJson( nbt );
|
||||
|
||||
return ComponentSerializer.deserializeStyle( json );
|
||||
return ChatSerializer.forVersion( protocolVersion ).deserializeStyle( json );
|
||||
}
|
||||
|
||||
public static void writeEitherBaseComponent(Either<String, BaseComponent> message, ByteBuf buf, int protocolVersion)
|
||||
@ -142,13 +151,13 @@ public abstract class DefinedPacket
|
||||
{
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_3 )
|
||||
{
|
||||
JsonElement json = ComponentSerializer.toJson( message );
|
||||
JsonElement json = ChatSerializer.forVersion( protocolVersion ).toJson( message );
|
||||
SpecificTag nbt = TagUtil.fromJson( json );
|
||||
|
||||
writeTag( nbt, buf, protocolVersion );
|
||||
} else
|
||||
{
|
||||
String string = ComponentSerializer.toString( message );
|
||||
String string = ChatSerializer.forVersion( protocolVersion ).toString( message );
|
||||
|
||||
writeString( string, buf );
|
||||
}
|
||||
@ -156,7 +165,7 @@ public abstract class DefinedPacket
|
||||
|
||||
public static void writeComponentStyle(ComponentStyle style, ByteBuf buf, int protocolVersion)
|
||||
{
|
||||
JsonElement json = ComponentSerializer.toJson( style );
|
||||
JsonElement json = ChatSerializer.forVersion( protocolVersion ).toJson( style );
|
||||
SpecificTag nbt = TagUtil.fromJson( json );
|
||||
|
||||
writeTag( nbt, buf, protocolVersion );
|
||||
@ -282,6 +291,31 @@ public abstract class DefinedPacket
|
||||
}
|
||||
}
|
||||
|
||||
public static void setVarInt(int value, ByteBuf output, int pos, int len)
|
||||
{
|
||||
switch ( len )
|
||||
{
|
||||
case 1:
|
||||
output.setByte( pos, value );
|
||||
break;
|
||||
case 2:
|
||||
output.setShort( pos, ( value & 0x7F | 0x80 ) << 8 | ( value >>> 7 & 0x7F ) );
|
||||
break;
|
||||
case 3:
|
||||
output.setMedium( pos, ( value & 0x7F | 0x80 ) << 16 | ( value >>> 7 & 0x7F | 0x80 ) << 8 | ( value >>> 14 & 0x7F ) );
|
||||
break;
|
||||
case 4:
|
||||
output.setInt( pos, ( value & 0x7F | 0x80 ) << 24 | ( value >>> 7 & 0x7F | 0x80 ) << 16 | ( value >>> 14 & 0x7F | 0x80 ) << 8 | ( value >>> 21 & 0x7F ) );
|
||||
break;
|
||||
case 5:
|
||||
output.setInt( pos, ( value & 0x7F | 0x80 ) << 24 | ( value >>> 7 & 0x7F | 0x80 ) << 16 | ( value >>> 14 & 0x7F | 0x80 ) << 8 | ( value >>> 21 & 0x7F | 0x80 ) );
|
||||
output.setByte( pos + 4, value >>> 28 );
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException( "Invalid varint len: " + len );
|
||||
}
|
||||
}
|
||||
|
||||
public static int readVarShort(ByteBuf buf)
|
||||
{
|
||||
int low = buf.readUnsignedShort();
|
||||
|
@ -99,7 +99,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x23 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x24 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x26 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x27 )
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x27 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x26 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
Login.class,
|
||||
@ -117,7 +118,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x28 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x29 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x2B ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x2C )
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x2C ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x2B )
|
||||
);
|
||||
TO_CLIENT.registerPacket( Chat.class,
|
||||
Chat::new,
|
||||
@ -149,7 +151,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x43 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_3, 0x45 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x47 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x4C )
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x4C ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x4B )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
BossBar.class,
|
||||
@ -160,7 +163,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_17, 0x0D ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x0A ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x0B ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x0A )
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x0A ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x09 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
PlayerListItem.class, // PlayerInfo
|
||||
@ -191,7 +195,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x0E ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x0D ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x0F ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x10 )
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x10 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x0F )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
ScoreboardObjective.class,
|
||||
@ -210,7 +215,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x5A ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_3, 0x5C ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x5E ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x64 )
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x64 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x63 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
ScoreboardScore.class,
|
||||
@ -229,14 +235,16 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x5D ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_3, 0x5F ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x61 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x68 )
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x68 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x67 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
ScoreboardScoreReset.class,
|
||||
ScoreboardScoreReset::new,
|
||||
map( ProtocolConstants.MINECRAFT_1_20_3, 0x42 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x44 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x49 )
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x49 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x48 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
ScoreboardDisplay.class,
|
||||
@ -255,7 +263,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x53 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_3, 0x55 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x57 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x5C )
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x5C ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x5B )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
Team.class,
|
||||
@ -274,7 +283,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x5C ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_3, 0x5E ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x60 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x67 )
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x67 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x66 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
PluginMessage.class,
|
||||
@ -292,7 +302,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x15 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x17 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x18 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x19 )
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x19 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x18 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
Kick.class,
|
||||
@ -310,7 +321,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x17 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x1A ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x1B ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x1D )
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x1D ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x1C )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
Title.class,
|
||||
@ -330,7 +342,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x61 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_3, 0x63 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x65 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x6C )
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x6C ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x6B )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
ClearTitles.class,
|
||||
@ -339,7 +352,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x0D ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x0C ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x0E ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x0F )
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x0F ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x0E )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
Subtitle.class,
|
||||
@ -352,7 +366,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x5F ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_3, 0x61 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x63 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x6A )
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x6A ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x69 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
TitleTimes.class,
|
||||
@ -365,7 +380,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x62 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_3, 0x64 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x66 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x6D )
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x6D ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x6C )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
SystemChat.class,
|
||||
@ -377,7 +393,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x67 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_3, 0x69 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x6C ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x73 )
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x73 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x72 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
PlayerListHeaderFooter.class,
|
||||
@ -400,7 +417,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x68 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_3, 0x6A ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x6D ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x74 )
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x74 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x73 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
EntityStatus.class,
|
||||
@ -418,7 +436,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x19 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x1C ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x1D ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x1F )
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x1F ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x1E )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
Commands.class,
|
||||
@ -431,7 +450,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19, 0x0F ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_3, 0x0E ),
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x10 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x11 )
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x11 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x10 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
GameState.class,
|
||||
@ -446,7 +466,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x1F ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x20 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x22 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x23 )
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x23 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x22 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
ViewDistance.class,
|
||||
@ -462,7 +483,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x51 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_3, 0x53 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x55 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x59 )
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x59 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x58 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
ServerData.class,
|
||||
@ -474,7 +496,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x47 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_3, 0x49 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x4B ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x50 )
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x50 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x4F )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
PlayerListItemRemove.class,
|
||||
@ -483,7 +506,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x39 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x3B ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x3D ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x3F )
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x3F ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x3E )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
PlayerListItemUpdate.class,
|
||||
@ -492,7 +516,8 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_19_4, 0x3A ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x3C ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x3E ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x40 )
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x40 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x3F )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
StartConfiguration.class,
|
||||
@ -500,18 +525,21 @@ public enum Protocol
|
||||
map( ProtocolConstants.MINECRAFT_1_20_2, 0x65 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_3, 0x67 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x69 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x70 )
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x70 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x6F )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
CookieRequest.class,
|
||||
CookieRequest::new,
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x16 )
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x16 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x15 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
StoreCookie.class,
|
||||
StoreCookie::new,
|
||||
map( ProtocolConstants.MINECRAFT_1_20_5, 0x6B ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x72 )
|
||||
map( ProtocolConstants.MINECRAFT_1_21_2, 0x72 ),
|
||||
map( ProtocolConstants.MINECRAFT_1_21_5, 0x71 )
|
||||
);
|
||||
TO_CLIENT.registerPacket(
|
||||
Transfer.class,
|
||||
@ -965,6 +993,8 @@ public enum Protocol
|
||||
}
|
||||
|
||||
ProtocolData data = protocols.get( protocol );
|
||||
Preconditions.checkState( data.packetConstructors[mapping.packetID] == null, "Duplicate packet mapping (%s)", mapping.packetID );
|
||||
|
||||
data.packetMap.put( packetClass, mapping.packetID );
|
||||
data.packetConstructors[mapping.packetID] = constructor;
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ public class ProtocolConstants
|
||||
public static final int MINECRAFT_1_21 = 767;
|
||||
public static final int MINECRAFT_1_21_2 = 768;
|
||||
public static final int MINECRAFT_1_21_4 = 769;
|
||||
public static final int MINECRAFT_1_21_5 = 770;
|
||||
public static final List<String> SUPPORTED_VERSIONS;
|
||||
public static final List<Integer> SUPPORTED_VERSION_IDS;
|
||||
|
||||
@ -112,13 +113,14 @@ public class ProtocolConstants
|
||||
ProtocolConstants.MINECRAFT_1_20_5,
|
||||
ProtocolConstants.MINECRAFT_1_21,
|
||||
ProtocolConstants.MINECRAFT_1_21_2,
|
||||
ProtocolConstants.MINECRAFT_1_21_4
|
||||
ProtocolConstants.MINECRAFT_1_21_4,
|
||||
ProtocolConstants.MINECRAFT_1_21_5
|
||||
);
|
||||
|
||||
if ( SNAPSHOT_SUPPORT )
|
||||
{
|
||||
// supportedVersions.add( "1.21.x" );
|
||||
// supportedVersionIds.add( ProtocolConstants.MINECRAFT_1_21_4 );
|
||||
// supportedVersionIds.add( ProtocolConstants.MINECRAFT_1_21_5 );
|
||||
}
|
||||
|
||||
SUPPORTED_VERSIONS = supportedVersions.build();
|
||||
|
@ -82,13 +82,27 @@ public final class TagUtil
|
||||
{
|
||||
List<JsonElement> jsonArray = ( (JsonArray) json ).asList();
|
||||
|
||||
if ( jsonArray.isEmpty() )
|
||||
Integer listType = null;
|
||||
|
||||
for ( JsonElement jsonEl : jsonArray )
|
||||
{
|
||||
int type = fromJson( jsonEl ).tagType();
|
||||
if ( listType == null )
|
||||
{
|
||||
listType = type;
|
||||
} else if ( listType != type )
|
||||
{
|
||||
listType = Tag.TAG_COMPOUND;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( listType == null )
|
||||
{
|
||||
return new ListTag( Tag.TAG_END, Collections.emptyList() );
|
||||
}
|
||||
|
||||
SpecificTag listTag;
|
||||
int listType = fromJson( jsonArray.get( 0 ) ).tagType();
|
||||
switch ( listType )
|
||||
{
|
||||
case Tag.TAG_BYTE:
|
||||
@ -124,7 +138,7 @@ public final class TagUtil
|
||||
for ( JsonElement jsonEl : jsonArray )
|
||||
{
|
||||
SpecificTag subTag = fromJson( jsonEl );
|
||||
if ( !( subTag instanceof CompoundTag ) )
|
||||
if ( listType == Tag.TAG_COMPOUND && !( subTag instanceof CompoundTag ) )
|
||||
{
|
||||
CompoundTag wrapper = new CompoundTag();
|
||||
wrapper.add( "", subTag );
|
||||
|
@ -1,26 +0,0 @@
|
||||
package net.md_5.bungee.protocol;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToMessageEncoder;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Prepend length of the message as a Varint21 using an extra buffer for the
|
||||
* length, avoiding copying packet data
|
||||
*/
|
||||
@ChannelHandler.Sharable
|
||||
public class Varint21LengthFieldExtraBufPrepender extends MessageToMessageEncoder<ByteBuf>
|
||||
{
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception
|
||||
{
|
||||
int bodyLen = msg.readableBytes();
|
||||
ByteBuf lenBuf = ctx.alloc().ioBuffer( Varint21LengthFieldPrepender.varintSize( bodyLen ) );
|
||||
DefinedPacket.writeVarInt( bodyLen, lenBuf );
|
||||
out.add( lenBuf );
|
||||
out.add( msg.retain() );
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
package net.md_5.bungee.protocol;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToMessageEncoder;
|
||||
import java.util.List;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Prepend length of the message as a Varint21 by writing length and data to a
|
||||
* new buffer
|
||||
*/
|
||||
public class Varint21LengthFieldPrepender extends MessageToMessageEncoder<ByteBuf>
|
||||
{
|
||||
|
||||
@Setter
|
||||
private boolean compose = true;
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> list) throws Exception
|
||||
{
|
||||
int bodyLen = msg.readableBytes();
|
||||
int headerLen = varintSize( bodyLen );
|
||||
if ( compose )
|
||||
{
|
||||
ByteBuf buf = ctx.alloc().directBuffer( headerLen );
|
||||
DefinedPacket.writeVarInt( bodyLen, buf );
|
||||
list.add( ctx.alloc().compositeDirectBuffer( 2 ).addComponents( true, buf, msg.retain() ) );
|
||||
} else
|
||||
{
|
||||
ByteBuf buf = ctx.alloc().directBuffer( headerLen + bodyLen );
|
||||
DefinedPacket.writeVarInt( bodyLen, buf );
|
||||
buf.writeBytes( msg );
|
||||
list.add( buf );
|
||||
}
|
||||
}
|
||||
|
||||
static int varintSize(int paramInt)
|
||||
{
|
||||
if ( ( paramInt & 0xFFFFFF80 ) == 0 )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if ( ( paramInt & 0xFFFFC000 ) == 0 )
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
if ( ( paramInt & 0xFFE00000 ) == 0 )
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
if ( ( paramInt & 0xF0000000 ) == 0 )
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
return 5;
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package net.md_5.bungee.protocol.channel;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* This class hold a netty channel initializer that calls the given {@link ChannelAcceptor}.
|
||||
* Use {@link BungeeChannelInitializer#create(ChannelAcceptor)} to create a new instance.
|
||||
* <p>
|
||||
* Please note that this API is unsafe and doesn't provide any guarantees about
|
||||
* the stability of the channel pipeline or the API itself. Use at your own
|
||||
* risk.
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public abstract class BungeeChannelInitializer
|
||||
{
|
||||
|
||||
public abstract ChannelAcceptor getChannelAcceptor();
|
||||
|
||||
public abstract ChannelInitializer<Channel> getChannelInitializer();
|
||||
|
||||
/**
|
||||
* Creates a new instance of BungeeChannelInitializer
|
||||
*
|
||||
* @param acceptor the {@link ChannelAcceptor} that will accept the channel
|
||||
* and initializer the pipeline
|
||||
* @return {@link BungeeChannelInitializer} containing a cached
|
||||
* {@link ChannelInitializer} that will call the acceptor
|
||||
*/
|
||||
public static BungeeChannelInitializer create(ChannelAcceptor acceptor)
|
||||
{
|
||||
return new BungeeChannelInitializer()
|
||||
{
|
||||
@Getter
|
||||
private final ChannelAcceptor channelAcceptor = acceptor;
|
||||
|
||||
@Getter // cache the ChannelInitializer
|
||||
private final ChannelInitializer<Channel> channelInitializer = new ChannelInitializer<Channel>()
|
||||
{
|
||||
@Override
|
||||
protected void initChannel(Channel channel) throws Exception
|
||||
{
|
||||
if ( !getChannelAcceptor().accept( channel ) )
|
||||
{
|
||||
channel.close();
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package net.md_5.bungee.protocol.channel;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ChannelAcceptor
|
||||
{
|
||||
|
||||
/**
|
||||
* Inside this method the pipeline should be initialized.
|
||||
*
|
||||
* @param channel the channel to be accepted and initialized
|
||||
* @return if the channel was accepted
|
||||
*/
|
||||
boolean accept(Channel channel);
|
||||
}
|
@ -25,6 +25,7 @@ public class ClientChat extends DefinedPacket
|
||||
private boolean signedPreview;
|
||||
private ChatChain chain;
|
||||
private SeenMessages seenMessages;
|
||||
private byte checksum;
|
||||
|
||||
@Override
|
||||
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
|
||||
@ -57,6 +58,11 @@ public class ClientChat extends DefinedPacket
|
||||
chain = new ChatChain();
|
||||
chain.read( buf, direction, protocolVersion );
|
||||
}
|
||||
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_21_5 )
|
||||
{
|
||||
checksum = buf.readByte();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -87,6 +93,11 @@ public class ClientChat extends DefinedPacket
|
||||
{
|
||||
chain.write( buf, direction, protocolVersion );
|
||||
}
|
||||
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_21_5 )
|
||||
{
|
||||
buf.writeByte( checksum );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -28,6 +28,7 @@ public class ClientCommand extends DefinedPacket
|
||||
private boolean signedPreview;
|
||||
private ChatChain chain;
|
||||
private SeenMessages seenMessages;
|
||||
private byte checksum;
|
||||
|
||||
@Override
|
||||
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
|
||||
@ -68,6 +69,11 @@ public class ClientCommand extends DefinedPacket
|
||||
chain = new ChatChain();
|
||||
chain.read( buf, direction, protocolVersion );
|
||||
}
|
||||
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_21_5 )
|
||||
{
|
||||
checksum = buf.readByte();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -101,6 +107,11 @@ public class ClientCommand extends DefinedPacket
|
||||
{
|
||||
chain.write( buf, direction, protocolVersion );
|
||||
}
|
||||
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_21_5 )
|
||||
{
|
||||
buf.writeByte( checksum );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -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<>();
|
||||
@ -312,6 +313,7 @@ public class Commands extends DefinedPacket
|
||||
private static final ArgumentSerializer[] IDS_1_19_4;
|
||||
private static final ArgumentSerializer[] IDS_1_20_3;
|
||||
private static final ArgumentSerializer[] IDS_1_20_5;
|
||||
private static final ArgumentSerializer[] IDS_1_21_5;
|
||||
private static final Map<Class<?>, ProperArgumentSerializer<?>> PROPER_PROVIDERS = new HashMap<>();
|
||||
//
|
||||
private static final ArgumentSerializer<Void> VOID = new ArgumentSerializer<Void>()
|
||||
@ -327,18 +329,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>()
|
||||
@ -355,7 +368,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)
|
||||
@ -383,8 +396,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)
|
||||
@ -412,8 +437,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)
|
||||
@ -441,6 +478,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>()
|
||||
{
|
||||
@ -456,7 +505,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)
|
||||
@ -484,6 +533,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>()
|
||||
{
|
||||
@ -539,11 +600,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 );
|
||||
@ -858,6 +928,65 @@ public class Commands extends DefinedPacket
|
||||
get( "minecraft:loot_predicate", VOID ),
|
||||
get( "minecraft:loot_modifier", VOID )
|
||||
};
|
||||
|
||||
IDS_1_21_5 = new ArgumentSerializer[]
|
||||
{
|
||||
get( "brigadier:bool", VOID ),
|
||||
get( "brigadier:float", FLOAT_RANGE ),
|
||||
get( "brigadier:double", DOUBLE_RANGE ),
|
||||
get( "brigadier:integer", INTEGER_RANGE ),
|
||||
get( "brigadier:long", LONG_RANGE ),
|
||||
get( "brigadier:string", STRING ),
|
||||
get( "minecraft:entity", BYTE ),
|
||||
get( "minecraft:game_profile", VOID ),
|
||||
get( "minecraft:block_pos", VOID ),
|
||||
get( "minecraft:column_pos", VOID ),
|
||||
get( "minecraft:vec3", VOID ),
|
||||
get( "minecraft:vec2", VOID ),
|
||||
get( "minecraft:block_state", VOID ),
|
||||
get( "minecraft:block_predicate", VOID ),
|
||||
get( "minecraft:item_stack", VOID ),
|
||||
get( "minecraft:item_predicate", VOID ),
|
||||
get( "minecraft:color", VOID ),
|
||||
get( "minecraft:component", VOID ),
|
||||
get( "minecraft:style", VOID ),
|
||||
get( "minecraft:message", VOID ),
|
||||
get( "minecraft:nbt_compound_tag", VOID ),
|
||||
get( "minecraft:nbt_tag", VOID ),
|
||||
get( "minecraft:nbt_path", VOID ),
|
||||
get( "minecraft:objective", VOID ),
|
||||
get( "minecraft:objective_criteria", VOID ),
|
||||
get( "minecraft:operation", VOID ),
|
||||
get( "minecraft:particle", VOID ),
|
||||
get( "minecraft:angle", VOID ),
|
||||
get( "minecraft:rotation", VOID ),
|
||||
get( "minecraft:scoreboard_slot", VOID ),
|
||||
get( "minecraft:score_holder", BYTE ),
|
||||
get( "minecraft:swizzle", VOID ),
|
||||
get( "minecraft:team", VOID ),
|
||||
get( "minecraft:item_slot", VOID ),
|
||||
get( "minecraft:item_slots", VOID ),
|
||||
get( "minecraft:resource_location", VOID ),
|
||||
get( "minecraft:function", VOID ),
|
||||
get( "minecraft:entity_anchor", VOID ),
|
||||
get( "minecraft:int_range", VOID ),
|
||||
get( "minecraft:float_range", VOID ),
|
||||
get( "minecraft:dimension", VOID ),
|
||||
get( "minecraft:gamemode", VOID ),
|
||||
get( "minecraft:time", INTEGER ),
|
||||
get( "minecraft:resource_or_tag", RAW_STRING ),
|
||||
get( "minecraft:resource_or_tag_key", RAW_STRING ),
|
||||
get( "minecraft:resource", RAW_STRING ),
|
||||
get( "minecraft:resource_key", RAW_STRING ),
|
||||
get( "minecraft:resource_selector", RAW_STRING ),
|
||||
get( "minecraft:template_mirror", VOID ),
|
||||
get( "minecraft:template_rotation", VOID ),
|
||||
get( "minecraft:uuid", VOID ),
|
||||
get( "minecraft:heightmap", VOID ),
|
||||
get( "minecraft:loot_table", VOID ),
|
||||
get( "minecraft:loot_predicate", VOID ),
|
||||
get( "minecraft:loot_modifier", VOID )
|
||||
};
|
||||
}
|
||||
|
||||
private static void register(String name, ArgumentSerializer serializer)
|
||||
@ -870,6 +999,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,7 +1406,10 @@ public class Commands extends DefinedPacket
|
||||
{
|
||||
key = readVarInt( buf );
|
||||
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_5 )
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_21_5 )
|
||||
{
|
||||
reader = IDS_1_21_5[(Integer) key];
|
||||
} else if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_5 )
|
||||
{
|
||||
reader = IDS_1_20_5[(Integer) key];
|
||||
} else if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_3 )
|
||||
@ -999,11 +1529,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>
|
||||
{
|
||||
|
@ -6,8 +6,8 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.chat.ComponentSerializer;
|
||||
import net.md_5.bungee.protocol.AbstractPacketHandler;
|
||||
import net.md_5.bungee.protocol.ChatSerializer;
|
||||
import net.md_5.bungee.protocol.DefinedPacket;
|
||||
import net.md_5.bungee.protocol.Protocol;
|
||||
import net.md_5.bungee.protocol.ProtocolConstants;
|
||||
@ -26,7 +26,7 @@ public class Kick extends DefinedPacket
|
||||
{
|
||||
if ( protocol == Protocol.LOGIN )
|
||||
{
|
||||
message = ComponentSerializer.deserialize( readString( buf ) );
|
||||
message = ChatSerializer.forVersion( protocolVersion ).deserialize( readString( buf ) );
|
||||
} else
|
||||
{
|
||||
message = readBaseComponent( buf, protocolVersion );
|
||||
@ -38,7 +38,7 @@ public class Kick extends DefinedPacket
|
||||
{
|
||||
if ( protocol == Protocol.LOGIN )
|
||||
{
|
||||
writeString( ComponentSerializer.toString( message ), buf );
|
||||
writeString( ChatSerializer.forVersion( protocolVersion ).toString( message ), buf );
|
||||
} else
|
||||
{
|
||||
writeBaseComponent( message, buf, protocolVersion );
|
||||
|
@ -22,19 +22,21 @@ import net.md_5.bungee.protocol.ProtocolConstants;
|
||||
public class PluginMessage extends DefinedPacket
|
||||
{
|
||||
|
||||
public static final String BUNGEE_CHANNEL_LEGACY = "BungeeCord";
|
||||
public static final String BUNGEE_CHANNEL_MODERN = "bungeecord:main";
|
||||
public static final Function<String, String> MODERNISE = new Function<String, String>()
|
||||
{
|
||||
@Override
|
||||
public String apply(String tag)
|
||||
{
|
||||
// Transform as per Bukkit
|
||||
if ( tag.equals( "BungeeCord" ) )
|
||||
if ( tag.equals( PluginMessage.BUNGEE_CHANNEL_LEGACY ) )
|
||||
{
|
||||
return "bungeecord:main";
|
||||
return PluginMessage.BUNGEE_CHANNEL_MODERN;
|
||||
}
|
||||
if ( tag.equals( "bungeecord:main" ) )
|
||||
if ( tag.equals( PluginMessage.BUNGEE_CHANNEL_MODERN ) )
|
||||
{
|
||||
return "BungeeCord";
|
||||
return PluginMessage.BUNGEE_CHANNEL_LEGACY;
|
||||
}
|
||||
|
||||
// Code that gets to here is UNLIKELY to be viable on the Bukkit side of side things,
|
||||
|
@ -1,10 +1,15 @@
|
||||
package net.md_5.bungee.protocol.packet;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.protocol.AbstractPacketHandler;
|
||||
import net.md_5.bungee.protocol.DefinedPacket;
|
||||
@ -26,8 +31,8 @@ public class Team extends DefinedPacket
|
||||
private Either<String, BaseComponent> displayName;
|
||||
private Either<String, BaseComponent> prefix;
|
||||
private Either<String, BaseComponent> suffix;
|
||||
private String nameTagVisibility;
|
||||
private String collisionRule;
|
||||
private NameTagVisibility nameTagVisibility;
|
||||
private CollisionRule collisionRule;
|
||||
private int color;
|
||||
private byte friendlyFire;
|
||||
private String[] players;
|
||||
@ -60,10 +65,18 @@ public class Team extends DefinedPacket
|
||||
displayName = readEitherBaseComponent( buf, protocolVersion, false );
|
||||
}
|
||||
friendlyFire = buf.readByte();
|
||||
nameTagVisibility = readString( buf );
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_21_5 )
|
||||
{
|
||||
nameTagVisibility = NameTagVisibility.BY_ID[readVarInt( buf )];
|
||||
collisionRule = CollisionRule.BY_ID[readVarInt( buf )];
|
||||
} else
|
||||
{
|
||||
nameTagVisibility = readStringMapKey( buf, NameTagVisibility.BY_NAME );
|
||||
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_9 )
|
||||
{
|
||||
collisionRule = readString( buf );
|
||||
collisionRule = readStringMapKey( buf, CollisionRule.BY_NAME );
|
||||
}
|
||||
}
|
||||
color = ( protocolVersion >= ProtocolConstants.MINECRAFT_1_13 ) ? readVarInt( buf ) : buf.readByte();
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_13 )
|
||||
@ -97,10 +110,17 @@ public class Team extends DefinedPacket
|
||||
writeEitherBaseComponent( suffix, buf, protocolVersion );
|
||||
}
|
||||
buf.writeByte( friendlyFire );
|
||||
writeString( nameTagVisibility, buf );
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_21_5 )
|
||||
{
|
||||
writeVarInt( nameTagVisibility.ordinal(), buf );
|
||||
writeVarInt( collisionRule.ordinal(), buf );
|
||||
} else
|
||||
{
|
||||
writeString( nameTagVisibility.getKey(), buf );
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_9 )
|
||||
{
|
||||
writeString( collisionRule, buf );
|
||||
writeString( collisionRule.getKey(), buf );
|
||||
}
|
||||
}
|
||||
|
||||
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_13 )
|
||||
@ -128,4 +148,66 @@ public class Team extends DefinedPacket
|
||||
{
|
||||
handler.handle( this );
|
||||
}
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum NameTagVisibility
|
||||
{
|
||||
|
||||
ALWAYS( "always" ),
|
||||
NEVER( "never" ),
|
||||
HIDE_FOR_OTHER_TEAMS( "hideForOtherTeams" ),
|
||||
HIDE_FOR_OWN_TEAM( "hideForOwnTeam" ),
|
||||
// 1.9 (and possibly other versions) appear to treat unknown values differently (always render rather than subject to spectator mode, friendly invisibles, etc).
|
||||
// we allow the empty value to achieve this in case it is potentially useful even though this is unsupported and its usage may be a bug (#3780).
|
||||
UNKNOWN( "" );
|
||||
//
|
||||
private final String key;
|
||||
//
|
||||
private static final Map<String, NameTagVisibility> BY_NAME;
|
||||
private static final NameTagVisibility[] BY_ID;
|
||||
|
||||
static
|
||||
{
|
||||
NameTagVisibility[] values = NameTagVisibility.values();
|
||||
ImmutableMap.Builder<String, NameTagVisibility> builder = ImmutableMap.builderWithExpectedSize( values.length );
|
||||
|
||||
for ( NameTagVisibility e : values )
|
||||
{
|
||||
builder.put( e.key, e );
|
||||
}
|
||||
|
||||
BY_NAME = builder.build();
|
||||
BY_ID = Arrays.copyOf( values, values.length - 1 ); // Ignore dummy UNKNOWN value
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum CollisionRule
|
||||
{
|
||||
|
||||
ALWAYS( "always" ),
|
||||
NEVER( "never" ),
|
||||
PUSH_OTHER_TEAMS( "pushOtherTeams" ),
|
||||
PUSH_OWN_TEAM( "pushOwnTeam" );
|
||||
//
|
||||
private final String key;
|
||||
//
|
||||
private static final Map<String, CollisionRule> BY_NAME;
|
||||
private static final CollisionRule[] BY_ID;
|
||||
|
||||
static
|
||||
{
|
||||
CollisionRule[] values = BY_ID = CollisionRule.values();
|
||||
ImmutableMap.Builder<String, CollisionRule> builder = ImmutableMap.builderWithExpectedSize( values.length );
|
||||
|
||||
for ( CollisionRule e : values )
|
||||
{
|
||||
builder.put( e.key, e );
|
||||
}
|
||||
|
||||
BY_NAME = builder.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,20 @@ package net.md_5.bungee.protocol;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import se.llbit.nbt.ByteArrayTag;
|
||||
import se.llbit.nbt.CompoundTag;
|
||||
import se.llbit.nbt.IntArrayTag;
|
||||
import se.llbit.nbt.IntTag;
|
||||
import se.llbit.nbt.ListTag;
|
||||
import se.llbit.nbt.LongArrayTag;
|
||||
import se.llbit.nbt.SpecificTag;
|
||||
import se.llbit.nbt.StringTag;
|
||||
import se.llbit.nbt.Tag;
|
||||
|
||||
public class TagUtilTest
|
||||
{
|
||||
@ -26,4 +37,190 @@ public class TagUtilTest
|
||||
{
|
||||
testDissembleReassemble( "{\"text\":\"\",\"extra\":[\"hello\",{\"text\":\"there\",\"color\":\"#ff0000\"},{\"text\":\"friend\",\"font\":\"minecraft:default\"}]}" );
|
||||
}
|
||||
|
||||
public void testCreateMixedList(JsonArray array)
|
||||
{
|
||||
SpecificTag tag = TagUtil.fromJson( array );
|
||||
assertInstanceOf( ListTag.class, tag );
|
||||
ListTag list = (ListTag) tag;
|
||||
assertEquals( SpecificTag.TAG_COMPOUND, list.getType() );
|
||||
assertEquals( array.size(), list.size() );
|
||||
|
||||
for ( int i = 0; i < list.size(); i++ )
|
||||
{
|
||||
assertTrue( i < array.size() );
|
||||
|
||||
Tag element = list.get( i );
|
||||
assertInstanceOf( CompoundTag.class, element );
|
||||
CompoundTag compound = (CompoundTag) element;
|
||||
|
||||
JsonElement expected = array.get( i );
|
||||
|
||||
if ( expected instanceof JsonObject )
|
||||
{
|
||||
assertEquals( TagUtil.fromJson( expected ), compound );
|
||||
} else
|
||||
{
|
||||
assertEquals( 1, compound.size() );
|
||||
Tag value = compound.get( "" );
|
||||
|
||||
if ( expected instanceof JsonPrimitive )
|
||||
{
|
||||
JsonPrimitive primitive = (JsonPrimitive) expected;
|
||||
|
||||
if ( primitive.isNumber() )
|
||||
{
|
||||
Number number = primitive.getAsNumber();
|
||||
|
||||
if ( number instanceof Integer )
|
||||
{
|
||||
assertInstanceOf( IntTag.class, value );
|
||||
|
||||
IntTag integer = (IntTag) value;
|
||||
assertEquals( array.get( i ).getAsInt(), integer.getData() );
|
||||
}
|
||||
|
||||
} else if ( primitive.isString() )
|
||||
{
|
||||
assertInstanceOf( StringTag.class, value );
|
||||
|
||||
StringTag string = (StringTag) value;
|
||||
assertEquals( array.get( i ).getAsString(), string.getData() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMixedListWithInt()
|
||||
{
|
||||
JsonArray array = new JsonArray();
|
||||
array.add( 1 );
|
||||
array.add( "a" );
|
||||
|
||||
testCreateMixedList( array );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMixedListWithString()
|
||||
{
|
||||
JsonArray array = new JsonArray();
|
||||
array.add( "a" );
|
||||
array.add( 1L );
|
||||
|
||||
testCreateMixedList( array );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMixedListWithObject()
|
||||
{
|
||||
JsonObject compound = new JsonObject();
|
||||
compound.addProperty( "a", "b" );
|
||||
|
||||
JsonArray array = new JsonArray();
|
||||
array.add( compound );
|
||||
array.add( 1L );
|
||||
|
||||
testCreateMixedList( array );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateEmptyList()
|
||||
{
|
||||
JsonArray array = new JsonArray();
|
||||
SpecificTag tag = TagUtil.fromJson( array );
|
||||
assertInstanceOf( ListTag.class, tag );
|
||||
ListTag list = (ListTag) tag;
|
||||
assertEquals( 0, list.size() );
|
||||
assertEquals( Tag.TAG_END, list.getType() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateByteArray()
|
||||
{
|
||||
JsonArray array = new JsonArray();
|
||||
array.add( ( (byte) 1 ) );
|
||||
array.add( ( (byte) 2 ) );
|
||||
|
||||
SpecificTag tag = TagUtil.fromJson( array );
|
||||
assertInstanceOf( ByteArrayTag.class, tag );
|
||||
ByteArrayTag byteArray = (ByteArrayTag) tag;
|
||||
assertEquals( 2, byteArray.getData().length );
|
||||
|
||||
for ( int i = 0; i < byteArray.getData().length; i++ )
|
||||
{
|
||||
assertTrue( i < array.size() );
|
||||
|
||||
byte item = byteArray.getData()[i];
|
||||
assertEquals( array.get( i ).getAsByte(), item );
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateIntArray()
|
||||
{
|
||||
JsonArray array = new JsonArray();
|
||||
array.add( 1 );
|
||||
array.add( 2 );
|
||||
|
||||
SpecificTag tag = TagUtil.fromJson( array );
|
||||
assertInstanceOf( IntArrayTag.class, tag );
|
||||
IntArrayTag intArray = (IntArrayTag) tag;
|
||||
assertEquals( 2, intArray.getData().length );
|
||||
|
||||
for ( int i = 0; i < intArray.getData().length; i++ )
|
||||
{
|
||||
assertTrue( i < array.size() );
|
||||
|
||||
int item = intArray.getData()[i];
|
||||
assertEquals( array.get( i ).getAsInt(), item );
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateLongArray()
|
||||
{
|
||||
JsonArray array = new JsonArray();
|
||||
array.add( 1L );
|
||||
array.add( 2L );
|
||||
|
||||
SpecificTag tag = TagUtil.fromJson( array );
|
||||
assertInstanceOf( LongArrayTag.class, tag );
|
||||
LongArrayTag intArray = (LongArrayTag) tag;
|
||||
assertEquals( 2, intArray.getData().length );
|
||||
|
||||
for ( int i = 0; i < intArray.getData().length; i++ )
|
||||
{
|
||||
assertTrue( i < array.size() );
|
||||
|
||||
long item = intArray.getData()[i];
|
||||
assertEquals( array.get( i ).getAsLong(), item );
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateStringList()
|
||||
{
|
||||
JsonArray array = new JsonArray();
|
||||
array.add( "a" );
|
||||
array.add( "b" );
|
||||
|
||||
SpecificTag tag = TagUtil.fromJson( array );
|
||||
assertInstanceOf( ListTag.class, tag );
|
||||
ListTag list = (ListTag) tag;
|
||||
assertEquals( SpecificTag.TAG_STRING, list.getType() );
|
||||
assertEquals( 2, list.size() );
|
||||
|
||||
for ( int i = 0; i < list.size(); i++ )
|
||||
{
|
||||
assertTrue( i < array.size() );
|
||||
|
||||
Tag item = list.get( i );
|
||||
assertInstanceOf( StringTag.class, item );
|
||||
|
||||
StringTag string = (StringTag) item;
|
||||
assertEquals( array.get( i ).getAsString(), string.getData() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ public class PluginMessageTest
|
||||
@Test
|
||||
public void testModerniseChannel()
|
||||
{
|
||||
assertEquals( "bungeecord:main", PluginMessage.MODERNISE.apply( "BungeeCord" ) );
|
||||
assertEquals( "BungeeCord", PluginMessage.MODERNISE.apply( "bungeecord:main" ) );
|
||||
assertEquals( PluginMessage.BUNGEE_CHANNEL_MODERN, PluginMessage.MODERNISE.apply( PluginMessage.BUNGEE_CHANNEL_LEGACY ) );
|
||||
assertEquals( PluginMessage.BUNGEE_CHANNEL_LEGACY, PluginMessage.MODERNISE.apply( PluginMessage.BUNGEE_CHANNEL_MODERN ) );
|
||||
assertEquals( "legacy:foo", PluginMessage.MODERNISE.apply( "FoO" ) );
|
||||
assertEquals( "foo:bar", PluginMessage.MODERNISE.apply( "foo:bar" ) );
|
||||
}
|
||||
|
@ -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.21-R0.1-SNAPSHOT</version>
|
||||
<version>1.21-R0.3-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-proxy</artifactId>
|
||||
<version>1.21-R0.1-SNAPSHOT</version>
|
||||
<version>1.21-R0.3-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-Proxy</name>
|
||||
@ -64,37 +63,37 @@
|
||||
<classifier>linux-aarch_64</classifier>
|
||||
</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>
|
||||
|
@ -6,8 +6,6 @@ import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
@ -52,31 +50,17 @@ import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.Synchronized;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.Favicon;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.ReconnectHandler;
|
||||
import net.md_5.bungee.api.ServerPing;
|
||||
import net.md_5.bungee.api.Title;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.ComponentStyle;
|
||||
import net.md_5.bungee.api.chat.KeybindComponent;
|
||||
import net.md_5.bungee.api.chat.ScoreComponent;
|
||||
import net.md_5.bungee.api.chat.SelectorComponent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.chat.TranslatableComponent;
|
||||
import net.md_5.bungee.api.config.ConfigurationAdapter;
|
||||
import net.md_5.bungee.api.config.ListenerInfo;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import net.md_5.bungee.api.plugin.PluginManager;
|
||||
import net.md_5.bungee.chat.ComponentSerializer;
|
||||
import net.md_5.bungee.chat.ComponentStyleSerializer;
|
||||
import net.md_5.bungee.chat.KeybindComponentSerializer;
|
||||
import net.md_5.bungee.chat.ScoreComponentSerializer;
|
||||
import net.md_5.bungee.chat.SelectorComponentSerializer;
|
||||
import net.md_5.bungee.chat.TextComponentSerializer;
|
||||
import net.md_5.bungee.chat.TranslatableComponentSerializer;
|
||||
import net.md_5.bungee.command.CommandBungee;
|
||||
import net.md_5.bungee.command.CommandEnd;
|
||||
import net.md_5.bungee.command.CommandIP;
|
||||
@ -91,10 +75,10 @@ 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;
|
||||
import net.md_5.bungee.protocol.channel.BungeeChannelInitializer;
|
||||
import net.md_5.bungee.protocol.packet.PluginMessage;
|
||||
import net.md_5.bungee.query.RemoteQuery;
|
||||
import net.md_5.bungee.scheduler.BungeeScheduler;
|
||||
@ -164,23 +148,12 @@ public class BungeeCord extends ProxyServer
|
||||
private final ConsoleReader consoleReader;
|
||||
@Getter
|
||||
private final Logger logger;
|
||||
public final Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter( BaseComponent.class, new ComponentSerializer() )
|
||||
.registerTypeAdapter( TextComponent.class, new TextComponentSerializer() )
|
||||
.registerTypeAdapter( TranslatableComponent.class, new TranslatableComponentSerializer() )
|
||||
.registerTypeAdapter( KeybindComponent.class, new KeybindComponentSerializer() )
|
||||
.registerTypeAdapter( ScoreComponent.class, new ScoreComponentSerializer() )
|
||||
.registerTypeAdapter( SelectorComponent.class, new SelectorComponentSerializer() )
|
||||
.registerTypeAdapter( ComponentStyle.class, new ComponentStyleSerializer() )
|
||||
.registerTypeAdapter( ServerPing.PlayerInfo.class, new PlayerInfoSerializer() )
|
||||
.registerTypeAdapter( Favicon.class, Favicon.getFaviconTypeAdapter() ).create();
|
||||
@Getter
|
||||
private ConnectionThrottle connectionThrottle;
|
||||
private final ModuleManager moduleManager = new ModuleManager();
|
||||
|
||||
{
|
||||
// TODO: Proper fallback when we interface the manager
|
||||
registerChannel( "BungeeCord" );
|
||||
registerChannel( PluginMessage.BUNGEE_CHANNEL_LEGACY );
|
||||
}
|
||||
|
||||
public static BungeeCord getInstance()
|
||||
@ -188,6 +161,21 @@ public class BungeeCord extends ProxyServer
|
||||
return (BungeeCord) ProxyServer.getInstance();
|
||||
}
|
||||
|
||||
private final Unsafe unsafe = new Unsafe()
|
||||
{
|
||||
@Getter
|
||||
@Setter
|
||||
private BungeeChannelInitializer frontendChannelInitializer;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private BungeeChannelInitializer backendChannelInitializer;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private BungeeChannelInitializer serverInfoChannelInitializer;
|
||||
};
|
||||
|
||||
@SuppressFBWarnings("DM_DEFAULT_ENCODING")
|
||||
public BungeeCord() throws IOException
|
||||
{
|
||||
@ -274,10 +262,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 );
|
||||
|
||||
@ -360,7 +344,7 @@ public class BungeeCord extends ProxyServer
|
||||
.channel( PipelineUtils.getServerChannel( info.getSocketAddress() ) )
|
||||
.option( ChannelOption.SO_REUSEADDR, true ) // TODO: Move this elsewhere!
|
||||
.childAttr( PipelineUtils.LISTENER, info )
|
||||
.childHandler( PipelineUtils.SERVER_CHILD )
|
||||
.childHandler( unsafe().getFrontendChannelInitializer().getChannelInitializer() )
|
||||
.group( eventLoops )
|
||||
.localAddress( info.getSocketAddress() )
|
||||
.bind().addListener( listener );
|
||||
@ -831,4 +815,10 @@ public class BungeeCord extends ProxyServer
|
||||
{
|
||||
return new BungeeTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Unsafe unsafe()
|
||||
{
|
||||
return unsafe;
|
||||
}
|
||||
}
|
||||
|
@ -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 ) );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,7 +186,7 @@ public class BungeeServerInfo implements ServerInfo
|
||||
new Bootstrap()
|
||||
.channel( PipelineUtils.getChannel( socketAddress ) )
|
||||
.group( BungeeCord.getInstance().eventLoops )
|
||||
.handler( PipelineUtils.BASE_SERVERSIDE )
|
||||
.handler( ProxyServer.getInstance().unsafe().getServerInfoChannelInitializer().getChannelInitializer() )
|
||||
.option( ChannelOption.CONNECT_TIMEOUT_MILLIS, BungeeCord.getInstance().getConfig().getRemotePingTimeout() )
|
||||
.remoteAddress( socketAddress )
|
||||
.connect()
|
||||
|
@ -156,7 +156,7 @@ public class BungeeTitle implements Title
|
||||
{
|
||||
if ( player.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_17 )
|
||||
{
|
||||
( (UserConnection) player ).sendPacketQueued( packet.newPacket );
|
||||
player.unsafe().sendPacketQueued( packet.newPacket );
|
||||
} else
|
||||
{
|
||||
player.unsafe().sendPacket( packet.oldPacket );
|
||||
|
@ -14,6 +14,7 @@ import net.md_5.bungee.api.connection.Server;
|
||||
import net.md_5.bungee.netty.ChannelWrapper;
|
||||
import net.md_5.bungee.protocol.DefinedPacket;
|
||||
import net.md_5.bungee.protocol.Protocol;
|
||||
import net.md_5.bungee.protocol.ProtocolConstants;
|
||||
import net.md_5.bungee.protocol.packet.PluginMessage;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@ -40,6 +41,18 @@ public class ServerConnection implements Server
|
||||
{
|
||||
ch.write( packet );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacketQueued(DefinedPacket packet)
|
||||
{
|
||||
if ( ch.getEncodeVersion() >= ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
ServerConnection.this.sendPacketQueued( packet );
|
||||
} else
|
||||
{
|
||||
sendPacket( packet );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public void sendPacketQueued(DefinedPacket packet)
|
||||
@ -53,6 +66,8 @@ public class ServerConnection implements Server
|
||||
Protocol encodeProtocol = ch.getEncodeProtocol();
|
||||
if ( !encodeProtocol.TO_SERVER.hasPacket( packet.getClass(), ch.getEncodeVersion() ) )
|
||||
{
|
||||
// we should limit this so bad api usage won't oom the server.
|
||||
Preconditions.checkState( packetQueue.size() <= 4096, "too many queued packets" );
|
||||
packetQueue.add( packet );
|
||||
} else
|
||||
{
|
||||
|
@ -25,7 +25,6 @@ import net.md_5.bungee.api.score.Objective;
|
||||
import net.md_5.bungee.api.score.Score;
|
||||
import net.md_5.bungee.api.score.Scoreboard;
|
||||
import net.md_5.bungee.api.score.Team;
|
||||
import net.md_5.bungee.chat.ComponentSerializer;
|
||||
import net.md_5.bungee.connection.CancelSendSignal;
|
||||
import net.md_5.bungee.connection.DownstreamBridge;
|
||||
import net.md_5.bungee.connection.LoginResult;
|
||||
@ -104,6 +103,7 @@ public class ServerConnector extends PacketHandler
|
||||
@Override
|
||||
public void connected(ChannelWrapper channel) throws Exception
|
||||
{
|
||||
channel.setVersion( user.getPendingConnection().getVersion() );
|
||||
this.ch = channel;
|
||||
|
||||
this.handshakeHandler = new ForgeServerHandler( user, ch, target );
|
||||
@ -117,7 +117,7 @@ public class ServerConnector extends PacketHandler
|
||||
LoginResult profile = user.getPendingConnection().getLoginProfile();
|
||||
if ( profile != null && profile.getProperties() != null && profile.getProperties().length > 0 )
|
||||
{
|
||||
newHost += "\00" + BungeeCord.getInstance().gson.toJson( profile.getProperties() );
|
||||
newHost += "\00" + LoginResult.GSON.toJson( profile.getProperties() );
|
||||
}
|
||||
copiedHandshake.setHost( newHost );
|
||||
} else if ( !user.getExtraDataInHandshake().isEmpty() )
|
||||
@ -301,7 +301,7 @@ public class ServerConnector extends PacketHandler
|
||||
{
|
||||
user.unsafe().sendPacket( new ScoreboardObjective(
|
||||
objective.getName(),
|
||||
( user.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_13 ) ? Either.right( ComponentSerializer.deserialize( objective.getValue() ) ) : Either.left( objective.getValue() ),
|
||||
( user.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_13 ) ? Either.right( user.getChatSerializer().deserialize( objective.getValue() ) ) : Either.left( objective.getValue() ),
|
||||
ScoreboardObjective.HealthDisplay.fromString( objective.getType() ),
|
||||
(byte) 1, null )
|
||||
);
|
||||
|
@ -3,10 +3,8 @@ package net.md_5.bungee;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.util.internal.PlatformDependent;
|
||||
import java.net.InetSocketAddress;
|
||||
@ -40,7 +38,7 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.PermissionCheckEvent;
|
||||
import net.md_5.bungee.api.event.ServerConnectEvent;
|
||||
import net.md_5.bungee.api.score.Scoreboard;
|
||||
import net.md_5.bungee.chat.ComponentSerializer;
|
||||
import net.md_5.bungee.chat.VersionedComponentSerializer;
|
||||
import net.md_5.bungee.connection.InitialHandler;
|
||||
import net.md_5.bungee.entitymap.EntityMap;
|
||||
import net.md_5.bungee.forge.ForgeClientHandler;
|
||||
@ -49,9 +47,8 @@ import net.md_5.bungee.forge.ForgeServerHandler;
|
||||
import net.md_5.bungee.netty.ChannelWrapper;
|
||||
import net.md_5.bungee.netty.HandlerBoss;
|
||||
import net.md_5.bungee.netty.PipelineUtils;
|
||||
import net.md_5.bungee.protocol.ChatSerializer;
|
||||
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;
|
||||
import net.md_5.bungee.protocol.Protocol;
|
||||
import net.md_5.bungee.protocol.ProtocolConstants;
|
||||
@ -137,6 +134,8 @@ public final class UserConnection implements ProxiedPlayer
|
||||
private String displayName;
|
||||
@Getter
|
||||
private EntityMap entityRewrite;
|
||||
@Getter
|
||||
private VersionedComponentSerializer chatSerializer;
|
||||
private Locale locale;
|
||||
/*========================================================================*/
|
||||
@Getter
|
||||
@ -154,11 +153,24 @@ public final class UserConnection implements ProxiedPlayer
|
||||
{
|
||||
ch.write( packet );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacketQueued(DefinedPacket packet)
|
||||
{
|
||||
if ( pendingConnection.getVersion() >= ProtocolConstants.MINECRAFT_1_20_2 )
|
||||
{
|
||||
UserConnection.this.sendPacketQueued( packet );
|
||||
} else
|
||||
{
|
||||
sendPacket( packet );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public boolean init()
|
||||
{
|
||||
this.entityRewrite = EntityMap.getEntityMap( getPendingConnection().getVersion() );
|
||||
this.chatSerializer = ChatSerializer.forVersion( getPendingConnection().getVersion() );
|
||||
|
||||
this.displayName = name;
|
||||
|
||||
@ -195,6 +207,8 @@ public final class UserConnection implements ProxiedPlayer
|
||||
Protocol encodeProtocol = ch.getEncodeProtocol();
|
||||
if ( !encodeProtocol.TO_CLIENT.hasPacket( packet.getClass(), getPendingConnection().getVersion() ) )
|
||||
{
|
||||
// we should limit this so bad api usage won't oom the server.
|
||||
Preconditions.checkState( packetQueue.size() <= 4096, "too many queued packets" );
|
||||
packetQueue.add( packet );
|
||||
} else
|
||||
{
|
||||
@ -362,17 +376,6 @@ public final class UserConnection implements ProxiedPlayer
|
||||
|
||||
pendingConnects.add( target );
|
||||
|
||||
ChannelInitializer initializer = new ChannelInitializer()
|
||||
{
|
||||
@Override
|
||||
protected void initChannel(Channel ch) throws Exception
|
||||
{
|
||||
PipelineUtils.BASE_SERVERSIDE.initChannel( ch );
|
||||
ch.pipeline().addAfter( PipelineUtils.FRAME_DECODER, PipelineUtils.PACKET_DECODER, new MinecraftDecoder( Protocol.HANDSHAKE, false, getPendingConnection().getVersion() ) );
|
||||
ch.pipeline().addAfter( PipelineUtils.FRAME_PREPENDER, PipelineUtils.PACKET_ENCODER, new MinecraftEncoder( Protocol.HANDSHAKE, false, getPendingConnection().getVersion() ) );
|
||||
ch.pipeline().get( HandlerBoss.class ).setHandler( new ServerConnector( bungee, UserConnection.this, target ) );
|
||||
}
|
||||
};
|
||||
ChannelFutureListener listener = new ChannelFutureListener()
|
||||
{
|
||||
@Override
|
||||
@ -401,13 +404,16 @@ public final class UserConnection implements ProxiedPlayer
|
||||
{
|
||||
sendMessage( bungee.getTranslation( "fallback_kick", connectionFailMessage( future.cause() ) ) );
|
||||
}
|
||||
} else
|
||||
{
|
||||
future.channel().pipeline().get( HandlerBoss.class ).setHandler( new ServerConnector( bungee, UserConnection.this, target ) );
|
||||
}
|
||||
}
|
||||
};
|
||||
Bootstrap b = new Bootstrap()
|
||||
.channel( PipelineUtils.getChannel( target.getAddress() ) )
|
||||
.group( ch.getHandle().eventLoop() )
|
||||
.handler( initializer )
|
||||
.handler( bungee.unsafe().getBackendChannelInitializer().getChannelInitializer() )
|
||||
.option( ChannelOption.CONNECT_TIMEOUT_MILLIS, request.getConnectTimeout() )
|
||||
.remoteAddress( target.getAddress() );
|
||||
// Windows is bugged, multi homed users will just have to live with random connecting IPs
|
||||
@ -554,7 +560,7 @@ public final class UserConnection implements ProxiedPlayer
|
||||
sendPacketQueued( new SystemChat( message, position.ordinal() ) );
|
||||
} else
|
||||
{
|
||||
sendPacketQueued( new Chat( ComponentSerializer.toString( message ), (byte) position.ordinal(), sender ) );
|
||||
sendPacketQueued( new Chat( chatSerializer.toString( message ), (byte) position.ordinal(), sender ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,57 +0,0 @@
|
||||
package net.md_5.bungee.compress;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToMessageEncoder;
|
||||
import java.util.List;
|
||||
import java.util.zip.Deflater;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.md_5.bungee.jni.zlib.BungeeZlib;
|
||||
import net.md_5.bungee.protocol.DefinedPacket;
|
||||
|
||||
public class PacketCompressor extends MessageToMessageEncoder<ByteBuf>
|
||||
{
|
||||
|
||||
@Getter
|
||||
private final BungeeZlib zlib = CompressFactory.zlib.newInstance();
|
||||
@Setter
|
||||
private int threshold = 256;
|
||||
@Setter
|
||||
private boolean compose = true;
|
||||
|
||||
@Override
|
||||
public void handlerAdded(ChannelHandlerContext ctx) throws Exception
|
||||
{
|
||||
zlib.init( true, Deflater.DEFAULT_COMPRESSION );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception
|
||||
{
|
||||
zlib.free();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception
|
||||
{
|
||||
int origSize = msg.readableBytes();
|
||||
if ( origSize < threshold )
|
||||
{
|
||||
if ( compose )
|
||||
{
|
||||
// create a virtual buffer to avoid copying of data
|
||||
out.add( ctx.alloc().compositeDirectBuffer( 2 ).addComponents( true, ctx.alloc().directBuffer( 1 ).writeByte( 0 ), msg.retain() ) );
|
||||
} else
|
||||
{
|
||||
out.add( ctx.alloc().directBuffer( origSize + 1 ).writeByte( 0 ).writeBytes( msg ) );
|
||||
}
|
||||
} else
|
||||
{
|
||||
ByteBuf buf = ctx.alloc().directBuffer( BungeeZlib.OUTPUT_BUFFER_SIZE );
|
||||
DefinedPacket.writeVarInt( origSize, buf );
|
||||
zlib.process( msg, buf );
|
||||
out.add( buf );
|
||||
}
|
||||
}
|
||||
}
|
@ -7,10 +7,12 @@ import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
import java.util.List;
|
||||
import net.md_5.bungee.jni.zlib.BungeeZlib;
|
||||
import net.md_5.bungee.protocol.DefinedPacket;
|
||||
import net.md_5.bungee.protocol.OverflowPacketException;
|
||||
|
||||
public class PacketDecompressor extends MessageToMessageDecoder<ByteBuf>
|
||||
{
|
||||
|
||||
private static final int MAX_DECOMPRESSED_LEN = 1 << 23;
|
||||
private final BungeeZlib zlib = CompressFactory.zlib.newInstance();
|
||||
|
||||
@Override
|
||||
@ -34,8 +36,14 @@ public class PacketDecompressor extends MessageToMessageDecoder<ByteBuf>
|
||||
out.add( in.retain() );
|
||||
} else
|
||||
{
|
||||
ByteBuf decompressed = ctx.alloc().directBuffer();
|
||||
if ( size > MAX_DECOMPRESSED_LEN )
|
||||
{
|
||||
throw new OverflowPacketException( "Packet may not be larger than " + MAX_DECOMPRESSED_LEN + " bytes" );
|
||||
}
|
||||
|
||||
// Do not use size as max capacity, as its possible that the entity rewriter increases the size afterwards
|
||||
// This would result in a kick (it happens rarely as the entity ids size must differ)
|
||||
ByteBuf decompressed = ctx.alloc().directBuffer( size, MAX_DECOMPRESSED_LEN );
|
||||
try
|
||||
{
|
||||
zlib.process( in, decompressed );
|
||||
|
@ -69,6 +69,8 @@ public class Configuration implements ProxyConfig
|
||||
private boolean preventProxyConnections;
|
||||
private boolean forgeSupport;
|
||||
private boolean rejectTransfers;
|
||||
private int maxPacketsPerSecond = 1 << 12;
|
||||
private int maxPacketDataPerSecond = 1 << 25;
|
||||
|
||||
public void load()
|
||||
{
|
||||
@ -105,6 +107,8 @@ public class Configuration implements ProxyConfig
|
||||
preventProxyConnections = adapter.getBoolean( "prevent_proxy_connections", preventProxyConnections );
|
||||
forgeSupport = adapter.getBoolean( "forge_support", forgeSupport );
|
||||
rejectTransfers = adapter.getBoolean( "reject_transfers", rejectTransfers );
|
||||
maxPacketsPerSecond = adapter.getInt( "max_packets_per_second", maxPacketsPerSecond );
|
||||
maxPacketDataPerSecond = adapter.getInt( "max_packets_data_per_second", maxPacketDataPerSecond );
|
||||
|
||||
disabledCommands = new CaseInsensitiveSet( (Collection<String>) adapter.getList( "disabled_commands", Arrays.asList( "disabledcommandhere" ) ) );
|
||||
|
||||
|
@ -189,7 +189,9 @@ public class YamlConfig implements ConfigurationAdapter
|
||||
@Override
|
||||
public int getInt(String path, int def)
|
||||
{
|
||||
return get( path, def );
|
||||
// #3791: Sometimes third-party tools rewrite large ints into doubles
|
||||
Number number = get( path, def );
|
||||
return number.intValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -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,9 +20,12 @@ 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.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.md_5.bungee.ServerConnection;
|
||||
@ -35,6 +39,7 @@ 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;
|
||||
@ -46,7 +51,6 @@ import net.md_5.bungee.api.score.Position;
|
||||
import net.md_5.bungee.api.score.Score;
|
||||
import net.md_5.bungee.api.score.Scoreboard;
|
||||
import net.md_5.bungee.api.score.Team;
|
||||
import net.md_5.bungee.chat.ComponentSerializer;
|
||||
import net.md_5.bungee.entitymap.EntityMap;
|
||||
import net.md_5.bungee.netty.ChannelWrapper;
|
||||
import net.md_5.bungee.netty.PacketHandler;
|
||||
@ -196,7 +200,7 @@ public class DownstreamBridge extends PacketHandler
|
||||
switch ( objective.getAction() )
|
||||
{
|
||||
case 0:
|
||||
serverScoreboard.addObjective( new Objective( objective.getName(), ( objective.getValue().isLeft() ) ? objective.getValue().getLeft() : ComponentSerializer.toString( objective.getValue().getRight() ), objective.getType().toString() ) );
|
||||
serverScoreboard.addObjective( new Objective( objective.getName(), ( objective.getValue().isLeft() ) ? objective.getValue().getLeft() : con.getChatSerializer().toString( objective.getValue().getRight() ), objective.getType().toString() ) );
|
||||
break;
|
||||
case 1:
|
||||
serverScoreboard.removeObjective( objective.getName() );
|
||||
@ -205,7 +209,7 @@ public class DownstreamBridge extends PacketHandler
|
||||
Objective oldObjective = serverScoreboard.getObjective( objective.getName() );
|
||||
if ( oldObjective != null )
|
||||
{
|
||||
oldObjective.setValue( ( objective.getValue().isLeft() ) ? objective.getValue().getLeft() : ComponentSerializer.toString( objective.getValue().getRight() ) );
|
||||
oldObjective.setValue( ( objective.getValue().isLeft() ) ? objective.getValue().getLeft() : con.getChatSerializer().toString( objective.getValue().getRight() ) );
|
||||
oldObjective.setType( objective.getType().toString() );
|
||||
}
|
||||
break;
|
||||
@ -279,13 +283,16 @@ public class DownstreamBridge extends PacketHandler
|
||||
{
|
||||
if ( team.getMode() == 0 || team.getMode() == 2 )
|
||||
{
|
||||
t.setDisplayName( team.getDisplayName().getLeftOrCompute( ComponentSerializer::toString ) );
|
||||
t.setPrefix( team.getPrefix().getLeftOrCompute( ComponentSerializer::toString ) );
|
||||
t.setSuffix( team.getSuffix().getLeftOrCompute( ComponentSerializer::toString ) );
|
||||
t.setDisplayName( team.getDisplayName().getLeftOrCompute( (component) -> con.getChatSerializer().toString( component ) ) );
|
||||
t.setPrefix( team.getPrefix().getLeftOrCompute( (component) -> con.getChatSerializer().toString( component ) ) );
|
||||
t.setSuffix( team.getSuffix().getLeftOrCompute( (component) -> con.getChatSerializer().toString( component ) ) );
|
||||
t.setFriendlyFire( team.getFriendlyFire() );
|
||||
t.setNameTagVisibility( team.getNameTagVisibility() );
|
||||
t.setCollisionRule( team.getCollisionRule() );
|
||||
t.setNameTagVisibility( team.getNameTagVisibility().getKey() );
|
||||
t.setColor( team.getColor() );
|
||||
if ( team.getCollisionRule() != null )
|
||||
{
|
||||
t.setCollisionRule( team.getCollisionRule().getKey() );
|
||||
}
|
||||
}
|
||||
if ( team.getPlayers() != null )
|
||||
{
|
||||
@ -324,7 +331,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
|
||||
@ -332,7 +339,7 @@ public class DownstreamBridge extends PacketHandler
|
||||
throw CancelSendSignal.INSTANCE;
|
||||
}
|
||||
|
||||
if ( pluginMessage.getTag().equals( "BungeeCord" ) )
|
||||
if ( pluginMessage.getTag().equals( PluginMessage.BUNGEE_CHANNEL_LEGACY ) )
|
||||
{
|
||||
ByteArrayDataOutput out = ByteStreams.newDataOutput();
|
||||
String subChannel = in.readUTF();
|
||||
@ -356,7 +363,7 @@ public class DownstreamBridge extends PacketHandler
|
||||
out.write( data );
|
||||
byte[] payload = out.toByteArray();
|
||||
|
||||
target.getServer().sendData( "BungeeCord", payload );
|
||||
target.getServer().sendData( PluginMessage.BUNGEE_CHANNEL_LEGACY, payload );
|
||||
}
|
||||
|
||||
// Null out stream, important as we don't want to send to ourselves
|
||||
@ -388,7 +395,7 @@ public class DownstreamBridge extends PacketHandler
|
||||
{
|
||||
if ( server != this.server.getInfo() )
|
||||
{
|
||||
server.sendData( "BungeeCord", payload );
|
||||
server.sendData( PluginMessage.BUNGEE_CHANNEL_LEGACY, payload );
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -397,7 +404,7 @@ public class DownstreamBridge extends PacketHandler
|
||||
{
|
||||
if ( server != this.server.getInfo() )
|
||||
{
|
||||
server.sendData( "BungeeCord", payload, false );
|
||||
server.sendData( PluginMessage.BUNGEE_CHANNEL_LEGACY, payload, false );
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -405,7 +412,7 @@ public class DownstreamBridge extends PacketHandler
|
||||
ServerInfo server = bungee.getServerInfo( target );
|
||||
if ( server != null )
|
||||
{
|
||||
server.sendData( "BungeeCord", payload );
|
||||
server.sendData( PluginMessage.BUNGEE_CHANNEL_LEGACY, payload );
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -553,7 +560,7 @@ public class DownstreamBridge extends PacketHandler
|
||||
case "MessageRaw":
|
||||
{
|
||||
String target = in.readUTF();
|
||||
BaseComponent[] message = ComponentSerializer.parse( in.readUTF() );
|
||||
BaseComponent[] message = con.getChatSerializer().parse( in.readUTF() );
|
||||
if ( target.equals( "ALL" ) )
|
||||
{
|
||||
for ( ProxiedPlayer player : bungee.getPlayers() )
|
||||
@ -620,7 +627,7 @@ public class DownstreamBridge extends PacketHandler
|
||||
ProxiedPlayer player = bungee.getPlayer( in.readUTF() );
|
||||
if ( player != null )
|
||||
{
|
||||
BaseComponent[] kickReason = ComponentSerializer.parse( in.readUTF() );
|
||||
BaseComponent[] kickReason = con.getChatSerializer().parse( in.readUTF() );
|
||||
player.disconnect( kickReason );
|
||||
}
|
||||
break;
|
||||
@ -633,7 +640,7 @@ public class DownstreamBridge extends PacketHandler
|
||||
byte[] b = out.toByteArray();
|
||||
if ( b.length != 0 )
|
||||
{
|
||||
server.sendData( "BungeeCord", b );
|
||||
server.sendData( PluginMessage.BUNGEE_CHANNEL_LEGACY, b );
|
||||
}
|
||||
}
|
||||
|
||||
@ -757,6 +764,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 ) )
|
||||
@ -773,11 +785,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
|
||||
{
|
||||
|
@ -2,6 +2,7 @@ package net.md_5.bungee.connection;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.gson.Gson;
|
||||
import io.netty.channel.EventLoop;
|
||||
import java.math.BigInteger;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
@ -121,6 +122,12 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
{
|
||||
ch.write( packet );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacketQueued(DefinedPacket packet)
|
||||
{
|
||||
throw new UnsupportedOperationException( "Not supported" );
|
||||
}
|
||||
};
|
||||
@Getter
|
||||
private boolean onlineMode = BungeeCord.getInstance().config.isOnlineMode();
|
||||
@ -143,6 +150,15 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
private boolean transferred;
|
||||
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
|
||||
{
|
||||
@ -187,12 +203,6 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(PluginMessage pluginMessage) throws Exception
|
||||
{
|
||||
this.relayMessage( pluginMessage );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(LegacyHandshake legacyHandshake) throws Exception
|
||||
{
|
||||
@ -228,11 +238,6 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
@Override
|
||||
public void done(ProxyPingEvent result, Throwable error)
|
||||
{
|
||||
if ( ch.isClosing() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ServerPing legacy = result.getResponse();
|
||||
String kickMessage;
|
||||
|
||||
@ -256,7 +261,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
}
|
||||
};
|
||||
|
||||
bungee.getPluginManager().callEvent( new ProxyPingEvent( InitialHandler.this, result, callback ) );
|
||||
bungee.getPluginManager().callEvent( new ProxyPingEvent( InitialHandler.this, result, eventLoopCallback( callback ) ) );
|
||||
}
|
||||
};
|
||||
|
||||
@ -309,7 +314,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
@Override
|
||||
public void done(ProxyPingEvent pingResult, Throwable error)
|
||||
{
|
||||
Gson gson = BungeeCord.getInstance().gson;
|
||||
Gson gson = PingHandler.gson;
|
||||
unsafe.sendPacket( new StatusResponse( gson.toJson( pingResult.getResponse() ) ) );
|
||||
if ( bungee.getConnectionThrottle() != null )
|
||||
{
|
||||
@ -318,7 +323,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
}
|
||||
};
|
||||
|
||||
bungee.getPluginManager().callEvent( new ProxyPingEvent( InitialHandler.this, result, callback ) );
|
||||
bungee.getPluginManager().callEvent( new ProxyPingEvent( InitialHandler.this, result, eventLoopCallback( callback ) ) );
|
||||
}
|
||||
};
|
||||
|
||||
@ -456,6 +461,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 )
|
||||
@ -464,14 +470,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>()
|
||||
{
|
||||
|
||||
@ -484,9 +482,15 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
disconnect( ( reason != null ) ? reason : TextComponent.fromLegacy( bungee.getTranslation( "kick_message" ) ) );
|
||||
return;
|
||||
}
|
||||
if ( ch.isClosing() )
|
||||
if ( !realName.equals( name ) )
|
||||
{
|
||||
return;
|
||||
// Floodgate changes the name attribute with reflexion
|
||||
setName( realName = name );
|
||||
}
|
||||
if ( uniqueId != null )
|
||||
{
|
||||
// if plugin called setUniqueId()
|
||||
realId = uniqueId;
|
||||
}
|
||||
if ( onlineMode )
|
||||
{
|
||||
@ -501,7 +505,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
};
|
||||
|
||||
// fire pre login event
|
||||
bungee.getPluginManager().callEvent( new PreLoginEvent( InitialHandler.this, callback ) );
|
||||
bungee.getPluginManager().callEvent( new PreLoginEvent( InitialHandler.this, eventLoopCallback( callback ) ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -514,7 +518,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
BungeeCipher decrypt = EncryptionUtil.getCipher( false, sharedKey );
|
||||
ch.addBefore( PipelineUtils.FRAME_DECODER, PipelineUtils.DECRYPT_HANDLER, new CipherDecoder( decrypt ) );
|
||||
BungeeCipher encrypt = EncryptionUtil.getCipher( true, sharedKey );
|
||||
ch.addBefore( PipelineUtils.FRAME_PREPENDER, PipelineUtils.ENCRYPT_HANDLER, new CipherEncoder( encrypt ) );
|
||||
ch.addBefore( PipelineUtils.FRAME_PREPENDER_AND_COMPRESS, PipelineUtils.ENCRYPT_HANDLER, new CipherEncoder( encrypt ) );
|
||||
// disable use of composite buffers if we use natives
|
||||
ch.updateComposite();
|
||||
|
||||
@ -540,12 +544,12 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
{
|
||||
if ( error == null )
|
||||
{
|
||||
LoginResult obj = BungeeCord.getInstance().gson.fromJson( result, LoginResult.class );
|
||||
LoginResult obj = LoginResult.GSON.fromJson( result, LoginResult.class );
|
||||
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;
|
||||
}
|
||||
@ -563,10 +567,25 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
|
||||
private void finish()
|
||||
{
|
||||
offlineId = UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + getName() ).getBytes( StandardCharsets.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;
|
||||
}
|
||||
}
|
||||
rewriteId = ( bungee.config.isIpForward() ) ? uniqueId : offlineId;
|
||||
|
||||
@ -621,18 +640,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
disconnect( ( reason != null ) ? reason : TextComponent.fromLegacy( bungee.getTranslation( "kick_message" ) ) );
|
||||
return;
|
||||
}
|
||||
if ( ch.isClosing() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ch.getHandle().eventLoop().execute( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if ( !ch.isClosing() )
|
||||
{
|
||||
userCon = new UserConnection( bungee, ch, getName(), InitialHandler.this );
|
||||
userCon.setCompressionThreshold( BungeeCord.getInstance().config.getCompressionThreshold() );
|
||||
|
||||
@ -643,13 +651,10 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
}
|
||||
finish2();
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
};
|
||||
|
||||
// fire login event
|
||||
bungee.getPluginManager().callEvent( new LoginEvent( InitialHandler.this, complete ) );
|
||||
bungee.getPluginManager().callEvent( new LoginEvent( InitialHandler.this, eventLoopCallback( complete ) ) );
|
||||
}
|
||||
|
||||
private void finish2()
|
||||
@ -680,18 +685,12 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
@Override
|
||||
public void done(PostLoginEvent result, Throwable error)
|
||||
{
|
||||
// #3612: Don't progress further if disconnected during event
|
||||
if ( ch.isClosing() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
userCon.connect( result.getTarget(), null, true, ServerConnectEvent.Reason.JOIN_PROXY );
|
||||
}
|
||||
};
|
||||
|
||||
// fire post-login event
|
||||
bungee.getPluginManager().callEvent( new PostLoginEvent( userCon, initialServer, complete ) );
|
||||
bungee.getPluginManager().callEvent( new PostLoginEvent( userCon, initialServer, eventLoopCallback( complete ) ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -704,6 +703,9 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
}
|
||||
Preconditions.checkState( future != null, "Unexpected custom LoginPayloadResponse" );
|
||||
future.complete( response.getData() );
|
||||
|
||||
// we should never pass this to the backend
|
||||
throw CancelSendSignal.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -781,6 +783,59 @@ 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;
|
||||
}
|
||||
|
||||
private void updateOfflineId()
|
||||
{
|
||||
offlineId = UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + getName() ).getBytes( StandardCharsets.UTF_8 ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVersion()
|
||||
{
|
||||
@ -917,4 +972,32 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
unsafe.sendPacket( new LoginPayloadRequest( id, channel, data ) );
|
||||
return future;
|
||||
}
|
||||
|
||||
// this method is used for event execution
|
||||
// if this connection is disconnected during an event-call, the original callback is not called
|
||||
// if the event was executed async, we execute the callback on the eventloop again
|
||||
// otherwise netty will schedule any pipeline related call by itself, this decreases performance
|
||||
private <T> Callback<T> eventLoopCallback(Callback<T> callback)
|
||||
{
|
||||
return (result, error) ->
|
||||
{
|
||||
EventLoop eventLoop = ch.getHandle().eventLoop();
|
||||
if ( eventLoop.inEventLoop() )
|
||||
{
|
||||
if ( !ch.isClosing() )
|
||||
{
|
||||
callback.done( result, error );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
eventLoop.execute( () ->
|
||||
{
|
||||
if ( !ch.isClosing() )
|
||||
{
|
||||
callback.done( result, error );
|
||||
}
|
||||
} );
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.md_5.bungee.connection;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import net.md_5.bungee.protocol.Property;
|
||||
@ -9,6 +10,8 @@ import net.md_5.bungee.protocol.Property;
|
||||
public class LoginResult
|
||||
{
|
||||
|
||||
public static final Gson GSON = new Gson();
|
||||
//
|
||||
private String id;
|
||||
private String name;
|
||||
private Property[] properties;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user