veloren_voxygen/session/
settings_change.rs

1use super::SessionState;
2use crate::{
3    GlobalState,
4    controller::ControllerSettings,
5    game_input::GameInput,
6    hud::{
7        AutoPressBehavior, BarNumbers, BuffPosition, ChatTab, CrosshairType, Intro, PressBehavior,
8        ScaleChange, ShortcutNumbers, XpBar,
9    },
10    render::RenderMode,
11    settings::{
12        AudioSettings, ChatSettings, ControlSettings, Fps, GamepadSettings, GameplaySettings,
13        GraphicsSettings, InterfaceSettings, audio::AudioVolume,
14    },
15    window::{FullScreenSettings, Window},
16};
17use i18n::{LanguageMetadata, LocalizationHandle};
18use std::rc::Rc;
19
20#[derive(Clone)]
21pub enum Audio {
22    AdjustMasterVolume(f32),
23    MuteMasterVolume(bool),
24    AdjustInactiveMasterVolume(f32),
25    MuteInactiveMasterVolume(bool),
26    AdjustMusicVolume(f32),
27    MuteMusicVolume(bool),
28    AdjustSfxVolume(f32),
29    MuteSfxVolume(bool),
30    AdjustAmbienceVolume(f32),
31    MuteAmbienceVolume(bool),
32    AdjustMusicSpacing(f32),
33    ToggleCombatMusic(bool),
34    //ChangeAudioDevice(String),
35    ResetAudioSettings,
36}
37#[derive(Clone)]
38pub enum Chat {
39    Transp(f32),
40    CharName(bool),
41    ChangeChatTab(Option<usize>),
42    ChatTabUpdate(usize, ChatTab),
43    ChatTabInsert(usize, ChatTab),
44    ChatTabMove(usize, usize), //(i, j) move item from position i, and insert into position j
45    ChatTabRemove(usize),
46    ResetChatSettings,
47}
48#[derive(Clone)]
49pub enum Control {
50    ChangeBinding(GameInput),
51    RemoveBinding(GameInput),
52    ResetKeyBindings,
53}
54#[derive(Clone)]
55pub enum Gamepad {}
56#[derive(Clone)]
57pub enum Gameplay {
58    AdjustMousePan(u32),
59    AdjustMouseZoom(u32),
60    AdjustCameraClamp(u32),
61    AdjustWalkingSpeed(f32),
62
63    ToggleControllerYInvert(bool),
64    ToggleMouseYInvert(bool),
65    ToggleZoomInvert(bool),
66
67    ToggleSmoothPan(bool),
68
69    ChangeFreeLookBehavior(PressBehavior),
70    ChangeAutoWalkBehavior(PressBehavior),
71    ChangeWalkingSpeedBehavior(PressBehavior),
72    ChangeCameraClampBehavior(PressBehavior),
73    ChangeZoomLockBehavior(AutoPressBehavior),
74    ChangeStopAutoWalkOnInput(bool),
75    ChangeAutoCamera(bool),
76    ChangeBowZoom(bool),
77    ChangeZoomLock(bool),
78    ChangeShowAllRecipes(bool),
79
80    AdjustAimOffsetX(f32),
81    AdjustAimOffsetY(f32),
82
83    ResetGameplaySettings,
84}
85#[derive(Clone)]
86pub enum Graphics {
87    AdjustTerrainViewDistance(u32),
88    AdjustEntityViewDistance(u32),
89    AdjustLodDistance(u32),
90    AdjustLodDetail(u32),
91    AdjustSpriteRenderDistance(u32),
92    AdjustFigureLoDRenderDistance(u32),
93
94    ChangeMaxFPS(Fps),
95    ChangeMaxBackgroundFPS(Fps),
96    ChangeFOV(u16),
97
98    ChangeGamma(f32),
99    ChangeExposure(f32),
100    ChangeAmbiance(f32),
101
102    ChangeRenderMode(Box<RenderMode>),
103
104    ChangeFullscreenMode(FullScreenSettings),
105    ToggleParticlesEnabled(bool),
106    ToggleWeaponTrailsEnabled(bool),
107    AdjustWindowSize([u16; 2]),
108
109    ResetGraphicsSettings,
110    ChangeGraphicsSettings(Rc<dyn Fn(GraphicsSettings) -> GraphicsSettings>),
111}
112#[derive(Clone)]
113pub enum Interface {
114    Sct(bool),
115    SctRoundDamage(bool),
116    SctDamageAccumDuration(f32),
117    SctIncomingDamage(bool),
118    SctIncomingDamageAccumDuration(f32),
119    SpeechBubbleSelf(bool),
120    SpeechBubbleDarkMode(bool),
121    SpeechBubbleIcon(bool),
122    ToggleDebug(bool),
123    ToggleHitboxes(bool),
124    ToggleChat(bool),
125    ToggleTips(bool),
126    ToggleHotkeyHints(bool),
127
128    CrosshairTransp(f32),
129    CrosshairType(CrosshairType),
130    Intro(Intro),
131    ToggleXpBar(XpBar),
132    ToggleHealthPrefixes(bool),
133    ToggleBarNumbers(BarNumbers),
134    ToggleAlwaysShowBars(bool),
135    TogglePoiseBar(bool),
136    ToggleShortcutNumbers(ShortcutNumbers),
137    BuffPosition(BuffPosition),
138
139    UiScale(ScaleChange),
140    //Minimap
141    MinimapShow(bool),
142    MinimapFaceNorth(bool),
143    MinimapZoom(f64),
144    //Map settings
145    MapZoom(f64),
146    MapShowTopoMap(bool),
147    MapShowDifficulty(bool),
148    MapShowTowns(bool),
149    MapShowDungeons(bool),
150    MapShowCastles(bool),
151    MapShowBridges(bool),
152    MapShowGliderCourses(bool),
153    MapShowCaves(bool),
154    MapShowTrees(bool),
155    MapShowPeaks(bool),
156    MapShowBiomes(bool),
157    MapShowVoxelMap(bool),
158    AccumExperience(bool),
159    //Slots
160    SlotsUsePrefixes(bool),
161    SlotsPrefixSwitchPoint(u32),
162
163    ResetInterfaceSettings,
164}
165#[derive(Clone)]
166pub enum Language {
167    ChangeLanguage(Box<LanguageMetadata>),
168    ToggleSendToServer(bool),
169    ToggleEnglishFallback(bool),
170}
171#[derive(Clone)]
172pub enum Networking {
173    AdjustTerrainViewDistance(u32),
174    AdjustEntityViewDistance(u32),
175    ChangePlayerPhysicsBehavior {
176        server_authoritative: bool,
177    },
178    ToggleLossyTerrainCompression(bool),
179
180    #[cfg(feature = "discord")]
181    ToggleDiscordIntegration(bool),
182    // TODO: reset option (ensure it handles the entity/terrain vd the same as graphics reset
183    // option)
184}
185
186#[derive(Clone)]
187pub enum Accessibility {
188    ChangeRenderMode(Box<RenderMode>),
189    SetSubtitles(bool),
190}
191
192#[derive(Clone)]
193pub enum SettingsChange {
194    Audio(Audio),
195    Chat(Chat),
196    Control(Control),
197    Gamepad(Gamepad),
198    Gameplay(Gameplay),
199    Graphics(Graphics),
200    Interface(Interface),
201    Language(Language),
202    Networking(Networking),
203    Accessibility(Accessibility),
204}
205
206macro_rules! settings_change_from {
207    ($i: ident) => {
208        impl From<$i> for SettingsChange {
209            fn from(change: $i) -> Self { SettingsChange::$i(change) }
210        }
211    };
212}
213settings_change_from!(Audio);
214settings_change_from!(Chat);
215settings_change_from!(Control);
216settings_change_from!(Gamepad);
217settings_change_from!(Gameplay);
218settings_change_from!(Graphics);
219settings_change_from!(Interface);
220settings_change_from!(Language);
221settings_change_from!(Networking);
222settings_change_from!(Accessibility);
223
224impl SettingsChange {
225    pub fn process(self, global_state: &mut GlobalState, session_state: &mut SessionState) {
226        let settings = &mut global_state.settings;
227
228        match self {
229            SettingsChange::Audio(audio_change) => {
230                fn update_volume(audio: &mut AudioVolume, volume: f32) -> f32 {
231                    audio.volume = volume;
232                    audio.get_checked()
233                }
234                fn update_muted(audio: &mut AudioVolume, muted: bool) -> f32 {
235                    audio.muted = muted;
236                    audio.get_checked()
237                }
238
239                match audio_change {
240                    Audio::AdjustMasterVolume(master_volume) => {
241                        let volume_checked =
242                            update_volume(&mut settings.audio.master_volume, master_volume);
243
244                        global_state.audio.set_master_volume(volume_checked);
245                    },
246                    Audio::MuteMasterVolume(master_muted) => {
247                        let volume_checked =
248                            update_muted(&mut settings.audio.master_volume, master_muted);
249
250                        global_state.audio.set_master_volume(volume_checked);
251                    },
252                    Audio::AdjustInactiveMasterVolume(inactive_master_volume_perc) => {
253                        settings.audio.inactive_master_volume_perc.volume =
254                            inactive_master_volume_perc;
255                    },
256                    Audio::MuteInactiveMasterVolume(inactive_master_volume_muted) => {
257                        settings.audio.inactive_master_volume_perc.muted =
258                            inactive_master_volume_muted;
259                    },
260                    Audio::AdjustMusicVolume(music_volume) => {
261                        let volume_checked =
262                            update_volume(&mut settings.audio.music_volume, music_volume);
263
264                        global_state.audio.set_music_volume(volume_checked);
265                    },
266                    Audio::MuteMusicVolume(music_muted) => {
267                        let volume_checked =
268                            update_muted(&mut settings.audio.music_volume, music_muted);
269
270                        global_state.audio.set_music_volume(volume_checked);
271                    },
272                    Audio::AdjustSfxVolume(sfx_volume) => {
273                        let volume_checked =
274                            update_volume(&mut settings.audio.sfx_volume, sfx_volume);
275
276                        global_state.audio.set_sfx_volume(volume_checked);
277                    },
278                    Audio::MuteSfxVolume(sfx_muted) => {
279                        let volume_checked =
280                            update_muted(&mut settings.audio.sfx_volume, sfx_muted);
281
282                        global_state.audio.set_sfx_volume(volume_checked);
283                    },
284                    Audio::AdjustAmbienceVolume(ambience_volume) => {
285                        global_state.audio.set_ambience_volume(ambience_volume);
286
287                        settings.audio.ambience_volume.volume = ambience_volume;
288                    },
289                    Audio::MuteAmbienceVolume(ambience_muted) => {
290                        let volume_checked =
291                            update_muted(&mut settings.audio.ambience_volume, ambience_muted);
292
293                        global_state.audio.set_ambience_volume(volume_checked);
294                    },
295                    Audio::AdjustMusicSpacing(multiplier) => {
296                        global_state.audio.set_music_spacing(multiplier);
297
298                        settings.audio.music_spacing = multiplier;
299                    },
300                    Audio::ToggleCombatMusic(combat_music_enabled) => {
301                        global_state.audio.combat_music_enabled = combat_music_enabled
302                    },
303                    Audio::ResetAudioSettings => {
304                        settings.audio = AudioSettings::default();
305
306                        let audio = &mut global_state.audio;
307
308                        audio.set_master_volume(settings.audio.master_volume.get_checked());
309                        audio.set_music_volume(settings.audio.music_volume.get_checked());
310                        audio.set_ambience_volume(settings.audio.ambience_volume.get_checked());
311                        audio.set_sfx_volume(settings.audio.sfx_volume.get_checked());
312                        audio.set_music_spacing(settings.audio.music_spacing);
313                    },
314                }
315            },
316            SettingsChange::Chat(chat_change) => {
317                let chat_tabs = &mut settings.chat.chat_tabs;
318                match chat_change {
319                    Chat::Transp(chat_opacity) => {
320                        settings.chat.chat_opacity = chat_opacity;
321                    },
322                    Chat::CharName(chat_char_name) => {
323                        settings.chat.chat_character_name = chat_char_name;
324                    },
325                    Chat::ChangeChatTab(chat_tab_index) => {
326                        settings.chat.chat_tab_index =
327                            chat_tab_index.filter(|i| *i < chat_tabs.len());
328                    },
329                    Chat::ChatTabUpdate(i, chat_tab) => {
330                        if i < chat_tabs.len() {
331                            chat_tabs[i] = chat_tab;
332                        }
333                    },
334                    Chat::ChatTabInsert(i, chat_tab) => {
335                        if i <= chat_tabs.len() {
336                            settings.chat.chat_tabs.insert(i, chat_tab);
337                        }
338                    },
339                    Chat::ChatTabMove(i, j) => {
340                        if i < chat_tabs.len() && j < chat_tabs.len() {
341                            let chat_tab = settings.chat.chat_tabs.remove(i);
342                            settings.chat.chat_tabs.insert(j, chat_tab);
343                        }
344                    },
345                    Chat::ChatTabRemove(i) => {
346                        if i < chat_tabs.len() {
347                            settings.chat.chat_tabs.remove(i);
348                        }
349                    },
350                    Chat::ResetChatSettings => {
351                        settings.chat = ChatSettings::default();
352                    },
353                }
354            },
355            SettingsChange::Control(control_change) => match control_change {
356                Control::ChangeBinding(game_input) => {
357                    global_state.window.set_keybinding_mode(game_input);
358                },
359                Control::RemoveBinding(game_input) => {
360                    settings.controls.remove_binding(game_input);
361                },
362                Control::ResetKeyBindings => {
363                    settings.controls = ControlSettings::default();
364                },
365            },
366            SettingsChange::Gamepad(gamepad_change) => match gamepad_change {},
367            SettingsChange::Gameplay(gameplay_change) => {
368                let window = &mut global_state.window;
369                match gameplay_change {
370                    Gameplay::AdjustMousePan(sensitivity) => {
371                        window.pan_sensitivity = sensitivity;
372                        settings.gameplay.pan_sensitivity = sensitivity;
373                    },
374                    Gameplay::AdjustMouseZoom(sensitivity) => {
375                        window.zoom_sensitivity = sensitivity;
376                        settings.gameplay.zoom_sensitivity = sensitivity;
377                    },
378                    Gameplay::AdjustCameraClamp(angle) => {
379                        settings.gameplay.camera_clamp_angle = angle;
380                    },
381                    Gameplay::AdjustWalkingSpeed(speed) => {
382                        settings.gameplay.walking_speed = speed;
383                    },
384                    Gameplay::ToggleControllerYInvert(controller_y_inverted) => {
385                        window.controller_settings.pan_invert_y = controller_y_inverted;
386                        settings.controller.pan_invert_y = controller_y_inverted;
387                    },
388                    Gameplay::ToggleMouseYInvert(mouse_y_inverted) => {
389                        window.mouse_y_inversion = mouse_y_inverted;
390                        settings.gameplay.mouse_y_inversion = mouse_y_inverted;
391                    },
392                    Gameplay::ToggleZoomInvert(zoom_inverted) => {
393                        window.zoom_inversion = zoom_inverted;
394                        settings.gameplay.zoom_inversion = zoom_inverted;
395                    },
396                    Gameplay::ToggleSmoothPan(smooth_pan_enabled) => {
397                        settings.gameplay.smooth_pan_enable = smooth_pan_enabled;
398                    },
399                    Gameplay::ChangeFreeLookBehavior(behavior) => {
400                        settings.gameplay.free_look_behavior = behavior;
401                    },
402                    Gameplay::ChangeAutoWalkBehavior(behavior) => {
403                        settings.gameplay.auto_walk_behavior = behavior;
404                    },
405                    Gameplay::ChangeWalkingSpeedBehavior(behavior) => {
406                        settings.gameplay.walking_speed_behavior = behavior;
407                    },
408                    Gameplay::ChangeCameraClampBehavior(behavior) => {
409                        settings.gameplay.camera_clamp_behavior = behavior;
410                    },
411                    Gameplay::ChangeZoomLockBehavior(state) => {
412                        settings.gameplay.zoom_lock_behavior = state;
413                    },
414                    Gameplay::ChangeStopAutoWalkOnInput(state) => {
415                        settings.gameplay.stop_auto_walk_on_input = state;
416                    },
417                    Gameplay::ChangeAutoCamera(state) => {
418                        settings.gameplay.auto_camera = state;
419                    },
420                    Gameplay::ChangeBowZoom(state) => {
421                        settings.gameplay.bow_zoom = state;
422                    },
423                    Gameplay::ChangeZoomLock(state) => {
424                        settings.gameplay.zoom_lock = state;
425                    },
426                    Gameplay::AdjustAimOffsetX(offset) => {
427                        settings.gameplay.aim_offset_x = offset;
428                    },
429                    Gameplay::AdjustAimOffsetY(offset) => {
430                        settings.gameplay.aim_offset_y = offset;
431                    },
432                    Gameplay::ResetGameplaySettings => {
433                        // Reset Gameplay Settings
434                        settings.gameplay = GameplaySettings::default();
435                        // Reset Gamepad and Controller Settings
436                        settings.controller = GamepadSettings::default();
437                        window.controller_settings = ControllerSettings::from(&settings.controller);
438                        // Pan Sensitivity
439                        window.pan_sensitivity = settings.gameplay.pan_sensitivity;
440                        // Zoom Sensitivity
441                        window.zoom_sensitivity = settings.gameplay.zoom_sensitivity;
442                        // Invert Scroll Zoom
443                        window.zoom_inversion = settings.gameplay.zoom_inversion;
444                        // Invert Mouse Y Axis
445                        window.mouse_y_inversion = settings.gameplay.mouse_y_inversion;
446                    },
447                    Gameplay::ChangeShowAllRecipes(state) => {
448                        settings.gameplay.show_all_recipes = state;
449                    },
450                }
451            },
452            SettingsChange::Graphics(graphics_change) => {
453                let mut change_preset = false;
454
455                match graphics_change {
456                    Graphics::AdjustTerrainViewDistance(terrain_vd) => {
457                        adjust_terrain_view_distance(terrain_vd, settings, session_state)
458                    },
459                    Graphics::AdjustEntityViewDistance(entity_vd) => {
460                        adjust_entity_view_distance(entity_vd, settings, session_state)
461                    },
462                    Graphics::AdjustLodDistance(lod_distance) => {
463                        session_state
464                            .client
465                            .borrow_mut()
466                            .set_lod_distance(lod_distance);
467
468                        settings.graphics.lod_distance = lod_distance;
469                    },
470                    Graphics::AdjustLodDetail(lod_detail) => {
471                        session_state.scene.lod.set_detail(lod_detail);
472
473                        settings.graphics.lod_detail = lod_detail;
474                    },
475                    Graphics::AdjustSpriteRenderDistance(sprite_render_distance) => {
476                        settings.graphics.sprite_render_distance = sprite_render_distance;
477                    },
478                    Graphics::AdjustFigureLoDRenderDistance(figure_lod_render_distance) => {
479                        settings.graphics.figure_lod_render_distance = figure_lod_render_distance;
480                    },
481                    Graphics::ChangeMaxFPS(fps) => {
482                        settings.graphics.max_fps = fps;
483                    },
484                    Graphics::ChangeMaxBackgroundFPS(fps) => {
485                        settings.graphics.max_background_fps = fps;
486                    },
487                    Graphics::ChangeFOV(new_fov) => {
488                        settings.graphics.fov = new_fov;
489                        session_state.scene.camera_mut().set_fov_deg(new_fov);
490                        session_state
491                            .scene
492                            .camera_mut()
493                            .compute_dependents(&session_state.client.borrow().state().terrain());
494                    },
495                    Graphics::ChangeGamma(new_gamma) => {
496                        settings.graphics.gamma = new_gamma;
497                    },
498                    Graphics::ChangeExposure(new_exposure) => {
499                        settings.graphics.exposure = new_exposure;
500                    },
501                    Graphics::ChangeAmbiance(new_ambiance) => {
502                        settings.graphics.ambiance = new_ambiance;
503                    },
504                    Graphics::ChangeRenderMode(new_render_mode) => {
505                        change_render_mode(*new_render_mode, &mut global_state.window, settings);
506                    },
507                    Graphics::ChangeFullscreenMode(new_fullscreen_settings) => {
508                        global_state
509                            .window
510                            .set_fullscreen_mode(new_fullscreen_settings);
511                        settings.graphics.fullscreen = new_fullscreen_settings;
512                    },
513                    Graphics::ToggleParticlesEnabled(particles_enabled) => {
514                        settings.graphics.particles_enabled = particles_enabled;
515                    },
516                    Graphics::ToggleWeaponTrailsEnabled(weapon_trails_enabled) => {
517                        settings.graphics.weapon_trails_enabled = weapon_trails_enabled;
518                    },
519                    Graphics::AdjustWindowSize(new_size) => {
520                        global_state.window.set_size(new_size.into());
521                        settings.graphics.window.size = new_size;
522                    },
523                    Graphics::ResetGraphicsSettings => {
524                        settings.graphics = GraphicsSettings::default();
525                        change_preset = true;
526                        // Fullscreen mode
527                        global_state
528                            .window
529                            .set_fullscreen_mode(settings.graphics.fullscreen);
530                        // Window size
531                        global_state
532                            .window
533                            .set_size(settings.graphics.window.size.into());
534                    },
535                    Graphics::ChangeGraphicsSettings(f) => {
536                        settings.graphics = f(settings.graphics.clone());
537                        change_preset = true;
538                    },
539                }
540
541                if change_preset {
542                    let graphics = &settings.graphics;
543                    // View distance
544                    client_set_view_distance(settings, session_state);
545                    // FOV
546                    session_state.scene.camera_mut().set_fov_deg(graphics.fov);
547                    session_state
548                        .scene
549                        .camera_mut()
550                        .compute_dependents(&session_state.client.borrow().state().terrain());
551                    // LoD
552                    session_state.scene.lod.set_detail(graphics.lod_detail);
553                    // LoD distance
554                    session_state
555                        .client
556                        .borrow_mut()
557                        .set_lod_distance(graphics.lod_distance);
558                    // Render mode
559                    global_state
560                        .window
561                        .renderer_mut()
562                        .set_render_mode(graphics.render_mode.clone())
563                        .unwrap();
564                }
565            },
566            SettingsChange::Interface(interface_change) => {
567                match interface_change {
568                    Interface::Sct(sct) => {
569                        settings.interface.sct = sct;
570                    },
571                    Interface::SctRoundDamage(sct_round_damage) => {
572                        settings.interface.sct_damage_rounding = sct_round_damage;
573                    },
574                    Interface::SctDamageAccumDuration(sct_dmg_accum_duration) => {
575                        settings.interface.sct_dmg_accum_duration = sct_dmg_accum_duration;
576                    },
577                    Interface::SctIncomingDamage(sct_inc_dmg) => {
578                        settings.interface.sct_inc_dmg = sct_inc_dmg;
579                    },
580                    Interface::SctIncomingDamageAccumDuration(sct_inc_dmg_accum_duration) => {
581                        settings.interface.sct_inc_dmg_accum_duration = sct_inc_dmg_accum_duration;
582                    },
583                    Interface::SpeechBubbleSelf(sbdm) => {
584                        settings.interface.speech_bubble_self = sbdm;
585                    },
586                    Interface::SpeechBubbleDarkMode(sbdm) => {
587                        settings.interface.speech_bubble_dark_mode = sbdm;
588                    },
589                    Interface::SpeechBubbleIcon(sbi) => {
590                        settings.interface.speech_bubble_icon = sbi;
591                    },
592                    Interface::ToggleDebug(toggle_debug) => {
593                        settings.interface.toggle_debug = toggle_debug;
594                    },
595                    Interface::ToggleHitboxes(toggle_hitboxes) => {
596                        settings.interface.toggle_hitboxes = toggle_hitboxes;
597                    },
598                    Interface::ToggleChat(toggle_chat) => {
599                        settings.interface.toggle_chat = toggle_chat;
600                    },
601                    Interface::ToggleTips(loading_tips) => {
602                        settings.interface.loading_tips = loading_tips;
603                    },
604                    Interface::ToggleHotkeyHints(toggle_hotkey_hints) => {
605                        settings.interface.toggle_hotkey_hints = toggle_hotkey_hints;
606                    },
607                    Interface::CrosshairTransp(crosshair_opacity) => {
608                        settings.interface.crosshair_opacity = crosshair_opacity;
609                    },
610                    Interface::CrosshairType(crosshair_type) => {
611                        settings.interface.crosshair_type = crosshair_type;
612                    },
613                    Interface::Intro(intro_show) => {
614                        settings.interface.intro_show = intro_show;
615                    },
616                    Interface::ToggleXpBar(xp_bar) => {
617                        settings.interface.xp_bar = xp_bar;
618                    },
619                    Interface::ToggleBarNumbers(bar_numbers) => {
620                        settings.interface.bar_numbers = bar_numbers;
621                    },
622                    Interface::ToggleAlwaysShowBars(always_show_bars) => {
623                        settings.interface.always_show_bars = always_show_bars;
624                    },
625                    Interface::TogglePoiseBar(enable_poise_bar) => {
626                        settings.interface.enable_poise_bar = enable_poise_bar;
627                    },
628                    Interface::ToggleHealthPrefixes(use_health_prefixes) => {
629                        settings.interface.use_health_prefixes = use_health_prefixes;
630                    },
631                    Interface::ToggleShortcutNumbers(shortcut_numbers) => {
632                        settings.interface.shortcut_numbers = shortcut_numbers;
633                    },
634                    Interface::BuffPosition(buff_position) => {
635                        settings.interface.buff_position = buff_position;
636                    },
637                    Interface::UiScale(scale_change) => {
638                        settings.interface.ui_scale = session_state.hud.scale_change(scale_change);
639                    },
640                    Interface::MinimapShow(state) => {
641                        settings.interface.minimap_show = state;
642                    },
643                    Interface::MinimapFaceNorth(state) => {
644                        settings.interface.minimap_face_north = state;
645                    },
646                    Interface::MinimapZoom(minimap_zoom) => {
647                        settings.interface.minimap_zoom = minimap_zoom;
648                    },
649                    Interface::MapZoom(map_zoom) => {
650                        settings.interface.map_zoom = map_zoom;
651                    },
652                    Interface::MapShowTopoMap(map_show_topo_map) => {
653                        settings.interface.map_show_topo_map = map_show_topo_map;
654                    },
655                    Interface::MapShowDifficulty(map_show_difficulty) => {
656                        settings.interface.map_show_difficulty = map_show_difficulty;
657                    },
658                    Interface::MapShowTowns(map_show_towns) => {
659                        settings.interface.map_show_towns = map_show_towns;
660                    },
661                    Interface::MapShowDungeons(map_show_dungeons) => {
662                        settings.interface.map_show_dungeons = map_show_dungeons;
663                    },
664                    Interface::MapShowCastles(map_show_castles) => {
665                        settings.interface.map_show_castles = map_show_castles;
666                    },
667                    Interface::MapShowBridges(map_show_bridges) => {
668                        settings.interface.map_show_bridges = map_show_bridges;
669                    },
670                    Interface::MapShowGliderCourses(map_show_glider_courses) => {
671                        settings.interface.map_show_glider_courses = map_show_glider_courses;
672                    },
673                    Interface::MapShowCaves(map_show_caves) => {
674                        settings.interface.map_show_caves = map_show_caves;
675                    },
676                    Interface::MapShowTrees(map_show_trees) => {
677                        settings.interface.map_show_trees = map_show_trees;
678                    },
679                    Interface::MapShowPeaks(map_show_peaks) => {
680                        settings.interface.map_show_peaks = map_show_peaks;
681                    },
682                    Interface::MapShowBiomes(map_show_biomes) => {
683                        settings.interface.map_show_biomes = map_show_biomes;
684                    },
685                    Interface::MapShowVoxelMap(map_show_voxel_map) => {
686                        settings.interface.map_show_voxel_map = map_show_voxel_map;
687                    },
688                    Interface::AccumExperience(accum_experience) => {
689                        settings.interface.accum_experience = accum_experience;
690                    },
691                    Interface::SlotsUsePrefixes(slots_use_prefixes) => {
692                        settings.interface.slots_use_prefixes = slots_use_prefixes;
693                        session_state.hud.set_slots_use_prefixes(slots_use_prefixes);
694                    },
695                    Interface::SlotsPrefixSwitchPoint(slots_prefix_switch_point) => {
696                        settings.interface.slots_prefix_switch_point = slots_prefix_switch_point;
697                        session_state
698                            .hud
699                            .set_slots_prefix_switch_point(slots_prefix_switch_point);
700                    },
701                    Interface::ResetInterfaceSettings => {
702                        // Reset Interface Settings
703                        let tmp = settings.interface.intro_show;
704                        settings.interface = InterfaceSettings::default();
705                        settings.interface.intro_show = tmp;
706                        // Update Current Scaling Mode
707                        session_state
708                            .hud
709                            .set_scaling_mode(settings.interface.ui_scale);
710                    },
711                }
712            },
713            SettingsChange::Language(language_change) => match language_change {
714                Language::ChangeLanguage(new_language) => {
715                    settings.language.selected_language = new_language.language_identifier;
716                    global_state.i18n =
717                        LocalizationHandle::load_expect(&settings.language.selected_language);
718                    global_state
719                        .i18n
720                        .set_english_fallback(settings.language.use_english_fallback);
721                    session_state.hud.update_fonts(&global_state.i18n.read());
722                },
723                Language::ToggleEnglishFallback(toggle_fallback) => {
724                    settings.language.use_english_fallback = toggle_fallback;
725                    global_state
726                        .i18n
727                        .set_english_fallback(settings.language.use_english_fallback);
728                },
729                Language::ToggleSendToServer(share) => {
730                    settings.language.send_to_server = share;
731                },
732            },
733            SettingsChange::Networking(networking_change) => match networking_change {
734                Networking::AdjustTerrainViewDistance(terrain_vd) => {
735                    adjust_terrain_view_distance(terrain_vd, settings, session_state)
736                },
737                Networking::AdjustEntityViewDistance(entity_vd) => {
738                    adjust_entity_view_distance(entity_vd, settings, session_state)
739                },
740                Networking::ChangePlayerPhysicsBehavior {
741                    server_authoritative,
742                } => {
743                    settings.networking.player_physics_behavior = server_authoritative;
744                    session_state
745                        .client
746                        .borrow_mut()
747                        .request_player_physics(server_authoritative);
748                },
749                Networking::ToggleLossyTerrainCompression(lossy_terrain_compression) => {
750                    settings.networking.lossy_terrain_compression = lossy_terrain_compression;
751                    session_state
752                        .client
753                        .borrow_mut()
754                        .request_lossy_terrain_compression(lossy_terrain_compression);
755                },
756                #[cfg(feature = "discord")]
757                Networking::ToggleDiscordIntegration(enabled) => {
758                    use crate::discord::Discord;
759
760                    settings.networking.enable_discord_integration = enabled;
761                    if enabled {
762                        global_state.discord = Discord::start(&global_state.tokio_runtime);
763
764                        #[cfg(feature = "singleplayer")]
765                        let singleplayer = global_state.singleplayer.is_running();
766                        #[cfg(not(feature = "singleplayer"))]
767                        let singleplayer = false;
768
769                        if singleplayer {
770                            global_state.discord.join_singleplayer();
771                        } else {
772                            global_state.discord.join_server(
773                                session_state.client.borrow().server_info().name.clone(),
774                            );
775                        }
776                    } else {
777                        global_state.discord.clear_activity();
778                        global_state.discord = Discord::Inactive;
779                    }
780                },
781            },
782            SettingsChange::Accessibility(accessibility_change) => match accessibility_change {
783                Accessibility::ChangeRenderMode(new_render_mode) => {
784                    change_render_mode(*new_render_mode, &mut global_state.window, settings);
785                },
786                Accessibility::SetSubtitles(enabled) => {
787                    global_state.settings.audio.subtitles = enabled;
788                    global_state.audio.set_subtitles(enabled);
789                },
790            },
791        }
792        global_state
793            .settings
794            .save_to_file_warn(&global_state.config_dir);
795    }
796}
797
798use crate::settings::Settings;
799
800pub fn change_render_mode(
801    new_render_mode: RenderMode,
802    window: &mut Window,
803    settings: &mut Settings,
804) {
805    // Do this first so if it crashes the setting isn't saved :)
806    window
807        .renderer_mut()
808        .set_render_mode(new_render_mode.clone())
809        .unwrap();
810    settings.graphics.render_mode = new_render_mode;
811}
812
813fn adjust_terrain_view_distance(
814    terrain_vd: u32,
815    settings: &mut Settings,
816    session_state: &mut SessionState,
817) {
818    settings.graphics.terrain_view_distance = terrain_vd;
819    client_set_view_distance(settings, session_state);
820}
821
822fn adjust_entity_view_distance(
823    entity_vd: u32,
824    settings: &mut Settings,
825    session_state: &mut SessionState,
826) {
827    settings.graphics.entity_view_distance = entity_vd;
828    client_set_view_distance(settings, session_state);
829}
830
831fn client_set_view_distance(settings: &Settings, session_state: &mut SessionState) {
832    let view_distances = common::ViewDistances {
833        terrain: settings.graphics.terrain_view_distance,
834        entity: settings.graphics.entity_view_distance,
835    };
836    session_state
837        .client
838        .borrow_mut()
839        .set_view_distances(view_distances);
840}