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
134
src/net/peer.rs
Normal file
134
src/net/peer.rs
Normal file
|
@ -0,0 +1,134 @@
|
|||
use std::{collections::HashMap, net::SocketAddr, time::Duration};
|
||||
|
||||
use bevy::prelude::*;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct Timing {
|
||||
timestamp: Option<Duration>,
|
||||
}
|
||||
|
||||
#[derive(Component, Debug, Default)]
|
||||
pub struct PeerSendTiming(Timing);
|
||||
|
||||
impl PeerSendTiming {
|
||||
pub fn update(&mut self, time: &Res<Time>) {
|
||||
self.0.timestamp = Some(time.elapsed())
|
||||
}
|
||||
|
||||
pub fn timestamp(&self) -> Option<Duration> {
|
||||
self.0.timestamp
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component, Debug, Default)]
|
||||
pub struct PeerReceiveTiming(Timing);
|
||||
|
||||
impl PeerReceiveTiming {
|
||||
pub fn new(time: &Res<Time>) -> Self {
|
||||
Self(Timing {
|
||||
timestamp: Some(time.elapsed()),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn update(&mut self, time: &Res<Time>) {
|
||||
self.0.timestamp = Some(time.elapsed())
|
||||
}
|
||||
|
||||
pub fn timestamp(&self) -> Option<Duration> {
|
||||
self.0.timestamp
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
#[require(PeerSendTiming, PeerReceiveTiming)]
|
||||
pub struct Peer {
|
||||
pub addr: SocketAddr,
|
||||
pub uuid: Uuid,
|
||||
}
|
||||
|
||||
impl Peer {
|
||||
pub fn new(addr: SocketAddr, uuid: Uuid) -> Self {
|
||||
Self { addr, uuid }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Resource)]
|
||||
pub struct PeerMap {
|
||||
map: HashMap<Uuid, Entity>,
|
||||
}
|
||||
|
||||
impl PeerMap {
|
||||
pub fn insert(&mut self, uuid: Uuid, id: Entity) {
|
||||
self.map.insert(uuid, id);
|
||||
}
|
||||
|
||||
pub fn get(&self, uuid: &Uuid) -> Option<&Entity> {
|
||||
self.map.get(uuid)
|
||||
}
|
||||
|
||||
pub fn try_get(&self, uuid: &Uuid) -> Result<&Entity, String> {
|
||||
self.get(uuid).ok_or(format!("No entity with uuid: {uuid}"))
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, uuid: &Uuid) -> Option<Entity> {
|
||||
self.map.remove(uuid)
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.map.len()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Event)]
|
||||
pub struct PeerChangeEvent {
|
||||
peer: Uuid,
|
||||
addr: Option<SocketAddr>,
|
||||
}
|
||||
|
||||
impl PeerChangeEvent {
|
||||
pub fn new(peer: Uuid, addr: Option<SocketAddr>) -> Self {
|
||||
Self { peer, addr }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_peer_change(
|
||||
mut changes: EventReader<PeerChangeEvent>,
|
||||
mut peer_map: ResMut<PeerMap>,
|
||||
mut peers: Query<&mut Peer>,
|
||||
mut commands: Commands,
|
||||
time: Res<Time>,
|
||||
) -> Result {
|
||||
for change in changes.read() {
|
||||
if let Some(entity) = peer_map.get(&change.peer) {
|
||||
if let Some(addr) = change.addr {
|
||||
if let Ok(mut peer) = peers.get_mut(*entity) {
|
||||
peer.addr = addr;
|
||||
} else {
|
||||
warn!("Peer {} doesn't exist (just added?)", change.peer);
|
||||
}
|
||||
} else {
|
||||
info!("Removing peer {}", change.peer);
|
||||
commands.get_entity(*entity)?.despawn();
|
||||
peer_map.remove(&change.peer);
|
||||
}
|
||||
} else if let Some(addr) = change.addr {
|
||||
info!("Adding peer {} ({:?})", change.peer, change.addr);
|
||||
peer_map.insert(
|
||||
change.peer,
|
||||
commands
|
||||
.spawn((Peer::new(addr, change.peer), PeerReceiveTiming::new(&time)))
|
||||
.id(),
|
||||
);
|
||||
} else {
|
||||
warn!("Peer {} already deleted", change.peer);
|
||||
}
|
||||
}
|
||||
if peer_map.len() > 1 {
|
||||
if let Some(entity) = peer_map.remove(&Uuid::nil()) {
|
||||
warn!("Removing initial Peer");
|
||||
commands.get_entity(entity)?.despawn();
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue