Last active
January 21, 2025 19:26
-
-
Save Muska-Ami/70b524a302deebf97e49320bee848286 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package moe.muska.ami.example; | |
import com.alibaba.fastjson.JSON; | |
import com.alibaba.fastjson.JSONObject; | |
import java.io.ByteArrayOutputStream; | |
import java.io.DataInputStream; | |
import java.io.DataOutputStream; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.io.InputStreamReader; | |
import java.io.OutputStream; | |
import java.net.InetSocketAddress; | |
import java.net.Socket; | |
import java.util.ArrayList; | |
import java.util.List; | |
/** | |
* @author Muska_Ami | |
* @author zh32 <zh32 at zh32.de> | |
* @author 猫车车 | |
*/ | |
public class ServerListPing { | |
private InetSocketAddress host; | |
private int timeout = 7000; | |
public void setAddress(InetSocketAddress host) { | |
this.host = host; | |
} | |
public InetSocketAddress getAddress() { | |
return host; | |
} | |
public void setTimeout(int timeout) { | |
this.timeout = timeout; | |
} | |
public int getTimeout() { | |
return this.timeout; | |
} | |
public int readVarInt(DataInputStream in) throws IOException { | |
int i = 0; | |
int j = 0; | |
while (true) { | |
int k = in.readByte(); | |
i |= (k & 0x7F) << j++ * 7; | |
if (j > 5) throw new RuntimeException("VarInt too big"); | |
if ((k & 0x80) != 128) break; | |
} | |
return i; | |
} | |
public void writeVarInt(DataOutputStream out, int paramInt) throws IOException { | |
while (true) { | |
if ((paramInt & 0xFFFFFF80) == 0) { | |
out.writeByte(paramInt); | |
return; | |
} | |
out.writeByte(paramInt & 0x7F | 0x80); | |
paramInt >>>= 7; | |
} | |
} | |
public void fetchData() throws IOException { | |
Socket socket = new Socket(); | |
OutputStream outputStream; | |
DataOutputStream dataOutputStream; | |
InputStream inputStream; | |
InputStreamReader inputStreamReader; | |
socket.setSoTimeout(this.timeout); | |
socket.connect(host, timeout); | |
outputStream = socket.getOutputStream(); | |
dataOutputStream = new DataOutputStream(outputStream); | |
inputStream = socket.getInputStream(); | |
inputStreamReader = new InputStreamReader(inputStream); | |
ByteArrayOutputStream b = new ByteArrayOutputStream(); | |
DataOutputStream handshake = new DataOutputStream(b); | |
handshake.writeByte(0x00); //packet id for handshake | |
writeVarInt(handshake, 4); //protocol version | |
writeVarInt(handshake, host.getHostString().length()); //host length | |
handshake.writeBytes(host.getHostString()); //host string | |
handshake.writeShort(host.getPort()); //port | |
writeVarInt(handshake, 1); //state (1 for handshake) | |
writeVarInt(dataOutputStream, b.size()); //prepend size | |
dataOutputStream.write(b.toByteArray()); //write handshake packet | |
dataOutputStream.writeByte(0x01); //size is only 1 | |
dataOutputStream.writeByte(0x00); //packet id for ping | |
DataInputStream dataInputStream = new DataInputStream(inputStream); | |
int size = readVarInt(dataInputStream); //size of packet | |
int id = readVarInt(dataInputStream); //packet id | |
if (id == -1) { | |
throw new IOException("Premature end of stream."); | |
} | |
if (id != 0x00) { //we want a status response | |
throw new IOException("Invalid packetID"); | |
} | |
int length = readVarInt(dataInputStream); //length of json string | |
if (length == -1) { | |
throw new IOException("Premature end of stream."); | |
} | |
if (length == 0) { | |
throw new IOException("Invalid string length."); | |
} | |
byte[] in = new byte[length]; | |
dataInputStream.readFully(in); //read json string | |
String json = new String(in); | |
long now = System.currentTimeMillis(); | |
dataOutputStream.writeByte(0x09); //size of packet | |
dataOutputStream.writeByte(0x01); //0x01 for ping | |
dataOutputStream.writeLong(now); //time!? | |
readVarInt(dataInputStream); | |
id = readVarInt(dataInputStream); | |
if (id == -1) { | |
throw new IOException("Premature end of stream."); | |
} | |
if (id != 0x01) { | |
throw new IOException("Invalid packetID"); | |
} | |
//read response | |
JSONObject object = JSON.parseObject(json); | |
JSONObject players = JSON.parseObject(object.get("players").toString()); | |
JSONObject description = JSON.parseObject(object.get("description").toString()); | |
JSONObject version = JSON.parseObject(object.get("version").toString()); | |
List<Object> list = new ArrayList<Object>(JSON.parseArray(String.valueOf(description.get("extra")))); | |
StringBuilder Motd = new StringBuilder(); | |
for (Object o : list) { | |
JSONObject text = JSON.parseObject(o.toString()); | |
Motd.append(text.get("text")); | |
} | |
if (object.get("favicon").toString() != null) { | |
ServerListPing.Response.setIcon(object.get("favicon").toString()); | |
} else { | |
ServerListPing.Response.setIcon(""); | |
} | |
ServerListPing.Response.setPlayerMax(players.get("max").toString()); | |
ServerListPing.Response.setPlayerOnline(players.get("online").toString()); | |
ServerListPing.Response.setProtocol(version.get("protocol").toString()); | |
ServerListPing.Response.setVersion(version.get("name").toString()); | |
ServerListPing.Response.setMOTD(Motd.toString()); | |
dataOutputStream.close(); | |
outputStream.close(); | |
inputStreamReader.close(); | |
inputStream.close(); | |
socket.close(); | |
} | |
/** | |
* 获取请求结果 | |
*/ | |
public static class Response { | |
private static String player_max; | |
private static String protocol; | |
private static String player_online; | |
private static String version; | |
private static String motd; | |
private static String favicon; | |
public static String getPlayerMax() { | |
return Response.player_max; | |
} | |
public static String getPlayerOnline() { | |
return Response.player_online; | |
} | |
public static String getProtocol() { | |
return Response.protocol; | |
} | |
public static String getVersion() { | |
return Response.version; | |
} | |
public static String getMOTD() { | |
return Response.motd; | |
} | |
public static String getIcon() { | |
return favicon; | |
} | |
// 内部变量 设置结果 | |
private static void setPlayerMax(String player_max) { | |
Response.player_max = player_max; | |
} | |
private static void setPlayerOnline(String player_online) { | |
Response.player_online = player_online; | |
} | |
private static void setProtocol(String protocol) { | |
Response.protocol = protocol; | |
} | |
private static void setVersion(String version) { | |
Response.version = version; | |
} | |
private static void setMOTD(String motd) { | |
Response.motd = motd; | |
} | |
private static void setIcon(String favicon) { | |
Response.favicon = favicon; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment