From 0927bec07047d775127ec55a86fcea35838499dd Mon Sep 17 00:00:00 2001 From: Thomas Deal Date: Sun, 23 Oct 2016 14:43:06 -0400 Subject: [PATCH] client.js now launches it's own server instance --- .gitignore | 4 +- client.js | 135 ++++++++++++++++++++++++++++++++++--------- config.json | 16 ++--- launchEverything.bat | 5 -- server-settings.json | 23 -------- 5 files changed, 117 insertions(+), 66 deletions(-) delete mode 100644 launchEverything.bat delete mode 100644 server-settings.json diff --git a/.gitignore b/.gitignore index c6f583e4..a9392b83 100644 --- a/.gitignore +++ b/.gitignore @@ -26,4 +26,6 @@ build/Release # Dependency directory # https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git node_modules -Factorio* \ No newline at end of file +Factorio* +/factorio +/instances diff --git a/client.js b/client.js index ef59cc74..567c943f 100644 --- a/client.js +++ b/client.js @@ -1,30 +1,111 @@ var fs = require('fs'); var needle = require("needle"); +var child_process = require('child_process'); + // require config.json var config = require('./config'); + +var instance = process.argv[2]; +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\ +"); + + var instconf = { + "factorioPort": "35001", + "clientPort": "35002", + "clientPassword": "clusterio" + } + fs.writeFileSync(instancedirectory + "/config.json", JSON.stringify(instconf, null, 4)); + + var serversettings = { + "name": config.username +"'s clusterio "+instance, + "description": "", + "tags": ["clusterio"], + "max_players": "20", + "visibility": "lan", + "username": config.username, + "token": config.usertoken, + "game_password": "", + "verify_user_identity": true, + "admins":[config.username], + "allow_commands":"admins-only", + "autosave_interval":10, + "autosave_slots":5, + "afk_autokick_interval":0, + "auto_pause":false + } + fs.writeFileSync(instancedirectory + "/server-settings.json", JSON.stringify(serversettings, null, 4)); + + var createSave = child_process.spawnSync( + './factorio/bin/x64/factorio.exe', + [ + '-c',instancedirectory+'/config.ini', + '--create',instancedirectory+'/save.zip', + ] + ) +} + +var instanceconfig = require(instancedirectory+'/config'); + + +process.on('SIGINT', function() { + console.log("Caught interrupt signal"); + //serverprocess.stdin.write('/quit') +}); + + +//var serverprocess = child_process.exec(commandline) +var serverprocess = child_process.spawn( + './factorio/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(); +}); + +serverprocess.stdout.on('data', (chunk) => { + console.log('OUT: '+chunk); +}) + +serverprocess.stderr.on('data', (chunk) => { + console.log('ERR: '+chunk); +}) + // connect us to the server with rcon // IP, port, password var Rcon = require('simple-rcon'); var client = new Rcon({ - host: config.clientIP, - port: config.clientPort, - password: config.clientPassword, + host: 'localhost', + port: instanceconfig.clientPort, + password: instanceconfig.clientPassword, timeout: 0 -}).connect(); +}); -if (!fs.existsSync(config.factorioDirectory)){ - console.error("FATAL ERROR: config.factorioDirectory DOES NOT EXIST, PLEASE UPDATE CONFIG.JSON"); - process.exit(1); -} -// make sure we got the files we need -if (!fs.existsSync(config.factorioDirectory + "/script-output/")){ - fs.mkdirSync(config.factorioDirectory + "/script-output/"); -} -if (!fs.existsSync(config.factorioDirectory + "/script-output/")){ - fs.writeFileSync(config.factorioDirectory + "/script-output/output.txt", "") -} -fs.writeFileSync(config.factorioDirectory + "/script-output/orders.txt", "") -fs.writeFileSync(config.factorioDirectory + "/script-output/txbuffer.txt", ""); +// 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); client.on('authenticated', function() { console.log('Authenticated!'); @@ -41,12 +122,12 @@ confirmedOrders = []; lastSignalCheck = Date.now(); // provide items -------------------------------------------------------------- // trigger when something happens to output.txt -fs.watch(config.factorioDirectory + "/script-output/output.txt", function(eventType, filename) { +fs.watch(instancedirectory + "/script-output/output.txt", function(eventType, filename) { // get array of lines in file - items = fs.readFileSync(config.factorioDirectory + "/script-output/output.txt", "utf8").split("\n"); + items = fs.readFileSync(instancedirectory + "/script-output/output.txt", "utf8").split("\n"); // if you found anything, reset the file if(items[0]) { - fs.writeFileSync(config.factorioDirectory + "/script-output/output.txt", "") + fs.writeFileSync(instancedirectory + "/script-output/output.txt", "") } for(i = 0;i < items.length; i++) { if(items[i]) { @@ -54,7 +135,7 @@ fs.watch(config.factorioDirectory + "/script-output/output.txt", function(eventT 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]}, + needle.post(config.masterIP + ":" + config.masterPort + '/place', {name:g[0], count:g[1]}, function(err, resp, body){ // console.log(body); }); @@ -64,10 +145,10 @@ fs.watch(config.factorioDirectory + "/script-output/output.txt", function(eventT // request items -------------------------------------------------------------- setInterval(function() { // get array of lines in file - items = fs.readFileSync(config.factorioDirectory + "/script-output/orders.txt", "utf8").split("\n"); + 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(config.factorioDirectory + "/script-output/orders.txt", ""); + 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++) { @@ -140,12 +221,12 @@ setInterval(function() { }); // after fetching all the latest frames, we take a timestamp. During the next iteration, we fetch all frames submitted after this. lastSignalCheck = Date.now(); - + // get array of lines in file, each line should correspond to a JSON encoded frame - signals = fs.readFileSync(config.factorioDirectory + "/script-output/txbuffer.txt", "utf8").split("\n"); + signals = fs.readFileSync(instancedirectory + "/script-output/txbuffer.txt", "utf8").split("\n"); // if we actually got anything from the file, proceed and reset file if(signals[0]) { - fs.writeFileSync(config.factorioDirectory + "/script-output/txbuffer.txt", ""); + fs.writeFileSync(instancedirectory + "/script-output/txbuffer.txt", ""); // loop through all our frames for(i = 0;i < signals.length; i++) { (function(i){ @@ -167,4 +248,4 @@ setInterval(function() { })(i); } } -}, 1000) \ No newline at end of file +}, 1000) diff --git a/config.json b/config.json index d3b3df82..8f7beb15 100644 --- a/config.json +++ b/config.json @@ -1,12 +1,8 @@ { - "__comment": "", - "__comment": "IP and port and password the factorio server runs at for rcon connection", - "clientIP": "localhost", - "clientPort": "12345", - "clientPassword": "123", - "__comment": "Where factorio folder. Should be in the same folder as this config file.", - "factorioDirectory": "factorio 0.13.9", - "__comment": "IP the master web server runs at, can be ignored on the master system", + "__comment": "IP and port for the clusterio master", "masterIP": "localhost", - "masterPort": 8080 -} \ No newline at end of file + "masterPort": 8080, + "__comment": "credentials for factorio MP services", + "username": "", + "usertoken": "" +} diff --git a/launchEverything.bat b/launchEverything.bat deleted file mode 100644 index f08a766e..00000000 --- a/launchEverything.bat +++ /dev/null @@ -1,5 +0,0 @@ -cd "Factorio_0.13.17" -@RD /S /Q "temp" -cd "bin/x64/" -start factorio.exe --start-server testmap.zip --rcon-port 12345 --rcon-password 123 --server-settings server-settings.json -pause \ No newline at end of file diff --git a/server-settings.json b/server-settings.json deleted file mode 100644 index 6e6009ff..00000000 --- a/server-settings.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "Name of the game as it will appear in the game listing", - "description": "Description of the game that will appear in the listing", - "tags": ["game", "tags"], - "max_players": "0", - - "_comment_visibility": ["public: Game will be published on the official Factorio matching server", - "lan: Game will be broadcast on LAN", - "hidden: Game will not be published anywhere"], - "visibility": "public", - - "_comment_credentials": "Your factorio.com login credentials. Required for games with visibility public", - "username": "", - "password": "", - - "_comment_token": "Authentication token. May be used instead of 'password' above.", - "token": "", - - "game_password": "", - - "_comment_verify_user_identity": "When set to true, the server will only allow clients that have a valid Factorio.com account", - "verify_user_identity": false -}