minecraft-pi-ruby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ *.gem
@@ -0,0 +1,142 @@
1
+ #Minecraft-Pi Ruby
2
+
3
+ ##Please note
4
+ This project is still in the early stages of development. It is not ready for use
5
+ with students and has not yet been pushed to RubyGems.
6
+
7
+ ##Overview
8
+
9
+ This is a Ruby gem to allow access to the Minecraft Pi Edition API from Ruby.
10
+ The aim is that the syntax is clear for fledgling coders to read and
11
+ understand as they work towards creating their own scripts.
12
+
13
+ All the fun of Minecraft Pi Edition and all the goodness of Ruby! With Sonic Pi,
14
+ KidsRuby and Minecraft, there really is no reason not to show you students the
15
+ joy of Ruby programming!
16
+
17
+ ##Introduction
18
+ The Pi Edition of Minecraft needs to be running for the gem to make a connection. Then you can use Ruby
19
+ code such as:
20
+ ```
21
+ Minecraft.world do
22
+ say "Hello from Ruby!"
23
+
24
+ position1 = Position.new(0,10,0)
25
+ position2 = Position.new(10,20,10)
26
+ make_cuboid(position1, position2, Block::DIAMOND_BLOCK)
27
+ sleep 2
28
+ make_cuboid(position1, position2, Block::AIR)
29
+
30
+ 10.times do |counter|
31
+ set_block(counter, 20, 0, Block::STONE)
32
+ set_block(counter, 20, 9, Block::STONE)
33
+ set_block(0, 20, counter, Block::STONE)
34
+ set_block(9, 20, counter, Block::STONE)
35
+ end
36
+
37
+ say "Bye from Ruby!"
38
+ end
39
+ ```
40
+
41
+ You can also instantiate a Minecraft object instead of writing script inside Ruby blocks.
42
+ For example:
43
+ ```
44
+ mc = Minecraft.new
45
+ mc.say 'Hello to Steve!'
46
+ mc.make_cuboid(16,18,16,20,20,20,Block::TNT,1)
47
+ mc.say 'Now go and click on the TNT!'
48
+ ```
49
+ ##Installation
50
+
51
+ TODO
52
+
53
+ ##Usage
54
+
55
+ So far, only the following commands have been implemented
56
+
57
+ - `say "message"` to display a message on the screen
58
+ - `set_camera_mode` to either `:fixed`, `:normal` or `:follow`
59
+ - `set_block` takes 3 values for the x, y and z location, or a Position (`Position.new(x,y,z)`)
60
+ - `set_blocks` is the same as `make_cuboid`. It takes 2 Positions and an ID for the block (see below), or
61
+ two sets of x,y,z coordinates followed by the block ID. For example: `make_cuboid(0,0,0,20,20,20,Block::OBSIDIAN)`.
62
+ - `get_ground_height(x,z)` or just `ground_height(x,z)` return the height of the ground at the (x,z) location
63
+ - `set_player_position(x,y,z)` or `set_player_position(Position)` moves the player to that position
64
+
65
+ ###Block IDs
66
+
67
+ Blocks can be set using and ID in the form Block::NAME. For example Block::TNT.
68
+
69
+ The blocks are:
70
+
71
+ - AIR numerical value is 0
72
+ - STONE numerical value is 1
73
+ - GRASS numerical value is 2
74
+ - DIRT numerical value is 3
75
+ - COBBLESTONE numerical value is 4
76
+ - WOOD_PLANKS numerical value is 5
77
+ - SAPLING numerical value is 6
78
+ - BEDROCK numerical value is 7
79
+ - WATER_FLOWING numerical value is 8
80
+ - WATER numerical value is WATER_FLOWING
81
+ - WATER_STATIONARY numerical value is 9
82
+ - LAVA_FLOWING numerical value is 10
83
+ - LAVA numerical value is LAVA_FLOWING
84
+ - LAVA_STATIONARY numerical value is 11
85
+ - SAND numerical value is 12
86
+ - GRAVEL numerical value is 13
87
+ - GOLD_ORE numerical value is 14
88
+ - IRON_ORE numerical value is 15
89
+ - COAL_ORE numerical value is 16
90
+ - WOOD numerical value is 17
91
+ - LEAVES numerical value is 18
92
+ - GLASS numerical value is 20
93
+ - LAPIS_LAZULI_ORE numerical value is 21
94
+ - LAPIS_LAZULI_BLOCK numerical value is 22
95
+ - SANDSTONE numerical value is 24
96
+ - BED numerical value is 26
97
+ - COBWEB numerical value is 30
98
+ - GRASS_TALL numerical value is 31
99
+ - WOOL numerical value is 35
100
+ - FLOWER_YELLOW numerical value is 37
101
+ - FLOWER_CYAN numerical value is 38
102
+ - MUSHROOM_BROWN numerical value is 39
103
+ - MUSHROOM_RED numerical value is 40
104
+ - GOLD_BLOCK numerical value is 41
105
+ - IRON_BLOCK numerical value is 42
106
+ - STONE_SLAB_DOUBLE numerical value is 43
107
+ - STONE_SLAB numerical value is 44
108
+ - BRICK_BLOCK numerical value is 45
109
+ - TNT numerical value is 46
110
+ - BOOKSHELF numerical value is 47
111
+ - MOSS_STONE numerical value is 48
112
+ - OBSIDIAN numerical value is 49
113
+ - TORCH numerical value is 50
114
+ - FIRE numerical value is 51
115
+ - STAIRS_WOOD numerical value is 53
116
+ - CHEST numerical value is 54
117
+ - DIAMOND_ORE numerical value is 56
118
+ - DIAMOND_BLOCK numerical value is 57
119
+ - CRAFTING_TABLE numerical value is 58
120
+ - FARMLAND numerical value is 60
121
+ - FURNACE_INACTIVE numerical value is 61
122
+ - FURNACE_ACTIVE numerical value is 62
123
+ - DOOR_WOOD numerical value is 64
124
+ - LADDER numerical value is 65
125
+ - STAIRS_COBBLESTONE numerical value is 67
126
+ - DOOR_IRON numerical value is 71
127
+ - REDSTONE_ORE numerical value is 73
128
+ - SNOW numerical value is 78
129
+ - ICE numerical value is 79
130
+ - SNOW_BLOCK numerical value is 80
131
+ - CACTUS numerical value is 81
132
+ - CLAY numerical value is 82
133
+ - SUGAR_CANE numerical value is 83
134
+ - FENCE numerical value is 85
135
+ - GLOWSTONE_BLOCK numerical value is 89
136
+ - BEDROCK_INVISIBLE numerical value is 95
137
+ - STONE_BRICK numerical value is 98
138
+ - GLASS_PANE numerical value is 102
139
+ - MELON numerical value is 103
140
+ - FENCE_GATE numerical value is 107
141
+ - GLOWING_OBSIDIAN numerical value is 246
142
+ - NETHER_REACTOR_CORE numerical value is 247
@@ -0,0 +1,74 @@
1
+ module Block
2
+ AIR = 0
3
+ STONE = 1
4
+ GRASS = 2
5
+ DIRT = 3
6
+ COBBLESTONE = 4
7
+ WOOD_PLANKS = 5
8
+ SAPLING = 6
9
+ BEDROCK = 7
10
+ WATER_FLOWING = 8
11
+ WATER = WATER_FLOWING
12
+ WATER_STATIONARY = 9
13
+ LAVA_FLOWING = 10
14
+ LAVA = LAVA_FLOWING
15
+ LAVA_STATIONARY = 11
16
+ SAND = 12
17
+ GRAVEL = 13
18
+ GOLD_ORE = 14
19
+ IRON_ORE = 15
20
+ COAL_ORE = 16
21
+ WOOD = 17
22
+ LEAVES = 18
23
+ GLASS = 20
24
+ LAPIS_LAZULI_ORE = 21
25
+ LAPIS_LAZULI_BLOCK = 22
26
+ SANDSTONE = 24
27
+ BED = 26
28
+ COBWEB = 30
29
+ GRASS_TALL = 31
30
+ WOOL = 35
31
+ FLOWER_YELLOW = 37
32
+ FLOWER_CYAN = 38
33
+ MUSHROOM_BROWN = 39
34
+ MUSHROOM_RED = 40
35
+ GOLD_BLOCK = 41
36
+ IRON_BLOCK = 42
37
+ STONE_SLAB_DOUBLE = 43
38
+ STONE_SLAB = 44
39
+ BRICK_BLOCK = 45
40
+ TNT = 46
41
+ BOOKSHELF = 47
42
+ MOSS_STONE = 48
43
+ OBSIDIAN = 49
44
+ TORCH = 50
45
+ FIRE = 51
46
+ STAIRS_WOOD = 53
47
+ CHEST = 54
48
+ DIAMOND_ORE = 56
49
+ DIAMOND_BLOCK = 57
50
+ CRAFTING_TABLE = 58
51
+ FARMLAND = 60
52
+ FURNACE_INACTIVE = 61
53
+ FURNACE_ACTIVE = 62
54
+ DOOR_WOOD = 64
55
+ LADDER = 65
56
+ STAIRS_COBBLESTONE = 67
57
+ DOOR_IRON = 71
58
+ REDSTONE_ORE = 73
59
+ SNOW = 78
60
+ ICE = 79
61
+ SNOW_BLOCK = 80
62
+ CACTUS = 81
63
+ CLAY = 82
64
+ SUGAR_CANE = 83
65
+ FENCE = 85
66
+ GLOWSTONE_BLOCK = 89
67
+ BEDROCK_INVISIBLE = 95
68
+ STONE_BRICK = 98
69
+ GLASS_PANE = 102
70
+ MELON = 103
71
+ FENCE_GATE = 107
72
+ GLOWING_OBSIDIAN = 246
73
+ NETHER_REACTOR_CORE = 247
74
+ end
@@ -0,0 +1,31 @@
1
+ require 'socket'
2
+
3
+ class Connection
4
+ def initialize (server = 'localhost', port = 4711)
5
+ begin
6
+ @socket = TCPSocket.new server, port
7
+ rescue
8
+ puts "Error connecting to Minecraft. Is it running?\n\n"
9
+ @socket.close if @socket
10
+ abort("#{$!}")
11
+ end
12
+ end
13
+
14
+ def send_command(command)
15
+ if @socket
16
+ @socket.puts command
17
+ else
18
+ puts "Not connected to Minecraft Pi! Is it running?"
19
+ end
20
+ end
21
+
22
+ def send_with_response(command)
23
+ send_command command
24
+ return @socket.gets.chomp
25
+ end
26
+
27
+
28
+ def Connection.finalize(id)
29
+ @socket.close if @socket
30
+ end
31
+ end
@@ -0,0 +1,87 @@
1
+ require_relative 'connection'
2
+ require_relative 'position'
3
+ require_relative 'blocks'
4
+
5
+ class Minecraft
6
+ include Block
7
+
8
+ def initialize(connection = nil)
9
+ @connection = connection
10
+ @connection ||= Connection.new
11
+ end
12
+
13
+ class << self
14
+ def control(&script)
15
+ mc = self.new
16
+ mc.instance_eval(&script)
17
+ end
18
+
19
+ alias_method :world, :control
20
+ end
21
+
22
+ def say(message)
23
+ @connection.send_command "chat.post(#{message})"
24
+ end
25
+
26
+ def set_camera_mode(mode)
27
+ @connection.send_command 'camera.mode.setNormal' if mode == :normal
28
+ @connection.send_command 'camera.mode.setFixed' if mode == :fixed
29
+ @connection.send_command 'camera.mode.setFollow' if mode == :follow
30
+ end
31
+
32
+ def set_block(*args)
33
+ command = "world.setBlock("
34
+ case args.length
35
+ when 2
36
+ command = command + "#{args[0]},#{args[1]})"
37
+ when 3
38
+ command += "#{args[0]},#{args[1]},#{args[2]})"
39
+ when 4
40
+ command += "#{args[0]},#{args[1]},#{args[2]},#{args[3]})"
41
+ when 5
42
+ command += "#{args[0]},#{args[1]},#{args[2]},#{args[3]},#{args[4]})"
43
+ else
44
+ return
45
+ end
46
+ @connection.send_command command
47
+ end
48
+
49
+ def set_blocks(*args)
50
+ command = "world.setBlocks("
51
+ case args.length
52
+ when 3
53
+ command += "#{args[0]},#{args[1]},#{args[2]})"
54
+ when 4
55
+ command += "#{args[0]},#{args[1]},#{args[2]},#{args[3]})"
56
+ when 7
57
+ command += "#{args[0]},#{args[1]},#{args[2]},#{args[3]},#{args[4]},#{args[5]},#{args[6]})"
58
+ when 8
59
+ command += "#{args[0]},#{args[1]},#{args[2]},#{args[3]},#{args[4]},#{args[5]},#{args[6]},#{args[7]})"
60
+ else
61
+ return
62
+ end
63
+ @connection.send_command command
64
+ end
65
+ alias_method :make_cuboid, :set_blocks
66
+
67
+ def get_ground_height(x,z)
68
+ return @connection.send_with_response "world.getHeight(#{x},#{z})"
69
+ #return s
70
+ end
71
+ alias_method :ground_height, :get_ground_height
72
+
73
+ def set_player_position(*args)
74
+ command = "player.setPos("
75
+ case args.length
76
+ when 1
77
+ command += "#{args[0].x},#{args[0].y},#{args[0].z})"
78
+ when 3
79
+ command += "#{args[0]},#{args[1]},#{args[2]})"
80
+ else
81
+ return
82
+ end
83
+ @connection.send_command command
84
+ end
85
+
86
+ end
87
+
@@ -0,0 +1,52 @@
1
+ class Position
2
+
3
+ attr_accessor :x, :y, :z
4
+
5
+ def initialize (x,y,z)
6
+ @x=x
7
+ @y=y
8
+ @z=z
9
+ end
10
+
11
+ def to_s
12
+ "#{@x},#{@y},#{@z}"
13
+ end
14
+
15
+
16
+ def eql?(position)
17
+ self.class.equal?(position.class) &&
18
+ @x == position.x &&
19
+ @y == position.y &&
20
+ @z == position.z
21
+ end
22
+ alias == eql?
23
+
24
+ def +(position)
25
+ @x+=position.x
26
+ @y+=position.y
27
+ @z+=position.z
28
+ self
29
+ end
30
+
31
+ def -(position)
32
+ @x-=position.x
33
+ @y-=position.y
34
+ @z-=position.z
35
+ self
36
+ end
37
+
38
+ def *(scale)
39
+ if scale.is_a?(Numeric)
40
+ @x*=scale
41
+ @y*=scale
42
+ @z*=scale
43
+ elsif scale.is_a?(Position)
44
+ @x*=scale.x
45
+ @y*=scale.y
46
+ @z*=scale.z
47
+ end
48
+
49
+ self
50
+ end
51
+
52
+ end
@@ -0,0 +1,12 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ Gem::Specification.new do |s|
3
+ s.name = 'minecraft-pi-ruby'
4
+ s.description = 'Control Minecraft Pi Edition using the Ruby programming language.'
5
+ s.version = '0.0.1'
6
+ s.date = '2014-10-26'
7
+ s.summary = 'Minecraft Pi Edition Ruby'
8
+ s.homepage = 'https://github.com/eaglestone/minecraft-pi-ruby'
9
+ s.authors = ["Tim Eaglestone"]
10
+ s.email = ["tim.eaglestone@gmail.com"]
11
+ s.files = `git ls-files`.split("\n")
12
+ end
data/test.rb ADDED
@@ -0,0 +1,29 @@
1
+ require_relative "lib/minecraft-pi-ruby"
2
+
3
+ Minecraft.world do
4
+ say "Hello from Ruby!"
5
+
6
+ position1 = Position.new(0,10,0)
7
+ position2 = Position.new(10,20,10)
8
+ make_cuboid(position1, position2, Block::DIAMOND_BLOCK)
9
+ sleep 2
10
+ make_cuboid(position1, position2, Block::AIR)
11
+
12
+ 10.times do |counter|
13
+ set_block(counter, 20, 0, Block::STONE)
14
+ set_block(counter, 20, 9, Block::STONE)
15
+ set_block(0, 20, counter, Block::STONE)
16
+ set_block(9, 20, counter, Block::STONE)
17
+ end
18
+
19
+ say "Bye from Ruby!"
20
+ end
21
+
22
+
23
+ mc = Minecraft.new
24
+ mc.say 'Hello to Steve!'
25
+ mc.set_player_position(16,16,16)
26
+ sleep 2
27
+ mc.set_player_position(Position.new(28,18,28))
28
+ mc.make_cuboid(16,18,16,20,20,20,Block::TNT,1)
29
+ mc.say 'Now go and click on the TNT!'
@@ -0,0 +1,63 @@
1
+ require 'minitest/autorun'
2
+ require_relative '../lib/minecraft-pi-ruby'
3
+ require_relative '../lib/position'
4
+
5
+ describe Minecraft do
6
+
7
+ before do
8
+ @conn = MiniTest::Mock.new
9
+ @mc = Minecraft.new(@conn)
10
+ end
11
+
12
+ it "can be created" do
13
+ Minecraft.new.must_be_instance_of Minecraft
14
+ end
15
+
16
+ it "can have control called on an instant of the class" do
17
+ Minecraft.must_respond_to 'control'
18
+ end
19
+
20
+ it "responds to world being called on an instance" do
21
+ Minecraft.must_respond_to 'world'
22
+ end
23
+
24
+ it "should call the cameraFollow API with the right protocol" do
25
+ @conn.expect :send_command, :return_value, ['camera.mode.setNormal']
26
+ @mc.set_camera_mode :normal
27
+
28
+ assert @conn.verify
29
+ end
30
+
31
+ it "should send the setBock(x,y,z,id) message" do
32
+ @conn.expect :send_command, :return_value, ['world.setBlock(1,2,3,4)']
33
+ @mc.set_block(1,2,3,4)
34
+
35
+ assert @conn.verify
36
+ end
37
+
38
+ it "should send the setBlock(x,y,z,id) message when called with a Position" do
39
+ @conn.expect :send_command, :return_value, ['world.setBlock(1,2,3,4)']
40
+ @mc.set_block(Position.new(1,2,3),4)
41
+ @conn.verify
42
+ end
43
+
44
+ it "should handle the setBlocks with two positions given" do
45
+ @conn.expect :send_command, :return_value, ['world.setBlocks(0,0,0,10,10,10,1)']
46
+ @mc.set_blocks(Position.new(0,0,0),Position.new(10,10,10),1)
47
+ assert @conn.verify
48
+ end
49
+
50
+ it "should handle setBlocks with individual coords" do
51
+ @conn.expect :send_command, :return_value, ['world.setBlocks(0,0,0,3,3,3,2)']
52
+ @mc.set_blocks(0,0,0,3,3,3,2)
53
+ assert @conn.verify
54
+ end
55
+
56
+ it "gets the ground level" do
57
+ @conn.expect :send_with_response, 10, ['world.getHeight(4,5)']
58
+ height = @mc.get_ground_height(4,5)
59
+ assert @conn.verify
60
+ height.must_be_kind_of(Numeric)
61
+ end
62
+
63
+ end
@@ -0,0 +1,34 @@
1
+ require 'minitest/autorun'
2
+ require_relative '../lib/position'
3
+
4
+ describe Position do
5
+ before do
6
+ @pos = Position.new(1,2,3)
7
+ end
8
+ it "initialises with 3 integers for x, y and z" do
9
+ @pos.x.must_equal 1
10
+ @pos.y.must_equal 2
11
+ @pos.z.must_equal 3
12
+ end
13
+
14
+ it "returns to_s in a format for sending to server" do
15
+ @pos.to_s.must_equal "1,2,3"
16
+ end
17
+
18
+ it "is equal to another Position if the coords are the same" do
19
+ Position.new(1,2,3).must_equal @pos
20
+ end
21
+
22
+ it "adds the dimensions with another position object" do
23
+ (@pos + @pos).must_equal Position.new(2,4,6)
24
+ end
25
+
26
+ it "subtracts the dimensions with another position object" do
27
+ (@pos - @pos).must_equal Position.new(0,0,0)
28
+ end
29
+
30
+ it "does scalar multiplication" do
31
+ (@pos*4).must_equal Position.new(4,8,12)
32
+ end
33
+
34
+ end
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: minecraft-pi-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Tim Eaglestone
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-10-26 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Control Minecraft Pi Edition using the Ruby programming language.
15
+ email:
16
+ - tim.eaglestone@gmail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - README.md
23
+ - lib/blocks.rb
24
+ - lib/connection.rb
25
+ - lib/minecraft-pi-ruby.rb
26
+ - lib/position.rb
27
+ - minecraft-pi-ruby.gemspec
28
+ - test.rb
29
+ - test/minecraft_spec.rb
30
+ - test/position_spec.rb
31
+ homepage: https://github.com/eaglestone/minecraft-pi-ruby
32
+ licenses: []
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ requirements: []
50
+ rubyforge_project:
51
+ rubygems_version: 1.8.23
52
+ signing_key:
53
+ specification_version: 3
54
+ summary: Minecraft Pi Edition Ruby
55
+ test_files: []