Compare commits
2 commits
c10f6cfb82
...
e58629c2f1
Author | SHA1 | Date | |
---|---|---|---|
e58629c2f1 | |||
591cfee715 |
5 changed files with 55 additions and 51 deletions
|
@ -4,6 +4,7 @@ use bevy::prelude::*;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
packet::{InboundPacket, OutboundPacket, Packet},
|
||||||
peer::{Peer, PeerChangeEvent, PeerMap, PeerReceiveTiming, PeerSendTiming},
|
peer::{Peer, PeerChangeEvent, PeerMap, PeerReceiveTiming, PeerSendTiming},
|
||||||
queues::{NetworkReceive, NetworkSend},
|
queues::{NetworkReceive, NetworkSend},
|
||||||
};
|
};
|
||||||
|
@ -18,10 +19,13 @@ pub fn handle_network_input(
|
||||||
) -> Result {
|
) -> Result {
|
||||||
for (mut message, address) in from_socket.iter() {
|
for (mut message, address) in from_socket.iter() {
|
||||||
if message.len() < 16 {
|
if message.len() < 16 {
|
||||||
return Err(format!("Message of length {} cannot contain UUID", message.len()).into());
|
return Err(format!(
|
||||||
|
"Message of length {} is not large enough to contain UUID",
|
||||||
|
message.len()
|
||||||
|
)
|
||||||
|
.into());
|
||||||
}
|
}
|
||||||
let uuid = Uuid::from_slice(message.split_off(message.len() - 16).as_slice())?;
|
let uuid = Uuid::from_slice(message.split_off(message.len() - 16).as_slice())?;
|
||||||
info!("Receiving: {:?} from {}", message, uuid);
|
|
||||||
to_app.write(InboundPacket(Packet::new(message, uuid)));
|
to_app.write(InboundPacket(Packet::new(message, uuid)));
|
||||||
if let Some(peer_id) = peer_map.get(&uuid) {
|
if let Some(peer_id) = peer_map.get(&uuid) {
|
||||||
let (peer, mut last) = peers.get_mut(*peer_id)?;
|
let (peer, mut last) = peers.get_mut(*peer_id)?;
|
||||||
|
@ -46,7 +50,6 @@ pub fn handle_network_output(
|
||||||
for packet in from_app.read() {
|
for packet in from_app.read() {
|
||||||
let peer_id = peer_map.try_get(&packet.0.peer)?;
|
let peer_id = peer_map.try_get(&packet.0.peer)?;
|
||||||
let (peer, mut last) = peers.get_mut(*peer_id)?;
|
let (peer, mut last) = peers.get_mut(*peer_id)?;
|
||||||
warn!("Sending: {:?} to {}", packet.0.message, peer.uuid);
|
|
||||||
// Append our UUID for client identification
|
// Append our UUID for client identification
|
||||||
let message = [packet.0.message.as_slice(), config.id.as_bytes()].concat();
|
let message = [packet.0.message.as_slice(), config.id.as_bytes()].concat();
|
||||||
to_socket.send(message, peer.addr)?;
|
to_socket.send(message, peer.addr)?;
|
||||||
|
@ -63,11 +66,9 @@ pub fn heartbeat(
|
||||||
mut outbound: EventWriter<OutboundPacket>,
|
mut outbound: EventWriter<OutboundPacket>,
|
||||||
) {
|
) {
|
||||||
for (peer, last) in peers {
|
for (peer, last) in peers {
|
||||||
if let Some(previous) = last.timestamp() {
|
// Allow for 2 consecutive missed heartbeats without timing out
|
||||||
// Allow for 2 consecutive missed heartbeats without timing out
|
if last.time() + TIMEOUT / 3 > time.elapsed() {
|
||||||
if previous + TIMEOUT / 3 > time.elapsed() {
|
continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
outbound.write(OutboundPacket(Packet::new(Vec::new(), peer.uuid)));
|
outbound.write(OutboundPacket(Packet::new(Vec::new(), peer.uuid)));
|
||||||
}
|
}
|
||||||
|
@ -79,7 +80,7 @@ pub fn timeouts(
|
||||||
mut delete: EventWriter<PeerChangeEvent>,
|
mut delete: EventWriter<PeerChangeEvent>,
|
||||||
) {
|
) {
|
||||||
for (peer, last) in peers {
|
for (peer, last) in peers {
|
||||||
if let Some(previous) = last.timestamp() {
|
if let Some(previous) = last.time() {
|
||||||
if previous + TIMEOUT < time.elapsed() {
|
if previous + TIMEOUT < time.elapsed() {
|
||||||
warn!("Peer {} timed out", peer.uuid);
|
warn!("Peer {} timed out", peer.uuid);
|
||||||
delete.write(PeerChangeEvent::new(peer.uuid, None));
|
delete.write(PeerChangeEvent::new(peer.uuid, None));
|
||||||
|
@ -98,21 +99,3 @@ impl Config {
|
||||||
Self { id: Uuid::new_v4() }
|
Self { id: Uuid::new_v4() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Packet {
|
|
||||||
pub message: Vec<u8>,
|
|
||||||
pub peer: Uuid,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Packet {
|
|
||||||
pub fn new(message: Vec<u8>, peer: Uuid) -> Self {
|
|
||||||
Self { peer, message }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Event)]
|
|
||||||
pub struct OutboundPacket(pub Packet);
|
|
||||||
|
|
||||||
#[derive(Debug, Event)]
|
|
||||||
pub struct InboundPacket(pub Packet);
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
mod io;
|
mod io;
|
||||||
|
mod packet;
|
||||||
mod peer;
|
mod peer;
|
||||||
mod plugin;
|
mod plugin;
|
||||||
mod queues;
|
mod queues;
|
||||||
|
@ -7,7 +8,7 @@ mod thread;
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use super::io::{InboundPacket, OutboundPacket, Packet};
|
pub use super::packet::{InboundPacket, OutboundPacket, Packet};
|
||||||
pub use super::peer::Peer;
|
pub use super::peer::Peer;
|
||||||
pub use super::plugin::{NetIOPlugin, NetworkState};
|
pub use super::plugin::{NetIOPlugin, NetworkState};
|
||||||
}
|
}
|
||||||
|
|
20
src/net/packet.rs
Normal file
20
src/net/packet.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Packet {
|
||||||
|
pub message: Vec<u8>,
|
||||||
|
pub peer: Uuid,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Packet {
|
||||||
|
pub fn new(message: Vec<u8>, peer: Uuid) -> Self {
|
||||||
|
Self { peer, message }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Event)]
|
||||||
|
pub struct OutboundPacket(pub Packet);
|
||||||
|
|
||||||
|
#[derive(Debug, Event)]
|
||||||
|
pub struct InboundPacket(pub Packet);
|
|
@ -3,40 +3,35 @@ use std::{collections::HashMap, net::SocketAddr, time::Duration};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
use super::packet::{OutboundPacket, Packet};
|
||||||
struct Timing {
|
|
||||||
timestamp: Option<Duration>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Component, Debug, Default)]
|
#[derive(Component, Debug, Default)]
|
||||||
pub struct PeerSendTiming(Timing);
|
pub struct PeerSendTiming(Duration);
|
||||||
|
|
||||||
impl PeerSendTiming {
|
impl PeerSendTiming {
|
||||||
pub fn update(&mut self, time: &Res<Time>) {
|
pub fn update(&mut self, time: &Res<Time>) {
|
||||||
self.0.timestamp = Some(time.elapsed())
|
self.0 = time.elapsed()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn timestamp(&self) -> Option<Duration> {
|
pub fn time(&self) -> Duration {
|
||||||
self.0.timestamp
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Debug, Default)]
|
#[derive(Component, Debug, Default)]
|
||||||
pub struct PeerReceiveTiming(Timing);
|
pub struct PeerReceiveTiming(Option<Duration>);
|
||||||
|
|
||||||
impl PeerReceiveTiming {
|
impl PeerReceiveTiming {
|
||||||
pub fn new(time: &Res<Time>) -> Self {
|
pub fn new(time: &Res<Time>) -> Self {
|
||||||
Self(Timing {
|
Self(Some(time.elapsed()))
|
||||||
timestamp: Some(time.elapsed()),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, time: &Res<Time>) {
|
pub fn update(&mut self, time: &Res<Time>) {
|
||||||
self.0.timestamp = Some(time.elapsed())
|
self.0 = Some(time.elapsed())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn timestamp(&self) -> Option<Duration> {
|
pub fn time(&self) -> Option<Duration> {
|
||||||
self.0.timestamp
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +103,6 @@ pub fn handle_peer_change(
|
||||||
warn!("Peer {} doesn't exist (just added?)", change.peer);
|
warn!("Peer {} doesn't exist (just added?)", change.peer);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
info!("Removing peer {}", change.peer);
|
|
||||||
commands.get_entity(*entity)?.despawn();
|
commands.get_entity(*entity)?.despawn();
|
||||||
peer_map.remove(&change.peer);
|
peer_map.remove(&change.peer);
|
||||||
}
|
}
|
||||||
|
@ -126,9 +120,17 @@ pub fn handle_peer_change(
|
||||||
}
|
}
|
||||||
if peer_map.len() > 1 {
|
if peer_map.len() > 1 {
|
||||||
if let Some(entity) = peer_map.remove(&Uuid::nil()) {
|
if let Some(entity) = peer_map.remove(&Uuid::nil()) {
|
||||||
warn!("Removing initial Peer");
|
|
||||||
commands.get_entity(entity)?.despawn();
|
commands.get_entity(entity)?.despawn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,11 +4,9 @@ use bevy::prelude::*;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
io::{
|
io::{Config, handle_network_input, handle_network_output, heartbeat, timeouts},
|
||||||
Config, InboundPacket, OutboundPacket, handle_network_input, handle_network_output,
|
packet::{InboundPacket, OutboundPacket},
|
||||||
heartbeat, timeouts,
|
peer::{Peer, PeerChangeEvent, PeerMap, handle_new_peer, handle_peer_change},
|
||||||
},
|
|
||||||
peer::{Peer, PeerChangeEvent, PeerMap, handle_peer_change},
|
|
||||||
queues::{NetworkReceive, NetworkSend},
|
queues::{NetworkReceive, NetworkSend},
|
||||||
socket::bind_socket,
|
socket::bind_socket,
|
||||||
};
|
};
|
||||||
|
@ -42,7 +40,7 @@ impl Plugin for NetIOPlugin {
|
||||||
)
|
)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
FixedUpdate,
|
FixedUpdate,
|
||||||
(heartbeat, timeouts).run_if(in_state(NetworkState::MultiPlayer)),
|
(heartbeat, timeouts, handle_new_peer).run_if(in_state(NetworkState::MultiPlayer)),
|
||||||
)
|
)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
FixedPostUpdate,
|
FixedPostUpdate,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue