forked from KNEMC/KLALB
312 lines
7.7 KiB
Java
312 lines
7.7 KiB
Java
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);
|
|
}
|
|
|
|
|
|
}
|