2021-08-24 15:29:46 +01:00
|
|
|
/*
|
|
|
|
===========- chunkManager.js -==========
|
|
|
|
Created by Holly (tgpethan) (c) 2021
|
|
|
|
Licenced under MIT
|
|
|
|
========================================
|
|
|
|
*/
|
|
|
|
|
2021-08-20 22:42:00 +01:00
|
|
|
const { Worker } = require('worker_threads');
|
2021-08-12 04:58:56 +01:00
|
|
|
const FunkyArray = require("./Util/funkyArray.js");
|
2021-10-21 01:29:25 +01:00
|
|
|
const pRandom = require("./Util/prettyRandom.js");
|
2021-08-12 22:01:07 +01:00
|
|
|
const config = require("../config.json");
|
|
|
|
|
2021-08-20 22:42:00 +01:00
|
|
|
const workerPath = `${__dirname}/Workers/ChunkWorker.js`;
|
2021-08-12 08:41:08 +01:00
|
|
|
|
2021-08-11 15:05:14 +01:00
|
|
|
module.exports = class {
|
|
|
|
constructor() {
|
2021-08-12 01:44:18 +01:00
|
|
|
this.chunks = {};
|
|
|
|
|
2021-08-12 04:58:56 +01:00
|
|
|
this.queuedBlockUpdates = new FunkyArray();
|
|
|
|
|
2021-08-12 08:41:08 +01:00
|
|
|
global.generatingChunks = true;
|
|
|
|
|
|
|
|
this.threadPool = [];
|
|
|
|
this.workPool = new FunkyArray();
|
|
|
|
this.toRemove = [];
|
|
|
|
|
2021-10-21 01:29:25 +01:00
|
|
|
// TODO: Figure out a better way of doing this?
|
|
|
|
this.seed = pRandom(-2147483647, 2147483647) - new Date().getTime() * pRandom(1, 6);
|
|
|
|
|
2021-08-15 11:32:38 +01:00
|
|
|
// WoAh!!! Thread pool in js!?!??!???!11!?!?!
|
2021-08-21 08:22:09 +01:00
|
|
|
for (let i = 0; i < config.worldThreads; i++) {
|
2021-08-12 08:41:08 +01:00
|
|
|
const worker = new Worker(workerPath);
|
|
|
|
this.threadPool.push([false, worker]);
|
|
|
|
const myID = i;
|
2021-08-12 22:01:07 +01:00
|
|
|
worker.on("message", (data) => {
|
2021-08-21 09:38:25 +01:00
|
|
|
let user;
|
2021-08-12 22:01:07 +01:00
|
|
|
switch (data[0]) {
|
|
|
|
case "chunk":
|
2021-08-21 09:38:25 +01:00
|
|
|
user = global.getUserByKey(data[2]);
|
2021-08-12 22:01:07 +01:00
|
|
|
user.chunksToSend.add(Buffer.from(data[1]));
|
2021-08-15 11:32:38 +01:00
|
|
|
this.toRemove.push(data[1]);
|
2021-08-12 22:01:07 +01:00
|
|
|
this.threadPool[myID][0] = false;
|
|
|
|
break;
|
|
|
|
|
2021-08-15 11:32:38 +01:00
|
|
|
case "generate":
|
|
|
|
this.chunks[data[2]][data[3]] = data[1];
|
|
|
|
this.toRemove.push(data[4]);
|
2021-10-21 01:29:25 +01:00
|
|
|
const treeBlocksRef = data[5];
|
|
|
|
treeBlocksRef.forEach((block) => {
|
2021-10-21 11:38:19 +01:00
|
|
|
this.setBlock(block[0], block[1], block[2], block[3], 0, false);
|
2021-10-21 01:29:25 +01:00
|
|
|
});
|
2021-10-21 11:38:19 +01:00
|
|
|
this.queuedBlockUpdates.regenerateIterableArray();
|
2021-08-12 22:01:07 +01:00
|
|
|
this.threadPool[myID][0] = false;
|
|
|
|
break;
|
|
|
|
}
|
2021-08-12 08:41:08 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-08-12 22:01:07 +01:00
|
|
|
console.log("Created thread pool with " + this.threadPool.length + " threads");
|
|
|
|
|
2021-08-12 08:41:08 +01:00
|
|
|
setInterval(() => {
|
|
|
|
if (this.workPool.getLength() > 0) {
|
|
|
|
let limit = Math.min(this.workPool.getLength(), this.threadPool.length);
|
|
|
|
for (let i = 0; i < limit; i++) {
|
|
|
|
for (let i1 = 0; i1 < this.threadPool.length; i1++) {
|
|
|
|
let thread = this.threadPool[i1];
|
|
|
|
if (!thread[0]) {
|
|
|
|
const key = this.workPool.itemKeys[i];
|
|
|
|
const item = this.workPool.getByKey(key);
|
|
|
|
// Already being processed
|
|
|
|
if (item == null) break;
|
|
|
|
if (item[0] == true) {
|
|
|
|
limit += 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
item[0] = true;
|
2021-08-12 22:01:07 +01:00
|
|
|
item[1][3] = key;
|
2021-08-12 08:41:08 +01:00
|
|
|
thread[1].postMessage(item[1]);
|
|
|
|
thread[0] = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let item of this.toRemove) {
|
|
|
|
//console.log("removing item " + this.workPool.getByKey(item)[0]);
|
|
|
|
this.workPool.remove(item);
|
|
|
|
}
|
|
|
|
this.toRemove = [];
|
|
|
|
}
|
2021-10-21 01:29:25 +01:00
|
|
|
}, 1000 / 60);
|
2021-08-12 08:41:08 +01:00
|
|
|
|
|
|
|
global.generatingChunks = false;
|
2021-08-12 01:44:18 +01:00
|
|
|
}
|
|
|
|
|
2021-08-12 04:58:56 +01:00
|
|
|
// TODO: Store metadata!
|
|
|
|
createChunk(cx = 0, cz = 0) {
|
|
|
|
if (this.chunks[cx] == null) this.chunks[cx] = {};
|
2021-08-12 22:01:07 +01:00
|
|
|
|
2021-10-21 01:29:25 +01:00
|
|
|
this.workPool.add([false, ["generate", cx, cz, null, this.seed]]);
|
2021-08-12 04:58:56 +01:00
|
|
|
}
|
|
|
|
|
2021-10-19 08:17:18 +01:00
|
|
|
chunkExists(cx = 0, cz = 0) {
|
|
|
|
if (this.chunks[cx] == null) return false;
|
|
|
|
if (this.chunks[cx][cz] == null) return false;
|
|
|
|
|
|
|
|
// In any other case the chunk exists
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-08-12 22:01:07 +01:00
|
|
|
multiBlockChunk(chunkX = 0, chunkZ = 0, user) {
|
|
|
|
this.workPool.add([false, ["chunk", [chunkX, chunkZ, this.chunks[chunkX][chunkZ]], user.id, null]]);
|
2021-08-12 04:58:56 +01:00
|
|
|
}
|
|
|
|
|
2021-10-21 11:38:19 +01:00
|
|
|
setBlock(x = 0, y = 0, z = 0, id = 0, metadata = 0, regenerate = true) {
|
2021-08-20 22:42:00 +01:00
|
|
|
if (y < 0 || y > 127) return console.error("Tried to set a block outside of the world!");
|
2021-08-12 04:58:56 +01:00
|
|
|
|
2021-10-19 08:17:18 +01:00
|
|
|
const chunkX = x >> 4;
|
|
|
|
const chunkZ = z >> 4;
|
2021-10-21 01:29:25 +01:00
|
|
|
const blockX = x - (chunkX << 4);
|
|
|
|
const blockZ = z - (chunkZ << 4);
|
2021-08-12 04:58:56 +01:00
|
|
|
|
2021-10-21 01:29:25 +01:00
|
|
|
// Don't queue a block update if that block is already this block (wow those ifs)
|
|
|
|
if (this.chunks[chunkX] != null)
|
|
|
|
if (this.chunks[chunkX][chunkZ] != null)
|
|
|
|
if (this.chunks[chunkX][chunkZ][y][blockX][blockZ] == id) return;
|
2021-08-12 01:44:18 +01:00
|
|
|
|
2021-10-21 11:38:19 +01:00
|
|
|
this.queuedBlockUpdates.add([chunkX, chunkZ, y, blockX, blockZ, id, metadata], regenerate);
|
2021-08-11 15:05:14 +01:00
|
|
|
}
|
|
|
|
}
|