rubycraft 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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