Add Via channel handlers instead of wrapping Vanilla handlers on Bukkit (#3132)

This commit is contained in:
Nassim Jahnke 2022-10-16 12:27:26 +02:00
parent 43ad855499
commit c5738a2203
No known key found for this signature in database
GPG Key ID: 6BE3B555EBC5982B
14 changed files with 173 additions and 248 deletions

View File

@ -34,29 +34,21 @@ import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class PipelineUtil { public final class PipelineUtil {
private static Method DECODE_METHOD; private static final Method DECODE_METHOD;
private static Method ENCODE_METHOD; private static final Method ENCODE_METHOD;
private static Method MTM_DECODE; private static final Method MTM_DECODE;
static { static {
try { try {
DECODE_METHOD = ByteToMessageDecoder.class.getDeclaredMethod("decode", ChannelHandlerContext.class, ByteBuf.class, List.class); DECODE_METHOD = ByteToMessageDecoder.class.getDeclaredMethod("decode", ChannelHandlerContext.class, ByteBuf.class, List.class);
DECODE_METHOD.setAccessible(true); DECODE_METHOD.setAccessible(true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
ENCODE_METHOD = MessageToByteEncoder.class.getDeclaredMethod("encode", ChannelHandlerContext.class, Object.class, ByteBuf.class); ENCODE_METHOD = MessageToByteEncoder.class.getDeclaredMethod("encode", ChannelHandlerContext.class, Object.class, ByteBuf.class);
ENCODE_METHOD.setAccessible(true); ENCODE_METHOD.setAccessible(true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
MTM_DECODE = MessageToMessageDecoder.class.getDeclaredMethod("decode", ChannelHandlerContext.class, Object.class, List.class); MTM_DECODE = MessageToMessageDecoder.class.getDeclaredMethod("decode", ChannelHandlerContext.class, Object.class, List.class);
MTM_DECODE.setAccessible(true); MTM_DECODE.setAccessible(true);
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
e.printStackTrace(); throw new RuntimeException(e);
} }
} }

View File

@ -29,7 +29,6 @@ import com.viaversion.viaversion.api.platform.ViaPlatform;
import com.viaversion.viaversion.bukkit.classgenerator.ClassGenerator; import com.viaversion.viaversion.bukkit.classgenerator.ClassGenerator;
import com.viaversion.viaversion.bukkit.commands.BukkitCommandHandler; import com.viaversion.viaversion.bukkit.commands.BukkitCommandHandler;
import com.viaversion.viaversion.bukkit.commands.BukkitCommandSender; import com.viaversion.viaversion.bukkit.commands.BukkitCommandSender;
import com.viaversion.viaversion.bukkit.listeners.ProtocolLibEnableListener;
import com.viaversion.viaversion.bukkit.platform.BukkitViaAPI; import com.viaversion.viaversion.bukkit.platform.BukkitViaAPI;
import com.viaversion.viaversion.bukkit.platform.BukkitViaConfig; import com.viaversion.viaversion.bukkit.platform.BukkitViaConfig;
import com.viaversion.viaversion.bukkit.platform.BukkitViaInjector; import com.viaversion.viaversion.bukkit.platform.BukkitViaInjector;
@ -89,10 +88,6 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform<Player>
@Override @Override
public void onLoad() { public void onLoad() {
// Via should load before PL, so we can't check for it in the constructor
Plugin protocolLib = Bukkit.getPluginManager().getPlugin("ProtocolLib");
ProtocolLibEnableListener.checkCompat(protocolLib);
// Spigot detector // Spigot detector
try { try {
Class.forName("org.spigotmc.SpigotConfig"); Class.forName("org.spigotmc.SpigotConfig");
@ -134,8 +129,6 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform<Player>
getCommand("viaversion").setExecutor(commandHandler); getCommand("viaversion").setExecutor(commandHandler);
getCommand("viaversion").setTabCompleter(commandHandler); getCommand("viaversion").setTabCompleter(commandHandler);
getServer().getPluginManager().registerEvents(new ProtocolLibEnableListener(), this);
// Warn them if they have anti-xray on and they aren't using spigot // Warn them if they have anti-xray on and they aren't using spigot
if (conf.isAntiXRay() && !spigot) { if (conf.isAntiXRay() && !spigot) {
getLogger().info("You have anti-xray on in your config, since you're not using spigot it won't fix xray!"); getLogger().info("You have anti-xray on in your config, since you're not using spigot it won't fix xray!");

View File

@ -21,8 +21,7 @@ import com.viaversion.viaversion.ViaVersionPlugin;
import com.viaversion.viaversion.bukkit.handlers.BukkitDecodeHandler; import com.viaversion.viaversion.bukkit.handlers.BukkitDecodeHandler;
import com.viaversion.viaversion.bukkit.handlers.BukkitEncodeHandler; import com.viaversion.viaversion.bukkit.handlers.BukkitEncodeHandler;
import com.viaversion.viaversion.bukkit.util.NMSUtil; import com.viaversion.viaversion.bukkit.util.NMSUtil;
import com.viaversion.viaversion.classgenerator.generated.BasicHandlerConstructor; import com.viaversion.viaversion.classgenerator.generated.HandlerSupplier;
import com.viaversion.viaversion.classgenerator.generated.HandlerConstructor;
import javassist.CannotCompileException; import javassist.CannotCompileException;
import javassist.ClassPool; import javassist.ClassPool;
import javassist.CtClass; import javassist.CtClass;
@ -48,11 +47,11 @@ import java.lang.reflect.Method;
//TODO maybe clean this up a bit 👀 //TODO maybe clean this up a bit 👀
public final class ClassGenerator { public final class ClassGenerator {
private static final boolean useModules = hasModuleMethod(); private static final boolean useModules = hasModuleMethod();
private static HandlerConstructor constructor = new BasicHandlerConstructor(); private static HandlerSupplier constructor = new HandlerSupplier.DefaultHandlerSupplier();
private static String psPackage; private static String psPackage;
private static Class psConnectListener; private static Class psConnectListener;
public static HandlerConstructor getConstructor() { public static HandlerSupplier handlerSupplier() {
return constructor; return constructor;
} }
@ -91,7 +90,7 @@ public final class ClassGenerator {
// Implement Constructor // Implement Constructor
CtClass generated = pool.makeClass("com.viaversion.viaversion.classgenerator.generated.GeneratedConstructor"); CtClass generated = pool.makeClass("com.viaversion.viaversion.classgenerator.generated.GeneratedConstructor");
CtClass handlerInterface = pool.get(HandlerConstructor.class.getName()); CtClass handlerInterface = pool.get(HandlerSupplier.class.getName());
generated.setInterfaces(new CtClass[]{handlerInterface}); generated.setInterfaces(new CtClass[]{handlerInterface});
// Import required classes // Import required classes
@ -107,7 +106,7 @@ public final class ClassGenerator {
" return new BukkitDecodeHandler(info, minecraftDecoder);\n" + " return new BukkitDecodeHandler(info, minecraftDecoder);\n" +
" }", generated)); " }", generated));
constructor = (HandlerConstructor) toClass(generated).getConstructor().newInstance(); constructor = (HandlerSupplier) toClass(generated).getConstructor().newInstance();
} catch (ReflectiveOperationException | CannotCompileException | NotFoundException e) { } catch (ReflectiveOperationException | CannotCompileException | NotFoundException e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -332,7 +331,7 @@ public final class ClassGenerator {
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private static Class<?> toClass(CtClass ctClass) throws CannotCompileException { private static Class<?> toClass(CtClass ctClass) throws CannotCompileException {
return useModules ? ctClass.toClass(HandlerConstructor.class) : ctClass.toClass(HandlerConstructor.class.getClassLoader()); return useModules ? ctClass.toClass(HandlerSupplier.class) : ctClass.toClass(HandlerSupplier.class.getClassLoader());
} }
private static boolean hasModuleMethod() { private static boolean hasModuleMethod() {

View File

@ -20,31 +20,47 @@ package com.viaversion.viaversion.bukkit.handlers;
import com.viaversion.viaversion.api.connection.UserConnection; import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.bukkit.classgenerator.ClassGenerator; import com.viaversion.viaversion.bukkit.classgenerator.ClassGenerator;
import com.viaversion.viaversion.bukkit.platform.PaperViaInjector; import com.viaversion.viaversion.bukkit.platform.PaperViaInjector;
import com.viaversion.viaversion.classgenerator.generated.HandlerConstructor;
import com.viaversion.viaversion.connection.UserConnectionImpl; import com.viaversion.viaversion.connection.UserConnectionImpl;
import com.viaversion.viaversion.platform.WrappedChannelInitializer; import com.viaversion.viaversion.platform.WrappedChannelInitializer;
import com.viaversion.viaversion.protocol.ProtocolPipelineImpl; import com.viaversion.viaversion.protocol.ProtocolPipelineImpl;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelInitializer;
import io.netty.handler.codec.ByteToMessageDecoder; import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.MessageToByteEncoder; import org.checkerframework.checker.nullness.qual.Nullable;
import java.lang.reflect.Method; import java.lang.reflect.Method;
public class BukkitChannelInitializer extends ChannelInitializer<Channel> implements WrappedChannelInitializer { public final class BukkitChannelInitializer extends ChannelInitializer<Channel> implements WrappedChannelInitializer {
public static final String VIA_ENCODER = "via-encoder";
public static final String VIA_DECODER = "via-decoder";
public static final String MINECRAFT_ENCODER = "encoder";
public static final String MINECRAFT_DECODER = "decoder";
public static final String MINECRAFT_COMPRESSOR = "compress";
public static final String MINECRAFT_DECOMPRESSOR = "decompress";
public static final Object COMPRESSION_ENABLED_EVENT = paperCompressionEnabledEvent();
private static final Method INIT_CHANNEL_METHOD; private static final Method INIT_CHANNEL_METHOD;
private final ChannelInitializer<Channel> original; private final ChannelInitializer<Channel> original;
static { static {
try { try {
INIT_CHANNEL_METHOD = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class); INIT_CHANNEL_METHOD = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class);
INIT_CHANNEL_METHOD.setAccessible(true); INIT_CHANNEL_METHOD.setAccessible(true);
} catch (NoSuchMethodException e) { } catch (final ReflectiveOperationException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
private static @Nullable Object paperCompressionEnabledEvent() {
try {
final Class<?> eventClass = Class.forName("io.papermc.paper.network.ConnectionEvent");
return eventClass.getDeclaredField("COMPRESSION_THRESHOLD_SET").get(null);
} catch (final ReflectiveOperationException e) {
return null;
}
}
public BukkitChannelInitializer(ChannelInitializer<Channel> oldInit) { public BukkitChannelInitializer(ChannelInitializer<Channel> oldInit) {
this.original = oldInit; this.original = oldInit;
} }
@ -62,7 +78,7 @@ public class BukkitChannelInitializer extends ChannelInitializer<Channel> implem
} }
public static void afterChannelInitialize(Channel channel) { public static void afterChannelInitialize(Channel channel) {
UserConnection connection = new UserConnectionImpl(channel); final UserConnection connection = new UserConnectionImpl(channel);
new ProtocolPipelineImpl(connection); new ProtocolPipelineImpl(connection);
if (PaperViaInjector.PAPER_PACKET_LIMITER) { if (PaperViaInjector.PAPER_PACKET_LIMITER) {
@ -70,12 +86,9 @@ public class BukkitChannelInitializer extends ChannelInitializer<Channel> implem
} }
// Add our transformers // Add our transformers
HandlerConstructor constructor = ClassGenerator.getConstructor(); final ChannelPipeline pipeline = channel.pipeline();
MessageToByteEncoder encoder = constructor.newEncodeHandler(connection, (MessageToByteEncoder) channel.pipeline().get("encoder")); pipeline.addBefore(MINECRAFT_ENCODER, VIA_ENCODER, ClassGenerator.handlerSupplier().newEncodeHandler(connection));
ByteToMessageDecoder decoder = constructor.newDecodeHandler(connection, (ByteToMessageDecoder) channel.pipeline().get("decoder")); pipeline.addBefore(MINECRAFT_DECODER, VIA_DECODER, ClassGenerator.handlerSupplier().newDecodeHandler(connection));
channel.pipeline().replace("encoder", "encoder", encoder);
channel.pipeline().replace("decoder", "decoder", decoder);
} }
@Override @Override

View File

@ -26,59 +26,64 @@ import com.viaversion.viaversion.exception.CancelDecoderException;
import com.viaversion.viaversion.exception.InformativeException; import com.viaversion.viaversion.exception.InformativeException;
import com.viaversion.viaversion.util.PipelineUtil; import com.viaversion.viaversion.util.PipelineUtil;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder; import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.MessageToMessageDecoder;
import java.lang.reflect.InvocationTargetException;
import java.util.List; import java.util.List;
public class BukkitDecodeHandler extends ByteToMessageDecoder { @ChannelHandler.Sharable
private final ByteToMessageDecoder minecraftDecoder; public final class BukkitDecodeHandler extends MessageToMessageDecoder<ByteBuf> {
private final UserConnection info; private final UserConnection connection;
public BukkitDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) { public BukkitDecodeHandler(final UserConnection connection) {
this.info = info; this.connection = connection;
this.minecraftDecoder = minecraftDecoder;
} }
@Override @Override
protected void decode(ChannelHandlerContext ctx, ByteBuf bytebuf, List<Object> list) throws Exception { protected void decode(final ChannelHandlerContext ctx, final ByteBuf bytebuf, final List<Object> out) throws Exception {
if (!info.checkServerboundPacket()) { if (!connection.checkServerboundPacket()) {
bytebuf.clear(); // Don't accumulate
throw CancelDecoderException.generate(null); throw CancelDecoderException.generate(null);
} }
if (!connection.shouldTransformPacket()) {
out.add(bytebuf.retain());
return;
}
ByteBuf transformedBuf = null; final ByteBuf transformedBuf = ctx.alloc().buffer().writeBytes(bytebuf);
try { try {
if (info.shouldTransformPacket()) { connection.transformIncoming(transformedBuf, CancelDecoderException::generate);
transformedBuf = ctx.alloc().buffer().writeBytes(bytebuf); out.add(transformedBuf.retain());
info.transformServerbound(transformedBuf, CancelDecoderException::generate);
}
try {
list.addAll(PipelineUtil.callDecode(this.minecraftDecoder, ctx, transformedBuf == null ? bytebuf : transformedBuf));
} catch (InvocationTargetException e) {
if (e.getCause() instanceof Exception) {
throw (Exception) e.getCause();
} else if (e.getCause() instanceof Error) {
throw (Error) e.getCause();
}
}
} finally { } finally {
if (transformedBuf != null) { transformedBuf.release();
transformedBuf.release();
}
} }
} }
@Override @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception {
if (PipelineUtil.containsCause(cause, CancelCodecException.class)) return; // ProtocolLib compat if (PipelineUtil.containsCause(cause, CancelCodecException.class)) {
return;
}
super.exceptionCaught(ctx, cause); super.exceptionCaught(ctx, cause);
if (!NMSUtil.isDebugPropertySet() && PipelineUtil.containsCause(cause, InformativeException.class) if (!NMSUtil.isDebugPropertySet() && PipelineUtil.containsCause(cause, InformativeException.class)
&& (info.getProtocolInfo().getState() != State.HANDSHAKE || Via.getManager().isDebug())) { && (connection.getProtocolInfo().getState() != State.HANDSHAKE || Via.getManager().isDebug())) {
cause.printStackTrace(); // Print if CB doesn't already do it cause.printStackTrace(); // Print if CB doesn't already do it
} }
} }
@Override
public void userEventTriggered(final ChannelHandlerContext ctx, final Object event) throws Exception {
if (BukkitChannelInitializer.COMPRESSION_ENABLED_EVENT == null || event != BukkitChannelInitializer.COMPRESSION_ENABLED_EVENT) {
super.userEventTriggered(ctx, event);
return;
}
// When compression handlers are added, the order becomes Minecraft Encoder -> Compressor -> Via Encoder; fix the order again
final ChannelPipeline pipeline = ctx.pipeline();
pipeline.addAfter(BukkitChannelInitializer.MINECRAFT_COMPRESSOR, BukkitChannelInitializer.VIA_ENCODER, pipeline.remove(BukkitChannelInitializer.VIA_ENCODER));
pipeline.addAfter(BukkitChannelInitializer.MINECRAFT_DECOMPRESSOR, BukkitChannelInitializer.VIA_DECODER, pipeline.remove(BukkitChannelInitializer.VIA_DECODER));
super.userEventTriggered(ctx, event);
}
} }

View File

@ -24,84 +24,99 @@ import com.viaversion.viaversion.bukkit.util.NMSUtil;
import com.viaversion.viaversion.exception.CancelCodecException; import com.viaversion.viaversion.exception.CancelCodecException;
import com.viaversion.viaversion.exception.CancelEncoderException; import com.viaversion.viaversion.exception.CancelEncoderException;
import com.viaversion.viaversion.exception.InformativeException; import com.viaversion.viaversion.exception.InformativeException;
import com.viaversion.viaversion.handlers.ChannelHandlerContextWrapper;
import com.viaversion.viaversion.handlers.ViaCodecHandler;
import com.viaversion.viaversion.util.PipelineUtil; import com.viaversion.viaversion.util.PipelineUtil;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.MessageToByteEncoder; import io.netty.handler.codec.MessageToByteEncoder;
import io.netty.handler.codec.MessageToMessageEncoder;
import java.lang.reflect.Field; import java.util.List;
import java.lang.reflect.InvocationTargetException;
public class BukkitEncodeHandler extends MessageToByteEncoder implements ViaCodecHandler { @ChannelHandler.Sharable
private static Field versionField; public final class BukkitEncodeHandler extends MessageToMessageEncoder<ByteBuf> {
private final UserConnection connection;
private boolean handledCompression = BukkitChannelInitializer.COMPRESSION_ENABLED_EVENT != null;
static { public BukkitEncodeHandler(final UserConnection connection) {
try { this.connection = connection;
// Attempt to get any version info from the handler
versionField = NMSUtil.nms(
"PacketEncoder",
"net.minecraft.network.PacketEncoder"
).getDeclaredField("version");
versionField.setAccessible(true);
} catch (Exception e) {
// Not compat version
}
}
private final UserConnection info;
private final MessageToByteEncoder minecraftEncoder;
public BukkitEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) {
this.info = info;
this.minecraftEncoder = minecraftEncoder;
} }
@Override @Override
protected void encode(final ChannelHandlerContext ctx, Object o, final ByteBuf bytebuf) throws Exception { protected void encode(final ChannelHandlerContext ctx, final ByteBuf bytebuf, final List<Object> out) throws Exception {
if (versionField != null) { if (!connection.checkClientboundPacket()) {
versionField.set(minecraftEncoder, versionField.get(this)); throw CancelEncoderException.generate(null);
} }
// handle the packet type if (!connection.shouldTransformPacket()) {
if (!(o instanceof ByteBuf)) { out.add(bytebuf.retain());
// call minecraft encoder return;
try { }
PipelineUtil.callEncode(this.minecraftEncoder, new ChannelHandlerContextWrapper(ctx, this), o, bytebuf);
} catch (InvocationTargetException e) { final ByteBuf transformedBuf = ctx.alloc().buffer().writeBytes(bytebuf);
if (e.getCause() instanceof Exception) { try {
throw (Exception) e.getCause(); final boolean needsCompression = !handledCompression && handleCompressionOrder(ctx, transformedBuf);
} else if (e.getCause() instanceof Error) { connection.transformClientbound(transformedBuf, CancelEncoderException::generate);
throw (Error) e.getCause(); if (needsCompression) {
} recompress(ctx, transformedBuf);
} }
} else { out.add(transformedBuf.retain());
bytebuf.writeBytes((ByteBuf) o); } finally {
transformedBuf.release();
}
}
private boolean handleCompressionOrder(final ChannelHandlerContext ctx, final ByteBuf buf) throws Exception {
final ChannelPipeline pipeline = ctx.pipeline();
final List<String> names = pipeline.names();
final int compressorIndex = names.indexOf(BukkitChannelInitializer.MINECRAFT_COMPRESSOR);
if (compressorIndex == -1) {
return false;
}
handledCompression = true;
if (compressorIndex > names.indexOf(BukkitChannelInitializer.VIA_ENCODER)) {
// Need to decompress this packet due to bad order
final ByteBuf decompressed = (ByteBuf) PipelineUtil.callDecode((ByteToMessageDecoder) pipeline.get(BukkitChannelInitializer.MINECRAFT_DECOMPRESSOR), ctx, buf).get(0);
try {
buf.clear().writeBytes(decompressed);
} finally {
decompressed.release();
}
pipeline.addAfter(BukkitChannelInitializer.MINECRAFT_COMPRESSOR, BukkitChannelInitializer.VIA_ENCODER, pipeline.remove(BukkitChannelInitializer.VIA_ENCODER));
pipeline.addAfter(BukkitChannelInitializer.MINECRAFT_DECOMPRESSOR, BukkitChannelInitializer.VIA_DECODER, pipeline.remove(BukkitChannelInitializer.VIA_DECODER));
return true;
}
return true;
}
private void recompress(final ChannelHandlerContext ctx, final ByteBuf buf) throws Exception {
final ByteBuf compressed = ctx.alloc().buffer();
try {
PipelineUtil.callEncode((MessageToByteEncoder<ByteBuf>) ctx.pipeline().get(BukkitChannelInitializer.MINECRAFT_COMPRESSOR), ctx, buf, compressed);
buf.clear().writeBytes(compressed);
} finally {
compressed.release();
} }
transform(bytebuf);
} }
@Override @Override
public void transform(ByteBuf bytebuf) throws Exception { public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception {
if (!info.checkClientboundPacket()) throw CancelEncoderException.generate(null); if (PipelineUtil.containsCause(cause, CancelCodecException.class)) {
if (!info.shouldTransformPacket()) return; return;
info.transformClientbound(bytebuf, CancelEncoderException::generate); }
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (PipelineUtil.containsCause(cause, CancelCodecException.class)) return; // ProtocolLib compat
super.exceptionCaught(ctx, cause); super.exceptionCaught(ctx, cause);
if (!NMSUtil.isDebugPropertySet() && PipelineUtil.containsCause(cause, InformativeException.class) if (!NMSUtil.isDebugPropertySet() && PipelineUtil.containsCause(cause, InformativeException.class)
&& (info.getProtocolInfo().getState() != State.HANDSHAKE || Via.getManager().isDebug())) { && (connection.getProtocolInfo().getState() != State.HANDSHAKE || Via.getManager().isDebug())) {
cause.printStackTrace(); // Print if CB doesn't already do it cause.printStackTrace(); // Print if CB doesn't already do it
} }
} }
public UserConnection getInfo() { public UserConnection connection() {
return info; return connection;
} }
} }

View File

@ -103,7 +103,7 @@ public class JoinListener implements Listener {
private @Nullable UserConnection getUserConnection(Channel channel) { private @Nullable UserConnection getUserConnection(Channel channel) {
BukkitEncodeHandler encoder = channel.pipeline().get(BukkitEncodeHandler.class); BukkitEncodeHandler encoder = channel.pipeline().get(BukkitEncodeHandler.class);
return encoder != null ? encoder.getInfo() : null; return encoder != null ? encoder.connection() : null;
} }
private Channel getChannel(Player player) throws Exception { private Channel getChannel(Player player) throws Exception {

View File

@ -1,62 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2022 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bukkit.listeners;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.bukkit.platform.BukkitViaInjector;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.event.server.PluginEnableEvent;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.Nullable;
public class ProtocolLibEnableListener implements Listener {
@EventHandler
public void onPluginEnable(PluginEnableEvent e) {
// Will likely never happen, but try to account for hacky plugin loading systems anyways
if (e.getPlugin().getName().equals("ProtocolLib")) {
checkCompat(e.getPlugin());
}
}
@EventHandler
public void onPluginDisable(PluginDisableEvent e) {
if (e.getPlugin().getName().equals("ProtocolLib")) {
((BukkitViaInjector) Via.getManager().getInjector()).setProtocolLib(false);
}
}
public static void checkCompat(@Nullable Plugin protocolLib) {
if (protocolLib != null) {
String version = protocolLib.getDescription().getVersion();
String majorVersion = version.split("\\.", 2)[0];
try {
// Only need the compat check for version < 5
if (Integer.parseInt(majorVersion) < 5) {
((BukkitViaInjector) Via.getManager().getInjector()).setProtocolLib(true);
return;
}
} catch (NumberFormatException ignored) {
Via.getPlatform().getLogger().warning("ProtocolLib version check failed for version " + version);
}
}
((BukkitViaInjector) Via.getManager().getInjector()).setProtocolLib(false);
}
}

View File

@ -35,7 +35,6 @@ import java.lang.reflect.Method;
import java.util.List; import java.util.List;
public class BukkitViaInjector extends LegacyViaInjector { public class BukkitViaInjector extends LegacyViaInjector {
private boolean protocolLib;
@Override @Override
public void inject() throws ReflectiveOperationException { public void inject() throws ReflectiveOperationException {
@ -112,11 +111,6 @@ public class BukkitViaInjector extends LegacyViaInjector {
throw new RuntimeException("Failed to get server"); throw new RuntimeException("Failed to get server");
} }
@Override
public String getDecoderName() {
return protocolLib ? "protocol_lib_decoder" : "decoder";
}
@Override @Override
protected @Nullable Object getServerConnection() throws ReflectiveOperationException { protected @Nullable Object getServerConnection() throws ReflectiveOperationException {
Class<?> serverClass = NMSUtil.nms( Class<?> serverClass = NMSUtil.nms(
@ -189,8 +183,4 @@ public class BukkitViaInjector extends LegacyViaInjector {
} }
return false; return false;
} }
public void setProtocolLib(boolean protocolLib) {
this.protocolLib = protocolLib;
}
} }

View File

@ -1,28 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2022 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.classgenerator.generated;
import com.viaversion.viaversion.api.connection.UserConnection;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.MessageToByteEncoder;
public interface HandlerConstructor {
public MessageToByteEncoder newEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder);
public ByteToMessageDecoder newDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder);
}

View File

@ -20,17 +20,25 @@ package com.viaversion.viaversion.classgenerator.generated;
import com.viaversion.viaversion.api.connection.UserConnection; import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.bukkit.handlers.BukkitDecodeHandler; import com.viaversion.viaversion.bukkit.handlers.BukkitDecodeHandler;
import com.viaversion.viaversion.bukkit.handlers.BukkitEncodeHandler; import com.viaversion.viaversion.bukkit.handlers.BukkitEncodeHandler;
import io.netty.handler.codec.ByteToMessageDecoder; import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.MessageToByteEncoder; import io.netty.handler.codec.MessageToMessageDecoder;
import io.netty.handler.codec.MessageToMessageEncoder;
public class BasicHandlerConstructor implements HandlerConstructor { public interface HandlerSupplier {
@Override
public BukkitEncodeHandler newEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) {
return new BukkitEncodeHandler(info, minecraftEncoder);
}
@Override MessageToMessageEncoder<ByteBuf> newEncodeHandler(UserConnection connection);
public BukkitDecodeHandler newDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) {
return new BukkitDecodeHandler(info, minecraftDecoder); MessageToMessageDecoder<ByteBuf> newDecodeHandler(UserConnection connection);
final class DefaultHandlerSupplier implements HandlerSupplier {
@Override
public MessageToMessageEncoder<ByteBuf> newEncodeHandler(final UserConnection connection) {
return new BukkitEncodeHandler(connection);
}
@Override
public MessageToMessageDecoder<ByteBuf> newDecodeHandler(final UserConnection connection) {
return new BukkitDecodeHandler(connection);
}
} }
} }

View File

@ -235,16 +235,6 @@ public abstract class LegacyViaInjector implements ViaInjector {
return data; return data;
} }
@Override
public String getEncoderName() {
return "encoder";
}
@Override
public String getDecoderName() {
return "decoder";
}
/** /**
* Returns the Vanilla server connection object the channels to be injected should be searched in. * Returns the Vanilla server connection object the channels to be injected should be searched in.
* *

View File

@ -1,5 +1,5 @@
# Project properties - we put these here so they can be modified without causing a recompile of the build scripts # Project properties - we put these here so they can be modified without causing a recompile of the build scripts
projectVersion=4.4.3-SNAPSHOT projectVersion=4.5.0-SNAPSHOT
# Gradle properties # Gradle properties
org.gradle.daemon=true org.gradle.daemon=true

View File

@ -50,4 +50,14 @@ public class SpongeViaInjector extends LegacyViaInjector {
protected void blame(ChannelHandler bootstrapAcceptor) { protected void blame(ChannelHandler bootstrapAcceptor) {
throw new RuntimeException("Unable to find core component 'childHandler', please check your plugins. Issue: " + bootstrapAcceptor.getClass().getName()); throw new RuntimeException("Unable to find core component 'childHandler', please check your plugins. Issue: " + bootstrapAcceptor.getClass().getName());
} }
@Override
public String getEncoderName() {
return "encoder";
}
@Override
public String getDecoderName() {
return "decoder";
}
} }