1
1
require " config"
2
2
3
+ local mod_version = " 0.0.2"
4
+ local mod_data_version = " 0.0.2"
5
+
3
6
termbelts = {}
4
7
curvebelts = {}
5
8
@@ -24,6 +27,27 @@ local function pos2s(pos)
24
27
return ' '
25
28
end
26
29
30
+ local function rotate_pos (pos ,dir )
31
+ local x ,y = pos .x ,pos .y
32
+ if not x then
33
+ x ,y = pos [1 ],pos [2 ]
34
+ end
35
+ if dir == defines .direction .north then
36
+ elseif dir == defines .direction .south then
37
+ x = - x
38
+ y = - y
39
+ elseif dir == defines .direction .east then
40
+ t = x
41
+ x = - y
42
+ y = t
43
+ elseif dir == defines .direction .west then
44
+ t = x
45
+ x = y
46
+ y = - t
47
+ end
48
+ return {x ,y ,x = x ,y = y }
49
+ end
50
+
27
51
local belt_speeds = {basic = 1 ,fast = 2 ,express = 3 ,faster = 4 ,purple = 5 }
28
52
29
53
-- starting_entity is a belt(-like) entity, or a belt combinator
@@ -35,24 +59,16 @@ local function terminal_belt_lines(entity,entity_to_ignore)
35
59
if # entity .neighbours > 0 then
36
60
return {}
37
61
else
38
- return {3 ,4 }
62
+ return {1 , 2 , 3 ,4 }
39
63
end
40
64
end
41
65
local dir = entity .direction
42
66
local pos = entity .position
43
67
local to_check = {}
44
68
if entity .type == " splitter" then
45
- if dir == defines .direction .north then
46
- to_check = {{pos = {x = pos .x - 0.5 ,y = pos .y },lines = {5 ,6 }},{pos = {x = pos .x + 0.5 ,y = pos .y },lines = {7 ,8 }}}
47
- elseif dir == defines .direction .south then
48
- to_check = {{pos = {x = pos .x + 0.5 ,y = pos .y },lines = {5 ,6 }},{pos = {x = pos .x - 0.5 ,y = pos .y },lines = {7 ,8 }}}
49
- elseif dir == defines .direction .east then
50
- to_check = {{pos = {x = pos .x ,y = pos .y - 0.5 },lines = {5 ,6 }},{pos = {x = pos .x ,y = pos .y + 0.5 },lines = {7 ,8 }}}
51
- elseif dir == defines .direction .west then
52
- to_check = {{pos = {x = pos .x ,y = pos .y + 0.5 },lines = {5 ,6 }},{pos = {x = pos .x ,y = pos .y - 0.5 },lines = {7 ,8 }}}
53
- else
54
- debug (" invalid direction for splitter entity" )
55
- end
69
+ to_check = {
70
+ {pos = rotate_pos ({x = pos .x - 0.5 ,y = pos .y },dir ),lines = {5 ,6 }},
71
+ {pos = rotate_pos ({x = pos .x + 0.5 ,y = pos .y },dir ),lines = {7 ,8 }}}
56
72
elseif entity .type == " transport-belt-to-ground" and
57
73
entity .belt_to_ground_type == " input" then
58
74
to_check = {{pos = pos ,lines = {3 ,4 }}}
@@ -69,20 +85,8 @@ local function terminal_belt_lines(entity,entity_to_ignore)
69
85
-- following code originally copied from https://github.com/sparr/factorio-mod-belt-combinators
70
86
for _ ,check in pairs (to_check ) do
71
87
debug (" checking " .. pos2s (check .pos ))
72
- local tpos = {}
73
- if dir == defines .direction .north then
74
- tpos = {x = check .pos .x ,y = check .pos .y - 1 }
75
- elseif dir == defines .direction .south then
76
- tpos = {x = check .pos .x ,y = check .pos .y + 1 }
77
- elseif dir == defines .direction .east then
78
- tpos = {x = check .pos .x + 1 ,y = check .pos .y }
79
- elseif dir == defines .direction .west then
80
- tpos = {x = check .pos .x - 1 ,y = check .pos .y }
81
- else
82
- debug (' nil target position' )
83
- tpos = nil
84
- end
85
- local entities = game .get_surface (entity .surface .index ).find_entities ({tpos ,tpos })
88
+ local tpos = rotate_pos ({x = check .pos .x ,y = check .pos .y - 1 },dir )
89
+ local entities = game .get_surface (entity .surface .index ).find_entities ({{0 ,0 },{0 ,0 }})
86
90
local target = nil
87
91
for _ ,candidate in pairs (entities ) do
88
92
if candidate ~= entity_to_ignore then
@@ -129,40 +133,23 @@ local function terminal_belt_lines(entity,entity_to_ignore)
129
133
if target .type == ' transport-belt' then
130
134
local belt_behind_target = false
131
135
-- find a belt-like entity behind the target or on the far side
132
- local bpd = {}
133
- if target .direction == defines .direction .north then
134
- bpd [1 ]= {pos = {target .position .x ,target .position .y + 1 },dir = target .direction }
135
- elseif target .direction == defines .direction .south then
136
- bpd [1 ]= {pos = {target .position .x ,target .position .y - 1 },dir = target .direction }
137
- elseif target .direction == defines .direction .east then
138
- bpd [1 ]= {pos = {target .position .x - 1 ,target .position .y },dir = target .direction }
139
- elseif target .direction == defines .direction .west then
140
- bpd [1 ]= {pos = {target .position .x + 1 ,target .position .y },dir = target .direction }
141
- end
142
- if dir == defines .direction .north then
143
- bpd [2 ]= {pos = {pos .x ,pos .y - 2 },dir = defines .direction .south }
144
- elseif dir == defines .direction .south then
145
- bpd [2 ]= {pos = {pos .x ,pos .y + 2 },dir = defines .direction .north }
146
- elseif dir == defines .direction .east then
147
- bpd [2 ]= {pos = {pos .x + 2 ,pos .y },dir = defines .direction .east }
148
- elseif dir == defines .direction .west then
149
- bpd [2 ]= {pos = {pos .x - 2 ,pos .y },dir = defines .direction .west }
150
- end
151
- if # bpd > 0 then
152
- for _ ,bpos in pairs (bpd ) do
153
- local entities = game .get_surface (entity .surface .index ).find_entities ({bpos .pos ,bpos .pos })
154
- for _ ,candidate in pairs (entities ) do
155
- if candidate .type == " transport-belt" or
156
- candidate .type == " transport-belt-to-ground" or
157
- candidate .type == " splitter" then
158
- if candidate .direction == bpos .dir then
159
- belt_behind_target = true
160
- end
161
- break
136
+ local bpd = {
137
+ {pos = rotate_pos ({target .position .x ,target .position .y + 1 },target .direction ),dir = target .direction },
138
+ {pos = rotate_pos ({pos .x ,pos .y - 2 },dir ),dir = defines .direction .south }
139
+ }
140
+ for _ ,bpos in pairs (bpd ) do
141
+ local entities = game .get_surface (entity .surface .index ).find_entities ({bpos .pos ,bpos .pos })
142
+ for _ ,candidate in pairs (entities ) do
143
+ if candidate .type == " transport-belt" or
144
+ candidate .type == " transport-belt-to-ground" or
145
+ candidate .type == " splitter" then
146
+ if candidate .direction == bpos .dir then
147
+ belt_behind_target = true
162
148
end
149
+ break
163
150
end
164
- if belt_behind_target then break end
165
151
end
152
+ if belt_behind_target then break end
166
153
end
167
154
if not belt_behind_target then
168
155
turn = true
@@ -193,60 +180,73 @@ local function onTick(event)
193
180
else
194
181
local e = belt .entity
195
182
local pos = e .position
183
+ local line_caps = {}
184
+ if e .type == " transport-belt" then
185
+ if curvebelts [pos .y ] and curvebelts [pos .y ][pos .x ]== " right" then
186
+ line_caps = {5 ,2 }
187
+ elseif curvebelts [pos .y ] and curvebelts [pos .y ][pos .x ]== " left" then
188
+ line_caps = {2 ,5 }
189
+ else
190
+ line_caps = {4 ,4 }
191
+ end
192
+ elseif e .type == " transport-belt-to-ground" then
193
+ -- caps for lines 3/4 will get set iff 1/2 are full
194
+ line_caps = {2 ,2 ,9999 ,9999 }
195
+ elseif e .type == " splitter" then
196
+ line_caps = {nil ,nil ,nil ,nil ,2 ,2 ,2 ,2 }
197
+ end
196
198
for _ ,line in pairs (belt .lines ) do
197
199
-- debug(pos2s(pos)..' line '..line..':')
198
- local line_caps = {}
199
- if e .type == " transport-belt" then
200
- if curvebelts [pos .y ] and curvebelts [pos .y ][pos .x ]== " right" then
201
- line_caps = {5 ,2 }
202
- elseif curvebelts [pos .y ] and curvebelts [pos .y ][pos .x ]== " left" then
203
- line_caps = {2 ,5 }
204
- else
205
- line_caps = {4 ,4 }
206
- end
207
- elseif e .type == " transport-belt-to-ground" then
208
- line_caps = {2 ,2 ,4 ,4 }
209
- elseif e .type == " splitter" then
210
- line_caps = {nil ,nil ,nil ,nil ,2 ,2 ,2 ,2 }
211
- end
212
200
local tl = e .get_transport_line (line )
213
201
local item_name = nil
214
202
for name ,count in pairs (tl .get_contents ()) do
215
203
-- debug(line..' '..name..' '..count)
216
204
item_name = name
217
205
end
218
206
if tl .get_item_count ()>= line_caps [line ] then
219
- debug (" overflow " .. e .type .. " " .. line .. " " .. tl .get_item_count ())
220
- -- overflow!
221
- local x ,y = pos .x ,pos .y
222
- local dir = e .direction
223
- if dir == defines .direction .north then
224
- y = y - 0.75
225
- if e .type == " splitter" then
226
- if line == 5 or line == 6 then x = x - 0.5 else x = x + 0.5 end
227
- end
228
- elseif dir == defines .direction .south then
229
- y = y + 0.75
230
- if e .type == " splitter" then
231
- if line == 5 or line == 6 then x = x + 0.5 else x = x - 0.5 end
207
+ if e .type == " transport-belt-to-ground" and e .belt_to_ground_type == " input" and line < 3 then
208
+ -- overflow lines 3/4 iff 1/2 are full, and don't overflor 1/2
209
+ line_caps [line + 2 ] = 4
210
+ else
211
+ debug (" overflow " .. e .type .. " " .. line .. " " .. tl .get_item_count ())
212
+ -- overflow!
213
+ -- figure out where the overflow spot is
214
+ local x ,y = pos .x ,pos .y
215
+ local dir = e .direction
216
+ local dx ,dy = 0 ,0
217
+ if e .type == " transport-belt-to-ground" and e .belt_to_ground_type == " input" then
218
+ -- spill beside the underground input
219
+ dy = dy + 0.25
220
+ if (line % 2 )== 0 then
221
+ dx = dx + 0.65
222
+ else
223
+ dx = dx - 0.65
224
+ end
225
+ else
226
+ -- spill past the end of the belt
227
+ dy = dy - 0.85
228
+ if e .type == " splitter" then
229
+ if line == 5 or line == 6 then dx = dx - 0.5 else dx = dx + 0.5 end
230
+ end
231
+ if (line % 2 )== 0 then dx = dx + 0.23 else dx = dx - 0.23 end
232
232
end
233
- elseif dir == defines .direction .east then
234
- x = x + 0.75
235
- if e .type == " splitter" then
236
- if line == 5 or line == 6 then y = y - 0.5 else y = y + 0.5 end
233
+ -- rotate the coordinate deltas
234
+ local rp = rotate_pos ({dx ,dy },dir )
235
+ x = x + rp .x
236
+ y = y + rp .y
237
+ if e .surface .find_entity (" item-on-ground" , {x ,y }) then
238
+ e .surface .spill_item_stack ({x ,y }, {name = item_name , count = 1 })
239
+ else -- spill always skips the target spot, fill it first
240
+ e .surface .create_entity {name = " item-on-ground" ,
241
+ position = {x ,y }, force = e .force ,
242
+ stack = {name = item_name , count = 1 }}
237
243
end
238
- elseif dir == defines . direction . west then
239
- x = x - 0.75
240
- if e . type == " splitter " then
241
- if line == 5 or line == 6 then y = y + 0.5 else y = y - 0.5 end
244
+ if tl . remove_item ({ name = item_name , count = 1 }) == 0 then
245
+ debug ( " failed to remove " .. item_name )
246
+ else
247
+ debug ( " removed " .. item_name .. " at " .. pos2s ( pos ))
242
248
end
243
249
end
244
- e .surface .spill_item_stack ({x ,y }, {name = item_name , count = 1 })
245
- if tl .remove_item ({name = item_name , count = 1 })== 0 then
246
- debug (" failed to remove " .. item_name )
247
- else
248
- debug (" removed " .. item_name .. " at " .. pos2s (pos ))
249
- end
250
250
end
251
251
end
252
252
end
@@ -336,17 +336,42 @@ local function find_all_entities(args)
336
336
return entities
337
337
end
338
338
339
+ local function refreshGlobalData ()
340
+ global .terminal_belts = {}
341
+ global .curve_belts = {}
342
+ for _ ,type in pairs ({" transport-belt" ," transport-belt-to-ground" ," splitter" }) do
343
+ for _ ,e in pairs (find_all_entities {type = type }) do
344
+ check_and_update (e ,false ,true )
345
+ end
346
+ end
347
+ end
348
+
349
+ local function checkForMigration (old_version , new_version )
350
+ -- TODO: when a migration is necessary, trigger it here or set a flag.
351
+ end
352
+
353
+ local function checkForDataMigration (old_data_version , new_data_version )
354
+ -- TODO: when a migration is necessary, trigger it here or set a flag.
355
+ if old_data_version ~= new_data_version then
356
+ refreshGlobalData ()
357
+ end
358
+ end
359
+
339
360
local function onLoad ()
361
+ -- The only reason to have version/data_version is to trigger migrations, so do that here.
362
+ if global .version then
363
+ checkForMigration (global .version , mod_version )
364
+ end
365
+ if global .data_version then
366
+ checkForDataMigration (global .data_version , mod_data_version )
367
+ end
368
+
369
+ -- After these lines, we can no longer check for migration.
370
+ global .version = mod_version
371
+ global .data_version = mod_data_version
372
+
340
373
if global .terminal_belts == nil then
341
- global .terminal_belts = {}
342
- global .curve_belts = {}
343
- termbelts = global .terminal_belts
344
- curvebelts = global .curve_belts
345
- for _ ,type in pairs ({" transport-belt" ," transport-belt-to-ground" ," splitter" }) do
346
- for _ ,e in pairs (find_all_entities {type = type }) do
347
- check_and_update (e ,false ,true )
348
- end
349
- end
374
+ refreshGlobalData ()
350
375
end
351
376
352
377
curvebelts = global .curve_belts
0 commit comments