package org.kne.cloud.network.minecraft; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.EOFException; import java.io.IOException; import java.io.Serializable; import java.net.Inet6Address; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; import java.util.Base64; import javax.imageio.ImageIO; import org.kne.cloud.network.MultiProtocolSocketAddress; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; public class MinecraftServerPinger implements Serializable{ /** * */ private static final long serialVersionUID = 1L; private transient Socket socket; private transient MinecraftProtocolContext mpc=new MinecraftProtocolContext(); private MultiProtocolSocketAddress targetaddr; private long latency=-1; private String json; //private BufferedImage icon; private int max; private int online; private String description; private boolean isOldDescription; private String version; private int protocol; private String klalbversion; private Inet6Address klalbvaddr; private int klalbvport; private String icon; private transient BufferedImage image; public MinecraftServerPinger(MultiProtocolSocketAddress target) throws UnknownHostException, IOException { this(target,target.connectSocket()); } public MinecraftServerPinger(MultiProtocolSocketAddress target, Socket Asocket) throws UnknownHostException, IOException{ targetaddr=target; socket=Asocket; socket.setTcpNoDelay(true); ping(); analyseJson(); } private void ping() throws IOException { MinecraftInputStream in=null; MinecraftOutputStream out=null; try { in=new MinecraftInputStream(socket.getInputStream(), mpc); out=new MinecraftOutputStream(socket.getOutputStream(), mpc); if(targetaddr instanceof MinecraftServerAddress) { out.writePacket(new MinecraftHandShakePacket(763, ((MinecraftServerAddress) targetaddr).getOriginAddr(), ((MinecraftServerAddress) targetaddr).getOriginPort(), 1)); }else { out.writePacket(new MinecraftHandShakePacket(763, targetaddr.getHost(), targetaddr.getPort(), 1)); } out.writePacket(new MinecraftMotdRequest()); out.flush(); MinecraftMotdResponse resp=(MinecraftMotdResponse) in.readPacket(); if(resp==null) throw new EOFException(); json=resp.getJson(); long pst=System.nanoTime(); out.writePacket(new MinecraftPingPacket(pst)); out.flush(); try { MinecraftPongPacket repo=(MinecraftPongPacket) in.readPacket(); latency=System.nanoTime()-repo.getTime(); }catch(EOFException e) { } }finally { try { if(in!=null) in.close(); }catch(IOException e) {} try { if(out!=null) out.close(); }catch(IOException e) {} try { if(socket!=null) socket.close(); }catch(IOException e) {} } } private void analyseJson() { // System.out.println(json); JsonObject jobj= (JsonObject) new JsonParser().parse(json); JsonObject versiont=(JsonObject) jobj.get("version"); if(versiont!=null) { version=versiont.get("name").getAsString(); protocol=versiont.get("protocol").getAsInt(); } JsonObject players=(JsonObject) jobj.get("players"); if(players!=null) { max=players.get("max").getAsInt(); online=players.get("online").getAsInt(); } JsonElement descriptionj =jobj.get("description"); if(descriptionj!=null) { isOldDescription=!(descriptionj instanceof JsonObject); if(isOldDescription) { description=descriptionj.getAsString(); }else { description=descriptionj.toString(); } } JsonElement klalb= jobj.get("KLALB"); if(klalb!=null&&(klalb instanceof JsonObject)) { JsonObject jobk=(JsonObject) klalb; klalbversion=jobk.get("version").getAsString(); try { klalbvaddr=(Inet6Address) InetAddress.getByName( jobk.get("vaddr").getAsString()); } catch (UnknownHostException e) { e.printStackTrace(); } klalbvport=jobk.get("vport").getAsInt(); } JsonElement favicon= jobj.get("favicon"); if(favicon!=null) { String s=favicon.getAsString(); if(s.startsWith("data:image/png;base64,")){ icon=s.replace("\n", ""); } } /*try { JsonReader jr = new JsonReader(new StringReader(json)); jr.setLenient(true); jr.beginObject(); while (jr.hasNext()) { String n0 = jr.nextName(); switch (n0) { case "version": jr.beginObject(); while (jr.hasNext()) { String n1 = jr.nextName(); switch (n1) { case "name": version=jr.nextString(); break; default: jr.skipValue(); break; } } jr.endObject(); break; case "players": jr.beginObject(); while (jr.hasNext()) { String n1 = jr.nextName(); switch (n1) { case "max": max=jr.nextInt(); break; case "online": online=jr.nextInt(); break; default: jr.skipValue(); break; } } jr.endObject(); break; case "description": JsonToken j=jr.peek(); if(j.equals(JsonToken.BEGIN_OBJECT)){ jr.beginObject(); while (jr.hasNext()) { String n1 = jr.nextName(); switch (n1) { case "text": description=jr.nextString(); break; default: jr.skipValue(); break; } } jr.endObject(); }else{ description=jr.nextString(); } break; case "favicon": String s=jr.nextString(); if(s.startsWith("data:image/png;base64,")){ s=s.replace("\n", ""); icon=ImageIO.read(new ByteArrayInputStream(Base64.getDecoder().decode(s.substring("data:image/png;base64,".length())))); } break; case "KLALB": klalbversion=jr.nextString(); break; default: jr.skipValue(); break; } } jr.endObject(); jr.close(); //System.out.println(time); } catch (IOException e) { e.printStackTrace(); }*/ } @Override public String toString() { return "MinecraftServerPinger [targetaddr=" + targetaddr + ", latency=" + latency + ", json=" + json + ", icon=" + icon + ", max=" + max + ", online=" + online + ", description=" + description + ", isOldDescription=" + isOldDescription + ", version=" + version + ", protocol=" + protocol + ", klalbversion=" + klalbversion + ", klalbvaddr=" + klalbvaddr+ ", klalbvport=" + klalbvport+ "]"; } public String getKlalbversion() { return klalbversion; } public Inet6Address getKlalbvaddr() { return klalbvaddr; } public int getKlalbvport() { return klalbvport; } public BufferedImage getIcon() { if(icon==null) return null; if(image==null) try { image= ImageIO.read(new ByteArrayInputStream(Base64.getDecoder().decode(icon.substring("data:image/png;base64,".length())))); } catch (IOException e) { e.printStackTrace(); } return image; } public int getMax() { return max; } public int getOnline() { return online; } public String getDescription() { return description; } public String getVersion() { return version; } public int getProtocol() { return protocol; } public boolean isOldDescription() { return isOldDescription; } public String getJson() { return json; } public MultiProtocolSocketAddress getTargetaddr() { return targetaddr; } public long getLatency() { return latency; } public static void main(String[] args) throws UnknownHostException, IOException {//hypixel.net MinecraftServerPinger sp=new MinecraftServerPinger(MinecraftServerAddress.findAddress("mc.hypixel.cn")); System.out.println(sp); } }