use std::collections::HashMap;
use std::fs::File;
use std::io::Read;
use std::num::NonZeroU32;
use std::path::Path;
use alligator_scripts::ScriptManager;
use alligator_sprites::SpriteManager;
use alligator_sys::{Renderer, RendererConfig, Window, WindowConfig, WindowEvent};
use serde::Deserialize;
use sha3::{Digest, Sha3_256};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
enum ScriptType {
Wasm,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
enum ConfigWindowMode {
Windowed,
BorderlessFullscreen,
}
#[derive(Debug, Clone, Deserialize)]
struct ConfigScript {
path: Box<Path>,
script_type: ScriptType,
hash: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
struct ConfigSprite {
texture: String,
x: f32,
y: f32,
z: f32,
}
#[derive(Debug, Clone, Deserialize)]
struct ConfigTexture {
size: usize,
path: Box<Path>,
}
#[derive(Debug, Clone, Deserialize)]
struct Scene {
initial_sprites: HashMap<String, ConfigSprite>,
initial_scripts: Vec<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct Config {
alligator_version: usize,
scenes: HashMap<String, Scene>,
textures: HashMap<String, ConfigTexture>,
scripts: HashMap<String, ConfigScript>,
default_scene: String,
sprite_manager_capacity: u32,
default_window_width: NonZeroU32,
default_window_height: NonZeroU32,
default_window_mode: ConfigWindowMode,
window_title: String,
vsync: bool,
}
fn sprite_manager(config: &Config) -> SpriteManager {
SpriteManager::with_capacity(config.sprite_manager_capacity as usize)
}
fn script_manager(config: &Config) -> ScriptManager {
let mut scripts = ScriptManager::new();
for (key, script) in config.scripts.iter() {
let path = script.path.clone();
let trusted = if let Some(hash) = &script.hash {
let mut bytes = Vec::new();
let mut msg = File::open(&path).unwrap();
msg.read_to_end(&mut bytes).unwrap();
let mut hasher = Sha3_256::new();
hasher.update(bytes);
let result = hasher.finalize();
hash.as_bytes() == &result[..]
} else {
false
};
scripts
.add_wasm_script(key.clone().into_boxed_str(), path, trusted)
.unwrap();
}
scripts
}
fn window(config: &Config) -> Window {
let config = WindowConfig {
title: config.window_title.clone(),
default_width: config.default_window_width.get(),
default_height: config.default_window_height.get(),
default_x: 100,
default_y: 100,
borderless_fullscreen: config.default_window_mode == ConfigWindowMode::BorderlessFullscreen,
visible: false,
};
Window::new(config)
}
fn renderer(config: &Config, window: &Window) -> Renderer {
let config = RendererConfig {
width: config.default_window_width.get(),
height: config.default_window_height.get(),
instance_capacity: config.sprite_manager_capacity,
fullscreen: false,
vsync: config.vsync,
};
Renderer::new(window, config)
}
fn main() {
std::env::set_current_dir(std::env::current_exe().unwrap().parent().unwrap()).unwrap();
let config = File::open("game.json").unwrap();
let config: Config = serde_json::from_reader(config).unwrap();
let sprites = sprite_manager(&config);
let scripts = script_manager(&config);
let mut window = window(&config);
window.wait_for_resume();
let mut renderer = renderer(&config, &window);
window.set_visible(true);
window.run(move |window, event| match event {
Some(WindowEvent::RedrawRequest) => {
renderer.render_frame();
}
Some(WindowEvent::CloseRequest) => {
std::process::exit(0);
}
Some(_) => (),
None => window.request_redraw(),
})
}
|