You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

83 lines
2.2 KiB
Rust

use bevy::{
asset::{AssetLoader, LoadContext, io::Reader},
prelude::*,
reflect::TypePath,
};
use serde::Deserialize;
use thiserror::Error;
#[derive(Asset, TypePath, Debug, Deserialize, Default, Clone)]
pub(crate) struct Monologue {
value: Vec<Vec<String>>,
}
impl Monologue {
pub fn get(&self, idx: usize) -> Option<&Vec<String>> {
self.value.get(idx)
}
}
#[derive(Default)]
struct MonologueLoader;
#[derive(Debug, Error)]
enum MonologueLoaderError {
#[error("Could not load asset: {0}")]
Io(#[from] std::io::Error),
#[error("Could not parse utf8")]
Utf8(#[from] std::string::FromUtf8Error),
}
impl AssetLoader for MonologueLoader {
type Asset = Monologue;
type Settings = ();
type Error = MonologueLoaderError;
async fn load(
&self,
reader: &mut dyn Reader,
_settings: &(),
_load_context: &mut LoadContext<'_>,
) -> Result<Self::Asset, Self::Error> {
let mut bytes: Vec<u8> = Vec::new();
reader.read_to_end(&mut bytes).await?;
let raw_string = String::from_utf8(bytes)?;
let value: Vec<Vec<String>> = raw_string
// First split on the '---' separators between batches
.split_terminator("---")
.map(|batch| {
batch
// Then split batches into newline-separated groups of text
.split_terminator("\n\n")
.filter_map(|line| {
// Filter out comments, empty lines, and extraneous newlines
(!line.starts_with("#") && !line.is_empty() && line != "\n")
// Trim the resulting dialog option
.then_some(line.trim().into())
})
.collect()
})
.filter(|sub: &Vec<String>| !sub.is_empty())
.collect();
info!("Monologue: {:#?}", value);
let thing = Monologue { value };
Ok(thing)
}
fn extensions(&self) -> &[&str] {
&["mono"]
}
}
pub struct MonologueAssetsPlugin;
impl Plugin for MonologueAssetsPlugin {
fn build(&self, app: &mut App) {
app.init_asset::<Monologue>()
.init_asset_loader::<MonologueLoader>();
}
}