z_mirror/Krastorio2

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

Caleb HeuerChange to four-space indentation07409ca6

four-space-indentation
5.0 KiB170 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
158--- @class LoaderSnappingHandler : event_handler
159local snap_loader = {}
160
161snap_loader.events = {
162    [defines.events.on_built_entity] = on_entity_built,
163    [defines.events.on_entity_cloned] = on_entity_built,
164    [defines.events.on_robot_built_entity] = on_entity_built,
165    [defines.events.script_raised_built] = on_entity_built,
166    [defines.events.script_raised_revive] = on_entity_built,
167    [defines.events.on_space_platform_built_entity] = on_entity_built,
168}
169
170return snap_loader