Last active
August 29, 2015 14:01
-
-
Save tompng/734b9562c8f3a10ad639 to your computer and use it in GitHub Desktop.
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
require 'net/http' | |
require 'json' | |
module Minecraft | |
class Client | |
def initialize host | |
@host = host | |
end | |
def get path | |
Net::HTTP.get URI.parse("http://#{@host}#{path}") | |
end | |
def post path, params | |
http = Net::HTTP.new *@host.split(':') | |
http.post(path, params.to_json, {'Content-Type' => 'application/json'}).body | |
end | |
#setblock 'minecraft:glass', x:1, y:1, z:1 | |
def setblock name, pos | |
setblocks [name: name, position: pos] | |
end | |
def setblocks blocks | |
post '/setblocks', blocks: blocks | |
end | |
def getblock pos | |
getblocks([pos]).first | |
end | |
def getblocks positions | |
begin | |
blocks = JSON.parse post('/getblocks', positions: positions) | |
blocks.map{|name| | |
if Minecraft::Block.const_defined?(name) | |
Minecraft::Block.const_get(name) | |
else | |
name | |
end | |
} | |
rescue => e | |
[] | |
end | |
end | |
#find name: 'tompng' #=> {x: 123.456, y: 62, z: 9.876} | |
def find name | |
begin | |
res = get "/find/#{name}" | |
pos = JSON.parse(res) | |
{x: pos['x'], y: pos['y'], z: pos['z']} if pos | |
rescue | |
end | |
end | |
#move 'tompng', x: 1, y: 62, z: 3 | |
#move 'tompng', dx: 0, dy: 1, dz: 0 | |
def move name, pos | |
post "/move/#{name}", position: pos | |
end | |
#summon 'Zombie', x:1, y:100, z:2 | |
def summon name, pos | |
post '/summon', name: name, position: pos | |
end | |
def call command | |
post '/call', command: command | |
end | |
end | |
end | |
module Minecraft | |
module Block | |
block_types = %w(air stone grass dirt cobblestone planks sapling bedrock flowing_water water flowing_lava lava sand gravel gold_ore iron_ore coal_ore log leaves sponge glass lapis_ore lapis_block dispenser sandstone noteblock bed golden_rail detector_rail sticky_piston web tallgrass deadbush piston piston_head wool piston_extension yellow_flower red_flower brown_mushroom red_mushroom gold_block iron_block double_stone_slab stone_slab brick_block tnt bookshelf mossy_cobblestone obsidian torch fire mob_spawner oak_stairs chest redstone_wire diamond_ore diamond_block crafting_table wheat farmland furnace lit_furnace standing_sign wooden_door ladder rail stone_stairs wall_sign lever stone_pressure_plate iron_door wooden_pressure_plate redstone_ore lit_redstone_ore unlit_redstone_torch redstone_torch stone_button snow_layer ice snow cactus clay reeds jukebox fence pumpkin netherrack soul_sand glowstone portal lit_pumpkin cake unpowered_repeater powered_repeater stained_glass trapdoor monster_egg stonebrick brown_mushroom_block red_mushroom_block iron_bars glass_pane melon_block pumpkin_stem melon_stem vine fence_gate brick_stairs stone_brick_stairs mycelium waterlily nether_brick nether_brick_fence nether_brick_stairs nether_wart enchanting_table brewing_stand cauldron end_portal end_portal_frame end_stone dragon_egg redstone_lamp lit_redstone_lamp double_wooden_slab wooden_slab cocoa sandstone_stairs emerald_ore ender_chest tripwire_hook tripwire emerald_block spruce_stairs birch_stairs jungle_stairs command_block beacon cobblestone_wall flower_pot carrots potatoes wooden_button skull anvil trapped_chest light_weighted_pressure_plate heavy_weighted_pressure_plate unpowered_comparator powered_comparator daylight_detector redstone_block quartz_ore hopper quartz_block quartz_stairs activator_rail dropper stained_hardened_clay stained_glass_pane leaves2 log2 acacia_stairs dark_oak_stairs hay_block carpet hardened_clay coal_block packed_ice double_plant) | |
block_types.each{|name| | |
const_set name.split('_').map(&:capitalize).join, "minecraft:#{name}" | |
} | |
end | |
end | |
require 'pry' | |
m = Minecraft::Client.new '192.168.1.3:4567' | |
binding.pry | |
# loop{ | |
# begin | |
# pos = m.find(:tompng) | |
# m.setblocks (-1..1).to_a.product((-1..1).to_a).map{|x,z| | |
# { | |
# name: Minecraft::Block::Leaves, | |
# position: {x: pos[:x]+x, y: [pos[:y]-1, 70].min, z: pos[:z]+z} | |
# } | |
# } | |
# rescue => e | |
# sleep 1 | |
# end | |
# sleep 0.25 | |
# } |
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
require 'pry' | |
require 'timeout' | |
require 'json' | |
require 'sinatra' | |
require 'active_support/core_ext/hash/indifferent_access' | |
command = 'cd bin;java -Xmx1024M -Xms1024M -jar minecraft_server.1.7.9.jar nogui' | |
module Minecraft | |
refine Hash do | |
def to_minecraft | |
'[' + map{|key, value|"#{key}=#{value}"}.join(',') + ']' | |
end | |
end | |
end | |
module Minecraft | |
Events = [] | |
Events << (/.+ joined the game$/) | |
end | |
class Minecraft::CommandExecutor | |
def initialize command | |
@queue = Queue.new | |
@mutex = Mutex.new | |
@io = IO.popen command, "r+" | |
Thread.new{ | |
begin | |
@io.each_line do |line| | |
p line | |
next unless /^\[..:..:..\] \[Server thread\/INFO\]: (?<response>.+)$/ =~ line.chomp | |
next if Minecraft::Events.any?{|pattern|pattern =~ response} | |
notify response | |
end | |
exit | |
rescue => e | |
p e | |
end | |
} | |
end | |
def notify response | |
@queue << response | |
end | |
def call command, option={} | |
p command | |
@mutex.synchronize do | |
@queue.clear | |
@io.puts command | |
unless option.key?(:response) && !option[:response] | |
return timeout(0.1){@queue.pop} | |
end | |
end | |
rescue | |
end | |
def find name | |
if /^Teleported .+ to (?<x>[\d.-]+),(?<y>[\d.-]+),(?<z>[\d.-]+)/ =~ call("tp #{name} ~0 ~0 ~0") | |
{x: x.to_f, y: y.to_f, z: z.to_f} | |
end | |
rescue | |
end | |
def move name, pos | |
x = pos[:x] || (pos[:dx] ? "~#{pos[:dx]}" : '~0') | |
y = pos[:y] || (pos[:dy] ? "~#{pos[:dy]}" : '~0') | |
z = pos[:z] || (pos[:dz] ? "~#{pos[:dz]}" : '~0') | |
call "tp #{name} #{x} #{y} #{z}", response: false | |
end | |
def setblock name, pos | |
call "setblock #{pos[:x].floor} #{pos[:y].floor} #{pos[:z].floor} #{name}", response: false | |
end | |
def getblock pos | |
response = call "testforblock #{pos[:x].floor} #{pos[:y].floor} #{pos[:z].floor} minecraft:air" | |
if /^Successfully/ =~ response | |
'Air' | |
elsif /^The block at .+ is (?<name>[^ ]+)/ =~ response | |
name | |
end | |
end | |
def summon name, pos | |
call "summon #{name} #{pos[:x]} #{pos[:y]} #{pos[:z]}", response: false | |
end | |
def test name, pos, r | |
result = call("xp 0 @p[name=#{name},x=#{pos[:x].round},y=#{pos[:y].round},z=#{pos[:z].round},r=#{r.ceil}]") | |
!!result.match(/^Given 0 experience to/) | |
end | |
def stop | |
call 'stop', response: false | |
end | |
end | |
minecraft = Minecraft::CommandExecutor.new command | |
before do | |
return unless request.content_type == 'application/json' | |
body = HashWithIndifferentAccess.new JSON.parse request.body.read | |
body.each{|key, value| | |
params[key] ||= value | |
} | |
end | |
set :bind, '0.0.0.0' | |
get '/find/:name' do | |
minecraft.find(params[:name]).to_json | |
end | |
post '/move/:name' do | |
minecraft.move(params[:name], params[:position]) | |
end | |
post '/setblocks' do | |
params[:blocks].each{|block| | |
minecraft.setblock(block[:name], block[:position]) | |
} | |
nil | |
end | |
post '/getblocks' do | |
params[:positions].map{|pos| | |
minecraft.getblock pos | |
}.to_json | |
end | |
post '/summon' do | |
minecraft.summon(params[:name], params[:position]) | |
end | |
post '/call' do | |
minecraft.call(params[:command]).to_s | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment