Compare commits

..

18 Commits

Author SHA1 Message Date
87b3d814dd new event TabCompleteRequestEvent and deprecate TabCompleteEvent 2023-10-07 17:32:18 +02:00
7b45fdcf98 Add CommandsDeclareEvent to declare commands with brigadier API 2023-10-07 17:32:18 +02:00
4dde9b0e5e Server branding now includes the backend server name 2023-10-07 17:32:18 +02:00
7022c64432 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-10-07 17:32:18 +02:00
d2dd9089e3 Change projet configuration and POM for Pandacube 2023-10-07 17:32:18 +02:00
24f3f21386 Remove modules and startup delay
We don’t need them for Pandacube
2023-10-07 17:32:12 +02:00
Outfluencer
a7dbbc2f0a
#3544: Remove redundant super call in handle(FinishConfiguration) 2023-10-05 07:21:46 +11:00
Outfluencer
68b2df2b1e
#3514: Add separator property to SelectorComponent 2023-10-05 07:21:13 +11:00
dependabot[bot]
1ef4d27dbe
#3543: Bump io.netty:netty-bom from 4.1.97.Final to 4.1.99.Final
Bumps [io.netty:netty-bom](https://github.com/netty/netty) from 4.1.97.Final to 4.1.99.Final.
- [Commits](https://github.com/netty/netty/compare/netty-4.1.97.Final...netty-4.1.99.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-09-29 07:50:39 +10:00
Outfluencer
94a1fb5117
#3535: Queue packets of Title api 2023-09-29 07:21:56 +10:00
md_5
78aef86a8f
#3533: Don't put initial client in configure phase until server is ready 2023-09-29 06:50:28 +10:00
md_5
b34cfcde5a
Simplify UpstreamBridge packet handling code 2023-09-28 06:55:00 +10:00
DartCZ
86e079a4b1
#3523, #3534: Fix kicking players with error 2023-09-28 06:55:00 +10:00
Outfluencer
1c42c34081
#3529: Use a synchronized list for /send command 2023-09-28 06:51:10 +10:00
dependabot[bot]
fed646d18b
#3531: Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.0 to 3.5.1
Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.5.0 to 3.5.1.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.0...maven-shade-plugin-3.5.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-26 07:52:07 +10:00
md_5
653f1691d7
Print full stack trace for packet decoder errors 2023-09-26 06:40:02 +10:00
md_5
3cb7a12738
#3527: Switching between servers causes a decoding error 2023-09-26 06:35:48 +10:00
bob7l
f3397b3003
#3525, #3526: Set encode protocol to CONFIGURATION before connecting to a downstream server 2023-09-25 18:57:40 +10:00
12 changed files with 68 additions and 34 deletions

View File

@ -52,7 +52,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId> <artifactId>maven-shade-plugin</artifactId>
<version>3.5.0</version> <version>3.5.1</version>
<executions> <executions>
<execution> <execution>
<phase>package</phase> <phase>package</phase>

View File

@ -33,6 +33,13 @@ public final class SelectorComponent extends BaseComponent
*/ */
private String selector; private String selector;
/**
* The separator of multiple selected entities.
* <br>
* The default is {@code {"color": "gray", "text": ", "}}.
*/
private BaseComponent separator;
/** /**
* Creates a selector component from the original to clone it. * Creates a selector component from the original to clone it.
* *
@ -42,6 +49,17 @@ public final class SelectorComponent extends BaseComponent
{ {
super( original ); super( original );
setSelector( original.getSelector() ); setSelector( original.getSelector() );
setSeparator( original.getSeparator() );
}
/**
* Creates a selector component from the selector
*
* @param selector the selector as a String
*/
public SelectorComponent(String selector)
{
setSelector( selector );
} }
@Override @Override

View File

@ -22,6 +22,12 @@ public class SelectorComponentSerializer extends BaseComponentSerializer impleme
throw new JsonParseException( "Could not parse JSON: missing 'selector' property" ); throw new JsonParseException( "Could not parse JSON: missing 'selector' property" );
} }
SelectorComponent component = new SelectorComponent( object.get( "selector" ).getAsString() ); SelectorComponent component = new SelectorComponent( object.get( "selector" ).getAsString() );
if ( object.has( "separator" ) )
{
component.setSeparator( ComponentSerializer.deserialize( object.get( "separator" ).getAsString() ) );
}
deserialize( object, component, context ); deserialize( object, component, context );
return component; return component;
} }
@ -32,6 +38,11 @@ public class SelectorComponentSerializer extends BaseComponentSerializer impleme
JsonObject object = new JsonObject(); JsonObject object = new JsonObject();
serialize( object, component, context ); serialize( object, component, context );
object.addProperty( "selector", component.getSelector() ); object.addProperty( "selector", component.getSelector() );
if ( component.getSeparator() != null )
{
object.addProperty( "separator", ComponentSerializer.toString( component.getSeparator() ) );
}
return object; return object;
} }
} }

View File

@ -82,7 +82,7 @@
<dependency> <dependency>
<groupId>io.netty</groupId> <groupId>io.netty</groupId>
<artifactId>netty-bom</artifactId> <artifactId>netty-bom</artifactId>
<version>4.1.97.Final</version> <version>4.1.99.Final</version>
<type>pom</type> <type>pom</type>
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>

View File

@ -31,12 +31,12 @@ public class LegacyDecoder extends ByteToMessageDecoder
if ( packetID == 0xFE ) if ( packetID == 0xFE )
{ {
out.add( new PacketWrapper( new LegacyPing( in.isReadable() && in.readUnsignedByte() == 0x01 ), Unpooled.EMPTY_BUFFER ) ); out.add( new PacketWrapper( new LegacyPing( in.isReadable() && in.readUnsignedByte() == 0x01 ), Unpooled.EMPTY_BUFFER, Protocol.STATUS ) );
return; return;
} else if ( packetID == 0x02 && in.isReadable() ) } else if ( packetID == 0x02 && in.isReadable() )
{ {
in.skipBytes( in.readableBytes() ); in.skipBytes( in.readableBytes() );
out.add( new PacketWrapper( new LegacyHandshake(), Unpooled.EMPTY_BUFFER ) ); out.add( new PacketWrapper( new LegacyHandshake(), Unpooled.EMPTY_BUFFER, Protocol.STATUS ) );
return; return;
} }

View File

@ -50,7 +50,7 @@ public class MinecraftDecoder extends MessageToMessageDecoder<ByteBuf>
in.skipBytes( in.readableBytes() ); in.skipBytes( in.readableBytes() );
} }
out.add( new PacketWrapper( packet, slice ) ); out.add( new PacketWrapper( packet, slice, protocol ) );
slice = null; slice = null;
} finally } finally
{ {

View File

@ -10,6 +10,7 @@ public class PacketWrapper
public final DefinedPacket packet; public final DefinedPacket packet;
public final ByteBuf buf; public final ByteBuf buf;
public final Protocol protocol;
@Setter @Setter
private boolean released; private boolean released;

View File

@ -172,7 +172,7 @@ public class BungeeTitle implements Title
{ {
if ( player.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_17 ) if ( player.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_17 )
{ {
player.unsafe().sendPacket( packet.newPacket ); ( (UserConnection) player ).sendPacketQueued( packet.newPacket );
} else } else
{ {
player.unsafe().sendPacket( packet.oldPacket ); player.unsafe().sendPacket( packet.oldPacket );

View File

@ -43,7 +43,6 @@ import net.md_5.bungee.protocol.packet.GameState;
import net.md_5.bungee.protocol.packet.Handshake; import net.md_5.bungee.protocol.packet.Handshake;
import net.md_5.bungee.protocol.packet.Kick; import net.md_5.bungee.protocol.packet.Kick;
import net.md_5.bungee.protocol.packet.Login; import net.md_5.bungee.protocol.packet.Login;
import net.md_5.bungee.protocol.packet.LoginAcknowledged;
import net.md_5.bungee.protocol.packet.LoginPayloadRequest; import net.md_5.bungee.protocol.packet.LoginPayloadRequest;
import net.md_5.bungee.protocol.packet.LoginPayloadResponse; import net.md_5.bungee.protocol.packet.LoginPayloadResponse;
import net.md_5.bungee.protocol.packet.LoginRequest; import net.md_5.bungee.protocol.packet.LoginRequest;
@ -334,9 +333,9 @@ public class ServerConnector extends PacketHandler
user.unsafe().sendPacket( new StartConfiguration() ); user.unsafe().sendPacket( new StartConfiguration() );
} else } else
{ {
ch.setDecodeProtocol( Protocol.CONFIGURATION ); LoginResult loginProfile = user.getPendingConnection().getLoginProfile();
ch.write( new LoginAcknowledged() ); user.unsafe().sendPacket( new LoginSuccess( user.getUniqueId(), user.getName(), ( loginProfile == null ) ? null : loginProfile.getProperties() ) );
ch.setEncodeProtocol( Protocol.CONFIGURATION ); user.getCh().setEncodeProtocol( Protocol.CONFIGURATION );
} }
} }

View File

@ -59,7 +59,6 @@ import net.md_5.bungee.protocol.packet.Handshake;
import net.md_5.bungee.protocol.packet.Kick; import net.md_5.bungee.protocol.packet.Kick;
import net.md_5.bungee.protocol.packet.LegacyHandshake; import net.md_5.bungee.protocol.packet.LegacyHandshake;
import net.md_5.bungee.protocol.packet.LegacyPing; import net.md_5.bungee.protocol.packet.LegacyPing;
import net.md_5.bungee.protocol.packet.LoginAcknowledged;
import net.md_5.bungee.protocol.packet.LoginPayloadResponse; import net.md_5.bungee.protocol.packet.LoginPayloadResponse;
import net.md_5.bungee.protocol.packet.LoginRequest; import net.md_5.bungee.protocol.packet.LoginRequest;
import net.md_5.bungee.protocol.packet.LoginSuccess; import net.md_5.bungee.protocol.packet.LoginSuccess;
@ -132,12 +131,12 @@ public class InitialHandler extends PacketHandler implements PendingConnection
private enum State private enum State
{ {
HANDSHAKE, STATUS, PING, USERNAME, ENCRYPT, FINISHING, CONFIGURING; HANDSHAKE, STATUS, PING, USERNAME, ENCRYPT, FINISHING;
} }
private boolean canSendKickMessage() private boolean canSendKickMessage()
{ {
return thisState == State.USERNAME || thisState == State.ENCRYPT || thisState == State.FINISHING || thisState == State.CONFIGURING; return thisState == State.USERNAME || thisState == State.ENCRYPT || thisState == State.FINISHING;
} }
@Override @Override
@ -625,15 +624,12 @@ public class InitialHandler extends PacketHandler implements PendingConnection
userCon = new UserConnection( bungee, ch, getName(), InitialHandler.this ); userCon = new UserConnection( bungee, ch, getName(), InitialHandler.this );
userCon.setCompressionThreshold( BungeeCord.getInstance().config.getCompressionThreshold() ); userCon.setCompressionThreshold( BungeeCord.getInstance().config.getCompressionThreshold() );
unsafe.sendPacket( new LoginSuccess( getUniqueId(), getName(), ( loginProfile == null ) ? null : loginProfile.getProperties() ) ); if ( getVersion() < ProtocolConstants.MINECRAFT_1_20_2 )
if ( getVersion() >= ProtocolConstants.MINECRAFT_1_20_2 )
{
thisState = State.CONFIGURING;
} else
{ {
unsafe.sendPacket( new LoginSuccess( getUniqueId(), getName(), ( loginProfile == null ) ? null : loginProfile.getProperties() ) );
ch.setProtocol( Protocol.GAME ); ch.setProtocol( Protocol.GAME );
finish2();
} }
finish2();
} }
} }
} ); } );
@ -644,15 +640,6 @@ public class InitialHandler extends PacketHandler implements PendingConnection
bungee.getPluginManager().callEvent( new LoginEvent( InitialHandler.this, complete ) ); bungee.getPluginManager().callEvent( new LoginEvent( InitialHandler.this, complete ) );
} }
@Override
public void handle(LoginAcknowledged loginAcknowledged) throws Exception
{
Preconditions.checkState( thisState == State.CONFIGURING, "Not expecting CONFIGURING" );
finish2();
ch.setEncodeProtocol( Protocol.CONFIGURATION );
}
private void finish2() private void finish2()
{ {
userCon.init(); userCon.init();

View File

@ -9,6 +9,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import net.md_5.bungee.BungeeCord; import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.ServerConnection;
import net.md_5.bungee.ServerConnection.KeepAliveData; import net.md_5.bungee.ServerConnection.KeepAliveData;
import net.md_5.bungee.UserConnection; import net.md_5.bungee.UserConnection;
import net.md_5.bungee.Util; import net.md_5.bungee.Util;
@ -134,14 +135,22 @@ public class UpstreamBridge extends PacketHandler
@Override @Override
public void handle(PacketWrapper packet) throws Exception public void handle(PacketWrapper packet) throws Exception
{ {
if ( con.getServer() != null ) ServerConnection server = con.getServer();
if ( server != null && server.isConnected() )
{ {
Protocol serverEncode = server.getCh().getEncodeProtocol();
// #3527: May still have old packets from client in game state when switching server to configuration state - discard those
if ( packet.protocol != serverEncode )
{
return;
}
EntityMap rewrite = con.getEntityRewrite(); EntityMap rewrite = con.getEntityRewrite();
if ( rewrite != null && con.getServer().getCh().getEncodeProtocol() == Protocol.GAME ) if ( rewrite != null && serverEncode == Protocol.GAME )
{ {
rewrite.rewriteServerbound( packet.buf, con.getClientEntityId(), con.getServerEntityId(), con.getPendingConnection().getVersion() ); rewrite.rewriteServerbound( packet.buf, con.getClientEntityId(), con.getServerEntityId(), con.getPendingConnection().getVersion() );
} }
con.getServer().getCh().write( packet ); server.getCh().write( packet );
} }
} }
@ -332,8 +341,19 @@ public class UpstreamBridge extends PacketHandler
con.getPendingConnection().relayMessage( pluginMessage ); con.getPendingConnection().relayMessage( pluginMessage );
} }
@Override
public void handle(LoginAcknowledged loginAcknowledged) throws Exception
{
configureServer();
}
@Override @Override
public void handle(StartConfiguration startConfiguration) throws Exception public void handle(StartConfiguration startConfiguration) throws Exception
{
configureServer();
}
private void configureServer()
{ {
ChannelWrapper ch = con.getServer().getCh(); ChannelWrapper ch = con.getServer().getCh();
if ( ch.getDecodeProtocol() == Protocol.LOGIN ) if ( ch.getDecodeProtocol() == Protocol.LOGIN )
@ -352,8 +372,6 @@ public class UpstreamBridge extends PacketHandler
public void handle(FinishConfiguration finishConfiguration) throws Exception public void handle(FinishConfiguration finishConfiguration) throws Exception
{ {
con.sendQueuedPackets(); con.sendQueuedPackets();
super.handle( finishConfiguration );
} }
@Override @Override

View File

@ -174,7 +174,7 @@ public class HandlerBoss extends ChannelInboundHandlerAdapter
{ {
ProxyServer.getInstance().getLogger().log( Level.WARNING, "{0} - could not decode packet! {1}", new Object[] ProxyServer.getInstance().getLogger().log( Level.WARNING, "{0} - could not decode packet! {1}", new Object[]
{ {
handler, cause.getCause() != null ? cause.getCause() : cause handler, cause
} ); } );
} }
} else if ( cause instanceof IOException || ( cause instanceof IllegalStateException && handler instanceof InitialHandler ) ) } else if ( cause instanceof IOException || ( cause instanceof IllegalStateException && handler instanceof InitialHandler ) )