z_mirror/Krastorio2

git clone https://git.raiguard.me/z_mirror/Krastorio2

Caleb HeuerDiagnostic fixes45624855

santichu95/patch-1
6.4 KiB242 linesraw
1local flib_gui = require("__flib__.gui")
2
3local constants = require("scripts.constants")
4local util = require("scripts.util")
5
6-- GUI
7
8--- @param player LuaPlayer
9--- @param entity LuaEntity
10local function update_gui(player, entity)
11  local player_gui = storage.roboport_guis[player.index]
12  if not player_gui or not player_gui.valid then
13    return
14  end
15  local mode = string.match(entity.name, "^.*%-(%w*)%-mode") or "normal"
16
17  for _, button in pairs(player_gui.inner_frame.children) do
18    if button.name == mode then
19      button.state = true
20    else
21      button.state = false
22    end
23  end
24end
25
26--- @param entity LuaEntity
27--- @param player LuaPlayer
28--- @param to_mode string?
29local function change_mode(entity, player, to_mode)
30  local matched, _, base_name, suffix = string.find(entity.name, "^(.-)(%-%w-%-mode)$")
31  if not matched then
32    base_name = entity.name
33    suffix = ""
34  end
35
36  local new_mode_data
37  if to_mode then
38    new_mode_data = constants.roboport_modes[to_mode]
39  else
40    new_mode_data = constants.roboport_modes[constants.next_roboport_mode[suffix]]
41  end
42
43  local new_name = base_name .. new_mode_data.suffix
44
45  if not prototypes.entity[new_name] then
46    util.flying_text_with_sound(player, { "message.kr-roboport-modes-not-supported" }, { position = entity.position })
47    return
48  end
49
50  local energy = entity.energy
51  local health = entity.health
52
53  -- Find all players that have this roboport open
54  -- This must be done before the roboport is swapped
55  local guis_to_update = {}
56  for player_index in pairs(storage.roboport_guis) do
57    local gui_player = game.get_player(player_index)
58    if gui_player and gui_player.opened_gui_type == defines.gui_type.entity then
59      local opened = gui_player.opened
60      if opened and opened == entity then
61        table.insert(guis_to_update, gui_player)
62      end
63    end
64  end
65
66  local new_entity = entity.surface.create_entity({
67    name = new_name,
68    position = entity.position,
69    force = entity.force,
70    direction = entity.direction,
71    fast_replace = true,
72    raise_built = true,
73    spill = false,
74    create_build_effect_smoke = false,
75  })
76
77  if new_entity then
78    new_entity.energy = energy
79    new_entity.health = health
80    new_entity.last_user = player
81
82    util.change_mode_fx(new_entity, { "message.kr-" .. new_mode_data.text .. "-mode" }, new_mode_data.color)
83
84    -- Re-open GUI for all players who had it open and update the radio buttons
85    for _, gui_player in pairs(guis_to_update) do
86      gui_player.opened = new_entity
87      update_gui(gui_player, new_entity)
88    end
89  end
90end
91
92--- @param e EventData.on_gui_checked_state_changed
93local function on_mode_radio_button_checked(e)
94  local player = game.get_player(e.player_index)
95  if not player or player.opened_gui_type ~= defines.gui_type.entity then
96    return
97  end
98  local entity = player.opened --[[@as LuaEntity]]
99  if not entity.valid or entity.type ~= "roboport" then
100    return
101  end
102  change_mode(entity, player, e.element.name)
103end
104
105--- @param mode string
106local function radio_button(mode)
107  return {
108    type = "radiobutton",
109    name = mode,
110    caption = { "message.kr-" .. mode .. "-mode" },
111    state = false,
112    handler = { [defines.events.on_gui_checked_state_changed] = on_mode_radio_button_checked },
113  }
114end
115
116--- @param player_index uint
117local function destroy_gui(player_index)
118  local player_gui = storage.roboport_guis[player_index]
119  if not player_gui then
120    return
121  end
122  if player_gui.valid then
123    player_gui.destroy()
124  end
125  storage.roboport_guis[player_index] = nil
126end
127
128--- @param player LuaPlayer
129local function refresh_gui(player)
130  destroy_gui(player.index)
131
132  _, storage.roboport_guis[player.index] = flib_gui.add(player.gui.relative, {
133    type = "frame",
134    name = "kr_roboport_mode_window",
135    caption = { "gui.kr-change-mode" },
136    anchor = {
137      gui = defines.relative_gui_type.roboport_gui,
138      position = defines.relative_gui_position.right,
139      names = storage.roboport_has_variants_gui,
140    },
141    {
142      type = "frame",
143      name = "inner_frame",
144      style = "inside_shallow_frame_with_padding",
145      direction = "vertical",
146      radio_button("normal"),
147      radio_button("construction"),
148      radio_button("logistic"),
149    },
150  })
151end
152
153local function find_variants()
154  -- Find all compatible roboports
155  local has_variants_gui = {}
156  for _, entity in pairs(prototypes.get_entity_filtered({ { filter = "type", type = "roboport" } })) do
157    local matched, _, base_name = string.find(entity.name, "^(.-)%-%w*%-mode")
158    if matched then
159      has_variants_gui[base_name] = true
160      has_variants_gui[entity.name] = true
161    end
162  end
163
164  -- Convert to a format usable by GuiAnchor
165  local output = {}
166  local i = 0
167  for entity in pairs(has_variants_gui) do
168    i = i + 1
169    output[i] = entity
170  end
171
172  storage.roboport_has_variants_gui = output
173end
174
175--- @param e EventData.on_gui_opened
176local function on_gui_opened(e)
177  local entity = e.entity
178  if not entity or not entity.valid then
179    return
180  end
181  local player = game.get_player(e.player_index)
182  if not player then
183    return
184  end
185  if entity.type == "roboport" then
186    update_gui(player, entity)
187  end
188end
189
190--- @param e EventData.on_player_created
191local function on_player_created(e)
192  local player = game.get_player(e.player_index)
193  if player then
194    refresh_gui(player)
195  end
196end
197
198--- @param e EventData.on_player_removed
199local function on_player_removed(e)
200  destroy_gui(e.player_index)
201end
202
203--- @param e EventData.CustomInputEvent
204local function on_change_roboport_mode_hotkey(e)
205  local player = game.get_player(e.player_index)
206  if not player then
207    return
208  end
209  local selected = player.selected
210  if selected and selected.valid and selected.type == "roboport" then
211    change_mode(selected, player)
212  end
213end
214
215local function on_configuration_changed()
216  find_variants()
217  for _, player in pairs(game.players) do
218    refresh_gui(player)
219  end
220end
221
222local function on_init()
223  --- @type table<uint, LuaGuiElement>
224  storage.roboport_guis = {}
225  on_configuration_changed()
226end
227
228local roboport = {}
229
230roboport.on_init = on_init
231roboport.on_configuration_changed = on_configuration_changed
232
233roboport.events = {
234  [defines.events.on_gui_opened] = on_gui_opened,
235  [defines.events.on_player_created] = on_player_created,
236  [defines.events.on_player_removed] = on_player_removed,
237  ["kr-change-roboport-state"] = on_change_roboport_mode_hotkey,
238}
239
240flib_gui.add_handlers({ roboport_on_mode_radio_button_checked = on_mode_radio_button_checked })
241
242return roboport