조금 늦었지만,이 정확한 코드는 Swift에서 한 번 작성되었습니다. 나는 그것을 오래 전에 썼다. 그래서 그것이 아직도 잘 작동하는지 나는 완전히 확신하지 않는다. 그러나 그것은해야한다. 또한 소켓 라이브러리 https://github.com/vapor/sockets이 필요합니다. 필자가 작성한 코드 중 가장 멋진 코드는 아니지만 서둘러서 간단히 던져 버렸습니다. 여기에 있습니다 :
import Foundation
import Sockets
import Dispatch
public class MinecraftQuery {
let STATISTIC: UInt8 = 0x00
let HANDSHAKE: UInt8 = 0x09
private let socket: UDPInternetSocket
private var challenge: [UInt8]? = nil
private var challengeNumber: Int32 = 0
private var last_connect_time = Date(timeIntervalSinceReferenceDate: 0)
private var response_received = false
private var update_queued = false
//toggle to prevent multple active connections
private var connection_active = false
public var serverInfo: [String: String] = [:]
public var playerList: [String] = []
init? (hostname: String, port: Port = 19132) {
do {
socket = try UDPInternetSocket(address: InternetAddress(hostname: hostname, port: port))
} catch (let error) {
debugPrint(error)
return nil
}
print("query_init working")
}
func connect() {
do {
try socket.sendto(data: [0xFE, 0xFD, self.HANDSHAKE, 0x01, 0x02, 0x03, 0x04 ])
// Should receive challenge
let temp_recv = try socket.recvfrom(maxBytes: 20)
guard temp_recv.sender == socket.address else {
print("Received query challenge from unknown source. Ignoring.")
return
}
guard temp_recv.data.starts(with: [self.HANDSHAKE, 1, 2, 3, 4]) else {
print("Received invalid challenge data. Ignoring.")
return
}
self.challenge = temp_recv.data
if let challengeString = String(utf8String: Array(challenge![5...].map({ (byte) -> Int8 in
Int8(byte)
}))) {
guard let challengeNumber = Int32(challengeString)?.byteSwapped else {
print("Could not convert challenge to number. Ignoring.")
return
}
self.challengeNumber = challengeNumber
}
} catch (let error) {
debugPrint(error)
}
}
func query() {
let queryData = Data([0xFE, 0xFD, self.STATISTIC, 1, 2, 3, 4]) + Data(bytes: &self.challengeNumber, count: 4) + [0, 0, 0, 0]
do {
try self.socket.sendto(data: Array(queryData))
let statisticRecv = try self.socket.recvfrom()
guard statisticRecv.sender == socket.address else {
print("Received statistics from unknown source. Ignoring.")
return
}
guard statisticRecv.data.starts(with: [0, 1, 2, 3, 4]) else {
print("Received invalid statistics data. Ignoring")
return
}
var resultsDict: [String: String] = [:]
let binStrings = statisticRecv.data[5...].split(separator: 0)
var playerHeaderIDX = 0
for index in 0..<binStrings.count {
if index % 2 == 0 {
if String(bytes: binStrings[index], encoding: .ascii) == "\u{01}player_" {
playerHeaderIDX = index
break
}
resultsDict[String(bytes: binStrings[index], encoding: .ascii)!] = String(bytes: binStrings[index + 1], encoding: .ascii)!
}
}
self.serverInfo = resultsDict
self.playerList = binStrings[(playerHeaderIDX + 1)...].map({ (binString) -> String in
if let returnString = String(bytes: binString, encoding: .ascii) {
return returnString
} else {
return ""
}
})
} catch (let error) {
debugPrint(error)
}
}
}
완료 방법을 보여주는 몇 가지 샘플 코드를 게시 할 수 있습니까? 자바? 나는 대부분의 사람들이 마인 크래프트 프로토콜을 모른다는 것을 모험한다. –
다음은 Java로 작성된 파일입니다. https://gist.github.com/zh32/7190955 – spacegeek224
@DavidShaw 질문에 추가했습니다. – spacegeek224