From 5279eeb7d45bf5c8857a365f09f1a93f67918722 Mon Sep 17 00:00:00 2001 From: Mark Date: Sun, 24 Dec 2023 23:03:00 -0800 Subject: [PATCH] Added basic system file --- Cargo.lock | 20 ++++++++ Cargo.toml | 1 + content/system.toml | 13 +++++ src/content/content.rs | 32 ++++++++++++ src/content/contenttype.rs | 30 ++++++++++++ src/content/mod.rs | 6 +++ src/content/syntax/mod.rs | 3 ++ src/content/syntax/system.rs | 95 ++++++++++++++++++++++++++++++++++++ src/main.rs | 21 ++++++-- 9 files changed, 218 insertions(+), 3 deletions(-) create mode 100644 content/system.toml create mode 100644 src/content/content.rs create mode 100644 src/content/contenttype.rs create mode 100644 src/content/mod.rs create mode 100644 src/content/syntax/mod.rs create mode 100644 src/content/syntax/system.rs diff --git a/Cargo.lock b/Cargo.lock index 0dde3ee..36bf207 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -543,6 +543,7 @@ dependencies = [ "rand", "serde", "toml", + "walkdir", "wgpu", "winit", ] @@ -1382,6 +1383,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scoped-tls" version = "1.0.1" @@ -1675,6 +1685,16 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 77cf4dc..f1d508b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,3 +40,4 @@ pollster = "0.3" anyhow = "1.0" cgmath = "0.18.0" rand = "0.8.5" +walkdir = "2.4.0" diff --git a/content/system.toml b/content/system.toml new file mode 100644 index 0000000..b9b595a --- /dev/null +++ b/content/system.toml @@ -0,0 +1,13 @@ +# content type: system +[system] +name = "12 Autumn above" + +[object.star] +sprite = "star::a0" +center = [0.0, 0.0] + +[object.earth] +sprite = "planet::earth" +center = "star" +radius = 200 +angle = 14 diff --git a/src/content/content.rs b/src/content/content.rs new file mode 100644 index 0000000..9221e2b --- /dev/null +++ b/src/content/content.rs @@ -0,0 +1,32 @@ +use anyhow::Result; + +use super::{syntax, ContentType}; + +#[derive(Debug)] +pub struct Content { + systems: Vec, +} + +impl Content { + pub fn new(cv: Vec) -> Result { + let mut content = Self { + systems: Vec::new(), + }; + + // TODO: locate bad files + + // These methods check intra-file consistency + for c in cv { + match c { + ContentType::System(v) => content.add_system(v)?, + }; + } + + return Ok(content); + } + + fn add_system(&mut self, toml: syntax::system::toml::SystemRoot) -> Result<()> { + self.systems.push(syntax::System::parse(toml)?); + return Ok(()); + } +} diff --git a/src/content/contenttype.rs b/src/content/contenttype.rs new file mode 100644 index 0000000..d73f037 --- /dev/null +++ b/src/content/contenttype.rs @@ -0,0 +1,30 @@ +use anyhow::Result; +use std::{fs::File, io::Read, path::Path}; + +use super::syntax; + +#[derive(Debug)] +pub enum ContentType { + System(syntax::system::toml::SystemRoot), +} + +// TODO: check content without loading game +impl ContentType { + pub fn try_parse(file_string: &str) -> Result> { + // TODO: More advanced parsing, read the whole top comment + let (first, _) = file_string.split_once("\n").unwrap(); + let type_spec = first[1..].trim(); // Remove hash + + return Ok(match type_spec { + "content type: system" => Some(Self::System(toml::from_str(&file_string)?)), + _ => None, + }); + } + + pub fn from_path(path: &Path) -> Result> { + let mut file_string = String::new(); + let _ = File::open(path)?.read_to_string(&mut file_string); + let file_string = file_string.trim(); + return Self::try_parse(&file_string); + } +} diff --git a/src/content/mod.rs b/src/content/mod.rs new file mode 100644 index 0000000..9cc6345 --- /dev/null +++ b/src/content/mod.rs @@ -0,0 +1,6 @@ +mod content; +mod contenttype; +mod syntax; + +pub use content::Content; +pub use contenttype::ContentType; diff --git a/src/content/syntax/mod.rs b/src/content/syntax/mod.rs new file mode 100644 index 0000000..57d8314 --- /dev/null +++ b/src/content/syntax/mod.rs @@ -0,0 +1,3 @@ +#![allow(dead_code)] +pub mod system; +pub use system::System; diff --git a/src/content/syntax/system.rs b/src/content/syntax/system.rs new file mode 100644 index 0000000..8ccacb9 --- /dev/null +++ b/src/content/syntax/system.rs @@ -0,0 +1,95 @@ +use anyhow::{bail, Result}; +use cgmath::Point2; +use std::collections::HashMap; + +use crate::physics::Pfloat; + +/// Toml file syntax +pub(in crate::content) mod toml { + use super::Pfloat; + use serde::Deserialize; + use std::collections::HashMap; + + #[derive(Debug, Deserialize)] + pub struct SystemRoot { + pub system: System, + pub object: HashMap, + } + + #[derive(Debug, Deserialize)] + pub struct System { + pub name: String, + } + + #[derive(Debug, Deserialize)] + pub struct Object { + pub sprite: String, + pub center: Center, + + #[serde(default)] + pub radius: Pfloat, + #[serde(default)] + pub angle: Pfloat, + } + + #[derive(Debug, Deserialize)] + #[serde(untagged)] + pub enum Center { + Label(String), + Coords([Pfloat; 2]), + } +} + +#[derive(Debug)] +pub struct System { + name: String, + objects: Vec, +} + +#[derive(Debug)] +struct Object { + sprite: String, + center: Point2, + radius: Pfloat, + angle: Pfloat, +} + +fn resolve_center( + objects: &HashMap, + obj: &toml::Object, +) -> Option> { + match &obj.center { + toml::Center::Label(s) => resolve_center(&objects, objects.get(s)?), + toml::Center::Coords(v) => Some(Point2::from(*v)), + } +} + +impl System { + pub fn parse(value: toml::SystemRoot) -> Result { + let mut objects = Vec::new(); + + for (_, obj) in &value.object { + let center = match resolve_center(&value.object, obj) { + Some(v) => v, + None => { + bail!( + "Failed to parse content file: could not resolve center label `{:?}`", + obj.center + ); + } + }; + + objects.push(Object { + sprite: obj.sprite.clone(), + center, + radius: obj.radius, + angle: obj.angle, + }); + } + + return Ok(Self { + name: value.system.name.clone(), + objects, + }); + } +} diff --git a/src/main.rs b/src/main.rs index ff516a0..0d8a053 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +mod content; mod doodad; mod inputstatus; mod physics; @@ -7,6 +8,8 @@ mod system; use anyhow::Result; use cgmath::{Deg, Point2}; +use std::time::Instant; +use walkdir::WalkDir; use winit::{ event::{ ElementState, Event, KeyboardInput, MouseButton, MouseScrollDelta, TouchPhase, @@ -160,8 +163,6 @@ impl Game { } } -use std::time::Instant; - pub async fn run() -> Result<()> { let event_loop = EventLoop::new(); let window = WindowBuilder::new().build(&event_loop).unwrap(); @@ -230,6 +231,20 @@ pub async fn run() -> Result<()> { } fn main() -> Result<()> { - pollster::block_on(run())?; + let mut raw_content = Vec::new(); + for e in WalkDir::new("content").into_iter().filter_map(|e| e.ok()) { + if e.metadata().unwrap().is_file() { + let c = crate::content::ContentType::from_path(e.path())?; + match c { + Some(c) => raw_content.push(c), + None => continue, + } + } + } + + let a = crate::content::Content::new(raw_content)?; + println!("{:?}", a); + + //pollster::block_on(run())?; return Ok(()); }