geforkt von Mirrors/Velocity
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:
Ursprung
9be0bca3c4
Commit
1cc3f120ee
@ -31,7 +31,6 @@ import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.event.HoverEventSource;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@ -148,10 +147,17 @@ public interface Player extends
|
||||
/**
|
||||
* Clears the tab list header and footer for the player.
|
||||
*
|
||||
* @deprecated Use {@link TabList#clearHeaderAndFooter()}.
|
||||
* @deprecated Use {@link Player#clearPlayerListHeaderAndFooter()}.
|
||||
*/
|
||||
@Deprecated
|
||||
void clearHeaderAndFooter();
|
||||
default void clearHeaderAndFooter() {
|
||||
clearPlayerListHeaderAndFooter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the player list header and footer.
|
||||
*/
|
||||
void clearPlayerListHeaderAndFooter();
|
||||
|
||||
/**
|
||||
* Returns the player's player list header.
|
||||
|
@ -24,6 +24,7 @@ import com.velocitypowered.proxy.VelocityServer;
|
||||
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||
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.util.ConnectionMessages;
|
||||
import com.velocitypowered.proxy.connection.util.ConnectionRequestResults;
|
||||
@ -152,22 +153,26 @@ public class ConfigSessionHandler implements MinecraftSessionHandler {
|
||||
@Override
|
||||
public boolean handle(FinishedUpdate packet) {
|
||||
MinecraftConnection smc = serverConn.ensureConnected();
|
||||
ConnectedPlayer player = serverConn.getPlayer();
|
||||
ClientConfigSessionHandler configHandler =
|
||||
(ClientConfigSessionHandler) serverConn.getPlayer().getConnection()
|
||||
.getActiveSessionHandler();
|
||||
(ClientConfigSessionHandler) player.getConnection().getActiveSessionHandler();
|
||||
|
||||
smc.setAutoReading(false);
|
||||
// Even when not auto reading messages are still decoded. Decode them with the correct state
|
||||
smc.getChannel().pipeline().get(MinecraftDecoder.class).setState(StateRegistry.PLAY);
|
||||
configHandler.handleBackendFinishUpdate(serverConn).thenAcceptAsync((unused) -> {
|
||||
if (serverConn == serverConn.getPlayer().getConnectedServer()) {
|
||||
if (serverConn == player.getConnectedServer()) {
|
||||
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 {
|
||||
smc.setActiveSessionHandler(StateRegistry.PLAY,
|
||||
new TransitionSessionHandler(server, serverConn, resultFuture));
|
||||
}
|
||||
if (serverConn.getPlayer().getAppliedResourcePack() == null && resourcePackToApply != null) {
|
||||
serverConn.getPlayer().queueResourcePack(resourcePackToApply);
|
||||
if (player.getAppliedResourcePack() == null && resourcePackToApply != null) {
|
||||
player.queueResourcePack(resourcePackToApply);
|
||||
}
|
||||
smc.setAutoReading(true);
|
||||
}, smc.eventLoop());
|
||||
|
@ -156,22 +156,20 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
||||
smc.setActiveSessionHandler(StateRegistry.PLAY,
|
||||
new TransitionSessionHandler(server, serverConn, resultFuture));
|
||||
} else {
|
||||
smc.setAutoReading(false);
|
||||
CompletableFuture<Void> switchFuture;
|
||||
if (serverConn.getPlayer().getConnection()
|
||||
.getActiveSessionHandler() instanceof ClientPlaySessionHandler) {
|
||||
switchFuture = ((ClientPlaySessionHandler) serverConn.getPlayer().getConnection()
|
||||
.getActiveSessionHandler()).doSwitch();
|
||||
} else {
|
||||
switchFuture = CompletableFuture.completedFuture(null);
|
||||
smc.write(new LoginAcknowledged());
|
||||
smc.setActiveSessionHandler(StateRegistry.CONFIG,
|
||||
new ConfigSessionHandler(server, serverConn, resultFuture));
|
||||
ConnectedPlayer player = serverConn.getPlayer();
|
||||
if (player.getClientSettingsPacket() != null) {
|
||||
smc.write(player.getClientSettingsPacket());
|
||||
}
|
||||
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;
|
||||
|
@ -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.ServerPostConnectEvent;
|
||||
import com.velocitypowered.api.network.ProtocolVersion;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.proxy.VelocityServer;
|
||||
import com.velocitypowered.proxy.connection.ConnectionTypes;
|
||||
@ -104,7 +105,7 @@ public class TransitionSessionHandler implements MinecraftSessionHandler {
|
||||
player.sendKeepAlive();
|
||||
|
||||
// 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.
|
||||
@ -143,7 +144,9 @@ public class TransitionSessionHandler implements MinecraftSessionHandler {
|
||||
// Now set the connected server.
|
||||
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());
|
||||
}
|
||||
|
||||
|
@ -482,12 +482,13 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
|
||||
// Send keep alive to try to avoid timeouts
|
||||
player.sendKeepAlive();
|
||||
|
||||
// Reset Tablist header and footer to prevent desync
|
||||
player.clearHeaderAndFooter();
|
||||
// Config state clears everything in the client. No need to clear later.
|
||||
spawned = false;
|
||||
serverBossBars.clear();
|
||||
player.clearPlayerListHeaderAndFooterSilent();
|
||||
player.getTabList().clearAllSilent();
|
||||
}
|
||||
|
||||
spawned = false;
|
||||
|
||||
player.switchToConfigState();
|
||||
|
||||
return configSwitchFuture;
|
||||
|
@ -544,8 +544,16 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearHeaderAndFooter() {
|
||||
tabList.clearHeaderAndFooter();
|
||||
public void clearPlayerListHeaderAndFooter() {
|
||||
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
|
||||
|
@ -35,4 +35,6 @@ public interface InternalTabList extends TabList {
|
||||
|
||||
default void processRemove(RemovePlayerInfo infoPacket) {
|
||||
}
|
||||
|
||||
void clearAllSilent();
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ import com.velocitypowered.api.proxy.player.TabListEntry;
|
||||
import com.velocitypowered.api.util.GameProfile;
|
||||
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
||||
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.chat.RemoteChatSession;
|
||||
import java.util.ArrayList;
|
||||
@ -70,7 +69,7 @@ public class KeyedVelocityTabList implements InternalTabList {
|
||||
|
||||
@Override
|
||||
public void clearHeaderAndFooter() {
|
||||
connection.write(HeaderAndFooter.reset());
|
||||
this.player.clearPlayerListHeaderAndFooter();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -131,10 +130,15 @@ public class KeyedVelocityTabList implements InternalTabList {
|
||||
for (TabListEntry value : listEntries) {
|
||||
items.add(LegacyPlayerListItem.Item.from(value));
|
||||
}
|
||||
entries.clear();
|
||||
clearAllSilent();
|
||||
connection.delayedWrite(new LegacyPlayerListItem(LegacyPlayerListItem.REMOVE_PLAYER, items));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAllSilent() {
|
||||
entries.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<TabListEntry> getEntries() {
|
||||
return Collections.unmodifiableCollection(this.entries.values());
|
||||
|
@ -25,7 +25,6 @@ import com.velocitypowered.api.util.GameProfile;
|
||||
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
||||
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
||||
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.UpsertPlayerInfo;
|
||||
import com.velocitypowered.proxy.protocol.packet.chat.RemoteChatSession;
|
||||
@ -74,7 +73,7 @@ public class VelocityTabList implements InternalTabList {
|
||||
|
||||
@Override
|
||||
public void clearHeaderAndFooter() {
|
||||
connection.write(HeaderAndFooter.reset());
|
||||
this.player.clearPlayerListHeaderAndFooter();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -175,6 +174,11 @@ public class VelocityTabList implements InternalTabList {
|
||||
@Override
|
||||
public void clearAll() {
|
||||
this.connection.delayedWrite(new RemovePlayerInfo(new ArrayList<>(this.entries.keySet())));
|
||||
clearAllSilent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAllSilent() {
|
||||
this.entries.clear();
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,11 @@ public class VelocityTabListLegacy extends KeyedVelocityTabList {
|
||||
connection.delayedWrite(new LegacyPlayerListItem(LegacyPlayerListItem.REMOVE_PLAYER,
|
||||
Collections.singletonList(LegacyPlayerListItem.Item.from(value))));
|
||||
}
|
||||
clearAllSilent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAllSilent() {
|
||||
entries.clear();
|
||||
nameMapping.clear();
|
||||
}
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren