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