From c10f6cfb826b123a208b597682f9ef24d592f22c Mon Sep 17 00:00:00 2001 From: Michael Bradley Date: Sat, 5 Jul 2025 15:01:33 -0400 Subject: [PATCH] Rework networking interface Add Bevy event queues for inbound and outbound packets, and use Bevy change detection for consumer new Peer handling. --- Cargo.lock | 5 +- Cargo.toml | 1 + src/game/mod.rs | 1 + src/game/net.rs | 39 +++++++++++++ src/game/plugin.rs | 13 ++++- src/net/io.rs | 118 +++++++++++++++++++++++++++++++++++++++ src/net/mod.rs | 10 +++- src/net/peer.rs | 134 +++++++++++++++++++++++++++++++++++++++++++++ src/net/plugin.rs | 99 +++++++++++---------------------- 9 files changed, 348 insertions(+), 72 deletions(-) create mode 100644 src/game/net.rs create mode 100644 src/net/io.rs create mode 100644 src/net/peer.rs diff --git a/Cargo.lock b/Cargo.lock index 9a74300..90ccc97 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1924,6 +1924,7 @@ dependencies = [ "crossbeam-channel", "log", "rand 0.9.1", + "uuid", "wyrand", ] @@ -4479,9 +4480,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" dependencies = [ "getrandom 0.3.3", "js-sys", diff --git a/Cargo.toml b/Cargo.toml index 7fcd521..a48d89a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,7 @@ rand = { version = "0.9.1", default-features = false, features = [ "std", "thread_rng", ] } +uuid = { version = "1.17.0", features = ["v4"] } wyrand = "0.3.2" [features] diff --git a/src/game/mod.rs b/src/game/mod.rs index 30eff06..02dda3b 100644 --- a/src/game/mod.rs +++ b/src/game/mod.rs @@ -1,3 +1,4 @@ +mod net; mod objects; mod plugin; mod rng; diff --git a/src/game/net.rs b/src/game/net.rs new file mode 100644 index 0000000..2cde3b5 --- /dev/null +++ b/src/game/net.rs @@ -0,0 +1,39 @@ +use bevy::prelude::*; + +use crate::net::prelude::*; + +use super::seed::Seed; + +pub fn handle_new_peer( + seed: Option>, + new_peers: Query<&Peer, Added>, + mut outbound: EventWriter, +) { + if let Some(seed) = seed { + for peer in new_peers { + warn!("Sending seed to peer: {}", peer.uuid); + outbound.write(OutboundPacket(Packet::new((*seed).into(), peer.uuid))); + } + } +} + +pub fn handle_deleted_peer(mut old_peers: RemovedComponents, peers: Query<&Peer>) -> Result { + for entity in old_peers.read() { + if let Ok(peer) = peers.get(entity) { + info!("Peer {} was removed", peer.uuid); + } else { + info!("Peer {} was removed", entity); + } + } + Ok(()) +} + +pub fn handle_incoming_packets(mut packets: EventReader, mut commands: Commands) { + for packet in packets.read() { + if let Ok(seed) = packet.0.message.clone().try_into() { + commands.insert_resource::(seed); + } else { + info!("Packet not seed: {:?}", packet.0.message); + } + } +} diff --git a/src/game/plugin.rs b/src/game/plugin.rs index ec35bef..27242d6 100644 --- a/src/game/plugin.rs +++ b/src/game/plugin.rs @@ -3,9 +3,10 @@ use std::net::SocketAddr; use avian2d::PhysicsPlugins; use bevy::{input::common_conditions::input_pressed, prelude::*}; -use crate::net::NetIOPlugin; +use crate::net::prelude::*; use super::{ + net::{handle_deleted_peer, handle_incoming_packets, handle_new_peer}, runtime::{move_camera, move_player, quit, zoom_camera}, seed::Seed, setup::{check_for_seed, setup_balls, setup_from_seed, setup_player, setup_ui, setup_walls}, @@ -65,7 +66,15 @@ impl Plugin for GamePlugin { ) .add_systems( FixedUpdate, - check_for_seed.run_if(in_state(AppState::Loading)), + ( + check_for_seed.run_if(in_state(AppState::Loading)), + ( + handle_new_peer, + handle_deleted_peer, + handle_incoming_packets, + ) + .run_if(in_state(NetworkState::MultiPlayer)), + ), ) .add_systems( Update, diff --git a/src/net/io.rs b/src/net/io.rs new file mode 100644 index 0000000..6d6759b --- /dev/null +++ b/src/net/io.rs @@ -0,0 +1,118 @@ +use std::time::Duration; + +use bevy::prelude::*; +use uuid::Uuid; + +use super::{ + peer::{Peer, PeerChangeEvent, PeerMap, PeerReceiveTiming, PeerSendTiming}, + queues::{NetworkReceive, NetworkSend}, +}; + +pub fn handle_network_input( + from_socket: Res, + peer_map: Res, + mut peers: Query<(&Peer, &mut PeerReceiveTiming)>, + mut to_app: EventWriter, + time: Res