mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-11 23:04:52 +09:00
Compare commits
41
Commits
v2.0.0-alpha.2
...
1.2.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a9a3fb3fce | ||
|
|
2b21bb36b6 | ||
|
|
e1771ecb38 | ||
|
|
70f3ad5ebd | ||
|
|
28b00ba5f6 | ||
|
|
9d885d5f91 | ||
|
|
d810b5646d | ||
|
|
10414eb4a6 | ||
|
|
3647ac7fc8 | ||
|
|
e75d9e967e | ||
|
|
25eb5e5d76 | ||
|
|
3c5b108e4b | ||
|
|
999c1b6c7a | ||
|
|
61b1b1a106 | ||
|
|
8b4ec58459 | ||
|
|
6e26d32fed | ||
|
|
74d9ec38dc | ||
|
|
dbef2bd2b3 | ||
|
|
e0b521d2fe | ||
|
|
9a032aed2e | ||
|
|
72b56a00c7 | ||
|
|
c25bf23286 | ||
|
|
9e983aff84 | ||
|
|
8973dcc6dd | ||
|
|
475128c8c4 | ||
|
|
0cdb5d0ce4 | ||
|
|
075d54f708 | ||
|
|
62f3a99feb | ||
|
|
3b1ed1a667 | ||
|
|
6a6274e85c | ||
|
|
a9cc743106 | ||
|
|
2a7758f60d | ||
|
|
7e2ca58a59 | ||
|
|
718d4ed659 | ||
|
|
6b090cddbe | ||
|
|
56c023f643 | ||
|
|
78de7236c5 | ||
|
|
97c7a69c7a | ||
|
|
0c45e57732 | ||
|
|
88eff17dfd | ||
|
|
e1374d501e |
No files matched your search
+1
-1
@@ -1,6 +1,6 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "9"
|
||||
- 10
|
||||
before_install:
|
||||
- sudo apt-get -qq update
|
||||
- sudo apt-get install -y curl git tar
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
Version 1.2.3
|
||||
-------------
|
||||
|
||||
- Disabled uploading mods to the master server by default as this is mostly
|
||||
just a waste of bandwidth with the mod portal being integrated into the
|
||||
game now.
|
||||
- Fixed researchSync breaking with heavily modded games due to the tech tree
|
||||
exceeding the default 100kb limit on JSON payloads.
|
||||
- Fixed the command inventoryImport sends referencing player instead of
|
||||
character, and trying to count the non-existant quick bar slots.
|
||||
- Fixed inventoryImport never receiving the script output after the default
|
||||
mode for reading script output changed to tail mode.
|
||||
- Fixed desync caused by the mods and loaded mods arrays in Hotpatch getting
|
||||
out of sync when plugins update their scenario mod code. To fix existing
|
||||
games you will need copy lib/scenarios/Hotpatch/hotpatch/mod-tools.lua
|
||||
over the existing mod-tools.lua in the save's hotpatch folder.
|
||||
- Updated the Windows install instructions.
|
||||
|
||||
|
||||
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
|
||||
-------------
|
||||
|
||||
- Updated node-factorio-api to v0.3.8 to fix mod downloads randomly breaking
|
||||
([#229][#229].)
|
||||
- Fixed SIGINT being sent twice to Factorio server when interrupted by CTRL+C
|
||||
on Linux ([#217][#217].)
|
||||
- Fixed package.json incorrectly reporting the license as ISC.
|
||||
|
||||
[#217]: https://github.com/clusterio/factorioClusterio/issues/217
|
||||
[#229]: https://github.com/clusterio/factorioClusterio/issues/229
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- Added authentication to the socket.io server running on the master.
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
FROM node:9.11.2
|
||||
FROM node:10
|
||||
RUN apt-get update && apt install git curl tar -y
|
||||
RUN mkdir factorioClusterio
|
||||
|
||||
|
||||
@@ -8,6 +8,13 @@
|
||||
|
||||
Discord for development/support/play: https://discord.gg/5XuDkje
|
||||
|
||||
## Important notice
|
||||
|
||||
This is the stable branch of the project. The
|
||||
[master branch](http://github.com/clusterio/factorioClusterio/tree/master)
|
||||
is undergoing significant changes that breaks compatibility to plugins and
|
||||
existing installations and is not recommended for use.
|
||||
|
||||
### Ways to support me/the project:
|
||||
|
||||
* Contribute with code/documentation. Always nice to move the project forward
|
||||
@@ -88,19 +95,21 @@ NodeJS does not support EOL ubuntu releases. Make sure you are on the most recen
|
||||
|
||||
Master and all slaves:
|
||||
|
||||
sudo curl -sL https://deb.nodesource.com/setup_9.x | sudo -E bash -
|
||||
sudo apt install -y nodejs python-dev git wget curl tar build-essential
|
||||
sudo npm install pm2 -g
|
||||
git clone https://github.com/Danielv123/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 1.2.x https://github.com/Danielv123/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.
|
||||
@@ -113,11 +122,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**
|
||||
|
||||
@@ -159,7 +169,7 @@ Game Client = The people connecting to the server
|
||||
|
||||
**Requirements**
|
||||
|
||||
download and install nodeJS 8 or 9 from http://nodejs.org
|
||||
download and install nodeJS 10 from http://nodejs.org
|
||||
|
||||
download and install git from https://git-scm.com/
|
||||
|
||||
@@ -167,28 +177,47 @@ reboot when you are done, then proceed to the next steps. *reboots matter*
|
||||
|
||||
**Master**
|
||||
|
||||
1. download and run https://puu.sh/toFHl/01eebbb333.bat
|
||||
1. Open PowerShell or Command prompt in the directory you want to install to and run the following commands.
|
||||
|
||||
2. Copy config.json.dist to config.json
|
||||
git clone -b 1.2.x https://github.com/clusterio/factorioClusterio
|
||||
cd factorioClusterio
|
||||
npm install --only=production
|
||||
copy config.json.dist config.json
|
||||
|
||||
3. Follow the instructions in the bat file
|
||||
3. Some of the instructions are outdated. If you get stuck somewhere, look at the Ubuntu section.
|
||||
2. Obtain Factorio by either of these two methods:
|
||||
|
||||
4. Run `node client.js manage shared mods add clusterio`
|
||||
- Via the stand alone version on from their website
|
||||
|
||||
5. type `node master.js` to start the server
|
||||
1. Download the MS Windows (64-bit zip package) from https://www.factorio.com/download
|
||||
|
||||
2. Open the zip file and drag the folder called "Factorio_0.17.x" into the factorioClusterio folder
|
||||
|
||||
3. Rename the folder to "factorio"
|
||||
|
||||
- Via steam installation
|
||||
|
||||
1. Locate the game files by right clicking the game in steam, selecting properties, then Local Files, then Browse local files.
|
||||
|
||||
2. Go to the parent folder of the folder that Steam opened and copy the Factorio folder into the factorioClusterio folder
|
||||
|
||||
3. Rename the folder to "factorio"
|
||||
|
||||
|
||||
3. Open `config.json` with a text editor and configure as desired.
|
||||
|
||||
4. Run `node master.js` to generate the athentication token into secret-api-token.txt
|
||||
|
||||
5. Run `node master.js` again to start the master server.
|
||||
|
||||
**Server Host**
|
||||
|
||||
1. download and run https://puu.sh/toFHl/01eebbb333.bat
|
||||
1. Do step 1 and 2 of the Master section above *OR* use the same folder that was created in that section.
|
||||
|
||||
2. Copy config.json.dist to config.json
|
||||
2. Open `config.json` with a text editor and configure as desired. You will need to set masterAuthToken to string found in secret-api-token.txt on the master server.
|
||||
|
||||
3. Follow the instructions given.
|
||||
3. Optionally run the command `node client.js manage shared mods add clusterio` to add the clusterio mod (needed for item teleports.)
|
||||
|
||||
3.5 Some of the instructions are outdated. If you get stuck somewhere, look at the Ubuntu section.
|
||||
|
||||
4. Type `node client.js start [instancename]` to create a new instance.
|
||||
4. Run `node client.js start [instancename]` to create a new instance. Repeat it again to start the instance.
|
||||
|
||||
To connect to a master server running on a remote machine, open config.json with your favourite text editor (notepad++). You can also set it up to use the official server browser.
|
||||
|
||||
|
||||
@@ -53,6 +53,8 @@ if(!config.masterAuthToken || typeof config.masterAuthToken !== "string"){
|
||||
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.");
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
const needleOptionsWithTokenAuthHeader = {
|
||||
compressed:true,
|
||||
@@ -359,7 +361,8 @@ write-data=${ path.resolve(config.instanceDirectory, instance) }\r\n
|
||||
'--rcon-port', Number(process.env.RCONPORT) || instconf.clientPort,
|
||||
'--rcon-password', instconf.clientPassword,
|
||||
], {
|
||||
'stdio': ['pipe', 'pipe', 'pipe']
|
||||
'stdio': ['pipe', 'pipe', 'pipe'],
|
||||
'detached': process.platform === "linux",
|
||||
}
|
||||
);
|
||||
factorio.stdout.on("data", data => {
|
||||
@@ -471,7 +474,8 @@ write-data=${ path.resolve(config.instanceDirectory, instance) }\r\n
|
||||
'--server-settings', instancedirectory + '/server-settings.json',
|
||||
'--port', args.port || Number(process.env.FACTORIOPORT) || instanceconfig.factorioPort
|
||||
], {
|
||||
'stdio': ['pipe', 'pipe', 'pipe']
|
||||
'stdio': ['pipe', 'pipe', 'pipe'],
|
||||
'detached': process.platform === "linux",
|
||||
}
|
||||
);
|
||||
|
||||
@@ -570,7 +574,10 @@ async function instanceManagement(instanceconfig) {
|
||||
console.log("Started instanceManagement();");
|
||||
|
||||
/* Open websocket connection to master */
|
||||
var socket = ioClient("http://"+config.masterIP+":"+config.masterPort);
|
||||
var socket = ioClient("http://"+config.masterIP+":"+config.masterPort+"?token="+config.masterAuthToken);
|
||||
socket.on("error", err => {
|
||||
console.log("SOCKET | Error: ", err);
|
||||
});
|
||||
socket.on("hello", data => {
|
||||
console.log("SOCKET | registering slave!");
|
||||
socket.emit("registerSlave", {
|
||||
|
||||
+2
-2
@@ -14,7 +14,7 @@
|
||||
"masterPort": 8080,
|
||||
|
||||
"__commentsslPort": "HTTPS port for the master to listen to. Set to 0 or an empty string to not listen for HTTPS.",
|
||||
"sslPort": 443,
|
||||
"sslPort": 0,
|
||||
"sslCert": "database/certificates/cert.crt",
|
||||
"sslPrivKey": "database/certificates/cert.key",
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
"__comment6.5": "When the master is undersupplied, we have 3 different modes to 'fairly' distribute items. First to ask gets all, dole division using weird formula or experimental neural net tries to make stuff as fair as possible. Feel free to play around.",
|
||||
"disableFairItemDistribution": false,
|
||||
"useNeuralNetDoleDivider": true,
|
||||
"uploadModsToMaster": true,
|
||||
"uploadModsToMaster": false,
|
||||
"msBetweenCommands": 10,
|
||||
"allowRemoteCommandExecution": true,
|
||||
"enableCrossServerShout": true,
|
||||
|
||||
@@ -461,8 +461,9 @@ install_mod = function(mod_name, mod_version, mod_code, mod_files)
|
||||
local index = find_installed_mod(mod_name)
|
||||
local mod = {}
|
||||
if index then
|
||||
-- TODO: notify about installing over top of existing mod
|
||||
mod = global.mods[index]
|
||||
debug_log('attempt to install mod that is already installed, reinstalling: ' .. mod_name)
|
||||
mod = table.remove(global.mods, index)
|
||||
table.insert(global.mods, mod)
|
||||
else
|
||||
--next free index
|
||||
table.insert(global.mods, mod)
|
||||
|
||||
@@ -83,7 +83,9 @@ const fileUpload = require('express-fileupload');
|
||||
var app = express();
|
||||
|
||||
app.use(cookieParser());
|
||||
app.use(bodyParser.json());
|
||||
app.use(bodyParser.json({
|
||||
limit: '10mb',
|
||||
}));
|
||||
app.use(bodyParser.urlencoded({
|
||||
parameterLimit: 100000,
|
||||
limit: '10mb',
|
||||
@@ -921,6 +923,18 @@ class wsSlave {
|
||||
}
|
||||
}
|
||||
|
||||
io.use((socket, next) => {
|
||||
let token = socket.handshake.query.token;
|
||||
authenticate.check(token).then((result) => {
|
||||
if (result.ok) {
|
||||
next();
|
||||
} else {
|
||||
console.error(`SOCKET | authentication failed for ${socket.handshake.address}`);
|
||||
next(new Error(result.msg));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
io.on('connection', function (socket) {
|
||||
// cleanup dead sockets from disconnected people
|
||||
let terminatedConnections = 0;
|
||||
|
||||
+7
-4
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "clusterio",
|
||||
"version": "1.7.0",
|
||||
"version": "1.2.3",
|
||||
"description": "Interserver communication for factorio",
|
||||
"repository": "https://github.com/Danielv123/factorioClusterio",
|
||||
"main": "master.js",
|
||||
@@ -15,12 +15,15 @@
|
||||
"factorio"
|
||||
],
|
||||
"author": "Danielv123",
|
||||
"license": "ISC",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"dependencies": {
|
||||
"as-table": "^1.0.31",
|
||||
"averaged-timeseries": "^1.4.0",
|
||||
"base64url": "^3.0.0",
|
||||
"bcrypt": "^2.0.1",
|
||||
"bcrypt": "^3.0.6",
|
||||
"bcrypt-promise": "^2.0.0",
|
||||
"body-parser": "^1.18.2",
|
||||
"cli": "^1.0.1",
|
||||
@@ -46,7 +49,7 @@
|
||||
"moment": "^2.22.2",
|
||||
"ncp": "^2.0.0",
|
||||
"needle": "^2.2.4",
|
||||
"node-factorio-api": "^0.3.5",
|
||||
"node-factorio-api": "^0.3.8",
|
||||
"node-forge": "^0.7.1",
|
||||
"prom-client": "^10.2.3",
|
||||
"rcon-client-fork": "^3.2.0",
|
||||
|
||||
@@ -17,4 +17,5 @@ module.exports = {
|
||||
description: "Clusterio plugin to fill character logistic slots with master imports",
|
||||
// We'll send everything in this file to your stdin. Beware.
|
||||
scriptOutputFileSubscription: "inventoryImports.txt",
|
||||
fileReadDelay: 100,
|
||||
}
|
||||
@@ -141,7 +141,10 @@ function pollInventories(outputFile){
|
||||
//console.log("/silent-command "+'local a=game.players["Danielv123"].get_inventory(defines.inventory.player_main).get_contents()local b=game.players["Danielv123"].get_quickbar().get_contents()local c={}for d=1,game.players["Danielv123"].force.character_logistic_slot_count do c[d]=game.players["Danielv123"].character.get_request_slot(d)end;local e="{inventory:{"for f,g in pairs(a)do e=e.."['+"'"+'"..f.."'+"'"+']:"..g..","end;for f,g in pairs(b)do e=e.."['+"'"+'"..f.."'+"'"+']:"..g..","end;e=e.."},requestSlots:{"for f,g in pairs(c)do e=e.."['+"'"+'"..g["name"].."'+"'"+']:"..g["count"]..", "end;e=e.."}}"game.write_file("'+pluginConfig.scriptOutputFileSubscription+'",e)')
|
||||
// console.log("/silent-command "+'local a="{"for b,c in pairs(game.players)do local d=game.players[b].get_inventory(defines.inventory.player_main).get_contents()local e=game.players[b].get_quickbar().get_contents()local f={}for g=1,game.players[b].force.character_logistic_slot_count do f[g]=game.players[b].character.get_request_slot(g)end;a=a..b..":{inventory:{"for h,i in pairs(d)do a=a.."['+"'"+'"..h.."'+"'"+']:"..i..","end;for h,i in pairs(e)do a=a.."['+"'"+'"..h.."'+"'"+']:"..i..","end;a=a.."},requestSlots:{"for h,i in pairs(f)do a=a.."['+"'"+'"..i["name"].."'+"'"+']:"..i["count"]..", "end;a=a.."}},"end;a=a.."}"game.write_file("'+pluginConfig.scriptOutputFileSubscription+'",a)')
|
||||
//return "/silent-command "+'local a="{"for b,c in pairs(game.players)do if c.connected then local d=game.players[b].get_inventory(defines.inventory.player_main).get_contents()local e=game.players[b].get_quickbar().get_contents()local f={}for g=1,game.players[b].force.character_logistic_slot_count do f[g]=game.players[b].character.get_request_slot(g)end;a=a..b..":{inventory:{"for h,i in pairs(d)do a=a.."['+"'"+'"..h.."'+"'"+']:"..i..","end;for h,i in pairs(e)do a=a.."['+"'"+'"..h.."'+"'"+']:"..i..","end;a=a.."},requestSlots:{"for h,i in pairs(f)do a=a.."['+"'"+'"..i["name"].."'+"'"+']:"..i["count"]..", "end;a=a.."}},"end end;a=a.."}"game.write_file("'+outputFile+'",a)'
|
||||
return '/silent-command '+'local a='+"'"+'{"players":{'+"'"+'local b=false;for c,d in pairs(game.players)do if d.connected and d.character then if b then a=a..'+"'"+','+"'"+'else b=true end;local e=game.players[c].get_inventory(defines.inventory.player_main).get_contents()local f=game.players[c].get_quickbar().get_contents()local g={}local z={}for j,k in pairs(e)do if z[j] ~= nil then z[j] = z[j] + k else z[j] = k end end for j,k in pairs(f)do if z[j] ~= nil then z[j] = z[j] + k else z[j] = k end end for h=1,game.players[c].force.character_logistic_slot_count do g[h]=game.players[c].character.get_request_slot(h)end;a=a..'+"'"+'"'+"'"+'..c..'+"'"+'":{"inventory":{'+"'"+'local i=false;for j,k in pairs(z)do if i then a=a..'+"'"+','+"'"+'else i=true end;a=a..'+"'"+'"'+"'"+'..j..'+"'"+'":'+"'"+'..k end;a=a..'+"'"+'},"requestSlots":{'+"'"+'i=false;for j,k in pairs(g)do if i then a=a..'+"'"+','+"'"+'else i=true end;a=a..'+"'"+'"'+"'"+'..k['+"'"+'name'+"'"+']..'+"'"+'":'+"'"+'..k['+"'"+'count'+"'"+']end;a=a..'+"'"+'}}'+"'"+'end end;a=a.."}}"game.write_file("'+outputFile+'",a,true,0)'
|
||||
//return '/silent-command '+'local a='+"'"+'{"players":{'+"'"+'local b=false;for c,d in pairs(game.players)do if d.connected and d.character then if b then a=a..'+"'"+','+"'"+'else b=true end;local e=game.players[c].get_inventory(defines.inventory.player_main).get_contents()local f=game.players[c].get_quickbar().get_contents()local g={}local z={}for j,k in pairs(e)do if z[j] ~= nil then z[j] = z[j] + k else z[j] = k end end for j,k in pairs(f)do if z[j] ~= nil then z[j] = z[j] + k else z[j] = k end end for h=1,game.players[c].force.character_logistic_slot_count do g[h]=game.players[c].character.get_request_slot(h)end;a=a..'+"'"+'"'+"'"+'..c..'+"'"+'":{"inventory":{'+"'"+'local i=false;for j,k in pairs(z)do if i then a=a..'+"'"+','+"'"+'else i=true end;a=a..'+"'"+'"'+"'"+'..j..'+"'"+'":'+"'"+'..k end;a=a..'+"'"+'},"requestSlots":{'+"'"+'i=false;for j,k in pairs(g)do if i then a=a..'+"'"+','+"'"+'else i=true end;a=a..'+"'"+'"'+"'"+'..k['+"'"+'name'+"'"+']..'+"'"+'":'+"'"+'..k['+"'"+'count'+"'"+']end;a=a..'+"'"+'}}'+"'"+'end end;a=a.."}}"game.write_file("'+outputFile+'",a,true,0)'
|
||||
|
||||
// Warning: This command is not in sync with lua commands.lua
|
||||
return `/silent-command local a='{"players":{'local b=false;for c,d in pairs(game.players)do if d.connected and d.character then if b then a=a..','else b=true end;local e=game.players[c].get_inventory(defines.inventory.character_main).get_contents()local g={}for h=1,game.players[c].force.character_logistic_slot_count do g[h]=game.players[c].character.get_request_slot(h)end;a=a..'"'..c..'":{"inventory":{'local i=false;for j,k in pairs(e)do if i then a=a..','else i=true end;a=a..'"'..j..'":'..k end;a=a..'},"requestSlots":{'i=false;for j,k in pairs(g)do if i then a=a..','else i=true end;a=a..'"'..k['name']..'":'..k['count']end;a=a..'}}'end end;a=a.."}}"game.write_file("${outputFile}",a,true,0)`
|
||||
/*
|
||||
needle.post(config.masterIP+':'+config.masterPort+'/api/editSlaveMeta', {instanceID: config.unique, password: config.clientPassword, meta: {UPS:UPS}}, function(err, resp) {
|
||||
// success?
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
-- WARNING: The commands in this file is not in sync with interfacingFunctions.js
|
||||
-- Lua cheatsheet
|
||||
|
||||
/c game.write_file("test.txt",serpent.block(game.players["Danielv123"].get_quickbar().get_contents()))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -169,21 +169,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 = {}
|
||||
@@ -193,7 +196,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) {
|
||||
@@ -208,65 +211,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
|
||||
@@ -274,8 +297,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)) {
|
||||
@@ -283,9 +307,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
|
||||
@@ -299,8 +323,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'
|
||||
@@ -317,11 +342,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}`)
|
||||
@@ -346,8 +370,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,
|
||||
|
||||
Reference in new issue
Block a user