diff options
Diffstat (limited to 'server')
| -rw-r--r-- | server/src/customer/mod.rs | 58 | ||||
| -rw-r--r-- | server/src/data.rs | 65 | ||||
| -rw-r--r-- | server/src/game.rs | 4 | ||||
| -rw-r--r-- | server/src/interaction.rs | 16 | ||||
| -rw-r--r-- | server/src/main.rs | 8 | ||||
| -rw-r--r-- | server/src/protocol.rs | 21 | 
6 files changed, 107 insertions, 65 deletions
| diff --git a/server/src/customer/mod.rs b/server/src/customer/mod.rs index ecd99250..4c557d41 100644 --- a/server/src/customer/mod.rs +++ b/server/src/customer/mod.rs @@ -47,7 +47,7 @@ struct Customer {  pub async fn customer(game: Arc<RwLock<Game>>, mut grx: broadcast::Receiver<PacketC>) {      let mut state = CustomerManager { -        customer_id_counter: 0, +        customer_id_counter: PlayerID(0),          walkable: Default::default(),          chairs: Default::default(),          items: Default::default(), @@ -56,14 +56,14 @@ pub async fn customer(game: Arc<RwLock<Game>>, mut grx: broadcast::Receiver<Pack              data: Gamedata::default(),          },      }; -    let initial = game.write().await.prime_client(-1); +    let initial = game.write().await.prime_client(PlayerID(-1));      for p in initial {          match p {              PacketC::Init { data, .. } => {                  state.demand.data = data;              }              PacketC::UpdateMap { pos, tile, .. } => { -                let tilename = &state.demand.data.tile_names[tile]; +                let tilename = state.demand.data.tile_name(tile);                  if tilename == "floor" || tilename == "door" || tilename == "chair" {                      state.walkable.insert(pos);                  } @@ -119,14 +119,14 @@ impl DemandState {      pub fn generate_demand(&self) -> DemandIndex {          // TODO insert sofa magic formula -        random::<usize>() % self.data.demands.len() +        DemandIndex(random::<usize>() % self.data.demands.len())      }  }  impl CustomerManager {      pub fn tick(&mut self, packets_out: &mut Vec<(PlayerID, PacketS)>, dt: f32) {          if self.customers.len() < self.demand.target_customer_count() { -            self.customer_id_counter -= 1; +            self.customer_id_counter.0 -= 1;              let id = self.customer_id_counter;              packets_out.push((                  id, @@ -164,7 +164,7 @@ impl CustomerManager {                          packets_out.push((                              id,                              PacketS::Communicate { -                                message: Some(Message::Item(self.demand.data.demands[demand].from)), +                                message: Some(Message::Item(self.demand.data.demand(demand).from)),                              },                          ));                          p.state = CustomerState::Waiting { @@ -174,41 +174,39 @@ impl CustomerManager {                      }                  }                  CustomerState::Waiting { chair, demand } => { +                    let demand = &self.demand.data.demand(*demand);                      let demand_pos = [IVec2::NEG_X, IVec2::NEG_Y, IVec2::X, IVec2::Y]                          .into_iter()                          .find_map(|off| {                              let pos = *chair + off; -                            if self.items.get(&pos) == Some(demand) { +                            if self.items.get(&pos) == Some(&demand.from) {                                  Some(pos)                              } else {                                  None                              }                          });                      if let Some(pos) = demand_pos { -                        let demand = &self.demand.data.demands[*demand]; -                        if self.items.get(&pos) == Some(&demand.from) { -                            packets_out.push((id, PacketS::Communicate { message: None })); -                            for edge in [true, false] { -                                packets_out.push((id, PacketS::Interact { pos, edge })) -                            } -                            packets_out.push(( -                                id, -                                PacketS::ReplaceHand { -                                    item: Some(demand.to), -                                }, -                            )); -                            for edge in [true, false] { -                                packets_out.push((id, PacketS::Interact { pos, edge })) -                            } -                            let path = find_path( -                                &self.walkable, -                                p.movement.position.as_ivec2(), -                                self.demand.data.customer_spawn.as_ivec2(), -                            ) -                            .expect("no path to exit"); -                            *self.chairs.get_mut(&chair).unwrap() = true; -                            p.state = CustomerState::Exiting { path } +                        packets_out.push((id, PacketS::Communicate { message: None })); +                        for edge in [true, false] { +                            packets_out.push((id, PacketS::Interact { pos, edge })) +                        } +                        packets_out.push(( +                            id, +                            PacketS::ReplaceHand { +                                item: Some(demand.to), +                            }, +                        )); +                        for edge in [true, false] { +                            packets_out.push((id, PacketS::Interact { pos, edge }))                          } +                        let path = find_path( +                            &self.walkable, +                            p.movement.position.as_ivec2(), +                            self.demand.data.customer_spawn.as_ivec2(), +                        ) +                        .expect("no path to exit"); +                        *self.chairs.get_mut(&chair).unwrap() = true; +                        p.state = CustomerState::Exiting { path }                      }                      debug!("waiting")                  } diff --git a/server/src/data.rs b/server/src/data.rs index e467fefa..51347c7c 100644 --- a/server/src/data.rs +++ b/server/src/data.rs @@ -1,4 +1,7 @@ -use crate::{interaction::Recipe, protocol::TileIndex}; +use crate::{ +    interaction::Recipe, +    protocol::{DemandIndex, ItemIndex, RecipeIndex, TileIndex}, +};  use glam::{IVec2, Vec2};  use serde::{Deserialize, Serialize};  use std::{collections::HashMap, sync::RwLock}; @@ -39,16 +42,16 @@ pub struct DemandDecl {  #[derive(Debug, Clone, Serialize, Deserialize)]  pub struct Demand { -    pub from: usize, -    pub to: usize, +    pub from: ItemIndex, +    pub to: ItemIndex,  }  #[derive(Debug, Clone, Serialize, Deserialize, Default)]  pub struct Gamedata { -    pub recipes: Vec<Recipe>, +    recipes: Vec<Recipe>,      pub demands: Vec<Demand>, -    pub item_names: Vec<String>, -    pub tile_names: Vec<String>, +    item_names: Vec<String>, +    tile_names: Vec<String>,      #[serde(skip)]      pub initial_map: HashMap<IVec2, TileIndex>,      pub chef_spawn: Vec2, @@ -67,9 +70,15 @@ pub fn build_gamedata(      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)); +        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)));          match r.action {              Action::Never => {}              Action::Passive(duration) => recipes.push(Recipe::Passive { @@ -98,8 +107,8 @@ pub fn build_gamedata(      for d in demands_in {          demands.push(Demand { -            from: register(&item_names, d.from), -            to: register(&item_names, d.to), +            from: ItemIndex(register(&item_names, d.from)), +            to: ItemIndex(register(&item_names, d.to)),          })      } @@ -118,7 +127,7 @@ pub fn build_gamedata(                  customer_spawn = pos.as_vec2();                  tilename = "floor".to_owned();              } -            let tile = register(&tile_names, tilename); +            let tile = TileIndex(register(&tile_names, tilename));              initial_map.insert(pos, tile);          }      } @@ -146,11 +155,35 @@ fn register(db: &RwLock<Vec<String>>, name: String) -> usize {  }  impl Gamedata { -    pub fn get_tile(&self, name: &str) -> Option<TileIndex> { -        self.tile_names.iter().position(|t| t == name) +    pub fn tile_name(&self, index: TileIndex) -> &String { +        &self.tile_names[index.0]      } -    pub fn get_item(&self, name: &str) -> Option<TileIndex> { -        self.item_names.iter().position(|t| t == name) +    pub fn item_name(&self, index: ItemIndex) -> &String { +        &self.item_names[index.0] +    } +    pub fn recipe(&self, index: RecipeIndex) -> &Recipe { +        &self.recipes[index.0] +    } +    pub fn demand(&self, index: DemandIndex) -> &Demand { +        &self.demands[index.0] +    } +    pub fn get_tile_by_name(&self, name: &str) -> Option<TileIndex> { +        self.tile_names +            .iter() +            .position(|t| t == name) +            .map(TileIndex) +    } +    pub fn get_item_by_name(&self, name: &str) -> Option<ItemIndex> { +        self.item_names +            .iter() +            .position(|t| t == name) +            .map(ItemIndex) +    } +    pub fn recipes(&self) -> impl Iterator<Item = (RecipeIndex, &Recipe)> { +        self.recipes +            .iter() +            .enumerate() +            .map(|(i, e)| (RecipeIndex(i), e))      }  }  impl Action { diff --git a/server/src/game.rs b/server/src/game.rs index b48e1833..e4693e4a 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -123,7 +123,7 @@ impl Game {                      Player {                          item: None,                          character, -                        position: if player < 0 { +                        position: if player.0 < 0 {                              self.data.customer_spawn                          } else {                              self.data.chef_spawn @@ -246,7 +246,7 @@ impl Game {                  player.interacting = if edge { Some(pos) } else { None };              }              PacketS::Communicate { message } => { -                info!("{player} message {message:?}"); +                info!("{player:?} message {message:?}");                  if let Some(player) = self.players.get_mut(&player) {                      player.communicate = message.clone()                  } diff --git a/server/src/interaction.rs b/server/src/interaction.rs index d822340f..a4b79bd0 100644 --- a/server/src/interaction.rs +++ b/server/src/interaction.rs @@ -70,7 +70,7 @@ pub fn interact(      if player.item.is_none() {          if let Some(item) = &mut tile.item {              if let Some(active) = &mut item.active { -                let recipe = &data.recipes[active.recipe]; +                let recipe = &data.recipe(active.recipe);                  if recipe.supports_tile(tile.kind) {                      if let Recipe::Active { outputs, .. } = recipe {                          if edge { @@ -92,7 +92,7 @@ pub fn interact(          return None;      } -    for (ri, recipe) in data.recipes.iter().enumerate() { +    for (ri, recipe) in data.recipes() {          if !recipe.supports_tile(tile.kind) {              continue;          } @@ -102,7 +102,7 @@ pub fn interact(                      if let Some(item) = &mut tile.item {                          if item.kind == *input {                              if item.active.is_none() { -                                info!("start active recipe {ri}"); +                                info!("start active recipe {ri:?}");                                  item.active = Some(Involvement {                                      recipe: ri,                                      working: 1, @@ -119,7 +119,7 @@ pub fn interact(                              if let Some(active) = &mut item.active {                                  active.working += 1;                              } else { -                                info!("start active recipe {ri}"); +                                info!("start active recipe {ri:?}");                                  item.active = Some(Involvement {                                      recipe: ri,                                      working: 1, @@ -140,7 +140,7 @@ pub fn interact(                  let ok = (inputs[0] == on_tile && inputs[1] == in_hand)                      || (inputs[1] == on_tile && inputs[0] == in_hand);                  if ok { -                    info!("instant recipe {ri}"); +                    info!("instant recipe {ri:?}");                      player.item = outputs[0].map(|kind| Item { kind, active: None });                      tile.item = outputs[1].map(|kind| Item { kind, active: None });                      return Some(InteractEffect::Produce); @@ -173,11 +173,11 @@ pub enum TickEffect {  pub fn tick_tile(dt: f32, data: &Gamedata, tile: &mut Tile) -> Option<TickEffect> {      if let Some(item) = &mut tile.item {          if let Some(a) = &mut item.active { -            let r = &data.recipes[a.recipe]; +            let r = &data.recipe(a.recipe);              if r.supports_tile(tile.kind) {                  a.progress += a.working as f32 * dt / r.duration().unwrap();                  if a.progress >= 1. { -                    if let Recipe::Passive { output, .. } = &data.recipes[a.recipe] { +                    if let Recipe::Passive { output, .. } = &data.recipe(a.recipe) {                          tile.item = output.map(|kind| Item { kind, active: None });                          return Some(TickEffect::Produce);                      }; @@ -186,7 +186,7 @@ pub fn tick_tile(dt: f32, data: &Gamedata, tile: &mut Tile) -> Option<TickEffect                  return Some(TickEffect::Progress);              }          } else { -            for (ri, recipe) in data.recipes.iter().enumerate() { +            for (ri, recipe) in data.recipes() {                  if let Some(tile_constraint) = recipe.tile() {                      if tile.kind != tile_constraint {                          continue; diff --git a/server/src/main.rs b/server/src/main.rs index 4d761b0c..3af71e17 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -14,7 +14,7 @@ use undercooked::{      customer::customer,      data::build_gamedata,      game::Game, -    protocol::{PacketC, PacketS}, +    protocol::{PacketC, PacketS, PlayerID},  };  #[tokio::main] @@ -57,7 +57,7 @@ async fn main() -> Result<()> {      spawn(customer(game.clone(), rx.resubscribe())); -    for id in 1.. { +    for id in (1..).map(PlayerID) {          tokio::select! {              r = raw_listener.accept() => {                  let (sock, addr) = r?; @@ -88,7 +88,7 @@ async fn main() -> Result<()> {                              warn!("invalid json over tcp");                              break                          }; -                        debug!("<- {id} {packet:?}"); +                        debug!("<- {id:?} {packet:?}");                          if let Err(e) = game.write().await.packet_in(id, packet) {                              warn!("client error: {e}");                          } @@ -133,7 +133,7 @@ async fn main() -> Result<()> {                                      warn!("invalid json over ws");                                      break                                  }; -                                debug!("<- {id} {packet:?}"); +                                debug!("<- {id:?} {packet:?}");                                  if let Err(e) = game.write().await.packet_in(id, packet) {                                      warn!("client error: {e}");                                  } diff --git a/server/src/protocol.rs b/server/src/protocol.rs index 24fe2468..a629ffbf 100644 --- a/server/src/protocol.rs +++ b/server/src/protocol.rs @@ -2,11 +2,22 @@ use crate::data::Gamedata;  use glam::{IVec2, Vec2};  use serde::{Deserialize, Serialize}; -pub type PlayerID = i64; -pub type ItemIndex = usize; -pub type TileIndex = usize; -pub type RecipeIndex = usize; -pub type DemandIndex = usize; +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[serde(transparent)] +pub struct PlayerID(pub i64); + +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[serde(transparent)] +pub struct ItemIndex(pub usize); +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[serde(transparent)] +pub struct TileIndex(pub usize); +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[serde(transparent)] +pub struct RecipeIndex(pub usize); +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[serde(transparent)] +pub struct DemandIndex(pub usize);  #[derive(Debug, Clone, Serialize, Deserialize)]  #[serde(rename_all = "snake_case", tag = "type")] | 
