z_mirror/EditorExtensions

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

Caleb HeuerFix crash when opening star map468b48b

hidden-items
7.1 KiB273 linesraw
1local gui = require("__flib__/gui-lite")
2local math = require("__flib__/math")
3local table = require("__flib__/table")
4
5local util = require("__EditorExtensions__/scripts/util")
6
7--- @param entity LuaEntity
8--- @param speed double
9local function set_speed(entity, speed)
10  entity.fluidbox[2] = {
11    name = "ee-super-pump-speed-fluid",
12    amount = 100000000000,
13    temperature = speed + 0.01, -- avoid floating point imprecision
14  }
15end
16
17--- @param entity LuaEntity
18local function get_speed(entity)
19  return math.floor(entity.fluidbox[2].temperature)
20end
21
22local slider_to_temperature = {
23  [0] = 0,
24  [1] = 100,
25  [2] = 200,
26  [3] = 300,
27  [4] = 400,
28  [5] = 500,
29  [6] = 600,
30  [7] = 700,
31  [8] = 800,
32  [9] = 900,
33  [10] = 1000,
34  [11] = 2000,
35  [12] = 3000,
36  [13] = 4000,
37  [14] = 5000,
38  [15] = 6000,
39  [16] = 7000,
40  [17] = 8000,
41  [18] = 9000,
42  [19] = 10000,
43  [20] = 15000,
44  [21] = 20000,
45  [22] = 25000,
46  [23] = 30000,
47}
48local temperature_to_slider = table.invert(slider_to_temperature)
49
50--- @param speed double
51--- @return double
52local function to_slider_value(speed)
53  local index
54  if speed == 0 then
55    index = 0
56  elseif speed < 1000 then
57    index = math.floor(speed / 100) * 100
58  elseif speed < 10000 then
59    index = math.floor(speed / 1000) * 1000
60  elseif speed < 30000 then
61    index = math.floor(speed / 5000) * 5000
62  else
63    index = 30000
64  end
65  return temperature_to_slider[index]
66end
67
68--- @param value double
69--- @return double
70local function from_slider_value(value)
71  return slider_to_temperature[value]
72end
73
74--- @param entity LuaEntity
75--- @param flow LuaGuiElement
76local function update_gui(entity, flow)
77  local speed = get_speed(entity)
78
79  local textfield = flow.speed_textfield --[[@as LuaGuiElement]]
80  textfield.style = "ee_slider_textfield"
81  textfield.text = tostring(speed)
82
83  local slider = flow.speed_slider --[[@as LuaGuiElement]]
84  slider.slider_value = to_slider_value(speed)
85end
86
87local handlers = {
88  --- @param entity LuaEntity
89  --- @param e EventData.on_gui_value_changed
90  on_pump_speed_slider_value_changed = function(entity, e)
91    local new_speed = from_slider_value(e.element.slider_value)
92    set_speed(entity, new_speed)
93    update_gui(entity, e.element.parent)
94  end,
95
96  --- @param entity LuaEntity
97  --- @param e EventData.on_gui_text_changed
98  on_pump_speed_textfield_changed = function(entity, e)
99    local textfield = e.element
100    local text = textfield.text
101    local speed = tonumber(text)
102
103    if not speed or speed > 600000 then
104      textfield.style = "ee_invalid_slider_textfield"
105      return
106    end
107
108    set_speed(entity, speed)
109    update_gui(entity, e.element.parent)
110  end,
111}
112
113gui.add_handlers(handlers, function(e, handler)
114  local player = game.get_player(e.player_index)
115  if not player or player.opened_gui_type ~= defines.gui_type.entity then
116    return
117  end
118  local entity = player.opened
119  if not entity or not entity.valid then
120    return
121  end
122  if entity.name ~= "ee-super-pump" then
123    return
124  end
125  handler(entity, e)
126end)
127
128--- @param player LuaPlayer
129local function create_gui(player)
130  local existing = player.gui.relative.ee_super_pump_window
131  if existing then
132    existing.destroy()
133  end
134
135  gui.add(player.gui.relative, {
136    type = "frame",
137    name = "ee_super_pump_window",
138    style = "frame_with_even_paddings",
139    style_mods = { width = 448 },
140    anchor = {
141      gui = defines.relative_gui_type.entity_with_energy_source_gui,
142      position = defines.relative_gui_position.bottom,
143      name = "ee-super-pump",
144    },
145    {
146      type = "frame",
147      name = "inner_frame",
148      style = "inside_shallow_frame_with_padding",
149      {
150        type = "flow",
151        name = "inner_flow",
152        style = "centering_horizontal_flow",
153        { type = "label", caption = { "gui.ee-speed" }, tooltip = { "gui.ee-speed-tooltip" } },
154        {
155          type = "slider",
156          name = "speed_slider",
157          style_mods = { horizontally_stretchable = true, margin = { 0, 8, 0, 8 } },
158          minimum_value = 0,
159          maximum_value = 23,
160          value = 0,
161          handler = { [defines.events.on_gui_value_changed] = handlers.on_pump_speed_slider_value_changed },
162        },
163        {
164          type = "textfield",
165          name = "speed_textfield",
166          style = "ee_slider_textfield",
167          numeric = true,
168          clear_and_focus_on_right_click = true,
169          handler = { [defines.events.on_gui_text_changed] = handlers.on_pump_speed_textfield_changed },
170        },
171      },
172    },
173  })
174end
175
176--- @param e BuiltEvent
177local function on_entity_built(e)
178  local entity = e.created_entity or e.entity or e.destination
179  if not entity or not entity.valid or entity.name ~= "ee-super-pump" then
180    return
181  end
182  local speed = 12000
183  local tags = e.tags
184  if tags and tags.EditorExtensions then
185    speed = tags.EditorExtensions.speed --[[@as double]]
186  end
187  set_speed(entity, speed)
188end
189
190--- @param e EventData.on_player_setup_blueprint
191local function on_player_setup_blueprint(e)
192  local blueprint = util.get_blueprint(e)
193  if not blueprint then
194    return
195  end
196
197  local entities = blueprint.get_blueprint_entities()
198  if not entities then
199    return
200  end
201  for i, entity in pairs(entities) do
202    --- @cast i uint
203    if entity.name ~= "ee-super-pump" then
204      goto continue
205    end
206    local real_entity = e.surface.find_entity(entity.name, entity.position)
207    if not real_entity then
208      goto continue
209    end
210    blueprint.set_blueprint_entity_tag(i, "EditorExtensions", { speed = get_speed(real_entity) })
211    ::continue::
212  end
213end
214
215local function on_entity_settings_pasted(e)
216  local source, destination = e.source, e.destination
217  if not source.valid or not destination.valid then
218    return
219  end
220  if source.name ~= "ee-super-pump" or destination.name ~= "ee-super-pump" then
221    return
222  end
223  set_speed(destination, get_speed(source))
224end
225
226--- @param e EventData.on_gui_opened
227local function on_gui_opened(e)
228  local player = game.get_player(e.player_index)
229  if not player or player.opened_gui_type ~= defines.gui_type.entity then
230    return
231  end
232  local entity = e.entity
233  if not entity or not entity.valid then
234    return
235  end
236  if entity.name ~= "ee-super-pump" then
237    return
238  end
239
240  update_gui(entity, player.gui.relative.ee_super_pump_window.inner_frame.inner_flow)
241end
242
243--- @param e EventData.on_player_created
244local function on_player_created(e)
245  local player = game.get_player(e.player_index)
246  if not player then
247    return
248  end
249
250  create_gui(player)
251end
252
253local super_pump = {}
254
255super_pump.on_configuration_changed = function()
256  for _, player in pairs(game.players) do
257    create_gui(player)
258  end
259end
260
261super_pump.events = {
262  [defines.events.on_built_entity] = on_entity_built,
263  [defines.events.on_entity_cloned] = on_entity_built,
264  [defines.events.on_entity_settings_pasted] = on_entity_settings_pasted,
265  [defines.events.on_gui_opened] = on_gui_opened,
266  [defines.events.on_player_created] = on_player_created,
267  [defines.events.on_player_setup_blueprint] = on_player_setup_blueprint,
268  [defines.events.on_robot_built_entity] = on_entity_built,
269  [defines.events.script_raised_built] = on_entity_built,
270  [defines.events.script_raised_revive] = on_entity_built,
271}
272
273return super_pump