feat(call-to-play)!: coordinate game sessions across peers

Implement the launcher design as a production peer-to-peer feature. Call to
Play actions are immutable, validated events broadcast over the existing QUIC
control channel, deduplicated in a bounded in-memory history, and exchanged in
Hello/HelloAck so late joiners reconstruct current calls.

Add the Tauri bridge and modular launcher surfaces for play-now and scheduled
calls, check-in, readiness buffers, role-aware controls, chat, tickers, and
actual caller launch. A deterministic frontend reducer derives presentation
state from replicated history. Extend the JSONL peer harness with publish/list
commands and a three-peer live-delivery and late-join scenario.

This intentionally raises the only supported wire protocol from version 5 to
version 6; older builds are not supported. Document the transport architecture
and exclude generated peer-test state from Docker build contexts.

Test Plan:
- `just fmt` -- passed
- `just clippy` -- passed
- `just test` -- passed
- `just frontend-test` -- passed, 20 tests
- `just build` -- passed
- `just peer-cli-tests S2 S48` -- passed
- `git diff --cached --check` -- passed
This commit is contained in:
ddidderr committed 2026-07-21 22:30:11 +02:00
1 parent 8f151e38b4
commit 0f53bc4b78
31 files changed
+3032 -21

No files matched your search

+15
View File
@@ -12,6 +12,7 @@
// Module declarations
// =============================================================================
mod call_to_play;
mod config;
mod context;
mod download;
@@ -46,6 +47,7 @@ pub use config::{CHUNK_SIZE, MAX_RETRY_COUNT};
pub use error::PeerError;
pub use install::{UnpackFuture, Unpacker};
use lanspread_db::db::{Game, GameCatalog, GameFileDescription};
pub use lanspread_proto::{CallToPlayAction, CallToPlayEvent};
pub use migration::{MigrationReport, migrate_legacy_state};
pub use peer_db::{
MajorityValidationResult,
@@ -159,6 +161,8 @@ pub enum PeerEvent {
ActiveOperationsChanged {
active_operations: Vec<ActiveOperation>,
},
/// New or requested Call to Play events in replication order.
CallToPlayEvents(Vec<CallToPlayEvent>),
/// A required peer runtime component failed.
RuntimeFailed {
component: PeerRuntimeComponent,
@@ -259,6 +263,10 @@ pub enum PeerCommand {
GetPeerCount,
/// Connect directly to a peer address without waiting for mDNS discovery.
ConnectPeer(SocketAddr),
/// Publish one local Call to Play action to this peer and the LAN.
PublishCallToPlay(CallToPlayEvent),
/// Request the complete in-memory Call to Play history.
GetCallToPlayEvents,
}
/// Optional startup settings for non-GUI callers and tests.
@@ -489,6 +497,13 @@ async fn handle_peer_commands(
PeerCommand::ConnectPeer(addr) => {
handle_connect_peer_command(ctx, tx_notify_ui, addr).await;
}
PeerCommand::PublishCallToPlay(event) => {
call_to_play::publish(ctx, tx_notify_ui, event).await;
}
PeerCommand::GetCallToPlayEvents => {
let events = ctx.call_to_play.read().await.snapshot();
events::send(tx_notify_ui, PeerEvent::CallToPlayEvents(events));
}
}
}
}