summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-07-02 14:57:22 +0200
committermetamuffin <metamuffin@disroot.org>2024-07-02 14:57:22 +0200
commitf15d6305a7f70e34ba1e5484d4f185d844cc3aaa (patch)
treedff0fd75749312084ab6210435af35132687bce6
parent9cffa5019b017045b7dbdf6577c89b70b8a11a50 (diff)
downloadhurrycurry-f15d6305a7f70e34ba1e5484d4f185d844cc3aaa.tar
hurrycurry-f15d6305a7f70e34ba1e5484d4f185d844cc3aaa.tar.bz2
hurrycurry-f15d6305a7f70e34ba1e5484d4f185d844cc3aaa.tar.zst
interaction between players
-rw-r--r--server/src/game.rs183
-rw-r--r--server/src/lib.rs2
-rw-r--r--server/src/protocol.rs2
3 files changed, 117 insertions, 70 deletions
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<PlayerID, Player>,
packet_out: VecDeque<PacketC>,
demand: Option<DemandState>,
- score_changed: bool,
pub points: i64,
end: Option<Instant>,
}
@@ -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();
+ 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
+ };
- 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
- }
- }
- }
+ 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"))?;
- player.interacting = if edge { Some(pos) } else { None };
+ 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<TileIndex> for Tile {
Self { kind, item: None }
}
}
+
+fn interact_effect(
+ data: &Gamedata,
+ edge: bool,
+ this: &mut Option<Item>,
+ this_loc: ItemLocation,
+ other: &mut Option<Item>,
+ other_loc: ItemLocation,
+ this_tile_kind: Option<TileIndex>,
+ packet_out: &mut VecDeque<PacketC>,
+ 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 <https://www.gnu.org/licenses/>.
*/
-#![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),