packages/slave/slave.js
/**
	 * Prepare a save for starting
	 *
	 * Creates a new save if no save is passed and patches it with modules.
	 *
	 * @param {String|null} saveName -
	 *     Save to prepare from the instance saves directory.  Creates a new
	 *     save if null.
	 * @returns {String} Name of the save prepared.
	 */
Prepare a save for starting
Creates a new save if no save is passed and patches it with modules.

@param {String|null} saveName
Save to prepare from the instance saves directory.  Creates a new
save if null.
@returns {String} Name of the save prepared.
Prepare a save for starting Creates a new save if no save is passed and patches it with modules . @param { String|null } saveName Save to prepare from the instance saves directory . Creates a new save if null . @returns { String } Name of the save prepared .
async prepareSave(saveName) {
		if (saveName === null) {
			saveName = await libFileOps.getNewestFile(
				this.path("saves"), (name) => !name.endsWith(".tmp.zip")
			);
		}
		if (saveName === null) {
			this.logger.info("Creating new save");
			await this.server.create("world.zip");
			saveName = "world.zip";
		}
		if (saveName.startsWith("_autosave")) {
			this.logger.info("Copying autosave");
			let now = new Date();
			let newName = util.format(
				"%s-%s-%s %s%s %s",
				now.getUTCFullYear(),
				(now.getUTCMonth() + 1).toLocaleString("en", { minimumIntegerDigits: 2 }),
				now.getUTCDate().toLocaleString("en", { minimumIntegerDigits: 2 }),
				now.getUTCHours().toLocaleString("en", { minimumIntegerDigits: 2 }),
				now.getUTCMinutes().toLocaleString("en", { minimumIntegerDigits: 2 }),
				saveName,
			);
			await fs.copy(this.path("saves", saveName), this.path("saves", newName));
			saveName = newName;
		}
		if (!this.config.get("factorio.enable_save_patching")) {
			return saveName;
		}
		this.logger.verbose("Patching save");
		let modules = new Map();
		for (let [pluginName, plugin] of this.plugins) {
			let pluginPackagePath = require.resolve(path.posix.join(plugin.info.requirePath, "package.json"));
			let modulePath = path.join(path.dirname(pluginPackagePath), "module");
			if (!await fs.pathExists(modulePath)) {
				continue;
			}
			let moduleJsonPath = path.join(modulePath, "module.json");
			if (!await fs.pathExists(moduleJsonPath)) {
				throw new Error(`Module for plugin ${pluginName} is missing module.json`);
			}
			let module = JSON.parse(await fs.readFile(moduleJsonPath));
			if (module.name !== pluginName) {
				throw new Error(`Expected name of module for plugin ${pluginName} to match the plugin name`);
			}
			module = {
				version: plugin.info.version,
				dependencies: { "clusterio": "*" },
				path: modulePath,
				load: [],
				require: [],
				...module,
			};
			modules.set(module.name, module);
		}
		for (let entry of await fs.readdir(path.join(__dirname, "modules"), { withFileTypes: true })) {
			if (!entry.isFile()) {
				if (modules.has(entry.name)) {
					throw new Error(`Module with name ${entry.name} already exists in a plugin`);
				}
				let moduleJsonPath = path.join(__dirname, "modules", entry.name, "module.json");
				if (!await fs.pathExists(moduleJsonPath)) {
					throw new Error(`Module ${entry.name} is missing module.json`);
				}
				let module = JSON.parse(await fs.readFile(moduleJsonPath));
				if (module.name !== entry.name) {
					throw new Error(`Expected name of module ${entry.name} to match the directory name`);
				}
				module = {
					path: path.join(__dirname, "modules", entry.name),
					dependencies: { "clusterio": "*" },
					load: [],
					require: [],
					...module,
				};
				modules.set(module.name, module);
			}
		}
		await libFactorio.patch(this.path("saves", saveName), [...modules.values()]);
		return saveName;
	}
async prepareSave ( saveName ) { if ( saveName === null ) { saveName = await libFileOps . getNewestFile ( this . path ( "saves" ) , ( name ) => ! name . endsWith ( ".tmp.zip" ) ) ; } if ( saveName === null ) { this . logger . info ( "Creating new save" ) ; await this . server . create ( "world.zip" ) ; saveName = "world.zip" ; } if ( saveName . startsWith ( "_autosave" ) ) { this . logger . info ( "Copying autosave" ) ; let now = new Date ( ) ; let newName = util . format ( "%s-%s-%s %s%s %s" , now . getUTCFullYear ( ) , ( now . getUTCMonth ( ) + 1 ) . toLocaleString ( "en" , { minimumIntegerDigits : 2 } ) , now . getUTCDate ( ) . toLocaleString ( "en" , { minimumIntegerDigits : 2 } ) , now . getUTCHours ( ) . toLocaleString ( "en" , { minimumIntegerDigits : 2 } ) , now . getUTCMinutes ( ) . toLocaleString ( "en" , { minimumIntegerDigits : 2 } ) , saveName , ) ; await fs . copy ( this . path ( "saves" , saveName ) , this . path ( "saves" , newName ) ) ; saveName = newName ; } if ( ! this . config . get ( "factorio.enable_save_patching" ) ) { return saveName ; } this . logger . verbose ( "Patching save" ) ; let modules = new Map ( ) ; for ( let [ pluginName , plugin ] of this . plugins ) { let pluginPackagePath = require . resolve ( path . posix . join ( plugin . info . requirePath , "package.json" ) ) ; let modulePath = path . join ( path . dirname ( pluginPackagePath ) , "module" ) ; if ( ! await fs . pathExists ( modulePath ) ) { continue ; } let moduleJsonPath = path . join ( modulePath , "module.json" ) ; if ( ! await fs . pathExists ( moduleJsonPath ) ) { throw new Error ( ` ${ pluginName } ` ) ; } let module = JSON . parse ( await fs . readFile ( moduleJsonPath ) ) ; if ( module . name !== pluginName ) { throw new Error ( ` ${ pluginName } ` ) ; } module = { version : plugin . info . version , dependencies : { "clusterio" : "*" } , path : modulePath , load : [ ] , require : [ ] , ... module , } ; modules . set ( module . name , module ) ; } for ( let entry of await fs . readdir ( path . join ( __dirname , "modules" ) , { withFileTypes : true } ) ) { if ( ! entry . isFile ( ) ) { if ( modules . has ( entry . name ) ) { throw new Error ( ` ${ entry . name } ` ) ; } let moduleJsonPath = path . join ( __dirname , "modules" , entry . name , "module.json" ) ; if ( ! await fs . pathExists ( moduleJsonPath ) ) { throw new Error ( ` ${ entry . name } ` ) ; } let module = JSON . parse ( await fs . readFile ( moduleJsonPath ) ) ; if ( module . name !== entry . name ) { throw new Error ( ` ${ entry . name } ` ) ; } module = { path : path . join ( __dirname , "modules" , entry . name ) , dependencies : { "clusterio" : "*" } , load : [ ] , require : [ ] , ... module , } ; modules . set ( module . name , module ) ; } } await libFactorio . patch ( this . path ( "saves" , saveName ) , [ ... modules . values ( ) ] ) ; return saveName ; }
Prepare a save for starting
 Creates a new save if no save is passed and patches it with modules.
Prepare a save for starting Creates a new save if no save is passed and patches it with modules .
// Use latest save if no save was specified // Create save if no save was found. // Load a copy if it's autosave to prevent overwriting the autosave // Patch save with lua modules from plugins // Find plugin modules to patch in // Find stand alone modules to load // XXX for now only the included clusterio module is loaded