diff --git a/master.js b/master.js index cba39301..358e911f 100644 --- a/master.js +++ b/master.js @@ -378,8 +378,13 @@ app.post("/api/getSlaveMeta", function (req, res) { endpointHitCounter.labels(req.route.path).inc(); console.log("body", req.body); if(req.body && req.body.instanceID && req.body.password){ - console.log("returning meta for ", req.body.instanceID); - res.send(JSON.stringify(slaves[req.body.instanceID].meta)) + if (slaves[req.body.instanceID]) { + console.log("returning meta for ", req.body.instanceID); + res.send(JSON.stringify(slaves[req.body.instanceID].meta)) + } else { + res.status(404) + res.send('{"status": 404, "info": "Slave not registered"}') + } } else { res.status(400); res.send('{"INVALID REQUEST":1}'); diff --git a/sharedPlugins/researchSync/dumpResearch.lua b/sharedPlugins/researchSync/dumpResearch.lua index 178365fc..27ec7946 100644 --- a/sharedPlugins/researchSync/dumpResearch.lua +++ b/sharedPlugins/researchSync/dumpResearch.lua @@ -9,11 +9,13 @@ for _, tech in pairs(force.technologies) do else progress = force.get_saved_technology_progress(tech.name); end + local infinite = tech.enabled == true and tech.prototype.max_level == 4294967295; local tech_data = { tech.name, tostring(tech.researched), tostring(tech.level), tostring(progress), + tostring(infinite), } tech_data = table.concat(tech_data, ':') table.insert(data, tech_data); diff --git a/sharedPlugins/researchSync/enableResearch.lua b/sharedPlugins/researchSync/enableResearch.lua index 22a00652..4e5af42a 100644 --- a/sharedPlugins/researchSync/enableResearch.lua +++ b/sharedPlugins/researchSync/enableResearch.lua @@ -1,16 +1,17 @@ if game.forces['player'].technologies['{tech_name}'] then - if game.forces['player'].technologies['{tech_name}'].researched ~= {tech_researched} then - game.forces['player'].technologies['{tech_name}'].researched = {tech_researched} - end - if game.forces['player'].technologies['{tech_name}'].level ~= {tech_level} then - game.forces['player'].technologies['{tech_name}'].level = {tech_level} - end + if 1 == {tech_infinite} then + game.forces['player'].technologies['{tech_name}'].level = {tech_level} + else + game.forces['player'].technologies['{tech_name}'].researched = true + end script.raise_event(defines.events.on_research_finished, {research=game.forces['player'].technologies['{tech_name}'], by_script=true}) - game.play_sound({path="utility/research_completed"}) - if game.forces['player'].technologies['{tech_name}'].researched == false then - game.print("Technology {tech_name} synced at level {tech_level}") - else - game.print("Technology {tech_name} synced") - end + if {notify} then + if 1 == {tech_infinite} then + game.print("Infinite technology {tech_name} level {tech_level} unlocked") + else + game.print("Technology {tech_name} researched") + end + game.play_sound({path="utility/research_completed"}) + end end diff --git a/sharedPlugins/researchSync/index.js b/sharedPlugins/researchSync/index.js index e23c79b9..d8cb5887 100644 --- a/sharedPlugins/researchSync/index.js +++ b/sharedPlugins/researchSync/index.js @@ -1,10 +1,6 @@ const fs = require('fs'); const needle = require("needle"); -function format_tech(tech) { - return `${!!tech.researched} at level ${tech.level}` -} - class ResearchSync { constructor(slaveConfig, messageInterface, extras = {}){ @@ -39,6 +35,14 @@ class ResearchSync { console.error(err) return } + if (res.statusCode === 404) { + console.log('researchSync: slave is not registered yet. Delaying for 5 secs') + setTimeout( + () => this.initial_request_own_data(callback), + 5000 + ) + return + } if (res.statusCode !== 200) { console.log(`Can't get own slave data:`) console.error(`status code ${res.statusCode}, ${res.body}`) @@ -47,6 +51,7 @@ class ResearchSync { techs = JSON.parse(techs) if (typeof techs.research === 'object') this.research = techs.research + console.log('researchSync: techs imported from master') callback() }) } @@ -82,6 +87,7 @@ class ResearchSync { && slave_data.meta && slave_data.meta.research ) + this.clear_contribution_to_researched_techs() let cluster_techs = this.get_cluster_techs(slaves_data) this.recount_cluster_research_progress(slaves_data, cluster_techs) @@ -98,6 +104,7 @@ class ResearchSync { password: this.config.clientPassword, meta: {research: this.research} }, {headers: {'x-access-token': this.config.masterAuthToken}, json: true}, function (err, resp) { + // it doesn't get called if (err) console.error(err) else @@ -105,27 +112,42 @@ class ResearchSync { }); } + clear_contribution_to_researched_techs() { + // if between updates tech was researched + if (!this.prev_research) + return + for (let [name, research] of Object.entries(this.research)) { + let researched + if (research.infinite) + researched = this.prev_research[name].level < research.level + else + researched = this.prev_research[name].researched < research.researched + + if (researched) + research.contribution = 0 + } + } + get_cluster_techs(slavesData) { - let researches = {} + let cluster_techs = {} for (let slave_data of slavesData) { let node_researches = slave_data.meta.research - for (let [name, research] of Object.entries(node_researches)) { - if (isNaN(research.researched) || isNaN(research.level)) + for (let [name, node_tech] of Object.entries(node_researches)) { + if (isNaN(node_tech.researched) || isNaN(node_tech.level) || isNaN(node_tech.infinite)) continue - if (researches[name]) { - if (researches[name].researched === 0) { - researches[name].researched = research.researched - } - if (researches[name].level < research.level) { - researches[name].level = research.level + if (cluster_techs[name]) { + if (cluster_techs[name].infinite === 1 && cluster_techs[name].level < node_tech.level) { + cluster_techs[name].level = node_tech.level + } else if (node_tech.researched > cluster_techs[name].researched) { + cluster_techs[name].researched = 1 } } else { - researches[name] = research + cluster_techs[name] = node_tech } } } - return researches + return cluster_techs } recount_cluster_research_progress(slaves_data, cluster_researches) { @@ -158,10 +180,14 @@ class ResearchSync { if (isNaN(cluster_researches[key].researched) || isNaN(cluster_researches[key].level)) continue - if (cluster_researches[key].researched > local_researches[key].researched - || cluster_researches[key].level > local_researches[key].level) { + let researched + if (local_researches[key].infinite) + researched = local_researches[key].level < cluster_researches[key].level + else + researched = local_researches[key].researched < cluster_researches[key].researched + + if (researched) result[key] = cluster_researches[key] - } } return result; } @@ -181,22 +207,26 @@ class ResearchSync { } research_technologies(to_research) { - for (let [name, tech] of Object.entries(to_research)) { + for (let name of Object.keys(to_research)) if (!this.research[name]) - continue + delete to_research[name] + + const notify = Object.keys(to_research).length === 1 + for (let [name, tech] of Object.entries(to_research)) { this.research[name].contribution = 0 this.research[name].progress = null let command = this.functions.enableResearch; command = command.replace(/{tech_name}/g, name); command = command.replace(/{tech_researched}/g, tech.researched); command = command.replace(/{tech_level}/g, tech.level); + command = command.replace(/{tech_infinite}/g, tech.infinite); + command = command.replace(/{notify}/g, notify); this.messageInterface(command); - console.log( - `Unlocking ${name}: ${format_tech(tech)}, was ${format_tech(this.research[name])}` - ); - this.messageInterface( - `Unlocking research: ${name} with research state ${format_tech(tech)}` - ); + let log_message = tech.infinite + ? `Unlocking infinite research ${name} at level ${this.research[name].level}` + : `Unlocking research ${name}` + console.log(log_message); + this.messageInterface(log_message); this.research[name] = tech; } } @@ -210,7 +240,6 @@ class ResearchSync { progress = 'nil' let command = this.functions.updateProgress command = command.replace(/{tech_name}/g, name) - command = command.replace(/{last_check_progress}/g, progress) command = command.replace(/{new_progress}/g, tech.progress) this.messageInterface(command); @@ -240,8 +269,9 @@ class ResearchSync { return command; } scriptOutput(data) { - let [name, researched, level, progress] = data.split(":") - researched = +(researched === 'true'); + let [name, researched, level, progress, infinite] = data.split(":") + researched = +(researched === 'true') + infinite = +(infinite === 'true') level = parseInt(level); if (progress === 'nil') progress = null @@ -257,13 +287,15 @@ class ResearchSync { level: null, progress: null, contribution: 0, + infinite, } } this.research[name] = { researched, level, progress, - contribution: this.prev_research[name].contribution + contribution: this.prev_research[name].contribution, + infinite } if (this.prev_research[name].progress && this.research[name].progress) { // this.prev_research[name].progress gets updated to overall cluster progress diff --git a/sharedPlugins/statisticsExporter/index.js b/sharedPlugins/statisticsExporter/index.js index bc2579fb..93062f9e 100644 --- a/sharedPlugins/statisticsExporter/index.js +++ b/sharedPlugins/statisticsExporter/index.js @@ -20,13 +20,19 @@ module.exports = class remoteCommands { setInterval(async () => { let stats = await this.getStats(); stats.forEach(force => { - needle.post(`${mergedConfig.masterIP}:${mergedConfig.masterPort}/api/logStats`, { + // I have no idea why I need to do JSON.stringify before passing it to needle.post, + // but if you do forceData: force.data, it doesn't work... + let request = { instanceID: this.config.unique, force: force.forceName, - data: force.data, - }, needleOptionsWithTokenAuthHeader, (err, resp) => { - if(!err && resp.body && resp.body.ok == false) console.log(resp.body); - }); + forceData: JSON.stringify(force.data), + }; + needle.post(`${mergedConfig.masterIP}:${mergedConfig.masterPort}/api/logStats`, + request, + needleOptionsWithTokenAuthHeader, (err, resp) => { + if(!err && resp.body && resp.body.ok == false) console.log("Error calling /api/logStats: " + resp.body); + } + ); }); }, 15000); } diff --git a/sharedPlugins/statisticsExporter/masterPlugin.js b/sharedPlugins/statisticsExporter/masterPlugin.js index 7a5da91e..689dd2eb 100644 --- a/sharedPlugins/statisticsExporter/masterPlugin.js +++ b/sharedPlugins/statisticsExporter/masterPlugin.js @@ -26,18 +26,22 @@ class masterPlugin { @returns {string} failure */ app.post("/api/logStats", authenticate.middleware, function(req,res) { + let data = req.body.forceData; + if(typeof req.body.forceData == "string") { + data = JSON.parse(req.body.forceData); + } // endpointHitCounter.labels(req.route.path).inc(); if(typeof req.body == "object" && req.body.instanceID && typeof req.body.instanceID == "string" && req.body.instanceID.length < 100 - && req.body.data - && typeof req.body.data == "object" - && !Array.isArray(req.body.data)){ + && data + && typeof data == "object" + && !Array.isArray(data)){ try{ - Object.keys(req.body.data).forEach(statisticName => { - Object.keys(req.body.data[statisticName]).forEach(direction => { - let statHash = req.body.data[statisticName][direction]; + Object.keys(data).forEach(statisticName => { + Object.keys(data[statisticName]).forEach(direction => { + let statHash = data[statisticName][direction]; Object.keys(statHash).forEach(item => { let value = Number(statHash[item]); if(value) prometheusStatisticsGauge.labels(req.body.instanceID, req.body.force, statisticName, direction, item).set(value); @@ -50,6 +54,8 @@ class masterPlugin { console.log(e) }; } else { + console.log(`/api/logStats: Invalid request. instanceID: ${req.body.instanceID}, dataIsArray: ` + + `${Array.isArray(data)}, ${typeof req.body.instanceID}, ${typeof data}`); res.send({ ok:false, msg:"Invalid request parameters"