mirror of
https://github.com/PaperMC/Velocity.git
synced 2026-04-20 03:18:17 +02:00
use outbound only queueing when reentering configuration (#1747)
* use outbound only queueing and guard serverbound forwarding during reconfiguration
This commit is contained in:
@@ -33,6 +33,7 @@ import com.velocitypowered.natives.encryption.VelocityCipher;
|
||||
import com.velocitypowered.natives.encryption.VelocityCipherFactory;
|
||||
import com.velocitypowered.natives.util.Natives;
|
||||
import com.velocitypowered.proxy.VelocityServer;
|
||||
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
||||
import com.velocitypowered.proxy.connection.client.HandshakeSessionHandler;
|
||||
import com.velocitypowered.proxy.connection.client.InitialLoginSessionHandler;
|
||||
import com.velocitypowered.proxy.connection.client.StatusSessionHandler;
|
||||
@@ -368,6 +369,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
|
||||
public void setState(StateRegistry state) {
|
||||
ensureInEventLoop();
|
||||
|
||||
final StateRegistry previousState = this.state;
|
||||
this.state = state;
|
||||
final MinecraftVarintFrameDecoder frameDecoder = this.channel.pipeline()
|
||||
.get(MinecraftVarintFrameDecoder.class);
|
||||
@@ -388,7 +390,13 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
|
||||
|
||||
if (state == StateRegistry.CONFIG) {
|
||||
// Activate the play packet queue
|
||||
addPlayPacketQueueHandler();
|
||||
if (previousState == StateRegistry.PLAY
|
||||
&& this.pendingConfigurationSwitch
|
||||
&& this.association instanceof ConnectedPlayer) {
|
||||
addPlayPacketQueueOutboundHandler();
|
||||
} else {
|
||||
addPlayPacketQueueHandler();
|
||||
}
|
||||
} else {
|
||||
// Remove the queue
|
||||
if (this.channel.pipeline().get(Connections.PLAY_PACKET_QUEUE_OUTBOUND) != null) {
|
||||
@@ -404,13 +412,23 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
|
||||
* Adds the play packet queue handler.
|
||||
*/
|
||||
public void addPlayPacketQueueHandler() {
|
||||
if (this.channel.pipeline().get(Connections.PLAY_PACKET_QUEUE_OUTBOUND) == null) {
|
||||
this.channel.pipeline().addAfter(Connections.MINECRAFT_ENCODER, Connections.PLAY_PACKET_QUEUE_OUTBOUND,
|
||||
new PlayPacketQueueOutboundHandler(this.protocolVersion, channel.pipeline().get(MinecraftEncoder.class).getDirection()));
|
||||
}
|
||||
addPlayPacketQueueOutboundHandler();
|
||||
|
||||
if (this.channel.pipeline().get(Connections.PLAY_PACKET_QUEUE_INBOUND) == null) {
|
||||
this.channel.pipeline().addAfter(Connections.MINECRAFT_DECODER, Connections.PLAY_PACKET_QUEUE_INBOUND,
|
||||
new PlayPacketQueueInboundHandler(this.protocolVersion, channel.pipeline().get(MinecraftDecoder.class).getDirection()));
|
||||
new PlayPacketQueueInboundHandler(this.protocolVersion,
|
||||
channel.pipeline().get(MinecraftDecoder.class).getDirection()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds only the outbound play packet queue handler.
|
||||
*/
|
||||
public void addPlayPacketQueueOutboundHandler() {
|
||||
if (this.channel.pipeline().get(Connections.PLAY_PACKET_QUEUE_OUTBOUND) == null) {
|
||||
this.channel.pipeline().addAfter(Connections.MINECRAFT_ENCODER, Connections.PLAY_PACKET_QUEUE_OUTBOUND,
|
||||
new PlayPacketQueueOutboundHandler(this.protocolVersion,
|
||||
channel.pipeline().get(MinecraftEncoder.class).getDirection()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -470,7 +470,11 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
|
||||
}
|
||||
|
||||
MinecraftConnection smc = serverConnection.getConnection();
|
||||
if (smc != null && serverConnection.getPhase().consideredComplete()) {
|
||||
final boolean stateAllowsForward = smc != null
|
||||
&& !smc.isClosed()
|
||||
&& serverConnection.getPhase().consideredComplete()
|
||||
&& smc.getState() == StateRegistry.PLAY;
|
||||
if (stateAllowsForward) {
|
||||
if (packet instanceof PluginMessagePacket) {
|
||||
((PluginMessagePacket) packet).retain();
|
||||
}
|
||||
@@ -487,7 +491,11 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
|
||||
}
|
||||
|
||||
MinecraftConnection smc = serverConnection.getConnection();
|
||||
if (smc != null && !smc.isClosed() && serverConnection.getPhase().consideredComplete()) {
|
||||
final boolean stateAllowsForward = smc != null
|
||||
&& !smc.isClosed()
|
||||
&& serverConnection.getPhase().consideredComplete()
|
||||
&& smc.getState() == StateRegistry.PLAY;
|
||||
if (stateAllowsForward) {
|
||||
smc.write(buf.retain());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1349,11 +1349,17 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
|
||||
final Long sentTime = serverConnection.getPendingPings().remove(packet.getRandomId());
|
||||
if (sentTime != null) {
|
||||
final MinecraftConnection smc = serverConnection.getConnection();
|
||||
if (smc != null) {
|
||||
final StateRegistry clientState = connection.getState();
|
||||
final boolean stateAllowsForward = smc != null
|
||||
&& !smc.isClosed()
|
||||
&& clientState == smc.getState()
|
||||
&& (clientState == StateRegistry.CONFIG || clientState == StateRegistry.PLAY);
|
||||
if (stateAllowsForward) {
|
||||
setPing(TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - sentTime));
|
||||
smc.write(packet);
|
||||
return true;
|
||||
}
|
||||
// We removed this, and so this is ours
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -1363,7 +1369,8 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
|
||||
* Switches the connection to the client into config state.
|
||||
*/
|
||||
public void switchToConfigState() {
|
||||
server.getEventManager().fire(new PlayerEnterConfigurationEvent(this, getConnectionInFlightOrConnectedServer()))
|
||||
final VelocityServerConnection targetServer = getConnectionInFlightOrConnectedServer();
|
||||
server.getEventManager().fire(new PlayerEnterConfigurationEvent(this, targetServer))
|
||||
.completeOnTimeout(null, 5, TimeUnit.SECONDS).thenRunAsync(() -> {
|
||||
// if the connection was closed earlier, there is a risk that the player is no longer connected
|
||||
if (!connection.getChannel().isActive()) {
|
||||
@@ -1378,7 +1385,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
|
||||
connection.pendingConfigurationSwitch = true;
|
||||
connection.getChannel().pipeline().get(MinecraftEncoder.class).setState(StateRegistry.CONFIG);
|
||||
// Make sure we don't send any play packets to the player after update start
|
||||
connection.addPlayPacketQueueHandler();
|
||||
connection.addPlayPacketQueueOutboundHandler();
|
||||
}, connection.eventLoop()).exceptionally((ex) -> {
|
||||
logger.error("Error switching player connection to config state", ex);
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user