rubycraft 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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