forked from wickedwaifus/wicked-waifus-rs
219 lines
6.3 KiB
Rust
219 lines
6.3 KiB
Rust
use std::fs::File;
|
|
use std::io::BufReader;
|
|
|
|
use paste::paste;
|
|
|
|
pub use level_entity_config::LevelEntityConfigData;
|
|
pub use misc_data::*;
|
|
|
|
pub mod node_data;
|
|
pub mod pb_components;
|
|
pub mod text_map_data;
|
|
|
|
mod misc_data;
|
|
|
|
#[derive(thiserror::Error, Debug)]
|
|
pub enum LoadDataError {
|
|
#[error("I/O error: {0}")]
|
|
Io(#[from] std::io::Error),
|
|
#[error("Failed to parse json: {0}")]
|
|
Json(#[from] serde_json::Error),
|
|
}
|
|
|
|
macro_rules! json_data {
|
|
($($table_type:ident;)*) => {
|
|
$(paste! {
|
|
mod [<$table_type:snake>];
|
|
pub use [<$table_type:snake>]::[<$table_type Data>];
|
|
})*
|
|
|
|
$(paste! {
|
|
pub mod [<$table_type:snake _data>] {
|
|
use std::sync::OnceLock;
|
|
type Data = super::[<$table_type Data>];
|
|
pub(crate) static TABLE: OnceLock<Vec<Data>> = OnceLock::new();
|
|
|
|
pub fn iter() -> std::slice::Iter<'static, Data> {
|
|
TABLE.get().unwrap().iter()
|
|
}
|
|
}
|
|
})*
|
|
|
|
fn load_json_data(base_path: &str) -> Result<(), LoadDataError> {
|
|
$(paste! {
|
|
let path = format!("{}/{}.json", base_path, stringify!($table_type));
|
|
tracing::debug!("Loading data started: {path}");
|
|
let file = File::open(&path)?;
|
|
let reader = BufReader::new(file);
|
|
let _ = [<$table_type:snake _data>]::TABLE.set(serde_json::from_reader(reader)?);
|
|
tracing::info!("Loading data finished: {path}");
|
|
})*
|
|
|
|
Ok(())
|
|
}
|
|
};
|
|
}
|
|
|
|
macro_rules! json_hash_table_data {
|
|
($($table_type:ident, $key_param:expr, $key_type:ty;)*) => {
|
|
$(paste! {
|
|
mod [<$table_type:snake>];
|
|
pub use [<$table_type:snake>]::[<$table_type Data>];
|
|
})*
|
|
|
|
$(paste! {
|
|
pub mod [<$table_type:snake _data>] {
|
|
use std::collections::HashMap;
|
|
use std::sync::OnceLock;
|
|
|
|
pub(crate) type Data = super::[<$table_type Data>];
|
|
pub(crate) static TABLE: OnceLock<HashMap<$key_type, Data>> = OnceLock::new();
|
|
|
|
pub fn iter() -> std::collections::hash_map::Iter<'static, $key_type, Data> {
|
|
TABLE.get().unwrap().iter()
|
|
}
|
|
|
|
pub fn get(k: &$key_type) -> Option<&'static Data> {
|
|
TABLE.get().unwrap().get(k)
|
|
}
|
|
}
|
|
})*
|
|
|
|
fn load_json_hash_table_data(base_path: &str) -> Result<(), LoadDataError> {
|
|
$(paste! {
|
|
let path = format!("{}/{}.json", base_path, stringify!($table_type));
|
|
tracing::debug!("Loading data started: {path}");
|
|
let file = File::open(&path)?;
|
|
let reader = BufReader::new(file);
|
|
// Key.clone() is required for String keys, for other types like ints, it doesn't
|
|
// have any effect since clone is *value
|
|
let _ = [<$table_type:snake _data>]::TABLE.set(
|
|
serde_json::from_reader::<BufReader<File>, Vec<[<$table_type:snake _data>]::Data>>(reader)?
|
|
.into_iter()
|
|
.map(|element| (element.$key_param.clone(), element))
|
|
.collect::<std::collections::HashMap<_, _>>()
|
|
);
|
|
tracing::info!("Loading data finished: {path}");
|
|
})*
|
|
|
|
Ok(())
|
|
}
|
|
};
|
|
}
|
|
|
|
pub fn load_all_json_data(base_path: &str) -> Result<(), LoadDataError> {
|
|
load_json_data(base_path)?;
|
|
load_json_hash_table_data(base_path)?;
|
|
load_json_entity_level_config_data(base_path)?;
|
|
Ok(())
|
|
}
|
|
|
|
json_data! {
|
|
Achievement;
|
|
AdventureTask;
|
|
Area;
|
|
BaseProperty;
|
|
CalabashDevelopReward;
|
|
CalabashLevel;
|
|
Damage;
|
|
DungeonDetection;
|
|
ExchangeReward;
|
|
ExchangeShared;
|
|
ExploreProgress;
|
|
ExploreTools;
|
|
FavorGoods;
|
|
FavorLevel;
|
|
FavorStory;
|
|
FavorWord;
|
|
ForgeFormula;
|
|
FunctionCondition;
|
|
Gacha;
|
|
GachaPool;
|
|
GachaViewInfo;
|
|
GuideGroup;
|
|
GuideTutorial;
|
|
InstanceDungeon;
|
|
ItemExchangeContent;
|
|
// LevelPlayData;
|
|
LevelPlayNodeData;
|
|
LivenessTask;
|
|
LordGym;
|
|
MonsterDetection;
|
|
MonsterPropertyGrowth;
|
|
Motion;
|
|
QuestNodeData;
|
|
ResonanceAmplification;
|
|
ResonantChain;
|
|
RoleBreach;
|
|
RoleExpItem;
|
|
RoleInfo;
|
|
RoleLevelConsume;
|
|
RolePropertyGrowth;
|
|
RoleSkin;
|
|
SilentAreaDetection;
|
|
SynthesisFormula;
|
|
Teleporter;
|
|
WeaponBreach;
|
|
WeaponConf;
|
|
WeaponExpItem;
|
|
WeaponLevel;
|
|
WeaponPropertyGrowth;
|
|
WeaponReson;
|
|
}
|
|
|
|
json_hash_table_data! {
|
|
AiBase, id, i32;
|
|
AiStateMachineConfig, id, String;
|
|
BlueprintConfig, blueprint_type, String;
|
|
DragonPool, id, i32;
|
|
DropPackage, id, i32;
|
|
TemplateConfig, blueprint_type, String;
|
|
SummonCfg, blueprint_type, String;
|
|
Buff, id, i64;
|
|
}
|
|
mod level_entity_config;
|
|
|
|
pub mod level_entity_config_data {
|
|
use std::collections::HashMap;
|
|
use std::sync::OnceLock;
|
|
|
|
pub(crate) type Data = super::LevelEntityConfigData;
|
|
pub(crate) static TABLE: OnceLock<HashMap<String, Data>> = OnceLock::new();
|
|
|
|
pub fn iter() -> std::collections::hash_map::Iter<'static, String, Data> {
|
|
TABLE.get().unwrap().iter()
|
|
}
|
|
|
|
pub fn get(map_id: i32, entity_id: i64) -> Option<&'static Data> {
|
|
TABLE
|
|
.get()
|
|
.unwrap()
|
|
.get(&create_key_internal(map_id, entity_id))
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn create_key(element: &Data) -> String {
|
|
create_key_internal(element.map_id, element.entity_id)
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn create_key_internal(map_id: i32, entity_id: i64) -> String {
|
|
format!("{}_{}", map_id, entity_id)
|
|
}
|
|
}
|
|
|
|
fn load_json_entity_level_config_data(base_path: &str) -> Result<(), LoadDataError> {
|
|
let path = format!("{}/LevelEntityConfig.json", base_path);
|
|
tracing::debug!("Loading data started: {path}");
|
|
let file = File::open(&path)?;
|
|
let reader = BufReader::new(file);
|
|
let _ = level_entity_config_data::TABLE.set(
|
|
serde_json::from_reader::<BufReader<File>, Vec<level_entity_config_data::Data>>(reader)?
|
|
.into_iter()
|
|
.map(|element| (level_entity_config_data::create_key(&element), element))
|
|
.collect::<std::collections::HashMap<_, _>>(),
|
|
);
|
|
tracing::info!("Loading data finished: {path}");
|
|
|
|
Ok(())
|
|
}
|