distributed_physics_test/src/net/peer.rs

132 lines
3.2 KiB
Rust

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 {
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()) {
commands.get_entity(entity)?.despawn();
}
}
Ok(())
}