diff options
Diffstat (limited to 'server')
| -rw-r--r-- | server/src/data.rs | 127 | ||||
| -rw-r--r-- | server/src/game.rs | 224 | ||||
| -rw-r--r-- | server/src/interaction.rs | 302 | ||||
| -rw-r--r-- | server/src/lib.rs | 2 | ||||
| -rw-r--r-- | server/src/main.rs | 2 | ||||
| -rw-r--r-- | server/src/protocol.rs | 24 | ||||
| -rw-r--r-- | server/src/recipes.rs | 104 | 
7 files changed, 427 insertions, 358 deletions
| diff --git a/server/src/data.rs b/server/src/data.rs new file mode 100644 index 00000000..6affccb5 --- /dev/null +++ b/server/src/data.rs @@ -0,0 +1,127 @@ +use crate::{interaction::Recipe, protocol::TileIndex}; +use glam::{IVec2, Vec2}; +use serde::{Deserialize, Serialize}; +use std::{collections::HashMap, sync::RwLock}; + +#[derive(Debug, Deserialize, Serialize, Clone, Copy, Default)] +#[serde(rename_all = "snake_case")] +pub enum Action { +    #[default] +    Never, +    Passive(f32), +    Active(f32), +    Instant, +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct RecipeDecl { +    #[serde(default)] +    pub tile: Option<String>, +    #[serde(default)] +    pub inputs: Vec<String>, +    #[serde(default)] +    pub outputs: Vec<String>, +    #[serde(default)] +    pub action: Action, +} + +#[derive(Debug, Clone, Deserialize)] +pub struct InitialMap { +    map: Vec<String>, +    tiles: HashMap<String, String>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Gamedata { +    pub recipes: Vec<Recipe>, +    pub item_names: Vec<String>, +    pub tile_names: Vec<String>, +    #[serde(skip)] +    pub initial_map: HashMap<IVec2, TileIndex>, +    pub spawn: Vec2, +} + +pub fn build_gamedata(recipes_in: Vec<RecipeDecl>, map_in: InitialMap) -> Gamedata { +    let item_names = RwLock::new(Vec::new()); +    let tile_names = RwLock::new(Vec::new()); +    let mut recipes = Vec::new(); + +    for r in recipes_in { +        let r2 = r.clone(); +        let mut inputs = r.inputs.into_iter().map(|i| register(&item_names, i)); +        let mut outputs = r.outputs.into_iter().map(|o| register(&item_names, o)); +        let tile = r.tile.map(|t| register(&tile_names, t)); +        match r.action { +            Action::Never => {} +            Action::Passive(duration) => recipes.push(Recipe::Passive { +                duration, +                tile, +                input: inputs.next().expect("passive recipe without input"), +                output: outputs.next(), +            }), +            Action::Active(duration) => recipes.push(Recipe::Active { +                duration, +                tile, +                input: inputs.next().expect("active recipe without input"), +                outputs: [outputs.next(), outputs.next()], +            }), +            Action::Instant => { +                recipes.push(Recipe::Instant { +                    tile, +                    inputs: [inputs.next(), inputs.next()], +                    outputs: [outputs.next(), outputs.next()], +                }); +            } +        } +        assert_eq!(inputs.next(), None, "{r2:?}"); +        assert_eq!(outputs.next(), None, "{r2:?}"); +    } + +    let mut spawn = Vec2::new(0., 0.); +    let mut initial_map = HashMap::new(); +    for (y, line) in map_in.map.iter().enumerate() { +        for (x, tile) in line.trim().char_indices() { +            let pos = IVec2::new(x as i32, y as i32); +            let mut tilename = map_in.tiles[&tile.to_string()].clone(); +            if tilename == "spawn" { +                spawn = pos.as_vec2(); +                tilename = "floor".to_owned(); +            } +            let tile = register(&tile_names, tilename); +            initial_map.insert(pos, tile); +        } +    } + +    Gamedata { +        recipes, +        initial_map, +        item_names: item_names.into_inner().unwrap(), +        tile_names: tile_names.into_inner().unwrap(), +        spawn, +    } +} + +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 +    } +} + +impl Gamedata { +    pub fn get_tile(&self, name: &str) -> Option<TileIndex> { +        self.tile_names.iter().position(|t| t == name) +    } +} +impl Action { +    pub fn duration(&self) -> f32 { +        match self { +            Action::Instant | Action::Never => 0., +            Action::Passive(x) | Action::Active(x) => *x, +        } +    } +} diff --git a/server/src/game.rs b/server/src/game.rs index 5cb155f1..d481dc4f 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -1,10 +1,10 @@  use crate::{ -    interaction::{interact, tick_tile, Out}, -    protocol::{ItemID, ItemIndex, PacketC, PacketS, PlayerID, RecipeIndex, TileIndex}, -    recipes::Gamedata, +    data::Gamedata, +    interaction::interact, +    protocol::{ItemIndex, PacketC, PacketS, PlayerID, RecipeIndex, TileIndex},  };  use anyhow::{anyhow, bail, Result}; -use glam::IVec2; +use glam::{IVec2, Vec2};  use log::info;  use std::{      collections::{HashMap, VecDeque}, @@ -12,29 +12,32 @@ use std::{      sync::Arc,  }; -pub struct ActiveRecipe { +pub struct Involvement {      pub recipe: RecipeIndex,      pub progress: f32,      pub working: usize,  } +pub struct Item { +    pub kind: ItemIndex, +    pub active: Option<Involvement>, +} +  pub struct Tile { -    kind: TileIndex, -    items: Vec<ItemID>, -    active: Option<ActiveRecipe>, +    pub kind: TileIndex, +    pub item: Option<Item>,  } -struct Player { -    name: String, -    interacting: bool, -    hand: Option<ItemID>, +pub struct Player { +    pub name: String, +    pub position: Vec2, +    pub interacting: bool, +    pub item: Option<Item>,  }  pub struct Game {      data: Arc<Gamedata>, -    item_id_counter: ItemID,      tiles: HashMap<IVec2, Tile>, -    items: HashMap<ItemID, ItemIndex>,      players: HashMap<PlayerID, Player>,      packet_out: VecDeque<PacketC>,  } @@ -43,8 +46,6 @@ impl Game {      pub fn new(gamedata: Arc<Gamedata>) -> Self {          let mut g = Self {              data: gamedata.clone(), -            item_id_counter: 0, -            items: Default::default(),              packet_out: Default::default(),              players: Default::default(),              tiles: Default::default(), @@ -69,19 +70,18 @@ impl Game {              out.push(PacketC::AddPlayer {                  id,                  name: player.name.clone(), -                hand: player.hand.map(|i| (i, self.items[&i].clone())), +                hand: player.item.as_ref().map(|i| i.kind),              })          } -        for (&pos, tdata) in &self.tiles { +        for (&tile, tdata) in &self.tiles {              out.push(PacketC::UpdateMap { -                pos, +                pos: tile,                  tile: tdata.kind.clone(),              }); -            for &id in &tdata.items { +            if let Some(item) = &tdata.item {                  out.push(PacketC::ProduceItem { -                    id, -                    pos, -                    kind: self.items[&id].clone(), +                    item: item.kind, +                    tile,                  })              }          } @@ -94,7 +94,8 @@ impl Game {                  self.players.insert(                      player,                      Player { -                        hand: None, +                        item: None, +                        position: self.data.spawn,                          interacting: false,                          name: name.clone(),                      }, @@ -110,8 +111,8 @@ impl Game {                      .players                      .remove(&player)                      .ok_or(anyhow!("player does not exist"))?; -                if let Some(id) = p.hand { -                    self.items.remove(&id).expect("hand item lost"); +                if let Some(id) = p.item { +                    // TODO place on ground                  }                  self.packet_out                      .push_back(PacketC::RemovePlayer { id: player }) @@ -137,108 +138,105 @@ impl Game {                      bail!("already (not) interacting")                  } -                let items = tile.items.iter().map(|e| self.items[e]).collect::<Vec<_>>(); -                let tilekind = tile.kind; -                let hand = player.hand.map(|e| self.items[&e]); +                let tile_had_item = tile.item.is_some(); -                interact( -                    &self.data, -                    edge, -                    tilekind, -                    &mut tile.active, -                    items, -                    hand, -                    |out| match out { -                        Out::Take(index) => { -                            info!("take"); -                            let item = tile.items.remove(index); -                            player.hand = Some(item); -                            self.packet_out -                                .push_back(PacketC::TakeItem { item, player: pid }) -                        } -                        Out::Put => { -                            info!("put"); -                            let hand = player.hand.take().unwrap(); -                            tile.items.push(hand); -                            self.packet_out -                                .push_back(PacketC::PutItem { item: hand, pos }) -                        } -                        Out::Produce(kind) => { -                            info!("produce"); -                            let id = self.item_id_counter; -                            self.item_id_counter += 1; -                            self.items.insert(id, kind); -                            tile.items.push(id); -                            self.packet_out -                                .push_back(PacketC::ProduceItem { id, pos, kind }); -                        } -                        Out::Consume(index) => { -                            info!("consume"); -                            let id = tile.items.remove(index); -                            info!("left {:?}", tile.items); -                            self.packet_out.push_back(PacketC::ConsumeItem { id, pos }); -                        } -                        Out::SetActive(progress) => { -                            self.packet_out.push_back(PacketC::SetActive { -                                tile: pos, -                                progress, -                            }); -                        } -                    }, -                ); +                interact(&self.data, edge, tile, player); + +                // interact( +                //     &self.data, +                //     edge, +                //     tilekind, +                //     &mut tile.active, +                //     item, +                //     hand, +                //     |out| match out { +                //         Out::Take(index) => { +                //             info!("take"); +                //             let item = tile.items.remove(index); +                //             player.hand = Some(item); +                //             self.packet_out +                //                 .push_back(PacketC::TakeItem { item, player: pid }) +                //         } +                //         Out::Put => { +                //             info!("put"); +                //             let hand = player.hand.take().unwrap(); +                //             tile.items.push(hand); +                //             self.packet_out +                //                 .push_back(PacketC::PutItem { item: hand, pos }) +                //         } +                //         Out::Produce(kind) => { +                //             info!("produce"); +                //             let id = self.item_id_counter; +                //             self.item_id_counter += 1; +                //             self.items.insert(id, kind); +                //             tile.items.push(id); +                //             self.packet_out +                //                 .push_back(PacketC::ProduceItem { id, pos, kind }); +                //         } +                //         Out::Consume(index) => { +                //             info!("consume"); +                //             let id = tile.items.remove(index); +                //             info!("left {:?}", tile.items); +                //             self.packet_out.push_back(PacketC::ConsumeItem { id, pos }); +                //         } +                //         Out::SetActive(progress) => { +                //             self.packet_out.push_back(PacketC::SetActive { +                //                 tile: pos, +                //                 progress, +                //             }); +                //         } +                //     }, +                // );                  player.interacting = edge;              } +            PacketS::Collide { player, force } => {}          }          Ok(())      }      pub fn tick(&mut self, dt: f32) {          for (&pos, tile) in &mut self.tiles { -            let items = tile.items.iter().map(|e| self.items[e]).collect::<Vec<_>>(); -            tick_tile( -                dt, -                &self.data, -                tile.kind, -                &mut tile.active, -                items, -                |out| match out { -                    Out::Take(_) | Out::Put => { -                        unreachable!() -                    } -                    Out::Produce(kind) => { -                        info!("produce"); -                        let id = self.item_id_counter; -                        self.item_id_counter += 1; -                        self.items.insert(id, kind); -                        tile.items.push(id); -                        self.packet_out -                            .push_back(PacketC::ProduceItem { id, pos, kind }); -                    } -                    Out::Consume(index) => { -                        info!("consume"); -                        let id = tile.items.remove(index); -                        info!("left {:?}", tile.items); -                        self.packet_out.push_back(PacketC::ConsumeItem { id, pos }); -                    } -                    Out::SetActive(progress) => { -                        self.packet_out.push_back(PacketC::SetActive { -                            tile: pos, -                            progress, -                        }); -                    } -                }, -            ); +            // let items = tile.items.iter().map(|e| self.items[e]).collect::<Vec<_>>(); +            // tick_tile( +            //     dt, +            //     &self.data, +            //     tile.kind, +            //     &mut tile.active, +            //     items, +            //     |out| match out { +            //         Out::Take(_) | Out::Put => { +            //             unreachable!() +            //         } +            //         Out::Produce(kind) => { +            //             info!("produce"); +            //             let id = self.item_id_counter; +            //             self.item_id_counter += 1; +            //             self.items.insert(id, kind); +            //             tile.items.push(id); +            //             self.packet_out +            //                 .push_back(PacketC::ProduceItem { id, pos, kind }); +            //         } +            //         Out::Consume(index) => { +            //             info!("consume"); +            //             let id = tile.items.remove(index); +            //             info!("left {:?}", tile.items); +            //             self.packet_out.push_back(PacketC::ConsumeItem { id, pos }); +            //         } +            //         Out::SetActive(progress) => { +            //             self.packet_out.push_back(PacketC::SetActive { +            //                 tile: pos, +            //                 progress, +            //             }); +            //         } +            //     }, +            // );          }      }  }  impl From<TileIndex> for Tile {      fn from(kind: TileIndex) -> Self { -        Self { -            kind, -            items: vec![], -            active: None, -        } +        Self { kind, item: None }      }  } diff --git a/server/src/interaction.rs b/server/src/interaction.rs index 11409b10..aa216410 100644 --- a/server/src/interaction.rs +++ b/server/src/interaction.rs @@ -1,150 +1,196 @@  use crate::{ -    game::ActiveRecipe, +    data::{Action, Gamedata}, +    game::{Involvement, Item, Player, Tile},      protocol::{ItemIndex, TileIndex}, -    recipes::{Action, Gamedata},  };  use log::{debug, info}; +use serde::{Deserialize, Serialize};  use std::collections::BTreeSet; -use Out::*; -pub enum Out { -    Take(usize), -    Put, -    Produce(ItemIndex), -    Consume(usize), -    SetActive(Option<f32>), +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum Recipe { +    Passive { +        duration: f32, +        tile: Option<TileIndex>, +        input: ItemIndex, +        output: Option<ItemIndex>, +    }, +    Active { +        duration: f32, +        tile: Option<TileIndex>, +        input: ItemIndex, +        outputs: [Option<ItemIndex>; 2], +    }, +    Instant { +        tile: Option<TileIndex>, +        inputs: [Option<ItemIndex>; 2], +        outputs: [Option<ItemIndex>; 2], +    },  } -pub fn interact( -    data: &Gamedata, -    edge: bool, -    tile: TileIndex, -    active: &mut Option<ActiveRecipe>, -    mut items: Vec<ItemIndex>, -    mut hand: Option<ItemIndex>, -    mut out: impl FnMut(Out), -) { -    let mut allowed = BTreeSet::new(); -    for r in &data.recipes { -        if r.tile == tile { -            allowed.extend(r.inputs.clone()) -        } -    } -    if !edge { -        debug!("falling edge"); -        if let Some(ac) = active { -            if matches!(data.recipes[ac.recipe].action, Action::Active(_)) { -                debug!("workers--"); -                ac.working -= 1; -            } -        } -        return; -    } - -    if hand.is_none() { -        debug!("rising edge"); -        if let Some(active) = active { -            if matches!(data.recipes[active.recipe].action, Action::Active(_)) { -                debug!("workers++"); -                active.working += 1; -            } +impl Recipe { +    pub fn tile(&self) -> Option<TileIndex> { +        match self { +            Recipe::Passive { tile, .. } => *tile, +            Recipe::Active { tile, .. } => *tile, +            Recipe::Instant { tile, .. } => *tile,          }      } +} -    if active.is_none() && !items.is_empty() && hand.is_none() { -        out(Take(items.len() - 1)); +pub fn interact(data: &Gamedata, edge: bool, tile: &mut Tile, player: &mut Player) { +    if !edge {          return;      } -    if active.is_none() { -        if let Some(hi) = hand { -            if allowed.contains(&hi) { -                out(Put); -                items.push(hi); -                hand = None; -            } -        } -    } - -    if hand.is_none() && active.is_none() { -        'rloop: for (ri, r) in data.recipes.iter().enumerate() { -            if tile != r.tile { -                continue; -            } -            let mut inputs = r.inputs.clone(); -            for i in &items { -                debug!("take {i:?} {inputs:?}"); -                let Some(pos) = inputs.iter().position(|e| e == i) else { -                    continue 'rloop; -                }; -                inputs.remove(pos); -            } -            debug!("end {inputs:?}"); -            if !inputs.is_empty() { +    for recipe in &data.recipes { +        if let Some(tile_constraint) = recipe.tile() { +            if tile.kind != tile_constraint {                  continue;              } - -            match r.action { -                Action::Passive(_) => { -                    info!("use passive recipe {ri}"); -                    *active = Some(ActiveRecipe { -                        recipe: ri, -                        progress: 0., -                        working: 1, -                    }); -                    break 'rloop; -                } -                Action::Active(_) => { -                    info!("use active recipe {ri}"); -                    *active = Some(ActiveRecipe { -                        recipe: ri, -                        progress: 0., -                        working: 1, -                    }); -                    break 'rloop; -                } -                Action::Instant => { -                    info!("use instant recipe {ri}"); -                    for _ in 0..items.len() { -                        out(Consume(0)) -                    } -                    for i in &r.outputs { -                        out(Produce(*i)); -                    } -                    if !r.outputs.is_empty() { -                        out(Take(r.outputs.len() - 1)); -                    } -                    items.clear(); -                    break 'rloop; +        } +        match recipe { +            Recipe::Passive { +                duration, +                input, +                output, +                .. +            } => todo!(), +            Recipe::Active { +                duration, +                input: inputs, +                outputs, +                .. +            } => todo!(), +            Recipe::Instant { +                inputs, outputs, .. +            } => { +                let on_tile = tile.item.as_ref().map(|i| i.kind); +                let in_hand = player.item.as_ref().map(|i| i.kind); +                let ok = (inputs[0] == on_tile && inputs[1] == in_hand) +                    || (inputs[1] == on_tile && inputs[0] == in_hand); +                if ok { +                    player.item = outputs[0].map(|kind| Item { kind, active: None }); +                    tile.item = outputs[1].map(|kind| Item { kind, active: None });                  } -                Action::Never => (),              }          }      }  } +// if !edge { +//     debug!("falling edge"); +//     if let Some(ac) = active { +//         if matches!(data.recipes[ac.recipe].action, Action::Active(_)) { +//             debug!("workers--"); +//             ac.working -= 1; +//         } +//     } +//     return; +// } -pub fn tick_tile( -    dt: f32, -    data: &Gamedata, -    _tile: TileIndex, -    active: &mut Option<ActiveRecipe>, -    items: Vec<ItemIndex>, -    mut out: impl FnMut(Out), -) { -    if let Some(a) = active { -        let r = &data.recipes[a.recipe]; -        a.progress += a.working as f32 * dt / r.action.duration(); -        if a.progress >= 1. { -            for _ in 0..items.len() { -                out(Consume(0)) -            } -            for i in &r.outputs { -                out(Produce(*i)); -            } -            out(SetActive(None)); -            active.take(); -        } else { -            out(SetActive(Some(a.progress))); -        } -    } -} +// if hand.is_none() { +//     debug!("rising edge"); +//     if let Some(active) = active { +//         if matches!(data.recipes[active.recipe].action, Action::Active(_)) { +//             debug!("workers++"); +//             active.working += 1; +//         } +//     } +// } + +// if active.is_none() && !items.is_empty() && hand.is_none() { +//     out(Take(items.len() - 1)); +//     return; +// } + +// if active.is_none() { +//     if let Some(hi) = hand { +//         if allowed.contains(&hi) { +//             out(Put); +//             items.push(hi); +//             hand = None; +//         } +//     } +// } + +// if hand.is_none() && active.is_none() { +//     'rloop: for (ri, r) in data.recipes.iter().enumerate() { +//         if tile != r.tile { +//             continue; +//         } +//         let mut inputs = r.inputs.clone(); +//         for i in &items { +//             debug!("take {i:?} {inputs:?}"); +//             let Some(pos) = inputs.iter().position(|e| e == i) else { +//                 continue 'rloop; +//             }; +//             inputs.remove(pos); +//         } +//         debug!("end {inputs:?}"); +//         if !inputs.is_empty() { +//             continue; +//         } + +//         match r.action { +//             Action::Passive(_) => { +//                 info!("use passive recipe {ri}"); +//                 *active = Some(Involvement { +//                     recipe: ri, +//                     progress: 0., +//                     working: 1, +//                 }); +//                 break 'rloop; +//             } +//             Action::Active(_) => { +//                 info!("use active recipe {ri}"); +//                 *active = Some(Involvement { +//                     recipe: ri, +//                     progress: 0., +//                     working: 1, +//                 }); +//                 break 'rloop; +//             } +//             Action::Instant => { +//                 info!("use instant recipe {ri}"); +//                 for _ in 0..items.len() { +//                     out(Consume(0)) +//                 } +//                 for i in &r.outputs { +//                     out(Produce(*i)); +//                 } +//                 if !r.outputs.is_empty() { +//                     out(Take(r.outputs.len() - 1)); +//                 } +//                 items.clear(); +//                 break 'rloop; +//             } +//             Action::Never => (), +//         } +//     } +// } + +// pub fn tick_tile( +//     dt: f32, +//     data: &Gamedata, +//     _tile: TileIndex, +//     active: &mut Option<Involvement>, +//     items: Vec<ItemIndex>, +//     mut out: impl FnMut(Out), +// ) { +//     if let Some(a) = active { +//         let r = &data.recipes[a.recipe]; +//         a.progress += a.working as f32 * dt / r.action.duration(); +//         if a.progress >= 1. { +//             for _ in 0..items.len() { +//                 out(Consume(0)) +//             } +//             for i in &r.outputs { +//                 out(Produce(*i)); +//             } +//             out(SetActive(None)); +//             active.take(); +//         } else { +//             out(SetActive(Some(a.progress))); +//         } +//     } +// } diff --git a/server/src/lib.rs b/server/src/lib.rs index 5bb09e41..b40bcdd8 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -1,4 +1,4 @@  pub mod game;  pub mod protocol; -pub mod recipes; +pub mod data;  pub mod interaction; diff --git a/server/src/main.rs b/server/src/main.rs index 5414e9fd..6cb65141 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -13,7 +13,7 @@ use tokio_tungstenite::tungstenite::Message;  use undercooked::{      game::Game,      protocol::{PacketC, PacketS}, -    recipes::build_gamedata, +    data::build_gamedata,  };  #[tokio::main] diff --git a/server/src/protocol.rs b/server/src/protocol.rs index 9e6717a3..4f04793f 100644 --- a/server/src/protocol.rs +++ b/server/src/protocol.rs @@ -1,9 +1,8 @@ -use crate::recipes::Gamedata; +use crate::data::Gamedata;  use glam::{IVec2, Vec2};  use serde::{Deserialize, Serialize};  pub type PlayerID = usize; -pub type ItemID = usize;  pub type ItemIndex = usize;  pub type TileIndex = usize;  pub type RecipeIndex = usize; @@ -15,6 +14,7 @@ pub enum PacketS {      Leave,      Position { pos: Vec2, rot: f32 },      Interact { pos: IVec2, edge: bool }, +    Collide { player: PlayerID, force: Vec2 },  }  #[derive(Debug, Clone, Serialize, Deserialize)] @@ -27,7 +27,7 @@ pub enum PacketC {      AddPlayer {          id: PlayerID,          name: String, -        hand: Option<(ItemID, ItemIndex)>, +        hand: Option<ItemIndex>,      },      RemovePlayer {          id: PlayerID, @@ -38,21 +38,19 @@ pub enum PacketC {          rot: f32,      },      TakeItem { -        item: ItemID, +        tile: IVec2,          player: PlayerID,      },      PutItem { -        item: ItemID, -        pos: IVec2, +        player: PlayerID, +        tile: IVec2,      },      ProduceItem { -        id: ItemID, -        pos: IVec2, -        kind: ItemIndex, +        tile: IVec2, +        item: ItemIndex,      },      ConsumeItem { -        id: ItemID, -        pos: IVec2, +        tile: IVec2,      },      SetActive {          tile: IVec2, @@ -62,4 +60,8 @@ pub enum PacketC {          pos: IVec2,          tile: TileIndex,      }, +    Collide { +        player: PlayerID, +        force: Vec2, +    },  } diff --git a/server/src/recipes.rs b/server/src/recipes.rs deleted file mode 100644 index 2dcb215c..00000000 --- a/server/src/recipes.rs +++ /dev/null @@ -1,104 +0,0 @@ -use crate::protocol::{ItemIndex, TileIndex}; -use glam::IVec2; -use log::debug; -use serde::{Deserialize, Serialize}; -use std::collections::HashMap; - -#[derive(Debug, Deserialize, Serialize, Clone, Copy, Default)] -#[serde(rename_all = "snake_case")] -pub enum Action { -    #[default] -    Never, -    Passive(f32), -    Active(f32), -    Instant, -} - -#[derive(Debug, Clone, Deserialize, Serialize)] -pub struct Recipe<T = TileIndex, I = ItemIndex> { -    pub tile: T, -    #[serde(default)] -    pub inputs: Vec<I>, -    #[serde(default)] -    pub outputs: Vec<I>, -    #[serde(default)] -    pub action: Action, -} - -#[derive(Debug, Clone, Deserialize)] -pub struct InitialMap { -    map: Vec<String>, -    tiles: HashMap<String, String>, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Gamedata { -    pub recipes: Vec<Recipe>, -    pub item_names: Vec<String>, -    pub tile_names: Vec<String>, -    #[serde(skip)] -    pub initial_map: HashMap<IVec2, TileIndex>, -} -pub fn build_gamedata(recipes_in: Vec<Recipe<String, String>>, map_in: InitialMap) -> Gamedata { -    let mut item_names = Vec::new(); -    let mut tile_names = Vec::new(); -    let mut recipes = Vec::new(); - -    for r in recipes_in { -        recipes.push(Recipe { -            action: r.action, -            tile: register(&mut tile_names, r.tile.clone()), -            inputs: r -                .inputs -                .clone() -                .into_iter() -                .map(|e| register(&mut item_names, e)) -                .collect(), -            outputs: r -                .outputs -                .clone() -                .into_iter() -                .map(|e| register(&mut item_names, e)) -                .collect(), -        }) -    } - -    let mut initial_map = HashMap::new(); -    for (y, line) in map_in.map.iter().enumerate() { -        for (x, tile) in line.trim().char_indices() { -            debug!("{tile:?}"); -            let tile = register(&mut tile_names, map_in.tiles[&tile.to_string()].clone()); -            initial_map.insert(IVec2::new(x as i32, y as i32), tile); -        } -    } - -    Gamedata { -        recipes, -        initial_map, -        item_names, -        tile_names, -    } -} -fn register(db: &mut Vec<String>, name: String) -> usize { -    if let Some(index) = db.iter().position(|e| e == &name) { -        index -    } else { -        let index = db.len(); -        db.push(name); -        index -    } -} - -impl Gamedata { -    pub fn get_tile(&self, name: &str) -> Option<TileIndex> { -        self.tile_names.iter().position(|t| t == name) -    } -} -impl Action { -    pub fn duration(&self) -> f32 { -        match self { -            Action::Instant | Action::Never => 0., -            Action::Passive(x) | Action::Active(x) => *x, -        } -    } -} | 
