diff --git a/CHANGELOG.md b/CHANGELOG.md index 824e2746..afd8f639 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,6 @@ Version 2.0.0 ### Breaking Changes -- Node.js versions below 10 are no longer supported. - lib/authenticate no longer requires config to be passed to it. Breaks playerManager. - The masterIP and masterPort config entries has been merged into masterURL. @@ -28,6 +27,29 @@ Version 2.0.0 .ejs. Breaks playerManager. +Version 1.2.2 +------------- + +- Fixed possible crash with modded technologies named the same as a built-in + Object prototype property in researchSync. +- Fixed progress of a current infinite tech carrying over to the next one + when researching it and another node completes it in researchSync. +- Fixed progress of a previous infinite tech from another node being applied + to the current one in researchSync. +- Fixed crash in researchSync when modded technologies are present only on some + nodes. +- Fixed install failing due to bcrypt version less than 3 not being supported + on node v10. +- Reordered install instructions to avoid problem with npm creating files owned + by root in the home directory. +- Swapped curl out with wget in the install instructions as the latter comes + pre-installed on Ubuntu. + +### Breaking Changes + +- Node.js versions below 10 are no longer supported. + + Version 1.2.1 ------------- diff --git a/README.md b/README.md index 695077ad..88dbcf95 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,13 @@ Discord for development/support/play: https://discord.gg/5XuDkje This is the development branch for factorioClusterio 2.0 which is currently undergoing heavy restructuring and refactoring. Expect plugins and existing installations to frequently break when using this branch. If you don't want to be an alpha tester for 2.0 please use the stable -[1.2.x branch](https://github.com/clusterio/factorioClusterio/tree/1.2.x) or +[1.2.x branch][1.2.x] or [latest stable release](https://github.com/clusterio/factorioClusterio/releases/latest). -Installation instructions below are for stable release - if you need a development version - -just drop `-b 1.2.x` from clone command and `--only=production` from the `npm install` command. +Installation instructions below are for the unstable master branch. Go to the page for +the [1.2.x branch][1.2.x] for instructions on how to install the stable version. + +[1.2.x]: https://github.com/clusterio/factorioClusterio/tree/1.2.x ### Ways to support me/the project: @@ -95,23 +97,28 @@ Clusterio can also do a few other neat things, such as giving you access to epoc ## Ubuntu setup +**Warning**: These instructions are for the unstable master version and is not +recommended for use, see [the 1.2.x branch][1.2.x] for how to install the stable version. + NodeJS does not support EOL ubuntu releases. Make sure you are on the most recent LTS release or newer. Master and all slaves: - sudo curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash - - sudo apt install -y nodejs python-dev git wget curl tar build-essential - sudo npm install pm2 -g - git clone -b 1.2.x https://github.com/clusterio/factorioClusterio.git + wget -qO - https://deb.nodesource.com/setup_10.x | sudo -E bash - + sudo apt install -y nodejs python-dev git build-essential + git clone -b master https://github.com/clusterio/factorioClusterio.git cd factorioClusterio - curl -o factorio.tar.gz -L https://www.factorio.com/get-download/latest/headless/linux64 + wget -O factorio.tar.gz https://www.factorio.com/get-download/latest/headless/linux64 tar -xf factorio.tar.gz npm install --only=production cp config.json.dist config.json node ./lib/npmPostinstall.js +downloads and installs nodejs, git and clusterio. To specify a version, change "latest" in the link to a version number like 0.14.21. -downloads and installs nodejs, pm2, git and clusterio. To specify a version, change "latest" in the link to a version number like 0.14.21. +Optional step (if you want to use pm2): + + sudo npm install pm2 -g Now you need to edit the `config.json` file. If you skip this step nothing will work. Pretty much all the blank fields should be filled in, except on the master where a few can be omitted. @@ -124,11 +131,12 @@ Pretty much all the blank fields should be filled in, except on the master where **Master** + node master.js + +Or with pm2 (it's recommened to run it without pm2 first): + pm2 start master.js --name master -OR - - node master.js **Server Host** @@ -160,6 +168,9 @@ The -v flag is used to specify the instance directory. Your instances (save file ## Windows setup +**Warning**: These instructions are for the unstable master version and is not +recommended for use, see [the 1.2.x branch][1.2.x] for how to install the stable version. + Clusterio is built up of multiple parts. Here is a quick guide: Master = master.js diff --git a/client.js b/client.js index f4318ae4..ddeec91b 100644 --- a/client.js +++ b/client.js @@ -631,9 +631,14 @@ async function startClient() { // make sure we have the master access token (can't write to master without it since clusterio 2.0) if(!config.masterAuthToken || typeof config.masterAuthToken !== "string"){ console.error("ERROR invalid config!"); - console.error("Master server now needs an access token for write operations. As clusterio slaves depends \ - upon this, please add your token to config.json in the field named masterAuthToken. \ - You can retrieve your auth token from the master in secret-api-token.txt after running it once."); + console.error( + "Master server now needs an access token for write operations. As clusterio\n"+ + "slaves depends upon this, please add your token to config.json in the field\n"+ + "named masterAuthToken. You can retrieve your auth token from the master in\n"+ + "secret-api-token.txt after running it once." + ); + process.exitCode = 1; + return; } // messageInterface Management diff --git a/sharedPlugins/researchSync/enableResearch.lua b/sharedPlugins/researchSync/enableResearch.lua index f83a1e93..8c8b7329 100644 --- a/sharedPlugins/researchSync/enableResearch.lua +++ b/sharedPlugins/researchSync/enableResearch.lua @@ -11,15 +11,22 @@ local function updateTech() end end -if game.forces['player'].technologies['{tech_name}'] then +local force = game.forces['player'] +local tech = force.technologies['{tech_name}'] +if tech then if 1 == {tech_infinite} then - if (game.forces['player'].technologies['{tech_name}'].level ~= level) then - game.forces['player'].technologies['{tech_name}'].level = {tech_level} + if (tech.level ~= level) then + tech.level = {tech_level} + if tech == force.current_research then + force.research_progress = {tech_progress} + else + force.set_saved_technology_progress(tech.name, {tech_progress}); + end updateTech() end else - if not game.forces['player'].technologies['{tech_name}'].researched then - game.forces['player'].technologies['{tech_name}'].researched = true + if not tech.researched then + tech.researched = true updateTech() end end diff --git a/sharedPlugins/researchSync/index.js b/sharedPlugins/researchSync/index.js index 918d63e9..5054083f 100644 --- a/sharedPlugins/researchSync/index.js +++ b/sharedPlugins/researchSync/index.js @@ -144,21 +144,24 @@ 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 + clear_contribution_to_researched_techs() { + for (let [name, tech] of Object.entries(this.research)) { + if (!Object.hasOwnProperty.call(this.prev_research, name)) { + continue; + } - if (researched) - research.contribution = 0 - } - } + let researched; + if (tech.infinite) { + researched = this.prev_research[name].level < tech.level; + } else { + researched = this.prev_research[name].researched < tech.researched; + } + + if (researched) { + tech.contribution = 0; + } + } + } get_cluster_techs(slavesData) { let cluster_techs = {} @@ -168,7 +171,7 @@ class ResearchSync { if (isNaN(node_tech.researched) || isNaN(node_tech.level) || isNaN(node_tech.infinite)) continue - if (cluster_techs[name]) { + if (Object.hasOwnProperty.call(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) { @@ -183,65 +186,85 @@ class ResearchSync { } recount_cluster_research_progress(slaves_data, cluster_researches) { - for (let [name, research] of Object.entries(cluster_researches)) - research.progress = this.research[name].contribution + for (let [name, tech] of Object.entries(cluster_researches)) { + if (Object.hasOwnProperty.call(this.research, name)) { + tech.progress = this.research[name].contribution + } else { + tech.progress = 0; + } + } for (let slave_data of slaves_data) { - for (let [name, research] of Object.entries(slave_data.meta.research)) { - if (!cluster_researches[name]) - continue - if (isNaN(cluster_researches[name].progress) - || isNaN(research.contribution) - || isNaN(research.level) - || isNaN(cluster_researches[name].level)) - continue - if (cluster_researches[name].level === research.level) - cluster_researches[name].progress += research.contribution + for (let [name, tech] of Object.entries(slave_data.meta.research)) { + if (!Object.hasOwnProperty.call(cluster_researches, name)) { + continue; + } + + if ( + isNaN(cluster_researches[name].progress) + || isNaN(tech.contribution) + || isNaN(tech.level) + || isNaN(cluster_researches[name].level) + ) { + continue; + } + + if (cluster_researches[name].level === tech.level) { + cluster_researches[name].progress += tech.contribution; + } } } - for (let [name, research] of Object.entries(cluster_researches)) { - if (research.progress > 1) { - research.progress = null - research.researched = 1 + for (let [name, tech] of Object.entries(cluster_researches)) { + if (Object.hasOwnProperty.call(this.research, name) && tech.progress > 1) { + tech.progress = null + tech.researched = 1 this.research[name].contribution = 0 - research.contribution = 0 - if (this.research[name].level >= research.level) - research.level = this.research[name].level + 1 + tech.contribution = 0 + if (this.research[name].level >= tech.level) + tech.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)) + for (let [name, tech] of Object.entries(this.research)) { + if (!Object.hasOwnProperty.call(cluster_researches, name)) { + continue; + } + + if (isNaN(cluster_researches[name].researched) || isNaN(cluster_researches[name].level)) continue 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 (tech.infinite) { + researched = tech.level < cluster_researches[name].level; + } else { + researched = tech.researched < cluster_researches[name].researched; + } if (researched) - result[key] = cluster_researches[key] + result[name] = cluster_researches[name] } 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 + for (let [name, tech] of Object.entries(this.research)) { + if (Object.hasOwnProperty.call(to_research, name) || !Object.hasOwnProperty.call(cluster_techs, name)) { + continue; + } if (isNaN(cluster_techs[name].progress)) continue - if (local_techs[name].progress < cluster_techs[name].progress) + + // Do not update progress for infinite techs with a local level that's higher. + if (tech.infinite && tech.level > cluster_techs[name].level) { + continue; + } + + if (tech.progress < cluster_techs[name].progress) result[name] = cluster_techs[name] } return result @@ -249,8 +272,9 @@ class ResearchSync { research_technologies(to_research) { for (let name of Object.keys(to_research)) - if (!this.research[name]) - delete to_research[name] + if (!Object.hasOwnProperty.call(this.research, name)) { + delete to_research[name]; + } const notify = Object.keys(to_research).length === 1 for (let [name, tech] of Object.entries(to_research)) { @@ -258,9 +282,9 @@ class ResearchSync { 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(/{tech_progress}/g, tech.progress) command = command.replace(/{notify}/g, notify); this.messageInterface(command); let log_message = tech.infinite @@ -274,8 +298,9 @@ class ResearchSync { update_technologies_progress(to_update) { for (let [name, tech] of Object.entries(to_update)) { - if (!this.research[name]) - continue + if (!Object.hasOwnProperty.call(this.research, name)) { + continue; + } let progress = this.research[name].progress if (progress === null) progress = 'nil' @@ -292,11 +317,10 @@ class ResearchSync { } print_own_contribution() { - if (!this.prev_research) - return for (let [name, tech] of Object.entries(this.research)) { - if (!this.prev_research[name]) - continue + if (!Object.hasOwnProperty.call(this.prev_research, name)) { + continue; + } let diff = this.research[name].contribution - this.prev_research[name].contribution if (Math.abs(diff) > Number.EPSILON * 1000) this.log(`Own research ${name}: ${this.research[name].progress} += ${diff}`) @@ -321,8 +345,10 @@ class ResearchSync { if (isNaN(level) || isNaN(researched)) return - this.prev_research[name] = this.research[name] - if (!this.prev_research[name]) { + + if (Object.hasOwnProperty.call(this.research, name)) { + this.prev_research[name] = this.research[name]; + } else { this.prev_research[name] = { researched: null, level: null,