Files
factorio-clusterio/plugins/research_sync/instance.js
T
Hornwitser 034ca4c250 Fix research_sync sending commands before instance start
Fix commands syncing researces being sent before the instance is started
up, and potential desync of research progress as a result of out of
order execution of RCON commands sent.
2021-10-01 01:52:18 +02:00

92 lines
2.7 KiB
JavaScript

"use strict";
const libPlugin = require("@clusterio/lib/plugin");
const libLuaTools = require("@clusterio/lib/lua_tools");
class InstancePlugin extends libPlugin.BaseInstancePlugin {
unexpectedError(err) {
this.logger.error(`Unexpected error:\n${err.stack}`);
}
async init() {
if (!this.instance.config.get("factorio.enable_save_patching")) {
throw new Error("research_sync plugin requires save patching.");
}
this.instance.server.on("ipc-research_sync:contribution", (tech) => {
this.researchContribution(tech).catch(err => this.unexpectedError(err));
});
this.instance.server.on("ipc-research_sync:finished", (tech) => {
this.researchFinished(tech).catch(err => this.unexpectedError(err));
});
this.syncStarted = false;
}
async researchContribution(tech) {
this.info.messages.contribution.send(this.instance, tech);
}
async progressEventHandler(message) {
if (!this.syncStarted || !["starting", "running"].includes(this.instance.status)) {
return;
}
let techsJson = libLuaTools.escapeString(JSON.stringify(message.data.technologies));
await this.sendOrderedRcon(`/sc research_sync.update_progress("${techsJson}")`, true);
}
async researchFinished(tech) {
this.info.messages.finished.send(this.instance, tech);
}
async finishedEventHandler(message) {
if (!this.syncStarted || !["starting", "running"].includes(this.instance.status)) {
return;
}
let { name, level, researched } = message.data;
await this.sendOrderedRcon(
`/sc research_sync.research_technology("${libLuaTools.escapeString(name)}", ${level})`, true
);
}
async onStart() {
let dumpJson = await this.sendOrderedRcon("/sc research_sync.dump_technologies()");
let techsToSend = [];
let instanceTechs = new Map();
for (let tech of JSON.parse(dumpJson)) {
techsToSend.push([
tech.name,
tech.level,
tech.progress || null,
tech.researched,
]);
instanceTechs.set(tech.name, tech);
}
let response = await this.info.messages.syncTechnologies.send(this.instance, { technologies: techsToSend });
this.syncStarted = true;
let techsToSync = [];
for (let masterTech of response.technologies) {
let [name, level, progress, researched] = masterTech;
let instanceTech = instanceTechs.get(name);
if (
!instanceTech
|| instanceTech.level !== level
|| (instanceTech.progress || null) !== progress
|| instanceTech.researched !== researched
) {
techsToSync.push(masterTech);
}
}
if (techsToSync.length) {
let syncJson = libLuaTools.escapeString(JSON.stringify(techsToSync));
await this.sendOrderedRcon(`/sc research_sync.sync_technologies("${syncJson}")`, true);
}
}
}
module.exports = {
InstancePlugin,
};