~starkingdoms/starkingdoms

ref: 8f2fb8085e0a75d87209a9063ec16b1f679ec345 starkingdoms/crates/unified/src/client/mod.rs -rw-r--r-- 4.1 KiB
8f2fb808 — core replicable colliders 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
use std::net::{SocketAddr, UdpSocket};
use std::time::SystemTime;
use bevy::prelude::*;
use bevy::window::PrimaryWindow;
use bevy_rapier2d::prelude::RigidBody;
use bevy_replicon::prelude::RepliconChannels;
use bevy_replicon_renet2::netcode::{ClientAuthentication, NetcodeClientTransport, NativeSocket};
use bevy_replicon_renet2::renet2::{ConnectionConfig, RenetClient};
use bevy_replicon_renet2::RenetChannelsExt;
use crate::ecs::{Ball, CursorWorldCoordinates, Ground, MainCamera, ReplicableCollider, SendBallHere};

pub struct ClientPlugin {
    pub server: SocketAddr
}
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, channels: Res<RepliconChannels>| {
                let client = RenetClient::new(
                    ConnectionConfig::from_channels(channels.server_configs(), channels.client_configs()),
                    false
                );
                let current_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
                let client_id = current_time.as_millis() as u64;
                let socket = UdpSocket::bind(SocketAddr::new("::1".parse().unwrap(), 0)).unwrap();
                let authentication = ClientAuthentication::Unsecure {
                    client_id,
                    protocol_id: 0,
                    socket_id: 0,
                    server_addr: server,
                    user_data: None
                };
                let transport = NetcodeClientTransport::new(current_time, authentication, NativeSocket::new(socket).unwrap()).unwrap();

                commands.insert_resource(client);
                commands.insert_resource(transport);

                info!(?client_id, "connected!");
            })
            .add_systems(Startup, setup_graphics)
            //.add_systems(Update, add_ball_sprite)
            //.add_systems(Update, add_ground_sprite)
            .add_systems(Update, update_cursor_position)
            .add_systems(Update, teleport_cube_around)
            .add_systems(Update, replicate_colliders);
    }
}

fn setup_graphics(mut commands: Commands) {
    commands.spawn(Camera2d::default())
        .insert(MainCamera);
}

fn replicate_colliders(mut commands: Commands, q: Query<(Entity, &ReplicableCollider), Added<ReplicableCollider>>) {
    for (entity, replicated_collider) in &q {
        commands.entity(entity)
            .insert(replicated_collider.to_collider());
    }
}

fn add_ball_sprite(mut commands: Commands, q: Query<Entity, Added<Ball>>, asset_server: Res<AssetServer>) {
    for item in &q {
        let mut sprite = Sprite::from_image(asset_server.load("textures/earth.png"));
        sprite.custom_size = Some(Vec2::new(100.0, 100.0));

        commands
            .entity(item)
            .insert(sprite);
    }
}
fn add_ground_sprite(mut commands: Commands, q: Query<Entity, Added<Ground>>, asset_server: Res<AssetServer>) {
    for item in &q {
        let mut sprite = Sprite::from_image(asset_server.load("textures/hearty.png"));
        sprite.custom_size = Some(Vec2::new(1000.0, 100.0));

        commands
            .entity(item)
            .insert(sprite);
    }
}

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;
    }
}
fn teleport_cube_around(
    cursor_world_coordinates: Res<CursorWorldCoordinates>,
    button_input: Res<ButtonInput<MouseButton>>,
    mut events: EventWriter<SendBallHere>
) {
    if let Some(position) = cursor_world_coordinates.0 && button_input.pressed(MouseButton::Left) {
        events.write(SendBallHere(position));
    }
}