Don't immediately send heartbeat
All checks were successful
CI / Formatting (push) Successful in 1m11s

This commit is contained in:
Michael Bradley 2025-07-05 18:09:46 -04:00
parent 591cfee715
commit e58629c2f1
Signed by: MichaelBradley
SSH key fingerprint: SHA256:o/aaeYtRubILK7OYYjYP12DmU7BsPUhKji1AgaQ+ge4
5 changed files with 50 additions and 46 deletions

View file

@ -4,6 +4,7 @@ use bevy::prelude::*;
use uuid::Uuid; use uuid::Uuid;
use super::{ use super::{
packet::{InboundPacket, OutboundPacket, Packet},
peer::{Peer, PeerChangeEvent, PeerMap, PeerReceiveTiming, PeerSendTiming}, peer::{Peer, PeerChangeEvent, PeerMap, PeerReceiveTiming, PeerSendTiming},
queues::{NetworkReceive, NetworkSend}, queues::{NetworkReceive, NetworkSend},
}; };
@ -65,12 +66,10 @@ pub fn heartbeat(
mut outbound: EventWriter<OutboundPacket>, mut outbound: EventWriter<OutboundPacket>,
) { ) {
for (peer, last) in peers { for (peer, last) in peers {
if let Some(previous) = last.timestamp() {
// Allow for 2 consecutive missed heartbeats without timing out // Allow for 2 consecutive missed heartbeats without timing out
if previous + TIMEOUT / 3 > time.elapsed() { if last.time() + TIMEOUT / 3 > time.elapsed() {
continue; continue;
} }
}
outbound.write(OutboundPacket(Packet::new(Vec::new(), peer.uuid))); outbound.write(OutboundPacket(Packet::new(Vec::new(), peer.uuid)));
} }
} }
@ -81,7 +80,7 @@ pub fn timeouts(
mut delete: EventWriter<PeerChangeEvent>, mut delete: EventWriter<PeerChangeEvent>,
) { ) {
for (peer, last) in peers { for (peer, last) in peers {
if let Some(previous) = last.timestamp() { if let Some(previous) = last.time() {
if previous + TIMEOUT < time.elapsed() { if previous + TIMEOUT < time.elapsed() {
warn!("Peer {} timed out", peer.uuid); warn!("Peer {} timed out", peer.uuid);
delete.write(PeerChangeEvent::new(peer.uuid, None)); delete.write(PeerChangeEvent::new(peer.uuid, None));
@ -100,21 +99,3 @@ impl Config {
Self { id: Uuid::new_v4() } Self { id: Uuid::new_v4() }
} }
} }
#[derive(Debug)]
pub struct Packet {
pub message: Vec<u8>,
pub peer: Uuid,
}
impl Packet {
pub fn new(message: Vec<u8>, peer: Uuid) -> Self {
Self { peer, message }
}
}
#[derive(Debug, Event)]
pub struct OutboundPacket(pub Packet);
#[derive(Debug, Event)]
pub struct InboundPacket(pub Packet);

View file

@ -1,4 +1,5 @@
mod io; mod io;
mod packet;
mod peer; mod peer;
mod plugin; mod plugin;
mod queues; mod queues;
@ -7,7 +8,7 @@ mod thread;
#[allow(unused_imports)] #[allow(unused_imports)]
pub mod prelude { pub mod prelude {
pub use super::io::{InboundPacket, OutboundPacket, Packet}; pub use super::packet::{InboundPacket, OutboundPacket, Packet};
pub use super::peer::Peer; pub use super::peer::Peer;
pub use super::plugin::{NetIOPlugin, NetworkState}; pub use super::plugin::{NetIOPlugin, NetworkState};
} }

20
src/net/packet.rs Normal file
View file

@ -0,0 +1,20 @@
use bevy::prelude::*;
use uuid::Uuid;
#[derive(Debug)]
pub struct Packet {
pub message: Vec<u8>,
pub peer: Uuid,
}
impl Packet {
pub fn new(message: Vec<u8>, peer: Uuid) -> Self {
Self { peer, message }
}
}
#[derive(Debug, Event)]
pub struct OutboundPacket(pub Packet);
#[derive(Debug, Event)]
pub struct InboundPacket(pub Packet);

View file

@ -3,40 +3,35 @@ use std::{collections::HashMap, net::SocketAddr, time::Duration};
use bevy::prelude::*; use bevy::prelude::*;
use uuid::Uuid; use uuid::Uuid;
#[derive(Debug, Default)] use super::packet::{OutboundPacket, Packet};
struct Timing {
timestamp: Option<Duration>,
}
#[derive(Component, Debug, Default)] #[derive(Component, Debug, Default)]
pub struct PeerSendTiming(Timing); pub struct PeerSendTiming(Duration);
impl PeerSendTiming { impl PeerSendTiming {
pub fn update(&mut self, time: &Res<Time>) { pub fn update(&mut self, time: &Res<Time>) {
self.0.timestamp = Some(time.elapsed()) self.0 = time.elapsed()
} }
pub fn timestamp(&self) -> Option<Duration> { pub fn time(&self) -> Duration {
self.0.timestamp self.0
} }
} }
#[derive(Component, Debug, Default)] #[derive(Component, Debug, Default)]
pub struct PeerReceiveTiming(Timing); pub struct PeerReceiveTiming(Option<Duration>);
impl PeerReceiveTiming { impl PeerReceiveTiming {
pub fn new(time: &Res<Time>) -> Self { pub fn new(time: &Res<Time>) -> Self {
Self(Timing { Self(Some(time.elapsed()))
timestamp: Some(time.elapsed()),
})
} }
pub fn update(&mut self, time: &Res<Time>) { pub fn update(&mut self, time: &Res<Time>) {
self.0.timestamp = Some(time.elapsed()) self.0 = Some(time.elapsed())
} }
pub fn timestamp(&self) -> Option<Duration> { pub fn time(&self) -> Option<Duration> {
self.0.timestamp self.0
} }
} }
@ -130,3 +125,12 @@ pub fn handle_peer_change(
} }
Ok(()) Ok(())
} }
pub fn handle_new_peer(
new_peers: Query<&Peer, Added<Peer>>,
mut outbound: EventWriter<OutboundPacket>,
) {
for peer in new_peers {
outbound.write(OutboundPacket(Packet::new(Vec::new(), peer.uuid)));
}
}

View file

@ -4,11 +4,9 @@ use bevy::prelude::*;
use uuid::Uuid; use uuid::Uuid;
use super::{ use super::{
io::{ io::{Config, handle_network_input, handle_network_output, heartbeat, timeouts},
Config, InboundPacket, OutboundPacket, handle_network_input, handle_network_output, packet::{InboundPacket, OutboundPacket},
heartbeat, timeouts, peer::{Peer, PeerChangeEvent, PeerMap, handle_new_peer, handle_peer_change},
},
peer::{Peer, PeerChangeEvent, PeerMap, handle_peer_change},
queues::{NetworkReceive, NetworkSend}, queues::{NetworkReceive, NetworkSend},
socket::bind_socket, socket::bind_socket,
}; };
@ -42,7 +40,7 @@ impl Plugin for NetIOPlugin {
) )
.add_systems( .add_systems(
FixedUpdate, FixedUpdate,
(heartbeat, timeouts).run_if(in_state(NetworkState::MultiPlayer)), (heartbeat, timeouts, handle_new_peer).run_if(in_state(NetworkState::MultiPlayer)),
) )
.add_systems( .add_systems(
FixedPostUpdate, FixedPostUpdate,