2020-11-02 18:30:56 +00:00
|
|
|
use crate::{client::Client, metrics::NetworkRequestMetrics, presence::Presence, Settings};
|
2020-10-16 23:42:19 +00:00
|
|
|
use common::{
|
2020-10-31 22:34:08 +00:00
|
|
|
comp::{CanBuild, ControlEvent, Controller, ForceUpdate, Health, Ori, Pos, Stats, Vel},
|
2020-10-16 23:42:19 +00:00
|
|
|
event::{EventBus, ServerEvent},
|
|
|
|
terrain::{TerrainChunkSize, TerrainGrid},
|
|
|
|
vol::{ReadVol, RectVolSize},
|
2021-03-04 14:00:16 +00:00
|
|
|
vsystem::{Origin, Phase, VJob, VSystem},
|
2020-10-16 23:42:19 +00:00
|
|
|
};
|
2020-12-13 17:11:55 +00:00
|
|
|
use common_net::msg::{ClientGeneral, PresenceKind, ServerGeneral};
|
2020-12-01 12:13:07 +00:00
|
|
|
use common_sys::state::BlockChange;
|
2021-03-04 14:00:16 +00:00
|
|
|
use specs::{Entities, Join, Read, ReadExpect, ReadStorage, Write, WriteStorage};
|
2020-10-16 23:42:19 +00:00
|
|
|
use tracing::{debug, trace};
|
|
|
|
|
|
|
|
impl Sys {
|
|
|
|
#[allow(clippy::too_many_arguments)]
|
|
|
|
fn handle_client_in_game_msg(
|
|
|
|
server_emitter: &mut common::event::Emitter<'_, ServerEvent>,
|
|
|
|
entity: specs::Entity,
|
2020-11-02 18:30:56 +00:00
|
|
|
client: &Client,
|
2020-10-30 16:39:53 +00:00
|
|
|
maybe_presence: &mut Option<&mut Presence>,
|
2020-10-16 23:42:19 +00:00
|
|
|
terrain: &ReadExpect<'_, TerrainGrid>,
|
|
|
|
network_metrics: &ReadExpect<'_, NetworkRequestMetrics>,
|
|
|
|
can_build: &ReadStorage<'_, CanBuild>,
|
|
|
|
force_updates: &ReadStorage<'_, ForceUpdate>,
|
|
|
|
stats: &mut WriteStorage<'_, Stats>,
|
2020-10-31 22:34:08 +00:00
|
|
|
healths: &ReadStorage<'_, Health>,
|
2020-10-16 23:42:19 +00:00
|
|
|
block_changes: &mut Write<'_, BlockChange>,
|
|
|
|
positions: &mut WriteStorage<'_, Pos>,
|
|
|
|
velocities: &mut WriteStorage<'_, Vel>,
|
|
|
|
orientations: &mut WriteStorage<'_, Ori>,
|
|
|
|
controllers: &mut WriteStorage<'_, Controller>,
|
|
|
|
settings: &Read<'_, Settings>,
|
|
|
|
msg: ClientGeneral,
|
|
|
|
) -> Result<(), crate::error::Error> {
|
2020-10-30 16:39:53 +00:00
|
|
|
let presence = match maybe_presence {
|
|
|
|
Some(g) => g,
|
|
|
|
None => {
|
|
|
|
debug!(?entity, "client is not in_game, ignoring msg");
|
|
|
|
trace!(?msg, "ignored msg content");
|
2020-12-10 11:50:48 +00:00
|
|
|
if matches!(msg, ClientGeneral::TerrainChunkRequest { .. }) {
|
2020-10-30 16:39:53 +00:00
|
|
|
network_metrics.chunks_request_dropped.inc();
|
|
|
|
}
|
|
|
|
return Ok(());
|
|
|
|
},
|
|
|
|
};
|
2020-10-16 23:42:19 +00:00
|
|
|
match msg {
|
|
|
|
// Go back to registered state (char selection screen)
|
|
|
|
ClientGeneral::ExitInGame => {
|
|
|
|
server_emitter.emit(ServerEvent::ExitIngame { entity });
|
2020-11-02 18:30:56 +00:00
|
|
|
client.send(ServerGeneral::ExitInGameSuccess)?;
|
2020-10-30 16:39:53 +00:00
|
|
|
*maybe_presence = None;
|
2020-10-16 23:42:19 +00:00
|
|
|
},
|
|
|
|
ClientGeneral::SetViewDistance(view_distance) => {
|
2020-10-30 16:39:53 +00:00
|
|
|
presence.view_distance = settings
|
|
|
|
.max_view_distance
|
|
|
|
.map(|max| view_distance.min(max))
|
|
|
|
.unwrap_or(view_distance);
|
2020-10-16 23:42:19 +00:00
|
|
|
|
|
|
|
//correct client if its VD is to high
|
|
|
|
if settings
|
|
|
|
.max_view_distance
|
|
|
|
.map(|max| view_distance > max)
|
|
|
|
.unwrap_or(false)
|
|
|
|
{
|
2020-11-02 18:30:56 +00:00
|
|
|
client.send(ServerGeneral::SetViewDistance(
|
2020-10-16 23:42:19 +00:00
|
|
|
settings.max_view_distance.unwrap_or(0),
|
|
|
|
))?;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
ClientGeneral::ControllerInputs(inputs) => {
|
2020-10-30 16:39:53 +00:00
|
|
|
if matches!(presence.kind, PresenceKind::Character(_)) {
|
2020-10-16 23:42:19 +00:00
|
|
|
if let Some(controller) = controllers.get_mut(entity) {
|
2021-02-19 23:45:48 +00:00
|
|
|
controller.inputs.update_with_new(*inputs);
|
2020-10-16 23:42:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
ClientGeneral::ControlEvent(event) => {
|
2020-10-30 16:39:53 +00:00
|
|
|
if matches!(presence.kind, PresenceKind::Character(_)) {
|
2020-10-16 23:42:19 +00:00
|
|
|
// Skip respawn if client entity is alive
|
|
|
|
if let ControlEvent::Respawn = event {
|
2020-10-31 22:34:08 +00:00
|
|
|
if healths.get(entity).map_or(true, |h| !h.is_dead) {
|
2020-10-16 23:42:19 +00:00
|
|
|
//Todo: comment why return!
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if let Some(controller) = controllers.get_mut(entity) {
|
|
|
|
controller.events.push(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
ClientGeneral::ControlAction(event) => {
|
2020-10-30 16:39:53 +00:00
|
|
|
if matches!(presence.kind, PresenceKind::Character(_)) {
|
2020-10-16 23:42:19 +00:00
|
|
|
if let Some(controller) = controllers.get_mut(entity) {
|
|
|
|
controller.actions.push(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
ClientGeneral::PlayerPhysics { pos, vel, ori } => {
|
2020-10-30 16:39:53 +00:00
|
|
|
if matches!(presence.kind, PresenceKind::Character(_))
|
|
|
|
&& force_updates.get(entity).is_none()
|
2020-10-31 22:34:08 +00:00
|
|
|
&& healths.get(entity).map_or(true, |h| !h.is_dead)
|
2020-10-30 16:39:53 +00:00
|
|
|
{
|
|
|
|
let _ = positions.insert(entity, pos);
|
|
|
|
let _ = velocities.insert(entity, vel);
|
|
|
|
let _ = orientations.insert(entity, ori);
|
2020-10-16 23:42:19 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
ClientGeneral::BreakBlock(pos) => {
|
|
|
|
if let Some(block) = can_build.get(entity).and_then(|_| terrain.get(pos).ok()) {
|
|
|
|
block_changes.set(pos, block.into_vacant());
|
|
|
|
}
|
|
|
|
},
|
|
|
|
ClientGeneral::PlaceBlock(pos, block) => {
|
|
|
|
if can_build.get(entity).is_some() {
|
|
|
|
block_changes.try_set(pos, block);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
ClientGeneral::TerrainChunkRequest { key } => {
|
2020-10-30 16:39:53 +00:00
|
|
|
let in_vd = if let Some(pos) = positions.get(entity) {
|
2020-10-16 23:42:19 +00:00
|
|
|
pos.0.xy().map(|e| e as f64).distance(
|
|
|
|
key.map(|e| e as f64 + 0.5) * TerrainChunkSize::RECT_SIZE.map(|e| e as f64),
|
2020-10-30 16:39:53 +00:00
|
|
|
) < (presence.view_distance as f64 - 1.0 + 2.5 * 2.0_f64.sqrt())
|
2020-10-16 23:42:19 +00:00
|
|
|
* TerrainChunkSize::RECT_SIZE.x as f64
|
|
|
|
} else {
|
|
|
|
true
|
|
|
|
};
|
|
|
|
if in_vd {
|
|
|
|
match terrain.get_key(key) {
|
|
|
|
Some(chunk) => {
|
|
|
|
network_metrics.chunks_served_from_memory.inc();
|
2020-11-02 18:30:56 +00:00
|
|
|
client.send(ServerGeneral::TerrainChunkUpdate {
|
2020-10-16 23:42:19 +00:00
|
|
|
key,
|
|
|
|
chunk: Ok(Box::new(chunk.clone())),
|
|
|
|
})?
|
|
|
|
},
|
|
|
|
None => {
|
|
|
|
network_metrics.chunks_generation_triggered.inc();
|
|
|
|
server_emitter.emit(ServerEvent::ChunkRequest(entity, key))
|
|
|
|
},
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
network_metrics.chunks_request_dropped.inc();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
ClientGeneral::UnlockSkill(skill) => {
|
|
|
|
stats
|
|
|
|
.get_mut(entity)
|
2021-01-07 20:25:12 +00:00
|
|
|
.map(|mut s| s.skill_set.unlock_skill(skill));
|
2020-10-16 23:42:19 +00:00
|
|
|
},
|
|
|
|
ClientGeneral::RefundSkill(skill) => {
|
|
|
|
stats
|
|
|
|
.get_mut(entity)
|
2021-01-07 20:25:12 +00:00
|
|
|
.map(|mut s| s.skill_set.refund_skill(skill));
|
2020-10-16 23:42:19 +00:00
|
|
|
},
|
2021-01-18 19:08:13 +00:00
|
|
|
ClientGeneral::UnlockSkillGroup(skill_group_kind) => {
|
2020-10-16 23:42:19 +00:00
|
|
|
stats
|
|
|
|
.get_mut(entity)
|
2021-01-18 19:08:13 +00:00
|
|
|
.map(|mut s| s.skill_set.unlock_skill_group(skill_group_kind));
|
2020-10-16 23:42:19 +00:00
|
|
|
},
|
|
|
|
_ => unreachable!("not a client_in_game msg"),
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// This system will handle new messages from clients
|
2021-03-04 14:00:16 +00:00
|
|
|
#[derive(Default)]
|
2020-10-16 23:42:19 +00:00
|
|
|
pub struct Sys;
|
2021-03-04 14:00:16 +00:00
|
|
|
impl<'a> VSystem<'a> for Sys {
|
2020-10-18 22:57:43 +00:00
|
|
|
#[allow(clippy::type_complexity)]
|
2020-10-16 23:42:19 +00:00
|
|
|
type SystemData = (
|
|
|
|
Entities<'a>,
|
|
|
|
Read<'a, EventBus<ServerEvent>>,
|
|
|
|
ReadExpect<'a, TerrainGrid>,
|
|
|
|
ReadExpect<'a, NetworkRequestMetrics>,
|
|
|
|
ReadStorage<'a, CanBuild>,
|
|
|
|
ReadStorage<'a, ForceUpdate>,
|
|
|
|
WriteStorage<'a, Stats>,
|
2020-10-31 22:34:08 +00:00
|
|
|
ReadStorage<'a, Health>,
|
2020-10-16 23:42:19 +00:00
|
|
|
Write<'a, BlockChange>,
|
|
|
|
WriteStorage<'a, Pos>,
|
|
|
|
WriteStorage<'a, Vel>,
|
|
|
|
WriteStorage<'a, Ori>,
|
2020-10-30 16:39:53 +00:00
|
|
|
WriteStorage<'a, Presence>,
|
2020-10-16 23:42:19 +00:00
|
|
|
WriteStorage<'a, Client>,
|
|
|
|
WriteStorage<'a, Controller>,
|
|
|
|
Read<'a, Settings>,
|
|
|
|
);
|
|
|
|
|
2021-03-04 14:00:16 +00:00
|
|
|
const NAME: &'static str = "msg::in_game";
|
|
|
|
const ORIGIN: Origin = Origin::Server;
|
|
|
|
const PHASE: Phase = Phase::Create;
|
|
|
|
|
2020-10-16 23:42:19 +00:00
|
|
|
fn run(
|
2021-03-04 14:00:16 +00:00
|
|
|
_job: &mut VJob<Self>,
|
2020-10-16 23:42:19 +00:00
|
|
|
(
|
|
|
|
entities,
|
|
|
|
server_event_bus,
|
|
|
|
terrain,
|
|
|
|
network_metrics,
|
|
|
|
can_build,
|
|
|
|
force_updates,
|
|
|
|
mut stats,
|
2020-10-31 22:34:08 +00:00
|
|
|
healths,
|
2020-10-16 23:42:19 +00:00
|
|
|
mut block_changes,
|
|
|
|
mut positions,
|
|
|
|
mut velocities,
|
|
|
|
mut orientations,
|
2020-10-30 16:39:53 +00:00
|
|
|
mut presences,
|
2020-10-16 23:42:19 +00:00
|
|
|
mut clients,
|
|
|
|
mut controllers,
|
|
|
|
settings,
|
|
|
|
): Self::SystemData,
|
|
|
|
) {
|
|
|
|
let mut server_emitter = server_event_bus.emitter();
|
|
|
|
|
2020-11-02 18:30:56 +00:00
|
|
|
for (entity, client, mut maybe_presence) in
|
|
|
|
(&entities, &mut clients, (&mut presences).maybe()).join()
|
2020-10-17 09:36:44 +00:00
|
|
|
{
|
2020-11-02 18:30:56 +00:00
|
|
|
let _ = super::try_recv_all(client, 2, |client, msg| {
|
2020-10-17 09:36:44 +00:00
|
|
|
Self::handle_client_in_game_msg(
|
|
|
|
&mut server_emitter,
|
|
|
|
entity,
|
|
|
|
client,
|
2021-01-07 20:25:12 +00:00
|
|
|
&mut maybe_presence.as_deref_mut(),
|
2020-10-17 09:36:44 +00:00
|
|
|
&terrain,
|
|
|
|
&network_metrics,
|
|
|
|
&can_build,
|
|
|
|
&force_updates,
|
|
|
|
&mut stats,
|
2020-10-31 22:34:08 +00:00
|
|
|
&healths,
|
2020-10-17 09:36:44 +00:00
|
|
|
&mut block_changes,
|
|
|
|
&mut positions,
|
|
|
|
&mut velocities,
|
|
|
|
&mut orientations,
|
|
|
|
&mut controllers,
|
|
|
|
&settings,
|
|
|
|
msg,
|
|
|
|
)
|
|
|
|
});
|
2020-10-16 23:42:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|