Skip to content

Instantly share code, notes, and snippets.

@ryush00
Forked from 4poc/gist:6281388
Last active February 23, 2016 16:55
Show Gist options
  • Save ryush00/5a5bf481c9536a422e0f to your computer and use it in GitHub Desktop.
Save ryush00/5a5bf481c9536a422e0f to your computer and use it in GitHub Desktop.
require 'socket'
##
# Pings a minecraft server and returns motd and playercount.
# Works with ruby >=1.9.3/2.0.0
#
# More information and sample code here:
# http://wiki.vg/Server_List_Ping
##
class MinecraftPing
def initialize(host, port=25565)
@host = host
@port = port
end
def ping
socket = TCPSocket.open(@host, @port)
# packet identifier & payload ...
socket.write([0xFE, 0x01, 0xFA].pack('CCC'))
socket.write(encode_string('MC|PingHost'))
socket.write([7 + 2 * @host.length].pack('n'))
socket.write([74].pack('c'))
socket.write(encode_string(@host))
socket.write([@port].pack('N'))
# read server response
if socket.read(1).unpack('C').first != 0xFF # Kick packet
raise 'unexpected server response packet'
end
len = socket.read(2).unpack('n').first
resp = decode_string(socket.read(len*2)).split("\u0000")
socket.close
if resp.shift != "\u00A71"
raise 'unexpected server response fields'
end
return {
:protocol_version => resp.shift.to_i,
:minecraft_version => resp.shift,
:motd => resp.shift,
:current_players => resp.shift.to_i,
:max_players => resp.shift.to_i
}
end
private
def encode_string(s)
begin
[s.length].pack('n') + Iconv.conv('utf-16be', 'utf-8', s)
rescue
[s.length].pack('n') + s.encode('utf-16be').force_encoding('ASCII-8BIT')
end
end
def decode_string(s)
begin
Iconv.conv('utf-8', 'utf-16be', s)
rescue
s.force_encoding('utf-16be').encode('utf-8')
end
end
end
puts MinecraftPing.new('aztec.geekosphere.org').ping.inspect
puts MinecraftPing.new('night.no-ip.org', 25565).ping.inspect
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment