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.List;
public class PipelineUtil {
private static Method DECODE_METHOD;
private static Method ENCODE_METHOD;
private static Method MTM_DECODE;
public final class PipelineUtil {
private static final Method DECODE_METHOD;
private static final Method ENCODE_METHOD;
private static final Method MTM_DECODE;
static {
try {
DECODE_METHOD = ByteToMessageDecoder.class.getDeclaredMethod("decode", ChannelHandlerContext.class, ByteBuf.class, List.class);
DECODE_METHOD.setAccessible(true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
ENCODE_METHOD = MessageToByteEncoder.class.getDeclaredMethod("encode", ChannelHandlerContext.class, Object.class, ByteBuf.class);
ENCODE_METHOD.setAccessible(true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
MTM_DECODE = MessageToMessageDecoder.class.getDeclaredMethod("decode", ChannelHandlerContext.class, Object.class, List.class);
MTM_DECODE.setAccessible(true);
} 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.commands.BukkitCommandHandler;
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.BukkitViaConfig;
import com.viaversion.viaversion.bukkit.platform.BukkitViaInjector;
@ -89,10 +88,6 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform<Player>
@Override
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
try {
Class.forName("org.spigotmc.SpigotConfig");
@ -134,8 +129,6 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform<Player>
getCommand("viaversion").setExecutor(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
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!");

View File

@ -21,8 +21,7 @@ import com.viaversion.viaversion.ViaVersionPlugin;
import com.viaversion.viaversion.bukkit.handlers.BukkitDecodeHandler;
import com.viaversion.viaversion.bukkit.handlers.BukkitEncodeHandler;
import com.viaversion.viaversion.bukkit.util.NMSUtil;
import com.viaversion.viaversion.classgenerator.generated.BasicHandlerConstructor;
import com.viaversion.viaversion.classgenerator.generated.HandlerConstructor;
import com.viaversion.viaversion.classgenerator.generated.HandlerSupplier;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
@ -48,11 +47,11 @@ import java.lang.reflect.Method;
//TODO maybe clean this up a bit 👀
public final class ClassGenerator {
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 Class psConnectListener;
public static HandlerConstructor getConstructor() {
public static HandlerSupplier handlerSupplier() {
return constructor;
}
@ -91,7 +90,7 @@ public final class ClassGenerator {
// Implement Constructor
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});
// Import required classes
@ -107,7 +106,7 @@ public final class ClassGenerator {
" return new BukkitDecodeHandler(info, minecraftDecoder);\n" +
" }", generated));
constructor = (HandlerConstructor) toClass(generated).getConstructor().newInstance();
constructor = (HandlerSupplier) toClass(generated).getConstructor().newInstance();
} catch (ReflectiveOperationException | CannotCompileException | NotFoundException e) {
e.printStackTrace();
}
@ -332,7 +331,7 @@ public final class ClassGenerator {
@SuppressWarnings("deprecation")
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() {

View File

@ -20,31 +20,47 @@ package com.viaversion.viaversion.bukkit.handlers;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.bukkit.classgenerator.ClassGenerator;
import com.viaversion.viaversion.bukkit.platform.PaperViaInjector;
import com.viaversion.viaversion.classgenerator.generated.HandlerConstructor;
import com.viaversion.viaversion.connection.UserConnectionImpl;
import com.viaversion.viaversion.platform.WrappedChannelInitializer;
import com.viaversion.viaversion.protocol.ProtocolPipelineImpl;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.MessageToByteEncoder;
import io.netty.channel.ChannelPipeline;
import org.checkerframework.checker.nullness.qual.Nullable;
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 final ChannelInitializer<Channel> original;
static {
try {
INIT_CHANNEL_METHOD = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class);
INIT_CHANNEL_METHOD.setAccessible(true);
} catch (NoSuchMethodException e) {
} catch (final ReflectiveOperationException 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) {
this.original = oldInit;
}
@ -62,7 +78,7 @@ public class BukkitChannelInitializer extends ChannelInitializer<Channel> implem
}
public static void afterChannelInitialize(Channel channel) {
UserConnection connection = new UserConnectionImpl(channel);
final UserConnection connection = new UserConnectionImpl(channel);
new ProtocolPipelineImpl(connection);
if (PaperViaInjector.PAPER_PACKET_LIMITER) {
@ -70,12 +86,9 @@ public class BukkitChannelInitializer extends ChannelInitializer<Channel> implem
}
// Add our transformers
HandlerConstructor constructor = ClassGenerator.getConstructor();
MessageToByteEncoder encoder = constructor.newEncodeHandler(connection, (MessageToByteEncoder) channel.pipeline().get("encoder"));
ByteToMessageDecoder decoder = constructor.newDecodeHandler(connection, (ByteToMessageDecoder) channel.pipeline().get("decoder"));
channel.pipeline().replace("encoder", "encoder", encoder);
channel.pipeline().replace("decoder", "decoder", decoder);
final ChannelPipeline pipeline = channel.pipeline();
pipeline.addBefore(MINECRAFT_ENCODER, VIA_ENCODER, ClassGenerator.handlerSupplier().newEncodeHandler(connection));
pipeline.addBefore(MINECRAFT_DECODER, VIA_DECODER, ClassGenerator.handlerSupplier().newDecodeHandler(connection));
}
@Override

View File

@ -26,59 +26,64 @@ import com.viaversion.viaversion.exception.CancelDecoderException;
import com.viaversion.viaversion.exception.InformativeException;
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.ByteToMessageDecoder;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.MessageToMessageDecoder;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
public class BukkitDecodeHandler extends ByteToMessageDecoder {
private final ByteToMessageDecoder minecraftDecoder;
private final UserConnection info;
@ChannelHandler.Sharable
public final class BukkitDecodeHandler extends MessageToMessageDecoder<ByteBuf> {
private final UserConnection connection;
public BukkitDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) {
this.info = info;
this.minecraftDecoder = minecraftDecoder;
public BukkitDecodeHandler(final UserConnection connection) {
this.connection = connection;
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf bytebuf, List<Object> list) throws Exception {
if (!info.checkServerboundPacket()) {
bytebuf.clear(); // Don't accumulate
protected void decode(final ChannelHandlerContext ctx, final ByteBuf bytebuf, final List<Object> out) throws Exception {
if (!connection.checkServerboundPacket()) {
throw CancelDecoderException.generate(null);
}
if (!connection.shouldTransformPacket()) {
out.add(bytebuf.retain());
return;
}
ByteBuf transformedBuf = null;
final ByteBuf transformedBuf = ctx.alloc().buffer().writeBytes(bytebuf);
try {
if (info.shouldTransformPacket()) {
transformedBuf = ctx.alloc().buffer().writeBytes(bytebuf);
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();
}
}
connection.transformIncoming(transformedBuf, CancelDecoderException::generate);
out.add(transformedBuf.retain());
} finally {
if (transformedBuf != null) {
transformedBuf.release();
}
transformedBuf.release();
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (PipelineUtil.containsCause(cause, CancelCodecException.class)) return; // ProtocolLib compat
public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception {
if (PipelineUtil.containsCause(cause, CancelCodecException.class)) {
return;
}
super.exceptionCaught(ctx, cause);
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
}
}
@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.CancelEncoderException;
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 io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
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.MessageToMessageEncoder;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
public class BukkitEncodeHandler extends MessageToByteEncoder implements ViaCodecHandler {
private static Field versionField;
@ChannelHandler.Sharable
public final class BukkitEncodeHandler extends MessageToMessageEncoder<ByteBuf> {
private final UserConnection connection;
private boolean handledCompression = BukkitChannelInitializer.COMPRESSION_ENABLED_EVENT != null;
static {
try {
// 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;
public BukkitEncodeHandler(final UserConnection connection) {
this.connection = connection;
}
@Override
protected void encode(final ChannelHandlerContext ctx, Object o, final ByteBuf bytebuf) throws Exception {
if (versionField != null) {
versionField.set(minecraftEncoder, versionField.get(this));
protected void encode(final ChannelHandlerContext ctx, final ByteBuf bytebuf, final List<Object> out) throws Exception {
if (!connection.checkClientboundPacket()) {
throw CancelEncoderException.generate(null);
}
// handle the packet type
if (!(o instanceof ByteBuf)) {
// call minecraft encoder
try {
PipelineUtil.callEncode(this.minecraftEncoder, new ChannelHandlerContextWrapper(ctx, this), o, bytebuf);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof Exception) {
throw (Exception) e.getCause();
} else if (e.getCause() instanceof Error) {
throw (Error) e.getCause();
}
if (!connection.shouldTransformPacket()) {
out.add(bytebuf.retain());
return;
}
final ByteBuf transformedBuf = ctx.alloc().buffer().writeBytes(bytebuf);
try {
final boolean needsCompression = !handledCompression && handleCompressionOrder(ctx, transformedBuf);
connection.transformClientbound(transformedBuf, CancelEncoderException::generate);
if (needsCompression) {
recompress(ctx, transformedBuf);
}
} else {
bytebuf.writeBytes((ByteBuf) o);
out.add(transformedBuf.retain());
} 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
public void transform(ByteBuf bytebuf) throws Exception {
if (!info.checkClientboundPacket()) throw CancelEncoderException.generate(null);
if (!info.shouldTransformPacket()) 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
public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception {
if (PipelineUtil.containsCause(cause, CancelCodecException.class)) {
return;
}
super.exceptionCaught(ctx, cause);
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
}
}
public UserConnection getInfo() {
return info;
public UserConnection connection() {
return connection;
}
}

View File

@ -103,7 +103,7 @@ public class JoinListener implements Listener {
private @Nullable UserConnection getUserConnection(Channel channel) {
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 {

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;
public class BukkitViaInjector extends LegacyViaInjector {
private boolean protocolLib;
@Override
public void inject() throws ReflectiveOperationException {
@ -112,11 +111,6 @@ public class BukkitViaInjector extends LegacyViaInjector {
throw new RuntimeException("Failed to get server");
}
@Override
public String getDecoderName() {
return protocolLib ? "protocol_lib_decoder" : "decoder";
}
@Override
protected @Nullable Object getServerConnection() throws ReflectiveOperationException {
Class<?> serverClass = NMSUtil.nms(
@ -189,8 +183,4 @@ public class BukkitViaInjector extends LegacyViaInjector {
}
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.bukkit.handlers.BukkitDecodeHandler;
import com.viaversion.viaversion.bukkit.handlers.BukkitEncodeHandler;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.MessageToByteEncoder;
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.MessageToMessageDecoder;
import io.netty.handler.codec.MessageToMessageEncoder;
public class BasicHandlerConstructor implements HandlerConstructor {
@Override
public BukkitEncodeHandler newEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) {
return new BukkitEncodeHandler(info, minecraftEncoder);
}
public interface HandlerSupplier {
@Override
public BukkitDecodeHandler newDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) {
return new BukkitDecodeHandler(info, minecraftDecoder);
MessageToMessageEncoder<ByteBuf> newEncodeHandler(UserConnection connection);
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;
}
@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.
*

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
projectVersion=4.4.3-SNAPSHOT
projectVersion=4.5.0-SNAPSHOT
# Gradle properties
org.gradle.daemon=true

View File

@ -50,4 +50,14 @@ public class SpongeViaInjector extends LegacyViaInjector {
protected void blame(ChannelHandler bootstrapAcceptor) {
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";
}
}