~starkingdoms/starkingdoms

ref: 1bcde11a581ededd03b6e60e8e97048f7556ad66 starkingdoms/crates/unified/src/client/mod.rs -rw-r--r-- 6.2 KiB
1bcde11a — core netcode: part updates (mystery performance issue, probably related to lots of malloc()) 8 days 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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
use aeronet::io::{Session, SessionEndpoint};
use aeronet::io::connection::{DisconnectReason, Disconnected};
use aeronet_transport::lane::LaneKind;
//use aeronet_replicon::client::AeronetRepliconClient;
use aeronet_transport::{Transport, TransportConfig};
use aeronet_websocket::client::{ClientConfig, WebSocketClient};
use crate::client::crafting::ui::crafting_ui_plugin;
use crate::client::key_input::key_input_plugin;
use crate::client::parts::parts_plugin;
use crate::client::planet::indicators::indicators_plugin;
use crate::client::starfield::starfield_plugin;
use crate::client::starguide::orbit::starguide_orbit_plugin;
use crate::client::ui::ui_plugin;
use crate::client::zoom::zoom_plugin;
use crate::client::starguide::init::starguide_init_plugin;
use crate::client::starguide::input::starguide_input_plugin;
use starguide::components::StarguideGizmos;
use bevy::dev_tools::picking_debug::DebugPickingMode;
use crate::prelude::*;
use planet::incoming_planets::incoming_planets_plugin;
use crate::client::components::Me;
use crate::client::ship::attachment::client_attachment_plugin;
use crate::shared::ecs::{GameplayState, TimeOffset};
use crate::shared::gravity::update_gravity;
use crate::shared::net::{Hi, ClientMessageRegistry, ServerMessageRegistry, ServerEntityMap};
use crate::shared::orbit::OrbitPlugin;

pub mod colors;
pub mod key_input;
pub mod parts;
pub mod planet;
pub mod starfield;
pub mod ui;
pub mod zoom;
pub mod ship;
pub mod rendering;
pub mod input;
pub mod starguide;
pub mod crafting;
pub mod components;
pub mod plugins;
mod net;

pub struct ClientPlugin {
    pub server: Option<String>
}

impl Plugin for ClientPlugin {
    fn build(&self, app: &mut App) {
        app
            .init_gizmo_group::<StarguideGizmos>()
            .add_plugins(net::net_plugin)
            .add_plugins(rendering::render_plugin)
            .add_plugins(OrbitPlugin)
            .add_systems(FixedUpdate, update_gravity.before(PhysicsSystems::Prepare))
            .add_plugins(input::input_plugin)
            .add_plugins(ship::thrusters::client_thrusters_plugin)
            .add_plugins((incoming_planets_plugin, indicators_plugin))
            .add_plugins(parts_plugin)
            .add_plugins(key_input_plugin)
            .add_plugins(starfield_plugin)
            .add_plugins(ui_plugin)
            .add_plugins(zoom_plugin)
            .add_plugins(client_attachment_plugin)
            .add_plugins(starguide_init_plugin)
            .add_plugins(starguide_input_plugin)
            .add_plugins(starguide_orbit_plugin)
            .add_plugins(crafting_ui_plugin)
            .insert_resource(HeartyEntityId(None))
            .add_systems(Update, (handle_hi, find_me))
            .insert_state(GameplayState::Main)
            .insert_resource(DebugPickingMode::Disabled)
            .insert_resource(TimeOffset::default());

        let server = self.server.clone();
        app.add_systems(PostStartup, move |mut commands: Commands| {
            #[cfg(target_arch = "wasm32")]
            let config = ClientConfig {};
            #[cfg(not(target_arch = "wasm32"))]
            let config = ClientConfig::builder().with_no_cert_validation();
            let Some(server) = server.as_ref() else { return };
            commands.spawn((Name::new("default-session"), TransportConfig { max_memory_usage: 536_870_912, ..default() }, /*AeronetRepliconClient*/))
                .queue(
                    WebSocketClient::connect(config, server.clone()));
        });
        if self.server.is_some() {
            app.add_observer(on_connecting);
            app.add_observer(on_connected);
            app.add_observer(on_disconnected);
        }
    }
}

pub fn on_connecting(
    trigger: On<Add, SessionEndpoint>,
    names: Query<&Name>,
    mut commands: Commands,
) {
    let entity = trigger.event_target();
    let name = names.get(entity).unwrap();
    info!("{name} is connecting");
}
pub fn on_connected(
    trigger: On<Add, Session>,
    names: Query<&Name>,
    sessions: Query<&Session>,
    server_message_registry: Res<ServerMessageRegistry>,
    client_message_registry: Res<ClientMessageRegistry>,
    mut commands: Commands,
) {
    let entity = trigger.event_target();
    let name = names.get(entity).unwrap();
    let Ok(session) = sessions.get(entity) else {
        return;
    };

    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(entity).insert(transport);

    info!("{name} is connected");
}
pub fn on_disconnected(trigger: On<Disconnected>, names: Query<&Name>) {
    let session = trigger.event_target();
    let name = names.get(session).unwrap();

    match &trigger.reason {
        DisconnectReason::ByUser(reason) => {
            info!(?name, ?reason, "session disconnected by user");
        }
        DisconnectReason::ByPeer(reason) => {
            info!(?name, ?reason, "session disconnected by peer");
        }
        DisconnectReason::ByError(err) => {
            warn!(?name, "session disconnected due to error: {err:?}");
        }
    }
}

#[derive(Resource)]
struct HeartyEntityId(Option<Entity>);

pub fn handle_hi(
    mut msgs: MessageReader<Hi>,
    mut res: ResMut<HeartyEntityId>,
    mut time_offset: ResMut<TimeOffset>,
) {
    for msg in msgs.read() {
        let we_are = msg.you_are;
        res.0 = Some(we_are);
        time_offset.0 = msg.time_offset;
    }
}

pub fn find_me(
    entity_map: Res<ServerEntityMap>,
    mut res: ResMut<HeartyEntityId>,
    mut commands: Commands,
) {
    let Some(server_entity) = res.0 else { return; };
    let Some(local_entity) = entity_map.server_to_client.get(&server_entity) else { return; };
    let Ok(mut e) = commands.get_entity(*local_entity) else { return; };
    info!(?local_entity, ?server_entity, "joined successfully");
    e.insert(Me);
    res.0 = None;
}