From fa4c10dce23de8165d1b148cf5a46c2277b219c1 Mon Sep 17 00:00:00 2001 From: TechnoStrife Date: Fri, 12 Jul 2019 16:22:26 +0300 Subject: [PATCH 1/4] Code refactor --- .gitignore | 3 + sharedPlugins/researchSync/dumpResearch.lua | 9 +- sharedPlugins/researchSync/enableResearch.lua | 2 +- sharedPlugins/researchSync/index.js | 133 ++++++++++-------- 4 files changed, 86 insertions(+), 61 deletions(-) diff --git a/.gitignore b/.gitignore index d12f04bb..a7049f1f 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,6 @@ sharedPlugins/scenario_loader/scenarios sharedPlugins/*/DISABLED \.cache-require-paths\.json + +# IDE +.idea/ diff --git a/sharedPlugins/researchSync/dumpResearch.lua b/sharedPlugins/researchSync/dumpResearch.lua index 2ecfb17b..e7e43cf0 100644 --- a/sharedPlugins/researchSync/dumpResearch.lua +++ b/sharedPlugins/researchSync/dumpResearch.lua @@ -1,9 +1,14 @@ -/silent-command local data = {}; for _, tech in pairs(game.forces["player"].technologies) do - table.insert(data, tech.name .. ":" .. tostring(tech.researched) .. ":" .. tostring(tech.level)); + local tech_data = { + tech.name, + tostring(tech.researched), + tostring(tech.level), + } + tech_data = table.concat(tech_data, ':') + table.insert(data, tech_data); end game.write_file("researchSync.txt", table.concat(data, "\n"), false, 0) diff --git a/sharedPlugins/researchSync/enableResearch.lua b/sharedPlugins/researchSync/enableResearch.lua index 13004d13..22a00652 100644 --- a/sharedPlugins/researchSync/enableResearch.lua +++ b/sharedPlugins/researchSync/enableResearch.lua @@ -1,4 +1,4 @@ -/silent-command + 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} diff --git a/sharedPlugins/researchSync/index.js b/sharedPlugins/researchSync/index.js index e198e310..7ab9c488 100644 --- a/sharedPlugins/researchSync/index.js +++ b/sharedPlugins/researchSync/index.js @@ -1,13 +1,24 @@ const fs = require('fs'); const needle = require("needle"); +function format_tech(tech) { + return `${!!tech.researched} at level ${tech.level}` +} + + +function log_tech_unlocking(key, current, prev) { + console.log( + `Unlocking ${key}: ${format_tech(current)}, was ${format_tech(prev)}` + ); +} + class ResearchSync { constructor(slaveConfig, messageInterface, extras = {}){ this.config = slaveConfig; this.messageInterface = messageInterface; this.functions = this.loadFunctions(); - + this.research = {}; setInterval(() => { @@ -22,61 +33,62 @@ class ResearchSync { } doSync() { - needle.get(this.config.masterIP + ':' + this.config.masterPort + '/api/slaves', (err, resp, slaveData) => { - if (err){ + const slaves_data_url = `${this.config.masterIP}:${this.config.masterPort}/api/slaves` + needle.get(slaves_data_url, (err, resp, slavesData) => { + if (err) { this.messageInterface("Unable to post JSON master/api/slaves, master might be unreachable"); return false; } - if (resp.statusCode !== 200){ + if (resp.statusCode !== 200) { this.messageInterface("got error when calling slaves", resp.statusCode, resp.body); return; } let needResearch = {}; + for (let slave_data of Object.values(slavesData)) { + if (slave_data.unique === this.config.unique.toString()) + continue; - Object.keys(slaveData).forEach(instanceKey => { - if (slaveData[instanceKey].unique === this.config.unique.toString()) { - return; + if (!slave_data.meta || !slave_data.meta.research) + continue; + + let researchList = slave_data.meta.research; + for (let [researchName, research] of Object.entries(researchList)) { + if (isNaN(research.researched) || isNaN(research.level)) + continue; + + if (needResearch[researchName]) { + if (needResearch[researchName].researched === 0) { + needResearch[researchName].researched = parseInt(research.researched); + } + if (needResearch[researchName].level < parseInt(research.level)) { + needResearch[researchName].level = parseInt(research.level); + } + } + else { + needResearch[researchName] = { + researched: parseInt(researchList[researchName].researched), + level: parseInt(researchList[researchName].level) + }; + } } - if (!slaveData[instanceKey].hasOwnProperty('meta') || !slaveData[instanceKey].meta.hasOwnProperty('research')) { - return; - } - let researchList = slaveData[instanceKey].meta.research; - if(researchList){ - Object.keys(researchList).forEach(researchName => { - if (isNaN(researchList[researchName].researched) || isNaN(researchList[researchName].level)) { - return; - } - if (needResearch.hasOwnProperty(researchName)) { - if (needResearch[researchName].researched === 0) { - needResearch[researchName].researched = parseInt(researchList[researchName].researched); - } - if (needResearch[researchName].level < parseInt(researchList[researchName].level)) { - needResearch[researchName].level = parseInt(researchList[researchName].level); - } - } - else { - needResearch[researchName] = {researched: parseInt(researchList[researchName].researched), level: parseInt(researchList[researchName].level)}; - } - }); - } - }); + } let difference = this.filterResearchDiff(this.research, needResearch); Object.keys(difference).forEach((key) => { - if (this.research[key]) { - let command = this.functions.enableResearch; - while(command.includes("{tech_name}")){ - command = command.replace("{tech_name}", key); - command = command.replace("{tech_researched}", difference[key].researched); - command = command.replace("{tech_level}", difference[key].level); - } - this.messageInterface(command); - console.log('Unlocking '+ key + ': ' + (difference[key].researched === 0 ? 'false' : 'true') + ' and level ' + difference[key].level + ', was '+ (this.research[key].researched === 0 ? 'false' : 'true') + ' at level ' + this.research[key].level); - this.messageInterface("Unlocking research: " + key + " at research state = " + (difference[key].researched === 0 ? 'false' : 'true') + ' and level ' + difference[key].level); - this.research[key] = difference[key]; - } + if (!this.research[key]) + return + let command = this.functions.enableResearch; + command = command.replace(/{tech_name}/g, key); + command = command.replace(/{tech_researched}/g, difference[key].researched); + command = command.replace(/{tech_level}/g, difference[key].level); + this.messageInterface(command); + log_tech_unlocking(key, difference[key], this.research[key]) + this.messageInterface( + `Unlocking research: ${key} with research state ${format_tech(difference[key])}` + ); + this.research[key] = difference[key]; }); needle.post(this.config.masterIP + ':' + this.config.masterPort + '/api/editSlaveMeta', { @@ -91,15 +103,20 @@ class ResearchSync { filterResearchDiff(localResearch, remoteResearch) { let diff = {}; - Object.keys(localResearch).forEach((key) => { - if (remoteResearch.hasOwnProperty(key)) { - if ((localResearch[key].researched === 0 && localResearch[key].researched !== remoteResearch[key].researched) || localResearch[key].level < remoteResearch[key].level) { - if (!isNaN(remoteResearch[key].researched) && !isNaN(remoteResearch[key].level)) { - diff[key] = {researched: remoteResearch[key].researched, level: remoteResearch[key].level}; - } - } + for (let key in localResearch) { + if (!remoteResearch[key]) + continue + if (isNaN(remoteResearch[key].researched) || isNaN(remoteResearch[key].level)) + continue + + if (remoteResearch[key].researched > localResearch[key].researched + || remoteResearch[key].level > localResearch[key].level) { + diff[key] = { + researched: remoteResearch[key].researched, + level: remoteResearch[key].level + }; } - }); + } return diff; } @@ -111,15 +128,15 @@ class ResearchSync { } loadFunc(path) { - return fs.readFileSync("sharedPlugins/researchSync/" + path,'utf-8').replace(/\r?\n|\r/g,' '); + let command = fs.readFileSync("sharedPlugins/researchSync/" + path,'utf-8') + command = command.replace(/\r?\n|\r/g,' ') + command = '/silent-command ' + command + return command; } - scriptOutput(data){ - let kv = data.split(":"); - let name = kv[0]; - let researched = ('true' !== kv[1] - ? 0 - : 1); - let level = parseInt(kv[2]); + scriptOutput(data) { + let [name, researched, level] = data.split(":") + researched = +(researched === 'true'); + level = parseInt(level); if (!isNaN(level) && !isNaN(researched)) { this.research[name] = {researched: researched, level: level}; } From 98c6795f8f7429293efe55e19ec316318a90264e Mon Sep 17 00:00:00 2001 From: TechnoStrife Date: Sun, 14 Jul 2019 23:29:15 +0300 Subject: [PATCH 2/4] Make researchSync work for any research on any node --- sharedPlugins/researchSync/dumpResearch.lua | 10 +- sharedPlugins/researchSync/index.js | 258 ++++++++++++------ sharedPlugins/researchSync/index.spec.js | 6 +- sharedPlugins/researchSync/updateProgress.lua | 28 ++ 4 files changed, 208 insertions(+), 94 deletions(-) create mode 100644 sharedPlugins/researchSync/updateProgress.lua diff --git a/sharedPlugins/researchSync/dumpResearch.lua b/sharedPlugins/researchSync/dumpResearch.lua index e7e43cf0..178365fc 100644 --- a/sharedPlugins/researchSync/dumpResearch.lua +++ b/sharedPlugins/researchSync/dumpResearch.lua @@ -1,11 +1,19 @@ local data = {}; +local force = game.forces["player"]; -for _, tech in pairs(game.forces["player"].technologies) do +for _, tech in pairs(force.technologies) do + local progress; + if tech == force.current_research then + progress = force.research_progress + else + progress = force.get_saved_technology_progress(tech.name); + end local tech_data = { tech.name, tostring(tech.researched), tostring(tech.level), + tostring(progress), } tech_data = table.concat(tech_data, ':') table.insert(data, tech_data); diff --git a/sharedPlugins/researchSync/index.js b/sharedPlugins/researchSync/index.js index 7ab9c488..c1fb9528 100644 --- a/sharedPlugins/researchSync/index.js +++ b/sharedPlugins/researchSync/index.js @@ -6,24 +6,22 @@ function format_tech(tech) { } -function log_tech_unlocking(key, current, prev) { - console.log( - `Unlocking ${key}: ${format_tech(current)}, was ${format_tech(prev)}` - ); -} - - class ResearchSync { constructor(slaveConfig, messageInterface, extras = {}){ this.config = slaveConfig; this.messageInterface = messageInterface; - this.functions = this.loadFunctions(); + this.functions = { + dumpResearch: this.loadFunc("dumpResearch.lua"), + enableResearch: this.loadFunc("enableResearch.lua"), + updateProgress: this.loadFunc("updateProgress.lua") + } this.research = {}; + this.prev_research = {}; setInterval(() => { this.pollResearch(); - setTimeout(this.doSync.bind(this), 2000); + setTimeout(this.request_cluster_data.bind(this), 2000); }, extras.researchSyncPollInterval || 5000); } @@ -32,99 +30,154 @@ class ResearchSync { this.messageInterface(this.functions.dumpResearch); } - doSync() { + request_cluster_data() { const slaves_data_url = `${this.config.masterIP}:${this.config.masterPort}/api/slaves` - needle.get(slaves_data_url, (err, resp, slavesData) => { - if (err) { - this.messageInterface("Unable to post JSON master/api/slaves, master might be unreachable"); - return false; - } - if (resp.statusCode !== 200) { - this.messageInterface("got error when calling slaves", resp.statusCode, resp.body); - return; - } + needle.get(slaves_data_url, this.sync_researches.bind(this)) + } - let needResearch = {}; - for (let slave_data of Object.values(slavesData)) { - if (slave_data.unique === this.config.unique.toString()) - continue; + sync_researches(err, resp, slaves_data) { + if (err) { + this.messageInterface("Unable to post JSON master/api/slaves, master might be unreachable"); + return false; + } + if (resp.statusCode !== 200) { + this.messageInterface("got error when calling slaves", resp.statusCode, resp.body); + return; + } - if (!slave_data.meta || !slave_data.meta.research) - continue; + slaves_data = Object.values(slaves_data) + slaves_data = slaves_data.filter( + slave_data => slave_data.unique !== this.config.unique.toString() + && slave_data.meta && slave_data.meta.research + ) - let researchList = slave_data.meta.research; - for (let [researchName, research] of Object.entries(researchList)) { - if (isNaN(research.researched) || isNaN(research.level)) - continue; + let cluster_techs = this.get_cluster_techs(slaves_data) + this.recount_cluster_research_progress(slaves_data, cluster_techs) - if (needResearch[researchName]) { - if (needResearch[researchName].researched === 0) { - needResearch[researchName].researched = parseInt(research.researched); - } - if (needResearch[researchName].level < parseInt(research.level)) { - needResearch[researchName].level = parseInt(research.level); - } - } - else { - needResearch[researchName] = { - researched: parseInt(researchList[researchName].researched), - level: parseInt(researchList[researchName].level) - }; - } - } - } + let to_research = this.filter_researched_techs(cluster_techs) + let to_update_progress = this.filter_updated_techs(cluster_techs, to_research) - let difference = this.filterResearchDiff(this.research, needResearch); + this.research_technologies(to_research) + this.update_technologies_progress(to_update_progress) - Object.keys(difference).forEach((key) => { - if (!this.research[key]) - return - let command = this.functions.enableResearch; - command = command.replace(/{tech_name}/g, key); - command = command.replace(/{tech_researched}/g, difference[key].researched); - command = command.replace(/{tech_level}/g, difference[key].level); - this.messageInterface(command); - log_tech_unlocking(key, difference[key], this.research[key]) - this.messageInterface( - `Unlocking research: ${key} with research state ${format_tech(difference[key])}` - ); - this.research[key] = difference[key]; - }); - - needle.post(this.config.masterIP + ':' + this.config.masterPort + '/api/editSlaveMeta', { - instanceID: this.config.unique, - password: this.config.clientPassword, - meta: {research: this.research} - }, {headers: {'x-access-token': this.config.masterAuthToken}}, function (err, resp) { - // success? - }); + needle.post(this.config.masterIP + ':' + this.config.masterPort + '/api/editSlaveMeta', { + instanceID: this.config.unique, + password: this.config.clientPassword, + meta: {research: this.research} + }, {headers: {'x-access-token': this.config.masterAuthToken}}, function (err, resp) { + // success? }); } - filterResearchDiff(localResearch, remoteResearch) { - let diff = {}; - for (let key in localResearch) { - if (!remoteResearch[key]) - continue - if (isNaN(remoteResearch[key].researched) || isNaN(remoteResearch[key].level)) - continue + get_cluster_techs(slavesData) { + let researches = {} + 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)) + continue - if (remoteResearch[key].researched > localResearch[key].researched - || remoteResearch[key].level > localResearch[key].level) { - diff[key] = { - researched: remoteResearch[key].researched, - level: remoteResearch[key].level - }; + if (researches[name]) { + if (researches[name].researched === 0) { + researches[name].researched = parseInt(research.researched) + } + if (researches[name].level < parseInt(research.level)) { + researches[name].level = parseInt(research.level) + } + } else { + researches[name] = { + researched: parseInt(research.researched), + level: parseInt(research.level) + } + } } } - return diff; + return researches } - loadFunctions() { - return { - dumpResearch: this.loadFunc("dumpResearch.lua"), - enableResearch: this.loadFunc("enableResearch.lua"), - }; + recount_cluster_research_progress(slaves_data, cluster_researches) { + for (let research of Object.values(cluster_researches)) + research.progress = research.contribution + + for (let slave_data of slaves_data) + for (let [name, research] of Object.entries(slave_data.meta.research)) + if (!isNaN(cluster_researches[name].progress) && !isNaN(research.contribution)) + cluster_researches[name].progress += research.contribution + + for (let [name, research] of Object.entries(cluster_researches)) { + if (research.progress > 1) { + research.progress = null + research.researched = 1 + if (this.research[name].level >= research.level) + research.level = this.research[name].level + 1 + } + } + } + + filter_researched_techs(cluster_researches) { + let local_researches = this.research + let result = {}; + for (let key in local_researches) { + if (!cluster_researches[key]) + continue + 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) { + result[key] = cluster_researches[key] + } + } + return result; + } + + filter_updated_techs(cluster_techs, to_research) { + let local_techs = this.research + let result = {} + for (let name in local_techs) { + if (name in to_research || !cluster_techs[name]) + continue + if (isNaN(cluster_techs[name].progress)) + continue + if (local_techs[name].progress < cluster_techs[name].progress) + result[name] = cluster_techs[name] + } + return result + } + + research_technologies(to_research) { + for (let [name, tech] of Object.entries(to_research)) { + if (!this.research[name]) + continue + let command = this.functions.enableResearch; + command = command.replace(/{tech_name}/g, key); + command = command.replace(/{tech_researched}/g, tech.researched); + command = command.replace(/{tech_level}/g, tech.level); + 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)}` + ); + this.research[key] = tech; + } + } + + update_technologies_progress(to_update) { + for (let [name, tech] of Object.entries(to_update)) { + if (!this.research[name]) + continue + let command = this.functions.updateProgress + command = command.replace(/{tech_name}/g, name) + command = command.replace(/{last_check_progress}/g, this.research[name].progress) + command = command.replace(/{new_progress}/g, tech.progress) + this.messageInterface(command); + console.log( + `Updating ${name}: progress += ${tech.progress - this.research[name].progress}` + ); + this.research[name].progress = tech.progress + } } loadFunc(path) { @@ -134,11 +187,36 @@ class ResearchSync { return command; } scriptOutput(data) { - let [name, researched, level] = data.split(":") + let [name, researched, level, progress] = data.split(":") researched = +(researched === 'true'); level = parseInt(level); - if (!isNaN(level) && !isNaN(researched)) { - this.research[name] = {researched: researched, level: level}; + if (progress === 'nil') + progress = null + else + progress = parseFloat(progress) + + if (isNaN(level) || isNaN(researched)) + return + this.prev_research[name] = this.research[name] + if (!this.prev_research[name]) { + this.prev_research[name] = { + researched: null, + level: null, + progress: null, + contribution: 0, + } + } + this.research[name] = { + researched, + level, + progress, + contribution: this.prev_research[name].contribution + } + if (this.prev_research[name].progress && this.research[name].progress) { + // this.prev_research[name].progress gets updated to overall cluster progress + // therefore contribution should be own research progress change over sync interval + let contribution = this.research[name].progress - this.prev_research[name].progress + this.research[name].contribution += contribution } } } diff --git a/sharedPlugins/researchSync/index.spec.js b/sharedPlugins/researchSync/index.spec.js index eae51abc..372bf01e 100644 --- a/sharedPlugins/researchSync/index.spec.js +++ b/sharedPlugins/researchSync/index.spec.js @@ -9,7 +9,7 @@ describe("researchSync/index.js", ()=>{ assert.equal(typeof researchSync, "function"); }); describe("class researchSync()", ()=>{ - it(".filterResearchDiff(object1, object2) returns research that needs enabling on the local instance", ()=>{ + it(".filter_researched_techs(object1, object2) returns research that needs enabling on the local instance", ()=>{ let reSync = new researchSync({}, function(){}); let obj1 = { @@ -24,9 +24,9 @@ describe("researchSync/index.js", ()=>{ c:{researched: false, level: 0}, e:{researched: false, level: 50}, }; - assert(typeof reSync.filterResearchDiff == "function"); + assert(typeof reSync.filter_researched_techs == "function"); - let diffResult = reSync.filterResearchDiff(obj1, obj2); + let diffResult = reSync.filter_researched_techs(obj1, obj2); assert(diffResult.a === undefined); diff --git a/sharedPlugins/researchSync/updateProgress.lua b/sharedPlugins/researchSync/updateProgress.lua new file mode 100644 index 00000000..68b7d4ec --- /dev/null +++ b/sharedPlugins/researchSync/updateProgress.lua @@ -0,0 +1,28 @@ + +local function get_tech_progress(tech) + if tech == force.current_research then + return force.research_progress + else + return force.get_saved_technology_progress(tech.name); + end +end +local function set_tech_progress(tech, progress) + if tech == force.current_research then + force.research_progress = progress + else + force.set_saved_technology_progress(tech.name, progress); + end +end + +local force = game.force['player'] +local tech_name = {tech_name} +local tech = force.technologies[tech_name] +local last_check_progress = {last_check_progress} +local new_progress = {new_progress} + +local progress_delta = get_tech_progress(tech) - last_check_progress +new_progress = new_progress + progress_delta +if new_progress > 1 then + new_progress = 1 +end +set_tech_progress(tech, new_progress) From 4a0956d17461c2cd283258a6254d135512a3606c Mon Sep 17 00:00:00 2001 From: TechnoStrife Date: Mon, 15 Jul 2019 11:26:03 +0300 Subject: [PATCH 3/4] Fix a bug causing all slaves data gets cleared on master startup Cherry-picked from fix-slaves-data-cleanup-on-startup --- master.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/master.js b/master.js index 276af857..cba39301 100644 --- a/master.js +++ b/master.js @@ -235,7 +235,7 @@ const db = {}; (function(){ try{ - let x = fs.statSync(path.resolve(config.databaseDirectory, "/slaves.json")); + let x = fs.statSync(path.resolve(config.databaseDirectory, "slaves.json")); console.log(`loading slaves from path.resolve(config.databaseDirectory, "slaves.json")`); slaves = JSON.parse(fs.readFileSync(path.resolve(config.databaseDirectory, "slaves.json"))); } catch (e){ From 251ec696a37b6725cfb3e008c341dd092215ddfd Mon Sep 17 00:00:00 2001 From: TechnoStrife Date: Mon, 15 Jul 2019 18:29:53 +0300 Subject: [PATCH 4/4] Fixes && debugging --- sharedPlugins/researchSync/index.js | 105 ++++++++++++++---- sharedPlugins/researchSync/updateProgress.lua | 19 ++-- 2 files changed, 93 insertions(+), 31 deletions(-) diff --git a/sharedPlugins/researchSync/index.js b/sharedPlugins/researchSync/index.js index c1fb9528..e23c79b9 100644 --- a/sharedPlugins/researchSync/index.js +++ b/sharedPlugins/researchSync/index.js @@ -18,16 +18,47 @@ class ResearchSync { this.research = {}; this.prev_research = {}; - - setInterval(() => { - this.pollResearch(); - setTimeout(this.request_cluster_data.bind(this), 2000); - }, extras.researchSyncPollInterval || 5000); + this.initial_request_own_data( + () => this.setup_sync_task(extras) + ) } - pollResearch() { - // this.messageInterface("Polling Research\n") + initial_request_own_data(callback) { + const url = `${this.config.masterIP}:${this.config.masterPort}/api/getSlaveMeta` + const data = { + instanceID: this.config.unique, + password: this.config.clientPassword, + } + const options = { + headers: {'x-access-token': this.config.masterAuthToken}, + json: true + } + needle.post(url, data, options, (err, res, techs) => { + if (err) { + console.log(`Can't get own slave data:`) + console.error(err) + return + } + if (res.statusCode !== 200) { + console.log(`Can't get own slave data:`) + console.error(`status code ${res.statusCode}, ${res.body}`) + return + } + techs = JSON.parse(techs) + if (typeof techs.research === 'object') + this.research = techs.research + callback() + }) + } + + setup_sync_task(extras) { + const timeout = extras.researchSyncPollInterval || 5000 + setInterval(() => this.sync_task(), timeout); + } + + sync_task() { this.messageInterface(this.functions.dumpResearch); + setTimeout(this.request_cluster_data.bind(this), 2000); } request_cluster_data() { @@ -60,12 +91,17 @@ class ResearchSync { this.research_technologies(to_research) this.update_technologies_progress(to_update_progress) + this.print_own_contribution() + needle.post(this.config.masterIP + ':' + this.config.masterPort + '/api/editSlaveMeta', { instanceID: this.config.unique, password: this.config.clientPassword, meta: {research: this.research} - }, {headers: {'x-access-token': this.config.masterAuthToken}}, function (err, resp) { - // success? + }, {headers: {'x-access-token': this.config.masterAuthToken}, json: true}, function (err, resp) { + if (err) + console.error(err) + else + console.log('sent') }); } @@ -79,16 +115,13 @@ class ResearchSync { if (researches[name]) { if (researches[name].researched === 0) { - researches[name].researched = parseInt(research.researched) + researches[name].researched = research.researched } - if (researches[name].level < parseInt(research.level)) { - researches[name].level = parseInt(research.level) + if (researches[name].level < research.level) { + researches[name].level = research.level } } else { - researches[name] = { - researched: parseInt(research.researched), - level: parseInt(research.level) - } + researches[name] = research } } } @@ -96,8 +129,8 @@ class ResearchSync { } recount_cluster_research_progress(slaves_data, cluster_researches) { - for (let research of Object.values(cluster_researches)) - research.progress = research.contribution + for (let [name, research] of Object.entries(cluster_researches)) + research.progress = this.research[name].contribution for (let slave_data of slaves_data) for (let [name, research] of Object.entries(slave_data.meta.research)) @@ -108,6 +141,8 @@ class ResearchSync { if (research.progress > 1) { research.progress = null research.researched = 1 + this.research[name].contribution = 0 + research.contribution = 0 if (this.research[name].level >= research.level) research.level = this.research[name].level + 1 } @@ -149,8 +184,10 @@ class ResearchSync { for (let [name, tech] of Object.entries(to_research)) { if (!this.research[name]) continue + this.research[name].contribution = 0 + this.research[name].progress = null let command = this.functions.enableResearch; - command = command.replace(/{tech_name}/g, key); + command = command.replace(/{tech_name}/g, name); command = command.replace(/{tech_researched}/g, tech.researched); command = command.replace(/{tech_level}/g, tech.level); this.messageInterface(command); @@ -160,7 +197,7 @@ class ResearchSync { this.messageInterface( `Unlocking research: ${name} with research state ${format_tech(tech)}` ); - this.research[key] = tech; + this.research[name] = tech; } } @@ -168,22 +205,38 @@ class ResearchSync { for (let [name, tech] of Object.entries(to_update)) { if (!this.research[name]) continue + let progress = this.research[name].progress + if (progress === null) + progress = 'nil' let command = this.functions.updateProgress command = command.replace(/{tech_name}/g, name) - command = command.replace(/{last_check_progress}/g, this.research[name].progress) + + command = command.replace(/{last_check_progress}/g, progress) command = command.replace(/{new_progress}/g, tech.progress) this.messageInterface(command); console.log( - `Updating ${name}: progress += ${tech.progress - this.research[name].progress}` + `Updating ${name}: ${this.research[name].progress} += ${tech.progress - this.research[name].progress}` ); this.research[name].progress = tech.progress } } - loadFunc(path) { + print_own_contribution() { + if (!this.prev_research) + return + for (let [name, tech] of Object.entries(this.research)) { + if (!this.prev_research[name]) + continue + let diff = this.research[name].contribution - this.prev_research[name].contribution + if (Math.abs(diff) > Number.EPSILON * 1000) + console.log(`Own research ${name}: ${this.research[name].progress} += ${diff}`) + } + } + + loadFunc(path, silent=true) { let command = fs.readFileSync("sharedPlugins/researchSync/" + path,'utf-8') command = command.replace(/\r?\n|\r/g,' ') - command = '/silent-command ' + command + command = (silent ? '/silent-command ' : '/c ') + command return command; } scriptOutput(data) { @@ -218,6 +271,10 @@ class ResearchSync { let contribution = this.research[name].progress - this.prev_research[name].progress this.research[name].contribution += contribution } + if (Math.abs(this.research[name].contribution) < Number.EPSILON * 1000) { + // if contribution should be 0 but because of floating-point precision is e.g. 2.2564e-18 + this.research[name].contribution = 0 + } } } diff --git a/sharedPlugins/researchSync/updateProgress.lua b/sharedPlugins/researchSync/updateProgress.lua index 68b7d4ec..0d07bb84 100644 --- a/sharedPlugins/researchSync/updateProgress.lua +++ b/sharedPlugins/researchSync/updateProgress.lua @@ -1,12 +1,12 @@ -local function get_tech_progress(tech) +local function get_tech_progress(force, tech) if tech == force.current_research then return force.research_progress else return force.get_saved_technology_progress(tech.name); end end -local function set_tech_progress(tech, progress) +local function set_tech_progress(force, tech, progress) if tech == force.current_research then force.research_progress = progress else @@ -14,15 +14,20 @@ local function set_tech_progress(tech, progress) end end -local force = game.force['player'] -local tech_name = {tech_name} +local force = game.forces['player'] +local tech_name = '{tech_name}' local tech = force.technologies[tech_name] local last_check_progress = {last_check_progress} local new_progress = {new_progress} -local progress_delta = get_tech_progress(tech) - last_check_progress -new_progress = new_progress + progress_delta +local progress_delta = get_tech_progress(force, tech) +if last_check_progress ~= nil then + progress_delta = progress_delta - last_check_progress +end +if progress_delta ~= nil then + new_progress = new_progress + progress_delta +end if new_progress > 1 then new_progress = 1 end -set_tech_progress(tech, new_progress) +set_tech_progress(force, tech, new_progress)