veloren_voxygen/session/
settings_change.rs

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