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