use super::SessionState; use crate::{ controller::ControllerSettings, game_input::GameInput, hud::{ AutoPressBehavior, BarNumbers, BuffPosition, ChatTab, CrosshairType, Intro, PressBehavior, ScaleChange, ShortcutNumbers, XpBar, }, render::RenderMode, settings::{ audio::AudioVolume, AudioSettings, ChatSettings, ControlSettings, Fps, GamepadSettings, GameplaySettings, GraphicsSettings, InterfaceSettings, }, window::{FullScreenSettings, Window}, GlobalState, }; use i18n::{LanguageMetadata, LocalizationHandle}; use std::rc::Rc; #[derive(Clone)] pub enum Audio { AdjustMasterVolume(f32), MuteMasterVolume(bool), AdjustInactiveMasterVolume(f32), MuteInactiveMasterVolume(bool), AdjustMusicVolume(f32), MuteMusicVolume(bool), AdjustSfxVolume(f32), MuteSfxVolume(bool), AdjustAmbienceVolume(f32), MuteAmbienceVolume(bool), AdjustMusicSpacing(f32), //ChangeAudioDevice(String), ResetAudioSettings, } #[derive(Clone)] pub enum Chat { Transp(f32), CharName(bool), ChangeChatTab(Option), ChatTabUpdate(usize, ChatTab), ChatTabInsert(usize, ChatTab), ChatTabMove(usize, usize), //(i, j) move item from position i, and insert into position j ChatTabRemove(usize), ResetChatSettings, } #[derive(Clone)] pub enum Control { ChangeBinding(GameInput), RemoveBinding(GameInput), ToggleKeybindingMode, ResetKeyBindings, } #[derive(Clone)] pub enum Gamepad {} #[derive(Clone)] pub enum Gameplay { AdjustMousePan(u32), AdjustMouseZoom(u32), AdjustCameraClamp(u32), ToggleControllerYInvert(bool), ToggleMouseYInvert(bool), ToggleZoomInvert(bool), ToggleSmoothPan(bool), ChangeFreeLookBehavior(PressBehavior), ChangeAutoWalkBehavior(PressBehavior), ChangeCameraClampBehavior(PressBehavior), ChangeZoomLockBehavior(AutoPressBehavior), ChangeStopAutoWalkOnInput(bool), ChangeAutoCamera(bool), ChangeBowZoom(bool), ChangeZoomLock(bool), ResetGameplaySettings, } #[derive(Clone)] pub enum Graphics { AdjustTerrainViewDistance(u32), AdjustEntityViewDistance(u32), AdjustLodDistance(u32), AdjustLodDetail(u32), AdjustSpriteRenderDistance(u32), AdjustFigureLoDRenderDistance(u32), ChangeMaxFPS(Fps), ChangeMaxBackgroundFPS(Fps), ChangeFOV(u16), ChangeGamma(f32), ChangeExposure(f32), ChangeAmbiance(f32), ChangeRenderMode(Box), ChangeFullscreenMode(FullScreenSettings), ToggleParticlesEnabled(bool), ToggleWeaponTrailsEnabled(bool), AdjustWindowSize([u16; 2]), ResetGraphicsSettings, ChangeGraphicsSettings(Rc GraphicsSettings>), } #[derive(Clone)] pub enum Interface { Sct(bool), SctRoundDamage(bool), SctDamageAccumDuration(f32), SctIncomingDamage(bool), SctIncomingDamageAccumDuration(f32), SpeechBubbleSelf(bool), SpeechBubbleDarkMode(bool), SpeechBubbleIcon(bool), ToggleHelp(bool), ToggleDebug(bool), ToggleHitboxes(bool), ToggleChat(bool), ToggleTips(bool), ToggleHotkeyHints(bool), CrosshairTransp(f32), CrosshairType(CrosshairType), Intro(Intro), ToggleXpBar(XpBar), ToggleBarNumbers(BarNumbers), ToggleAlwaysShowBars(bool), TogglePoiseBar(bool), ToggleShortcutNumbers(ShortcutNumbers), BuffPosition(BuffPosition), UiScale(ScaleChange), //Minimap MinimapShow(bool), MinimapFaceNorth(bool), MinimapZoom(f64), //Map settings MapZoom(f64), MapShowTopoMap(bool), MapShowDifficulty(bool), MapShowTowns(bool), MapShowDungeons(bool), MapShowCastles(bool), MapShowBridges(bool), MapShowCaves(bool), MapShowTrees(bool), MapShowPeaks(bool), MapShowBiomes(bool), MapShowVoxelMap(bool), AccumExperience(bool), ResetInterfaceSettings, } #[derive(Clone)] pub enum Language { ChangeLanguage(Box), ToggleEnglishFallback(bool), } #[derive(Clone)] pub enum Networking { AdjustTerrainViewDistance(u32), AdjustEntityViewDistance(u32), ChangePlayerPhysicsBehavior { server_authoritative: bool, }, ToggleLossyTerrainCompression(bool), #[cfg(feature = "discord")] ToggleDiscordIntegration(bool), // TODO: reset option (ensure it handles the entity/terrain vd the same as graphics reset // option) } #[derive(Clone)] pub enum Accessibility { ChangeRenderMode(Box), SetSubtitles(bool), } #[derive(Clone)] pub enum SettingsChange { Audio(Audio), Chat(Chat), Control(Control), Gamepad(Gamepad), Gameplay(Gameplay), Graphics(Graphics), Interface(Interface), Language(Language), Networking(Networking), Accessibility(Accessibility), } macro_rules! settings_change_from { ($i: ident) => { impl From<$i> for SettingsChange { fn from(change: $i) -> Self { SettingsChange::$i(change) } } }; } settings_change_from!(Audio); settings_change_from!(Chat); settings_change_from!(Control); settings_change_from!(Gamepad); settings_change_from!(Gameplay); settings_change_from!(Graphics); settings_change_from!(Interface); settings_change_from!(Language); settings_change_from!(Networking); settings_change_from!(Accessibility); impl SettingsChange { pub fn process(self, global_state: &mut GlobalState, session_state: &mut SessionState) { let mut settings = &mut global_state.settings; match self { SettingsChange::Audio(audio_change) => { fn update_volume(audio: &mut AudioVolume, volume: f32) -> f32 { audio.volume = volume; audio.get_checked() } fn update_muted(audio: &mut AudioVolume, muted: bool) -> f32 { audio.muted = muted; audio.get_checked() } match audio_change { Audio::AdjustMasterVolume(master_volume) => { let volume_checked = update_volume(&mut settings.audio.master_volume, master_volume); global_state.audio.set_master_volume(volume_checked); }, Audio::MuteMasterVolume(master_muted) => { let volume_checked = update_muted(&mut settings.audio.master_volume, master_muted); global_state.audio.set_master_volume(volume_checked); }, Audio::AdjustInactiveMasterVolume(inactive_master_volume_perc) => { settings.audio.inactive_master_volume_perc.volume = inactive_master_volume_perc; }, Audio::MuteInactiveMasterVolume(inactive_master_volume_muted) => { settings.audio.inactive_master_volume_perc.muted = inactive_master_volume_muted; }, Audio::AdjustMusicVolume(music_volume) => { let volume_checked = update_volume(&mut settings.audio.music_volume, music_volume); global_state.audio.set_music_volume(volume_checked); }, Audio::MuteMusicVolume(music_muted) => { let volume_checked = update_muted(&mut settings.audio.music_volume, music_muted); global_state.audio.set_music_volume(volume_checked); }, Audio::AdjustSfxVolume(sfx_volume) => { let volume_checked = update_volume(&mut settings.audio.sfx_volume, sfx_volume); global_state.audio.set_sfx_volume(volume_checked); }, Audio::MuteSfxVolume(sfx_muted) => { let volume_checked = update_muted(&mut settings.audio.sfx_volume, sfx_muted); global_state.audio.set_sfx_volume(volume_checked); }, Audio::AdjustAmbienceVolume(ambience_volume) => { global_state.audio.set_ambience_volume(ambience_volume); settings.audio.ambience_volume.volume = ambience_volume; }, Audio::MuteAmbienceVolume(ambience_muted) => { let volume_checked = update_muted(&mut settings.audio.ambience_volume, ambience_muted); global_state.audio.set_ambience_volume(volume_checked); }, Audio::AdjustMusicSpacing(multiplier) => { global_state.audio.set_music_spacing(multiplier); settings.audio.music_spacing = multiplier; }, //Audio::ChangeAudioDevice(name) => { // global_state.audio.set_device(name.clone()); // settings.audio.output = AudioOutput::Device(name); //}, Audio::ResetAudioSettings => { settings.audio = AudioSettings::default(); let audio = &mut global_state.audio; // TODO: check if updating the master volume is necessary // (it wasn't done before) audio.set_master_volume(settings.audio.master_volume.get_checked()); audio.set_music_volume(settings.audio.music_volume.get_checked()); audio.set_sfx_volume(settings.audio.sfx_volume.get_checked()); }, } }, SettingsChange::Chat(chat_change) => { let chat_tabs = &mut settings.chat.chat_tabs; match chat_change { Chat::Transp(chat_opacity) => { settings.chat.chat_opacity = chat_opacity; }, Chat::CharName(chat_char_name) => { settings.chat.chat_character_name = chat_char_name; }, Chat::ChangeChatTab(chat_tab_index) => { settings.chat.chat_tab_index = chat_tab_index.filter(|i| *i < chat_tabs.len()); }, Chat::ChatTabUpdate(i, chat_tab) => { if i < chat_tabs.len() { chat_tabs[i] = chat_tab; } }, Chat::ChatTabInsert(i, chat_tab) => { if i <= chat_tabs.len() { settings.chat.chat_tabs.insert(i, chat_tab); } }, Chat::ChatTabMove(i, j) => { if i < chat_tabs.len() && j < chat_tabs.len() { let chat_tab = settings.chat.chat_tabs.remove(i); settings.chat.chat_tabs.insert(j, chat_tab); } }, Chat::ChatTabRemove(i) => { if i < chat_tabs.len() { settings.chat.chat_tabs.remove(i); } }, Chat::ResetChatSettings => { settings.chat = ChatSettings::default(); }, } }, SettingsChange::Control(control_change) => match control_change { Control::ChangeBinding(game_input) => { global_state.window.set_keybinding_mode(game_input); }, Control::RemoveBinding(game_input) => { settings.controls.remove_binding(game_input); }, Control::ToggleKeybindingMode => { global_state.window.toggle_keybinding_mode(); }, Control::ResetKeyBindings => { settings.controls = ControlSettings::default(); }, }, SettingsChange::Gamepad(gamepad_change) => match gamepad_change {}, SettingsChange::Gameplay(gameplay_change) => { let mut window = &mut global_state.window; match gameplay_change { Gameplay::AdjustMousePan(sensitivity) => { window.pan_sensitivity = sensitivity; settings.gameplay.pan_sensitivity = sensitivity; }, Gameplay::AdjustMouseZoom(sensitivity) => { window.zoom_sensitivity = sensitivity; settings.gameplay.zoom_sensitivity = sensitivity; }, Gameplay::AdjustCameraClamp(angle) => { settings.gameplay.camera_clamp_angle = angle; }, Gameplay::ToggleControllerYInvert(controller_y_inverted) => { window.controller_settings.pan_invert_y = controller_y_inverted; settings.controller.pan_invert_y = controller_y_inverted; }, Gameplay::ToggleMouseYInvert(mouse_y_inverted) => { window.mouse_y_inversion = mouse_y_inverted; settings.gameplay.mouse_y_inversion = mouse_y_inverted; }, Gameplay::ToggleZoomInvert(zoom_inverted) => { window.zoom_inversion = zoom_inverted; settings.gameplay.zoom_inversion = zoom_inverted; }, Gameplay::ToggleSmoothPan(smooth_pan_enabled) => { settings.gameplay.smooth_pan_enable = smooth_pan_enabled; }, Gameplay::ChangeFreeLookBehavior(behavior) => { settings.gameplay.free_look_behavior = behavior; }, Gameplay::ChangeAutoWalkBehavior(behavior) => { settings.gameplay.auto_walk_behavior = behavior; }, Gameplay::ChangeCameraClampBehavior(behavior) => { settings.gameplay.camera_clamp_behavior = behavior; }, Gameplay::ChangeZoomLockBehavior(state) => { settings.gameplay.zoom_lock_behavior = state; }, Gameplay::ChangeStopAutoWalkOnInput(state) => { settings.gameplay.stop_auto_walk_on_input = state; }, Gameplay::ChangeAutoCamera(state) => { settings.gameplay.auto_camera = state; }, Gameplay::ChangeBowZoom(state) => { settings.gameplay.bow_zoom = state; }, Gameplay::ChangeZoomLock(state) => { settings.gameplay.zoom_lock = state; }, Gameplay::ResetGameplaySettings => { // Reset Gameplay Settings settings.gameplay = GameplaySettings::default(); // Reset Gamepad and Controller Settings settings.controller = GamepadSettings::default(); window.controller_settings = ControllerSettings::from(&settings.controller); // Pan Sensitivity window.pan_sensitivity = settings.gameplay.pan_sensitivity; // Zoom Sensitivity window.zoom_sensitivity = settings.gameplay.zoom_sensitivity; // Invert Scroll Zoom window.zoom_inversion = settings.gameplay.zoom_inversion; // Invert Mouse Y Axis window.mouse_y_inversion = settings.gameplay.mouse_y_inversion; }, } }, SettingsChange::Graphics(graphics_change) => { let mut change_preset = false; match graphics_change { 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 .client .borrow_mut() .set_lod_distance(lod_distance); settings.graphics.lod_distance = lod_distance; }, Graphics::AdjustLodDetail(lod_detail) => { session_state.scene.lod.set_detail(lod_detail); settings.graphics.lod_detail = lod_detail; }, Graphics::AdjustSpriteRenderDistance(sprite_render_distance) => { settings.graphics.sprite_render_distance = sprite_render_distance; }, Graphics::AdjustFigureLoDRenderDistance(figure_lod_render_distance) => { settings.graphics.figure_lod_render_distance = figure_lod_render_distance; }, Graphics::ChangeMaxFPS(fps) => { settings.graphics.max_fps = fps; }, Graphics::ChangeMaxBackgroundFPS(fps) => { settings.graphics.max_background_fps = fps; }, Graphics::ChangeFOV(new_fov) => { settings.graphics.fov = new_fov; session_state.scene.camera_mut().set_fov_deg(new_fov); session_state .scene .camera_mut() .compute_dependents(&session_state.client.borrow().state().terrain()); }, Graphics::ChangeGamma(new_gamma) => { settings.graphics.gamma = new_gamma; }, Graphics::ChangeExposure(new_exposure) => { settings.graphics.exposure = new_exposure; }, Graphics::ChangeAmbiance(new_ambiance) => { settings.graphics.ambiance = new_ambiance; }, Graphics::ChangeRenderMode(new_render_mode) => { change_render_mode(*new_render_mode, &mut global_state.window, settings); }, Graphics::ChangeFullscreenMode(new_fullscreen_settings) => { global_state .window .set_fullscreen_mode(new_fullscreen_settings); settings.graphics.fullscreen = new_fullscreen_settings; }, Graphics::ToggleParticlesEnabled(particles_enabled) => { settings.graphics.particles_enabled = particles_enabled; }, Graphics::ToggleWeaponTrailsEnabled(weapon_trails_enabled) => { settings.graphics.weapon_trails_enabled = weapon_trails_enabled; }, Graphics::AdjustWindowSize(new_size) => { global_state.window.set_size(new_size.into()); settings.graphics.window_size = new_size; }, Graphics::ResetGraphicsSettings => { settings.graphics = GraphicsSettings::default(); change_preset = true; // Fullscreen mode global_state .window .set_fullscreen_mode(settings.graphics.fullscreen); // Window size global_state .window .set_size(settings.graphics.window_size.into()); }, Graphics::ChangeGraphicsSettings(f) => { settings.graphics = f(settings.graphics.clone()); change_preset = true; }, } if change_preset { let graphics = &settings.graphics; // View distance client_set_view_distance(settings, session_state); // FOV session_state.scene.camera_mut().set_fov_deg(graphics.fov); session_state .scene .camera_mut() .compute_dependents(&session_state.client.borrow().state().terrain()); // LoD session_state.scene.lod.set_detail(graphics.lod_detail); // LoD distance session_state .client .borrow_mut() .set_lod_distance(graphics.lod_distance); // Render mode global_state .window .renderer_mut() .set_render_mode(graphics.render_mode.clone()) .unwrap(); } }, SettingsChange::Interface(interface_change) => { match interface_change { Interface::Sct(sct) => { settings.interface.sct = sct; }, Interface::SctRoundDamage(sct_round_damage) => { settings.interface.sct_damage_rounding = sct_round_damage; }, Interface::SctDamageAccumDuration(sct_dmg_accum_duration) => { settings.interface.sct_dmg_accum_duration = sct_dmg_accum_duration; }, Interface::SctIncomingDamage(sct_inc_dmg) => { settings.interface.sct_inc_dmg = sct_inc_dmg; }, Interface::SctIncomingDamageAccumDuration(sct_inc_dmg_accum_duration) => { settings.interface.sct_inc_dmg_accum_duration = sct_inc_dmg_accum_duration; }, Interface::SpeechBubbleSelf(sbdm) => { settings.interface.speech_bubble_self = sbdm; }, Interface::SpeechBubbleDarkMode(sbdm) => { settings.interface.speech_bubble_dark_mode = sbdm; }, Interface::SpeechBubbleIcon(sbi) => { settings.interface.speech_bubble_icon = sbi; }, Interface::ToggleHelp(_) => { // implemented in hud }, Interface::ToggleDebug(toggle_debug) => { settings.interface.toggle_debug = toggle_debug; }, Interface::ToggleHitboxes(toggle_hitboxes) => { settings.interface.toggle_hitboxes = toggle_hitboxes; }, Interface::ToggleChat(toggle_chat) => { settings.interface.toggle_chat = toggle_chat; }, Interface::ToggleTips(loading_tips) => { settings.interface.loading_tips = loading_tips; }, Interface::ToggleHotkeyHints(toggle_hotkey_hints) => { settings.interface.toggle_hotkey_hints = toggle_hotkey_hints; }, Interface::CrosshairTransp(crosshair_opacity) => { settings.interface.crosshair_opacity = crosshair_opacity; }, Interface::CrosshairType(crosshair_type) => { settings.interface.crosshair_type = crosshair_type; }, Interface::Intro(intro_show) => { settings.interface.intro_show = intro_show; }, Interface::ToggleXpBar(xp_bar) => { settings.interface.xp_bar = xp_bar; }, Interface::ToggleBarNumbers(bar_numbers) => { settings.interface.bar_numbers = bar_numbers; }, Interface::ToggleAlwaysShowBars(always_show_bars) => { settings.interface.always_show_bars = always_show_bars; }, Interface::TogglePoiseBar(enable_poise_bar) => { settings.interface.enable_poise_bar = enable_poise_bar; }, Interface::ToggleShortcutNumbers(shortcut_numbers) => { settings.interface.shortcut_numbers = shortcut_numbers; }, Interface::BuffPosition(buff_position) => { settings.interface.buff_position = buff_position; }, Interface::UiScale(scale_change) => { settings.interface.ui_scale = session_state.hud.scale_change(scale_change); }, Interface::MinimapShow(state) => { settings.interface.minimap_show = state; }, Interface::MinimapFaceNorth(state) => { settings.interface.minimap_face_north = state; }, Interface::MinimapZoom(minimap_zoom) => { settings.interface.minimap_zoom = minimap_zoom; }, Interface::MapZoom(map_zoom) => { settings.interface.map_zoom = map_zoom; }, Interface::MapShowTopoMap(map_show_topo_map) => { settings.interface.map_show_topo_map = map_show_topo_map; }, Interface::MapShowDifficulty(map_show_difficulty) => { settings.interface.map_show_difficulty = map_show_difficulty; }, Interface::MapShowTowns(map_show_towns) => { settings.interface.map_show_towns = map_show_towns; }, Interface::MapShowDungeons(map_show_dungeons) => { settings.interface.map_show_dungeons = map_show_dungeons; }, Interface::MapShowCastles(map_show_castles) => { settings.interface.map_show_castles = map_show_castles; }, Interface::MapShowBridges(map_show_bridges) => { settings.interface.map_show_bridges = map_show_bridges; }, Interface::MapShowCaves(map_show_caves) => { settings.interface.map_show_caves = map_show_caves; }, Interface::MapShowTrees(map_show_trees) => { settings.interface.map_show_trees = map_show_trees; }, Interface::MapShowPeaks(map_show_peaks) => { settings.interface.map_show_peaks = map_show_peaks; }, Interface::MapShowBiomes(map_show_biomes) => { settings.interface.map_show_biomes = map_show_biomes; }, Interface::MapShowVoxelMap(map_show_voxel_map) => { settings.interface.map_show_voxel_map = map_show_voxel_map; }, Interface::AccumExperience(accum_experience) => { settings.interface.accum_experience = accum_experience; }, Interface::ResetInterfaceSettings => { // Reset Interface Settings let tmp = settings.interface.intro_show; settings.interface = InterfaceSettings::default(); settings.interface.intro_show = tmp; // Update Current Scaling Mode session_state .hud .set_scaling_mode(settings.interface.ui_scale); }, } }, SettingsChange::Language(language_change) => match language_change { Language::ChangeLanguage(new_language) => { settings.language.selected_language = new_language.language_identifier; global_state.i18n = LocalizationHandle::load_expect(&settings.language.selected_language); global_state .i18n .set_english_fallback(settings.language.use_english_fallback); session_state.hud.update_fonts(&global_state.i18n.read()); }, Language::ToggleEnglishFallback(toggle_fallback) => { settings.language.use_english_fallback = toggle_fallback; global_state .i18n .set_english_fallback(settings.language.use_english_fallback); }, }, SettingsChange::Networking(networking_change) => match networking_change { 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, } => { settings.networking.player_physics_behavior = server_authoritative; session_state .client .borrow_mut() .request_player_physics(server_authoritative); }, Networking::ToggleLossyTerrainCompression(lossy_terrain_compression) => { settings.networking.lossy_terrain_compression = lossy_terrain_compression; session_state .client .borrow_mut() .request_lossy_terrain_compression(lossy_terrain_compression); }, #[cfg(feature = "discord")] Networking::ToggleDiscordIntegration(enabled) => { use crate::discord::Discord; settings.networking.enable_discord_integration = enabled; if enabled { global_state.discord = Discord::start(&global_state.tokio_runtime); #[cfg(feature = "singleplayer")] let singleplayer = global_state.singleplayer.is_some(); #[cfg(not(feature = "singleplayer"))] let singleplayer = false; if singleplayer { global_state.discord.join_singleplayer(); } else { global_state.discord.join_server( session_state.client.borrow().server_info().name.clone(), ); } } else { global_state.discord.clear_activity(); global_state.discord = Discord::Inactive; } }, }, SettingsChange::Accessibility(accessibility_change) => match accessibility_change { Accessibility::ChangeRenderMode(new_render_mode) => { change_render_mode(*new_render_mode, &mut global_state.window, settings); }, Accessibility::SetSubtitles(enabled) => { global_state.settings.audio.subtitles = enabled; global_state.audio.set_subtitles(enabled); }, }, } global_state .settings .save_to_file_warn(&global_state.config_dir); } } use crate::settings::Settings; pub fn change_render_mode( new_render_mode: RenderMode, window: &mut Window, settings: &mut Settings, ) { // Do this first so if it crashes the setting isn't saved :) window .renderer_mut() .set_render_mode(new_render_mode.clone()) .unwrap(); settings.graphics.render_mode = new_render_mode; } 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_distances(view_distances); }