mod earth_parts; mod gravity; mod part; mod heat; mod drill; mod craft; mod damping; pub mod net; pub mod planets; pub mod player; mod system_sets; pub mod orbit; pub mod plugins; pub mod components; pub mod visibility; use std::net::SocketAddr; use aeronet::io::connection::{DisconnectReason, Disconnected, LocalAddr}; use aeronet::io::server::Server; use aeronet::io::Session; //use aeronet_replicon::server::AeronetRepliconServer; use aeronet_transport::lane::LaneKind; use aeronet_transport::{Transport, TransportConfig}; use aeronet_websocket::server::{ServerConfig, WebSocketServer}; //use bevy_replicon::prelude::Replicated; //use bevy_replicon::server::AuthorizedClient; use crate::server::craft::craft_plugin; use crate::server::damping::damping_plugin; use crate::server::drill::drill_plugin; use crate::server::earth_parts::spawn_parts_plugin; use crate::server::gravity::newtonian_gravity_plugin; use crate::server::net::net_plugin; use crate::server::part::part_management_plugin; use crate::server::planets::planets_plugin; use crate::server::player::player_management_plugin; use crate::server::system_sets::{PlayerInputSet, WorldUpdateSet}; use crate::prelude::*; use crate::server::orbit::OrbitPlugin; use crate::server::player::thrust::server_thrust_plugin; use crate::shared::net::{ClientMessageRegistry, ServerMessageRegistry}; pub struct ServerPlugin { pub bind: SocketAddr } impl Plugin for ServerPlugin { fn build(&self, app: &mut App) { let bind = self.bind; app .add_plugins(net_plugin) .add_plugins(planets_plugin) .add_plugins(newtonian_gravity_plugin) .add_plugins(player_management_plugin) .add_plugins(spawn_parts_plugin) .add_plugins(part_management_plugin) .add_plugins(server_thrust_plugin) /*.add_plugins(heat_cooling_plugin) .add_plugins(heat_radiation_plugin) .add_plugins(heat_conduction_plugin)*/ .add_plugins(drill_plugin) .add_plugins(craft_plugin) .add_plugins(OrbitPlugin) .add_plugins(damping_plugin) .configure_sets(Update, WorldUpdateSet.before(PlayerInputSet)) .add_observer(on_opened) .add_observer(on_connected) .add_observer(on_disconnected) .add_systems(Startup, move |mut commands: Commands| { commands.spawn((Name::new("websocket-server"), /*AeronetRepliconServer*/)) .queue(WebSocketServer::open(ServerConfig::builder() .with_bind_address(bind) .with_no_encryption())); }); //.add_systems(Update, handle_authorized); } } #[derive(Component, Debug)] pub struct ConnectedGameEntity { pub network_entity: Entity, } #[derive(Component)] pub struct ConnectedNetworkEntity { pub game_entity: Entity, } fn on_opened(trigger: On, servers: Query<&LocalAddr>) { let server = trigger.event_target(); let local_addr = servers.get(server).unwrap(); info!(server_entity=?server, "websocket server opened on {:?}", *local_addr); } fn on_connected( trigger: On, clients: Query<&ChildOf>, sessions: Query<&Session>, server_message_registry: Res, client_message_registry: Res, mut commands: Commands, ) { let client = trigger.event_target(); let Ok(&ChildOf(server)) = clients.get(client) else { return; }; let Ok(session) = sessions.get(client) else { return; }; info!(?client, ?server, "client connected"); let player = commands .spawn((ConnectedGameEntity { network_entity: client, })) .id(); let server_message_count = server_message_registry.message_count(); let client_message_count = client_message_registry.message_count(); let message_count = server_message_count + client_message_count; debug!("message count: {}", message_count); let lanes = [LaneKind::ReliableOrdered].repeat(message_count); let transport = Transport::new( session, lanes.clone(), lanes, bevy::platform::time::Instant::now(), ).expect("packet MTU too small to support transport"); commands.entity(client).insert(( ConnectedNetworkEntity { game_entity: player, }, transport, TransportConfig { max_memory_usage: 536_870_912, // 512 MiB, ..Default::default() } )); } fn on_disconnected( trigger: On, clients: Query<&ChildOf>, player_entity: Query<&ConnectedNetworkEntity>, mut commands: Commands, ) { let client = trigger.event_target(); let Ok(&ChildOf(server)) = clients.get(client) else { return; }; match &trigger.reason { DisconnectReason::ByUser(reason) => { info!(?client, ?server, ?reason, "client disconnected by user"); } DisconnectReason::ByPeer(reason) => { info!(?client, ?server, ?reason, "client disconnected by peer"); } DisconnectReason::ByError(err) => { warn!(?client, ?server, "client disconnected with error: {err:?}"); } } let Ok(other_entity) = player_entity.get(client) else { return; }; let Ok(mut commands) = commands.get_entity(other_entity.game_entity) else { return; }; commands.despawn(); }