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