mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
No longer block the main thread for client connections, new clients will be handled by server without waiting.
- Instread we have a dedicated thread that will async wait for new participants to connect and then notify the main thread - registry no longer sends a view distance with it. - remove ClientMsg::Command again as it's unused
This commit is contained in:
parent
017e004309
commit
8b40f81ee2
@ -25,10 +25,10 @@ use common::{
|
||||
},
|
||||
event::{EventBus, LocalEvent},
|
||||
msg::{
|
||||
validate_chat_msg, ChatMsgValidationError, ClientInGameMsg, ClientIngame, ClientGeneralMsg,
|
||||
validate_chat_msg, ChatMsgValidationError, ClientGeneralMsg, ClientInGameMsg, ClientIngame,
|
||||
ClientNotInGameMsg, ClientRegisterMsg, ClientType, DisconnectReason, InviteAnswer,
|
||||
Notification, PingMsg, PlayerInfo, PlayerListUpdate, RegisterError, ServerInGameMsg,
|
||||
ServerInfo, ServerInitMsg, ServerGeneralMsg, ServerNotInGameMsg, ServerRegisterAnswerMsg,
|
||||
Notification, PingMsg, PlayerInfo, PlayerListUpdate, RegisterError, ServerGeneralMsg,
|
||||
ServerInGameMsg, ServerInfo, ServerInitMsg, ServerNotInGameMsg, ServerRegisterAnswerMsg,
|
||||
MAX_BYTES_CHAT_MSG,
|
||||
},
|
||||
outcome::Outcome,
|
||||
@ -444,11 +444,8 @@ impl Client {
|
||||
}
|
||||
).unwrap_or(Ok(username))?;
|
||||
|
||||
//TODO move ViewDistance out of register
|
||||
self.register_stream.send(ClientRegisterMsg {
|
||||
view_distance: self.view_distance,
|
||||
token_or_username,
|
||||
})?;
|
||||
self.register_stream
|
||||
.send(ClientRegisterMsg { token_or_username })?;
|
||||
|
||||
match block_on(self.register_stream.recv::<ServerRegisterAnswerMsg>())? {
|
||||
Err(RegisterError::AlreadyLoggedIn) => Err(Error::AlreadyLoggedIn),
|
||||
@ -1123,11 +1120,13 @@ impl Client {
|
||||
},
|
||||
DisconnectReason::Kicked(reason) => {
|
||||
debug!("sending ClientMsg::Terminate because we got kicked");
|
||||
frontend_events.push(Event::Kicked(reason.clone()));
|
||||
frontend_events.push(Event::Kicked(reason));
|
||||
self.singleton_stream.send(ClientGeneralMsg::Terminate)?;
|
||||
},
|
||||
},
|
||||
ServerGeneralMsg::PlayerListUpdate(PlayerListUpdate::Init(list)) => self.player_list = list,
|
||||
ServerGeneralMsg::PlayerListUpdate(PlayerListUpdate::Init(list)) => {
|
||||
self.player_list = list
|
||||
},
|
||||
ServerGeneralMsg::PlayerListUpdate(PlayerListUpdate::Add(uid, player_info)) => {
|
||||
if let Some(old_player_info) = self.player_list.insert(uid, player_info.clone()) {
|
||||
warn!(
|
||||
@ -1148,7 +1147,10 @@ impl Client {
|
||||
);
|
||||
}
|
||||
},
|
||||
ServerGeneralMsg::PlayerListUpdate(PlayerListUpdate::SelectedCharacter(uid, char_info)) => {
|
||||
ServerGeneralMsg::PlayerListUpdate(PlayerListUpdate::SelectedCharacter(
|
||||
uid,
|
||||
char_info,
|
||||
)) => {
|
||||
if let Some(player_info) = self.player_list.get_mut(&uid) {
|
||||
player_info.character = Some(char_info);
|
||||
} else {
|
||||
@ -1423,6 +1425,9 @@ impl Client {
|
||||
},
|
||||
ServerNotInGameMsg::CharacterSuccess => {
|
||||
debug!("client is now in ingame state on server");
|
||||
if let Some(vd) = self.view_distance {
|
||||
self.set_view_distance(vd);
|
||||
}
|
||||
},
|
||||
}
|
||||
Ok(())
|
||||
|
@ -20,7 +20,6 @@ pub enum ClientType {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ClientRegisterMsg {
|
||||
pub view_distance: Option<u32>,
|
||||
pub token_or_username: String,
|
||||
}
|
||||
|
||||
@ -65,7 +64,6 @@ pub enum ClientInGameMsg {
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum ClientGeneralMsg {
|
||||
ChatMsg(String),
|
||||
Command(String),
|
||||
Disconnect,
|
||||
Terminate,
|
||||
}
|
||||
}
|
||||
|
@ -4,12 +4,14 @@ pub mod server;
|
||||
|
||||
// Reexports
|
||||
pub use self::{
|
||||
client::{ClientInGameMsg, ClientGeneralMsg, ClientNotInGameMsg, ClientRegisterMsg, ClientType},
|
||||
client::{
|
||||
ClientGeneralMsg, ClientInGameMsg, ClientNotInGameMsg, ClientRegisterMsg, ClientType,
|
||||
},
|
||||
ecs_packet::EcsCompPacket,
|
||||
server::{
|
||||
CharacterInfo, DisconnectReason, InviteAnswer, Notification, PlayerInfo, PlayerListUpdate,
|
||||
RegisterError, ServerInGameMsg, ServerInfo, ServerInitMsg, ServerGeneralMsg, ServerNotInGameMsg,
|
||||
ServerRegisterAnswerMsg,
|
||||
RegisterError, ServerGeneralMsg, ServerInGameMsg, ServerInfo, ServerInitMsg,
|
||||
ServerNotInGameMsg, ServerRegisterAnswerMsg,
|
||||
},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -194,6 +194,7 @@ pub enum DisconnectReason {
|
||||
|
||||
/// Reponse To ClientType
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[allow(clippy::clippy::large_enum_variant)]
|
||||
pub enum ServerInitMsg {
|
||||
TooManyPlayers,
|
||||
GameSync {
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::error::Error;
|
||||
use common::msg::{
|
||||
ClientInGameMsg, ClientIngame, ClientGeneralMsg, ClientNotInGameMsg, ClientType, PingMsg,
|
||||
ServerInGameMsg, ServerInitMsg, ServerGeneralMsg, ServerNotInGameMsg,
|
||||
ClientGeneralMsg, ClientInGameMsg, ClientIngame, ClientNotInGameMsg, ClientType, PingMsg,
|
||||
ServerGeneralMsg, ServerInGameMsg, ServerInitMsg, ServerNotInGameMsg,
|
||||
};
|
||||
use hashbrown::HashSet;
|
||||
use network::{MessageBuffer, Participant, Stream};
|
||||
|
@ -12,7 +12,7 @@ use common::{
|
||||
cmd::{ChatCommand, CHAT_COMMANDS, CHAT_SHORTCUTS},
|
||||
comp::{self, ChatType, Item, LightEmitter, WaypointArea},
|
||||
event::{EventBus, ServerEvent},
|
||||
msg::{DisconnectReason, Notification, PlayerListUpdate, ServerInGameMsg, ServerGeneralMsg},
|
||||
msg::{DisconnectReason, Notification, PlayerListUpdate, ServerGeneralMsg, ServerInGameMsg},
|
||||
npc::{self, get_npc_name},
|
||||
state::TimeOfDay,
|
||||
sync::{Uid, WorldSyncExt},
|
||||
@ -504,8 +504,10 @@ fn handle_alias(
|
||||
ecs.read_storage::<comp::Player>().get(target),
|
||||
old_alias_optional,
|
||||
) {
|
||||
let msg =
|
||||
ServerGeneralMsg::PlayerListUpdate(PlayerListUpdate::Alias(*uid, player.alias.clone()));
|
||||
let msg = ServerGeneralMsg::PlayerListUpdate(PlayerListUpdate::Alias(
|
||||
*uid,
|
||||
player.alias.clone(),
|
||||
));
|
||||
server.state.notify_registered_clients(msg);
|
||||
|
||||
// Announce alias change if target has a Body.
|
||||
@ -1157,7 +1159,10 @@ fn handle_waypoint(
|
||||
.write_storage::<comp::Waypoint>()
|
||||
.insert(target, comp::Waypoint::new(pos.0, *time));
|
||||
server.notify_client(client, ChatType::CommandInfo.server_msg("Waypoint saved!"));
|
||||
server.notify_client(client, ServerGeneralMsg::Notification(Notification::WaypointSaved));
|
||||
server.notify_client(
|
||||
client,
|
||||
ServerGeneralMsg::Notification(Notification::WaypointSaved),
|
||||
);
|
||||
},
|
||||
None => server.notify_client(
|
||||
client,
|
||||
|
163
server/src/connection_handler.rs
Normal file
163
server/src/connection_handler.rs
Normal file
@ -0,0 +1,163 @@
|
||||
use crate::{Client, ClientType, ServerInfo};
|
||||
use crossbeam::{bounded, unbounded, Receiver, Sender};
|
||||
use futures_executor::block_on;
|
||||
use futures_timer::Delay;
|
||||
use futures_util::{select, FutureExt};
|
||||
use network::{Network, Participant, Promises};
|
||||
use std::{
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc,
|
||||
},
|
||||
thread,
|
||||
time::Duration,
|
||||
};
|
||||
use tracing::{debug, error, trace, warn};
|
||||
|
||||
pub(crate) struct ServerInfoPacket {
|
||||
pub info: ServerInfo,
|
||||
pub time: f64,
|
||||
}
|
||||
|
||||
pub(crate) type ConnectionDataPacket = Client;
|
||||
|
||||
pub(crate) struct ConnectionHandler {
|
||||
_network: Arc<Network>,
|
||||
thread_handle: Option<thread::JoinHandle<()>>,
|
||||
pub client_receiver: Receiver<ConnectionDataPacket>,
|
||||
pub info_requester_receiver: Receiver<Sender<ServerInfoPacket>>,
|
||||
running: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
/// Instead of waiting the main loop we are handling connections, especially
|
||||
/// their slow network .await part on a different thread. We need to communicate
|
||||
/// to the Server main thread sometimes tough to get the current server_info and
|
||||
/// time
|
||||
impl ConnectionHandler {
|
||||
pub fn new(network: Network) -> Self {
|
||||
let network = Arc::new(network);
|
||||
let network_clone = Arc::clone(&network);
|
||||
let running = Arc::new(AtomicBool::new(true));
|
||||
let running_clone = Arc::clone(&running);
|
||||
|
||||
let (client_sender, client_receiver) = unbounded::<ConnectionDataPacket>();
|
||||
let (info_requester_sender, info_requester_receiver) =
|
||||
bounded::<Sender<ServerInfoPacket>>(1);
|
||||
|
||||
let thread_handle = Some(thread::spawn(|| {
|
||||
block_on(Self::work(
|
||||
network_clone,
|
||||
client_sender,
|
||||
info_requester_sender,
|
||||
running_clone,
|
||||
));
|
||||
}));
|
||||
|
||||
Self {
|
||||
_network: network,
|
||||
thread_handle,
|
||||
client_receiver,
|
||||
info_requester_receiver,
|
||||
running,
|
||||
}
|
||||
}
|
||||
|
||||
async fn work(
|
||||
network: Arc<Network>,
|
||||
client_sender: Sender<ConnectionDataPacket>,
|
||||
info_requester_sender: Sender<Sender<ServerInfoPacket>>,
|
||||
running: Arc<AtomicBool>,
|
||||
) {
|
||||
while running.load(Ordering::Relaxed) {
|
||||
const TIMEOUT: Duration = Duration::from_secs(5);
|
||||
let participant = match select!(
|
||||
_ = Delay::new(TIMEOUT).fuse() => None,
|
||||
p = network.connected().fuse() => Some(p),
|
||||
) {
|
||||
None => continue, //check condition
|
||||
Some(Ok(p)) => p,
|
||||
Some(Err(e)) => {
|
||||
error!(
|
||||
?e,
|
||||
"Stopping Conection Handler, no new connections can be made to server now!"
|
||||
);
|
||||
break;
|
||||
},
|
||||
};
|
||||
|
||||
let client_sender = client_sender.clone();
|
||||
let info_requester_sender = info_requester_sender.clone();
|
||||
|
||||
match Self::init_participant(participant, client_sender, info_requester_sender).await {
|
||||
Ok(_) => (),
|
||||
Err(e) => warn!(?e, "drop new participant, because an error occurred"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn init_participant(
|
||||
participant: Participant,
|
||||
client_sender: Sender<ConnectionDataPacket>,
|
||||
info_requester_sender: Sender<Sender<ServerInfoPacket>>,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
debug!("New Participant connected to the server");
|
||||
let (sender, receiver) = bounded(1);
|
||||
info_requester_sender.send(sender)?;
|
||||
|
||||
let reliable = Promises::ORDERED | Promises::CONSISTENCY;
|
||||
let reliablec = reliable | Promises::COMPRESSED;
|
||||
|
||||
let general_stream = participant.open(10, reliablec).await?;
|
||||
let ping_stream = participant.open(5, reliable).await?;
|
||||
let mut register_stream = participant.open(10, reliablec).await?;
|
||||
let in_game_stream = participant.open(10, reliablec).await?;
|
||||
let not_in_game_stream = participant.open(10, reliablec).await?;
|
||||
|
||||
let server_data = receiver.recv()?;
|
||||
|
||||
register_stream.send(server_data.info)?;
|
||||
|
||||
const TIMEOUT: Duration = Duration::from_secs(5);
|
||||
let client_type = match select!(
|
||||
_ = Delay::new(TIMEOUT).fuse() => None,
|
||||
t = register_stream.recv::<ClientType>().fuse() => Some(t),
|
||||
) {
|
||||
None => {
|
||||
debug!("slow client connection detected, dropping it");
|
||||
return Ok(());
|
||||
},
|
||||
Some(client_type) => client_type?,
|
||||
};
|
||||
|
||||
let client = Client {
|
||||
registered: false,
|
||||
client_type,
|
||||
in_game: None,
|
||||
participant: std::sync::Mutex::new(Some(participant)),
|
||||
singleton_stream: general_stream,
|
||||
ping_stream,
|
||||
register_stream,
|
||||
in_game_stream,
|
||||
not_in_game_stream,
|
||||
network_error: std::sync::atomic::AtomicBool::new(false),
|
||||
last_ping: server_data.time,
|
||||
login_msg_sent: false,
|
||||
};
|
||||
|
||||
client_sender.send(client)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ConnectionHandler {
|
||||
fn drop(&mut self) {
|
||||
self.running.store(false, Ordering::Relaxed);
|
||||
trace!("blocking till ConnectionHandler is closed");
|
||||
self.thread_handle
|
||||
.take()
|
||||
.unwrap()
|
||||
.join()
|
||||
.expect("There was an error in ConnectionHandler, clean shutdown impossible");
|
||||
trace!("gracefully closed ConnectionHandler!");
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ use common::{
|
||||
Player, Pos, Stats,
|
||||
},
|
||||
lottery::Lottery,
|
||||
msg::{PlayerListUpdate, ServerInGameMsg, ServerGeneralMsg},
|
||||
msg::{PlayerListUpdate, ServerGeneralMsg, ServerInGameMsg},
|
||||
outcome::Outcome,
|
||||
state::BlockChange,
|
||||
sync::{Uid, UidAllocator, WorldSyncExt},
|
||||
@ -656,7 +656,7 @@ pub fn handle_level_up(server: &mut Server, entity: EcsEntity, new_level: u32) {
|
||||
|
||||
server
|
||||
.state
|
||||
.notify_registered_clients(ServerGeneralMsg::PlayerListUpdate(PlayerListUpdate::LevelChange(
|
||||
*uid, new_level,
|
||||
)));
|
||||
.notify_registered_clients(ServerGeneralMsg::PlayerListUpdate(
|
||||
PlayerListUpdate::LevelChange(*uid, new_level),
|
||||
));
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use crate::{
|
||||
use common::{
|
||||
comp,
|
||||
comp::{group, Player},
|
||||
msg::{PlayerListUpdate, ServerInGameMsg, ServerGeneralMsg},
|
||||
msg::{PlayerListUpdate, ServerGeneralMsg, ServerInGameMsg},
|
||||
span,
|
||||
sync::{Uid, UidAllocator},
|
||||
};
|
||||
@ -130,8 +130,9 @@ pub fn handle_client_disconnect(server: &mut Server, entity: EcsEntity) -> Event
|
||||
) {
|
||||
state.notify_registered_clients(comp::ChatType::Offline(*uid).server_msg(""));
|
||||
|
||||
state
|
||||
.notify_registered_clients(ServerGeneralMsg::PlayerListUpdate(PlayerListUpdate::Remove(*uid)));
|
||||
state.notify_registered_clients(ServerGeneralMsg::PlayerListUpdate(
|
||||
PlayerListUpdate::Remove(*uid),
|
||||
));
|
||||
}
|
||||
|
||||
// Make sure to remove the player from the logged in list. (See LoginProvider)
|
||||
|
@ -9,6 +9,7 @@ mod character_creator;
|
||||
pub mod chunk_generator;
|
||||
pub mod client;
|
||||
pub mod cmd;
|
||||
pub mod connection_handler;
|
||||
mod data_dir;
|
||||
pub mod error;
|
||||
pub mod events;
|
||||
@ -35,6 +36,7 @@ use crate::{
|
||||
chunk_generator::ChunkGenerator,
|
||||
client::{Client, RegionSubscription},
|
||||
cmd::ChatCommandExt,
|
||||
connection_handler::ConnectionHandler,
|
||||
data_dir::DataDir,
|
||||
login_provider::LoginProvider,
|
||||
state_ext::StateExt,
|
||||
@ -45,8 +47,8 @@ use common::{
|
||||
comp::{self, ChatType},
|
||||
event::{EventBus, ServerEvent},
|
||||
msg::{
|
||||
server::WorldMapMsg, ClientType, DisconnectReason, ServerInGameMsg, ServerInfo,
|
||||
ServerInitMsg, ServerGeneralMsg, ServerNotInGameMsg,
|
||||
server::WorldMapMsg, ClientType, DisconnectReason, ServerGeneralMsg, ServerInGameMsg,
|
||||
ServerInfo, ServerInitMsg, ServerNotInGameMsg,
|
||||
},
|
||||
outcome::Outcome,
|
||||
recipe::default_recipe_book,
|
||||
@ -56,10 +58,8 @@ use common::{
|
||||
vol::{ReadVol, RectVolSize},
|
||||
};
|
||||
use futures_executor::block_on;
|
||||
use futures_timer::Delay;
|
||||
use futures_util::{select, FutureExt};
|
||||
use metrics::{ServerMetrics, StateTickMetrics, TickMetrics};
|
||||
use network::{Network, Pid, Promises, ProtocolAddr};
|
||||
use network::{Network, Pid, ProtocolAddr};
|
||||
use persistence::{
|
||||
character_loader::{CharacterLoader, CharacterLoaderResponseType},
|
||||
character_updater::CharacterUpdater,
|
||||
@ -100,7 +100,7 @@ pub struct Server {
|
||||
index: IndexOwned,
|
||||
map: WorldMapMsg,
|
||||
|
||||
network: Network,
|
||||
connection_handler: ConnectionHandler,
|
||||
|
||||
thread_pool: ThreadPool,
|
||||
|
||||
@ -335,6 +335,7 @@ impl Server {
|
||||
.expect("Failed to initialize server metrics submodule.");
|
||||
thread_pool.execute(f);
|
||||
block_on(network.listen(ProtocolAddr::Tcp(settings.gameserver_address)))?;
|
||||
let connection_handler = ConnectionHandler::new(network);
|
||||
|
||||
let this = Self {
|
||||
state,
|
||||
@ -342,7 +343,7 @@ impl Server {
|
||||
index,
|
||||
map,
|
||||
|
||||
network,
|
||||
connection_handler,
|
||||
|
||||
thread_pool,
|
||||
|
||||
@ -452,7 +453,7 @@ impl Server {
|
||||
let before_new_connections = Instant::now();
|
||||
|
||||
// 3) Handle inputs from clients
|
||||
block_on(self.handle_new_connections(&mut frontend_events))?;
|
||||
self.handle_new_connections(&mut frontend_events)?;
|
||||
|
||||
let before_message_system = Instant::now();
|
||||
|
||||
@ -794,59 +795,30 @@ impl Server {
|
||||
}
|
||||
|
||||
/// Handle new client connections.
|
||||
async fn handle_new_connections(
|
||||
&mut self,
|
||||
frontend_events: &mut Vec<Event>,
|
||||
) -> Result<(), Error> {
|
||||
//TIMEOUT 0.1 ms for msg handling
|
||||
const TIMEOUT: Duration = Duration::from_micros(100);
|
||||
loop {
|
||||
let participant = match select!(
|
||||
_ = Delay::new(TIMEOUT).fuse() => None,
|
||||
pr = self.network.connected().fuse() => Some(pr),
|
||||
) {
|
||||
None => return Ok(()),
|
||||
Some(pr) => pr?,
|
||||
};
|
||||
debug!("New Participant connected to the server");
|
||||
let reliable = Promises::ORDERED | Promises::CONSISTENCY;
|
||||
let reliablec = reliable | Promises::COMPRESSED;
|
||||
fn handle_new_connections(&mut self, frontend_events: &mut Vec<Event>) -> Result<(), Error> {
|
||||
while let Ok(sender) = self.connection_handler.info_requester_receiver.try_recv() {
|
||||
// can fail, e.g. due to timeout or network prob.
|
||||
trace!("sending info to connection_handler");
|
||||
let _ = sender.send(crate::connection_handler::ServerInfoPacket {
|
||||
info: self.get_server_info(),
|
||||
time: self.state.get_time(),
|
||||
});
|
||||
}
|
||||
|
||||
let stream = participant.open(10, reliablec).await?;
|
||||
let ping_stream = participant.open(5, reliable).await?;
|
||||
let mut register_stream = participant.open(10, reliablec).await?;
|
||||
let in_game_stream = participant.open(10, reliablec).await?;
|
||||
let not_in_game_stream = participant.open(10, reliablec).await?;
|
||||
|
||||
register_stream.send(self.get_server_info())?;
|
||||
let client_type: ClientType = register_stream.recv().await?;
|
||||
while let Ok(data) = self.connection_handler.client_receiver.try_recv() {
|
||||
let mut client = data;
|
||||
|
||||
if self.settings().max_players
|
||||
<= self.state.ecs().read_storage::<Client>().join().count()
|
||||
{
|
||||
trace!(
|
||||
?participant,
|
||||
?client.participant,
|
||||
"to many players, wont allow participant to connect"
|
||||
);
|
||||
register_stream.send(ServerInitMsg::TooManyPlayers)?;
|
||||
client.register_stream.send(ServerInitMsg::TooManyPlayers)?;
|
||||
continue;
|
||||
}
|
||||
|
||||
let client = Client {
|
||||
registered: false,
|
||||
client_type,
|
||||
in_game: None,
|
||||
participant: std::sync::Mutex::new(Some(participant)),
|
||||
singleton_stream: stream,
|
||||
ping_stream,
|
||||
register_stream,
|
||||
in_game_stream,
|
||||
not_in_game_stream,
|
||||
network_error: std::sync::atomic::AtomicBool::new(false),
|
||||
last_ping: self.state.get_time(),
|
||||
login_msg_sent: false,
|
||||
};
|
||||
|
||||
let entity = self
|
||||
.state
|
||||
.ecs_mut()
|
||||
@ -881,6 +853,7 @@ impl Server {
|
||||
frontend_events.push(Event::ClientConnected { entity });
|
||||
debug!("Done initial sync with client.");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn notify_client<S>(&self, entity: EcsEntity, msg: S)
|
||||
|
@ -6,7 +6,7 @@ use common::{
|
||||
comp,
|
||||
effect::Effect,
|
||||
msg::{
|
||||
CharacterInfo, ClientIngame, PlayerListUpdate, ServerInGameMsg, ServerGeneralMsg,
|
||||
CharacterInfo, ClientIngame, PlayerListUpdate, ServerGeneralMsg, ServerInGameMsg,
|
||||
ServerNotInGameMsg,
|
||||
},
|
||||
state::State,
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
||||
};
|
||||
use common::{
|
||||
comp::{ForceUpdate, Inventory, InventoryUpdate, Last, Ori, Player, Pos, Vel},
|
||||
msg::{ServerInGameMsg, ServerGeneralMsg},
|
||||
msg::{ServerGeneralMsg, ServerInGameMsg},
|
||||
outcome::Outcome,
|
||||
region::{Event as RegionEvent, RegionMap},
|
||||
span,
|
||||
@ -128,13 +128,14 @@ impl<'a> System<'a> for Sys {
|
||||
(uid, pos, velocities.get(entity), orientations.get(entity))
|
||||
})
|
||||
}) {
|
||||
let create_msg =
|
||||
ServerGeneralMsg::CreateEntity(tracked_comps.create_entity_package(
|
||||
let create_msg = ServerGeneralMsg::CreateEntity(
|
||||
tracked_comps.create_entity_package(
|
||||
entity,
|
||||
Some(*pos),
|
||||
vel.copied(),
|
||||
ori.copied(),
|
||||
));
|
||||
),
|
||||
);
|
||||
for (client, regions, client_entity, _) in &mut subscribers {
|
||||
if maybe_key
|
||||
.as_ref()
|
||||
|
@ -15,10 +15,10 @@ use common::{
|
||||
},
|
||||
event::{EventBus, ServerEvent},
|
||||
msg::{
|
||||
validate_chat_msg, CharacterInfo, ChatMsgValidationError, ClientInGameMsg, ClientIngame,
|
||||
ClientGeneralMsg, ClientNotInGameMsg, ClientRegisterMsg, DisconnectReason, PingMsg, PlayerInfo,
|
||||
PlayerListUpdate, RegisterError, ServerInGameMsg, ServerGeneralMsg, ServerNotInGameMsg,
|
||||
ServerRegisterAnswerMsg, MAX_BYTES_CHAT_MSG,
|
||||
validate_chat_msg, CharacterInfo, ChatMsgValidationError, ClientGeneralMsg,
|
||||
ClientInGameMsg, ClientIngame, ClientNotInGameMsg, ClientRegisterMsg, DisconnectReason,
|
||||
PingMsg, PlayerInfo, PlayerListUpdate, RegisterError, ServerGeneralMsg, ServerInGameMsg,
|
||||
ServerNotInGameMsg, ServerRegisterAnswerMsg, MAX_BYTES_CHAT_MSG,
|
||||
},
|
||||
span,
|
||||
state::{BlockChange, Time},
|
||||
@ -68,26 +68,6 @@ impl Sys {
|
||||
}
|
||||
}
|
||||
},
|
||||
ClientGeneralMsg::Command(message) => {
|
||||
if client.registered {
|
||||
match validate_chat_msg(&message) {
|
||||
Ok(()) => {
|
||||
if let Some(from) = uids.get(entity) {
|
||||
let mode = chat_modes.get(entity).cloned().unwrap_or_default();
|
||||
let msg = mode.new_message(*from, message);
|
||||
new_chat_msgs.push((Some(entity), msg));
|
||||
} else {
|
||||
error!("Could not send message. Missing player uid");
|
||||
}
|
||||
},
|
||||
Err(ChatMsgValidationError::TooLong) => {
|
||||
let max = MAX_BYTES_CHAT_MSG;
|
||||
let len = message.len();
|
||||
warn!(?len, ?max, "Received a chat message that's too long")
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
ClientGeneralMsg::Disconnect => {
|
||||
client.send_msg(ServerGeneralMsg::Disconnect(DisconnectReason::Requested));
|
||||
},
|
||||
@ -122,7 +102,7 @@ impl Sys {
|
||||
settings: &Read<'_, Settings>,
|
||||
msg: ClientInGameMsg,
|
||||
) -> Result<(), crate::error::Error> {
|
||||
if !client.in_game.is_some() {
|
||||
if client.in_game.is_none() {
|
||||
debug!(?entity, "client is not in_game, ignoring msg");
|
||||
trace!(?msg, "ignored msg content");
|
||||
if matches!(msg, ClientInGameMsg::TerrainChunkRequest{ .. }) {
|
||||
@ -147,6 +127,7 @@ impl Sys {
|
||||
)
|
||||
});
|
||||
|
||||
//correct client if its VD is to high
|
||||
if settings
|
||||
.max_view_distance
|
||||
.map(|max| view_distance > max)
|
||||
@ -278,7 +259,7 @@ impl Sys {
|
||||
}
|
||||
},
|
||||
ClientNotInGameMsg::Character(character_id) => {
|
||||
if client.registered && !client.in_game.is_some() {
|
||||
if client.registered && client.in_game.is_none() {
|
||||
// Only send login message if it wasn't already
|
||||
// sent previously
|
||||
if let Some(player) = players.get(entity) {
|
||||
@ -384,7 +365,6 @@ impl Sys {
|
||||
login_provider: &mut WriteExpect<'_, LoginProvider>,
|
||||
admins: &mut WriteStorage<'_, Admin>,
|
||||
players: &mut WriteStorage<'_, Player>,
|
||||
settings: &Read<'_, Settings>,
|
||||
editable_settings: &ReadExpect<'_, EditableSettings>,
|
||||
msg: ClientRegisterMsg,
|
||||
) -> Result<(), crate::error::Error> {
|
||||
@ -403,10 +383,8 @@ impl Sys {
|
||||
Ok((username, uuid)) => (username, uuid),
|
||||
};
|
||||
|
||||
let vd = msg
|
||||
.view_distance
|
||||
.map(|vd| vd.min(settings.max_view_distance.unwrap_or(vd)));
|
||||
let player = Player::new(username.clone(), None, vd, uuid);
|
||||
const INITIAL_VD: Option<u32> = Some(5); //will be changed after login
|
||||
let player = Player::new(username.clone(), None, INITIAL_VD, uuid);
|
||||
let is_admin = editable_settings.admins.contains(&uuid);
|
||||
|
||||
if !player.is_valid() {
|
||||
@ -442,19 +420,6 @@ impl Sys {
|
||||
// Add to list to notify all clients of the new player
|
||||
new_players.push(entity);
|
||||
}
|
||||
|
||||
// Limit view distance if it's too high
|
||||
// This comes after state registration so that the client actually hears it
|
||||
if settings
|
||||
.max_view_distance
|
||||
.zip(msg.view_distance)
|
||||
.map(|(max, vd)| vd > max)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
client.send_in_game(ServerInGameMsg::SetViewDistance(
|
||||
settings.max_view_distance.unwrap_or(0),
|
||||
));
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -564,7 +529,6 @@ impl Sys {
|
||||
login_provider,
|
||||
admins,
|
||||
players,
|
||||
settings,
|
||||
editable_settings,
|
||||
msg,
|
||||
)?;
|
||||
@ -734,12 +698,13 @@ impl<'a> System<'a> for Sys {
|
||||
// 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 msg = ServerGeneralMsg::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.
|
||||
}));
|
||||
let msg =
|
||||
ServerGeneralMsg::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.
|
||||
}));
|
||||
for client in (&mut clients).join().filter(|c| c.registered) {
|
||||
client.send_msg(msg.clone())
|
||||
}
|
||||
|
@ -42,7 +42,9 @@ impl<'a> System<'a> for Sys {
|
||||
if let Ok(wp_old) = waypoints.insert(entity, Waypoint::new(player_pos.0, *time))
|
||||
{
|
||||
if wp_old.map_or(true, |w| w.elapsed(*time) > NOTIFY_TIME) {
|
||||
client.send_msg(ServerGeneralMsg::Notification(Notification::WaypointSaved));
|
||||
client.send_msg(ServerGeneralMsg::Notification(
|
||||
Notification::WaypointSaved,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user