z_mirror/EditorExtensions

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

Caleb HeuerRefactor linked belt5063e34

1.14
6.7 KiB254 linesraw
1local util = require("__EditorExtensions__/scripts/util")
2
3--- @param objects table
4--- @param color Color
5--- @param dashed boolean
6--- @param player_index uint
7--- @param source LuaEntity
8--- @param destination LuaEntity?
9local function draw_connection(objects, color, dashed, player_index, source, destination)
10  for _, entity in pairs({ source, destination }) do
11    objects[#objects + 1] = rendering.draw_circle({
12      color = color,
13      radius = 0.15,
14      width = 2,
15      filled = not dashed,
16      target = entity.position,
17      surface = entity.surface,
18      players = { player_index },
19    })
20  end
21  if destination and source.surface == destination.surface then
22    objects[#objects + 1] = rendering.draw_line({
23      color = color,
24      width = 2,
25      gap_length = dashed and 0.3 or 0,
26      dash_length = dashed and 0.3 or 0,
27      from = source.position,
28      to = destination.position,
29      surface = source.surface,
30      players = { player_index },
31    })
32  end
33end
34
35--- @type table<string, Color>
36local colors = {
37  red = { r = 1, g = 0.5, b = 0.5 },
38  green = { r = 0.3, g = 0.8, b = 0.3 },
39  teal = { r = 0.5, g = 1, b = 1 },
40}
41
42--- @param player LuaPlayer
43local function render_connection(player)
44  local objects = global.linked_belt_render_objects[player.index] or {}
45  for i = #objects, 1, -1 do
46    rendering.destroy(objects[i])
47    objects[i] = nil
48  end
49
50  local source = global.linked_belt_source[player.index]
51  local selected = player.selected
52  if selected and selected.name ~= "ee-linked-belt" then
53    selected = nil
54  end
55
56  if selected then
57    local neighbour = selected.linked_belt_neighbour
58    if neighbour and neighbour ~= source then
59      draw_connection(objects, colors.green, false, player.index, selected, neighbour)
60    end
61  end
62
63  if source and source.valid then
64    local neighbour = source.linked_belt_neighbour
65    if neighbour then
66      draw_connection(objects, colors.red, false, player.index, source, neighbour)
67    end
68    if selected and selected ~= neighbour then
69      draw_connection(objects, colors.teal, true, player.index, source, selected)
70    end
71    draw_connection(objects, colors.teal, true, player.index, source)
72  end
73
74  if objects[1] then
75    global.linked_belt_render_objects[player.index] = objects
76  else
77    global.linked_belt_render_objects[player.index] = nil
78  end
79end
80
81--- @param player LuaPlayer
82--- @param entity LuaEntity
83--- @param shift boolean?
84local function start_connection(player, entity, shift)
85  local neighbour = entity.linked_belt_neighbour
86  local source
87  if neighbour then
88    if shift then
89      source = neighbour
90    else
91      source = entity
92    end
93  else
94    source = entity
95  end
96  global.linked_belt_source[player.index] = source
97
98  render_connection(player)
99end
100
101--- @param player LuaPlayer
102--- @param entity LuaEntity
103--- @param shift boolean?
104local function finish_connection(player, entity, shift)
105  local source = global.linked_belt_source[player.index]
106  if not source or not source.valid then
107    return
108  end
109
110  local neighbour = entity.linked_belt_neighbour
111  if entity.unit_number == source.unit_number then
112    return
113  end
114  if neighbour and not shift then
115    util.flying_text(player, { "message.ee-connection-blocked" }, true, entity.position)
116    return
117  end
118  if neighbour then
119    entity.disconnect_linked_belts()
120  end
121
122  entity.linked_belt_type = source.linked_belt_type == "input" and "output" or "input"
123  entity.connect_linked_belts(source)
124
125  global.linked_belt_source[player.index] = nil
126
127  render_connection(player)
128end
129
130--- @param player LuaPlayer
131local function cancel_connection(player)
132  local source = global.linked_belt_source[player.index]
133  if not source then
134    return
135  end
136  global.linked_belt_source[player.index] = nil
137  render_connection(player)
138end
139
140--- @param e EventData.on_player_rotated_entity
141local function on_player_rotated_entity(e)
142  local entity = e.entity
143  if entity.name ~= "ee-linked-belt" then
144    return
145  end
146
147  entity.direction = e.previous_direction
148
149  local neighbour = entity.linked_belt_neighbour
150  if neighbour then
151    -- disconnect, flip both ends, reconnect
152    entity.disconnect_linked_belts()
153    entity.linked_belt_type = entity.linked_belt_type == "output" and "input" or "output"
154    neighbour.linked_belt_type = neighbour.linked_belt_type == "output" and "input" or "output"
155    entity.connect_linked_belts(neighbour)
156  else
157    entity.linked_belt_type = entity.linked_belt_type == "output" and "input" or "output"
158  end
159end
160
161--- @param e EventData.on_selected_entity_changed
162local function on_selected_entity_changed(e)
163  local player = game.get_player(e.player_index)
164  if not player then
165    return
166  end
167
168  render_connection(player)
169end
170
171--- @param e EventData.CustomInputEvent
172local function on_clear_cursor(e)
173  local player = game.get_player(e.player_index)
174  if not player then
175    return
176  end
177  cancel_connection(player)
178end
179
180--- @param e EventData.CustomInputEvent
181local function on_left_click(e)
182  local player = game.get_player(e.player_index)
183  if not player then
184    return
185  end
186
187  local selected = player.selected
188  if not selected or selected.name ~= "ee-linked-belt" then
189    return
190  end
191
192  local source = global.linked_belt_source[e.player_index]
193  if source then
194    finish_connection(player, selected)
195  else
196    start_connection(player, selected)
197  end
198end
199
200--- @param e EventData.CustomInputEvent
201local function on_shift_left_click(e)
202  local player = game.get_player(e.player_index)
203  if not player then
204    return
205  end
206
207  local selected = player.selected
208  if not selected or selected.name ~= "ee-linked-belt" then
209    return
210  end
211
212  local source = global.linked_belt_source[e.player_index]
213  if source then
214    finish_connection(player, selected, true)
215  else
216    start_connection(player, selected, true)
217  end
218end
219
220--- @param e EventData.CustomInputEvent
221local function on_shift_right_click(e)
222  local player = game.get_player(e.player_index)
223  if not player then
224    return
225  end
226
227  local selected = player.selected
228  if not selected or selected.name ~= "ee-linked-belt" or not selected.linked_belt_neighbour then
229    return
230  end
231
232  selected.disconnect_linked_belts()
233  render_connection(player)
234end
235
236local linked_belt = {}
237
238linked_belt.on_init = function()
239  --- @type table<uint, LuaEntity>
240  global.linked_belt_source = {}
241  --- @type table<uint, uint64[]>
242  global.linked_belt_render_objects = {}
243end
244
245linked_belt.events = {
246  [defines.events.on_player_rotated_entity] = on_player_rotated_entity,
247  [defines.events.on_selected_entity_changed] = on_selected_entity_changed,
248  ["ee-linked-clear-cursor"] = on_clear_cursor,
249  ["ee-linked-copy-entity-settings"] = on_shift_right_click,
250  ["ee-linked-open-gui"] = on_left_click,
251  ["ee-linked-paste-entity-settings"] = on_shift_left_click,
252}
253
254return linked_belt