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