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 +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/lib/region.rb
DELETED
@@ -1,257 +0,0 @@
|
|
1
|
-
require 'chunk'
|
2
|
-
|
3
|
-
class LazyChunkDelegate
|
4
|
-
include ByteConverter
|
5
|
-
include ZlibHelper
|
6
|
-
|
7
|
-
def initialize(bytes)
|
8
|
-
@bytes = bytes
|
9
|
-
@chunk = nil
|
10
|
-
end
|
11
|
-
|
12
|
-
def each(&block)
|
13
|
-
_getchunk.each &block
|
14
|
-
end
|
15
|
-
|
16
|
-
def block_map(&block)
|
17
|
-
_getchunk.block_map &block
|
18
|
-
end
|
19
|
-
def block_type_map(&block)
|
20
|
-
_getchunk.block_type_map &block
|
21
|
-
end
|
22
|
-
|
23
|
-
def [](z, x, y)
|
24
|
-
_getchunk[z, x, y]
|
25
|
-
end
|
26
|
-
|
27
|
-
def []=(z, x, y, value)
|
28
|
-
_getchunk[z, x, y] = value
|
29
|
-
end
|
30
|
-
|
31
|
-
def export
|
32
|
-
_getchunk.export
|
33
|
-
end
|
34
|
-
|
35
|
-
|
36
|
-
def toNbt
|
37
|
-
return @bytes if @chunk.nil?
|
38
|
-
@chunk.toNbt
|
39
|
-
end
|
40
|
-
|
41
|
-
|
42
|
-
# unloacs the loaded chunk. Needed for memory optmization
|
43
|
-
def _unload
|
44
|
-
return if @chunk.nil?
|
45
|
-
@bytes = @chunk.toNbt
|
46
|
-
@chunk = nil
|
47
|
-
end
|
48
|
-
|
49
|
-
protected
|
50
|
-
def _getchunk
|
51
|
-
if @chunk.nil?
|
52
|
-
@chunk = Chunk.fromNbt @bytes
|
53
|
-
end
|
54
|
-
@chunk
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
58
|
-
|
59
|
-
# Enumerable over chunks
|
60
|
-
class Region
|
61
|
-
include Enumerable
|
62
|
-
include ByteConverter
|
63
|
-
include ZlibHelper
|
64
|
-
|
65
|
-
class RegionWritter
|
66
|
-
def initialize(io)
|
67
|
-
@io = io
|
68
|
-
end
|
69
|
-
|
70
|
-
def pad(count, value = 0)
|
71
|
-
self << Array.new(count) { value }
|
72
|
-
end
|
73
|
-
|
74
|
-
def <<(o)
|
75
|
-
input = o.kind_of?(Array) ? o : [o]
|
76
|
-
@io << ByteConverter.toByteString(input)
|
77
|
-
end
|
78
|
-
|
79
|
-
def close
|
80
|
-
@io.close
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def self.fromFile(filename)
|
85
|
-
new ByteConverter.stringToByteArray IO.read filename
|
86
|
-
end
|
87
|
-
|
88
|
-
def initialize(bytes)
|
89
|
-
raise "Must be an io" if bytes.kind_of?(String)
|
90
|
-
@bytes = bytes
|
91
|
-
@chunks = Array.new(32) { Array.new(32) }
|
92
|
-
readChunks bytes
|
93
|
-
end
|
94
|
-
|
95
|
-
def chunk(z, x)
|
96
|
-
@chunks[z][x]
|
97
|
-
end
|
98
|
-
|
99
|
-
def unloadChunk(z, x)
|
100
|
-
@chunks[z][x]._unload
|
101
|
-
end
|
102
|
-
|
103
|
-
def each(&block)
|
104
|
-
@chunks.each do |line|
|
105
|
-
line.each do |chunk|
|
106
|
-
yield chunk
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
def cube(z, y, x, opts = {}, &block)
|
112
|
-
c = ChunkCube.new(self, [z, y, x], opts[:width], opts[:length], opts[:height])
|
113
|
-
return c unless block_given?
|
114
|
-
c.each &block
|
115
|
-
end
|
116
|
-
|
117
|
-
def exportTo(io)
|
118
|
-
output = RegionWritter.new io
|
119
|
-
chunks = getChunks
|
120
|
-
writeChunkOffsets output, chunks
|
121
|
-
output.pad blockSize, dummytimestamp
|
122
|
-
writeChunks output, chunks
|
123
|
-
output.close
|
124
|
-
end
|
125
|
-
|
126
|
-
def exportToFile(filename)
|
127
|
-
File.open(filename, "wb") { |f| exportTo f }
|
128
|
-
end
|
129
|
-
|
130
|
-
|
131
|
-
protected
|
132
|
-
def readChunks(bytes)
|
133
|
-
bytes[0..(blockSize - 1)].each_slice(4).each_with_index do |ar, i|
|
134
|
-
offset = bytesToInt [0] + ar[0..-2]
|
135
|
-
count = ar.last
|
136
|
-
if count > 0
|
137
|
-
@chunks[i / 32][i % 32 ] = readChunk(offset, bytes)
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def readChunk(offset, bytes)
|
143
|
-
o = offset * blockSize
|
144
|
-
bytecount = bytesToInt bytes[o..(o + 4)]
|
145
|
-
o += 5
|
146
|
-
nbtBytes = bytes[o..(o + bytecount - 2)]
|
147
|
-
LazyChunkDelegate.new nbtBytes
|
148
|
-
end
|
149
|
-
|
150
|
-
def chunkSize(chunk)
|
151
|
-
chunk.size + chunkMetaDataSize
|
152
|
-
end
|
153
|
-
|
154
|
-
def chunkBlocks(chunk)
|
155
|
-
((chunkSize chunk).to_f / blockSize).ceil
|
156
|
-
end
|
157
|
-
|
158
|
-
def writeChunks(output, chunks)
|
159
|
-
for chunk in chunks
|
160
|
-
next if chunk.nil?
|
161
|
-
output << intBytes(chunk.size + 1)
|
162
|
-
output << defaultCompressionType
|
163
|
-
output << chunk
|
164
|
-
remaining = blockSize - chunkSize(chunk)
|
165
|
-
output.pad remaining % blockSize
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
def writeChunkOffsets(output, chunks)
|
170
|
-
lastVacantPosition = 2
|
171
|
-
for chunk in chunks
|
172
|
-
if chunk
|
173
|
-
sizeCount = chunkBlocks chunk
|
174
|
-
output << intBytes(lastVacantPosition)[1..3]
|
175
|
-
output << sizeCount
|
176
|
-
lastVacantPosition += sizeCount
|
177
|
-
else
|
178
|
-
output.pad 4
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
def getChunks
|
184
|
-
map do |chunk|
|
185
|
-
if chunk.nil?
|
186
|
-
nil
|
187
|
-
else
|
188
|
-
chunk.toNbt
|
189
|
-
end
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
def chunkMetaDataSize
|
194
|
-
5
|
195
|
-
end
|
196
|
-
|
197
|
-
def defaultCompressionType
|
198
|
-
2
|
199
|
-
end
|
200
|
-
|
201
|
-
def dummytimestamp
|
202
|
-
0
|
203
|
-
end
|
204
|
-
|
205
|
-
def blockSize
|
206
|
-
4096
|
207
|
-
end
|
208
|
-
|
209
|
-
end
|
210
|
-
|
211
|
-
|
212
|
-
class ChunkCube
|
213
|
-
include Enumerable
|
214
|
-
|
215
|
-
# width corresponds do z, length to x, and height to y.
|
216
|
-
def initialize(region, initialPos, width, length, height)
|
217
|
-
@region = region
|
218
|
-
@initialPos = initialPos
|
219
|
-
@width = width || 1
|
220
|
-
@length = length || 1
|
221
|
-
@height = height || 1
|
222
|
-
end
|
223
|
-
|
224
|
-
def each(&block)
|
225
|
-
z, x, y = @initialPos
|
226
|
-
firstChunkX = x / chunkSide
|
227
|
-
firstChunkZ = z / chunkSide
|
228
|
-
lastChunkX = (x + @length - 1) / chunkSide
|
229
|
-
lastChunkZ = (z + @width - 1) / chunkSide
|
230
|
-
for j in firstChunkZ..lastChunkZ
|
231
|
-
for i in firstChunkX..lastChunkX
|
232
|
-
iterateOverChunk j, i, &block
|
233
|
-
end
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
protected
|
238
|
-
def iterateOverChunk(j, i, &block)
|
239
|
-
chunk = @region.chunk(j, i)
|
240
|
-
return if chunk.nil?
|
241
|
-
z, x, y = @initialPos
|
242
|
-
chunk.each do |b|
|
243
|
-
globalZ = b.z + (j * chunkSide)
|
244
|
-
globalX = b.x + (i * chunkSide)
|
245
|
-
if globalZ.between?(z, z + @width - 1) and
|
246
|
-
globalX.between?(x, x + @length - 1) and
|
247
|
-
b.y.between?(y, y + @height - 1)
|
248
|
-
yield b, globalZ - z, globalX - x , b.y - y
|
249
|
-
end
|
250
|
-
end
|
251
|
-
@region.unloadChunk(j, i)
|
252
|
-
end
|
253
|
-
|
254
|
-
def chunkSide
|
255
|
-
16
|
256
|
-
end
|
257
|
-
end
|