Add very rough heartbeat
All checks were successful
CI / Formatting (push) Successful in 1m0s

This also means that the peer can be started up before the main game
This commit is contained in:
Michael Bradley 2025-07-01 14:43:47 -04:00
parent 293ccf9370
commit cceca83dac
Signed by: MichaelBradley
SSH key fingerprint: SHA256:BKO2eI2LPsCbQS3n3i5SdwZTAIV3F1lHezR07qP+Ob0

View file

@ -1,21 +1,21 @@
use std::net::SocketAddr;
use std::{net::SocketAddr, time::Duration};
use bevy::prelude::*;
use crate::game::prelude::Seed;
use super::{
queues::{NetworkReceive, NetworkSend},
socket::bind_socket,
};
use crate::game::prelude::Seed;
fn handle_network_io(
fn handle_network_input(
receive: Res<NetworkReceive>,
send: Res<NetworkSend>,
seed: Option<Res<Seed>>,
mut commands: Commands,
) -> Result {
for (message, address) in receive.iter() {
// Temporary logic just for initial connection, if there is already a seed then the peer wants it
if let Some(ref value) = seed {
send.send((**value).into(), address)?;
} else {
@ -26,6 +26,25 @@ fn handle_network_io(
Ok(())
}
const TIMEOUT: Duration = Duration::from_secs(5);
fn heartbeat(
peers: Query<(&Peer, &mut PeerSendTiming)>,
send: Res<NetworkSend>,
time: Res<Time>,
) -> Result {
for (peer, ref mut last) in peers {
if let Some(previous) = last.timestamp {
if previous + TIMEOUT > time.elapsed() {
continue;
}
}
send.send(Vec::new(), peer.addr)?;
last.timestamp = Some(time.elapsed());
}
Ok(())
}
#[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash)]
enum NetworkState {
#[default]
@ -33,6 +52,28 @@ enum NetworkState {
MultiPlayer,
}
#[derive(Component, Debug, Default)]
struct PeerSendTiming {
timestamp: Option<Duration>,
}
#[derive(Component, Debug, Default)]
struct PeerReceiveTiming {
timestamp: Option<Duration>,
}
#[derive(Component, Debug)]
#[require(PeerSendTiming, PeerReceiveTiming)]
struct Peer {
addr: SocketAddr,
}
impl Peer {
fn new(addr: SocketAddr) -> Self {
Self { addr }
}
}
pub struct NetIOPlugin {
listen: u16,
peer: Option<SocketAddr>,
@ -48,21 +89,18 @@ impl Plugin for NetIOPlugin {
fn build(&self, app: &mut App) {
app.init_state::<NetworkState>().add_systems(
FixedUpdate,
handle_network_io.run_if(in_state(NetworkState::MultiPlayer)),
(handle_network_input, heartbeat).run_if(in_state(NetworkState::MultiPlayer)),
);
match bind_socket(self.listen) {
Ok((send, receive)) => {
if let Some(socket) = self.peer {
if let Err(err) = send.try_send((Vec::new(), socket)) {
warn!("Failed to send to peer: {err}");
return;
}
}
app.insert_state(NetworkState::MultiPlayer)
.insert_resource(NetworkSend::new(send))
.insert_resource(NetworkReceive::new(receive));
if let Some(socket) = self.peer {
app.world_mut().spawn(Peer::new(socket));
}
}
Err(err) => {
warn!("Failed to set up networking: {err}");