mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Add an entity view distance setting that allows limiting the distance
entities are synced from and displayed in. NOTE: Syncing entities work at the granularity regions which are multi-chunk squares but the display of entities in voxygen is limited in a circle with the radiues of the supplied distance. Additional details and changes: * Added `ViewDistances` struct in `common` that contains separate terrain and entity view distances (the entity view distance will be clamped by the terrain view distance in uses of this). * View distance requests from the client to the server now use this type. * When requesting the character or spectate state the client now passes its desired view distances. This is exposed as a new parameter on `Client::request_character`/`Client::request_spectate`. And the client no longer needs to send a view distance request after entering these states. This also allows us to avoid needing to initialize `Presence` with a default view distance value on the server. * Removed `DerefFlaggedStorage` from `Presence` and `RegionSubscription` since the change tracking isn't used for these components. * Add sliders in voxygen graphics and network tabs for this new setting. Show the clamped value as well as the selected value next to the slider. * Rename existing "Entities View Distance" slider (which AFAIK controls the distance at which different LOD levels apply to figures) to "Entities Detail Distance" so we can use the former name for this new slider.
This commit is contained in:
parent
895d6a2d8b
commit
334937568e
@ -54,9 +54,10 @@ hud-settings-auto_camera = Auto camera
|
||||
hud-settings-bow_zoom = Zoom in when charging bow
|
||||
hud-settings-reset_gameplay = Reset to Defaults
|
||||
hud-settings-view_distance = View Distance
|
||||
hud-settings-entity_view_distance = Entities View Distance
|
||||
hud-settings-lod_distance = LoD Distance
|
||||
hud-settings-sprites_view_distance = Sprites View Distance
|
||||
hud-settings-figures_view_distance = Entities View Distance
|
||||
hud-settings-entities_detail_distance = Entities Detail Distance
|
||||
hud-settings-maximum_fps = Maximum FPS
|
||||
hud-settings-background_fps = Background FPS
|
||||
hud-settings-present_mode = Present Mode
|
||||
|
@ -249,6 +249,7 @@ pub struct Client {
|
||||
state: State,
|
||||
|
||||
server_view_distance_limit: Option<u32>,
|
||||
/// Terrrain view distance
|
||||
view_distance: Option<u32>,
|
||||
lod_distance: f32,
|
||||
// TODO: move into voxygen
|
||||
@ -805,8 +806,8 @@ impl Client {
|
||||
| ClientGeneral::CreateCharacter { .. }
|
||||
| ClientGeneral::EditCharacter { .. }
|
||||
| ClientGeneral::DeleteCharacter(_)
|
||||
| ClientGeneral::Character(_)
|
||||
| ClientGeneral::Spectate => &mut self.character_screen_stream,
|
||||
| ClientGeneral::Character(_, _)
|
||||
| ClientGeneral::Spectate(_) => &mut self.character_screen_stream,
|
||||
//Only in game
|
||||
ClientGeneral::ControllerInputs(_)
|
||||
| ClientGeneral::ControlEvent(_)
|
||||
@ -881,16 +882,16 @@ impl Client {
|
||||
}
|
||||
|
||||
/// Request a state transition to `ClientState::Character`.
|
||||
pub fn request_character(&mut self, character_id: CharacterId) {
|
||||
self.send_msg(ClientGeneral::Character(character_id));
|
||||
pub fn request_character(&mut self, character_id: CharacterId, view_distances: common::ViewDistances) {
|
||||
self.send_msg(ClientGeneral::Character(character_id, view_distances));
|
||||
|
||||
// Assume we are in_game unless server tells us otherwise
|
||||
self.presence = Some(PresenceKind::Character(character_id));
|
||||
}
|
||||
|
||||
/// Request a state transition to `ClientState::Spectate`.
|
||||
pub fn request_spectate(&mut self) {
|
||||
self.send_msg(ClientGeneral::Spectate);
|
||||
pub fn request_spectate(&mut self, view_distances: common::ViewDistances) {
|
||||
self.send_msg(ClientGeneral::Spectate(view_distances));
|
||||
|
||||
self.presence = Some(PresenceKind::Spectator);
|
||||
}
|
||||
@ -944,11 +945,14 @@ impl Client {
|
||||
self.send_msg(ClientGeneral::ExitInGame);
|
||||
}
|
||||
|
||||
pub fn set_view_distance(&mut self, view_distance: u32) {
|
||||
if self.server_view_distance_limit.map_or(true, |limit| view_distance >= limit) {
|
||||
let view_distance = view_distance.max(1).min(65);
|
||||
self.view_distance = Some(view_distance);
|
||||
self.send_msg(ClientGeneral::SetViewDistance(view_distance));
|
||||
pub fn set_view_distances(&mut self, view_distances: common::ViewDistances) {
|
||||
if self.server_view_distance_limit.map_or(true, |limit| view_distances.terrain >= limit) {
|
||||
let view_distances = common::ViewDistances {
|
||||
terrain: view_distances.terrain.max(1).min(65),
|
||||
entity: view_distances.entity,
|
||||
};
|
||||
self.view_distance = Some(view_distances.terrain);
|
||||
self.send_msg(ClientGeneral::SetViewDistance(view_distances));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2357,18 +2361,10 @@ impl Client {
|
||||
ServerGeneral::CharacterEdited(character_id) => {
|
||||
events.push(Event::CharacterEdited(character_id));
|
||||
},
|
||||
ServerGeneral::CharacterSuccess => {
|
||||
debug!("client is now in ingame state on server");
|
||||
if let Some(vd) = self.view_distance {
|
||||
self.set_view_distance(vd);
|
||||
}
|
||||
},
|
||||
ServerGeneral::CharacterSuccess => debug!("client is now in ingame state on server"),
|
||||
ServerGeneral::SpectatorSuccess(spawn_point) => {
|
||||
if let Some(vd) = self.view_distance {
|
||||
events.push(Event::StartSpectate(spawn_point));
|
||||
debug!("client is now in ingame state on server");
|
||||
self.set_view_distance(vd);
|
||||
}
|
||||
events.push(Event::StartSpectate(spawn_point));
|
||||
debug!("client is now in ingame state on server");
|
||||
},
|
||||
_ => unreachable!("Not a character_screen msg"),
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ use common::{
|
||||
comp,
|
||||
comp::{Skill, SkillGroupKind},
|
||||
terrain::block::Block,
|
||||
ViewDistances,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use vek::*;
|
||||
@ -60,13 +61,13 @@ pub enum ClientGeneral {
|
||||
alias: String,
|
||||
body: comp::Body,
|
||||
},
|
||||
Character(CharacterId),
|
||||
Spectate,
|
||||
Character(CharacterId, ViewDistances),
|
||||
Spectate(ViewDistances),
|
||||
//Only in game
|
||||
ControllerInputs(Box<comp::ControllerInputs>),
|
||||
ControlEvent(comp::ControlEvent),
|
||||
ControlAction(comp::ControlAction),
|
||||
SetViewDistance(u32),
|
||||
SetViewDistance(ViewDistances),
|
||||
BreakBlock(Vec3<i32>),
|
||||
PlaceBlock(Vec3<i32>, Block),
|
||||
ExitInGame,
|
||||
@ -121,7 +122,7 @@ impl ClientMsg {
|
||||
| ClientGeneral::DeleteCharacter(_) => {
|
||||
c_type != ClientType::ChatOnly && presence.is_none()
|
||||
},
|
||||
ClientGeneral::Character(_) | ClientGeneral::Spectate => {
|
||||
ClientGeneral::Character(_, _) | ClientGeneral::Spectate(_) => {
|
||||
c_type == ClientType::Game && presence.is_none()
|
||||
},
|
||||
//Only in game
|
||||
|
@ -166,6 +166,10 @@ pub enum ServerGeneral {
|
||||
/// from an ingame state
|
||||
ExitInGameSuccess,
|
||||
InventoryUpdate(comp::Inventory, comp::InventoryUpdateEvent),
|
||||
/// NOTE: The client can infer that entity view distance will be at most the
|
||||
/// terrain view distance that we send here (and if lower it won't be
|
||||
/// modified). So we just need to send the terrain VD back to the client
|
||||
/// if corrections are made.
|
||||
SetViewDistance(u32),
|
||||
Outcomes(Vec<Outcome>),
|
||||
Knockback(Vec3<f32>),
|
||||
|
@ -107,8 +107,9 @@ pub enum ServerEvent {
|
||||
InitCharacterData {
|
||||
entity: EcsEntity,
|
||||
character_id: CharacterId,
|
||||
requested_view_distances: crate::ViewDistances,
|
||||
},
|
||||
InitSpectator(EcsEntity),
|
||||
InitSpectator(EcsEntity, crate::ViewDistances),
|
||||
UpdateCharacterData {
|
||||
entity: EcsEntity,
|
||||
components: (
|
||||
|
@ -81,6 +81,7 @@ pub mod terrain;
|
||||
#[cfg(not(target_arch = "wasm32"))] pub mod typed;
|
||||
pub mod uid;
|
||||
#[cfg(not(target_arch = "wasm32"))] pub mod util;
|
||||
mod view_distances;
|
||||
#[cfg(not(target_arch = "wasm32"))] pub mod vol;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub mod volumes;
|
||||
@ -98,3 +99,4 @@ pub use comp::inventory::loadout_builder::LoadoutBuilder;
|
||||
pub use explosion::{Explosion, RadiusEffect};
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub use skillset_builder::SkillSetBuilder;
|
||||
pub use view_distances::ViewDistances;
|
||||
|
23
common/src/view_distances.rs
Normal file
23
common/src/view_distances.rs
Normal file
@ -0,0 +1,23 @@
|
||||
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
|
||||
pub struct ViewDistances {
|
||||
pub terrain: u32,
|
||||
/// Server will clamp this to `terrain` if it is larger.
|
||||
///
|
||||
/// NOTE: Importantly, the server still loads entities in the `terrain` view
|
||||
/// distance (at least currently, please update this if you change it!),
|
||||
/// but the syncing to the client is done based on the entity view
|
||||
/// distance.
|
||||
pub entity: u32,
|
||||
}
|
||||
|
||||
impl ViewDistances {
|
||||
/// Clamps the terrain view distance to an optional max and clamps the
|
||||
/// entity view distance to the resulting terrain view distance.
|
||||
pub fn clamp(self, max: Option<u32>) -> Self {
|
||||
let terrain = max.unwrap_or(u32::MAX).min(self.terrain);
|
||||
Self {
|
||||
terrain,
|
||||
entity: self.entity.min(terrain),
|
||||
}
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@ use common::{
|
||||
rtsim::RtSimEntity,
|
||||
uid::Uid,
|
||||
util::Dir,
|
||||
ViewDistances,
|
||||
};
|
||||
use common_net::{msg::ServerGeneral, sync::WorldSyncExt};
|
||||
use specs::{Builder, Entity as EcsEntity, WorldExt};
|
||||
@ -29,12 +30,29 @@ pub fn handle_initialize_character(
|
||||
server: &mut Server,
|
||||
entity: EcsEntity,
|
||||
character_id: CharacterId,
|
||||
requested_view_distances: ViewDistances,
|
||||
) {
|
||||
server.state.initialize_character_data(entity, character_id);
|
||||
let clamped_vds = requested_view_distances.clamp(server.settings().max_view_distance);
|
||||
server
|
||||
.state
|
||||
.initialize_character_data(entity, character_id, clamped_vds);
|
||||
// Correct client if its requested VD is too high.
|
||||
if requested_view_distances.terrain != clamped_vds.terrain {
|
||||
server.notify_client(entity, ServerGeneral::SetViewDistance(clamped_vds.terrain));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_initialize_spectator(server: &mut Server, entity: EcsEntity) {
|
||||
server.state.initialize_spectator_data(entity);
|
||||
pub fn handle_initialize_spectator(
|
||||
server: &mut Server,
|
||||
entity: EcsEntity,
|
||||
requested_view_distances: ViewDistances,
|
||||
) {
|
||||
let clamped_vds = requested_view_distances.clamp(server.settings().max_view_distance);
|
||||
server.state.initialize_spectator_data(entity, clamped_vds);
|
||||
// Correct client if its requested VD is too high.
|
||||
if requested_view_distances.terrain != clamped_vds.terrain {
|
||||
server.notify_client(entity, ServerGeneral::SetViewDistance(clamped_vds.terrain));
|
||||
}
|
||||
sys::subscription::initialize_region_subscription(server.state.ecs(), entity);
|
||||
}
|
||||
|
||||
|
@ -140,8 +140,16 @@ impl Server {
|
||||
ServerEvent::InitCharacterData {
|
||||
entity,
|
||||
character_id,
|
||||
} => handle_initialize_character(self, entity, character_id),
|
||||
ServerEvent::InitSpectator(entity) => handle_initialize_spectator(self, entity),
|
||||
requested_view_distances,
|
||||
} => handle_initialize_character(
|
||||
self,
|
||||
entity,
|
||||
character_id,
|
||||
requested_view_distances,
|
||||
),
|
||||
ServerEvent::InitSpectator(entity, requested_view_distances) => {
|
||||
handle_initialize_spectator(self, entity, requested_view_distances)
|
||||
},
|
||||
ServerEvent::UpdateCharacterData { entity, components } => {
|
||||
let (
|
||||
body,
|
||||
|
@ -1,22 +1,24 @@
|
||||
use common_net::msg::PresenceKind;
|
||||
use hashbrown::HashSet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specs::{Component, DerefFlaggedStorage, NullStorage};
|
||||
use specs::{Component, NullStorage};
|
||||
use std::time::{Duration, Instant};
|
||||
use vek::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Presence {
|
||||
// TODO: separate view distance for syncing entities?
|
||||
pub view_distance: ViewDistance,
|
||||
pub terrain_view_distance: ViewDistance,
|
||||
pub entity_view_distance: ViewDistance,
|
||||
pub kind: PresenceKind,
|
||||
pub lossy_terrain_compression: bool,
|
||||
}
|
||||
|
||||
impl Presence {
|
||||
pub fn new(view_distance: u32, kind: PresenceKind) -> Self {
|
||||
pub fn new(view_distances: common::ViewDistances, kind: PresenceKind) -> Self {
|
||||
let now = Instant::now();
|
||||
Self {
|
||||
view_distance: ViewDistance::new(view_distance, Instant::now()),
|
||||
terrain_view_distance: ViewDistance::new(view_distances.terrain, now),
|
||||
entity_view_distance: ViewDistance::new(view_distances.entity, now),
|
||||
kind,
|
||||
lossy_terrain_compression: false,
|
||||
}
|
||||
@ -24,7 +26,7 @@ impl Presence {
|
||||
}
|
||||
|
||||
impl Component for Presence {
|
||||
type Storage = DerefFlaggedStorage<Self, specs::DenseVecStorage<Self>>;
|
||||
type Storage = specs::DenseVecStorage<Self>;
|
||||
}
|
||||
|
||||
// Distance from fuzzy_chunk before snapping to current chunk
|
||||
@ -35,12 +37,12 @@ pub const REGION_FUZZ: u32 = 16;
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RegionSubscription {
|
||||
pub fuzzy_chunk: Vec2<i32>,
|
||||
pub last_view_distance: u32,
|
||||
pub last_entity_view_distance: u32,
|
||||
pub regions: HashSet<Vec2<i32>>,
|
||||
}
|
||||
|
||||
impl Component for RegionSubscription {
|
||||
type Storage = DerefFlaggedStorage<Self, specs::DenseVecStorage<Self>>;
|
||||
type Storage = specs::DenseVecStorage<Self>;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
|
||||
|
@ -26,6 +26,7 @@ use common::{
|
||||
resources::{Time, TimeOfDay},
|
||||
slowjob::SlowJobPool,
|
||||
uid::{Uid, UidAllocator},
|
||||
ViewDistances,
|
||||
};
|
||||
use common_net::{
|
||||
msg::{CharacterInfo, PlayerListUpdate, PresenceKind, ServerGeneral},
|
||||
@ -107,9 +108,14 @@ pub trait StateExt {
|
||||
index: &world::IndexOwned,
|
||||
) -> EcsEntityBuilder;
|
||||
/// Insert common/default components for a new character joining the server
|
||||
fn initialize_character_data(&mut self, entity: EcsEntity, character_id: CharacterId);
|
||||
fn initialize_character_data(
|
||||
&mut self,
|
||||
entity: EcsEntity,
|
||||
character_id: CharacterId,
|
||||
view_distances: ViewDistances,
|
||||
);
|
||||
/// Insert common/default components for a new spectator joining the server
|
||||
fn initialize_spectator_data(&mut self, entity: EcsEntity);
|
||||
fn initialize_spectator_data(&mut self, entity: EcsEntity, view_distances: ViewDistances);
|
||||
/// Update the components associated with the entity's current character.
|
||||
/// Performed after loading component data from the database
|
||||
fn update_character_data(&mut self, entity: EcsEntity, components: PersistedComponents);
|
||||
@ -488,10 +494,21 @@ impl StateExt for State {
|
||||
self.ecs_mut()
|
||||
.create_entity_synced()
|
||||
.with(pos)
|
||||
.with(Presence::new(view_distance, PresenceKind::Spectator))
|
||||
.with(Presence::new(
|
||||
ViewDistances {
|
||||
terrain: view_distance,
|
||||
entity: view_distance,
|
||||
},
|
||||
PresenceKind::Spectator,
|
||||
))
|
||||
}
|
||||
|
||||
fn initialize_character_data(&mut self, entity: EcsEntity, character_id: CharacterId) {
|
||||
fn initialize_character_data(
|
||||
&mut self,
|
||||
entity: EcsEntity,
|
||||
character_id: CharacterId,
|
||||
view_distances: ViewDistances,
|
||||
) {
|
||||
let spawn_point = self.ecs().read_resource::<SpawnPoint>().0;
|
||||
|
||||
if let Some(player_uid) = self.read_component_copied::<Uid>(entity) {
|
||||
@ -519,10 +536,9 @@ impl StateExt for State {
|
||||
// Make sure physics components are updated
|
||||
self.write_component_ignore_entity_dead(entity, comp::ForceUpdate::forced());
|
||||
|
||||
const INITIAL_VD: u32 = 5; // will be changed after login
|
||||
self.write_component_ignore_entity_dead(
|
||||
entity,
|
||||
Presence::new(INITIAL_VD, PresenceKind::Character(character_id)),
|
||||
Presence::new(view_distances, PresenceKind::Character(character_id)),
|
||||
);
|
||||
|
||||
// Tell the client its request was successful.
|
||||
@ -532,7 +548,7 @@ impl StateExt for State {
|
||||
}
|
||||
}
|
||||
|
||||
fn initialize_spectator_data(&mut self, entity: EcsEntity) {
|
||||
fn initialize_spectator_data(&mut self, entity: EcsEntity, view_distances: ViewDistances) {
|
||||
let spawn_point = self.ecs().read_resource::<SpawnPoint>().0;
|
||||
|
||||
if self.read_component_copied::<Uid>(entity).is_some() {
|
||||
@ -545,10 +561,9 @@ impl StateExt for State {
|
||||
// Make sure physics components are updated
|
||||
self.write_component_ignore_entity_dead(entity, comp::ForceUpdate::forced());
|
||||
|
||||
const INITIAL_VD: u32 = 5; //will be changed after login
|
||||
self.write_component_ignore_entity_dead(
|
||||
entity,
|
||||
Presence::new(INITIAL_VD, PresenceKind::Spectator),
|
||||
Presence::new(view_distances, PresenceKind::Spectator),
|
||||
);
|
||||
|
||||
// Tell the client its request was successful.
|
||||
|
@ -384,7 +384,7 @@ impl<'a> System<'a> for Sys {
|
||||
let is_near = |o_pos: Vec3<f32>| {
|
||||
pos.zip_with(presence, |pos, presence| {
|
||||
pos.0.xy().distance_squared(o_pos.xy())
|
||||
< (presence.view_distance.current() as f32
|
||||
< (presence.entity_view_distance.current() as f32
|
||||
* TerrainChunkSize::RECT_SIZE.x as f32)
|
||||
.powi(2)
|
||||
})
|
||||
|
@ -64,17 +64,17 @@ impl Sys {
|
||||
};
|
||||
match msg {
|
||||
// Request spectator state
|
||||
ClientGeneral::Spectate => {
|
||||
ClientGeneral::Spectate(requested_view_distances) => {
|
||||
if let Some(admin) = admins.get(entity) && admin.0 >= AdminRole::Moderator {
|
||||
send_join_messages()?;
|
||||
|
||||
server_emitter.emit(ServerEvent::InitSpectator(entity));
|
||||
server_emitter.emit(ServerEvent::InitSpectator(entity, requested_view_distances));
|
||||
|
||||
} else {
|
||||
debug!("dropped Spectate msg from unprivileged client")
|
||||
}
|
||||
},
|
||||
ClientGeneral::Character(character_id) => {
|
||||
ClientGeneral::Character(character_id, requested_view_distances) => {
|
||||
if let Some(player) = players.get(entity) {
|
||||
if presences.contains(entity) {
|
||||
debug!("player already ingame, aborting");
|
||||
@ -117,6 +117,7 @@ impl Sys {
|
||||
server_emitter.emit(ServerEvent::InitCharacterData {
|
||||
entity,
|
||||
character_id,
|
||||
requested_view_distances,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
@ -53,7 +53,7 @@ impl Sys {
|
||||
time_for_vd_changes: Instant,
|
||||
msg: ClientGeneral,
|
||||
) -> Result<(), crate::error::Error> {
|
||||
let presence = match maybe_presence {
|
||||
let presence = match maybe_presence.as_deref_mut() {
|
||||
Some(g) => g,
|
||||
None => {
|
||||
debug!(?entity, "client is not in_game, ignoring msg");
|
||||
@ -68,16 +68,15 @@ impl Sys {
|
||||
client.send(ServerGeneral::ExitInGameSuccess)?;
|
||||
*maybe_presence = None;
|
||||
},
|
||||
ClientGeneral::SetViewDistance(view_distance) => {
|
||||
let clamped_view_distance = settings
|
||||
.max_view_distance
|
||||
.map(|max| view_distance.min(max))
|
||||
.unwrap_or(view_distance);
|
||||
presence.view_distance.set_target(clamped_view_distance, time_for_vd_changes);
|
||||
ClientGeneral::SetViewDistance(view_distances) => {
|
||||
let clamped_vds = view_distances.clamp(settings.max_view_distance);
|
||||
|
||||
presence.terrain_view_distance.set_target(clamped_vds.terrain, time_for_vd_changes);
|
||||
presence.entity_view_distance.set_target(clamped_vds.entity, time_for_vd_changes);
|
||||
|
||||
// Correct client if its requested VD is too high.
|
||||
if view_distance != clamped_view_distance {
|
||||
client.send(ServerGeneral::SetViewDistance(clamped_view_distance))?;
|
||||
if view_distances.terrain != clamped_vds.terrain {
|
||||
client.send(ServerGeneral::SetViewDistance(clamped_vds.terrain))?;
|
||||
}
|
||||
},
|
||||
ClientGeneral::ControllerInputs(inputs) => {
|
||||
@ -296,8 +295,8 @@ impl Sys {
|
||||
| ClientGeneral::CreateCharacter { .. }
|
||||
| ClientGeneral::EditCharacter { .. }
|
||||
| ClientGeneral::DeleteCharacter(_)
|
||||
| ClientGeneral::Character(_)
|
||||
| ClientGeneral::Spectate
|
||||
| ClientGeneral::Character(_, _)
|
||||
| ClientGeneral::Spectate(_)
|
||||
| ClientGeneral::TerrainChunkRequest { .. }
|
||||
| ClientGeneral::LodZoneRequest { .. }
|
||||
| ClientGeneral::ChatMsg(_)
|
||||
@ -419,8 +418,9 @@ impl<'a> System<'a> for Sys {
|
||||
|
||||
// Ensure deferred view distance changes are applied (if the
|
||||
// requsite time has elapsed).
|
||||
if let Some(mut presence) = maybe_presence {
|
||||
presence.view_distance.update(time_for_vd_changes);
|
||||
if let Some(presence) = maybe_presence {
|
||||
presence.terrain_view_distance.update(time_for_vd_changes);
|
||||
presence.entity_view_distance.update(time_for_vd_changes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ impl<'a> System<'a> for Sys {
|
||||
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.view_distance.current() as f64 - 1.0
|
||||
) < ((presence.terrain_view_distance.current() as f64 - 1.0
|
||||
+ 2.5 * 2.0_f64.sqrt())
|
||||
* TerrainChunkSize::RECT_SIZE.x as f64)
|
||||
.powi(2)
|
||||
|
@ -79,7 +79,7 @@ impl<'a> System<'a> for Sys {
|
||||
)
|
||||
.join()
|
||||
{
|
||||
let vd = presence.view_distance.current();
|
||||
let vd = presence.entity_view_distance.current();
|
||||
// Calculate current chunk
|
||||
let chunk = (Vec2::<f32>::from(pos.0))
|
||||
.map2(TerrainChunkSize::RECT_SIZE, |e, sz| e as i32 / sz as i32);
|
||||
@ -99,10 +99,10 @@ impl<'a> System<'a> for Sys {
|
||||
e.abs() > (sz / 2 + presence::CHUNK_FUZZ) as f32
|
||||
})
|
||||
.reduce_or()
|
||||
|| subscription.last_view_distance != vd
|
||||
|| subscription.last_entity_view_distance != vd
|
||||
{
|
||||
// Update the view distance
|
||||
subscription.last_view_distance = vd;
|
||||
subscription.last_entity_view_distance = vd;
|
||||
// Update current chunk
|
||||
subscription.fuzzy_chunk = Vec2::<f32>::from(pos.0)
|
||||
.map2(TerrainChunkSize::RECT_SIZE, |e, sz| e as i32 / sz as i32);
|
||||
@ -222,7 +222,7 @@ pub fn initialize_region_subscription(world: &World, entity: specs::Entity) {
|
||||
let chunk_size = TerrainChunkSize::RECT_SIZE.reduce_max() as f32;
|
||||
let regions = regions_in_vd(
|
||||
client_pos.0,
|
||||
(presence.view_distance.current() as f32 * chunk_size) as f32
|
||||
(presence.entity_view_distance.current() as f32 * chunk_size) as f32
|
||||
+ (presence::CHUNK_FUZZ as f32 + chunk_size) * 2.0f32.sqrt(),
|
||||
);
|
||||
|
||||
@ -267,7 +267,7 @@ pub fn initialize_region_subscription(world: &World, entity: specs::Entity) {
|
||||
|
||||
if let Err(e) = world.write_storage().insert(entity, RegionSubscription {
|
||||
fuzzy_chunk,
|
||||
last_view_distance: presence.view_distance.current(),
|
||||
last_entity_view_distance: presence.entity_view_distance.current(),
|
||||
regions,
|
||||
}) {
|
||||
error!(?e, "Failed to insert region subscription component");
|
||||
|
@ -269,7 +269,7 @@ impl<'a> System<'a> for Sys {
|
||||
.map(|e: i32| (e.unsigned_abs()).saturating_sub(2))
|
||||
.magnitude_squared();
|
||||
|
||||
if adjusted_dist_sqr <= presence.view_distance.current().pow(2) {
|
||||
if adjusted_dist_sqr <= presence.terrain_view_distance.current().pow(2) {
|
||||
chunk_send_emitter.emit(ChunkSendEntry {
|
||||
entity,
|
||||
chunk_key: key,
|
||||
@ -293,7 +293,7 @@ impl<'a> System<'a> for Sys {
|
||||
|
||||
// For each player with a position, calculate the distance.
|
||||
for (presence, pos) in (&presences, &positions).join() {
|
||||
if chunk_in_vd(pos.0, chunk_key, &terrain, presence.view_distance.current()) {
|
||||
if chunk_in_vd(pos.0, chunk_key, &terrain, presence.terrain_view_distance.current()) {
|
||||
should_drop = false;
|
||||
break;
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ impl<'a> System<'a> for Sys {
|
||||
pos.0,
|
||||
*chunk_key,
|
||||
&terrain,
|
||||
presence.view_distance.current(),
|
||||
presence.terrain_view_distance.current(),
|
||||
) {
|
||||
chunk_send_emitter.emit(ChunkSendEntry {
|
||||
entity,
|
||||
|
@ -15,9 +15,12 @@ widget_ids! {
|
||||
struct Ids {
|
||||
window,
|
||||
window_r,
|
||||
vd_text,
|
||||
vd_slider,
|
||||
vd_value,
|
||||
terrain_vd_text,
|
||||
terrain_vd_slider,
|
||||
terrain_vd_value,
|
||||
entity_vd_text,
|
||||
entity_vd_slider,
|
||||
entity_vd_value,
|
||||
player_physics_behavior_text,
|
||||
player_physics_behavior_list,
|
||||
lossy_terrain_compression_button,
|
||||
@ -97,35 +100,84 @@ impl<'a> Widget for Networking<'a> {
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.vd_text, ui);
|
||||
.set(state.ids.terrain_vd_text, ui);
|
||||
|
||||
let terrain_view_distance = self.global_state.settings.graphics.terrain_view_distance;
|
||||
let server_view_distance_limit = self.server_view_distance_limit.unwrap_or(u32::MAX);
|
||||
if let Some(new_val) = ImageSlider::discrete(
|
||||
self.global_state.settings.graphics.view_distance,
|
||||
terrain_view_distance,
|
||||
1,
|
||||
65,
|
||||
self.imgs.slider_indicator,
|
||||
self.imgs.slider,
|
||||
)
|
||||
.w_h(104.0, 22.0)
|
||||
.down_from(state.ids.vd_text, 8.0)
|
||||
.down_from(state.ids.terrain_vd_text, 8.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.soft_max(self.server_view_distance_limit.unwrap_or(u32::MAX))
|
||||
.soft_max(server_view_distance_limit)
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(state.ids.vd_slider, ui)
|
||||
.set(state.ids.terrain_vd_slider, ui)
|
||||
{
|
||||
events.push(NetworkingChange::AdjustViewDistance(new_val));
|
||||
events.push(NetworkingChange::AdjustTerrainViewDistance(new_val));
|
||||
}
|
||||
|
||||
Text::new(&format!(
|
||||
"{}",
|
||||
self.global_state.settings.graphics.view_distance
|
||||
))
|
||||
.right_from(state.ids.vd_slider, 8.0)
|
||||
Text::new(&if terrain_view_distance <= server_view_distance_limit {
|
||||
format!("{terrain_view_distance}")
|
||||
} else {
|
||||
format!("{terrain_view_distance} ({server_view_distance_limit})")
|
||||
})
|
||||
.right_from(state.ids.terrain_vd_slider, 8.0)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.vd_value, ui);
|
||||
.set(state.ids.terrain_vd_value, ui);
|
||||
|
||||
// Entity View Distance
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get_msg("hud-settings-entity_view_distance"),
|
||||
)
|
||||
.down_from(state.ids.terrain_vd_slider, 10.0)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.entity_vd_text, ui);
|
||||
|
||||
let soft_entity_vd_max = self
|
||||
.server_view_distance_limit
|
||||
.unwrap_or(u32::MAX)
|
||||
.min(terrain_view_distance);
|
||||
let entity_view_distance = self.global_state.settings.graphics.entity_view_distance;
|
||||
if let Some(new_val) = ImageSlider::discrete(
|
||||
entity_view_distance,
|
||||
1,
|
||||
65,
|
||||
self.imgs.slider_indicator,
|
||||
self.imgs.slider,
|
||||
)
|
||||
.w_h(104.0, 22.0)
|
||||
.down_from(state.ids.entity_vd_text, 8.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.soft_max(soft_entity_vd_max)
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(state.ids.entity_vd_slider, ui)
|
||||
{
|
||||
events.push(NetworkingChange::AdjustEntityViewDistance(new_val));
|
||||
}
|
||||
|
||||
Text::new(&if entity_view_distance <= soft_entity_vd_max {
|
||||
format!("{entity_view_distance}")
|
||||
} else {
|
||||
format!("{entity_view_distance} ({soft_entity_vd_max})")
|
||||
})
|
||||
.right_from(state.ids.entity_vd_slider, 8.0)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.entity_vd_value, ui);
|
||||
|
||||
// Player physics behavior
|
||||
Text::new(
|
||||
@ -133,7 +185,7 @@ impl<'a> Widget for Networking<'a> {
|
||||
.localized_strings
|
||||
.get_msg("hud-settings-player_physics_behavior"),
|
||||
)
|
||||
.down_from(state.ids.vd_slider, 8.0)
|
||||
.down_from(state.ids.entity_vd_slider, 8.0)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
|
@ -36,9 +36,12 @@ widget_ids! {
|
||||
reset_graphics_button,
|
||||
fps_counter,
|
||||
pipeline_recreation_text,
|
||||
vd_slider,
|
||||
vd_text,
|
||||
vd_value,
|
||||
terrain_vd_slider,
|
||||
terrain_vd_text,
|
||||
terrain_vd_value,
|
||||
entity_vd_slider,
|
||||
entity_vd_text,
|
||||
entity_vd_value,
|
||||
ld_slider,
|
||||
ld_text,
|
||||
ld_value,
|
||||
@ -285,39 +288,126 @@ impl<'a> Widget for Video<'a> {
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.vd_text, ui);
|
||||
.set(state.ids.terrain_vd_text, ui);
|
||||
|
||||
let terrain_view_distance = self.global_state.settings.graphics.terrain_view_distance;
|
||||
let server_view_distance_limit = self.server_view_distance_limit.unwrap_or(u32::MAX);
|
||||
if let Some(new_val) = ImageSlider::discrete(
|
||||
self.global_state.settings.graphics.view_distance,
|
||||
terrain_view_distance,
|
||||
1,
|
||||
65,
|
||||
self.imgs.slider_indicator,
|
||||
self.imgs.slider,
|
||||
)
|
||||
.w_h(104.0, 22.0)
|
||||
.down_from(state.ids.vd_text, 8.0)
|
||||
.down_from(state.ids.terrain_vd_text, 8.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.soft_max(self.server_view_distance_limit.unwrap_or(u32::MAX))
|
||||
.soft_max(server_view_distance_limit)
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(state.ids.vd_slider, ui)
|
||||
.set(state.ids.terrain_vd_slider, ui)
|
||||
{
|
||||
events.push(GraphicsChange::AdjustViewDistance(new_val));
|
||||
events.push(GraphicsChange::AdjustTerrainViewDistance(new_val));
|
||||
}
|
||||
|
||||
Text::new(&format!(
|
||||
"{}",
|
||||
self.global_state.settings.graphics.view_distance
|
||||
))
|
||||
.right_from(state.ids.vd_slider, 8.0)
|
||||
Text::new(&if terrain_view_distance <= server_view_distance_limit {
|
||||
format!("{terrain_view_distance}")
|
||||
} else {
|
||||
format!("{terrain_view_distance} ({server_view_distance_limit})")
|
||||
})
|
||||
.right_from(state.ids.terrain_vd_slider, 8.0)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.vd_value, ui);
|
||||
.set(state.ids.terrain_vd_value, ui);
|
||||
|
||||
// Entity View Distance
|
||||
let soft_entity_vd_max = self
|
||||
.server_view_distance_limit
|
||||
.unwrap_or(u32::MAX)
|
||||
.min(terrain_view_distance);
|
||||
let entity_view_distance = self.global_state.settings.graphics.entity_view_distance;
|
||||
if let Some(new_val) = ImageSlider::discrete(
|
||||
entity_view_distance,
|
||||
1,
|
||||
65,
|
||||
self.imgs.slider_indicator,
|
||||
self.imgs.slider,
|
||||
)
|
||||
.w_h(104.0, 22.0)
|
||||
.right_from(state.ids.terrain_vd_slider, 70.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.soft_max(soft_entity_vd_max)
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(state.ids.entity_vd_slider, ui)
|
||||
{
|
||||
events.push(GraphicsChange::AdjustEntityViewDistance(new_val));
|
||||
}
|
||||
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get_msg("hud-settings-entity_view_distance"),
|
||||
)
|
||||
.up_from(state.ids.entity_vd_slider, 10.0)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.entity_vd_text, ui);
|
||||
|
||||
Text::new(&if entity_view_distance <= soft_entity_vd_max {
|
||||
format!("{entity_view_distance}")
|
||||
} else {
|
||||
format!("{entity_view_distance} ({soft_entity_vd_max})")
|
||||
})
|
||||
.right_from(state.ids.entity_vd_slider, 8.0)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.entity_vd_value, ui);
|
||||
|
||||
// Sprites VD
|
||||
if let Some(new_val) = ImageSlider::discrete(
|
||||
self.global_state.settings.graphics.sprite_render_distance,
|
||||
50,
|
||||
500,
|
||||
self.imgs.slider_indicator,
|
||||
self.imgs.slider,
|
||||
)
|
||||
.w_h(104.0, 22.0)
|
||||
.right_from(state.ids.entity_vd_slider, 70.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(state.ids.sprite_dist_slider, ui)
|
||||
{
|
||||
events.push(GraphicsChange::AdjustSpriteRenderDistance(new_val));
|
||||
}
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get_msg("hud-settings-sprites_view_distance"),
|
||||
)
|
||||
.up_from(state.ids.sprite_dist_slider, 10.0)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.sprite_dist_text, ui);
|
||||
|
||||
Text::new(&format!(
|
||||
"{}",
|
||||
self.global_state.settings.graphics.sprite_render_distance
|
||||
))
|
||||
.right_from(state.ids.sprite_dist_slider, 8.0)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.sprite_dist_value, ui);
|
||||
|
||||
// LoD Distance
|
||||
Text::new(&self.localized_strings.get_msg("hud-settings-lod_distance"))
|
||||
.down_from(state.ids.vd_slider, 10.0)
|
||||
.down_from(state.ids.terrain_vd_slider, 10.0)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
@ -350,6 +440,50 @@ impl<'a> Widget for Video<'a> {
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.ld_value, ui);
|
||||
|
||||
// Figure LOD distance
|
||||
if let Some(new_val) = ImageSlider::discrete(
|
||||
self.global_state
|
||||
.settings
|
||||
.graphics
|
||||
.figure_lod_render_distance,
|
||||
50,
|
||||
500,
|
||||
self.imgs.slider_indicator,
|
||||
self.imgs.slider,
|
||||
)
|
||||
.w_h(104.0, 22.0)
|
||||
.right_from(state.ids.ld_slider, 70.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(state.ids.figure_dist_slider, ui)
|
||||
{
|
||||
events.push(GraphicsChange::AdjustFigureLoDRenderDistance(new_val));
|
||||
}
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get_msg("hud-settings-entities_detail_distance"),
|
||||
)
|
||||
.up_from(state.ids.figure_dist_slider, 8.0)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.figure_dist_text, ui);
|
||||
|
||||
Text::new(&format!(
|
||||
"{}",
|
||||
self.global_state
|
||||
.settings
|
||||
.graphics
|
||||
.figure_lod_render_distance
|
||||
))
|
||||
.right_from(state.ids.figure_dist_slider, 8.0)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.figure_dist_value, ui);
|
||||
|
||||
// Max FPS
|
||||
Text::new(&self.localized_strings.get_msg("hud-settings-maximum_fps"))
|
||||
.down_from(state.ids.ld_slider, 10.0)
|
||||
@ -392,7 +526,7 @@ impl<'a> Widget for Video<'a> {
|
||||
.get_msg("hud-settings-background_fps"),
|
||||
)
|
||||
.down_from(state.ids.ld_slider, 10.0)
|
||||
.right_from(state.ids.max_fps_value, 30.0)
|
||||
.right_from(state.ids.max_fps_value, 44.0)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
@ -655,87 +789,6 @@ impl<'a> Widget for Video<'a> {
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.ambiance_value, ui);
|
||||
|
||||
// Sprites VD
|
||||
if let Some(new_val) = ImageSlider::discrete(
|
||||
self.global_state.settings.graphics.sprite_render_distance,
|
||||
50,
|
||||
500,
|
||||
self.imgs.slider_indicator,
|
||||
self.imgs.slider,
|
||||
)
|
||||
.w_h(104.0, 22.0)
|
||||
.right_from(state.ids.vd_slider, 50.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(state.ids.sprite_dist_slider, ui)
|
||||
{
|
||||
events.push(GraphicsChange::AdjustSpriteRenderDistance(new_val));
|
||||
}
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get_msg("hud-settings-sprites_view_distance"),
|
||||
)
|
||||
.up_from(state.ids.sprite_dist_slider, 8.0)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.sprite_dist_text, ui);
|
||||
|
||||
Text::new(&format!(
|
||||
"{}",
|
||||
self.global_state.settings.graphics.sprite_render_distance
|
||||
))
|
||||
.right_from(state.ids.sprite_dist_slider, 8.0)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.sprite_dist_value, ui);
|
||||
// Figure VD
|
||||
if let Some(new_val) = ImageSlider::discrete(
|
||||
self.global_state
|
||||
.settings
|
||||
.graphics
|
||||
.figure_lod_render_distance,
|
||||
50,
|
||||
500,
|
||||
self.imgs.slider_indicator,
|
||||
self.imgs.slider,
|
||||
)
|
||||
.w_h(104.0, 22.0)
|
||||
.right_from(state.ids.sprite_dist_slider, 50.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(state.ids.figure_dist_slider, ui)
|
||||
{
|
||||
events.push(GraphicsChange::AdjustFigureLoDRenderDistance(new_val));
|
||||
}
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get_msg("hud-settings-figures_view_distance"),
|
||||
)
|
||||
.up_from(state.ids.figure_dist_slider, 8.0)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.figure_dist_text, ui);
|
||||
|
||||
Text::new(&format!(
|
||||
"{}",
|
||||
self.global_state
|
||||
.settings
|
||||
.graphics
|
||||
.figure_lod_render_distance
|
||||
))
|
||||
.right_from(state.ids.figure_dist_slider, 8.0)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.figure_dist_value, ui);
|
||||
|
||||
// AaMode
|
||||
Text::new(
|
||||
&self
|
||||
|
@ -137,10 +137,11 @@ impl PlayState for CharSelectionState {
|
||||
ui::Event::Play(character_id) => {
|
||||
{
|
||||
let mut c = self.client.borrow_mut();
|
||||
c.request_character(character_id);
|
||||
//Send our ViewDistance and LoD distance
|
||||
c.set_view_distance(global_state.settings.graphics.view_distance);
|
||||
c.set_lod_distance(global_state.settings.graphics.lod_distance);
|
||||
let graphics = &global_state.settings.graphics;
|
||||
c.request_character(character_id, common::ViewDistances {
|
||||
terrain: graphics.terrain_view_distance,
|
||||
entity: graphics.entity_view_distance,
|
||||
});
|
||||
}
|
||||
return PlayStateResult::Switch(Box::new(SessionState::new(
|
||||
global_state,
|
||||
@ -150,9 +151,11 @@ impl PlayState for CharSelectionState {
|
||||
ui::Event::Spectate => {
|
||||
{
|
||||
let mut c = self.client.borrow_mut();
|
||||
c.request_spectate();
|
||||
c.set_view_distance(global_state.settings.graphics.view_distance);
|
||||
c.set_lod_distance(global_state.settings.graphics.lod_distance);
|
||||
let graphics = &global_state.settings.graphics;
|
||||
c.request_spectate(common::ViewDistances {
|
||||
terrain: graphics.terrain_view_distance,
|
||||
entity: graphics.entity_view_distance,
|
||||
});
|
||||
}
|
||||
return PlayStateResult::Switch(Box::new(SessionState::new(
|
||||
global_state,
|
||||
|
@ -629,7 +629,7 @@ impl FigureMgr {
|
||||
let time = state.get_time() as f32;
|
||||
let tick = scene_data.tick;
|
||||
let ecs = state.ecs();
|
||||
let view_distance = scene_data.view_distance;
|
||||
let view_distance = scene_data.entity_view_distance;
|
||||
let dt = state.get_delta_time();
|
||||
let dt_lerp = (15.0 * dt).min(1.0);
|
||||
let frustum = camera.frustum();
|
||||
|
@ -120,7 +120,8 @@ pub struct SceneData<'a> {
|
||||
pub mutable_viewpoint: bool,
|
||||
pub target_entity: Option<specs::Entity>,
|
||||
pub loaded_distance: f32,
|
||||
pub view_distance: u32,
|
||||
pub terrain_view_distance: u32, // not used currently
|
||||
pub entity_view_distance: u32,
|
||||
pub tick: u64,
|
||||
pub gamma: f32,
|
||||
pub exposure: f32,
|
||||
|
@ -1697,7 +1697,11 @@ impl PlayState for SessionState {
|
||||
// Only highlight if interactable
|
||||
target_entity: self.interactable.and_then(Interactable::entity),
|
||||
loaded_distance: client.loaded_distance(),
|
||||
view_distance: client.view_distance().unwrap_or(1),
|
||||
terrain_view_distance: client.view_distance().unwrap_or(1),
|
||||
entity_view_distance: client
|
||||
.view_distance()
|
||||
.unwrap_or(1)
|
||||
.min(global_state.settings.graphics.entity_view_distance),
|
||||
tick: client.get_tick(),
|
||||
gamma: global_state.settings.graphics.gamma,
|
||||
exposure: global_state.settings.graphics.exposure,
|
||||
@ -1783,7 +1787,11 @@ impl PlayState for SessionState {
|
||||
// Only highlight if interactable
|
||||
target_entity: self.interactable.and_then(Interactable::entity),
|
||||
loaded_distance: client.loaded_distance(),
|
||||
view_distance: client.view_distance().unwrap_or(1),
|
||||
terrain_view_distance: client.view_distance().unwrap_or(1),
|
||||
entity_view_distance: client
|
||||
.view_distance()
|
||||
.unwrap_or(1)
|
||||
.min(settings.graphics.entity_view_distance),
|
||||
tick: client.get_tick(),
|
||||
gamma: settings.graphics.gamma,
|
||||
exposure: settings.graphics.exposure,
|
||||
|
@ -70,7 +70,8 @@ pub enum Gameplay {
|
||||
}
|
||||
#[derive(Clone)]
|
||||
pub enum Graphics {
|
||||
AdjustViewDistance(u32),
|
||||
AdjustTerrainViewDistance(u32),
|
||||
AdjustEntityViewDistance(u32),
|
||||
AdjustLodDistance(u32),
|
||||
AdjustLodDetail(u32),
|
||||
AdjustSpriteRenderDistance(u32),
|
||||
@ -147,7 +148,8 @@ pub enum Language {
|
||||
}
|
||||
#[derive(Clone)]
|
||||
pub enum Networking {
|
||||
AdjustViewDistance(u32),
|
||||
AdjustTerrainViewDistance(u32),
|
||||
AdjustEntityViewDistance(u32),
|
||||
ChangePlayerPhysicsBehavior {
|
||||
server_authoritative: bool,
|
||||
},
|
||||
@ -155,6 +157,8 @@ pub enum Networking {
|
||||
|
||||
#[cfg(feature = "discord")]
|
||||
ToggleDiscordIntegration(bool),
|
||||
// TODO: reset option (ensure it handles the entity/terrain vd the same as graphics reset
|
||||
// option)
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -354,8 +358,11 @@ impl SettingsChange {
|
||||
},
|
||||
SettingsChange::Graphics(graphics_change) => {
|
||||
match graphics_change {
|
||||
Graphics::AdjustViewDistance(view_distance) => {
|
||||
adjust_view_distance(view_distance, global_state, session_state)
|
||||
Graphics::AdjustTerrainViewDistance(terrain_vd) => {
|
||||
adjust_terrain_view_distance(terrain_vd, settings, session_state)
|
||||
},
|
||||
Graphics::AdjustEntityViewDistance(entity_vd) => {
|
||||
adjust_entity_view_distance(entity_vd, settings, session_state)
|
||||
},
|
||||
Graphics::AdjustLodDistance(lod_distance) => {
|
||||
session_state
|
||||
@ -428,10 +435,7 @@ impl SettingsChange {
|
||||
settings.graphics = GraphicsSettings::default();
|
||||
let graphics = &settings.graphics;
|
||||
// View distance
|
||||
session_state
|
||||
.client
|
||||
.borrow_mut()
|
||||
.set_view_distance(graphics.view_distance);
|
||||
client_set_view_distance(settings, session_state);
|
||||
// FOV
|
||||
session_state.scene.camera_mut().set_fov_deg(graphics.fov);
|
||||
session_state
|
||||
@ -599,8 +603,11 @@ impl SettingsChange {
|
||||
},
|
||||
},
|
||||
SettingsChange::Networking(networking_change) => match networking_change {
|
||||
Networking::AdjustViewDistance(view_distance) => {
|
||||
adjust_view_distance(view_distance, global_state, session_state)
|
||||
Networking::AdjustTerrainViewDistance(terrain_vd) => {
|
||||
adjust_terrain_view_distance(terrain_vd, settings, session_state)
|
||||
},
|
||||
Networking::AdjustEntityViewDistance(entity_vd) => {
|
||||
adjust_entity_view_distance(entity_vd, settings, session_state)
|
||||
},
|
||||
Networking::ChangePlayerPhysicsBehavior {
|
||||
server_authoritative,
|
||||
@ -651,15 +658,33 @@ impl SettingsChange {
|
||||
}
|
||||
}
|
||||
|
||||
fn adjust_view_distance(
|
||||
view_distance: u32,
|
||||
global_state: &mut GlobalState,
|
||||
use crate::settings::Settings;
|
||||
|
||||
fn adjust_terrain_view_distance(
|
||||
terrain_vd: u32,
|
||||
settings: &mut Settings,
|
||||
session_state: &mut SessionState,
|
||||
) {
|
||||
settings.graphics.terrain_view_distance = terrain_vd;
|
||||
client_set_view_distance(settings, session_state);
|
||||
}
|
||||
|
||||
fn adjust_entity_view_distance(
|
||||
entity_vd: u32,
|
||||
settings: &mut Settings,
|
||||
session_state: &mut SessionState,
|
||||
) {
|
||||
settings.graphics.entity_view_distance = entity_vd;
|
||||
client_set_view_distance(settings, session_state);
|
||||
}
|
||||
|
||||
fn client_set_view_distance(settings: &Settings, session_state: &mut SessionState) {
|
||||
let view_distances = common::ViewDistances {
|
||||
terrain: settings.graphics.terrain_view_distance,
|
||||
entity: settings.graphics.entity_view_distance,
|
||||
};
|
||||
session_state
|
||||
.client
|
||||
.borrow_mut()
|
||||
.set_view_distance(view_distance);
|
||||
|
||||
global_state.settings.graphics.view_distance = view_distance;
|
||||
.set_view_distances(view_distances);
|
||||
}
|
||||
|
@ -29,7 +29,8 @@ impl fmt::Display for Fps {
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct GraphicsSettings {
|
||||
pub view_distance: u32,
|
||||
pub terrain_view_distance: u32,
|
||||
pub entity_view_distance: u32,
|
||||
pub lod_distance: u32,
|
||||
pub sprite_render_distance: u32,
|
||||
pub particles_enabled: bool,
|
||||
@ -50,7 +51,8 @@ pub struct GraphicsSettings {
|
||||
impl Default for GraphicsSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
view_distance: 10,
|
||||
terrain_view_distance: 10,
|
||||
entity_view_distance: 65,
|
||||
lod_distance: 200,
|
||||
sprite_render_distance: 100,
|
||||
particles_enabled: true,
|
||||
|
Loading…
Reference in New Issue
Block a user