~starkingdoms/starkingdoms

ref: 71ade52ef032a59f7fc96e236eefa00dbc6285d7 starkingdoms/crates/unified/src/client/mod.rs -rw-r--r-- 4.1 KiB
71ade52eghostly_zsh even better animation 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;
    }
}