2020-02-16 20:04:06 +00:00
|
|
|
use super::Event;
|
2020-05-13 12:08:26 +00:00
|
|
|
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 log::error;
|
2020-03-10 21:04:13 +00:00
|
|
|
use specs::{saveload::MarkerAllocator, Builder, Entity as EcsEntity, Join, WorldExt};
|
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(err) = state.delete_entity_recorded(entity) {
|
|
|
|
error!("Failed to delete entity when removing character: {:?}", err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
2020-03-10 21:04:13 +00:00
|
|
|
// And send a disconnected message
|
2020-03-09 19:52:04 +00:00
|
|
|
{
|
|
|
|
let players = state.ecs().read_storage::<Player>();
|
|
|
|
let mut accounts = state.ecs().write_resource::<AuthProvider>();
|
2020-03-10 21:04:13 +00:00
|
|
|
let mut clients = state.ecs().write_storage::<Client>();
|
2020-03-09 19:52:04 +00:00
|
|
|
|
|
|
|
if let Some(player) = players.get(entity) {
|
|
|
|
accounts.logout(player.uuid());
|
2020-03-10 21:04:13 +00:00
|
|
|
|
|
|
|
let msg = ServerMsg::broadcast(format!("{} went offline.", &player.alias));
|
|
|
|
for client in (&mut clients).join().filter(|c| c.is_registered()) {
|
|
|
|
client.notify(msg.clone());
|
|
|
|
}
|
2020-03-09 19:52:04 +00:00
|
|
|
}
|
|
|
|
}
|
2020-05-13 12:08:26 +00:00
|
|
|
|
|
|
|
// Sync the player's character data to the database
|
2020-05-15 20:03:51 +00:00
|
|
|
if let (Some(player), Some(stats), updater) = (
|
2020-05-13 12:08:26 +00:00
|
|
|
state.read_storage::<Player>().get(entity),
|
|
|
|
state.read_storage::<comp::Stats>().get(entity),
|
2020-05-15 20:03:51 +00:00
|
|
|
state.ecs().read_resource::<persistence::stats::Updater>(),
|
2020-05-13 12:08:26 +00:00
|
|
|
) {
|
|
|
|
if let Some(character_id) = player.character_id {
|
2020-05-15 20:03:51 +00:00
|
|
|
updater.update(character_id, stats);
|
2020-05-13 12:08:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-16 20:04:06 +00:00
|
|
|
// Delete client entity
|
|
|
|
if let Err(err) = state.delete_entity_recorded(entity) {
|
|
|
|
error!("Failed to delete disconnected client: {:?}", err);
|
|
|
|
}
|
|
|
|
|
|
|
|
Event::ClientDisconnected { entity }
|
|
|
|
}
|