Skip to content

Commit 0b099e5

Browse files
committed
v0.0.2, better spill locations, code deduplication, bug fixes
1 parent 7835a72 commit 0b099e5

File tree

2 files changed

+133
-108
lines changed

2 files changed

+133
-108
lines changed

Diff for: control.lua

+132-107
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
require "config"
22

3+
local mod_version="0.0.2"
4+
local mod_data_version="0.0.2"
5+
36
termbelts = {}
47
curvebelts = {}
58

@@ -24,6 +27,27 @@ local function pos2s(pos)
2427
return ''
2528
end
2629

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+
2751
local belt_speeds = {basic=1,fast=2,express=3,faster=4,purple=5}
2852

2953
-- starting_entity is a belt(-like) entity, or a belt combinator
@@ -35,24 +59,16 @@ local function terminal_belt_lines(entity,entity_to_ignore)
3559
if #entity.neighbours>0 then
3660
return {}
3761
else
38-
return {3,4}
62+
return {1,2,3,4}
3963
end
4064
end
4165
local dir = entity.direction
4266
local pos = entity.position
4367
local to_check = {}
4468
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}}}
5672
elseif entity.type=="transport-belt-to-ground" and
5773
entity.belt_to_ground_type=="input" then
5874
to_check = {{pos=pos,lines={3,4}}}
@@ -69,20 +85,8 @@ local function terminal_belt_lines(entity,entity_to_ignore)
6985
-- following code originally copied from https://github.com/sparr/factorio-mod-belt-combinators
7086
for _,check in pairs(to_check) do
7187
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}})
8690
local target = nil
8791
for _,candidate in pairs(entities) do
8892
if candidate ~= entity_to_ignore then
@@ -129,40 +133,23 @@ local function terminal_belt_lines(entity,entity_to_ignore)
129133
if target.type=='transport-belt' then
130134
local belt_behind_target = false
131135
-- 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
162148
end
149+
break
163150
end
164-
if belt_behind_target then break end
165151
end
152+
if belt_behind_target then break end
166153
end
167154
if not belt_behind_target then
168155
turn = true
@@ -193,60 +180,73 @@ local function onTick(event)
193180
else
194181
local e = belt.entity
195182
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
196198
for _,line in pairs(belt.lines) do
197199
-- 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
212200
local tl = e.get_transport_line(line)
213201
local item_name = nil
214202
for name,count in pairs(tl.get_contents()) do
215203
-- debug(line..' '..name..' '..count)
216204
item_name = name
217205
end
218206
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
232232
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}}
237243
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))
242248
end
243249
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
250250
end
251251
end
252252
end
@@ -336,17 +336,42 @@ local function find_all_entities(args)
336336
return entities
337337
end
338338

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+
339360
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+
340373
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()
350375
end
351376

352377
curvebelts = global.curve_belts

Diff for: info.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "belt-overflow",
3-
"version": "0.0.1",
3+
"version": "0.0.2",
44
"title": "Belt Overflow",
55
"author": "Sparr",
66
"homepage": "http://github.com/sparr/factorio-mod-belt-overflow",

0 commit comments

Comments
 (0)