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