3
0
Mirror von https://github.com/PaperMC/Velocity.git synchronisiert 2024-09-29 06:30:16 +02:00

Several improvements and fixes for 1.20.2 (#1097)

* Send LoginAcknowledged immediately

* Resend player list header/footer after backend server switched to config state

* Fix clearHeaderAndFooter not clearing fields in ConnectedPlayer

* Clear boss bars, header/footer, tab list when switching client to config state

* Send client settings in config state
Dieser Commit ist enthalten in:
Gero 2023-10-12 11:11:47 +02:00 committet von GitHub
Ursprung 9be0bca3c4
Commit 1cc3f120ee
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 4AEE18F83AFDEB23
10 geänderte Dateien mit 72 neuen und 36 gelöschten Zeilen

Datei anzeigen

@ -31,7 +31,6 @@ import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.event.HoverEventSource; import net.kyori.adventure.text.event.HoverEventSource;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
/** /**
@ -148,10 +147,17 @@ public interface Player extends
/** /**
* Clears the tab list header and footer for the player. * Clears the tab list header and footer for the player.
* *
* @deprecated Use {@link TabList#clearHeaderAndFooter()}. * @deprecated Use {@link Player#clearPlayerListHeaderAndFooter()}.
*/ */
@Deprecated @Deprecated
void clearHeaderAndFooter(); default void clearHeaderAndFooter() {
clearPlayerListHeaderAndFooter();
}
/**
* Clears the player list header and footer.
*/
void clearPlayerListHeaderAndFooter();
/** /**
* Returns the player's player list header. * Returns the player's player list header.

Datei anzeigen

@ -24,6 +24,7 @@ import com.velocitypowered.proxy.VelocityServer;
import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler; import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.connection.client.ClientConfigSessionHandler; import com.velocitypowered.proxy.connection.client.ClientConfigSessionHandler;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.connection.player.VelocityResourcePackInfo; import com.velocitypowered.proxy.connection.player.VelocityResourcePackInfo;
import com.velocitypowered.proxy.connection.util.ConnectionMessages; import com.velocitypowered.proxy.connection.util.ConnectionMessages;
import com.velocitypowered.proxy.connection.util.ConnectionRequestResults; import com.velocitypowered.proxy.connection.util.ConnectionRequestResults;
@ -152,22 +153,26 @@ public class ConfigSessionHandler implements MinecraftSessionHandler {
@Override @Override
public boolean handle(FinishedUpdate packet) { public boolean handle(FinishedUpdate packet) {
MinecraftConnection smc = serverConn.ensureConnected(); MinecraftConnection smc = serverConn.ensureConnected();
ConnectedPlayer player = serverConn.getPlayer();
ClientConfigSessionHandler configHandler = ClientConfigSessionHandler configHandler =
(ClientConfigSessionHandler) serverConn.getPlayer().getConnection() (ClientConfigSessionHandler) player.getConnection().getActiveSessionHandler();
.getActiveSessionHandler();
smc.setAutoReading(false); smc.setAutoReading(false);
// Even when not auto reading messages are still decoded. Decode them with the correct state // Even when not auto reading messages are still decoded. Decode them with the correct state
smc.getChannel().pipeline().get(MinecraftDecoder.class).setState(StateRegistry.PLAY); smc.getChannel().pipeline().get(MinecraftDecoder.class).setState(StateRegistry.PLAY);
configHandler.handleBackendFinishUpdate(serverConn).thenAcceptAsync((unused) -> { configHandler.handleBackendFinishUpdate(serverConn).thenAcceptAsync((unused) -> {
if (serverConn == serverConn.getPlayer().getConnectedServer()) { if (serverConn == player.getConnectedServer()) {
smc.setActiveSessionHandler(StateRegistry.PLAY); smc.setActiveSessionHandler(StateRegistry.PLAY);
player.sendPlayerListHeaderAndFooter(
player.getPlayerListHeader(), player.getPlayerListFooter());
// The client cleared the tab list. TODO: Restore changes done via TabList API
player.getTabList().clearAllSilent();
} else { } else {
smc.setActiveSessionHandler(StateRegistry.PLAY, smc.setActiveSessionHandler(StateRegistry.PLAY,
new TransitionSessionHandler(server, serverConn, resultFuture)); new TransitionSessionHandler(server, serverConn, resultFuture));
} }
if (serverConn.getPlayer().getAppliedResourcePack() == null && resourcePackToApply != null) { if (player.getAppliedResourcePack() == null && resourcePackToApply != null) {
serverConn.getPlayer().queueResourcePack(resourcePackToApply); player.queueResourcePack(resourcePackToApply);
} }
smc.setAutoReading(true); smc.setAutoReading(true);
}, smc.eventLoop()); }, smc.eventLoop());

Datei anzeigen

@ -156,22 +156,20 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
smc.setActiveSessionHandler(StateRegistry.PLAY, smc.setActiveSessionHandler(StateRegistry.PLAY,
new TransitionSessionHandler(server, serverConn, resultFuture)); new TransitionSessionHandler(server, serverConn, resultFuture));
} else { } else {
smc.setAutoReading(false); smc.write(new LoginAcknowledged());
CompletableFuture<Void> switchFuture; smc.setActiveSessionHandler(StateRegistry.CONFIG,
if (serverConn.getPlayer().getConnection() new ConfigSessionHandler(server, serverConn, resultFuture));
.getActiveSessionHandler() instanceof ClientPlaySessionHandler) { ConnectedPlayer player = serverConn.getPlayer();
switchFuture = ((ClientPlaySessionHandler) serverConn.getPlayer().getConnection() if (player.getClientSettingsPacket() != null) {
.getActiveSessionHandler()).doSwitch(); smc.write(player.getClientSettingsPacket());
} else { }
switchFuture = CompletableFuture.completedFuture(null); if (player.getConnection().getActiveSessionHandler() instanceof ClientPlaySessionHandler) {
smc.setAutoReading(false);
((ClientPlaySessionHandler) player.getConnection()
.getActiveSessionHandler()).doSwitch().thenAcceptAsync((unused) -> {
smc.setAutoReading(true);
}, smc.eventLoop());
} }
switchFuture.thenAcceptAsync((unused) -> {
smc.write(new LoginAcknowledged());
// Sync backend
smc.setActiveSessionHandler(StateRegistry.CONFIG,
new ConfigSessionHandler(server, serverConn, resultFuture));
smc.setAutoReading(true);
}, smc.eventLoop());
} }
return true; return true;

Datei anzeigen

@ -22,6 +22,7 @@ import static com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeHands
import com.velocitypowered.api.event.player.ServerConnectedEvent; import com.velocitypowered.api.event.player.ServerConnectedEvent;
import com.velocitypowered.api.event.player.ServerPostConnectEvent; import com.velocitypowered.api.event.player.ServerPostConnectEvent;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.api.proxy.server.RegisteredServer; import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.VelocityServer;
import com.velocitypowered.proxy.connection.ConnectionTypes; import com.velocitypowered.proxy.connection.ConnectionTypes;
@ -104,7 +105,7 @@ public class TransitionSessionHandler implements MinecraftSessionHandler {
player.sendKeepAlive(); player.sendKeepAlive();
// Reset Tablist header and footer to prevent desync // Reset Tablist header and footer to prevent desync
player.clearHeaderAndFooter(); player.clearPlayerListHeaderAndFooter();
} }
// The goods are in hand! We got JoinGame. Let's transition completely to the new state. // The goods are in hand! We got JoinGame. Let's transition completely to the new state.
@ -143,7 +144,9 @@ public class TransitionSessionHandler implements MinecraftSessionHandler {
// Now set the connected server. // Now set the connected server.
serverConn.getPlayer().setConnectedServer(serverConn); serverConn.getPlayer().setConnectedServer(serverConn);
if (player.getClientSettingsPacket() != null) { // Send client settings. In 1.20.2+ this is done in the config state.
if (smc.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_20_2) < 0
&& player.getClientSettingsPacket() != null) {
serverConn.ensureConnected().write(player.getClientSettingsPacket()); serverConn.ensureConnected().write(player.getClientSettingsPacket());
} }

Datei anzeigen

@ -482,12 +482,13 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
// Send keep alive to try to avoid timeouts // Send keep alive to try to avoid timeouts
player.sendKeepAlive(); player.sendKeepAlive();
// Reset Tablist header and footer to prevent desync // Config state clears everything in the client. No need to clear later.
player.clearHeaderAndFooter(); spawned = false;
serverBossBars.clear();
player.clearPlayerListHeaderAndFooterSilent();
player.getTabList().clearAllSilent();
} }
spawned = false;
player.switchToConfigState(); player.switchToConfigState();
return configSwitchFuture; return configSwitchFuture;

Datei anzeigen

@ -544,8 +544,16 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
} }
@Override @Override
public void clearHeaderAndFooter() { public void clearPlayerListHeaderAndFooter() {
tabList.clearHeaderAndFooter(); clearPlayerListHeaderAndFooterSilent();
if (this.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) {
this.connection.write(HeaderAndFooter.reset());
}
}
public void clearPlayerListHeaderAndFooterSilent() {
this.playerListHeader = Component.empty();
this.playerListFooter = Component.empty();
} }
@Override @Override

Datei anzeigen

@ -35,4 +35,6 @@ public interface InternalTabList extends TabList {
default void processRemove(RemovePlayerInfo infoPacket) { default void processRemove(RemovePlayerInfo infoPacket) {
} }
void clearAllSilent();
} }

Datei anzeigen

@ -26,7 +26,6 @@ import com.velocitypowered.api.proxy.player.TabListEntry;
import com.velocitypowered.api.util.GameProfile; import com.velocitypowered.api.util.GameProfile;
import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer; import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.protocol.packet.HeaderAndFooter;
import com.velocitypowered.proxy.protocol.packet.LegacyPlayerListItem; import com.velocitypowered.proxy.protocol.packet.LegacyPlayerListItem;
import com.velocitypowered.proxy.protocol.packet.chat.RemoteChatSession; import com.velocitypowered.proxy.protocol.packet.chat.RemoteChatSession;
import java.util.ArrayList; import java.util.ArrayList;
@ -70,7 +69,7 @@ public class KeyedVelocityTabList implements InternalTabList {
@Override @Override
public void clearHeaderAndFooter() { public void clearHeaderAndFooter() {
connection.write(HeaderAndFooter.reset()); this.player.clearPlayerListHeaderAndFooter();
} }
@Override @Override
@ -131,10 +130,15 @@ public class KeyedVelocityTabList implements InternalTabList {
for (TabListEntry value : listEntries) { for (TabListEntry value : listEntries) {
items.add(LegacyPlayerListItem.Item.from(value)); items.add(LegacyPlayerListItem.Item.from(value));
} }
entries.clear(); clearAllSilent();
connection.delayedWrite(new LegacyPlayerListItem(LegacyPlayerListItem.REMOVE_PLAYER, items)); connection.delayedWrite(new LegacyPlayerListItem(LegacyPlayerListItem.REMOVE_PLAYER, items));
} }
@Override
public void clearAllSilent() {
entries.clear();
}
@Override @Override
public Collection<TabListEntry> getEntries() { public Collection<TabListEntry> getEntries() {
return Collections.unmodifiableCollection(this.entries.values()); return Collections.unmodifiableCollection(this.entries.values());

Datei anzeigen

@ -25,7 +25,6 @@ import com.velocitypowered.api.util.GameProfile;
import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer; import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.console.VelocityConsole; import com.velocitypowered.proxy.console.VelocityConsole;
import com.velocitypowered.proxy.protocol.packet.HeaderAndFooter;
import com.velocitypowered.proxy.protocol.packet.RemovePlayerInfo; import com.velocitypowered.proxy.protocol.packet.RemovePlayerInfo;
import com.velocitypowered.proxy.protocol.packet.UpsertPlayerInfo; import com.velocitypowered.proxy.protocol.packet.UpsertPlayerInfo;
import com.velocitypowered.proxy.protocol.packet.chat.RemoteChatSession; import com.velocitypowered.proxy.protocol.packet.chat.RemoteChatSession;
@ -74,7 +73,7 @@ public class VelocityTabList implements InternalTabList {
@Override @Override
public void clearHeaderAndFooter() { public void clearHeaderAndFooter() {
connection.write(HeaderAndFooter.reset()); this.player.clearPlayerListHeaderAndFooter();
} }
@Override @Override
@ -175,6 +174,11 @@ public class VelocityTabList implements InternalTabList {
@Override @Override
public void clearAll() { public void clearAll() {
this.connection.delayedWrite(new RemovePlayerInfo(new ArrayList<>(this.entries.keySet()))); this.connection.delayedWrite(new RemovePlayerInfo(new ArrayList<>(this.entries.keySet())));
clearAllSilent();
}
@Override
public void clearAllSilent() {
this.entries.clear(); this.entries.clear();
} }

Datei anzeigen

@ -71,6 +71,11 @@ public class VelocityTabListLegacy extends KeyedVelocityTabList {
connection.delayedWrite(new LegacyPlayerListItem(LegacyPlayerListItem.REMOVE_PLAYER, connection.delayedWrite(new LegacyPlayerListItem(LegacyPlayerListItem.REMOVE_PLAYER,
Collections.singletonList(LegacyPlayerListItem.Item.from(value)))); Collections.singletonList(LegacyPlayerListItem.Item.from(value))));
} }
clearAllSilent();
}
@Override
public void clearAllSilent() {
entries.clear(); entries.clear();
nameMapping.clear(); nameMapping.clear();
} }