-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcontrol.lua
More file actions
325 lines (314 loc) · 13.8 KB
/
control.lua
File metadata and controls
325 lines (314 loc) · 13.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
-- control.lua
-- Main entry point for the Factorio Admin Command Center (FACC) mod.
--------------------------------------------------------------------------------
-- Shared permission checker
--------------------------------------------------------------------------------
local permissions = require("scripts/utils/permissions")
_G.is_allowed = permissions.is_allowed
local flib_on_tick_n = require("__flib__.on-tick-n")
local flib_table = require("__flib__.table")
local compat = require("scripts/utils/mod_compat")
local function safe_control_call(label, fn, ...)
local ok, err = pcall(fn, ...)
if not ok then
log("[FACC][CONTROL] " .. tostring(label) .. " failed: " .. tostring(err))
return false
end
return true
end
-- Alias the persistent global table so every module can use the shorter `storage`
-- name (historically used by the mod) while still relying on Factorio's official
-- persistence table. This keeps saves compatible across updates/load.
storage = storage or global
--------------------------------------------------------------------------------
-- Helpers for resource regeneration
--------------------------------------------------------------------------------
-- Restore finite resources when infinite-resources is disabled
local regenerate_finite = require("scripts/planets/regenerate_resources")
-- Top up infinite resources to exactly N× prototype normal amount
local regenerate_infinite = require("scripts/startup-settings/regenerate_to_infinite_resources")
--------------------------------------------------------------------------------
-- NEW: Invincible player switch module (reapply on join/respawn)
--------------------------------------------------------------------------------
local invincible_player = require("scripts/character/invincible_player")
--------------------------------------------------------------------------------
-- Utility: parse "Nx" and read (solid, fluid) multipliers with legacy fallback
--------------------------------------------------------------------------------
--- Parse "Nx" into a number (default 1).
-- @param s string|nil
-- @return number
local function parse_x(s)
if type(s) ~= "string" then return 1 end
local n = tonumber(s:match("^(%d+)x$"))
return n or 1
end
--- Read both multipliers (solid, fluid). If legacy single setting exists, use it as fallback.
-- @return number mult_solid, number mult_fluid
local function read_multipliers_pair()
local legacy = settings.startup["facc-infinite-resources-multiplier"]
and settings.startup["facc-infinite-resources-multiplier"].value
or nil
local solid_str = (settings.startup["facc-infinite-resources-multiplier-solid"]
and settings.startup["facc-infinite-resources-multiplier-solid"].value)
or legacy or "1x"
local fluid_str = (settings.startup["facc-infinite-resources-multiplier-fluid"]
and settings.startup["facc-infinite-resources-multiplier-fluid"].value)
or legacy or "1x"
return parse_x(solid_str), parse_x(fluid_str)
end
--- Reads whether automatic resource regeneration should run when startup
-- infinite-resources toggles are applied.
-- Prefers runtime-global setting and keeps startup fallback for compatibility.
-- @return boolean
local function is_auto_resource_regeneration_enabled()
if settings.global and settings.global["facc-enable-auto-resource-regeneration"] then
return settings.global["facc-enable-auto-resource-regeneration"].value == true
end
if settings.startup and settings.startup["facc-enable-auto-resource-regeneration"] then
return settings.startup["facc-enable-auto-resource-regeneration"].value == true
end
return false
end
--- Check whether a resource entity behaves like a "fluid resource".
-- Heuristics:
-- 1) resource_category/category contains "fluid"
-- 2) mineable products include a fluid
-- @param res LuaEntity (type="resource")
-- @return boolean
local function is_fluid_resource_entity(res)
local proto = res and res.prototype
if not proto then return false end
local cat = proto.resource_category or proto.category or "basic-solid"
if type(cat) == "string" and string.find(cat, "fluid", 1, true) then
return true
end
local mp = proto.mineable_properties
if mp and mp.products then
for _, p in pairs(mp.products) do
if p and p.type == "fluid" then
return true
end
end
end
return false
end
--------------------------------------------------------------------------------
-- Utility: top up infinite resources in a given area (used on chunk generation)
--------------------------------------------------------------------------------
local function top_up_area(surface, area)
-- Read multipliers at runtime, with legacy fallback
local mult_solid, mult_fluid = read_multipliers_pair()
flib_table.for_each(surface.find_entities_filtered{ area = area, type = "resource" }, function(resource)
if resource.prototype.infinite_resource then
local normal = resource.prototype.normal_resource_amount
if normal and normal > 0 then
local m = is_fluid_resource_entity(resource) and mult_fluid or mult_solid
local full_amount = normal * m
resource.initial_amount = full_amount
resource.amount = full_amount
end
end
end)
end
--------------------------------------------------------------------------------
-- Remove legacy UI buttons on init/updates
--------------------------------------------------------------------------------
local function remove_old_button()
flib_table.for_each(game.players, function(player)
for _, name in ipairs({ "facc_main_button", "factorio_admin_command_center_button" }) do
local btn = player.gui.top[name]
if btn and btn.valid then
btn.destroy()
end
end
end)
end
--------------------------------------------------------------------------------
-- Hide or show the Legendary Upgrader shortcut based on Quality mod presence
--------------------------------------------------------------------------------
local function is_legendary_quality_module_researched(force)
if not (force and force.valid and force.technologies) then
return false
end
local legendary_quality = force.technologies["legendary-quality"]
if not (legendary_quality and legendary_quality.valid) then
return false
end
return legendary_quality.researched == true
end
local function update_legendary_shortcut_availability()
local quality_active = compat.is_quality_active()
flib_table.for_each(game.players, function(player)
if not (player and player.valid) then
return
end
local researched = is_legendary_quality_module_researched(player.force)
local available = (quality_active and researched) == true
local ok, err = pcall(function()
player.set_shortcut_available("facc_give_legendary_upgrader", available)
end)
if not ok then
log("[FACC][CONTROL] set_shortcut_available failed: " .. tostring(err))
end
end)
end
--------------------------------------------------------------------------------
-- On first load: remove old buttons and update shortcuts
--------------------------------------------------------------------------------
script.on_init(function()
flib_on_tick_n.init()
storage.facc_auto_task_ids = nil
storage.facc_auto_task_intervals = nil
remove_old_button()
update_legendary_shortcut_availability()
end)
--------------------------------------------------------------------------------
-- When configuration changes (mod update or startup setting change):
-- 1) remove old buttons
-- 2) update legendary upgrader shortcut
-- 3) automatically regenerate resources if user did NOT disable it
--------------------------------------------------------------------------------
script.on_configuration_changed(function(event)
if not storage.__flib or not storage.__flib.on_tick_n then
flib_on_tick_n.init()
storage.facc_auto_task_ids = nil
storage.facc_auto_task_intervals = nil
end
remove_old_button()
update_legendary_shortcut_availability()
-- Skip auto-regeneration if the user has activated the new setting
if is_auto_resource_regeneration_enabled() then
-- If infinite-resources was just disabled, restore finite resources on all surfaces
if not settings.startup["facc-infinite-resources"].value then
flib_table.for_each(game.surfaces, function(surface)
-- dummy context to satisfy regenerate_finite.run
local ctx = {
surface = surface,
admin = true,
print = function() end
}
safe_control_call("regenerate_finite.run", regenerate_finite.run, ctx)
end)
end
-- If infinite-resources is enabled, top up every existing surface to N× once
if settings.startup["facc-infinite-resources"].value then
flib_table.for_each(game.surfaces, function(surface)
safe_control_call("regenerate_infinite.run_on_surface", regenerate_infinite.run_on_surface, surface)
end)
end
end
end)
--------------------------------------------------------------------------------
-- Whenever a player joins (covers save-load and multiplayer joins)
-- Also reapply the saved invincibility state for that player.
--------------------------------------------------------------------------------
script.on_event(defines.events.on_player_joined_game, function(e)
update_legendary_shortcut_availability()
local p = game.get_player(e.player_index)
if p then invincible_player.apply_saved(p) end
end)
script.on_event(defines.events.on_research_finished, function()
update_legendary_shortcut_availability()
end)
script.on_event(defines.events.on_technology_effects_reset, function()
update_legendary_shortcut_availability()
end)
script.on_event(defines.events.on_player_changed_force, function()
update_legendary_shortcut_availability()
end)
--------------------------------------------------------------------------------
-- Reapply invincibility on respawn (if previously enabled via switch)
--------------------------------------------------------------------------------
script.on_event(defines.events.on_player_respawned, function(e)
local p = game.get_player(e.player_index)
if p then invincible_player.apply_saved(p) end
end)
--------------------------------------------------------------------------------
-- When a new chunk is generated: enforce infinite-resource top-up if setting is on
--------------------------------------------------------------------------------
script.on_event(defines.events.on_chunk_generated, function(event)
if settings.startup["facc-infinite-resources"].value then
safe_control_call("top_up_area", top_up_area, event.surface, event.area)
end
end)
--------------------------------------------------------------------------------
-- When a new surface is created: enforce infinite-resource top-up if setting is on
--------------------------------------------------------------------------------
script.on_event(defines.events.on_surface_created, function(event)
if settings.startup["facc-infinite-resources"].value then
local surf = game.surfaces[event.surface_index]
safe_control_call("regenerate_infinite.run_on_surface", regenerate_infinite.run_on_surface, surf)
end
end)
--------------------------------------------------------------------------------
-- Load core modules
--------------------------------------------------------------------------------
for _, path in ipairs({
"scripts/init",
"scripts/gui/main_gui",
"scripts/environment/clean_pollution",
"scripts/environment/remove_ground_items",
"scripts/cheats/instant_research",
"scripts/gui/console_gui",
"scripts/gui/teleport_gui",
"scripts/gui/stats_hud",
"scripts/remote/public_api",
"scripts/events/gui_events",
"scripts/legendary-upgrader/legendary_upgrader",
"scripts/events/build_events"
}) do
require(path)
end
--------------------------------------------------------------------------------
-- Shortcut handlers (Ctrl+., Ctrl+Enter, toolbar buttons)
--------------------------------------------------------------------------------
local main_gui = require("scripts/gui/main_gui")
local console_gui = require("scripts/gui/console_gui")
local teleport_gui = require("scripts/gui/teleport_gui")
script.on_event(defines.events.on_player_changed_surface, function(e)
local player = game.get_player(e.player_index)
if player and main_gui and main_gui.refresh_open_gui then
safe_control_call("main_gui.refresh_open_gui", main_gui.refresh_open_gui, player)
end
end)
-- Toggle admin GUI with Ctrl+.
script.on_event("facc_toggle_gui", function(e)
local player = game.get_player(e.player_index)
if player then
main_gui.toggle_main_gui(player)
end
end)
-- Handle toolbar shortcuts
script.on_event(defines.events.on_lua_shortcut, function(e)
local player = game.get_player(e.player_index)
if not player then return end
if e.prototype_name == "facc_toggle_gui_shortcut" then
main_gui.toggle_main_gui(player)
elseif e.prototype_name == "facc_give_legendary_upgrader" then
if is_allowed(player) then
if not compat.is_quality_active() or not is_legendary_quality_module_researched(player.force) then
player.print({ "facc.legendary-upgrader-research-required" })
return
end
player.clear_cursor()
pcall(function()
player.cursor_stack.set_stack({ name = "facc_legendary_upgrader" })
end)
player.print({ "facc.legendary-upgrader-equipped" })
end
end
end)
-- Execute Lua console command with Ctrl+Enter
script.on_event("facc_console_exec_input", function(e)
local player = game.get_player(e.player_index)
if player and player.gui.screen.facc_console_frame then
console_gui.exec_console_command(player)
end
end)
-- Toggle Fast Teleport Manager with Ctrl+Shift+T
script.on_event("facc_toggle_fast_teleport", function(e)
local player = game.get_player(e.player_index)
if player then
teleport_gui.toggle_teleport_gui(player)
end
end)