z_mirror/EditorExtensions

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

Patrick 'Quezler' MounierMerge branch 'master' into patch-1e65a4b6

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