~starkingdoms/starkingdoms

ref: e1dacc56a2f556eee875e4c92b0890a531551a65 starkingdoms/crates/unified/src/client/mod.rs -rw-r--r-- 4.2 KiB
e1dacc56 — core feat: particle effect description 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
125
126
127
128
mod colors;
mod incoming_particles;
mod incoming_parts;
mod key_input;
mod net;
mod starfield;
mod ui;
mod planet;
mod zoom;

use crate::client::incoming_particles::replicated_particles_plugin;
use crate::client::incoming_parts::incoming_parts_plugin;
use planet::incoming_planets::incoming_planets_plugin;
use crate::client::key_input::key_input_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::core_pipeline::bloom::Bloom;
use bevy::core_pipeline::fxaa::Fxaa;
use bevy::core_pipeline::tonemapping::DebandDither;
use bevy::prelude::*;
use bevy::window::PrimaryWindow;
use bevy_replicon::shared::server_entity_map::ServerEntityMap;
use crate::client::planet::indicators::indicators_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_plugins((incoming_planets_plugin, indicators_plugin))
            .add_plugins(incoming_parts_plugin)
            .add_plugins(key_input_plugin)
            .add_plugins(starfield_plugin)
            .add_plugins(ui_plugin)
            .add_plugins(replicated_particles_plugin)
            .add_plugins(zoom_plugin);
    }
}

#[derive(Component)]
pub struct Me;

fn find_me(
    mut commands: Commands,
    q_clients: Query<(Entity, &Player, &Part), Added<Player>>,
    entity_map: Res<ServerEntityMap>,
    asset_server: Res<AssetServer>,
) {
    for (entity, player, part) in q_clients.iter() {
        let this_id_clientside = entity_map.to_client().get(&player.client).unwrap();
        if *this_id_clientside == entity {
            info!("hi! i've been found!");
            commands.entity(entity).insert(Me);
            let mut heart_sprite = Sprite::from_image(asset_server.load("sprites/heart_sprite.png"));
            heart_sprite.custom_size = Some(Vec2::new(part.width, part.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 {
            hdr: true,
            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;
    }
}