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