aboutsummaryrefslogtreecommitdiff
path: root/server/src/server.rs
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-10-19 00:38:09 +0200
committermetamuffin <metamuffin@disroot.org>2025-10-19 00:38:09 +0200
commit62d918e5feeaf5b3add982a5baaffb201a1f2ece (patch)
treeb14a0fa01f9df692592bf5d16543f43b6eb933d6 /server/src/server.rs
parent6b156bea343a0fd9a043dcfe7113986855a89aab (diff)
downloadhurrycurry-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.rs204
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,
},