z_mirror/EditorExtensions

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

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

Quezler/patch-1
8.7 KiB291 linesraw
1--- @class InfinityCargoWagonData
2--- @field flip integer
3--- @field proxy LuaEntity
4--- @field proxy_inv LuaInventory
5--- @field wagon LuaEntity
6--- @field wagon_inv LuaInventory
7--- @field wagon_last_position MapPosition
8--- @field wagon_name string
9
10--- @class InfinityFluidWagonData
11--- @field flip integer
12--- @field proxy LuaEntity
13--- @field proxy_fluidbox LuaFluidBox
14--- @field wagon LuaEntity
15--- @field wagon_last_position MapPosition
16--- @field wagon_name string
17
18local wagon_names = {
19  ["ee-infinity-cargo-wagon"] = true,
20  ["ee-infinity-fluid-wagon"] = true,
21}
22
23--- @param player LuaPlayer
24--- @param entity LuaEntity
25local function open_gui(player, entity)
26  player.opened = storage.wagons[entity.unit_number].proxy
27end
28
29--- @param e BuiltEvent
30local function on_entity_built(e)
31  local entity = e.entity or e.destination
32  if not entity or not entity.valid or not wagon_names[entity.name] then
33    return
34  end
35
36  local proxy = entity.surface.create_entity({
37    name = "ee-infinity-wagon-" .. (entity.name == "ee-infinity-cargo-wagon" and "chest" or "pipe"),
38    position = entity.position,
39    force = entity.force,
40  })
41  if not proxy then
42    return
43  end
44
45  -- Create all api lookups here to save time in on_tick()
46  local data = {
47    flip = 0,
48    proxy = proxy,
49    proxy_fluidbox = proxy.fluidbox,
50    proxy_inv = proxy.get_inventory(defines.inventory.chest),
51    wagon = entity,
52    wagon_inv = entity.get_inventory(defines.inventory.cargo_wagon),
53    wagon_last_position = entity.position,
54    wagon_name = entity.name,
55  }
56  storage.wagons[entity.unit_number] = data
57
58  -- Apply any pre-existing filters
59  local tags = e.tags
60  if not tags or not tags.EditorExtensions then
61    return
62  end
63  local tags = tags.EditorExtensions
64  if entity.name == "ee-infinity-cargo-wagon" then
65    -- LEGACY: Before v1.9.16, we did not store the `remove unfiltered items` setting
66    if tags.filters then
67      data.proxy.infinity_container_filters = tags.filters
68      data.proxy.remove_unfiltered_items = tags.remove_unfiltered_items
69    else
70      --- @cast tags InfinityInventoryFilter[]
71      data.proxy.infinity_container_filters = tags
72    end
73  elseif entity.name == "ee-infinity-fluid-wagon" then
74    --- @cast tags InfinityPipeFilter
75    proxy.set_infinity_pipe_filter(tags)
76  end
77end
78
79--- @param e DestroyedEvent
80local function on_entity_destroyed(e)
81  local entity = e.entity
82  if not entity or not entity.valid or not wagon_names[entity.name] then
83    return
84  end
85
86  local proxy = storage.wagons[entity.unit_number].proxy
87  if proxy and proxy.valid then
88    proxy.destroy({})
89  end
90  storage.wagons[entity.unit_number] = nil
91end
92
93--- @param e EventData.on_marked_for_deconstruction
94local function on_marked_for_deconstruction(e)
95  local entity = e.entity
96  if not entity.valid or entity.name ~= "ee-infinity-cargo-wagon" then
97    return
98  end
99  storage.wagons[entity.unit_number].flip = 3
100  entity.get_inventory(defines.inventory.cargo_wagon).clear()
101end
102
103--- @param e EventData.on_cancelled_deconstruction
104local function on_cancelled_deconstruction(e)
105  local entity = e.entity
106  if not entity.valid or entity.name ~= "ee-infinity-cargo-wagon" then
107    return
108  end
109  -- Resume syncing
110  storage.wagons[entity.unit_number].flip = 0
111end
112
113--- @param data InfinityCargoWagonData
114local function sync_cargo(data)
115  if data.flip == 0 then
116    data.wagon_inv.clear()
117    for _, item in pairs(data.proxy_inv.get_contents()) do
118      data.wagon_inv.insert({ name = item.name, count = item.count, quality = item.quality })
119    end
120    data.flip = 1
121  elseif data.flip == 1 then
122    data.proxy_inv.clear()
123    for _, item in pairs(data.wagon_inv.get_contents()) do
124      data.proxy_inv.insert({ name = item.name, count = item.count, quality = item.quality })
125    end
126    data.flip = 0
127  end
128end
129
130local abs = math.abs
131
132--- @param data InfinityFluidWagonData
133local function sync_fluid(data)
134  if data.flip == 0 then
135    local fluid = data.proxy_fluidbox[1]
136    data.wagon.set_fluid(1, fluid and fluid.amount > 0 and {
137      name = fluid.name,
138      amount = (abs(fluid.amount) * 250),
139      temperature = fluid.temperature,
140    } or nil)
141    data.flip = 1
142  elseif data.flip == 1 then
143    local fluid = data.wagon.get_fluid(1)
144    data.proxy_fluidbox[1] = fluid
145        and fluid.amount > 0
146        and {
147          name = fluid.name,
148          amount = (abs(fluid.amount) / 250),
149          temperature = fluid.temperature,
150        }
151      or nil
152    data.flip = 0
153  end
154end
155
156local function on_tick()
157  for unit_number, data in pairs(storage.wagons) do
158    if not data.wagon.valid or not data.proxy.valid then
159      if data.wagon.valid then
160        data.wagon.destroy({ raise_destroy = true })
161      end
162      if data.proxy.valid then
163        data.proxy.destroy({ raise_destroy = true })
164      end
165      storage.wagons[unit_number] = nil
166      goto continue
167    end
168    if data.wagon_name == "ee-infinity-cargo-wagon" then
169      --- @cast data InfinityCargoWagonData
170      sync_cargo(data)
171    elseif data.wagon_name == "ee-infinity-fluid-wagon" then
172      --- @cast data InfinityFluidWagonData
173      sync_fluid(data)
174    end
175    local position = data.wagon.position
176    local last_position = data.wagon_last_position
177    if not last_position or last_position.x ~= position.x or last_position.y ~= position.y then
178      data.proxy.teleport(data.wagon.position)
179      data.wagon_last_position = data.wagon.position
180    end
181    ::continue::
182  end
183end
184
185--- @param e EventData.on_gui_opened
186local function on_gui_opened(e)
187  local player = game.get_player(e.player_index)
188  if not player then
189    return
190  end
191  local entity = e.entity
192  if not entity or not entity.valid or not wagon_names[entity.name] then
193    return
194  end
195  open_gui(player, entity)
196end
197
198--- @param e EventData.CustomInputEvent
199local function on_linked_open_gui(e)
200  local player = game.get_player(e.player_index)
201  if not player then
202    return
203  end
204  local entity = player.selected
205  if not entity or entity.name ~= "ee-infinity-fluid-wagon" then
206    return
207  end
208  if not player.can_reach_entity(entity) then
209    return
210  end
211  open_gui(player, entity)
212end
213
214--- @param e EventData.on_entity_settings_pasted
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 not wagon_names[source.name] or not wagon_names[destination.name] then
221    return
222  end
223  if source.name ~= destination.name then
224    return
225  end
226
227  storage.wagons[destination.unit_number].proxy.copy_settings(storage.wagons[source.unit_number].proxy)
228end
229
230--- @param e EventData.on_player_setup_blueprint
231local function on_player_setup_blueprint(e)
232  local blueprint = e.stack or e.record
233  if not blueprint then
234    return
235  end
236
237  local entities = blueprint.get_blueprint_entities()
238  if not entities then
239    return
240  end
241  for i, entity in pairs(entities) do
242    --- @cast i uint
243    if not wagon_names[entity.name] then
244      goto continue
245    end
246    local real_entity = e.surface.find_entity(entity.name, entity.position)
247    if not real_entity then
248      goto continue
249    end
250    local proxy = storage.wagons[real_entity.unit_number].proxy
251    local tags = {}
252    if entity.name == "ee-infinity-cargo-wagon" then
253      tags.filters = proxy.infinity_container_filters
254      tags.remove_unfiltered_items = proxy.remove_unfiltered_items
255    else
256      tags = proxy.get_infinity_pipe_filter()
257    end
258    blueprint.set_blueprint_entity_tag(i, "EditorExtensions", tags --[[@as AnyBasic]])
259    ::continue::
260  end
261end
262
263local infinity_wagon = {}
264
265infinity_wagon.on_init = function()
266  --- @type table<uint, InfinityCargoWagonData|InfinityFluidWagonData>
267  storage.wagons = {}
268end
269
270infinity_wagon.events = {
271  [defines.events.on_built_entity] = on_entity_built,
272  [defines.events.on_cancelled_deconstruction] = on_cancelled_deconstruction,
273  [defines.events.on_entity_cloned] = on_entity_built,
274  [defines.events.on_entity_died] = on_entity_destroyed,
275  [defines.events.on_entity_settings_pasted] = on_entity_settings_pasted,
276  [defines.events.on_gui_opened] = on_gui_opened,
277  [defines.events.on_marked_for_deconstruction] = on_marked_for_deconstruction,
278  [defines.events.on_player_mined_entity] = on_entity_destroyed,
279  [defines.events.on_player_setup_blueprint] = on_player_setup_blueprint,
280  [defines.events.on_robot_built_entity] = on_entity_built,
281  [defines.events.on_robot_mined_entity] = on_entity_destroyed,
282  [defines.events.on_tick] = on_tick,
283  [defines.events.script_raised_built] = on_entity_built,
284  [defines.events.script_raised_destroy] = on_entity_destroyed,
285  [defines.events.script_raised_revive] = on_entity_built,
286  [defines.events.on_space_platform_built_entity] = on_entity_built,
287  [defines.events.on_space_platform_mined_entity] = on_entity_destroyed,
288  ["ee-linked-open-gui"] = on_linked_open_gui,
289}
290
291return infinity_wagon