Use stationary interfaces for external connections

This commit is contained in:
hal8174 2025-02-28 21:15:54 +01:00
parent fda5361a2b
commit 41a528a49c
3 changed files with 171 additions and 69 deletions

View file

@ -38,6 +38,16 @@ pub struct FactoryConnection {
pub to: usize, pub to: usize,
} }
struct IntermediateConnection {
input: HashMap<usize, IntermediateConnectionEntry>,
output: HashMap<usize, IntermediateConnectionEntry>,
}
struct IntermediateConnectionEntry {
block: Option<usize>,
interface: usize,
}
pub fn generate_factory<L: Layouter, P: Pathfinder + Sync, R: Rng + SeedableRng + Send + Sync>( pub fn generate_factory<L: Layouter, P: Pathfinder + Sync, R: Rng + SeedableRng + Send + Sync>(
layouter: &L, layouter: &L,
pathfinder: &P, pathfinder: &P,
@ -49,6 +59,9 @@ pub fn generate_factory<L: Layouter, P: Pathfinder + Sync, R: Rng + SeedableRng
let mut connections = Vec::new(); let mut connections = Vec::new();
let mut intermediate_connections = Vec::new(); let mut intermediate_connections = Vec::new();
let mut static_input = Vec::new();
let mut static_output = Vec::new();
for (i, b) in factory_graph.subfactories.iter().enumerate() { for (i, b) in factory_graph.subfactories.iter().enumerate() {
let mut input_connections = factory_graph let mut input_connections = factory_graph
.factory_connections .factory_connections
@ -76,8 +89,13 @@ pub fn generate_factory<L: Layouter, P: Pathfinder + Sync, R: Rng + SeedableRng
assert_eq!(output_connections.len(), 1); assert_eq!(output_connections.len(), 1);
assert!(input_connections.len() <= 3); assert!(input_connections.len() <= 3);
let output_connection = output_connections.first().unwrap(); let output_connection = output_connections.first().unwrap();
let intermediate_output_connection = let intermediate_output_connection = HashMap::from([(
HashMap::from([(output_connection.0, (block_index, 0))]); output_connection.0,
IntermediateConnectionEntry {
block: Some(block_index),
interface: 0,
},
)]);
input_connections.sort_by(|a, b| b.1.amount.total_cmp(&a.1.amount)); input_connections.sort_by(|a, b| b.1.amount.total_cmp(&a.1.amount));
let (input_belt1, input_belt2, addition_blocks) = if let Some( let (input_belt1, input_belt2, addition_blocks) = if let Some(
@ -90,14 +108,32 @@ pub fn generate_factory<L: Layouter, P: Pathfinder + Sync, R: Rng + SeedableRng
input_connections.first_chunk() input_connections.first_chunk()
{ {
let c0_bigger = c0.amount > c1.amount + c2.amount; let c0_bigger = c0.amount > c1.amount + c2.amount;
intermediate_connections.push(( intermediate_connections.push(IntermediateConnection {
HashMap::from([ input: HashMap::from([
(connection_id0, (block_index, if c0_bigger { 1 } else { 0 })), (
(connection_id1, (block_index + 1, 0)), connection_id0,
(connection_id2, (block_index + 1, 1)), IntermediateConnectionEntry {
block: Some(block_index),
interface: if c0_bigger { 1 } else { 0 },
},
),
(
connection_id1,
IntermediateConnectionEntry {
block: Some(block_index + 1),
interface: 0,
},
),
(
connection_id2,
IntermediateConnectionEntry {
block: Some(block_index + 1),
interface: 1,
},
),
]), ]),
intermediate_output_connection, output: intermediate_output_connection,
)); });
let beltspeed = let beltspeed =
Beltspeed::from_items_per_second(2.0 * f64::max(c1.amount, c2.amount)); Beltspeed::from_items_per_second(2.0 * f64::max(c1.amount, c2.amount));
@ -144,23 +180,41 @@ pub fn generate_factory<L: Layouter, P: Pathfinder + Sync, R: Rng + SeedableRng
} else if let Some(&[(connection_id0, c0), (connection_id1, c1)]) = } else if let Some(&[(connection_id0, c0), (connection_id1, c1)]) =
input_connections.first_chunk() input_connections.first_chunk()
{ {
intermediate_connections.push(( intermediate_connections.push(IntermediateConnection {
HashMap::from([ input: HashMap::from([
(connection_id0, (block_index, 0)), (
(connection_id1, (block_index, 1)), connection_id0,
IntermediateConnectionEntry {
block: Some(block_index),
interface: 0,
},
),
(
connection_id1,
IntermediateConnectionEntry {
block: Some(block_index),
interface: 1,
},
),
]), ]),
intermediate_output_connection, output: intermediate_output_connection,
)); });
( (
Beltspeed::from_items_per_second(c0.amount), Beltspeed::from_items_per_second(c0.amount),
Some(Beltspeed::from_items_per_second(c1.amount)), Some(Beltspeed::from_items_per_second(c1.amount)),
vec![], vec![],
) )
} else if let Some(&[(connection_id, c)]) = input_connections.first_chunk() { } else if let Some(&[(connection_id, c)]) = input_connections.first_chunk() {
intermediate_connections.push(( intermediate_connections.push(IntermediateConnection {
HashMap::from([(connection_id, (block_index, 0))]), input: HashMap::from([(
intermediate_output_connection, connection_id,
)); IntermediateConnectionEntry {
block: Some(block_index),
interface: 0,
},
)]),
output: intermediate_output_connection,
});
(Beltspeed::from_items_per_second(c.amount), None, vec![]) (Beltspeed::from_items_per_second(c.amount), None, vec![])
} else { } else {
unreachable!() unreachable!()
@ -202,35 +256,51 @@ pub fn generate_factory<L: Layouter, P: Pathfinder + Sync, R: Rng + SeedableRng
} }
Building::ExternalConnection { inputs, outputs } => { Building::ExternalConnection { inputs, outputs } => {
let step = 4; let step = 4;
blocks.push(MacroBlock { let static_input_offset = static_input.len();
size: Position::new(1, step * (inputs + outputs) as PositionType), let static_output_offset = static_output.len();
input: (0..*inputs) static_input.extend((0..*inputs).map(|y| Interface {
.map(|y| Interface { offset: Position::new(
offset: Position::new(0, step * y as PositionType), 0,
step * (y + static_input_offset + static_output_offset) as PositionType,
),
dir: Direction::Left, dir: Direction::Left,
}) }));
.collect(), static_output.extend((0..*outputs).map(|y| Interface {
output: (0..*outputs) offset: Position::new(
.map(|y| Interface { 0,
offset: Position::new(0, step * (inputs + y) as PositionType), step * (y + static_input_offset + static_output_offset + inputs)
as PositionType,
),
dir: Direction::Right, dir: Direction::Right,
}));
intermediate_connections.push(IntermediateConnection {
input: input_connections
.iter()
.enumerate()
.map(|(port, &(connection_id, _))| {
(
connection_id,
IntermediateConnectionEntry {
block: None,
interface: static_input_offset + port,
},
)
}) })
.collect(), .collect::<HashMap<_, _>>(),
output: output_connections
.iter()
.enumerate()
.map(|(port, &(connection_id, _))| {
(
connection_id,
IntermediateConnectionEntry {
block: None,
interface: static_output_offset + port,
},
)
})
.collect::<HashMap<_, _>>(),
}); });
blueprints.push(Blueprint::new());
intermediate_connections.push((
input_connections
.iter()
.enumerate()
.map(|(port, &(connection_id, _))| (connection_id, (block_index, port)))
.collect::<HashMap<_, _>>(),
output_connections
.iter()
.enumerate()
.map(|(port, &(connection_id, _))| (connection_id, (block_index, port)))
.collect::<HashMap<_, _>>(),
));
} }
Building::SideLoader => { Building::SideLoader => {
let mut blueprint = Blueprint::new(); let mut blueprint = Blueprint::new();
@ -263,18 +333,34 @@ pub fn generate_factory<L: Layouter, P: Pathfinder + Sync, R: Rng + SeedableRng
}], }],
}); });
blueprints.push(blueprint); blueprints.push(blueprint);
intermediate_connections.push(( intermediate_connections.push(IntermediateConnection {
input_connections input: input_connections
.iter() .iter()
.enumerate() .enumerate()
.map(|(port, &(connection_id, _))| (connection_id, (block_index, port))) .map(|(port, &(connection_id, _))| {
(
connection_id,
IntermediateConnectionEntry {
block: Some(block_index),
interface: port,
},
)
})
.collect::<HashMap<_, _>>(), .collect::<HashMap<_, _>>(),
output_connections output: output_connections
.iter() .iter()
.enumerate() .enumerate()
.map(|(port, &(connection_id, _))| (connection_id, (block_index, port))) .map(|(port, &(connection_id, _))| {
(
connection_id,
IntermediateConnectionEntry {
block: Some(block_index),
interface: port,
},
)
})
.collect::<HashMap<_, _>>(), .collect::<HashMap<_, _>>(),
)); });
} }
Building::Splitter => { Building::Splitter => {
let mut blueprint = Blueprint::new(); let mut blueprint = Blueprint::new();
@ -315,18 +401,34 @@ pub fn generate_factory<L: Layouter, P: Pathfinder + Sync, R: Rng + SeedableRng
], ],
}); });
blueprints.push(blueprint); blueprints.push(blueprint);
intermediate_connections.push(( intermediate_connections.push(IntermediateConnection {
input_connections input: input_connections
.iter() .iter()
.enumerate() .enumerate()
.map(|(port, &(connection_id, _))| (connection_id, (block_index, port))) .map(|(port, &(connection_id, _))| {
(
connection_id,
IntermediateConnectionEntry {
block: Some(block_index),
interface: port,
},
)
})
.collect::<HashMap<_, _>>(), .collect::<HashMap<_, _>>(),
output_connections output: output_connections
.iter() .iter()
.enumerate() .enumerate()
.map(|(port, &(connection_id, _))| (connection_id, (block_index, port))) .map(|(port, &(connection_id, _))| {
(
connection_id,
IntermediateConnectionEntry {
block: Some(block_index),
interface: port,
},
)
})
.collect::<HashMap<_, _>>(), .collect::<HashMap<_, _>>(),
)); });
} }
} }
} }
@ -335,10 +437,10 @@ pub fn generate_factory<L: Layouter, P: Pathfinder + Sync, R: Rng + SeedableRng
for (i, c) in factory_graph.factory_connections.iter().enumerate() { for (i, c) in factory_graph.factory_connections.iter().enumerate() {
// dbg!(i, c); // dbg!(i, c);
connections.push(Connection { connections.push(Connection {
startblock: Some(intermediate_connections[c.from].1[&i].0), startblock: intermediate_connections[c.from].output[&i].block,
startpoint: intermediate_connections[c.from].1[&i].1, startpoint: intermediate_connections[c.from].output[&i].interface,
endblock: Some(intermediate_connections[c.to].0[&i].0), endblock: intermediate_connections[c.to].input[&i].block,
endpoint: intermediate_connections[c.to].0[&i].1, endpoint: intermediate_connections[c.to].input[&i].interface,
lanes: 1, lanes: 1,
beltspeed: Beltspeed::from_items_per_second(c.amount), beltspeed: Beltspeed::from_items_per_second(c.amount),
}); });
@ -348,8 +450,8 @@ pub fn generate_factory<L: Layouter, P: Pathfinder + Sync, R: Rng + SeedableRng
// dbg!(&connections); // dbg!(&connections);
let layout_input = LayoutInput { let layout_input = LayoutInput {
input: Vec::new(), static_input,
output: Vec::new(), static_output,
blocks, blocks,
connections, connections,
}; };

View file

@ -41,8 +41,8 @@ pub struct Connection {
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct LayoutInput { pub struct LayoutInput {
pub blocks: Vec<MacroBlock>, pub blocks: Vec<MacroBlock>,
pub input: Vec<Interface>, pub static_input: Vec<Interface>,
pub output: Vec<Interface>, pub static_output: Vec<Interface>,
pub connections: Vec<Connection>, pub connections: Vec<Connection>,
} }

View file

@ -121,8 +121,8 @@ pub fn path_input_from_blocks_positions(
.dir .dir
.transform(start_transform); .transform(start_transform);
} else { } else {
start_pos = input.output[c.startpoint].offset; start_pos = input.static_output[c.startpoint].offset;
start_dir = input.output[c.startpoint].dir; start_dir = input.static_output[c.startpoint].dir;
} }
let end_pos; let end_pos;
let end_dir; let end_dir;
@ -135,8 +135,8 @@ pub fn path_input_from_blocks_positions(
.dir .dir
.transform(end_transform); .transform(end_transform);
} else { } else {
end_pos = input.input[c.endpoint].offset; end_pos = input.static_input[c.endpoint].offset;
end_dir = input.input[c.endpoint].dir; end_dir = input.static_input[c.endpoint].dir;
} }
connections.push(Connection { connections.push(Connection {