diff --git a/package.json b/package.json index 2326cd5..18c1e7d 100644 --- a/package.json +++ b/package.json @@ -34,10 +34,11 @@ "prismarine-block": "0.1.0", "prismarine-chunk": "0.2.1", "prismarine-entity": "0.1.0", - "prismarine-world": "0.1.0", + "prismarine-world": "0.2.0", "request-promise": "^0.4.3", "requireindex": "~1.0.0", - "vec3": "0.1.3" + "vec3": "0.1.3", + "spiralloop": "1.0.2" }, "repository": { "type": "git", diff --git a/src/lib/playerPlugins/login.js b/src/lib/playerPlugins/login.js index cb75cc8..5f4abb0 100644 --- a/src/lib/playerPlugins/login.js +++ b/src/lib/playerPlugins/login.js @@ -1,4 +1,6 @@ var Entity=require("prismarine-entity"); +var spiralloop = require('spiralloop'); +var Vec3=require("vec3"); module.exports=inject; @@ -17,9 +19,11 @@ function inject(serv,player) player.entity.player=player; player.entity.health = 20; player.entity.food = 20; + player.view=8; player.username=player._client.username; serv.players.push(player); serv.uuidToPlayer[player._client.uuid] = player; + player.loadedChunks={}; } function sendLogin() @@ -34,20 +38,78 @@ function inject(serv,player) reducedDebugInfo: false, maxPlayers: serv._server.maxPlayers }); + player.entity.position=player.spawnPoint.scaled(32); } + + function spiral(arr) + { + var t=[]; + spiralloop(arr,function(x,z){ + t.push([x,z]); + }); + return t; + } + + + function sendChunk(chunkX,chunkZ,column) + { + player._client.write('map_chunk', { + x: chunkX, + z: chunkZ, + groundUp: true, + bitMap: 0xffff, + chunkData: column.dump() + }); + return Promise.resolve(); + } + + function sendChunksAroundPlayer(view) + { + 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})=> + acc + //.then(() => sleep(10)) + .then(() => serv.world.getColumn(chunkX,chunkZ)) + .then((column) => sendChunk(chunkX,chunkZ,column)) + ,Promise.resolve()); + } + function sendMap() { - serv.world.getColumns().forEach(function(column){ - player._client.write('map_chunk', { - x: column.chunkX, - z: column.chunkZ, - groundUp: true, - bitMap: 0xffff, - chunkData: column.column.dump() - }); + var initialChunks=sendChunksAroundPlayer(2); + player.sendingChunks=true; + sendChunksAroundPlayer(player.view).then(() => player.sendingChunks=false); + + player.on("positionChanged",function(){ + if(!player.sendingChunks && player.entity.position.distanceTo(player.lastPositionChunkUpdated)>16*32) + { + player.sendingChunks=true; + sendChunksAroundPlayer(player.view).then(() => player.sendingChunks=false); + } }); + return initialChunks; } + + function sleep(ms = 0) { + return new Promise(r => setTimeout(r, ms)); + } + + + function sendSpawnPosition() { console.log("setting spawn at "+player.spawnPoint); @@ -161,7 +223,7 @@ function inject(serv,player) player.emit("connected"); } - function login() + async function login() { if (serv.uuidToPlayer[player._client.uuid]) { player._client.end("You are already connected"); @@ -174,7 +236,7 @@ function inject(serv,player) addPlayer(); sendLogin(); - sendMap(); + await sendMap(); sendSpawnPosition(); sendInitialPosition(); @@ -189,7 +251,6 @@ function inject(serv,player) announceJoin(); } - player.setGameMode=setGameMode; player.login=login; player.sendInitialPosition=sendInitialPosition; diff --git a/src/lib/playerPlugins/updatePositions.js b/src/lib/playerPlugins/updatePositions.js index 66bac76..0dd2941 100644 --- a/src/lib/playerPlugins/updatePositions.js +++ b/src/lib/playerPlugins/updatePositions.js @@ -4,7 +4,7 @@ module.exports=inject; function toFixedPosition(p) { - return new vec3(Math.floor(p.x*32),Math.floor(p.y*32),Math.floor(p.z*32)) + return p.scaled(32); } function inject(serv,player) @@ -80,5 +80,6 @@ function inject(serv,player) } player.entity.position = newPosition; player.entity.onGround = onGround; + player.emit("positionChanged"); } } \ No newline at end of file diff --git a/src/lib/serverPlugins/world.js b/src/lib/serverPlugins/world.js index a2fb75b..1f9a456 100644 --- a/src/lib/serverPlugins/world.js +++ b/src/lib/serverPlugins/world.js @@ -6,22 +6,20 @@ module.exports=inject; function inject(serv) { - serv.world=new World(); + function generateSimpleChunk(chunkX, chunkZ) { + var chunk=new Chunk(); - for(var chunkX=-1;chunkX<2;chunkX++) - { - for(var chunkZ=-1;chunkZ<2;chunkZ++) - { - var chunk=new Chunk(); - for (var x = 0; x < 16;x++) { - for (var z = 0; z < 16; z++) { - chunk.setBlockType(new Vec3(x, 50, z), 2); - for (var y = 0; y < 256; y++) { - chunk.setSkyLight(new Vec3(x, y, z), 15); - } + for (var x = 0; x < 16;x++) { + for (var z = 0; z < 16; z++) { + chunk.setBlockType(new Vec3(x, 50, z), 2); + for (var y = 0; y < 256; y++) { + chunk.setSkyLight(new Vec3(x, y, z), 15); } } - serv.world.setColumn(chunkX,chunkZ,chunk); } + + return chunk; } + + serv.world=new World(generateSimpleChunk); } \ No newline at end of file