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