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());
}
}