~starkingdoms/starkingdoms

ref: d733c4e3b55f6eaed09948f4309c32ab33f4c02b starkingdoms/crates/unified/src/client/mod.rs -rw-r--r-- 4.1 KiB
d733c4e3 — core feat: avian! 28 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
mod colors;
mod key_input;
mod net;
mod particles;
mod parts;
mod planet;
mod starfield;
mod ui;
mod zoom;

use crate::client::key_input::key_input_plugin;
use crate::client::net::set_config;
use crate::client::parts::parts_plugin;
use crate::client::planet::indicators::indicators_plugin;
use crate::client::starfield::starfield_plugin;
use crate::client::ui::ui_plugin;
use crate::client::zoom::zoom_plugin;
use crate::ecs::{CursorWorldCoordinates, MainCamera, Part, Player};
use aeronet_websocket::client::WebSocketClient;
use bevy::anti_alias::fxaa::Fxaa;
use bevy::core_pipeline::tonemapping::DebandDither;
use bevy::dev_tools::picking_debug::DebugPickingMode;
use bevy::post_process::bloom::Bloom;
use crate::prelude::*;
use bevy::window::PrimaryWindow;
use planet::incoming_planets::incoming_planets_plugin;

pub struct ClientPlugin {
    pub server: String,
}
impl Plugin for ClientPlugin {
    fn build(&self, app: &mut App) {
        let server = self.server.clone();
        app
            .insert_resource(CursorWorldCoordinates(None))
            .add_systems(Startup, move |mut commands: Commands| {
                let config = net::websocket_config();

                commands
                    .spawn(Name::new("default-session"))
                    .queue(WebSocketClient::connect(config, server.clone()));
            })
            .add_observer(net::on_connecting)
            .add_observer(net::on_connected)
            .add_observer(net::on_disconnected)
            .add_systems(Startup, setup_graphics)
            .add_systems(Update, update_cursor_position)
            .add_systems(Update, follow_camera)
            .add_systems(Update, find_me)
            .add_systems(Update, set_config)
            .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)
            .insert_resource(DebugPickingMode::Disabled);
    }
}

#[derive(Component)]
pub struct Me;

fn find_me(
    mut commands: Commands,
    q_clients: Query<(Entity, &Player, &Part), Added<Player>>,
    asset_server: Res<AssetServer>,
) {
    for (entity, player, part) in q_clients.iter() {
        if player.client == entity {
            commands.entity(entity).insert(Me);
            let mut heart_sprite =
                Sprite::from_image(asset_server.load("sprites/hearty_heart.png"));
            heart_sprite.custom_size = Some(Vec2::new(
                part.strong_config.physics.width,
                part.strong_config.physics.height,
            ));
            heart_sprite.color = Color::srgb(20.0, 0.0, 0.0);

            commands.spawn((
                ChildOf(entity),
                heart_sprite,
                Transform::from_xyz(0.0, 0.0, 10.0),
            ));
        }
    }
}

fn setup_graphics(mut commands: Commands) {
    commands
        .spawn(Camera2d)
        .insert(Camera {
            clear_color: ClearColorConfig::Custom(Color::BLACK),
            ..default()
        })
        .insert(Bloom::default())
        .insert(DebandDither::Enabled)
        .insert(Fxaa::default())
        .insert(MainCamera);
}

fn follow_camera(
    mut camera: Query<&mut Transform, (With<MainCamera>, Without<Me>)>,
    player: Query<&Transform, With<Me>>,
) {
    let mut camera = camera.single_mut().unwrap();
    let Ok(player) = player.single() else {
        return;
    };
    camera.translation = player.translation;
}

fn update_cursor_position(
    q_windows: Query<&Window, With<PrimaryWindow>>,
    q_camera: Query<(&Camera, &GlobalTransform), With<MainCamera>>,
    mut coords: ResMut<CursorWorldCoordinates>,
) {
    let (camera, camera_transform) = q_camera.single().unwrap();
    let window = q_windows.single().unwrap();

    if let Some(world_position) = window
        .cursor_position()
        .and_then(|cursor| camera.viewport_to_world(camera_transform, cursor).ok())
        .map(|ray| ray.origin.truncate())
    {
        coords.0 = Some(world_position);
    } else {
        coords.0 = None;
    }
}