rubycraft 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -2,7 +2,9 @@ RubyCraft
2
2
  ==============
3
3
 
4
4
  RubyCraft is a simple library for manipulating [Minecraft](http://www.minecraft.net/)
5
- region files.
5
+ region files. Installation is as simple as:
6
+
7
+ $ gem install rubycraft
6
8
 
7
9
  Region files are files with the mcr extension on the region folder of a save folder. The
8
10
  save folders are located below the saves folder of the minecraft data folder (for
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.1.1
@@ -0,0 +1,5 @@
1
+ module RubyCraft
2
+ VERSION = "0.1.1".freeze
3
+ end
4
+
5
+ require 'rubycraft/region'
@@ -0,0 +1,78 @@
1
+ require 'rubycraft/block_type'
2
+
3
+ module RubyCraft
4
+ # A minecraft block. Its position is given by a coord[x, z, y]
5
+ class Block
6
+
7
+ attr_accessor :block_type, :pos, :data
8
+ def initialize(blockType, data = 0)
9
+ @blockType = blockType
10
+ @data = 0
11
+ end
12
+
13
+ def self.get(key)
14
+ new BlockType.get key
15
+ end
16
+
17
+ def self.of(key)
18
+ self[key]
19
+ end
20
+
21
+ def self.[](key)
22
+ new BlockType[key]
23
+ end
24
+
25
+
26
+ def color=(color)
27
+ @data = BlockColor::InvertedColor[color]
28
+ end
29
+
30
+ def color
31
+ BlockColor.typeColor[@data].name
32
+ end
33
+
34
+ def blockColor
35
+ BlockColor.typeColor[@data]
36
+ end
37
+
38
+ def is(name)
39
+ self.name == name.to_s
40
+ end
41
+
42
+ def name
43
+ @blockType.name
44
+ end
45
+
46
+ def id
47
+ @blockType.id
48
+ end
49
+
50
+ def transparent
51
+ @blockType.transparent
52
+ end
53
+
54
+ #sets block type by name
55
+ def name=(newName)
56
+ return if name == newName.to_s
57
+ @blockType = BlockType[newName]
58
+ end
59
+
60
+ #sets block type by id
61
+ def id=(id)
62
+ return if id == id
63
+ @blockType = BlockType.get id
64
+ end
65
+
66
+ def y
67
+ pos[2]
68
+ end
69
+
70
+ def z
71
+ pos[1]
72
+ end
73
+
74
+ def x
75
+ pos[0]
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,193 @@
1
+ module RubyCraft
2
+ BlockTypeDSL = proc do
3
+ transparent_block 0, :air
4
+ block 1, :stone
5
+ block 2, :grass
6
+ block 3, :dirt
7
+ block 4, :cobblestone
8
+ block 5, :planks
9
+ transparent_block 6, :sapling
10
+ block 7, :bedrock
11
+ block 8, :watersource
12
+ block 9, :water
13
+ block 10, :lavasource
14
+ block 11, :lava
15
+ block 12, :sand
16
+ block 13, :gravel
17
+ block 14, :goldore
18
+ block 15, :ironore
19
+ block 16, :coal
20
+ block 17, :log
21
+ block 18, :leaves
22
+ block 19, :sponge
23
+ transparent_block 20, :glass
24
+ block 21, :lapisore
25
+ block 22, :lapis
26
+ block 23, :dispenser
27
+ block 24, :sandstone
28
+ block 25, :note
29
+ block 26, :bed
30
+ transparent_block 27, :powered_rail
31
+ transparent_block 28, :detector_rail
32
+ block 29, :sticky_piston
33
+ transparent_block 30, :cobweb
34
+ transparent_block 31, :tall_grass
35
+ transparent_block 32, :dead_shrubs
36
+ block 33, :piston
37
+ block 34, :piston_extension
38
+ block 35, :wool
39
+ transparent_block 37, :dandelion
40
+ transparent_block 38, :rose
41
+ transparent_block 39, :brown_mushroom
42
+ transparent_block 40, :red_mushroom
43
+ block 41, :gold
44
+ block 42, :iron
45
+ block 43, :slabs
46
+ block 44, :slab
47
+ block 45, :brick
48
+ block 46, :tnt
49
+ block 47, :bookshelf
50
+ block 48, :mossy
51
+ block 49, :obsidian
52
+ transparent_block 50, :torch
53
+ transparent_block 51, :fire
54
+ block 52, :spawner
55
+ block 53, :stairs
56
+ block 54, :chest
57
+ transparent_block 55, :redstone_wire
58
+ block 56, :diamond_ore
59
+ block 57, :diamond_block
60
+ block 58, :crafting_table
61
+ block 59, :seeds
62
+ block 60, :farmland
63
+ block 61, :furnace
64
+ block 62, :burning_furnace
65
+ transparent_block 63, :signpost
66
+ transparent_block 64, :door
67
+ transparent_block 65, :ladder
68
+ transparent_block 66, :rails
69
+ block 67, :cobblestone_stairs
70
+ transparent_block 68, :wall_sign
71
+ transparent_block 69, :lever
72
+ transparent_block 70, :stone_pressure_plate
73
+ transparent_block 71, :iron_door
74
+ transparent_block 72, :wooden_pressure_plate
75
+ block 73, :redstone_ore
76
+ block 74, :glowing_redstone_ore
77
+ transparent_block 75, :redstone_torch_off
78
+ transparent_block 76, :redstone_torch_on
79
+ transparent_block 77, :stone_button
80
+ block 78, :snow
81
+ block 79, :ice
82
+ block 80, :snow_block
83
+ transparent_block 81, :cactus
84
+ block 82, :clay
85
+ block 83, :sugar_cane
86
+ block 84, :jukebox
87
+ transparent_block 85, :fence
88
+ block 86, :pumpkin
89
+ block 87, :netherrack
90
+ block 88, :soulsand
91
+ block 89, :glowstone
92
+ transparent_block 90, :portal
93
+ block 91, :jock_o_lantern
94
+ transparent_block 92, :cake
95
+ transparent_block 93, :repeater_off
96
+ transparent_block 94, :repeater_on
97
+ block 95, :locked_chest
98
+ transparent_block 96, :trapdoor
99
+ end
100
+
101
+
102
+ # DSL: color name r, g, b
103
+ BlockColorDSL = proc do
104
+ white 221, 221, 221
105
+ orange 233, 126, 55
106
+ magenta 179, 75, 200
107
+ light_blue 103, 137, 211
108
+ yellow 192, 179, 28
109
+ light_green 59, 187, 47
110
+ pink 217, 132, 153
111
+ dark_gray 66, 67, 67
112
+ gray 157, 164, 165
113
+ cyan 39, 116, 148
114
+ purple 128, 53, 195
115
+ blue 39, 51, 153
116
+ brown 85, 51, 27
117
+ dark_green 55, 76, 24
118
+ red 162, 44, 42
119
+ black 26, 23, 23
120
+ end
121
+
122
+ class BlockColor
123
+ @typeColor = []
124
+
125
+ def self.method_missing(name, *args)
126
+ args << @typeColor.size
127
+ @typeColor << new(name, *args)
128
+ end
129
+
130
+ def self.typeColor
131
+ @typeColor
132
+ end
133
+
134
+ attr_reader :name, :r, :g, :b, :data
135
+ def initialize(name, r, g, b, data)
136
+ @name = name
137
+ @r = r
138
+ @g = g
139
+ @b = b
140
+ @data = data
141
+ end
142
+
143
+ def rgb
144
+ [r, g, b]
145
+ end
146
+
147
+ class_eval &BlockColorDSL
148
+ InvertedColor = Hash[typeColor.each_with_index.map { |obj, i| [obj.name, i] }]
149
+ end
150
+
151
+ # class methods and dsl for block
152
+ class BlockType
153
+ @blocks = {}
154
+ @blocks_by_name = {}
155
+ attr_reader :id, :name, :transparent
156
+
157
+ def initialize(id, name, transparent)
158
+ @id = id
159
+ @name = name.to_s
160
+ @transparent = transparent
161
+ end
162
+
163
+ def self.block(id, name, transparent = false)
164
+ block = new id, name, transparent
165
+ @blocks[id] = block
166
+ @blocks_by_name[name.to_s] = block
167
+
168
+ end
169
+
170
+ def self.transparent_block(id, name)
171
+ block id, name, true
172
+ end
173
+
174
+ def self.get(key)
175
+ if @blocks.has_key?(key)
176
+ return @blocks[key].clone
177
+ end
178
+ new(key, "unknown(#{key})", false)
179
+ end
180
+
181
+ def self.of(key)
182
+ self[key]
183
+ end
184
+
185
+ def self.[](key)
186
+ key = key.to_s
187
+ return @blocks_by_name[key] if @blocks_by_name.has_key?(key)
188
+ raise "no such name: #{key}"
189
+ end
190
+
191
+ class_eval &BlockTypeDSL
192
+ end
193
+ end
@@ -0,0 +1,48 @@
1
+ require 'stringio'
2
+
3
+ module RubyCraft
4
+ # Utils for manipulating bytes back and forth as strings, strings and numbers
5
+ module ByteConverter
6
+ def toByteString(array)
7
+ array.pack('C*')
8
+ end
9
+
10
+ def intBytes(i)
11
+ [i >> 24, (i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF]
12
+ end
13
+
14
+ def stringToByteArray(str)
15
+ str.bytes.to_a
16
+ end
17
+
18
+ def arrayToIO(arr)
19
+ io = StringIO.new
20
+ io.write toByteString arr
21
+ io.rewind
22
+ io
23
+ end
24
+
25
+ def stringToIo(str)
26
+ arrayToIO stringToByteArray(str)
27
+ end
28
+
29
+ def concat(array, enum)
30
+ for i in enum
31
+ array << i
32
+ end
33
+ end
34
+
35
+ def bytesToInt(array)
36
+ array.pack('C*').unpack("N").first
37
+ end
38
+
39
+ def pad(array, count, value = 0)
40
+ count.times do
41
+ array << value
42
+ end
43
+ array
44
+ end
45
+
46
+ extend self
47
+ end
48
+ end
@@ -0,0 +1,120 @@
1
+ # Represents a chunk data
2
+ require 'rubycraft/nbt_helper'
3
+ require 'rubycraft/byte_converter'
4
+ require 'rubycraft/block'
5
+ require 'rubycraft/matrix3d'
6
+
7
+ module RubyCraft
8
+ # Chunks are enumerable over blocks
9
+ class Chunk
10
+ include Enumerable
11
+ include ZlibHelper
12
+
13
+ Width = 16
14
+ Length = 16
15
+ Height = 128
16
+
17
+ def self.fromNbt(bytes)
18
+ new NbtHelper.fromNbt bytes
19
+ end
20
+
21
+ def initialize(nbtData)
22
+ name, @nbtBody = nbtData
23
+ bytes = level["Blocks"].value.bytes
24
+ @blocks = matrixfromBytes bytes
25
+ @blocks.each_triple_index do |b, z, x, y|
26
+ b.pos = [z, x, y]
27
+ end
28
+ data = level["Data"].value.bytes.to_a
29
+ @blocks.each_with_index do |b, index|
30
+ v = data[index / 2]
31
+ if index % 2 == 0
32
+ b.data = v & 0xF
33
+ else
34
+ b.data = v >> 4
35
+ end
36
+ end
37
+ end
38
+
39
+ # Iterates over the blocks
40
+ def each(&block)
41
+ @blocks.each &block
42
+ end
43
+
44
+
45
+ # Converts all blocks on data do another type. Gives the block and sets
46
+ # the received name
47
+ def block_map(&block)
48
+ each { |b| b.name = yield b }
49
+ end
50
+
51
+ # Converts all blocks on data do another type. Gives the block name sets
52
+ # the received name
53
+ def block_type_map(&block)
54
+ each { |b| b.name = yield b.name.to_sym }
55
+ end
56
+
57
+ def [](z, x, y)
58
+ @blocks[z, x, y]
59
+ end
60
+
61
+ def []=(z, x, y, value)
62
+ @blocks[z, x, y] = value
63
+ end
64
+
65
+ def export
66
+ level["Data"] = byteArray exportLevelData
67
+ level["Blocks"] = byteArray @blocks.map { |b| b.id }
68
+ level["HeightMap"] = byteArray exportHeightMap
69
+ ["", @nbtBody]
70
+ end
71
+
72
+ def toNbt
73
+ NbtHelper.toBytes export
74
+ end
75
+
76
+ protected
77
+ def exportHeightMap
78
+ zwidth, xwidth, ywidth = @blocks.bounds
79
+ matrix = Array.new(zwidth) { Array.new(xwidth) { 1 }}
80
+ @blocks.each_triple_index do |b, z, x, y|
81
+ unless b.transparent
82
+ matrix[z][x] = [matrix[z][x], y + 1].max
83
+ end
84
+ end
85
+ ret = []
86
+ matrix.each do |line|
87
+ line.each do |height|
88
+ ret << height
89
+ end
90
+ end
91
+ ret
92
+ end
93
+
94
+ def level
95
+ @nbtBody["Level"]
96
+ end
97
+
98
+ def exportLevelData
99
+ data = []
100
+ @blocks.each_with_index do |b, i|
101
+ if i % 2 == 0
102
+ data << b.data
103
+ else
104
+ data[i / 2] += (b.data << 4)
105
+ end
106
+ end
107
+ data
108
+ end
109
+
110
+ def byteArray(data)
111
+ NBTFile::Types::ByteArray.new ByteConverter.toByteString(data)
112
+ end
113
+
114
+ def matrixfromBytes(bytes)
115
+ Matrix3d.new(Width, Length, Height).fromArray bytes.map {|byte| Block.get(byte) }
116
+ end
117
+
118
+
119
+ end
120
+ end