mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Add LoD zone data to char select screen
This commit is contained in:
parent
5d4133eea5
commit
5bc60f2436
@ -242,6 +242,7 @@ pub struct Client {
|
||||
available_recipes: HashMap<String, Option<SpriteKind>>,
|
||||
lod_zones: HashMap<Vec2<i32>, lod::Zone>,
|
||||
lod_last_requested: Option<Instant>,
|
||||
lod_pos_fallback: Option<Vec2<f32>>,
|
||||
force_update_counter: u64,
|
||||
|
||||
max_group_size: u32,
|
||||
@ -753,6 +754,7 @@ impl Client {
|
||||
|
||||
lod_zones: HashMap::new(),
|
||||
lod_last_requested: None,
|
||||
lod_pos_fallback: None,
|
||||
|
||||
force_update_counter: 0,
|
||||
|
||||
@ -890,7 +892,7 @@ impl Client {
|
||||
| ClientGeneral::DeleteCharacter(_)
|
||||
| ClientGeneral::Character(_, _)
|
||||
| ClientGeneral::Spectate(_) => &mut self.character_screen_stream,
|
||||
//Only in game
|
||||
// Only in game
|
||||
ClientGeneral::ControllerInputs(_)
|
||||
| ClientGeneral::ControlEvent(_)
|
||||
| ClientGeneral::ControlAction(_)
|
||||
@ -911,7 +913,7 @@ impl Client {
|
||||
}
|
||||
&mut self.in_game_stream
|
||||
},
|
||||
//Only in game, terrain
|
||||
// Terrain
|
||||
ClientGeneral::TerrainChunkRequest { .. }
|
||||
| ClientGeneral::LodZoneRequest { .. } => {
|
||||
#[cfg(feature = "tracy")]
|
||||
@ -920,7 +922,7 @@ impl Client {
|
||||
}
|
||||
&mut self.terrain_stream
|
||||
},
|
||||
//Always possible
|
||||
// Always possible
|
||||
ClientGeneral::ChatMsg(_)
|
||||
| ClientGeneral::Command(_, _)
|
||||
| ClientGeneral::Terminate => &mut self.general_stream,
|
||||
@ -1196,6 +1198,10 @@ impl Client {
|
||||
|
||||
pub fn lod_zones(&self) -> &HashMap<Vec2<i32>, lod::Zone> { &self.lod_zones }
|
||||
|
||||
/// Set the fallback position used for loading LoD zones when the client
|
||||
/// entity does not have a position.
|
||||
pub fn set_lod_pos_fallback(&mut self, pos: Vec2<f32>) { self.lod_pos_fallback = Some(pos); }
|
||||
|
||||
/// Returns whether the specified recipe can be crafted and the sprite, if
|
||||
/// any, that is required to do so.
|
||||
pub fn can_craft_recipe(&self, recipe: &str, amount: u32) -> (bool, Option<SpriteKind>) {
|
||||
@ -2088,9 +2094,11 @@ impl Client {
|
||||
let now = Instant::now();
|
||||
self.pending_chunks
|
||||
.retain(|_, created| now.duration_since(*created) < Duration::from_secs(3));
|
||||
}
|
||||
|
||||
if let Some(lod_pos) = pos.map(|p| p.0.xy()).or(self.lod_pos_fallback) {
|
||||
// Manage LoD zones
|
||||
let lod_zone = pos.0.xy().map(|e| lod::from_wpos(e as i32));
|
||||
let lod_zone = lod_pos.map(|e| lod::from_wpos(e as i32));
|
||||
|
||||
// Request LoD zones that are in range
|
||||
if self
|
||||
|
@ -128,7 +128,6 @@ impl ClientMsg {
|
||||
| ClientGeneral::ExitInGame
|
||||
| ClientGeneral::PlayerPhysics { .. }
|
||||
| ClientGeneral::TerrainChunkRequest { .. }
|
||||
| ClientGeneral::LodZoneRequest { .. }
|
||||
| ClientGeneral::UnlockSkill(_)
|
||||
| ClientGeneral::RequestSiteInfo(_)
|
||||
| ClientGeneral::RequestPlayerPhysics { .. }
|
||||
@ -140,7 +139,9 @@ impl ClientMsg {
|
||||
//Always possible
|
||||
ClientGeneral::ChatMsg(_)
|
||||
| ClientGeneral::Command(_, _)
|
||||
| ClientGeneral::Terminate => true,
|
||||
| ClientGeneral::Terminate
|
||||
// LodZoneRequest is required by the char select screen
|
||||
| ClientGeneral::LodZoneRequest { .. } => true,
|
||||
}
|
||||
},
|
||||
ClientMsg::Ping(_) => true,
|
||||
|
@ -324,7 +324,6 @@ impl ServerMsg {
|
||||
| ServerGeneral::InventoryUpdate(_, _)
|
||||
| ServerGeneral::GroupInventoryUpdate(_, _, _)
|
||||
| ServerGeneral::TerrainChunkUpdate { .. }
|
||||
| ServerGeneral::LodZoneUpdate { .. }
|
||||
| ServerGeneral::TerrainBlockUpdates(_)
|
||||
| ServerGeneral::SetViewDistance(_)
|
||||
| ServerGeneral::Outcomes(_)
|
||||
@ -348,7 +347,8 @@ impl ServerMsg {
|
||||
| ServerGeneral::CreateEntity(_)
|
||||
| ServerGeneral::DeleteEntity(_)
|
||||
| ServerGeneral::Disconnect(_)
|
||||
| ServerGeneral::Notification(_) => true,
|
||||
| ServerGeneral::Notification(_)
|
||||
| ServerGeneral::LodZoneUpdate { .. } => true,
|
||||
}
|
||||
},
|
||||
ServerMsg::Ping(_) => true,
|
||||
|
@ -192,7 +192,7 @@ impl Client {
|
||||
| ServerGeneral::SpectatePosition(_) => {
|
||||
PreparedMsg::new(2, &g, &self.in_game_stream_params)
|
||||
},
|
||||
//In-game related, terrain
|
||||
// Terrain
|
||||
ServerGeneral::TerrainChunkUpdate { .. }
|
||||
| ServerGeneral::LodZoneUpdate { .. }
|
||||
| ServerGeneral::TerrainBlockUpdates(_) => {
|
||||
|
@ -61,61 +61,63 @@ impl<'a> System<'a> for Sys {
|
||||
|(chunk_send_emitter, server_emitter), (entity, client, maybe_presence)| {
|
||||
let mut chunk_requests = Vec::new();
|
||||
let _ = super::try_recv_all(client, 5, |client, msg| {
|
||||
let presence = match maybe_presence {
|
||||
Some(g) => g,
|
||||
None => {
|
||||
debug!(?entity, "client is not in_game, ignoring msg");
|
||||
trace!(?msg, "ignored msg content");
|
||||
if matches!(msg, ClientGeneral::TerrainChunkRequest { .. }) {
|
||||
network_metrics.chunks_request_dropped.inc();
|
||||
}
|
||||
return Ok(());
|
||||
},
|
||||
};
|
||||
match msg {
|
||||
ClientGeneral::TerrainChunkRequest { key } => {
|
||||
let in_vd = if let Some(pos) = positions.get(entity) {
|
||||
pos.0.xy().map(|e| e as f64).distance_squared(
|
||||
key.map(|e| e as f64 + 0.5)
|
||||
* TerrainChunkSize::RECT_SIZE.map(|e| e as f64),
|
||||
) < ((presence.terrain_view_distance.current() as f64 - 1.0
|
||||
+ 2.5 * 2.0_f64.sqrt())
|
||||
* TerrainChunkSize::RECT_SIZE.x as f64)
|
||||
.powi(2)
|
||||
} else {
|
||||
true
|
||||
};
|
||||
if in_vd {
|
||||
if terrain.get_key_arc(key).is_some() {
|
||||
network_metrics.chunks_served_from_memory.inc();
|
||||
chunk_send_emitter.emit(ChunkSendEntry {
|
||||
chunk_key: key,
|
||||
entity,
|
||||
});
|
||||
} else {
|
||||
network_metrics.chunks_generation_triggered.inc();
|
||||
chunk_requests.push(ChunkRequest { entity, key });
|
||||
// SPECIAL CASE: LOD zone requests can be sent by non-present players
|
||||
if let ClientGeneral::LodZoneRequest { key } = &msg {
|
||||
client.send(ServerGeneral::LodZoneUpdate {
|
||||
key: *key,
|
||||
zone: lod.zone(*key).clone(),
|
||||
})?;
|
||||
} else {
|
||||
let presence = match maybe_presence {
|
||||
Some(g) => g,
|
||||
None => {
|
||||
debug!(?entity, "client is not in_game, ignoring msg");
|
||||
trace!(?msg, "ignored msg content");
|
||||
if matches!(msg, ClientGeneral::TerrainChunkRequest { .. }) {
|
||||
network_metrics.chunks_request_dropped.inc();
|
||||
}
|
||||
} else {
|
||||
network_metrics.chunks_request_dropped.inc();
|
||||
}
|
||||
},
|
||||
ClientGeneral::LodZoneRequest { key } => {
|
||||
client.send(ServerGeneral::LodZoneUpdate {
|
||||
key,
|
||||
zone: lod.zone(key).clone(),
|
||||
})?;
|
||||
},
|
||||
_ => {
|
||||
debug!(
|
||||
"Kicking possibly misbehaving client due to invalud terrain \
|
||||
request"
|
||||
);
|
||||
server_emitter.emit(ServerEvent::ClientDisconnect(
|
||||
entity,
|
||||
common::comp::DisconnectReason::NetworkError,
|
||||
));
|
||||
},
|
||||
return Ok(());
|
||||
},
|
||||
};
|
||||
match msg {
|
||||
ClientGeneral::TerrainChunkRequest { key } => {
|
||||
let in_vd = if let Some(pos) = positions.get(entity) {
|
||||
pos.0.xy().map(|e| e as f64).distance_squared(
|
||||
key.map(|e| e as f64 + 0.5)
|
||||
* TerrainChunkSize::RECT_SIZE.map(|e| e as f64),
|
||||
) < ((presence.terrain_view_distance.current() as f64 - 1.0
|
||||
+ 2.5 * 2.0_f64.sqrt())
|
||||
* TerrainChunkSize::RECT_SIZE.x as f64)
|
||||
.powi(2)
|
||||
} else {
|
||||
true
|
||||
};
|
||||
if in_vd {
|
||||
if terrain.get_key_arc(key).is_some() {
|
||||
network_metrics.chunks_served_from_memory.inc();
|
||||
chunk_send_emitter.emit(ChunkSendEntry {
|
||||
chunk_key: key,
|
||||
entity,
|
||||
});
|
||||
} else {
|
||||
network_metrics.chunks_generation_triggered.inc();
|
||||
chunk_requests.push(ChunkRequest { entity, key });
|
||||
}
|
||||
} else {
|
||||
network_metrics.chunks_request_dropped.inc();
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
debug!(
|
||||
"Kicking possibly misbehaving client due to invalud terrain \
|
||||
request"
|
||||
);
|
||||
server_emitter.emit(ServerEvent::ClientDisconnect(
|
||||
entity,
|
||||
common::comp::DisconnectReason::NetworkError,
|
||||
));
|
||||
},
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
|
@ -27,7 +27,7 @@ impl CharSelectionState {
|
||||
pub fn new(global_state: &mut GlobalState, client: Rc<RefCell<Client>>) -> Self {
|
||||
let scene = Scene::new(
|
||||
global_state.window.renderer_mut(),
|
||||
&client.borrow(),
|
||||
&mut client.borrow_mut(),
|
||||
&global_state.settings,
|
||||
);
|
||||
let char_selection_ui = CharSelectionUi::new(global_state, &client.borrow());
|
||||
|
@ -96,7 +96,7 @@ pub struct SceneData<'a> {
|
||||
}
|
||||
|
||||
impl Scene {
|
||||
pub fn new(renderer: &mut Renderer, client: &Client, settings: &Settings) -> Self {
|
||||
pub fn new(renderer: &mut Renderer, client: &mut Client, settings: &Settings) -> Self {
|
||||
let start_angle = -90.0f32.to_radians();
|
||||
let resolution = renderer.resolution().map(|e| e as f32);
|
||||
|
||||
@ -132,6 +132,8 @@ impl Scene {
|
||||
.get(char_chunk)
|
||||
.map_or(0.0, |z| *z as f32 + 100.0),
|
||||
);
|
||||
client.set_lod_pos_fallback(char_pos.xy());
|
||||
client.set_lod_distance(settings.graphics.lod_distance);
|
||||
|
||||
Self {
|
||||
data,
|
||||
|
Loading…
Reference in New Issue
Block a user