Skip to main content

veloren_voxygen/session/
settings_change.rs

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