diff options
| author | metamuffin <metamuffin@disroot.org> | 2024-07-11 16:55:39 +0200 | 
|---|---|---|
| committer | metamuffin <metamuffin@disroot.org> | 2024-07-11 16:55:39 +0200 | 
| commit | 2537e764a359328870c3eabb16ee5238becd3c73 (patch) | |
| tree | 07b731da36fd795399dbb62446e8a36ae3318f0b /server/src | |
| parent | 51f3c580fcfac8d37e5e345031cadda141f0340f (diff) | |
| download | hurrycurry-2537e764a359328870c3eabb16ee5238becd3c73.tar hurrycurry-2537e764a359328870c3eabb16ee5238becd3c73.tar.bz2 hurrycurry-2537e764a359328870c3eabb16ee5238becd3c73.tar.zst | |
add conveyor filters
Diffstat (limited to 'server/src')
| -rw-r--r-- | server/src/data.rs | 74 | ||||
| -rw-r--r-- | server/src/entity/conveyor.rs | 33 | ||||
| -rw-r--r-- | server/src/entity/mod.rs | 56 | ||||
| -rw-r--r-- | server/src/entity/portal.rs | 46 | 
4 files changed, 150 insertions, 59 deletions
| diff --git a/server/src/data.rs b/server/src/data.rs index c5ed25ad..966fd0d2 100644 --- a/server/src/data.rs +++ b/server/src/data.rs @@ -179,23 +179,16 @@ impl Gamedata {          demands_in: Vec<DemandDecl>,          recipes_in: Vec<RecipeDecl>,      ) -> Result<Self> { -        let item_names = RwLock::new(Vec::new()); -        let tile_names = RwLock::new(Vec::new()); +        let reg = ItemTileRegistry::default();          let mut recipes = Vec::new();          let mut demands = Vec::new();          let mut entities = Vec::new();          for mut r in recipes_in {              let r2 = r.clone(); -            let mut inputs = r -                .inputs -                .into_iter() -                .map(|i| ItemIndex(register(&item_names, i))); -            let mut outputs = r -                .outputs -                .into_iter() -                .map(|o| ItemIndex(register(&item_names, o))); -            let tile = r.tile.map(|t| TileIndex(register(&tile_names, t))); +            let mut inputs = r.inputs.into_iter().map(|i| reg.register_item(i)); +            let mut outputs = r.outputs.into_iter().map(|o| reg.register_item(o)); +            let tile = r.tile.map(|t| reg.register_tile(t));              match r.action {                  Action::Never => {}                  Action::Passive => recipes.push(Recipe::Passive { @@ -228,8 +221,8 @@ impl Gamedata {          for d in demands_in {              demands.push(Demand { -                from: ItemIndex(register(&item_names, d.from)), -                to: d.to.map(|to| ItemIndex(register(&item_names, to))), +                from: reg.register_item(d.from), +                to: d.to.map(|to| reg.register_item(to)),                  duration: d.duration,                  points: d.points,              }) @@ -253,18 +246,25 @@ impl Gamedata {                      .ok_or(anyhow!("tile {tile} is undefined"))?                      .clone();                  if let Some(ent) = map_in.tile_entities.get(&tile) { -                    entities.push(construct_entity(Some(pos), ent)?); +                    entities.push(construct_entity(Some(pos), ent, ®)?);                  }                  let itemname = map_in.items.get(&tile).cloned(); -                let tile = TileIndex(register(&tile_names, tilename)); -                let item = itemname.map(|i| ItemIndex(register(&item_names, i))); +                let tile = reg.register_tile(tilename); +                let item = itemname.map(|i| reg.register_item(i));                  initial_map.insert(pos, (tile, item));              }          } -        let item_names = item_names.into_inner().unwrap(); -        let tile_names = tile_names.into_inner().unwrap(); +        entities.extend( +            map_in +                .entities +                .iter() +                .map(|decl| construct_entity(None, decl, ®)) +                .try_collect::<Vec<_>>()?, +        ); +        let item_names = reg.items.into_inner().unwrap(); +        let tile_names = reg.tiles.into_inner().unwrap();          let tile_collide = tile_names              .iter()              .map(|i| !map_in.walkable.contains(i)) @@ -274,14 +274,6 @@ impl Gamedata {              .map(|i| !map_in.collider.contains(i) && !map_in.walkable.contains(i))              .collect(); -        entities.extend( -            map_in -                .entities -                .iter() -                .map(|decl| construct_entity(None, decl)) -                .try_collect::<Vec<_>>()?, -        ); -          Ok(Gamedata {              spec,              demands, @@ -299,14 +291,28 @@ impl Gamedata {      }  } -fn register(db: &RwLock<Vec<String>>, name: String) -> usize { -    let mut db = db.write().unwrap(); -    if let Some(index) = db.iter().position(|e| e == &name) { -        index -    } else { -        let index = db.len(); -        db.push(name); -        index +#[derive(Default)] +pub struct ItemTileRegistry { +    tiles: RwLock<Vec<String>>, +    items: RwLock<Vec<String>>, +} + +impl ItemTileRegistry { +    pub fn register_tile(&self, name: String) -> TileIndex { +        TileIndex(Self::register(&self.tiles, name)) +    } +    pub fn register_item(&self, name: String) -> ItemIndex { +        ItemIndex(Self::register(&self.items, name)) +    } +    fn register(db: &RwLock<Vec<String>>, name: String) -> usize { +        let mut db = db.write().unwrap(); +        if let Some(index) = db.iter().position(|e| e == &name) { +            index +        } else { +            let index = db.len(); +            db.push(name); +            index +        }      }  } diff --git a/server/src/entity/conveyor.rs b/server/src/entity/conveyor.rs index 4d11ffe1..2d56c144 100644 --- a/server/src/entity/conveyor.rs +++ b/server/src/entity/conveyor.rs @@ -21,13 +21,15 @@ use crate::{      game::{interact_effect, Tile},  };  use anyhow::{anyhow, Result}; -use hurrycurry_protocol::{glam::IVec2, ItemLocation, PacketC}; +use hurrycurry_protocol::{glam::IVec2, ItemIndex, ItemLocation, PacketC};  use std::collections::{HashMap, VecDeque}; -#[derive(Debug, Default, Clone)] +#[derive(Debug, Clone)]  pub struct Conveyor {      pub(super) from: IVec2,      pub(super) to: IVec2, +    pub(super) filter_tile: Option<IVec2>, +    pub(super) filter_item: Option<ItemIndex>,      pub(super) cooldown: f32,      pub(super) max_cooldown: f32,  } @@ -41,17 +43,36 @@ impl EntityT for Conveyor {          tiles: &mut HashMap<IVec2, Tile>,          dt: f32,      ) -> Result<()> { -        let [from, to] = tiles -            .get_many_mut([&self.from, &self.to]) -            .ok_or(anyhow!("conveyor does ends in itself"))?; +        let from = tiles +            .get(&self.from) +            .ok_or(anyhow!("conveyor from missing"))?; + +        if let Some(from_item) = from.item.as_ref() { +            let filter = if let Some(t) = &self.filter_tile { +                let filter_tile = tiles.get(t).ok_or(anyhow!("conveyor filter missing"))?; +                filter_tile.item.as_ref().map(|e| e.kind) +            } else if let Some(i) = &self.filter_item { +                Some(*i) +            } else { +                None +            }; + +            if let Some(filter) = filter { +                if from_item.kind != filter { +                    return Ok(()); +                } +            } -        if from.item.is_some() {              self.cooldown += dt;              if self.cooldown < self.max_cooldown {                  return Ok(());              }              self.cooldown = 0.; +            let [from, to] = tiles +                .get_many_mut([&self.from, &self.to]) +                .ok_or(anyhow!("conveyor does ends in itself"))?; +              interact_effect(                  data,                  true, diff --git a/server/src/entity/mod.rs b/server/src/entity/mod.rs index 925ed5f4..a1f690a3 100644 --- a/server/src/entity/mod.rs +++ b/server/src/entity/mod.rs @@ -16,10 +16,15 @@  */  pub mod conveyor; -use crate::{data::Gamedata, game::Tile}; +pub mod portal; +use crate::{ +    data::{Gamedata, ItemTileRegistry}, +    game::Tile, +};  use anyhow::{anyhow, Result};  use conveyor::Conveyor;  use hurrycurry_protocol::{glam::IVec2, PacketC}; +use portal::Portal;  use serde::{Deserialize, Serialize};  use std::collections::{HashMap, VecDeque}; @@ -34,43 +39,54 @@ pub trait EntityT: Clone {      ) -> Result<()>;  } -#[derive(Debug, Clone)] -pub enum Entity { -    Conveyor(Conveyor), -} -impl EntityT for Entity { -    fn tick( -        &mut self, -        data: &Gamedata, -        points: &mut i64, -        packet_out: &mut VecDeque<PacketC>, -        tiles: &mut HashMap<IVec2, Tile>, -        dt: f32, -    ) -> Result<()> { -        match self { -            Entity::Conveyor(x) => x.tick(data, points, packet_out, tiles, dt), +macro_rules! entities { +    ($($e:ident),*) => { +        #[derive(Debug, Clone)] +        pub enum Entity { $($e($e)),* } +        impl EntityT for Entity { +            fn tick(&mut self, data: &Gamedata, points: &mut i64, packet_out: &mut VecDeque<PacketC>, tiles: &mut HashMap<IVec2, Tile>, dt: f32) -> Result<()> { +                match self { $(Entity::$e(x) => x.tick(data, points, packet_out, tiles, dt)),*, } +            }          } -    } +    };  } +entities!(Conveyor, Portal); +  #[derive(Debug, Clone, Deserialize, Serialize)]  #[serde(rename_all = "snake_case")]  pub enum EntityDecl {      Conveyor {          from: Option<IVec2>,          to: Option<IVec2>, +        filter_dir: Option<IVec2>, +        filter: Option<String>,          dir: Option<IVec2>,          speed: Option<f32>,      }, +    Portal { +        from: Option<IVec2>, +        to: IVec2, +    },  } -pub fn construct_entity(pos: Option<IVec2>, decl: &EntityDecl) -> Result<Entity> { +pub fn construct_entity( +    pos: Option<IVec2>, +    decl: &EntityDecl, +    reg: &ItemTileRegistry, +) -> Result<Entity> {      Ok(match decl.to_owned() { +        EntityDecl::Portal { from, to } => Entity::Portal(Portal { +            from: from.or(pos).ok_or(anyhow!("no portla start"))?, +            to, +        }),          EntityDecl::Conveyor {              from,              to,              speed,              dir, +            filter, +            filter_dir,          } => {              let from = from.or(pos).ok_or(anyhow!("conveyor has no start"))?;              let to = to @@ -80,7 +96,9 @@ pub fn construct_entity(pos: Option<IVec2>, decl: &EntityDecl) -> Result<Entity>                  from,                  to,                  max_cooldown: 1. / speed.unwrap_or(2.), -                ..Default::default() +                filter_tile: filter_dir.map(|o| to + o), +                filter_item: filter.map(|name| reg.register_item(name)), +                cooldown: 0.,              })          }      }) diff --git a/server/src/entity/portal.rs b/server/src/entity/portal.rs new file mode 100644 index 00000000..e0195b9f --- /dev/null +++ b/server/src/entity/portal.rs @@ -0,0 +1,46 @@ +use super::EntityT; +use crate::{ +    data::Gamedata, +    game::{interact_effect, Tile}, +}; +use anyhow::{anyhow, Result}; +use hurrycurry_protocol::{glam::IVec2, ItemLocation, PacketC}; +use std::collections::{HashMap, VecDeque}; + +#[derive(Debug, Default, Clone)] +pub struct Portal { +    pub(super) from: IVec2, +    pub(super) to: IVec2, +} + +impl EntityT for Portal { +    fn tick( +        &mut self, +        data: &Gamedata, +        points: &mut i64, +        packet_out: &mut VecDeque<PacketC>, +        tiles: &mut HashMap<IVec2, Tile>, +        _dt: f32, +    ) -> Result<()> { +        let [from, to] = tiles +            .get_many_mut([&self.from, &self.to]) +            .ok_or(anyhow!("conveyor does ends in itself"))?; + +        if from.item.is_some() { +            interact_effect( +                data, +                true, +                &mut to.item, +                ItemLocation::Tile(self.to), +                &mut from.item, +                ItemLocation::Tile(self.from), +                Some(to.kind), +                packet_out, +                points, +                true, +            ); +        } + +        Ok(()) +    } +} | 
