UNPKG

prismarine-chunk

Version:
228 lines (175 loc) 5.58 kB
'use strict' const SubChunk = require('./subchunk') const Vec3 = require('vec3') const BIOME_ID_SIZE = 256 const HEIGHT_SIZE = 256 * 2 const BUFFER_SIZE = BIOME_ID_SIZE + HEIGHT_SIZE module.exports = loader function loader (registry) { Block = require('prismarine-block')(registry) Chunk.w = 16 Chunk.l = 16 Chunk.h = 256 Chunk.BUFFER_SIZE = 3 + 256 + 512 + (16 * 10241) Chunk.version = registry.version return Chunk } let Block function exists (val) { return val !== undefined } class Chunk { constructor () { this.chunks = new Array(16) for (let i = 0; i < this.chunks.length; i++) { this.chunks[i] = new SubChunk() } this.data = Buffer.alloc(BUFFER_SIZE) this.data.fill(0) // init biome id for (let j = 0; j < 256; j++) { this.data[j] = 1 } } toJson () { return JSON.stringify({ data: this.data, sections: this.chunks.map(section => section.toJson()) }) } static fromJson (j) { const parsed = JSON.parse(j) const chunk = new Chunk() chunk.data = parsed.data chunk.chunks = parsed.sections.map(s => SubChunk.fromJson(s)) return chunk } initialize (iniFunc) { const p = new Vec3(0, 0, 0) for (p.y = 0; p.y < Chunk.h; p.y++) { for (p.z = 0; p.z < Chunk.w; p.z++) { for (p.x = 0; p.x < Chunk.l; p.x++) { const block = iniFunc(p.x, p.y, p.z) if (block === null) { continue } this.setBlock(p, block) } } } } getBlock (pos) { const block = new Block(this.getBlockType(pos), this.getBiome(pos), this.getBlockData(pos)) block.light = this.getBlockLight(pos) block.skyLight = this.getSkyLight(pos) return block } setBlock (pos, block) { if (exists(block.type)) { this.setBlockType(pos, block.type) } if (exists(block.metadata)) { this.setBlockData(pos, block.metadata) } if (exists(block.biome)) { this.setBiome(pos, block.biome.id) } if (exists(block.skyLight)) { this.setSkyLight(pos, block.skyLight) } if (exists(block.light)) { this.setBlockLight(pos, block.light) } } getBlockType (pos) { const chunk = this.chunks[pos.y >> 4] return chunk ? chunk.getBlockType(new Vec3(pos.x, pos.y - 16 * (pos.y >> 4), pos.z)) : 0 } setBlockType (pos, type) { const chunk = this.chunks[pos.y >> 4] return chunk && chunk.setBlockType(new Vec3(pos.x, pos.y - 16 * (pos.y >> 4), pos.z), type) } getBlockData (pos) { const chunk = this.chunks[pos.y >> 4] return chunk ? chunk.getBlockData(new Vec3(pos.x, pos.y - 16 * (pos.y >> 4), pos.z)) : 0 } setBlockData (pos, data) { const chunk = this.chunks[pos.y >> 4] return chunk && chunk.setBlockData(new Vec3(pos.x, pos.y - 16 * (pos.y >> 4), pos.z), data) } getBlockLight (pos) { const chunk = this.chunks[pos.y >> 4] return chunk ? chunk.getBlockLight(new Vec3(pos.x, pos.y - 16 * (pos.y >> 4), pos.z)) : 0 } setBlockLight (pos, light) { const chunk = this.chunks[pos.y >> 4] return chunk && chunk.setBlockLight(new Vec3(pos.x, pos.y - 16 * (pos.y >> 4), pos.z), light) } getSkyLight (pos) { const chunk = this.chunks[pos.y >> 4] return chunk ? chunk.getSkyLight(new Vec3(pos.x, pos.y - 16 * (pos.y >> 4), pos.z)) : 15 } setSkyLight (pos, light) { const chunk = this.chunks[pos.y >> 4] return chunk && chunk.setSkyLight(new Vec3(pos.x, pos.y - 16 * (pos.y >> 4), pos.z), light) } getBiomeColor (pos) { return { x: 0, y: 0, z: 0 } } setBiomeColor (pos, r, g, b) { // no longer a feature ;( } getBiome (pos) { return this.data.readUInt8((pos.z << 4) + (pos.x)) } setBiome (pos, id) { this.data.writeUInt8(id, (pos.z << 4) + (pos.x)) } getHeight (pos) { return this.data.readUInt8((pos.z << 4) + (pos.x)) } setHeight (pos, height) { this.data.writeUInt8(height, (pos.z << 4) + (pos.x)) } load (newData) { if (!Buffer.isBuffer(newData)) { throw (new Error('Data must be a buffer')) } let offset = 0 const numberOfChunks = newData.readUInt8(offset) offset += 1 if (((numberOfChunks * 10241) + 1) > newData.length) { throw (new Error(`Data buffer not correct size (was ${newData.length}, expected ${3 + 256 + 512 + (16 * 10241)})`)) } for (let i = 0; i < numberOfChunks; i++) { this.chunks[i].load(newData.slice(offset, offset + 10241)) offset += 10241 } // ignore the rest } size () { let size = 1 // count of subchunks (byte) size += this.chunks.length * 10241 // all of the chunks and their size size += HEIGHT_SIZE size += BIOME_ID_SIZE size += 1 // border block count (byte) size += 1 // signed varint block extradata count return size } // These methods do nothing, and are present only for API compatibility dumpBiomes () { } dumpLight () { } loadLight () { } loadBiomes () { } dump () { let offset = 0 const exportData = Buffer.alloc(this.size()) exportData.fill(0) exportData.writeUInt8(this.chunks.length, offset) offset += 1 for (let i = 0; i < this.chunks.length; i++) { const dump = this.chunks[i].dump() dump.copy(exportData, offset) offset += dump.length } this.data.copy(exportData, offset) offset += this.data.length exportData.writeUInt8(0, offset) // border block count offset += 1 exportData.writeUInt8(0, offset) // signed varint ?! (extdata count) offset += 1 return exportData } getMask () { return 0xFFFF } }