use indexmap::IndexMap;
use crate::{
errors::BrError,
wrapper::{
Brick, Entity, Guid, Owner, Position, UnsavedFs, UnsavedWorld, WireConnection, WirePort,
WorldMeta,
},
};
#[derive(Default)]
pub struct World {
pub meta: WorldMeta,
pub owners: IndexMap<Guid, Owner>,
pub bricks: Vec<Brick>,
pub grids: Vec<(Entity, Vec<Brick>)>,
pub wires: Vec<WireConnection>,
pub entities: Vec<Entity>,
}
impl World {
pub fn new() -> Self {
Self::default()
}
#[cfg(feature = "brdb")]
pub fn write_brdb(&self, path: impl AsRef<std::path::Path>) -> Result<(), BrError> {
crate::Brdb::new(path)?.save("BRDB-RS", self)
}
#[cfg(feature = "brz")]
pub fn write_brz(&self, path: impl AsRef<std::path::Path>) -> Result<(), BrError> {
crate::Brz::save(path, self)
}
#[cfg(feature = "brz")]
pub fn to_brz_vec(&self) -> Result<Vec<u8>, BrError> {
let mut data = Vec::new();
self.to_unsaved()?
.to_pending()?
.to_brz_data(Some(14))?
.write(&mut data, Some(14))?;
Ok(data)
}
pub fn to_unsaved(&self) -> Result<UnsavedFs, BrError> {
let mut unsaved_fs = UnsavedFs {
meta: self.meta.clone(),
worlds: Default::default(),
};
{
let mut world = UnsavedWorld::default();
for o in self.owners.values() {
world.owners.add(o);
}
world.add_bricks_to_grid(1, &self.bricks);
for (entity, bricks) in &self.grids {
let grid_id = world.add_entity(entity);
world.add_bricks_to_grid(grid_id, bricks);
}
for entity in &self.entities {
world.add_entity(entity);
}
for (i, wire) in self.wires.iter().enumerate() {
world
.add_wire(wire)
.map_err(|e| e.wrap(format!("wire {i}: {wire}")))?;
}
unsaved_fs.worlds.insert(0, world);
}
Ok(unsaved_fs)
}
pub fn add_brick(&mut self, brick: Brick) {
self.bricks.push(brick);
}
pub fn add_bricks(&mut self, bricks: impl IntoIterator<Item = Brick>) {
self.bricks.extend(bricks);
}
pub fn add_entity(&mut self, entity: Entity) {
self.entities.push(entity);
}
pub fn add_brick_grid(&mut self, entity: Entity, bricks: impl IntoIterator<Item = Brick>) {
self.grids.push((
entity,
bricks
.into_iter()
.map(|mut b| {
b.position = b.position - Position::CHUNK_HALF;
b
})
.collect(),
));
}
pub fn add_wire(&mut self, conn: WireConnection) {
self.wires.push(conn);
}
pub fn add_wires(&mut self, wires: impl IntoIterator<Item = WireConnection>) {
self.wires.extend(wires);
}
pub fn add_wire_connection(&mut self, source: WirePort, target: WirePort) {
self.wires.push(WireConnection { source, target });
}
}