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