Skip to content

Instantly share code, notes, and snippets.

@Muska-Ami
Created May 3, 2025 15:36
Show Gist options
  • Save Muska-Ami/69c4c9ccd201e3f9af8d67f8506b2c0f to your computer and use it in GitHub Desktop.
Save Muska-Ami/69c4c9ccd201e3f9af8d67f8506b2c0f to your computer and use it in GitHub Desktop.
BedrockMotd.kt
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