diff options
Diffstat (limited to 'server/src')
| -rw-r--r-- | server/src/customer/mod.rs | 57 | ||||
| -rw-r--r-- | server/src/data.rs | 13 | ||||
| -rw-r--r-- | server/src/main.rs | 1 | 
3 files changed, 56 insertions, 15 deletions
| diff --git a/server/src/customer/mod.rs b/server/src/customer/mod.rs index ab3accdd..7c6cd235 100644 --- a/server/src/customer/mod.rs +++ b/server/src/customer/mod.rs @@ -21,12 +21,17 @@ use tokio::{      time::interval,  }; -struct DemandState { -    data: Gamedata, +struct CustomerManager {      walkable: HashSet<IVec2>,      chairs: HashMap<IVec2, bool>,      items: HashMap<IVec2, ItemIndex>,      customers: HashMap<PlayerID, Customer>, +    customer_id_counter: PlayerID, +    demand: DemandState, +} + +struct DemandState { +    data: Gamedata,  }  enum CustomerState { @@ -41,21 +46,24 @@ struct Customer {  }  pub async fn customer(game: Arc<RwLock<Game>>, mut grx: broadcast::Receiver<PacketC>) { -    let mut state = DemandState { +    let mut state = CustomerManager { +        customer_id_counter: 0,          walkable: Default::default(),          chairs: Default::default(),          items: Default::default(),          customers: Default::default(), -        data: Gamedata::default(), +        demand: DemandState { +            data: Gamedata::default(), +        },      };      let initial = game.write().await.prime_client(-1);      for p in initial {          match p {              PacketC::Init { data, .. } => { -                state.data = data; +                state.demand.data = data;              }              PacketC::UpdateMap { pos, tile, .. } => { -                let tilename = &state.data.tile_names[tile]; +                let tilename = &state.demand.data.tile_names[tile];                  if tilename == "floor" || tilename == "door" || tilename == "chair" {                      state.walkable.insert(pos);                  } @@ -95,7 +103,7 @@ pub async fn customer(game: Arc<RwLock<Game>>, mut grx: broadcast::Receiver<Pack      }  } -fn update_items(state: &mut DemandState, game: &Game) { +fn update_items(state: &mut CustomerManager, game: &Game) {      state.items.clear();      for (&pos, tile) in game.tiles() {          if let Some(item) = &tile.item { @@ -105,9 +113,22 @@ fn update_items(state: &mut DemandState, game: &Game) {  }  impl DemandState { +    pub fn target_customer_count(&self) -> usize { +        // TODO insert sofa magic formula +        5 +    } +    pub fn generate_demand(&self) -> usize { +        // TODO insert sofa magic formula +        use rand::seq::IndexedRandom; +        *self.data.demands.choose(&mut thread_rng()).unwrap() +    } +} + +impl CustomerManager {      pub fn tick(&mut self, packets_out: &mut Vec<(PlayerID, PacketS)>, dt: f32) { -        if self.customers.is_empty() { -            let id = -1; +        if self.customers.len() < self.demand.target_customer_count() { +            self.customer_id_counter -= 1; +            let id = self.customer_id_counter;              packets_out.push((                  id,                  PacketS::Join { @@ -116,13 +137,17 @@ impl DemandState {                  },              ));              let chair = select_chair(&mut self.chairs); -            let path = find_path(&self.walkable, self.data.customer_spawn.as_ivec2(), chair) -                .expect("no path"); +            let path = find_path( +                &self.walkable, +                self.demand.data.customer_spawn.as_ivec2(), +                chair, +            ) +            .expect("no path");              self.customers.insert(                  id,                  Customer {                      movement: MovementBase { -                        position: self.data.customer_spawn, +                        position: self.demand.data.customer_spawn,                          facing: Vec2::X,                          vel: Vec2::ZERO,                      }, @@ -136,7 +161,7 @@ impl DemandState {                  CustomerState::WalkingToChair { path, chair } => {                      packets_out.push((id, path.execute_tick(&mut p.movement, &self.walkable, dt)));                      if path.is_done() { -                        let demand = self.data.get_item("tomato").unwrap(); +                        let demand = self.demand.generate_demand();                          packets_out.push((                              id,                              PacketS::Communicate { @@ -163,12 +188,16 @@ impl DemandState {                      if let Some(pos) = demand_pos {                          if self.items.get(&pos) == Some(demand) {                              packets_out.push((id, PacketS::Communicate { message: None })); +                            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.data.customer_spawn.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 }                          }                      } diff --git a/server/src/data.rs b/server/src/data.rs index d138f360..3526d786 100644 --- a/server/src/data.rs +++ b/server/src/data.rs @@ -40,12 +40,18 @@ pub struct Gamedata {      pub initial_map: HashMap<IVec2, TileIndex>,      pub chef_spawn: Vec2,      pub customer_spawn: Vec2, +    pub demands: Vec<usize>,  } -pub fn build_gamedata(recipes_in: Vec<RecipeDecl>, map_in: InitialMap) -> Gamedata { +pub fn build_gamedata( +    recipes_in: Vec<RecipeDecl>, +    map_in: InitialMap, +    demands_in: Vec<String>, +) -> Gamedata {      let item_names = RwLock::new(Vec::new());      let tile_names = RwLock::new(Vec::new());      let mut recipes = Vec::new(); +    let mut demands = Vec::new();      for r in recipes_in {          let r2 = r.clone(); @@ -78,6 +84,10 @@ pub fn build_gamedata(recipes_in: Vec<RecipeDecl>, map_in: InitialMap) -> Gameda          assert_eq!(outputs.next(), None, "{r2:?}");      } +    for d in demands_in { +        demands.push(register(&item_names, d)) +    } +      let mut chef_spawn = Vec2::new(0., 0.);      let mut customer_spawn = Vec2::new(0., 0.);      let mut initial_map = HashMap::new(); @@ -99,6 +109,7 @@ pub fn build_gamedata(recipes_in: Vec<RecipeDecl>, map_in: InitialMap) -> Gameda      }      Gamedata { +        demands,          recipes,          initial_map,          item_names: item_names.into_inner().unwrap(), diff --git a/server/src/main.rs b/server/src/main.rs index e505195c..4d761b0c 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -31,6 +31,7 @@ async fn main() -> Result<()> {      let data = build_gamedata(          serde_yaml::from_reader(File::open("data/recipes.yaml").unwrap()).unwrap(),          serde_yaml::from_reader(File::open("data/map.yaml").unwrap()).unwrap(), +        serde_yaml::from_reader(File::open("data/demands.yaml").unwrap()).unwrap(),      );      let game = Arc::new(RwLock::new(Game::new(data.into()))); | 
