diff options
Diffstat (limited to 'server/src/customer/mod.rs')
| -rw-r--r-- | server/src/customer/mod.rs | 290 | 
1 files changed, 0 insertions, 290 deletions
| diff --git a/server/src/customer/mod.rs b/server/src/customer/mod.rs deleted file mode 100644 index bf385927..00000000 --- a/server/src/customer/mod.rs +++ /dev/null @@ -1,290 +0,0 @@ -/* -    Hurry Curry! - a game about cooking -    Copyright 2024 metamuffin - -    This program is free software: you can redistribute it and/or modify -    it under the terms of the GNU Affero General Public License as published by -    the Free Software Foundation, version 3 of the License only. - -    This program is distributed in the hope that it will be useful, -    but WITHOUT ANY WARRANTY; without even the implied warranty of -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -    GNU Affero General Public License for more details. - -    You should have received a copy of the GNU Affero General Public License -    along with this program.  If not, see <https://www.gnu.org/licenses/>. - -*/ -mod pathfinding; - -use crate::{data::Gamedata, game::Tile}; -use anyhow::{anyhow, Result}; -use fake::{faker, Fake}; -use hurrycurry_protocol::{ -    glam::IVec2, movement::MovementBase, DemandIndex, Message, PacketS, PlayerID, -}; -use log::info; -use pathfinding::{find_path, Path}; -use rand::{random, thread_rng}; -use std::{ -    collections::{HashMap, HashSet}, -    sync::Arc, -}; - -pub struct DemandState { -    data: Arc<Gamedata>, -    walkable: HashSet<IVec2>, -    chairs: HashMap<IVec2, bool>, -    customer_id_counter: PlayerID, -    customers: HashMap<PlayerID, Customer>, -    spawn_cooldown: f32, - -    pub completed: usize, -    pub failed: usize, -    pub score_changed: bool, -} - -enum CustomerState { -    Entering { -        path: Path, -        chair: IVec2, -    }, -    Waiting { -        demand: DemandIndex, -        chair: IVec2, -        timeout: f32, -    }, -    Eating { -        demand: DemandIndex, -        target: IVec2, -        progress: f32, -        chair: IVec2, -    }, -    Exiting { -        path: Path, -    }, -} - -pub struct Customer { -    movement: MovementBase, -    state: CustomerState, -} - -impl DemandState { -    pub fn new(data: Arc<Gamedata>, map: &HashMap<IVec2, Tile>) -> Self { -        let chair = data.get_tile_by_name("chair"); -        Self { -            score_changed: true, -            completed: 0, -            failed: 0, -            walkable: map -                .iter() -                .filter(|(_, v)| !data.is_tile_colliding(v.kind)) -                .map(|(e, _)| *e) -                .collect(), -            chairs: map -                .iter() -                .filter(|(_, v)| Some(v.kind) == chair) -                .map(|(e, _)| (*e, true)) -                .collect(), -            customer_id_counter: PlayerID(0), -            customers: Default::default(), -            data, -            spawn_cooldown: 0., -        } -    } -} - -impl DemandState { -    pub fn tick( -        &mut self, -        packets_out: &mut Vec<(PlayerID, PacketS)>, -        tiles: &mut HashMap<IVec2, Tile>, -        data: &Gamedata, -        dt: f32, -        points: &mut i64, -    ) -> Result<()> { -        self.spawn_cooldown -= dt; -        self.spawn_cooldown = self.spawn_cooldown.max(0.); -        if self.customers.len() < 5 && self.spawn_cooldown <= 0. { -            self.spawn_cooldown = 10. + random::<f32>() * 10.; -            self.customer_id_counter.0 -= 1; -            let id = self.customer_id_counter; -            packets_out.push(( -                id, -                PacketS::Join { -                    name: faker::name::fr_fr::Name().fake(), -                    character: -1 - (random::<u16>() as i32), -                }, -            )); -            let chair = self.select_chair().ok_or(anyhow!("no free chair found"))?; -            let from = data.customer_spawn.as_ivec2(); -            let path = find_path(&self.walkable, from, chair) -                .ok_or(anyhow!("no path from {from} to {chair}"))?; -            info!("{id:?} -> entering"); -            self.customers.insert( -                id, -                Customer { -                    movement: MovementBase::new(data.customer_spawn), -                    state: CustomerState::Entering { path, chair }, -                }, -            ); -        } -        let mut customers_to_remove = Vec::new(); -        for (&id, p) in &mut self.customers { -            match &mut p.state { -                CustomerState::Entering { path, chair } => { -                    packets_out.push((id, path.execute_tick(&mut p.movement, &self.walkable, dt))); -                    if path.is_done() { -                        let demand = DemandIndex(random::<usize>() % self.data.demands.len()); -                        packets_out.push(( -                            id, -                            PacketS::Communicate { -                                message: Some(Message::Item(data.demand(demand).from)), -                                persist: true, -                            }, -                        )); -                        info!("{id:?} -> waiting"); -                        p.state = CustomerState::Waiting { -                            chair: *chair, -                            timeout: 90. + random::<f32>() * 60., -                            demand, -                        }; -                    } -                } -                CustomerState::Waiting { -                    chair, -                    demand, -                    timeout, -                } => { -                    *timeout -= dt; -                    if *timeout <= 0. { -                        packets_out.push(( -                            id, -                            PacketS::Communicate { -                                message: None, -                                persist: true, -                            }, -                        )); -                        packets_out.push(( -                            id, -                            PacketS::Communicate { -                                message: Some(Message::Effect("angry".to_string())), -                                persist: false, -                            }, -                        )); -                        let path = find_path( -                            &self.walkable, -                            p.movement.position.as_ivec2(), -                            data.customer_spawn.as_ivec2(), -                        ) -                        .expect("no path to exit"); -                        *self.chairs.get_mut(&chair).unwrap() = true; -                        self.failed += 1; -                        *points -= 1; -                        self.score_changed = true; -                        info!("{id:?} -> exiting"); -                        p.state = CustomerState::Exiting { path } -                    } else { -                        let demand_data = &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 tiles -                                    .get(&pos) -                                    .map(|t| { -                                        t.item -                                            .as_ref() -                                            .map(|i| i.kind == demand_data.from) -                                            .unwrap_or_default() -                                    }) -                                    .unwrap_or_default() -                                { -                                    Some(pos) -                                } else { -                                    None -                                } -                            }); -                        if let Some(pos) = demand_pos { -                            packets_out.push(( -                                id, -                                PacketS::Communicate { -                                    persist: true, -                                    message: None, -                                }, -                            )); -                            packets_out.push(( -                                id, -                                PacketS::Communicate { -                                    message: Some(Message::Effect("satisfied".to_string())), -                                    persist: false, -                                }, -                            )); -                            packets_out.push((id, PacketS::Interact { pos: Some(pos) })); -                            packets_out.push((id, PacketS::Interact { pos: None })); -                            info!("{id:?} -> eating"); -                            p.state = CustomerState::Eating { -                                demand: *demand, -                                target: pos, -                                progress: 0., -                                chair: *chair, -                            } -                        } -                    } -                } -                CustomerState::Eating { -                    demand, -                    target, -                    progress, -                    chair, -                } => { -                    let demand = data.demand(*demand); -                    *progress += dt / demand.duration; -                    if *progress >= 1. { -                        packets_out.push((id, PacketS::ReplaceHand { item: demand.to })); -                        if demand.to.is_some() { -                            packets_out.push((id, PacketS::Interact { pos: Some(*target) })); -                            packets_out.push((id, PacketS::Interact { pos: None })); -                        } -                        let path = find_path( -                            &self.walkable, -                            p.movement.position.as_ivec2(), -                            data.customer_spawn.as_ivec2(), -                        ) -                        .ok_or(anyhow!("no path to exit"))?; -                        *self.chairs.get_mut(&chair).unwrap() = true; -                        self.completed += 1; -                        *points += demand.points; -                        self.score_changed = true; -                        info!("{id:?} -> exiting"); -                        p.state = CustomerState::Exiting { path } -                    } -                } -                CustomerState::Exiting { path } => { -                    packets_out.push((id, path.execute_tick(&mut p.movement, &self.walkable, dt))); -                    if path.is_done() { -                        info!("{id:?} -> leave"); -                        packets_out.push((id, PacketS::Leave)); -                        customers_to_remove.push(id); -                    } -                } -            } -        } -        for c in customers_to_remove { -            self.customers.remove(&c).unwrap(); -        } -        Ok(()) -    } - -    fn select_chair(&mut self) -> Option<IVec2> { -        use rand::seq::IteratorRandom; -        let (chosen, free) = self -            .chairs -            .iter_mut() -            .filter(|(_p, free)| **free) -            .choose(&mut thread_rng())?; -        *free = false; -        Some(*chosen) -    } -} | 
