Mirror von
https://github.com/ViaVersion/ViaVersion.git
synchronisiert 2024-12-28 09:00:09 +01:00
Add separate client and server protocol state
Dieser Commit ist enthalten in:
Ursprung
d92b9fdeaa
Commit
854696abff
@ -23,6 +23,7 @@
|
|||||||
package com.viaversion.viaversion.api.connection;
|
package com.viaversion.viaversion.api.connection;
|
||||||
|
|
||||||
import com.viaversion.viaversion.api.protocol.ProtocolPipeline;
|
import com.viaversion.viaversion.api.protocol.ProtocolPipeline;
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.Direction;
|
||||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
@ -33,10 +34,63 @@ public interface ProtocolInfo {
|
|||||||
* Returns the protocol state the user is currently in.
|
* Returns the protocol state the user is currently in.
|
||||||
*
|
*
|
||||||
* @return protocol state
|
* @return protocol state
|
||||||
|
* @deprecated server and client can be in different states, use {@link #getClientState()} or {@link #getServerState()}
|
||||||
*/
|
*/
|
||||||
State getState();
|
@Deprecated/*(forRemoval = true)*/
|
||||||
|
default State getState() {
|
||||||
|
return this.getServerState();
|
||||||
|
}
|
||||||
|
|
||||||
void setState(State state);
|
/**
|
||||||
|
* Returns the protocol state the client is currently in.
|
||||||
|
*
|
||||||
|
* @return the client protocol state
|
||||||
|
*/
|
||||||
|
State getClientState();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the protocol state the server is currently in.
|
||||||
|
*
|
||||||
|
* @return the server protocol state
|
||||||
|
*/
|
||||||
|
State getServerState();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the protocol state for the given direction.
|
||||||
|
*
|
||||||
|
* @param direction protocol direction
|
||||||
|
* @return state for the given direction
|
||||||
|
*/
|
||||||
|
default State getState(final Direction direction) {
|
||||||
|
// Return the state the packet is coming from
|
||||||
|
return direction == Direction.CLIENTBOUND ? this.getServerState() : this.getClientState();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets both client and server state.
|
||||||
|
*
|
||||||
|
* @param state the new protocol state
|
||||||
|
* @see #setClientState(State)
|
||||||
|
* @see #setServerState(State)
|
||||||
|
*/
|
||||||
|
default void setState(final State state) {
|
||||||
|
this.setClientState(state);
|
||||||
|
this.setServerState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the client protocol state.
|
||||||
|
*
|
||||||
|
* @param clientState the new client protocol state
|
||||||
|
*/
|
||||||
|
void setClientState(State clientState);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the server protocol state.
|
||||||
|
*
|
||||||
|
* @param serverState the new server protocol state
|
||||||
|
*/
|
||||||
|
void setServerState(State serverState);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the user's protocol version, or -1 if not set.
|
* Returns the user's protocol version, or -1 if not set.
|
||||||
|
@ -96,19 +96,7 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
|
|||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
registerPackets();
|
registerPackets();
|
||||||
|
registerConfigurationChangeHandlers();
|
||||||
// Register handlers for protocol state switching
|
|
||||||
// TODO Only register one of those handlers, possibly somehow in the base protocol
|
|
||||||
final SU configurationAcknowledgedPacket = configurationAcknowledgedPacket();
|
|
||||||
if (configurationAcknowledgedPacket != null) {
|
|
||||||
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
|
// Register the rest of the ids with no handlers if necessary
|
||||||
if (unmappedClientboundPacketType != null && mappedClientboundPacketType != null
|
if (unmappedClientboundPacketType != null && mappedClientboundPacketType != null
|
||||||
@ -131,6 +119,33 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void registerConfigurationChangeHandlers() {
|
||||||
|
// Register handlers for protocol state switching
|
||||||
|
// Assuming ids will change too often, it is cleaner to register them here instead of the base protocols,
|
||||||
|
// even if there will be multiple of these handlers
|
||||||
|
final SU configurationAcknowledgedPacket = configurationAcknowledgedPacket();
|
||||||
|
if (configurationAcknowledgedPacket != null) {
|
||||||
|
registerServerbound(configurationAcknowledgedPacket, setClientStateHandler(State.CONFIGURATION));
|
||||||
|
}
|
||||||
|
|
||||||
|
final CU startConfigurationPacket = startConfigurationPacket();
|
||||||
|
if (startConfigurationPacket != null) {
|
||||||
|
registerClientbound(startConfigurationPacket, setServerStateHandler(State.CONFIGURATION));
|
||||||
|
}
|
||||||
|
|
||||||
|
final ServerboundPacketType finishConfigurationPacket = serverboundFinishConfigurationPacket();
|
||||||
|
if (finishConfigurationPacket != null) {
|
||||||
|
final int id = finishConfigurationPacket.getId();
|
||||||
|
registerServerbound(State.CONFIGURATION, id, id, setClientStateHandler(State.PLAY));
|
||||||
|
}
|
||||||
|
|
||||||
|
final ClientboundPacketType clientboundFinishConfigurationPacket = clientboundFinishConfigurationPacket();
|
||||||
|
if (clientboundFinishConfigurationPacket != null) {
|
||||||
|
final int id = clientboundFinishConfigurationPacket.getId();
|
||||||
|
registerClientbound(State.CONFIGURATION, id, id, setServerStateHandler(State.PLAY));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private <U extends PacketType, M extends PacketType> void registerPacketIdChanges(
|
private <U extends PacketType, M extends PacketType> void registerPacketIdChanges(
|
||||||
Map<State, PacketTypeMap<U>> unmappedPacketTypes,
|
Map<State, PacketTypeMap<U>> unmappedPacketTypes,
|
||||||
Map<State, PacketTypeMap<M>> mappedPacketTypes,
|
Map<State, PacketTypeMap<M>> mappedPacketTypes,
|
||||||
@ -228,7 +243,18 @@ 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() {
|
protected @Nullable CU startConfigurationPacket() {
|
||||||
|
final Map<State, PacketTypeMap<CU>> packetTypes = packetTypesProvider.unmappedClientboundPacketTypes();
|
||||||
|
final PacketTypeMap<CU> packetTypeMap = packetTypes.get(State.PLAY);
|
||||||
|
return packetTypeMap != null ? packetTypeMap.typeByName("START_CONFIGURATION") : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected @Nullable ServerboundPacketType serverboundFinishConfigurationPacket() {
|
||||||
|
// To be overridden
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected @Nullable ClientboundPacketType clientboundFinishConfigurationPacket() {
|
||||||
// To be overridden
|
// To be overridden
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -429,6 +455,14 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected PacketHandler setClientStateHandler(final State state) {
|
||||||
|
return wrapper -> wrapper.user().getProtocolInfo().setClientState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PacketHandler setServerStateHandler(final State state) {
|
||||||
|
return wrapper -> wrapper.user().getProtocolInfo().setClientState(state);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PacketTypesProvider<CU, CM, SM, SU> getPacketTypesProvider() {
|
public PacketTypesProvider<CU, CM, SM, SU> getPacketTypesProvider() {
|
||||||
return packetTypesProvider;
|
return packetTypesProvider;
|
||||||
|
@ -73,6 +73,8 @@ public interface ProtocolPipeline extends SimpleProtocol {
|
|||||||
*/
|
*/
|
||||||
List<Protocol> pipes();
|
List<Protocol> pipes();
|
||||||
|
|
||||||
|
List<Protocol> reversedPipes();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether this pipe has protocols that are not base protocols, as given by {@link Protocol#isBaseProtocol()}.
|
* Returns whether this pipe has protocols that are not base protocols, as given by {@link Protocol#isBaseProtocol()}.
|
||||||
*
|
*
|
||||||
|
@ -27,6 +27,6 @@ public enum State {
|
|||||||
HANDSHAKE,
|
HANDSHAKE,
|
||||||
STATUS,
|
STATUS,
|
||||||
LOGIN,
|
LOGIN,
|
||||||
PLAY,
|
CONFIGURATION,
|
||||||
CONFIGURATION
|
PLAY
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.viaversion.viaversion.connection;
|
package com.viaversion.viaversion.connection;
|
||||||
|
|
||||||
|
import com.viaversion.viaversion.api.Via;
|
||||||
import com.viaversion.viaversion.api.connection.ProtocolInfo;
|
import com.viaversion.viaversion.api.connection.ProtocolInfo;
|
||||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||||
import com.viaversion.viaversion.api.protocol.ProtocolPipeline;
|
import com.viaversion.viaversion.api.protocol.ProtocolPipeline;
|
||||||
@ -26,25 +27,42 @@ import java.util.UUID;
|
|||||||
|
|
||||||
public class ProtocolInfoImpl implements ProtocolInfo {
|
public class ProtocolInfoImpl implements ProtocolInfo {
|
||||||
private final UserConnection connection;
|
private final UserConnection connection;
|
||||||
private State state = State.HANDSHAKE;
|
private State clientState = State.HANDSHAKE;
|
||||||
|
private State serverState = State.HANDSHAKE;
|
||||||
private int protocolVersion = -1;
|
private int protocolVersion = -1;
|
||||||
private int serverProtocolVersion = -1;
|
private int serverProtocolVersion = -1;
|
||||||
private String username;
|
private String username;
|
||||||
private UUID uuid;
|
private UUID uuid;
|
||||||
private ProtocolPipeline pipeline;
|
private ProtocolPipeline pipeline;
|
||||||
|
|
||||||
public ProtocolInfoImpl(UserConnection connection) {
|
public ProtocolInfoImpl(final UserConnection connection) {
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public State getState() {
|
public State getClientState() {
|
||||||
return state;
|
return clientState;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setState(State state) {
|
public void setClientState(final State clientState) {
|
||||||
this.state = state;
|
if (Via.getManager().debugHandler().enabled()) {
|
||||||
|
Via.getPlatform().getLogger().info("Client state changed from " + this.clientState + " to " + clientState + " for " + connection.getProtocolInfo().getUuid());
|
||||||
|
}
|
||||||
|
this.clientState = clientState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public State getServerState() {
|
||||||
|
return serverState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setServerState(final State serverState) {
|
||||||
|
if (Via.getManager().debugHandler().enabled()) {
|
||||||
|
Via.getPlatform().getLogger().info("Server state changed from " + this.serverState + " to " + serverState + " for " + connection.getProtocolInfo().getUuid());
|
||||||
|
}
|
||||||
|
this.serverState = serverState;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -108,7 +126,8 @@ public class ProtocolInfoImpl implements ProtocolInfo {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ProtocolInfo{" +
|
return "ProtocolInfo{" +
|
||||||
"state=" + state +
|
"clientState=" + clientState +
|
||||||
|
", serverState=" + serverState +
|
||||||
", protocolVersion=" + protocolVersion +
|
", protocolVersion=" + protocolVersion +
|
||||||
", serverProtocolVersion=" + serverProtocolVersion +
|
", serverProtocolVersion=" + serverProtocolVersion +
|
||||||
", username='" + username + '\'' +
|
", username='" + username + '\'' +
|
||||||
|
@ -27,6 +27,7 @@ import com.viaversion.viaversion.api.protocol.Protocol;
|
|||||||
import com.viaversion.viaversion.api.protocol.packet.Direction;
|
import com.viaversion.viaversion.api.protocol.packet.Direction;
|
||||||
import com.viaversion.viaversion.api.protocol.packet.PacketTracker;
|
import com.viaversion.viaversion.api.protocol.packet.PacketTracker;
|
||||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||||
import com.viaversion.viaversion.api.type.Type;
|
import com.viaversion.viaversion.api.type.Type;
|
||||||
import com.viaversion.viaversion.exception.CancelException;
|
import com.viaversion.viaversion.exception.CancelException;
|
||||||
import com.viaversion.viaversion.protocol.packet.PacketWrapperImpl;
|
import com.viaversion.viaversion.protocol.packet.PacketWrapperImpl;
|
||||||
@ -324,8 +325,9 @@ public class UserConnectionImpl implements UserConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PacketWrapper wrapper = new PacketWrapperImpl(id, buf, this);
|
PacketWrapper wrapper = new PacketWrapperImpl(id, buf, this);
|
||||||
|
State state = protocolInfo.getState(direction);
|
||||||
try {
|
try {
|
||||||
protocolInfo.getPipeline().transform(direction, protocolInfo.getState(), wrapper);
|
protocolInfo.getPipeline().transform(direction, state, wrapper);
|
||||||
} catch (CancelException ex) {
|
} catch (CancelException ex) {
|
||||||
throw cancelSupplier.apply(ex);
|
throw cancelSupplier.apply(ex);
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
|||||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
@ -43,6 +44,7 @@ public class ProtocolPipelineImpl extends AbstractSimpleProtocol implements Prot
|
|||||||
* Protocol list ordered from client to server transforation with the base protocols at the end.
|
* Protocol list ordered from client to server transforation with the base protocols at the end.
|
||||||
*/
|
*/
|
||||||
private List<Protocol> protocolList;
|
private List<Protocol> protocolList;
|
||||||
|
private List<Protocol> reversedProtocolList;
|
||||||
private Set<Class<? extends Protocol>> protocolSet;
|
private Set<Class<? extends Protocol>> protocolSet;
|
||||||
|
|
||||||
public ProtocolPipelineImpl(UserConnection userConnection) {
|
public ProtocolPipelineImpl(UserConnection userConnection) {
|
||||||
@ -54,12 +56,14 @@ public class ProtocolPipelineImpl extends AbstractSimpleProtocol implements Prot
|
|||||||
@Override
|
@Override
|
||||||
protected void registerPackets() {
|
protected void registerPackets() {
|
||||||
protocolList = new CopyOnWriteArrayList<>();
|
protocolList = new CopyOnWriteArrayList<>();
|
||||||
|
reversedProtocolList = new CopyOnWriteArrayList<>();
|
||||||
// Create a backing set for faster contains calls with larger pipes
|
// Create a backing set for faster contains calls with larger pipes
|
||||||
protocolSet = Sets.newSetFromMap(new ConcurrentHashMap<>());
|
protocolSet = Sets.newSetFromMap(new ConcurrentHashMap<>());
|
||||||
|
|
||||||
// This is a pipeline so we register basic pipes
|
// This is a pipeline so we register basic pipes
|
||||||
Protocol baseProtocol = Via.getManager().getProtocolManager().getBaseProtocol();
|
final Protocol<?, ?, ?, ?> baseProtocol = Via.getManager().getProtocolManager().getBaseProtocol();
|
||||||
protocolList.add(baseProtocol);
|
protocolList.add(baseProtocol);
|
||||||
|
reversedProtocolList.add(baseProtocol);
|
||||||
protocolSet.add(baseProtocol.getClass());
|
protocolSet.add(baseProtocol.getClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,12 +75,22 @@ public class ProtocolPipelineImpl extends AbstractSimpleProtocol implements Prot
|
|||||||
@Override
|
@Override
|
||||||
public void add(Protocol protocol) {
|
public void add(Protocol protocol) {
|
||||||
protocolList.add(protocol);
|
protocolList.add(protocol);
|
||||||
|
|
||||||
protocolSet.add(protocol.getClass());
|
protocolSet.add(protocol.getClass());
|
||||||
protocol.init(userConnection);
|
protocol.init(userConnection);
|
||||||
|
|
||||||
if (!protocol.isBaseProtocol()) {
|
if (!protocol.isBaseProtocol()) {
|
||||||
moveBaseProtocolsToTail();
|
moveBaseProtocolsToTail(protocolList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setReversedProtocolList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setReversedProtocolList() {
|
||||||
|
final List<Protocol> reversedProtocolList = new ArrayList<>(protocolList);
|
||||||
|
Collections.reverse(this.reversedProtocolList);
|
||||||
|
moveBaseProtocolsToTail(reversedProtocolList);
|
||||||
|
this.reversedProtocolList = new CopyOnWriteArrayList<>(reversedProtocolList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -87,25 +101,26 @@ public class ProtocolPipelineImpl extends AbstractSimpleProtocol implements Prot
|
|||||||
this.protocolSet.add(protocol.getClass());
|
this.protocolSet.add(protocol.getClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
moveBaseProtocolsToTail();
|
moveBaseProtocolsToTail(protocolList);
|
||||||
|
setReversedProtocolList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void moveBaseProtocolsToTail() {
|
private List<Protocol> filterBaseProtocols(final List<Protocol> protocols) {
|
||||||
// Move base Protocols to the end, so the login packets can be modified by other protocols
|
final List<Protocol> baseProtocols = new ArrayList<>();
|
||||||
List<Protocol> baseProtocols = null;
|
for (final Protocol protocol : protocolList) {
|
||||||
for (Protocol protocol : protocolList) {
|
|
||||||
if (protocol.isBaseProtocol()) {
|
if (protocol.isBaseProtocol()) {
|
||||||
if (baseProtocols == null) {
|
|
||||||
baseProtocols = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
baseProtocols.add(protocol);
|
baseProtocols.add(protocol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return baseProtocols;
|
||||||
|
}
|
||||||
|
|
||||||
if (baseProtocols != null) {
|
private void moveBaseProtocolsToTail(final List<Protocol> protocols) {
|
||||||
protocolList.removeAll(baseProtocols);
|
// Move base Protocols to the end, so the login packets can be modified by other protocols
|
||||||
protocolList.addAll(baseProtocols);
|
final List<Protocol> baseProtocols = filterBaseProtocols(protocols);
|
||||||
|
if (!baseProtocols.isEmpty()) {
|
||||||
|
protocols.removeAll(baseProtocols);
|
||||||
|
protocols.addAll(baseProtocols);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +134,7 @@ public class ProtocolPipelineImpl extends AbstractSimpleProtocol implements Prot
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply protocols
|
// Apply protocols
|
||||||
packetWrapper.apply(direction, state, 0, protocolList, direction == Direction.CLIENTBOUND);
|
packetWrapper.apply(direction, state, 0, protocolListFor(direction), true);
|
||||||
super.transform(direction, state, packetWrapper);
|
super.transform(direction, state, packetWrapper);
|
||||||
|
|
||||||
if (debugHandler.enabled() && debugHandler.logPostPacketTransform() && debugHandler.shouldLog(packetWrapper, direction)) {
|
if (debugHandler.enabled() && debugHandler.logPostPacketTransform() && debugHandler.shouldLog(packetWrapper, direction)) {
|
||||||
@ -127,6 +142,10 @@ public class ProtocolPipelineImpl extends AbstractSimpleProtocol implements Prot
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<Protocol> protocolListFor(final Direction direction) {
|
||||||
|
return direction == Direction.CLIENTBOUND ? reversedProtocolList : protocolList;
|
||||||
|
}
|
||||||
|
|
||||||
private void logPacket(Direction direction, State state, PacketWrapper packetWrapper, int originalID) {
|
private void logPacket(Direction direction, State state, PacketWrapper packetWrapper, int originalID) {
|
||||||
// Debug packet
|
// Debug packet
|
||||||
int clientProtocol = userConnection.getProtocolInfo().getProtocolVersion();
|
int clientProtocol = userConnection.getProtocolInfo().getProtocolVersion();
|
||||||
@ -169,6 +188,11 @@ public class ProtocolPipelineImpl extends AbstractSimpleProtocol implements Prot
|
|||||||
return protocolList;
|
return protocolList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Protocol> reversedPipes() {
|
||||||
|
return reversedProtocolList;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNonBaseProtocols() {
|
public boolean hasNonBaseProtocols() {
|
||||||
for (Protocol protocol : protocolList) {
|
for (Protocol protocol : protocolList) {
|
||||||
|
@ -19,6 +19,7 @@ package com.viaversion.viaversion.protocol.packet;
|
|||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.viaversion.viaversion.api.Via;
|
import com.viaversion.viaversion.api.Via;
|
||||||
|
import com.viaversion.viaversion.api.connection.ProtocolInfo;
|
||||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||||
import com.viaversion.viaversion.api.protocol.packet.Direction;
|
import com.viaversion.viaversion.api.protocol.packet.Direction;
|
||||||
@ -309,8 +310,10 @@ public class PacketWrapperImpl implements PacketWrapper {
|
|||||||
*/
|
*/
|
||||||
private ByteBuf constructPacket(Class<? extends Protocol> packetProtocol, boolean skipCurrentPipeline, Direction direction) throws Exception {
|
private ByteBuf constructPacket(Class<? extends Protocol> packetProtocol, boolean skipCurrentPipeline, Direction direction) throws Exception {
|
||||||
// Apply current pipeline - for outgoing protocol, the collection will be reversed in the apply method
|
// Apply current pipeline - for outgoing protocol, the collection will be reversed in the apply method
|
||||||
Protocol[] protocols = user().getProtocolInfo().getPipeline().pipes().toArray(PROTOCOL_ARRAY);
|
final ProtocolInfo protocolInfo = user().getProtocolInfo();
|
||||||
boolean reverse = direction == Direction.CLIENTBOUND;
|
final boolean reverse = direction == Direction.CLIENTBOUND;
|
||||||
|
final List<Protocol> pipes = reverse ? protocolInfo.getPipeline().reversedPipes() : protocolInfo.getPipeline().pipes();
|
||||||
|
final Protocol[] protocols = pipes.toArray(PROTOCOL_ARRAY);
|
||||||
int index = -1;
|
int index = -1;
|
||||||
for (int i = 0; i < protocols.length; i++) {
|
for (int i = 0; i < protocols.length; i++) {
|
||||||
if (protocols[i].getClass() == packetProtocol) {
|
if (protocols[i].getClass() == packetProtocol) {
|
||||||
@ -332,8 +335,8 @@ public class PacketWrapperImpl implements PacketWrapper {
|
|||||||
resetReader();
|
resetReader();
|
||||||
|
|
||||||
// Apply other protocols
|
// Apply other protocols
|
||||||
apply(direction, user().getProtocolInfo().getState(), index, protocols, reverse);
|
apply(direction, protocolInfo.getState(direction), index, protocols, true);
|
||||||
ByteBuf output = inputBuffer == null ? user().getChannel().alloc().buffer() : inputBuffer.alloc().buffer();
|
final ByteBuf output = inputBuffer == null ? user().getChannel().alloc().buffer() : inputBuffer.alloc().buffer();
|
||||||
try {
|
try {
|
||||||
writeToBuffer(output);
|
writeToBuffer(output);
|
||||||
return output.retain();
|
return output.retain();
|
||||||
@ -402,15 +405,22 @@ public class PacketWrapperImpl implements PacketWrapper {
|
|||||||
|
|
||||||
private PacketWrapperImpl apply(Direction direction, State state, int index, Protocol[] pipeline, boolean reverse) throws Exception {
|
private PacketWrapperImpl apply(Direction direction, State state, int index, Protocol[] pipeline, boolean reverse) throws Exception {
|
||||||
// Reset the reader after every transformation for the packetWrapper, so it can be recycled across packets
|
// Reset the reader after every transformation for the packetWrapper, so it can be recycled across packets
|
||||||
|
State updatedState = state; // The state might change while transforming, so we need to check for that
|
||||||
if (reverse) {
|
if (reverse) {
|
||||||
for (int i = index; i >= 0; i--) {
|
for (int i = index; i >= 0; i--) {
|
||||||
pipeline[i].transform(direction, state, this);
|
pipeline[i].transform(direction, updatedState, this);
|
||||||
resetReader();
|
resetReader();
|
||||||
|
if (this.packetType != null) {
|
||||||
|
updatedState = this.packetType.state();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = index; i < pipeline.length; i++) {
|
for (int i = index; i < pipeline.length; i++) {
|
||||||
pipeline[i].transform(direction, state, this);
|
pipeline[i].transform(direction, updatedState, this);
|
||||||
resetReader();
|
resetReader();
|
||||||
|
if (this.packetType != null) {
|
||||||
|
updatedState = this.packetType.state();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
@ -33,12 +33,10 @@ import com.viaversion.viaversion.api.protocol.version.VersionProvider;
|
|||||||
import com.viaversion.viaversion.api.type.Type;
|
import com.viaversion.viaversion.api.type.Type;
|
||||||
import com.viaversion.viaversion.protocol.ProtocolManagerImpl;
|
import com.viaversion.viaversion.protocol.ProtocolManagerImpl;
|
||||||
import com.viaversion.viaversion.protocol.ServerProtocolVersionSingleton;
|
import com.viaversion.viaversion.protocol.ServerProtocolVersionSingleton;
|
||||||
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ServerboundConfigurationPackets1_20_2;
|
|
||||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.Protocol1_9To1_8;
|
import com.viaversion.viaversion.protocols.protocol1_9to1_8.Protocol1_9To1_8;
|
||||||
import com.viaversion.viaversion.util.ChatColorUtil;
|
import com.viaversion.viaversion.util.ChatColorUtil;
|
||||||
import com.viaversion.viaversion.util.GsonUtil;
|
import com.viaversion.viaversion.util.GsonUtil;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@ -121,8 +119,9 @@ public class BaseProtocol1_7 extends AbstractProtocol {
|
|||||||
// Login Success Packet
|
// Login Success Packet
|
||||||
registerClientbound(ClientboundLoginPackets.GAME_PROFILE, wrapper -> {
|
registerClientbound(ClientboundLoginPackets.GAME_PROFILE, wrapper -> {
|
||||||
ProtocolInfo info = wrapper.user().getProtocolInfo();
|
ProtocolInfo info = wrapper.user().getProtocolInfo();
|
||||||
if (info.getProtocolVersion() < ProtocolVersion.v1_20_2.getVersion()) {
|
info.setServerState(State.PLAY);
|
||||||
info.setState(State.PLAY);
|
if (info.getProtocolVersion() < ProtocolVersion.v1_20_2.getVersion()) { // 1.20.2+ clients will send a login ack first
|
||||||
|
info.setClientState(State.PLAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
UUID uuid = passthroughLoginUUID(wrapper);
|
UUID uuid = passthroughLoginUUID(wrapper);
|
||||||
@ -165,7 +164,10 @@ public class BaseProtocol1_7 extends AbstractProtocol {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
registerServerbound(ServerboundLoginPackets.LOGIN_ACKNOWLEDGED, wrapper -> wrapper.user().getProtocolInfo().setState(State.CONFIGURATION));
|
registerServerbound(ServerboundLoginPackets.LOGIN_ACKNOWLEDGED, wrapper -> {
|
||||||
|
final ProtocolInfo info = wrapper.user().getProtocolInfo();
|
||||||
|
info.setClientState(State.CONFIGURATION);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -20,6 +20,7 @@ package com.viaversion.viaversion.protocols.protocol1_20_2to1_20;
|
|||||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.viaversion.viaversion.api.Via;
|
import com.viaversion.viaversion.api.Via;
|
||||||
|
import com.viaversion.viaversion.api.connection.ProtocolInfo;
|
||||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||||
import com.viaversion.viaversion.api.data.MappingData;
|
import com.viaversion.viaversion.api.data.MappingData;
|
||||||
import com.viaversion.viaversion.api.data.MappingDataBase;
|
import com.viaversion.viaversion.api.data.MappingDataBase;
|
||||||
@ -114,10 +115,6 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
|
|||||||
// 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(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 -> {
|
||||||
@ -131,6 +128,8 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
|
|||||||
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();
|
||||||
|
|
||||||
|
wrapper.user().getProtocolInfo().setClientState(State.PLAY);
|
||||||
|
|
||||||
final ConfigurationState configurationState = wrapper.user().get(ConfigurationState.class);
|
final ConfigurationState configurationState = wrapper.user().get(ConfigurationState.class);
|
||||||
configurationState.setBridgePhase(BridgePhase.NONE);
|
configurationState.setBridgePhase(BridgePhase.NONE);
|
||||||
configurationState.sendQueuedPackets(wrapper.user());
|
configurationState.sendQueuedPackets(wrapper.user());
|
||||||
@ -153,6 +152,7 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reenter the configuration state
|
// Reenter the configuration state
|
||||||
|
wrapper.user().getProtocolInfo().setClientState(State.CONFIGURATION);
|
||||||
configurationState.setBridgePhase(BridgePhase.CONFIGURATION);
|
configurationState.setBridgePhase(BridgePhase.CONFIGURATION);
|
||||||
|
|
||||||
final LastResourcePack lastResourcePack = wrapper.user().get(LastResourcePack.class);
|
final LastResourcePack lastResourcePack = wrapper.user().get(LastResourcePack.class);
|
||||||
@ -180,6 +180,12 @@ 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 {
|
||||||
|
if (direction == Direction.SERVERBOUND) {
|
||||||
|
// The client will have the correct state set
|
||||||
|
super.transform(direction, state, packetWrapper);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final ConfigurationState configurationBridge = packetWrapper.user().get(ConfigurationState.class);
|
final ConfigurationState configurationBridge = packetWrapper.user().get(ConfigurationState.class);
|
||||||
if (configurationBridge == null) {
|
if (configurationBridge == null) {
|
||||||
// Bad state during an unexpected disconnect
|
// Bad state during an unexpected disconnect
|
||||||
@ -192,12 +198,6 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (direction == Direction.SERVERBOUND) {
|
|
||||||
// Client and server will be on different protocol states, pick the right client protocol state
|
|
||||||
super.transform(direction, phase == BridgePhase.PROFILE_SENT ? State.LOGIN
|
|
||||||
: phase == BridgePhase.REENTERING_CONFIGURATION ? State.PLAY : State.CONFIGURATION, packetWrapper);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (phase == BridgePhase.PROFILE_SENT || phase == BridgePhase.REENTERING_CONFIGURATION) {
|
if (phase == BridgePhase.PROFILE_SENT || phase == BridgePhase.REENTERING_CONFIGURATION) {
|
||||||
// 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
|
||||||
@ -252,6 +252,9 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void sendConfigurationPackets(final UserConnection connection, final CompoundTag dimensionRegistry, @Nullable final LastResourcePack lastResourcePack) throws Exception {
|
public static void sendConfigurationPackets(final UserConnection connection, final CompoundTag dimensionRegistry, @Nullable final LastResourcePack lastResourcePack) throws Exception {
|
||||||
|
final ProtocolInfo protocolInfo = connection.getProtocolInfo();
|
||||||
|
protocolInfo.setServerState(State.CONFIGURATION);
|
||||||
|
|
||||||
final PacketWrapper registryDataPacket = PacketWrapper.create(ClientboundConfigurationPackets1_20_2.REGISTRY_DATA, connection);
|
final PacketWrapper registryDataPacket = PacketWrapper.create(ClientboundConfigurationPackets1_20_2.REGISTRY_DATA, connection);
|
||||||
registryDataPacket.write(Type.NAMELESS_NBT, dimensionRegistry);
|
registryDataPacket.write(Type.NAMELESS_NBT, dimensionRegistry);
|
||||||
registryDataPacket.send(Protocol1_20_2To1_20.class);
|
registryDataPacket.send(Protocol1_20_2To1_20.class);
|
||||||
@ -275,6 +278,8 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
|
|||||||
|
|
||||||
final PacketWrapper finishConfigurationPacket = PacketWrapper.create(ClientboundConfigurationPackets1_20_2.FINISH_CONFIGURATION, connection);
|
final PacketWrapper finishConfigurationPacket = PacketWrapper.create(ClientboundConfigurationPackets1_20_2.FINISH_CONFIGURATION, connection);
|
||||||
finishConfigurationPacket.send(Protocol1_20_2To1_20.class);
|
finishConfigurationPacket.send(Protocol1_20_2To1_20.class);
|
||||||
|
|
||||||
|
protocolInfo.setServerState(State.PLAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -283,8 +288,8 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected @Nullable ServerboundPackets1_20_2 configurationAcknowledgedPacket() {
|
protected void registerConfigurationChangeHandlers() {
|
||||||
return null; // Don't handle it in the transitioning protocol
|
// Don't handle it in the transitioning protocol
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -32,7 +32,7 @@ import java.util.logging.Level;
|
|||||||
public class MovementTransmitterProvider implements Provider {
|
public class MovementTransmitterProvider implements Provider {
|
||||||
|
|
||||||
public void sendPlayer(UserConnection userConnection) {
|
public void sendPlayer(UserConnection userConnection) {
|
||||||
if (userConnection.getProtocolInfo().getState() != State.PLAY || userConnection.getEntityTracker(Protocol1_9To1_8.class).clientEntityId() == -1) {
|
if (userConnection.getProtocolInfo().getClientState() != State.PLAY || userConnection.getEntityTracker(Protocol1_9To1_8.class).clientEntityId() == -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren