Refactor StationSpec

This commit is contained in:
hal8174 2025-05-10 22:22:35 +02:00
parent a98e2cfb2b
commit d26449195b
5 changed files with 570 additions and 410 deletions

View file

@ -2,8 +2,8 @@ use clap::Parser;
use factorio_blueprint::abstraction::serde::AbstractBlueprintString; use factorio_blueprint::abstraction::serde::AbstractBlueprintString;
use factorio_blueprint::abstraction::{ChestType, InserterType, Quality}; use factorio_blueprint::abstraction::{ChestType, InserterType, Quality};
use factorio_blueprint::encode; use factorio_blueprint::encode;
use factorio_blueprint_generator::multistation::{StationSpec, multistation}; use factorio_blueprint_generator::multistation::multistation;
use factorio_blueprint_generator::station::StationBasicSpec; use factorio_blueprint_generator::station::StationSpec;
use factorio_core::beltoptions::{Beltspeed, Belttype}; use factorio_core::beltoptions::{Beltspeed, Belttype};
use factorio_core::visualize::Visualize; use factorio_core::visualize::Visualize;
@ -38,55 +38,57 @@ fn main() {
.map(|os| { .map(|os| {
let (locomotives, s) = os.split_once('-').expect("extracting locomotive count"); let (locomotives, s) = os.split_once('-').expect("extracting locomotive count");
let (wagons, s) = s.split_at(s.find(['u', 'l']).expect("extracting wagon count")); let (wagons, s) = s.split_at(s.find(['u', 'l', 'e']).expect("extracting wagon count"));
let (load, s) = s.split_at_checked(1).expect("extracting direction"); let (load, s) = s.split_at_checked(1).expect("extracting direction");
let (beltspeed, s) = s.split_at_checked(1).expect("extracting lanes"); match load {
"l" | "u" => {
let (beltspeed, s) = s.split_at_checked(1).expect("extracting lanes");
let lanes = s.trim_end_matches(['r', 'l', 's']); let lanes = s.trim_end_matches(['r', 'l', 's']);
StationSpec { StationSpec::new_belt(
locomotives: locomotives.parse().expect("parsing locomotive count"), locomotives.parse().expect("parsing locomotive count"),
wagons: wagons.parse().expect("parsing wagon count"), wagons.parse().expect("parsing wagon count"),
load: match load { format!("test"),
"l" => true, match load {
"u" => false, "l" => true,
_ => panic!("unknown directino {load}"), "u" => false,
}, _ => panic!("unknown directino {load}"),
beltspeed: match beltspeed { },
"n" => Beltspeed::Normal, match beltspeed {
"f" => Beltspeed::Fast, "n" => Beltspeed::Normal,
"e" => Beltspeed::Express, "f" => Beltspeed::Fast,
"t" => Beltspeed::Turbo, "e" => Beltspeed::Express,
_ => panic!("unknown belt speed {beltspeed}"), "t" => Beltspeed::Turbo,
}, _ => panic!("unknown belt speed {beltspeed}"),
lanes: lanes.parse().expect("parsing lane count"), },
belttype: if s.contains('l') { lanes.parse().expect("parsing lane count"),
Belttype::Left if s.contains('l') {
} else if s.contains('r') { Belttype::Left
Belttype::Right } else if s.contains('r') {
} else { Belttype::Right
Belttype::Full } else {
}, Belttype::Full
stacked: s.contains('s'), },
s.contains('s'),
)
}
"e" => StationSpec::new_empty(
locomotives.parse().expect("parsing locomotive count"),
wagons.parse().expect("parsing wagon count"),
format!("test"),
s.parse().expect("Unable to parse space"),
),
_ => panic!("unknown station type"),
} }
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
dbg!(&stations); dbg!(&stations);
let mut b = multistation( let mut b = multistation(&stations, args.stacker_size).0;
&stations,
args.stacker_size,
&StationBasicSpec {
inserter_type: args.wagon_inserter_type,
inserter_quality: args.wagon_inserter_quality,
chest_type: args.chest_type,
chest_quality: args.chest_quality,
},
)
.0;
b.connect_power_networks(); b.connect_power_networks();

View file

@ -1,9 +1,6 @@
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use factorio_blueprint::{BlueprintBook, BlueprintBookEntry, BlueprintString, encode}; use factorio_blueprint::{BlueprintBook, BlueprintBookEntry, BlueprintString, encode};
use factorio_blueprint_generator::{ use factorio_blueprint_generator::station::{StationSpec, station};
multistation::StationSpec,
station::{StationBasicSpec, basic_station},
};
use factorio_core::beltoptions::{Beltspeed, Belttype}; use factorio_core::beltoptions::{Beltspeed, Belttype};
#[derive(Parser)] #[derive(Parser)]
@ -65,18 +62,16 @@ fn main() {
for (l, o) in (0..=(cargo as u32).ilog2()).enumerate() { for (l, o) in (0..=(cargo as u32).ilog2()).enumerate() {
let o = 1 << o; let o = 1 << o;
let blueprint = basic_station( let blueprint = station(&StationSpec::new_belt(
&StationSpec { locomotives,
locomotives, cargo,
wagons: cargo, format!("test"),
load, load,
beltspeed, beltspeed,
lanes: o, o,
belttype: Belttype::Full, Belttype::Full,
stacked: false, false,
}, ));
&factorio_blueprint_generator::station::StationBasicSpec::default(),
);
inner_inner_b.push(BlueprintBookEntry::new( inner_inner_b.push(BlueprintBookEntry::new(
BlueprintString::Blueprint(blueprint.to_blueprint()), BlueprintString::Blueprint(blueprint.to_blueprint()),
@ -136,18 +131,16 @@ fn main() {
belttype, belttype,
} => { } => {
let b = BlueprintString::Blueprint( let b = BlueprintString::Blueprint(
basic_station( station(&StationSpec::new_belt(
&StationSpec { locomotives,
locomotives, length,
wagons: length, format!("test"),
load, load,
beltspeed, beltspeed,
lanes: outputs, outputs,
belttype, belttype,
stacked: false, false,
}, ))
&StationBasicSpec::default(),
)
.to_blueprint(), .to_blueprint(),
); );

View file

@ -1,5 +1,6 @@
use crate::{ use crate::{
multistation::{StationSpec, multistation}, multistation::multistation,
station::{StationSpec, StationType},
subfactory::{BeltConnection, SubFactory}, subfactory::{BeltConnection, SubFactory},
}; };
use factorio_blueprint::abstraction::{Blueprint, Entity}; use factorio_blueprint::abstraction::{Blueprint, Entity};
@ -406,23 +407,29 @@ pub fn generate_factory<L: Layouter, P: Pathfinder + Sync, R: Rng + SeedableRng
// dir: Direction::Right, // dir: Direction::Right,
// })); // }));
station_spec.extend(input_connections.iter().map(|&(_, c)| StationSpec { station_spec.extend(input_connections.iter().map(|&(_, c)| {
locomotives: 2, StationSpec::new_belt(
wagons: 4, 2,
load: true, 4,
beltspeed: Beltspeed::from_items_per_second(c.amount), format!("load-[item=]"),
lanes: 1, true,
belttype: factorio_core::beltoptions::Belttype::Full, Beltspeed::from_items_per_second(c.amount),
stacked: false, 1,
factorio_core::beltoptions::Belttype::Full,
false,
)
})); }));
station_spec.extend(output_connections.iter().map(|&(_, c)| StationSpec { station_spec.extend(output_connections.iter().map(|&(_, c)| {
locomotives: 2, StationSpec::new_belt(
wagons: 4, 2,
load: false, 4,
beltspeed: Beltspeed::from_items_per_second(c.amount), format!("load-[item=]"),
lanes: 1, false,
belttype: factorio_core::beltoptions::Belttype::Full, Beltspeed::from_items_per_second(c.amount),
stacked: false, 1,
factorio_core::beltoptions::Belttype::Full,
false,
)
})); }));
intermediate_connections.push(IntermediateConnection { intermediate_connections.push(IntermediateConnection {
@ -780,11 +787,8 @@ pub fn generate_factory<L: Layouter, P: Pathfinder + Sync, R: Rng + SeedableRng
// dbg!(&blocks); // dbg!(&blocks);
// dbg!(&connections); // dbg!(&connections);
let (multistation_blueprint, multistation_x_offset, mut multistation_y_offsets) = multistation( let (multistation_blueprint, multistation_x_offset, mut multistation_y_offsets) =
&station_spec, multistation(&station_spec, 8);
8,
&crate::station::StationBasicSpec::default(),
);
let multistation_y_offset = multistation_y_offsets[0]; let multistation_y_offset = multistation_y_offsets[0];
multistation_y_offsets.iter_mut().for_each(move |y| { multistation_y_offsets.iter_mut().for_each(move |y| {
@ -795,11 +799,15 @@ pub fn generate_factory<L: Layouter, P: Pathfinder + Sync, R: Rng + SeedableRng
.iter() .iter()
.zip(multistation_y_offsets.iter()) .zip(multistation_y_offsets.iter())
.filter_map(|(s, y)| { .filter_map(|(s, y)| {
if s.load { if let StationType::Belt(station_type_belt) = &s.station_type {
Some(Interface { if station_type_belt.load {
offset: Position::new(-1, y / 2), Some(Interface {
dir: Direction::Left, offset: Position::new(-1, y / 2),
}) dir: Direction::Left,
})
} else {
None
}
} else { } else {
None None
} }
@ -810,11 +818,15 @@ pub fn generate_factory<L: Layouter, P: Pathfinder + Sync, R: Rng + SeedableRng
.iter() .iter()
.zip(multistation_y_offsets.iter()) .zip(multistation_y_offsets.iter())
.filter_map(|(s, y)| { .filter_map(|(s, y)| {
if !s.load { if let StationType::Belt(station_type_belt) = &s.station_type {
Some(Interface { if !station_type_belt.load {
offset: Position::new(-1, y / 2), Some(Interface {
dir: Direction::Right, offset: Position::new(-1, y / 2),
}) dir: Direction::Right,
})
} else {
None
}
} else { } else {
None None
} }

View file

@ -1,25 +1,11 @@
use crate::{ use crate::{
balancer::binary_balancer, balancer::binary_balancer,
station::{StationBasicSpec, basic_station}, station::{StationSpec, station},
}; };
use factorio_blueprint::abstraction::{ use factorio_blueprint::abstraction::{
Blueprint, ElectricPoleType, Entity, RailType, UndergroundType, Blueprint, ElectricPoleType, Entity, RailType, UndergroundType,
}; };
use factorio_core::{ use factorio_core::{beltoptions::Beltspeed, prelude::*};
beltoptions::{Beltspeed, Belttype},
prelude::*,
};
#[derive(Debug, Clone)]
pub struct StationSpec {
pub locomotives: usize,
pub wagons: usize,
pub load: bool,
pub beltspeed: Beltspeed,
pub lanes: usize,
pub belttype: Belttype,
pub stacked: bool,
}
fn calculate_station_height( fn calculate_station_height(
output_height: PositionType, output_height: PositionType,
@ -53,11 +39,10 @@ fn calculate_station_height(
pub fn multistation( pub fn multistation(
stations: &[StationSpec], stations: &[StationSpec],
stacker_size: usize, stacker_size: usize,
basic_spec: &StationBasicSpec,
) -> (Blueprint, PositionType, Vec<PositionType>) { ) -> (Blueprint, PositionType, Vec<PositionType>) {
let longest_train = stations let longest_train = stations
.iter() .iter()
.map(|s| s.locomotives + s.wagons) .map(|s| s.train_information.locomotives + s.train_information.wagons)
.max() .max()
.unwrap(); .unwrap();
@ -167,7 +152,7 @@ pub fn multistation(
let mut output_heights = Vec::new(); let mut output_heights = Vec::new();
let mut previous_station_heights = 0; let mut previous_station_heights = 0;
// station // station
for (i, station) in stations.iter().enumerate() { for (i, station_spec) in stations.iter().enumerate() {
// in turn // in turn
blueprint.add_entity(Entity::new_rail( blueprint.add_entity(Entity::new_rail(
RailType::CurvedA, RailType::CurvedA,
@ -253,7 +238,9 @@ pub fn multistation(
)); ));
for j in 0..((7 * longest_train).div_ceil(2) for j in 0..((7 * longest_train).div_ceil(2)
- (7 * (station.locomotives + station.wagons)).div_ceil(2)) - (7 * (station_spec.train_information.locomotives
+ station_spec.train_information.wagons))
.div_ceil(2))
{ {
blueprint.add_entity(Entity::new_rail( blueprint.add_entity(Entity::new_rail(
RailType::Straight, RailType::Straight,
@ -266,7 +253,7 @@ pub fn multistation(
} }
// station // station
let mut b = basic_station(station, basic_spec); let mut b = station(station_spec);
let output_height = -b.bounding_box().min().y; let output_height = -b.bounding_box().min().y;
b.transform(Transformation::new( b.transform(Transformation::new(
@ -279,104 +266,259 @@ pub fn multistation(
blueprint.add_blueprint(b); blueprint.add_blueprint(b);
// belt output let station_height = match &station_spec.station_type {
let station_height = crate::station::StationType::Empty(station_type_empty) => 4 + station_type_empty.space,
calculate_station_height(output_height, station.lanes, station.beltspeed); crate::station::StationType::Belt(station_type_belt) => {
// belt output
let station_height = calculate_station_height(
output_height,
station_type_belt.lanes,
station_type_belt.beltspeed,
);
output_heights.push(30 + total_stacker_height + previous_station_heights + output_height); output_heights
.push(30 + total_stacker_height + previous_station_heights + output_height);
// rail crossing // rail crossing
let (beltdirection, underground_left, underground_right) = match station.load { let (beltdirection, underground_left, underground_right) =
true => ( match station_type_belt.load {
Direction::Left, true => (
UndergroundType::Output, Direction::Left,
UndergroundType::Input, UndergroundType::Output,
), UndergroundType::Input,
false => (
Direction::Right,
UndergroundType::Input,
UndergroundType::Output,
),
};
let mut belt_x = outrail_x - 28 - 14 * station.locomotives as PositionType - 3
+ 2 * (station.wagons / station.lanes).ilog2() as PositionType;
let (balancer_length, mut b) = binary_balancer(station.lanes, station.beltspeed);
if station.load {
b.transform(Transformation::new(
Direction::Down,
Position::new(balancer_length, 2 * station.lanes as PositionType),
));
}
b.transform(Transformation::new(
Direction::Up,
Position::new(
belt_x - 1,
31 + total_stacker_height + previous_station_heights + output_height
- 2 * station.lanes as PositionType,
),
));
blueprint.add_blueprint(b);
belt_x += balancer_length;
for j in 0..station.lanes {
let (underground_x, signal) = match station_height
- (output_height - 2 * j as PositionType)
{
5 => {
blueprint.add_entity(Entity::new_underground_belt(
station.beltspeed,
underground_left,
Position::new(
outrail_x - 23,
30 + total_stacker_height + previous_station_heights + output_height
- 2 * j as PositionType,
), ),
beltdirection, false => (
)); Direction::Right,
blueprint.add_entity(Entity::new_underground_belt( UndergroundType::Input,
station.beltspeed, UndergroundType::Output,
underground_right,
Position::new(
outrail_x - 9,
30 + total_stacker_height + previous_station_heights + output_height
- 2 * j as PositionType,
), ),
beltdirection, };
let mut belt_x = outrail_x
- 28
- 14 * station_spec.train_information.locomotives as PositionType
- 3
+ 2 * (station_spec.train_information.wagons / station_type_belt.lanes).ilog2()
as PositionType;
let (balancer_length, mut b) =
binary_balancer(station_type_belt.lanes, station_type_belt.beltspeed);
if station_type_belt.load {
b.transform(Transformation::new(
Direction::Down,
Position::new(balancer_length, 2 * station_type_belt.lanes as PositionType),
)); ));
blueprint.add_entity(Entity::new_underground_belt(
station.beltspeed,
underground_left,
Position::new(
outrail_x - 7,
30 + total_stacker_height + previous_station_heights + output_height
- 2 * j as PositionType,
),
beltdirection,
));
(outrail_x - 23, false)
} }
7 => {
blueprint.add_entity(Entity::new_underground_belt( b.transform(Transformation::new(
station.beltspeed, Direction::Up,
underground_left, Position::new(
Position::new( belt_x - 1,
outrail_x - 17, 31 + total_stacker_height + previous_station_heights + output_height
30 + total_stacker_height + previous_station_heights + output_height - 2 * station_type_belt.lanes as PositionType,
- 2 * j as PositionType, ),
), ));
beltdirection,
)); blueprint.add_blueprint(b);
if station.beltspeed != Beltspeed::Turbo {
belt_x += balancer_length;
for j in 0..station_type_belt.lanes {
let (underground_x, signal) =
match station_height - (output_height - 2 * j as PositionType) {
5 => {
blueprint.add_entity(Entity::new_underground_belt(
station_type_belt.beltspeed,
underground_left,
Position::new(
outrail_x - 23,
30 + total_stacker_height
+ previous_station_heights
+ output_height
- 2 * j as PositionType,
),
beltdirection,
));
blueprint.add_entity(Entity::new_underground_belt(
station_type_belt.beltspeed,
underground_right,
Position::new(
outrail_x - 9,
30 + total_stacker_height
+ previous_station_heights
+ output_height
- 2 * j as PositionType,
),
beltdirection,
));
blueprint.add_entity(Entity::new_underground_belt(
station_type_belt.beltspeed,
underground_left,
Position::new(
outrail_x - 7,
30 + total_stacker_height
+ previous_station_heights
+ output_height
- 2 * j as PositionType,
),
beltdirection,
));
(outrail_x - 23, false)
}
7 => {
blueprint.add_entity(Entity::new_underground_belt(
station_type_belt.beltspeed,
underground_left,
Position::new(
outrail_x - 17,
30 + total_stacker_height
+ previous_station_heights
+ output_height
- 2 * j as PositionType,
),
beltdirection,
));
if station_type_belt.beltspeed != Beltspeed::Turbo {
blueprint.add_entity(Entity::new_underground_belt(
station_type_belt.beltspeed,
underground_right,
Position::new(
outrail_x - 7,
30 + total_stacker_height
+ previous_station_heights
+ output_height
- 2 * j as PositionType,
),
beltdirection,
));
blueprint.add_entity(Entity::new_underground_belt(
station_type_belt.beltspeed,
underground_left,
Position::new(
outrail_x - 5,
30 + total_stacker_height
+ previous_station_heights
+ output_height
- 2 * j as PositionType,
),
beltdirection,
));
}
(outrail_x - 17, false)
}
9 => {
blueprint.add_entity(Entity::new_underground_belt(
station_type_belt.beltspeed,
underground_left,
Position::new(
outrail_x - 15,
30 + total_stacker_height
+ previous_station_heights
+ output_height
- 2 * j as PositionType,
),
beltdirection,
));
(outrail_x - 15, false)
}
11 => {
blueprint.add_entity(Entity::new_underground_belt(
station_type_belt.beltspeed,
underground_left,
Position::new(
outrail_x - 11,
30 + total_stacker_height
+ previous_station_heights
+ output_height
- 2 * j as PositionType,
),
beltdirection,
));
(outrail_x - 11, false)
}
13 => {
blueprint.add_entity(Entity::new_underground_belt(
station_type_belt.beltspeed,
underground_left,
Position::new(
outrail_x - 9,
30 + total_stacker_height
+ previous_station_heights
+ output_height
- 2 * j as PositionType,
),
beltdirection,
));
(outrail_x - 9, false)
}
15 => {
blueprint.add_entity(Entity::new_underground_belt(
station_type_belt.beltspeed,
underground_left,
Position::new(
outrail_x - 9,
30 + total_stacker_height
+ previous_station_heights
+ output_height
- 2 * j as PositionType,
),
beltdirection,
));
(outrail_x - 9, true)
}
17 => {
blueprint.add_entity(Entity::new_underground_belt(
station_type_belt.beltspeed,
underground_left,
Position::new(
outrail_x - 7,
30 + total_stacker_height
+ previous_station_heights
+ output_height
- 2 * j as PositionType,
),
beltdirection,
));
(outrail_x - 7, false)
}
19 | 21 | 23 => {
blueprint.add_entity(Entity::new_underground_belt(
station_type_belt.beltspeed,
underground_left,
Position::new(
outrail_x - 5,
30 + total_stacker_height
+ previous_station_heights
+ output_height
- 2 * j as PositionType,
),
beltdirection,
));
(outrail_x - 5, false)
}
_ => {
blueprint.add_entity(Entity::new_underground_belt(
station_type_belt.beltspeed,
underground_left,
Position::new(
outrail_x - 3,
30 + total_stacker_height
+ previous_station_heights
+ output_height
- 2 * j as PositionType,
),
beltdirection,
));
(outrail_x - 3, false)
}
};
if signal {
blueprint.add_entity(Entity::new_underground_belt( blueprint.add_entity(Entity::new_underground_belt(
station.beltspeed, station_type_belt.beltspeed,
underground_right, underground_right,
Position::new( Position::new(
outrail_x - 7, outrail_x + 5,
30 + total_stacker_height 30 + total_stacker_height
+ previous_station_heights + previous_station_heights
+ output_height + output_height
@ -384,11 +526,23 @@ pub fn multistation(
), ),
beltdirection, beltdirection,
)); ));
} else {
blueprint.add_entity(Entity::new_underground_belt( blueprint.add_entity(Entity::new_underground_belt(
station.beltspeed, station_type_belt.beltspeed,
underground_left, underground_right,
Position::new( Position::new(
outrail_x - 5, outrail_x + 3,
30 + total_stacker_height
+ previous_station_heights
+ output_height
- 2 * j as PositionType,
),
beltdirection,
));
blueprint.add_entity(Entity::new_belt(
station_type_belt.beltspeed,
Position::new(
outrail_x + 5,
30 + total_stacker_height 30 + total_stacker_height
+ previous_station_heights + previous_station_heights
+ output_height + output_height
@ -397,146 +551,24 @@ pub fn multistation(
beltdirection, beltdirection,
)); ));
} }
(outrail_x - 17, false)
}
9 => {
blueprint.add_entity(Entity::new_underground_belt(
station.beltspeed,
underground_left,
Position::new(
outrail_x - 15,
30 + total_stacker_height + previous_station_heights + output_height
- 2 * j as PositionType,
),
beltdirection,
));
(outrail_x - 15, false)
}
11 => {
blueprint.add_entity(Entity::new_underground_belt(
station.beltspeed,
underground_left,
Position::new(
outrail_x - 11,
30 + total_stacker_height + previous_station_heights + output_height
- 2 * j as PositionType,
),
beltdirection,
));
(outrail_x - 11, false)
}
13 => {
blueprint.add_entity(Entity::new_underground_belt(
station.beltspeed,
underground_left,
Position::new(
outrail_x - 9,
30 + total_stacker_height + previous_station_heights + output_height
- 2 * j as PositionType,
),
beltdirection,
));
(outrail_x - 9, false)
}
15 => {
blueprint.add_entity(Entity::new_underground_belt(
station.beltspeed,
underground_left,
Position::new(
outrail_x - 9,
30 + total_stacker_height + previous_station_heights + output_height
- 2 * j as PositionType,
),
beltdirection,
));
(outrail_x - 9, true)
}
17 => {
blueprint.add_entity(Entity::new_underground_belt(
station.beltspeed,
underground_left,
Position::new(
outrail_x - 7,
30 + total_stacker_height + previous_station_heights + output_height
- 2 * j as PositionType,
),
beltdirection,
));
(outrail_x - 7, false)
}
19 | 21 | 23 => {
blueprint.add_entity(Entity::new_underground_belt(
station.beltspeed,
underground_left,
Position::new(
outrail_x - 5,
30 + total_stacker_height + previous_station_heights + output_height
- 2 * j as PositionType,
),
beltdirection,
));
(outrail_x - 5, false)
}
_ => {
blueprint.add_entity(Entity::new_underground_belt(
station.beltspeed,
underground_left,
Position::new(
outrail_x - 3,
30 + total_stacker_height + previous_station_heights + output_height
- 2 * j as PositionType,
),
beltdirection,
));
(outrail_x - 3, false)
}
};
if signal { for l in 0..((underground_x - belt_x) / 2) {
blueprint.add_entity(Entity::new_underground_belt( blueprint.add_entity(Entity::new_belt(
station.beltspeed, station_type_belt.beltspeed,
underground_right, Position::new(
Position::new( belt_x + 2 * l,
outrail_x + 5, 30 + total_stacker_height
30 + total_stacker_height + previous_station_heights + output_height + previous_station_heights
- 2 * j as PositionType, + output_height
), - 2 * j as PositionType,
beltdirection, ),
)); beltdirection,
} else { ));
blueprint.add_entity(Entity::new_underground_belt( }
station.beltspeed, }
underground_right, station_height
Position::new(
outrail_x + 3,
30 + total_stacker_height + previous_station_heights + output_height
- 2 * j as PositionType,
),
beltdirection,
));
blueprint.add_entity(Entity::new_belt(
station.beltspeed,
Position::new(
outrail_x + 5,
30 + total_stacker_height + previous_station_heights + output_height
- 2 * j as PositionType,
),
beltdirection,
));
} }
};
for l in 0..((underground_x - belt_x) / 2) {
blueprint.add_entity(Entity::new_belt(
station.beltspeed,
Position::new(
belt_x + 2 * l,
30 + total_stacker_height + previous_station_heights + output_height
- 2 * j as PositionType,
),
beltdirection,
));
}
}
// rail connection // rail connection
if i != stations.len() - 1 { if i != stations.len() - 1 {

View file

@ -6,15 +6,112 @@ use factorio_core::{
prelude::*, prelude::*,
}; };
use crate::{binary_merger::merger, multistation::StationSpec}; use crate::binary_merger::merger;
pub struct StationBasicSpec { #[derive(Debug)]
pub struct StationSpec {
pub train_information: TrainInformation,
pub station_name: String,
pub station_type: StationType,
}
#[derive(Debug)]
pub struct TrainInformation {
pub locomotives: usize,
pub wagons: usize,
}
#[derive(Debug)]
pub enum StationType {
Empty(StationTypeEmpty),
Belt(StationTypeBelt),
}
#[derive(Debug)]
pub struct StationTypeEmpty {
pub space: PositionType,
}
#[derive(Debug)]
pub struct StationTypeBelt {
pub load: bool,
pub beltspeed: Beltspeed,
pub lanes: usize,
pub belttype: Belttype,
pub stacked: bool,
pub inserter_type: InserterType, pub inserter_type: InserterType,
pub inserter_quality: Quality, pub inserter_quality: Quality,
pub chest_type: ChestType, pub chest_type: ChestType,
pub chest_quality: Quality, pub chest_quality: Quality,
} }
#[derive(Debug)]
struct StationBasicSpec {
inserter_type: InserterType,
inserter_quality: Quality,
chest_type: ChestType,
chest_quality: Quality,
}
impl StationSpec {
pub fn new(
locomotives: usize,
wagons: usize,
station_name: String,
station_type: StationType,
) -> Self {
Self {
train_information: TrainInformation {
locomotives,
wagons,
},
station_name,
station_type,
}
}
pub fn new_belt(
locomotives: usize,
wagons: usize,
station_name: String,
load: bool,
beltspeed: Beltspeed,
lanes: usize,
belttype: Belttype,
stacked: bool,
) -> Self {
Self::new(
locomotives,
wagons,
station_name,
StationType::Belt(StationTypeBelt {
load,
beltspeed,
lanes,
belttype,
stacked,
inserter_type: InserterType::Bulk,
inserter_quality: Quality::Normal,
chest_type: ChestType::Steel,
chest_quality: Quality::Normal,
}),
)
}
pub fn new_empty(
locomotives: usize,
wagons: usize,
station_name: String,
space: PositionType,
) -> Self {
Self::new(
locomotives,
wagons,
station_name,
StationType::Empty(StationTypeEmpty { space }),
)
}
}
impl Default for StationBasicSpec { impl Default for StationBasicSpec {
fn default() -> Self { fn default() -> Self {
Self { Self {
@ -26,7 +123,7 @@ impl Default for StationBasicSpec {
} }
} }
pub fn unloader( fn unloader(
beltspeed: Beltspeed, beltspeed: Beltspeed,
belttype: Belttype, belttype: Belttype,
stacked: bool, stacked: bool,
@ -164,7 +261,7 @@ pub fn unloader(
} }
} }
pub fn one_loader( fn one_loader(
beltspeed: Beltspeed, beltspeed: Beltspeed,
stacked: bool, stacked: bool,
basic_spec: &StationBasicSpec, basic_spec: &StationBasicSpec,
@ -223,20 +320,28 @@ pub fn one_loader(
(b, -6) (b, -6)
} }
#[allow(clippy::too_many_arguments)] fn belt_station(
pub fn basic_station(station_spec: &StationSpec, basic_spec: &StationBasicSpec) -> Blueprint { blueprint: &mut Blueprint,
let section_size = station_spec.wagons / station_spec.lanes; train_information: &TrainInformation,
assert!(station_spec.wagons % station_spec.lanes == 0); station_type_belt: &StationTypeBelt,
) {
let section_size = train_information.wagons / station_type_belt.lanes;
assert!(train_information.wagons % station_type_belt.lanes == 0);
assert!(section_size.is_power_of_two()); assert!(section_size.is_power_of_two());
assert!(station_spec.lanes <= station_spec.wagons); assert!(station_type_belt.lanes <= train_information.wagons);
let mut blueprint = Blueprint::new(); let global_x_offset = train_information.locomotives * 7;
let global_x_offset = station_spec.locomotives * 7; let basic_spec = StationBasicSpec {
inserter_type: station_type_belt.inserter_type,
inserter_quality: station_type_belt.inserter_quality,
chest_type: station_type_belt.chest_type,
chest_quality: station_type_belt.chest_quality,
};
// electric poles // electric poles
let mut poles = Vec::new(); let mut poles = Vec::new();
for l in 1..=(station_spec.wagons + station_spec.locomotives) { for l in 1..=(train_information.wagons + train_information.locomotives) {
poles.push(blueprint.add_entity(Entity::new_electric_pole( poles.push(blueprint.add_entity(Entity::new_electric_pole(
ElectricPoleType::Medium, ElectricPoleType::Medium,
Position::new(1, 1) + 2 * Position::new(7 * l as PositionType, -2), Position::new(1, 1) + 2 * Position::new(7 * l as PositionType, -2),
@ -247,43 +352,42 @@ pub fn basic_station(station_spec: &StationSpec, basic_spec: &StationBasicSpec)
blueprint.add_wire(a, 5, b, 5); blueprint.add_wire(a, 5, b, 5);
} }
// unloader let (_, output_y) = match station_type_belt.load {
let (_, output_y) = match station_spec.load {
false => unloader( false => unloader(
station_spec station_type_belt
.beltspeed .beltspeed
.halvings((station_spec.wagons / station_spec.lanes).ilog2() as usize), .halvings((train_information.wagons / station_type_belt.lanes).ilog2() as usize),
station_spec.belttype, station_type_belt.belttype,
station_spec.stacked, station_type_belt.stacked,
basic_spec, &basic_spec,
), ),
true => one_loader( true => one_loader(
station_spec station_type_belt
.beltspeed .beltspeed
.halvings((station_spec.wagons / station_spec.lanes).ilog2() as usize), .halvings((train_information.wagons / station_type_belt.lanes).ilog2() as usize),
station_spec.stacked, station_type_belt.stacked,
basic_spec, &basic_spec,
), ),
}; };
for l in 0..station_spec.wagons { for l in 0..train_information.wagons {
let (mut unloader, _) = match station_spec.load { let (mut unloader, _) =
false => unloader( match station_type_belt.load {
station_spec false => unloader(
.beltspeed station_type_belt.beltspeed.halvings(
.halvings((station_spec.wagons / station_spec.lanes).ilog2() as usize), (train_information.wagons / station_type_belt.lanes).ilog2() as usize,
station_spec.belttype, ),
station_spec.stacked, station_type_belt.belttype,
basic_spec, station_type_belt.stacked,
), &basic_spec,
true => one_loader( ),
station_spec true => one_loader(
.beltspeed station_type_belt.beltspeed.halvings(
.halvings((station_spec.wagons / station_spec.lanes).ilog2() as usize), (train_information.wagons / station_type_belt.lanes).ilog2() as usize,
station_spec.stacked, ),
basic_spec, station_type_belt.stacked,
), &basic_spec,
}; ),
};
unloader.transform(Transformation::new( unloader.transform(Transformation::new(
Direction::Up, Direction::Up,
@ -293,6 +397,27 @@ pub fn basic_station(station_spec: &StationSpec, basic_spec: &StationBasicSpec)
blueprint.add_blueprint(unloader); blueprint.add_blueprint(unloader);
} }
let mut m = merger(
station_type_belt.load,
station_type_belt.beltspeed,
7,
station_type_belt.lanes,
train_information.wagons,
);
m.transform(Transformation::new(
Direction::Up,
2 * Position::new(global_x_offset as PositionType + 3, output_y),
));
blueprint.add_blueprint(m);
}
pub fn station(station_spec: &StationSpec) -> Blueprint {
let mut blueprint = Blueprint::new();
// unloader
// train stop // train stop
blueprint.add_entity(Entity::new_unknown( blueprint.add_entity(Entity::new_unknown(
"train-stop", "train-stop",
@ -302,7 +427,11 @@ pub fn basic_station(station_spec: &StationSpec, basic_spec: &StationBasicSpec)
)); ));
// rails // rails
for l in 0..(station_spec.wagons * 7 + global_x_offset).div_ceil(2) { for l in 0..((station_spec.train_information.wagons
+ station_spec.train_information.locomotives)
* 7)
.div_ceil(2)
{
blueprint.add_entity(Entity::new_unknown( blueprint.add_entity(Entity::new_unknown(
"straight-rail", "straight-rail",
Position::new(2 + 4 * l as PositionType, 2), Position::new(2 + 4 * l as PositionType, 2),
@ -311,22 +440,14 @@ pub fn basic_station(station_spec: &StationSpec, basic_spec: &StationBasicSpec)
)); ));
} }
// output and merging match &station_spec.station_type {
StationType::Empty(_station_type_empty) => (),
let mut m = merger( StationType::Belt(station_type_belt) => belt_station(
station_spec.load, &mut blueprint,
station_spec.beltspeed, &station_spec.train_information,
7, station_type_belt,
station_spec.lanes, ),
station_spec.wagons, }
);
m.transform(Transformation::new(
Direction::Up,
2 * Position::new(global_x_offset as PositionType + 3, output_y),
));
blueprint.add_blueprint(m);
blueprint blueprint
} }