Skip to main content

veloren_voxygen/
lib.rs

1#![deny(unsafe_code)]
2#![expect(incomplete_features)]
3#![expect(
4    clippy::identity_op,
5    clippy::option_map_unit_fn,
6    clippy::needless_pass_by_ref_mut //until we find a better way for specs
7)]
8#![deny(clippy::clone_on_ref_ptr)]
9#![feature(generic_const_exprs)]
10#![recursion_limit = "2048"]
11
12#[macro_use]
13pub mod ui;
14pub mod audio;
15pub mod cli;
16pub mod cmd;
17mod credits;
18#[cfg(feature = "discord")] pub mod discord;
19mod ecs;
20pub mod error;
21pub mod game_input;
22pub mod hud;
23pub mod key_state;
24pub mod menu;
25pub mod mesh;
26pub mod panic_handler;
27pub mod profile;
28pub mod render;
29pub mod run;
30pub mod scene;
31pub mod session;
32pub mod settings;
33#[cfg(feature = "singleplayer")]
34pub mod singleplayer;
35pub mod window;
36
37#[cfg(feature = "singleplayer")]
38use crate::singleplayer::Singleplayer;
39#[cfg(feature = "singleplayer")]
40use crate::singleplayer::SingleplayerState;
41#[cfg(feature = "egui-ui")]
42use crate::ui::egui::EguiState;
43use crate::{
44    audio::AudioFrontend,
45    profile::Profile,
46    render::{Drawer, GlobalsBindGroup},
47    settings::Settings,
48    window::{Event, Window},
49};
50use common::clock::Clock;
51use common_base::span;
52use i18n::LocalizationHandle;
53use std::{path::PathBuf, sync::Arc};
54use tokio::runtime::Runtime;
55
56/// A type used to store state that is shared between all play states.
57pub struct GlobalState {
58    pub userdata_dir: PathBuf,
59    pub config_dir: PathBuf,
60    pub settings: Settings,
61    pub profile: Profile,
62    pub window: Window,
63    pub tokio_runtime: Arc<Runtime>,
64    #[cfg(feature = "egui-ui")]
65    pub egui_state: EguiState,
66    pub lazy_init: scene::terrain::SpriteRenderContextLazy,
67    pub audio: AudioFrontend,
68    pub info_message: Option<String>,
69    pub clock: Clock,
70    #[cfg(feature = "singleplayer")]
71    pub singleplayer: SingleplayerState,
72    // TODO: redo this so that the watcher doesn't have to exist for reloading to occur
73    pub i18n: LocalizationHandle,
74    pub clipboard: ui::ice::Clipboard,
75    /// Used to clear the shadow textures when entering a PlayState that doesn't
76    /// utilise shadows.
77    pub clear_shadows_next_frame: bool,
78    /// CLI arguments passed to voxygen
79    pub args: crate::cli::Args,
80    /// A channel that sends Discord activity updates to a background task
81    #[cfg(feature = "discord")]
82    pub discord: crate::discord::Discord,
83}
84
85impl GlobalState {
86    /// Called after a change in play state has occurred (usually used to
87    /// reverse any temporary effects a state may have made).
88    pub fn on_play_state_changed(&mut self) {
89        self.window.grab_cursor(false);
90        self.window.needs_refresh_resize();
91    }
92
93    pub fn maintain(&mut self) {
94        span!(_guard, "maintain", "GlobalState::maintain");
95        self.audio.maintain();
96        self.window.renderer().maintain()
97    }
98
99    #[cfg(feature = "singleplayer")]
100    pub fn paused(&self) -> bool {
101        self.singleplayer
102            .as_running()
103            .is_some_and(Singleplayer::is_paused)
104    }
105
106    #[cfg(not(feature = "singleplayer"))]
107    pub fn paused(&self) -> bool { false }
108
109    #[cfg(feature = "singleplayer")]
110    pub fn unpause(&self) { self.singleplayer.as_running().map(|s| s.pause(false)); }
111
112    #[cfg(feature = "singleplayer")]
113    pub fn pause(&self) { self.singleplayer.as_running().map(|s| s.pause(true)); }
114}
115
116// TODO: appears to be currently unused by playstates
117pub enum Direction {
118    Forwards,
119    Backwards,
120}
121
122/// States can either close (and revert to a previous state), push a new state
123/// on top of themselves, or switch to a totally different state.
124pub enum PlayStateResult {
125    /// Keep running this play state.
126    Continue,
127    /// Pop all play states in reverse order and shut down the program.
128    Shutdown,
129    /// Close the current play state and pop it from the play state stack.
130    Pop,
131    /// Push a new play state onto the play state stack.
132    Push(Box<dyn PlayState>),
133    /// Switch the current play state with a new play state.
134    Switch(Box<dyn PlayState>),
135}
136
137/// A trait representing a playable game state. This may be a menu, a game
138/// session, the title screen, etc.
139pub trait PlayState {
140    /// Called when entering this play state from another
141    fn enter(&mut self, global_state: &mut GlobalState, direction: Direction);
142
143    /// Tick the play state
144    fn tick(&mut self, global_state: &mut GlobalState, events: Vec<Event>) -> PlayStateResult;
145
146    /// Get a descriptive name for this state type.
147    fn name(&self) -> &'static str;
148
149    /// Determines whether the play state should have an enforced FPS cap
150    fn capped_fps(&self) -> bool;
151
152    fn globals_bind_group(&self) -> &GlobalsBindGroup;
153
154    /// Draw the play state.
155    fn render(&self, drawer: &mut Drawer<'_>, settings: &Settings);
156
157    /// Determines whether egui will be rendered for this play state
158    fn egui_enabled(&self) -> bool;
159}