Ongoing changes for 2.2.2

Reviewed-on: WutheringSlaves/wicked-waifus-rs#3
This commit is contained in:
xavo95 2025-03-09 09:10:08 +00:00
parent c0b872ede4
commit ab868a158a
165 changed files with 10782 additions and 1183 deletions

2
.gitignore vendored
View file

@ -7,3 +7,5 @@
/gameserver.toml
/wicked-waifus-protocol-internal/generated
/wicked-waifus-protocol/generated
/data/assets/config-server
/data/assets/game-data

6
.gitmodules vendored
View file

@ -1,6 +0,0 @@
[submodule "data/assets/config-server"]
path = data/assets/config-server
url = https://git.xeondev.com/wickedwaifus/wicked-waifus-config-server-files.git
[submodule "data/assets/game-data"]
path = data/assets/game-data
url = https://git.xeondev.com/wickedwaifus/wicked-waifus-data.git

719
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
[workspace]
members = ["wicked-waifus-commons", "wicked-waifus-config-server", "wicked-waifus-hotpatch-server", "wicked-waifus-login-server", "wicked-waifus-gateway-server", "wicked-waifus-gateway-server/kcp", "wicked-waifus-database", "wicked-waifus-http", "wicked-waifus-protokey", "wicked-waifus-protocol-internal", "wicked-waifus-game-server", "wicked-waifus-network", "wicked-waifus-data"]
members = ["wicked-waifus-asset-updater", "wicked-waifus-commons", "wicked-waifus-config-server", "wicked-waifus-hotpatch-server", "wicked-waifus-login-server", "wicked-waifus-gateway-server", "wicked-waifus-gateway-server/kcp", "wicked-waifus-database", "wicked-waifus-http", "wicked-waifus-protokey", "wicked-waifus-protocol-internal", "wicked-waifus-game-server", "wicked-waifus-network", "wicked-waifus-data"]
resolver = "2"
[workspace.package]
@ -47,6 +47,7 @@ tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
# Internal
kcp = { path = "wicked-waifus-gateway-server/kcp" }
wicked-waifus-asset-updater = { path = "wicked-waifus-asset-updater" }
wicked-waifus-commons = { path = "wicked-waifus-commons" }
wicked-waifus-http = { path = "wicked-waifus-http" }
wicked-waifus-data = { path = "wicked-waifus-data" }

@ -1 +0,0 @@
Subproject commit 146c610632c8d9c3948c6a64ffc6cfe0258bcced

@ -1 +0,0 @@
Subproject commit c00cdaefddc9c81ae6d79589c31ee169d59f2382

View file

@ -0,0 +1,12 @@
[package]
name = "wicked-waifus-asset-updater"
edition = "2021"
version.workspace = true
[dependencies]
git2 = "0.20.0"
ureq = "3.0.5"
zip-extract = "0.2.1"
tracing.workspace = true
thiserror.workspace = true

View file

@ -0,0 +1,145 @@
use std::io::{Cursor, Read, Write};
use std::path::Path;
use git2::{FetchOptions, RemoteCallbacks, Repository};
use git2::build::RepoBuilder;
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("UReq error: {0}")]
UReq(#[from] ureq::Error),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("ZipExtract error: {0}")]
ZipExtract(#[from] zip_extract::ZipExtractError),
#[error("Git error: {0}")]
Git(#[from] git2::Error),
#[error("Option conversion error")]
Option(),
}
pub fn update_from_releases<T: AsRef<str> + std::fmt::Display>(object_url: T,
target_folder: T,
max_buffer: usize) -> Result<(), Error> {
let path = Path::new(target_folder.as_ref());
std::fs::create_dir_all(path)?;
let version = path.join("version.txt");
let new_version = object_url.as_ref();
if version.exists() {
tracing::debug!("Version marker exists, checking version");
let old_version = std::fs::read_to_string(&version)?;
if old_version.eq(new_version) {
tracing::debug!("The version to download is the current one, skipping ...");
return Ok(())
} else {
tracing::debug!("The old version is: {old_version}, new version: {new_version}")
}
} else {
tracing::debug!("Version marker doesn't exist, fetching resources for first time")
}
tracing::debug!("Starting the download of static assets from {object_url}");
let mut bytes: Vec<u8> = Vec::with_capacity(max_buffer);
let agent = ureq::config::Config::builder()
.timeout_send_body(Some(std::time::Duration::from_secs(60)))
.timeout_recv_body(Some(std::time::Duration::from_secs(60)))
.build()
.new_agent();
let response = agent.get(new_version).call()?;
response.into_body().as_reader().read_to_end(&mut bytes)?;
tracing::debug!("Downloading assets from: {object_url} finished, extracting into {target_folder}");
zip_extract::extract(Cursor::new(bytes), path, true)?;
tracing::debug!("Resources extracted");
let mut file = std::fs::File::create(&version)?;
file.write_all(new_version.as_bytes())?;
Ok(())
}
pub fn clone_or_update_repository<T: AsRef<str> + std::fmt::Display>(repository_url: T,
repository_path: T,
ref_name: T,
discard_local_changes: bool) -> Result<(), Error> {
// Open existing repository or clone if not existing
let path = Path::new(repository_path.as_ref());
let repository = match path.exists() {
true => {
tracing::debug!("Path {repository_path} exists, opening repository");
Repository::open(repository_path.as_ref())
}
false => clone_repository(repository_url.as_ref(), path)
}?;
// TODO: Fetch remote updates????
// Get reference
let (object, reference) = repository.revparse_ext(ref_name.as_ref())?;
tracing::debug!("Reference {ref_name} found in repository");
let update_needed = match &reference {
Some(reference) => repository.head()?.eq(reference),
None => repository.head()?.target().ok_or(Error::Option())?.eq(&object.id()),
};
// If we are already in commit, no need to modify anything
if update_needed {
// Discard all local changes
if discard_local_changes {
tracing::debug!("discard_local_changes was set to true, changes will be discarded");
repository.checkout_head(None)?;
} else {
tracing::warn!("discard_local_changes was set to false, changes will be kept");
}
// Checkout required remote
repository.checkout_tree(&object, None)?;
// Checkout the needed commit
match reference {
Some(repo_reference) => repository.set_head(repo_reference.name().unwrap())?,
None => repository.set_head_detached(object.id())?,
}
tracing::debug!("Repository has been updated to {ref_name}");
} else {
tracing::debug!("Repository is already at the desired reference, no update needed");
};
Ok(())
}
fn clone_repository(repository_url: &str, path: &Path) -> Result<Repository, git2::Error> {
tracing::debug!(
"Path {path:?} doesn't exists, cloning repository at {repository_url}"
);
let mut remote_callbacks = RemoteCallbacks::new();
remote_callbacks.sideband_progress(|data| {
tracing::debug!("remote: {}", std::str::from_utf8(data).unwrap());
std::io::stdout().flush().unwrap();
true
});
remote_callbacks.transfer_progress(|stats| {
if stats.received_objects() == stats.total_objects() {
tracing::debug!(
"Resolving deltas {}/{}\r",
stats.indexed_deltas(),
stats.total_deltas()
);
} else if stats.total_objects() > 0 {
tracing::debug!(
"Received {}/{} objects ({}) in {} bytes\r",
stats.received_objects(),
stats.total_objects(),
stats.indexed_objects(),
stats.received_bytes()
);
}
std::io::stdout().flush().unwrap();
true
});
let mut fetch_options = FetchOptions::new();
fetch_options.remote_callbacks(remote_callbacks);
let result = RepoBuilder::new()
.fetch_options(fetch_options)
.clone(repository_url, path);
result
}

View file

@ -1,5 +1,17 @@
use std::time::{SystemTime, UNIX_EPOCH};
const SECONDS_PER_MINUTE: u64 = 60;
const SECONDS_PER_HOUR: u64 = 60 * SECONDS_PER_MINUTE;
const SECONDS_PER_DAY: u64 = 24 * SECONDS_PER_HOUR;
pub fn unix_days() -> i32 {
(SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs()
/ SECONDS_PER_DAY) as i32
}
pub fn unix_timestamp() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)

View file

@ -18,5 +18,6 @@ anyhow.workspace = true
tracing.workspace = true
# Internal
wicked-waifus-asset-updater.workspace = true
wicked-waifus-commons.workspace = true
wicked-waifus-http.workspace = true

View file

@ -8,3 +8,8 @@ iv = "fprc5lBWADQB7tim0R2JxQ=="
[serve]
serve_web_path = "/"
serve_dir_path = "data/assets/config-server"
[asset_config]
repository_url = "https://git.xeondev.com/wickedwaifus/wicked-waifus-config-server-files.git"
reference = "4d51547b78"
discard_local_changes = true

View file

@ -15,11 +15,19 @@ pub struct ServeConfig {
pub serve_dir_path: String,
}
#[derive(Deserialize)]
pub struct AssetConfig {
pub repository_url: String,
pub reference: String,
pub discard_local_changes: bool,
}
#[derive(Deserialize)]
pub struct ServerConfig {
pub network: NetworkSettings,
pub encryption: AesSettings,
pub serve: ServeConfig,
pub asset_config: Option<AssetConfig>,
}
impl TomlConfig for ServerConfig {
@ -34,6 +42,15 @@ async fn main() -> Result<()> {
::wicked_waifus_commons::splash::print_splash();
::wicked_waifus_commons::logging::init_axum(::tracing::Level::DEBUG);
if let Some(asset_config) = &CONFIG.asset_config {
wicked_waifus_asset_updater::clone_or_update_repository(
&asset_config.repository_url,
&CONFIG.serve.serve_dir_path,
&asset_config.reference,
asset_config.discard_local_changes,
).unwrap();
}
tracing::debug!(
"Serving files from {} at {}",
&CONFIG.serve.serve_web_path,

View file

@ -3,9 +3,13 @@ name = "wicked-waifus-data"
edition = "2021"
version.workspace = true
[features]
strict_json_fields = []
[dependencies]
serde.workspace = true
serde_json.workspace = true
serde_repr.workspace = true
paste.workspace = true
thiserror.workspace = true
tracing.workspace = true

View file

@ -0,0 +1,21 @@
use serde::Deserialize;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct AchievementData {
pub id: i32,
pub group_id: i32,
pub level: i32,
#[cfg(feature = "strict_json_fields")]
pub name: String,
#[cfg(feature = "strict_json_fields")]
pub desc: String,
#[cfg(feature = "strict_json_fields")]
pub icon_path: String,
pub override_drop_id: i32,
pub hidden: bool,
pub next_link: i32,
pub client_trigger: bool,
pub third_party_trophy_id: i32,
}

View file

@ -1,15 +1,19 @@
#[cfg(feature = "strict_json_fields")]
use std::collections::HashMap;
use serde::Deserialize;
#[derive(Debug, Deserialize, Clone)]
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct AdventureTaskData {
pub id: i32,
pub chapter_id: i32,
#[cfg(feature = "strict_json_fields")]
pub task_text: String,
pub record_id: Vec<i32>,
pub need_progress: i32,
pub drop_ids: i32,
pub path_id: i32,
#[cfg(feature = "strict_json_fields")]
pub jump_to: HashMap<String, String>,
}

View file

@ -0,0 +1,41 @@
use serde::Deserialize;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct SubBehaviorConfigs {
#[cfg(feature = "strict_json_fields")]
pub ai_alert: Option<String>,
#[cfg(feature = "strict_json_fields")]
pub ai_base_skill: Option<String>,
#[cfg(feature = "strict_json_fields")]
pub ai_battle_wander: Option<String>,
#[cfg(feature = "strict_json_fields")]
pub ai_flee: Option<String>,
#[cfg(feature = "strict_json_fields")]
pub ai_hate: Option<String>,
#[cfg(feature = "strict_json_fields")]
pub ai_patrol: Option<String>,
#[cfg(feature = "strict_json_fields")]
pub ai_sense: Option<String>,
#[cfg(feature = "strict_json_fields")]
pub ai_wander: Option<String>,
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct AiBaseData {
pub id: i32,
pub state_machine: String,
#[cfg(feature = "strict_json_fields")]
pub ai_controller: String,
#[cfg(feature = "strict_json_fields")]
pub behavior_tree: String,
#[cfg(feature = "strict_json_fields")]
pub sub_behavior_configs: SubBehaviorConfigs,
#[cfg(feature = "strict_json_fields")]
pub team: bool,
#[cfg(feature = "strict_json_fields")]
pub monster_type: i32,
}

View file

@ -0,0 +1,10 @@
use serde::Deserialize;
use crate::StateMachineJson;
#[derive(Clone, Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct AiStateMachineConfigData {
pub id: String,
pub state_machine_json: StateMachineJson,
}

View file

@ -1,15 +1,19 @@
use std::collections::HashMap;
use serde::Deserialize;
#[derive(Debug, Deserialize, Clone)]
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct AreaData {
pub area_id: i32,
pub level: i32,
pub country_id: i32,
pub delivery_mark_id: i32,
#[cfg(feature = "strict_json_fields")]
pub area_name: String,
pub map_config_id: i32,
pub dungeon_id: i32,
#[cfg(feature = "strict_json_fields")]
pub title: String,
pub father: i32,
pub tag: Vec<i32>,
@ -22,9 +26,10 @@ pub struct AreaData {
pub wu_yin_qu_id: i32,
pub state_id: i32,
pub atmosphere_id: i32,
#[cfg(feature = "strict_json_fields")]
pub edge_wall_name: String,
pub delivery_mark_type: i32,
pub sort_index: i32,
pub enter_area_tags: HashMap<String, i32>,
pub leave_area_tags: HashMap<String, i32>,
pub enter_area_tags: HashMap<i32, i32>,
pub leave_area_tags: HashMap<i32, i32>,
}

View file

@ -1,6 +1,7 @@
use serde::Deserialize;
#[derive(Deserialize)]
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct BasePropertyData {
pub id: i32,

View file

@ -0,0 +1,19 @@
use serde::Deserialize;
use crate::{EntityLogic, EntityType};
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct BlueprintConfigData {
pub id: i32,
pub blueprint_type: String,
pub entity_type: EntityType,
pub entity_logic: EntityLogic,
#[cfg(feature = "strict_json_fields")]
pub model_id: i32,
#[cfg(feature = "strict_json_fields")]
pub half_height: i32,
#[cfg(feature = "strict_json_fields")]
pub track_height: i32,
}

View file

@ -0,0 +1,22 @@
use serde::Deserialize;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct CalabashDevelopRewardData {
pub monster_id: i32,
pub develop_condition: Vec<i32>,
pub monster_info_id: i32,
pub all_exp: i32,
pub sort_id: i32,
pub monster_probe_id: i32,
#[cfg(feature = "strict_json_fields")]
pub hand_book_bp: String,
pub monster_body_type: i32,
#[cfg(feature = "strict_json_fields")]
pub hand_book_camera: String,
#[cfg(feature = "strict_json_fields")]
pub monster_number: String,
pub interaction_radius: i32,
pub is_show: bool,
}

View file

@ -0,0 +1,24 @@
use std::collections::HashMap;
use serde::Deserialize;
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct CalabashLevelData {
pub level: i32,
pub level_up_exp: i32,
pub level_up_condition: i32,
pub temp_catch_gain: i32,
pub buff_ids: Vec<i32>,
#[cfg(feature = "strict_json_fields")]
pub buff_description: String,
#[cfg(feature = "strict_json_fields")]
pub level_up_description: String,
#[cfg(feature = "strict_json_fields")]
pub quality_description: String,
pub buff_description_map: HashMap<i32, i32>,
pub cost: i32,
pub reward_id: i32,
pub quality_drop_weight: HashMap<i32, i32>,
}

View file

@ -0,0 +1,43 @@
use serde::Deserialize;
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct DamageData {
pub id: i64,
pub calculate_type: i32,
pub element: i32,
pub damage_text_type: i32,
pub payload_id: i32,
pub r#type: i32,
pub sub_type: Vec<i32>,
pub smash_type: i32,
pub cure_base_value: Vec<i32>,
pub related_property: i32,
pub rate_lv: Vec<i32>,
pub hardness_lv: Vec<i32>,
pub tough_lv: Vec<i32>,
pub energy: Vec<i32>,
pub special_energy1: Vec<i32>,
pub special_energy2: Vec<i32>,
pub special_energy3: Vec<i32>,
pub special_energy4: Vec<i32>,
pub element_power_type: i32,
pub element_power: Vec<i32>,
pub formula_type: i32,
pub formula_param1: Vec<i32>,
pub formula_param2: Vec<i32>,
pub formula_param3: Vec<i32>,
pub formula_param4: Vec<i32>,
pub formula_param5: Vec<i32>,
pub formula_param6: Vec<i32>,
pub formula_param7: Vec<i32>,
pub formula_param8: Vec<i32>,
pub formula_param9: Vec<i32>,
pub formula_param10: Vec<i32>,
pub immune_type: i32,
pub percent0: Vec<i32>,
pub percent1: Vec<i32>,
pub fluctuation_lower: Vec<i32>,
pub fluctuation_upper: Vec<i32>,
}

View file

@ -1,6 +1,7 @@
use serde::Deserialize;
#[derive(Debug, Deserialize, Clone)]
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct DragonPoolData {
pub id: i32,

View file

@ -0,0 +1,14 @@
use std::collections::HashMap;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct DropPackageData {
pub id: i32,
pub show_bg: bool,
#[cfg(feature = "strict_json_fields")]
pub title: String,
pub drop_plan: i32,
pub drop_preview: HashMap<i32, i32>,
}

View file

@ -0,0 +1,48 @@
use std::collections::HashMap;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct DungeonDetectionData {
pub id: i32,
pub dungeon_id: i32,
pub name: String,
pub role_id: i32,
pub guide_id: i32,
#[cfg(feature = "strict_json_fields")]
pub level_play_list: Vec<Option<serde_json::Value>>,
#[cfg(feature = "strict_json_fields")]
pub instance_sub_type_description: String,
pub type_description1: i32,
pub secondary: i32,
pub mat_type: i32,
#[cfg(feature = "strict_json_fields")]
pub type_description2: String,
#[cfg(feature = "strict_json_fields")]
pub attributes_description_lock: String,
#[cfg(feature = "strict_json_fields")]
pub attributes_description_unlock: String,
#[cfg(feature = "strict_json_fields")]
pub big_icon: String,
#[cfg(feature = "strict_json_fields")]
pub icon: String,
#[cfg(feature = "strict_json_fields")]
pub lock_big_icon: String,
#[cfg(feature = "strict_json_fields")]
pub temporary_icon_un_lock: String,
#[cfg(feature = "strict_json_fields")]
pub temporary_iconlock: String,
pub show_reward: i32,
pub show_reward_map: HashMap<String, i32>,
pub begin_time_stamp: i32,
pub pre_open_id: i32,
pub lock_con: i32,
#[cfg(feature = "strict_json_fields")]
pub phantom_id: Vec<Option<serde_json::Value>>,
pub sub_dungeon_id: i32,
pub sort_id: i32,
#[cfg(feature = "strict_json_fields")]
pub new_content: String,
}

View file

@ -0,0 +1,15 @@
use std::collections::HashMap;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct ExchangeRewardData {
pub id: i32,
pub shared_id: i32,
pub max_count: i32,
pub cost: HashMap<i32, i32>,
pub reward_id: HashMap<i32, i32>,
pub preview_reward: HashMap<i32, i32>,
}

View file

@ -0,0 +1,13 @@
use std::collections::HashMap;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct ExchangeSharedData {
pub id: i32,
pub max_count: i32,
pub cost: HashMap<i32, i32>,
pub reset_time_id: i32,
}

View file

@ -0,0 +1,26 @@
use std::collections::HashMap;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct ExploreProgressData {
pub id: i32,
pub area: i32,
pub explore_type: i32,
pub sub_type_score: HashMap<i32, i32>,
pub phantom_skill_id: i32,
#[cfg(feature = "strict_json_fields")]
pub unlock_text_id: String,
#[cfg(feature = "strict_json_fields")]
pub lock_text_id: String,
pub unlock_condition: i32,
#[cfg(feature = "strict_json_fields")]
pub special_player_map: HashMap<i32, i32>,
pub is_recommend: bool,
pub is_show_progress: bool,
pub is_show_track: bool,
#[cfg(feature = "strict_json_fields")]
pub special_player_desc: String,
}

View file

@ -3,6 +3,7 @@ use std::collections::HashMap;
use serde::Deserialize;
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct ExploreToolsData {
pub phantom_skill_id: i32,

View file

@ -0,0 +1,24 @@
use serde::Deserialize;
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct FavorGoodsData {
pub id: i32,
pub role_id: i32,
pub sort: i32,
#[cfg(feature = "strict_json_fields")]
pub title: String,
#[cfg(feature = "strict_json_fields")]
pub content: String,
#[cfg(feature = "strict_json_fields")]
pub pic: String,
pub cond_group_id: i32,
pub r#type: i32,
#[cfg(feature = "strict_json_fields")]
pub motion_img: String,
#[cfg(feature = "strict_json_fields")]
pub ani_blueprint: String,
#[cfg(feature = "strict_json_fields")]
pub ani_montage: String,
}

View file

@ -0,0 +1,9 @@
use serde::Deserialize;
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct FavorLevelData {
pub level: i32,
pub level_up_exp: i32,
}

View file

@ -0,0 +1,22 @@
use serde::Deserialize;
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct FavorStoryData {
pub id: i32,
pub role_id: i32,
pub sort: i32,
#[cfg(feature = "strict_json_fields")]
pub title: String,
#[cfg(feature = "strict_json_fields")]
pub content: String,
pub cond_group_id: i32,
pub r#type: i32,
#[cfg(feature = "strict_json_fields")]
pub motion_img: String,
#[cfg(feature = "strict_json_fields")]
pub ani_blueprint: String,
#[cfg(feature = "strict_json_fields")]
pub ani_montage: String,
}

View file

@ -0,0 +1,36 @@
use serde::Deserialize;
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct FavorWordData {
pub id: i32,
pub role_id: i32,
pub r#type: i32,
pub sort: i32,
#[cfg(feature = "strict_json_fields")]
pub title: String,
#[cfg(feature = "strict_json_fields")]
pub content: String,
#[cfg(feature = "strict_json_fields")]
pub voice: String,
#[cfg(feature = "strict_json_fields")]
#[serde(rename = "CVCn")]
pub cv_cn: String,
#[cfg(feature = "strict_json_fields")]
#[serde(rename = "CVJp")]
pub cv_jp: String,
#[cfg(feature = "strict_json_fields")]
#[serde(rename = "CVEn")]
pub cv_en: String,
#[cfg(feature = "strict_json_fields")]
#[serde(rename = "CVKo")]
pub cv_ko: String,
pub cond_group_id: i32,
#[cfg(feature = "strict_json_fields")]
pub motion_img: String,
#[cfg(feature = "strict_json_fields")]
pub ani_blueprint: String,
#[cfg(feature = "strict_json_fields")]
pub ani_montage: String,
}

View file

@ -0,0 +1,22 @@
use serde::Deserialize;
use crate::ConsumeItem;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct ForgeFormulaData {
pub id: i32,
pub formula_item_id: i32,
pub item_id: i32,
pub type_id: i32,
pub unlock: bool,
pub sort_id: i32,
#[cfg(feature = "strict_json_fields")]
pub name: String,
pub consume_items: Vec<ConsumeItem>,
#[cfg(feature = "strict_json_fields")]
pub forge_content: String,
#[cfg(feature = "strict_json_fields")]
pub background: String,
pub role_list: Vec<i32>,
}

View file

@ -1,10 +1,25 @@
use serde::Deserialize;
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct FunctionConditionData {
pub function_id: i32,
#[cfg(feature = "strict_json_fields")]
pub name: String,
pub is_on: bool,
pub open_condition_id: i32,
#[cfg(feature = "strict_json_fields")]
#[serde(rename = "ShowUIType")]
pub show_ui_type: i32,
#[cfg(feature = "strict_json_fields")]
pub delay: i32,
#[cfg(feature = "strict_json_fields")]
pub title: String,
#[cfg(feature = "strict_json_fields")]
pub desc: String,
#[cfg(feature = "strict_json_fields")]
pub icon: String,
#[cfg(feature = "strict_json_fields")]
pub icon_sprite: String,
}

View file

@ -1,6 +1,7 @@
use serde::Deserialize;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct GachaData {
pub id: i32,

View file

@ -1,6 +1,7 @@
use serde::Deserialize;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct GachaPoolData {
pub id: i32,

View file

@ -2,20 +2,34 @@ use serde::Deserialize;
use crate::GachaViewTypeInfoId;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct GachaViewInfoData {
pub id: i32,
pub r#type: GachaViewTypeInfoId,
pub summary_title: String,
pub summary_describe: String,
// TODO: Effect path
pub theme_color: String,
#[cfg(feature = "strict_json_fields")]
pub effect_location: RawVectorData,
#[cfg(feature = "strict_json_fields")]
pub effect_path: String,
#[cfg(feature = "strict_json_fields")]
pub text_texture: String,
#[cfg(feature = "strict_json_fields")]
pub content_texture_path: String,
#[cfg(feature = "strict_json_fields")]
pub content_texture_bg_path: String,
#[cfg(feature = "strict_json_fields")]
pub under_bg_texture_path: String,
#[cfg(feature = "strict_json_fields")]
pub tag_not_selected_sprite_path: String,
#[cfg(feature = "strict_json_fields")]
pub tag_selected_sprite_path: String,
#[cfg(feature = "strict_json_fields")]
pub weapon_prefab_path: String,
#[cfg(feature = "strict_json_fields")]
pub spine_prefab_resource: String,
pub up_list: Vec<i32>,
pub show_id_list: Vec<i32>,
pub preview_id_list: Vec<i32>,

View file

@ -0,0 +1,16 @@
use serde::Deserialize;
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct GuideGroupData {
pub id: i32,
pub step: Vec<i32>,
pub open_limit_condition: i32,
pub auto_open_condition: i32,
pub limit_repeat: Vec<i32>,
pub dungeon_id: Vec<i32>,
pub reset_in_dungeon: bool,
pub online_mode: i32,
pub priority: i32,
}

View file

@ -1,11 +1,20 @@
use serde::Deserialize;
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct GuideTutorialData {
pub id: i32,
pub tutorial_type: i32,
pub tutorial_order: i32,
pub page_id: Vec<i32>,
pub page_replace_condition_group_id: i32,
pub replace_page_id: Vec<i32>,
#[cfg(feature = "strict_json_fields")]
pub group_name: String,
pub tutorial_tip: bool,
}
pub drop_id: i32,
pub disable_drop_reward: bool,
pub require_read_all: bool,
pub exclude_from_wiki: bool,
}

View file

@ -5,29 +5,49 @@ use serde::Deserialize;
use crate::{EntranceEntityData, VectorData};
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct InstanceDungeonData {
pub id: i32,
pub map_config_id: i32,
#[cfg(feature = "strict_json_fields")]
pub map_name: String,
pub inst_type: i32,
pub inst_sub_type: i32,
pub online_type: i32,
pub custom_types: Vec<i32>,
pub mini_map_id: i32,
pub sub_levels: Vec<String>,
pub fight_formation_id: i32,
pub role_type_list: Vec<i32>,
pub trial_role_info: Vec<i32>,
pub trial_formation_id: Option<i32>,
pub revive_id: i32,
pub born_position: VectorData,
pub born_rotation: VectorData,
pub recover_world_location: Vec<i32>,
pub exit_dungeon_confirm_id: Vec<i32>,
pub entrance_entities: Vec<EntranceEntityData>,
pub exit_entities: Vec<i32>,
#[cfg(feature = "strict_json_fields")]
pub dungeon_desc: String,
pub title: i32,
#[cfg(feature = "strict_json_fields")]
pub banner_path: String,
pub monster_preview: Vec<i32>,
#[cfg(feature = "strict_json_fields")]
pub monster_tips: String,
pub first_reward_id: i32,
pub reward_id: i32,
pub repeat_reward_id: i32,
pub exchange_reward_id: i32,
pub shared_treasure_group: Vec<i32>,
pub enter_control_id: i32,
pub enter_condition: Vec<i32>,
#[cfg(feature = "strict_json_fields")]
pub enter_condition_text: String,
#[cfg(feature = "strict_json_fields")]
pub difficulty_icon: String,
pub entity_level: i32,
pub recommend_level: HashMap<i32, i32>,
pub recommend_role: Vec<i32>,

View file

@ -0,0 +1,13 @@
use std::collections::HashMap;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct ItemExchangeContentData {
pub item_id: i32,
pub times: i32,
pub gain_count: i32,
pub consume: HashMap<i32, i32>,
}

View file

@ -1,13 +1,16 @@
use serde::Deserialize;
use crate::{ComponentsData, RawVectorData};
use crate::RawVectorData;
use crate::pb_components::ComponentsData;
#[derive(Deserialize, Debug)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct LevelEntityConfigData {
pub id: i32,
pub map_id: i32,
pub entity_id: i64,
pub blueprint_type: String,
#[cfg(feature = "strict_json_fields")]
pub name: String,
pub in_sleep: bool,
pub is_hidden: bool,

View file

@ -0,0 +1,11 @@
use serde::Deserialize;
use crate::LevelPlayDataDetail;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct LevelPlayDataData { // Json file contains Data in name, so it has to be DataData
pub level_play_id: i32,
pub data: LevelPlayDataDetail,
}

View file

@ -0,0 +1,11 @@
use serde::Deserialize;
use crate::node_data::NodeDataDetail;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct LevelPlayNodeDataData { // Json file contains Data in name, so it has to be DataData
pub key: String,
pub data: NodeDataDetail,
}

View file

@ -3,9 +3,15 @@ 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}")]
@ -35,9 +41,12 @@ macro_rules! json_data {
fn load_json_data(base_path: &str) -> Result<(), LoadDataError> {
$(paste! {
let file = File::open(&format!("{}/{}.json", base_path, stringify!($table_type)))?;
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(())
@ -64,7 +73,7 @@ macro_rules! json_hash_table_data {
TABLE.get().unwrap().iter()
}
pub fn get(k: &$key_type) -> Option<&Data> {
pub fn get(k: &$key_type) -> Option<&'static Data> {
TABLE.get().unwrap().get(k)
}
}
@ -72,14 +81,19 @@ macro_rules! json_hash_table_data {
fn load_json_hash_table_data(base_path: &str) -> Result<(), LoadDataError> {
$(paste! {
let file = File::open(&format!("{}/{}.json", base_path, stringify!($table_type)))?;
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, element))
.map(|element| (element.$key_param.clone(), element))
.collect::<std::collections::HashMap<_, _>>()
);
tracing::info!("Loading data finished: {path}");
})*
Ok(())
@ -90,105 +104,112 @@ macro_rules! json_hash_table_data {
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;
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;
LevelEntityConfig, entity_id, i64;
// TemplateConfig, blueprint_type, String;
DropPackage, id, i32;
TemplateConfig, blueprint_type, String;
}
mod textmap;
mod level_entity_config;
pub mod text_map_data {
use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::io::BufReader;
pub mod level_entity_config_data {
use std::collections::HashMap;
use std::sync::OnceLock;
use crate::LoadDataError;
use crate::textmap::TextMapData;
use crate::gacha_view_info_data;
pub(crate) type Data = super::LevelEntityConfigData;
pub(crate) static TABLE: OnceLock<HashMap<String, Data>> = OnceLock::new();
static EMPTY: OnceLock<HashMap<String, String>> = OnceLock::new();
static TABLE: OnceLock<HashMap<String, HashMap<String, String>>> = OnceLock::new();
pub fn load_textmaps(base_path: &str) -> Result<(), LoadDataError> {
// TODO: Ideally we would expose a function here to allow other components to add to the
// filter, since right now only gacha uses it, we can do this
let filters = get_filters();
let languages = std::fs::read_dir(base_path)?
.filter_map(|entry| entry.ok())
.filter(|entry| entry.path().is_dir())
.collect::<Vec<_>>();
let mut result: HashMap<String, HashMap<String, String>> = HashMap::new();
for language in languages {
let lang_id = language.file_name().to_str().unwrap().to_string();
let file = File::open(&format!("{base_path}/{lang_id}/multi_text/MultiText.json"))?;
let reader = BufReader::new(file);
result.insert(
lang_id,
serde_json::from_reader::<BufReader<File>, Vec<TextMapData>>(reader)?
.into_iter()
.filter(|element| filters.contains(&element.id))
.map(|element| (element.id, element.content))
.collect::<HashMap<_, _>>(),
);
}
let _ = TABLE.set(result);
Ok(())
pub fn iter() -> std::collections::hash_map::Iter<'static, String, Data> {
TABLE.get().unwrap().iter()
}
pub fn get_textmap(language: i32) -> &'static HashMap<String, String> {
let (text_code, _audio_code) = get_language_from_i32(language);
TABLE.get_or_init(|| HashMap::new())
.get(text_code)
.unwrap_or(EMPTY.get_or_init(|| HashMap::new()))
pub fn get(map_id: i32, entity_id: i64) -> Option<&'static Data> {
TABLE.get().unwrap().get(&create_key_internal(map_id, entity_id))
}
fn get_language_from_i32(language: i32) -> (&'static str, &'static str) {
match language {
0 => ("zh-Hans", "zh"),
1 => ("en", "en"),
2 => ("ja", "ja"),
3 => ("ko", "ko"),
4 => ("ru", "en"),
5 => ("zh-Hant", "zh"),
6 => ("de", "en"),
7 => ("es", "en"),
8 => ("pt", "en"),
9 => ("id", "en"),
10 => ("fr", "en"),
11 => ("vi", "en"),
12 => ("th", "en"),
_ => ("en", "en"),
}
#[inline(always)]
pub fn create_key(element: &Data) -> String {
create_key_internal(element.map_id, element.entity_id)
}
fn get_filters() -> HashSet<String> {
let mut filters = HashSet::new();
for gacha_view_info in gacha_view_info_data::iter() {
filters.insert(gacha_view_info.summary_title.clone());
filters.insert(gacha_view_info.summary_describe.clone());
}
filters
#[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(())
}

View file

@ -0,0 +1,18 @@
use std::collections::HashMap;
use serde::Deserialize;
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct LivenessTaskData {
pub task_id: i32,
#[cfg(feature = "strict_json_fields")]
pub task_name: String,
pub update_type: i32,
pub task_reward: HashMap<i32, i32>,
#[cfg(feature = "strict_json_fields")]
pub task_func: Vec<String>,
pub unlock_condition: i32,
pub sort_rank: i32,
}

View file

@ -1,20 +1,28 @@
use serde::Deserialize;
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct LordGymData {
pub id: i32,
pub difficulty: i32,
pub reward_id: i32,
pub play_id: i32,
#[cfg(feature = "strict_json_fields")]
pub gym_title: String,
#[cfg(feature = "strict_json_fields")]
pub new_gym_title: String,
#[cfg(feature = "strict_json_fields")]
pub icon_path: String,
#[cfg(feature = "strict_json_fields")]
pub play_description: String,
pub help_id: i32,
pub monster_list: Vec<i32>,
pub monster_level: i32,
pub lock_con: i32,
#[cfg(feature = "strict_json_fields")]
pub lock_description: String,
pub filter_type: i32,
pub is_new: bool,
pub is_debug: bool,
}

View file

@ -1,6 +1,9 @@
use serde::Deserialize;
use serde_repr::Deserialize_repr;
use crate::pb_components::action::Action;
use crate::pb_components::condition::Condition;
#[derive(Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct PropValueData {
@ -53,7 +56,7 @@ impl RawVectorData {
#[serde(rename_all = "PascalCase")]
pub struct EntranceEntityData {
pub dungeon_id: i32,
pub entrance_entity_id: i32,
pub entrance_entity_id: i64,
}
#[derive(Deserialize_repr, PartialEq, Debug, Copy, Clone)]
@ -67,186 +70,423 @@ pub enum GachaViewTypeInfoId {
BeginnersChoiceConvene = 6,
}
#[derive(Deserialize, Debug, Clone)]
#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "PascalCase")]
pub struct Category {
pub main_type: Option<String>,
pub monster_match_type: Option<i32>,
pub struct ConsumeItem {
pub item_id: i32,
pub count: i32,
}
#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "PascalCase")]
pub struct ScanFunction {
pub scan_id: Option<i32>,
pub is_concealed: Option<bool>,
#[derive(Deserialize, PartialEq, Debug, Copy, Clone)]
pub enum EntityType {
AdsorptionFoundation,
AdviseItem,
AiAlertNotifier,
AiGearController,
AiMovementGear,
AirPassage,
AiSceneItem,
Animal,
Animal2,
AnnunciatorCenter,
AnnunciatorWire,
AreaOccupation,
Audio,
AudioBox,
BatchBulletCaster,
BeamCastBullet,
BeamCaster,
BeamCrystal,
BeamDeliver,
BeamReceiver,
BondageTrap,
BuffConsumer,
BuffProducer,
BurstCrystalFoundation,
Chair,
Chair2,
ChallengeInteract,
Chessboard,
Chessman,
ClientTrigger,
Collect,
Collect2,
Collect3,
CollectAnimal,
CollectAnimalPart,
CombatAnimal,
CombatAnimal2,
CombinedVisibleGroup,
ControlConnector,
ConveyorBelt,
CookTool,
CustomAoiEditor,
Destructible,
DestructibleControl,
DestructibleExploreInteractor,
DestructibleSceneBullet,
DestructibleTrigger,
Disc,
Drop,
DungeonEntry,
DynamicPortalCreater,
EffectArea,
EnrichmentArea,
EntityBundle,
EntityList,
EntityPackage,
ExploreSkillInteractor,
FishingBoat,
FollowShooter,
FollowShooter2,
FollowTrack,
FollowTrackFoundation,
Gramophone,
GravityFlip,
GroupAi,
HackingTypeFollowShooter,
HookLockPoint,
HookSoundBox,
HookWithRange,
HorseBettingTuanzi,
InhaledItem,
InteractFoundation,
InteractFoundationWithSceneItemAttribute,
InteractGear,
InteractGearGroup,
InteractiveConditionListener,
Item,
ItemFoundation,
JigsawFoundation,
JigsawItem,
KiteHook,
LevelPlay,
LevelPlayReward,
LevelQteTrigger,
LevitateMagnet,
LifePointCenter,
Lift,
LightDeliver,
LocationSafety,
Monitor,
Monster,
MonsterGachaBase,
MonsterGachaItem,
MoveableTrigger,
NoRenderPortal,
Npc,
Npc2,
PasserbyNpc,
PhotoTarget,
PhysicsSwing,
Portal,
Position,
ProgressBarController,
ProgressBarControllerWithAttribute,
PullingObject,
Range,
RangeTriggerTargetGear,
ReboundPlateGear,
RefreshGroup,
RenderSpecifiedRange,
Resurrection,
RollingFireball,
Rotator,
SceneAura,
SceneBullet,
SceneBulletCanHit,
SceneBulletWithMovement,
SceneItemStateHint,
SimpleInteract,
SimpleNPc,
SkyboxTrigger,
SoundBox,
SpawnMonster,
SpawnPasserbyNpc,
Spline,
SummonGongduolaPoint,
StateSceneItem,
StateTrigger,
StatueFoundation,
SuiGuangHook,
TargetGear,
TargetGearGroup,
TargetGearGroup2,
TargetGearPro,
TargetGearWithLevelPrefabPerform,
TeleControl,
TeleControl3,
TeleControlGroup,
Teleporter,
TemporaryTeleporter,
TimelineTrackController,
TimeStop,
Trample,
Trample2,
Trample3,
TreasureBox,
Trigger,
TriggerConditionListener,
TurntableController,
VacuumCleaner,
VarManager,
Vehicle,
Vehicle2,
VehicleNpc,
VehicleSceneItem,
VisibleTrigger,
Vision,
VisionItem,
VisionTreasureBox,
WalkingPatternController,
WaterCollection,
WaterSpout,
Weapon,
}
#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "PascalCase")]
pub struct WorldLevelBonusType {
pub r#type: Option<i32>,
pub world_level_bonus_id: Option<i32>,
#[derive(Deserialize, PartialEq, Debug, Copy, Clone)]
pub enum EntityLogic {
Item,
Animal,
Monster,
Vehicle,
Npc,
Vision,
ClientOnly,
ServerOnly,
Custom,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
pub struct BaseInfoComponent {
pub tid_name: Option<String>,
pub category: Option<Category>,
pub camp: Option<i32>,
pub online_interact_type: Option<i32>,
pub scan_function: Option<ScanFunction>,
pub aoi_layer: Option<i32>,
pub entity_property_id: Option<i32>,
pub focus_priority: Option<i32>,
pub aoi_zradius: Option<i32>,
// TODO: Add more
#[derive(Debug, Deserialize)]
pub enum LevelPlayType {
Challenge,
SilentArea,
Dungeon,
MonsterTreasure,
Quest,
Riddle,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
pub struct AiComponent {
pub disabled: Option<bool>,
pub ai_id: Option<i32>,
// TODO: Add more
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase", deny_unknown_fields)]
pub struct LevelPlayOpenCondition {
pub conditions: Option<Vec<Condition>>,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
pub struct AttributeComponent {
pub property_id: Option<i32>,
pub level: Option<i32>,
pub world_level_bonus_type: Option<WorldLevelBonusType>,
pub rage_mode_id: Option<i32>,
pub hardness_mode_id: Option<i32>,
pub monster_prop_extra_rate_id: Option<i32>,
pub world_level_bonus_id: Option<i32>,
pub fight_music: Option<String>,
// TODO: Add more
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase", deny_unknown_fields)]
pub struct LevelPlayActive {
pub active_type: i32,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
pub struct TeleportPosition {
pub x: Option<f32>,
pub y: Option<f32>,
pub z: Option<f32>,
pub a: Option<f32>,
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase", deny_unknown_fields)]
pub struct LevelPlayRewardConfigResetTypeMidNight {
pub count: i32,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
pub struct TeleportComponent {
pub disabled: Option<bool>,
pub teleporter_id: Option<i32>,
#[serde(rename = "TeleportPos")]
pub teleport_position: Option<TeleportPosition>,
#[derive(Debug, Deserialize)]
#[serde(tag = "Type")]
pub enum LevelPlayRewardConfigResetType {
MidNight(LevelPlayRewardConfigResetTypeMidNight),
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
pub struct ComponentsData {
pub base_info_component: Option<BaseInfoComponent>,
pub ai_component: Option<AiComponent>,
pub attribute_component: Option<AttributeComponent>,
pub teleport_component: Option<TeleportComponent>,
// TODO: Implement this ones
// pub scene_actor_ref_component: Option<serde_json::Value>,
// pub effect_area_component: Option<serde_json::Value>,
// pub entity_state_component: Option<serde_json::Value>,
// pub condition_listener_component: Option<serde_json::Value>,
// pub interact_component: Option<serde_json::Value>,
// pub npc_perform_component: Option<serde_json::Value>,
// pub var_component: Option<serde_json::Value>,
// pub entity_visible_component: Option<serde_json::Value>,
// pub level_ai_component: Option<serde_json::Value>,
// pub trigger_component: Option<serde_json::Value>,
// pub range_component: Option<serde_json::Value>,
// pub spline_component: Option<serde_json::Value>,
// pub bubble_component: Option<serde_json::Value>,
// pub reward_component: Option<serde_json::Value>,
// pub refresh_component: Option<serde_json::Value>,
// pub passerby_npc_spawn_component: Option<serde_json::Value>,
// pub vision_capture_component: Option<serde_json::Value>,
// pub refresh_group_component: Option<serde_json::Value>,
// pub collect_component: Option<serde_json::Value>,
// pub target_gear_component: Option<serde_json::Value>,
// pub fight_interact_component: Option<serde_json::Value>,
// pub guide_line_creator_component: Option<serde_json::Value>,
// pub photo_target_component: Option<serde_json::Value>,
// pub model_component: Option<serde_json::Value>,
// pub entity_group_component: Option<serde_json::Value>,
// pub scene_item_life_cycle_component: Option<serde_json::Value>,
// pub entity_state_audio_component: Option<serde_json::Value>,
// pub animal_component: Option<serde_json::Value>,
// pub monster_component: Option<serde_json::Value>,
// pub nearby_tracking_component: Option<serde_json::Value>,
// pub follow_track_component: Option<serde_json::Value>,
// pub jigsaw_foundation: Option<serde_json::Value>,
// pub treasure_box_component: Option<serde_json::Value>,
// pub hook_lock_point: Option<serde_json::Value>,
// pub explore_skill_interact_component: Option<serde_json::Value>,
// pub attach_target_component: Option<serde_json::Value>,
// pub target_gear_group_component: Option<serde_json::Value>,
// pub spawn_monster_component: Option<serde_json::Value>,
// pub skybox_component: Option<serde_json::Value>,
// pub destructible_item: Option<serde_json::Value>,
// pub fan_component: Option<serde_json::Value>,
// pub state_hint_component: Option<serde_json::Value>,
// pub buff_consumer_component: Option<serde_json::Value>,
// pub reset_entities_pos_component: Option<serde_json::Value>,
// pub group_ai_component: Option<serde_json::Value>,
// pub pulling_object_foundation: Option<serde_json::Value>,
// pub lift_component: Option<serde_json::Value>,
// pub scene_item_movement_component: Option<serde_json::Value>,
// pub reset_self_pos_component: Option<serde_json::Value>,
// pub jigsaw_item: Option<serde_json::Value>,
// pub level_play_component: Option<serde_json::Value>,
// pub interact_gear_component: Option<serde_json::Value>,
// pub ai_gear_strategy_component: Option<serde_json::Value>,
// pub pick_interact_component: Option<serde_json::Value>,
// pub level_sequence_frame_event_component: Option<serde_json::Value>,
// pub air_wall_spawner_component: Option<serde_json::Value>,
// pub progress_bar_control_component: Option<serde_json::Value>,
// pub batch_bullet_caster_component: Option<serde_json::Value>,
// pub client_trigger_component: Option<serde_json::Value>,
// pub enrichment_area_component: Option<serde_json::Value>,
// pub vehicle_component: Option<serde_json::Value>,
// pub item_foundation2: Option<serde_json::Value>,
// pub tele_control2: Option<serde_json::Value>,
// pub interact_audio_component: Option<serde_json::Value>,
// pub level_qte_component: Option<serde_json::Value>,
// pub resurrection_component: Option<serde_json::Value>,
// pub ai_alert_notify_component: Option<serde_json::Value>,
// pub trample_component: Option<serde_json::Value>,
// pub dungeon_entry_component: Option<serde_json::Value>,
// pub level_prefab_perform_component: Option<serde_json::Value>,
// pub render_specified_range_component: Option<serde_json::Value>,
// pub walking_pattern_component: Option<serde_json::Value>,
// pub no_render_portal_component: Option<serde_json::Value>,
// pub adsorb_component: Option<serde_json::Value>,
// pub beam_cast_component: Option<serde_json::Value>,
// pub beam_receive_component: Option<serde_json::Value>,
// pub timeline_track_control_component: Option<serde_json::Value>,
// pub scene_bullet_component: Option<serde_json::Value>,
// pub edit_custom_aoi_component: Option<serde_json::Value>,
// pub combat_component: Option<serde_json::Value>,
// pub location_safety_component: Option<serde_json::Value>,
// pub turntable_control_component: Option<serde_json::Value>,
// pub scene_item_ai_component: Option<serde_json::Value>,
// pub buff_producer_component: Option<serde_json::Value>,
// pub portal_component: Option<serde_json::Value>,
// pub inhalation_ability_component: Option<serde_json::Value>,
// pub inhaled_item_component: Option<serde_json::Value>,
// pub monster_gacha_base_component: Option<serde_json::Value>,
// pub monster_gacha_item_component: Option<serde_json::Value>,
// pub time_stop_component: Option<serde_json::Value>,
// pub hit_component: Option<serde_json::Value>,
// pub levitate_magnet_component: Option<serde_json::Value>,
// pub rebound_component: Option<serde_json::Value>,
// pub rotator_component2: Option<serde_json::Value>,
// pub conveyor_belt_component: Option<serde_json::Value>,
// pub dynamic_portal_creator_component: Option<serde_json::Value>,
// pub connector_component: Option<serde_json::Value>,
// pub monitor_component: Option<serde_json::Value>,
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase", deny_unknown_fields)]
pub struct LevelPlayRewardConfigInteract {
pub reward_id: i32,
pub reward_entity_id: i64,
pub reward_complete_actions: Vec<Action>,
pub first_complete_actions: Option<Vec<Action>>,
pub reset: Option<LevelPlayRewardConfigResetType>,
}
#[derive(Debug, Deserialize)]
#[serde(tag = "Type")]
pub enum LevelPlayRewardConfig {
None,
Interact(LevelPlayRewardConfigInteract),
}
#[derive(Debug, Deserialize)]
pub enum FixedDateTime {
Daily,
Weekly
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase", deny_unknown_fields)]
pub struct LevelPlayRefreshConfigFixedDateTime {
pub update_type: FixedDateTime,
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase", deny_unknown_fields)]
pub struct LevelPlayRefreshConfigCompleted {
pub min_refresh_cd: i32,
pub max_refresh_cd: i32,
}
#[derive(Debug, Deserialize)]
#[serde(tag = "Type")]
pub enum LevelPlayRefreshConfig {
None,
FixedDateTime(LevelPlayRefreshConfigFixedDateTime),
Completed(LevelPlayRefreshConfigCompleted),
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase", deny_unknown_fields)]
pub struct LevelPlayTrack {
pub track_radius: i32,
pub track_priority: i32,
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase", deny_unknown_fields)]
pub struct LevelPlayMark {
pub mark_id: i32,
pub map_bg_path: String,
}
#[derive(Debug, Deserialize)]
pub enum OnlineType {
Multiplayer,
Local,
Hang,
}
#[derive(Debug, Deserialize)]
pub enum ObjType {
LevelPlay,
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase", deny_unknown_fields)]
pub struct LevelPlayDataDetail { // Json file contains Data in name, so it has to be DataData
pub id: i32,
pub key: String,
#[cfg(feature = "strict_json_fields")]
pub internal_dest: String,
pub level_id: i32,
#[cfg(feature = "strict_json_fields")]
pub tid_name: String,
pub r#type: LevelPlayType,
pub instance_id: i32,
pub level_play_entity_id: i64,
pub level_additive_id: i32,
pub enter_radius: i32,
pub leave_radius: i32,
pub delay_refresh: bool,
pub delay_destroy: bool,
pub level_play_open_condition: LevelPlayOpenCondition,
pub level_play_active: LevelPlayActive,
pub level_play_reward_config: LevelPlayRewardConfig,
pub level_play_refresh_config: LevelPlayRefreshConfig,
pub level_play_track: LevelPlayTrack,
pub level_play_mark: Option<LevelPlayMark>,
pub enter_in_range_actions: Option<Vec<Action>>,
pub pack_id: i32,
pub online_type: OnlineType,
pub obj_type: ObjType,
#[cfg(feature = "strict_json_fields")]
pub children: Option<Vec<String>>,
#[cfg(feature = "strict_json_fields")]
pub reference: Vec<String>,
#[cfg(feature = "strict_json_fields")]
pub weak_reference: Option<Vec<String>>,
pub exploratory_degree: Option<i32>,
}
#[derive(Clone, Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct StateMachineTransition {
pub from: i32,
pub to: i32,
pub transition_prediction_type: i32,
pub weight: i32,
#[cfg(feature = "strict_json_fields")]
pub conditions: Vec<serde_json::Value>, // TODO: Implement conditions
}
#[derive(Clone, Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct StateMachineNodeCommon {
pub uuid: i32,
#[cfg(feature = "strict_json_fields")]
pub is_anim_state_machine: Option<bool>,
#[cfg(feature = "strict_json_fields")]
pub is_conduit_node: Option<bool>,
#[cfg(feature = "strict_json_fields")]
pub is_any_state: Option<bool>,
#[cfg(feature = "strict_json_fields")]
pub name: String,
#[cfg(feature = "strict_json_fields")]
pub take_control_type: i32,
#[cfg(feature = "strict_json_fields")]
pub transition_rule: i32,
pub children: Option<Vec<i32>>,
pub transitions: Option<Vec<StateMachineTransition>>,
#[cfg(feature = "strict_json_fields")]
pub on_enter_actions: Option<Vec<serde_json::Value>>, // TODO: Implement actions
#[cfg(feature = "strict_json_fields")]
pub on_exit_actions: Option<Vec<serde_json::Value>>, // TODO: Implement actions
#[cfg(feature = "strict_json_fields")]
pub bind_states: Option<Vec<serde_json::Value>>, // TODO: Implement bindStates
#[cfg(feature = "strict_json_fields")]
pub task: Option<serde_json::Value>, // TODO: Implement bindStates
}
#[derive(Clone, Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct StateMachineNodeReferenced {
pub reference_uuid: i32,
#[serde(flatten)]
pub common: StateMachineNodeCommon,
}
#[derive(Clone, Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct StateMachineNodeOverrideCommon {
pub override_common_uuid: i32,
#[serde(flatten)]
pub common: StateMachineNodeCommon,
}
#[derive(Clone, Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct StateMachineNodeCustom {
#[serde(flatten)]
pub common: StateMachineNodeCommon,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
pub enum StateMachineNode {
Reference(StateMachineNodeReferenced),
Override(StateMachineNodeOverrideCommon),
Custom(StateMachineNodeCustom),
}
#[derive(Clone, Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct StateMachineJson {
pub version: u32,
pub state_machines: Vec<i32>,
pub nodes: Vec<StateMachineNode>,
}

View file

@ -0,0 +1,31 @@
use serde::Deserialize;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct MonsterDetectionData {
pub id: i32,
pub blueprint_type: String,
pub mark_id: i32,
#[cfg(feature = "strict_json_fields")]
pub name: String,
pub show_reward: i32,
pub entity_config_id: i32,
pub danger_type: i32,
pub type_description2: i32,
#[cfg(feature = "strict_json_fields")]
pub attributes_description_lock: String,
#[cfg(feature = "strict_json_fields")]
pub attributes_description_unlock: String,
#[cfg(feature = "strict_json_fields")]
pub big_icon: String,
#[cfg(feature = "strict_json_fields")]
pub icon: String,
#[cfg(feature = "strict_json_fields")]
pub temporary_icon_un_lock: String,
#[cfg(feature = "strict_json_fields")]
pub temporary_iconlock: String,
pub begin_time_stamp: i32,
pub lock_con: i32,
pub monster_info_id: i32,
}

View file

@ -0,0 +1,19 @@
use serde::Deserialize;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct MonsterPropertyGrowthData {
pub id: i32,
pub curve_id: i32,
pub level: i32,
pub life_max_ratio: i32,
pub atk_ratio: i32,
pub def_ratio: i32,
pub hardness_max_ratio: i32,
pub hardness_ratio: i32,
pub hardness_recover_ratio: i32,
pub rage_max_ratio: i32,
pub rage_ratio: i32,
pub rage_recover_ratio: i32,
}

View file

@ -0,0 +1,23 @@
use serde::Deserialize;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct MotionData {
pub id: i32,
pub role_id: i32,
pub skin_id: i32,
pub r#type: i32,
pub sort: i32,
#[cfg(feature = "strict_json_fields")]
pub title: String,
#[cfg(feature = "strict_json_fields")]
pub content: String,
#[cfg(feature = "strict_json_fields")]
pub motion_img: String,
#[cfg(feature = "strict_json_fields")]
pub ani_blueprint: String,
#[cfg(feature = "strict_json_fields")]
pub ani_montage: String,
pub cond_group_id: i32,
}

View file

@ -0,0 +1,265 @@
use serde::Deserialize;
use crate::pb_components::action::Action;
use crate::pb_components::common::Location;
use crate::pb_components::condition::{Condition, Conditions};
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct TrackTypeLocations {
pub locations: Vec<Location>,
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct TrackTypeEntities {
pub entity_ids: Vec<i64>,
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct TrackTypeCaptureVisions {
pub vision_drop_entities: Vec<i64>,
}
#[derive(Deserialize, Debug)]
#[serde(tag = "Type")]
pub enum TrackType {
Locations(TrackTypeLocations),
Entities(TrackTypeEntities),
CaptureVisions(TrackTypeCaptureVisions),
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct TrackTarget {
pub track_type: TrackType,
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct NodeDataDetailCommon {
pub id: i32,
// In ps we don't care about description
#[cfg(feature = "strict_json_fields")]
pub desc: String,
// ParentNodeId is not defined for child items. i.e.: QuestSucceed/ConditionSelector sub items
pub parent_node_id: Option<i32>,
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase", deny_unknown_fields)]
pub struct PosRollbackCfg {
pub range_entity_id: i64,
pub position_entity_id: i64,
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase", deny_unknown_fields)]
pub struct SaveConfig {
pub disable_rollback_while_reconnect: Option<bool>,
pub enable_rollback_while_switch_online_mode: Option<bool>,
pub enter_actions: Option<Vec<Action>>,
pub pos_rollback_cfg: Option<PosRollbackCfg>,
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct NodeDataDetailSequence {
#[serde(flatten)]
pub common: NodeDataDetailCommon,
pub children: Option<Vec<NodeDataDetail>>,
#[cfg(feature = "strict_json_fields")]
pub save_config: Option<SaveConfig>,
#[cfg(feature = "strict_json_fields")]
#[serde(rename = "UIConfig")]
pub ui_config: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub information_view: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub statistics: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub enable_system: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub special_game_play_config: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub reward_config: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub fix_processor: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub budget_camera_type: Option<serde_json::Value>,
pub disable_online: Option<bool>,
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct NodeDataDetailChildQuest {
#[serde(flatten)]
pub common: NodeDataDetailCommon,
pub condition: Option<Condition>,
// In ps we don't care about tid tip
#[cfg(feature = "strict_json_fields")]
pub tid_tip: Option<String>,
pub track_target: Option<TrackTarget>,
pub enter_actions: Option<Vec<Action>>,
pub finish_actions: Option<Vec<Action>>,
#[cfg(feature = "strict_json_fields")]
pub fix_processor: Option<serde_json::Value>,
pub reward_id: Option<i32>,
// In ps we don't care about this
#[cfg(feature = "strict_json_fields")]
pub reward_get_ui_type: Option<i32>,
// In ps we don't care about this
#[cfg(feature = "strict_json_fields")]
pub show_tip_before_enter_actions: Option<bool>,
// In ps we don't care about this
#[cfg(feature = "strict_json_fields")]
pub hide_ui: Option<bool>,
// In ps we don't care about this
#[cfg(feature = "strict_json_fields")]
pub hide_tip: Option<bool>,
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct NodeDataDetailSelect {
#[serde(flatten)]
pub common: NodeDataDetailCommon,
pub children: Option<Vec<NodeDataDetail>>,
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct NodeDataDetailParallelSelect {
#[serde(flatten)]
pub common: NodeDataDetailCommon,
pub count: i32,
pub children: Option<Vec<NodeDataDetail>>,
#[cfg(feature = "strict_json_fields")]
pub save_config: Option<SaveConfig>,
#[cfg(feature = "strict_json_fields")]
#[serde(rename = "UIConfig")]
pub ui_config: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub statistics: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub occupation_config: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub start_wave: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub composite_track_view_mode: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub enable_system: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub information_view: Option<serde_json::Value>,
pub disable_online: Option<bool>,
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct ConditionSelectorSlot {
pub condition: Conditions,
pub node: Option<NodeDataDetail>,
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct NodeDataDetailConditionSelector {
#[serde(flatten)]
pub common: NodeDataDetailCommon,
pub slots: Vec<ConditionSelectorSlot>,
#[cfg(feature = "strict_json_fields")]
pub save_config: Option<SaveConfig>,
#[cfg(feature = "strict_json_fields")]
#[serde(rename = "UIConfig")]
pub ui_config: Option<serde_json::Value>,
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct NodeDataDetailRepeater {
#[serde(flatten)]
pub common: NodeDataDetailCommon,
pub max_repeat_times: Option<i32>,
pub exit_condition: Option<Conditions>,
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct NodeDataDetailCondition {
#[serde(flatten)]
pub common: NodeDataDetailCommon,
pub condition: Conditions,
pub wait_until_true: Option<bool>,
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct NodeDataDetailAction {
#[serde(flatten)]
pub common: NodeDataDetailCommon,
pub actions: Vec<Action>,
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct NodeDataDetailQuestSucceed {
#[serde(flatten)]
pub common: NodeDataDetailCommon,
pub finish_actions: Option<Vec<Action>>,
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct NodeDataDetailQuestFailed {
#[serde(flatten)]
pub common: NodeDataDetailCommon,
#[cfg(feature = "strict_json_fields")]
pub failed_condition: Option<serde_json::Value>,
pub finish_actions: Option<Vec<Action>>,
pub auto_failed: Option<bool>,
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct NodeDataDetailAlways {
#[serde(flatten)]
pub common: NodeDataDetailCommon,
pub child: Option<Box<NodeDataDetail>>,
}
#[derive(Debug, Deserialize)]
#[serde(tag = "Type")]
pub enum NodeDataDetail {
Sequence(NodeDataDetailSequence),
ChildQuest(NodeDataDetailChildQuest),
Select(NodeDataDetailSelect),
ParallelSelect(NodeDataDetailParallelSelect),
ConditionSelector(NodeDataDetailConditionSelector),
Repeater(NodeDataDetailRepeater),
Condition(NodeDataDetailCondition),
Action(NodeDataDetailAction),
QuestSucceed(NodeDataDetailQuestSucceed),
QuestFailed(NodeDataDetailQuestFailed),
AlwaysFalse(NodeDataDetailAlways),
AlwaysTrue(NodeDataDetailAlways),
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,60 @@
use serde::Deserialize;
use crate::pb_components::action::Actions;
use crate::pb_components::condition::Conditions;
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct InitState {
pub wander: Option<i32>,
pub standby_tags: Option<Vec<String>>,
pub r#type: Option<i32>,
pub birth_tag: Option<String>,
pub conditions: Option<Vec<Conditions>>,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct Patrol {
pub is_circle: Option<bool>,
pub spline_entity_id: Option<i64>,
pub actions: Option<Vec<Actions>>
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct EntityPos {
pub key: String,
pub entity_id: i64,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct EntityId {
pub key: String,
pub entity_id: i64,
}
#[derive(Deserialize, Debug, Clone)]
#[serde(tag = "Type")]
pub enum BlackBoard {
EntityPos(EntityPos),
EntityId(EntityId),
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct AiComponent {
pub disabled: Option<bool>,
pub ai_id: Option<i32>,
pub ai_team_level_id: Option<i32>,
pub center_point: Option<i32>,
pub init_black_board: Option<Vec<BlackBoard>>,
pub init_state: Option<InitState>,
pub patrol: Option<Patrol>,
pub weapon_id: Option<String>,
}

View file

@ -0,0 +1,41 @@
use serde::Deserialize;
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct WorldLevelBonusType {
pub r#type: Option<i32>,
pub world_level_bonus_id: Option<i32>,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct FightMusic {
pub fight_music: Option<String>,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct FightMusics {
pub r#type: Option<String>,
pub element: Option<Vec<FightMusic>>,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct AttributeComponent {
pub disabled: Option<bool>,
pub append_buff_ids: Option<Vec<i64>>,
pub property_id: Option<i32>,
pub level: Option<i32>,
pub world_level_bonus_type: Option<WorldLevelBonusType>,
pub rage_mode_id: Option<i32>,
pub hardness_mode_id: Option<i32>,
pub monster_prop_extra_rate_id: Option<i32>,
pub world_level_bonus_id: Option<i32>,
pub fight_music: Option<String>,
pub fight_musics: Option<FightMusics>,
}

View file

@ -0,0 +1,90 @@
use serde::Deserialize;
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct Category {
pub main_type: Option<String>,
pub monster_match_type: Option<i32>,
pub trace_match_type: Option<i32>,
pub entity_plot_binding_type: Option<String>,
pub exploratory_degree: Option<i32>,
pub hide_in_flow_type: Option<i32>,
pub destructible_type: Option<String>,
pub vehicle_type: Option<String>,
pub npc_type: Option<i32>,
pub animal_type: Option<i32>, // non use except of null so type not exact
pub collect_type: Option<String>,
pub pull_statue_match_type: Option<String>,
pub control_match_type: Option<String>,
pub item_foundation: Option<String>,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct TraceEffect {
pub target: Option<i32>,
pub effect: Option<String>,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct ScanFunction {
pub scan_id: Option<i32>,
pub is_concealed: Option<bool>,
pub trace_effect: Option<TraceEffect>,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct HeadStateViewConfig {
pub head_state_view_type: Option<i32>,
#[serde(rename = "ZOffset")]
pub z_offset: Option<i32>,
pub forward_offset: Option<i32>,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct CustomAoiZRadius {
pub up: Option<i32>,
pub down: Option<i32>,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct BaseInfoComponent {
pub disabled: Option<bool>,
pub tid_name: Option<String>,
pub category: Option<Category>,
pub camp: Option<i32>,
pub head_info: Option<i32>,
pub pack_id: Option<i32>,
pub data_layers: Option<Vec<i32>>,
pub is_show_name_on_head: Option<bool>,
pub head_state_view_config: Option<HeadStateViewConfig>,
#[cfg(feature = "strict_json_fields")]
pub fix_processor: Option<serde_json::Value>, // TODO: Implement this shit
pub online_interact_type: Option<i32>,
pub scan_function: Option<ScanFunction>,
pub aoi_layer: Option<i32>,
pub entity_property_id: Option<i32>,
pub focus_priority: Option<i32>,
#[serde(rename = "AoiZRadius")]
pub aoi_zradius: Option<i32>,
#[serde(rename = "CustomAoiZRadius")]
pub custom_aoi_zradius: Option<CustomAoiZRadius>,
pub child_entity_ids: Option<Vec<i64>>,
pub not_allow_hided_by_target_range: Option<bool>,
pub occupation: Option<String>,
pub is_online_standalone: Option<bool>,
pub entity_update_strategy: Option<i32>,
pub specified_online_standalone_parent_uids: Option<Vec<String>>,
pub lower_npc_density: Option<i32>,
pub map_icon: Option<i32>,
}

View file

@ -0,0 +1,19 @@
use serde::Deserialize;
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct Point {
pub x: Option<f32>,
pub y: Option<f32>,
pub z: Option<f32>,
}
#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "PascalCase")]
pub struct Location {
pub x: Option<f32>,
pub y: Option<f32>,
pub z: Option<f32>,
pub a: Option<f32>,
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,60 @@
use serde::Deserialize;
use crate::pb_components::action::Action;
use crate::pb_components::condition::Conditions;
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase", deny_unknown_fields)]
pub struct ConditionAction {
pub condition: Conditions,
pub action: Vec<Action>,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase", deny_unknown_fields)]
pub struct DelayChangeState {
pub time: f32,
pub new_state: String,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase", deny_unknown_fields)]
pub struct StateConfigs {
pub duration: f32,
pub state: String,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase", deny_unknown_fields)]
pub struct StateChangeBehaviors {
pub state: String,
pub action: Option<Vec<Action>>,
pub condition_action: Option<Vec<ConditionAction>>,
pub delay_change_state: Option<DelayChangeState>
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase", deny_unknown_fields)]
pub struct LockConfig {
pub lock_type: Option<String>, // TODO: Enum
pub is_init_lock: Option<bool>,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase", deny_unknown_fields)]
pub struct EntityStateComponent {
pub disabled: Option<bool>,
pub r#type: Option<String>,
pub state: Option<String>,
pub state_change_condition: Option<Conditions>,
pub state_change_behaviors: Option<Vec<StateChangeBehaviors>>,
pub state_configs: Option<Vec<StateConfigs>>,
pub cycle_states: Option<Vec<String>>,
pub prefab_performance_type: Option<String>,
pub lock_config: Option<LockConfig>,
}

View file

@ -0,0 +1,11 @@
use serde::Deserialize;
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct Flow {
pub flow_list_name: String,
pub flow_id: i32,
pub state_id: Option<i32>,
pub flow_guid: Option<String>
}

View file

@ -0,0 +1,87 @@
use serde::Deserialize;
use crate::pb_components::action::Action;
use crate::pb_components::common::Point;
use crate::pb_components::flow::Flow;
use crate::pb_components::option::GameOption;
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct MatchRoleOption {
pub r#type: String,
pub id: Option<i32>,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct SectorRange {
pub begin: Option<f32>,
pub end: Option<f32>,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct RandomInteract {
pub random_count: Option<i32>,
#[cfg(feature = "strict_json_fields")]
pub options: Option<serde_json::Value>, // TODO
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct Npc {}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct LeisureInteraction {
pub begin: i32,
pub end: i32,
}
#[derive(Deserialize, Debug, Clone)]
#[serde(tag = "Type")]
pub enum SectorRangeFromPlayerToEntity {
Npc(Npc),
LeisureInteraction(LeisureInteraction),
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct Actions {
pub actions: Vec<Action>,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct Flows {
pub flow: Flow,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct InteractComponent {
pub disabled: Option<bool>,
pub pre_flow: Option<Flow>,
pub do_intact_type: Option<String>,
pub options: Option<Vec<GameOption>>,
pub match_role_option: Option<Vec<MatchRoleOption>>,
pub range: Option<i32>,
pub is_wait_for_turn_around_complete: Option<bool>,
pub turn_around_type: Option<String>,
pub interact_default_icon: Option<String>,
pub tid_content: Option<String>,
pub interact_point_offset: Option<Point>,
pub sector_range: Option<SectorRange>,
pub random_interact: Option<RandomInteract>,
pub sector_range_from_player_to_entity: Option<SectorRangeFromPlayerToEntity>,
pub interact_icon: Option<String>,
pub quest_ids: Option<Vec<i32>>,
pub exit_range: Option<i32>,
}

View file

@ -0,0 +1,235 @@
use serde::Deserialize;
pub mod action;
pub mod ai;
pub mod attribute;
pub mod base_info;
pub mod common;
pub mod condition;
pub mod entity_state;
pub mod flow;
pub mod interact;
pub mod monster;
pub mod option;
pub mod reward;
pub mod teleport;
pub mod timer;
pub mod var;
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct ComponentsData {
pub base_info_component: Option<base_info::BaseInfoComponent>,
pub ai_component: Option<ai::AiComponent>,
pub attribute_component: Option<attribute::AttributeComponent>,
pub teleport_component: Option<teleport::TeleportComponent>,
pub monster_component: Option<monster::MonsterComponent>,
pub interact_component: Option<interact::InteractComponent>,
pub entity_state_component: Option<entity_state::EntityStateComponent>,
pub reward_component: Option<reward::RewardComponent>,
// TODO: Implement this ones
#[cfg(feature = "strict_json_fields")]
pub scene_actor_ref_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub effect_area_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub condition_listener_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub npc_perform_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub var_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub entity_visible_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub level_ai_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub trigger_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub range_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub spline_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub bubble_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub refresh_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub passerby_npc_spawn_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub vision_capture_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub refresh_group_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub collect_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub target_gear_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub fight_interact_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub guide_line_creator_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub photo_target_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub model_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub entity_group_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub scene_item_life_cycle_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub entity_state_audio_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub animal_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub nearby_tracking_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub follow_track_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub jigsaw_foundation: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub treasure_box_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub hook_lock_point: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub explore_skill_interact_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub attach_target_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub target_gear_group_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub spawn_monster_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub skybox_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub destructible_item: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub fan_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub state_hint_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub buff_consumer_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub reset_entities_pos_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub group_ai_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub pulling_object_foundation: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub lift_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub scene_item_movement_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub reset_self_pos_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub jigsaw_item: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub level_play_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub interact_gear_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub ai_gear_strategy_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub pick_interact_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub level_sequence_frame_event_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub air_wall_spawner_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub progress_bar_control_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub batch_bullet_caster_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub client_trigger_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub enrichment_area_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub vehicle_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub item_foundation2: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub tele_control2: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub interact_audio_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub level_qte_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub resurrection_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub ai_alert_notify_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub trample_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub dungeon_entry_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub level_prefab_perform_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub render_specified_range_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub walking_pattern_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub no_render_portal_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub adsorb_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub beam_cast_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub beam_receive_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub timeline_track_control_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub scene_bullet_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub edit_custom_aoi_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub combat_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub location_safety_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub turntable_control_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub scene_item_ai_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub buff_producer_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub portal_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub inhalation_ability_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub inhaled_item_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub monster_gacha_base_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub monster_gacha_item_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub time_stop_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub hit_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub levitate_magnet_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub rebound_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub rotator_component2: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub conveyor_belt_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub dynamic_portal_creator_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub connector_component: Option<serde_json::Value>,
#[cfg(feature = "strict_json_fields")]
pub monitor_component: Option<serde_json::Value>,
}
impl ComponentsData {
pub fn merge_with_template(&self, template: &Self) -> Self {
Self {
base_info_component: self.base_info_component.as_ref().or(template.base_info_component.as_ref()).cloned(),
ai_component: self.ai_component.as_ref().or(template.ai_component.as_ref()).cloned(),
attribute_component: self.attribute_component.as_ref().or(template.attribute_component.as_ref()).cloned(),
teleport_component: self.teleport_component.as_ref().or(template.teleport_component.as_ref()).cloned(),
monster_component: self.monster_component.as_ref().or(template.monster_component.as_ref()).cloned(),
interact_component: self.interact_component.as_ref().or(template.interact_component.as_ref()).cloned(),
entity_state_component: self.entity_state_component.as_ref().or(template.entity_state_component.as_ref()).cloned(),
reward_component: self.reward_component.as_ref().or(template.reward_component.as_ref()).cloned(),
}
}
}

View file

@ -0,0 +1,40 @@
use serde::Deserialize;
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct BossViewConfig {
pub boss_state_view_type: Option<i32>,
pub boss_state_info_show_type: Option<i32>,
pub tid_level_text: Option<String>,
pub tid_boss_sub_title: Option<String>,
pub show_distance: Option<i32>,
pub only_show_in_battle_state: Option<bool>,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct ShowOnDeath {
pub r#type: Option<i32>,
pub effect_id: Option<i32>,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct PerformConfig {
pub show_on_death: Option<ShowOnDeath>,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct MonsterComponent {
pub disabled: Option<bool>,
pub init_gas_tag: Option<Vec<String>>,
pub special_hate_and_sense_config: Option<i32>,
pub boss_view_config: Option<BossViewConfig>,
pub perform_config: Option<PerformConfig>,
pub fight_config_id: Option<i32>,
}

View file

@ -0,0 +1,27 @@
use serde::Deserialize;
use crate::pb_components::condition::Conditions;
use crate::pb_components::interact::{Actions, Flows};
#[derive(Deserialize, Debug)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct SitDown {}
#[derive(Deserialize, Debug, Clone)]
#[serde(tag = "Type")]
pub enum OptionType {
Actions(Actions),
Flow(Flows),
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct GameOption {
pub tid_content: Option<String>,
pub guid: Option<String>,
pub uniqueness_test: Option<String>,
pub r#type: Option<OptionType>,
pub condition: Option<Conditions>,
pub icon: Option<String>
}

View file

@ -0,0 +1,11 @@
use serde::Deserialize;
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct RewardComponent {
pub disabled: Option<bool>,
pub reward_id: Option<i32>,
pub reward_type: Option<i32>,
pub drop_on_event: Option<i32>,
}

View file

@ -0,0 +1,21 @@
use serde::Deserialize;
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct TeleportPosition {
pub x: Option<f32>,
pub y: Option<f32>,
pub z: Option<f32>,
pub a: Option<f32>,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct TeleportComponent {
pub disabled: Option<bool>,
pub teleporter_id: Option<i32>,
#[serde(rename = "TeleportPos")]
pub teleport_position: Option<TeleportPosition>,
}

View file

@ -0,0 +1,12 @@
use serde::Deserialize;
#[derive(Deserialize, Debug, Clone)]
pub enum TimerType {
CountDownChallenge,
WaitTime,
GameStartCountDown,
PublicTime,
BehaviorTreeTimer1,
BehaviorTreeTimer2,
BehaviorTreeTimer3,
}

View file

@ -0,0 +1,102 @@
use serde::Deserialize;
#[derive(Deserialize, Debug, Clone)]
pub enum CompareType {
Ne, // Not equal
Eq, // Equal
Ge, // Greater or equal
Gt, // Greater than
Le, // Less or equal
Lt, // Less than
}
impl CompareType {
pub fn cmp<T: PartialOrd + PartialEq>(self, left: &T, right: &T) -> bool {
match self {
CompareType::Ne => left.ne(right),
CompareType::Eq => left.eq(right),
CompareType::Ge => left.ge(right),
CompareType::Gt => left.gt(right),
CompareType::Le => left.le(right),
CompareType::Lt => left.lt(right),
}
}
}
#[derive(Deserialize, Debug, Clone)]
pub enum OpType {
Add, // Addition
Sub, // Subtraction
Mut, // Multiplication ??
Reduce, // Reduce ?? ?? ??
Set, // Assign
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct ConstantWrapper<T> {
pub value: T,
}
#[derive(Deserialize, Debug, Clone)]
#[serde(tag = "Type")]
pub enum Constant {
Boolean(ConstantWrapper<bool>),
Int(ConstantWrapper<i32>),
String(ConstantWrapper<String>),
Float(ConstantWrapper<f32>),
}
#[derive(Deserialize, Debug, Clone)]
pub enum VarType {
Boolean,
Int,
String,
Float,
Prefab
}
#[derive(Deserialize, Debug, Clone)]
pub enum RefType {
Entity,
Quest,
LevelPlay,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct Other {
pub r#type: VarType,
pub ref_type: RefType,
pub ref_id: i64,
pub name: String,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct Global {
pub r#type: VarType,
pub keyword: String,
}
#[derive(Deserialize, Debug, Clone)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct SelfVar {
pub r#type: VarType,
pub name: String,
}
#[derive(Deserialize, Debug, Clone)]
#[serde(tag = "Source")]
pub enum Var {
Constant(Constant),
Other(Other),
Global(Global),
#[serde(rename = "Self")]
SelfVar(SelfVar),
}

View file

@ -0,0 +1,11 @@
use serde::Deserialize;
use crate::node_data::NodeDataDetail;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct QuestNodeDataData { // Json file contains Data in name, so it has to be DataData
pub key: String,
pub data: NodeDataDetail,
}

View file

@ -0,0 +1,10 @@
use serde::Deserialize;
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct ResonanceAmplificationData {
pub id: i32,
pub attr: i32,
pub life_seat_boost_factor: Vec<f64>,
}

View file

@ -0,0 +1,28 @@
use std::collections::HashMap;
use serde::Deserialize;
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct ResonantChainData {
pub id: i32,
pub group_id: i32,
pub group_index: i32,
pub node_type: i32,
#[cfg(feature = "strict_json_fields")]
pub node_index: String,
#[cfg(feature = "strict_json_fields")]
pub node_name: String,
#[cfg(feature = "strict_json_fields")]
pub attributes_description: String,
#[cfg(feature = "strict_json_fields")]
pub bg_description: String,
pub buff_ids: Vec<i64>,
pub add_prop: Vec<i32>,
pub activate_consume: HashMap<i32, i32>,
#[cfg(feature = "strict_json_fields")]
pub attributes_description_params: Vec<String>,
#[cfg(feature = "strict_json_fields")]
pub node_icon: String,
}

View file

@ -0,0 +1,16 @@
use std::collections::HashMap;
use serde::Deserialize;
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct RoleBreachData {
pub id: i32,
pub breach_group_id: i32,
pub breach_level: i32,
pub max_level: i32,
pub breach_consume: HashMap<i32, i32>,
pub breach_reward: i32,
pub condition_id: i32,
}

View file

@ -0,0 +1,9 @@
use serde::Deserialize;
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct RoleExpItemData {
pub id: i32,
pub basic_exp: i32,
}

View file

@ -3,14 +3,18 @@ use std::collections::HashMap;
use serde::Deserialize;
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct RoleInfoData {
pub id: i32,
pub quality_id: i32,
pub role_type: i32,
pub is_trial: bool,
#[cfg(feature = "strict_json_fields")]
pub name: String,
#[cfg(feature = "strict_json_fields")]
pub nick_name: String,
#[cfg(feature = "strict_json_fields")]
pub introduction: String,
pub tag: Vec<i32>,
pub parent_id: i32,
@ -18,9 +22,35 @@ pub struct RoleInfoData {
pub show_property: Vec<i32>,
pub element_id: i32,
pub skin_id: i32,
#[cfg(feature = "strict_json_fields")]
pub role_head_icon_circle: String,
#[cfg(feature = "strict_json_fields")]
pub role_head_icon_large: String,
#[cfg(feature = "strict_json_fields")]
pub role_head_icon_big: String,
#[cfg(feature = "strict_json_fields")]
pub card: String,
#[cfg(feature = "strict_json_fields")]
pub role_head_icon: String,
#[cfg(feature = "strict_json_fields")]
pub formation_role_card: String,
#[cfg(feature = "strict_json_fields")]
pub role_stand: String,
#[cfg(feature = "strict_json_fields")]
pub role_portrait: String,
pub spillover_item: HashMap<i32, i32>,
#[cfg(feature = "strict_json_fields")]
pub mesh_id: i32,
#[cfg(feature = "strict_json_fields")]
pub ui_mesh_id: i32,
#[cfg(feature = "strict_json_fields")]
pub role_body: String,
pub breach_model: i32,
pub special_energy_bar_id: i32,
#[cfg(feature = "strict_json_fields")]
pub camera_config: String,
#[cfg(feature = "strict_json_fields")]
pub camera_float_height: i32,
pub entity_property: i32,
pub max_level: i32,
pub level_consume_id: i32,
@ -33,10 +63,45 @@ pub struct RoleInfoData {
pub exchange_consume: HashMap<i32, i32>,
pub init_weapon_item_id: i32,
pub weapon_type: i32,
#[cfg(feature = "strict_json_fields")]
#[serde(rename = "SkillDAPath")]
pub skill_da_path: String,
#[cfg(feature = "strict_json_fields")]
#[serde(rename = "SkillLockDAPath")]
pub skill_lock_da_path: String,
#[cfg(feature = "strict_json_fields")]
#[serde(rename = "UiScenePerformanceABP")]
pub ui_scene_performance_abp: String,
pub lock_on_default_id: i32,
pub lock_on_look_on_id: i32,
#[cfg(feature = "strict_json_fields")]
#[serde(rename = "SkillEffectDA")]
pub skill_effect_da: String,
#[cfg(feature = "strict_json_fields")]
pub foot_step_state: String,
pub party_id: i32,
#[cfg(feature = "strict_json_fields")]
pub attributes_description: String,
#[cfg(feature = "strict_json_fields")]
pub icon: String,
pub item_quality_id: i32,
#[cfg(feature = "strict_json_fields")]
pub obtained_show_description: String,
pub num_limit: i32,
pub show_in_bag: bool,
#[cfg(feature = "strict_json_fields")]
pub weapon_scale: Vec<i32>,
#[cfg(feature = "strict_json_fields")]
pub intervene: bool,
#[cfg(feature = "strict_json_fields")]
pub character_voice: String,
pub trial_role: i32,
pub is_aim: bool,
pub role_guide: i32,
#[cfg(feature = "strict_json_fields")]
pub red_dot_disable_rule: i32,
#[cfg(feature = "strict_json_fields")]
pub skin_damage: Vec<String>,
#[cfg(feature = "strict_json_fields")]
pub hide_hu_lu: bool,
}

View file

@ -0,0 +1,11 @@
use serde::Deserialize;
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct RoleLevelConsumeData {
pub id: i32,
pub consume_group_id: i32,
pub level: i32,
pub exp_count: i32,
}

View file

@ -0,0 +1,13 @@
use serde::Deserialize;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct RolePropertyGrowthData {
pub id: i32,
pub level: i32,
pub breach_level: i32,
pub life_max_ratio: i32,
pub atk_ratio: i32,
pub def_ratio: i32,
}

View file

@ -0,0 +1,47 @@
use std::collections::HashMap;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct SilentAreaDetectionData {
pub id: i32,
#[cfg(feature = "strict_json_fields")]
pub name: String,
pub guide_id: i32,
pub level_play_list: Vec<i32>,
#[cfg(feature = "strict_json_fields")]
pub instance_sub_type_description: String,
pub danger_type: i32,
pub secondary: i32,
pub type_description2: i32,
pub mat_type: i32,
#[cfg(feature = "strict_json_fields")]
pub attributes_description_lock: String,
#[cfg(feature = "strict_json_fields")]
pub attributes_description_unlock: String,
#[cfg(feature = "strict_json_fields")]
pub big_icon: String,
#[cfg(feature = "strict_json_fields")]
pub icon: String,
#[cfg(feature = "strict_json_fields")]
pub lock_big_icon: String,
#[cfg(feature = "strict_json_fields")]
pub temporary_icon_un_lock: String,
#[cfg(feature = "strict_json_fields")]
pub temporary_iconlock: String,
pub show_reward: i32,
pub show_reward_map: HashMap<i32, i32>,
pub begin_time_stamp: i32,
pub pre_open_id: i32,
pub mark_id: i32,
pub lock_con: i32,
#[cfg(feature = "strict_json_fields")]
pub phantom_id: Vec<Option<serde_json::Value>>,
pub first_drop_id: i32,
pub additional_id: i32,
pub sort_id: i32,
#[cfg(feature = "strict_json_fields")]
pub new_content: String,
}

View file

@ -0,0 +1,29 @@
use serde::Deserialize;
use crate::ConsumeItem;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct SynthesisFormulaData {
pub id: i32,
pub formula_item_id: i32,
pub item_id: i32,
pub formula_type: i32,
pub item_group: i32,
#[cfg(feature = "strict_json_fields")]
pub name: String,
pub consume_items: Vec<ConsumeItem>,
pub sort_id: i32,
pub unlock_condition: i32,
pub proficiency: i32,
pub max_proficiency_count: i32,
pub type_id: i32,
pub unlock: bool,
pub limit_count: i32,
pub permanent_limit: bool,
pub role_list: Vec<i32>,
#[cfg(feature = "strict_json_fields")]
pub compose_content: String,
#[cfg(feature = "strict_json_fields")]
pub compose_background: String,
}

View file

@ -1,15 +1,16 @@
use serde::Deserialize;
#[derive(Debug, Deserialize, Clone)]
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct TeleporterData {
pub id: i32,
pub map_id: i32,
pub object_id: i32,
pub area_id: i32,
pub fog_id: i32,
pub r#type: i32,
pub teleport_entity_config_id: i64,
#[cfg(feature = "strict_json_fields")]
pub plot: String,
pub after_network_action: i32,
pub show_world_map: bool,

View file

@ -1,11 +1,13 @@
use serde::Deserialize;
use crate::ComponentsData;
use crate::pb_components::ComponentsData;
#[derive(Debug, Deserialize, Clone)]
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct TemplateConfigData {
pub id: i32,
pub blueprint_type: String,
#[cfg(feature = "strict_json_fields")]
pub name: String,
pub components_data: ComponentsData,
}

View file

@ -0,0 +1,78 @@
use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::io::BufReader;
use std::sync::{LazyLock, Mutex, OnceLock};
use serde::Deserialize;
use crate::LoadDataError;
static FILTERS: LazyLock<Mutex<HashSet<String>>> = LazyLock::new(|| Mutex::new(HashSet::new()));
static EMPTY: OnceLock<HashMap<String, String>> = OnceLock::new();
static TABLE: OnceLock<HashMap<String, HashMap<String, String>>> = OnceLock::new();
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct TextMapData {
pub id: String,
pub content: String,
}
pub fn register_filter(filter: String) {
match TABLE.get() {
None => { FILTERS.lock().unwrap().insert(filter); }
Some(_) => {
// TODO: Implement error if filter is added after textmap was loaded already
}
};
}
pub fn load_textmaps(base_path: &str) -> Result<(), LoadDataError> {
let languages = std::fs::read_dir(base_path)?
.filter_map(|entry| entry.ok())
.filter(|entry| entry.path().is_dir())
.collect::<Vec<_>>();
let mut result: HashMap<String, HashMap<String, String>> = HashMap::new();
let mut filters = FILTERS.lock().unwrap();
for language in languages {
let lang_id = language.file_name().to_str().unwrap().to_string();
let file = File::open(&format!("{base_path}/{lang_id}/multi_text/MultiText.json"))?;
let reader = BufReader::new(file);
result.insert(
lang_id,
serde_json::from_reader::<BufReader<File>, Vec<TextMapData>>(reader)?
.into_iter()
.filter(|element| filters.contains(&element.id))
.map(|element| (element.id, element.content))
.collect::<HashMap<_, _>>(),
);
}
let _ = TABLE.set(result);
filters.clear();
Ok(())
}
pub fn get_textmap(language: i32) -> &'static HashMap<String, String> {
let (text_code, _audio_code) = get_language_from_i32(language);
TABLE.get_or_init(|| HashMap::new())
.get(text_code)
.unwrap_or(EMPTY.get_or_init(|| HashMap::new()))
}
fn get_language_from_i32(language: i32) -> (&'static str, &'static str) {
match language {
0 => ("zh-Hans", "zh"),
1 => ("en", "en"),
2 => ("ja", "ja"),
3 => ("ko", "ko"),
4 => ("ru", "en"),
5 => ("zh-Hant", "zh"),
6 => ("de", "en"),
7 => ("es", "en"),
8 => ("pt", "en"),
9 => ("id", "en"),
10 => ("fr", "en"),
11 => ("vi", "en"),
12 => ("th", "en"),
_ => ("en", "en"),
}
}

View file

@ -1,8 +0,0 @@
use serde::Deserialize;
#[derive(Deserialize, Clone)]
#[serde(rename_all = "PascalCase")]
pub struct TextMapData {
pub id: String,
pub content: String,
}

View file

@ -0,0 +1,16 @@
use std::collections::HashMap;
use serde::Deserialize;
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct WeaponBreachData {
pub id: i32,
pub breach_id: i32,
pub level: i32,
pub condition_id: i32,
pub level_limit: i32,
pub consume: HashMap<i32, i32>,
pub gold_consume: i32,
}

View file

@ -3,13 +3,18 @@ use serde::Deserialize;
use crate::PropValueData;
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct WeaponConfData {
pub item_id: i32,
#[cfg(feature = "strict_json_fields")]
pub weapon_name: String,
pub quality_id: i32,
pub weapon_type: i32,
#[cfg(feature = "strict_json_fields")]
pub model_id: i32,
pub transform_id: i32,
#[cfg(feature = "strict_json_fields")]
pub models: Vec<i32>,
pub reson_level_limit: i32,
pub first_prop_id: PropValueData,

View file

@ -0,0 +1,10 @@
use serde::Deserialize;
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct WeaponExpItemData {
pub id: i32,
pub cost: i32,
pub basic_exp: i32,
}

View file

@ -0,0 +1,11 @@
use serde::Deserialize;
#[derive(Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct WeaponLevelData {
pub id: i32,
pub level_id: i32,
pub level: i32,
pub exp: i32,
}

View file

@ -0,0 +1,12 @@
use serde::Deserialize;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct WeaponPropertyGrowthData {
pub id: i32,
pub curve_id: i32,
pub level: i32,
pub breach_level: i32,
pub curve_value: i32,
}

View file

@ -0,0 +1,17 @@
use serde::Deserialize;
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
#[serde(rename_all = "PascalCase")]
pub struct WeaponResonData {
pub id: i32,
pub reson_id: i32,
pub level: i32,
#[cfg(feature = "strict_json_fields")]
pub name: String,
#[cfg(feature = "strict_json_fields")]
pub effect: Vec<i32>,
pub consume: i32,
pub gold_consume: i32,
pub alternative_consume: Vec<i32>,
}

View file

@ -11,8 +11,11 @@ tokio.workspace = true
serde.workspace = true
# Util
indexmap = "2.7.1"
uuid = { version = "1.11.0", features = ["v4"] }
rand = "0.9.0-alpha.2"
unreal-niggery-rs = { git = "https://git.xeondev.com/xavo95/unreal-niggery-rs.git" }
widestring = "1.1.0"
# Used for debug
#serde_json = "1.0.135"
@ -26,6 +29,7 @@ hex.workspace = true
tracing.workspace = true
# Internal
wicked-waifus-asset-updater.workspace = true
wicked-waifus-commons.workspace = true
wicked-waifus-data.workspace = true
wicked-waifus-database.workspace = true

View file

@ -13,6 +13,23 @@ addr = "tcp://127.0.0.1:10004"
addr = "tcp://127.0.0.1:10003"
[game_server_config]
resources_path = "data/assets/game-data"
load_textmaps = true
# Do not change yet, issues to be solved
quadrant_size = 1000000
[asset_config]
asset_url = "https://git.xeondev.com/wickedwaifus/wicked-waifus-data/releases/download/pioneer_2.2.3/bundle.zip"
buffer_size = 268435456
[default_unlocks]
unlock_all_roles = true
unlock_all_roles_max_level = false
unlock_all_roles_all_sequences = false
unlock_all_mc_elements = true
unlock_all_weapons = false
unlock_all_adventures = false
unlock_all_functions = true
unlock_all_guides = false
unlock_all_tutorials = false
unlock_all_teleporter = false

View file

@ -0,0 +1,3 @@
const UiManager_1 = require("../Ui/UiManager");
const BattleView = UiManager_1.UiManager.GetViewByName("BattleView");
BattleView.ort(9).GetText(0).SetUIActive(false);

View file

@ -1,5 +1,8 @@
use std::sync::OnceLock;
use serde::Deserialize;
use wicked_waifus_commons::config_util;
use wicked_waifus_commons::config_util::TomlConfig;
use wicked_waifus_database::DatabaseSettings;
use wicked_waifus_network::config::ServiceEndPoint;
@ -11,14 +14,43 @@ pub struct ServiceConfig {
pub service_end_point: ServiceEndPoint,
pub gateway_end_point: ServiceEndPoint,
pub game_server_config: GameServerConfig,
pub asset_config: AssetConfig,
pub default_unlocks: DefaultUnlocks,
}
#[derive(Deserialize)]
pub struct GameServerConfig {
pub resources_path: String,
pub load_textmaps: bool,
pub quadrant_size: f32,
}
#[derive(Deserialize)]
pub struct AssetConfig {
pub asset_url: String,
pub buffer_size: usize,
}
#[derive(Deserialize)]
pub struct DefaultUnlocks {
pub unlock_all_roles: bool,
pub unlock_all_roles_max_level: bool,
pub unlock_all_roles_all_sequences: bool,
pub unlock_all_mc_elements: bool,
pub unlock_all_weapons: bool, // TODO:
pub unlock_all_adventures: bool,
pub unlock_all_functions: bool,
pub unlock_all_guides: bool,
pub unlock_all_tutorials: bool,
pub unlock_all_teleporter: bool,
}
impl TomlConfig for ServiceConfig {
const DEFAULT_TOML: &str = include_str!("../gameserver.default.toml");
}
static CONFIG: OnceLock<ServiceConfig> = OnceLock::new();
pub fn get_config() -> &'static ServiceConfig {
CONFIG.get_or_init(|| config_util::load_or_create("gameserver.toml"))
}

View file

@ -10,6 +10,8 @@ use crate::logic::utils::load_role_info::attribute_from_data;
pub struct Attribute {
pub attr_map: HashMap<EAttributeType, (i32, i32)>,
pub hardness_mode_id: i32,
pub rage_mode_id: i32,
}
impl Component for Attribute {
@ -40,9 +42,13 @@ impl Attribute {
}
#[inline(always)]
pub fn from_data(base_property: &BasePropertyData) -> Self {
pub fn from_data(base_property: &BasePropertyData,
hardness_mode_id: Option<i32>,
rage_mode_id: Option<i32>) -> Self {
Self {
attr_map: attribute_from_data(base_property),
hardness_mode_id: hardness_mode_id.unwrap_or_default(),
rage_mode_id: rage_mode_id.unwrap_or_default(),
}
}
@ -58,8 +64,8 @@ impl Attribute {
value_increment: *incr,
})
.collect(),
hardness_mode_id: 0,
rage_mode_id: 0,
hardness_mode_id: self.hardness_mode_id,
rage_mode_id: self.rage_mode_id,
}
}
}

View file

@ -0,0 +1,22 @@
use wicked_waifus_protocol::{ConcomitantsComponentPb, EntityComponentPb};
use wicked_waifus_protocol::entity_component_pb::ComponentPb;
use crate::logic::ecs::component::Component;
pub struct Concomitant {
pub vision_entity_id: i64,
pub custom_entity_ids: Vec<i64>,
pub phantom_role_id: i64,
}
impl Component for Concomitant {
fn set_pb_data(&self, pb: &mut wicked_waifus_protocol::EntityPb) {
pb.component_pbs.push(EntityComponentPb {
component_pb: Some(ComponentPb::ConcomitantsComponentPb(ConcomitantsComponentPb {
vision_entity_id: self.vision_entity_id,
custom_entity_ids: self.custom_entity_ids.clone(),
phantom_role_id: self.phantom_role_id,
})),
})
}
}

View file

@ -1,8 +1,9 @@
use wicked_waifus_protocol::{EEntityType, EntityConfigType, EntityState};
use wicked_waifus_protocol::entity_pb::D3s;
use crate::logic::ecs::component::Component;
pub struct EntityConfig {
pub camp: i32,
pub config_id: i32,
pub config_type: EntityConfigType,
pub entity_type: EEntityType,
@ -11,6 +12,7 @@ pub struct EntityConfig {
impl Component for EntityConfig {
fn set_pb_data(&self, pb: &mut wicked_waifus_protocol::EntityPb) {
pb.d3s = Some(D3s::Camp(self.camp));
pb.config_id = self.config_id;
pb.config_type = self.config_type.into();
pb.entity_type = self.entity_type.into();

View file

@ -1,24 +1,25 @@
use wicked_waifus_protocol::{BuffEffectCd, EntityComponentPb, FightBuffComponentPb, FightBuffInformation};
use wicked_waifus_protocol::entity_component_pb::ComponentPb;
use wicked_waifus_protocol::{
BuffEffectCd, EntityComponentPb, FightBuffComponentPb, FightBuffInformation,
};
use crate::logic::ecs::component::Component;
use crate::logic::utils::buff_util::add_buff_to_manager;
#[derive(Default, Clone)]
pub struct FightBuff {
pub fight_buff_infos: Vec<FightBuffInformation>,
pub permanent_fight_buff_infos: Vec<FightBuffInformation>,
pub list_buff_effect_cd: Vec<BuffEffectCd>,
}
impl FightBuff {
fn get_pb_data(pb: &wicked_waifus_protocol::EntityPb) -> Vec<&FightBuffComponentPb> {
pb.component_pbs.iter()
pb.component_pbs
.iter()
.filter_map(|pb| {
if let Some(value) = &pb.component_pb {
match value {
ComponentPb::FightBuffComponent(result) => Some(result),
_ => None
_ => None,
}
} else {
None
@ -31,43 +32,13 @@ impl FightBuff {
let pb_data = Self::get_pb_data(pb);
match pb_data.get(0) {
None => Self::default(),
Some(pb) => {
Self {
Some(pb) => Self {
fight_buff_infos: pb.fight_buff_infos.clone(),
list_buff_effect_cd: pb.list_buff_effect_cd.clone(),
..Default::default()
},
}
}
}
}
pub fn add_permanent_buff(&mut self, id: i64) {
self.permanent_fight_buff_infos.push(FightBuffInformation {
handle_id: 0, // TODO: Although permanent buffs dont require a handle it would be best to have them
buff_id: id,
level: 1,
stack_count: 1,
instigator_id: 0,
entity_id: 0,
apply_type: 0,
duration: -1f32,
left_duration: -1f32,
context: vec![],
is_active: true,
server_id: 0,
message_id: 0,
})
}
pub fn add_generic_permanent_buffs(&mut self) {
self.add_permanent_buff(3003); // Remove wall run prohibition
self.add_permanent_buff(3004); // Remove gliding prohibition
self.add_permanent_buff(1213); // Reduce stamina while flying
self.add_permanent_buff(1214); // Reduce stamina while flying in sprint
self.add_permanent_buff(1215); // Reduce stamina while flying up in sprint
self.add_permanent_buff(1216); // Reduce stamina while flying down in sprint
self.add_permanent_buff(640012051); // Allow flying
}
}
impl Component for FightBuff {
@ -77,27 +48,17 @@ impl Component for FightBuff {
if let Some(value) = &component_pb.component_pb {
match value {
ComponentPb::FightBuffComponent(_) => false,
_ => true
_ => true,
}
} else {
true
}
});
// Fix Instigator and Entity Id for permanent buffs
let mut fight_buff_infos = self.fight_buff_infos.clone();
let mut permanent_buffs = self.permanent_fight_buff_infos.clone();
for buf in &mut permanent_buffs {
buf.instigator_id = pb.id;
buf.entity_id = pb.id;
add_buff_to_manager(buf);
fight_buff_infos.push(buf.clone());
}
// Add new FightBuffComponent
pb.component_pbs.push(EntityComponentPb {
component_pb: Some(ComponentPb::FightBuffComponent(FightBuffComponentPb {
fight_buff_infos,
fight_buff_infos: self.fight_buff_infos.clone(),
list_buff_effect_cd: self.list_buff_effect_cd.clone(),
})),
});

View file

@ -1,25 +1,116 @@
use crate::logic::ecs::component::Component;
use wicked_waifus_protocol::entity_component_pb::ComponentPb;
use wicked_waifus_protocol::{DFsm, DFsmBlackBoard, EntityComponentPb, EntityFsmComponentPb, FsmCustomBlackboardDatas};
use std::string::ToString;
use std::sync::OnceLock;
use indexmap::IndexMap;
use wicked_waifus_protocol::{DFsm, DFsmBlackBoard, EntityComponentPb, EntityFsmComponentPb, FsmCustomBlackboardDatas};
use wicked_waifus_protocol::entity_component_pb::ComponentPb;
use wicked_waifus_data::{ai_base_data, ai_state_machine_config_data, AiStateMachineConfigData, StateMachineJson, StateMachineNode, StateMachineNodeCommon};
use crate::logic::ecs::component::Component;
static COMMON_FSM: OnceLock<AiStateMachineConfigData> = OnceLock::new();
#[derive(Default)]
pub struct Fsm {
pub fsms: Vec<DFsm>,
pub hash_code: i32,
pub common_hash_code: i32,
pub black_board: Vec<DFsmBlackBoard>,
pub fsm_custom_blackboard_datas: Option<FsmCustomBlackboardDatas>,
pub state_list: Vec<i32>,
pub node_list: IndexMap<i32, StateMachineNodeCommon>,
}
impl Component for Fsm {
fn set_pb_data(&self, pb: &mut wicked_waifus_protocol::EntityPb) {
pb.component_pbs.push(EntityComponentPb {
component_pb: Some(ComponentPb::EntityFsmComponentPb(EntityFsmComponentPb {
fsms: self.fsms.clone(),
fsms: self.get_initial_fsm(),
hash_code: self.hash_code,
common_hash_code: self.common_hash_code,
black_board: self.black_board.clone(),
fsm_custom_blackboard_datas: self.fsm_custom_blackboard_datas.clone(),
black_board: self.get_black_board(),
fsm_custom_blackboard_datas: self.get_fsm_custom_blackboard_datas(),
})),
})
}
}
impl Fsm {
pub fn from_ai_id(ai_id: i32) -> Self {
let ai_base = ai_base_data::get(&ai_id);
let Some(base) = ai_base else {
tracing::error!("Ai Base not found for AI ID: {}", ai_id);
return Self::default();
};
let common_state_machine: &StateMachineJson = &get_common_fsm().state_machine_json;
// Should always be defined since it comes from bindata
let Some(state_machine_config_data) = ai_state_machine_config_data::get(&base.state_machine) else {
tracing::error!("State machine config not found for AI ID: {}", ai_id);
return Self::default();
};
let state_machine_config: &StateMachineJson = &state_machine_config_data.state_machine_json;
let mut fsm_tree: IndexMap<i32, StateMachineNodeCommon> = IndexMap::with_capacity(state_machine_config.nodes.len());
for state_machine in &state_machine_config.state_machines {
for node in &state_machine_config.nodes {
match node {
StateMachineNode::Reference(_node) => {
// TODO:
// common_state_machine.nodes.iter()
// .filter_map(|state_machine_node| match state_machine_node {
// StateMachineNode::Reference(_) => None,
// StateMachineNode::Override(_) => None,
// StateMachineNode::Custom(custom) => Some(custom)
// })
// .find()
}
StateMachineNode::Override(node) => {
// TODO:
tracing::warn!(
"FSM: {state_machine} with override node {} for {} unimplemented",
node.common.uuid,
node.override_common_uuid
);
}
StateMachineNode::Custom(node) => {
fsm_tree.insert(node.common.uuid, node.common.clone());
}
}
}
}
Self {
hash_code: state_machine_config.version as i32,
common_hash_code: common_state_machine.version as i32,
state_list: state_machine_config.state_machines.clone(),
node_list: fsm_tree,
}
}
fn get_initial_fsm(&self) -> Vec<DFsm> {
self.node_list.iter()
.filter_map(|(&id, node)| {
self.state_list.contains(&id).then(|| DFsm {
fsm_id: id,
current_state: node.children.as_ref()
.and_then(|c| c.get(0).cloned())
.unwrap_or_default(),
flag: 0, // TODO:
k_ts: 0, // TODO:
})
}).collect::<Vec<_>>()
}
fn get_black_board(&self) -> Vec<DFsmBlackBoard> {
vec![]
}
fn get_fsm_custom_blackboard_datas(&self) -> Option<FsmCustomBlackboardDatas> {
None
}
}
fn get_common_fsm() -> &'static AiStateMachineConfigData {
COMMON_FSM.get_or_init(|| {
let name = "SM_Common".to_string();
// Common shall be always defined
ai_state_machine_config_data::get(&name).cloned().unwrap()
})
}

View file

@ -3,7 +3,7 @@ mod entity_config;
mod equip;
mod movement;
mod owner_player;
mod player_entity_marker;
mod player_owned_entity_marker;
mod position;
mod visibility;
mod vision_skill;
@ -15,13 +15,15 @@ mod state_tag;
mod tag;
mod autonomous;
mod interact;
mod concomitant;
mod summoner;
pub use attribute::Attribute;
pub use entity_config::EntityConfig;
pub use equip::Equip;
pub use movement::Movement;
pub use owner_player::OwnerPlayer;
pub use player_entity_marker::PlayerEntityMarker;
pub use player_owned_entity_marker::PlayerOwnedEntityMarker;
pub use position::Position;
pub use visibility::Visibility;
pub use vision_skill::VisionSkill;
@ -33,3 +35,5 @@ pub use state_tag::StateTag;
pub use tag::Tag;
pub use autonomous::Autonomous;
pub use interact::Interact;
pub use concomitant::Concomitant;
pub use summoner::Summoner;

Some files were not shown because too many files have changed in this diff Show more