From afb00ab3fbfcd0340875ce0dcea032005490dce9 Mon Sep 17 00:00:00 2001 From: Danielv123 Date: Mon, 7 Nov 2016 09:26:58 +0100 Subject: [PATCH 01/11] Production chart partially added and hidden --- package.json | 1 + static/index.html | 8 +- static/main.js | 220 ++++++++++++++++++++++++++-------------------- static/style.css | 3 + 4 files changed, 132 insertions(+), 100 deletions(-) diff --git a/package.json b/package.json index cb9a0d13..9d8c3ff9 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "license": "ISC", "dependencies": { "body-parser": "^1.15.2", + "canvasjs": "^1.8.1", "child_process": "^1.0.2", "express": "^4.14.0", "fs": "0.0.2", diff --git a/static/index.html b/static/index.html index 4386f494..c959ca84 100644 --- a/static/index.html +++ b/static/index.html @@ -2,7 +2,7 @@ Clusterio - + @@ -31,13 +31,13 @@ -
+

Slaves

diff --git a/static/main.js b/static/main.js index 86b02406..0b2591b4 100644 --- a/static/main.js +++ b/static/main.js @@ -4,6 +4,7 @@ contents = { "copper-plate":7312, } // nice functions +// hash a string to a hash function djb2(str){ var hash = 5381; for (var i = 0; i < str.length; i++) { @@ -11,7 +12,7 @@ function djb2(str){ } return hash; } - +// hash a string to a color function hashColor(str) { var hash = djb2(str); var r = (hash & 0xFF0000) >> 16; @@ -19,21 +20,23 @@ function hashColor(str) { var b = hash & 0x0000FF; return "#" + ("0" + r.toString(16)).substr(-2) + ("0" + g.toString(16)).substr(-2) + ("0" + b.toString(16)).substr(-2); } - +// exactly what you would expect it to, returns String function capitalizeFirstLetter(string) { return string.charAt(0).toUpperCase() + string.slice(1); } -// function to draw data we recieve from ajax requests +// hide the HTML object passed as argument #1 function hideThis(object) { object.style.visibility = "hidden"; } +// function to sort arrays of objects after a keys value function sortByKey(array, key) { return array.sort(function(a, b) { var x = Number(a[key]); var y = Number(b[key]); return ((x < y) ? 1 : ((x > y) ? -1 : 0)); }); } +// function to draw data we recieve from ajax requests function drawcontents(data) { var data = sortByKey(data, "count"); result = ""; @@ -65,88 +68,125 @@ function display(page) { } } -// Function to redraw charts in case they bug out -function drawcharts() { - // create chart of items in master storage - ctx = document.querySelector("#contentGraph").getContext('2d'); - PieChart = new Chart(ctx); - - // production chart - // https://codepen.io/statuswoe/pen/hyldD - var count = 20; - var data = { - labels : ["1","2","3","4","5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"], - datasets : [ - { - fillColor : "rgba(220,220,220,0.5)", - strokeColor : "rgba(220,220,220,1)", - pointColor : "rgba(220,220,220,1)", - pointStrokeColor : "#fff", - title:"one", - data : [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1] - }, - { - fillColor : "rgba(151,187,205,0.5)", - strokeColor : "rgba(151,187,205,1)", - pointColor : "rgba(151,187,205,1)", - pointStrokeColor : "#fff", - title:"two", - data : [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1] - } - ] - } - // this is ugly, don't judge me - var updateData = function(oldData){ - if(piedataOld[0]){ - //console.log(piedata) - var labels = oldData["labels"]; - var dataSetA = oldData["datasets"][0]["data"]; - var dataSetB = oldData["datasets"][1]["data"]; - - labels.shift(); - count++; - labels.push(count.toString()); - // this is where we generate new data - var newDataA = piedata[0].value - piedataOld[0].value; - var newDataB = piedata[1].value - piedataOld[1].value; - // not quite sure how this works, where is dataSetA placed in data/the graph? - dataSetA.push(newDataA); - dataSetB.push(newDataB); - dataSetA.shift(); - dataSetB.shift(); - } - }; - - // Not sure why the scaleOverride isn't working... - var optionsNoAnimation = { - animation : false, - //Boolean - If we want to override with a hard coded scale - scaleOverride : true, - //** Required if scaleOverride is true ** - //Number - The number of steps in a hard coded scale - scaleSteps : 20, - //Number - The value jump in the hard coded scale - scaleStepWidth : 10, - //Number - The scale starting value - scaleStartValue : 0 - } - - //Get the context of the canvas element we want to select - var ctx = document.getElementById("productionChart").getContext("2d"); - var optionsNoAnimation = {animation : false} - productionChart = new Chart(ctx); - productionChart.Line(data, optionsNoAnimation); - - setInterval(function(){ - updateData(data); - productionChart.Line(data, optionsNoAnimation); - },1000); -} - // setTimeout is used to put this processing in the back of the queue, after the HTML canvas is done -setTimeout(function(){ - drawcharts(); -},10) +window.onload = function () { + // dataPoints + var dataPoints1 = []; + var dataPoints2 = []; + + var chart = new CanvasJS.Chart("productionChart",{ + zoomEnabled: true, + title: { + text: "Production" + }, + toolTip: { + shared: true + }, + legend: { + verticalAlign: "top", + horizontalAlign: "center", + fontSize: 14, + fontWeight: "bold", + fontFamily: "calibri", + fontColor: "dimGrey" + }, + axisX: { + title: "Shows items in network" + }, + axisY:{ + prefix: '', + includeZero: true + }, + data: [{ + // dataSeries1 + type: "line", + xValueType: "dateTime", + showInLegend: true, + name: "Company A", + dataPoints: dataPoints1 + }, + { + // dataSeries2 + type: "line", + xValueType: "dateTime", + showInLegend: true, + name: "Company B" , + dataPoints: dataPoints2 + }], + legend:{ + cursor:"pointer", + itemclick : function(e) { + if (typeof(e.dataSeries.visible) === "undefined" || e.dataSeries.visible) { + e.dataSeries.visible = false; + } + else { + e.dataSeries.visible = true; + } + chart.render(); + } + } + }); + + + + var updateInterval = 10000; + // initial value + var yValue1 = 640; + var yValue2 = 604; + + var time = new Date; + time.setHours(9); + time.setMinutes(30); + time.setSeconds(00); + time.setMilliseconds(00); + // starting at 9.30 am + + var updateChart = function (count) { + count = count || 1; + + // count is number of times loop runs to generate random dataPoints. + + for (var i = 0; i < count; i++) { + + // add interval duration to time + time.setTime(time.getTime()+ updateInterval); + + + // generating random values + var deltaY1 = .5 + Math.random() *(-.5-.5); + var deltaY2 = .5 + Math.random() *(-.5-.5); + + // adding random value and rounding it to two digits. + yValue1 = Math.round((yValue1 + deltaY1)*100)/100; + yValue2 = Math.round((yValue2 + deltaY2)*100)/100; + + // pushing the new values + dataPoints1.push({ + x: time.getTime(), + y: yValue1 + }); + dataPoints2.push({ + x: time.getTime(), + y: yValue2 + }); + + + }; + + // updating legend text with updated with y Value + chart.options.data[0].legendText = " Company A $" + yValue1; + chart.options.data[1].legendText = " Company B $" + yValue2; + + chart.render(); + + }; + + // generates first set of dataPoints + updateChart(3000); + + // update chart after specified interval + setInterval(function(){updateChart()}, updateInterval); +} var piedata = {}; var piedataOld = {}; @@ -172,18 +212,6 @@ setInterval(function() { label: data[i].name, } } - PieChart.Pie(piedata, { - animation: false, - legend: { - display: true, - labels: { - fontColor: 'rgb(255, 99, 132)' - } - }, - hover: { - mode: "label", - } - }); } } xmlhttp.open("GET", "inventory", true); diff --git a/static/style.css b/static/style.css index d2a2fc76..13e5a73c 100644 --- a/static/style.css +++ b/static/style.css @@ -19,6 +19,9 @@ #body > div { display:none; } +#body > #production { + display:block; +} #contents { width:300px; } From 37fdbb68d1ac97d80021387ef74f4be413f12e43 Mon Sep 17 00:00:00 2001 From: Danielv123 Date: Mon, 7 Nov 2016 11:14:25 +0100 Subject: [PATCH 02/11] Remove currently non functioning graph from nav, start on storage page --- static/index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/static/index.html b/static/index.html index c959ca84..4c6789df 100644 --- a/static/index.html +++ b/static/index.html @@ -17,9 +17,9 @@ - - +

Slaves

From eb786ff1465ff410ec1a4c4825c13434bc1b2752 Mon Sep 17 00:00:00 2001 From: Danielv123 Date: Mon, 7 Nov 2016 13:33:15 +0100 Subject: [PATCH 03/11] Slave display now only shows connected slaves, autoupdates, trangartime Added hidden option to show dates in trangartime y-ymd-ymd-y instead of ISO 6801 Ctrl+shift+i g.trangarTime = true --- client.js | 1 + master.js | 2 +- static/main.js | 23 +++++++++++++++++++---- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/client.js b/client.js index a7c8ee97..8c1035e4 100644 --- a/client.js +++ b/client.js @@ -152,6 +152,7 @@ function getID() { }) } +setInterval(getID, 10000) // provide items -------------------------------------------------------------- // trigger when something happens to output.txt fs.watch(instancedirectory + "/script-output/output.txt", function(eventType, filename) { diff --git a/master.js b/master.js index 55a86494..5131370f 100644 --- a/master.js +++ b/master.js @@ -45,6 +45,7 @@ db.items.additem = function(object) { } var slaves = {} // world ID management +// slaves post here to tell the server they exist app.post("/getID", function(req,res) { // request.body should be an object // {rconPort, rconPassword, serverPort, mac, time} @@ -55,7 +56,6 @@ app.post("/getID", function(req,res) { console.log("Slave: " + req.body.mac + " : " + req.body.serverPort) } }); - // endpoint for getting information about all our slaves app.get("/slaves", function(req, res) { res.header("Access-Control-Allow-Origin", "*"); diff --git a/static/main.js b/static/main.js index 0b2591b4..ee568da4 100644 --- a/static/main.js +++ b/static/main.js @@ -1,4 +1,4 @@ - +var g = {} contents = { "iron-plate":100, "copper-plate":7312, @@ -70,6 +70,7 @@ function display(page) { // setTimeout is used to put this processing in the back of the queue, after the HTML canvas is done window.onload = function () { + display("storage") // dataPoints var dataPoints1 = []; var dataPoints2 = []; @@ -221,19 +222,32 @@ setInterval(function() { Date.prototype.yyyymmdd = function() { // http://stackoverflow.com/questions/3066586/get-string-in-yyyymmdd-format-from-js-date-object var mm = this.getMonth() + 1; // getMonth() is zero-based var dd = this.getDate(); - return [this.getFullYear(), !mm[1] && '0', mm, !dd[1] && '0', dd].join(''); // padding + if(mm<10)mm = "0"+mm + if(dd<10)dd = "0"+dd + console.log(this.getFullYear()) + return this.getFullYear()+""+mm+""+dd+ ""; // padding }; var date = new Date(); + +// ask master for slaves setInterval(function() { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if(xmlhttp.readyState == 4 && xmlhttp.status == 200) { var slaveData = JSON.parse(xmlhttp.responseText); - var HTML = "

Latest connections:

" + var HTML = "

Current connections:

" for(i=0;i

Last seen: "+date.yyyymmdd(slaveData[key].time)+"

Port: "+slaveData[key].serverPort+"

Host: "+slaveData[key].mac+"

" + if(Date.now() - slaveData[key].time < 12000) { + // Display ISO 6801 compliant date to please Zarthus + // maybe include an option to use y-ymd-ymd-y for Trangar compatibility as well + var seenDate = date.yyyymmdd(slaveData[key].time) + if(g.trangarTime == true){ + var seenDate = (seenDate+"")[0]+"-"+(seenDate+"")[1]+(seenDate+"")[4]+(seenDate+"")[6]+"-"+(seenDate+"")[2]+(seenDate+"")[5]+(seenDate+"")[7]+"-"+(seenDate+"")[3] + } + HTML += "

ID: " + slaveData[key].unique + "

Last seen: "+seenDate+"

Port: "+slaveData[key].serverPort+"

Host: "+slaveData[key].mac+"

" + } } document.querySelector("#slaves > #display").innerHTML = HTML } @@ -244,6 +258,7 @@ setInterval(function() { // image data // key is the name of the item in the database, value is the name of the image on wiki.factorio.com/images/* +// this list has to include all entities that doesn't just follow the simple capitalize first letter convention var imagedata = { ["empty-barrel"]: "Barrel-empty", ["transport-belt"]: "Basic-transport-belt", From 187c05640ff96b89b69204a2308f2cebe83287bf Mon Sep 17 00:00:00 2001 From: Danielv123 Date: Mon, 19 Dec 2016 13:21:36 +0100 Subject: [PATCH 04/11] Argument --- static/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/main.js b/static/main.js index ee568da4..5c63abe6 100644 --- a/static/main.js +++ b/static/main.js @@ -219,7 +219,7 @@ setInterval(function() { xmlhttp.send(); }, 500) // get all slaves recently connected to master -Date.prototype.yyyymmdd = function() { // http://stackoverflow.com/questions/3066586/get-string-in-yyyymmdd-format-from-js-date-object +Date.prototype.yyyymmdd = function(time) { // http://stackoverflow.com/questions/3066586/get-string-in-yyyymmdd-format-from-js-date-object var mm = this.getMonth() + 1; // getMonth() is zero-based var dd = this.getDate(); if(mm<10)mm = "0"+mm From 1c5bb9e8abae32a239c6b83db1d49e6def936bf6 Mon Sep 17 00:00:00 2001 From: Danielv123 Date: Mon, 19 Dec 2016 13:23:53 +0100 Subject: [PATCH 05/11] Consistent styling --- client.js | 337 ++++++++++++++++++++++++---------------------- database/items.db | 0 2 files changed, 176 insertions(+), 161 deletions(-) create mode 100644 database/items.db diff --git a/client.js b/client.js index 8c1035e4..425fcba4 100644 --- a/client.js +++ b/client.js @@ -6,37 +6,37 @@ var child_process = require('child_process'); var config = require('./config'); var instance = process.argv[2]; -if(!instance){ +if (!instance) { console.error("Usage: node client.js [instance name]") process.exit(1) } -if(!fs.existsSync("./instances/")){ - fs.mkdirSync("instances"); +if (!fs.existsSync("./instances/")) { + fs.mkdirSync("instances"); } -var instancedirectory = './instances/'+instance; -if (!fs.existsSync(instancedirectory)){ - fs.mkdirSync(instancedirectory); - fs.mkdirSync(instancedirectory + "/script-output/"); - fs.writeFileSync(instancedirectory + "/script-output/output.txt", "") - fs.writeFileSync(instancedirectory + "/script-output/orders.txt", "") - fs.writeFileSync(instancedirectory + "/script-output/txbuffer.txt", "") - fs.mkdirSync(instancedirectory + "/mods/") - fs.symlinkSync('../../../clusterio_0.0.3',instancedirectory + "/mods/clusterio_0.0.3",'junction') - fs.writeFileSync(instancedirectory + "/config.ini", "[path]\r\n\ +var instancedirectory = './instances/' + instance; +if (!fs.existsSync(instancedirectory)) { + fs.mkdirSync(instancedirectory); + fs.mkdirSync(instancedirectory + "/script-output/"); + fs.writeFileSync(instancedirectory + "/script-output/output.txt", "") + fs.writeFileSync(instancedirectory + "/script-output/orders.txt", "") + fs.writeFileSync(instancedirectory + "/script-output/txbuffer.txt", "") + fs.mkdirSync(instancedirectory + "/mods/") + fs.symlinkSync('../../../clusterio_0.0.3', instancedirectory + "/mods/clusterio_0.0.3", 'junction') + fs.writeFileSync(instancedirectory + "/config.ini", "[path]\r\n\ read-data=__PATH__executable__\\..\\..\\data\r\n\ -write-data=__PATH__executable__\\..\\..\\..\\instances\\"+instance+"\r\n\ +write-data=__PATH__executable__\\..\\..\\..\\instances\\" + instance + "\r\n\ "); var instconf = { - "factorioPort": Math.floor(Math.random()*65535), - "clientPort": Math.floor(Math.random()*65535), + "factorioPort": Math.floor(Math.random() * 65535), + "clientPort": Math.floor(Math.random() * 65535), "clientPassword": Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 8), } console.log(instconf) fs.writeFileSync(instancedirectory + "/config.json", JSON.stringify(instconf, null, 4)); var serversettings = { - "name": config.username +"'s clusterio "+instance, + "name": config.username + "'s clusterio " + instance, "description": config.description, "tags": ["clusterio"], "max_players": "20", @@ -45,60 +45,57 @@ write-data=__PATH__executable__\\..\\..\\..\\instances\\"+instance+"\r\n\ "token": config.usertoken, "game_password": config.game_password, "verify_user_identity": config.verify_user_identity, - "admins":[config.username], - "allow_commands":config.allow_commands, - "autosave_interval":10, - "autosave_slots":5, - "afk_autokick_interval":0, - "auto_pause":config.auto_pause + "admins": [config.username], + "allow_commands": config.allow_commands, + "autosave_interval": 10, + "autosave_slots": 5, + "afk_autokick_interval": 0, + "auto_pause": config.auto_pause } fs.writeFileSync(instancedirectory + "/server-settings.json", JSON.stringify(serversettings, null, 4)); var createSave = child_process.spawnSync( - './' + config.factorioDirectory + '/bin/x64/factorio.exe', - [ - '-c',instancedirectory+'/config.ini', - '--create',instancedirectory+'/save.zip', + './' + config.factorioDirectory + '/bin/x64/factorio.exe', [ + '-c', instancedirectory + '/config.ini', + '--create', instancedirectory + '/save.zip', ] ) } -var instanceconfig = require(instancedirectory+'/config'); +var instanceconfig = require(instancedirectory + '/config'); -process.on('SIGINT', function() { - console.log("Caught interrupt signal"); - //serverprocess.stdin.write('/quit') +process.on('SIGINT', function () { + console.log("Caught interrupt signal"); + //serverprocess.stdin.write('/quit') }); //var serverprocess = child_process.exec(commandline) var serverprocess = child_process.spawn( - './' + config.factorioDirectory + '/bin/x64/factorio.exe', - [ - '-c',instancedirectory+'/config.ini', - '--start-server',instancedirectory+'/save.zip', - '--rcon-port',instanceconfig.clientPort, - '--rcon-password',instanceconfig.clientPassword, - '--server-settings',instancedirectory+'/server-settings.json', - '--port',instanceconfig.factorioPort - ], - { - 'stdio':['pipe','pipe','pipe'] - } + './' + config.factorioDirectory + '/bin/x64/factorio.exe', [ + '-c', instancedirectory + '/config.ini', + '--start-server', instancedirectory + '/save.zip', + '--rcon-port', instanceconfig.clientPort, + '--rcon-password', instanceconfig.clientPassword, + '--server-settings', instancedirectory + '/server-settings.json', + '--port', instanceconfig.factorioPort + ], { + 'stdio': ['pipe', 'pipe', 'pipe'] + } ) serverprocess.on('close', (code) => { - console.log(`child process exited with code ${code}`); - process.exit(); + console.log(`child process exited with code ${code}`); + process.exit(); }); serverprocess.stdout.on('data', (chunk) => { - console.log('OUT: '+chunk); + console.log('OUT: ' + chunk); }) serverprocess.stderr.on('data', (chunk) => { - console.log('ERR: '+chunk); + console.log('ERR: ' + chunk); }) // connect us to the server with rcon @@ -113,14 +110,16 @@ var client = new Rcon({ // wait a few seconds to let the server finish starting before connecting rcon //TODO: catch '2.033 Info RemoteCommandProcessor.cpp:97: Starting RCON interface at port 35002' from stdout maybe? -setTimeout(() => { client.connect(); }, 5000); +setTimeout(() => { + client.connect(); +}, 5000); -client.on('authenticated', function() { +client.on('authenticated', function () { console.log('Authenticated!'); -}).on('connected', function() { +}).on('connected', function () { console.log('Connected!'); getID(); -}).on('disconnected', function() { +}).on('disconnected', function () { console.log('Disconnected!'); // now reconnect client.connect(); @@ -133,118 +132,134 @@ lastSignalCheck = Date.now(); // world IDs ------------------------------------------------------------------ function getID() { var payload = { - time : Date.now(), - rconPort : instanceconfig.clientPort, - rconPassword : instanceconfig.clientPassword, - serverPort : instanceconfig.factorioPort, - unique : instanceconfig.clientPassword.hashCode() + time: Date.now(), + rconPort: instanceconfig.clientPort, + rconPassword: instanceconfig.clientPassword, + serverPort: instanceconfig.factorioPort, + unique: instanceconfig.clientPassword.hashCode() } - require('getmac').getMac(function(err,mac){ + require('getmac').getMac(function (err, mac) { if (err) throw err payload.mac = mac console.log(payload) - needle.post(config.masterIP + ":" + config.masterPort + '/getID', payload, function(err, response, body){ - if(response && response.body) { + needle.post(config.masterIP + ":" + config.masterPort + '/getID', payload, function (err, response, body) { + if (response && response.body) { // In the future we might be interested in whether or not we actually manage to send it, but honestly I don't care. console.log(response.body) } - } ); + }); }) - + } setInterval(getID, 10000) -// provide items -------------------------------------------------------------- -// trigger when something happens to output.txt -fs.watch(instancedirectory + "/script-output/output.txt", function(eventType, filename) { - // get array of lines in file - items = fs.readFileSync(instancedirectory + "/script-output/output.txt", "utf8").split("\n"); - // if you found anything, reset the file - if(items[0]) { - fs.writeFileSync(instancedirectory + "/script-output/output.txt", "") - } - for(i = 0;i < items.length; i++) { - if(items[i]) { - g = items[i].split(" "); - g[0] = g[0].replace("\u0000", ""); - // console.log("exporting " + JSON.stringify(g)); - // send our entity and count to the master for him to keep track of - needle.post(config.masterIP + ":" + config.masterPort + '/place', {name:g[0], count:g[1]}, - function(err, resp, body){ - // console.log(body); - }); + // provide items -------------------------------------------------------------- + // trigger when something happens to output.txt +fs.watch(instancedirectory + "/script-output/output.txt", function (eventType, filename) { + // get array of lines in file + items = fs.readFileSync(instancedirectory + "/script-output/output.txt", "utf8").split("\n"); + // if you found anything, reset the file + if (items[0]) { + fs.writeFileSync(instancedirectory + "/script-output/output.txt", "") } - } -}) -// request items -------------------------------------------------------------- -setInterval(function() { - // get array of lines in file - items = fs.readFileSync(instancedirectory + "/script-output/orders.txt", "utf8").split("\n"); - // if we actually got anything from the file, proceed and reset file - if(items[0]) { - fs.writeFileSync(instancedirectory + "/script-output/orders.txt", ""); - // prepare a package of all our requested items in a more tranfer friendly format - var preparedPackage = {}; - for(i = 0;i < items.length; i++) { - (function(i){ - if(items[i]) { - items[i] = items[i].split(" "); - items[i][0] = items[i][0].replace("\u0000", ""); - items[i][0] = items[i][0].replace(",", ""); - if(preparedPackage[items[i][0]]){ - if(typeof Number(preparedPackage[items[i][0]].count) == "number" && typeof Number(items[i][1]) == "number") { - preparedPackage[items[i][0]] = {"name":items[i][0], "count":Number(preparedPackage[items[i][0]].count) + Number(items[i][1])}; - } else if (typeof Number(items[i][1]) == "number") { - preparedPackage[items[i][0]] = {"name":items[i][0], "count":Number(items[i][1])}; - } - } else if (typeof Number(items[i][1]) == "number") { - preparedPackage[items[i][0]] = {"name":items[i][0], "count":Number(items[i][1])}; - } - } - })(i); - } - // request our items, one item at a time - for(i = 0;i Date: Wed, 21 Dec 2016 14:08:21 +0100 Subject: [PATCH 06/11] Added list and delete commands to client.js for managing instances client.js list client.js delete [instance] also adde --help to show usage --- client.js | 45 +++++++++++++++++++++++++++++++++++++++++++-- package.json | 3 ++- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/client.js b/client.js index 425fcba4..a0e3f784 100644 --- a/client.js +++ b/client.js @@ -1,20 +1,61 @@ var fs = require('fs'); var needle = require("needle"); var child_process = require('child_process'); +var path = require('path') // require config.json var config = require('./config'); var instance = process.argv[2]; -if (!instance) { - console.error("Usage: node client.js [instance name]") +if (!instance || instance == "help" || instance == "--help") { + console.error("Usage: ") + console.error("node client.js [instance name]") + console.error("node client.js list") + console.error("node client.js delete [instance]") process.exit(1) } +if (process.argv[2] == "list") { + console.dir(getDirectories("./instances/")); + process.exit(1) +} +var deleteFolderRecursive = function (path) { + if (fs.existsSync(path)) { + fs.readdirSync(path).forEach(function (file, index) { + var curPath = path + "/" + file; + if (fs.lstatSync(curPath).isDirectory()) { // recurse + deleteFolderRecursive(curPath); + } else { // delete file + fs.unlinkSync(curPath); + } + }); + fs.rmdirSync(path); + } +}; +if (process.argv[2] == "delete") { + if (!process.argv[3]) { + console.error("Usage: node client.js delete [instance]"); + process.exit(1) + } else if (typeof process.argv[3] == "string" && fs.existsSync("./instances/"+process.argv[3]) && process.argv[3] != "/" && process.argv[3] != "") { + deleteFolderRecursive("./instances/"+process.argv[3]); + console.log("Deleted instance " + process.argv[3]) + process.exit(1) + } else { + console.error("Instance not found: " + process.argv[3]); + process.exit(1) + } +} +function getDirectories(srcpath) { + return fs.readdirSync(srcpath).filter(function (file) { + return fs.statSync(path.join(srcpath, file)).isDirectory(); + }); +} if (!fs.existsSync("./instances/")) { fs.mkdirSync("instances"); } var instancedirectory = './instances/' + instance; +// if instance does not exist, create it if (!fs.existsSync(instancedirectory)) { + console.log("Creating instance...") fs.mkdirSync(instancedirectory); fs.mkdirSync(instancedirectory + "/script-output/"); fs.writeFileSync(instancedirectory + "/script-output/output.txt", "") diff --git a/package.json b/package.json index 9d8c3ff9..829c3e21 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "Factorio cluster???", "main": "master.js", "scripts": { - "test": "nodemon master.js" + "test": "nodemon master.js", + "start": "echo Run node client.js [instance] to start slaves && node master.js" }, "keywords": [ "factorio" From ba05b14e6fa5115c8395874f4c97dea25289b9be Mon Sep 17 00:00:00 2001 From: Danielv123 Date: Wed, 21 Dec 2016 14:16:29 +0100 Subject: [PATCH 07/11] Maintainability, avoid bugs when not exiting after special commands --- client.js | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/client.js b/client.js index a0e3f784..ff307a6e 100644 --- a/client.js +++ b/client.js @@ -5,19 +5,7 @@ var path = require('path') // require config.json var config = require('./config'); - -var instance = process.argv[2]; -if (!instance || instance == "help" || instance == "--help") { - console.error("Usage: ") - console.error("node client.js [instance name]") - console.error("node client.js list") - console.error("node client.js delete [instance]") - process.exit(1) -} -if (process.argv[2] == "list") { - console.dir(getDirectories("./instances/")); - process.exit(1) -} +// Functions var deleteFolderRecursive = function (path) { if (fs.existsSync(path)) { fs.readdirSync(path).forEach(function (file, index) { @@ -31,7 +19,28 @@ var deleteFolderRecursive = function (path) { fs.rmdirSync(path); } }; -if (process.argv[2] == "delete") { +function getDirectories(srcpath) { + return fs.readdirSync(srcpath).filter(function (file) { + return fs.statSync(path.join(srcpath, file)).isDirectory(); + }); +} +if (!fs.existsSync("./instances/")) { + fs.mkdirSync("instances"); +} +var instance = process.argv[2]; +var instancedirectory = './instances/' + instance; + +// handle commandline parameters +if (!instance || instance == "help" || instance == "--help") { + console.error("Usage: ") + console.error("node client.js [instance name]") + console.error("node client.js list") + console.error("node client.js delete [instance]") + process.exit(1) +} else if (process.argv[2] == "list") { + console.dir(getDirectories("./instances/")); + process.exit(1) +} else if (process.argv[2] == "delete") { if (!process.argv[3]) { console.error("Usage: node client.js delete [instance]"); process.exit(1) @@ -43,18 +52,8 @@ if (process.argv[2] == "delete") { console.error("Instance not found: " + process.argv[3]); process.exit(1) } -} -function getDirectories(srcpath) { - return fs.readdirSync(srcpath).filter(function (file) { - return fs.statSync(path.join(srcpath, file)).isDirectory(); - }); -} -if (!fs.existsSync("./instances/")) { - fs.mkdirSync("instances"); -} -var instancedirectory = './instances/' + instance; -// if instance does not exist, create it -if (!fs.existsSync(instancedirectory)) { +} else if (!fs.existsSync(instancedirectory)) { + // if instance does not exist, create it console.log("Creating instance...") fs.mkdirSync(instancedirectory); fs.mkdirSync(instancedirectory + "/script-output/"); @@ -101,6 +100,7 @@ write-data=__PATH__executable__\\..\\..\\..\\instances\\" + instance + "\r\n\ '--create', instancedirectory + '/save.zip', ] ) + console.log("Instance created!") } var instanceconfig = require(instancedirectory + '/config'); From cb77717650421b5a0cdf55866c6a27abc3d25ff0 Mon Sep 17 00:00:00 2001 From: Danielv123 Date: Wed, 21 Dec 2016 14:33:34 +0100 Subject: [PATCH 08/11] Starting instances now require "start" as second param, instance 3rd --- client.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/client.js b/client.js index ff307a6e..f5923a50 100644 --- a/client.js +++ b/client.js @@ -27,20 +27,20 @@ function getDirectories(srcpath) { if (!fs.existsSync("./instances/")) { fs.mkdirSync("instances"); } -var instance = process.argv[2]; +var instance = process.argv[3]; var instancedirectory = './instances/' + instance; - +var command = process.argv[2]; // handle commandline parameters -if (!instance || instance == "help" || instance == "--help") { +if (!command || command == "help" || command == "--help") { console.error("Usage: ") - console.error("node client.js [instance name]") + console.error("node client.js start [instance name]") console.error("node client.js list") console.error("node client.js delete [instance]") process.exit(1) -} else if (process.argv[2] == "list") { +} else if (command == "list") { console.dir(getDirectories("./instances/")); process.exit(1) -} else if (process.argv[2] == "delete") { +} else if (command == "delete") { if (!process.argv[3]) { console.error("Usage: node client.js delete [instance]"); process.exit(1) @@ -52,7 +52,7 @@ if (!instance || instance == "help" || instance == "--help") { console.error("Instance not found: " + process.argv[3]); process.exit(1) } -} else if (!fs.existsSync(instancedirectory)) { +} else if (command == "start" && typeof instance == "string" && instance != "/" && !fs.existsSync(instancedirectory)) { // if instance does not exist, create it console.log("Creating instance...") fs.mkdirSync(instancedirectory); From aac101bad74afe79213b4820c784aa7222c54895 Mon Sep 17 00:00:00 2001 From: Danielv123 Date: Wed, 21 Dec 2016 14:40:43 +0100 Subject: [PATCH 09/11] prettify --- client.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client.js b/client.js index f5923a50..ea5c0bac 100644 --- a/client.js +++ b/client.js @@ -19,6 +19,7 @@ var deleteFolderRecursive = function (path) { fs.rmdirSync(path); } }; + function getDirectories(srcpath) { return fs.readdirSync(srcpath).filter(function (file) { return fs.statSync(path.join(srcpath, file)).isDirectory(); @@ -44,8 +45,8 @@ if (!command || command == "help" || command == "--help") { if (!process.argv[3]) { console.error("Usage: node client.js delete [instance]"); process.exit(1) - } else if (typeof process.argv[3] == "string" && fs.existsSync("./instances/"+process.argv[3]) && process.argv[3] != "/" && process.argv[3] != "") { - deleteFolderRecursive("./instances/"+process.argv[3]); + } else if (typeof process.argv[3] == "string" && fs.existsSync("./instances/" + process.argv[3]) && process.argv[3] != "/" && process.argv[3] != "") { + deleteFolderRecursive("./instances/" + process.argv[3]); console.log("Deleted instance " + process.argv[3]) process.exit(1) } else { @@ -190,7 +191,6 @@ function getID() { } }); }) - } setInterval(getID, 10000) // provide items -------------------------------------------------------------- From af92716c7754de73ecb16b6d1acf6e9611116158 Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 22 Dec 2016 16:09:20 +0100 Subject: [PATCH 10/11] Ubuntu install instructions added --- README.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2a05b561..2d03c6d4 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ There are no requirements for other mods, they can be ran in any configuration a You can change the name and path expected in config.json if wanted. -3. node client.js [instancename] +3. node client.js start [instancename] Repeat step 3 for more servers on one machine. You should be able to find its port by looking at the console output or at the slave section on master:8080 @@ -59,3 +59,25 @@ Repeat step 3 for more servers on one machine. You should be able to find its po 2. Drop it into ./factorio/mods 3. Run factorio and connect to slave as a normal MP game. + +#Ubuntu setup + +Master and all slaves: + + sudo curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash - && sudo apt install -y git nodejs && git clone https://github.com/Danielv123/factorioClusterio.git && cd factorioClusterio && npm install + +downloads and installs nodejs, git and clusterio. + +**Master** + + node master.js + +**Slave** + +Download factorio with curl. Make sure to insert the correct version number. + +Start the slave with node client.js + + curl -o factorio.tar.gz -L https://www.factorio.com/get-download/0.14.21/headless/linux64 && tar -xvzf factorio.tar.gz + + node client.js start [instancename] From ace440dbef7d4bb19c349832b2e27e91e8dc6da6 Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 22 Dec 2016 16:21:14 +0100 Subject: [PATCH 11/11] Removed .exe to allow launching on linuxes --- client.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client.js b/client.js index ea5c0bac..5d35369e 100644 --- a/client.js +++ b/client.js @@ -96,7 +96,7 @@ write-data=__PATH__executable__\\..\\..\\..\\instances\\" + instance + "\r\n\ fs.writeFileSync(instancedirectory + "/server-settings.json", JSON.stringify(serversettings, null, 4)); var createSave = child_process.spawnSync( - './' + config.factorioDirectory + '/bin/x64/factorio.exe', [ + './' + config.factorioDirectory + '/bin/x64/factorio', [ '-c', instancedirectory + '/config.ini', '--create', instancedirectory + '/save.zip', ] @@ -115,7 +115,7 @@ process.on('SIGINT', function () { //var serverprocess = child_process.exec(commandline) var serverprocess = child_process.spawn( - './' + config.factorioDirectory + '/bin/x64/factorio.exe', [ + './' + config.factorioDirectory + '/bin/x64/factorio', [ '-c', instancedirectory + '/config.ini', '--start-server', instancedirectory + '/save.zip', '--rcon-port', instanceconfig.clientPort, @@ -350,4 +350,4 @@ String.prototype.hashCode = function () { hash = hash & hash; // Convert to 32bit integer } return hash; -} \ No newline at end of file +}