WAD、BIN、BNK、WPK文件简单处理
Project description
league-tools
WAD、BIN、BNK、WPK文件简单处理
介绍
一个用于处理英雄联盟(League of Legends)数据文件的 Python 库,提供对 WAD、BIN、BNK 和 WPK 格式文件的底层解析功能。
- WAD (
.wad.client): 游戏资源包,包含游戏中的模型、贴图、音频等各种资源。 - BIN (
.bin): 游戏内的数据文件,用于定义英雄、皮肤、技能等的属性和逻辑。 - BNK (
.bnk): Wwise SoundBank 格式,包含音频元数据和事件信息。 - WPK (
.wpk): Wwise Packed File,通常用于打包多个.wem音频文件。
本库专注于提供稳定、独立的解析器,方便开发者进行二次开发。
安装
pip install league-tools
pip install -e git+https://github.com/Virace/py-bnk-extract@package#egg=league_tools
开发环境(Windows / WSL)
项目在 Windows 与 WSL 共享工作区时,请不要共用同一个 .venv,建议按平台分离:
- Windows:
.venv-win - WSL:
.venv-wsl
WSL 下可直接运行:
./scripts/_uv.sh init
./scripts/_uv.sh run pytest -q
该脚本会统一设置项目内环境目录并调用 uv,默认使用:
.venv-wsl.cache/uv(以及.cache/).config/.state/
兼容旧入口(等价于 ./scripts/_uv.sh init):
./scripts/setup_wsl_env.sh
另外,仓库中的自动化测试应放在 tests/ 并遵循 pytest 规范;手动调试脚本请放到 manual_tests/(该目录默认不提交)。
维护与发布流程
维护期的开发、分支切换、构建与发布流程详见:
测试样本准备(WAD 自动提取)
可在运行测试前,自动从本地游戏目录提取样本:
./scripts/_uv.sh run python scripts/extract_wad_fixtures.py \
--game-root "/mnt/d/Games/Tencent/WeGameApps/英雄联盟/Game/DATA/FINAL/Champions" \
--locale zh_CN \
--sample-size 5 \
--skin 1 \
--output tests/fixtures/external
说明:
- 默认使用脚本内置英雄池(
--champion-source hardcoded)并按顺序抽样,保证稳定。 - 如需从 CommunityDragon 最新列表获取候选英雄,可加
--champion-source communitydragon。 - 需要随机化时显式加
--shuffle(可配合--seed复现)。
也可让 pytest 在会话开始前自动执行提取:
./scripts/_uv.sh run pytest -q \
--prepare-fixtures \
--fixture-game-root "/mnt/d/Games/Tencent/WeGameApps/英雄联盟/Game/DATA/FINAL/Champions" \
--fixture-sample-size 5
使用
以下是如何使用本库解析四种核心文件格式的示例。
日志输出控制(默认关闭)
本库默认关闭 loguru 输出,避免作为依赖库时污染上游项目日志。
如需输出日志,请在上游项目中手动开启:
from league_tools import enable_logging, disable_logging
# 手动开启日志输出
enable_logging()
# ... 执行业务逻辑 ...
# 可选:在不再需要日志时关闭
disable_logging()
解析 WPK 文件
WPK 文件是一个音频包,通常包含多个 .wem 文件。
from pathlib import Path
from league_tools.formats.wpk.parser import WPK
# 初始化WPK解析器
wpk_file = WPK('path/to/your/audio.wpk')
# 提取所有包含完整数据的音频文件
# extract_files() 返回一个 WemFile 对象的列表
wem_files = wpk_file.extract_files()
# 创建输出目录
output_dir = Path('./wpk_output')
output_dir.mkdir(exist_ok=True)
# 遍历并保存文件
for wem in wem_files:
# WemFile.id 是从文件名解析出的数字ID
# WemFile.data 包含了文件的二进制数据
print(f"提取文件: ID={wem.id}, 大小={wem.length}字节")
# 定义输出路径
output_path = output_dir / f"{wem.id}.wem"
# WemFile对象提供了save_file方法,可以直接保存
if wem.data:
try:
wem.save_file(output_path)
except Exception as e:
print(f"保存文件 {wem.id}.wem 失败: {e}")
解析 BNK 文件
BNK 文件是 Wwise SoundBank,它包含音频文件的索引(DIDX)和数据(DATA)。本库的 BNK 解析器会自动处理这两部分,并提供统一的接口。
from pathlib import Path
from league_tools.formats.bnk.parser import BNK
# 初始化BNK解析器
bnk_file = BNK('path/to/your/audio.bnk')
# 检查BNK文件版本是否受支持
if not bnk_file.is_version_supported():
print(f"警告: 不支持的BNK版本 {bnk_file.get_soundbank_version()}")
# 提取所有音频文件
# 如果BNK文件包含DATA区块,返回的WemFile对象将包含完整的二进制数据
wem_files = bnk_file.extract_files()
# 创建输出目录
output_dir = Path('./bnk_output')
output_dir.mkdir(exist_ok=True)
# 遍历并保存文件
for wem in wem_files:
print(f"提取文件: ID={wem.id}, 大小={wem.length}字节")
# 定义输出路径
output_path = output_dir / f"{wem.id}.wem"
# BNK解析器已经将数据填充到wem.data属性中
# 可以直接使用 WemFile 内置的保存方法
if wem.data:
try:
wem.save_file(output_path)
except Exception as e:
print(f"保存文件 {wem.id}.wem 失败: {e}")
解析 WAD 文件
WAD 文件是主要的游戏资源存档。你可以根据文件路径来提取其中的文件。
from pathlib import Path
from league_tools.formats.wad.parser import WAD
# 初始化WAD解析器
wad_file = WAD('path/to/your/archive.wad.client')
# 查看WAD文件中的部分文件信息
# WAD.files 是一个 WADSection 对象的列表
print(f"WAD文件包含 {len(wad_file.files)} 个文件。")
for file_entry in wad_file.files[:5]:
# WADSection.path_hash 是文件的路径哈希
print(f" - 文件哈希: {file_entry.path_hash:x}, 大小: {file_entry.size}")
# 创建输出目录
output_dir = Path('./wad_output')
output_dir.mkdir(exist_ok=True)
# 提取单个已知路径的文件
# 注意: WAD内部不存储完整路径,需要提供路径来进行哈希匹配
target_file_path = 'assets/sounds/vo/champions/gwen/skin01/vo_gwen_skin01_events.bnk'
# 直接提取到目录
wad_file.extract([target_file_path], out_dir=output_dir)
print(f"尝试提取文件到: {output_dir / Path(target_file_path).name}")
解析 BIN 文件
BIN 文件通常用于定义游戏对象的属性,例如英雄皮肤的音频事件。
from league_tools.formats.bin.parser import BIN
# 初始化BIN解析器
bin_file = BIN('path/to/your/skin.bin')
# 检查是否为皮肤文件
if not bin_file.is_skin:
print("这是一个通用的BIN文件,而非皮肤文件。")
# 遍历文件中的音频组 (AudioGroup)
# 每个AudioGroup包含一个或多个BankUnit
for i, audio_group in enumerate(bin_file.data):
print(f"--- 音频组 #{i + 1} ---")
# 遍历BankUnit (通常按类别划分,如Attack, Spell, Emote)
for unit in audio_group.bank_units:
print(f" 类别: {unit.category}")
print(f" 关联的Bank文件: {unit.bank_path}")
# 打印此类别下的所有音频事件
for event in unit.events:
# event.string 是事件名称, e.g., "Play_vo_Gwen_Skin01_Attack2D_3"
# event.hash 是事件名称的FNV-1a 32位哈希
print(f" - 事件: {event.string} (哈希: {event.hash:x})")
# 如果音频组有关联的音乐数据
if audio_group.music:
print(" 关联音乐数据:")
print(f" - 胜利音乐: {audio_group.music.victory_music_id}")
print(f" - 失败音乐: {audio_group.music.defeat_music_id}")
参考
感谢前人栽树
- WPK参考 Morilli 编写的解包工具 bnk-extract。
- WAD 文件结构及部分逻辑来源于 CommunityDragon/CDTB 和 Pupix/lol-file-parser。
- BNK 文件结构参考自 Xentax Wiki。
维护者
Virace
- blog: 孤独的未知数
感谢
-
@Morilli, bnk-extract
-
@Pupix, lol-file-parser
-
@CommunityDragon, CDTB
-
@vgmstream, vgmstream
-
以及JetBrains提供开发环境支持
许可证
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file league_tools-1.1.2.tar.gz.
File metadata
- Download URL: league_tools-1.1.2.tar.gz
- Upload date:
- Size: 128.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6a857d276f0ac64b0ceb12c9dc24a58797823505716127c4f6f8b18f4e8909a9
|
|
| MD5 |
e29e1825f75a4f7170a5705dd8baeaf8
|
|
| BLAKE2b-256 |
87c69ea315a35b2ec542663bdf33d66a8255c98c221b7e5aa505d193036a1a90
|
Provenance
The following attestation bundles were made for league_tools-1.1.2.tar.gz:
Publisher:
python-publish.yml on Virace/league-tools
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
league_tools-1.1.2.tar.gz -
Subject digest:
6a857d276f0ac64b0ceb12c9dc24a58797823505716127c4f6f8b18f4e8909a9 - Sigstore transparency entry: 1018682357
- Sigstore integration time:
-
Permalink:
Virace/league-tools@257008f094ea85004a6a3775cfac27c49904484f -
Branch / Tag:
refs/tags/v1.1.2 - Owner: https://github.com/Virace
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@257008f094ea85004a6a3775cfac27c49904484f -
Trigger Event:
release
-
Statement type:
File details
Details for the file league_tools-1.1.2-py3-none-any.whl.
File metadata
- Download URL: league_tools-1.1.2-py3-none-any.whl
- Upload date:
- Size: 93.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c8a3483395563dd7bd21439aeea3dd143cec974256a6c7c276ffbb9b7e2c922c
|
|
| MD5 |
95b102b2d29c1cdc703b292420c64336
|
|
| BLAKE2b-256 |
8f7a2c1b999ca4155a474b6f9db879aa048a3dd2f3e67782996edc64224b96e8
|
Provenance
The following attestation bundles were made for league_tools-1.1.2-py3-none-any.whl:
Publisher:
python-publish.yml on Virace/league-tools
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
league_tools-1.1.2-py3-none-any.whl -
Subject digest:
c8a3483395563dd7bd21439aeea3dd143cec974256a6c7c276ffbb9b7e2c922c - Sigstore transparency entry: 1018682373
- Sigstore integration time:
-
Permalink:
Virace/league-tools@257008f094ea85004a6a3775cfac27c49904484f -
Branch / Tag:
refs/tags/v1.1.2 - Owner: https://github.com/Virace
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@257008f094ea85004a6a3775cfac27c49904484f -
Trigger Event:
release
-
Statement type: