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,
}
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>(
layouter: &L,
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 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() {
let mut input_connections = factory_graph
.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!(input_connections.len() <= 3);
let output_connection = output_connections.first().unwrap();
let intermediate_output_connection =
HashMap::from([(output_connection.0, (block_index, 0))]);
let intermediate_output_connection = HashMap::from([(
output_connection.0,
IntermediateConnectionEntry {
block: Some(block_index),
interface: 0,
},
)]);
input_connections.sort_by(|a, b| b.1.amount.total_cmp(&a.1.amount));
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()
{
let c0_bigger = c0.amount > c1.amount + c2.amount;
intermediate_connections.push((
HashMap::from([
(connection_id0, (block_index, if c0_bigger { 1 } else { 0 })),
(connection_id1, (block_index + 1, 0)),
(connection_id2, (block_index + 1, 1)),
intermediate_connections.push(IntermediateConnection {
input: HashMap::from([
(
connection_id0,
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 =
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)]) =
input_connections.first_chunk()
{
intermediate_connections.push((
HashMap::from([
(connection_id0, (block_index, 0)),
(connection_id1, (block_index, 1)),
intermediate_connections.push(IntermediateConnection {
input: HashMap::from([
(
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),
Some(Beltspeed::from_items_per_second(c1.amount)),
vec![],
)
} else if let Some(&[(connection_id, c)]) = input_connections.first_chunk() {
intermediate_connections.push((
HashMap::from([(connection_id, (block_index, 0))]),
intermediate_output_connection,
));
intermediate_connections.push(IntermediateConnection {
input: HashMap::from([(
connection_id,
IntermediateConnectionEntry {
block: Some(block_index),
interface: 0,
},
)]),
output: intermediate_output_connection,
});
(Beltspeed::from_items_per_second(c.amount), None, vec![])
} else {
unreachable!()
@ -202,35 +256,51 @@ pub fn generate_factory<L: Layouter, P: Pathfinder + Sync, R: Rng + SeedableRng
}
Building::ExternalConnection { inputs, outputs } => {
let step = 4;
blocks.push(MacroBlock {
size: Position::new(1, step * (inputs + outputs) as PositionType),
input: (0..*inputs)
.map(|y| Interface {
offset: Position::new(0, step * y as PositionType),
dir: Direction::Left,
let static_input_offset = static_input.len();
let static_output_offset = static_output.len();
static_input.extend((0..*inputs).map(|y| Interface {
offset: Position::new(
0,
step * (y + static_input_offset + static_output_offset) as PositionType,
),
dir: Direction::Left,
}));
static_output.extend((0..*outputs).map(|y| Interface {
offset: Position::new(
0,
step * (y + static_input_offset + static_output_offset + inputs)
as PositionType,
),
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(),
output: (0..*outputs)
.map(|y| Interface {
offset: Position::new(0, step * (inputs + y) as PositionType),
dir: Direction::Right,
.collect::<HashMap<_, _>>(),
output: output_connections
.iter()
.enumerate()
.map(|(port, &(connection_id, _))| {
(
connection_id,
IntermediateConnectionEntry {
block: None,
interface: static_output_offset + port,
},
)
})
.collect(),
.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 => {
let mut blueprint = Blueprint::new();
@ -263,18 +333,34 @@ pub fn generate_factory<L: Layouter, P: Pathfinder + Sync, R: Rng + SeedableRng
}],
});
blueprints.push(blueprint);
intermediate_connections.push((
input_connections
intermediate_connections.push(IntermediateConnection {
input: input_connections
.iter()
.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<_, _>>(),
output_connections
output: output_connections
.iter()
.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<_, _>>(),
));
});
}
Building::Splitter => {
let mut blueprint = Blueprint::new();
@ -315,18 +401,34 @@ pub fn generate_factory<L: Layouter, P: Pathfinder + Sync, R: Rng + SeedableRng
],
});
blueprints.push(blueprint);
intermediate_connections.push((
input_connections
intermediate_connections.push(IntermediateConnection {
input: input_connections
.iter()
.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<_, _>>(),
output_connections
output: output_connections
.iter()
.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<_, _>>(),
));
});
}
}
}
@ -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() {
// dbg!(i, c);
connections.push(Connection {
startblock: Some(intermediate_connections[c.from].1[&i].0),
startpoint: intermediate_connections[c.from].1[&i].1,
endblock: Some(intermediate_connections[c.to].0[&i].0),
endpoint: intermediate_connections[c.to].0[&i].1,
startblock: intermediate_connections[c.from].output[&i].block,
startpoint: intermediate_connections[c.from].output[&i].interface,
endblock: intermediate_connections[c.to].input[&i].block,
endpoint: intermediate_connections[c.to].input[&i].interface,
lanes: 1,
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);
let layout_input = LayoutInput {
input: Vec::new(),
output: Vec::new(),
static_input,
static_output,
blocks,
connections,
};

View file

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

View file

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