veloren_voxygen/session/
settings_change.rs

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