mirror of
https://github.com/griffi-gh/kubi.git
synced 2024-12-22 03:48:21 -06:00
Big refactor + Early wip position sync /connect events in multiplayer
This commit is contained in:
parent
3a50065cc5
commit
96a6693faa
|
@ -1,4 +1,5 @@
|
|||
use shipyard::{UniqueView, NonSendSync, EntitiesViewMut, ViewMut, UniqueViewMut, AllStoragesView};
|
||||
use glam::{Vec3, Mat4, vec3};
|
||||
use shipyard::{UniqueView, NonSendSync, EntitiesViewMut, ViewMut, UniqueViewMut, AllStoragesView, IntoIter};
|
||||
use uflow::{server::Event as ServerEvent, SendMode};
|
||||
use kubi_shared::{
|
||||
networking::{
|
||||
|
@ -6,9 +7,11 @@ use kubi_shared::{
|
|||
ClientToServerMessage,
|
||||
ServerToClientMessage,
|
||||
InitData,
|
||||
C_CLIENT_HELLO
|
||||
ClientInitData,
|
||||
C_CLIENT_HELLO,
|
||||
},
|
||||
client::{Client, ClientId}, channels::CHANNEL_AUTH
|
||||
client::{Client, ClientId, Username},
|
||||
channels::{CHANNEL_AUTH, CHANNEL_SYS_EVT},
|
||||
},
|
||||
player::{Player, PLAYER_HEALTH},
|
||||
transform::Transform, entity::{Entity, Health}
|
||||
|
@ -99,13 +102,15 @@ pub fn authenticate_players(
|
|||
&mut storages.borrow::<ViewMut<Client>>().unwrap(),
|
||||
&mut storages.borrow::<ViewMut<ClientAddress>>().unwrap(),
|
||||
&mut storages.borrow::<ViewMut<Transform>>().unwrap(),
|
||||
&mut storages.borrow::<ViewMut<Username>>().unwrap(),
|
||||
), (
|
||||
Entity,
|
||||
Player,
|
||||
Health::new(PLAYER_HEALTH),
|
||||
Client(client_id),
|
||||
ClientAddress(*client_addr),
|
||||
Transform::default(),
|
||||
Transform(Mat4::from_translation(vec3(0., 60., 0.))),
|
||||
Username(username.clone()),
|
||||
))
|
||||
};
|
||||
|
||||
|
@ -113,12 +118,60 @@ pub fn authenticate_players(
|
|||
client_entity_map.0.insert(client_id, entity_id);
|
||||
client_addr_map.0.insert(*client_addr, entity_id);
|
||||
|
||||
//Approve the user
|
||||
//Create init data
|
||||
let init_data = {
|
||||
let mut user = None;
|
||||
let mut users = Vec::with_capacity(client_entity_map.0.len() - 1);
|
||||
for (client, username, transform, &health) in (
|
||||
&storages.borrow::<ViewMut<Client>>().unwrap(),
|
||||
&storages.borrow::<ViewMut<Username>>().unwrap(),
|
||||
&storages.borrow::<ViewMut<Transform>>().unwrap(),
|
||||
&storages.borrow::<ViewMut<Health>>().unwrap(),
|
||||
).iter() {
|
||||
let (_, direction, position) = transform.0.to_scale_rotation_translation();
|
||||
let idata = ClientInitData {
|
||||
client_id: client.0,
|
||||
username: username.0.clone(),
|
||||
position,
|
||||
velocity: Vec3::ZERO,
|
||||
direction,
|
||||
health,
|
||||
};
|
||||
if client_id == client.0 {
|
||||
user = Some(idata);
|
||||
} else {
|
||||
users.push(idata);
|
||||
}
|
||||
}
|
||||
InitData {
|
||||
user: user.unwrap(),
|
||||
users
|
||||
}
|
||||
};
|
||||
|
||||
//Announce new player to other clients
|
||||
{
|
||||
let message = &ServerToClientMessage::PlayerConnected {
|
||||
init: init_data.user.clone()
|
||||
};
|
||||
for (other_client_addr, _) in client_addr_map.0.iter() {
|
||||
//TODO: ONLY JOINED CLIENTS HERE!
|
||||
let Some(other_client) = server.0.client(other_client_addr) else {
|
||||
log::error!("Other client doesn't exist");
|
||||
continue
|
||||
};
|
||||
other_client.borrow_mut().send(
|
||||
postcard::to_allocvec(&message).unwrap().into_boxed_slice(),
|
||||
CHANNEL_SYS_EVT,
|
||||
SendMode::Reliable
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//Approve the user and send init data
|
||||
client.borrow_mut().send(
|
||||
postcard::to_allocvec(&ServerToClientMessage::ServerHello {
|
||||
init: InitData {
|
||||
users: vec![] //TODO create init data
|
||||
}
|
||||
init: init_data
|
||||
}).unwrap().into_boxed_slice(),
|
||||
CHANNEL_AUTH,
|
||||
SendMode::Reliable
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
use shipyard::{Component, EntityId, Unique, AllStoragesView};
|
||||
use shipyard::{Component, EntityId, Unique, AllStoragesView, UniqueView, NonSendSync, View, Get};
|
||||
use hashbrown::HashMap;
|
||||
use std::net::SocketAddr;
|
||||
pub use kubi_shared::networking::client::ClientIdMap;
|
||||
use uflow::server::Event as ServerEvent;
|
||||
use kubi_shared::networking::{
|
||||
client::{ClientIdMap, Client},
|
||||
messages::{ClientToServerMessage, C_POSITION_CHANGED}
|
||||
};
|
||||
use crate::server::{ServerEvents, IsMessageOfType, UdpServer};
|
||||
|
||||
#[derive(Component, Clone, Copy)]
|
||||
pub struct ClientAddress(pub SocketAddr);
|
||||
|
@ -18,3 +23,40 @@ pub fn init_client_maps(
|
|||
storages.add_unique(ClientIdMap::new());
|
||||
storages.add_unique(ClientAddressMap::new());
|
||||
}
|
||||
|
||||
pub fn sync_client_positions(
|
||||
server: NonSendSync<UniqueView<UdpServer>>,
|
||||
events: UniqueView<ServerEvents>,
|
||||
addr_map: UniqueView<ClientAddressMap>,
|
||||
clients: View<Client>,
|
||||
) {
|
||||
for event in &events.0 {
|
||||
let ServerEvent::Receive(client_addr, data) = event else{
|
||||
continue
|
||||
};
|
||||
if !event.is_message_of_type::<C_POSITION_CHANGED>() {
|
||||
continue
|
||||
}
|
||||
let Some(client) = server.0.client(client_addr) else {
|
||||
log::error!("Client doesn't exist");
|
||||
continue
|
||||
};
|
||||
let Some(&entity_id) = addr_map.0.get(client_addr) else {
|
||||
log::error!("Client not authenticated");
|
||||
continue
|
||||
};
|
||||
let Ok(&Client(client_id)) = (&clients).get(entity_id) else {
|
||||
log::error!("Entity ID is invalid");
|
||||
continue
|
||||
};
|
||||
let Ok(parsed_message) = postcard::from_bytes(data) else {
|
||||
log::error!("Malformed message");
|
||||
continue
|
||||
};
|
||||
let ClientToServerMessage::PositionChanged { position, velocity, direction } = parsed_message else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,10 +13,11 @@ use uflow::{
|
|||
use lz4_flex::compress_prepend_size as lz4_compress;
|
||||
use anyhow::Result;
|
||||
use std::{rc::Rc, cell::RefCell};
|
||||
use kubi_shared::networking::client::ClientIdMap;
|
||||
use crate::{
|
||||
server::{UdpServer, ServerEvents, IsMessageOfType},
|
||||
config::ConfigTable,
|
||||
client::{ClientAddress, ClientIdMap, ClientAddressMap},
|
||||
client::{ClientAddress, ClientAddressMap},
|
||||
};
|
||||
|
||||
pub mod chunk;
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
use shipyard::Component;
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct Entity;
|
||||
|
||||
#[derive(Component)]
|
||||
#[derive(Component, Serialize, Deserialize, Clone, Copy, Debug)]
|
||||
pub struct Health {
|
||||
pub current: u8,
|
||||
pub max: u8,
|
||||
|
@ -16,3 +17,19 @@ impl Health {
|
|||
}
|
||||
}
|
||||
}
|
||||
impl PartialEq for Health {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.current == other.current
|
||||
}
|
||||
}
|
||||
impl Eq for Health {}
|
||||
impl PartialOrd for Health {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
self.current.partial_cmp(&other.current)
|
||||
}
|
||||
}
|
||||
impl Ord for Health {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.current.cmp(&other.current)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,3 +3,4 @@ pub const CHANNEL_AUTH: usize = 1;
|
|||
pub const CHANNEL_WORLD: usize = 2;
|
||||
pub const CHANNEL_BLOCK: usize = 3;
|
||||
pub const CHANNEL_MOVE: usize = 4;
|
||||
pub const CHANNEL_SYS_EVT: usize = 5;
|
||||
|
|
|
@ -4,16 +4,24 @@ use nohash_hasher::BuildNoHashHasher;
|
|||
|
||||
pub type ClientId = u16;
|
||||
|
||||
#[derive(Component, Clone, Debug)]
|
||||
#[repr(transparent)]
|
||||
pub struct Username(pub String);
|
||||
|
||||
#[derive(Component, Clone, Copy, Debug)]
|
||||
#[repr(transparent)]
|
||||
pub struct Client(pub ClientId);
|
||||
|
||||
#[derive(Unique)]
|
||||
#[repr(transparent)]
|
||||
pub struct ClientIdMap(pub HashMap<ClientId, EntityId, BuildNoHashHasher<ClientId>>);
|
||||
|
||||
impl ClientIdMap {
|
||||
pub fn new() -> Self {
|
||||
Self(HashMap::with_capacity_and_hasher(16, BuildNoHashHasher::default()))
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ClientIdMap {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use glam::{Vec3, IVec3, Quat};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use crate::{chunk::BlockData, queue::QueuedBlock};
|
||||
use crate::{chunk::BlockData, queue::QueuedBlock, entity::Health};
|
||||
use super::client::ClientId;
|
||||
|
||||
//protocol id not used yet
|
||||
|
@ -41,6 +41,7 @@ pub const S_PLAYER_POSITION_CHANGED: u8 = 2;
|
|||
pub const S_CHUNK_RESPONSE: u8 = 3;
|
||||
pub const S_QUEUE_BLOCK: u8 = 4;
|
||||
pub const S_PLAYER_CONNECTED: u8 = 5;
|
||||
pub const S_PLAYER_DISCONNECTED: u8 = 6;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[repr(u8)]
|
||||
|
@ -52,7 +53,7 @@ pub enum ServerToClientMessage {
|
|||
reason: String,
|
||||
} = S_SERVER_FUCK_OFF,
|
||||
PlayerPositionChanged {
|
||||
client_id: u8,
|
||||
client_id: ClientId,
|
||||
position: Vec3,
|
||||
direction: Quat,
|
||||
} = S_PLAYER_POSITION_CHANGED,
|
||||
|
@ -69,22 +70,27 @@ pub enum ServerToClientMessage {
|
|||
item: QueuedBlock
|
||||
} = S_QUEUE_BLOCK,
|
||||
PlayerConnected {
|
||||
init: UserInitData
|
||||
init: ClientInitData
|
||||
} = S_PLAYER_CONNECTED,
|
||||
PlayerDisconnected {
|
||||
id: ClientId
|
||||
} = S_PLAYER_DISCONNECTED,
|
||||
}
|
||||
|
||||
//---
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct UserInitData {
|
||||
pub struct ClientInitData {
|
||||
pub client_id: ClientId,
|
||||
pub username: String,
|
||||
pub position: Vec3,
|
||||
pub velocity: Vec3,
|
||||
pub direction: Quat,
|
||||
pub health: Health,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct InitData {
|
||||
pub users: Vec<UserInitData>
|
||||
pub user: ClientInitData,
|
||||
pub users: Vec<ClientInitData>
|
||||
}
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
use shipyard::Component;
|
||||
use crate::block::Block;
|
||||
|
||||
pub const PLAYER_HEALTH: u8 = 20;
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct Player;
|
||||
|
||||
#[derive(Component, Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||
#[repr(transparent)]
|
||||
pub struct PlayerHolding(pub Option<Block>);
|
||||
|
|
|
@ -2,7 +2,9 @@ use shipyard::Component;
|
|||
use glam::{Mat4, Mat3};
|
||||
|
||||
#[derive(Component, Clone, Copy, Debug, Default)]
|
||||
#[repr(transparent)]
|
||||
pub struct Transform(pub Mat4);
|
||||
|
||||
#[derive(Component, Clone, Copy, Debug, Default)]
|
||||
#[repr(transparent)]
|
||||
pub struct Transform2d(pub Mat3);
|
||||
|
|
|
@ -2,7 +2,8 @@ use shipyard::{UniqueViewMut, UniqueView, View, IntoIter, ViewMut, EntitiesViewM
|
|||
use glium::glutin::event::VirtualKeyCode;
|
||||
use kubi_shared::{
|
||||
block::Block,
|
||||
queue::QueuedBlock,
|
||||
queue::QueuedBlock,
|
||||
player::PlayerHolding,
|
||||
};
|
||||
use crate::{
|
||||
player::MainPlayer,
|
||||
|
@ -11,14 +12,6 @@ use crate::{
|
|||
events::{EventComponent, player_actions::PlayerActionEvent},
|
||||
};
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct PlayerHolding(pub Block);
|
||||
impl Default for PlayerHolding {
|
||||
fn default() -> Self {
|
||||
Self(Block::Cobblestone)
|
||||
}
|
||||
}
|
||||
|
||||
const BLOCK_KEY_MAP: &[(VirtualKeyCode, Block)] = &[
|
||||
(VirtualKeyCode::Key1, Block::Cobblestone),
|
||||
(VirtualKeyCode::Key2, Block::Planks),
|
||||
|
@ -38,7 +31,7 @@ fn pick_block_with_number_keys(
|
|||
let Some((_, mut holding)) = (&main_player, &mut holding).iter().next() else { return };
|
||||
for &(key, block) in BLOCK_KEY_MAP {
|
||||
if input.keyboard_state.contains(&key) {
|
||||
holding.0 = block;
|
||||
holding.0 = Some(block);
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -63,9 +56,9 @@ fn block_placement_system(
|
|||
let Some(ray) = ray.0 else { return };
|
||||
//get coord and block type
|
||||
let (place_position, place_block) = if action_place {
|
||||
if block.0 == Block::Air { return }
|
||||
if block.0.is_none() { return }
|
||||
let position = (ray.position - ray.direction * (RAYCAST_STEP + 0.001)).floor().as_ivec3();
|
||||
(position, block.0)
|
||||
(position, block.0.unwrap())
|
||||
} else {
|
||||
(ray.block_position, Block::Air)
|
||||
};
|
||||
|
|
|
@ -29,6 +29,8 @@ use world::{
|
|||
};
|
||||
use player::send_player_movement_events;
|
||||
|
||||
use self::player::{receive_player_movement_events, receive_player_connect_events};
|
||||
|
||||
#[derive(Unique, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum GameType {
|
||||
Singleplayer,
|
||||
|
@ -120,8 +122,14 @@ pub fn update_networking() -> Workload {
|
|||
handle_disconnect,
|
||||
).into_sequential_workload().run_if(is_join_state::<{ClientJoinState::Connected as u8}>),
|
||||
(
|
||||
recv_block_place_events
|
||||
).run_if(is_join_state::<{ClientJoinState::Joined as u8}>).run_if(is_ingame_or_loading),
|
||||
(
|
||||
receive_player_connect_events
|
||||
),
|
||||
(
|
||||
recv_block_place_events,
|
||||
receive_player_movement_events,
|
||||
).into_workload()
|
||||
).into_sequential_workload().run_if(is_join_state::<{ClientJoinState::Joined as u8}>).run_if(is_ingame_or_loading),
|
||||
inject_network_responses_into_manager_queue.run_if(is_ingame_or_loading).skip_if_missing_unique::<ChunkTaskManager>(),
|
||||
).into_sequential_workload()
|
||||
}
|
||||
|
@ -131,7 +139,7 @@ pub fn update_networking_late() -> Workload {
|
|||
(
|
||||
send_block_place_events,
|
||||
send_player_movement_events,
|
||||
).into_sequential_workload().run_if(is_join_state::<{ClientJoinState::Joined as u8}>),
|
||||
).into_workload().run_if(is_join_state::<{ClientJoinState::Joined as u8}>),
|
||||
flush_client,
|
||||
).into_sequential_workload()
|
||||
}
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
use shipyard::{UniqueViewMut, View, IntoIter};
|
||||
use glam::Mat4;
|
||||
use shipyard::{UniqueViewMut, View, IntoIter, AllStoragesViewMut, ViewMut, IntoWithId};
|
||||
use uflow::{client::Event as ClientEvent, SendMode};
|
||||
use kubi_shared::networking::{
|
||||
messages::{ClientToServerMessage, ServerToClientMessage, S_SERVER_HELLO},
|
||||
state::ClientJoinState,
|
||||
channels::CHANNEL_AUTH,
|
||||
use kubi_shared::{
|
||||
networking::{
|
||||
messages::{ClientToServerMessage, ServerToClientMessage, S_SERVER_HELLO},
|
||||
state::ClientJoinState,
|
||||
channels::CHANNEL_AUTH,
|
||||
client::{Username, Client},
|
||||
},
|
||||
transform::Transform, entity::Health
|
||||
};
|
||||
use super::{UdpClient, NetworkEvent};
|
||||
use crate::player::MainPlayer;
|
||||
use super::{UdpClient, NetworkEvent, player::add_net_player};
|
||||
|
||||
pub fn set_client_join_state_to_connected(
|
||||
mut join_state: UniqueViewMut<ClientJoinState>
|
||||
|
@ -16,14 +22,15 @@ pub fn set_client_join_state_to_connected(
|
|||
|
||||
pub fn say_hello(
|
||||
mut client: UniqueViewMut<UdpClient>,
|
||||
main_player: View<MainPlayer>,
|
||||
username: View<Username>
|
||||
) {
|
||||
let username = (&main_player, &username).iter().next().unwrap().1.0.clone();
|
||||
let password = None;
|
||||
log::info!("Authenticating");
|
||||
client.0.send(
|
||||
postcard::to_allocvec(
|
||||
&ClientToServerMessage::ClientHello {
|
||||
username: "Sbeve".into(),
|
||||
password: None
|
||||
}
|
||||
&ClientToServerMessage::ClientHello { username, password }
|
||||
).unwrap().into_boxed_slice(),
|
||||
CHANNEL_AUTH,
|
||||
SendMode::Reliable
|
||||
|
@ -31,26 +38,63 @@ pub fn say_hello(
|
|||
}
|
||||
|
||||
pub fn check_server_hello_response(
|
||||
network_events: View<NetworkEvent>,
|
||||
mut join_state: UniqueViewMut<ClientJoinState>
|
||||
mut storages: AllStoragesViewMut,
|
||||
) {
|
||||
for event in network_events.iter() {
|
||||
//Check if we got the message and extract the init data from it
|
||||
let Some(init) = storages.borrow::<View<NetworkEvent>>().unwrap().iter().find_map(|event| {
|
||||
let ClientEvent::Receive(data) = &event.0 else {
|
||||
continue
|
||||
return None
|
||||
};
|
||||
if !event.is_message_of_type::<S_SERVER_HELLO>() {
|
||||
continue
|
||||
return None
|
||||
}
|
||||
let Ok(parsed_message) = postcard::from_bytes(data) else {
|
||||
log::error!("Malformed message");
|
||||
continue
|
||||
return None
|
||||
};
|
||||
let ServerToClientMessage::ServerHello { init: _ } = parsed_message else {
|
||||
let ServerToClientMessage::ServerHello { init } = parsed_message else {
|
||||
unreachable!()
|
||||
};
|
||||
//TODO handle init data
|
||||
*join_state = ClientJoinState::Joined;
|
||||
log::info!("Joined the server!");
|
||||
return;
|
||||
Some(init)
|
||||
}) else { return };
|
||||
|
||||
// struct ClientInitData {
|
||||
// client_id: ClientId,
|
||||
// username: String,
|
||||
// position: Vec3,
|
||||
// velocity: Vec3,
|
||||
// direction: Quat,
|
||||
// health: Health,
|
||||
// }
|
||||
|
||||
//Add components to main player
|
||||
{
|
||||
let entity = (&storages.borrow::<View<MainPlayer>>().unwrap()).iter().with_id().next().unwrap().0;
|
||||
storages.add_component(entity, Client(init.user.client_id));
|
||||
}
|
||||
|
||||
//Modify main player
|
||||
{
|
||||
for (entity, (_, mut username, mut transform, mut health)) in (
|
||||
&storages.borrow::<View<MainPlayer>>().unwrap(),
|
||||
&mut storages.borrow::<ViewMut<Username>>().unwrap(),
|
||||
&mut storages.borrow::<ViewMut<Transform>>().unwrap(),
|
||||
&mut storages.borrow::<ViewMut<Health>>().unwrap(),
|
||||
).iter().with_id() {
|
||||
username.0 = init.user.username.clone();
|
||||
transform.0 = Mat4::from_rotation_translation(init.user.direction, init.user.position);
|
||||
*health = init.user.health;
|
||||
}
|
||||
}
|
||||
|
||||
//Init players
|
||||
for init_data in init.users {
|
||||
add_net_player(&mut storages, init_data);
|
||||
}
|
||||
|
||||
// Set state to connected
|
||||
let mut join_state = storages.borrow::<UniqueViewMut<ClientJoinState>>().unwrap();
|
||||
*join_state = ClientJoinState::Joined;
|
||||
|
||||
log::info!("Joined the server!");
|
||||
}
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
use glam::Vec3;
|
||||
use hashbrown::HashMap;
|
||||
use nohash_hasher::BuildNoHashHasher;
|
||||
use shipyard::{UniqueViewMut, View, IntoIter, Unique, EntityId, AllStoragesView};
|
||||
use glam::{Vec3, Mat4};
|
||||
use shipyard::{UniqueViewMut, View, IntoIter, AllStoragesView, AllStoragesViewMut, UniqueView, ViewMut, Get};
|
||||
use uflow::{SendMode, client::Event as ClientEvent};
|
||||
use kubi_shared::networking::{
|
||||
messages::{ClientToServerMessage, ServerToClientMessage, S_PLAYER_POSITION_CHANGED},
|
||||
channels::CHANNEL_MOVE,
|
||||
client::{ClientId, ClientIdMap},
|
||||
use kubi_shared::{
|
||||
player::{Player, PlayerHolding},
|
||||
entity::Entity,
|
||||
transform::Transform,
|
||||
networking::{
|
||||
messages::{ClientToServerMessage, ServerToClientMessage, S_PLAYER_POSITION_CHANGED, ClientInitData},
|
||||
channels::CHANNEL_MOVE,
|
||||
client::{ClientIdMap, Username, Client},
|
||||
},
|
||||
};
|
||||
use crate::events::player_actions::PlayerActionEvent;
|
||||
use super::{UdpClient, NetworkEvent};
|
||||
|
@ -17,8 +20,33 @@ pub fn init_client_map(
|
|||
storages.add_unique(ClientIdMap::new());
|
||||
}
|
||||
|
||||
pub fn add_net_player() {
|
||||
//TODO
|
||||
pub fn add_net_player(
|
||||
storages: &mut AllStoragesViewMut,
|
||||
init: ClientInitData
|
||||
) {
|
||||
// struct ClientInitData {
|
||||
// client_id: ClientId,
|
||||
// username: String,
|
||||
// position: Vec3,
|
||||
// velocity: Vec3,
|
||||
// direction: Quat,
|
||||
// health: Health,
|
||||
// }
|
||||
|
||||
//Spawn player locally
|
||||
let entity_id = storages.add_entity((
|
||||
Username(init.username),
|
||||
Client(init.client_id),
|
||||
Player,
|
||||
Entity,
|
||||
init.health,
|
||||
Transform(Mat4::from_rotation_translation(init.direction, init.position)),
|
||||
PlayerHolding::default(),
|
||||
));
|
||||
|
||||
//Add it to the client id map
|
||||
let mut client_id_map = storages.borrow::<UniqueViewMut<ClientIdMap>>().unwrap();
|
||||
client_id_map.0.insert(init.client_id, entity_id);
|
||||
}
|
||||
|
||||
pub fn send_player_movement_events(
|
||||
|
@ -42,29 +70,60 @@ pub fn send_player_movement_events(
|
|||
}
|
||||
|
||||
pub fn receive_player_movement_events(
|
||||
mut transforms: ViewMut<Transform>,
|
||||
network_events: View<NetworkEvent>,
|
||||
id_map: UniqueView<ClientIdMap>
|
||||
) {
|
||||
for event in network_events.iter() {
|
||||
let ClientEvent::Receive(data) = &event.0 else {
|
||||
continue
|
||||
};
|
||||
|
||||
if !event.is_message_of_type::<S_PLAYER_POSITION_CHANGED>() {
|
||||
continue
|
||||
}
|
||||
|
||||
let Ok(parsed_message) = postcard::from_bytes(data) else {
|
||||
log::error!("Malformed message");
|
||||
continue
|
||||
};
|
||||
|
||||
let ServerToClientMessage::PlayerPositionChanged {
|
||||
client_id, position, direction
|
||||
} = parsed_message else { unreachable!() };
|
||||
//TODO apply position to local player
|
||||
|
||||
let Some(&ent_id) = id_map.0.get(&client_id) else {
|
||||
log::error!("Not in client-id map");
|
||||
continue
|
||||
};
|
||||
|
||||
let mut transform = (&mut transforms).get(ent_id)
|
||||
.expect("invalid player entity id");
|
||||
|
||||
transform.0 = Mat4::from_rotation_translation(direction, position);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn receive_connected_players(
|
||||
network_events: View<NetworkEvent>,
|
||||
pub fn receive_player_connect_events(
|
||||
mut storages: AllStoragesViewMut,
|
||||
) {
|
||||
let messages: Vec<ServerToClientMessage> = storages.borrow::<View<NetworkEvent>>().unwrap().iter().filter_map(|event| {
|
||||
let ClientEvent::Receive(data) = &event.0 else {
|
||||
return None
|
||||
};
|
||||
if !event.is_message_of_type::<S_PLAYER_POSITION_CHANGED>() {
|
||||
return None
|
||||
};
|
||||
let Ok(parsed_message) = postcard::from_bytes(data) else {
|
||||
log::error!("Malformed message");
|
||||
return None
|
||||
};
|
||||
Some(parsed_message)
|
||||
}).collect();
|
||||
|
||||
for message in messages {
|
||||
let ServerToClientMessage::PlayerConnected { init } = message else { unreachable!() };
|
||||
log::info!("player connected: {} (id {})", init.username, init.client_id);
|
||||
add_net_player(&mut storages, init);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
use shipyard::{Component, AllStoragesViewMut};
|
||||
use kubi_shared::{
|
||||
entity::{Entity, Health},
|
||||
player::PLAYER_HEALTH
|
||||
player::{PLAYER_HEALTH, PlayerHolding},
|
||||
networking::client::Username
|
||||
};
|
||||
use crate::{
|
||||
transform::Transform,
|
||||
camera::Camera,
|
||||
fly_controller::FlyController,
|
||||
world::raycast::LookingAtBlock,
|
||||
block_placement::PlayerHolding,
|
||||
};
|
||||
pub use kubi_shared::player::Player;
|
||||
|
||||
|
@ -29,5 +29,6 @@ pub fn spawn_player (
|
|||
FlyController,
|
||||
LookingAtBlock::default(),
|
||||
PlayerHolding::default(),
|
||||
Username("Sbeve".into())
|
||||
));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue