~starkingdoms/starkingdoms

ref: 05fbfecfb41273eb861531bc69beed8f4f72f026 starkingdoms/crates/unified/src/server/mod.rs -rw-r--r-- 3.7 KiB
05fbfecf — core feat(netcode): aeronet 5 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
mod gravity;
pub mod planets;
pub mod player;
mod world_config;

use std::net::SocketAddr;
use aeronet::io::connection::{Disconnected, LocalAddr};
use aeronet::io::server::Server;
use aeronet::io::Session;
use aeronet_replicon::server::AeronetRepliconServer;
use aeronet_websocket::server::WebSocketServer;
use bevy::asset::AssetContainer;
use bevy::prelude::*;
use bevy_replicon::prelude::Replicated;
use crate::server::gravity::newtonian_gravity_plugin;
use crate::server::planets::planets_plugin;
use crate::server::player::player_management_plugin;
use crate::server::world_config::world_config_plugin;

pub struct ServerPlugin {
    pub bind: SocketAddr,
    pub max_clients: usize,
}
impl Plugin for ServerPlugin {
    fn build(&self, app: &mut App) {
        let config = self.websocket_config();

        app.add_systems(FixedPreUpdate, bevy_replicon::server::increment_tick) // !!important!! do not remove or move
            .add_systems(Startup, move |mut commands: Commands| {
                let server = commands.spawn(Name::new("ws-server"))
                    .insert(AeronetRepliconServer)
                    .insert(Transform::from_xyz(0.0,0.0,0.0))
                    .queue(WebSocketServer::open(config.clone()))
                    .id();

                info!(entity_id=?server, "opening websocket server");
            })
            .add_observer(on_opened)
            .add_observer(on_connected)
            .add_observer(on_disconnected)
            .add_plugins(planets_plugin)
            .add_plugins(world_config_plugin)
            .add_plugins(newtonian_gravity_plugin)
            .add_plugins(player_management_plugin);
    }
}
impl ServerPlugin {
    fn websocket_config(&self) -> aeronet_websocket::server::ServerConfig {
        aeronet_websocket::server::ServerConfig::builder()
            .with_bind_address(self.bind)
            .with_no_encryption()
    }
}

#[derive(Component)]
pub struct ConnectedGameEntity {
    pub network_entity: Entity
}
#[derive(Component)]
pub struct ConnectedNetworkEntity {
    pub game_entity: Entity
}


fn on_opened(trigger: Trigger<OnAdd, Server>, servers: Query<&LocalAddr>) {
    let server = trigger.target();
    let local_addr = servers.get(server).unwrap();
    info!(server_entity=?server, "websocket server opened on {:?}", *local_addr);
}
fn on_connected(
    trigger: Trigger<OnAdd, Session>,
    clients: Query<&ChildOf>,
    mut commands: Commands,
) {
    let client = trigger.target();
    let Ok(&ChildOf(server)) = clients.get(client) else {
        return;
    };
    info!(?client, ?server, "client connected");

    // spawn the player

    let player = commands.spawn(ConnectedGameEntity {
        network_entity: client
    }).id();

    commands.entity(client).insert((
        Replicated,
        ConnectedNetworkEntity {
            game_entity: player
        },
    ));
}
fn on_disconnected(trigger: Trigger<Disconnected>, clients: Query<&ChildOf>, player_entity: Query<&ConnectedNetworkEntity>, mut commands: Commands) {
    let client = trigger.target();
    let Ok(&ChildOf(server)) = clients.get(client) else {
        return;
    };
    match &*trigger {
        Disconnected::ByUser(reason) => {
            info!(?client, ?server, ?reason, "client disconnected by user");
        },
        Disconnected::ByPeer(reason) => {
            info!(?client, ?server, ?reason, "client disconnected by peer");
        },
        Disconnected::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();
}