-
Notifications
You must be signed in to change notification settings - Fork 13
/
control.lua
155 lines (137 loc) · 4.97 KB
/
control.lua
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
script.on_configuration_changed(function()
for _, force in pairs(game.forces) do
force.reset_recipes()
force.reset_technologies()
force.reset_technology_effects()
end
if remote.interfaces["pywiki_turd_page"] then
for _, force in pairs(game.forces) do remote.call("pywiki_turd_page", "reapply_turd_bonuses", force) end
end
if remote.interfaces["pyse_start_seqence"] then
for _, force in pairs(game.forces) do remote.call("pyse_start_seqence", "update_force", force) end
end
end)
-- We risk more problems than solutions if we expand further
-- This will need changes if TURD works off locking techs!
local checked_mods = {
base = true,
pyalienlife = true,
pyalternativeenergy = true,
pycoalprocessing = true,
pyfusionenergy = true,
pyhightech = true,
pyindustry = true,
pypetroleumhandling = true,
pypostprocessing = true,
pyrawores = true
}
commands.add_command("check-technology-consistency", {"command-help.check-technology-consistency"}, function()
-- Build a list of base-game techs
local filtered_prototypes = {}
for name, prototype in pairs(prototypes.technology) do
local history = prototypes.get_history("technology", name)
if checked_mods[history.created] then
filtered_prototypes[name] = prototype
end
end
-- Iterate and verify
for _, force in pairs(game.forces) do
local force_techs = force.technologies
for name, prototype in pairs(filtered_prototypes) do
local tech = force_techs[name]
if tech.enabled ~= prototype.enabled then
tech.enabled = prototype.enabled
local localised_name = tech.localised_name or ("technology-name." .. name)
game.print {"command-output.fixed-technology", localised_name}
end
end
end
game.print {"command-output.consistency-check-complete"}
end)
local dev_mode = settings.startup["pypp-dev-mode"].value
if dev_mode then require "tests.control" end
require "lib"
-- delayed functions
---@type table<integer, table<int, {name: string, params: any[]?}>>
storage.on_tick = storage.on_tick or {}
py.on_event(defines.events.on_tick, function(event)
local tick = event.tick
storage.on_tick = storage.on_tick or {}
if not storage.on_tick[tick] then return end
for _, func_details in pairs(storage.on_tick[tick]) do
local success, err = pcall(py.on_tick_funcs[func_details.name], table.unpack(func_details.params))
if not success then error("error in on tick function " .. func_details.name .. ": " .. err) end
end
storage.on_tick[tick] = nil
end)
-- on_nth_tick functions
---@class NthTickOrder
---@field func string
---@field delay int
---@class NthTickFunc
---@field tick int
---@field mod string
---@type table<string, NthTickFunc>
py.nth_tick_funcs = {}
py.nth_tick_total = 0
---use instead of script.on_nth_tick
---@param func_list NthTickFunc[]
local register_on_nth_tick = function(func_list)
for func_name, details in pairs(func_list) do
log("registered on_nth_tick function " .. func_name .. " from mod " .. details.mod)
py.nth_tick_total = py.nth_tick_total + 1 / details.tick
py.nth_tick_funcs[details.mod .. "-" .. func_name] = {mod = details.mod, tick = details.tick}
end
end
local function init_nth_tick()
---@type table<int, NthTickOrder[]>
storage.nth_tick_order = storage.nth_tick_order or {}
local added_funcs = {}
for _, tick_funcs in pairs(storage.nth_tick_order) do
for _, details in pairs(tick_funcs) do
added_funcs[details.func] = true
end
end
for name, details in pairs(py.nth_tick_funcs) do
if not added_funcs[name] then
next_tick = math.ceil(game.tick / details.tick) * details.tick
if not storage.nth_tick_order[next_tick] then storage.nth_tick_order[next_tick] = {} end
table.insert(storage.nth_tick_order[next_tick], {func = name, delay = 0})
end
end
py.nth_tick_setup = true
end
---@param event EventData.on_tick
py.on_event(defines.events.on_tick, function(event)
local tick = event.tick
if not py.nth_tick_setup then init_nth_tick() end
local max_funcs_per_tick = math.ceil(py.nth_tick_total * 2)
local this_tick_total = 0
local delayed = 0
for _, order in pairs(storage.nth_tick_order[tick] or {}) do
if not py.nth_tick_funcs[order.func] then goto continue end
this_tick_total = this_tick_total + (game.tick ~= 0 and 1 or 0)
if this_tick_total <= max_funcs_per_tick then
remote.call(py.nth_tick_funcs[order.func].mod, "execute_on_nth_tick", order.func)
local next_tick = tick + py.nth_tick_funcs[order.func].tick - order.delay
order.delay = 0
if next_tick <= tick then
order.delay = tick + 1 - next_tick
next_tick = tick + 1
end
if not storage.nth_tick_order[next_tick] then storage.nth_tick_order[next_tick] = {} end
table.insert(storage.nth_tick_order[next_tick], order)
else
delayed = delayed + 1
if not storage.nth_tick_order[tick + 1] then storage.nth_tick_order[tick + 1] = {} end
order.delay = order.delay + 1
table.insert(storage.nth_tick_order[tick + 1], delayed, order)
end
::continue::
end
storage.nth_tick_order[tick] = nil
end)
py.finalize_events()
remote.add_interface("on_nth_tick", {
add = register_on_nth_tick
})