1+ local blacklist = {' factory-port-marker' , ' hidden_trade_post' , ' castle_dummy' , ' castle' }
2+
3+ function is_value_in_list (value , list )
4+ for i , v in pairs (list ) do
5+ if v == value then return true end
6+ end
7+ return false
8+ end
9+
10+
11+ function is_pipe_connection_collides (entity , position , prev_pipe_connections )
12+ local prev_pipe_connections = prev_pipe_connections or {}
13+ local all_pipe_connections = prev_pipe_connections -- pipe_connections
14+
15+ local positions = entity .energy_source and entity .energy_source .fluid_box and entity .energy_source .fluid_box .pipe_connections or {}
16+
17+ for i , pos in pairs (positions ) do
18+ local x = pos .x or pos [1 ]
19+ local y = pos .y or pos [2 ]
20+ table.insert (all_pipe_connections , {x = x , y = y })
21+ end
22+
23+ local fluid_boxes = entity .fluid_boxes or {}
24+
25+ for i , fluid_box in pairs (fluid_boxes ) do
26+ if type (fluid_box ) == ' table' then -- somehow it was boolean
27+ local pipe_connections = fluid_box .pipe_connections or {}
28+
29+ for j , pipe_connection in pairs (pipe_connections ) do
30+ local pos = pipe_connection .position
31+ local x = pos .x or pos [1 ]
32+ local y = pos .y or pos [2 ]
33+ table.insert (all_pipe_connections , {x = x , y = y })
34+ end
35+ end
36+ end
37+
38+ for i , pipe_connection in pairs (all_pipe_connections ) do
39+ if pipe_connection .x == position .x and pipe_connection .y == position .y then
40+ return true
41+ end
42+ end
43+ return false
44+ end
45+
46+
47+ function get_free_pipe_connection (entity , best_position , prev_pipe_connections )
48+ local cb = entity .collision_box
49+ local min_x = math.floor (cb [1 ][1 ]* 2 )/ 2 -- -0.4 --> -0.5; -1.4 --> -1.5; -1.2 --> -1.5
50+ local min_y = math.floor (cb [1 ][2 ]* 2 )/ 2
51+
52+ local max_x = math.ceil (cb [2 ][1 ]* 2 )/ 2
53+ local max_y = math.ceil (cb [2 ][2 ]* 2 )/ 2
54+
55+ local all_c_positions = {}
56+ local all_c_positions_list = {}
57+
58+ for x = (min_x + 0.5 ), (max_x - 0.5 ) do
59+ for _ , y in pairs ({(min_y - 0.5 ), (max_y + 0.5 )}) do
60+ if not all_c_positions [x ] then all_c_positions [x ] = {} end
61+ if not all_c_positions [x ][y ] then all_c_positions [x ][y ] = true end
62+ table.insert (all_c_positions_list , {x = x ,y = y })
63+ end
64+ end
65+
66+ for y = (min_y + 0.5 ), (max_y - 0.5 ) do
67+ for _ , x in pairs ({(min_x - 0.5 ), (max_x + 0.5 )}) do
68+ if not all_c_positions [x ] then all_c_positions [x ] = {} end
69+ if not all_c_positions [x ][y ] then all_c_positions [x ][y ] = true end
70+ table.insert (all_c_positions_list , {x = x ,y = y })
71+ end
72+ end
73+
74+ local all_pcs = {} -- all pipe connections
75+
76+ local ipcs = entity .input_fluid_box and entity .input_fluid_box .pipe_connections or {}
77+
78+ local espcs = entity .energy_source and entity .energy_source .fluid_box and entity .energy_source .fluid_box .pipe_connections or {}
79+
80+ for i , pcs in pairs ({ipcs , espcs }) do
81+ for j , pc in pairs (pcs ) do
82+ table.insert (all_pcs , pc )
83+ end
84+ end
85+
86+ if # all_pcs > 0 then
87+ for i , pc in pairs (all_pcs ) do
88+ local position = pc .position
89+ local x = position [1 ]
90+ local y = position [2 ]
91+ if all_c_positions [x ] and all_c_positions [x ][y ] then
92+ all_c_positions [x ][y ] = nil
93+
94+ for i = # all_c_positions_list , 1 , - 1 do -- backwards!
95+ local pos = all_c_positions_list [i ]
96+ if pos .x == x and pos .y == y then
97+ table.remove (all_c_positions_list , i )
98+ end
99+
100+ end
101+
102+ end
103+ end
104+ end
105+
106+ if best_position and all_c_positions [best_position .x ] and all_c_positions [best_position .x ][best_position .y ] then
107+ return best_position
108+ end
109+
110+ -- best position was already used
111+ local best_list = {}
112+ for i , pos in pairs (all_c_positions_list ) do
113+ local position = pos
114+ if pos .x == best_position .x or pos .y == best_position .y then
115+ if not (is_pipe_connection_collides (entity , position , prev_pipe_connections )) then
116+ table.insert (best_list , pos )
117+ end
118+ end
119+ end
120+
121+
122+
123+ if # best_list > 0 then
124+ return best_list [1 ]
125+ else
126+
127+ for i , pos in pairs (all_c_positions_list ) do
128+ if pos .x == (- 0.5 ) or pos .x == (0 ) or pos .x == (0.5 ) or pos .y == (- 0.5 ) or pos .y == (0 ) or pos .y == (0.5 ) then
129+ table.insert (best_list , pos )
130+ end
131+ end
132+
133+ if # best_list > 0 then
134+ return best_list [1 ]
135+ end
136+
137+ end
138+
139+ if # all_c_positions_list > 0 then
140+ return best_list [1 ]
141+ end
142+
143+ log (' error: no position found for entity "' .. entity .name .. ' "' )
144+ return nil
145+ end
146+
147+ --- add a pipe connection to the list of connections to be added to the entity
148+ -- @param into_table - table to add the pipe into
149+ -- @param entity - the entity to add pipe connections to
150+ -- @param best_position - the preferred position for a new pipe connection
151+ -- @param prev_connections - a table of pipe connections previously added with this function
152+ function insert_pipe_connection (into_table , entity , position , prev_connections )
153+ local pipe_connection_position = get_free_pipe_connection (entity , position , prev_connections )
154+ if pipe_connection_position then
155+ local new_connection = {position = pipe_connection_position }
156+ table.insert (into_table , new_connection )
157+ table.insert (prev_connections , new_connection .position )
158+ end
159+ end
160+
161+ local entity_types_to_alter = {
162+ ' furnace' ,
163+ ' assembling-machine' ,
164+ ' mining-drill' ,
165+ ' lab'
166+ }
167+
168+ for i , type_name in pairs (entity_types_to_alter ) do
169+ local prot_type = data .raw [type_name ]
170+ for name , prot in pairs (prot_type ) do
171+
172+ if prot .energy_source and prot .energy_source .type and prot .energy_source .type == " electric" then
173+
174+ if
175+ prot .collision_box
176+ and not (prot .energy_source .burner_only )
177+ and not (is_value_in_list (name , blacklist )) -- maybe as selectable_in_game?
178+ then
179+
180+ local x = prot .collision_box [1 ][1 ] -- -1.4
181+ local y = prot .collision_box [1 ][2 ] -- -1.4
182+
183+ x = math.floor (x * 2 )/ 2 - 0.5
184+ y = math.floor (y * 2 )/ 2 - 0.5
185+
186+ local pipe_connections = {}
187+ local new_connections = {}
188+
189+ -- left and right
190+ insert_pipe_connection (pipe_connections , prot , {x = x , y = y + 2 }, new_connections )
191+ insert_pipe_connection (pipe_connections , prot , {x =- x , y = y + 2 }, new_connections )
192+
193+ if type_name == " lab" then
194+ -- top and bottom
195+ insert_pipe_connection (pipe_connections , prot , {x = x + 2 , y = y }, new_connections )
196+ insert_pipe_connection (pipe_connections , prot , {x = x + 2 , y =- y }, new_connections )
197+ end
198+
199+ local images = data .raw [" mining-drill" ][" electric-mining-drill" ].input_fluid_box
200+ local emissions_per_minute = prot .energy_source .emissions_per_minute
201+
202+ prot .energy_source =
203+ {
204+ type = ' fluid' ,
205+ maximum_temperature = 165 ,
206+ emissions_per_minute = emissions_per_minute ,
207+
208+ fluid_box =
209+ {
210+ production_type = " input-output" ,
211+ filter = " steam" ,
212+ pipe_picture = images .pipe_picture ,
213+ pipe_covers = images .pipe_covers ,
214+ base_area = 1 ,
215+ height = 2 ,
216+ base_level = - 1 ,
217+ pipe_connections = pipe_connections
218+ }
219+ }
220+ end
221+ end
222+ end
223+ end
0 commit comments