use aeronet_io::connection::PeerAddr;
use aeronet_steam::client::SteamNetClient;
use aeronet_steam::{
SessionConfig, SteamworksClient,
client::{ConnectTarget, SteamNetClientPlugin},
};
use alloc::string::ToString;
use bevy_app::{App, Plugin};
use bevy_ecs::lifecycle::HookContext;
use bevy_ecs::prelude::*;
use bevy_ecs::world::DeferredWorld;
use lightyear_aeronet::{AeronetLinkOf, AeronetPlugin};
use lightyear_connection::client::{Connected, Disconnect};
use lightyear_core::id::{LocalId, PeerId, RemoteId};
use lightyear_link::{Link, LinkStart, Linked, Linking, Unlink};
use tracing::trace;
pub struct SteamClientPlugin;
impl Plugin for SteamClientPlugin {
fn build(&self, app: &mut App) {
if !app.is_plugin_added::<AeronetPlugin>() {
app.add_plugins(AeronetPlugin);
}
app.add_plugins(SteamNetClientPlugin);
app.add_observer(Self::link);
app.add_observer(Self::on_linked);
app.add_observer(Self::disconnect);
}
}
#[derive(Debug, Component)]
#[component(on_add = SteamClientIo::on_add)]
#[require(Link)]
pub struct SteamClientIo {
pub target: ConnectTarget,
pub config: SessionConfig,
}
impl SteamClientIo {
fn on_add(mut world: DeferredWorld, context: HookContext) {
let entity = context.entity;
let local_steam_id = world.resource::<SteamworksClient>().0.user().steam_id();
world
.commands()
.entity(entity)
.insert(LocalId(PeerId::Steam(local_steam_id.raw())));
}
}
impl SteamClientPlugin {
fn link(
trigger: On<LinkStart>,
query: Query<(Entity, &SteamClientIo), (Without<Linking>, Without<Linked>)>,
mut commands: Commands,
) -> Result {
if let Ok((entity, client)) = query.get(trigger.entity) {
let config = client.config.clone();
let target = client.target;
trace!(
"LinkStart triggered for SteamClientIo on entity {entity:?} with target {target:?}"
);
commands.queue(move |world: &mut World| -> Result {
let mut link_entity_mut = world.entity_mut(entity);
match target {
ConnectTarget::Addr(peer_addr) => {
link_entity_mut.insert(PeerAddr(peer_addr));
link_entity_mut.insert(RemoteId(PeerId::Server));
}
ConnectTarget::Peer { steam_id, .. } => {
link_entity_mut.insert(RemoteId(PeerId::Steam(steam_id.raw())));
}
}
let entity_mut =
world.spawn((
AeronetLinkOf(entity),
Name::from("SteamClient")
));
let aeronet_entity = entity_mut.id();
trace!("Starting LinkStart for SteamClientIo on entity {entity:?}. Spawning aeronet entity: {aeronet_entity:?}");
SteamNetClient::connect(config, target).apply(entity_mut);
Ok(())
});
}
Ok(())
}
fn on_linked(
trigger: On<Add, Linked>,
query: Query<(), With<SteamClientIo>>,
mut commands: Commands,
) {
if query.get(trigger.entity).is_ok() {
trace!(
"Steam client entity {:?} is now Linked, inserting Connected component",
trigger.entity
);
commands.entity(trigger.entity).insert(Connected);
}
}
fn disconnect(
trigger: On<Disconnect>,
query: Query<(), With<SteamClientIo>>,
mut commands: Commands,
) {
if query.get(trigger.entity).is_ok() {
commands.trigger(Unlink {
entity: trigger.entity,
reason: "User requested disconnect".to_string(),
});
}
}
}