mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Moved back register to a system
This commit is contained in:
@ -1,7 +1,7 @@
|
|||||||
use std::sync::atomic::{AtomicPtr, AtomicU32, AtomicU64, Ordering};
|
use std::sync::atomic::{AtomicPtr, AtomicU32, AtomicU64, Ordering};
|
||||||
|
|
||||||
use serde::{de::DeserializeOwned, Serialize};
|
use serde::{de::DeserializeOwned, Serialize};
|
||||||
use specs::{shred::Fetch, Entities, ReadStorage};
|
use specs::{Entities, Read, ReadStorage};
|
||||||
use wasmer::{Function, Memory, Value};
|
use wasmer::{Function, Memory, Value};
|
||||||
|
|
||||||
use common::{
|
use common::{
|
||||||
@ -11,17 +11,17 @@ use common::{
|
|||||||
|
|
||||||
use super::errors::{MemoryAllocationError, PluginModuleError};
|
use super::errors::{MemoryAllocationError, PluginModuleError};
|
||||||
|
|
||||||
pub struct EcsWorld<'a> {
|
pub struct EcsWorld<'a, 'b> {
|
||||||
pub entities: Entities<'a>,
|
pub entities: &'b Entities<'a>,
|
||||||
pub health: ReadStorage<'a, Health>,
|
pub health: &'b ReadStorage<'a, Health>,
|
||||||
pub uid: ReadStorage<'a, Uid>,
|
pub uid: &'b ReadStorage<'a, Uid>,
|
||||||
//pub player: ReadStorage<'a, Player>,
|
//pub player: ReadStorage<'a, Player>,
|
||||||
pub uid_allocator: Fetch<'a, UidAllocator>,
|
pub uid_allocator: &'b Read<'a, UidAllocator>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This structure wraps the ECS pointer to ensure safety
|
/// This structure wraps the ECS pointer to ensure safety
|
||||||
pub struct EcsAccessManager {
|
pub struct EcsAccessManager {
|
||||||
ecs_pointer: AtomicPtr<EcsWorld<'static>>,
|
ecs_pointer: AtomicPtr<EcsWorld<'static, 'static>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for EcsAccessManager {
|
impl Default for EcsAccessManager {
|
||||||
|
@ -10,6 +10,7 @@ use common::{
|
|||||||
terrain::{Block, TerrainChunk, TerrainGrid},
|
terrain::{Block, TerrainChunk, TerrainGrid},
|
||||||
time::DayPeriod,
|
time::DayPeriod,
|
||||||
trade::Trades,
|
trade::Trades,
|
||||||
|
uid::UidAllocator,
|
||||||
vol::{ReadVol, WriteVol},
|
vol::{ReadVol, WriteVol},
|
||||||
};
|
};
|
||||||
use common_base::span;
|
use common_base::span;
|
||||||
@ -212,10 +213,10 @@ impl State {
|
|||||||
ecs.insert(match PluginMgr::from_assets() {
|
ecs.insert(match PluginMgr::from_assets() {
|
||||||
Ok(plugin_mgr) => {
|
Ok(plugin_mgr) => {
|
||||||
let ecs_world = EcsWorld {
|
let ecs_world = EcsWorld {
|
||||||
entities: ecs.entities(),
|
entities: &ecs.entities(),
|
||||||
health: ecs.read_component(),
|
health: &ecs.read_component(),
|
||||||
uid: ecs.read_component(),
|
uid: &ecs.read_component(),
|
||||||
uid_allocator: ecs.read_resource(),
|
uid_allocator: &ecs.read_resource::<UidAllocator>().into(),
|
||||||
//player: Either::First(ecs.read_component()),
|
//player: Either::First(ecs.read_component()),
|
||||||
};
|
};
|
||||||
if let Err(e) = plugin_mgr
|
if let Err(e) = plugin_mgr
|
||||||
|
@ -24,7 +24,6 @@ pub mod login_provider;
|
|||||||
pub mod metrics;
|
pub mod metrics;
|
||||||
pub mod persistence;
|
pub mod persistence;
|
||||||
pub mod presence;
|
pub mod presence;
|
||||||
mod register;
|
|
||||||
pub mod rtsim;
|
pub mod rtsim;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
pub mod state_ext;
|
pub mod state_ext;
|
||||||
@ -59,27 +58,26 @@ use common::{
|
|||||||
assets::AssetExt,
|
assets::AssetExt,
|
||||||
cmd::ChatCommand,
|
cmd::ChatCommand,
|
||||||
comp,
|
comp,
|
||||||
comp::{item::MaterialStatManifest, Admin, CharacterAbility, Player, Stats},
|
comp::{item::MaterialStatManifest, CharacterAbility},
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
recipe::default_recipe_book,
|
recipe::default_recipe_book,
|
||||||
resources::TimeOfDay,
|
resources::TimeOfDay,
|
||||||
rtsim::RtSimEntity,
|
rtsim::RtSimEntity,
|
||||||
terrain::TerrainChunkSize,
|
terrain::TerrainChunkSize,
|
||||||
|
uid::UidAllocator,
|
||||||
vol::{ReadVol, RectVolSize},
|
vol::{ReadVol, RectVolSize},
|
||||||
};
|
};
|
||||||
use common_ecs::run_now;
|
use common_ecs::run_now;
|
||||||
use common_net::{
|
use common_net::{
|
||||||
msg::{
|
msg::{
|
||||||
CharacterInfo, ClientType, DisconnectReason, PlayerInfo, PlayerListUpdate, ServerGeneral,
|
ClientType, DisconnectReason, ServerGeneral, ServerInfo, ServerInit, ServerMsg, WorldMapMsg,
|
||||||
ServerInfo, ServerInit, ServerMsg, WorldMapMsg,
|
|
||||||
},
|
},
|
||||||
sync::WorldSyncExt,
|
sync::WorldSyncExt,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "plugins")]
|
#[cfg(feature = "plugins")]
|
||||||
use common_sys::plugin::PluginMgr;
|
use common_sys::plugin::PluginMgr;
|
||||||
use common_sys::{plugin::memory_manager::EcsWorld, state::State};
|
use common_sys::{plugin::memory_manager::EcsWorld, state::State};
|
||||||
use hashbrown::HashMap;
|
use metrics::{EcsSystemMetrics, PhysicsMetrics, TickMetrics};
|
||||||
use metrics::{EcsSystemMetrics, PhysicsMetrics, PlayerMetrics, TickMetrics};
|
|
||||||
use network::{Network, Pid, ProtocolAddr};
|
use network::{Network, Pid, ProtocolAddr};
|
||||||
use persistence::{
|
use persistence::{
|
||||||
character_loader::{CharacterLoader, CharacterLoaderResponseKind},
|
character_loader::{CharacterLoader, CharacterLoaderResponseKind},
|
||||||
@ -498,7 +496,7 @@ impl Server {
|
|||||||
// (e.g. run before controller system)
|
// (e.g. run before controller system)
|
||||||
//TODO: run in parallel
|
//TODO: run in parallel
|
||||||
run_now::<sys::msg::general::Sys>(&self.state.ecs());
|
run_now::<sys::msg::general::Sys>(&self.state.ecs());
|
||||||
self.register_run();
|
run_now::<sys::msg::register::Sys>(&self.state.ecs());
|
||||||
run_now::<sys::msg::character_screen::Sys>(&self.state.ecs());
|
run_now::<sys::msg::character_screen::Sys>(&self.state.ecs());
|
||||||
run_now::<sys::msg::in_game::Sys>(&self.state.ecs());
|
run_now::<sys::msg::in_game::Sys>(&self.state.ecs());
|
||||||
run_now::<sys::msg::ping::Sys>(&self.state.ecs());
|
run_now::<sys::msg::ping::Sys>(&self.state.ecs());
|
||||||
@ -725,75 +723,6 @@ impl Server {
|
|||||||
self.state.cleanup();
|
self.state.cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_run(&mut self) {
|
|
||||||
let world = self.state_mut().ecs_mut();
|
|
||||||
let entities = world.entities();
|
|
||||||
let player_metrics = world.read_resource::<PlayerMetrics>();
|
|
||||||
let uids = world.read_storage::<Uid>();
|
|
||||||
let clients = world.read_storage::<Client>();
|
|
||||||
let mut players = world.write_storage::<Player>();
|
|
||||||
let stats = world.read_storage::<Stats>();
|
|
||||||
let mut login_provider = world.write_resource::<LoginProvider>();
|
|
||||||
let mut admins = world.write_storage::<Admin>();
|
|
||||||
let editable_settings = world.read_resource::<EditableSettings>();
|
|
||||||
|
|
||||||
// Player list to send new players.
|
|
||||||
let player_list = (&uids, &players, stats.maybe(), admins.maybe())
|
|
||||||
.join()
|
|
||||||
.map(|(uid, player, stats, admin)| {
|
|
||||||
(*uid, PlayerInfo {
|
|
||||||
is_online: true,
|
|
||||||
is_admin: admin.is_some(),
|
|
||||||
player_alias: player.alias.clone(),
|
|
||||||
character: stats.map(|stats| CharacterInfo {
|
|
||||||
name: stats.name.clone(),
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect::<HashMap<_, _>>();
|
|
||||||
// List of new players to update player lists of all clients.
|
|
||||||
let mut new_players = Vec::new();
|
|
||||||
|
|
||||||
for (entity, client) in (&entities, &clients).join() {
|
|
||||||
let _ = sys::msg::try_recv_all(client, 0, |client, msg| {
|
|
||||||
register::handle_register_msg(
|
|
||||||
&world,
|
|
||||||
&player_list,
|
|
||||||
&mut new_players,
|
|
||||||
entity,
|
|
||||||
client,
|
|
||||||
&player_metrics,
|
|
||||||
&mut login_provider,
|
|
||||||
&mut admins,
|
|
||||||
&mut players,
|
|
||||||
&editable_settings,
|
|
||||||
msg,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle new players.
|
|
||||||
// Tell all clients to add them to the player list.
|
|
||||||
for entity in new_players {
|
|
||||||
if let (Some(uid), Some(player)) = (uids.get(entity), players.get(entity)) {
|
|
||||||
let mut lazy_msg = None;
|
|
||||||
for (_, client) in (&players, &clients).join() {
|
|
||||||
if lazy_msg.is_none() {
|
|
||||||
lazy_msg = Some(client.prepare(ServerGeneral::PlayerListUpdate(
|
|
||||||
PlayerListUpdate::Add(*uid, PlayerInfo {
|
|
||||||
player_alias: player.alias.clone(),
|
|
||||||
is_online: true,
|
|
||||||
is_admin: admins.get(entity).is_some(),
|
|
||||||
character: None, // new players will be on character select.
|
|
||||||
}),
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
lazy_msg.as_ref().map(|ref msg| client.send_prepared(&msg));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn initialize_client(
|
fn initialize_client(
|
||||||
&mut self,
|
&mut self,
|
||||||
client: crate::connection_handler::IncomingClient,
|
client: crate::connection_handler::IncomingClient,
|
||||||
@ -912,10 +841,10 @@ impl Server {
|
|||||||
{
|
{
|
||||||
let plugin_manager = self.state.ecs().read_resource::<PluginMgr>();
|
let plugin_manager = self.state.ecs().read_resource::<PluginMgr>();
|
||||||
let ecs_world = EcsWorld {
|
let ecs_world = EcsWorld {
|
||||||
entities: self.state.ecs().entities(),
|
entities: &self.state.ecs().entities(),
|
||||||
health: self.state.ecs().read_component(),
|
health: &self.state.ecs().read_component(),
|
||||||
uid: self.state.ecs().read_component(),
|
uid: &self.state.ecs().read_component(),
|
||||||
uid_allocator: self.state.ecs().read_resource(),
|
uid_allocator: &self.state.ecs().read_resource::<UidAllocator>().into(),
|
||||||
};
|
};
|
||||||
let rs = plugin_manager.execute_event(
|
let rs = plugin_manager.execute_event(
|
||||||
&ecs_world,
|
&ecs_world,
|
||||||
|
@ -57,7 +57,7 @@ impl LoginProvider {
|
|||||||
pub fn try_login(
|
pub fn try_login(
|
||||||
&mut self,
|
&mut self,
|
||||||
username_or_token: &str,
|
username_or_token: &str,
|
||||||
world: &EcsWorld,
|
#[cfg(feature = "plugins")] world: &EcsWorld,
|
||||||
#[cfg(feature = "plugins")] plugin_manager: &PluginMgr,
|
#[cfg(feature = "plugins")] plugin_manager: &PluginMgr,
|
||||||
admins: &HashSet<Uuid>,
|
admins: &HashSet<Uuid>,
|
||||||
whitelist: &HashSet<Uuid>,
|
whitelist: &HashSet<Uuid>,
|
||||||
|
@ -1,92 +0,0 @@
|
|||||||
use common::comp::{Admin, Player};
|
|
||||||
use common_net::msg::{
|
|
||||||
ClientRegister, PlayerInfo, PlayerListUpdate, RegisterError, ServerGeneral,
|
|
||||||
ServerRegisterAnswer,
|
|
||||||
};
|
|
||||||
|
|
||||||
use common_sys::plugin::memory_manager::EcsWorld;
|
|
||||||
#[cfg(feature = "plugins")]
|
|
||||||
use common_sys::plugin::PluginMgr;
|
|
||||||
use hashbrown::HashMap;
|
|
||||||
use plugin_api::Uid;
|
|
||||||
use specs::{
|
|
||||||
shred::{Fetch, FetchMut},
|
|
||||||
Entity, World, WorldExt, WriteStorage,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
client::Client, login_provider::LoginProvider, metrics::PlayerMetrics, EditableSettings,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
|
||||||
pub(crate) fn handle_register_msg(
|
|
||||||
world: &World,
|
|
||||||
player_list: &HashMap<Uid, PlayerInfo>,
|
|
||||||
new_players: &mut Vec<Entity>,
|
|
||||||
entity: Entity,
|
|
||||||
client: &Client,
|
|
||||||
player_metrics: &Fetch<'_, PlayerMetrics>,
|
|
||||||
login_provider: &mut FetchMut<'_, LoginProvider>,
|
|
||||||
admins: &mut WriteStorage<'_, Admin>,
|
|
||||||
players: &mut WriteStorage<'_, Player>,
|
|
||||||
editable_settings: &Fetch<'_, EditableSettings>,
|
|
||||||
msg: ClientRegister,
|
|
||||||
) -> Result<(), crate::error::Error> {
|
|
||||||
#[cfg(feature = "plugins")]
|
|
||||||
let plugin_mgr = world.read_resource::<PluginMgr>();
|
|
||||||
let ecs_world = EcsWorld {
|
|
||||||
entities: world.entities(),
|
|
||||||
health: world.read_component(),
|
|
||||||
uid: world.read_component(),
|
|
||||||
uid_allocator: world.read_resource(),
|
|
||||||
};
|
|
||||||
let (username, uuid) = match login_provider.try_login(
|
|
||||||
&msg.token_or_username,
|
|
||||||
&ecs_world,
|
|
||||||
#[cfg(feature = "plugins")]
|
|
||||||
&plugin_mgr,
|
|
||||||
&*editable_settings.admins,
|
|
||||||
&*editable_settings.whitelist,
|
|
||||||
&*editable_settings.banlist,
|
|
||||||
) {
|
|
||||||
Err(err) => {
|
|
||||||
client.send(ServerRegisterAnswer::Err(err))?;
|
|
||||||
return Ok(());
|
|
||||||
},
|
|
||||||
Ok((username, uuid)) => (username, uuid),
|
|
||||||
};
|
|
||||||
|
|
||||||
let player = Player::new(username, uuid);
|
|
||||||
let is_admin = editable_settings.admins.contains(&uuid);
|
|
||||||
|
|
||||||
if !player.is_valid() {
|
|
||||||
// Invalid player
|
|
||||||
client.send(ServerRegisterAnswer::Err(RegisterError::InvalidCharacter))?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
if !players.contains(entity) {
|
|
||||||
// Add Player component to this client
|
|
||||||
let _ = players.insert(entity, player);
|
|
||||||
player_metrics.players_connected.inc();
|
|
||||||
|
|
||||||
// Give the Admin component to the player if their name exists in
|
|
||||||
// admin list
|
|
||||||
if is_admin {
|
|
||||||
let _ = admins.insert(entity, Admin);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tell the client its request was successful.
|
|
||||||
client.send(ServerRegisterAnswer::Ok(()))?;
|
|
||||||
|
|
||||||
// Send initial player list
|
|
||||||
client.send(ServerGeneral::PlayerListUpdate(PlayerListUpdate::Init(
|
|
||||||
player_list.clone(),
|
|
||||||
)))?;
|
|
||||||
|
|
||||||
// Add to list to notify all clients of the new player
|
|
||||||
new_players.push(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
@ -2,6 +2,7 @@ pub mod character_screen;
|
|||||||
pub mod general;
|
pub mod general;
|
||||||
pub mod in_game;
|
pub mod in_game;
|
||||||
pub mod ping;
|
pub mod ping;
|
||||||
|
pub mod register;
|
||||||
|
|
||||||
use crate::client::Client;
|
use crate::client::Client;
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
|
164
server/src/sys/msg/register.rs
Normal file
164
server/src/sys/msg/register.rs
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
use crate::{
|
||||||
|
client::Client, login_provider::LoginProvider, metrics::PlayerMetrics, EditableSettings,
|
||||||
|
};
|
||||||
|
use common::{
|
||||||
|
comp::{Admin, Player, Stats},
|
||||||
|
uid::{Uid, UidAllocator},
|
||||||
|
};
|
||||||
|
use common_ecs::{Job, Origin, Phase, System};
|
||||||
|
use common_net::msg::{
|
||||||
|
CharacterInfo, ClientRegister, PlayerInfo, PlayerListUpdate, RegisterError, ServerGeneral,
|
||||||
|
ServerRegisterAnswer,
|
||||||
|
};
|
||||||
|
use hashbrown::HashMap;
|
||||||
|
use plugin_api::Health;
|
||||||
|
use specs::{Entities, Join, Read, ReadExpect, ReadStorage, WriteExpect, WriteStorage};
|
||||||
|
|
||||||
|
use common_sys::plugin::memory_manager::EcsWorld;
|
||||||
|
|
||||||
|
#[cfg(feature = "plugins")]
|
||||||
|
use common_sys::plugin::PluginMgr;
|
||||||
|
|
||||||
|
/// This system will handle new messages from clients
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Sys;
|
||||||
|
impl<'a> System<'a> for Sys {
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
type SystemData = (
|
||||||
|
Entities<'a>,
|
||||||
|
ReadExpect<'a, PlayerMetrics>,
|
||||||
|
ReadStorage<'a, Health>,
|
||||||
|
ReadStorage<'a, Uid>,
|
||||||
|
ReadStorage<'a, Client>,
|
||||||
|
WriteStorage<'a, Player>,
|
||||||
|
Read<'a, UidAllocator>,
|
||||||
|
Read<'a, PluginMgr>,
|
||||||
|
ReadStorage<'a, Stats>,
|
||||||
|
WriteExpect<'a, LoginProvider>,
|
||||||
|
WriteStorage<'a, Admin>,
|
||||||
|
ReadExpect<'a, EditableSettings>,
|
||||||
|
);
|
||||||
|
|
||||||
|
const NAME: &'static str = "msg::register";
|
||||||
|
const ORIGIN: Origin = Origin::Server;
|
||||||
|
const PHASE: Phase = Phase::Create;
|
||||||
|
|
||||||
|
fn run(
|
||||||
|
_job: &mut Job<Self>,
|
||||||
|
(
|
||||||
|
entities,
|
||||||
|
player_metrics,
|
||||||
|
health_comp,
|
||||||
|
uids,
|
||||||
|
clients,
|
||||||
|
mut players,
|
||||||
|
uid_allocator,
|
||||||
|
plugin_mgr,
|
||||||
|
stats,
|
||||||
|
mut login_provider,
|
||||||
|
mut admins,
|
||||||
|
editable_settings,
|
||||||
|
): Self::SystemData,
|
||||||
|
) {
|
||||||
|
// Player list to send new players.
|
||||||
|
let player_list = (&uids, &players, stats.maybe(), admins.maybe())
|
||||||
|
.join()
|
||||||
|
.map(|(uid, player, stats, admin)| {
|
||||||
|
(*uid, PlayerInfo {
|
||||||
|
is_online: true,
|
||||||
|
is_admin: admin.is_some(),
|
||||||
|
player_alias: player.alias.clone(),
|
||||||
|
character: stats.map(|stats| CharacterInfo {
|
||||||
|
name: stats.name.clone(),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
// List of new players to update player lists of all clients.
|
||||||
|
let mut new_players = Vec::new();
|
||||||
|
|
||||||
|
#[cfg(feature = "plugins")]
|
||||||
|
let ecs_world = EcsWorld {
|
||||||
|
entities: &entities,
|
||||||
|
health: &health_comp,
|
||||||
|
uid: &uids,
|
||||||
|
uid_allocator: &uid_allocator,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (entity, client) in (&entities, &clients).join() {
|
||||||
|
let _ = super::try_recv_all(client, 0, |client, msg: ClientRegister| {
|
||||||
|
let (username, uuid) = match login_provider.try_login(
|
||||||
|
&msg.token_or_username,
|
||||||
|
#[cfg(feature = "plugins")]
|
||||||
|
&ecs_world,
|
||||||
|
#[cfg(feature = "plugins")]
|
||||||
|
&plugin_mgr,
|
||||||
|
&*editable_settings.admins,
|
||||||
|
&*editable_settings.whitelist,
|
||||||
|
&*editable_settings.banlist,
|
||||||
|
) {
|
||||||
|
Err(err) => {
|
||||||
|
client.send(ServerRegisterAnswer::Err(err))?;
|
||||||
|
return Ok(());
|
||||||
|
},
|
||||||
|
Ok((username, uuid)) => (username, uuid),
|
||||||
|
};
|
||||||
|
|
||||||
|
let player = Player::new(username, uuid);
|
||||||
|
let is_admin = editable_settings.admins.contains(&uuid);
|
||||||
|
|
||||||
|
if !player.is_valid() {
|
||||||
|
// Invalid player
|
||||||
|
client.send(ServerRegisterAnswer::Err(RegisterError::InvalidCharacter))?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if !players.contains(entity) {
|
||||||
|
// Add Player component to this client
|
||||||
|
let _ = players.insert(entity, player);
|
||||||
|
player_metrics.players_connected.inc();
|
||||||
|
|
||||||
|
// Give the Admin component to the player if their name exists in
|
||||||
|
// admin list
|
||||||
|
if is_admin {
|
||||||
|
let _ = admins.insert(entity, Admin);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tell the client its request was successful.
|
||||||
|
client.send(ServerRegisterAnswer::Ok(()))?;
|
||||||
|
|
||||||
|
// Send initial player list
|
||||||
|
client.send(ServerGeneral::PlayerListUpdate(PlayerListUpdate::Init(
|
||||||
|
player_list.clone(),
|
||||||
|
)))?;
|
||||||
|
|
||||||
|
// Add to list to notify all clients of the new player
|
||||||
|
new_players.push(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle new players.
|
||||||
|
// Tell all clients to add them to the player list.
|
||||||
|
for entity in new_players {
|
||||||
|
if let (Some(uid), Some(player)) = (uids.get(entity), players.get(entity)) {
|
||||||
|
let mut lazy_msg = None;
|
||||||
|
for (_, client) in (&players, &clients).join() {
|
||||||
|
if lazy_msg.is_none() {
|
||||||
|
lazy_msg = Some(client.prepare(ServerGeneral::PlayerListUpdate(
|
||||||
|
PlayerListUpdate::Add(*uid, PlayerInfo {
|
||||||
|
player_alias: player.alias.clone(),
|
||||||
|
is_online: true,
|
||||||
|
is_admin: admins.get(entity).is_some(),
|
||||||
|
character: None, // new players will be on character select.
|
||||||
|
}),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
lazy_msg.as_ref().map(|ref msg| client.send_prepared(&msg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user