Add Bevy event queues for inbound and outbound packets, and use Bevy change detection for consumer new Peer handling.
This commit is contained in:
parent
cceca83dac
commit
c10f6cfb82
9 changed files with 348 additions and 72 deletions
|
@ -1,79 +1,25 @@
|
|||
use std::{net::SocketAddr, time::Duration};
|
||||
use std::net::SocketAddr;
|
||||
|
||||
use bevy::prelude::*;
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::{
|
||||
io::{
|
||||
Config, InboundPacket, OutboundPacket, handle_network_input, handle_network_output,
|
||||
heartbeat, timeouts,
|
||||
},
|
||||
peer::{Peer, PeerChangeEvent, PeerMap, handle_peer_change},
|
||||
queues::{NetworkReceive, NetworkSend},
|
||||
socket::bind_socket,
|
||||
};
|
||||
use crate::game::prelude::Seed;
|
||||
|
||||
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 {
|
||||
commands.insert_resource::<Seed>(message.try_into()?);
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
pub enum NetworkState {
|
||||
#[default]
|
||||
SinglePlayer,
|
||||
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>,
|
||||
|
@ -87,10 +33,25 @@ impl NetIOPlugin {
|
|||
|
||||
impl Plugin for NetIOPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.init_state::<NetworkState>().add_systems(
|
||||
FixedUpdate,
|
||||
(handle_network_input, heartbeat).run_if(in_state(NetworkState::MultiPlayer)),
|
||||
);
|
||||
app.init_state::<NetworkState>()
|
||||
.add_systems(
|
||||
FixedPreUpdate,
|
||||
(handle_network_input, handle_peer_change)
|
||||
.chain()
|
||||
.run_if(in_state(NetworkState::MultiPlayer)),
|
||||
)
|
||||
.add_systems(
|
||||
FixedUpdate,
|
||||
(heartbeat, timeouts).run_if(in_state(NetworkState::MultiPlayer)),
|
||||
)
|
||||
.add_systems(
|
||||
FixedPostUpdate,
|
||||
handle_network_output.run_if(in_state(NetworkState::MultiPlayer)),
|
||||
)
|
||||
.insert_resource(Config::new())
|
||||
.add_event::<PeerChangeEvent>()
|
||||
.add_event::<InboundPacket>()
|
||||
.add_event::<OutboundPacket>();
|
||||
|
||||
match bind_socket(self.listen) {
|
||||
Ok((send, receive)) => {
|
||||
|
@ -98,9 +59,13 @@ impl Plugin for NetIOPlugin {
|
|||
.insert_resource(NetworkSend::new(send))
|
||||
.insert_resource(NetworkReceive::new(receive));
|
||||
|
||||
let mut peer_map = PeerMap::default();
|
||||
if let Some(socket) = self.peer {
|
||||
app.world_mut().spawn(Peer::new(socket));
|
||||
let entity = app.world_mut().spawn(Peer::new(socket, Uuid::nil()));
|
||||
peer_map.insert(Uuid::nil(), entity.id());
|
||||
}
|
||||
|
||||
app.insert_resource(peer_map);
|
||||
}
|
||||
Err(err) => {
|
||||
warn!("Failed to set up networking: {err}");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue