mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-13 23:14:53 +09:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7569c4a878 | ||
|
|
8ec7ec86d6 | ||
|
|
5fe98a0d60 | ||
|
|
136bd24399 | ||
|
|
c380fe269f | ||
|
|
909e7d5ad6 | ||
|
|
76cca59807 | ||
|
|
3e7d4a8648 | ||
|
|
b0eb188e22 | ||
|
|
e70cfe7abd |
No files matched your search
@@ -1,6 +1,17 @@
|
|||||||
Changelog
|
Changelog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
Version 1.2.4
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- Removed broken remote combinator signaling.
|
||||||
|
- Fixed research sync endlessly updating already researched technologies
|
||||||
|
- Removed obsolete item/fluid statistics from clusterioMod
|
||||||
|
- Removed per mod upload logging when config.uploadModsToMaster disabled
|
||||||
|
- Fixed bcrypt failing to install on windows due to the new version not
|
||||||
|
having Windows binaries.
|
||||||
|
|
||||||
|
|
||||||
Version 1.2.3
|
Version 1.2.3
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
|||||||
@@ -299,7 +299,6 @@ if (!command || command == "help" || command == "--help") {
|
|||||||
fs.mkdirSync(instancedirectory + "/saves/");
|
fs.mkdirSync(instancedirectory + "/saves/");
|
||||||
fs.writeFileSync(instancedirectory + "/script-output/output.txt", "");
|
fs.writeFileSync(instancedirectory + "/script-output/output.txt", "");
|
||||||
fs.writeFileSync(instancedirectory + "/script-output/orders.txt", "");
|
fs.writeFileSync(instancedirectory + "/script-output/orders.txt", "");
|
||||||
fs.writeFileSync(instancedirectory + "/script-output/txbuffer.txt", "");
|
|
||||||
fs.mkdirSync(instancedirectory + "/mods/");
|
fs.mkdirSync(instancedirectory + "/mods/");
|
||||||
fs.mkdirSync(instancedirectory + "/instanceMods/");
|
fs.mkdirSync(instancedirectory + "/instanceMods/");
|
||||||
fs.mkdirSync(instancedirectory + "/scenarios/");
|
fs.mkdirSync(instancedirectory + "/scenarios/");
|
||||||
@@ -738,19 +737,19 @@ async function instanceManagement(instanceconfig) {
|
|||||||
|
|
||||||
setTimeout(function(){hashMods(instance, uploadMods)}, 5000);
|
setTimeout(function(){hashMods(instance, uploadMods)}, 5000);
|
||||||
function uploadMods(modHashes) {
|
function uploadMods(modHashes) {
|
||||||
// [{modName:string,hash:string}, ... ]
|
if (config.uploadModsToMaster) {
|
||||||
for(let i=0;i<modHashes.length;i++){
|
// [{modName:string,hash:string}, ... ]
|
||||||
let payload = {
|
for(let i=0;i<modHashes.length;i++){
|
||||||
modName: modHashes[i].modName,
|
let payload = {
|
||||||
hash: modHashes[i].hash,
|
modName: modHashes[i].modName,
|
||||||
};
|
hash: modHashes[i].hash,
|
||||||
needle.post(config.masterIP + ":" + config.masterPort + '/api/checkMod', payload, needleOptionsWithTokenAuthHeader, function (err, response, body) {
|
};
|
||||||
if(err) console.error("Unable to contact master server /api/checkMod! Please check your config.json.");
|
needle.post(config.masterIP + ":" + config.masterPort + '/api/checkMod', payload, needleOptionsWithTokenAuthHeader, function (err, response, body) {
|
||||||
if(response && body && body == "found") {
|
if(err) console.error("Unable to contact master server /api/checkMod! Please check your config.json.");
|
||||||
console.log("master has mod "+modHashes[i].modName);
|
if(response && body && body == "found") {
|
||||||
} else if (response && body && typeof body == "string") {
|
console.log("master has mod "+modHashes[i].modName);
|
||||||
let mod = response.body;
|
} else if (response && body && typeof body == "string") {
|
||||||
if(config.uploadModsToMaster){
|
let mod = response.body;
|
||||||
console.log("Sending mod: " + mod);
|
console.log("Sending mod: " + mod);
|
||||||
// Send mods master says it wants
|
// Send mods master says it wants
|
||||||
// response.body is a string which is a modName.zip
|
// response.body is a string which is a modName.zip
|
||||||
@@ -767,11 +766,11 @@ async function instanceManagement(instanceconfig) {
|
|||||||
});
|
});
|
||||||
var form = req.form();
|
var form = req.form();
|
||||||
form.append('file', fs.createReadStream(config.instanceDirectory+"/"+instance+"/mods/"+mod));
|
form.append('file', fs.createReadStream(config.instanceDirectory+"/"+instance+"/mods/"+mod));
|
||||||
} else {
|
|
||||||
console.log("Not sending mod: " + mod + " to master because config.uploadModsToMaster is not enabled")
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
|
} else {
|
||||||
|
console.log("Bypassing sending mods to master because config.uploadModsToMaster is not enabled")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // END OF INSTANCE START ---------------------------------------------------------------------
|
} // END OF INSTANCE START ---------------------------------------------------------------------
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
Clusterio master server. Facilitates communication between slaves through
|
Clusterio master server. Facilitates communication between slaves through
|
||||||
a webserver, storing data related to slaves like production graphs and
|
a webserver, storing data related to slaves like production graphs.
|
||||||
combinator signals.
|
|
||||||
|
|
||||||
@module clusterioMaster
|
@module clusterioMaster
|
||||||
@author Danielv123
|
@author Danielv123
|
||||||
@@ -876,14 +875,6 @@ class wsSlave {
|
|||||||
prometheusWsUsageCounter.labels('heartbeat', this.instanceID).inc();
|
prometheusWsUsageCounter.labels('heartbeat', this.instanceID).inc();
|
||||||
this.lastBeat = Date.now();
|
this.lastBeat = Date.now();
|
||||||
});
|
});
|
||||||
this.socket.on("combinatorSignal", circuitFrameWithMeta => {
|
|
||||||
prometheusWsUsageCounter.labels('combinatorSignal', this.instanceID).inc();
|
|
||||||
if(circuitFrameWithMeta && typeof circuitFrameWithMeta == "object"){
|
|
||||||
Object.keys(wsSlaves).forEach(instanceID => {
|
|
||||||
wsSlaves[instanceID].socket.emit("processCombinatorSignal", circuitFrameWithMeta);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// handle command return values
|
// handle command return values
|
||||||
this.commandsWaitingForReturn = {};
|
this.commandsWaitingForReturn = {};
|
||||||
this.socket.on("runCommandReturnValue", resp => {
|
this.socket.on("runCommandReturnValue", resp => {
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "clusterio",
|
"name": "clusterio",
|
||||||
"version": "1.2.3",
|
"version": "1.2.4",
|
||||||
"description": "Interserver communication for factorio",
|
"description": "Interserver communication for factorio",
|
||||||
"repository": "https://github.com/Danielv123/factorioClusterio",
|
"repository": "https://github.com/Danielv123/factorioClusterio",
|
||||||
"main": "master.js",
|
"main": "master.js",
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
"as-table": "^1.0.31",
|
"as-table": "^1.0.31",
|
||||||
"averaged-timeseries": "^1.4.0",
|
"averaged-timeseries": "^1.4.0",
|
||||||
"base64url": "^3.0.0",
|
"base64url": "^3.0.0",
|
||||||
"bcrypt": "^3.0.6",
|
"bcrypt": "=3.0.6",
|
||||||
"bcrypt-promise": "^2.0.0",
|
"bcrypt-promise": "^2.0.0",
|
||||||
"body-parser": "^1.18.2",
|
"body-parser": "^1.18.2",
|
||||||
"cli": "^1.0.1",
|
"cli": "^1.0.1",
|
||||||
|
|||||||
@@ -35,61 +35,6 @@ module.exports = class remoteCommands {
|
|||||||
}
|
}
|
||||||
})().catch(e => console.log(e));
|
})().catch(e => console.log(e));
|
||||||
|
|
||||||
// flow/production statistics ------------------------------------------------------------
|
|
||||||
var oldFlowStats = false;
|
|
||||||
var oldTimestamp;
|
|
||||||
var oldFlowStats;
|
|
||||||
setInterval(function(){
|
|
||||||
fs.readFile(instancedirectory + "/script-output/flows.txt", {encoding: "utf8"}, function(err, data) {
|
|
||||||
if(!err && data) {
|
|
||||||
let timestamp = Date.now();
|
|
||||||
data = data.split("\n");
|
|
||||||
let flowStats = [];
|
|
||||||
for(let i = 0; i < data.length; i++) {
|
|
||||||
// try catch to remove any invalid json
|
|
||||||
try{
|
|
||||||
flowStats[flowStats.length] = JSON.parse(data[i]);
|
|
||||||
} catch (e) {
|
|
||||||
// console.log(" invalid json: " + i);
|
|
||||||
// some lines of JSON are invalid but don't worry, we just filter em out
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// fluids
|
|
||||||
let flowStat1 = flowStats[flowStats.length-1].flows.player.input_counts
|
|
||||||
// items
|
|
||||||
let flowStat2 = flowStats[flowStats.length-2].flows.player.input_counts
|
|
||||||
// merge fluid and item flows
|
|
||||||
let totalFlows = {};
|
|
||||||
for(let key in flowStat1) totalFlows[key] = flowStat1[key];
|
|
||||||
for(let key in flowStat2) totalFlows[key] = flowStat2[key];
|
|
||||||
if(oldFlowStats && totalFlows && oldTimestamp) {
|
|
||||||
let payload = objectOps.deepclone(totalFlows);
|
|
||||||
// change from total reported to per time unit
|
|
||||||
for(let key in oldFlowStats) {
|
|
||||||
// get production per minute
|
|
||||||
payload[key] = Math.floor((payload[key] - oldFlowStats[key])/(timestamp - oldTimestamp)*60000);
|
|
||||||
if(payload[key] < 0) {
|
|
||||||
payload[key] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(let key in payload) {
|
|
||||||
if(payload[key] == '0') {
|
|
||||||
delete payload[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log("Recorded flows, copper plate since last time: " + payload["copper-plate"]);
|
|
||||||
needle.post(that.config.masterIP + ":" + that.config.masterPort + '/api/logStats', {timestamp: timestamp, instanceID: that.config.unique, data: payload}, needleOptionsWithTokenAuthHeader, function (err, response, body) {
|
|
||||||
// we did it, keep going
|
|
||||||
});
|
|
||||||
}
|
|
||||||
oldTimestamp = timestamp;
|
|
||||||
oldFlowStats = totalFlows;
|
|
||||||
fs.writeFileSync(instancedirectory + "/script-output/flows.txt", "");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// we don't need to update stats quickly as that could be expensive
|
|
||||||
}, 60000*5);
|
|
||||||
|
|
||||||
// provide items --------------------------------------------------------------
|
// provide items --------------------------------------------------------------
|
||||||
// trigger when something happens to output.txt
|
// trigger when something happens to output.txt
|
||||||
fs.watch(instancedirectory + "/script-output/output.txt", function (eventType, filename) {
|
fs.watch(instancedirectory + "/script-output/output.txt", function (eventType, filename) {
|
||||||
@@ -232,56 +177,6 @@ module.exports = class remoteCommands {
|
|||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
messageInterface("/silent-command remote.call('clusterio','setWorldID',"+that.config.unique+")")
|
messageInterface("/silent-command remote.call('clusterio','setWorldID',"+that.config.unique+")")
|
||||||
}, 20000);
|
}, 20000);
|
||||||
/* REMOTE SIGNALLING
|
|
||||||
* send any signals the slave has been told to send
|
|
||||||
* Fetch combinator signals from the server
|
|
||||||
*/
|
|
||||||
this.socket.on("processCombinatorSignal", circuitFrameWithMeta => {
|
|
||||||
if(circuitFrameWithMeta && typeof circuitFrameWithMeta == "object" && circuitFrameWithMeta.frame && Array.isArray(circuitFrameWithMeta.frame)){
|
|
||||||
messageInterface("/silent-command remote.call('clusterio', 'receiveFrame', '"+JSON.stringify(circuitFrameWithMeta.frame)+"')");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// get outbound frames from file and send to master
|
|
||||||
// get array of lines in file, each line should correspond to a JSON encoded frame
|
|
||||||
let signals = fs.readFileSync(instancedirectory + "/script-output/txbuffer.txt", "utf8").split("\n");
|
|
||||||
// if we actually got anything from the file, proceed and reset file
|
|
||||||
let readingTxBufferSoon = false;
|
|
||||||
let txBufferClearCounter = 0;
|
|
||||||
fs.watch(instancedirectory + "/script-output/txbuffer.txt", "utf-8", (eventType, filename) => {
|
|
||||||
if(!readingTxBufferSoon){ // use a 100ms delay to avoid messing with rapid sequential writes from factorio (I think that might be a problem maybe?)
|
|
||||||
readingTxBufferSoon = true;
|
|
||||||
setTimeout(()=>{
|
|
||||||
txBufferClearCounter++;
|
|
||||||
fs.readFile(instancedirectory + "/script-output/txbuffer.txt", "utf-8", (err, signals) => {
|
|
||||||
signals = signals.split("\n");
|
|
||||||
if (signals[0]) {
|
|
||||||
//if(txBufferClearCounter > 500){
|
|
||||||
fs.writeFileSync(instancedirectory + "/script-output/txbuffer.txt", "");
|
|
||||||
// txBufferClearCounter = 0;
|
|
||||||
//}
|
|
||||||
|
|
||||||
// loop through all our frames
|
|
||||||
for (let i = 0; i < signals.length; i++) {
|
|
||||||
if (signals[i] && objectOps.isJSON(signals[i])) {
|
|
||||||
// signals[i] is a JSON array called a "frame" of signals. We timestamp it for storage on master
|
|
||||||
// then we unpack and RCON in this.frame to the game later.
|
|
||||||
let framepart = JSON.parse(signals[i]);
|
|
||||||
let doneframe = {
|
|
||||||
time: Date.now(),
|
|
||||||
frame: framepart, // thats our array of objects(single signals);
|
|
||||||
}
|
|
||||||
// send to master using socket.io, opened at the top of instanceManagement()
|
|
||||||
this.socket.emit("combinatorSignal", doneframe);
|
|
||||||
} else {
|
|
||||||
// console.log("Invalid jsony: "+typeof signals[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
readingTxBufferSoon = false;
|
|
||||||
},100);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
async getCommand(file){
|
async getCommand(file){
|
||||||
this.commandCache = this.commandCache || {};
|
this.commandCache = this.commandCache || {};
|
||||||
|
|||||||
@@ -284,6 +284,11 @@ class ResearchSync {
|
|||||||
if (isNaN(cluster_techs[name].progress))
|
if (isNaN(cluster_techs[name].progress))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
// Ignore researched techs
|
||||||
|
if (!tech.infinite && tech.researched) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Do not update progress for infinite techs with a local level that's higher.
|
// Do not update progress for infinite techs with a local level that's higher.
|
||||||
if (tech.infinite && tech.level > cluster_techs[name].level) {
|
if (tech.infinite && tech.level > cluster_techs[name].level) {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
Reference in new issue
Block a user