···1919- [x] Meta : Recipes for type binding generation
2020- [x] Signaling: All of it
2121- [x] Backend : Better transport error handling
2222-- [ ] Backend : Abstract lobby? Separate crate?
2222+- [x] Backend : Abstract lobby? Separate crate?
2323- [x] Transport : Handle transport cancellation better
2424- [x] Backend : Add checks for when the `powerup_locations` field is an empty array in settings
2525- [ ] Backend : More tests
+5-11
backend/Cargo.toml
···2222tauri-plugin-opener = "2"
2323serde = { version = "1", features = ["derive"] }
2424serde_json = "1"
2525-chrono = { version = "0.4", features = ["serde", "now"] }
2625tokio = { version = "1.45", features = ["sync", "macros", "time", "fs"] }
2727-rand = { version = "0.9", features = ["thread_rng"] }
2826tauri-plugin-geolocation = "2"
2929-rand_chacha = "0.9.0"
3030-futures = "0.3.31"
3131-matchbox_socket = "0.12.0"
3232-uuid = { version = "1.17.0", features = ["serde", "v4"] }
3333-rmp-serde = "1.3.0"
3427tauri-plugin-store = "2.2.0"
3535-specta = { version = "=2.0.0-rc.22", features = ["chrono", "uuid"] }
2828+specta = { version = "=2.0.0-rc.22", features = ["chrono", "uuid", "export"] }
3629tauri-specta = { version = "=2.0.0-rc.21", features = ["derive", "typescript"] }
3730specta-typescript = "0.0.9"
3831tauri-plugin-log = "2"
3932tauri-plugin-notification = "2"
4033log = "0.4.27"
4141-tokio-util = "0.7.15"
4234anyhow = "1.0.98"
4343-reqwest = { version = "0.12.20", default-features = false, features = ["charset", "http2", "rustls-tls", "system-proxy"] }
4444-const-str = "0.6.2"
4535tauri-plugin-dialog = "2"
3636+manhunt-logic = { version = "0.1.0", path = "../manhunt-logic" }
3737+manhunt-transport = { version = "0.1.0", path = "../manhunt-transport" }
3838+uuid = { version = "1.17.0", features = ["serde"] }
3939+chrono = { version = "0.4.41", features = ["serde"] }
···11use serde::{Deserialize, Serialize};
2233-use super::{location::Location, state::PlayerPing, Id, UtcDT};
33+use crate::{
44+ game::{Id, UtcDT},
55+ game_state::PlayerPing,
66+ location::Location,
77+};
4859/// An event used between players to update state
610#[derive(Debug, Clone, Serialize, Deserialize, specta::Type)]
···1721 /// Contains location history of the given player, used after the game to sync location
1822 /// histories
1923 PostGameSync(Id, Vec<(UtcDT, Location)>),
2020- /// A player has been disconnected and removed from the game (because of error or otherwise).
2121- /// The player should be removed from all state
2222- DroppedPlayer(Id),
2323- /// The underlying transport has disconnected
2424- TransportDisconnect,
2525- /// The underlying transport encountered an error
2626- TransportError(String),
2724}
···11+use std::sync::Arc;
22+33+use super::{game_events::GameEvent, lobby::LobbyMessage};
44+use serde::{Deserialize, Serialize};
55+use uuid::Uuid;
66+77+#[derive(Debug, Serialize, Deserialize, Clone)]
88+pub enum TransportMessage {
99+ /// Message related to the actual game
1010+ /// Boxed for space reasons
1111+ Game(Box<GameEvent>),
1212+ /// Message related to the pre-game lobby
1313+ Lobby(Box<LobbyMessage>),
1414+ /// Internal message when peer connects
1515+ PeerConnect(Uuid),
1616+ /// Internal message when peer disconnects
1717+ PeerDisconnect(Uuid),
1818+ /// Event sent when the transport gets disconnected, used to help consumers know when to stop
1919+ /// consuming messages. Note this should represent a success state, the disconnect was
2020+ /// triggered by user action.
2121+ Disconnected,
2222+ /// Event when the transport encounters a critical error and needs to disconnect.
2323+ Error(String),
2424+}
2525+2626+impl From<GameEvent> for TransportMessage {
2727+ fn from(v: GameEvent) -> Self {
2828+ Self::Game(Box::new(v))
2929+ }
3030+}
3131+3232+impl From<LobbyMessage> for TransportMessage {
3333+ fn from(v: LobbyMessage) -> Self {
3434+ Self::Lobby(Box::new(v))
3535+ }
3636+}
3737+3838+pub type MsgPair = (Option<Uuid>, TransportMessage);
3939+4040+pub trait Transport: Send + Sync {
4141+ /// Start the transport loop, This is expected to spawn a new job that will loop until
4242+ /// cancelled or an error occurs.
4343+ fn initialize(
4444+ code: &str,
4545+ host: bool,
4646+ ) -> impl std::future::Future<Output = Result<Arc<Self>, anyhow::Error>> + Send;
4747+ /// Get the local user's ID
4848+ fn self_id(&self) -> Uuid;
4949+ /// Check if a room is open to join, non-host players will call this with a code
5050+ fn room_joinable(&self, _code: &str) -> impl std::future::Future<Output = bool> + Send {
5151+ async { true }
5252+ }
5353+ /// Request a room be marked unjoinable (due to a game starting), the host user will call this.
5454+ fn mark_room_started(&self, _code: &str) -> impl Future<Output = ()> {
5555+ async {}
5656+ }
5757+ /// Receive an event
5858+ fn receive_messages(&self) -> impl Future<Output = impl Iterator<Item = MsgPair>>;
5959+ /// Send a message to a specific peer
6060+ fn send_message_single(&self, peer: Uuid, msg: TransportMessage) -> impl Future<Output = ()>;
6161+ /// Send a message to all other peers
6262+ fn send_message(&self, msg: TransportMessage) -> impl Future<Output = ()>;
6363+ /// Send a message to the local user
6464+ fn send_self(&self, msg: TransportMessage) -> impl Future<Output = ()>;
6565+ /// Disconnect from the transport
6666+ fn disconnect(&self) -> impl Future<Output = ()> {
6767+ async {}
6868+ }
6969+}
+20
manhunt-transport/Cargo.toml
···11+[package]
22+name = "manhunt-transport"
33+version = "0.1.0"
44+edition = "2024"
55+66+[dependencies]
77+anyhow = "1.0.98"
88+futures = "0.3.31"
99+log = "0.4.27"
1010+matchbox_protocol = "0.12.0"
1111+matchbox_socket = "0.12.0"
1212+rmp-serde = "1.3.0"
1313+serde = { version = "1.0.219", features = ["derive"] }
1414+tokio = { version = "1.45.1", features = ["macros", "sync", "time", "rt"] }
1515+tokio-util = "0.7.15"
1616+uuid = { version = "1.17.0", features = ["serde"] }
1717+manhunt-logic = { version = "0.1.0", path = "../manhunt-logic" }
1818+rand = { version = "0.9.1", features = ["thread_rng"] }
1919+reqwest = { version = "0.12.20", default-features = false, features = ["charset", "http2", "rustls-tls", "system-proxy"] }
2020+const-str = "0.6.2"
+6
manhunt-transport/src/lib.rs
···11+mod matchbox;
22+mod packets;
33+mod server;
44+55+pub use matchbox::MatchboxTransport;
66+pub use server::{generate_join_code, room_exists};