Skip to content

Commit

Permalink
1.20.2 Support (#1088)
Browse files Browse the repository at this point in the history
Co-authored-by: RednedEpic <[email protected]>
Co-authored-by: Gero <[email protected]>
  • Loading branch information
3 people authored Oct 10, 2023
1 parent 19abb90 commit 768ecdb
Show file tree
Hide file tree
Showing 38 changed files with 2,277 additions and 600 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ gradle-app.setting
logs/
/velocity.toml
/forwarding.secret
forwarding.secret
velocity.toml
server-icon.png
/bin/
run/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ public enum ProtocolVersion {
MINECRAFT_1_19_1(760, "1.19.1", "1.19.2"),
MINECRAFT_1_19_3(761, "1.19.3"),
MINECRAFT_1_19_4(762, "1.19.4"),
MINECRAFT_1_20(763, "1.20", "1.20.1");
MINECRAFT_1_20(763, "1.20", "1.20.1"),
MINECRAFT_1_20_2(764, "1.20.2");

private static final int SNAPSHOT_BIT = 30;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import com.velocitypowered.proxy.connection.client.HandshakeSessionHandler;
import com.velocitypowered.proxy.connection.client.InitialLoginSessionHandler;
import com.velocitypowered.proxy.connection.client.StatusSessionHandler;
import com.velocitypowered.proxy.network.Connections;
import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.VelocityConnectionEvent;
Expand All @@ -46,6 +47,7 @@
import com.velocitypowered.proxy.protocol.netty.MinecraftDecoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftEncoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftVarintLengthEncoder;
import com.velocitypowered.proxy.protocol.netty.PlayPacketQueueHandler;
import com.velocitypowered.proxy.util.except.QuietDecoderException;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
Expand All @@ -60,6 +62,9 @@
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.security.GeneralSecurityException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
Expand All @@ -78,7 +83,8 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
private final Channel channel;
private SocketAddress remoteAddress;
private StateRegistry state;
private @Nullable MinecraftSessionHandler sessionHandler;
private Map<StateRegistry, MinecraftSessionHandler> sessionHandlers;
private @Nullable MinecraftSessionHandler activeSessionHandler;
private ProtocolVersion protocolVersion;
private @Nullable MinecraftConnectionAssociation association;
public final VelocityServer server;
Expand All @@ -96,12 +102,14 @@ public MinecraftConnection(Channel channel, VelocityServer server) {
this.remoteAddress = channel.remoteAddress();
this.server = server;
this.state = StateRegistry.HANDSHAKE;

this.sessionHandlers = new HashMap<>();
}

@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
if (sessionHandler != null) {
sessionHandler.connected();
if (activeSessionHandler != null) {
activeSessionHandler.connected();
}

if (association != null && server.getConfiguration().isLogPlayerConnections()) {
Expand All @@ -111,12 +119,12 @@ public void channelActive(ChannelHandlerContext ctx) throws Exception {

@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
if (sessionHandler != null) {
sessionHandler.disconnected();
if (activeSessionHandler != null) {
activeSessionHandler.disconnected();
}

if (association != null && !knownDisconnect
&& !(sessionHandler instanceof StatusSessionHandler)
&& !(activeSessionHandler instanceof StatusSessionHandler)
&& server.getConfiguration().isLogPlayerConnections()) {
logger.info("{} has disconnected", association);
}
Expand All @@ -125,12 +133,12 @@ public void channelInactive(ChannelHandlerContext ctx) throws Exception {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
try {
if (sessionHandler == null) {
if (activeSessionHandler == null) {
// No session handler available, do nothing
return;
}

if (sessionHandler.beforeHandle()) {
if (activeSessionHandler.beforeHandle()) {
return;
}

Expand All @@ -140,15 +148,15 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception

if (msg instanceof MinecraftPacket) {
MinecraftPacket pkt = (MinecraftPacket) msg;
if (!pkt.handle(sessionHandler)) {
sessionHandler.handleGeneric((MinecraftPacket) msg);
if (!pkt.handle(activeSessionHandler)) {
activeSessionHandler.handleGeneric((MinecraftPacket) msg);
}
} else if (msg instanceof HAProxyMessage) {
HAProxyMessage proxyMessage = (HAProxyMessage) msg;
this.remoteAddress = new InetSocketAddress(proxyMessage.sourceAddress(),
proxyMessage.sourcePort());
} else if (msg instanceof ByteBuf) {
sessionHandler.handleUnknown((ByteBuf) msg);
activeSessionHandler.handleUnknown((ByteBuf) msg);
}
} finally {
ReferenceCountUtil.release(msg);
Expand All @@ -157,34 +165,36 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception

@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
if (sessionHandler != null) {
sessionHandler.readCompleted();
if (activeSessionHandler != null) {
activeSessionHandler.readCompleted();
}
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (ctx.channel().isActive()) {
if (sessionHandler != null) {
if (activeSessionHandler != null) {
try {
sessionHandler.exception(cause);
activeSessionHandler.exception(cause);
} catch (Exception ex) {
logger.error("{}: exception handling exception in {}",
(association != null ? association : channel.remoteAddress()), sessionHandler, cause);
(association != null ? association : channel.remoteAddress()), activeSessionHandler,
cause);
}
}

if (association != null) {
if (cause instanceof ReadTimeoutException) {
logger.error("{}: read timed out", association);
} else {
boolean frontlineHandler = sessionHandler instanceof InitialLoginSessionHandler
|| sessionHandler instanceof HandshakeSessionHandler
|| sessionHandler instanceof StatusSessionHandler;
boolean frontlineHandler = activeSessionHandler instanceof InitialLoginSessionHandler
|| activeSessionHandler instanceof HandshakeSessionHandler
|| activeSessionHandler instanceof StatusSessionHandler;
boolean isQuietDecoderException = cause instanceof QuietDecoderException;
boolean willLog = !isQuietDecoderException && !frontlineHandler;
if (willLog) {
logger.error("{}: exception encountered in {}", association, sessionHandler, cause);
logger.error("{}: exception encountered in {}", association, activeSessionHandler,
cause);
} else {
knownDisconnect = true;
}
Expand All @@ -197,8 +207,8 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws E

@Override
public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
if (sessionHandler != null) {
sessionHandler.writabilityChanged();
if (activeSessionHandler != null) {
activeSessionHandler.writabilityChanged();
}
}

Expand Down Expand Up @@ -323,7 +333,7 @@ public boolean isKnownDisconnect() {
}

/**
* Determines whether or not the channel should continue reading data automaticaly.
* Determines whether or not the channel should continue reading data automatically.
*
* @param autoReading whether or not we should read data automatically
*/
Expand All @@ -341,17 +351,38 @@ public void setAutoReading(boolean autoReading) {
}
}

// Ideally only used by the state switch

/**
* Changes the state of the Minecraft connection.
* Sets the new state for the connection.
*
* @param state the new state
* @param state the state to use
*/
public void setState(StateRegistry state) {
ensureInEventLoop();

this.state = state;
this.channel.pipeline().get(MinecraftEncoder.class).setState(state);
this.channel.pipeline().get(MinecraftDecoder.class).setState(state);

if (state == StateRegistry.CONFIG) {
// Activate the play packet queue
addPlayPacketQueueHandler();
} else if (this.channel.pipeline().get(Connections.PLAY_PACKET_QUEUE) != null) {
// Remove the queue
this.channel.pipeline().remove(Connections.PLAY_PACKET_QUEUE);
}
}

/**
* Adds the play packet queue handler.
*/
public void addPlayPacketQueueHandler() {
if (this.channel.pipeline().get(Connections.PLAY_PACKET_QUEUE) == null) {
this.channel.pipeline().addAfter(Connections.MINECRAFT_ENCODER, Connections.PLAY_PACKET_QUEUE,
new PlayPacketQueueHandler(this.protocolVersion,
channel.pipeline().get(MinecraftEncoder.class).getDirection()));
}
}

public ProtocolVersion getProtocolVersion() {
Expand Down Expand Up @@ -382,32 +413,81 @@ public void setProtocolVersion(ProtocolVersion protocolVersion) {
}
}

public @Nullable MinecraftSessionHandler getSessionHandler() {
return sessionHandler;
public @Nullable MinecraftSessionHandler getActiveSessionHandler() {
return activeSessionHandler;
}

public @Nullable MinecraftSessionHandler getSessionHandlerForRegistry(StateRegistry registry) {
return this.sessionHandlers.getOrDefault(registry, null);
}

/**
* Sets the session handler for this connection.
*
* @param registry the registry of the handler
* @param sessionHandler the handler to use
*/
public void setSessionHandler(MinecraftSessionHandler sessionHandler) {
public void setActiveSessionHandler(StateRegistry registry,
MinecraftSessionHandler sessionHandler) {
Preconditions.checkNotNull(registry);
ensureInEventLoop();

if (this.sessionHandler != null) {
this.sessionHandler.deactivated();
if (this.activeSessionHandler != null) {
this.activeSessionHandler.deactivated();
}
this.sessionHandler = sessionHandler;
this.sessionHandlers.put(registry, sessionHandler);
this.activeSessionHandler = sessionHandler;
setState(registry);
sessionHandler.activated();
}

/**
* Switches the active session handler to the respective registry one.
*
* @param registry the registry of the handler
* @return true if successful and handler is present
*/
public boolean setActiveSessionHandler(StateRegistry registry) {
Preconditions.checkNotNull(registry);
ensureInEventLoop();

MinecraftSessionHandler handler = getSessionHandlerForRegistry(registry);
if (handler != null) {
boolean flag = true;
if (this.activeSessionHandler != null
&& (flag = !Objects.equals(handler, this.activeSessionHandler))) {
this.activeSessionHandler.deactivated();
}
this.activeSessionHandler = handler;
setState(registry);
if (flag) {
handler.activated();
}
}
return handler != null;
}

/**
* Adds a secondary session handler for this connection.
*
* @param registry the registry of the handler
* @param sessionHandler the handler to use
*/
public void addSessionHandler(StateRegistry registry, MinecraftSessionHandler sessionHandler) {
Preconditions.checkNotNull(registry);
Preconditions.checkArgument(registry != state, "Handler would overwrite handler");
ensureInEventLoop();

this.sessionHandlers.put(registry, sessionHandler);
}

private void ensureOpen() {
Preconditions.checkState(!isClosed(), "Connection is closed.");
}

/**
* Sets the compression threshold on the connection. You are responsible for sending
* {@link com.velocitypowered.proxy.protocol.packet.SetCompression} beforehand.
* Sets the compression threshold on the connection. You are responsible for sending {@link
* com.velocitypowered.proxy.protocol.packet.SetCompression} beforehand.
*
* @param threshold the compression threshold to use
*/
Expand Down Expand Up @@ -497,5 +577,4 @@ public ConnectionType getType() {
public void setType(ConnectionType connectionType) {
this.connectionType = connectionType;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@
import com.velocitypowered.proxy.protocol.packet.LegacyHandshake;
import com.velocitypowered.proxy.protocol.packet.LegacyPing;
import com.velocitypowered.proxy.protocol.packet.LegacyPlayerListItem;
import com.velocitypowered.proxy.protocol.packet.LoginAcknowledged;
import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage;
import com.velocitypowered.proxy.protocol.packet.LoginPluginResponse;
import com.velocitypowered.proxy.protocol.packet.PingIdentify;
import com.velocitypowered.proxy.protocol.packet.PluginMessage;
import com.velocitypowered.proxy.protocol.packet.RemovePlayerInfo;
import com.velocitypowered.proxy.protocol.packet.ResourcePackRequest;
Expand All @@ -55,6 +57,11 @@
import com.velocitypowered.proxy.protocol.packet.chat.legacy.LegacyChat;
import com.velocitypowered.proxy.protocol.packet.chat.session.SessionPlayerChat;
import com.velocitypowered.proxy.protocol.packet.chat.session.SessionPlayerCommand;
import com.velocitypowered.proxy.protocol.packet.config.ActiveFeatures;
import com.velocitypowered.proxy.protocol.packet.config.FinishedUpdate;
import com.velocitypowered.proxy.protocol.packet.config.RegistrySync;
import com.velocitypowered.proxy.protocol.packet.config.StartUpdate;
import com.velocitypowered.proxy.protocol.packet.config.TagsUpdate;
import com.velocitypowered.proxy.protocol.packet.title.LegacyTitlePacket;
import com.velocitypowered.proxy.protocol.packet.title.TitleActionbarPacket;
import com.velocitypowered.proxy.protocol.packet.title.TitleClearPacket;
Expand Down Expand Up @@ -279,4 +286,32 @@ default boolean handle(RemovePlayerInfo packet) {
default boolean handle(UpsertPlayerInfo packet) {
return false;
}

default boolean handle(LoginAcknowledged packet) {
return false;
}

default boolean handle(ActiveFeatures packet) {
return false;
}

default boolean handle(FinishedUpdate packet) {
return false;
}

default boolean handle(RegistrySync packet) {
return false;
}

default boolean handle(TagsUpdate packet) {
return false;
}

default boolean handle(StartUpdate packet) {
return false;
}

default boolean handle(PingIdentify pingIdentify) {
return false;
}
}
Loading

0 comments on commit 768ecdb

Please sign in to comment.