Add first blueprint abstraction

This commit is contained in:
hal8174 2025-01-20 23:15:55 +01:00
parent 505ca6ff5c
commit 2f12802507
4 changed files with 251 additions and 70 deletions

View file

@ -1,27 +1,12 @@
use factorio_blueprint::{
Blueprint, BlueprintEntity, BlueprintPosition, belt::convert_to_blueprint,
Blueprint, BlueprintEntity, BlueprintPosition,
abstraction::{self, Entity},
belt::convert_to_blueprint,
};
use factorio_core::{beltoptions::Beltspeed, pathfield::PathField, prelude::*};
pub fn generate_4_lane_balancer() -> Blueprint {
let mut e = vec![
BlueprintEntity::builder("splitter".to_owned(), 1, BlueprintPosition::new(1.0, 0.5))
.build(),
BlueprintEntity::builder("splitter".to_owned(), 2, BlueprintPosition::new(3.0, 0.5))
.build(),
BlueprintEntity::builder("splitter".to_owned(), 3, BlueprintPosition::new(2.0, 1.5))
.build(),
BlueprintEntity::builder("splitter".to_owned(), 11, BlueprintPosition::new(2.0, 4.5))
.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;
e.extend(convert_to_blueprint(
&[
fn balancer_path() -> Vec<PathField> {
vec![
PathField::Belt {
pos: Position::new(0, 1),
dir: Direction::Up,
@ -88,7 +73,47 @@ pub fn generate_4_lane_balancer() -> Blueprint {
dir: Direction::Up,
len: 4,
},
],
]
}
pub fn generate_4_lane_balancer2() -> Blueprint {
let mut b = abstraction::Blueprint::new();
let splitter_pos = [(0, 0), (2, 0), (1, 1), (1, 4), (0, 7), (2, 7)];
for (x, y) in splitter_pos {
b.add_entity(Entity::new(
"splitter",
Position::new(x, y),
Direction::Up,
Position::new(2, 1),
));
}
b.add_path(&balancer_path(), Beltspeed::Normal);
b.to_blueprint()
}
pub fn generate_4_lane_balancer() -> Blueprint {
let mut e = vec![
BlueprintEntity::builder("splitter".to_owned(), 1, BlueprintPosition::new(1.0, 0.5))
.build(),
BlueprintEntity::builder("splitter".to_owned(), 2, BlueprintPosition::new(3.0, 0.5))
.build(),
BlueprintEntity::builder("splitter".to_owned(), 3, BlueprintPosition::new(2.0, 1.5))
.build(),
BlueprintEntity::builder("splitter".to_owned(), 11, BlueprintPosition::new(2.0, 4.5))
.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;
e.extend(convert_to_blueprint(
&balancer_path(),
&Beltspeed::Normal,
&mut nextfree,
));

View file

@ -1,10 +1,13 @@
use factorio_blueprint::{BlueprintString, encode};
use factorio_blueprint_generator::balancer::generate_4_lane_balancer;
use factorio_blueprint_generator::balancer::{generate_4_lane_balancer, generate_4_lane_balancer2};
fn main() {
let b = BlueprintString::Blueprint(generate_4_lane_balancer());
let b2 = BlueprintString::Blueprint(generate_4_lane_balancer2());
println!("{}", serde_json::to_string_pretty(&b).unwrap());
println!("{}", serde_json::to_string_pretty(&b).unwrap());
println!("{}", encode(&serde_json::to_string(&b).unwrap()));
println!("{}", encode(&serde_json::to_string(&b2).unwrap()));
}

View file

@ -0,0 +1,152 @@
use factorio_core::{
beltoptions::Beltspeed,
pathfield::PathField,
prelude::{Direction, Position, PositionType},
};
use std::{collections::HashMap, str::FromStr, sync::atomic::AtomicUsize};
use crate::{BlueprintEntity, BlueprintPosition};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum UndergroundType {
Input,
Output,
}
pub struct Entity {
name: String,
position: Position,
direction: Direction,
size: Position,
underground_type: Option<UndergroundType>,
}
impl Entity {
pub fn new(
name: impl AsRef<str>,
position: Position,
direction: Direction,
size: Position,
) -> Self {
Self {
name: name.as_ref().to_owned(),
position,
direction,
size,
underground_type: None,
}
}
pub fn underground_type(mut self, underground_type: UndergroundType) -> Self {
self.underground_type = Some(underground_type);
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct EntityKey(usize);
static ENTITY_COUNTER: AtomicUsize = AtomicUsize::new(0);
pub struct Blueprint {
entities: Vec<(EntityKey, Entity)>,
keys: HashMap<EntityKey, usize>,
}
impl Blueprint {
pub fn new() -> Self {
Self {
entities: Vec::new(),
keys: HashMap::new(),
}
}
pub fn add_entity(&mut self, entity: Entity) -> EntityKey {
let id = EntityKey(ENTITY_COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed));
let pos = self.entities.len();
self.keys.insert(id, pos);
self.entities.push((id, entity));
id
}
pub fn add_path<'a>(
&mut self,
path: impl IntoIterator<Item = &'a PathField>,
beltspeed: Beltspeed,
) {
for &p in path {
match p {
PathField::Belt { pos, dir } => {
self.add_entity(Entity::new(
beltspeed.string(),
pos,
dir,
Position::new(1, 1),
));
}
PathField::Underground { pos, dir, len } => {
self.add_entity(
Entity::new(
beltspeed.string_underground(),
pos,
dir,
Position::new(1, 1),
)
.underground_type(UndergroundType::Input),
);
self.add_entity(
Entity::new(
beltspeed.string_underground(),
pos.in_direction(&dir, len as PositionType),
dir,
Position::new(1, 1),
)
.underground_type(UndergroundType::Output),
);
}
};
}
}
pub fn to_blueprint(&self) -> super::Blueprint {
let entities = self
.entities
.iter()
.enumerate()
.map(|(i, (_, e))| {
BlueprintEntity::builder(
e.name.clone(),
i as u32 + 1,
BlueprintPosition::new(
e.position.x as f64 + 0.5 * e.size.x as f64,
e.position.y as f64 + 0.5 * e.size.y as f64,
),
)
.direction(match e.direction {
Direction::Up => 0,
Direction::Right => 4,
Direction::Down => 8,
Direction::Left => 12,
})
.maybe_underground_type(e.underground_type.map(|u| match u {
UndergroundType::Input => String::from("input"),
UndergroundType::Output => String::from("output"),
}))
.build()
})
.collect();
super::Blueprint::builder()
.label(String::from("test"))
.entities(entities)
.build()
}
}
impl Default for Blueprint {
fn default() -> Self {
Self::new()
}
}

View file

@ -5,6 +5,7 @@ pub mod belt;
pub mod structs;
pub use structs::*;
pub mod abstraction;
pub fn decode(s: &str) -> String {
let raw = s.trim().as_bytes();