kubi/kubi-server/src/auth.rs
griffi-gh d5e8b4c6b7 add raw-evt feature, fix clippy warnings
`raw-evt` is enable by default
forcing it off is required for kb input on android
mouse input is not supported without it yet though
2023-06-04 15:16:25 +02:00

185 lines
6.1 KiB
Rust

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::{
messages::{
ClientToServerMessage,
ServerToClientMessage,
InitData,
ClientInitData,
C_CLIENT_HELLO,
},
client::{Client, ClientId, Username},
channels::{CHANNEL_AUTH, CHANNEL_SYS_EVT},
},
player::{Player, PLAYER_HEALTH},
transform::Transform, entity::{Entity, Health}
};
use crate::{
config::ConfigTable,
server::{ServerEvents, UdpServer, IsMessageOfType},
client::{ClientAddress, ClientAddressMap}
};
pub use kubi_shared::networking::client::ClientIdMap;
pub fn authenticate_players(
storages: AllStoragesView,
) {
let mut client_entity_map = storages.borrow::<UniqueViewMut<ClientIdMap>>().unwrap();
let mut client_addr_map = storages.borrow::<UniqueViewMut<ClientAddressMap>>().unwrap();
let server = storages.borrow::<NonSendSync<UniqueView<UdpServer>>>().unwrap();
let events = storages.borrow::<UniqueView<ServerEvents>>().unwrap();
let config = storages.borrow::<UniqueView<ConfigTable>>().unwrap();
for event in &events.0 {
// NOT using `check_message_auth` here because the user is not authed yet!
let ServerEvent::Receive(client_addr, data) = event else{
continue
};
if !event.is_message_of_type::<C_CLIENT_HELLO>() {
continue
}
let Some(client) = server.0.client(client_addr) else {
log::error!("Client doesn't exist");
continue
};
let Ok(parsed_message) = postcard::from_bytes(data) else {
log::error!("Malformed message");
continue
};
let ClientToServerMessage::ClientHello { username, password } = parsed_message else {
unreachable!()
};
log::info!("ClientHello; username={} password={:?}", username, password);
// Handle password auth
if let Some(server_password) = &config.server.password {
if let Some(user_password) = &password {
if server_password != user_password {
client.borrow_mut().send(
postcard::to_allocvec(&ServerToClientMessage::ServerFuckOff {
reason: "Incorrect password".into()
}).unwrap().into_boxed_slice(),
CHANNEL_AUTH,
SendMode::Reliable
);
continue
}
} else {
client.borrow_mut().send(
postcard::to_allocvec(&ServerToClientMessage::ServerFuckOff {
reason: "This server is password protected".into()
}).unwrap().into_boxed_slice(),
CHANNEL_AUTH,
SendMode::Reliable
);
continue
}
}
//Find the player ID
let max_clients = config.server.max_clients as ClientId;
let Some(client_id) = (0..max_clients).find(|id| {
!client_entity_map.0.contains_key(id)
}) else {
client.borrow_mut().send(
postcard::to_allocvec(&ServerToClientMessage::ServerFuckOff {
reason: "Can't find a free spot for you!".into()
}).unwrap().into_boxed_slice(),
CHANNEL_AUTH,
SendMode::Reliable
);
continue
};
//Spawn the user
let entity_id = {
storages.borrow::<EntitiesViewMut>().unwrap().add_entity((
&mut storages.borrow::<ViewMut<Entity>>().unwrap(),
&mut storages.borrow::<ViewMut<Player>>().unwrap(),
&mut storages.borrow::<ViewMut<Health>>().unwrap(),
&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(Mat4::from_translation(vec3(0., 60., 0.))),
Username(username.clone()),
))
};
//Add the user to the ClientIdMap and ClientAddressMap
client_entity_map.0.insert(client_id, entity_id);
client_addr_map.0.insert(*client_addr, entity_id);
//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! USE URL AS REFERENCE
// https://github.com/griffi-gh/kubi/blob/96a6693faa14580fca560f4a64f0e88e595a8ca0/kubi-server/src/world.rs#L144
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: init_data
}).unwrap().into_boxed_slice(),
CHANNEL_AUTH,
SendMode::Reliable
);
log::info!("{username}({client_id}) joined the game!")
}
}