Skip to content

Commit

Permalink
Initial Support for 1.20.5 (#2894)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ingrim4 authored Apr 28, 2024
1 parent d0c7382 commit 70e4812
Show file tree
Hide file tree
Showing 8 changed files with 817 additions and 457 deletions.
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
package com.comphenix.protocol.injector.netty.channel;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;

import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
import com.comphenix.protocol.reflect.accessors.MethodAccessor;
import com.comphenix.protocol.reflect.fuzzy.FuzzyFieldContract;
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
import com.comphenix.protocol.utility.MinecraftReflection;

import io.netty.channel.Channel;
import io.netty.util.AttributeKey;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.function.BiFunction;

@SuppressWarnings("unchecked")
final class ChannelProtocolUtil {

Expand All @@ -28,7 +32,10 @@ final class ChannelProtocolUtil {
.build());

BiFunction<Channel, PacketType.Sender, Object> baseResolver = null;
if (attributeKeys.size() == 1) {
if (attributeKeys.isEmpty()) {
// since 1.20.5 the protocol is stored as final field in de-/encoder
baseResolver = new Post1_20_5WrappedResolver();
} else if (attributeKeys.size() == 1) {
// if there is only one attribute key we can assume it's the correct one (1.8 - 1.20.1)
Object protocolKey = Accessors.getFieldAccessor(attributeKeys.get(0)).get(null);
baseResolver = new Pre1_20_2DirectResolver((AttributeKey<Object>) protocolKey);
Expand Down Expand Up @@ -130,4 +137,70 @@ private FieldAccessor getProtocolAccessor(Class<?> codecClass) {
return this.protocolAccessor;
}
}

/**
* Since 1.20.5 the protocol is stored as final field in de-/encoder
*/
private static final class Post1_20_5WrappedResolver implements BiFunction<Channel, PacketType.Sender, Object> {

// lazy initialized when needed
private Function<Object, Object> serverProtocolAccessor;
private Function<Object, Object> clientProtocolAccessor;

@Override
public Object apply(Channel channel, PacketType.Sender sender) {
String key = this.getKeyForSender(sender);
Object codecHandler = channel.pipeline().get(key);
if (codecHandler == null) {
return null;
}

Function<Object, Object> protocolAccessor = this.getProtocolAccessor(codecHandler.getClass(), sender);
return protocolAccessor.apply(codecHandler);
}

private Function<Object, Object> getProtocolAccessor(Class<?> codecHandler, PacketType.Sender sender) {
switch (sender) {
case SERVER:
if (this.serverProtocolAccessor == null) {
this.serverProtocolAccessor = getProtocolAccessor(codecHandler);
}
return this.serverProtocolAccessor;
case CLIENT:
if (this.clientProtocolAccessor == null) {
this.clientProtocolAccessor = getProtocolAccessor(codecHandler);
}
return this.clientProtocolAccessor;
default:
throw new IllegalArgumentException("Illegal packet sender " + sender.name());
}
}

private String getKeyForSender(PacketType.Sender sender) {
switch (sender) {
case SERVER:
return "encoder";
case CLIENT:
return "decoder";
default:
throw new IllegalArgumentException("Illegal packet sender " + sender.name());
}
}

private Function<Object, Object> getProtocolAccessor(Class<?> codecHandler) {
Class<?> protocolInfoClass = MinecraftReflection.getProtocolInfoClass();

MethodAccessor protocolAccessor = Accessors.getMethodAccessor(FuzzyReflection
.fromClass(protocolInfoClass)
.getMethodByReturnTypeAndParameters("id", MinecraftReflection.getEnumProtocolClass(), new Class[0]));

FieldAccessor protocolInfoAccessor = Accessors.getFieldAccessor(codecHandler, protocolInfoClass, true);

// get ProtocolInfo from handler and get EnumProtocol of ProtocolInfo
return (handler) -> {
Object protocolInfo = protocolInfoAccessor.get(handler);
return protocolAccessor.invoke(protocolInfo);
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoop;
import io.netty.util.AttributeKey;
import org.bukkit.Server;
Expand Down Expand Up @@ -202,9 +203,18 @@ public boolean inject() {
return false;
}

ChannelPipeline pipeline = this.wrappedChannel.pipeline();

// since 1.20.5 the encoder is renamed to outbound_config only in the handshake phase
String encoderName = pipeline.get("outbound_config") != null
? "outbound_config" : "encoder";

// inject our handlers
this.wrappedChannel.pipeline().addAfter("encoder", WIRE_PACKET_ENCODER_NAME, WIRE_PACKET_ENCODER);
this.wrappedChannel.pipeline().addAfter(
pipeline.addAfter(
encoderName,
WIRE_PACKET_ENCODER_NAME,
WIRE_PACKET_ENCODER);
pipeline.addAfter(
"decoder",
INTERCEPTOR_NAME,
new InboundPacketInterceptor(this, this.channelListener));
Expand Down
Loading

0 comments on commit 70e4812

Please sign in to comment.