From 44b68c92d53b538694111f5b78e294046b1a44b7 Mon Sep 17 00:00:00 2001 From: Danielv123 Date: Sun, 10 Dec 2017 11:27:02 +0100 Subject: [PATCH] Big changes to plugin system, fixed inventoryImports --- client.js | 156 ++++++++++++++--------- sharedPlugins/inventoryImports/config.js | 2 +- sharedPlugins/inventoryImports/index.js | 43 +++---- 3 files changed, 114 insertions(+), 87 deletions(-) diff --git a/client.js b/client.js index 5d508f35..91e9ad9e 100644 --- a/client.js +++ b/client.js @@ -415,74 +415,104 @@ function instanceManagement() { let plugins = []; for(let i=0; i { - if(data.toString('utf8')[0] != "/") { - log("Stdout: " + data.toString('utf8')) - } else { - messageInterface(data.toString('utf8')); + let pluginConfig = require("./sharedPlugins/" + pluginDirectories[i] + "/config.js"); + if(pluginConfig.binary == "nodePackage"){ + // require index.js.main() of plugin and execute it as a function + let pluginClass = require("./sharedPlugins/" + pluginDirectories[I] + "/index.js"); + plugins[I] = new pluginClass(combinedConfig, function(data){ + if(data.toString('utf8')[0] != "/") { + log("Stdout: " + data.toString('utf8')); + } else { + messageInterface(data.toString('utf8')); + } + }); + if(pluginConfig.scriptOutputFileSubscription && typeof pluginConfig.scriptOutputFileSubscription == "string"){ + fs.watch(instancedirectory + "/script-output/" + pluginConfig.scriptOutputFileSubscription, function (eventType, filename) { + // get array of lines in file + let stuff = fs.readFileSync(instancedirectory + "/script-output/" + filename, "utf8").split("\n"); + // if you found anything, reset the file + if (stuff[0]) { + fs.writeFileSync(instancedirectory + "/script-output/" + filename, ""); + } + for (let i = 0; i < stuff.length; i++) { + if (stuff[i]) { + plugins[I].scriptOutput(stuff[i]); + } + } + }); } - }); - plugins[i].stderr.on("data", (data) => { - log("STDERR: " + data); - }); - plugins[i].on('close', (code) => { - log(`child process exited with code ${code}`); - }); + console.log("Clusterio | Loaded plugin " + pluginDirectories[i]); + } else if(pluginConfig.binary != "nodePackage"){ + // handle as fragile executable plugin + let args = pluginConfig.args || []; + plugins[I]=child_process.spawn(pluginConfig.binary, args, { + cwd: "./sharedPlugins/"+pluginDirectories[i], + stdio: ['pipe', 'pipe', 'pipe'], + }); + + /* + to send to stdin, use: + spawn.stdin.write("text\n"); + */ + + if(!global.subscribedFiles) { + global.subscribedFiles = {}; + } + // If plugin has subscribed to a file, send any text appearing in that file to stdin + if(pluginConfig.scriptOutputFileSubscription && typeof pluginConfig.scriptOutputFileSubscription == "string") { + if(global.subscribedFiles[pluginConfig.scriptOutputFileSubscription]) { + // please choose a unique file to subscribe to. If you need plugins to share this interface, set up a direct communication + // between those plugins instead. + throw "FATAL ERROR IN " + pluginDirectories[i] + " FILE ALREADY SUBSCRIBED " + pluginConfig.scriptOutputFileSubscription; + } + + if (!fs.existsSync(instancedirectory + "/script-output/" + pluginConfig.scriptOutputFileSubscription)) { + // Do something + fs.writeFileSync(instancedirectory + "/script-output/" + pluginConfig.scriptOutputFileSubscription, ""); + } + global.subscribedFiles[pluginConfig.scriptOutputFileSubscription] = true; + fs.watch(instancedirectory + "/script-output/" + pluginConfig.scriptOutputFileSubscription, function (eventType, filename) { + // get array of lines in file + let stuff = fs.readFileSync(instancedirectory + "/script-output/" + filename, "utf8").split("\n"); + // if you found anything, reset the file + if (stuff[0]) { + fs.writeFileSync(instancedirectory + "/script-output/" + filename, ""); + } + for (let i = 0; i < stuff.length; i++) { + if (stuff[i]) { + plugins[I].stdin.write(stuff[i]); + } + } + }); + } + // these are our two config files. We need to send these in case plugin + // wants to contact master or know something. + // send through script-output file, maybe more compat? + fs.writeFileSync(instancedirectory + "/script-output/" + pluginConfig.scriptOutputFileSubscription, JSON.stringify(combinedConfig)+"\r\n"); + // send directly through stdin + // plugins[i].stdin.write(JSON.stringify(combinedConfig)+"\n"); + + console.log("Clusterio | Loaded plugin " + pluginDirectories[i]); + plugins[i].stdout.on("data", (data) => { + if(data.toString('utf8')[0] != "/") { + log("Stdout: " + data.toString('utf8')) + } else { + messageInterface(data.toString('utf8')); + } + }); + plugins[i].stderr.on("data", (data) => { + log("STDERR: " + data); + }); + plugins[i].on('close', (code) => { + log(`child process exited with code ${code}`); + }); + } } // world IDs ------------------------------------------------------------------ diff --git a/sharedPlugins/inventoryImports/config.js b/sharedPlugins/inventoryImports/config.js index 4f49d047..9b2258cf 100644 --- a/sharedPlugins/inventoryImports/config.js +++ b/sharedPlugins/inventoryImports/config.js @@ -12,7 +12,7 @@ module.exports = { version: "1.0.0", // Binary entrypoint for plugin. Don't let it crash. Stdout is sent to game as server chat (run /c commands from here for interface) // Make sure its cross platform somehow. - binary: "node", + binary: "nodePackage", arguments: ["index.js"], description: "Clusterio plugin to fill character logistic slots with master imports", // We'll send everything in this file to your stdin. Beware. diff --git a/sharedPlugins/inventoryImports/index.js b/sharedPlugins/inventoryImports/index.js index dbf5e216..ebec81df 100644 --- a/sharedPlugins/inventoryImports/index.js +++ b/sharedPlugins/inventoryImports/index.js @@ -4,27 +4,24 @@ const pluginConfig = require("./config.js"); const functions = require("./interfacingFunctions"); -console.log("/silent-command game.print('InventoryImports enabled')"); - -var config = {}; -process.stdin.setEncoding('utf8'); -process.stdin.on('readable', () => { - var chunk = process.stdin.read(); - // console.log(chunk) - if (chunk !== null && isNaN(chunk) && config && isJson(chunk) && !JSON.parse(chunk).factorioPort){ - let inventory = JSON.parse(chunk) - // process inventory of players and ask master for more stuff - functions.handleInventory(inventory, config, console.log); - } else if(isJson(chunk) && JSON.parse(chunk).factorioPort){ - config = JSON.parse(chunk); - } -}); -process.stdin.on('end', () => { - process.stdout.write('end'); -}); - // poll inventories -setInterval(function(){ - // console.log("Polling inventories\n") - console.log(functions.pollInventories(pluginConfig.scriptOutputFileSubscription)); -}, 10000); + +class inventoryImports { + constructor(slaveConfig, messageInterface){ + this.config = slaveConfig; + this.messageInterface = messageInterface; + messageInterface("/silent-command game.print('InventoryImports enabled')"); + setInterval(function(){ + messageInterface("Polling inventories\n") + messageInterface(functions.pollInventories(pluginConfig.scriptOutputFileSubscription)); + }, 10000); + } + scriptOutput(data){ + if(data !== null && isJson(data)){ + let inventory = JSON.parse(data); + // process inventory of players and ask master for more stuff + functions.handleInventory(inventory, this.config, this.messageInterface); + } + } +} +module.exports = inventoryImports; \ No newline at end of file