From 2f12802507635580a2ee4ea019f28b52b6f7e61c Mon Sep 17 00:00:00 2001 From: hal8174 Date: Mon, 20 Jan 2025 23:15:55 +0100 Subject: [PATCH] Add first blueprint abstraction --- factorio-blueprint-generator/src/balancer.rs | 163 ++++++++++-------- .../src/bin/balancer_blueprint.rs | 5 +- factorio-blueprint/src/abstraction.rs | 152 ++++++++++++++++ factorio-blueprint/src/lib.rs | 1 + 4 files changed, 251 insertions(+), 70 deletions(-) create mode 100644 factorio-blueprint/src/abstraction.rs diff --git a/factorio-blueprint-generator/src/balancer.rs b/factorio-blueprint-generator/src/balancer.rs index 752de18..f285e2a 100644 --- a/factorio-blueprint-generator/src/balancer.rs +++ b/factorio-blueprint-generator/src/balancer.rs @@ -1,8 +1,100 @@ 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::*}; +fn balancer_path() -> Vec { + vec![ + PathField::Belt { + pos: Position::new(0, 1), + dir: Direction::Up, + }, + 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 { + pos: Position::new(1, 3), + dir: Direction::Left, + }, + PathField::Belt { + pos: Position::new(2, 3), + dir: Direction::Right, + }, + PathField::Belt { + pos: Position::new(3, 3), + dir: Direction::Up, + }, + PathField::Belt { + pos: Position::new(0, 5), + dir: Direction::Right, + }, + PathField::Belt { + pos: Position::new(1, 5), + dir: Direction::Up, + }, + PathField::Belt { + pos: Position::new(2, 5), + dir: Direction::Up, + }, + PathField::Belt { + pos: Position::new(3, 5), + dir: Direction::Left, + }, + PathField::Belt { + pos: Position::new(0, 6), + dir: Direction::Up, + }, + PathField::Belt { + pos: Position::new(3, 6), + dir: Direction::Up, + }, + PathField::Underground { + pos: Position::new(1, 6), + dir: Direction::Up, + len: 4, + }, + PathField::Underground { + pos: Position::new(2, 6), + 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)) @@ -21,74 +113,7 @@ pub fn generate_4_lane_balancer() -> Blueprint { let mut nextfree = e.len() as u32; e.extend(convert_to_blueprint( - &[ - PathField::Belt { - pos: Position::new(0, 1), - dir: Direction::Up, - }, - 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 { - pos: Position::new(1, 3), - dir: Direction::Left, - }, - PathField::Belt { - pos: Position::new(2, 3), - dir: Direction::Right, - }, - PathField::Belt { - pos: Position::new(3, 3), - dir: Direction::Up, - }, - PathField::Belt { - pos: Position::new(0, 5), - dir: Direction::Right, - }, - PathField::Belt { - pos: Position::new(1, 5), - dir: Direction::Up, - }, - PathField::Belt { - pos: Position::new(2, 5), - dir: Direction::Up, - }, - PathField::Belt { - pos: Position::new(3, 5), - dir: Direction::Left, - }, - PathField::Belt { - pos: Position::new(0, 6), - dir: Direction::Up, - }, - PathField::Belt { - pos: Position::new(3, 6), - dir: Direction::Up, - }, - PathField::Underground { - pos: Position::new(1, 6), - dir: Direction::Up, - len: 4, - }, - PathField::Underground { - pos: Position::new(2, 6), - dir: Direction::Up, - len: 4, - }, - ], + &balancer_path(), &Beltspeed::Normal, &mut nextfree, )); diff --git a/factorio-blueprint-generator/src/bin/balancer_blueprint.rs b/factorio-blueprint-generator/src/bin/balancer_blueprint.rs index e3d73ba..c9414f9 100644 --- a/factorio-blueprint-generator/src/bin/balancer_blueprint.rs +++ b/factorio-blueprint-generator/src/bin/balancer_blueprint.rs @@ -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())); } diff --git a/factorio-blueprint/src/abstraction.rs b/factorio-blueprint/src/abstraction.rs new file mode 100644 index 0000000..7163e63 --- /dev/null +++ b/factorio-blueprint/src/abstraction.rs @@ -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, +} + +impl Entity { + pub fn new( + name: impl AsRef, + 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, +} + +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, + 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() + } +} diff --git a/factorio-blueprint/src/lib.rs b/factorio-blueprint/src/lib.rs index 7928fcc..1a456e1 100644 --- a/factorio-blueprint/src/lib.rs +++ b/factorio-blueprint/src/lib.rs @@ -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();