From 688a6dda186a90b09d54bb2b58fcaa0563a6e626 Mon Sep 17 00:00:00 2001 From: Cooldude2606 <25043174+Cooldude2606@users.noreply.github.com> Date: Sat, 30 Aug 2025 20:18:37 +0100 Subject: [PATCH 1/5] Fix uninitialised data in player bonus Fixes: #406 --- exp_scenario/module/gui/player_bonus.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/exp_scenario/module/gui/player_bonus.lua b/exp_scenario/module/gui/player_bonus.lua index afadf3df..b136495f 100644 --- a/exp_scenario/module/gui/player_bonus.lua +++ b/exp_scenario/module/gui/player_bonus.lua @@ -359,6 +359,9 @@ Elements.container = Gui.define("player_bonus/container") local container = Gui.elements.container(parent) local header = Gui.elements.header(container, { caption = { "exp-gui_player-bonus.caption-main" } }) + local player = Gui.get_player(parent) + def.data[player] = def.data[player] or {} -- Used within bonus_table.add_row + local elements = {} --- @cast elements ExpGui_PlayerBonus.elements.bonus_slider.elements local bonus_table = Elements.bonus_table(container) elements.bonus_used = Elements.bonus_used(header) @@ -376,8 +379,7 @@ Elements.container = Gui.define("player_bonus/container") Elements.bonus_used.refresh(elements.bonus_used, bonus_cost) return Gui.elements.container.get_root_element(container) - end) - :player_data{} --[[ @as any ]] + end) --[[ @as any ]] --- Set the bonus value for a player --- @param player LuaPlayer From 3e5043d29e422fb6c7047794e184310525b43073 Mon Sep 17 00:00:00 2001 From: Cooldude2606 <25043174+Cooldude2606@users.noreply.github.com> Date: Sat, 30 Aug 2025 20:39:37 +0100 Subject: [PATCH 2/5] Add space platform event to entity protection (#402) --- exp_legacy/module/modules/control/protection.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/exp_legacy/module/modules/control/protection.lua b/exp_legacy/module/modules/control/protection.lua index 4f0d5c95..79415756 100644 --- a/exp_legacy/module/modules/control/protection.lua +++ b/exp_legacy/module/modules/control/protection.lua @@ -199,6 +199,7 @@ local function event_remove_entity(event) EntityProtection.remove_entity(event.entity) end +Event.add(defines.events.on_space_platform_pre_mined, event_remove_entity) Event.add(defines.events.on_pre_player_mined_item, event_remove_entity) Event.add(defines.events.on_robot_pre_mined, event_remove_entity) Event.add(defines.events.on_entity_died, event_remove_entity) From 82c2c7f23cb33fc7a5f9c6d90cd95be7c37e8569 Mon Sep 17 00:00:00 2001 From: Cooldude2606 <25043174+Cooldude2606@users.noreply.github.com> Date: Sat, 30 Aug 2025 20:39:46 +0100 Subject: [PATCH 3/5] Reattempt set slot after filter fail (#403) --- exp_legacy/module/modules/control/vlayer.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/exp_legacy/module/modules/control/vlayer.lua b/exp_legacy/module/modules/control/vlayer.lua index 4e7e17a1..fd32a966 100644 --- a/exp_legacy/module/modules/control/vlayer.lua +++ b/exp_legacy/module/modules/control/vlayer.lua @@ -612,7 +612,11 @@ local function handle_circuit_interfaces() -- Set the item signals based on stored items for item_name, count in pairs(vlayer_data.storage.items) do if prototypes.item[item_name] and count > 0 then - circuit_oc.set_slot(signal_index, { value = { type = "item", name = item_name, quality = "normal" }, min = count }) + local existing_index = circuit_oc.set_slot(signal_index, { value = { type = "item", name = item_name, quality = "normal" }, min = count }) + if existing_index then + circuit_oc.clear_slot(existing_index) + circuit_oc.set_slot(signal_index, { value = { type = "item", name = item_name, quality = "normal" }, min = count }) + end signal_index = signal_index + 1 end end From 8bcb65101b82cab43c66ea71a94166999fd431b5 Mon Sep 17 00:00:00 2001 From: Cooldude2606 <25043174+Cooldude2606@users.noreply.github.com> Date: Sat, 30 Aug 2025 20:39:54 +0100 Subject: [PATCH 4/5] Switch to sp/mp init events (#404) --- exp_commands/module/commands/ipc.lua | 3 +++ exp_commands/module/commands/rcon.lua | 3 --- exp_legacy/module/control.lua | 2 +- exp_legacy/module/utils/event.lua | 4 ++-- exp_util/module/async.lua | 7 ++----- exp_util/module/include/package.lua | 7 ++----- exp_util/module/storage.lua | 12 +++++------- 7 files changed, 15 insertions(+), 23 deletions(-) diff --git a/exp_commands/module/commands/ipc.lua b/exp_commands/module/commands/ipc.lua index b4799405..efc0e856 100644 --- a/exp_commands/module/commands/ipc.lua +++ b/exp_commands/module/commands/ipc.lua @@ -10,6 +10,9 @@ local Clustorio = require("modules/clusterio/api") local json_to_table = helpers.json_to_table +Commands.add_rcon_static("Clustorio", Clustorio) +Commands.add_rcon_static("ipc", Clustorio.send_json) + Commands.new("_ipc", { "exp-commands_ipc.description" }) :argument("channel", { "exp-commands_ipc.arg-channel" }, Commands.types.string) :argument("message", { "exp-commands_ipc.arg-message" }, Commands.types.string) diff --git a/exp_commands/module/commands/rcon.lua b/exp_commands/module/commands/rcon.lua index 3e7b7059..1e1d2ec5 100644 --- a/exp_commands/module/commands/rcon.lua +++ b/exp_commands/module/commands/rcon.lua @@ -11,7 +11,6 @@ System command which runs arbitrary code within a custom (not sandboxed) environ local ExpUtil = require("modules/exp_util") local Async = require("modules/exp_util/async") local Storage = require("modules/exp_util/storage") -local Clustorio = require("modules/clusterio/api") local Commands = require("modules/exp_commands") --- @class Commands @@ -26,9 +25,7 @@ setmetatable(rcon_env, { __index = rcon_static }) rcon_static.Async = Async rcon_static.ExpUtil = ExpUtil rcon_static.Commands = Commands -rcon_static.Clustorio = Clustorio rcon_static.print = Commands.print -rcon_static.ipc = Clustorio.send_json --- @diagnostic enable: name-style-check --- Some common callback values which are useful when a player uses the command diff --git a/exp_legacy/module/control.lua b/exp_legacy/module/control.lua index b1c46a23..f5033af3 100644 --- a/exp_legacy/module/control.lua +++ b/exp_legacy/module/control.lua @@ -41,6 +41,6 @@ for _, error in ipairs(errors) do log(error) end log("[END] -----| Explosive Gaming Scenario Loader |-----") ---- Register all event handlers via clusterio +--- Register all event handlers via event handler local Event = require("modules/exp_legacy/utils/event") return Event.real_handlers diff --git a/exp_legacy/module/utils/event.lua b/exp_legacy/module/utils/event.lua index 216eac16..f2407f06 100644 --- a/exp_legacy/module/utils/event.lua +++ b/exp_legacy/module/utils/event.lua @@ -1,4 +1,3 @@ -local Clustorio = require("modules/clusterio/api") local ExpUtil = require("modules/exp_util") local Event = { @@ -66,7 +65,8 @@ function Event.on_init(handler) end handlers[#handlers + 1] = handler - Event.add(Clustorio.events.on_server_startup, handler) + Event.add(defines.events.on_singleplayer_init, handler) + Event.add(defines.events.on_multiplayer_init, handler) end function Event.on_load(handler) diff --git a/exp_util/module/async.lua b/exp_util/module/async.lua index ba37af7f..b31554f6 100644 --- a/exp_util/module/async.lua +++ b/exp_util/module/async.lua @@ -408,13 +408,10 @@ end local e = defines.events local events = { [e.on_tick] = on_tick, + [e.on_singleplayer_init] = Async.on_init, + [e.on_multiplayer_init] = Async.on_init, } -local Clustorio = ExpUtil.optional_require("modules/clusterio/api") -if Clustorio then - events[Clustorio.events.on_server_startup] = Async.on_init -end - Async._function_metatable.__call = Async._function_prototype.start_soon Async.events = events --- @package return Async diff --git a/exp_util/module/include/package.lua b/exp_util/module/include/package.lua index 8d09dcea..96181735 100644 --- a/exp_util/module/include/package.lua +++ b/exp_util/module/include/package.lua @@ -1,7 +1,5 @@ -- luacheck:ignore global package -local Clustorio = require("modules/clusterio/api") - --- Enum values for the different lifecycle stages within a factorio module -- Info on the data lifecycle and how we use it: https://lua-api.factorio.com/latest/auxiliary/data-lifecycle.html -- We start in control stage and so values 1 thorough 3 are only present for completeness @@ -25,10 +23,9 @@ return setmetatable({ on_load = function() package.lifecycle = package.lifecycle_stage.load end, on_configuration_changed = function() package.lifecycle = package.lifecycle_stage.config_change end, events = { - -- TODO find a reliable way to set to runtime because currently it will desync if accessed before player joined - -- TODO make clusterio optional dependency [defines.events.on_player_joined_game] = function() package.lifecycle = package.lifecycle_stage.runtime end, - [Clustorio.events.on_server_startup] = function() package.lifecycle = package.lifecycle_stage.runtime end, + [defines.events.on_singleplayer_init] = function() package.lifecycle = package.lifecycle_stage.runtime end, + [defines.events.on_multiplayer_init] = function() package.lifecycle = package.lifecycle_stage.runtime end, }, }, { __index = package, diff --git a/exp_util/module/storage.lua b/exp_util/module/storage.lua index 5ec30318..2347c882 100644 --- a/exp_util/module/storage.lua +++ b/exp_util/module/storage.lua @@ -119,12 +119,10 @@ function Storage.on_init() end end -local events = {} +--- @package +Storage.events = { + [defines.events.on_multiplayer_init] = Storage.on_init, + [defines.events.on_singleplayer_init] = Storage.on_init, +} -local Clustorio = ExpUtil.optional_require("modules/clusterio/api") -if Clustorio then - events[Clustorio.events.on_server_startup] = Storage.on_init -end - -Storage.events = events --- @package return Storage From d85f69b9cb0bcde9d237e1da708105d111b24237 Mon Sep 17 00:00:00 2001 From: Cooldude2606 <25043174+Cooldude2606@users.noreply.github.com> Date: Sat, 30 Aug 2025 20:40:02 +0100 Subject: [PATCH 5/5] Pause server ups when no players online (#405) --- exp_server_ups/instance.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/exp_server_ups/instance.ts b/exp_server_ups/instance.ts index 7d0cb350..b0a97830 100644 --- a/exp_server_ups/instance.ts +++ b/exp_server_ups/instance.ts @@ -24,6 +24,14 @@ export class InstancePlugin extends BaseInstancePlugin { } } + async onPlayerEvent(event: lib.PlayerEvent): Promise { + if (event.type === "join" && !this.updateInterval) { + await this.onStart(); + } else if (event.type === "leave" && this.instance.playersOnline.size == 0 && this.instance.config.get("factorio.settings")["auto_pause"] as boolean) { + this.onExit(); + } + } + async updateUps() { let ups = 0; const collected = this.gameTimes.length - 1;