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.

Revisions

  1. Muska-Ami renamed this gist May 3, 2025. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  2. Muska-Ami created this gist May 3, 2025.
    137 changes: 137 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,137 @@
    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
    )
    }