flying-squid/src/lib/plugins/world.js

179 lines
No EOL
5.2 KiB
JavaScript

var Vec3 = require("vec3").Vec3
var spiralloop = require('spiralloop');
var Chunk = require('prismarine-chunk')(require("../version"));
var World = require('prismarine-world');
var WorldSync = require("prismarine-world-sync");
var generations={
'grass_field':require("../worldGenerations/grass_field"),
'diamond_square':require("../worldGenerations/diamond_square"),
'superflat':require("../worldGenerations/superflat"),
'all_the_blocks':require("../worldGenerations/all_the_blocks"),
'nether':require("../worldGenerations/nether")
};
module.exports.server=function(serv,{regionFolder,generation={"name":"diamond_square","options":{"worldHeight":80}}}={}) {
generation.options.seed=generation.options.seed || Math.random()*Math.pow(2, 32);
serv.emit("seed",generation.options.seed);
serv.overworld = new World(generations[generation.name](generation.options), regionFolder);
serv.netherworld = new World(generations["nether"]({}));
//serv.endworld = new World(generations["end"]({}));
serv._worldSync=new WorldSync(serv.overworld);
// WILL BE REMOVED WHEN ACTUALLY IMPLEMENTED
serv.overworld.blockEntityData = {};
serv.netherworld.blockEntityData = {};
//////////////
serv.pregenWorld = (world, size=3) => {
var promises = [];
for (var x = -size; x < size; x++) {
for (var z = -size; z < size; z++) {
promises.push(world.getColumn(x, z));
}
}
return Promise.all(promises);
};
serv.setBlock = async (world,position,blockType,blockData) =>
{
serv.players
.filter(p => p.world==world)
.forEach(player => player.sendBlock(position, blockType, blockData));
await world.setBlockType(position,blockType);
await world.setBlockData(position,blockData);
};
//serv.pregenWorld(serv.overworld).then(() => serv.log('Pre-Generated Overworld'));
//serv.pregenWorld(serv.netherworld).then(() => serv.log('Pre-Generated Nether'));
};
module.exports.player=function(player,serv) {
player.spawnEntity = entity => {
player._client.write(entity.spawnPacketName, entity.getSpawnPacket());
if (typeof entity.itemId != 'undefined') {
entity.setMetadata([{
"key": 10,
"type": 5,
"value": {
blockId: entity.itemId,
itemDamage: entity.itemDamage
}
}]);
}
};
player.sendChunk = (chunkX,chunkZ,column) =>
{
player._client.write('map_chunk', {
x: chunkX,
z: chunkZ,
groundUp: true,
bitMap: 0xffff,
chunkData: column.dump()
});
return Promise.resolve();
};
function spiral(arr)
{
var t=[];
spiralloop(arr,(x,z) => {
t.push([x,z]);
});
return t;
}
player.sendNearbyChunks = (view,group) =>
{
player.lastPositionChunkUpdated=player.entity.position;
var playerChunkX=Math.floor(player.entity.position.x/16/32);
var playerChunkZ=Math.floor(player.entity.position.z/16/32);
return spiral([view*2,view*2])
.map(t => ({
chunkX:playerChunkX+t[0]-view,
chunkZ:playerChunkZ+t[1]-view
}))
.filter(({chunkX,chunkZ}) => {
var key=chunkX+","+chunkZ;
var loaded=player.loadedChunks[key];
if(!loaded) player.loadedChunks[key]=1;
return !loaded;
})
.reduce((acc,{chunkX,chunkZ},i)=> {
var p=acc
.then(() => player.world.getColumn(chunkX, chunkZ))
.then((column) => player.sendChunk(chunkX, chunkZ, column));
return group ? p.then(() => sleep(5)) : p;
}
,Promise.resolve());
};
function sleep(ms = 0) {
return new Promise(r => setTimeout(r, ms));
}
player.sendMap = () =>
{
return player.sendNearbyChunks(3)
.catch((err) => setTimeout(() => { throw err; }), 0);
};
player.sendRestMap = () =>
{
player.sendingChunks=true;
player.sendNearbyChunks(player.view,true)
.then(() => player.sendingChunks=false)
.catch((err)=> setTimeout(() => {throw err;},0));
};
player.sendSpawnPosition = () =>
{
console.log("setting spawn at "+player.spawnPoint);
player._client.write('spawn_position',{
"location":player.spawnPoint
});
};
player.changeWorld = async (world, opt) => {
if(player.world == world) return Promise.resolve();
opt = opt || {};
player.world = world;
player.entity.world = world;
player.loadedChunks={};
if (typeof opt.gamemode != 'undefined') player.gameMode = opt.gamemode;
player._client.write("respawn",{
dimension: opt.dimension || 0,
difficulty: opt.difficulty || 0,
gamemode: opt.gamemode || player.gameMode,
levelType:'default'
});
player.entity.position=player.spawnPoint.toFixedPosition();
player.sendSpawnPosition();
player.entity.updateAndSpawn();
await player.sendMap();
player.sendPosition();
player.emit('change_world');
await player.waitPlayerLogin();
player.sendRestMap();
};
player.commands.add({
base: 'changeworld',
info: 'to change world',
usage: '/changeworld overworld|nether',
action(world) {
if(world=="nether") player.changeWorld(serv.netherworld, {dimension: -1});
if(world=="overworld") player.changeWorld(serv.overworld, {dimension: 0});
}
});
};