From 892c8034960e76fbe2977b2e6c743caed05090d2 Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Sun, 5 Jan 2020 23:19:34 +0100 Subject: [PATCH] Add on_server_startup event Add startup event to the Clusterio module API which is raised at startup of a Factorio server. This is to server as a replacement for the on_init and on_configuration_changed events which cannot be used in modules. Adds clusterio_patch_number global from the patcher in order to implement this. This is a number that's incremented every time the save is patched. --- docs/developing-for-clusterio.md | 19 +++++++++++++++++-- docs/writing-plugins.md | 2 +- lib/factorio/patch.js | 4 ++++ modules/clusterio/api.lua | 13 ++++++++++++- modules/clusterio/impl.lua | 15 ++++++++++----- test/lib/factorio/patch.js | 2 ++ 6 files changed, 46 insertions(+), 9 deletions(-) diff --git a/docs/developing-for-clusterio.md b/docs/developing-for-clusterio.md index 2f14f529..33a83730 100644 --- a/docs/developing-for-clusterio.md +++ b/docs/developing-for-clusterio.md @@ -14,6 +14,7 @@ Contents - [event_handler interface](#event_handler-interface) - [Communicating with Clusterio](#communicating-with-clusterio) - [Clusterio Modules](#clusterio-modules) + - [Clusterio Module API](#clusterio-module-api) - [Clusterio Plugins](#clusterio-plugins) @@ -188,6 +189,7 @@ structure: "name": "my_module", "version": "1.2.0", "dependencies": { + "clusterio": "*", "foo": ">=0.4.2" }, "require": ["bar.lua"], @@ -248,8 +250,21 @@ module. Because modules can be patched into an existing game you cannot rely on the `on_init` callback to be called in Clusterio Modules. Nor can you rely on the `on_configuration_changed` callback, as this is not called -when level code changes. Instead you will have to initialize whatever -global variable you need when you first use them. +when level code changes. The `clusterio` module provides the custom +`on_server_startup` event that can be used as a substitute, see the next +section. + + +### Clusterio Module API + +There's a builtin clusterio module that provides some tools for getting +instance info and communicating to plugins, script events to listen for +and a Factorio remote call API. The available interfaces is documented +in [modules/clusterio/api.lua](modules/clusterio/api.lua). To use this +API from another module, require it using something along the lines of +`local clusterio_api = require("modules/clusterio/api")`. Make sure to +add `clusterio` as a dependency in your module.json if you use the +dependency entry in it. Clusterio Plugins diff --git a/docs/writing-plugins.md b/docs/writing-plugins.md index ac534027..8f71771a 100644 --- a/docs/writing-plugins.md +++ b/docs/writing-plugins.md @@ -190,7 +190,7 @@ And then in the module for the plugin: local clusterio_api = require('modules/clusterio/api') -- inside some event handler - clusterio_api.send('my_plugin_foo', { data = 123 }) + clusterio_api.send_json('my_plugin_foo', { data = 123 }) It's recommended to either use the plugin name as the channel name or to prefix the channel name with the name of the plugin if you need multiple diff --git a/lib/factorio/patch.js b/lib/factorio/patch.js index 0940a932..2d5c1957 100644 --- a/lib/factorio/patch.js +++ b/lib/factorio/patch.js @@ -65,6 +65,7 @@ function generateLoader(patchInfo) { let lines = [ '-- Auto generated scenario module loader created by Clusterio', '-- Modifications to this file will be lost when loaded in Clusterio', + `clusterio_patch_number = ${patchInfo.patch_number}`, '', 'local event_handler = require("event_handler")', '', @@ -226,6 +227,9 @@ async function patch(savePath, modules) { } } + // Increment patch number + patchInfo["patch_number"] = (patchInfo["patch_number"] || 0) + 1; + // Remove any existing modules from the save patchInfo["modules"] = []; for (let file of root.file(/^modules\//)) { diff --git a/modules/clusterio/api.lua b/modules/clusterio/api.lua index 9d94e19a..2132f4fa 100644 --- a/modules/clusterio/api.lua +++ b/modules/clusterio/api.lua @@ -10,6 +10,18 @@ api.events = { -- instance_id: The id of the instance. -- instance_name: the name of the instance. on_instance_updated = script.generate_event_name(), + + -- Raised when the server is starting up + -- This event serves as the stand-in for the on_init and + -- on_configuration_changed events for modules. It is invoked as early + -- as possible, before most but not all other events, every time the + -- server is started up. + + -- Use this event to initialize and and/or migrate the data structures + -- you need. Keep in mind that Clusterio can switch from any version of + -- your module to any version of your module so it should be able to + -- handle both forwards and backwards migrations. + on_server_startup = script.generate_event_name(), } -- Send a table as json to Clusterio @@ -50,4 +62,3 @@ end return api - diff --git a/modules/clusterio/impl.lua b/modules/clusterio/impl.lua index 2f97ffba..d4989221 100644 --- a/modules/clusterio/impl.lua +++ b/modules/clusterio/impl.lua @@ -1,9 +1,17 @@ local api = require('modules/clusterio/api') - local impl = {} -local function init() + +impl.events = {} +impl.events[defines.events.on_tick] = function() + if global.clusterio_patch_number ~= clusterio_patch_number then + global.clusterio_patch_number = clusterio_patch_number + script.raise_event(api.events.on_server_startup, {}) + end +end + +impl.events[api.events.on_server_startup] = function() if not global.clusterio then global.clusterio = { instance_id = nil, @@ -15,7 +23,6 @@ end -- Internal API clusterio_private = {} function clusterio_private.update_instance(new_id, new_name) - init() global.clusterio.instance_id = new_id global.clusterio.instance_name = new_name script.raise_event(api.events.on_instance_updated, { @@ -35,14 +42,12 @@ function impl.add_remote_interface() -- Returns the instance id the game is run under -- This may change over time and/or be nil. get_instance_id = function() - init() return global.clusterio.instance_id end, -- Returns the name of the instance the game runs under. -- This may change over time and/or be nil. get_instance_name = function() - init() return global.clusterio.instance_name end, }) diff --git a/test/lib/factorio/patch.js b/test/lib/factorio/patch.js index bcbf2dbe..3a1f890e 100644 --- a/test/lib/factorio/patch.js +++ b/test/lib/factorio/patch.js @@ -52,6 +52,7 @@ describe("lib/factorio", function() { let reference = [ '-- Auto generated scenario module loader created by Clusterio', '-- Modifications to this file will be lost when loaded in Clusterio', + 'clusterio_patch_number = 1', '', 'local event_handler = require("event_handler")', '', @@ -64,6 +65,7 @@ describe("lib/factorio", function() { '', ].join('\n'); let patchInfo = { + "patch_number": 1, "scenario": { "modules": ["foo"] }, "modules": [{ "name": "spam",