z_mirror/Krastorio2

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

Caleb HeuerMake loader snapping work with linked and proxy containersa2aa5f2a

real-fusion-reactor
4.6 KiB169 linesraw
1local flib_direction = require("__flib__.direction")
2local flib_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 belt_types = {
13  "linked-belt",
14  "loader",
15  "loader-1x1",
16  "splitter",
17  "transport-belt",
18  "underground-belt",
19}
20
21local container_types = {
22  "assembling-machine",
23  "beacon",
24  "boiler",
25  "burner-generator",
26  "container",
27  "curved-rail",
28  "furnace",
29  "infinity-container",
30  "lab",
31  "linked-container",
32  "logistic-container",
33  "mining-drill",
34  "proxy-container",
35  "rail",
36  "reactor",
37  "rocket-silo",
38  "straight-rail",
39}
40
41--- @param entity LuaEntity
42local function flip_loader(entity)
43  entity.direction = flib_direction.opposite(entity.direction)
44  entity.loader_type = entity.loader_type == "output" and "input" or "output"
45end
46
47--- Find entities and entity ghosts of the corresponding types.
48--- @param surface LuaSurface
49--- @param position MapPosition
50--- @param force ForceID
51--- @param types string[]
52--- @return LuaEntity[]
53local function find_entities(surface, position, force, types)
54  local entities = surface.find_entities_filtered({
55    force = force,
56    position = position,
57    type = types,
58  })
59  local ghosts = surface.find_entities_filtered({
60    force = force,
61    ghost_type = types,
62    position = position,
63  })
64  for i = 1, #ghosts do
65    entities[#entities + 1] = ghosts[i]
66  end
67  return entities
68end
69
70--- Ensure that the loader has the belt on the correct side.
71--- @param entity LuaEntity
72local function snap_direction(entity)
73  local offset_direction = entity.direction
74  if entity.loader_type == "input" then
75    offset_direction = flib_direction.opposite(offset_direction)
76  end
77  local container_position = flib_position.add(entity.position, offsets[offset_direction])
78
79  -- Case 1: If a container is in front, then flip the loader
80  local containers = find_entities(entity.surface, container_position, entity.force, container_types)
81  if #containers > 0 then
82    -- Check that it's not a composite loader entity
83    local is_composite = entity.surface.count_entities_filtered({
84      force = entity.force,
85      position = container_position,
86      type = { "loader", "loader-1x1" },
87    }) > 0
88    if not is_composite then
89      flip_loader(entity)
90      return
91    end
92  end
93
94  -- Case 2: If a belt is behind, then flip the loader
95  offset_direction = flib_direction.opposite(offset_direction)
96  local belt_position = flib_position.add(entity.position, offsets[offset_direction])
97  local belt = find_entities(entity.surface, belt_position, entity.force, belt_types)[1]
98  if not belt then
99    return
100  end
101
102  local belt_type = belt.type
103  if belt_type == "entity-ghost" then
104    belt_type = belt.ghost_type
105  end
106  if
107    belt_type == "transport-belt"
108    or belt_type == "underground-belt"
109    or math.abs(offset_direction - belt.direction) % 4 == 0
110  then
111    flip_loader(entity)
112  end
113end
114
115--- @param entity LuaEntity
116local function snap_to_belt(entity)
117  local offset_direction = entity.direction
118  if entity.loader_type == "input" then
119    offset_direction = flib_direction.opposite(offset_direction)
120  end
121  local belt_position = flib_position.add(entity.position, offsets[offset_direction])
122
123  local belt = find_entities(entity.surface, belt_position, entity.force, belt_types)[1]
124  if not belt then
125    return
126  end
127
128  local belt_direction = belt.direction
129  local belt_type = belt.type
130  if belt_type == "entity-ghost" then
131    belt_type = belt.ghost_type
132  end
133  if entity.direction == belt_direction then
134    -- Pass
135  elseif entity.direction == flib_direction.opposite(belt_direction) then
136    entity.loader_type = "input"
137  elseif belt_type == "transport-belt" or belt_type == "underground-belt" then
138    -- Sideloading
139    entity.loader_type = "output"
140  end
141end
142
143--- @param e EntityBuiltEvent
144local function on_entity_built(e)
145  local entity = e.entity or e.destination
146  if not entity.valid or not string.match(entity.name, "^kr.*%-loader$") then
147    return
148  end
149
150  entity.update_connections()
151  if not entity.loader_container then
152    snap_direction(entity)
153  end
154
155  snap_to_belt(entity)
156end
157
158local snap_loader = {}
159
160snap_loader.events = {
161  [defines.events.on_built_entity] = on_entity_built,
162  [defines.events.on_entity_cloned] = on_entity_built,
163  [defines.events.on_robot_built_entity] = on_entity_built,
164  [defines.events.script_raised_built] = on_entity_built,
165  [defines.events.script_raised_revive] = on_entity_built,
166  [defines.events.on_space_platform_built_entity] = on_entity_built,
167}
168
169return snap_loader