z_mirror/Krastorio2

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

Caleb HeuerChange to four-space indentation07409ca6

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