Replicate Sounds (#68)

This commit is contained in:
PROMETHIA-27
2025-09-29 14:46:38 -04:00
committed by GitHub
parent a07dfb3840
commit a16ee231cc
47 changed files with 992 additions and 721 deletions

View File

@@ -1,42 +1,54 @@
use crate::config::ServerConfig;
use bevy::prelude::*;
use lightyear::{
connection::client::PeerMetadata,
link::LinkConditioner,
prelude::{
server::{NetcodeConfig, NetcodeServer, ServerUdpIo, Started},
server::{ClientOf, NetcodeConfig, NetcodeServer, ServerUdpIo, Started},
*,
},
};
use shared::{GameState, global_observer, heads_database::HeadsDatabase, tb_entities::SpawnPoint};
use shared::{
GameState, global_observer,
heads_database::HeadsDatabase,
protocol::{
ClientEnteredPlaying, channels::UnorderedReliableChannel, messages::AssignClientPlayer,
},
tb_entities::SpawnPoint,
};
use std::{
net::{IpAddr, Ipv4Addr, SocketAddr},
time::Duration,
};
pub fn plugin(app: &mut App) {
app.add_systems(Startup, (start_server, setup_timeout_timer));
app.add_systems(
OnEnter(GameState::Playing),
(start_server, setup_timeout_timer),
);
app.add_systems(
Update,
(
notify_started.run_if(in_state(GameState::Playing)),
run_timeout,
),
(notify_started, run_timeout).run_if(in_state(GameState::Playing)),
);
global_observer!(app, handle_new_client);
global_observer!(app, on_client_connected);
global_observer!(app, on_client_playing);
global_observer!(app, close_on_disconnect);
global_observer!(app, cancel_timeout);
}
#[derive(Component)]
struct ClientPlayerId(u8);
fn handle_new_client(
trigger: Trigger<OnAdd, Connected>,
trigger: Trigger<OnAdd, Linked>,
mut commands: Commands,
id: Query<&PeerAddr>,
asset_server: Res<AssetServer>,
query: Query<&Transform, With<SpawnPoint>>,
heads_db: Res<HeadsDatabase>,
) -> Result {
let id = id.get(trigger.target())?;
let Ok(id) = id.get(trigger.target()) else {
return Ok(());
};
info!("Client connected on IP: {}", id.ip());
@@ -46,11 +58,38 @@ fn handle_new_client(
incoming_loss: 0.0,
});
commands
.entity(trigger.target())
.insert((ReplicationSender::default(), Link::new(Some(conditioner))));
commands.entity(trigger.target()).insert((
ReplicationSender::default(),
Link::new(Some(conditioner)),
ClientPlayerId(0),
));
crate::player::spawn(commands, trigger.target(), query, asset_server, heads_db);
Ok(())
}
fn on_client_connected(
trigger: Trigger<OnAdd, ClientOf>,
mut assign_player: Query<(&ClientPlayerId, &mut MessageSender<AssignClientPlayer>)>,
) -> Result {
// `Linked` happens before the `ClientOf` and `MessageSender` components are added, so the server can't
// send the client player id until now.
let (id, mut sender) = assign_player.get_mut(trigger.target())?;
sender.send::<UnorderedReliableChannel>(AssignClientPlayer(id.0));
Ok(())
}
fn on_client_playing(
trigger: Trigger<RemoteTrigger<ClientEnteredPlaying>>,
commands: Commands,
query: Query<&Transform, With<SpawnPoint>>,
heads_db: Res<HeadsDatabase>,
peers: Res<PeerMetadata>,
) -> Result {
let Some(&client) = peers.mapping.get(&trigger.from) else {
return Ok(());
};
crate::player::spawn(commands, client, query, heads_db).ok_or("failed to spawn player")?;
Ok(())
}
@@ -61,6 +100,7 @@ fn close_on_disconnect(
mut writer: EventWriter<AppExit>,
) {
if config.close_on_client_disconnect {
info!("client disconnected, exiting");
writer.write(AppExit::Success);
}
}
@@ -103,10 +143,12 @@ fn run_timeout(mut timer: ResMut<TimeoutTimer>, mut writer: EventWriter<AppExit>
timer.0 -= time.delta_secs();
if timer.0 <= 0.0 {
info!("client timed out, exiting");
writer.write(AppExit::Success);
}
}
fn cancel_timeout(_trigger: Trigger<OnAdd, Connected>, mut timer: ResMut<TimeoutTimer>) {
info!("client connected, cancelling timeout");
timer.0 = f32::INFINITY;
}