Add connect output belt to station

This commit is contained in:
hal8174 2025-01-26 15:58:58 +01:00
parent aabd9486e0
commit 1af9712bcb
4 changed files with 435 additions and 139 deletions

View file

@ -1,125 +1,108 @@
use factorio_blueprint::{ use factorio_blueprint::abstraction::{Blueprint, Entity};
Blueprint, BlueprintEntity, BlueprintPosition,
abstraction::{self, Entity},
belt::convert_to_blueprint,
};
use factorio_core::{beltoptions::Beltspeed, pathfield::PathField, prelude::*}; use factorio_core::{beltoptions::Beltspeed, pathfield::PathField, prelude::*};
fn balancer_path() -> Vec<PathField> { fn balancer_path() -> Vec<PathField> {
vec![ vec![
PathField::Belt { PathField::Belt {
pos: Position::new(0, 1), pos: Position::new(1, 0),
dir: Direction::Up, dir: Direction::Right,
},
PathField::Belt {
pos: Position::new(3, 1),
dir: Direction::Up,
},
PathField::Belt {
pos: Position::new(0, 2),
dir: Direction::Up,
},
PathField::Belt {
pos: Position::new(3, 2),
dir: Direction::Up,
},
PathField::Belt {
pos: Position::new(0, 3),
dir: Direction::Up,
}, },
PathField::Belt { PathField::Belt {
pos: Position::new(1, 3), pos: Position::new(1, 3),
dir: Direction::Left, dir: Direction::Right,
},
PathField::Belt {
pos: Position::new(2, 0),
dir: Direction::Right,
}, },
PathField::Belt { PathField::Belt {
pos: Position::new(2, 3), pos: Position::new(2, 3),
dir: Direction::Right, dir: Direction::Right,
}, },
PathField::Belt {
pos: Position::new(3, 0),
dir: Direction::Down,
},
PathField::Belt {
pos: Position::new(3, 1),
dir: Direction::Right,
},
PathField::Belt {
pos: Position::new(3, 2),
dir: Direction::Right,
},
PathField::Belt { PathField::Belt {
pos: Position::new(3, 3), pos: Position::new(3, 3),
dir: Direction::Up, dir: Direction::Up,
}, },
PathField::Belt { PathField::Belt {
pos: Position::new(0, 5), pos: Position::new(5, 0),
dir: Direction::Right, dir: Direction::Right,
}, },
PathField::Belt { PathField::Belt {
pos: Position::new(1, 5), pos: Position::new(5, 1),
dir: Direction::Up, dir: Direction::Up,
}, },
PathField::Belt { PathField::Belt {
pos: Position::new(2, 5), pos: Position::new(5, 2),
dir: Direction::Up, dir: Direction::Down,
}, },
PathField::Belt { PathField::Belt {
pos: Position::new(3, 5), pos: Position::new(5, 3),
dir: Direction::Left, dir: Direction::Right,
}, },
PathField::Belt { PathField::Belt {
pos: Position::new(0, 6), pos: Position::new(6, 0),
dir: Direction::Up, dir: Direction::Right,
}, },
PathField::Belt { PathField::Belt {
pos: Position::new(3, 6), pos: Position::new(6, 3),
dir: Direction::Up, dir: Direction::Right,
}, },
PathField::Underground { PathField::Underground {
pos: Position::new(1, 6), pos: Position::new(2, 1),
dir: Direction::Up, dir: Direction::Right,
len: 4, len: 4,
}, },
PathField::Underground { PathField::Underground {
pos: Position::new(2, 6), pos: Position::new(2, 2),
dir: Direction::Up, dir: Direction::Right,
len: 4, len: 4,
}, },
] ]
} }
pub fn generate_4_lane_balancer2() -> Blueprint { pub fn generate_4_lane_balancer(beltspeed: Beltspeed) -> Blueprint {
let mut b = abstraction::Blueprint::new(); let mut b = Blueprint::new();
let splitter_pos = [(2, 1), (6, 1), (4, 3), (4, 9), (2, 15), (6, 15)]; let splitter_pos = [(1, 2), (1, 6), (3, 4), (9, 4), (15, 2), (15, 6)];
for (x, y) in splitter_pos { for (x, y) in splitter_pos {
b.add_entity(Entity::new_splitter( b.add_entity(Entity::new_splitter(
Beltspeed::Normal, beltspeed,
Position::new(x, y), Position::new(x, y),
Direction::Up, Direction::Right,
)); ));
} }
b.add_path(&balancer_path(), Beltspeed::Normal); b.add_path(&balancer_path(), beltspeed);
// b.transform(Transformation::new(Direction::Right, Position::new(0, 0))); b
b.to_blueprint()
} }
pub fn generate_4_lane_balancer() -> Blueprint { pub fn binary_balancer(lanes: usize, beltspeed: Beltspeed) -> (PositionType, Blueprint) {
let mut e = vec![ match lanes {
BlueprintEntity::builder("splitter".to_owned(), 1, BlueprintPosition::new(1.0, 0.5)) 4 => (16, generate_4_lane_balancer(beltspeed)),
.build(), 2 => {
BlueprintEntity::builder("splitter".to_owned(), 2, BlueprintPosition::new(3.0, 0.5)) let mut b = Blueprint::new();
.build(), b.add_entity(Entity::new_splitter(
BlueprintEntity::builder("splitter".to_owned(), 3, BlueprintPosition::new(2.0, 1.5)) beltspeed,
.build(), Position::new(1, 2),
BlueprintEntity::builder("splitter".to_owned(), 11, BlueprintPosition::new(2.0, 4.5)) Direction::Right,
.build(), ));
BlueprintEntity::builder("splitter".to_owned(), 20, BlueprintPosition::new(1.0, 7.5))
.build(),
BlueprintEntity::builder("splitter".to_owned(), 21, BlueprintPosition::new(3.0, 7.5))
.build(),
];
let mut nextfree = e.len() as u32; (2, b)
e.extend(convert_to_blueprint( }
&balancer_path(), _ => (0, Blueprint::new()),
&Beltspeed::Normal, }
&mut nextfree,
));
Blueprint::builder()
.label("balancer".to_string())
.entities(e)
.build()
} }

View file

@ -1,13 +1,27 @@
use factorio_blueprint::{BlueprintString, encode}; use factorio_blueprint::{BlueprintBook, BlueprintBookEntry, BlueprintString, encode};
use factorio_blueprint_generator::balancer::{generate_4_lane_balancer, generate_4_lane_balancer2}; use factorio_blueprint_generator::balancer::{binary_balancer, generate_4_lane_balancer};
fn main() { fn main() {
let b = BlueprintString::Blueprint(generate_4_lane_balancer()); let mut v = Vec::new();
let b2 = BlueprintString::Blueprint(generate_4_lane_balancer2());
for i in 0..3 {
let lanes = 1 << i;
let (_, b) = binary_balancer(lanes, factorio_core::beltoptions::Beltspeed::Normal);
v.push(BlueprintBookEntry::new(
BlueprintString::Blueprint(b.to_blueprint()),
i + 1,
));
}
let b = BlueprintString::BlueprintBook(
BlueprintBook::builder()
.blueprints(v)
.active_index(1)
.build(),
);
println!("{}", serde_json::to_string_pretty(&b).unwrap()); println!("{}", serde_json::to_string_pretty(&b).unwrap());
println!("{}", serde_json::to_string_pretty(&b2).unwrap());
println!("{}", encode(&serde_json::to_string(&b).unwrap())); println!("{}", encode(&serde_json::to_string(&b).unwrap()));
println!("{}", encode(&serde_json::to_string(&b2).unwrap()));
} }

View file

@ -12,63 +12,77 @@ struct Args {
fn main() { fn main() {
let args = Args::parse(); let args = Args::parse();
// let stations: Vec<_> = (0..2) let stations: Vec<_> = [false, true]
// .map(|_| StationSpec { .into_iter()
// locomotives: 1, .flat_map(|load| {
// wagons: 2, [
// load: false, Beltspeed::Normal,
// beltspeed: Beltspeed::Turbo, Beltspeed::Fast,
// lanes: 2, Beltspeed::Express,
// }) Beltspeed::Turbo,
// .collect(); ]
.into_iter()
.flat_map(move |beltspeed| {
(0..6).flat_map(move |i| {
(0..=i).map(move |j| StationSpec {
locomotives: 1,
wagons: 1 << i,
load,
beltspeed,
lanes: 1 << j,
})
})
})
})
.collect();
let b = BlueprintString::Blueprint( let b = BlueprintString::Blueprint(
multistation( multistation(
// &stations, &stations,
&[ // &[
StationSpec { // StationSpec {
locomotives: 2, // locomotives: 2,
wagons: 4, // wagons: 4,
load: false, // load: false,
beltspeed: Beltspeed::Normal, // beltspeed: Beltspeed::Normal,
lanes: 4, // lanes: 4,
}, // },
StationSpec { // StationSpec {
locomotives: 3, // locomotives: 3,
wagons: 8, // wagons: 8,
load: false, // load: false,
beltspeed: Beltspeed::Turbo, // beltspeed: Beltspeed::Turbo,
lanes: 8, // lanes: 8,
}, // },
StationSpec { // StationSpec {
locomotives: 3, // locomotives: 3,
wagons: 8, // wagons: 8,
load: false, // load: false,
beltspeed: Beltspeed::Turbo, // beltspeed: Beltspeed::Turbo,
lanes: 4, // lanes: 4,
}, // },
StationSpec { // StationSpec {
locomotives: 3, // locomotives: 3,
wagons: 8, // wagons: 8,
load: false, // load: false,
beltspeed: Beltspeed::Turbo, // beltspeed: Beltspeed::Turbo,
lanes: 2, // lanes: 2,
}, // },
StationSpec { // StationSpec {
locomotives: 3, // locomotives: 3,
wagons: 8, // wagons: 8,
load: false, // load: false,
beltspeed: Beltspeed::Turbo, // beltspeed: Beltspeed::Turbo,
lanes: 1, // lanes: 1,
}, // },
StationSpec { // StationSpec {
locomotives: 1, // locomotives: 1,
wagons: 1, // wagons: 1,
load: false, // load: false,
beltspeed: Beltspeed::Turbo, // beltspeed: Beltspeed::Turbo,
lanes: 1, // lanes: 1,
}, // },
], // ],
8, 8,
) )
.to_blueprint(), .to_blueprint(),

View file

@ -1,7 +1,7 @@
use factorio_blueprint::abstraction::{Blueprint, Entity, EntityType, RailType}; use factorio_blueprint::abstraction::{Blueprint, Entity, EntityType, RailType, UndergroundType};
use factorio_core::{beltoptions::Beltspeed, prelude::*}; use factorio_core::{beltoptions::Beltspeed, prelude::*};
use crate::station::basic_station; use crate::{balancer::binary_balancer, station::basic_station};
pub struct StationSpec { pub struct StationSpec {
pub locomotives: usize, pub locomotives: usize,
@ -11,6 +11,35 @@ pub struct StationSpec {
pub lanes: usize, pub lanes: usize,
} }
fn calculate_station_height(
output_height: PositionType,
lanes: usize,
beltspeed: Beltspeed,
) -> PositionType {
let station_height = match beltspeed {
Beltspeed::Normal => {
if lanes == 1 && output_height % 4 == 1 {
4 + ((3 + output_height) & !0b11)
} else {
4 + ((15 + output_height) & !0b11)
}
}
Beltspeed::Fast => {
if lanes == 1 || lanes == 2 && output_height % 4 == 3 {
4 + ((3 + output_height) & !0b11)
} else {
4 + ((9 + output_height) & !0b11)
}
}
Beltspeed::Express | Beltspeed::Turbo => 4 + ((3 + output_height) & !0b11),
};
let station_height = PositionType::max(12, station_height);
assert!(station_height % 4 == 0);
station_height
}
pub fn multistation(stations: &[StationSpec], stacker_size: usize) -> Blueprint { pub fn multistation(stations: &[StationSpec], stacker_size: usize) -> Blueprint {
let longest_train = stations let longest_train = stations
.iter() .iter()
@ -215,6 +244,7 @@ pub fn multistation(stations: &[StationSpec], stacker_size: usize) -> Blueprint
)); ));
} }
// station
let mut b = basic_station( let mut b = basic_station(
station.load, station.load,
station.locomotives, station.locomotives,
@ -223,9 +253,7 @@ pub fn multistation(stations: &[StationSpec], stacker_size: usize) -> Blueprint
station.beltspeed, station.beltspeed,
factorio_core::beltoptions::Belttype::Full, factorio_core::beltoptions::Belttype::Full,
); );
let output_height = -b.bounding_box().min().y;
let station_height = PositionType::max(12, 4 + ((3 - b.bounding_box().min().y) / 4) * 4);
assert!(station_height % 4 == 0);
b.transform(Transformation::new( b.transform(Transformation::new(
Direction::Down, Direction::Down,
@ -237,6 +265,263 @@ pub fn multistation(stations: &[StationSpec], stacker_size: usize) -> Blueprint
blueprint.add_blueprint(b); blueprint.add_blueprint(b);
// belt output
let station_height =
calculate_station_height(output_height, station.lanes, station.beltspeed);
// rail crossing
let (beltdirection, underground_left, underground_right) = match station.load {
true => (
Direction::Left,
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,
));
blueprint.add_entity(Entity::new_underground_belt(
station.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.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.beltspeed,
underground_left,
Position::new(
outrail_x - 17,
30 + total_stacker_height + previous_station_heights + output_height
- 2 * j as PositionType,
),
beltdirection,
));
if station.beltspeed != Beltspeed::Turbo {
blueprint.add_entity(Entity::new_underground_belt(
station.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.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.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 {
blueprint.add_entity(Entity::new_underground_belt(
station.beltspeed,
underground_right,
Position::new(
outrail_x + 5,
30 + total_stacker_height + previous_station_heights + output_height
- 2 * j as PositionType,
),
beltdirection,
));
} else {
blueprint.add_entity(Entity::new_underground_belt(
station.beltspeed,
underground_right,
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 {
for j in 0..(station_height / 4) { for j in 0..(station_height / 4) {
@ -262,7 +547,7 @@ pub fn multistation(stations: &[StationSpec], stacker_size: usize) -> Blueprint
RailType::ChainSignal, RailType::ChainSignal,
Position::new( Position::new(
inrail_x - 3, inrail_x - 3,
total_stacker_height + 13 + previous_station_heights, total_stacker_height + 15 + previous_station_heights,
), ),
0, 0,
)); ));
@ -270,7 +555,7 @@ pub fn multistation(stations: &[StationSpec], stacker_size: usize) -> Blueprint
RailType::RailSignal, RailType::RailSignal,
Position::new( Position::new(
outrail_x + 3, outrail_x + 3,
total_stacker_height + 13 + previous_station_heights, total_stacker_height + 15 + previous_station_heights,
), ),
8, 8,
)); ));