-
Notifications
You must be signed in to change notification settings - Fork 23
/
power.lua
192 lines (172 loc) · 5.45 KB
/
power.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
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
local script_data = {
has_checked = false,
networks = {},
switches = {},
}
local map = {}
local function new_entity_entry(entity)
local base = {
entity_number = entity.unit_number,
prev = { input = {}, output = {} },
}
if script_data.networks[entity.electric_network_id] then
base.prev = script_data.networks[entity.electric_network_id].prev
end
script_data.networks[entity.electric_network_id] = base
map[entity.unit_number] = entity
end
local function find_entity(unit_number, entity_type)
if map[unit_number] then
return map[unit_number]
end
for _, surface in pairs(game.surfaces) do
local ents = surface.find_entities_filtered({ type = entity_type })
for _, entity in pairs(ents) do
if entity.unit_number == unit_number then
map[entity.unit_number] = entity
return entity
end
end
end
end
local function rescan_worlds()
local networks = script_data.networks
local invalids = {}
local remove = {}
for idx, network in pairs(networks) do
if network.entity then
network.entity_number = network.entity.unit_number
network.entity = nil
end
if network.entity_number then
local assoc = find_entity(network.entity_number, "electric-pole")
if not assoc then
invalids[idx] = true
end
else
remove[idx] = true
end
end
for _, surface in pairs(game.surfaces) do
local ents = surface.find_entities_filtered({ type = "electric-pole" })
for _, entity in pairs(ents) do
if not networks[entity.electric_network_id] or invalids[entity.electric_network_id] then
new_entity_entry(entity)
invalids[entity.electric_network_id] = nil
end
end
end
if table_size(remove) > 0 then
for idx, _ in pairs(remove) do
networks[idx] = nil
end
end
end
local function get_ignored_networks_by_switches()
local ignored = {}
local max = math.max
for switch_id, val in pairs(script_data.switches) do
-- assume old entity
if val ~= 1 and val and val.valid then
script_data.switches[val.unit_number] = 1
script_data.switches[switch_id] = nil
end
local switch = find_entity(switch_id, "power-switch")
if switch.power_switch_state and #switch.neighbours.copper > 1 then
local network =
max(switch.neighbours.copper[1].electric_network_id, switch.neighbours.copper[2].electric_network_id)
ignored[network] = true
end
end
return ignored
end
function on_power_build(event)
local entity = event.entity or event.created_entity
if entity and entity.type == "electric-pole" then
if not script_data.networks[entity.electric_network_id] then
new_entity_entry(entity)
end
elseif entity and entity.type == "power-switch" then
script_data.switches[entity.unit_number] = 1
map[entity.unit_number] = entity
end
end
function on_power_destroy(event)
local entity = event.entity
if entity.type == "electric-pole" then
local pos = entity.position
local max = entity.prototype and entity.prototype.max_wire_distance
or game.max_electric_pole_connection_distance
local area = { { pos.x - max, pos.y - max }, { pos.x + max, pos.y + max } }
local surface = entity.surface
local networks = script_data.networks
local current_idx = entity.electric_network_id
-- Make sure to create the new network ids before collecting new info
if entity.neighbours.copper and event.damage_type == nil then
entity.disconnect_neighbour()
end
local finds = surface.find_entities_filtered({ type = "electric-pole", area = area })
for _, new_entity in pairs(finds) do
if new_entity ~= entity then
if new_entity.electric_network_id == current_idx or not networks[new_entity.electric_network_id] then
-- here we need to add the new_entity
new_entity_entry(new_entity)
end
end
end
elseif entity.type == "power-switch" then
script_data.switches[entity.unit_number] = nil
end
-- if some unexpected stuff occurs, try enabling rescan_worlds
-- rescan_worlds()
end
function on_power_load()
script_data.has_checked = false
end
function on_power_init()
script_data.has_checked = false
end
function on_power_tick(event)
if event.tick then
local ignored = get_ignored_networks_by_switches()
if not script_data.has_checked then
rescan_worlds()
script_data.has_checked = true
end
gauge_power_production_input:reset()
gauge_power_production_output:reset()
for idx, network in pairs(script_data.networks) do
-- reset old style in case it still is old
if network.entity then
network.entity_number = network.entity.unit_number
network.entity = nil
end
local entity = find_entity(network.entity_number, "electric-pole")
if not entity then
rescan_worlds()
entity = find_entity(network.entity_number, "electric-pole")
end
if
entity
and entity.valid
and not ignored[entity.electric_network_id]
and entity.electric_network_id == idx
then
local force_name = entity.force.name
local surface_name = entity.surface.name
for name, n in pairs(entity.electric_network_statistics.input_counts) do
gauge_power_production_input:set(n, { force_name, name, idx, surface_name })
end
for name, n in pairs(entity.electric_network_statistics.output_counts) do
gauge_power_production_output:set(n, { force_name, name, idx, surface_name })
end
elseif entity and entity.valid and entity.electric_network_id ~= idx then
-- assume this network has been merged with some other so unset
script_data.networks[idx] = nil
elseif entity and not entity.valid then
-- Invalid entity remove anyhow
script_data.networks[idx] = nil
end
end
end
end