mirror of
https://github.com/RustySamovar/RustySamovar.git
synced 2024-11-27 12:25:52 +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-macro = { path = "packet-processor-macro" }
|
||||||
packet-processor = { path = "packet-processor" }
|
packet-processor = { path = "packet-processor" }
|
||||||
rs-ipc = { path = "rs-ipc" }
|
rs-ipc = { path = "rs-ipc" }
|
||||||
|
excel-hash-wrapper-macro = { path = "excel-hash-wrapper-macro" }
|
||||||
|
|
||||||
prost = "0.8"
|
prost = "0.8"
|
||||||
bytes = "1.1.0"
|
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 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")]
|
#[serde(rename_all="PascalCase")]
|
||||||
#[derive(Serialize, Deserialize, Clone)]
|
|
||||||
pub struct AvatarGachaHashes {
|
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_card_name_hash_suffix: u32,
|
||||||
pub gacha_image_name_hash_pre: u8,
|
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")]
|
#[serde(rename_all="PascalCase")]
|
||||||
#[derive(Serialize, Deserialize, Clone)]
|
|
||||||
pub struct Avatar {
|
pub struct Avatar {
|
||||||
// Entity fields
|
// Entity fields
|
||||||
pub id: u32,
|
pub id: u32,
|
||||||
pub name_text_map_hash: u32,
|
pub name_text_map_hash: u32,
|
||||||
|
/*
|
||||||
pub prefab_path_hash_pre: u8,
|
pub prefab_path_hash_pre: u8,
|
||||||
pub prefab_path_hash_suffix: u32,
|
pub prefab_path_hash_suffix: u32,
|
||||||
|
|
||||||
pub prefab_path_remote_hash_pre: u8,
|
pub prefab_path_remote_hash_pre: u8,
|
||||||
pub prefab_path_remote_hash_suffix: u32,
|
pub prefab_path_remote_hash_suffix: u32,
|
||||||
|
|
||||||
pub controller_path_hash_pre: u8,
|
pub controller_path_hash_pre: u8,
|
||||||
pub controller_path_hash_suffix: u32,
|
pub controller_path_hash_suffix: u32,
|
||||||
|
|
||||||
pub controller_path_remote_hash_pre: u8,
|
pub controller_path_remote_hash_pre: u8,
|
||||||
pub controller_path_remote_hash_suffix: u32,
|
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 camp_id: Option<u32>, // Avatars don't have these
|
||||||
pub lod_pattern_name: String,
|
pub lod_pattern_name: Option<String>,
|
||||||
|
|
||||||
// Creature fields
|
// Creature fields
|
||||||
pub hp_base: f32,
|
pub hp_base: f32,
|
||||||
@ -71,14 +111,9 @@ pub struct Avatar {
|
|||||||
|
|
||||||
//pub prop_grow_curves: Vec<PropGrowConfig>, // TODO: unify with monster!
|
//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
|
// Avatar fields
|
||||||
pub use_type: Option<String>, // TODO: actually an enum
|
pub use_type: Option<String>, // TODO: actually an enum
|
||||||
pub body_type: 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 icon_name: String,
|
||||||
pub side_icon_name: String,
|
pub side_icon_name: String,
|
||||||
pub quality_type: String, // TODO: actually an enum
|
pub quality_type: String, // TODO: actually an enum
|
||||||
@ -87,25 +122,17 @@ pub struct Avatar {
|
|||||||
pub heal_add: f32,
|
pub heal_add: f32,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub healed_add: f32,
|
pub healed_add: f32,
|
||||||
pub combat_config_hash_pre: u8,
|
|
||||||
pub combat_config_hash_suffix: u32,
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub is_range_attack: bool,
|
pub is_range_attack: bool,
|
||||||
pub initial_weapon: u32,
|
pub initial_weapon: u32,
|
||||||
pub weapon_type: String, // TODO: actually an enum
|
pub weapon_type: String, // TODO: actually an enum
|
||||||
pub manekin_path_hash_pre: u8,
|
|
||||||
pub manekin_path_hash_suffix: u32,
|
|
||||||
pub image_name: String,
|
pub image_name: String,
|
||||||
#[serde(flatten)] // Those fields are present or absent all together, so we grouped them
|
#[serde(flatten)] // Those fields are present or absent all together, so we grouped them
|
||||||
pub avatar_gacha_hashes: Option<AvatarGachaHashes>,
|
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 cutscene_show: String,
|
||||||
pub skill_depot_id: u32,
|
pub skill_depot_id: u32,
|
||||||
pub stamina_recover_speed: f32,
|
pub stamina_recover_speed: f32,
|
||||||
pub cand_skill_depot_ids: Vec<u32>,
|
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 manekin_motion_config: u32,
|
||||||
pub desc_text_map_hash: u32,
|
pub desc_text_map_hash: u32,
|
||||||
pub avatar_identity_type: Option<String>, // TODO: actually an enum
|
pub avatar_identity_type: Option<String>, // TODO: actually an enum
|
||||||
|
@ -8,7 +8,7 @@ pub struct AvatarSkill {
|
|||||||
pub ability_name: String,
|
pub ability_name: String,
|
||||||
pub desc_text_map_hash: u32,
|
pub desc_text_map_hash: u32,
|
||||||
pub skill_icon: String,
|
pub skill_icon: String,
|
||||||
pub cost_stamina: Option<u32>,
|
pub cost_stamina: Option<f32>,
|
||||||
pub max_charge_num: u32,
|
pub max_charge_num: u32,
|
||||||
pub trigger_id: Option<u32>,
|
pub trigger_id: Option<u32>,
|
||||||
pub lock_shape: String, // TODO: probably an enum
|
pub lock_shape: String, // TODO: probably an enum
|
||||||
|
@ -60,7 +60,7 @@ pub struct Monster {
|
|||||||
pub exclude_weathers: String,
|
pub exclude_weathers: String,
|
||||||
|
|
||||||
#[serde(rename = "FeatureTagGroupID")]
|
#[serde(rename = "FeatureTagGroupID")]
|
||||||
pub feature_tag_group_id: u32,
|
pub feature_tag_group_id: Option<u32>,
|
||||||
#[serde(rename = "MpPropID")]
|
#[serde(rename = "MpPropID")]
|
||||||
pub mp_prop_id: u32,
|
pub mp_prop_id: u32,
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user