feat: prepare experiment push package

This commit is contained in:
2026-06-30 00:08:36 +08:00
parent 3c00659691
commit adc1cd5b91
45 changed files with 7858 additions and 65 deletions
@@ -0,0 +1,32 @@
use bat_adapters::official::launcher::YostarJpInstalledGameBootstrap;
use std::env;
use std::path::PathBuf;
fn main() -> anyhow::Result<()> {
let mut args = env::args().skip(1);
let root = args
.next()
.map(PathBuf::from)
.ok_or_else(|| anyhow::anyhow!("usage: yostar_jp_client_bootstrap <official-game-root>"))?;
let bootstrap =
YostarJpInstalledGameBootstrap::from_game_root(&root).map_err(anyhow::Error::msg)?;
println!("client_root={}", root.display());
println!("app_version={}", bootstrap.app_version);
println!("executable_name={}", bootstrap.executable_name);
println!("executable_params={:?}", bootstrap.executable_params);
println!(
"manifest_basis={}",
bootstrap.basis.as_deref().unwrap_or("<none>")
);
println!(
"manifest_file_count={}",
bootstrap
.manifest_file_count
.map(|count| count.to_string())
.unwrap_or_else(|| "<none>".to_string())
);
Ok(())
}
+93
View File
@@ -0,0 +1,93 @@
use bat_adapters::official::yostar_jp::{
PatchPlatform, YostarJpResourceEndpoint, YostarJpResourceEndpointKind, YostarJpServerInfo,
};
use std::env;
use std::fs;
fn main() -> anyhow::Result<()> {
let args = env::args().collect::<Vec<_>>();
if args.len() < 2 {
print_usage(&args[0]);
std::process::exit(2);
}
let server_info_path = &args[1];
let connection_group = args.get(2).map(String::as_str).unwrap_or("Prod-Audit");
let app_version = args.get(3).map(String::as_str).unwrap_or("1.70.0");
let platforms = args
.get(4)
.map(|value| parse_platforms(value))
.transpose()
.map_err(anyhow::Error::msg)?
.unwrap_or_else(|| vec![PatchPlatform::Windows, PatchPlatform::Android]);
let data = fs::read(server_info_path)?;
let server_info = YostarJpServerInfo::from_slice(&data)?;
let plan = server_info
.discovery_plan(connection_group, app_version, &platforms)
.map_err(anyhow::Error::msg)?;
println!("connection_group={}", plan.connection_group_name);
println!("app_version={}", plan.app_version);
println!(
"bundle_version={}",
plan.bundle_version.as_deref().unwrap_or("<none>")
);
println!("addressables_root={}", plan.addressables_root);
println!();
for endpoint in &plan.endpoints {
println!(
"{}\t{}\t{}",
endpoint_kind_label(endpoint.kind),
platform_label(endpoint),
endpoint.url
);
}
Ok(())
}
fn print_usage(binary: &str) {
eprintln!(
"usage: {binary} <server-info.json> [connection-group] [app-version] [platforms]\n\
platforms: comma-separated Windows,Android"
);
}
fn parse_platforms(value: &str) -> Result<Vec<PatchPlatform>, String> {
value
.split(',')
.map(str::trim)
.filter(|part| !part.is_empty())
.map(parse_platform)
.collect()
}
fn parse_platform(value: &str) -> Result<PatchPlatform, String> {
match value.to_ascii_lowercase().as_str() {
"windows" | "win" => Ok(PatchPlatform::Windows),
"android" => Ok(PatchPlatform::Android),
_ => Err(format!("unsupported platform: {value}")),
}
}
fn endpoint_kind_label(kind: YostarJpResourceEndpointKind) -> &'static str {
match kind {
YostarJpResourceEndpointKind::TableCatalog => "table_catalog",
YostarJpResourceEndpointKind::TableCatalogHash => "table_catalog_hash",
YostarJpResourceEndpointKind::AddressablesCatalog => "addressables_catalog",
YostarJpResourceEndpointKind::AddressablesCatalogHash => "addressables_catalog_hash",
YostarJpResourceEndpointKind::BundlePackingInfo => "bundle_packing_info",
YostarJpResourceEndpointKind::BundlePackingInfoHash => "bundle_packing_info_hash",
YostarJpResourceEndpointKind::MediaCatalog => "media_catalog",
YostarJpResourceEndpointKind::MediaCatalogHash => "media_catalog_hash",
}
}
fn platform_label(endpoint: &YostarJpResourceEndpoint) -> &'static str {
endpoint
.platform
.map(PatchPlatform::as_str)
.unwrap_or("shared")
}
+72
View File
@@ -0,0 +1,72 @@
use bat_adapters::official::inventory::YostarJpDownloadInventory;
use bat_adapters::official::yostar_jp::{
verified_official_platforms, PatchPlatform, YostarJpResourceRoot,
};
use std::env;
use std::fs;
fn main() -> anyhow::Result<()> {
let args = env::args().collect::<Vec<_>>();
if args.len() < 5 {
print_usage(&args[0]);
std::process::exit(2);
}
let root_token = &args[1];
let bundle_packing_info_path = &args[2];
let table_catalog_path = &args[3];
let media_catalog_path = &args[4];
let platforms = args
.get(5)
.map(|value| parse_platforms(value))
.transpose()
.map_err(anyhow::Error::msg)?
.unwrap_or_else(verified_official_platforms);
let inventory = YostarJpDownloadInventory::from_catalog_bytes(
&fs::read(bundle_packing_info_path)?,
&fs::read(table_catalog_path)?,
&fs::read(media_catalog_path)?,
);
let root = YostarJpResourceRoot::from_root_token(root_token).map_err(anyhow::Error::msg)?;
println!(
"bundle_patch_pack_count={}",
inventory.bundle_patch_pack_names.len()
);
println!("table_file_count={}", inventory.table_file_names.len());
println!("media_file_count={}", inventory.media_file_names.len());
println!();
for url in inventory
.direct_download_urls_for_platforms(&root, &platforms)
.map_err(anyhow::Error::msg)?
{
println!("{url}");
}
Ok(())
}
fn print_usage(binary: &str) {
eprintln!(
"usage: {binary} <root-token> <BundlePackingInfo.bytes> <TableCatalog.bytes> <MediaCatalog.bytes> [platforms]"
);
}
fn parse_platforms(value: &str) -> Result<Vec<PatchPlatform>, String> {
value
.split(',')
.map(str::trim)
.filter(|part| !part.is_empty())
.map(parse_platform)
.collect()
}
fn parse_platform(value: &str) -> Result<PatchPlatform, String> {
match value.to_ascii_lowercase().as_str() {
"windows" | "win" => Ok(PatchPlatform::Windows),
"android" => Ok(PatchPlatform::Android),
_ => Err(format!("unsupported platform: {value}")),
}
}