make chunk generation use the thread pool
This commit is contained in:
parent
cfde8a7b87
commit
19880f1e8d
4 changed files with 101 additions and 79 deletions
|
@ -1,3 +1,4 @@
|
||||||
{
|
{
|
||||||
"port": 25565
|
"port": 25565,
|
||||||
|
"threadPoolCount": 8
|
||||||
}
|
}
|
|
@ -5,36 +5,59 @@ const bufferStuff = require("../bufferStuff.js");
|
||||||
let chunkY = 0;
|
let chunkY = 0;
|
||||||
let busyInterval = null;
|
let busyInterval = null;
|
||||||
|
|
||||||
parentPort.on("message", (chunk) => {
|
parentPort.on("message", (data) => {
|
||||||
if (busyInterval == null) {
|
// This stops the thread from stopping :)
|
||||||
busyInterval = setInterval(() => {}, 86400000);
|
if (busyInterval == null) busyInterval = setInterval(() => {}, 86400000);
|
||||||
|
|
||||||
|
switch (data[0]) {
|
||||||
|
case "chunk":
|
||||||
|
chunkY = 0;
|
||||||
|
|
||||||
|
parentPort.postMessage([data[0], doSquareChunk(data[1]), data[2]]);
|
||||||
|
chunkY += 16;
|
||||||
|
parentPort.postMessage([data[0], doSquareChunk(data[1]), data[2]]);
|
||||||
|
chunkY += 16;
|
||||||
|
parentPort.postMessage([data[0], doSquareChunk(data[1]), data[2]]);
|
||||||
|
chunkY += 16;
|
||||||
|
parentPort.postMessage([data[0], doSquareChunk(data[1]), data[2]]);
|
||||||
|
chunkY += 16;
|
||||||
|
parentPort.postMessage([data[0], doSquareChunk(data[1]), data[2]]);
|
||||||
|
chunkY += 16;
|
||||||
|
parentPort.postMessage([data[0], doSquareChunk(data[1]), data[2]]);
|
||||||
|
chunkY += 16;
|
||||||
|
parentPort.postMessage([data[0], doSquareChunk(data[1]), data[2]]);
|
||||||
|
chunkY += 16;
|
||||||
|
parentPort.postMessage([data[0], doSquareChunk(data[1]), data[2]]);
|
||||||
|
|
||||||
|
parentPort.postMessage(["remove", data[3]]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "generate":
|
||||||
|
parentPort.postMessage([data[0], generateChunk(), data[1], data[2], data[3]]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function generateChunk() {
|
||||||
|
let chunk = {};
|
||||||
|
for (let y = 0; y < 128; y++) {
|
||||||
|
chunk[y] = {};
|
||||||
|
for (let x = 0; x < 16; x++) {
|
||||||
|
chunk[y][x] = {};
|
||||||
|
for (let z = 0; z < 16; z++) {
|
||||||
|
if (y == 64) {
|
||||||
|
chunk[y][x][z] = 2;
|
||||||
|
}
|
||||||
|
else if (y == 63 || y == 62) chunk[y][x][z] = 3;
|
||||||
|
else if (y == 0) chunk[y][x][z] = 7;
|
||||||
|
else if (y < 62) chunk[y][x][z] = 1;
|
||||||
|
else chunk[y][x][z] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chunkY = 0;
|
return chunk;
|
||||||
// I couldn't figure out how to construct a chunk lmao
|
}
|
||||||
// __ima just send each block individually__
|
|
||||||
// Using multi block chunks now!
|
|
||||||
// TODO: yknow, figure out how to chunk.
|
|
||||||
let chunksToSend = [];
|
|
||||||
|
|
||||||
chunksToSend.push(doSquareChunk(chunk));
|
|
||||||
chunkY += 16;
|
|
||||||
chunksToSend.push(doSquareChunk(chunk));
|
|
||||||
chunkY += 16;
|
|
||||||
chunksToSend.push(doSquareChunk(chunk));
|
|
||||||
chunkY += 16;
|
|
||||||
chunksToSend.push(doSquareChunk(chunk));
|
|
||||||
chunkY += 16;
|
|
||||||
chunksToSend.push(doSquareChunk(chunk));
|
|
||||||
chunkY += 16;
|
|
||||||
chunksToSend.push(doSquareChunk(chunk));
|
|
||||||
chunkY += 16;
|
|
||||||
chunksToSend.push(doSquareChunk(chunk));
|
|
||||||
chunkY += 16;
|
|
||||||
chunksToSend.push(doSquareChunk(chunk));
|
|
||||||
|
|
||||||
parentPort.postMessage([chunk[3], chunksToSend, chunk[4], chunk[5]]);
|
|
||||||
});
|
|
||||||
|
|
||||||
function doSquareChunk(chunk) {
|
function doSquareChunk(chunk) {
|
||||||
let blocksToSend = [];
|
let blocksToSend = [];
|
||||||
|
@ -47,6 +70,9 @@ function doSquareChunk(chunk) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// I couldn't figure out how to construct a chunk lmao
|
||||||
|
// Using multi block chunks for now
|
||||||
|
// TODO: yknow, figure out how to actually chunk.
|
||||||
const writer = new bufferStuff.Writer();
|
const writer = new bufferStuff.Writer();
|
||||||
writer.writeByte(0x34);
|
writer.writeByte(0x34);
|
||||||
writer.writeInt(chunk[0]);
|
writer.writeInt(chunk[0]);
|
||||||
|
@ -65,7 +91,5 @@ function doSquareChunk(chunk) {
|
||||||
writer.writeByte(0);
|
writer.writeByte(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//user.chunksToSend.add(writer.buffer) // so we don't flood the client queue these
|
|
||||||
//parentPort.postMessage(writer.buffer);
|
|
||||||
return writer.buffer;
|
return writer.buffer;
|
||||||
}
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
const FunkyArray = require("./Util/funkyArray.js");
|
const FunkyArray = require("./Util/funkyArray.js");
|
||||||
const bufferStuff = require("./bufferStuff.js");
|
const bufferStuff = require("./bufferStuff.js");
|
||||||
|
|
||||||
const { Worker, isMainThread, parentPort } = require('worker_threads');
|
const config = require("../config.json");
|
||||||
|
|
||||||
|
const { Worker } = require('worker_threads');
|
||||||
|
|
||||||
const workerPath = __dirname + "/Workers/ChunkPacketGenerator.js";
|
const workerPath = __dirname + "/Workers/ChunkPacketGenerator.js";
|
||||||
|
|
||||||
|
@ -18,18 +20,38 @@ module.exports = class {
|
||||||
|
|
||||||
this.toRemove = [];
|
this.toRemove = [];
|
||||||
|
|
||||||
for (let i = 0; i < 4; i++) {
|
for (let i = 0; i < config.threadPoolCount; i++) {
|
||||||
const worker = new Worker(workerPath);
|
const worker = new Worker(workerPath);
|
||||||
this.threadPool.push([false, worker]);
|
this.threadPool.push([false, worker]);
|
||||||
const myID = i;
|
const myID = i;
|
||||||
worker.on("message", (message) => {
|
worker.on("message", (data) => {
|
||||||
const user = global.getUserByKey(message[0]);
|
/*const user = global.getUserByKey(message[0]);
|
||||||
for (let square of message[1]) { user.chunksToSend.add(Buffer.from(square)); }
|
for (let square of message[1]) { user.chunksToSend.add(Buffer.from(square)); }
|
||||||
this.threadPool[myID][0] = false;
|
this.threadPool[myID][0] = false;
|
||||||
this.toRemove.push(message[2]);
|
this.toRemove.push(message[2]);*/
|
||||||
|
switch (data[0]) {
|
||||||
|
case "chunk":
|
||||||
|
const user = global.getUserByKey(data[2]);
|
||||||
|
user.chunksToSend.add(Buffer.from(data[1]));
|
||||||
|
//this.threadPool[myID][0] = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "generate":
|
||||||
|
this.chunks[data[2]][data[3]] = data[1];
|
||||||
|
this.toRemove.push(data[4]);
|
||||||
|
this.threadPool[myID][0] = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "remove":
|
||||||
|
this.toRemove.push(data[1]);
|
||||||
|
this.threadPool[myID][0] = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("Created thread pool with " + this.threadPool.length + " threads");
|
||||||
|
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
if (this.workPool.getLength() > 0) {
|
if (this.workPool.getLength() > 0) {
|
||||||
let limit = Math.min(this.workPool.getLength(), this.threadPool.length);
|
let limit = Math.min(this.workPool.getLength(), this.threadPool.length);
|
||||||
|
@ -46,8 +68,7 @@ module.exports = class {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
item[0] = true;
|
item[0] = true;
|
||||||
item[1][4] = key;
|
item[1][3] = key;
|
||||||
item[1][5] = i1;
|
|
||||||
thread[1].postMessage(item[1]);
|
thread[1].postMessage(item[1]);
|
||||||
thread[0] = true;
|
thread[0] = true;
|
||||||
break;
|
break;
|
||||||
|
@ -63,13 +84,11 @@ module.exports = class {
|
||||||
}
|
}
|
||||||
}, 1000 / 20);
|
}, 1000 / 20);
|
||||||
|
|
||||||
const chunkStartTime = new Date().getTime();
|
|
||||||
for (let x = -3; x < 4; x++) {
|
for (let x = -3; x < 4; x++) {
|
||||||
for (let z = -3; z < 4; z++) {
|
for (let z = -3; z < 4; z++) {
|
||||||
this.createChunk(x, z);
|
this.createChunk(x, z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log("Chunk generation took " + (new Date().getTime() - chunkStartTime) + "ms");
|
|
||||||
|
|
||||||
global.generatingChunks = false;
|
global.generatingChunks = false;
|
||||||
}
|
}
|
||||||
|
@ -77,46 +96,12 @@ module.exports = class {
|
||||||
// TODO: Store metadata!
|
// TODO: Store metadata!
|
||||||
createChunk(cx = 0, cz = 0) {
|
createChunk(cx = 0, cz = 0) {
|
||||||
if (this.chunks[cx] == null) this.chunks[cx] = {};
|
if (this.chunks[cx] == null) this.chunks[cx] = {};
|
||||||
this.chunks[cx][cz] = {};
|
|
||||||
|
|
||||||
let chunkQueuedBlocks = [];
|
this.workPool.add([false, ["generate", cx, cz, null]]);
|
||||||
|
|
||||||
for (let y = 0; y < 128; y++) {
|
|
||||||
this.chunks[cx][cz][y] = {};
|
|
||||||
for (let x = 0; x < 16; x++) {
|
|
||||||
this.chunks[cx][cz][y][x] = {};
|
|
||||||
for (let z = 0; z < 16; z++) {
|
|
||||||
if (y == 64) {
|
|
||||||
// Make a tree :)
|
|
||||||
if (Math.random() <= 0.01) {
|
|
||||||
this.chunks[cx][cz][y][x][z] = 3;
|
|
||||||
|
|
||||||
const newX = x + (16 * cx), newZ = z + (16 * cz);
|
|
||||||
// trunk
|
|
||||||
this.setBlock(17, newX, y + 1, newZ);
|
|
||||||
this.setBlock(17, newX, y + 2, newZ);
|
|
||||||
this.setBlock(17, newX, y + 3, newZ);
|
|
||||||
this.setBlock(17, newX, y + 4, newZ);
|
|
||||||
// leaves
|
|
||||||
// left
|
|
||||||
this.setBlock(18, newX, y + 5, newZ);
|
|
||||||
// right line
|
|
||||||
} else {
|
|
||||||
this.chunks[cx][cz][y][x][z] = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (y == 63 || y == 62) this.chunks[cx][cz][y][x][z] = 3;
|
|
||||||
else if (y == 0) this.chunks[cx][cz][y][x][z] = 7;
|
|
||||||
else if (y < 62) this.chunks[cx][cz][y][x][z] = 1;
|
|
||||||
else this.chunks[cx][cz][y][x][z] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async multiBlockChunk(chunkX = 0, chunkZ = 0, user) {
|
multiBlockChunk(chunkX = 0, chunkZ = 0, user) {
|
||||||
//worker.postMessage([chunkX, chunkZ, this.chunks[chunkX][chunkZ]]);
|
this.workPool.add([false, ["chunk", [chunkX, chunkZ, this.chunks[chunkX][chunkZ]], user.id, null]]);
|
||||||
this.workPool.add([false, [chunkX, chunkZ, this.chunks[chunkX][chunkZ], user.id, null, null]]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setBlock(id = 0, x = 0, y = 0, z = 0) {
|
setBlock(id = 0, x = 0, y = 0, z = 0) {
|
||||||
|
|
|
@ -49,12 +49,19 @@ module.exports.init = function(config) {
|
||||||
console.log(`Up! Running at 0.0.0.0:${config.port}`);
|
console.log(`Up! Running at 0.0.0.0:${config.port}`);
|
||||||
|
|
||||||
tickInterval = setInterval(() => {
|
tickInterval = setInterval(() => {
|
||||||
|
if (tickCounter % tickRate == 0) {
|
||||||
|
for (let key of netUserKeys) {
|
||||||
|
netUsers[key].socket.write(new PacketMappingTable[NamedPackets.KeepAlive]().writePacket());
|
||||||
|
}
|
||||||
|
}
|
||||||
// Update Chunks
|
// Update Chunks
|
||||||
if (!global.generatingChunks) {
|
if (!global.generatingChunks) {
|
||||||
let itemsToRemove = [];
|
let itemsToRemove = [];
|
||||||
for (let i = 0; i < Math.min(global.chunkManager.queuedBlockUpdates.getLength(), 128); i++) {
|
for (let i = 0; i < Math.min(global.chunkManager.queuedBlockUpdates.getLength(), 128); i++) {
|
||||||
const chunkUpdateKey = global.chunkManager.queuedBlockUpdates.itemKeys[i];
|
const chunkUpdateKey = global.chunkManager.queuedBlockUpdates.itemKeys[i];
|
||||||
const chunkUpdate = global.chunkManager.queuedBlockUpdates.items[chunkUpdateKey];
|
const chunkUpdate = global.chunkManager.queuedBlockUpdates.items[chunkUpdateKey];
|
||||||
|
if (global.chunkManager.chunks[chunkUpdate[1]] == null) continue;
|
||||||
|
if (global.chunkManager.chunks[chunkUpdate[1]][chunkUpdate[2]] == null) continue;
|
||||||
itemsToRemove.push(chunkUpdateKey);
|
itemsToRemove.push(chunkUpdateKey);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -117,7 +124,12 @@ module.exports.connection = async function(socket = new Socket) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log("Chunk packet generation took " + (new Date().getTime() - dt) + "ms");
|
console.log("Chunk packet generation took " + (new Date().getTime() - dt) + "ms");
|
||||||
socket.write(new PacketMappingTable[NamedPackets.BlockChange](8, 64, 8, 20, 0).writePacket());
|
|
||||||
|
for (let x = 0; x < 16; x++) {
|
||||||
|
for (let z = 0; z < 16; z++) {
|
||||||
|
socket.write(new PacketMappingTable[NamedPackets.BlockChange](x, 64, z, 20, 0).writePacket());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
socket.write(new PacketMappingTable[NamedPackets.Player](true).writePacket());
|
socket.write(new PacketMappingTable[NamedPackets.Player](true).writePacket());
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue