~starkingdoms/starkingdoms

ref: 103444e57478b2f702c26a6dfb9a62b34a60e5fe starkingdoms/crates/unified/src/server/player.rs -rw-r--r-- 5.1 KiB
103444e5 — core chore(wasm)!: fix compilations on webassembly 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
114
115
116
117
118
119
120
121
122
123
124
use std::f32::consts::PI;

use bevy::prelude::*;
use bevy_rapier2d::prelude::{AdditionalMassProperties, Collider, ExternalForce, ExternalImpulse, MassProperties, ReadMassProperties, RigidBody, Sensor};
use bevy_replicon::prelude::{ConnectedClient, FromClient, Replicated};
use crate::config::planet::Planet;
use crate::ecs::{Part, PartBundle, Player, PlayerThrust, ThrustEvent};
use crate::server::world_config::WorldConfigResource;

pub fn player_management_plugin(app: &mut App) {
    app
        .add_systems(PreUpdate, reset_movement)
        .add_systems(Update, (handle_new_players, player_thrust));
}

fn reset_movement(
    mut players: Query<(&mut ExternalForce, &mut ExternalImpulse)>
) {
    for (mut force, mut impulse) in &mut players {
        force.force = Vec2::ZERO;
        force.torque = 0.0;
        impulse.impulse = Vec2::ZERO;
    }
}

fn handle_new_players(mut commands: Commands, q_new_clients: Query<Entity, Added<ConnectedClient>>, world_config: Res<WorldConfigResource>, planets: Query<(&Transform, &Planet)>) {
    let Some(wc) = &world_config.config else { return; };
    for joined_player in &q_new_clients {
        // find earth
        let (earth_pos, earth_planet) = planets.iter().find(|p| p.1.name == "Earth").expect("earth is missing? (check that the planet is named 'Earth')");
        let angle = rand::random::<f32>() * std::f32::consts::TAU;
        let offset = earth_planet.radius + 150.0;
        let mut new_transform = Transform::from_xyz(angle.cos() * offset, angle.sin() * offset, 0.0);
        new_transform.rotate_z(angle);
        new_transform.translation += earth_pos.translation;


        commands.entity(joined_player)
            .insert(PartBundle {
                part: Part {
                    sprite: "textures/hearty.png".to_string(),
                    width: wc.part.default_width,
                    height: wc.part.default_height,
                    mass: wc.part.default_mass
                },
                transform: new_transform,
                collider: Collider::cuboid(wc.part.default_width / 2.0, wc.part.default_height / 2.0),
                additional_mass_properties: AdditionalMassProperties::MassProperties(MassProperties {
                    local_center_of_mass: Vec2::ZERO,
                    mass: wc.part.default_mass,
                    principal_inertia: 7.5,
                })
            })
            .insert(Replicated)
            .insert(ExternalForce::default())
            .insert(PlayerThrust::default())
            .insert(Player {
                client: joined_player,
            });
    }
}

fn player_thrust(
    mut players: Query<(&Transform, &mut ExternalForce, &mut PlayerThrust)>,
    mut thrust_event: EventReader<FromClient<ThrustEvent>>,
    world_config: Res<WorldConfigResource>,
) {
    use ThrustEvent::*;
    for event in thrust_event.read() {
        let FromClient { client_entity, event } = event;
        let Ok((_, _, mut thrust)) = players.get_mut(*client_entity) else { continue };
        match *event {
            Up(on) => thrust.up = on,
            Down(on) => thrust.down = on,
            Left(on) => thrust.left = on,
            Right(on) => thrust.right = on,
        }
    }
    for (transform, mut force, thrust) in &mut players {
        let Some(world_config) = &world_config.config else { return; };

        let forward = (transform.rotation * Vec3::Y).xy();
        let mut external_force = ExternalForce::default();
        let mut thrusters = [0.0; 4]; // counterclockwise wrt +y axis
        if thrust.up {
            thrusters[1] = 1.0;
            thrusters[2] = 1.0;
        }
        if thrust.down {
            thrusters[0] = 1.0;
            thrusters[3] = 1.0;
        }
        if thrust.left {
            thrusters[0] = 1.0;
            thrusters[2] = 1.0;
        }
        if thrust.right {
            thrusters[1] = 1.0;
            thrusters[3] = 1.0;
        }
        let half_size = Vec2::new(world_config.part.default_width/2.0, world_config.part.default_height/2.0).length();
        external_force += ExternalForce::at_point(
            -forward*thrusters[0]*world_config.hearty.thrust,
            transform.translation.xy() + half_size*Vec2::new((1.0*PI/4.0).cos(), (1.0*PI/4.0).sin()).rotate(forward),
            transform.translation.xy(),
        );
        external_force += ExternalForce::at_point(
            forward*thrusters[1]*world_config.hearty.thrust,
            transform.translation.xy() + half_size*Vec2::new((3.0*PI/4.0).cos(), (3.0*PI/4.0).sin()).rotate(forward),
            transform.translation.xy(),
        );
        external_force += ExternalForce::at_point(
            forward*thrusters[2]*world_config.hearty.thrust,
            transform.translation.xy() + half_size*Vec2::new((5.0*PI/4.0).cos(), (5.0*PI/4.0).sin()).rotate(forward),
            transform.translation.xy(),
        );
        external_force += ExternalForce::at_point(
            -forward*thrusters[3]*world_config.hearty.thrust,
            transform.translation.xy() + half_size*Vec2::new((7.0*PI/4.0).cos(), (7.0*PI/4.0).sin()).rotate(forward),
            transform.translation.xy(),
        );
        *force += external_force;
    }
}