From 2cd0c7d840a253bc0680f8b7739c7c57fcf2c98a Mon Sep 17 00:00:00 2001 From: Nobody Date: Wed, 2 Feb 2022 20:42:41 +0500 Subject: [PATCH] Implement Lua Scene loading --- .gitignore | 4 +- Cargo.toml | 1 + src/luamanager/lua_manager.rs | 122 ++++++++++++++++++++++ src/luamanager/mod.rs | 4 + src/luamanager/scene_config.rs | 178 +++++++++++++++++++++++++++++++++ src/main.rs | 2 + src/server/game_server.rs | 4 +- 7 files changed, 312 insertions(+), 3 deletions(-) create mode 100644 src/luamanager/lua_manager.rs create mode 100644 src/luamanager/mod.rs create mode 100644 src/luamanager/scene_config.rs diff --git a/.gitignore b/.gitignore index b922ff0..5da46ab 100644 --- a/.gitignore +++ b/.gitignore @@ -22,5 +22,5 @@ Cargo.lock # Local database database.db3* -# JSON files -/json/ +# Data files +/data/ diff --git a/Cargo.toml b/Cargo.toml index d503b58..3e38971 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ edition = "2018" kcp = { path = "../kcp" } mhycrypt = { path = "../mhycrypt" } proto = { path = "../proto" } +lua_serde = { path = "../lua_serde" } packet-processor-macro = { path = "packet-processor-macro" } packet-processor = { path = "packet-processor" } diff --git a/src/luamanager/lua_manager.rs b/src/luamanager/lua_manager.rs new file mode 100644 index 0000000..34ea5e9 --- /dev/null +++ b/src/luamanager/lua_manager.rs @@ -0,0 +1,122 @@ +use std::collections::HashMap; +use std::result::Result; + +use lua_serde::from_file; + +use super::scene_config::Group; +use super::scene_config::Block; +use super::scene_config::Scene; + +#[derive(Debug)] +struct InternalSceneData { + pub scene_id: u32, + pub scene: Scene, + pub blocks: HashMap, +} + +#[derive(Debug)] +struct InternalBlockData { + pub scene_id: u32, + pub block_id: u32, + pub block: Block, + pub groups: HashMap, +} + +#[derive(Debug)] +struct InternalGroupData { + pub scene_id: u32, + pub block_id: u32, + pub group_id: u32, + pub group: Group, + // No extra data here +} + +pub struct LuaManager { + scenes_data: HashMap, +} + +// TODO: Hack-y stuff! +macro_rules! scene_name { () => ("{}/Scene/{}/scene{}.lua")} +macro_rules! block_name { () => ("{}/Scene/{}/scene{}_block{}.lua")} +macro_rules! group_name { () => ("{}/Scene/{}/scene{}_group{}.lua")} + +impl LuaManager { + pub fn new(directory: &str) -> LuaManager { + let scenes_to_load = vec![3]; // TODO! + + let scenes = Self::load_scenes(directory, &scenes_to_load); + + LuaManager { + scenes_data: scenes, + } + } + + fn load_scenes(directory: &str, scenes_to_load: &Vec) -> HashMap { + scenes_to_load + .iter() + .map(|scene_id| (*scene_id, Self::load_scene(directory, *scene_id))) + .collect() + } + + fn load_scene(directory: &str, scene_id: u32) -> InternalSceneData { + let filename = format!(scene_name!(), directory, scene_id, scene_id); + + let scene: Scene = from_file(&filename).unwrap(); // TODO: error handling! + + let blocks = scene.blocks + .iter() + .map(|(key, block_id)| (*block_id, Self::load_block(directory, scene_id, *block_id))) + .collect(); + + InternalSceneData { + scene_id, + scene, + blocks, + } + } + + fn load_block(directory: &str, scene_id: u32, block_id: u32) -> InternalBlockData { + let filename = format!(block_name!(), directory, scene_id, scene_id, block_id); + let block: Block = from_file(&filename).unwrap(); // TODO: error handling! + + let groups = if false + { + // TODO: should be this! But some groups are missing + block.groups + .iter() + .map(|(key, group_info)| (group_info.id, Self::load_group(directory, scene_id, block_id, group_info.id).unwrap() /* Unwrap to make compiler happy*/)) + .collect() + } else { + let (groups, errors): (Vec<_>, Vec<_>) = block.groups + .iter() + .map(|(key, group_info)| (group_info.id, Self::load_group(directory, scene_id, block_id, group_info.id))) + .partition(|(group_id, result)| result.is_ok()); + + let groups = groups.into_iter().map(|(group_id, result)| (group_id, result.unwrap())).collect(); + let errors: Vec<_> = errors.into_iter().map(|(group_id, result)| (group_id, result.unwrap_err())).collect(); + + println!("Missing groups: {:?}", errors); + groups + }; + + InternalBlockData { + scene_id, + block_id, + block, + groups, + } + } + + fn load_group(directory: &str, scene_id: u32, block_id: u32, group_id: u32) -> Result { + let filename = format!(group_name!(), directory, scene_id, scene_id, group_id); + //let group: Group = from_file(&filename).unwrap(); // TODO: error handling! + let group: Group = from_file(&filename)?; + + Ok(InternalGroupData { + scene_id, + block_id, + group_id, + group, + }) + } +} \ No newline at end of file diff --git a/src/luamanager/mod.rs b/src/luamanager/mod.rs new file mode 100644 index 0000000..78f4a97 --- /dev/null +++ b/src/luamanager/mod.rs @@ -0,0 +1,4 @@ +mod lua_manager; +mod scene_config; + +pub use self::lua_manager::LuaManager; \ No newline at end of file diff --git a/src/luamanager/scene_config.rs b/src/luamanager/scene_config.rs new file mode 100644 index 0000000..937434d --- /dev/null +++ b/src/luamanager/scene_config.rs @@ -0,0 +1,178 @@ +use std::collections::HashMap; + +use serde::Deserialize; + +// sceneX.lua + +#[derive(Deserialize, PartialEq, Debug)] +pub struct Vector { + #[serde(default)] + pub x: T, + #[serde(default)] + pub y: T, + #[serde(default)] + pub z: T, +} + +#[derive(Deserialize, PartialEq, Debug)] +pub struct BlockRect { + pub min: Vector, + pub max: Vector, +} + +#[derive(Deserialize, PartialEq, Debug)] +pub struct SceneConfig { + pub born_rot: Vector, + pub born_pos: Vector, + pub begin_pos: Vector, + pub size: Vector, + #[serde(default)] + pub die_y: f32, +} + +#[derive(Deserialize, PartialEq, Debug)] +pub struct Scene { + pub blocks: HashMap, + #[serde(default)] + pub block_rects: HashMap, + #[serde(default)] + pub routes_config: HashMap, + #[serde(default)] + pub dummy_points: HashMap, + pub scene_config: SceneConfig, +} + +// sceneX_blockY.lua + +#[derive(Deserialize, PartialEq, Debug)] +pub struct Block { + pub groups: HashMap, +} + +#[derive(Deserialize, PartialEq, Debug)] +pub struct GroupInfo { + pub is_replaceable: Option, + #[serde(default)] + pub dynamic_load: bool, + pub id: u32, + pub area: Option, + pub pos: Vector, + pub business: Option, +} + +#[derive(Deserialize, PartialEq, Debug)] +pub struct ComplicatedBool { + pub version: u32, + pub value: bool, + pub new_bin_only: bool, +} + +#[derive(Deserialize, PartialEq, Debug)] +pub struct Business { + pub r#type: u32, +} + +// sceneX_groupZ.lua + +#[derive(Deserialize, PartialEq, Debug)] +pub struct Group { + pub init_config: Option, + #[serde(default)] + pub suites: HashMap, + + #[serde(default)] + pub npcs: HashMap, + #[serde(default)] + pub variables: HashMap, + #[serde(default)] + pub triggers: HashMap, + #[serde(default)] + pub regions: HashMap, + #[serde(default)] + pub gadgets: HashMap, + #[serde(default)] + pub monsters: HashMap, + + // MovePlatform - Function??? +} + +#[derive(Deserialize, PartialEq, Debug)] +pub struct Suite { + pub rand_weight: u32, + + #[serde(default)] + pub npcs: HashMap, + // Variables? + #[serde(default)] + pub triggers: HashMap, + #[serde(default)] + pub regions: HashMap, + #[serde(default)] + pub gadgets: HashMap, + #[serde(default)] + pub monsters: HashMap, +} + +#[derive(Deserialize, PartialEq, Debug)] +pub struct GroupInitConfig { + pub end_suite: Option, + //#[serde(default)] + pub rand_suite: bool, + pub suite: u32, +} + +#[derive(Deserialize, PartialEq, Debug)] +pub struct Variable { + pub name: String, + pub value: u32, + pub no_refresh: bool, +} + +#[derive(Deserialize, PartialEq, Debug)] +pub struct Monster { + pub rot: Vector, + pub pos: Vector, + pub config_id: u32, + pub level: u32, + pub monster_id: u32, +} + +#[derive(Deserialize, PartialEq, Debug)] +pub struct Npc { + pub rot: Vector, + pub pos: Vector, + pub config_id: u32, + pub npc_id: u32, + + pub area_id: Option, + pub room: Option, +} + +#[derive(Deserialize, PartialEq, Debug)] +pub struct Gadget { + pub rot: Vector, + pub pos: Vector, + pub config_id: u32, + pub level: u32, + pub gadget_id: u32, + + #[serde(default)] + pub drop_count: u32, + pub explore: Option, + #[serde(default)] + pub isOneoff: bool, + pub area_id: Option, + #[serde(default)] + pub persistent: bool, + pub chest_drop_id: Option, + #[serde(default)] + pub start_route: bool, + #[serde(default)] + pub is_use_point_array: bool, +} + +#[derive(Deserialize, PartialEq, Debug)] +pub struct ExploreInfo { + pub exp: u32, + pub name: String, +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index c895db2..bb1877b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,11 +9,13 @@ mod server; mod utils; mod dbmanager; mod jsonmanager; +mod luamanager; use server::NetworkServer; use server::DispatchServer; use dbmanager::DatabaseManager; use jsonmanager::JsonManager; +use luamanager::LuaManager; fn main() { pretty_env_logger::init(); diff --git a/src/server/game_server.rs b/src/server/game_server.rs index 56dbf9a..67dbb15 100644 --- a/src/server/game_server.rs +++ b/src/server/game_server.rs @@ -9,6 +9,7 @@ use crate::server::IpcMessage; use crate::DatabaseManager; use crate::JsonManager; +use crate::LuaManager; use crate::server::LoginManager; use std::sync::Arc; @@ -24,8 +25,9 @@ pub struct GameServer { impl GameServer { pub fn new(packets_to_process_rx: mpsc::Receiver, packets_to_send_tx: mpsc::Sender) -> GameServer { let db = Arc::new(DatabaseManager::new("sqlite://./database.db3")); - let jm = Arc::new(JsonManager::new("./json")); + let jm = Arc::new(JsonManager::new("./data/json")); let lm = LoginManager::new(db.clone(), jm.clone(), packets_to_send_tx.clone()); + let lum = Arc::new(LuaManager::new("./data/lua")); let gs = GameServer { packets_to_process_rx: packets_to_process_rx,