forked from feather-rs/feather
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathnetwork.rs
More file actions
95 lines (88 loc) · 3.14 KB
/
network.rs
File metadata and controls
95 lines (88 loc) · 3.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//! Network logic. This module includes:
//! * `Network`, a component assigned to entities
//! which can send and receive packets. (This is only
//! added for players, obviously.)
//! * `PacketQueue`, which stores packets received
//! from players and allows systems to poll for packets
//! received of a given type.
use crate::game::Game;
use crate::io::{
ListenerToServerMessage, ServerToListenerMessage, ServerToWorkerMessage, WorkerToServerMessage,
};
use crate::BumpVec;
use crossbeam::Receiver;
use feather_core::Packet;
use fecs::{IntoQuery, Read, World};
use futures::channel::mpsc::UnboundedSender;
use std::iter;
/// Network component containing channels to send and receive packets.
///
/// Systems should call `Network::send` to send a packet to this entity (player).
pub struct Network {
pub tx: UnboundedSender<ServerToWorkerMessage>,
pub rx: Receiver<WorkerToServerMessage>,
}
impl Network {
/// Sends a packet to this player.
pub fn send<P>(&self, packet: P)
where
P: Packet,
{
self.send_boxed(Box::new(packet));
}
/// Sends a boxed packet to this player.
pub fn send_boxed(&self, packet: Box<dyn Packet>) {
// Discard error in case the channel was disconnected
// (e.g. if the player disconnected and its worker task
// shut down, and the disconnect was not yet registered
// by the server)
let _ = self
.tx
.unbounded_send(ServerToWorkerMessage::SendPacket(packet));
}
}
/// System which polls for player disconnects.
#[system]
pub fn poll_player_disconnect(game: &mut Game, world: &mut World) {
// For each player with a Network component,
// check their channel for disconnects.
let mut to_despawn = BumpVec::new_in(game.bump());
<Read<Network>>::query()
.iter_entities(world.inner())
.for_each(|(entity, network)| {
while let Ok(msg) = network.rx.try_recv() {
match msg {
WorkerToServerMessage::NotifyDisconnected { reason } => {
to_despawn.push((entity, reason));
}
}
}
});
to_despawn.into_iter().for_each(|(player, reason)| {
game.disconnect(player, world, reason);
});
}
/// System which polls for new clients from the listener task.
#[system]
pub fn poll_new_clients(game: &mut Game, world: &mut World) {
while let Ok(msg) = game.io_handle.rx.try_recv() {
match msg {
ListenerToServerMessage::NewClient(info) => {
game.spawn_player(info, world);
}
ListenerToServerMessage::RequestEntity => {
let entity = world.spawn(iter::once(()))[0];
let _ = game
.io_handle
.tx
.unbounded_send(ServerToListenerMessage::Entity(entity));
}
ListenerToServerMessage::DeleteEntity(entity) => {
// no need to use `Game::despawn` here as
// the entity hasn't actually "existed" yet;
// it has no components
world.despawn(entity);
}
}
}
}