diff options
Diffstat (limited to 'server/src/entity')
| -rw-r--r-- | server/src/entity/mod.rs | 7 | ||||
| -rw-r--r-- | server/src/entity/tag_minigame.rs | 96 |
2 files changed, 102 insertions, 1 deletions
diff --git a/server/src/entity/mod.rs b/server/src/entity/mod.rs index 6418d0c7..01cb9462 100644 --- a/server/src/entity/mod.rs +++ b/server/src/entity/mod.rs @@ -24,10 +24,14 @@ pub mod environment_effect; pub mod item_portal; pub mod pedestrians; pub mod player_portal; +pub mod tag_minigame; pub mod tram; pub mod tutorial; -use crate::{entity::pedestrians::Pedestrians, scoreboard::ScoreboardStore}; +use crate::{ + entity::{pedestrians::Pedestrians, tag_minigame::TagMinigame}, + scoreboard::ScoreboardStore, +}; use anyhow::Result; use book::Book; use campaign::{Gate, Map}; @@ -82,6 +86,7 @@ pub trait Entity: Any { pub fn construct_entity(decl: &EntityDecl) -> DynEntity { match decl.to_owned() { + EntityDecl::TagMinigame { tag_item } => Box::new(TagMinigame::new(tag_item)), EntityDecl::Book { pos } => Box::new(Book(pos)), EntityDecl::ItemPortal { from, to } => Box::new(ItemPortal { from, to }), EntityDecl::PlayerPortal { from, to } => Box::new(PlayerPortal { from, to }), diff --git a/server/src/entity/tag_minigame.rs b/server/src/entity/tag_minigame.rs new file mode 100644 index 00000000..02c3726f --- /dev/null +++ b/server/src/entity/tag_minigame.rs @@ -0,0 +1,96 @@ +/* + Hurry Curry! - a game about cooking + Copyright (C) 2025 Hurry Curry! Contributors + + 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/>. + +*/ +use super::{Entity, EntityContext}; +use anyhow::Result; +use hurrycurry_client_lib::Item; +use hurrycurry_protocol::{Hand, ItemIndex, ItemLocation, Message, PacketC, PlayerID}; +use std::{collections::HashMap, fmt::Write}; + +#[derive(Debug, Clone)] +pub struct TagMinigame { + scores: HashMap<PlayerID, f32>, + report_cooldown: f32, + init_done: bool, + tag_item: ItemIndex, +} +impl TagMinigame { + pub fn new(tag_item: ItemIndex) -> Self { + Self { + init_done: false, + report_cooldown: 0., + scores: HashMap::new(), + tag_item, + } + } +} +impl Entity for TagMinigame { + fn tick(&mut self, c: EntityContext) -> Result<()> { + if !self.init_done { + self.init_done = true; + // Hand out item every but one player (not random yet) + for (id, player) in c.game.players.iter_mut().skip(1) { + if let Some(slot) = player.items.get_mut(0) { + *slot = Some(Item { + active: None, + kind: self.tag_item, + }); + c.packet_out.push_back(PacketC::SetItem { + location: ItemLocation::Player(*id, Hand(0)), + item: Some(self.tag_item), + }); + } + } + } + + // Award points to players with the item + for (&id, player) in &c.game.players { + if let Some(slot) = player.items.get(0) + && let Some(item) = slot + && item.kind == self.tag_item + { + *self.scores.entry(id).or_default() += c.dt + } + } + + // Send out a scoreboard message every 0.1s + self.report_cooldown -= c.dt; + if self.report_cooldown < 0. { + self.report_cooldown = 0.1; + let mut scores = self + .scores + .iter() + .map(|(x, y)| ((y * 10.) as i64, *x)) + .collect::<Vec<_>>(); + scores.sort_by_key(|(s, _)| -s); + + let mut o = String::new(); + writeln!(o, "Tag Minigame — Try to not have your lettuce stolen!").unwrap(); + for ((score, player), rank) in scores.into_iter().zip(1..) { + let name = c.game.players.get(&player).map_or("unknown", |p| &p.name); + writeln!(o, "{rank:>2} {score:>4} {name}").unwrap(); + } + o.pop(); // newline + c.packet_out.push_back(PacketC::ServerMessage { + error: false, + message: Message::Text(o), + }); + } + + Ok(()) + } +} |