From f15d6305a7f70e34ba1e5484d4f185d844cc3aaa Mon Sep 17 00:00:00 2001 From: metamuffin Date: Tue, 2 Jul 2024 14:57:22 +0200 Subject: interaction between players --- server/src/game.rs | 185 +++++++++++++++++++++++++++++++------------------ server/src/lib.rs | 2 +- server/src/protocol.rs | 2 +- 3 files changed, 118 insertions(+), 71 deletions(-) (limited to 'server/src') diff --git a/server/src/game.rs b/server/src/game.rs index 711b66b5..838a71e4 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -67,7 +67,6 @@ pub struct Game { pub players: HashMap, packet_out: VecDeque, demand: Option, - score_changed: bool, pub points: i64, end: Option, } @@ -81,7 +80,6 @@ impl Game { tiles: Default::default(), demand: None, end: None, - score_changed: false, points: 0, } } @@ -219,6 +217,8 @@ impl Game { } } pub fn packet_in(&mut self, player: PlayerID, packet: PacketS) -> Result<()> { + let points_before = self.points; + match packet { PacketS::Join { name, character } => { let position = if player.0 < 0 { @@ -306,7 +306,7 @@ impl Game { let pid = player; let player = self .players - .get_mut(&player) + .get_mut(&pid) .ok_or(anyhow!("player does not exist"))?; let tile = self .tiles @@ -319,74 +319,55 @@ impl Game { if !edge && player.interacting != Some(pos) { bail!("already not interacting here") } - if edge && (pos.as_vec2() + Vec2::splat(0.5)).distance(player.position) > 2. { + let entpos = pos.as_vec2() + Vec2::splat(0.5); + if edge && entpos.distance(player.position) > 2. { bail!("interacting too far from player"); } + player.interacting = if edge { Some(pos) } else { None }; - let tile_had_item = tile.item.is_some(); - let player_had_item = player.item.is_some(); - - if let Some(effect) = interact( - &self.data, - edge, - Some(tile.kind), - &mut tile.item, - &mut player.item, - &mut self.points, - ) { - match effect { - InteractEffect::Put => self.packet_out.push_back(PacketC::MoveItem { - from: ItemLocation::Player(pid), - to: ItemLocation::Tile(pos), - }), - InteractEffect::Take => self.packet_out.push_back(PacketC::MoveItem { - from: ItemLocation::Tile(pos), - to: ItemLocation::Player(pid), - }), - InteractEffect::Produce => { - if tile_had_item { - self.packet_out.push_back(PacketC::SetProgress { - item: ItemLocation::Tile(pos), - progress: None, - warn: false, - }); - self.packet_out.push_back(PacketC::SetItem { - location: ItemLocation::Tile(pos), - item: None, - }); - } - if player_had_item { - self.packet_out.push_back(PacketC::MoveItem { - from: ItemLocation::Player(pid), - to: ItemLocation::Tile(pos), - }); - self.packet_out.push_back(PacketC::SetItem { - location: ItemLocation::Tile(pos), - item: None, - }); - } - if let Some(i) = &player.item { - self.packet_out.push_back(PacketC::SetItem { - location: ItemLocation::Tile(pos), - item: Some(i.kind), - }); - self.packet_out.push_back(PacketC::MoveItem { - from: ItemLocation::Tile(pos), - to: ItemLocation::Player(pid), - }) - } - if let Some(i) = &tile.item { - self.packet_out.push_back(PacketC::SetItem { - location: ItemLocation::Tile(pos), - item: Some(i.kind), - }); - } - self.score_changed = true - } - } - } + let other_pid = if !self.data.is_tile_interactable(tile.kind) { + self.players + .iter() + .find(|(id, p)| **id != pid && p.position.distance(entpos) < 0.7) + .map(|(&id, _)| id) + } else { + None + }; - player.interacting = if edge { Some(pos) } else { None }; + if let Some(base_pid) = other_pid { + let [other, this] = self + .players + .get_many_mut([&pid, &base_pid]) + .ok_or(anyhow!("interacting with yourself. this is impossible"))?; + interact_effect( + &self.data, + edge, + &mut this.item, + ItemLocation::Player(base_pid), + &mut other.item, + ItemLocation::Player(pid), + None, + &mut self.packet_out, + &mut self.points, + ) + } else { + let player = self + .players + .get_mut(&pid) + .ok_or(anyhow!("player does not exist"))?; + + interact_effect( + &self.data, + edge, + &mut tile.item, + ItemLocation::Tile(pos), + &mut player.item, + ItemLocation::Player(pid), + Some(tile.kind), + &mut self.packet_out, + &mut self.points, + ) + } } PacketS::Communicate { message, persist } => { info!("{player:?} message {message:?}"); @@ -417,8 +398,7 @@ impl Game { } } - if self.score_changed { - self.score_changed = false; + if self.points != points_before { self.packet_out.push_back(self.score()) } Ok(()) @@ -505,3 +485,70 @@ impl From for Tile { Self { kind, item: None } } } + +fn interact_effect( + data: &Gamedata, + edge: bool, + this: &mut Option, + this_loc: ItemLocation, + other: &mut Option, + other_loc: ItemLocation, + this_tile_kind: Option, + packet_out: &mut VecDeque, + points: &mut i64, +) { + let this_had_item = this.is_some(); + let other_had_item = other.is_some(); + + if let Some(effect) = interact(&data, edge, this_tile_kind, this, other, points) { + match effect { + InteractEffect::Put => packet_out.push_back(PacketC::MoveItem { + from: other_loc, + to: this_loc, + }), + InteractEffect::Take => packet_out.push_back(PacketC::MoveItem { + from: this_loc, + to: other_loc, + }), + InteractEffect::Produce => { + if this_had_item { + packet_out.push_back(PacketC::SetProgress { + item: this_loc, + progress: None, + warn: false, + }); + 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 466defb4..b8929bd6 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -15,7 +15,7 @@ along with this program. If not, see . */ -#![feature(if_let_guard)] +#![feature(if_let_guard, map_many_mut, let_chains)] pub mod customer; pub mod data; pub mod game; diff --git a/server/src/protocol.rs b/server/src/protocol.rs index 54992feb..58182917 100644 --- a/server/src/protocol.rs +++ b/server/src/protocol.rs @@ -143,7 +143,7 @@ pub enum PacketC { }, } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Copy)] #[serde(rename_all = "snake_case")] pub enum ItemLocation { Tile(IVec2), -- cgit v1.2.3-70-g09d2