Войти или зарегистрироваться
  • Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.

Помогите ServerConnection и его NetworkManager

ReloGGrc

Активный участник
Пользователь
Баллы
46
Имя в Minecraft
ALis
В общем, получаю листы List<ChannelFuture> и List<NetworkManager> из класса ServerConnection(его в свою очередь из класса MinecraftServer), и пытаюсь подключиться к ним для прослушивания пакетов. Для подключения к ChannelFuture пытался использовать .addBefore("packet_handler", "...", PacketHandler.class), как понятно, не получилось, порыскал в интернете немного и понял что для ChannelFuture нужно вшивать в его поле childHandler свой packethandler, вроде минус одна проблема(это я ещё не проверял). А вот касательно NetworkManager'ов там есть поле Channel но оно всегда null и как быть?(Проверял даже без использования рефлексии, напрямую, все равно null)
Было бы идеально если бы кто-то направил меня на верный путь. Заранее спасибо
 
Вот пример который заменяет ChannelInitializer.
Метод initChannel берём из ServerConnection и добавляем в него что надо.
Данный способ не очень хорош в плане совместимости, но если только один плагин его использует думаю ничего страшного не произойдёт.
Метод init() лучше вызывать из onLoad()
Код:
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPromise;
import io.netty.channel.MultithreadEventLoopGroup;
import io.netty.channel.epoll.Epoll;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.timeout.ReadTimeoutHandler;
import net.minecraft.server.v1_12_R1.EnumProtocolDirection;
import net.minecraft.server.v1_12_R1.HandshakeListener;
import net.minecraft.server.v1_12_R1.LazyInitVar;
import net.minecraft.server.v1_12_R1.LegacyPingHandler;
import net.minecraft.server.v1_12_R1.MinecraftServer;
import net.minecraft.server.v1_12_R1.NetworkManager;
import net.minecraft.server.v1_12_R1.PacketDataSerializer;
import net.minecraft.server.v1_12_R1.PacketDecoder;
import net.minecraft.server.v1_12_R1.PacketEncoder;
import net.minecraft.server.v1_12_R1.PacketPlayOutLogin;
import net.minecraft.server.v1_12_R1.PacketPlayOutRespawn;
import net.minecraft.server.v1_12_R1.PacketPrepender;
import net.minecraft.server.v1_12_R1.PacketSplitter;
import net.minecraft.server.v1_12_R1.ServerConnection;

class ChannelHandler {
    private static final MinecraftServer minecraftServer;
    private static final ServerConnection serverConnection;
    private static final List<ChannelFuture> serverchannels;
    private static final List<NetworkManager> servernetworkmanagers;
    private static final Class<? extends ServerSocketChannel> socketchannel;
    private static final LazyInitVar<? extends MultithreadEventLoopGroup> eventloop;
    static {
        Field achannel = null;
        Field anetwork = null;
        try {
            achannel = ServerConnection.class.getDeclaredField("g");
            achannel.setAccessible(true);
            anetwork = ServerConnection.class.getDeclaredField("h");
            anetwork.setAccessible(true);
        } catch (NoSuchFieldException | SecurityException e) {
        }
        minecraftServer = MinecraftServer.getServer();
        serverConnection = minecraftServer.getServerConnection();
        List<ChannelFuture> channelFutureList = null;
        List<NetworkManager> networkManagerList = null;

        try {
            channelFutureList = (List<ChannelFuture>) achannel.get(serverConnection);
            networkManagerList = (List<NetworkManager>) anetwork.get(serverConnection);
            achannel.setAccessible(false);
            anetwork.setAccessible(false);
        } catch (IllegalAccessException e) {
        }
        
        serverchannels = channelFutureList;
        servernetworkmanagers = networkManagerList;
        
        channelFutureList.get(0).channel().close().awaitUninterruptibly();
        channelFutureList.clear();
        
        Class<? extends ServerSocketChannel> socketChannelClass;
        LazyInitVar<? extends MultithreadEventLoopGroup> eventLoopGroup;

        if (Epoll.isAvailable() && minecraftServer.af()) {
            socketChannelClass = EpollServerSocketChannel.class;
            eventLoopGroup = ServerConnection.b;
        } else {
            socketChannelClass = NioServerSocketChannel.class;
            eventLoopGroup = ServerConnection.a;
        }
        socketchannel = socketChannelClass;
        eventloop = eventLoopGroup;
    }
    
    protected static void init() throws UnknownHostException {
        serverchannels.add((new ServerBootstrap()).channel(socketchannel).childHandler(new ChannelInitializer() {
            protected void initChannel(Channel channel) {
                try {
                    channel.config().setOption(ChannelOption.TCP_NODELAY, true);
                } catch (ChannelException ignored) {
                }
                channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)).addLast("legacy_query", new LegacyPingHandler(serverConnection)).addLast("splitter", new PacketSplitter()).addLast("decoder", new PacketDecoder(EnumProtocolDirection.SERVERBOUND)).addLast("prepender", new PacketPrepender()).addLast("encoder", new PacketEncoder(EnumProtocolDirection.CLIENTBOUND));
                NetworkManager networkmanager = new NetworkManager(EnumProtocolDirection.SERVERBOUND);
                servernetworkmanagers.add(networkmanager);
                channel.pipeline().addLast("forceend",new ChannelDuplexHandler() {
                    @Override
                    public void write(ChannelHandlerContext context, Object packet, ChannelPromise channelPromise) throws Exception {
                        if(packet instanceof PacketPlayOutLogin) {
                            PacketPlayOutLogin info = (PacketPlayOutLogin)packet;
                            PacketDataSerializer packetdataserializer = new PacketDataSerializer(Unpooled.buffer(12,28));
                            info.b(packetdataserializer);
                            packetdataserializer.setInt(5, 1);
                            info.a(packetdataserializer);
                        }
                        if(packet instanceof PacketPlayOutRespawn) {
                            PacketPlayOutRespawn info = (PacketPlayOutRespawn)packet;
                            PacketDataSerializer packetdataserializer = new PacketDataSerializer(Unpooled.buffer(6,22));
                            info.b(packetdataserializer);
                            packetdataserializer.setInt(0, 1);
                            info.a(packetdataserializer);
                        }
                        super.write(context, packet, channelPromise);
                    }
                });
                channel.pipeline().addLast("packet_handler", networkmanager);
                networkmanager.setPacketListener(new HandshakeListener(minecraftServer, networkmanager));
            }
        }).group(eventloop.c()).localAddress(InetAddress.getByName(minecraftServer.getServerIp()), minecraftServer.P()).bind().syncUninterruptibly());
    }
    
}
 

Поделиться этой страницей

Назад
Верх