package net.minecraft.client.network; import com.google.common.base.Charsets; import com.google.common.base.Splitter; import com.google.common.collect.Iterables; import com.mojang.authlib.GameProfile; import cpw.mods.fml.client.FMLClientHandler; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.ChannelException; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.util.concurrent.GenericFutureListener; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ServerAddress; import net.minecraft.client.multiplayer.ServerData; import net.minecraft.network.EnumConnectionState; import net.minecraft.network.NetworkManager; import net.minecraft.network.ServerStatusResponse; import net.minecraft.network.handshake.client.C00Handshake; import net.minecraft.network.status.INetHandlerStatusClient; import net.minecraft.network.status.client.C00PacketServerQuery; import net.minecraft.network.status.client.C01PacketPing; import net.minecraft.network.status.server.S00PacketServerInfo; import net.minecraft.network.status.server.S01PacketPong; import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IChatComponent; import net.minecraft.util.MathHelper; import org.apache.commons.lang3.ArrayUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @SideOnly(Side.CLIENT) public class OldServerPinger { private static final Splitter PING_RESPONSE_SPLITTER = Splitter.on('\u0000').limit(6); private static final Logger logger = LogManager.getLogger(); /** A list of NetworkManagers that have pending pings */ private final List pingDestinations = Collections.synchronizedList(new ArrayList()); private static final String __OBFID = "CL_00000892"; public void ping(final ServerData server) throws UnknownHostException { ServerAddress serveraddress = ServerAddress.func_78860_a(server.serverIP); final NetworkManager networkmanager = NetworkManager.provideLanClient(InetAddress.getByName(serveraddress.getIP()), serveraddress.getPort()); this.pingDestinations.add(networkmanager); server.serverMOTD = "Pinging..."; server.pingToServer = -1L; server.playerList = null; networkmanager.setNetHandler(new INetHandlerStatusClient() { private boolean field_147403_d = false; private static final String __OBFID = "CL_00000893"; public void handleServerInfo(S00PacketServerInfo packetIn) { ServerStatusResponse serverstatusresponse = packetIn.func_149294_c(); if (serverstatusresponse.getServerDescription() != null) { server.serverMOTD = serverstatusresponse.getServerDescription().getFormattedText(); } else { server.serverMOTD = ""; } if (serverstatusresponse.getProtocolVersionInfo() != null) { server.gameVersion = serverstatusresponse.getProtocolVersionInfo().getName(); server.version = serverstatusresponse.getProtocolVersionInfo().getProtocol(); } else { server.gameVersion = "Old"; server.version = 0; } if (serverstatusresponse.getPlayerCountData() != null) { server.populationInfo = EnumChatFormatting.GRAY + "" + serverstatusresponse.getPlayerCountData().getOnlinePlayerCount() + "" + EnumChatFormatting.DARK_GRAY + "/" + EnumChatFormatting.GRAY + serverstatusresponse.getPlayerCountData().getMaxPlayers(); if (ArrayUtils.isNotEmpty(serverstatusresponse.getPlayerCountData().getPlayers())) { StringBuilder stringbuilder = new StringBuilder(); GameProfile[] agameprofile = serverstatusresponse.getPlayerCountData().getPlayers(); int i = agameprofile.length; for (int j = 0; j < i; ++j) { GameProfile gameprofile = agameprofile[j]; if (stringbuilder.length() > 0) { stringbuilder.append("\n"); } stringbuilder.append(gameprofile.getName()); } if (serverstatusresponse.getPlayerCountData().getPlayers().length < serverstatusresponse.getPlayerCountData().getOnlinePlayerCount()) { if (stringbuilder.length() > 0) { stringbuilder.append("\n"); } stringbuilder.append("... and ").append(serverstatusresponse.getPlayerCountData().getOnlinePlayerCount() - serverstatusresponse.getPlayerCountData().getPlayers().length).append(" more ..."); } server.playerList = stringbuilder.toString(); } } else { server.populationInfo = EnumChatFormatting.DARK_GRAY + "???"; } if (serverstatusresponse.getFavicon() != null) { String s = serverstatusresponse.getFavicon(); if (s.startsWith("data:image/png;base64,")) { server.setBase64EncodedIconData(s.substring("data:image/png;base64,".length())); } else { OldServerPinger.logger.error("Invalid server icon (unknown format)"); } } else { server.setBase64EncodedIconData((String)null); } FMLClientHandler.instance().bindServerListData(server, serverstatusresponse); networkmanager.scheduleOutboundPacket(new C01PacketPing(Minecraft.getSystemTime()), new GenericFutureListener[0]); this.field_147403_d = true; } public void handlePong(S01PacketPong packetIn) { long i = packetIn.func_149292_c(); long j = Minecraft.getSystemTime(); server.pingToServer = j - i; networkmanager.closeChannel(new ChatComponentText("Finished")); } /** * Invoked when disconnecting, the parameter is a ChatComponent describing the reason for termination */ public void onDisconnect(IChatComponent reason) { if (!this.field_147403_d) { OldServerPinger.logger.error("Can\'t ping " + server.serverIP + ": " + reason.getUnformattedText()); server.serverMOTD = EnumChatFormatting.DARK_RED + "Can\'t connect to server."; server.populationInfo = ""; OldServerPinger.this.tryCompatibilityPing(server); } } /** * Allows validation of the connection state transition. Parameters: from, to (connection state). Typically * throws IllegalStateException or UnsupportedOperationException if validation fails */ public void onConnectionStateTransition(EnumConnectionState oldState, EnumConnectionState newState) { if (newState != EnumConnectionState.STATUS) { throw new UnsupportedOperationException("Unexpected change in protocol to " + newState); } } /** * For scheduled network tasks. Used in NetHandlerPlayServer to send keep-alive packets and in * NetHandlerLoginServer for a login-timeout */ public void onNetworkTick() {} }); try { networkmanager.scheduleOutboundPacket(new C00Handshake(5, serveraddress.getIP(), serveraddress.getPort(), EnumConnectionState.STATUS), new GenericFutureListener[0]); networkmanager.scheduleOutboundPacket(new C00PacketServerQuery(), new GenericFutureListener[0]); } catch (Throwable throwable) { logger.error(throwable); } } private void tryCompatibilityPing(final ServerData server) { final ServerAddress serveraddress = ServerAddress.func_78860_a(server.serverIP); ((Bootstrap)((Bootstrap)((Bootstrap)(new Bootstrap()).group(NetworkManager.eventLoops)).handler(new ChannelInitializer() { private static final String __OBFID = "CL_00000894"; protected void initChannel(Channel p_initChannel_1_) { try { p_initChannel_1_.config().setOption(ChannelOption.IP_TOS, Integer.valueOf(24)); } catch (ChannelException channelexception1) { ; } try { p_initChannel_1_.config().setOption(ChannelOption.TCP_NODELAY, Boolean.valueOf(false)); } catch (ChannelException channelexception) { ; } p_initChannel_1_.pipeline().addLast(new ChannelHandler[] {new SimpleChannelInboundHandler() { private static final String __OBFID = "CL_00000895"; public void channelActive(ChannelHandlerContext p_channelActive_1_) throws Exception { super.channelActive(p_channelActive_1_); ByteBuf bytebuf = Unpooled.buffer(); try { bytebuf.writeByte(254); bytebuf.writeByte(1); bytebuf.writeByte(250); char[] achar = "MC|PingHost".toCharArray(); bytebuf.writeShort(achar.length); char[] achar1 = achar; int i = achar.length; int j; char c0; for (j = 0; j < i; ++j) { c0 = achar1[j]; bytebuf.writeChar(c0); } bytebuf.writeShort(7 + 2 * serveraddress.getIP().length()); bytebuf.writeByte(127); achar = serveraddress.getIP().toCharArray(); bytebuf.writeShort(achar.length); achar1 = achar; i = achar.length; for (j = 0; j < i; ++j) { c0 = achar1[j]; bytebuf.writeChar(c0); } bytebuf.writeInt(serveraddress.getPort()); p_channelActive_1_.channel().writeAndFlush(bytebuf).addListener(ChannelFutureListener.CLOSE_ON_FAILURE); } finally { bytebuf.release(); } } protected void channelRead0(ChannelHandlerContext p_channelRead0_1_, ByteBuf p_channelRead0_2_) { short short1 = p_channelRead0_2_.readUnsignedByte(); if (short1 == 255) { String s = new String(p_channelRead0_2_.readBytes(p_channelRead0_2_.readShort() * 2).array(), Charsets.UTF_16BE); String[] astring = (String[])Iterables.toArray(OldServerPinger.PING_RESPONSE_SPLITTER.split(s), String.class); if ("\u00a71".equals(astring[0])) { int i = MathHelper.parseIntWithDefault(astring[1], 0); String s1 = astring[2]; String s2 = astring[3]; int j = MathHelper.parseIntWithDefault(astring[4], -1); int k = MathHelper.parseIntWithDefault(astring[5], -1); server.version = -1; server.gameVersion = s1; server.serverMOTD = s2; server.populationInfo = EnumChatFormatting.GRAY + "" + j + "" + EnumChatFormatting.DARK_GRAY + "/" + EnumChatFormatting.GRAY + k; } } p_channelRead0_1_.close(); } public void exceptionCaught(ChannelHandlerContext p_exceptionCaught_1_, Throwable p_exceptionCaught_2_) { p_exceptionCaught_1_.close(); } protected void channelRead0(ChannelHandlerContext p_channelRead0_1_, Object p_channelRead0_2_) { this.channelRead0(p_channelRead0_1_, (ByteBuf)p_channelRead0_2_); } } }); } })).channel(NioSocketChannel.class)).connect(serveraddress.getIP(), serveraddress.getPort()); } public void pingPendingNetworks() { List list = this.pingDestinations; synchronized (this.pingDestinations) { Iterator iterator = this.pingDestinations.iterator(); while (iterator.hasNext()) { NetworkManager networkmanager = (NetworkManager)iterator.next(); if (networkmanager.isChannelOpen()) { networkmanager.processReceivedPackets(); } else { iterator.remove(); if (networkmanager.getExitMessage() != null) { networkmanager.getNetHandler().onDisconnect(networkmanager.getExitMessage()); } } } } } public void clearPendingNetworks() { List list = this.pingDestinations; synchronized (this.pingDestinations) { Iterator iterator = this.pingDestinations.iterator(); while (iterator.hasNext()) { NetworkManager networkmanager = (NetworkManager)iterator.next(); if (networkmanager.isChannelOpen()) { iterator.remove(); networkmanager.closeChannel(new ChatComponentText("Cancelled")); } } } } }