【拆包】如何拆卡牌资源以外的各类资源

分类: 365bet正网注册 时间: 2025-12-30 09:58:42 作者: admin 阅读: 4217

这几天排炉石太慢了,所以趁着间隙研究了一下拆包

零、准备工作

下载AssetStudio.CLI或者类似的可以用命令行调用的拆包工具

一门可以调用命令行的语言(最好支持多线程)

直接用AssetStudio的GUI,不用任何编程语言也可以,但是纯手动的走复杂的拆包流程会很痛苦。

一、前情提要

如何通过拆包定向查找素材? ——炉石传说拆包教学(1)

THorougH 2023-07-17

关于炉石拆包的流程和经验分享

穿山辛 2024-05-06

由于是打牌间隙写得,部分内容会写得比较糙,看不懂的时候可以回去翻翻,特别是th的那篇文章,讲得比我这里细致。(顺便催更拆包教学2)

二、AssetStudio.CLI的使用

调用的标准格式为:AssetStudio [options]

其中input_path可以是文件,也可以是文件夹,output_path则必须是文件夹

注:对于路径里面有空格等情况,可以用""将其包裹起来,其他地方的字符串也是同理

options很多,本文并不会全部提及,而且我使用的CLI和你用的可能存在版本差异,如想深入研究可以进CLI的github界面看readme文件,或者AssetStudioCli -?来获取相关信息

--game 大概是针对特定游戏做出来的设定,必须填,我一般用的--game Normal

--types 允许筛选出特定类型,支持"A|B"这样筛选多个类型,常见类型比如MonoBehaviour(文本信息)、Texture2D(图片)、AudioClip(音乐)等,不过我用的这个CLI似乎有点毛病,types选择Texture2D后不能正常导出

--names 通过资源文件的名字进行筛选,支持正则,不区分大小写

--containers 通过container进行筛选,对于炉石来说,container即guid

注:看源代码会发现,names会在加载资源之前就做好判断,containers则是加载资源之后再进行移除,所以速度上来说names更快一些。

--group_assets 有ByContainer BySource ByType None四种模式,默认ByType

ByContainer导出到output/guid/文件,如果一个文件中有很多需要资源导出,推荐使用这个方案

BySource会导出到output/xxx.unity3d_exports/CAB-xxx/文件,想要确定一个资源是出自哪个文件的时候可以用这个模式

ByType会导出到output/type/文件,没啥用

None则是导出到output/文件,需要注意,input为文件夹的时候,对于同名文件,CLI并不会做好保护,有时导出文件会被覆盖。

map

--map_name 将会导出到output/map_name[.map_type]

--map_op 选择导出模式,我直接选择的ALL

--map_type 导出格式,我这里选择的JSON

map文件最重要的性质是可以导出pathID,这是cli导出pathID的唯一方案。

三、一些前置概念

上文中不加说明的提到了一些概念,这里进行一下补充。

3.1 guid(global unique id)

一串32位的十六进制数,从命名来判断应该是全局唯一的,也即AssetStudio中的Container

在各种MonoBehaviour文件中常常这样出现,即一个「文件名:guid」:

"m_detailsTexture": "Default_Texture_DetailsFallback.tif:cc27f02843038f942ab18443d5b08305",

其中,文件名并不准确,基本可以当作没用。

在asset_manifest.unity3d的base_assets_catalog文件中,存在着这样的对应关系:

m_assets[n].guid->m_bundleNames[ m_assets[n].bundleId ]

guid -> 对应的unity3d文件名

对于一些国服特供的内容则需要在asset_manifest_zhcn.unity3d找到asset_catalog_locale_zhCN文件:

m_assets[n].baseGuid->m_assets[n].guid->m_bundleNames[ m_assets[n].bundleId ]

原本的guid -> 新的guid -> 对应的unity3d文件名

如此找到新的guid和对应文件。

3.2 pathid

一串int64的数字,应该不保证全局唯一性,不过数字够大也几乎可以认为是唯一的。

在各种MonoBehaviour文件中常常这样出现:

"m_Script": {

"m_FileID": 0,

"m_PathID": 485247164769422224

},

其中FileID=0似乎代表就在同一个文件中,不过我通常没有搭理这个。

举例来说,如果上述的文本信息来自initial_bgs_global-c05a2d0e-prefab-0.unity3d中

那么想要找的东西总会在以下文件中,把下面的文件全拆出来,然后生成map文件,接着根据PathID即可找到对应的guid,group_assets 选择ByContainer模式,根据guid即可获取文件。

如果想找的是图片,那么图片总会出现在prefab/texture结尾的文件中,可以排除掉material之类的文件。

需要注意前面的部分,有些是_base_,有些是_bgs_,这几个文件都有可能,所以搜索相关文件时最好只搜含有c05a2d0e的文件

3.3 多语言

"m_collectionName": {

"m_locValues": [

"Classic",

"Klassisch",

"Clásico",

"Clásico",

"Classique",

"Classico",

"クラシック",

"기본",

"Klasyczne",

"Clássico",

"Классика",

"คลาสสิค",

"经典",

"經典"

],

"m_locId": 2824665

},

在更早期的版本中,这里是"m_collectionName":{"m_currentLocaleValue":"经典"}

想要更好的兼容性可以考虑两者都兼顾一下。

四、一些示例

4.1 水印

"Records": [

{

"m_ID": 1001,

"m_isCollectible": 1,

"m_isCoreCardSet": 0,

"m_legacyCardSetEvent": 164,

"m_contentLaunchEvent": 307,

"m_isFeaturedCardSet": 0,

"m_standardEvent": 10000140,

"m_craftableWhenWild": 0,

"m_cardWatermarkTexture": "ICCIcon.tif:461f6ce4699d457429c62796700085ed",

"m_setFilterEvent": 203,

"m_filterIconTexture": "Filter_Icons.tif:87d111b8cf28af64ca1a5d50ce478c31",

"m_filterIconOffsetX": 0.75,

"m_filterIconOffsetY": 0.0,

"m_releaseOrder": 1009,

"m_isExpansionCardSet": 1

},

...

]

其中的m_ID即set id,不过并没有特别好的方案获取到扩展包名字和set id的对应关系,就按下不表。

在dbf.unity3d->CARD_SET里面可以找到m_cardWatermarkTexture,其guid对应的即是水印了

遍历提取出所有的guid,找到对应的文件,会发现主要就集中在少数几个文件中,不妨将所有文件按照groups_assets="ByContainer"解压缩,然后遍历去找output/guid下面的文件,即可提取出来。

4.2 卡背

"Records": [

{

"m_ID": 0,

"m_data1": 0,

"m_source": 0,

"m_enabled": 1,

"m_sortCategory": 1,

"m_sortOrder": 1,

"m_prefabName": "Card_Back_Default.prefab:581a152092244499aa68d46c804051f1",

"m_name": {

"m_locValues": [

...,

"怀旧经典",

"經典"

],

"m_locId": 20881

},

"m_description": {

"m_locValues": [

...,

"经典款,总会给你带来最初的感觉。",

"經典設計,成就永恆。"

],

"m_locId": 20882

},

"m_isRandomCardBack": 0,

"m_collectionManagerPurchaseProductId": 0

},

...,

]

在dbf.unity3d->CARD_BACK可以找到上面这一段,有名字,有描述,这很不错,导出后可以改文件名,使其包含这些信息。

不过m_prefabName对应的文件就不是很舒服了,里面全是fileID和pathID:

{

"m_GameObject": {

"m_FileID": 0,

"m_PathID": -742154249242800108

},

"m_Enabled": 1,

"m_Script": {

"m_FileID": 0,

"m_PathID": -7755206838764419031

},

...,

"m_CardBackTexture": {

"m_FileID": 9,

"m_PathID": 2050936170184355078

},

....

}

当然,pathID只是麻烦了一点,并非不能解决。

首先先看看m_prefabName找出来的文件都放在哪儿的:

essential_base_global-prefab-0.unity3dinitial_base_global-3b2513bf-prefab-0.unity3dinitial_base_global-34be6ac6-prefab-0.unity3dinitial_base_global-34be6ac6-prefab-1.unity3d

然后找出所有对应的texture文件:

essential_base_global-texture-0.unity3dessential_base_global-texture-1.unity3dessential_base_global-texture-2.unity3dinitial_base_global-3b2513bf-texture-0.unity3dinitial_base_global-34be6ac6-texture-0.unity3dinitial_base_global-34be6ac6-texture-1.unity3dinitial_base_global-34be6ac6-texture-2.unity3dinitial_base_global-34be6ac6-texture-3.unity3dinitial_base_global-34be6ac6-texture-4.unity3dinitial_base_global-34be6ac6-texture-5.unity3dinitial_base_global-34be6ac6-texture-6.unity3dinitial_base_global-34be6ac6-texture-7.unity3d

按照guid分类提取出来,并建立map文件。

由于整个过程是逐个文件进行的,map文件也会建立多个,最好是提取一个文件后立刻解析并删除对应的map文件。

之后根据map文件,由pathID找到对应guid,即可回归到类似水印的提取过程中去。

4.3 酒馆表情

"Records": [

{

"m_ID": 1,

"m_enabled": 1,

"m_rarityId": 2,

"m_collectionShortName": {

"m_locValues": [

...,

"欢乐的牛头人",

"快樂牛頭人"

],

"m_locId": 2833718

},

"m_description": {

"m_locValues": [

...,

"选择你的英雄,在对战中发送表情。",

"在對戰中選擇你的英雄即可使用表情符號。"

],

"m_locId": 2853032

},

"m_animationPath": "Default_Emotes_2.controller:1cc6b65bfe961db489aac3784148c257",

"m_xOffset": 0.0,

"m_zOffset": -0.079,

"m_isDefault": 1,

"m_isAnimating": 0,

"m_borderType": 0

},

同卡背一样,这一次也有名字和描述,挺不错的。

但是这次的m_animationPath没能导出任何东西。

使用GUI到对应的文件查看,发现preview和dump一样,看来是真的导出不了。

而且这里面也没有找到pathid的线索

不过,还是可以像之前卡背的思路一样,提取所有相关的prefab文件和texture文件,然后全部导出

这次根据m_animationPath前面的文件名来进行判断,比如Default_Emotes_2.png即是欢乐的牛头人。

不过后面那个文件名并不准确,有些时候会有乌龙,比如下图这里就多打了一个_final

又比如下图这里多打了一个空格1

这种情况只能自己灵活处理一下了,好在大部分时候都是对的

五、结语

相关代码链接:https://pan.baidu.com/s/1-N6Y4KpzK2Z7TENT2l-zSg?pwd=1234

想直接用可以运行bat。不过如果代码哪里写得有问题,我也懒得修,毕竟本来也只是写着练手玩的。

正巧排进酒馆了,就此搁笔。

相关文章

365bet正网注册

奔驰g500油耗多少公里 奔驰g500一公里多少油钱

365bet正网注册

菲尔顿宠物:母猫绝育的疼痛感多久能减轻

be365备用网址

1一50年都是什么婚?不同年份的婚姻叫法和意义