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;
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<Add, Server>, 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<Add, Session>,
clients: Query<&ChildOf>,
sessions: Query<&Session>,
server_message_registry: Res<ServerMessageRegistry>,
client_message_registry: Res<ClientMessageRegistry>,
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
));
}
fn on_disconnected(
trigger: On<Disconnected>,
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();
}