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
96
97
98
99
100
//! Defines the client bevy systems and run conditions
use bevy::prelude::{Events, Fixed, Mut, Res, ResMut, Time, Virtual, World};
use tracing::{debug, info, trace};
use crate::client::events::{ConnectEvent, DisconnectEvent, EntityDespawnEvent, EntitySpawnEvent};
use crate::client::resource::Client;
use crate::connection::events::{IterEntityDespawnEvent, IterEntitySpawnEvent};
use crate::protocol::component::ComponentProtocol;
use crate::protocol::message::MessageProtocol;
use crate::protocol::Protocol;
pub(crate) fn receive<P: Protocol>(world: &mut World) {
trace!("Receive server packets");
world.resource_scope(|world, mut client: Mut<Client<P>>| {
world.resource_scope(|world, time: Mut<Time<Virtual>>| {
let fixed_time = world.get_resource::<Time<Fixed>>().unwrap();
// TODO: here we can control time elapsed from the client's perspective?
// TODO: THE CLIENT COULD DO PHYSICS UPDATES INSIDE FIXED-UPDATE SYSTEMS
// WE SHOULD BE CALLING UPDATE INSIDE THOSE AS WELL SO THAT WE CAN SEND UPDATES
// IN THE MIDDLE OF THE FIXED UPDATE LOOPS
// WE JUST KEEP AN INTERNAL TIMER TO KNOW IF WE REACHED OUR TICK AND SHOULD RECEIVE/SEND OUT PACKETS?
// FIXED-UPDATE.expend() updates the clock by the fixed update interval
// THE NETWORK TICK INTERVAL COULD BE IN BETWEEN FIXED UPDATE INTERVALS
// update client state, send keep-alives, receive packets from io
// update connection sync state
client.update(time.delta(), fixed_time.overstep()).unwrap();
// buffer packets into message managers
client.recv_packets().unwrap();
// receive packets from message managers
let mut events = client.receive(world);
if !events.is_empty() {
// NOTE: maybe no need to send those events, because the client knows when it's connected/disconnected?
// if events.has_connection() {
// let mut connect_event_writer =
// world.get_resource_mut::<Events<ConnectEvent>>().unwrap();
// debug!("Client connected event");
// connect_event_writer.send(ConnectEvent::new(()));
// }
//
// if events.has_disconnection() {
// let mut disconnect_event_writer =
// world.get_resource_mut::<Events<DisconnectEvent>>().unwrap();
// debug!("Client disconnected event");
// disconnect_event_writer.send(DisconnectEvent::new(()));
// }
// Message Events
P::Message::push_message_events(world, &mut events);
// SpawnEntity event
if events.has_entity_spawn() {
let mut entity_spawn_event_writer = world
.get_resource_mut::<Events<EntitySpawnEvent>>()
.unwrap();
for (entity, _) in events.into_iter_entity_spawn() {
entity_spawn_event_writer.send(EntitySpawnEvent::new(entity, ()));
}
}
// DespawnEntity event
if events.has_entity_despawn() {
let mut entity_despawn_event_writer = world
.get_resource_mut::<Events<EntityDespawnEvent>>()
.unwrap();
for (entity, _) in events.into_iter_entity_despawn() {
entity_despawn_event_writer.send(EntityDespawnEvent::new(entity, ()));
}
}
// Update component events (updates, inserts, removes)
P::Components::push_component_events(world, &mut events);
}
trace!("finished recv");
});
});
}
pub(crate) fn send<P: Protocol>(mut client: ResMut<Client<P>>) {
trace!("Send packets to server");
// send buffered packets to io
client.send_packets().unwrap();
}
pub(crate) fn is_ready_to_send<P: Protocol>(client: Res<Client<P>>) -> bool {
client.is_ready_to_send()
}
pub(crate) fn sync_update<P: Protocol>(world: &mut World) {
world.resource_scope(|world, mut client: Mut<Client<P>>| {
world.resource_scope(|world, mut time: Mut<Time<Virtual>>| {
// Handle pongs, update RTT estimates, update client's speed
client.sync_update();
// after the sync manager ran (and possibly re-computed RTT estimates), update the client's speed
client.update_relative_speed(&mut time);
})
})
}