[display] vsync = "mailbox" # "vsync" | "mailbox" | "uncapped" VsyncMode enum with custom Deserialize — accepts string values in toml. apply_vsync_setting system reads GameConfig on every frame, updates Window.present_mode immediately on change. No restart needed.
105 lines
2.6 KiB
Rust
105 lines
2.6 KiB
Rust
use bevy::prelude::Resource;
|
|
use serde::Deserialize;
|
|
use std::collections::HashMap;
|
|
use std::fs;
|
|
use std::sync::OnceLock;
|
|
|
|
#[derive(Debug, Deserialize, Clone, Resource)]
|
|
pub struct GameConfig {
|
|
pub initial_chunk_radius: i32,
|
|
pub spawn_counts: SpawnCounts,
|
|
#[serde(default)]
|
|
pub display: DisplaySettings,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize, Clone, Default)]
|
|
pub struct DisplaySettings {
|
|
#[serde(default)]
|
|
pub vsync: VsyncMode,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
|
|
pub enum VsyncMode {
|
|
#[default]
|
|
Vsync,
|
|
Mailbox,
|
|
Uncapped,
|
|
}
|
|
|
|
impl<'de> Deserialize<'de> for VsyncMode {
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
where
|
|
D: serde::Deserializer<'de>,
|
|
{
|
|
let s = String::deserialize(deserializer)?;
|
|
match s.as_str() {
|
|
"vsync" => Ok(VsyncMode::Vsync),
|
|
"mailbox" => Ok(VsyncMode::Mailbox),
|
|
"uncapped" => Ok(VsyncMode::Uncapped),
|
|
_ => Ok(VsyncMode::Vsync),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Deserialize, Clone)]
|
|
pub struct SpawnCounts {
|
|
pub dorfs: u32,
|
|
pub pigs: u32,
|
|
pub rabbits: u32,
|
|
}
|
|
|
|
impl GameConfig {
|
|
pub fn load() -> Self {
|
|
let config_str = fs::read_to_string("config.toml").expect("Failed to find config.toml");
|
|
toml::from_str(&config_str).expect("Failed to parse config.toml")
|
|
}
|
|
}
|
|
|
|
static TILE_REGISTRY: OnceLock<TileRegistry> = OnceLock::new();
|
|
|
|
#[derive(Debug, Deserialize, Clone)]
|
|
pub struct TileRegistry {
|
|
pub floor_tiles: HashMap<String, FloorTileDef>,
|
|
pub fixture_tiles: HashMap<String, FixtureTileDef>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize, Clone, Copy)]
|
|
pub struct FloorTileDef {
|
|
pub id: u8,
|
|
pub can_stand_in: bool,
|
|
pub can_stand_on: bool,
|
|
pub transparent: bool,
|
|
pub astar_weight: u8,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize, Clone, Copy)]
|
|
pub struct FixtureTileDef {
|
|
pub id: u32,
|
|
pub solid: bool,
|
|
}
|
|
|
|
impl TileRegistry {
|
|
pub fn load() -> Self {
|
|
let config_str = fs::read_to_string("tiles.toml").expect("Failed to find tiles.toml");
|
|
toml::from_str(&config_str).expect("Failed to parse tiles.toml")
|
|
}
|
|
|
|
pub fn global() -> &'static Self {
|
|
TILE_REGISTRY.get_or_init(|| Self::load())
|
|
}
|
|
|
|
pub fn floor(&self, name: &str) -> FloorTileDef {
|
|
*self
|
|
.floor_tiles
|
|
.get(name)
|
|
.unwrap_or_else(|| panic!("Unknown floor tile: {}", name))
|
|
}
|
|
|
|
pub fn fixture(&self, name: &str) -> FixtureTileDef {
|
|
*self
|
|
.fixture_tiles
|
|
.get(name)
|
|
.unwrap_or_else(|| panic!("Unknown fixture tile: {}", name))
|
|
}
|
|
}
|