aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/multiplayer.gd5
-rw-r--r--server/protocol/src/lib.rs5
-rw-r--r--server/src/customer/mod.rs10
-rw-r--r--server/src/game.rs47
-rw-r--r--server/src/main.rs11
-rw-r--r--server/src/state.rs8
-rw-r--r--test-client/main.ts2
-rw-r--r--test-client/protocol.ts2
8 files changed, 60 insertions, 30 deletions
diff --git a/client/multiplayer.gd b/client/multiplayer.gd
index cdb6d97c..19cb5e8c 100644
--- a/client/multiplayer.gd
+++ b/client/multiplayer.gd
@@ -81,7 +81,7 @@ func _process(_delta):
var code = socket.get_close_code()
var reason = socket.get_close_reason()
connection_closed.emit(
- "WebSocket closed with code: %d, reason %s. Clean: %s" % [code, reason, code != -1]
+ "WebSocket closed with code: %d, reason %s. Clean: %s" % [code, reason, code != - 1]
)
self.queue_free()
@@ -266,8 +266,7 @@ func send_position(pos: Vector2, rotation: float, boosting: bool):
func send_tile_interact(pos: Vector2i, edge: bool):
send_packet({
"type": "interact",
- "pos": [pos.x, pos.y],
- "edge": edge
+ "pos": [pos.x, pos.y] if edge else null,
})
func set_player_interact(_player: int, _edge: bool):
diff --git a/server/protocol/src/lib.rs b/server/protocol/src/lib.rs
index 36a496a0..9c8d6bee 100644
--- a/server/protocol/src/lib.rs
+++ b/server/protocol/src/lib.rs
@@ -62,8 +62,7 @@ pub enum PacketS {
boosting: bool,
},
Interact {
- pos: IVec2,
- edge: bool,
+ pos: Option<IVec2>,
},
Collide {
player: PlayerID,
@@ -165,7 +164,7 @@ pub enum PacketC {
ReplayStart,
}
-#[derive(Debug, Clone, Serialize, Deserialize, Copy)]
+#[derive(Debug, Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Hash)]
#[serde(rename_all = "snake_case")]
pub enum ItemLocation {
Tile(IVec2),
diff --git a/server/src/customer/mod.rs b/server/src/customer/mod.rs
index 10788206..ba57542c 100644
--- a/server/src/customer/mod.rs
+++ b/server/src/customer/mod.rs
@@ -220,9 +220,8 @@ impl DemandState {
persist: false,
},
));
- for edge in [true, false] {
- packets_out.push((id, PacketS::Interact { pos, edge }))
- }
+ packets_out.push((id, PacketS::Interact { pos: Some(pos) }));
+ packets_out.push((id, PacketS::Interact { pos: None }));
p.state = CustomerState::Eating {
demand: *demand,
target: pos,
@@ -244,9 +243,8 @@ impl DemandState {
if *progress >= 1. {
packets_out.push((id, PacketS::ReplaceHand { item: demand.to }));
if demand.to.is_some() {
- for edge in [true, false] {
- packets_out.push((id, PacketS::Interact { pos: *target, edge }))
- }
+ packets_out.push((id, PacketS::Interact { pos: Some(*target) }));
+ packets_out.push((id, PacketS::Interact { pos: None }));
}
let path = find_path(
&self.walkable,
diff --git a/server/src/game.rs b/server/src/game.rs
index 3eb6e5a6..908c0b4e 100644
--- a/server/src/game.rs
+++ b/server/src/game.rs
@@ -325,29 +325,34 @@ impl Game {
self.packet_out
.push_back(PacketC::Collide { player, force });
}
- PacketS::Interact { pos, edge } => {
- info!("interact {pos:?} edge={edge}");
+ PacketS::Interact { pos } => {
+ info!("interact {pos:?}");
let pid = player;
let player = self
.players
.get_mut(&pid)
.ok_or(anyhow!("player does not exist"))?;
- let tile = self
- .tiles
- .get_mut(&pos)
- .ok_or(anyhow!("tile does not exist"))?;
- if edge && player.interacting.is_some() {
- bail!("already interacting")
- }
- if !edge && player.interacting != Some(pos) {
- bail!("already not interacting here")
- }
+ let (pos, edge) = match (pos, player.interacting) {
+ (None, None) => return Ok(()), // this is silent because of auto release
+ (None, Some(pos)) => (pos, false),
+ (Some(pos), None) => (pos, true),
+ (Some(_), Some(_)) => bail!("already interacting"),
+ };
+
let entpos = pos.as_vec2() + Vec2::splat(0.5);
if edge && entpos.distance(player.position) > 2. {
bail!("interacting too far from player");
}
+
+ let tile = self
+ .tiles
+ .get_mut(&pos)
+ .ok_or(anyhow!("tile does not exist"))?;
+
+ // No going back from here on
+
player.interacting = if edge { Some(pos) } else { None };
let other_pid = if !self.data.is_tile_interactable(tile.kind) {
@@ -509,6 +514,24 @@ impl Game {
}
}
+ let mut players_auto_release = Vec::new();
+ for (pid, player) in &mut self.players {
+ if let Some(pos) = player.interacting {
+ if let Some(tile) = self.tiles.get(&pos) {
+ if let Some(item) = &tile.item {
+ if let Some(involvement) = &item.active {
+ if involvement.progress >= 1. {
+ players_auto_release.push(*pid);
+ }
+ }
+ }
+ }
+ }
+ }
+ for pid in players_auto_release.drain(..) {
+ let _ = self.packet_in(pid, PacketS::Interact { pos: None });
+ }
+
for entity in &mut self.entities {
if let Err(e) = entity.tick(
&self.data,
diff --git a/server/src/main.rs b/server/src/main.rs
index 27f81fbb..6ef34e45 100644
--- a/server/src/main.rs
+++ b/server/src/main.rs
@@ -20,7 +20,7 @@ use clap::Parser;
use futures_util::{SinkExt, StreamExt};
use hurrycurry_protocol::{PacketC, PacketS, PlayerID};
use hurrycurry_server::{data::DATA_DIR, state::State};
-use log::{debug, info, warn, LevelFilter};
+use log::{debug, info, trace, warn, LevelFilter};
use std::{path::PathBuf, process::exit, str::FromStr, sync::Arc, time::Duration};
use tokio::{
net::TcpListener,
@@ -156,7 +156,14 @@ async fn run() -> anyhow::Result<()> {
break;
}
};
- debug!("<- {id:?} {packet:?}");
+ if matches!(
+ packet,
+ PacketS::Position { .. } | PacketS::ReplayTick { .. }
+ ) {
+ trace!("<- {id:?} {packet:?}");
+ } else {
+ debug!("<- {id:?} {packet:?}");
+ }
let packet_out = match state.write().await.packet_in(id, packet).await {
Ok(packets) => packets,
Err(e) => {
diff --git a/server/src/state.rs b/server/src/state.rs
index 5af6f181..b496040b 100644
--- a/server/src/state.rs
+++ b/server/src/state.rs
@@ -21,7 +21,7 @@ use crate::{data::DataIndex, game::Game};
use anyhow::{anyhow, bail, Result};
use clap::{Parser, ValueEnum};
use hurrycurry_protocol::{Message, PacketC, PacketS, PlayerID};
-use log::debug;
+use log::{debug, trace};
use tokio::sync::broadcast::Sender;
pub struct State {
@@ -91,7 +91,11 @@ impl State {
);
}
while let Some(p) = self.game.packet_out() {
- debug!("-> {p:?}");
+ if matches!(p, PacketC::UpdateMap { .. } | PacketC::Position { .. }) {
+ trace!("-> {p:?}");
+ } else {
+ debug!("-> {p:?}");
+ }
let _ = self.tx.send(p);
}
Ok(())
diff --git a/test-client/main.ts b/test-client/main.ts
index 2987af54..f295e0ca 100644
--- a/test-client/main.ts
+++ b/test-client/main.ts
@@ -284,7 +284,7 @@ export function get_interact_target(): V2 | undefined {
function set_interact(edge: boolean) {
if (edge) interacting = get_interact_target()
- if (interacting) send({ type: "interact", pos: [interacting.x, interacting.y], edge })
+ if (interacting) send({ type: "interact", pos: edge ? [interacting.x, interacting.y] : undefined })
if (!edge) interacting = undefined
}
diff --git a/test-client/protocol.ts b/test-client/protocol.ts
index 34efe602..ddbc43c8 100644
--- a/test-client/protocol.ts
+++ b/test-client/protocol.ts
@@ -33,7 +33,7 @@ export type PacketS =
{ type: "join", name: string, character: number } // Spawns your character. Dont send it to spectate.
| { type: "leave" } // Despawns your character
| { type: "position", pos: Vec2, rot: number, boosting: boolean } // Update your position and rotation in radians (0 is -y)
- | { type: "interact", pos: Vec2, edge: boolean } // Interact with some tile. edge is true when pressing and false when releasing interact button
+ | { type: "interact", pos?: Vec2 } // Interact with some tile. pos is a position when pressing and null when releasing interact button
| { type: "communicate", message?: Message, persist: boolean } // Send a message
| { type: "collide", player: PlayerID, force: Vec2 } // Apply force to another player as a result of a collision