136 lines
3.3 KiB
Rust
136 lines
3.3 KiB
Rust
use std::{collections::HashMap, net::SocketAddr, time::Duration};
|
|
|
|
use bevy::prelude::*;
|
|
use uuid::Uuid;
|
|
|
|
use super::packet::{OutboundPacket, Packet};
|
|
|
|
#[derive(Component, Debug, Default)]
|
|
pub struct PeerSendTiming(Duration);
|
|
|
|
impl PeerSendTiming {
|
|
pub fn update(&mut self, time: &Res<Time>) {
|
|
self.0 = time.elapsed()
|
|
}
|
|
|
|
pub fn time(&self) -> Duration {
|
|
self.0
|
|
}
|
|
}
|
|
|
|
#[derive(Component, Debug, Default)]
|
|
pub struct PeerReceiveTiming(Option<Duration>);
|
|
|
|
impl PeerReceiveTiming {
|
|
pub fn new(time: &Res<Time>) -> Self {
|
|
Self(Some(time.elapsed()))
|
|
}
|
|
|
|
pub fn update(&mut self, time: &Res<Time>) {
|
|
self.0 = Some(time.elapsed())
|
|
}
|
|
|
|
pub fn time(&self) -> Option<Duration> {
|
|
self.0
|
|
}
|
|
}
|
|
|
|
#[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(())
|
|
}
|
|
|
|
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)));
|
|
}
|
|
}
|