1use std::collections::HashMap;
2
3use bevy::prelude::*;
4use felix_audio::{SAMPLE_RATE, source::{FelixAudioSource, stream_source::StreamAudioSource}};
5use felix_net::{packet::PacketTypes, packets::update_server_position::UpdateServerPositions};
6
7use crate::{debug_camera::DebugCamera, net::{NetClientCommand, connection::Connection}, remote_player::RemotePlayer};
8
9pub fn fixed_update(
10 mut query: Query<(&mut DebugCamera, &mut Transform)>,
11
12 mut networking: Query<&mut Connection>,
13
14 mut commands: Commands,
15 mut meshes: ResMut<Assets<Mesh>>,
16 mut materials: ResMut<Assets<StandardMaterial>>,
17
18 players: Query<(Entity, &mut RemotePlayer)>
19){
20 let ( _, transform ) = query.single_mut().unwrap();
21 let mut net_manager = networking.single_mut().unwrap();
22
23 let update_pos_packet = UpdateServerPositions {
24 position: transform.translation.clone(),
25 rotation: transform.rotation.clone()
26 };
27
28 net_manager.try_send_unreliable(update_pos_packet).unwrap();
29
30 if let Ok(ev) = net_manager.recv_event(){
31 match ev{
32 NetClientCommand::Connected(id) => {
33 println!("[INFO] Connected to server as {}", id);
34 }
35 NetClientCommand::Disconnected => {
36 println!("[WARN] Disconnected from server.");
37 }
38 NetClientCommand::RecvPacket(packet) => {
39 match packet{
40 PacketTypes::PlayerJoinPacket(packet) => {
41 join_players(vec![packet.id], &mut commands, &mut meshes, &mut materials, &mut net_manager);
42 }
43 PacketTypes::PlayerListPacket(packet) => {
44 join_players(packet.ids, &mut commands, &mut meshes, &mut materials, &mut net_manager);
45 }
46 PacketTypes::PlayerLeavePacket(packet) => {
47 leave_player(packet.id, &mut commands, players, &mut net_manager);
48 }
49 PacketTypes::UpdateClientsPositions(packet) => {
50 let mut map = HashMap::new();
51
52 for ( id, pos, rot ) in packet.players{
53 map.insert(id, (pos, rot)); }
54
55 for ( _, mut player ) in players{
56 let ( pos, rot ) = map.get(&player.id).unwrap();
57
58 player.pos = *pos;
59 player.rot = *rot;
60 }
61 }
62 _ => {}
63 }
64 }
65 }
66 }
67}
68
69fn join_players(
70 players: Vec<String>,
71
72 commands: &mut Commands,
73 meshes: &mut ResMut<Assets<Mesh>>,
74 materials: &mut ResMut<Assets<StandardMaterial>>,
75
76 net_manager: &mut Connection
77){
78 for id in players{
79 let listener = net_manager.start_listening_for_player_voice(&id);
80
81 commands.spawn((
82 Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
83 MeshMaterial3d(materials.add(Color::WHITE)),
84 Transform::from_xyz(0.0, 0.0, 0.0),
85 RemotePlayer { id, ..Default::default() },
86 FelixAudioSource::from(StreamAudioSource::new(SAMPLE_RATE, move | len | {
87 let mut buf = vec![0.0; len];
88 let mut lock = listener.lock().unwrap();
89
90 for i in 0..buf.len(){
91 buf[i] = lock.pop_front().unwrap_or(0.0); }
92
93 buf
94 }))
95 ));
96 }
97}
98
99fn leave_player(
100 id: String,
101 commands: &mut Commands,
102
103 players: Query<(Entity, &mut RemotePlayer)>,
104 net_manager: &mut Connection
105){
106 net_manager.stop_listening_for_player_voice(&id);
107
108 for ( entity, player ) in players{
109 if id == player.id{
110 commands.entity(entity).despawn();
111 break;
112 }
113 }
114}