Compare commits

...

29 Commits

Author SHA1 Message Date
adaebb32f5 new event TabCompleteRequestEvent and deprecate TabCompleteEvent 2023-12-07 23:41:36 +01:00
525403b004 Add CommandsDeclareEvent to declare commands with brigadier API 2023-12-07 23:41:36 +01:00
4e5410fe30 Server branding now includes the backend server name 2023-12-07 23:41:36 +01:00
6707a3731f Multi-session with same Minecraft account with specific permission
Players with permission bungeecord.multiple_connect can have multiple connections with the same Minecraft account.
The UUID and player name is altered to avoid collision with other player:
UUID : xxxxxxxx-xxxx-VIxx-xxxx-xxxxxxxxxxxx
- The UUID version (V above) is now the provided version + 8 (for online player, it is 4, so it becomes C).
- The I digit will follow the index of the duplicated player : first duplicated player is 1, second one is 2.
- The name of the player will be the real player name, followed by the character "." (dot) followed by the duplication index.

Bedrock accounts connected using the Floodgate plugin will not be able to connect multiple times due to the risk of xUID collision.
2023-12-07 23:41:32 +01:00
f0a7644d5b Change projet configuration and POM for Pandacube 2023-12-07 23:16:32 +01:00
45b1d1e41c Remove modules and startup delay
We don’t need them for Pandacube
2023-12-07 23:16:27 +01:00
md_5
231024ba42
Relax chat parsing to treat bytes as booleans to allow formatting read from NBT 2023-12-06 21:55:56 +11:00
md_5
8ce7a7f8b6
Minecraft 1.20.3 support 2023-12-06 03:40:00 +11:00
md_5
e1462ccdd1
Minecraft 1.20.3-rc1 support 2023-12-04 19:02:45 +11:00
md_5
70f346c1dc
Fix extra write in ScoreboardScore packet 2023-11-26 08:12:30 +11:00
md_5
197bf13a28
Minecraft 1.20.3-pre2 support 2023-11-25 17:02:40 +11:00
md_5
0925c06f9b
#3563: Correct max string length for reading SystemChat packets 2023-11-13 20:09:48 +13:00
Parker Hawke
16298a75f2
#3558: Add Translatable interface for fluid creation of TranslatableComponents 2023-11-10 07:03:46 +11:00
md_5
39b10c0b16
Minecraft 23w45a support 2023-11-09 19:33:11 +11:00
dependabot[bot]
bd8d114992
#3561: Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.0 to 3.6.2
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.6.0 to 3.6.2.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.6.0...maven-javadoc-plugin-3.6.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-07 20:17:54 +11:00
dependabot[bot]
30e12c6fe0
#3560: Bump org.junit.jupiter:junit-jupiter from 5.10.0 to 5.10.1
Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.10.0 to 5.10.1.
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.10.0...r5.10.1)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-07 20:17:20 +11:00
md_5
bd009ca52d
#3559: Fix serialisation of certain scoreboard packets < 1.13 2023-11-06 20:14:57 +11:00
md_5
65d8edf62d
Minecraft 23w44a support 2023-11-06 20:14:55 +11:00
BoomEaro
f5157f12a4
#3438: Fix possible race condition in duplicate player check 2023-11-01 21:32:31 +11:00
BoomEaro
df20effacc
#3557: Replace Guava Charsets with Java StandardCharsets 2023-10-31 21:49:17 +11:00
md_5
c92581d0dc
#3556: Deserialize arrays to single components 2023-10-29 11:30:54 +11:00
Outfluencer
e442c3da5c
#3546: Add string length checks to isValidName 2023-10-28 13:11:55 +11:00
dependabot[bot]
f903c54d55
#3554: Bump org.apache.maven.plugins:maven-checkstyle-plugin
Bumps [org.apache.maven.plugins:maven-checkstyle-plugin](https://github.com/apache/maven-checkstyle-plugin) from 3.3.0 to 3.3.1.
- [Commits](https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.3.0...maven-checkstyle-plugin-3.3.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-28 13:06:40 +11:00
Parker Hawke
0d45378986
#3540: Add TextComponent#fromLegacy() as an array-free alternative to #fromLegacyText() 2023-10-28 13:04:18 +11:00
md_5
0f5f09b6c5
Minecraft 23w43b support 2023-10-28 12:57:19 +11:00
md_5
e5c80d0044
Fix code formatting 2023-10-28 12:57:16 +11:00
md_5
9cdb2ba3ea
Deprecate exposed scoreboard API 2023-10-22 09:25:25 +11:00
dependabot[bot]
d0e5cf7ce5
#3549: Bump io.netty:netty-bom from 4.1.99.Final to 4.1.100.Final
Bumps [io.netty:netty-bom](https://github.com/netty/netty) from 4.1.99.Final to 4.1.100.Final.
- [Commits](https://github.com/netty/netty/compare/netty-4.1.99.Final...netty-4.1.100.Final)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-21 09:16:02 +11:00
md_5
c8568764f6
Fix writing non-compound root NBT tags 2023-10-14 16:38:11 +11:00
117 changed files with 2148 additions and 1935 deletions

View File

@ -4,13 +4,12 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>net.md-5</groupId> <groupId>fr.pandacube.bungeecord</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.20-R0.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId> <artifactId>bungeecord-api</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.20-R0.2-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
@ -20,25 +19,25 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>fr.pandacube.bungeecord</groupId>
<artifactId>bungeecord-chat</artifactId> <artifactId>bungeecord-chat</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>fr.pandacube.bungeecord</groupId>
<artifactId>bungeecord-config</artifactId> <artifactId>bungeecord-config</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>fr.pandacube.bungeecord</groupId>
<artifactId>bungeecord-event</artifactId> <artifactId>bungeecord-event</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>fr.pandacube.bungeecord</groupId>
<artifactId>bungeecord-protocol</artifactId> <artifactId>bungeecord-protocol</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>

View File

@ -105,13 +105,13 @@ public class ServerPing
@Deprecated @Deprecated
public ServerPing(Protocol version, Players players, String description, String favicon) public ServerPing(Protocol version, Players players, String description, String favicon)
{ {
this( version, players, new TextComponent( TextComponent.fromLegacyText( description ) ), favicon == null ? null : Favicon.create( favicon ) ); this( version, players, TextComponent.fromLegacy( description ), favicon == null ? null : Favicon.create( favicon ) );
} }
@Deprecated @Deprecated
public ServerPing(Protocol version, Players players, String description, Favicon favicon) public ServerPing(Protocol version, Players players, String description, Favicon favicon)
{ {
this( version, players, new TextComponent( TextComponent.fromLegacyText( description ) ), favicon ); this( version, players, TextComponent.fromLegacy( description ), favicon );
} }
@Deprecated @Deprecated
@ -139,7 +139,7 @@ public class ServerPing
@Deprecated @Deprecated
public void setDescription(String description) public void setDescription(String description)
{ {
this.description = new TextComponent( TextComponent.fromLegacyText( description ) ); this.description = TextComponent.fromLegacy( description );
} }
@Deprecated @Deprecated

View File

@ -334,6 +334,9 @@ public interface ProxiedPlayer extends Connection, CommandSender
* Get the {@link Scoreboard} that belongs to this player. * Get the {@link Scoreboard} that belongs to this player.
* *
* @return this player's {@link Scoreboard} * @return this player's {@link Scoreboard}
* @deprecated for internal use only, setters will not have the expected
* effect, will not update client state, and may corrupt proxy state
*/ */
@Deprecated
Scoreboard getScoreboard(); Scoreboard getScoreboard();
} }

View File

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

View File

@ -1,9 +1,7 @@
package net.md_5.bungee.api.event; package net.md_5.bungee.api.event;
import lombok.AccessLevel;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.Setter;
import lombok.ToString; import lombok.ToString;
import net.md_5.bungee.api.Callback; import net.md_5.bungee.api.Callback;
import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.BaseComponent;
@ -27,8 +25,7 @@ public class LoginEvent extends AsyncEvent<LoginEvent> implements Cancellable
/** /**
* Message to use when kicking if this event is canceled. * Message to use when kicking if this event is canceled.
*/ */
@Setter(AccessLevel.NONE) private BaseComponent reason;
private BaseComponent[] cancelReasonComponents;
/** /**
* Connection attempting to login. * Connection attempting to login.
*/ */
@ -42,28 +39,44 @@ public class LoginEvent extends AsyncEvent<LoginEvent> implements Cancellable
/** /**
* @return reason to be displayed * @return reason to be displayed
* @deprecated Use component methods instead. * @deprecated use component methods instead
*/ */
@Deprecated @Deprecated
public String getCancelReason() public String getCancelReason()
{ {
return BaseComponent.toLegacyText( getCancelReasonComponents() ); return TextComponent.toLegacyText( getReason() );
} }
/** /**
* @param cancelReason reason to be displayed * @param cancelReason reason to be displayed
* @deprecated Use * @deprecated use component methods instead
* {@link #setCancelReason(net.md_5.bungee.api.chat.BaseComponent...)}
* instead.
*/ */
@Deprecated @Deprecated
public void setCancelReason(String cancelReason) public void setCancelReason(String cancelReason)
{ {
setCancelReason( TextComponent.fromLegacyText( cancelReason ) ); setReason( TextComponent.fromLegacy( cancelReason ) );
} }
/**
* @return reason to be displayed
* @deprecated use single component methods instead
*/
@Deprecated
public BaseComponent[] getCancelReasonComponents()
{
return new BaseComponent[]
{
getReason()
};
}
/**
* @param cancelReason reason to be displayed
* @deprecated use single component methods instead
*/
@Deprecated
public void setCancelReason(BaseComponent... cancelReason) public void setCancelReason(BaseComponent... cancelReason)
{ {
this.cancelReasonComponents = cancelReason; setReason( TextComponent.fromArray( cancelReason ) );
} }
} }

View File

@ -1,9 +1,7 @@
package net.md_5.bungee.api.event; package net.md_5.bungee.api.event;
import lombok.AccessLevel;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.Setter;
import lombok.ToString; import lombok.ToString;
import net.md_5.bungee.api.Callback; import net.md_5.bungee.api.Callback;
import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.BaseComponent;
@ -32,8 +30,7 @@ public class PreLoginEvent extends AsyncEvent<PreLoginEvent> implements Cancella
/** /**
* Message to use when kicking if this event is canceled. * Message to use when kicking if this event is canceled.
*/ */
@Setter(AccessLevel.NONE) private BaseComponent reason;
private BaseComponent[] cancelReasonComponents;
/** /**
* Connection attempting to login. * Connection attempting to login.
*/ */
@ -47,28 +44,44 @@ public class PreLoginEvent extends AsyncEvent<PreLoginEvent> implements Cancella
/** /**
* @return reason to be displayed * @return reason to be displayed
* @deprecated Use component methods instead. * @deprecated use component methods instead
*/ */
@Deprecated @Deprecated
public String getCancelReason() public String getCancelReason()
{ {
return BaseComponent.toLegacyText( getCancelReasonComponents() ); return BaseComponent.toLegacyText( getReason() );
} }
/** /**
* @param cancelReason reason to be displayed * @param cancelReason reason to be displayed
* @deprecated Use * @deprecated Use component methods instead
* {@link #setCancelReason(net.md_5.bungee.api.chat.BaseComponent...)}
* instead.
*/ */
@Deprecated @Deprecated
public void setCancelReason(String cancelReason) public void setCancelReason(String cancelReason)
{ {
setCancelReason( TextComponent.fromLegacyText( cancelReason ) ); setReason( TextComponent.fromLegacy( cancelReason ) );
} }
/**
* @return reason to be displayed
* @deprecated use single component methods instead
*/
@Deprecated
public BaseComponent[] getCancelReasonComponents()
{
return new BaseComponent[]
{
getReason()
};
}
/**
* @param cancelReason reason to be displayed
* @deprecated use single component methods instead
*/
@Deprecated
public void setCancelReason(BaseComponent... cancelReason) public void setCancelReason(BaseComponent... cancelReason)
{ {
this.cancelReasonComponents = cancelReason; setReason( TextComponent.fromArray( cancelReason ) );
} }
} }

View File

@ -35,7 +35,7 @@ public class ServerKickEvent extends Event implements Cancellable
/** /**
* Kick reason. * Kick reason.
*/ */
private BaseComponent[] kickReasonComponent; private BaseComponent reason;
/** /**
* Server to send player to if this event is cancelled. * Server to send player to if this event is cancelled.
*/ */
@ -63,24 +63,61 @@ public class ServerKickEvent extends Event implements Cancellable
this( player, player.getServer().getInfo(), kickReasonComponent, cancelServer, state ); this( player, player.getServer().getInfo(), kickReasonComponent, cancelServer, state );
} }
@Deprecated
public ServerKickEvent(ProxiedPlayer player, ServerInfo kickedFrom, BaseComponent[] kickReasonComponent, ServerInfo cancelServer, State state) public ServerKickEvent(ProxiedPlayer player, ServerInfo kickedFrom, BaseComponent[] kickReasonComponent, ServerInfo cancelServer, State state)
{
this( player, kickedFrom, TextComponent.fromArray( kickReasonComponent ), cancelServer, state );
}
public ServerKickEvent(ProxiedPlayer player, ServerInfo kickedFrom, BaseComponent reason, ServerInfo cancelServer, State state)
{ {
this.player = player; this.player = player;
this.kickedFrom = kickedFrom; this.kickedFrom = kickedFrom;
this.kickReasonComponent = kickReasonComponent; this.reason = reason;
this.cancelServer = cancelServer; this.cancelServer = cancelServer;
this.state = state; this.state = state;
} }
/**
* @return the kick reason
* @deprecated use component methods instead
*/
@Deprecated @Deprecated
public String getKickReason() public String getKickReason()
{ {
return BaseComponent.toLegacyText( kickReasonComponent ); return BaseComponent.toLegacyText( getReason() );
} }
/**
* @param reason the kick reason
* @deprecated use component methods instead
*/
@Deprecated @Deprecated
public void setKickReason(String reason) public void setKickReason(String reason)
{ {
kickReasonComponent = TextComponent.fromLegacyText( reason ); this.setReason( TextComponent.fromLegacy( reason ) );
}
/**
* @return the kick reason
* @deprecated use single component methods instead
*/
@Deprecated
public BaseComponent[] getKickReasonComponent()
{
return new BaseComponent[]
{
getReason()
};
}
/**
* @param kickReasonComponent the kick reason
* @deprecated use single component methods instead
*/
@Deprecated
public void setKickReasonComponent(BaseComponent[] kickReasonComponent)
{
this.setReason( TextComponent.fromArray( kickReasonComponent ) );
} }
} }

View File

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

View File

@ -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;
}
}

View File

@ -4,13 +4,12 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>net.md-5</groupId> <groupId>fr.pandacube.bungeecord</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.20-R0.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-bootstrap</artifactId> <artifactId>bungeecord-bootstrap</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.20-R0.2-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
@ -21,14 +20,12 @@
<properties> <properties>
<maven.deploy.skip>true</maven.deploy.skip> <maven.deploy.skip>true</maven.deploy.skip>
<maven.javadoc.skip>true</maven.javadoc.skip> <maven.javadoc.skip>true</maven.javadoc.skip>
<maven.compiler.source>1.6</maven.compiler.source>
<maven.compiler.target>1.6</maven.compiler.target>
<maven.build.timestamp.format>yyyyMMdd</maven.build.timestamp.format> <maven.build.timestamp.format>yyyyMMdd</maven.build.timestamp.format>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>fr.pandacube.bungeecord</groupId>
<artifactId>bungeecord-proxy</artifactId> <artifactId>bungeecord-proxy</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>

View File

@ -4,13 +4,12 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>net.md-5</groupId> <groupId>fr.pandacube.bungeecord</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.20-R0.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-chat</artifactId> <artifactId>bungeecord-chat</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.20-R0.2-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>

View File

@ -204,6 +204,33 @@ public final class ComponentBuilder
return this; return this;
} }
/**
* Appends the {@link TranslationProvider} object to the builder and makes
* the last element the current target for formatting. The components will
* have all the formatting from previous part.
*
* @param translatable the translatable object to append
* @return this ComponentBuilder for chaining
*/
public ComponentBuilder append(TranslationProvider translatable)
{
return append( translatable, FormatRetention.ALL );
}
/**
* Appends the {@link TranslationProvider} object to the builder and makes
* the last element the current target for formatting. You can specify the
* amount of formatting retained from previous part.
*
* @param translatable the translatable object to append
* @param retention the formatting to retain
* @return this ComponentBuilder for chaining
*/
public ComponentBuilder append(TranslationProvider translatable, FormatRetention retention)
{
return append( translatable.asTranslatableComponent(), retention );
}
/** /**
* Appends the text to the builder and makes it the current target for * Appends the text to the builder and makes it the current target for
* formatting. The text will have all the formatting from previous part. * formatting. The text will have all the formatting from previous part.
@ -455,8 +482,8 @@ public final class ComponentBuilder
} }
/** /**
* Returns the component built by this builder. If this builder is * Returns the component built by this builder. If this builder is empty, an
* empty, an empty text component will be returned. * empty text component will be returned.
* *
* @return the component * @return the component
*/ */
@ -478,8 +505,8 @@ public final class ComponentBuilder
* <p> * <p>
* <strong>NOTE:</strong> {@link #build()} is preferred as it will * <strong>NOTE:</strong> {@link #build()} is preferred as it will
* consolidate all components into a single BaseComponent with extra * consolidate all components into a single BaseComponent with extra
* contents as opposed to an array of components which is non-standard * contents as opposed to an array of components which is non-standard and
* and may result in unexpected behavior. * may result in unexpected behavior.
* *
* @return the created components * @return the created components
*/ */

View File

@ -2,6 +2,7 @@ package net.md_5.bungee.api.chat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.function.Consumer;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
@ -27,6 +28,41 @@ public final class TextComponent extends BaseComponent
* @param message the text to convert * @param message the text to convert
* @return the components needed to print the message to the client * @return the components needed to print the message to the client
*/ */
public static BaseComponent fromLegacy(String message)
{
return fromLegacy( message, ChatColor.WHITE );
}
/**
* Converts the old formatting system that used
* {@link net.md_5.bungee.api.ChatColor#COLOR_CHAR} into the new json based
* system.
*
* @param message the text to convert
* @param defaultColor color to use when no formatting is to be applied
* (i.e. after ChatColor.RESET).
* @return the components needed to print the message to the client
*/
public static BaseComponent fromLegacy(String message, ChatColor defaultColor)
{
ComponentBuilder componentBuilder = new ComponentBuilder();
populateComponentStructure( message, defaultColor, componentBuilder::append );
return componentBuilder.build();
}
/**
* Converts the old formatting system that used
* {@link net.md_5.bungee.api.ChatColor#COLOR_CHAR} into the new json based
* system.
*
* @param message the text to convert
* @return the components needed to print the message to the client
* @deprecated {@link #fromLegacy(String)} is preferred as it will
* consolidate all components into a single BaseComponent with extra
* contents as opposed to an array of components which is non-standard and
* may result in unexpected behavior.
*/
@Deprecated
public static BaseComponent[] fromLegacyText(String message) public static BaseComponent[] fromLegacyText(String message)
{ {
return fromLegacyText( message, ChatColor.WHITE ); return fromLegacyText( message, ChatColor.WHITE );
@ -41,10 +77,21 @@ public final class TextComponent extends BaseComponent
* @param defaultColor color to use when no formatting is to be applied * @param defaultColor color to use when no formatting is to be applied
* (i.e. after ChatColor.RESET). * (i.e. after ChatColor.RESET).
* @return the components needed to print the message to the client * @return the components needed to print the message to the client
* @deprecated {@link #fromLegacy(String, ChatColor)} is preferred as it
* will consolidate all components into a single BaseComponent with extra
* contents as opposed to an array of components which is non-standard and
* may result in unexpected behavior.
*/ */
@Deprecated
public static BaseComponent[] fromLegacyText(String message, ChatColor defaultColor) public static BaseComponent[] fromLegacyText(String message, ChatColor defaultColor)
{ {
ArrayList<BaseComponent> components = new ArrayList<>(); ArrayList<BaseComponent> components = new ArrayList<>();
populateComponentStructure( message, defaultColor, components::add );
return components.toArray( new BaseComponent[ 0 ] );
}
private static void populateComponentStructure(String message, ChatColor defaultColor, Consumer<BaseComponent> appender)
{
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
TextComponent component = new TextComponent(); TextComponent component = new TextComponent();
Matcher matcher = url.matcher( message ); Matcher matcher = url.matcher( message );
@ -94,7 +141,7 @@ public final class TextComponent extends BaseComponent
component = new TextComponent( old ); component = new TextComponent( old );
old.setText( builder.toString() ); old.setText( builder.toString() );
builder = new StringBuilder(); builder = new StringBuilder();
components.add( old ); appender.accept( old );
} }
if ( format == ChatColor.BOLD ) if ( format == ChatColor.BOLD )
{ {
@ -137,7 +184,7 @@ public final class TextComponent extends BaseComponent
component = new TextComponent( old ); component = new TextComponent( old );
old.setText( builder.toString() ); old.setText( builder.toString() );
builder = new StringBuilder(); builder = new StringBuilder();
components.add( old ); appender.accept( old );
} }
TextComponent old = component; TextComponent old = component;
@ -146,7 +193,7 @@ public final class TextComponent extends BaseComponent
component.setText( urlString ); component.setText( urlString );
component.setClickEvent( new ClickEvent( ClickEvent.Action.OPEN_URL, component.setClickEvent( new ClickEvent( ClickEvent.Action.OPEN_URL,
urlString.startsWith( "http" ) ? urlString : "http://" + urlString ) ); urlString.startsWith( "http" ) ? urlString : "http://" + urlString ) );
components.add( component ); appender.accept( component );
i += pos - i - 1; i += pos - i - 1;
component = old; component = old;
continue; continue;
@ -155,9 +202,29 @@ public final class TextComponent extends BaseComponent
} }
component.setText( builder.toString() ); component.setText( builder.toString() );
components.add( component ); appender.accept( component );
}
return components.toArray( new BaseComponent[ 0 ] ); /**
* Internal compatibility method to transform an array of components to a
* single component.
*
* @param components array
* @return single component
*/
public static BaseComponent fromArray(BaseComponent... components)
{
if ( components == null )
{
return null;
}
if ( components.length == 1 )
{
return components[0];
}
return new TextComponent( components );
} }
/** /**

View File

@ -86,6 +86,21 @@ public final class TranslatableComponent extends BaseComponent
} }
} }
/**
* Creates a translatable component with the passed substitutions
*
* @param translatable the translatable object
* @param with the {@link java.lang.String}s and
* {@link net.md_5.bungee.api.chat.BaseComponent}s to use into the
* translation
* @see #translate
* @see #setWith(java.util.List)
*/
public TranslatableComponent(TranslationProvider translatable, Object... with)
{
this( translatable.getTranslationKey(), with );
}
/** /**
* Creates a duplicate of this TranslatableComponent. * Creates a duplicate of this TranslatableComponent.
* *

View File

@ -0,0 +1,38 @@
package net.md_5.bungee.api.chat;
/**
* An object capable of being translated by the client in a
* {@link TranslatableComponent}.
*/
public interface TranslationProvider
{
/**
* Get the translation key.
*
* @return the translation key
*/
String getTranslationKey();
/**
* Get this translatable object as a {@link TranslatableComponent}.
*
* @return the translatable component
*/
default TranslatableComponent asTranslatableComponent()
{
return asTranslatableComponent( (Object[]) null );
}
/**
* Get this translatable object as a {@link TranslatableComponent}.
*
* @param with the {@link String Strings} and
* {@link BaseComponent BaseComponents} to use in the translation
* @return the translatable component
*/
default TranslatableComponent asTranslatableComponent(Object... with)
{
return new TranslatableComponent( this, with );
}
}

View File

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

View File

@ -5,6 +5,7 @@ import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParseException; import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializationContext;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -20,27 +21,51 @@ import net.md_5.bungee.api.chat.hover.content.Content;
public class BaseComponentSerializer public class BaseComponentSerializer
{ {
private static boolean getAsBoolean(JsonElement el)
{
if ( el.isJsonPrimitive() )
{
JsonPrimitive primitive = (JsonPrimitive) el;
if ( primitive.isBoolean() )
{
return primitive.getAsBoolean();
}
if ( primitive.isNumber() )
{
Number number = primitive.getAsNumber();
if ( number instanceof Byte )
{
return number.byteValue() != 0;
}
}
}
return false;
}
protected void deserialize(JsonObject object, BaseComponent component, JsonDeserializationContext context) protected void deserialize(JsonObject object, BaseComponent component, JsonDeserializationContext context)
{ {
if ( object.has( "bold" ) ) if ( object.has( "bold" ) )
{ {
component.setBold( object.get( "bold" ).getAsBoolean() ); component.setBold( getAsBoolean( object.get( "bold" ) ) );
} }
if ( object.has( "italic" ) ) if ( object.has( "italic" ) )
{ {
component.setItalic( object.get( "italic" ).getAsBoolean() ); component.setItalic( getAsBoolean( object.get( "italic" ) ) );
} }
if ( object.has( "underlined" ) ) if ( object.has( "underlined" ) )
{ {
component.setUnderlined( object.get( "underlined" ).getAsBoolean() ); component.setUnderlined( getAsBoolean( object.get( "underlined" ) ) );
} }
if ( object.has( "strikethrough" ) ) if ( object.has( "strikethrough" ) )
{ {
component.setStrikethrough( object.get( "strikethrough" ).getAsBoolean() ); component.setStrikethrough( getAsBoolean( object.get( "strikethrough" ) ) );
} }
if ( object.has( "obfuscated" ) ) if ( object.has( "obfuscated" ) )
{ {
component.setObfuscated( object.get( "obfuscated" ).getAsBoolean() ); component.setObfuscated( getAsBoolean( object.get( "obfuscated" ) ) );
} }
if ( object.has( "color" ) ) if ( object.has( "color" ) )
{ {

View File

@ -2,12 +2,14 @@ package net.md_5.bungee.chat;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer; import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParseException; import com.google.gson.JsonParseException;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Set; import java.util.Set;
import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.BaseComponent;
@ -44,16 +46,17 @@ public class ComponentSerializer implements JsonDeserializer<BaseComponent>
/** /**
* Parse a JSON-compliant String as an array of base components. The input * 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. * can be one of either an array of components, or a single component
* If the input is an array, each component will be parsed individually and * object. If the input is an array, each component will be parsed
* returned in the order that they were parsed. If the input is a single * individually and returned in the order that they were parsed. If the
* component object, a single-valued array with the component will be returned. * input is a single component object, a single-valued array with the
* component will be returned.
* <p> * <p>
* <strong>NOTE:</strong> {@link #deserialize(String)} is preferred as it will * <strong>NOTE:</strong> {@link #deserialize(String)} is preferred as it
* parse only one component as opposed to an array of components which is non- * will parse only one component as opposed to an array of components which
* standard behavior. This method is still appropriate for parsing multiple * is non- standard behavior. This method is still appropriate for parsing
* components at once, although such use case is rarely (if at all) exhibited * multiple components at once, although such use case is rarely (if at all)
* in vanilla Minecraft. * exhibited in vanilla Minecraft.
* *
* @param json the component json to parse * @param json the component json to parse
* @return an array of all parsed components * @return an array of all parsed components
@ -75,25 +78,51 @@ public class ComponentSerializer implements JsonDeserializer<BaseComponent>
} }
/** /**
* Deserialize a JSON-compliant String as a single component. The input is * Deserialize a JSON-compliant String as a single component.
* expected to be a JSON object that represents only one component.
* *
* @param json the component json to parse * @param json the component json to parse
* @return the deserialized component * @return the deserialized component
* @throws IllegalArgumentException if anything other than a JSON object is * @throws IllegalArgumentException if anything other than a valid JSON
* passed as input * component string is passed as input
*/ */
public static BaseComponent deserialize(String json) public static BaseComponent deserialize(String json)
{ {
JsonElement jsonElement = JsonParser.parseString( json ); JsonElement jsonElement = JsonParser.parseString( json );
if ( !jsonElement.isJsonObject() )
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 static BaseComponent deserialize(JsonElement jsonElement)
{ {
throw new IllegalArgumentException( "Malformatted JSON. Expected object, got array for input \"" + json + "\"." ); 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 gson.fromJson( jsonElement, BaseComponent.class );
} }
public static JsonElement toJson(BaseComponent component)
{
return gson.toJsonTree( component );
}
public static String toString(Object object) public static String toString(Object object)
{ {
return gson.toJson( object ); return gson.toJson( object );

View File

@ -18,11 +18,10 @@ public class TextComponentSerializer extends BaseComponentSerializer implements
{ {
TextComponent component = new TextComponent(); TextComponent component = new TextComponent();
JsonObject object = json.getAsJsonObject(); JsonObject object = json.getAsJsonObject();
if ( !object.has( "text" ) ) if ( object.has( "text" ) )
{ {
throw new JsonParseException( "Could not parse JSON: missing 'text' property" );
}
component.setText( object.get( "text" ).getAsString() ); component.setText( object.get( "text" ).getAsString() );
}
deserialize( object, component, context ); deserialize( object, component, context );
return component; return component;
} }

View File

@ -1,11 +1,11 @@
package net.md_5.bungee.chat; package net.md_5.bungee.chat;
import com.google.common.base.Charsets;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -102,7 +102,7 @@ public final class TranslationRegistry
public JsonProvider(String resourcePath) throws IOException public JsonProvider(String resourcePath) throws IOException
{ {
try ( InputStreamReader rd = new InputStreamReader( JsonProvider.class.getResourceAsStream( resourcePath ), Charsets.UTF_8 ) ) try ( InputStreamReader rd = new InputStreamReader( JsonProvider.class.getResourceAsStream( resourcePath ), StandardCharsets.UTF_8 ) )
{ {
JsonObject obj = new Gson().fromJson( rd, JsonObject.class ); JsonObject obj = new Gson().fromJson( rd, JsonObject.class );
for ( Map.Entry<String, JsonElement> entries : obj.entrySet() ) for ( Map.Entry<String, JsonElement> entries : obj.entrySet() )

View File

@ -8,7 +8,6 @@ import java.util.function.Function;
import java.util.function.ObjIntConsumer; import java.util.function.ObjIntConsumer;
import java.util.function.Supplier; import java.util.function.Supplier;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.hover.content.Item;
import net.md_5.bungee.api.chat.hover.content.Text; import net.md_5.bungee.api.chat.hover.content.Text;
import net.md_5.bungee.chat.ComponentSerializer; import net.md_5.bungee.chat.ComponentSerializer;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -72,6 +71,8 @@ public class ComponentsTest
assertEquals( hoverVal, ComponentSerializer.toString( (BaseComponent[]) contentText.getValue() ) ); assertEquals( hoverVal, ComponentSerializer.toString( (BaseComponent[]) contentText.getValue() ) );
testDissembleReassemble( components ); testDissembleReassemble( components );
////////// //////////
// TODO: now ambiguous since "text" to distinguish Text from Item is not required
/*
TextComponent component1 = new TextComponent( "HoverableText" ); TextComponent component1 = new TextComponent( "HoverableText" );
String nbt = "{display:{Name:{text:Hello},Lore:[{text:Line_1},{text:Line_2}]},ench:[{id:49,lvl:5}],Unbreakable:1}}"; String nbt = "{display:{Name:{text:Hello},Lore:[{text:Line_1},{text:Line_2}]},ench:[{id:49,lvl:5}],Unbreakable:1}}";
Item contentItem = new Item( "minecraft:wood", 1, ItemTag.ofNbt( nbt ) ); Item contentItem = new Item( "minecraft:wood", 1, ItemTag.ofNbt( nbt ) );
@ -84,6 +85,7 @@ public class ComponentsTest
assertEquals( contentItem.getCount(), parsedContentItem.getCount() ); assertEquals( contentItem.getCount(), parsedContentItem.getCount() );
assertEquals( contentItem.getId(), parsedContentItem.getId() ); assertEquals( contentItem.getId(), parsedContentItem.getId() );
assertEquals( nbt, parsedContentItem.getTag().getNbt() ); assertEquals( nbt, parsedContentItem.getTag().getNbt() );
*/
} }
@Test @Test
@ -561,8 +563,7 @@ public class ComponentsTest
this.testBuilder( this.testBuilder(
ComponentBuilder::create, ComponentBuilder::create,
BaseComponent::toPlainText, BaseComponent::toPlainText,
ChatColor.RED + "Hello " + ChatColor.BLUE + ChatColor.BOLD ChatColor.RED + "Hello " + ChatColor.BLUE + ChatColor.BOLD + "World" + ChatColor.YELLOW + ChatColor.BOLD + "!",
+ "World" + ChatColor.YELLOW + ChatColor.BOLD + "!",
BaseComponent::toLegacyText BaseComponent::toLegacyText
); );
} }
@ -574,8 +575,7 @@ public class ComponentsTest
ComponentBuilder::build, ComponentBuilder::build,
(component) -> BaseComponent.toPlainText( component ), (component) -> BaseComponent.toPlainText( component ),
// An extra format code is appended to the beginning because there is an empty TextComponent at the start of every component // An extra format code is appended to the beginning because there is an empty TextComponent at the start of every component
ChatColor.WHITE.toString() + ChatColor.RED + "Hello " + ChatColor.BLUE + ChatColor.BOLD ChatColor.WHITE.toString() + ChatColor.RED + "Hello " + ChatColor.BLUE + ChatColor.BOLD + "World" + ChatColor.YELLOW + ChatColor.BOLD + "!",
+ "World" + ChatColor.YELLOW + ChatColor.BOLD + "!",
(component) -> BaseComponent.toLegacyText( component ) (component) -> BaseComponent.toLegacyText( component )
); );
} }

View File

@ -4,13 +4,12 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>net.md-5</groupId> <groupId>fr.pandacube.bungeecord</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.20-R0.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-config</artifactId> <artifactId>bungeecord-config</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.20-R0.2-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>

View File

@ -1,6 +1,5 @@
package net.md_5.bungee.config; package net.md_5.bungee.config;
import com.google.common.base.Charsets;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
@ -16,6 +15,7 @@ import java.io.OutputStreamWriter;
import java.io.Reader; import java.io.Reader;
import java.io.Writer; import java.io.Writer;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import lombok.AccessLevel; import lombok.AccessLevel;
@ -37,7 +37,7 @@ public class JsonConfiguration extends ConfigurationProvider
@Override @Override
public void save(Configuration config, File file) throws IOException public void save(Configuration config, File file) throws IOException
{ {
try ( Writer writer = new OutputStreamWriter( new FileOutputStream( file ), Charsets.UTF_8 ) ) try ( Writer writer = new OutputStreamWriter( new FileOutputStream( file ), StandardCharsets.UTF_8 ) )
{ {
save( config, writer ); save( config, writer );
} }
@ -91,7 +91,7 @@ public class JsonConfiguration extends ConfigurationProvider
@Override @Override
public Configuration load(InputStream is, Configuration defaults) public Configuration load(InputStream is, Configuration defaults)
{ {
return load( new InputStreamReader( is, Charsets.UTF_8 ), defaults ); return load( new InputStreamReader( is, StandardCharsets.UTF_8 ), defaults );
} }
@Override @Override

View File

@ -1,6 +1,5 @@
package net.md_5.bungee.config; package net.md_5.bungee.config;
import com.google.common.base.Charsets;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -9,6 +8,7 @@ import java.io.InputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.io.Reader; import java.io.Reader;
import java.io.Writer; import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import lombok.AccessLevel; import lombok.AccessLevel;
@ -54,7 +54,7 @@ public class YamlConfiguration extends ConfigurationProvider
@Override @Override
public void save(Configuration config, File file) throws IOException public void save(Configuration config, File file) throws IOException
{ {
try ( Writer writer = new OutputStreamWriter( new FileOutputStream( file ), Charsets.UTF_8 ) ) try ( Writer writer = new OutputStreamWriter( new FileOutputStream( file ), StandardCharsets.UTF_8 ) )
{ {
save( config, writer ); save( config, writer );
} }

View File

@ -4,13 +4,12 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>net.md-5</groupId> <groupId>fr.pandacube.bungeecord</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.20-R0.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-event</artifactId> <artifactId>bungeecord-event</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.20-R0.2-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>

View File

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

View File

@ -1,8 +1,8 @@
package net.md_5.bungee.log; package net.md_5.bungee.log;
import com.google.common.base.Charsets;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -19,7 +19,7 @@ public class LoggingOutputStream extends ByteArrayOutputStream
@Override @Override
public void flush() throws IOException public void flush() throws IOException
{ {
String contents = toString( Charsets.UTF_8.name() ); String contents = toString( StandardCharsets.UTF_8.name() );
super.reset(); super.reset();
if ( !contents.isEmpty() && !contents.equals( separator ) ) if ( !contents.isEmpty() && !contents.equals( separator ) )
{ {

View File

@ -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>

View File

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

View File

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

View File

@ -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() ) );
}
}
}
}
}

View File

@ -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() );
}
}

View File

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

View File

@ -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>

View File

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

View File

@ -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();
}
}

View File

@ -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() );
}
}

View File

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

View File

@ -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>

View File

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

View File

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

View File

@ -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() );
}
}

View File

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

View File

@ -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>

View File

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

View File

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

View File

@ -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() );
}
}

View File

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

View File

@ -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>

View File

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

View File

@ -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;
}
}

View File

@ -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() );
}
}

View File

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

View File

@ -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>

View File

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

View File

@ -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();
}
} );
}
}

View File

@ -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() );
}
}

View File

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

View File

@ -1,55 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module</artifactId>
<version>1.20-R0.2-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>

View File

@ -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>

View File

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

View File

@ -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;
}
}
}
}

View File

@ -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()
{
}
}

View File

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

View File

@ -4,13 +4,12 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>net.md-5</groupId> <groupId>fr.pandacube.bungeecord</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.20-R0.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-native</artifactId> <artifactId>bungeecord-native</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.20-R0.2-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>

13
pom.xml
View File

@ -3,7 +3,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>net.md-5</groupId> <groupId>fr.pandacube.bungeecord</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.20-R0.2-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
@ -37,7 +37,6 @@
<module>config</module> <module>config</module>
<module>event</module> <module>event</module>
<module>log</module> <module>log</module>
<module>module</module>
<module>protocol</module> <module>protocol</module>
<module>proxy</module> <module>proxy</module>
<module>query</module> <module>query</module>
@ -83,7 +82,7 @@
<dependency> <dependency>
<groupId>io.netty</groupId> <groupId>io.netty</groupId>
<artifactId>netty-bom</artifactId> <artifactId>netty-bom</artifactId>
<version>4.1.99.Final</version> <version>4.1.100.Final</version>
<type>pom</type> <type>pom</type>
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>
@ -93,7 +92,7 @@
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId> <artifactId>junit-jupiter</artifactId>
<version>5.10.0</version> <version>5.10.1</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
@ -122,7 +121,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.0</version> <version>3.6.2</version>
</plugin> </plugin>
</plugins> </plugins>
</pluginManagement> </pluginManagement>
@ -132,7 +131,7 @@
<artifactId>scriptus</artifactId> <artifactId>scriptus</artifactId>
<version>0.5.0</version> <version>0.5.0</version>
<configuration> <configuration>
<format>git:${project.name}:${project.version}:%s:${build.number}</format> <format>git:${project.name}-Pandacube:${project.version}:%s:${build.number}</format>
</configuration> </configuration>
<executions> <executions>
<execution> <execution>
@ -151,7 +150,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId> <artifactId>maven-checkstyle-plugin</artifactId>
<version>3.3.0</version> <version>3.3.1</version>
<executions> <executions>
<execution> <execution>
<phase>process-classes</phase> <phase>process-classes</phase>

View File

@ -4,13 +4,12 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>net.md-5</groupId> <groupId>fr.pandacube.bungeecord</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.20-R0.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-protocol</artifactId> <artifactId>bungeecord-protocol</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.20-R0.2-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
@ -18,30 +17,24 @@
<name>BungeeCord-Protocol</name> <name>BungeeCord-Protocol</name>
<description>Minimal implementation of the Minecraft protocol for use in BungeeCord</description> <description>Minimal implementation of the Minecraft protocol for use in BungeeCord</description>
<!-- We really shouldn't depend on external repositories, but at least this is the Central staging one --> <!-- We really shouldn't depend on external repositories -->
<repositories> <repositories>
<repository> <repository>
<id>sonatype-nexus-snapshots</id> <id>minecraft-libraries</id>
<name>Sonatype Nexus Snapshots</name> <name>Minecraft Libraries</name>
<url>https://oss.sonatype.org/content/repositories/snapshots</url> <url>https://libraries.minecraft.net/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository> </repository>
</repositories> </repositories>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>com.mojang</groupId>
<artifactId>brigadier</artifactId> <artifactId>brigadier</artifactId>
<version>1.0.16-SNAPSHOT</version> <version>1.2.9</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>fr.pandacube.bungeecord</groupId>
<artifactId>bungeecord-chat</artifactId> <artifactId>bungeecord-chat</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>

View File

@ -34,6 +34,7 @@ import net.md_5.bungee.protocol.packet.Respawn;
import net.md_5.bungee.protocol.packet.ScoreboardDisplay; import net.md_5.bungee.protocol.packet.ScoreboardDisplay;
import net.md_5.bungee.protocol.packet.ScoreboardObjective; import net.md_5.bungee.protocol.packet.ScoreboardObjective;
import net.md_5.bungee.protocol.packet.ScoreboardScore; import net.md_5.bungee.protocol.packet.ScoreboardScore;
import net.md_5.bungee.protocol.packet.ScoreboardScoreReset;
import net.md_5.bungee.protocol.packet.ServerData; import net.md_5.bungee.protocol.packet.ServerData;
import net.md_5.bungee.protocol.packet.SetCompression; import net.md_5.bungee.protocol.packet.SetCompression;
import net.md_5.bungee.protocol.packet.StartConfiguration; import net.md_5.bungee.protocol.packet.StartConfiguration;
@ -143,6 +144,10 @@ public abstract class AbstractPacketHandler
{ {
} }
public void handle(ScoreboardScoreReset scoreboardScoreReset) throws Exception
{
}
public void handle(EncryptionRequest encryptionRequest) throws Exception public void handle(EncryptionRequest encryptionRequest) throws Exception
{ {
} }

View File

@ -1,20 +1,25 @@
package net.md_5.bungee.protocol; package net.md_5.bungee.protocol;
import com.google.common.base.Charsets; import com.google.common.base.Function;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.gson.JsonElement;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream; import io.netty.buffer.ByteBufInputStream;
import io.netty.buffer.ByteBufOutputStream; import io.netty.buffer.ByteBufOutputStream;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.BitSet; import java.util.BitSet;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.function.BiConsumer;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.chat.ComponentSerializer;
import se.llbit.nbt.ErrorTag; import se.llbit.nbt.ErrorTag;
import se.llbit.nbt.NamedTag; import se.llbit.nbt.NamedTag;
import se.llbit.nbt.SpecificTag; import se.llbit.nbt.SpecificTag;
@ -24,6 +29,23 @@ import se.llbit.nbt.Tag;
public abstract class DefinedPacket public abstract class DefinedPacket
{ {
public <T> T readNullable(Function<ByteBuf, T> reader, ByteBuf buf)
{
return buf.readBoolean() ? reader.apply( buf ) : null;
}
public <T> void writeNullable(T t0, BiConsumer<T, ByteBuf> writer, ByteBuf buf)
{
if ( t0 != null )
{
buf.writeBoolean( true );
writer.accept( t0, buf );
} else
{
buf.writeBoolean( false );
}
}
public static void writeString(String s, ByteBuf buf) public static void writeString(String s, ByteBuf buf)
{ {
writeString( s, buf, Short.MAX_VALUE ); writeString( s, buf, Short.MAX_VALUE );
@ -36,7 +58,7 @@ public abstract class DefinedPacket
throw new OverflowPacketException( "Cannot send string longer than " + maxLength + " (got " + s.length() + " characters)" ); throw new OverflowPacketException( "Cannot send string longer than " + maxLength + " (got " + s.length() + " characters)" );
} }
byte[] b = s.getBytes( Charsets.UTF_8 ); byte[] b = s.getBytes( StandardCharsets.UTF_8 );
if ( b.length > maxLength * 3 ) if ( b.length > maxLength * 3 )
{ {
throw new OverflowPacketException( "Cannot send string longer than " + ( maxLength * 3 ) + " (got " + b.length + " bytes)" ); throw new OverflowPacketException( "Cannot send string longer than " + ( maxLength * 3 ) + " (got " + b.length + " bytes)" );
@ -59,7 +81,7 @@ public abstract class DefinedPacket
throw new OverflowPacketException( "Cannot receive string longer than " + maxLen * 3 + " (got " + len + " bytes)" ); throw new OverflowPacketException( "Cannot receive string longer than " + maxLen * 3 + " (got " + len + " bytes)" );
} }
String s = buf.toString( buf.readerIndex(), len, Charsets.UTF_8 ); String s = buf.toString( buf.readerIndex(), len, StandardCharsets.UTF_8 );
buf.readerIndex( buf.readerIndex() + len ); buf.readerIndex( buf.readerIndex() + len );
if ( s.length() > maxLen ) if ( s.length() > maxLen )
@ -70,6 +92,59 @@ public abstract class DefinedPacket
return s; return s;
} }
public static Either<String, BaseComponent> readEitherBaseComponent(ByteBuf buf, int protocolVersion, boolean string)
{
return ( string ) ? Either.left( readString( buf ) ) : Either.right( readBaseComponent( buf, protocolVersion ) );
}
public static BaseComponent readBaseComponent(ByteBuf buf, int protocolVersion)
{
return readBaseComponent( buf, Short.MAX_VALUE, protocolVersion );
}
public static BaseComponent readBaseComponent(ByteBuf buf, int maxStringLength, int protocolVersion)
{
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_3 )
{
SpecificTag nbt = (SpecificTag) readTag( buf, protocolVersion );
JsonElement json = TagUtil.toJson( nbt );
return ComponentSerializer.deserialize( json );
} else
{
String string = readString( buf, maxStringLength );
return ComponentSerializer.deserialize( string );
}
}
public static void writeEitherBaseComponent(Either<String, BaseComponent> message, ByteBuf buf, int protocolVersion)
{
if ( message.isLeft() )
{
writeString( message.getLeft(), buf );
} else
{
writeBaseComponent( message.getRight(), buf, protocolVersion );
}
}
public static void writeBaseComponent(BaseComponent message, ByteBuf buf, int protocolVersion)
{
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_3 )
{
JsonElement json = ComponentSerializer.toJson( message );
SpecificTag nbt = TagUtil.fromJson( json );
writeTag( nbt, buf, protocolVersion );
} else
{
String string = ComponentSerializer.toString( message );
writeString( string, buf );
}
}
public static void writeArray(byte[] b, ByteBuf buf) public static void writeArray(byte[] b, ByteBuf buf)
{ {
if ( b.length > Short.MAX_VALUE ) if ( b.length > Short.MAX_VALUE )
@ -295,6 +370,38 @@ public abstract class DefinedPacket
return null; return null;
} }
public static void writeNumberFormat(NumberFormat format, ByteBuf buf, int protocolVersion)
{
writeVarInt( format.getType().ordinal(), buf );
switch ( format.getType() )
{
case BLANK:
break;
case STYLED:
writeBaseComponent( (BaseComponent) format.getValue(), buf, protocolVersion ); // TODO: style
break;
case FIXED:
writeBaseComponent( (BaseComponent) format.getValue(), buf, protocolVersion );
break;
}
}
public static NumberFormat readNumberFormat(ByteBuf buf, int protocolVersion)
{
int format = readVarInt( buf );
switch ( format )
{
case 0:
return new NumberFormat( NumberFormat.Type.BLANK, null );
case 1:
return new NumberFormat( NumberFormat.Type.STYLED, readBaseComponent( buf, protocolVersion ) ); // TODO: style
case 2:
return new NumberFormat( NumberFormat.Type.FIXED, readBaseComponent( buf, protocolVersion ) );
default:
throw new IllegalArgumentException( "Unknown number format " + format );
}
}
public static Tag readTag(ByteBuf input, int protocolVersion) public static Tag readTag(ByteBuf input, int protocolVersion)
{ {
DataInputStream in = new DataInputStream( new ByteBufInputStream( input ) ); DataInputStream in = new DataInputStream( new ByteBufInputStream( input ) );
@ -325,9 +432,18 @@ public abstract class DefinedPacket
public static void writeTag(Tag tag, ByteBuf output, int protocolVersion) public static void writeTag(Tag tag, ByteBuf output, int protocolVersion)
{ {
DataOutputStream out = new DataOutputStream( new ByteBufOutputStream( output ) );
try try
{ {
tag.write( new DataOutputStream( new ByteBufOutputStream( output ) ) ); if ( tag instanceof SpecificTag )
{
SpecificTag specificTag = (SpecificTag) tag;
specificTag.writeType( out );
specificTag.write( out );
} else
{
tag.write( out );
}
} catch ( IOException ex ) } catch ( IOException ex )
{ {
throw new RuntimeException( "Exception writing tag", ex ); throw new RuntimeException( "Exception writing tag", ex );
@ -386,6 +502,11 @@ public abstract class DefinedPacket
throw new UnsupportedOperationException( "Packet must implement read method" ); throw new UnsupportedOperationException( "Packet must implement read method" );
} }
public void read(ByteBuf buf, Protocol protocol, ProtocolConstants.Direction direction, int protocolVersion)
{
read( buf, direction, protocolVersion );
}
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{ {
read( buf ); read( buf );
@ -396,6 +517,11 @@ public abstract class DefinedPacket
throw new UnsupportedOperationException( "Packet must implement write method" ); throw new UnsupportedOperationException( "Packet must implement write method" );
} }
public void write(ByteBuf buf, Protocol protocol, ProtocolConstants.Direction direction, int protocolVersion)
{
write( buf, direction, protocolVersion );
}
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{ {
write( buf ); write( buf );

View File

@ -0,0 +1,34 @@
package net.md_5.bungee.protocol;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public final class Either<L, R>
{
private final L left;
private final R right;
public boolean isLeft()
{
return this.left != null;
}
public boolean isRight()
{
return this.right != null;
}
public static <L, R> Either<L, R> left(L left)
{
return new Either<>( left, null );
}
public static <L, R> Either<L, R> right(R right)
{
return new Either<>( null, right );
}
}

View File

@ -39,7 +39,7 @@ public class MinecraftDecoder extends MessageToMessageDecoder<ByteBuf>
DefinedPacket packet = prot.createPacket( packetId, protocolVersion ); DefinedPacket packet = prot.createPacket( packetId, protocolVersion );
if ( packet != null ) if ( packet != null )
{ {
packet.read( in, prot.getDirection(), protocolVersion ); packet.read( in, protocol, prot.getDirection(), protocolVersion );
if ( in.isReadable() ) if ( in.isReadable() )
{ {

View File

@ -24,6 +24,6 @@ public class MinecraftEncoder extends MessageToByteEncoder<DefinedPacket>
{ {
Protocol.DirectionData prot = ( server ) ? protocol.TO_CLIENT : protocol.TO_SERVER; Protocol.DirectionData prot = ( server ) ? protocol.TO_CLIENT : protocol.TO_SERVER;
DefinedPacket.writeVarInt( prot.getId( msg.getClass(), protocolVersion ), out ); DefinedPacket.writeVarInt( prot.getId( msg.getClass(), protocolVersion ), out );
msg.write( out, prot.getDirection(), protocolVersion ); msg.write( out, protocol, prot.getDirection(), protocolVersion );
} }
} }

View File

@ -0,0 +1,18 @@
package net.md_5.bungee.protocol;
import lombok.Data;
@Data
public class NumberFormat
{
private final Type type;
private final Object value;
public enum Type
{
BLANK,
STYLED,
FIXED;
}
}

View File

@ -40,6 +40,7 @@ import net.md_5.bungee.protocol.packet.Respawn;
import net.md_5.bungee.protocol.packet.ScoreboardDisplay; import net.md_5.bungee.protocol.packet.ScoreboardDisplay;
import net.md_5.bungee.protocol.packet.ScoreboardObjective; import net.md_5.bungee.protocol.packet.ScoreboardObjective;
import net.md_5.bungee.protocol.packet.ScoreboardScore; import net.md_5.bungee.protocol.packet.ScoreboardScore;
import net.md_5.bungee.protocol.packet.ScoreboardScoreReset;
import net.md_5.bungee.protocol.packet.ServerData; import net.md_5.bungee.protocol.packet.ServerData;
import net.md_5.bungee.protocol.packet.SetCompression; import net.md_5.bungee.protocol.packet.SetCompression;
import net.md_5.bungee.protocol.packet.StartConfiguration; import net.md_5.bungee.protocol.packet.StartConfiguration;
@ -134,7 +135,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_1, 0x3E ), map( ProtocolConstants.MINECRAFT_1_19_1, 0x3E ),
map( ProtocolConstants.MINECRAFT_1_19_3, 0x3D ), map( ProtocolConstants.MINECRAFT_1_19_3, 0x3D ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x41 ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x41 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x43 ) map( ProtocolConstants.MINECRAFT_1_20_2, 0x43 ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x45 )
); );
TO_CLIENT.registerPacket( TO_CLIENT.registerPacket(
BossBar.class, BossBar.class,
@ -192,7 +194,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_1, 0x56 ), map( ProtocolConstants.MINECRAFT_1_19_1, 0x56 ),
map( ProtocolConstants.MINECRAFT_1_19_3, 0x54 ), map( ProtocolConstants.MINECRAFT_1_19_3, 0x54 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x58 ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x58 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x5A ) map( ProtocolConstants.MINECRAFT_1_20_2, 0x5A ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x5C )
); );
TO_CLIENT.registerPacket( TO_CLIENT.registerPacket(
ScoreboardScore.class, ScoreboardScore.class,
@ -208,7 +211,13 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_1, 0x59 ), map( ProtocolConstants.MINECRAFT_1_19_1, 0x59 ),
map( ProtocolConstants.MINECRAFT_1_19_3, 0x57 ), map( ProtocolConstants.MINECRAFT_1_19_3, 0x57 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x5B ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x5B ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x5D ) map( ProtocolConstants.MINECRAFT_1_20_2, 0x5D ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x5F )
);
TO_CLIENT.registerPacket(
ScoreboardScoreReset.class,
ScoreboardScoreReset::new,
map( ProtocolConstants.MINECRAFT_1_20_3, 0x42 )
); );
TO_CLIENT.registerPacket( TO_CLIENT.registerPacket(
ScoreboardDisplay.class, ScoreboardDisplay.class,
@ -224,7 +233,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_1, 0x4F ), map( ProtocolConstants.MINECRAFT_1_19_1, 0x4F ),
map( ProtocolConstants.MINECRAFT_1_19_3, 0x4D ), map( ProtocolConstants.MINECRAFT_1_19_3, 0x4D ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x51 ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x51 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x53 ) map( ProtocolConstants.MINECRAFT_1_20_2, 0x53 ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x55 )
); );
TO_CLIENT.registerPacket( TO_CLIENT.registerPacket(
Team.class, Team.class,
@ -240,7 +250,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_1, 0x58 ), map( ProtocolConstants.MINECRAFT_1_19_1, 0x58 ),
map( ProtocolConstants.MINECRAFT_1_19_3, 0x56 ), map( ProtocolConstants.MINECRAFT_1_19_3, 0x56 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x5A ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x5A ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x5C ) map( ProtocolConstants.MINECRAFT_1_20_2, 0x5C ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x5E )
); );
TO_CLIENT.registerPacket( TO_CLIENT.registerPacket(
PluginMessage.class, PluginMessage.class,
@ -291,7 +302,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_1, 0x5D ), map( ProtocolConstants.MINECRAFT_1_19_1, 0x5D ),
map( ProtocolConstants.MINECRAFT_1_19_3, 0x5B ), map( ProtocolConstants.MINECRAFT_1_19_3, 0x5B ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x5F ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x5F ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x61 ) map( ProtocolConstants.MINECRAFT_1_20_2, 0x61 ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x63 )
); );
TO_CLIENT.registerPacket( TO_CLIENT.registerPacket(
ClearTitles.class, ClearTitles.class,
@ -310,7 +322,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_1, 0x5B ), map( ProtocolConstants.MINECRAFT_1_19_1, 0x5B ),
map( ProtocolConstants.MINECRAFT_1_19_3, 0x59 ), map( ProtocolConstants.MINECRAFT_1_19_3, 0x59 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x5D ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x5D ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x5F ) map( ProtocolConstants.MINECRAFT_1_20_2, 0x5F ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x61 )
); );
TO_CLIENT.registerPacket( TO_CLIENT.registerPacket(
TitleTimes.class, TitleTimes.class,
@ -320,7 +333,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_1, 0x5E ), map( ProtocolConstants.MINECRAFT_1_19_1, 0x5E ),
map( ProtocolConstants.MINECRAFT_1_19_3, 0x5C ), map( ProtocolConstants.MINECRAFT_1_19_3, 0x5C ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x60 ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x60 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x62 ) map( ProtocolConstants.MINECRAFT_1_20_2, 0x62 ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x64 )
); );
TO_CLIENT.registerPacket( TO_CLIENT.registerPacket(
SystemChat.class, SystemChat.class,
@ -329,7 +343,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_1, 0x62 ), map( ProtocolConstants.MINECRAFT_1_19_1, 0x62 ),
map( ProtocolConstants.MINECRAFT_1_19_3, 0x60 ), map( ProtocolConstants.MINECRAFT_1_19_3, 0x60 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x64 ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x64 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x67 ) map( ProtocolConstants.MINECRAFT_1_20_2, 0x67 ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x69 )
); );
TO_CLIENT.registerPacket( TO_CLIENT.registerPacket(
PlayerListHeaderFooter.class, PlayerListHeaderFooter.class,
@ -349,7 +364,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_1, 0x63 ), map( ProtocolConstants.MINECRAFT_1_19_1, 0x63 ),
map( ProtocolConstants.MINECRAFT_1_19_3, 0x61 ), map( ProtocolConstants.MINECRAFT_1_19_3, 0x61 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x65 ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x65 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x68 ) map( ProtocolConstants.MINECRAFT_1_20_2, 0x68 ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x6A )
); );
TO_CLIENT.registerPacket( TO_CLIENT.registerPacket(
EntityStatus.class, EntityStatus.class,
@ -405,7 +421,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_1, 0x4C ), map( ProtocolConstants.MINECRAFT_1_19_1, 0x4C ),
map( ProtocolConstants.MINECRAFT_1_19_3, 0x4B ), map( ProtocolConstants.MINECRAFT_1_19_3, 0x4B ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x4F ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x4F ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x51 ) map( ProtocolConstants.MINECRAFT_1_20_2, 0x51 ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x53 )
); );
TO_CLIENT.registerPacket( TO_CLIENT.registerPacket(
ServerData.class, ServerData.class,
@ -414,7 +431,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_1, 0x42 ), map( ProtocolConstants.MINECRAFT_1_19_1, 0x42 ),
map( ProtocolConstants.MINECRAFT_1_19_3, 0x41 ), map( ProtocolConstants.MINECRAFT_1_19_3, 0x41 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x45 ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x45 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x47 ) map( ProtocolConstants.MINECRAFT_1_20_2, 0x47 ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x49 )
); );
TO_CLIENT.registerPacket( TO_CLIENT.registerPacket(
PlayerListItemRemove.class, PlayerListItemRemove.class,
@ -433,7 +451,8 @@ public enum Protocol
TO_CLIENT.registerPacket( TO_CLIENT.registerPacket(
StartConfiguration.class, StartConfiguration.class,
StartConfiguration::new, StartConfiguration::new,
map( ProtocolConstants.MINECRAFT_1_20_2, 0x65 ) map( ProtocolConstants.MINECRAFT_1_20_2, 0x65 ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x67 )
); );
TO_SERVER.registerPacket( TO_SERVER.registerPacket(
@ -451,7 +470,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_1, 0x12 ), map( ProtocolConstants.MINECRAFT_1_19_1, 0x12 ),
map( ProtocolConstants.MINECRAFT_1_19_3, 0x11 ), map( ProtocolConstants.MINECRAFT_1_19_3, 0x11 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x12 ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x12 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x14 ) map( ProtocolConstants.MINECRAFT_1_20_2, 0x14 ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x15 )
); );
TO_SERVER.registerPacket( Chat.class, TO_SERVER.registerPacket( Chat.class,
Chat::new, Chat::new,
@ -517,7 +537,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_1, 0x0D ), map( ProtocolConstants.MINECRAFT_1_19_1, 0x0D ),
map( ProtocolConstants.MINECRAFT_1_19_3, 0x0C ), map( ProtocolConstants.MINECRAFT_1_19_3, 0x0C ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x0D ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x0D ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x0F ) map( ProtocolConstants.MINECRAFT_1_20_2, 0x0F ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x10 )
); );
TO_SERVER.registerPacket( TO_SERVER.registerPacket(
StartConfiguration.class, StartConfiguration.class,

View File

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

View File

@ -0,0 +1,218 @@
package net.md_5.bungee.protocol;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import se.llbit.nbt.ByteArrayTag;
import se.llbit.nbt.ByteTag;
import se.llbit.nbt.CompoundTag;
import se.llbit.nbt.DoubleTag;
import se.llbit.nbt.FloatTag;
import se.llbit.nbt.IntArrayTag;
import se.llbit.nbt.IntTag;
import se.llbit.nbt.ListTag;
import se.llbit.nbt.LongArrayTag;
import se.llbit.nbt.LongTag;
import se.llbit.nbt.NamedTag;
import se.llbit.nbt.ShortTag;
import se.llbit.nbt.SpecificTag;
import se.llbit.nbt.StringTag;
import se.llbit.nbt.Tag;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class TagUtil
{
public static SpecificTag fromJson(JsonElement json)
{
if ( json instanceof JsonPrimitive )
{
JsonPrimitive jsonPrimitive = (JsonPrimitive) json;
if ( jsonPrimitive.isNumber() )
{
Number number = json.getAsNumber();
if ( number instanceof Byte )
{
return new ByteTag( (Byte) number );
} else if ( number instanceof Short )
{
return new ShortTag( (Short) number );
} else if ( number instanceof Integer )
{
return new IntTag( (Integer) number );
} else if ( number instanceof Long )
{
return new LongTag( (Long) number );
} else if ( number instanceof Float )
{
return new FloatTag( (Float) number );
} else if ( number instanceof Double )
{
return new DoubleTag( (Double) number );
}
} else if ( jsonPrimitive.isString() )
{
return new StringTag( jsonPrimitive.getAsString() );
} else if ( jsonPrimitive.isBoolean() )
{
return new ByteTag( jsonPrimitive.getAsBoolean() ? 1 : 0 );
} else
{
throw new IllegalArgumentException( "Unknown JSON primitive: " + jsonPrimitive );
}
} else if ( json instanceof JsonObject )
{
CompoundTag compoundTag = new CompoundTag();
for ( Map.Entry<String, JsonElement> property : ( (JsonObject) json ).entrySet() )
{
compoundTag.add( property.getKey(), fromJson( property.getValue() ) );
}
return compoundTag;
} else if ( json instanceof JsonArray )
{
List<JsonElement> jsonArray = ( (JsonArray) json ).asList();
if ( jsonArray.isEmpty() )
{
return new ListTag( Tag.TAG_END, Collections.emptyList() );
}
SpecificTag listTag;
int listType = fromJson( jsonArray.get( 0 ) ).tagType();
switch ( listType )
{
case Tag.TAG_BYTE:
byte[] bytes = new byte[ jsonArray.size() ];
for ( int i = 0; i < bytes.length; i++ )
{
bytes[i] = (Byte) ( (JsonPrimitive) jsonArray.get( i ) ).getAsNumber();
}
listTag = new ByteArrayTag( bytes );
break;
case Tag.TAG_INT:
int[] ints = new int[ jsonArray.size() ];
for ( int i = 0; i < ints.length; i++ )
{
ints[i] = (Integer) ( (JsonPrimitive) jsonArray.get( i ) ).getAsNumber();
}
listTag = new IntArrayTag( ints );
break;
case Tag.TAG_LONG:
long[] longs = new long[ jsonArray.size() ];
for ( int i = 0; i < longs.length; i++ )
{
longs[i] = (Long) ( (JsonPrimitive) jsonArray.get( i ) ).getAsNumber();
}
listTag = new LongArrayTag( longs );
break;
default:
List<SpecificTag> tagItems = new ArrayList<>( jsonArray.size() );
for ( JsonElement jsonEl : jsonArray )
{
SpecificTag subTag = fromJson( jsonEl );
if ( subTag.tagType() != listType )
{
throw new IllegalArgumentException( "Cannot convert mixed JsonArray to Tag" );
}
tagItems.add( subTag );
}
listTag = new ListTag( listType, tagItems );
break;
}
return listTag;
} else if ( json instanceof JsonNull )
{
return Tag.END;
}
throw new IllegalArgumentException( "Unknown JSON element: " + json );
}
public static JsonElement toJson(SpecificTag tag)
{
switch ( tag.tagType() )
{
case Tag.TAG_BYTE:
return new JsonPrimitive( (byte) ( (ByteTag) tag ).getData() );
case Tag.TAG_SHORT:
return new JsonPrimitive( ( (ShortTag) tag ).getData() );
case Tag.TAG_INT:
return new JsonPrimitive( ( (IntTag) tag ).getData() );
case Tag.TAG_LONG:
return new JsonPrimitive( ( (LongTag) tag ).getData() );
case Tag.TAG_FLOAT:
return new JsonPrimitive( ( (FloatTag) tag ).getData() );
case Tag.TAG_DOUBLE:
return new JsonPrimitive( ( (DoubleTag) tag ).getData() );
case Tag.TAG_BYTE_ARRAY:
byte[] byteArray = ( (ByteArrayTag) tag ).getData();
JsonArray jsonByteArray = new JsonArray( byteArray.length );
for ( byte b : byteArray )
{
jsonByteArray.add( new JsonPrimitive( b ) );
}
return jsonByteArray;
case Tag.TAG_STRING:
return new JsonPrimitive( ( (StringTag) tag ).getData() );
case Tag.TAG_LIST:
List<SpecificTag> items = ( (ListTag) tag ).items;
JsonArray jsonList = new JsonArray( items.size() );
for ( SpecificTag subTag : items )
{
jsonList.add( toJson( subTag ) );
}
return jsonList;
case Tag.TAG_COMPOUND:
JsonObject jsonObject = new JsonObject();
for ( NamedTag subTag : (CompoundTag) tag )
{
jsonObject.add( subTag.name(), toJson( subTag.getTag() ) );
}
return jsonObject;
case Tag.TAG_INT_ARRAY:
int[] intArray = ( (IntArrayTag) tag ).getData();
JsonArray jsonIntArray = new JsonArray( intArray.length );
for ( int i : intArray )
{
jsonIntArray.add( new JsonPrimitive( i ) );
}
return jsonIntArray;
case Tag.TAG_LONG_ARRAY:
long[] longArray = ( (LongArrayTag) tag ).getData();
JsonArray jsonLongArray = new JsonArray( longArray.length );
for ( long l : longArray )
{
jsonLongArray.add( new JsonPrimitive( l ) );
}
return jsonLongArray;
default:
throw new IllegalArgumentException( "Unknown NBT tag: " + tag );
}
}
}

View File

@ -7,7 +7,8 @@ import io.netty.handler.codec.MessageToMessageEncoder;
import java.util.List; import java.util.List;
/** /**
* Prepend length of the message as a Varint21 using an extra buffer for the length, avoiding copying packet data * Prepend length of the message as a Varint21 using an extra buffer for the
* length, avoiding copying packet data
*/ */
@ChannelHandler.Sharable @ChannelHandler.Sharable
public class Varint21LengthFieldExtraBufPrepender extends MessageToMessageEncoder<ByteBuf> public class Varint21LengthFieldExtraBufPrepender extends MessageToMessageEncoder<ByteBuf>

View File

@ -6,7 +6,8 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder; import io.netty.handler.codec.MessageToByteEncoder;
/** /**
* Prepend length of the message as a Varint21 by writing length and data to a new buffer * Prepend length of the message as a Varint21 by writing length and data to a
* new buffer
*/ */
@ChannelHandler.Sharable @ChannelHandler.Sharable
public class Varint21LengthFieldPrepender extends MessageToByteEncoder<ByteBuf> public class Varint21LengthFieldPrepender extends MessageToByteEncoder<ByteBuf>

View File

@ -5,6 +5,7 @@ import java.util.UUID;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.protocol.AbstractPacketHandler; import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.ProtocolConstants; import net.md_5.bungee.protocol.ProtocolConstants;
@ -17,7 +18,7 @@ public class BossBar extends DefinedPacket
private UUID uuid; private UUID uuid;
private int action; private int action;
private String title; private BaseComponent title;
private float health; private float health;
private int color; private int color;
private int division; private int division;
@ -39,7 +40,7 @@ public class BossBar extends DefinedPacket
{ {
// Add // Add
case 0: case 0:
title = readString( buf ); title = readBaseComponent( buf, protocolVersion );
health = buf.readFloat(); health = buf.readFloat();
color = readVarInt( buf ); color = readVarInt( buf );
division = readVarInt( buf ); division = readVarInt( buf );
@ -51,7 +52,7 @@ public class BossBar extends DefinedPacket
break; break;
// Title // Title
case 3: case 3:
title = readString( buf ); title = readBaseComponent( buf, protocolVersion );
break; break;
// Style // Style
case 4: case 4:
@ -75,7 +76,7 @@ public class BossBar extends DefinedPacket
{ {
// Add // Add
case 0: case 0:
writeString( title, buf ); writeBaseComponent( title, buf, protocolVersion );
buf.writeFloat( health ); buf.writeFloat( health );
writeVarInt( color, buf ); writeVarInt( color, buf );
writeVarInt( division, buf ); writeVarInt( division, buf );
@ -87,7 +88,7 @@ public class BossBar extends DefinedPacket
break; break;
// Title // Title
case 3: case 3:
writeString( title, buf ); writeBaseComponent( title, buf, protocolVersion );
break; break;
// Style // Style
case 4: case 4:

View File

@ -4,6 +4,7 @@ import com.google.common.base.Preconditions;
import com.mojang.brigadier.Command; import com.mojang.brigadier.Command;
import com.mojang.brigadier.StringReader; import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.arguments.BoolArgumentType;
import com.mojang.brigadier.arguments.DoubleArgumentType; import com.mojang.brigadier.arguments.DoubleArgumentType;
import com.mojang.brigadier.arguments.FloatArgumentType; import com.mojang.brigadier.arguments.FloatArgumentType;
import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.arguments.IntegerArgumentType;
@ -303,13 +304,14 @@ public class Commands extends DefinedPacket
} }
@Data @Data
private static class ArgumentRegistry public static class ArgumentRegistry
{ {
private static final Map<String, ArgumentSerializer> PROVIDERS = new HashMap<>(); private static final Map<String, ArgumentSerializer> PROVIDERS = new HashMap<>();
private static final ArgumentSerializer[] IDS_1_19; private static final ArgumentSerializer[] IDS_1_19;
private static final ArgumentSerializer[] IDS_1_19_3; private static final ArgumentSerializer[] IDS_1_19_3;
private static final ArgumentSerializer[] IDS_1_19_4; private static final ArgumentSerializer[] IDS_1_19_4;
private static final ArgumentSerializer[] IDS_1_20_3;
private static final Map<Class<?>, ProperArgumentSerializer<?>> PROPER_PROVIDERS = new HashMap<>(); private static final Map<Class<?>, ProperArgumentSerializer<?>> PROPER_PROVIDERS = new HashMap<>();
// //
private static final ArgumentSerializer<Void> VOID = new ArgumentSerializer<Void>() private static final ArgumentSerializer<Void> VOID = new ArgumentSerializer<Void>()
@ -325,18 +327,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 @Override
protected Boolean read(ByteBuf buf) protected BoolArgumentType read(ByteBuf buf)
{ {
return buf.readBoolean(); return BoolArgumentType.bool();
} }
@Override @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>() private static final ArgumentSerializer<Byte> BYTE = new ArgumentSerializer<Byte>()
@ -353,7 +366,7 @@ public class Commands extends DefinedPacket
buf.writeByte( t ); buf.writeByte( t );
} }
}; };
private static final ArgumentSerializer<FloatArgumentType> FLOAT_RANGE = new ArgumentSerializer<FloatArgumentType>() private static final ProperArgumentSerializer<FloatArgumentType> FLOAT_RANGE = new ProperArgumentSerializer<FloatArgumentType>()
{ {
@Override @Override
protected FloatArgumentType read(ByteBuf buf) protected FloatArgumentType read(ByteBuf buf)
@ -381,8 +394,20 @@ public class Commands extends DefinedPacket
buf.writeFloat( t.getMaximum() ); 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 @Override
protected DoubleArgumentType read(ByteBuf buf) protected DoubleArgumentType read(ByteBuf buf)
@ -410,8 +435,20 @@ public class Commands extends DefinedPacket
buf.writeDouble( t.getMaximum() ); 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 @Override
protected IntegerArgumentType read(ByteBuf buf) protected IntegerArgumentType read(ByteBuf buf)
@ -439,6 +476,18 @@ public class Commands extends DefinedPacket
buf.writeInt( t.getMaximum() ); 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>() private static final ArgumentSerializer<Integer> INTEGER = new ArgumentSerializer<Integer>()
{ {
@ -454,7 +503,7 @@ public class Commands extends DefinedPacket
buf.writeInt( t ); buf.writeInt( t );
} }
}; };
private static final ArgumentSerializer<LongArgumentType> LONG_RANGE = new ArgumentSerializer<LongArgumentType>() private static final ProperArgumentSerializer<LongArgumentType> LONG_RANGE = new ProperArgumentSerializer<LongArgumentType>()
{ {
@Override @Override
protected LongArgumentType read(ByteBuf buf) protected LongArgumentType read(ByteBuf buf)
@ -482,6 +531,18 @@ public class Commands extends DefinedPacket
buf.writeLong( t.getMaximum() ); 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>() private static final ProperArgumentSerializer<StringArgumentType> STRING = new ProperArgumentSerializer<StringArgumentType>()
{ {
@ -537,11 +598,20 @@ public class Commands extends DefinedPacket
static static
{ {
register( "brigadier:bool", VOID ); register( "brigadier:bool", BOOLEAN );
PROPER_PROVIDERS.put( BoolArgumentType.class, BOOLEAN );
register( "brigadier:float", FLOAT_RANGE ); register( "brigadier:float", FLOAT_RANGE );
PROPER_PROVIDERS.put( FloatArgumentType.class, FLOAT_RANGE );
register( "brigadier:double", DOUBLE_RANGE ); register( "brigadier:double", DOUBLE_RANGE );
PROPER_PROVIDERS.put( DoubleArgumentType.class, DOUBLE_RANGE );
register( "brigadier:integer", INTEGER_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 ); register( "brigadier:string", STRING );
PROPER_PROVIDERS.put( StringArgumentType.class, STRING ); PROPER_PROVIDERS.put( StringArgumentType.class, STRING );
@ -744,6 +814,60 @@ public class Commands extends DefinedPacket
get( "minecraft:uuid", VOID ), get( "minecraft:uuid", VOID ),
get( "minecraft:heightmap", VOID ) get( "minecraft:heightmap", VOID )
}; };
IDS_1_20_3 = 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: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:template_mirror", VOID ),
get( "minecraft:template_rotation", VOID ),
get( "minecraft:uuid", VOID ),
get( "minecraft:heightmap", VOID )
};
} }
private static void register(String name, ArgumentSerializer serializer) private static void register(String name, ArgumentSerializer serializer)
@ -756,6 +880,404 @@ public class Commands extends DefinedPacket
return serializer; 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) private static ArgumentType<?> read(ByteBuf buf, int protocolVersion)
{ {
Object key; Object key;
@ -765,7 +1287,10 @@ public class Commands extends DefinedPacket
{ {
key = readVarInt( buf ); key = readVarInt( buf );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_4 ) if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_3 )
{
reader = IDS_1_20_3[(Integer) key];
} else if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_4 )
{ {
reader = IDS_1_19_4[(Integer) key]; reader = IDS_1_19_4[(Integer) key];
} else if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_3 ) } else if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_3 )
@ -879,11 +1404,15 @@ public class Commands extends DefinedPacket
private static String getKey(SuggestionProvider<DummyProvider> provider) 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) provider ).key;
} }
return ( (DummyProvider) ASK_SERVER ).key;
}
@Data @Data
private static final class DummyProvider implements SuggestionProvider<DummyProvider> private static final class DummyProvider implements SuggestionProvider<DummyProvider>
{ {

View File

@ -5,8 +5,12 @@ import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor; 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.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.Protocol;
import net.md_5.bungee.protocol.ProtocolConstants;
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@ -15,18 +19,30 @@ import net.md_5.bungee.protocol.DefinedPacket;
public class Kick extends DefinedPacket public class Kick extends DefinedPacket
{ {
private String message; private BaseComponent message;
@Override @Override
public void read(ByteBuf buf) public void read(ByteBuf buf, Protocol protocol, ProtocolConstants.Direction direction, int protocolVersion)
{ {
message = readString( buf ); if ( protocol == Protocol.LOGIN )
{
message = ComponentSerializer.deserialize( readString( buf ) );
} else
{
message = readBaseComponent( buf, protocolVersion );
}
} }
@Override @Override
public void write(ByteBuf buf) public void write(ByteBuf buf, Protocol protocol, ProtocolConstants.Direction direction, int protocolVersion)
{ {
writeString( message, buf ); if ( protocol == Protocol.LOGIN )
{
writeString( ComponentSerializer.toString( message ), buf );
} else
{
writeBaseComponent( message, buf, protocolVersion );
}
} }
@Override @Override

View File

@ -5,6 +5,7 @@ import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.protocol.AbstractPacketHandler; import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.ProtocolConstants; import net.md_5.bungee.protocol.ProtocolConstants;
@ -16,21 +17,21 @@ import net.md_5.bungee.protocol.ProtocolConstants;
public class PlayerListHeaderFooter extends DefinedPacket public class PlayerListHeaderFooter extends DefinedPacket
{ {
private String header; private BaseComponent header;
private String footer; private BaseComponent footer;
@Override @Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{ {
header = readString( buf ); header = readBaseComponent( buf, protocolVersion );
footer = readString( buf ); footer = readBaseComponent( buf, protocolVersion );
} }
@Override @Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{ {
writeString( header, buf ); writeBaseComponent( header, buf, protocolVersion );
writeString( footer, buf ); writeBaseComponent( footer, buf, protocolVersion );
} }
@Override @Override

View File

@ -5,6 +5,7 @@ import java.util.UUID;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.protocol.AbstractPacketHandler; import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.PlayerPublicKey; import net.md_5.bungee.protocol.PlayerPublicKey;
@ -38,7 +39,7 @@ public class PlayerListItem extends DefinedPacket
item.ping = DefinedPacket.readVarInt( buf ); item.ping = DefinedPacket.readVarInt( buf );
if ( buf.readBoolean() ) if ( buf.readBoolean() )
{ {
item.displayName = DefinedPacket.readString( buf ); item.displayName = DefinedPacket.readBaseComponent( buf, protocolVersion );
} }
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 ) if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 )
{ {
@ -54,7 +55,7 @@ public class PlayerListItem extends DefinedPacket
case UPDATE_DISPLAY_NAME: case UPDATE_DISPLAY_NAME:
if ( buf.readBoolean() ) if ( buf.readBoolean() )
{ {
item.displayName = DefinedPacket.readString( buf ); item.displayName = DefinedPacket.readBaseComponent( buf, protocolVersion );
} }
} }
} }
@ -78,7 +79,7 @@ public class PlayerListItem extends DefinedPacket
buf.writeBoolean( item.displayName != null ); buf.writeBoolean( item.displayName != null );
if ( item.displayName != null ) if ( item.displayName != null )
{ {
DefinedPacket.writeString( item.displayName, buf ); DefinedPacket.writeBaseComponent( item.displayName, buf, protocolVersion );
} }
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 ) if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 )
{ {
@ -95,7 +96,7 @@ public class PlayerListItem extends DefinedPacket
buf.writeBoolean( item.displayName != null ); buf.writeBoolean( item.displayName != null );
if ( item.displayName != null ) if ( item.displayName != null )
{ {
DefinedPacket.writeString( item.displayName, buf ); DefinedPacket.writeBaseComponent( item.displayName, buf, protocolVersion );
} }
break; break;
} }
@ -142,7 +143,7 @@ public class PlayerListItem extends DefinedPacket
Integer ping; Integer ping;
// ADD_PLAYER & UPDATE_DISPLAY_NAME // ADD_PLAYER & UPDATE_DISPLAY_NAME
String displayName; BaseComponent displayName;
} }
} }

View File

@ -58,7 +58,7 @@ public class PlayerListItemUpdate extends DefinedPacket
case UPDATE_DISPLAY_NAME: case UPDATE_DISPLAY_NAME:
if ( buf.readBoolean() ) if ( buf.readBoolean() )
{ {
item.displayName = DefinedPacket.readString( buf ); item.displayName = DefinedPacket.readBaseComponent( buf, protocolVersion );
} }
break; break;
} }
@ -106,7 +106,7 @@ public class PlayerListItemUpdate extends DefinedPacket
buf.writeBoolean( item.displayName != null ); buf.writeBoolean( item.displayName != null );
if ( item.displayName != null ) if ( item.displayName != null )
{ {
DefinedPacket.writeString( item.displayName, buf ); DefinedPacket.writeBaseComponent( item.displayName, buf, protocolVersion );
} }
break; break;
} }

View File

@ -6,8 +6,11 @@ import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.protocol.AbstractPacketHandler; import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.Either;
import net.md_5.bungee.protocol.NumberFormat;
import net.md_5.bungee.protocol.ProtocolConstants; import net.md_5.bungee.protocol.ProtocolConstants;
@Data @Data
@ -18,12 +21,13 @@ public class ScoreboardObjective extends DefinedPacket
{ {
private String name; private String name;
private String value; private Either<String, BaseComponent> value;
private HealthDisplay type; private HealthDisplay type;
/** /**
* 0 to create, 1 to remove, 2 to update display text. * 0 to create, 1 to remove, 2 to update display text.
*/ */
private byte action; private byte action;
private NumberFormat numberFormat;
@Override @Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
@ -32,14 +36,19 @@ public class ScoreboardObjective extends DefinedPacket
action = buf.readByte(); action = buf.readByte();
if ( action == 0 || action == 2 ) if ( action == 0 || action == 2 )
{ {
value = readString( buf );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_13 ) if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_13 )
{ {
value = readEitherBaseComponent( buf, protocolVersion, false );
type = HealthDisplay.values()[readVarInt( buf )]; type = HealthDisplay.values()[readVarInt( buf )];
} else } else
{ {
value = readEitherBaseComponent( buf, protocolVersion, true );
type = HealthDisplay.fromString( readString( buf ) ); type = HealthDisplay.fromString( readString( buf ) );
} }
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_3 )
{
numberFormat = readNullable( (b) -> readNumberFormat( b, protocolVersion ), buf );
}
} }
} }
@ -50,7 +59,7 @@ public class ScoreboardObjective extends DefinedPacket
buf.writeByte( action ); buf.writeByte( action );
if ( action == 0 || action == 2 ) if ( action == 0 || action == 2 )
{ {
writeString( value, buf ); writeEitherBaseComponent( value, buf, protocolVersion );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_13 ) if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_13 )
{ {
writeVarInt( type.ordinal(), buf ); writeVarInt( type.ordinal(), buf );
@ -58,6 +67,10 @@ public class ScoreboardObjective extends DefinedPacket
{ {
writeString( type.toString(), buf ); writeString( type.toString(), buf );
} }
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_3 )
{
writeNullable( numberFormat, (s, b) -> DefinedPacket.writeNumberFormat( s, b, protocolVersion ), buf );
}
} }
} }

View File

@ -5,8 +5,10 @@ import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.protocol.AbstractPacketHandler; import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.NumberFormat;
import net.md_5.bungee.protocol.ProtocolConstants; import net.md_5.bungee.protocol.ProtocolConstants;
@Data @Data
@ -23,29 +25,50 @@ public class ScoreboardScore extends DefinedPacket
private byte action; private byte action;
private String scoreName; private String scoreName;
private int value; private int value;
private BaseComponent displayName;
private NumberFormat numberFormat;
@Override @Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{ {
itemName = readString( buf ); itemName = readString( buf );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_3 )
{
action = 0;
} else
{
action = buf.readByte(); action = buf.readByte();
}
scoreName = readString( buf ); scoreName = readString( buf );
if ( action != 1 ) if ( action != 1 )
{ {
value = readVarInt( buf ); value = readVarInt( buf );
} }
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_3 )
{
displayName = readNullable( (b) -> readBaseComponent( b, protocolVersion ), buf );
numberFormat = readNullable( (b) -> readNumberFormat( b, protocolVersion ), buf );
}
} }
@Override @Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{ {
writeString( itemName, buf ); writeString( itemName, buf );
if ( protocolVersion < ProtocolConstants.MINECRAFT_1_20_3 )
{
buf.writeByte( action ); buf.writeByte( action );
}
writeString( scoreName, buf ); writeString( scoreName, buf );
if ( action != 1 ) if ( action != 1 || protocolVersion >= ProtocolConstants.MINECRAFT_1_20_3 )
{ {
writeVarInt( value, buf ); writeVarInt( value, buf );
} }
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_3 )
{
writeNullable( displayName, (s, b) -> DefinedPacket.writeBaseComponent( s, b, protocolVersion ), buf );
writeNullable( numberFormat, (s, b) -> DefinedPacket.writeNumberFormat( s, b, protocolVersion ), buf );
}
} }
@Override @Override

View File

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

View File

@ -5,6 +5,7 @@ import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.protocol.AbstractPacketHandler; import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.ProtocolConstants; import net.md_5.bungee.protocol.ProtocolConstants;
@ -16,7 +17,7 @@ import net.md_5.bungee.protocol.ProtocolConstants;
public class ServerData extends DefinedPacket public class ServerData extends DefinedPacket
{ {
private String motd; private BaseComponent motd;
private Object icon; private Object icon;
private boolean preview; private boolean preview;
private boolean enforceSecure; private boolean enforceSecure;
@ -26,7 +27,7 @@ public class ServerData extends DefinedPacket
{ {
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_4 || buf.readBoolean() ) if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_4 || buf.readBoolean() )
{ {
motd = readString( buf, 262144 ); motd = readBaseComponent( buf, protocolVersion );
} }
if ( buf.readBoolean() ) if ( buf.readBoolean() )
{ {
@ -59,7 +60,7 @@ public class ServerData extends DefinedPacket
{ {
buf.writeBoolean( true ); buf.writeBoolean( true );
} }
writeString( motd, buf, 262144 ); writeBaseComponent( motd, buf, protocolVersion );
} else } else
{ {
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_4 ) if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_4 )

View File

@ -4,6 +4,7 @@ import io.netty.buffer.ByteBuf;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.protocol.AbstractPacketHandler; import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.ProtocolConstants; import net.md_5.bungee.protocol.ProtocolConstants;
@ -14,18 +15,18 @@ import net.md_5.bungee.protocol.ProtocolConstants;
public class Subtitle extends DefinedPacket public class Subtitle extends DefinedPacket
{ {
private String text; private BaseComponent text;
@Override @Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{ {
text = readString( buf ); text = readBaseComponent( buf, protocolVersion );
} }
@Override @Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{ {
writeString( text, buf ); writeBaseComponent( text, buf, protocolVersion );
} }
@Override @Override

View File

@ -6,6 +6,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.protocol.AbstractPacketHandler; import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.ProtocolConstants; import net.md_5.bungee.protocol.ProtocolConstants;
@ -17,20 +18,20 @@ import net.md_5.bungee.protocol.ProtocolConstants;
public class SystemChat extends DefinedPacket public class SystemChat extends DefinedPacket
{ {
private String message; private BaseComponent message;
private int position; private int position;
@Override @Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{ {
message = readString( buf, 262144 ); message = readBaseComponent( buf, 262144, protocolVersion );
position = ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 ) ? ( ( buf.readBoolean() ) ? ChatMessageType.ACTION_BAR.ordinal() : 0 ) : readVarInt( buf ); position = ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 ) ? ( ( buf.readBoolean() ) ? ChatMessageType.ACTION_BAR.ordinal() : 0 ) : readVarInt( buf );
} }
@Override @Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{ {
writeString( message, buf, 262144 ); writeBaseComponent( message, buf, protocolVersion );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 ) if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 )
{ {
buf.writeBoolean( position == ChatMessageType.ACTION_BAR.ordinal() ); buf.writeBoolean( position == ChatMessageType.ACTION_BAR.ordinal() );

View File

@ -1,6 +1,6 @@
package net.md_5.bungee.protocol.packet; package net.md_5.bungee.protocol.packet;
import com.mojang.brigadier.LiteralMessage; import com.mojang.brigadier.Message;
import com.mojang.brigadier.context.StringRange; import com.mojang.brigadier.context.StringRange;
import com.mojang.brigadier.suggestion.Suggestion; import com.mojang.brigadier.suggestion.Suggestion;
import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.Suggestions;
@ -10,6 +10,7 @@ import java.util.List;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.protocol.AbstractPacketHandler; import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.ProtocolConstants; import net.md_5.bungee.protocol.ProtocolConstants;
@ -51,9 +52,9 @@ public class TabCompleteResponse extends DefinedPacket
for ( int i = 0; i < cnt; i++ ) for ( int i = 0; i < cnt; i++ )
{ {
String match = readString( buf ); String match = readString( buf );
String tooltip = buf.readBoolean() ? readString( buf ) : null; BaseComponent tooltip = buf.readBoolean() ? readBaseComponent( buf, protocolVersion ) : null;
matches.add( new Suggestion( range, match, new LiteralMessage( tooltip ) ) ); matches.add( new Suggestion( range, match, ( tooltip != null ) ? new ComponentMessage( tooltip ) : null ) );
} }
suggestions = new Suggestions( range, matches ); suggestions = new Suggestions( range, matches );
@ -76,10 +77,10 @@ public class TabCompleteResponse extends DefinedPacket
for ( Suggestion suggestion : suggestions.getList() ) for ( Suggestion suggestion : suggestions.getList() )
{ {
writeString( suggestion.getText(), buf ); writeString( suggestion.getText(), buf );
buf.writeBoolean( suggestion.getTooltip() != null && suggestion.getTooltip().getString() != null ); buf.writeBoolean( suggestion.getTooltip() != null );
if ( suggestion.getTooltip() != null && suggestion.getTooltip().getString() != null ) if ( suggestion.getTooltip() != null )
{ {
writeString( suggestion.getTooltip().getString(), buf ); writeBaseComponent( ( (ComponentMessage) suggestion.getTooltip() ).getComponent(), buf, protocolVersion );
} }
} }
} else } else
@ -93,4 +94,17 @@ public class TabCompleteResponse extends DefinedPacket
{ {
handler.handle( this ); handler.handle( this );
} }
@Data
private static class ComponentMessage implements Message
{
private final BaseComponent component;
@Override
public String getString()
{
return component.toPlainText();
}
}
} }

View File

@ -5,8 +5,10 @@ import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.protocol.AbstractPacketHandler; import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.Either;
import net.md_5.bungee.protocol.ProtocolConstants; import net.md_5.bungee.protocol.ProtocolConstants;
@Data @Data
@ -21,9 +23,9 @@ public class Team extends DefinedPacket
* 0 - create, 1 remove, 2 info update, 3 player add, 4 player remove. * 0 - create, 1 remove, 2 info update, 3 player add, 4 player remove.
*/ */
private byte mode; private byte mode;
private String displayName; private Either<String, BaseComponent> displayName;
private String prefix; private Either<String, BaseComponent> prefix;
private String suffix; private Either<String, BaseComponent> suffix;
private String nameTagVisibility; private String nameTagVisibility;
private String collisionRule; private String collisionRule;
private int color; private int color;
@ -48,11 +50,14 @@ public class Team extends DefinedPacket
mode = buf.readByte(); mode = buf.readByte();
if ( mode == 0 || mode == 2 ) if ( mode == 0 || mode == 2 )
{ {
displayName = readString( buf );
if ( protocolVersion < ProtocolConstants.MINECRAFT_1_13 ) if ( protocolVersion < ProtocolConstants.MINECRAFT_1_13 )
{ {
prefix = readString( buf ); displayName = readEitherBaseComponent( buf, protocolVersion, true );
suffix = readString( buf ); prefix = readEitherBaseComponent( buf, protocolVersion, true );
suffix = readEitherBaseComponent( buf, protocolVersion, true );
} else
{
displayName = readEitherBaseComponent( buf, protocolVersion, false );
} }
friendlyFire = buf.readByte(); friendlyFire = buf.readByte();
nameTagVisibility = readString( buf ); nameTagVisibility = readString( buf );
@ -63,8 +68,8 @@ public class Team extends DefinedPacket
color = ( protocolVersion >= ProtocolConstants.MINECRAFT_1_13 ) ? readVarInt( buf ) : buf.readByte(); color = ( protocolVersion >= ProtocolConstants.MINECRAFT_1_13 ) ? readVarInt( buf ) : buf.readByte();
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_13 ) if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_13 )
{ {
prefix = readString( buf ); prefix = readEitherBaseComponent( buf, protocolVersion, false );
suffix = readString( buf ); suffix = readEitherBaseComponent( buf, protocolVersion, false );
} }
} }
if ( mode == 0 || mode == 3 || mode == 4 ) if ( mode == 0 || mode == 3 || mode == 4 )
@ -85,11 +90,11 @@ public class Team extends DefinedPacket
buf.writeByte( mode ); buf.writeByte( mode );
if ( mode == 0 || mode == 2 ) if ( mode == 0 || mode == 2 )
{ {
writeString( displayName, buf ); writeEitherBaseComponent( displayName, buf, protocolVersion );
if ( protocolVersion < ProtocolConstants.MINECRAFT_1_13 ) if ( protocolVersion < ProtocolConstants.MINECRAFT_1_13 )
{ {
writeString( prefix, buf ); writeEitherBaseComponent( prefix, buf, protocolVersion );
writeString( suffix, buf ); writeEitherBaseComponent( suffix, buf, protocolVersion );
} }
buf.writeByte( friendlyFire ); buf.writeByte( friendlyFire );
writeString( nameTagVisibility, buf ); writeString( nameTagVisibility, buf );
@ -101,8 +106,8 @@ public class Team extends DefinedPacket
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_13 ) if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_13 )
{ {
writeVarInt( color, buf ); writeVarInt( color, buf );
writeString( prefix, buf ); writeEitherBaseComponent( prefix, buf, protocolVersion );
writeString( suffix, buf ); writeEitherBaseComponent( suffix, buf, protocolVersion );
} else } else
{ {
buf.writeByte( color ); buf.writeByte( color );

View File

@ -4,6 +4,7 @@ import io.netty.buffer.ByteBuf;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.protocol.AbstractPacketHandler; import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.ProtocolConstants; import net.md_5.bungee.protocol.ProtocolConstants;
@ -17,7 +18,7 @@ public class Title extends DefinedPacket
private Action action; private Action action;
// TITLE & SUBTITLE // TITLE & SUBTITLE
private String text; private BaseComponent text;
// TIMES // TIMES
private int fadeIn; private int fadeIn;
@ -34,7 +35,7 @@ public class Title extends DefinedPacket
{ {
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_17 ) if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_17 )
{ {
text = readString( buf ); text = readBaseComponent( buf, protocolVersion );
return; return;
} }
@ -52,7 +53,7 @@ public class Title extends DefinedPacket
case TITLE: case TITLE:
case SUBTITLE: case SUBTITLE:
case ACTIONBAR: case ACTIONBAR:
text = readString( buf ); text = readBaseComponent( buf, protocolVersion );
break; break;
case TIMES: case TIMES:
fadeIn = buf.readInt(); fadeIn = buf.readInt();
@ -67,7 +68,7 @@ public class Title extends DefinedPacket
{ {
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_17 ) if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_17 )
{ {
writeString( text, buf ); writeBaseComponent( text, buf, protocolVersion );
return; return;
} }
@ -85,7 +86,7 @@ public class Title extends DefinedPacket
case TITLE: case TITLE:
case SUBTITLE: case SUBTITLE:
case ACTIONBAR: case ACTIONBAR:
writeString( text, buf ); writeBaseComponent( text, buf, protocolVersion );
break; break;
case TIMES: case TIMES:
buf.writeInt( fadeIn ); buf.writeInt( fadeIn );

View File

@ -4,13 +4,12 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>net.md-5</groupId> <groupId>fr.pandacube.bungeecord</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.20-R0.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-proxy</artifactId> <artifactId>bungeecord-proxy</artifactId>
<version>1.20-R0.2-SNAPSHOT</version> <version>1.20-R0.2-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
@ -52,37 +51,37 @@
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>fr.pandacube.bungeecord</groupId>
<artifactId>bungeecord-api</artifactId> <artifactId>bungeecord-api</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>fr.pandacube.bungeecord</groupId>
<artifactId>bungeecord-log</artifactId> <artifactId>bungeecord-log</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>fr.pandacube.bungeecord</groupId>
<artifactId>bungeecord-native</artifactId> <artifactId>bungeecord-native</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>fr.pandacube.bungeecord</groupId>
<artifactId>bungeecord-protocol</artifactId> <artifactId>bungeecord-protocol</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>fr.pandacube.bungeecord</groupId>
<artifactId>bungeecord-query</artifactId> <artifactId>bungeecord-query</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>fr.pandacube.bungeecord</groupId>
<artifactId>bungeecord-slf4j</artifactId> <artifactId>bungeecord-slf4j</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>

View File

@ -1,6 +1,5 @@
package net.md_5.bungee; package net.md_5.bungee;
import com.google.common.base.Charsets;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@ -24,6 +23,7 @@ import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
import java.text.Format; import java.text.Format;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
@ -89,7 +89,6 @@ import net.md_5.bungee.forge.ForgeConstants;
import net.md_5.bungee.log.BungeeLogger; import net.md_5.bungee.log.BungeeLogger;
import net.md_5.bungee.log.LoggingForwardHandler; import net.md_5.bungee.log.LoggingForwardHandler;
import net.md_5.bungee.log.LoggingOutputStream; 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.netty.PipelineUtils;
import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.ProtocolConstants; import net.md_5.bungee.protocol.ProtocolConstants;
@ -173,7 +172,6 @@ public class BungeeCord extends ProxyServer
.registerTypeAdapter( Favicon.class, Favicon.getFaviconTypeAdapter() ).create(); .registerTypeAdapter( Favicon.class, Favicon.getFaviconTypeAdapter() ).create();
@Getter @Getter
private ConnectionThrottle connectionThrottle; private ConnectionThrottle connectionThrottle;
private final ModuleManager moduleManager = new ModuleManager();
{ {
// TODO: Proper fallback when we interface the manager // TODO: Proper fallback when we interface the manager
@ -271,10 +269,6 @@ public class BungeeCord extends ProxyServer
eventLoops = PipelineUtils.newEventLoopGroup( 0, new ThreadFactoryBuilder().setNameFormat( "Netty IO Thread #%1$d" ).build() ); 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(); pluginsFolder.mkdir();
pluginManager.detectPlugins( pluginsFolder ); pluginManager.detectPlugins( pluginsFolder );
@ -691,10 +685,10 @@ public class BungeeCord extends ProxyServer
{ {
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_13 ) if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_13 )
{ {
return new PluginMessage( "minecraft:register", String.join( "\00", Iterables.transform( pluginChannels, PluginMessage.MODERNISE ) ).getBytes( Charsets.UTF_8 ), false ); return new PluginMessage( "minecraft:register", String.join( "\00", Iterables.transform( pluginChannels, PluginMessage.MODERNISE ) ).getBytes( StandardCharsets.UTF_8 ), false );
} }
return new PluginMessage( "REGISTER", String.join( "\00", pluginChannels ).getBytes( Charsets.UTF_8 ), false ); return new PluginMessage( "REGISTER", String.join( "\00", pluginChannels ).getBytes( StandardCharsets.UTF_8 ), false );
} }
@Override @Override
@ -730,13 +724,13 @@ public class BungeeCord extends ProxyServer
@Override @Override
public void broadcast(String message) public void broadcast(String message)
{ {
broadcast( TextComponent.fromLegacyText( message ) ); broadcast( TextComponent.fromLegacy( message ) );
} }
@Override @Override
public void broadcast(BaseComponent... message) public void broadcast(BaseComponent... message)
{ {
getConsole().sendMessage( BaseComponent.toLegacyText( message ) ); getConsole().sendMessage( message );
for ( ProxiedPlayer player : getPlayers() ) for ( ProxiedPlayer player : getPlayers() )
{ {
player.sendMessage( message ); player.sendMessage( message );
@ -746,14 +740,14 @@ public class BungeeCord extends ProxyServer
@Override @Override
public void broadcast(BaseComponent message) public void broadcast(BaseComponent message)
{ {
getConsole().sendMessage( message.toLegacyText() ); getConsole().sendMessage( message );
for ( ProxiedPlayer player : getPlayers() ) for ( ProxiedPlayer player : getPlayers() )
{ {
player.sendMessage( message ); player.sendMessage( message );
} }
} }
public void addConnection(UserConnection con) public boolean addConnection(UserConnection con)
{ {
UUID offlineId = con.getPendingConnection().getOfflineId(); UUID offlineId = con.getPendingConnection().getOfflineId();
if ( offlineId != null && offlineId.version() != 3 ) if ( offlineId != null && offlineId.version() != 3 )
@ -763,6 +757,10 @@ public class BungeeCord extends ProxyServer
connectionLock.writeLock().lock(); connectionLock.writeLock().lock();
try try
{ {
if ( connections.containsKey( con.getName() ) || connectionsByUUID.containsKey( con.getUniqueId() ) || connectionsByOfflineUUID.containsKey( offlineId ) )
{
return false;
}
connections.put( con.getName(), con ); connections.put( con.getName(), con );
connectionsByUUID.put( con.getUniqueId(), con ); connectionsByUUID.put( con.getUniqueId(), con );
connectionsByOfflineUUID.put( offlineId, con ); connectionsByOfflineUUID.put( offlineId, con );
@ -770,6 +768,7 @@ public class BungeeCord extends ProxyServer
{ {
connectionLock.writeLock().unlock(); connectionLock.writeLock().unlock();
} }
return true;
} }
public void removeConnection(UserConnection con) public void removeConnection(UserConnection con)

View File

@ -5,7 +5,6 @@ import java.text.SimpleDateFormat;
import java.util.Arrays; import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.concurrent.TimeUnit;
import joptsimple.OptionParser; import joptsimple.OptionParser;
import joptsimple.OptionSet; import joptsimple.OptionSet;
import net.md_5.bungee.api.ChatColor; 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( "*** Warning, this build is outdated ***" );
System.err.println( "*** Please download a new build from http://ci.md-5.net/job/BungeeCord ***" ); 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( "*** You will get NO support regarding this build ***" );
System.err.println( "*** Server will start in 10 seconds ***" );
Thread.sleep( TimeUnit.SECONDS.toMillis( 10 ) );
} }
} }

View File

@ -3,8 +3,8 @@ package net.md_5.bungee;
import lombok.Data; import lombok.Data;
import net.md_5.bungee.api.Title; import net.md_5.bungee.api.Title;
import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.chat.ComponentSerializer;
import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.ProtocolConstants; import net.md_5.bungee.protocol.ProtocolConstants;
import net.md_5.bungee.protocol.packet.ClearTitles; import net.md_5.bungee.protocol.packet.ClearTitles;
@ -53,21 +53,14 @@ public class BungeeTitle implements Title
title = new TitlePacketHolder<>( packet, packet ); title = new TitlePacketHolder<>( packet, packet );
} }
title.oldPacket.setText( ComponentSerializer.toString( text ) ); // = newPacket title.oldPacket.setText( text ); // = newPacket
return this; return this;
} }
@Override @Override
public Title title(BaseComponent... text) public Title title(BaseComponent... text)
{ {
if ( title == null ) return title( TextComponent.fromArray( text ) );
{
net.md_5.bungee.protocol.packet.Title packet = new net.md_5.bungee.protocol.packet.Title( Action.TITLE );
title = new TitlePacketHolder<>( packet, packet );
}
title.oldPacket.setText( ComponentSerializer.toString( text ) ); // = newPacket
return this;
} }
@Override @Override
@ -78,24 +71,15 @@ public class BungeeTitle implements Title
subtitle = new TitlePacketHolder<>( new net.md_5.bungee.protocol.packet.Title( Action.SUBTITLE ), new Subtitle() ); subtitle = new TitlePacketHolder<>( new net.md_5.bungee.protocol.packet.Title( Action.SUBTITLE ), new Subtitle() );
} }
String serialized = ComponentSerializer.toString( text ); subtitle.oldPacket.setText( text );
subtitle.oldPacket.setText( serialized ); subtitle.newPacket.setText( text );
subtitle.newPacket.setText( serialized );
return this; return this;
} }
@Override @Override
public Title subTitle(BaseComponent... text) public Title subTitle(BaseComponent... text)
{ {
if ( subtitle == null ) return subTitle( TextComponent.fromArray( text ) );
{
subtitle = new TitlePacketHolder<>( new net.md_5.bungee.protocol.packet.Title( Action.SUBTITLE ), new Subtitle() );
}
String serialized = ComponentSerializer.toString( text );
subtitle.oldPacket.setText( serialized );
subtitle.newPacket.setText( serialized );
return this;
} }
@Override @Override

View File

@ -14,6 +14,7 @@ import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.event.ServerConnectEvent; import net.md_5.bungee.api.event.ServerConnectEvent;
import net.md_5.bungee.api.event.ServerConnectedEvent; import net.md_5.bungee.api.event.ServerConnectedEvent;
@ -34,6 +35,7 @@ import net.md_5.bungee.netty.ChannelWrapper;
import net.md_5.bungee.netty.HandlerBoss; import net.md_5.bungee.netty.HandlerBoss;
import net.md_5.bungee.netty.PacketHandler; import net.md_5.bungee.netty.PacketHandler;
import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.Either;
import net.md_5.bungee.protocol.PacketWrapper; import net.md_5.bungee.protocol.PacketWrapper;
import net.md_5.bungee.protocol.Protocol; import net.md_5.bungee.protocol.Protocol;
import net.md_5.bungee.protocol.ProtocolConstants; import net.md_5.bungee.protocol.ProtocolConstants;
@ -51,6 +53,7 @@ import net.md_5.bungee.protocol.packet.PluginMessage;
import net.md_5.bungee.protocol.packet.Respawn; import net.md_5.bungee.protocol.packet.Respawn;
import net.md_5.bungee.protocol.packet.ScoreboardObjective; import net.md_5.bungee.protocol.packet.ScoreboardObjective;
import net.md_5.bungee.protocol.packet.ScoreboardScore; import net.md_5.bungee.protocol.packet.ScoreboardScore;
import net.md_5.bungee.protocol.packet.ScoreboardScoreReset;
import net.md_5.bungee.protocol.packet.SetCompression; import net.md_5.bungee.protocol.packet.SetCompression;
import net.md_5.bungee.protocol.packet.StartConfiguration; import net.md_5.bungee.protocol.packet.StartConfiguration;
import net.md_5.bungee.protocol.packet.ViewDistance; import net.md_5.bungee.protocol.packet.ViewDistance;
@ -278,11 +281,22 @@ public class ServerConnector extends PacketHandler
Scoreboard serverScoreboard = user.getServerSentScoreboard(); Scoreboard serverScoreboard = user.getServerSentScoreboard();
for ( Objective objective : serverScoreboard.getObjectives() ) for ( Objective objective : serverScoreboard.getObjectives() )
{ {
user.unsafe().sendPacket( new ScoreboardObjective( objective.getName(), objective.getValue(), ScoreboardObjective.HealthDisplay.fromString( objective.getType() ), (byte) 1 ) ); user.unsafe().sendPacket( new ScoreboardObjective(
objective.getName(),
( user.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_13 ) ? Either.right( ComponentSerializer.deserialize( objective.getValue() ) ) : Either.left( objective.getValue() ),
ScoreboardObjective.HealthDisplay.fromString( objective.getType() ),
(byte) 1, null )
);
} }
for ( Score score : serverScoreboard.getScores() ) for ( Score score : serverScoreboard.getScores() )
{ {
user.unsafe().sendPacket( new ScoreboardScore( score.getItemName(), (byte) 1, score.getScoreName(), score.getValue() ) ); if ( user.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_20_3 )
{
user.unsafe().sendPacket( new ScoreboardScoreReset( score.getItemName(), null ) );
} else
{
user.unsafe().sendPacket( new ScoreboardScore( score.getItemName(), (byte) 1, score.getScoreName(), score.getValue(), null, null ) );
}
} }
for ( Team team : serverScoreboard.getTeams() ) for ( Team team : serverScoreboard.getTeams() )
{ {
@ -383,7 +397,10 @@ public class ServerConnector extends PacketHandler
public void handle(Kick kick) throws Exception public void handle(Kick kick) throws Exception
{ {
ServerInfo def = user.updateAndGetNextServer( target ); ServerInfo def = user.updateAndGetNextServer( target );
ServerKickEvent event = new ServerKickEvent( user, target, ComponentSerializer.parse( kick.getMessage() ), def, ServerKickEvent.State.CONNECTING ); ServerKickEvent event = new ServerKickEvent( user, target, new BaseComponent[]
{
kick.getMessage()
}, def, ServerKickEvent.State.CONNECTING );
if ( event.getKickReason().toLowerCase( Locale.ROOT ).contains( "outdated" ) && def != null ) if ( event.getKickReason().toLowerCase( Locale.ROOT ).contains( "outdated" ) && def != null )
{ {
// Pre cancel the event if we are going to try another server // Pre cancel the event if we are going to try another server

View File

@ -153,7 +153,7 @@ public final class UserConnection implements ProxiedPlayer
} }
}; };
public void init() public boolean init()
{ {
this.entityRewrite = EntityMap.getEntityMap( getPendingConnection().getVersion() ); this.entityRewrite = EntityMap.getEntityMap( getPendingConnection().getVersion() );
@ -172,6 +172,8 @@ public final class UserConnection implements ProxiedPlayer
// Set whether the connection has a 1.8 FML marker in the handshake. // Set whether the connection has a 1.8 FML marker in the handshake.
forgeClientHandler.setFmlTokenInHandshake( this.getPendingConnection().getExtraDataInHandshake().contains( ForgeConstants.FML_HANDSHAKE_TOKEN ) ); forgeClientHandler.setFmlTokenInHandshake( this.getPendingConnection().getExtraDataInHandshake().contains( ForgeConstants.FML_HANDSHAKE_TOKEN ) );
return BungeeCord.getInstance().addConnection( this );
} }
public void sendPacket(PacketWrapper packet) public void sendPacket(PacketWrapper packet)
@ -406,13 +408,13 @@ public final class UserConnection implements ProxiedPlayer
@Override @Override
public void disconnect(String reason) public void disconnect(String reason)
{ {
disconnect0( TextComponent.fromLegacyText( reason ) ); disconnect( TextComponent.fromLegacy( reason ) );
} }
@Override @Override
public void disconnect(BaseComponent... reason) public void disconnect(BaseComponent... reason)
{ {
disconnect0( reason ); disconnect( TextComponent.fromArray( reason ) );
} }
@Override @Override
@ -421,7 +423,7 @@ public final class UserConnection implements ProxiedPlayer
disconnect0( reason ); disconnect0( reason );
} }
public void disconnect0(final BaseComponent... reason) public void disconnect0(final BaseComponent reason)
{ {
if ( !ch.isClosing() ) if ( !ch.isClosing() )
{ {
@ -430,7 +432,7 @@ public final class UserConnection implements ProxiedPlayer
getName(), BaseComponent.toLegacyText( reason ) getName(), BaseComponent.toLegacyText( reason )
} ); } );
ch.close( new Kick( ComponentSerializer.toString( reason ) ) ); ch.close( new Kick( reason ) );
if ( server != null ) if ( server != null )
{ {
@ -454,7 +456,7 @@ public final class UserConnection implements ProxiedPlayer
@Override @Override
public void sendMessage(String message) public void sendMessage(String message)
{ {
sendMessage( TextComponent.fromLegacyText( message ) ); sendMessage( TextComponent.fromLegacy( message ) );
} }
@Override @Override
@ -481,7 +483,7 @@ public final class UserConnection implements ProxiedPlayer
@Override @Override
public void sendMessage(ChatMessageType position, BaseComponent... message) public void sendMessage(ChatMessageType position, BaseComponent... message)
{ {
sendMessage( position, null, message ); sendMessage( position, null, TextComponent.fromArray( message ) );
} }
@Override @Override
@ -493,7 +495,7 @@ public final class UserConnection implements ProxiedPlayer
@Override @Override
public void sendMessage(UUID sender, BaseComponent... message) public void sendMessage(UUID sender, BaseComponent... message)
{ {
sendMessage( ChatMessageType.CHAT, sender, message ); sendMessage( ChatMessageType.CHAT, sender, TextComponent.fromArray( message ) );
} }
@Override @Override
@ -502,8 +504,28 @@ public final class UserConnection implements ProxiedPlayer
sendMessage( ChatMessageType.CHAT, sender, message ); sendMessage( ChatMessageType.CHAT, sender, message );
} }
private void sendMessage(ChatMessageType position, UUID sender, String message) private void sendMessage(ChatMessageType position, UUID sender, BaseComponent message)
{ {
// transform score components
message = ChatComponentTransformer.getInstance().transform( this, true, message );
if ( position == ChatMessageType.ACTION_BAR && getPendingConnection().getVersion() < ProtocolConstants.MINECRAFT_1_17 )
{
// Versions older than 1.11 cannot send the Action bar with the new JSON formattings
// Fix by converting to a legacy message, see https://bugs.mojang.com/browse/MC-119145
if ( getPendingConnection().getVersion() <= ProtocolConstants.MINECRAFT_1_10 )
{
message = new TextComponent( BaseComponent.toLegacyText( message ) );
} else
{
net.md_5.bungee.protocol.packet.Title title = new net.md_5.bungee.protocol.packet.Title();
title.setAction( net.md_5.bungee.protocol.packet.Title.Action.ACTIONBAR );
title.setText( message );
sendPacketQueued( title );
return;
}
}
if ( getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_19 ) if ( getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_19 )
{ {
// Align with Spigot and remove client side formatting for now // Align with Spigot and remove client side formatting for now
@ -515,32 +537,7 @@ public final class UserConnection implements ProxiedPlayer
sendPacketQueued( new SystemChat( message, position.ordinal() ) ); sendPacketQueued( new SystemChat( message, position.ordinal() ) );
} else } else
{ {
sendPacketQueued( new Chat( message, (byte) position.ordinal(), sender ) ); sendPacketQueued( new Chat( ComponentSerializer.toString( message ), (byte) position.ordinal(), sender ) );
}
}
private void sendMessage(ChatMessageType position, UUID sender, BaseComponent... message)
{
// transform score components
message = ChatComponentTransformer.getInstance().transform( this, true, message );
if ( position == ChatMessageType.ACTION_BAR && getPendingConnection().getVersion() < ProtocolConstants.MINECRAFT_1_17 )
{
// Versions older than 1.11 cannot send the Action bar with the new JSON formattings
// Fix by converting to a legacy message, see https://bugs.mojang.com/browse/MC-119145
if ( getPendingConnection().getVersion() <= ProtocolConstants.MINECRAFT_1_10 )
{
sendMessage( position, sender, ComponentSerializer.toString( new TextComponent( BaseComponent.toLegacyText( message ) ) ) );
} else
{
net.md_5.bungee.protocol.packet.Title title = new net.md_5.bungee.protocol.packet.Title();
title.setAction( net.md_5.bungee.protocol.packet.Title.Action.ACTIONBAR );
title.setText( ComponentSerializer.toString( message ) );
sendPacketQueued( title );
}
} else
{
sendMessage( position, sender, ComponentSerializer.toString( message ) );
} }
} }
@ -720,25 +717,19 @@ public final class UserConnection implements ProxiedPlayer
@Override @Override
public void setTabHeader(BaseComponent header, BaseComponent footer) public void setTabHeader(BaseComponent header, BaseComponent footer)
{ {
header = ChatComponentTransformer.getInstance().transform( this, true, header )[0]; header = ChatComponentTransformer.getInstance().transform( this, true, header );
footer = ChatComponentTransformer.getInstance().transform( this, true, footer )[0]; footer = ChatComponentTransformer.getInstance().transform( this, true, footer );
sendPacketQueued( new PlayerListHeaderFooter( sendPacketQueued( new PlayerListHeaderFooter(
ComponentSerializer.toString( header ), header,
ComponentSerializer.toString( footer ) footer
) ); ) );
} }
@Override @Override
public void setTabHeader(BaseComponent[] header, BaseComponent[] footer) public void setTabHeader(BaseComponent[] header, BaseComponent[] footer)
{ {
header = ChatComponentTransformer.getInstance().transform( this, true, header ); setTabHeader( TextComponent.fromArray( header ), TextComponent.fromArray( footer ) );
footer = ChatComponentTransformer.getInstance().transform( this, true, footer );
sendPacketQueued( new PlayerListHeaderFooter(
ComponentSerializer.toString( header ),
ComponentSerializer.toString( footer )
) );
} }
@Override @Override

View File

@ -1,6 +1,5 @@
package net.md_5.bungee.conf; package net.md_5.bungee.conf;
import com.google.common.base.Charsets;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -10,6 +9,7 @@ import java.io.InputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.io.Writer; import java.io.Writer;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@ -176,7 +176,7 @@ public class YamlConfig implements ConfigurationAdapter
{ {
try try
{ {
try ( Writer wr = new OutputStreamWriter( new FileOutputStream( file ), Charsets.UTF_8 ) ) try ( Writer wr = new OutputStreamWriter( new FileOutputStream( file ), StandardCharsets.UTF_8 ) )
{ {
yaml.dump( config, wr ); yaml.dump( config, wr );
} }

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