diff options
| author | metamuffin <metamuffin@disroot.org> | 2025-10-19 23:50:23 +0200 |
|---|---|---|
| committer | metamuffin <metamuffin@disroot.org> | 2025-10-19 23:50:23 +0200 |
| commit | ab83f982601d93b2399102c4d030fd6e13c4c735 (patch) | |
| tree | c0536ca9e328707d6b4f4cfc7a2307713466a5be /server/src | |
| parent | 231a5ce21fcee9195fcc504ee672e4464d627c47 (diff) | |
| download | hurrycurry-ab83f982601d93b2399102c4d030fd6e13c4c735.tar hurrycurry-ab83f982601d93b2399102c4d030fd6e13c4c735.tar.bz2 hurrycurry-ab83f982601d93b2399102c4d030fd6e13c4c735.tar.zst | |
Refactor and move interaction code
Diffstat (limited to 'server/src')
| -rw-r--r-- | server/src/entity/bot.rs | 3 | ||||
| -rw-r--r-- | server/src/entity/campaign.rs | 4 | ||||
| -rw-r--r-- | server/src/entity/conveyor.rs | 31 | ||||
| -rw-r--r-- | server/src/entity/customers.rs | 9 | ||||
| -rw-r--r-- | server/src/entity/environment_effect.rs | 3 | ||||
| -rw-r--r-- | server/src/entity/item_portal.rs | 32 | ||||
| -rw-r--r-- | server/src/entity/mod.rs | 4 | ||||
| -rw-r--r-- | server/src/entity/pedestrians.rs | 3 | ||||
| -rw-r--r-- | server/src/entity/player_portal.rs | 7 | ||||
| -rw-r--r-- | server/src/entity/tag_minigame.rs | 3 | ||||
| -rw-r--r-- | server/src/entity/tram.rs | 3 | ||||
| -rw-r--r-- | server/src/entity/tutorial.rs | 4 | ||||
| -rw-r--r-- | server/src/interaction.rs | 354 | ||||
| -rw-r--r-- | server/src/lib.rs | 1 | ||||
| -rw-r--r-- | server/src/server.rs | 111 |
15 files changed, 49 insertions, 523 deletions
diff --git a/server/src/entity/bot.rs b/server/src/entity/bot.rs index 9627bb76..51a09b62 100644 --- a/server/src/entity/bot.rs +++ b/server/src/entity/bot.rs @@ -18,6 +18,7 @@ use super::{Entity, EntityContext}; use anyhow::Result; use hurrycurry_bot::{BotAlgo, DynBotAlgo}; +use hurrycurry_locale::TrError; use hurrycurry_protocol::{Character, Hand, ItemLocation, PacketS, PlayerClass, PlayerID}; use log::debug; use std::any::Any; @@ -47,7 +48,7 @@ impl<T: BotAlgo + Any> Entity for BotDriver<T> { fn finished(&self) -> bool { self.left } - fn tick(&mut self, c: EntityContext<'_>) -> Result<()> { + fn tick(&mut self, c: EntityContext<'_>) -> Result<(), TrError> { if let Some((name, character, class)) = self.join_data.take() { self.id = c.game.get_unused_player_id(); // TODO clashes when multiple bots join in the same tick debug!("join {}", self.id); diff --git a/server/src/entity/campaign.rs b/server/src/entity/campaign.rs index 1966fc01..b7d7d8db 100644 --- a/server/src/entity/campaign.rs +++ b/server/src/entity/campaign.rs @@ -32,7 +32,7 @@ pub struct Map { } impl Entity for Map { - fn tick(&mut self, c: EntityContext) -> Result<()> { + fn tick(&mut self, c: EntityContext) -> Result<(), TrError> { let mut activate = false; c.game .players_spatial_index @@ -55,7 +55,7 @@ pub struct Gate { pub condition: GateCondition, } impl Entity for Gate { - fn tick(&mut self, c: EntityContext<'_>) -> Result<()> { + fn tick(&mut self, c: EntityContext<'_>) -> Result<(), TrError> { if self.active { self.active = false; self.unlocked = self.condition.check(c.scoreboard); diff --git a/server/src/entity/conveyor.rs b/server/src/entity/conveyor.rs index 9534b045..6757ed43 100644 --- a/server/src/entity/conveyor.rs +++ b/server/src/entity/conveyor.rs @@ -16,8 +16,8 @@ */ use super::{Entity, EntityContext}; -use crate::interaction::interact; -use anyhow::{Result, anyhow, bail}; +use anyhow::Result; +use hurrycurry_locale::TrError; use hurrycurry_protocol::{ItemLocation, glam::IVec2}; #[derive(Debug, Clone)] @@ -29,12 +29,12 @@ pub struct Conveyor { } impl Entity for Conveyor { - fn tick(&mut self, c: EntityContext) -> Result<()> { + fn tick(&mut self, c: EntityContext) -> Result<(), TrError> { let from = c .game .tiles .get(&self.from) - .ok_or(anyhow!("conveyor from missing"))?; + .ok_or(TrError::Plain("conveyor from missing".into()))?; if from.item.is_some() { self.cooldown += c.dt; @@ -43,28 +43,11 @@ impl Entity for Conveyor { } self.cooldown = 0.; - if self.from == self.to { - bail!("conveyor does ends in itself") - } - let [Some(from), Some(to)] = c.game.tiles.get_disjoint_mut([&self.from, &self.to]) - else { - bail!("at least one conveyor end not on map"); - }; - - interact( - &c.game.data, - true, - Some(to.kind), - None, - &mut to.item, - ItemLocation::Tile(self.to), - &mut from.item, + c.game.interact( ItemLocation::Tile(self.from), - &mut c.game.score, - c.score_changed, + ItemLocation::Tile(self.to), true, - c.packet_out, - ); + )?; } Ok(()) diff --git a/server/src/entity/customers.rs b/server/src/entity/customers.rs index 1e795ac5..36afe24a 100644 --- a/server/src/entity/customers.rs +++ b/server/src/entity/customers.rs @@ -1,7 +1,3 @@ -use std::random::random; - -use crate::random_float; - /* Hurry Curry! - a game about cooking Copyright (C) 2025 Hurry Curry! Contributors @@ -20,9 +16,12 @@ use crate::random_float; */ use super::{Entity, EntityContext, bot::BotDriver}; +use crate::random_float; use anyhow::Result; use hurrycurry_bot::algos::{Customer, CustomerConfig}; +use hurrycurry_locale::TrError; use hurrycurry_protocol::{Character, PlayerClass}; +use std::random::random; pub struct Customers { customers: Vec<BotDriver<Customer>>, @@ -43,7 +42,7 @@ impl Customers { } impl Entity for Customers { - fn tick(&mut self, c: EntityContext) -> Result<()> { + fn tick(&mut self, c: EntityContext) -> Result<(), TrError> { let chairs = *self.chair_count.get_or_insert_with(|| { c.game .tiles diff --git a/server/src/entity/environment_effect.rs b/server/src/entity/environment_effect.rs index b5344a27..e50a65ff 100644 --- a/server/src/entity/environment_effect.rs +++ b/server/src/entity/environment_effect.rs @@ -19,6 +19,7 @@ use crate::random_float; */ use super::{Entity, EntityContext}; use hurrycurry_data::entities::EnvironmentEffect; +use hurrycurry_locale::TrError; use hurrycurry_protocol::PacketC; use std::time::{Duration, Instant}; @@ -39,7 +40,7 @@ impl EnvironmentEffectController { } } impl Entity for EnvironmentEffectController { - fn tick(&mut self, c: EntityContext) -> anyhow::Result<()> { + fn tick(&mut self, c: EntityContext) -> Result<(), TrError> { if self.next_transition < Instant::now() { if self.active { self.next_transition += diff --git a/server/src/entity/item_portal.rs b/server/src/entity/item_portal.rs index f0472802..4335a659 100644 --- a/server/src/entity/item_portal.rs +++ b/server/src/entity/item_portal.rs @@ -16,8 +16,8 @@ */ use super::{Entity, EntityContext}; -use crate::interaction::interact; -use anyhow::{Result, bail}; +use anyhow::Result; +use hurrycurry_locale::TrError; use hurrycurry_protocol::{ItemLocation, glam::IVec2}; #[derive(Debug, Default, Clone)] @@ -27,29 +27,19 @@ pub struct ItemPortal { } impl Entity for ItemPortal { - fn tick(&mut self, c: EntityContext) -> Result<()> { - if self.from == self.to { - bail!("item portal ends in itself") - } - let [Some(from), Some(to)] = c.game.tiles.get_disjoint_mut([&self.from, &self.to]) else { - bail!("at least one item portal end not on map"); - }; + fn tick(&mut self, c: EntityContext) -> Result<(), TrError> { + let from = c + .game + .tiles + .get(&self.from) + .ok_or(TrError::Plain("portal from missing".into()))?; if from.item.is_some() { - interact( - &c.game.data, - true, - Some(to.kind), - None, - &mut to.item, - ItemLocation::Tile(self.to), - &mut from.item, + c.game.interact( ItemLocation::Tile(self.from), - &mut c.game.score, - c.score_changed, + ItemLocation::Tile(self.to), true, - c.packet_out, - ); + )?; } Ok(()) diff --git a/server/src/entity/mod.rs b/server/src/entity/mod.rs index 34815d0d..2e235c95 100644 --- a/server/src/entity/mod.rs +++ b/server/src/entity/mod.rs @@ -38,8 +38,8 @@ use campaign::{Gate, Map}; use conveyor::Conveyor; use customers::Customers; use environment_effect::{EnvironmentController, EnvironmentEffectController}; -use hurrycurry_game_core::Game; use hurrycurry_data::{Serverdata, entities::EntityDecl}; +use hurrycurry_game_core::Game; use hurrycurry_locale::TrError; use hurrycurry_protocol::{Character, ItemLocation, PacketC, PacketS, PlayerID}; use item_portal::ItemPortal; @@ -66,7 +66,7 @@ pub struct EntityContext<'a> { } pub trait Entity: Any { - fn tick(&mut self, _c: EntityContext<'_>) -> Result<()> { + fn tick(&mut self, _c: EntityContext<'_>) -> Result<(), TrError> { Ok(()) } fn finished(&self) -> bool { diff --git a/server/src/entity/pedestrians.rs b/server/src/entity/pedestrians.rs index edfe5ca3..0d33bfd0 100644 --- a/server/src/entity/pedestrians.rs +++ b/server/src/entity/pedestrians.rs @@ -19,6 +19,7 @@ use crate::random_gauss; */ use super::{Entity, EntityContext}; use anyhow::Result; +use hurrycurry_locale::TrError; use hurrycurry_protocol::{Character, PacketS, PlayerClass, PlayerID, glam::Vec2}; use std::{collections::HashMap, random::random}; @@ -35,7 +36,7 @@ impl Entity for Pedestrians { fn finished(&self) -> bool { false } - fn tick(&mut self, c: EntityContext<'_>) -> Result<()> { + fn tick(&mut self, c: EntityContext<'_>) -> Result<(), TrError> { self.cooldown -= c.dt; if self.cooldown <= 0. && self.players.len() < 32 { let id = c.game.get_unused_player_id(); diff --git a/server/src/entity/player_portal.rs b/server/src/entity/player_portal.rs index 1717002a..a2653900 100644 --- a/server/src/entity/player_portal.rs +++ b/server/src/entity/player_portal.rs @@ -16,7 +16,8 @@ */ use super::{Entity, EntityContext}; -use anyhow::{Result, anyhow}; +use anyhow::Result; +use hurrycurry_locale::TrError; use hurrycurry_protocol::{PacketC, glam::Vec2}; #[derive(Debug, Default, Clone)] @@ -26,7 +27,7 @@ pub struct PlayerPortal { } impl Entity for PlayerPortal { - fn tick(&mut self, c: EntityContext) -> Result<()> { + fn tick(&mut self, c: EntityContext) -> Result<(), TrError> { let mut players = Vec::new(); c.game .players_spatial_index @@ -37,7 +38,7 @@ impl Entity for PlayerPortal { .game .players .get_mut(&pid) - .ok_or(anyhow!("Player is missing"))?; + .ok_or(TrError::Plain("Player is missing".to_string()))?; p.movement.position = self.to; c.packet_out .push_back(PacketC::MovementSync { player: pid }); diff --git a/server/src/entity/tag_minigame.rs b/server/src/entity/tag_minigame.rs index a76b0511..089fd49e 100644 --- a/server/src/entity/tag_minigame.rs +++ b/server/src/entity/tag_minigame.rs @@ -18,6 +18,7 @@ use super::{Entity, EntityContext}; use anyhow::Result; use hurrycurry_game_core::{Item, Tile}; +use hurrycurry_locale::TrError; use hurrycurry_protocol::{ Hand, ItemIndex, ItemLocation, Message, PacketC, PlayerID, TileIndex, glam::IVec2, }; @@ -49,7 +50,7 @@ impl TagMinigame { } } impl Entity for TagMinigame { - fn tick(&mut self, c: EntityContext) -> Result<()> { + fn tick(&mut self, c: EntityContext) -> Result<(), TrError> { if !self.init_done { self.init_done = true; // Hand out the item to some player(s) diff --git a/server/src/entity/tram.rs b/server/src/entity/tram.rs index 2d6aa8c1..20fe8120 100644 --- a/server/src/entity/tram.rs +++ b/server/src/entity/tram.rs @@ -17,6 +17,7 @@ */ use super::{Entity, EntityContext}; use anyhow::Result; +use hurrycurry_locale::TrError; use hurrycurry_protocol::{Character, PacketS, PlayerClass, PlayerID, glam::Vec2}; pub struct Tram { @@ -33,7 +34,7 @@ impl Entity for Tram { fn finished(&self) -> bool { false } - fn tick(&mut self, c: EntityContext<'_>) -> Result<()> { + fn tick(&mut self, c: EntityContext<'_>) -> Result<(), TrError> { if self.ids.len() < self.length { let id = c.game.get_unused_player_id(); c.packet_in.push_back(PacketS::Join { diff --git a/server/src/entity/tutorial.rs b/server/src/entity/tutorial.rs index 8cc896ac..46b2a0db 100644 --- a/server/src/entity/tutorial.rs +++ b/server/src/entity/tutorial.rs @@ -17,7 +17,7 @@ */ use super::{Entity, EntityContext}; use anyhow::Result; -use hurrycurry_locale::trm; +use hurrycurry_locale::{TrError, trm}; use hurrycurry_protocol::{ ItemIndex, Message, PacketC, PlayerID, Recipe, RecipeIndex, TileIndex, glam::IVec2, }; @@ -67,7 +67,7 @@ impl Entity for Tutorial { success: false, }); } - fn tick(&mut self, c: EntityContext<'_>) -> Result<()> { + fn tick(&mut self, c: EntityContext<'_>) -> Result<(), TrError> { if self.ended { return Ok(()); } diff --git a/server/src/interaction.rs b/server/src/interaction.rs deleted file mode 100644 index a2e8643a..00000000 --- a/server/src/interaction.rs +++ /dev/null @@ -1,354 +0,0 @@ -/* - 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 hurrycurry_game_core::{Involvement, Item, gamedata_index::GamedataIndex}; -use hurrycurry_protocol::{Gamedata, ItemLocation, PacketC, PlayerID, Recipe, Score, TileIndex}; -use log::info; -use std::collections::{BTreeSet, VecDeque}; - -#[allow(clippy::too_many_arguments)] -pub fn interact( - data: &Gamedata, - edge: bool, - tile: Option<TileIndex>, - player: Option<PlayerID>, - this: &mut Option<Item>, - this_loc: ItemLocation, - other: &mut Option<Item>, - other_loc: ItemLocation, - score: &mut Score, - score_changed: &mut bool, - automated: bool, - packet_out: &mut VecDeque<PacketC>, -) { - if other.is_none() - && let Some(item) = this - && let Some(inv) = &mut item.active - { - let recipe = &data.recipe(inv.recipe); - if recipe.supports_tile(tile) - && let Recipe::Active { outputs, speed, .. } = recipe - { - if edge { - inv.players.extend(player); - } else { - if let Some(player) = player { - inv.players.remove(&player); - } - } - inv.speed = speed * inv.players.len() as f32; - - if inv.position >= 1. { - let this_had_item = this.is_some(); - let other_had_item = other.is_some(); - *other = outputs[0].map(|kind| Item { kind, active: None }); - *this = outputs[1].map(|kind| Item { kind, active: None }); - produce( - this_had_item, - other_had_item, - this, - this_loc, - other, - other_loc, - score_changed, - packet_out, - ); - } else { - packet_out.push_back(PacketC::SetProgress { - players: inv.players.clone(), - item: this_loc, - position: inv.position, - speed: inv.speed, - warn: inv.warn, - }); - } - return; - } - } - if !edge { - return; - } - for (ri, recipe) in data.recipes() { - if !recipe.supports_tile(tile) { - continue; - } - match recipe { - Recipe::Active { input, speed, .. } => { - if other.is_none() - && let Some(item) = this - && item.kind == *input - && item.active.is_none() - { - info!("start active {ri}"); - item.active = Some(Involvement { - players: player.into_iter().collect(), - recipe: ri, - speed: *speed, - position: 0., - warn: false, - }); - } - if this.is_none() - && let Some(item) = &other - && item.kind == *input - && item.active.is_none() - { - let mut item = other.take().unwrap(); - info!("start active {ri}"); - item.active = Some(Involvement { - players: player.into_iter().collect(), - recipe: ri, - speed: *speed, - position: 0., - warn: false, - }); - *this = Some(item); - score.active_recipes += 1; - packet_out.push_back(PacketC::MoveItem { - from: other_loc, - to: this_loc, - }); - packet_out.push_back(PacketC::SetProgress { - players: player.into_iter().collect(), - item: this_loc, - position: 0., - speed: *speed, - warn: false, - }); - return; - } - } - Recipe::Instant { - inputs, - outputs, - points: pd, - .. - } => { - let on_tile = this.as_ref().map(|i| i.kind); - let in_hand = other.as_ref().map(|i| i.kind); - let ok = inputs[0] == on_tile && inputs[1] == in_hand; - let ok_rev = inputs[1] == on_tile && inputs[0] == in_hand; - if ok || ok_rev { - info!("instant {ri} reversed={ok_rev}"); - let ok_rev = ok_rev as usize; - let this_had_item = this.is_some(); - let other_had_item = other.is_some(); - *other = outputs[1 - ok_rev].map(|kind| Item { kind, active: None }); - *this = outputs[ok_rev].map(|kind| Item { kind, active: None }); - score.points += pd; - score.instant_recipes += 1; - *score_changed = true; - produce( - this_had_item, - other_had_item, - this, - this_loc, - other, - other_loc, - score_changed, - packet_out, - ); - return; - } - } - _ => (), - } - } - - let can_place = automated - || tile.is_none_or(|tile| { - other.as_ref().is_some_and(|other| { - data.tile_placeable_items - .get(&tile) - .is_none_or(|pl| pl.contains(&other.kind)) - }) - }); - - if can_place - && this.is_none() - && let Some(item) = other.take() - { - *this = Some(item); - packet_out.push_back(PacketC::MoveItem { - from: other_loc, - to: this_loc, - }); - return; - } - if other.is_none() - && let Some(item) = this.take() - { - *other = Some(item); - packet_out.push_back(PacketC::MoveItem { - from: this_loc, - to: other_loc, - }); - } -} - -pub enum TickEffect { - Progress { - speed: f32, - position: f32, - warn: bool, - }, - ClearProgress, - Produce, -} - -#[allow(clippy::too_many_arguments)] -pub fn tick_slot( - dt: f32, - data: &Gamedata, - data_index: &GamedataIndex, - tile: Option<TileIndex>, - slot: &mut Option<Item>, - slot_loc: ItemLocation, - score: &mut Score, - score_changed: &mut bool, - packet_out: &mut VecDeque<PacketC>, -) { - if let Some(item) = slot { - if let Some(a) = &mut item.active { - let r = &data.recipe(a.recipe); - let prev_speed = a.speed; - - if r.supports_tile(tile) { - if a.speed <= 0. - && let Recipe::Passive { speed, .. } = &data.recipe(a.recipe) - { - a.speed = *speed; - } - } else if let Some(revert_speed) = r.revert_speed() { - a.speed = -revert_speed - } else { - a.speed = 0.; - } - - if a.position < 0. { - item.active = None; - packet_out.push_back(PacketC::ClearProgress { item: slot_loc }); - return; - } - if a.position >= 1. - && let Recipe::Passive { output, warn, .. } = &data.recipe(a.recipe) - { - *slot = output.map(|kind| Item { kind, active: None }); - score.passive_recipes += 1; - *score_changed = true; - packet_out.push_back(PacketC::SetProgress { - players: BTreeSet::new(), - warn: *warn, - item: slot_loc, - position: 1., - speed: 0., - }); - packet_out.push_back(PacketC::SetItem { - location: slot_loc, - item: slot.as_ref().map(|i| i.kind), - }); - return; - }; - - a.position += dt * a.speed; - a.position = a.position.min(1.); - - if a.speed != prev_speed { - packet_out.push_back(PacketC::SetProgress { - players: a.players.clone(), - position: a.position, - speed: a.speed, - warn: a.warn, - item: slot_loc, - }); - } - } else if let Some(recipes) = data_index.recipe_passive_by_input.get(&item.kind) { - for &ri in recipes { - let recipe = data.recipe(ri); - if recipe.supports_tile(tile) - && let Recipe::Passive { - input, warn, speed, .. - } = recipe - && *input == item.kind - { - item.active = Some(Involvement { - players: BTreeSet::new(), - recipe: ri, - position: 0., - warn: *warn, - speed: *speed, - }); - packet_out.push_back(PacketC::SetProgress { - players: BTreeSet::new(), - position: 0., - speed: *speed, - warn: *warn, - item: slot_loc, - }); - return; - } - } - } - } -} - -#[allow(clippy::too_many_arguments)] -fn produce( - this_had_item: bool, - other_had_item: bool, - this: &Option<Item>, - this_loc: ItemLocation, - other: &Option<Item>, - other_loc: ItemLocation, - score_changed: &mut bool, - packet_out: &mut VecDeque<PacketC>, -) { - info!("produce {this_loc} <~ {other_loc}"); - *score_changed = true; - if this_had_item { - packet_out.push_back(PacketC::SetItem { - location: this_loc, - item: None, - }); - } - if other_had_item { - packet_out.push_back(PacketC::MoveItem { - from: other_loc, - to: this_loc, - }); - packet_out.push_back(PacketC::SetItem { - location: this_loc, - item: None, - }); - } - if let Some(i) = &other { - packet_out.push_back(PacketC::SetItem { - location: this_loc, - item: Some(i.kind), - }); - packet_out.push_back(PacketC::MoveItem { - from: this_loc, - to: other_loc, - }) - } - if let Some(i) = &this { - packet_out.push_back(PacketC::SetItem { - location: this_loc, - item: Some(i.kind), - }); - } -} diff --git a/server/src/lib.rs b/server/src/lib.rs index 260221da..0f591851 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -18,7 +18,6 @@ #![feature(if_let_guard, iterator_try_collect, stmt_expr_attributes, random)] pub mod commands; pub mod entity; -pub mod interaction; pub mod network; pub mod scoreboard; pub mod server; diff --git a/server/src/server.rs b/server/src/server.rs index 7ded8eb7..45f31e0b 100644 --- a/server/src/server.rs +++ b/server/src/server.rs @@ -18,13 +18,12 @@ use crate::{ ConnectionID, entity::{Entities, EntityContext, construct_entity}, - interaction::{interact, tick_slot}, random_float, scoreboard::ScoreboardStore, }; use anyhow::{Context, Result}; -use hurrycurry_game_core::{Game, Involvement, Item, Player, Tile}; use hurrycurry_data::{Serverdata, index::DataIndex}; +use hurrycurry_game_core::{Game, Involvement, Item, Player, Tile}; use hurrycurry_locale::{ FALLBACK_LOCALE, TrError, message::{COLORED, MessageDisplayExt}, @@ -546,83 +545,9 @@ impl Server { return Err(tre!("s.error.interacting_too_far")); } - // No going back from here on - player.interacting = if edge { Some((loc, hand)) } else { None }; - - match loc { - ItemLocation::Tile(pos) => { - let player = self - .game - .players - .get_mut(&pid) - .ok_or(tre!("s.error.no_player"))?; - - let hslot = player - .items - .get_mut(hand.0) - .ok_or(tre!("s.error.no_hand"))?; - - let tile = self - .game - .tiles - .get_mut(&pos) - .ok_or(tre!("s.error.no_tile"))?; - - interact( - &self.game.data, - edge, - Some(tile.kind), - Some(pid), - &mut tile.item, - ItemLocation::Tile(pos), - hslot, - ItemLocation::Player(pid, hand), - &mut self.game.score, - &mut self.score_changed, - false, - &mut self.packet_out, - ) - } - ItemLocation::Player(other_pid, other_hand) => { - if pid == other_pid { - return Err(tre!("s.error.self_interact")); - } - let [Some(other), Some(this)] = - self.game.players.get_disjoint_mut([&pid, &other_pid]) - else { - return Err(tre!("s.error.no_player")); - }; - - if this.class == PlayerClass::Customer - || other.class == PlayerClass::Customer - { - return Err(tre!("s.error.customer_interact")); - } - - let this_hslot = - this.items.get_mut(hand.0).ok_or(tre!("s.error.no_hand"))?; - let other_hslot = other - .items - .get_mut(other_hand.0) - .ok_or(tre!("s.error.no_hand"))?; - - interact( - &self.game.data, - edge, - None, - Some(pid), - this_hslot, - ItemLocation::Player(other_pid, hand), - other_hslot, - ItemLocation::Player(pid, hand), - &mut self.game.score, - &mut self.score_changed, - false, - &mut self.packet_out, - ) - } - } + self.game + .interact(loc, ItemLocation::Player(pid, hand), edge)?; } PacketS::Communicate { message, @@ -695,18 +620,10 @@ impl Server { .push_back(PacketC::Score(self.game.score.clone())); } - for (&pos, tile) in &mut self.game.tiles { - tick_slot( - dt, - &self.game.data, - &self.game.data_index, - Some(tile.kind), - &mut tile.item, - ItemLocation::Tile(pos), - &mut self.game.score, - &mut self.score_changed, - &mut self.packet_out, - ); + for loc in self.game.item_locations_index.clone() { + if let Err(e) = self.game.tick_slot(loc, dt) { + warn!("Slot tick failed: {}", e.to_string()); + } } for (&pid, player) in &mut self.game.players { @@ -737,20 +654,6 @@ impl Server { boost: player.movement.boosting, rot: player.movement.rotation, }); - - for (i, item) in player.items.iter_mut().enumerate() { - tick_slot( - dt, - &self.game.data, - &self.game.data_index, - None, - item, - ItemLocation::Player(pid, Hand(i)), - &mut self.game.score, - &mut self.score_changed, - &mut self.packet_out, - ); - } } let mut players_auto_release = Vec::new(); |