diff --git a/CHANGELOG.md b/CHANGELOG.md index f0b64fc8..8074d6fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -98,6 +98,8 @@ Version 2.0.0 - Removed the hello event from the socket connection handshake. Breaks playerManager, trainTeleports, serverSelect, and discordChat - Changed the format of database/slaves.json. +- Removed the output file subscription system. Breaks inventoryImports, + playerManager, trainTeleports, serverSelect and researchSync. Version 1.2.4 diff --git a/client.js b/client.js index d533b5a2..f7bfbe45 100644 --- a/client.js +++ b/client.js @@ -1,27 +1,15 @@ const fs = require('fs-extra'); -const Tail = require('tail').Tail; -const needle = require("needle"); -const child_process = require('child_process'); const path = require('path'); -const request = require("request"); -const deepmerge = require("deepmerge"); -const ioClient = require("socket.io-client"); -const util = require("util"); const yargs = require("yargs"); const version = require("./package").version; // internal libraries -const objectOps = require("lib/objectOps"); const fileOps = require("lib/fileOps"); -const pluginManager = require("lib/manager/pluginManager"); const hashFile = require('lib/hash').hashFile; const factorio = require("lib/factorio"); -const schema = require("lib/schema"); const link = require("lib/link"); const errors = require("lib/errors"); -// Uhm... -var global = {}; /** * Keeps track of the runtime parameters of an instance @@ -186,7 +174,6 @@ class Instance extends link.Link{ clientPort: this.server.rconPort, clientPassword: this.server.rconPassword, } - //instanceManagement(slaveConfig, this, compatConfig, this.server, socket); // XXX async function }); await this.server.start(saveName); @@ -739,130 +726,6 @@ async function startClient() { */ } -// ensure instancemanagement only ever runs once -var _instanceInitialized; -async function instanceManagement(slaveConfig, instance, instanceconfig, server, socket) { - if (_instanceInitialized) return; - _instanceInitialized = true; - - let compatUrl = slaveConfig.masterUrl; - if (compatUrl.endsWith("/")) { - compatUrl = compatUrl.slice(0, -1); - } - let compatConfig = { - name: slaveConfig.name, - masterURL: compatUrl, - masterAuthToken: slaveConfig.masterToken, - publicIP: slaveConfig.publicAddress, - instanceDirectory: slaveConfig.instancesDir, - factorioDirectory: slaveConfig.factorioDir, - } - - console.log("Started instanceManagement();"); - - // load plugins and execute onLoad event - let pluginsToLoad = await pluginManager.getPlugins(); - let plugins = []; - - for(let i = 0; i < pluginsToLoad.length; i++){ - let pluginLoadStarted = Date.now(); - let combinedConfig = deepmerge(instanceconfig,compatConfig,{clone:true}); - combinedConfig.instanceName = instance.name; - let pluginConfig = pluginsToLoad[i]; - - if(!global.subscribedFiles) { - global.subscribedFiles = {}; - } - if (pluginConfig.enabled) { - // require plugin class and execute it - let pluginClass = require(path.resolve(pluginConfig.pluginPath, "index")); - plugins[i] = new pluginClass(combinedConfig, async function(data, callback){ - if(data && data.toString('utf8')[0] != "/") { - console.log("Clusterio | "+ pluginsToLoad[i].name + " | " + data.toString('utf8')); - return true; - } else if (data && data.toString('utf8')[0] == "/"){ - let result = await server.sendRcon(data.toString('utf8')); - if (typeof callback === "function") { - callback(result); - } - return result; - } - }, { // extra functions to pass in object. Should have done it like this from the start, but won't break backwards compat. - socket, // socket.io connection to master (and ES6 destructuring, yay) - }); - if(plugins[i].factorioOutput && typeof plugins[i].factorioOutput === "function"){ - // when factorio logs a line, send it to the plugin. This includes things like autosaves, chat, errors etc - server.on('stdout', data => plugins[i].factorioOutput(data.toString())); - } - 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 " + pluginConfig.name + " FILE ALREADY SUBSCRIBED " + pluginConfig.scriptOutputFileSubscription; - } - - let outputPath = instance.path( - "script-output", - pluginConfig.scriptOutputFileSubscription - ); - if (!fs.existsSync(outputPath)) { - // Do something - fs.writeFileSync(outputPath, ""); - } - global.subscribedFiles[pluginConfig.scriptOutputFileSubscription] = true; - console.log("Clusterio | Registered file subscription on "+outputPath); - - - if(!pluginConfig.fileReadDelay || pluginConfig.fileReadDelay == 0) { - // only wipe the file on restart for now, should most likely be rotated during runtime too - fs.writeFileSync(outputPath, ""); - let tail = new Tail(outputPath); - tail.on("line", function (data) { - plugins[i].scriptOutput(data); - }); - } else { - fs.watch(outputPath, fileChangeHandler); - // run once in case a plugin wrote out information before the plugin loaded fully - // delay, so the socket got enough time to connect - setTimeout(() => { - fileChangeHandler(false, pluginConfig.scriptOutputFileSubscription); - }, 500); - - // send file contents to plugin for processing - function fileChangeHandler(eventType, filename) { - if (filename != null) { - setTimeout( - () => { - // get array of lines in file - let stuff = fs.readFileSync(instance.path("script-output", filename), "utf8").split("\n"); - - // if you found anything, reset the file - if (stuff[0]) { - fs.writeFileSync(instance.path("script-output", filename), ""); - } - for (let o = 0; o < stuff.length; o++) { - if (stuff[o] && !stuff[o].includes('\u0000\u0000')) { - try { - plugins[i].scriptOutput(stuff[o]); - } catch (e) { - console.error(e) - } - } - } - }, - pluginConfig.fileReadDelay || 0 - ); - } - } - } - } - console.log(`Clusterio | Loaded plugin ${pluginsToLoad[i].name} in ${Date.now() - pluginLoadStarted}ms`); - } else { - // this plugin doesn't have a client portion. Maybe it runs on the master only? - } - } -} // END OF INSTANCE START --------------------------------------------------------------------- - // string, function // returns [{modName:string,hash:string}, ... ] function hashMods(instance, callback) { diff --git a/lib/manager/pluginManager.js b/lib/manager/pluginManager.js deleted file mode 100644 index f0d03ca3..00000000 --- a/lib/manager/pluginManager.js +++ /dev/null @@ -1,125 +0,0 @@ -const fs = require("fs-extra"); -const path = require("path"); -const git = require("simple-git")("./sharedPlugins"); - - -async function listPlugins() { - let plugins = await this.getPlugins(); - plugins.forEach(plug => { - console.log(`${plug.name}`.padEnd(22).substr(0,22)+` - ${plug.description}`.substr(0,80-22)); - }); -} - -async function getPlugins() { - let directories = await fs.readdir("./sharedPlugins"); - let returnArray = []; - for(let i in directories){ - let dir = directories[i]; - let pluginContents = await fs.readdir(path.join("./sharedPlugins", dir)); - // console.log(pluginContents) - if(pluginContents.includes("config.js") || pluginContents.includes("config.json")){ - try{ - var pluginConfig = require(path.join("./../../sharedPlugins", dir, "config")); - pluginConfig.pluginPath = path.join("./sharedPlugins", dir); - }catch(e){ - console.log(e) - } - - // check if plugin is enabled - try{ - await fs.stat(path.join(pluginConfig.pluginPath, "DISABLED")) - pluginConfig.enabled = false; - }catch(e){ - pluginConfig.enabled = true; - } - returnArray.push(pluginConfig); - } - } - return returnArray; -} - -function addPlugin(path) { - return new Promise((resolve, reject) => { - if(path.includes("git")){ // we are decently sure this is a git repo - git.clone(path, data => resolve(data)) - } - }); -} - -async function removePlugin(name) { - let plugins = await this.getPlugins(); - for(let i in plugins){ - let plug = plugins[i]; - if(plug.name.includes(name)){ - // console.log(`Removing plugin ${plug.name}`); - await fs.remove(plug.pluginPath); - return { - ok:true, - msg:`Deleted plugin ${plug.name}` - } - } - } - return { - ok:false, - msg:`Plugin matching "${name}" not found`, - } -} - -async function enablePlugin(name, instance) { - let plugins = await this.getPlugins(); - let plugin = plugins[findInArray("name", name, plugins)[0]]; - if(plugin){ - let files = await fs.readdir(plugin.pluginPath); - if(files.includes("DISABLED")){ - await fs.unlink(path.join(plugin.pluginPath, "DISABLED")); - return { - ok:true, - msg:`Globally enabled plugin ${name}`, - } - } else { - return { - ok:true, - msg:`Plugin ${name} already enabled`, - } - } - } else { - return { - ok:false, - msg:`Found no excact match for plugin ${name}`, - } - } -} - -async function disablePlugin(name, instance) { - let plugins = await this.getPlugins(); - let plugin = plugins[findInArray("name", name, plugins)[0]]; - if(plugin){ - await fs.writeFile(path.join(plugin.pluginPath, "DISABLED"), ""); - return { - ok:true, - msg:`Plugin ${name} is now disabled on this host`, - } - } else { - return { - ok:false, - msg:`Found no excact match for plugin ${name}`, - } - } -} - -function findInArray(key, value, array) { - let indexes = []; - for(let i in array){ - if(array[i][key] && array[i][key] === value) indexes.push(i); - } - return indexes; -} - -module.exports = { - listPlugins, - getPlugins, - addPlugin, - removePlugin, - enablePlugin, - disablePlugin, -}; diff --git a/master.js b/master.js index c2970929..593f7b88 100644 --- a/master.js +++ b/master.js @@ -32,7 +32,6 @@ let config = {}; // homebrew modules const generateSSLcert = require("lib/generateSSLcert"); -const pluginManager = require("lib/manager/pluginManager"); const database = require("lib/database"); const factorio = require("lib/factorio"); const schema = require("lib/schema"); @@ -502,46 +501,10 @@ io.on('connection', function (socket) { var masterPlugins = []; async function pluginManagement(){ let startPluginLoad = Date.now(); - masterPlugins = await getPlugins(); + // masterPlugins = await getPlugins(); console.log("All plugins loaded in "+(Date.now() - startPluginLoad)+"ms"); } -async function getPlugins(){ - let plugins = []; - let pluginsToLoad = await pluginManager.getPlugins(); - for(let i = 0; i < pluginsToLoad.length; i++){ - let pluginStartedLoading = Date.now(); // just for logging - let stats = await fs.stat(pluginsToLoad[i].pluginPath); - if(stats.isDirectory()){ - let pluginConfig = pluginsToLoad[i]; - if(pluginConfig.masterPlugin && pluginConfig.enabled){ - let masterPlugin = require(path.resolve(pluginConfig.pluginPath, pluginConfig.masterPlugin)); - plugins.push({ - main:new masterPlugin({ - config, - pluginConfig, - path: pluginConfig.pluginPath, - socketio: io, - express: app, - db, - Prometheus, - prometheusPrefix, - endpointHitCounter, - }), - pluginConfig, - }); - - console.log("Loaded plugin "+pluginConfig.name+" in "+(Date.now() - pluginStartedLoading)+"ms"); - } - } - } - for(let i in plugins){ - let plugin = plugins[i]; - if(plugin.main.onLoadFinish && typeof plugin.main.onLoadFinish == "function") await plugin.main.onLoadFinish({plugins}); - } - return plugins; -} - /** * Calls listen on server capturing any errors that occurs * binding to the port. diff --git a/package.json b/package.json index a56560de..85995813 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,6 @@ "socket.io-client": "^2.2.0", "socket.io-prometheus": "^0.2.1", "sync-request": "^4.0.1", - "tail": "^2.0.2", "typescript-collections": "^1.3.2", "yargs": "^14.2.0" }, diff --git a/test/missing.js b/test/missing.js index b93e9446..836dd6af 100644 --- a/test/missing.js +++ b/test/missing.js @@ -2,7 +2,6 @@ // required here in order to track coverage for them. require('lib/manager/modManager'); -require('lib/manager/pluginManager'); require('lib/npmPostinstall.js'); require('lib/typedef'); require('../clusterctl.js');