~starkingdoms/starkingdoms

ref: 10afa15d4a9a5bf9df7f161eccc6b8e2f9116a7f starkingdoms/crates/unified/src/server/player/join.rs -rw-r--r-- 4.3 KiB
10afa15d — core feat(netcode-rewrite): remove interpolation 26 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
use bevy_replicon::prelude::{ClientId, SendMode, ToClients};
use crate::client::components::Me;
use crate::shared::config::planet::Planet;
use crate::shared::config::world::GlobalWorldConfig;
use crate::shared::ecs::{Player, PlayerStorage};
use crate::prelude::*;
use crate::server::ConnectedGameEntity;
use crate::server::part::SpawnPartRequest;
use crate::shared::net::Hi;
use crate::shared::world_config::WorldConfigResource;

const SPAWN_ORBIT_OFFSET: f64 = 150.0;
const INITIAL_FUEL_CAPACITY: f32 = 25.0;
const INITIAL_POWER_CAPACITY: f32 = 25.0;

fn join_player(joined_player: Entity, mut commands: Commands, wc: &GlobalWorldConfig,
    planets: Query<(&Transform, &LinearVelocity, &Planet)>, asset_server: &AssetServer
) {
    trace!(?joined_player, "detected joined player!");
    // find earth
    if planets.is_empty() {
        warn!("planets have not loaded yet, setting this player to pending until they do!");
        commands.entity(joined_player).insert(PendingPlayer);
        return;
    }
    let (spawn_planet_pos, spawn_planet_vel, spawn_planet) = planets
        .iter()
        .find(|p| p.2.name == wc.hearty.spawn_at)
        .unwrap_or_else(|| {
            panic!(
                "spawn planet {} is missing? (check that the planet is named exactly '{}')",
                wc.hearty.spawn_at, wc.hearty.spawn_at
            )
        });
    let angle = rand::random::<f32>() * std::f32::consts::TAU;
    let offset = spawn_planet.radius + SPAWN_ORBIT_OFFSET;
    let mut new_transform =
        Transform::from_xyz(angle.cos() * offset as f32, angle.sin() * offset as f32, 0.0);
    new_transform.rotate_z(angle);
    new_transform.translation += spawn_planet_pos.translation;

    info!(?new_transform, ?joined_player, "set player's position!");

    commands
        .entity(joined_player)
        .insert(new_transform)
        .insert(SpawnPartRequest(
            asset_server.load("config/parts/hearty.part.toml"),
        ))
        .insert(PlayerStorage {
            fuel_capacity: INITIAL_FUEL_CAPACITY,
            fuel: INITIAL_FUEL_CAPACITY,
            power_capacity: INITIAL_POWER_CAPACITY,
            power: INITIAL_POWER_CAPACITY,
        })
        .insert(Player {
            client: joined_player,
        })
        .insert(*spawn_planet_vel)
        .remove::<PendingPlayer>();
}

#[derive(Component)]
pub struct PendingPlayer;

pub fn handle_new_players(
    mut commands: Commands,
    q_new_clients: Query<(Entity, &ConnectedGameEntity), Added<ConnectedGameEntity>>,
    world_config: Res<WorldConfigResource>,
    planets: Query<(&Transform, &LinearVelocity, &Planet)>,
    asset_server: Res<AssetServer>,
    mut welcome_messages: MessageWriter<ToClients<Hi>>
) {
    if q_new_clients.is_empty() { return }
    let Some(wc) = &world_config.config else {
        warn!("got a joined player, but world config is not loaded! waiting until it is...");
        for joined_player in &q_new_clients {
            commands.entity(joined_player.0).insert(PendingPlayer);
        }
        return;
    };
    for joined_player in &q_new_clients {
        debug!(?joined_player, "new player!");
        welcome_messages.write(ToClients {
            mode: SendMode::Direct(ClientId::Client(joined_player.1.network_entity)),
            message: Hi {
                you_are: joined_player.0
            },
        });
        join_player(joined_player.0, commands.reborrow(), wc, planets, &asset_server);
    }
}
pub fn handle_pending_players(
    mut commands: Commands,
    pending_players: Query<Entity, With<PendingPlayer>>,
    world_config: Res<WorldConfigResource>,
    planets: Query<(&Transform, &LinearVelocity, &Planet)>,
    asset_server: Res<AssetServer>,
    mut welcome_messages: MessageWriter<ToClients<Hi>>
) {
    if pending_players.is_empty() { return };
    let Some(wc) = &world_config.config else {
        warn!("there are pending players, but world config is not loaded! waiting until it is...");
        return;
    };

    for pending_player in &pending_players {
        warn!(?pending_player, "reprocessing pending player");
        join_player(pending_player, commands.reborrow(), wc, planets, &asset_server);
    }
}

pub fn spawn_singleplayer_player(mut commands: Commands) {
    commands.spawn((
        ConnectedGameEntity { network_entity: Entity::PLACEHOLDER },
        Me,
    ));
}