Mirror von
https://github.com/ViaVersion/ViaVersion.git
synchronisiert 2024-12-26 16:12:42 +01:00
Fix Velocity compatibility (requires Velocity 3.0.0)
This finally removes the hacky reorder fix on Velocity; it added a few more events that could benefit us, but this is the most important right now.
Dieser Commit ist enthalten in:
Ursprung
86278e837a
Commit
7a82ded94b
@ -39,11 +39,11 @@ import com.viaversion.viaversion.util.GsonUtil;
|
||||
import com.viaversion.viaversion.util.VersionInfo;
|
||||
import com.viaversion.viaversion.velocity.command.VelocityCommandHandler;
|
||||
import com.viaversion.viaversion.velocity.command.VelocityCommandSender;
|
||||
import com.viaversion.viaversion.velocity.platform.VelocityViaTask;
|
||||
import com.viaversion.viaversion.velocity.platform.VelocityViaAPI;
|
||||
import com.viaversion.viaversion.velocity.platform.VelocityViaConfig;
|
||||
import com.viaversion.viaversion.velocity.platform.VelocityViaInjector;
|
||||
import com.viaversion.viaversion.velocity.platform.VelocityViaLoader;
|
||||
import com.viaversion.viaversion.velocity.platform.VelocityViaTask;
|
||||
import com.viaversion.viaversion.velocity.service.ProtocolDetectorService;
|
||||
import com.viaversion.viaversion.velocity.util.LoggerWrapper;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
|
@ -26,33 +26,42 @@ import io.netty.channel.ChannelInitializer;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class VelocityChannelInitializer extends ChannelInitializer<Channel> {
|
||||
public static final String MINECRAFT_ENCODER = "minecraft-encoder";
|
||||
public static final String MINECRAFT_DECODER = "minecraft-decoder";
|
||||
public static final String VIA_ENCODER = "via-encoder";
|
||||
public static final String VIA_DECODER = "via-decoder";
|
||||
public static final Object COMPRESSION_ENABLED_EVENT;
|
||||
private static final Method INIT_CHANNEL;
|
||||
|
||||
private final ChannelInitializer<?> original;
|
||||
private final boolean clientSide;
|
||||
private static Method initChannel;
|
||||
|
||||
static {
|
||||
try {
|
||||
INIT_CHANNEL = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class);
|
||||
INIT_CHANNEL.setAccessible(true);
|
||||
|
||||
Class<?> eventClass = Class.forName("com.velocitypowered.proxy.protocol.VelocityConnectionEvent");
|
||||
COMPRESSION_ENABLED_EVENT = eventClass.getDeclaredField("COMPRESSION_ENABLED").get(null);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public VelocityChannelInitializer(ChannelInitializer<?> original, boolean clientSide) {
|
||||
this.original = original;
|
||||
this.clientSide = clientSide;
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
initChannel = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class);
|
||||
initChannel.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initChannel(Channel channel) throws Exception {
|
||||
initChannel.invoke(original, channel);
|
||||
INIT_CHANNEL.invoke(original, channel);
|
||||
|
||||
UserConnection user = new UserConnectionImpl(channel, clientSide);
|
||||
new ProtocolPipelineImpl(user);
|
||||
|
||||
// We need to add a separated handler because Velocity uses pipeline().get(MINECRAFT_DECODER)
|
||||
channel.pipeline().addBefore("minecraft-encoder", "via-encoder", new VelocityEncodeHandler(user));
|
||||
channel.pipeline().addBefore("minecraft-decoder", "via-decoder", new VelocityDecodeHandler(user));
|
||||
channel.pipeline().addBefore(MINECRAFT_ENCODER, VIA_ENCODER, new VelocityEncodeHandler(user));
|
||||
channel.pipeline().addBefore(MINECRAFT_DECODER, VIA_DECODER, new VelocityDecodeHandler(user));
|
||||
}
|
||||
}
|
||||
|
@ -20,21 +20,17 @@ package com.viaversion.viaversion.velocity.handlers;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.exception.CancelCodecException;
|
||||
import com.viaversion.viaversion.exception.CancelDecoderException;
|
||||
import com.viaversion.viaversion.util.PipelineUtil;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
|
||||
@ChannelHandler.Sharable
|
||||
public class VelocityDecodeHandler extends MessageToMessageDecoder<ByteBuf> {
|
||||
private final UserConnection info;
|
||||
private boolean handledCompression;
|
||||
private boolean skipDoubleTransform;
|
||||
|
||||
public VelocityDecodeHandler(UserConnection info) {
|
||||
this.info = info;
|
||||
@ -42,12 +38,6 @@ public class VelocityDecodeHandler extends MessageToMessageDecoder<ByteBuf> {
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf bytebuf, List<Object> out) throws Exception {
|
||||
if (skipDoubleTransform) {
|
||||
skipDoubleTransform = false;
|
||||
out.add(bytebuf.retain());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info.checkIncomingPacket()) throw CancelDecoderException.generate(null);
|
||||
if (!info.shouldTransformPacket()) {
|
||||
out.add(bytebuf.retain());
|
||||
@ -56,58 +46,39 @@ public class VelocityDecodeHandler extends MessageToMessageDecoder<ByteBuf> {
|
||||
|
||||
ByteBuf transformedBuf = ctx.alloc().buffer().writeBytes(bytebuf);
|
||||
try {
|
||||
boolean needsCompress = handleCompressionOrder(ctx, transformedBuf);
|
||||
|
||||
info.transformIncoming(transformedBuf, CancelDecoderException::generate);
|
||||
|
||||
if (needsCompress) {
|
||||
recompress(ctx, transformedBuf);
|
||||
skipDoubleTransform = true;
|
||||
}
|
||||
out.add(transformedBuf.retain());
|
||||
} finally {
|
||||
transformedBuf.release();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleCompressionOrder(ChannelHandlerContext ctx, ByteBuf buf) throws InvocationTargetException {
|
||||
if (handledCompression) return false;
|
||||
|
||||
int decoderIndex = ctx.pipeline().names().indexOf("compression-decoder");
|
||||
if (decoderIndex == -1) return false;
|
||||
handledCompression = true;
|
||||
if (decoderIndex > ctx.pipeline().names().indexOf("via-decoder")) {
|
||||
// Need to decompress this packet due to bad order
|
||||
ByteBuf decompressed = (ByteBuf) PipelineUtil.callDecode((MessageToMessageDecoder<?>) ctx.pipeline().get("compression-decoder"), ctx, buf).get(0);
|
||||
try {
|
||||
buf.clear().writeBytes(decompressed);
|
||||
} finally {
|
||||
decompressed.release();
|
||||
}
|
||||
ChannelHandler encoder = ctx.pipeline().get("via-encoder");
|
||||
ChannelHandler decoder = ctx.pipeline().get("via-decoder");
|
||||
ctx.pipeline().remove(encoder);
|
||||
ctx.pipeline().remove(decoder);
|
||||
ctx.pipeline().addAfter("compression-encoder", "via-encoder", encoder);
|
||||
ctx.pipeline().addAfter("compression-decoder", "via-decoder", decoder);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void recompress(ChannelHandlerContext ctx, ByteBuf buf) throws Exception {
|
||||
ByteBuf compressed = ctx.alloc().buffer();
|
||||
try {
|
||||
PipelineUtil.callEncode((MessageToByteEncoder<?>) ctx.pipeline().get("compression-encoder"), ctx, buf, compressed);
|
||||
buf.clear().writeBytes(compressed);
|
||||
} finally {
|
||||
compressed.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
if (cause instanceof CancelCodecException) return;
|
||||
super.exceptionCaught(ctx, cause);
|
||||
}
|
||||
|
||||
// Abuse decoder handler to catch events
|
||||
@Override
|
||||
public void userEventTriggered(ChannelHandlerContext ctx, Object event) throws Exception {
|
||||
if (event != VelocityChannelInitializer.COMPRESSION_ENABLED_EVENT) {
|
||||
super.userEventTriggered(ctx, event);
|
||||
return;
|
||||
}
|
||||
|
||||
// When Velocity adds the compression handlers, the order becomes Minecraft Encoder -> Compressor -> Via Encoder
|
||||
// Move Via codec handlers back to right position
|
||||
ChannelPipeline pipeline = ctx.pipeline();
|
||||
|
||||
ChannelHandler encoder = pipeline.get(VelocityChannelInitializer.VIA_ENCODER);
|
||||
pipeline.remove(encoder);
|
||||
pipeline.addBefore(VelocityChannelInitializer.MINECRAFT_ENCODER, VelocityChannelInitializer.VIA_ENCODER, encoder);
|
||||
|
||||
ChannelHandler decoder = pipeline.get(VelocityChannelInitializer.VIA_DECODER);
|
||||
pipeline.remove(decoder);
|
||||
pipeline.addBefore(VelocityChannelInitializer.MINECRAFT_DECODER, VelocityChannelInitializer.VIA_DECODER, decoder);
|
||||
|
||||
super.userEventTriggered(ctx, event);
|
||||
}
|
||||
}
|
||||
|
@ -20,21 +20,16 @@ package com.viaversion.viaversion.velocity.handlers;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.exception.CancelCodecException;
|
||||
import com.viaversion.viaversion.exception.CancelEncoderException;
|
||||
import com.viaversion.viaversion.util.PipelineUtil;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
import io.netty.handler.codec.MessageToMessageEncoder;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
|
||||
@ChannelHandler.Sharable
|
||||
public class VelocityEncodeHandler extends MessageToMessageEncoder<ByteBuf> {
|
||||
private final UserConnection info;
|
||||
private boolean handledCompression;
|
||||
|
||||
public VelocityEncodeHandler(UserConnection info) {
|
||||
this.info = info;
|
||||
@ -50,54 +45,13 @@ public class VelocityEncodeHandler extends MessageToMessageEncoder<ByteBuf> {
|
||||
|
||||
ByteBuf transformedBuf = ctx.alloc().buffer().writeBytes(bytebuf);
|
||||
try {
|
||||
boolean needsCompress = handleCompressionOrder(ctx, transformedBuf);
|
||||
|
||||
info.transformOutgoing(transformedBuf, CancelEncoderException::generate);
|
||||
|
||||
if (needsCompress) {
|
||||
recompress(ctx, transformedBuf);
|
||||
}
|
||||
out.add(transformedBuf.retain());
|
||||
} finally {
|
||||
transformedBuf.release();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleCompressionOrder(ChannelHandlerContext ctx, ByteBuf buf) throws InvocationTargetException {
|
||||
if (handledCompression) return false;
|
||||
|
||||
int encoderIndex = ctx.pipeline().names().indexOf("compression-encoder");
|
||||
if (encoderIndex == -1) return false;
|
||||
handledCompression = true;
|
||||
if (encoderIndex > ctx.pipeline().names().indexOf("via-encoder")) {
|
||||
// Need to decompress this packet due to bad order
|
||||
ByteBuf decompressed = (ByteBuf) PipelineUtil.callDecode((MessageToMessageDecoder<?>) ctx.pipeline().get("compression-decoder"), ctx, buf).get(0);
|
||||
try {
|
||||
buf.clear().writeBytes(decompressed);
|
||||
} finally {
|
||||
decompressed.release();
|
||||
}
|
||||
ChannelHandler encoder = ctx.pipeline().get("via-encoder");
|
||||
ChannelHandler decoder = ctx.pipeline().get("via-decoder");
|
||||
ctx.pipeline().remove(encoder);
|
||||
ctx.pipeline().remove(decoder);
|
||||
ctx.pipeline().addAfter("compression-encoder", "via-encoder", encoder);
|
||||
ctx.pipeline().addAfter("compression-decoder", "via-decoder", decoder);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void recompress(ChannelHandlerContext ctx, ByteBuf buf) throws InvocationTargetException {
|
||||
ByteBuf compressed = ctx.alloc().buffer();
|
||||
try {
|
||||
PipelineUtil.callEncode((MessageToByteEncoder<?>) ctx.pipeline().get("compression-encoder"), ctx, buf, compressed);
|
||||
buf.clear().writeBytes(compressed);
|
||||
} finally {
|
||||
compressed.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
if (cause instanceof CancelCodecException) return;
|
||||
|
@ -48,6 +48,7 @@ public class VelocityVersionProvider extends BaseVersionProvider {
|
||||
}
|
||||
|
||||
private int getBackProtocol(UserConnection user) throws Exception {
|
||||
//TODO use newly added Velocity netty event
|
||||
ChannelHandler mcHandler = user.getChannel().pipeline().get("handler");
|
||||
return ProtocolDetectorService.getProtocolId(
|
||||
((ServerConnection) getAssociation.invoke(mcHandler)).getServerInfo().getName());
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren