diff options
| author | metamuffin <metamuffin@disroot.org> | 2025-10-19 00:38:09 +0200 |
|---|---|---|
| committer | metamuffin <metamuffin@disroot.org> | 2025-10-19 00:38:09 +0200 |
| commit | 62d918e5feeaf5b3add982a5baaffb201a1f2ece (patch) | |
| tree | b14a0fa01f9df692592bf5d16543f43b6eb933d6 /server/src/server.rs | |
| parent | 6b156bea343a0fd9a043dcfe7113986855a89aab (diff) | |
| download | hurrycurry-62d918e5feeaf5b3add982a5baaffb201a1f2ece.tar hurrycurry-62d918e5feeaf5b3add982a5baaffb201a1f2ece.tar.bz2 hurrycurry-62d918e5feeaf5b3add982a5baaffb201a1f2ece.tar.zst | |
Implement interaction with other players through id instead of tile pos
Diffstat (limited to 'server/src/server.rs')
| -rw-r--r-- | server/src/server.rs | 204 |
1 files changed, 112 insertions, 92 deletions
diff --git a/server/src/server.rs b/server/src/server.rs index 8675638b..954d9a2c 100644 --- a/server/src/server.rs +++ b/server/src/server.rs @@ -515,7 +515,11 @@ impl Server { } } } - PacketS::Interact { pos, player, hand } => { + PacketS::Interact { + target, + player, + hand, + } => { for e in &mut self.entities { if e.interact( EntityContext { @@ -529,7 +533,7 @@ impl Server { replies: Some(replies), dt: 0., }, - pos, + target, player, )? { return Ok(()); @@ -543,105 +547,113 @@ impl Server { .get_mut(&pid) .ok_or(tre!("s.error.no_player"))?; - let pos = pos.map(|p| (p, hand)); + let loc = target.map(|p| (p, hand)); - let ((pos, hand), edge) = match (pos, player.interacting) { + let ((loc, hand), edge) = match (loc, player.interacting) { (None, None) => return Ok(()), // this is silent because of auto release - (None, Some(pos)) => (pos, false), - (Some(pos), None) => (pos, true), + (None, Some(t)) => (t, false), + (Some(t), None) => (t, true), (Some(_), Some(_)) => return Err(tre!("s.error.already_interacting")), }; - let entpos = pos.as_vec2() + Vec2::splat(0.5); - if edge && entpos.distance(player.movement.position) > 2. { - return Err(tre!("s.error.interacting_too_far")); - } + let pos = match loc { + ItemLocation::Tile(pos) => pos.as_vec2() + Vec2::splat(0.5), + ItemLocation::Player(p, _) => { + self.game + .players + .get(&p) + .ok_or_else(|| tre!("s.error.no_player"))? + .movement + .position + } + }; - let tile = self + let player = self .game - .tiles - .get_mut(&pos) - .ok_or(tre!("s.error.no_tile"))?; + .players + .get_mut(&pid) + .ok_or(tre!("s.error.no_player"))?; + + if edge && pos.distance(player.movement.position) > 2. { + return Err(tre!("s.error.interacting_too_far")); + } // No going back from here on - player.interacting = if edge { Some((pos, hand)) } else { None }; + player.interacting = if edge { Some((loc, hand)) } else { None }; - // Dont try interacting with player it tile is interactable - let other_pid = if self - .game - .data - .tile_placeable_items - .get(&tile.kind) - // TODO check for hand item - .is_none_or(|p| p.is_empty()) - { - self.game - .players - .iter() - .find(|(id, p)| **id != pid && p.movement.position.distance(entpos) < 0.7) - .map(|(&id, _)| id) - } else { - None - }; + match loc { + ItemLocation::Tile(pos) => { + let player = self + .game + .players + .get_mut(&pid) + .ok_or(tre!("s.error.no_player"))?; - if let Some(base_pid) = other_pid { - if pid == base_pid { - return Err(tre!("s.error.self_interact")); - } - let [Some(other), Some(this)] = - self.game.players.get_disjoint_mut([&pid, &base_pid]) - else { - return Err(tre!("s.error.self_interact")); - }; + let hslot = player + .items + .get_mut(hand.0) + .ok_or(tre!("s.error.no_hand"))?; - if this.class == PlayerClass::Customer || other.class == PlayerClass::Customer { - return Err(tre!("s.error.customer_interact")); - } + let tile = self + .game + .tiles + .get_mut(&pos) + .ok_or(tre!("s.error.no_tile"))?; - let this_hslot = this.items.get_mut(hand.0).ok_or(tre!("s.error.no_hand"))?; - let other_hslot = other.items.get_mut(hand.0).ok_or(tre!("s.error.no_hand"))?; + 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")); + }; - interact( - &self.game.data, - edge, - None, - Some(pid), - this_hslot, - ItemLocation::Player(base_pid, hand), - other_hslot, - ItemLocation::Player(pid, hand), - &mut self.game.score, - &mut self.score_changed, - false, - &mut self.packet_out, - ) - } else { - let player = self - .game - .players - .get_mut(&pid) - .ok_or(tre!("s.error.no_player"))?; + if this.class == PlayerClass::Customer + || other.class == PlayerClass::Customer + { + return Err(tre!("s.error.customer_interact")); + } - let hslot = player - .items - .get_mut(hand.0) - .ok_or(tre!("s.error.no_hand"))?; + 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, - 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, - ) + 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, + ) + } } } PacketS::Communicate { @@ -781,20 +793,28 @@ impl Server { player.communicate_persist = None; } } - if let Some((pos, hand)) = player.interacting - && let Some(tile) = self.game.tiles.get(&pos) - && let Some(item) = &tile.item - && let Some(involvement) = &item.active - && involvement.position >= 1. - { - players_auto_release.push((*pid, hand)); + if let Some((loc, hand)) = player.interacting { + match loc { + ItemLocation::Tile(pos) => { + if let Some(tile) = self.game.tiles.get(&pos) + && let Some(item) = &tile.item + && let Some(involvement) = &item.active + && involvement.position >= 1. + { + players_auto_release.push((*pid, hand)); + } + } + ItemLocation::Player(_pid, _hand) => { + // TODO + } + } } } for (player, hand) in players_auto_release.drain(..) { let _ = self.packet_in( None, PacketS::Interact { - pos: None, + target: None, player, hand, }, |