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

@ -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();