UNPKG

minecraft.js

Version:

Minecraft data serialization/deserialization and networking

138 lines (113 loc) 4.77 kB
var Region = require(__dirname + '/region.js'), Chunk = require(__dirname + '/chunk.js'), Player = require(__dirname + '/player.js'), Vector3 = require(__dirname + '/vector3.js'), constants = require(__dirname + '/constants.js'), TagFormat = require(__dirname + '/tagFormat.js'); /** @constructor */ var World = module.exports = function(args) { args = args || {}; this.xSize = args.xSize || 1; this.zSize = args.zSize || 1; this.xStart = -Math.floor(this.xSize / 2); this.zStart = -Math.floor(this.zSize / 2); this.regions = {}; for(var i = this.xStart; i < this.xStart + this.xSize; i++) { this.regions[i] = {}; for(var j = this.zStart; j < this.zStart + this.zSize; j++) { this.regions[i][j] = new Region(); } } this.spawn = args.spawn || new Vector3(0,64,0); this.sizeOnDisk = args.sizeOnDisk || 0; this.randomSeed = args.randomSeed || (Math.floor(Math.random() * 99999999999999)); this.version = args.version || 19132; this.levelName = args.levelName || "Untitled World"; this.raining = args.raining || false; this.thundering = args.thundering || false; this.rainTime = args.rainTime || 1000000; this.thunderTime = args.thunderTime || 1000000; this.gameType = args.gameType || 0; this.mapFeatures = args.mapFeatures || true; this.hardcore = args.hardcore || false; this.player = args.player || new Player(); }; World.prototype.getChunk = function(x, z) { var regionX = Math.floor(x / constants.REGION_SIZE); var regionZ = Math.floor(z / constants.REGION_SIZE); var region = this.regions[regionX][regionZ]; if(region != undefined) return region.getChunk(x % constants.REGION_SIZE, z % constants.REGION_SIZE); }; World.prototype.setChunk = function(x, z, chunk) { var regionX = Math.floor(x / constants.REGION_SIZE); var regionZ = Math.floor(z / constants.REGION_SIZE); if(this.regions[regionX] == undefined) { this.regions[regionX] = {}; } if(this.regions[regionX][regionZ] == undefined) { this.regions[regionX][regionZ] = new Region(); } this.regions[regionX][regionZ].setChunk(x & constants.REGION_SIZE - 1, z & constants.REGION_SIZE - 1, chunk); return this; }; World.prototype.getBlock = function(x, y, z) { var chunkX = Math.floor(x / constants.CHUNK_SIZE); var chunkZ = Math.floor(z / constants.CHUNK_SIZE); var chunk = this.getChunk(chunkX, chunkZ); if(!chunk) { throw new Error('Chunk (' + chunkX + ', ' + chunkZ + ') does not exist'); return; } return chunk.getBlock(x, y, z); }; World.prototype.setBlock = function(x, y, z, value) { var chunkX = Math.floor(x / constants.CHUNK_SIZE); var chunkZ = Math.floor(z / constants.CHUNK_SIZE); if(!this.getChunk(chunkX, chunkZ)) { this.setChunk(chunkX, chunkZ, new Chunk()); } this.getChunk(chunkX, chunkZ).setBlock(x, y, z, value); return this; }; World.prototype.download = function() { var fr = new FileReader(); var worldZip = new JSZip(); worldZip.folder('region'); //add world metadata fr.onloadend = function() { worldZip.add('level.dat', btoa(fr.result), {base64: true}); }; fr.readAsBinaryString(this.tagFormat.encode(this).toBlob()); //for each region, build binary region file and add to world zip for(var i = this.xStart; i < this.xStart + this.xSize; i++) { for(var j = this.zStart; j < this.zStart + this.zSize; j++) { var regionFr = new FileReader(); regionFr.onloadend = function() { worldZip.add('r.' + (i >> 5) + '.' + (j >> 5) + '.mcr', btoa(regionFr.result), {base64: true}); }; regionFr.readAsBinaryString(this.regions[x][z].toBlob()); } } }; World.prototype.tagFormat = new TagFormat( 'compound', 'Data', '', [ new TagFormat('long', 'Time', 'time'), new TagFormat('long', 'LastPlayed', 'lastPlayed'), Player.prototype.tagFormat, new TagFormat('int', 'SpawnX', 'spawn.x'), new TagFormat('int', 'SpawnY', 'spawn.y'), new TagFormat('int', 'SpawnZ', 'spawn.z'), new TagFormat('long', 'SizeOnDisk', 'sizeOnDisk'), new TagFormat('long', 'RandomSeed', 'randomSeed'), new TagFormat('int', 'version', 'version'), new TagFormat('string', 'LevelName', 'levelName'), new TagFormat('byte', 'raining', 'raining'), new TagFormat('byte', 'thundering', 'thundering'), new TagFormat('int', 'rainTime', 'rainTime'), new TagFormat('int', 'thunderTime', 'thunderTime'), new TagFormat('int', 'GameType', 'gameType'), new TagFormat('byte', 'MapFeatures', 'mapFeatures'), new TagFormat('byte', 'hardcore', 'hardcore') ]);