Created
May 3, 2025 15:36
-
-
Save Muska-Ami/69c4c9ccd201e3f9af8d67f8506b2c0f to your computer and use it in GitHub Desktop.
BedrockMotd.kt
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
import java.net.DatagramPacket | |
import java.net.DatagramSocket | |
import java.net.InetAddress | |
import java.nio.ByteBuffer | |
import java.nio.ByteOrder | |
import java.util.concurrent.TimeUnit | |
class BedrockMotd { | |
/*** | |
* Ping | |
* | |
* @param timeout 超时时间 | |
* @param address 服务器地址 | |
*/ | |
fun ping(timeout: Int, address: String): BedrockMotdResponse { | |
return send(timeout, address) | |
} | |
/*** | |
* Ping | |
* | |
* @param timeout 超时时间 | |
* @param address 服务器端口 | |
*/ | |
fun ping(timeout: Int, address: String, port: Int): BedrockMotdResponse { | |
return send(timeout, address, port) | |
} | |
/** | |
* 发送请求 | |
*/ | |
private fun send(timeout: Int, address: String, port: Int = 19132): BedrockMotdResponse { | |
val socket = DatagramSocket() | |
val dataResponse: ByteArray | |
val startTime: Long | |
val endTime: Long | |
try { | |
startTime = System.nanoTime() | |
sendData(socket, InetAddress.getByName(address), port) | |
dataResponse = receive(socket, timeout) | |
endTime = System.nanoTime() | |
} catch (_: Exception) { | |
return BedrockMotdResponse(status = "offline") | |
} | |
val delay: Long = (endTime - startTime) / 1000000 | |
return parseResult(dataResponse, delay) | |
} | |
/** | |
* 发送数据 | |
*/ | |
private fun sendData(socket: DatagramSocket, address: InetAddress, port: Int) { | |
fun createSendData(): ByteArray { | |
val packetId = byteArrayOf(0x01) | |
val clientSendTime = ByteBuffer.allocate(8) | |
.order(ByteOrder.BIG_ENDIAN) | |
.putLong(TimeUnit.MILLISECONDS.toMillis(System.currentTimeMillis())) | |
.array() | |
val magic = byteArrayOf( | |
0x00, | |
0xFF.toByte(), | |
0xFF.toByte(), | |
0x00, | |
0xFE.toByte(), | |
0xFE.toByte(), | |
0xFE.toByte(), | |
0xFE.toByte(), | |
0xFD.toByte(), | |
0xFD.toByte(), | |
0xFD.toByte(), | |
0xFD.toByte() | |
) | |
val clientId = byteArrayOf(0x12, 0x34, 0x56, 0x78, 0x00) | |
val clientGuid = ByteArray(8) // Initialize with zeros | |
return packetId + clientSendTime + magic + clientId + clientGuid | |
} | |
val bytesData = createSendData() | |
val packet = DatagramPacket(bytesData, bytesData.size, address, port) | |
socket.send(packet) | |
} | |
/** | |
* 接收数据 | |
*/ | |
private fun receive(socket: DatagramSocket, timeout: Int): ByteArray { | |
val receiveData = ByteArray(256) | |
socket.soTimeout = timeout | |
val receivePacket = DatagramPacket(receiveData, receiveData.size) | |
socket.receive(receivePacket) | |
return receiveData | |
} | |
/** | |
* 解析结果 | |
*/ | |
private fun parseResult(response: ByteArray, delay: Long): BedrockMotdResponse { | |
val serverInfo = response.sliceArray(33 until response.size) | |
val motdData = String(serverInfo).split(";") | |
val motdLine1 = motdData[1] | |
val motdLine2 = motdData[7] | |
val protocolVersion = motdData[2].toInt() | |
val versionName = motdData[3] | |
val players = motdData[4].toInt() | |
val maxPlayers = motdData[5].toInt() | |
val serverUniqueId = motdData[6] | |
val gameMode = motdData[8] | |
return BedrockMotdResponse( | |
status = "online", | |
motds = arrayListOf(motdLine1, motdLine2), | |
protocol = protocolVersion, | |
version = versionName, | |
onlinePlayers = players, | |
maxPlayers = maxPlayers, | |
gameMode = gameMode, | |
uniqueId = serverUniqueId, | |
delay = delay, | |
) | |
} | |
data class BedrockMotdResponse( | |
val status: String, | |
val motds: List<String>? = null, | |
val protocol: Int? = null, | |
val version: String? = null, | |
val onlinePlayers: Int? = null, | |
val maxPlayers: Int? = null, | |
val gameMode: String? = null, | |
val uniqueId: String? = null, | |
val delay: Long? = null | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment