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 +3 -1
- data/VERSION +1 -1
- data/lib/rubycraft.rb +5 -0
- data/lib/rubycraft/block.rb +78 -0
- data/lib/rubycraft/block_type.rb +193 -0
- data/lib/rubycraft/byte_converter.rb +48 -0
- data/lib/rubycraft/chunk.rb +120 -0
- data/lib/rubycraft/matrix3d.rb +87 -0
- data/lib/rubycraft/nbt_helper.rb +49 -0
- data/lib/rubycraft/region.rb +259 -0
- metadata +11 -10
- data/lib/block.rb +0 -77
- data/lib/block_type.rb +0 -191
- data/lib/byte_converter.rb +0 -46
- data/lib/chunk.rb +0 -118
- data/lib/matrix3d.rb +0 -86
- data/lib/nbt_helper.rb +0 -48
- data/lib/region.rb +0 -257
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.
|
1
|
+
0.1.1
|
data/lib/rubycraft.rb
ADDED
@@ -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
|