mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-11 23:04:52 +09:00
Rename the onExit hook for master plugins to onShutdown to better reflect when it is invoked.
185 lines
4.8 KiB
JavaScript
185 lines
4.8 KiB
JavaScript
const fs = require("fs-extra");
|
|
const path = require("path");
|
|
|
|
const plugin = require("lib/plugin");
|
|
|
|
|
|
class MasterPlugin extends plugin.BaseMasterPlugin {
|
|
async init() {
|
|
this.technologies = await loadTechnologies(this.master.config);
|
|
this.lastProgressBroadcast = Date.now();
|
|
this.progressBroadcastId = null;
|
|
this.progressToBroadcast = new Set();
|
|
}
|
|
|
|
async onShutdown() {
|
|
if (this.progressBroadcastId) {
|
|
clearTimeout(this.progressBroadcastId);
|
|
}
|
|
await saveTechnologies(this.master.config, this.technologies);
|
|
}
|
|
|
|
registerProgress() {
|
|
// Rate limit progress broadcasts to one per second
|
|
if (Date.now() < this.lastProgressBroadcast + 1000) {
|
|
if (!this.progressBroadcastId) {
|
|
this.progressBroadcastId = setTimeout(() => {
|
|
this.broadcastProgress();
|
|
this.progressBroadcastId = null;
|
|
}, 2000);
|
|
}
|
|
|
|
} else {
|
|
if (this.progressBroadcastId) {
|
|
clearTimeout(this.progressBroadcastId);
|
|
}
|
|
this.broadcastProgress();
|
|
}
|
|
}
|
|
|
|
broadcastProgress() {
|
|
let techs = []
|
|
for (let name of this.progressToBroadcast) {
|
|
let tech = this.technologies.get(name);
|
|
if (tech.progress) {
|
|
techs.push({ name, level: tech.level, progress: tech.progress });
|
|
}
|
|
}
|
|
this.progressToBroadcast.clear();
|
|
|
|
this.lastProgressBroadcast = Date.now();
|
|
if (techs.length) {
|
|
for (let slaveConnection of this.master.slaveConnections.values()) {
|
|
this.info.messages.progress.send(slaveConnection, { technologies: techs });
|
|
}
|
|
}
|
|
}
|
|
|
|
async contributionEventHandler(message) {
|
|
let { name, level, contribution } = message.data;
|
|
let tech = this.technologies.get(name);
|
|
if (!tech) {
|
|
tech = { level, progress: 0, researched: false };
|
|
this.technologies.set(name, tech)
|
|
|
|
// Ignore contribution to already researched technologies
|
|
} else if (tech.level > level || tech.level === level && tech.researched) {
|
|
return;
|
|
}
|
|
|
|
let newProgress = tech.progress + contribution;
|
|
if (newProgress < 1) {
|
|
tech.progress = newProgress;
|
|
this.progressToBroadcast.add(name);
|
|
this.registerProgress();
|
|
|
|
} else {
|
|
tech.researched = true;
|
|
tech.progress = null;
|
|
this.progressToBroadcast.delete(name);
|
|
|
|
for (let slaveConnection of this.master.slaveConnections.values()) {
|
|
this.info.messages.finished.send(slaveConnection, {
|
|
name,
|
|
level: tech.level
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
async finishedEventHandler(message) {
|
|
let { name, level } = message.data;
|
|
let tech = this.technologies.get(name);
|
|
if (!tech || tech.level <= level) {
|
|
this.progressToBroadcast.delete(name);
|
|
this.technologies.set(name, { level, progress: null, researched: true })
|
|
}
|
|
}
|
|
|
|
async syncTechnologiesRequestHandler(message) {
|
|
function baseLevel(name) {
|
|
let match = /-(\d+)$/.exec(name);
|
|
if (!match) {
|
|
return 1;
|
|
} else {
|
|
return Number.parseInt(match[1], 10);
|
|
}
|
|
}
|
|
|
|
for (let instanceTech of message.data.technologies) {
|
|
let [name, level, progress, researched] = instanceTech;
|
|
let tech = this.technologies.get(name);
|
|
if (!tech) {
|
|
this.technologies.set(name, { level, progress, researched });
|
|
if (progress) {
|
|
this.progressToBroadcast.add(name);
|
|
} else if (researched || baseLevel(name) != level) {
|
|
for (let slaveConnection of this.master.slaveConnections.values()) {
|
|
this.info.messages.finished.send(slaveConnection, { name, level });
|
|
}
|
|
}
|
|
|
|
} else {
|
|
if (tech.level > level || tech.level === level && tech.researched) {
|
|
continue;
|
|
}
|
|
|
|
if (tech.level < level || researched) {
|
|
tech.level = level;
|
|
tech.progress = progress;
|
|
tech.researched = researched;
|
|
for (let slaveConnection of this.master.slaveConnections.values()) {
|
|
this.info.messages.finished.send(slaveConnection, { name, level });
|
|
}
|
|
|
|
if (progress) {
|
|
this.progressToBroadcast.add(name);
|
|
} else {
|
|
this.progressToBroadcast.delete(name);
|
|
}
|
|
|
|
} else if (tech.progress < progress) {
|
|
tech.progress = progress;
|
|
this.progressToBroadcast.add(name);
|
|
}
|
|
}
|
|
}
|
|
this.registerProgress();
|
|
|
|
let technologies = [];
|
|
for (let [name, tech] of this.technologies) {
|
|
technologies.push([ name, tech.level, tech.progress, tech.researched ])
|
|
}
|
|
|
|
return { technologies }
|
|
}
|
|
}
|
|
|
|
async function loadTechnologies(masterConfig) {
|
|
let filePath = path.join(masterConfig.get("master.database_directory"), "technologies.json");
|
|
console.log(`Loading ${filePath}`);
|
|
try {
|
|
return new Map(JSON.parse(await fs.readFile(filePath)));
|
|
|
|
} catch (err) {
|
|
if (err.code === "ENOENT") {
|
|
console.log("Creating new technologies database");
|
|
return new Map();
|
|
|
|
} else {
|
|
throw err;
|
|
}
|
|
}
|
|
}
|
|
|
|
async function saveTechnologies(masterConfig, technologies) {
|
|
let filePath = path.join(masterConfig.get("master.database_directory"), "technologies.json");
|
|
console.log(`writing ${filePath}`);
|
|
await fs.outputFile(filePath, JSON.stringify([...technologies.entries()], null, 4));
|
|
}
|
|
|
|
|
|
module.exports = {
|
|
MasterPlugin
|
|
}
|