Skip to content

Commit

Permalink
Merge pull request #56 from IceDynamix/local-resources
Browse files Browse the repository at this point in the history
Download resources in build script instead of at runtime
  • Loading branch information
IceDynamix authored Aug 23, 2024
2 parents 0723fb6 + 6d6a991 commit d62302b
Show file tree
Hide file tree
Showing 8 changed files with 267 additions and 159 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 8 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,20 @@ homepage = "https://github.com/IceDynamix/reliquary-archiver"

[dependencies]
base64 = "0.22.1"
clap = { version = "4.5.14", features = ["derive"] }
clap = { version = "4.5.16", features = ["derive"] }
color-eyre = "0.6.3"
pcap = "2.0.0"
protobuf = "~3.4.0" # match the protobuf version used in reliquary-codegen
serde = { version = "1.0.205", features = ["derive"] }
serde_json = "1.0.122"
serde = { version = "1.0.208", features = ["derive"] }
serde_json = "1.0.125"
tracing = "0.1.40"
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "json"] }
ureq = { version = "2.10.1", features = ["json"] }
ureq = { version = "2.10.1" }
reliquary = { git = "https://github.com/IceDynamix/reliquary", tag = "v3.1.0" }

[dependencies.reliquary]
git = "https://github.com/IceDynamix/reliquary"
tag = "v3.1.0"
[build-dependencies]
ureq = { version = "2.10.1", features = ["json"] }
reliquary = { git = "https://github.com/IceDynamix/reliquary", tag = "v3.1.0" }

[profile.release]
opt-level = "z" # optimize for size
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ to output logs to a file, provide `--log-path <path>`. file logs will always be
to this directory was enough to link successfully
- `cargo build` / `cargo run`
note that the necessary resource files are downloaded in the build script and compiled into the binary.
## library
want to do more with packet parsing? check out the
Expand Down
54 changes: 54 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use std::env;
use std::fs::File;
use std::path::Path;

use reliquary::resource::excel::{
AvatarConfigMap, AvatarSkillTreeConfigMap, EquipmentConfigMap, MultiplePathAvatarConfigMap,
RelicConfigMap, RelicMainAffixConfigMap, RelicSetConfigMap, RelicSubAffixConfigMap,
};
use reliquary::resource::ResourceMap;
use ureq::serde_json::Value;

const BASE_RESOURCE_URL: &str = "https://raw.githubusercontent.com/Dimbreath/StarRailData/master";
const KEY_URL: &str =
"https://raw.githubusercontent.com/juliuskreutz/stardb-exporter/master/keys.json";

fn main() {
println!("cargo::rerun-if-changed=Cargo.toml");

download_config::<AvatarConfigMap>();
download_config::<AvatarSkillTreeConfigMap>();
download_config::<EquipmentConfigMap>();
download_config::<MultiplePathAvatarConfigMap>();
download_config::<RelicConfigMap>();
download_config::<RelicMainAffixConfigMap>();
download_config::<RelicSetConfigMap>();
download_config::<RelicSubAffixConfigMap>();

download_and_write_to_out(
"TextMapEN.json",
format!("{BASE_RESOURCE_URL}/TextMap/TextMapEN.json").as_str(),
);
download_and_write_to_out("keys.json", KEY_URL);
}

fn download_config<T: ResourceMap>() {
let file_name = T::get_json_name();

let url = format!("{BASE_RESOURCE_URL}/ExcelOutput/{file_name}");

download_and_write_to_out(file_name, &url);
}

fn download_and_write_to_out(file: &str, url: &str) {
// downloaded files are in pretty format, deserialize and serialize
// to compress file size
let value: Value = ureq::get(url).call().unwrap().into_json().unwrap();

let out_dir = env::var_os("OUT_DIR").unwrap();
let out_path = Path::new(&out_dir).join(file);

let mut file = File::create(out_path).unwrap();

ureq::serde_json::to_writer(&mut file, &value).unwrap();
}
102 changes: 102 additions & 0 deletions src/export/database.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
use base64::prelude::BASE64_STANDARD;
use base64::Engine;
use reliquary::resource::excel::{
AvatarConfigMap, AvatarSkillTreeConfigMap, EquipmentConfigMap, MultiplePathAvatarConfigMap,
RelicConfigMap, RelicMainAffixConfigMap, RelicSetConfigMap, RelicSubAffixConfigMap,
};
use reliquary::resource::text_map::TextMap;
use serde::de::DeserializeOwned;
use std::collections::HashMap;
use tracing::{info, instrument};

pub struct Database {
pub avatar_config: AvatarConfigMap,
pub avatar_skill_tree_config: AvatarSkillTreeConfigMap,
pub equipment_config: EquipmentConfigMap,
pub multipath_avatar_config: MultiplePathAvatarConfigMap,
pub relic_config: RelicConfigMap,
pub relic_set_config: RelicSetConfigMap,
pub relic_main_affix_config: RelicMainAffixConfigMap,
pub relic_sub_affix_config: RelicSubAffixConfigMap,
pub text_map: TextMap,
pub keys: HashMap<u32, Vec<u8>>,
}

impl Database {
#[instrument(name = "config_map")]
pub fn new() -> Self {
info!("using local database");

// config files are downloaded by the build script
//
// i *would* create a fn load_local_config<T: ResourceMap + DeserializeOwned>()
// to avoid duplicating the json file names by using T::get_json_name,
// but concat!() only takes string literals. it doesn't even take `&'static str`!!
// https://github.com/rust-lang/rust/issues/53749
Database {
avatar_config: Self::parse_json(include_str!(concat!(
env!("OUT_DIR"),
"/AvatarConfig.json"
))),
avatar_skill_tree_config: Self::parse_json(include_str!(concat!(
env!("OUT_DIR"),
"/AvatarSkillTreeConfig.json"
))),
equipment_config: Self::parse_json(include_str!(concat!(
env!("OUT_DIR"),
"/EquipmentConfig.json"
))),
multipath_avatar_config: Self::parse_json(include_str!(concat!(
env!("OUT_DIR"),
"/MultiplePathAvatarConfig.json"
))),
relic_config: Self::parse_json(include_str!(concat!(
env!("OUT_DIR"),
"/RelicConfig.json"
))),
relic_set_config: Self::parse_json(include_str!(concat!(
env!("OUT_DIR"),
"/RelicSetConfig.json"
))),
relic_main_affix_config: Self::parse_json(include_str!(concat!(
env!("OUT_DIR"),
"/RelicMainAffixConfig.json"
))),
relic_sub_affix_config: Self::parse_json(include_str!(concat!(
env!("OUT_DIR"),
"/RelicSubAffixConfig.json"
))),
text_map: Self::parse_json(include_str!(concat!(env!("OUT_DIR"), "/TextMapEN.json"))),
keys: Self::load_local_keys(),
}
}

fn parse_json<T: DeserializeOwned>(str: &'static str) -> T {
serde_json::de::from_str(str).unwrap()
}

fn load_local_keys() -> HashMap<u32, Vec<u8>> {
let keys: HashMap<u32, String> =
Self::parse_json(include_str!(concat!(env!("OUT_DIR"), "/keys.json")));
let mut keys_bytes = HashMap::new();

for (k, v) in keys {
keys_bytes.insert(k, BASE64_STANDARD.decode(v).unwrap());
}

keys_bytes
}

pub(crate) fn lookup_avatar_name(&self, avatar_id: u32) -> Option<String> {
if avatar_id == 0 {
return None;
}

if avatar_id >= 8000 {
Some("Trailblazer".to_owned())
} else {
let cfg = self.avatar_config.get(&avatar_id)?;
cfg.AvatarName.lookup(&self.text_map).map(|s| s.to_string())
}
}
}
Loading

0 comments on commit d62302b

Please sign in to comment.