mirror of
https://github.com/RustySamovar/RustySamovar.git
synced 2024-11-23 19:06:48 +00:00
Fix data loading errors with 3.4+ excels
This commit is contained in:
parent
6d566ca425
commit
c748b144ca
@ -16,6 +16,7 @@ lua_serde = { path = "lua_serde" }
|
||||
packet-processor-macro = { path = "packet-processor-macro" }
|
||||
packet-processor = { path = "packet-processor" }
|
||||
rs-ipc = { path = "rs-ipc" }
|
||||
excel-hash-wrapper-macro = { path = "excel-hash-wrapper-macro" }
|
||||
|
||||
prost = "0.8"
|
||||
bytes = "1.1.0"
|
||||
|
14
excel-hash-wrapper-macro/.gitignore
vendored
Normal file
14
excel-hash-wrapper-macro/.gitignore
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
|
||||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
||||
Cargo.lock
|
||||
|
||||
# These are backup files generated by rustfmt
|
||||
**/*.rs.bk
|
||||
|
||||
# Vim temp files
|
||||
.*.swp
|
||||
.*.swo
|
16
excel-hash-wrapper-macro/Cargo.toml
Normal file
16
excel-hash-wrapper-macro/Cargo.toml
Normal file
@ -0,0 +1,16 @@
|
||||
[package]
|
||||
name = "excel-hash-wrapper-macro"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
regex = "1"
|
||||
syn = { version = "1.0", features = ["full","derive"] }
|
||||
quote = "1.0"
|
||||
proc-macro2 = "1.0"
|
||||
convert_case = "0.4.0"
|
103
excel-hash-wrapper-macro/src/lib.rs
Normal file
103
excel-hash-wrapper-macro/src/lib.rs
Normal file
@ -0,0 +1,103 @@
|
||||
use proc_macro::{self, TokenStream};
|
||||
use quote::quote;
|
||||
use syn::{parse_macro_input, AttributeArgs};
|
||||
|
||||
fn get_nested_meta_name(nested_meta: &syn::NestedMeta) -> String {
|
||||
match nested_meta {
|
||||
syn::NestedMeta::Meta(meta) => match meta {
|
||||
syn::Meta::Path(ident) => ident.get_ident().cloned().unwrap().to_string(),
|
||||
_ => panic!("Unsupported macro argument"),
|
||||
},
|
||||
syn::NestedMeta::Lit(_) => panic!("Only identifiers are supported as an arguments to the macro"),
|
||||
}
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn excel_hash_wrapper(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let args = parse_macro_input!(args as AttributeArgs);
|
||||
let args = args.clone().into_iter().map(|a| get_nested_meta_name(&a));
|
||||
|
||||
// Generate all "X_hash", "X_hash_pre" and "X_hash_suffix" strings as well as getter names
|
||||
let args_hash = args.clone().into_iter().map(|a| format!("{}_hash", a));
|
||||
let args_hash_pre = args.clone().into_iter().map(|a| format!("{}_hash_pre", a));
|
||||
let args_hash_suffix = args.clone().into_iter().map(|a| format!("{}_hash_suffix", a));
|
||||
let get_args_hash = args.clone().into_iter().map(|a| format!("get_{}_hash", a));
|
||||
|
||||
let args_hash: Vec<proc_macro2::TokenStream> = args_hash.map(|a| a.parse().unwrap()).collect();
|
||||
let args_hash_pre: Vec<proc_macro2::TokenStream> = args_hash_pre.map(|a| a.parse().unwrap()).collect();
|
||||
let args_hash_suffix: Vec<proc_macro2::TokenStream> = args_hash_suffix.map(|a| a.parse().unwrap()).collect();
|
||||
let get_args_hash: Vec<proc_macro2::TokenStream> = get_args_hash.map(|a| a.parse().unwrap()).collect();
|
||||
|
||||
let mut found_struct = false;
|
||||
let mut struct_name = None;
|
||||
|
||||
let modified_struct: proc_macro::TokenStream = input.into_iter().map(|r| {
|
||||
match &r {
|
||||
&proc_macro::TokenTree::Ident(ref ident) if ident.to_string() == "struct" => { // react on keyword "struct" so we don't randomly modify non-structs
|
||||
found_struct = true;
|
||||
r
|
||||
},
|
||||
&proc_macro::TokenTree::Ident(ref ident) if found_struct == true && struct_name == None => { // Next ident right after "struct" is the struct name
|
||||
struct_name = Some(ident.to_string());
|
||||
r
|
||||
},
|
||||
&proc_macro::TokenTree::Group(ref group) if group.delimiter() == proc_macro::Delimiter::Brace && found_struct == true => { // Opening brackets for the struct
|
||||
let mut stream = proc_macro::TokenStream::new();
|
||||
|
||||
stream.extend(
|
||||
// For each hash name, generate three fields: prefix, suffix and the one that combines them
|
||||
vec![proc_macro::TokenStream::from(quote!(
|
||||
#(
|
||||
pub #args_hash_pre: Option<u8>,
|
||||
pub #args_hash_suffix: Option<u32>,
|
||||
pub #args_hash: Option<u64>,
|
||||
)*
|
||||
))]
|
||||
);
|
||||
stream.extend(group.stream());
|
||||
|
||||
proc_macro::TokenTree::Group(
|
||||
proc_macro::Group::new(
|
||||
proc_macro::Delimiter::Brace,
|
||||
stream
|
||||
)
|
||||
)
|
||||
}
|
||||
_ => r
|
||||
}
|
||||
}).collect();
|
||||
|
||||
let struct_name: proc_macro2::TokenStream = match &struct_name {
|
||||
None => panic!("Failed to find struct name"),
|
||||
Some(name) => name.clone().parse().unwrap(),
|
||||
};
|
||||
|
||||
let implementation = vec![proc_macro::TokenStream::from(quote!(
|
||||
// This implements getters for hashes
|
||||
// They first try to extract the value from u64 field
|
||||
// If it fails, they default to combining prefix and suffix
|
||||
impl #struct_name {
|
||||
#(
|
||||
pub fn #get_args_hash (&self) -> u64 {
|
||||
match self.#args_hash {
|
||||
Some(value) => value,
|
||||
None => match self.#args_hash_pre {
|
||||
None => panic!("Attempt to get an empty prefix for {} (object {:?})", stringify!(#args_hash), self),
|
||||
Some(prefix) => match self.#args_hash_suffix {
|
||||
None => panic!("Attempt to get an empty suffix for {} (object {:?})", stringify!(#args_hash), self),
|
||||
Some(suffix) => IdManager::get_hash_by_prefix_suffix(prefix, suffix),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
|
||||
))];
|
||||
|
||||
let mut ret = proc_macro::TokenStream::new();
|
||||
ret.extend(modified_struct);
|
||||
ret.extend(implementation);
|
||||
println!("{}", ret);
|
||||
ret
|
||||
}
|
@ -1,30 +1,70 @@
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
use crate::utils::IdManager;
|
||||
|
||||
use excel_hash_wrapper_macro::*;
|
||||
|
||||
#[excel_hash_wrapper(gacha_card_name, gacha_image_name)]
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(rename_all="PascalCase")]
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct AvatarGachaHashes {
|
||||
pub gacha_card_name_hash_pre: u8,
|
||||
/*pub gacha_card_name_hash_pre: u8,
|
||||
pub gacha_card_name_hash_suffix: u32,
|
||||
pub gacha_image_name_hash_pre: u8,
|
||||
pub gacha_image_name_hash_suffix: u32,
|
||||
pub gacha_image_name_hash_suffix: u32,*/
|
||||
}
|
||||
|
||||
#[excel_hash_wrapper(
|
||||
prefab_path,
|
||||
prefab_path_remote,
|
||||
controller_path,
|
||||
controller_path_remote,
|
||||
prefab_path_ragdoll,
|
||||
script_data_path,
|
||||
combat_config,
|
||||
manekin_path,
|
||||
coop_pic_name,
|
||||
manekin_json_config
|
||||
)]
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(rename_all="PascalCase")]
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct Avatar {
|
||||
// Entity fields
|
||||
pub id: u32,
|
||||
pub name_text_map_hash: u32,
|
||||
/*
|
||||
pub prefab_path_hash_pre: u8,
|
||||
pub prefab_path_hash_suffix: u32,
|
||||
|
||||
pub prefab_path_remote_hash_pre: u8,
|
||||
pub prefab_path_remote_hash_suffix: u32,
|
||||
|
||||
pub controller_path_hash_pre: u8,
|
||||
pub controller_path_hash_suffix: u32,
|
||||
|
||||
pub controller_path_remote_hash_pre: u8,
|
||||
pub controller_path_remote_hash_suffix: u32,
|
||||
|
||||
pub prefab_path_ragdoll_hash_pre: u8,
|
||||
pub prefab_path_ragdoll_hash_suffix: u32,
|
||||
|
||||
pub script_data_path_hash_pre: u8,
|
||||
pub script_data_path_hash_suffix: u32,
|
||||
|
||||
pub combat_config_hash_pre: u8,
|
||||
pub combat_config_hash_suffix: u32,
|
||||
|
||||
pub manekin_path_hash_pre: u8,
|
||||
pub manekin_path_hash_suffix: u32,
|
||||
|
||||
pub coop_pic_name_hash_pre: Option<u8>,
|
||||
pub coop_pic_name_hash_suffix: Option<u32>,
|
||||
|
||||
pub manekin_json_config_hash_pre: u8,
|
||||
pub manekin_json_config_hash_suffix: u32,*/
|
||||
|
||||
//pub camp_id: Option<u32>, // Avatars don't have these
|
||||
pub lod_pattern_name: String,
|
||||
pub lod_pattern_name: Option<String>,
|
||||
|
||||
// Creature fields
|
||||
pub hp_base: f32,
|
||||
@ -71,14 +111,9 @@ pub struct Avatar {
|
||||
|
||||
//pub prop_grow_curves: Vec<PropGrowConfig>, // TODO: unify with monster!
|
||||
|
||||
pub prefab_path_ragdoll_hash_pre: u8,
|
||||
pub prefab_path_ragdoll_hash_suffix: u32,
|
||||
|
||||
// Avatar fields
|
||||
pub use_type: Option<String>, // TODO: actually an enum
|
||||
pub body_type: String, // TODO: actually an enum
|
||||
pub script_data_path_hash_pre: u8,
|
||||
pub script_data_path_hash_suffix: u32,
|
||||
pub icon_name: String,
|
||||
pub side_icon_name: String,
|
||||
pub quality_type: String, // TODO: actually an enum
|
||||
@ -87,25 +122,17 @@ pub struct Avatar {
|
||||
pub heal_add: f32,
|
||||
#[serde(default)]
|
||||
pub healed_add: f32,
|
||||
pub combat_config_hash_pre: u8,
|
||||
pub combat_config_hash_suffix: u32,
|
||||
#[serde(default)]
|
||||
pub is_range_attack: bool,
|
||||
pub initial_weapon: u32,
|
||||
pub weapon_type: String, // TODO: actually an enum
|
||||
pub manekin_path_hash_pre: u8,
|
||||
pub manekin_path_hash_suffix: u32,
|
||||
pub image_name: String,
|
||||
#[serde(flatten)] // Those fields are present or absent all together, so we grouped them
|
||||
pub avatar_gacha_hashes: Option<AvatarGachaHashes>,
|
||||
pub coop_pic_name_hash_pre: Option<u8>,
|
||||
pub coop_pic_name_hash_suffix: Option<u32>,
|
||||
pub cutscene_show: String,
|
||||
pub skill_depot_id: u32,
|
||||
pub stamina_recover_speed: f32,
|
||||
pub cand_skill_depot_ids: Vec<u32>,
|
||||
pub manekin_json_config_hash_pre: u8,
|
||||
pub manekin_json_config_hash_suffix: u32,
|
||||
pub manekin_motion_config: u32,
|
||||
pub desc_text_map_hash: u32,
|
||||
pub avatar_identity_type: Option<String>, // TODO: actually an enum
|
||||
|
@ -8,7 +8,7 @@ pub struct AvatarSkill {
|
||||
pub ability_name: String,
|
||||
pub desc_text_map_hash: u32,
|
||||
pub skill_icon: String,
|
||||
pub cost_stamina: Option<u32>,
|
||||
pub cost_stamina: Option<f32>,
|
||||
pub max_charge_num: u32,
|
||||
pub trigger_id: Option<u32>,
|
||||
pub lock_shape: String, // TODO: probably an enum
|
||||
|
@ -60,7 +60,7 @@ pub struct Monster {
|
||||
pub exclude_weathers: String,
|
||||
|
||||
#[serde(rename = "FeatureTagGroupID")]
|
||||
pub feature_tag_group_id: u32,
|
||||
pub feature_tag_group_id: Option<u32>,
|
||||
#[serde(rename = "MpPropID")]
|
||||
pub mp_prop_id: u32,
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user