Finish up state switching

This commit is contained in:
Nassim Jahnke 2023-08-06 15:40:15 +10:00
parent 39efc5262e
commit 9c92ccea77
2 changed files with 29 additions and 17 deletions

View File

@ -97,13 +97,20 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
registerPackets(); registerPackets();
// Register the rest of the ids with no handlers if necessary // Register handlers for protocol state switching
// TODO Only register one of those handlers, possibly somehow in the base protocol
final SU configurationAcknowledgedPacket = configurationAcknowledgedPacket(); final SU configurationAcknowledgedPacket = configurationAcknowledgedPacket();
if (configurationAcknowledgedPacket != null) { if (configurationAcknowledgedPacket != null) {
// TODO Only register one of those handlers, possibly somehow in the base protocol
registerServerbound(configurationAcknowledgedPacket, wrapper -> wrapper.user().getProtocolInfo().setState(State.CONFIGURATION)); registerServerbound(configurationAcknowledgedPacket, wrapper -> wrapper.user().getProtocolInfo().setState(State.CONFIGURATION));
} }
final ServerboundPacketType finishConfigurationPacket = finishConfigurationPacket();
if (finishConfigurationPacket != null) {
final int id = finishConfigurationPacket.getId();
registerServerbound(State.CONFIGURATION, id, id, wrapper -> wrapper.user().getProtocolInfo().setState(State.PLAY));
}
// Register the rest of the ids with no handlers if necessary
if (unmappedClientboundPacketType != null && mappedClientboundPacketType != null if (unmappedClientboundPacketType != null && mappedClientboundPacketType != null
&& unmappedClientboundPacketType != mappedClientboundPacketType) { && unmappedClientboundPacketType != mappedClientboundPacketType) {
registerPacketIdChanges( registerPacketIdChanges(
@ -221,6 +228,11 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
return packetTypeMap != null ? packetTypeMap.typeByName("CONFIGURATION_ACKNOWLEDGED") : null; return packetTypeMap != null ? packetTypeMap.typeByName("CONFIGURATION_ACKNOWLEDGED") : null;
} }
protected @Nullable ServerboundPacketType finishConfigurationPacket() {
// To be overridden
return null;
}
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
@Override @Override

View File

@ -40,6 +40,7 @@ import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.Serverbou
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.rewriter.BlockItemPacketRewriter1_20_2; import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.rewriter.BlockItemPacketRewriter1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.rewriter.EntityPacketRewriter1_20_2; import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.rewriter.EntityPacketRewriter1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.storage.ConfigurationState; import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.storage.ConfigurationState;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.storage.ConfigurationState.BridgePhase;
import java.util.UUID; import java.util.UUID;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
@ -76,26 +77,27 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
// hence packets are added to a queue. With the data from the login packet, we sent what is needed // hence packets are added to a queue. With the data from the login packet, we sent what is needed
// during the configuration phase before finally transitioning to the play state with the client as well. // during the configuration phase before finally transitioning to the play state with the client as well.
registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE.getId(), ClientboundLoginPackets.GAME_PROFILE.getId(), wrapper -> { registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE.getId(), ClientboundLoginPackets.GAME_PROFILE.getId(), wrapper -> {
wrapper.user().get(ConfigurationState.class).setBridgePhase(ConfigurationState.BridgePhase.PROFILE_SENT); wrapper.user().get(ConfigurationState.class).setBridgePhase(BridgePhase.PROFILE_SENT);
// Set the state according to what the server expects. All packets between now and when the client
// switches to PLAY as well will be discarded after being dealt with.
wrapper.user().getProtocolInfo().setState(State.PLAY);
}); });
registerServerbound(State.LOGIN, ServerboundLoginPackets.LOGIN_ACKNOWLEDGED.getId(), -1, wrapper -> { registerServerbound(State.LOGIN, ServerboundLoginPackets.LOGIN_ACKNOWLEDGED.getId(), -1, wrapper -> {
wrapper.cancel(); wrapper.cancel();
final ConfigurationState configurationState = wrapper.user().get(ConfigurationState.class); final ConfigurationState configurationState = wrapper.user().get(ConfigurationState.class);
configurationState.setBridgePhase(ConfigurationState.BridgePhase.CONFIGURATION); configurationState.setBridgePhase(BridgePhase.CONFIGURATION);
// TODO: ... WE NEED TO SET THE ACTUAL STATE TO CONFIGURATON FOR PROTOCOLS DOWN THE LINE AAAAAAAAAAAAAAA
wrapper.user().getProtocolInfo().setState(State.PLAY);
configurationState.sendQueuedPackets(wrapper.user()); configurationState.sendQueuedPackets(wrapper.user());
}); });
cancelServerbound(State.LOGIN, ServerboundLoginPackets.CUSTOM_QUERY_ANSWER.getId()); cancelServerbound(State.LOGIN, ServerboundLoginPackets.CUSTOM_QUERY_ANSWER.getId());
// TODO Needs baseprotocol logic or something to set to PLAY from the next version onwards
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.FINISH_CONFIGURATION.getId(), -1, wrapper -> { registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.FINISH_CONFIGURATION.getId(), -1, wrapper -> {
wrapper.cancel(); wrapper.cancel();
final ConfigurationState configurationState = wrapper.user().get(ConfigurationState.class); final ConfigurationState configurationState = wrapper.user().get(ConfigurationState.class);
configurationState.setBridgePhase(ConfigurationState.BridgePhase.NONE); configurationState.setBridgePhase(BridgePhase.NONE);
configurationState.sendQueuedPackets(wrapper.user()); configurationState.sendQueuedPackets(wrapper.user());
configurationState.clear(); configurationState.clear();
}); });
@ -120,30 +122,28 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
@Override @Override
public void transform(final Direction direction, final State state, final PacketWrapper packetWrapper) throws Exception { public void transform(final Direction direction, final State state, final PacketWrapper packetWrapper) throws Exception {
final ConfigurationState configurationBridge = packetWrapper.user().get(ConfigurationState.class); final ConfigurationState configurationBridge = packetWrapper.user().get(ConfigurationState.class);
if (configurationBridge.bridgePhase() == ConfigurationState.BridgePhase.NONE) { final BridgePhase phase = configurationBridge.bridgePhase();
if (phase == BridgePhase.NONE) {
super.transform(direction, state, packetWrapper); super.transform(direction, state, packetWrapper);
return; return;
} }
if (direction == Direction.SERVERBOUND) { if (direction == Direction.SERVERBOUND) {
// Client and server might be on two different protocol states - always let the client packets go through // Client and server will be on different protocol states, pick the right client protocol state
// Simply change the processed state if necessary super.transform(direction, phase == BridgePhase.PROFILE_SENT ? State.LOGIN : State.CONFIGURATION, packetWrapper);
super.transform(direction, configurationBridge.bridgePhase() == ConfigurationState.BridgePhase.CONFIGURATION
? State.CONFIGURATION : state, packetWrapper);
return; return;
} }
if (phase == BridgePhase.PROFILE_SENT) {
// Queue packets sent by the server while we wait for the client to transition to the configuration state // Queue packets sent by the server while we wait for the client to transition to the configuration state
if (configurationBridge.bridgePhase() == ConfigurationState.BridgePhase.PROFILE_SENT) {
configurationBridge.addPacketToQueue(packetWrapper, true); configurationBridge.addPacketToQueue(packetWrapper, true);
throw CancelException.generate(); throw CancelException.generate();
} }
// Map some of them to their configuration state counterparts, but make sure to late join game through
if (packetWrapper.getPacketType() == null || packetWrapper.getPacketType().state() != State.CONFIGURATION) { if (packetWrapper.getPacketType() == null || packetWrapper.getPacketType().state() != State.CONFIGURATION) {
// Map some of them to their configuration state counterparts, but make sure to let join game through
final int unmappedId = packetWrapper.getId(); final int unmappedId = packetWrapper.getId();
if (unmappedId == ClientboundPackets1_19_4.JOIN_GAME.getId()) { if (unmappedId == ClientboundPackets1_19_4.JOIN_GAME.getId()) {
// Make sure we handle the start of the play phase correctly
super.transform(direction, state, packetWrapper); super.transform(direction, state, packetWrapper);
return; return;
} }