veloren_voxygen/session/
settings_change.rs

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