z_mirror/EditorExtensions

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

Caleb HeuerImprove handler naming consistencyb32ba01

hidden-items
6.2 KiB221 linesraw
1local direction_util = require("__flib__/direction")
2local position = require("__flib__/position")
3
4--- @type table<defines.direction, Vector>
5local offsets = {
6  [defines.direction.north] = { 0, -1 },
7  [defines.direction.east] = { 1, 0 },
8  [defines.direction.south] = { 0, 1 },
9  [defines.direction.west] = { -1, 0 },
10}
11
12local transport_belt_connectables = {
13  "transport-belt",
14  "underground-belt",
15  "splitter",
16  "loader",
17  "loader-1x1",
18  "linked-belt",
19}
20
21--- @param entity LuaEntity
22local function snap(entity)
23  local offset_direction = entity.direction
24  if entity.loader_type == "input" then
25    offset_direction = direction_util.opposite(offset_direction)
26  end
27  local belt_position = position.add(entity.position, offsets[offset_direction])
28  local belt =
29    entity.surface.find_entities_filtered({ position = belt_position, type = transport_belt_connectables })[1]
30  if not belt then
31    belt =
32      entity.surface.find_entities_filtered({ position = belt_position, ghost_type = transport_belt_connectables })[1]
33  end
34  if not belt then
35    return
36  end
37  if belt.direction == direction_util.opposite(entity.direction) then
38    entity.loader_type = entity.loader_type == "output" and "input" or "output"
39  end
40end
41
42--- @param entity LuaEntity
43--- @param chest LuaEntity?
44local function sync_chest_filter(entity, chest)
45  if not chest then
46    chest = entity.surface.find_entity("ee-infinity-loader-chest", entity.position)
47  end
48  if not chest then
49    entity.destroy()
50    return
51  end
52  local filter = entity.get_filter(1)
53  if filter then
54    chest.set_infinity_container_filter(1, {
55      index = 1,
56      name = filter,
57      count = game.item_prototypes[filter].stack_size * 5,
58      mode = "exactly",
59    })
60  else
61    chest.set_infinity_container_filter(1, nil)
62  end
63end
64
65--- @param loader LuaEntity
66--- @param combinator LuaEntity
67local function copy_from_loader_to_combinator(loader, combinator)
68  local filter = loader.get_filter(1)
69  if not filter then
70    return
71  end
72  local cb = combinator.get_or_create_control_behavior() --[[@as LuaConstantCombinatorControlBehavior]]
73  cb.set_signal(1, {
74    signal = { type = "item", name = filter },
75    count = 1,
76  })
77end
78
79--- @param combinator LuaEntity
80--- @param loader LuaEntity
81local function copy_from_combinator_to_loader(combinator, loader)
82  local cb = combinator.get_control_behavior() --[[@as LuaConstantCombinatorControlBehavior?]]
83  if not cb then
84    return
85  end
86  local signal = cb.get_signal(1)
87  if signal.signal and signal.signal.type == "item" then
88    loader.set_filter(1, signal.signal.name)
89  else
90    loader.set_filter(1, nil)
91  end
92  sync_chest_filter(loader)
93end
94
95--- @param e BuiltEvent
96local function on_entity_built(e)
97  local entity = e.entity or e.created_entity or e.destination
98  if not entity.valid then
99    return
100  end
101
102  if entity.name ~= "ee-infinity-loader" then
103    return
104  end
105
106  -- Create chest
107  local chest = entity.surface.create_entity({
108    name = "ee-infinity-loader-chest",
109    position = entity.position,
110    force = entity.force,
111    create_build_effect_smoke = false,
112    raise_built = true,
113  })
114
115  if not chest then
116    entity.destroy()
117    return
118  end
119
120  chest.remove_unfiltered_items = true
121  sync_chest_filter(entity, chest)
122  snap(entity)
123end
124
125--- @param e DestroyedEvent
126local function on_entity_destroyed(e)
127  local entity = e.entity
128  if not entity.valid or entity.name ~= "ee-infinity-loader" then
129    return
130  end
131  local chest = entity.surface.find_entity("ee-infinity-loader-chest", entity.position)
132  if chest then
133    chest.destroy({ raise_destroy = true })
134  end
135end
136
137--- @param e EventData.on_player_rotated_entity
138local function on_entity_rotated(e)
139  local entity = e.entity
140  if not entity.valid or entity.name ~= "ee-infinity-loader" then
141    return
142  end
143  sync_chest_filter(entity)
144end
145
146--- @param e EventData.on_entity_settings_pasted
147local function on_entity_settings_pasted(e)
148  local source, destination = e.source, e.destination
149  local source_is_loader, destination_is_loader =
150    source.name == "ee-infinity-loader", destination.name == "ee-infinity-loader"
151  if source_is_loader and destination.name == "constant-combinator" then
152    copy_from_loader_to_combinator(source, destination)
153  elseif source.name == "constant-combinator" and destination_is_loader then
154    copy_from_combinator_to_loader(source, destination)
155  elseif destination_is_loader then
156    sync_chest_filter(destination)
157  end
158end
159
160--- @param e EventData.on_gui_opened
161local function on_gui_opened(e)
162  if e.gui_type ~= defines.gui_type.entity then
163    return
164  end
165  local entity = e.entity
166  if not entity or not entity.valid then
167    return
168  end
169  if entity.name == "ee-infinity-loader" then
170    global.infinity_loader_open[e.player_index] = entity
171  end
172end
173
174--- @param e EventData.on_gui_closed
175local function on_gui_closed(e)
176  if e.gui_type ~= defines.gui_type.entity then
177    return
178  end
179  local loader = global.infinity_loader_open[e.player_index]
180  if loader and loader.valid then
181    sync_chest_filter(loader)
182    global.infinity_loader_open[e.player_index] = nil
183  end
184end
185
186local infinity_loader = {}
187
188function infinity_loader.on_init()
189  --- @type table<uint, LuaEntity>
190  global.infinity_loader_open = {}
191end
192
193infinity_loader.events = {
194  [defines.events.on_built_entity] = on_entity_built,
195  [defines.events.on_entity_cloned] = on_entity_built,
196  [defines.events.on_entity_died] = on_entity_destroyed,
197  [defines.events.on_entity_settings_pasted] = on_entity_settings_pasted,
198  [defines.events.on_gui_closed] = on_gui_closed,
199  [defines.events.on_gui_opened] = on_gui_opened,
200  [defines.events.on_player_mined_entity] = on_entity_destroyed,
201  [defines.events.on_player_rotated_entity] = on_entity_rotated,
202  [defines.events.on_robot_built_entity] = on_entity_built,
203  [defines.events.on_robot_mined_entity] = on_entity_destroyed,
204  [defines.events.script_raised_built] = on_entity_built,
205  [defines.events.script_raised_destroy] = on_entity_destroyed,
206  [defines.events.script_raised_revive] = on_entity_built,
207}
208
209infinity_loader.on_nth_tick = {
210  [15] = function()
211    for unit_number, loader in pairs(global.infinity_loader_open) do
212      if loader.valid then
213        sync_chest_filter(loader)
214      else
215        global.infinity_loader_open[unit_number] = nil
216      end
217    end
218  end,
219}
220
221return infinity_loader