veloren/server/src/events/player.rs

93 lines
3.5 KiB
Rust
Raw Normal View History

2020-02-16 20:04:06 +00:00
use super::Event;
use crate::{
auth_provider::AuthProvider, client::Client, persistence, state_ext::StateExt, Server,
};
2020-02-16 20:04:06 +00:00
use common::{
comp,
2020-03-09 19:52:04 +00:00
comp::Player,
2020-02-16 20:04:06 +00:00
msg::{ClientState, PlayerListUpdate, ServerMsg},
sync::{Uid, UidAllocator},
};
use specs::{saveload::MarkerAllocator, Builder, Entity as EcsEntity, WorldExt};
use tracing::error;
2020-02-16 20:04:06 +00:00
pub fn handle_exit_ingame(server: &mut Server, entity: EcsEntity) {
let state = server.state_mut();
// Create new entity with just `Client`, `Uid`, and `Player` components
// Easier than checking and removing all other known components
// Note: If other `ServerEvent`s are referring to this entity they will be
// disrupted
let maybe_client = state.ecs().write_storage::<Client>().remove(entity);
let maybe_uid = state.read_component_cloned::<Uid>(entity);
let maybe_player = state.ecs().write_storage::<comp::Player>().remove(entity);
if let (Some(mut client), Some(uid), Some(player)) = (maybe_client, maybe_uid, maybe_player) {
// Tell client its request was successful
client.allow_state(ClientState::Registered);
// Tell client to clear out other entities and its own components
client.notify(ServerMsg::ExitIngameCleanup);
let entity_builder = state.ecs_mut().create_entity().with(client).with(player);
// Ensure UidAllocator maps this uid to the new entity
let uid = entity_builder
.world
.write_resource::<UidAllocator>()
.allocate(entity_builder.entity, Some(uid.into()));
entity_builder.with(uid).build();
}
// Delete old entity
if let Err(e) = state.delete_entity_recorded(entity) {
error!(
?e,
?entity,
"Failed to delete entity when removing character"
);
2020-02-16 20:04:06 +00:00
}
}
pub fn handle_client_disconnect(server: &mut Server, entity: EcsEntity) -> Event {
let state = server.state_mut();
// Tell other clients to remove from player list
if let (Some(uid), Some(_)) = (
state.read_storage::<Uid>().get(entity),
state.read_storage::<comp::Player>().get(entity),
) {
state.notify_registered_clients(ServerMsg::PlayerListUpdate(PlayerListUpdate::Remove(
(*uid).into(),
)))
}
2020-03-09 19:52:04 +00:00
// Make sure to remove the player from the logged in list. (See AuthProvider)
// And send a disconnected message
if let Some(player) = state.ecs().read_storage::<Player>().get(entity) {
2020-03-09 19:52:04 +00:00
let mut accounts = state.ecs().write_resource::<AuthProvider>();
accounts.logout(player.uuid());
2020-03-09 19:52:04 +00:00
2020-06-12 17:44:29 +00:00
let msg = comp::ChatType::Offline.server_msg(format!("{} went offline.", &player.alias));
state.notify_registered_clients(msg);
2020-03-09 19:52:04 +00:00
}
// Sync the player's character data to the database
if let (Some(player), Some(stats), Some(inventory), Some(loadout), updater) = (
state.read_storage::<Player>().get(entity),
state.read_storage::<comp::Stats>().get(entity),
state.read_storage::<comp::Inventory>().get(entity),
state.read_storage::<comp::Loadout>().get(entity),
state
.ecs()
.read_resource::<persistence::character::CharacterUpdater>(),
) {
if let Some(character_id) = player.character_id {
updater.update(character_id, stats, inventory, loadout);
}
}
2020-02-16 20:04:06 +00:00
// Delete client entity
if let Err(e) = state.delete_entity_recorded(entity) {
error!(?e, ?entity, "Failed to delete disconnected client");
2020-02-16 20:04:06 +00:00
}
Event::ClientDisconnected { entity }
}