找回密码
 点一下
查看: 1936|回复: 3

对SC2反编译的一些研究成果

[复制链接]
发表于 2018-3-4 02:30:28 | 显示全部楼层 |阅读模式
本帖最后由 chansey 于 2018-3-5 14:52 编辑

## 概述:
本文阐述了我对SC2进行反编译的一些研究成果,其内容主要包括:
反编译出的数据模型文件、通过反编译出的文件生成C++代码和文档、开发了一个小工具帮助你在XML文件里导航。

## 为什么要反编译SC2?:
主要原因还是SC2编辑器的文档不全,特别是数据编辑器部分:我们只能填写实例数据,看不到这些实例数据背后的数据模型,举个例子:
  1. <CAbilEffectTarget id="PsiStorm">
  2.     <Range index="0" value="10"/>
  3.     <Cost index="0">
  4.     <Vital index="Energy" value="60"/>
  5.     </Cost>
  6. </CAbilEffectTarget>
复制代码
这段文本定义了一个效果模板(这个模板是一个CAbilEffectTarget类型的实例),并且设置了这个模板的两个属性Range和Cost。  

注意:模板的属性几乎只能通过数据编辑器的“表格视图”或“细节视图”来设置,想通过修改XML作为一种通用方法来修改模板几乎是不可能的,原因是我们不知道CAbilEffectTarget的描述,例如:CAbilEffectTarget究竟有哪些属性?这些属性是单值还是多值,是多值的话index/value的类型分别是什么?甚至连Effect这个Catalog里究竟有哪些CEffect以及它们的层次关系如何,我们都是不知道的。(SC2的数据编辑器里的XML文本编辑器可没有自动提示功能)

当然,我们可以切换到“表格视图”去查看这些信息,SC2也提供了“显示原始数据 Ctrl+D” 以及 “数据提示查看器 Ctrl+Alt+H”功能,但这始终不方便(也不完整),我们希望有一个统一的界面来查看这些信息。

那么是否有办法提取这些信息?  
目前来看除了反编译之外,似乎没有其他更好的办法。这些信息应该是被内嵌到了编辑器的代码里,没有以数据的形式提供出来。因此,即使你用MPQEditor或CASCExplorer把SC2解包后也拿不到这些信息。

好了,回答了为什么需要反编译SC2的原因后,下面就介绍我对SC2进行反编译后的成果。

## sc2-mined-data
项目地址: https://github.com/chansey97/sc2-mined-data  
这个项目保存了我反编译SC2后得到的一些结构化数据,其中:
  • /2.0.6.25180/gamedata/model.xml  就是上述提到的数据模型的结构化文本表现
比如:CAbilEffectTarget类型的定义在model.xml里大概就是长这个样子:
  1. <core:Class name="CAbilEffectTarget" category="Unknown" superClass="CAbilEffect">
  2.     <core:Field name="CmdButtonArray" type="SAbilCmdButton" array="true" indexEnum="EAbilEffectTargetCmd"/>
  3.     <core:Field name="PlaceUnit" type="CUnitLink"/>
  4.     <core:Field name="AcquireAttackers" type="flag8" minValue="0" maxValue="1"/>
  5.     <core:Field name="FollowRange" type="CFixed" minValue="0" maxValue="500"/>
  6.     <core:Field name="FinishCommand" type="CAbilCommand"/>
  7. </core:Class>
复制代码
注:2.0.6.25180代表的是SC2版本。你没有理解错,我确实是基于2.x版本做的反编译,原因下面再会阐述。


## sc2-gamedata-documentation
项目地址: https://github.com/chansey97/sc2-gamedata-documentation/
该项目基于sc2-mined-data里的数据模型来生成C++代码及文档。

使用C++文档的好处在于它支持 搜索 和 引用跳转,非常方便。
比如:我们可以通过chm搜索CAbilEffectTarget类,在CAbilEffectTarget类下,找到CmdButtonArray属性
CmdButtonArray.PNG
很显然,它是一个多值属性(用了std:vector),并且value类型是SAbilCmdButton,index类型是EAbilEffectTargetCmd,你可以直接通过点击EAbilEffectTargetCmd跳转到EAbilEffectTargetCmd的定义上,这要比直接在xml文件里搜索方便很多。

另外,C++文档还支持Inheritance diagram, Collaboration diagram 以及 Include dependency graph,这些图可以让你对SC2的数据模型有一个全局掌控。
CAbilEffectTarget.PNG Abil.PNG
注意:这个Include dependency graph不是最优的,我只是维持了反编译后数据的原来的样子,暴雪内部代码未必真的就是这样(并且100%不是)。
顺便说一下:如果你想把C++代码的文件组织形式构造成很像暴雪内部代码的样子,需要自己重写C++生成器,按照自己对SC2的理解来划分模块,这并不会很困难,但是我不会去做,我会尽量维持了反编译后数据的原来的样子。况且暴雪内部代码是否真的存在这样的类,也要打个问号。

## sc2-project-template
项目地址: https://github.com/chansey97/sc2-project-template  
这是我基于上面的model.xml写的一个小工具帮助你在XML文件里导航,以下是主要的应用场景:
我们在创作地图时,有时会参考别人的地图。特别是在开发比较复杂的战役/Mod时,甚至可能会去参考官方战役/Mod里对于XML的数据模板。官方的数据模板组织固然很有条理,但由于数据量过于庞大,很容易迷失在这些数据的海洋里。

比方说:你写一个<CActorUnit id="Marine">的模板,这样Marine究竟继承了哪些属性?需要手动到Swarm -> Liberty -> Core 这些Mod里一层层的去查,效率很低。
依靠“表格视图”的颜色区分确实是个办法,但是颜色的数目有限,当继承层次多余颜色数目限制时便无法区分

这个工具可以帮助你分析一个模板的继承层次,比如上面<CActorUnit id="Marine">的例子,可以自动得到如下结果:
CActorUnit-hier.PNG
最上面的是当前模板,后面的是父模板、父模板的父模板、。。。双击后能够自动打开目标文件,并跳到指定行。

具体方法如下:
1. 安装OxygenXML编辑器(我用的是19.0版)

2. 使用MPQEditor或CASCExplorer解包SC2(未必要2.0.6.25180版,可以是最新版)

3. 下载https://github.com/chansey97/sc2-project-template 解压sc2-project-template-master.zip到任意目录,双击sc2-project-template.xpr打开OxygenXML项目

4. 删除蓝色的逻辑目录mods(这个mods里面的目录指向我的硬盘上的SC2,你显然没有的),Add Folder你自己的SC2路径

5. 根据你的SC2路径和地图(地图必须以文件夹形式保存)路径配置configuration.xml,比如:
  1. <configuration>
  2.    <mod href="file:/D:/starcraft2-2.0.6.25180-extracted/mods/Core.SC2Mod/"/>
  3.    <mod href="file:/D:/starcraft2-2.0.6.25180-extracted/mods/Liberty.SC2Mod/"/>
  4.    <mod href="file:/D:/starcraft2-2.0.6.25180-extracted/mods/Swarm.SC2Mod/"/>
  5.    <mod href="file:/D:/TestMap.SC2Map/"/>
  6. </configuration>
复制代码
其中上面的mod代表父mod,下面的mod代表子mod,最后一个就是你当前正在创作的地图(这个4个mod的顺序代表着mod之间的继承层级)

6. 打开XPath Builder View, 选择XPath 3.0
XPath-open-builder.PNG

7. 打开xquery目录,该目录下有3个脚本文件:
entry-ancestor-or-self.xquery 找出当前模板的直接和间接parent模板,并按照层级排序
entry-children.xquery 找出当前模板的所有children模板
entry-descendant.xquery 找出当前模板的所有子孙模板
我们现在需要计算<CActorUnit id="Marine">模板的父层级,当然是选择entry-ancestor-or-self.xquery,双击打开该文件,拷贝除了declare行之外的所有内容到XPath Builder View
XPathBuilder.PNG

8. 打开你想要分析的模板文件,比如:TestMap.SC2Map下的/Base.SC2Data/GameData/ActorData.xml (假定我们正在开发TestMap.SC2Map这张地图),选中你想要分析的模板CActorUnit:  
CActorUnit.PNG

9. 在XPath Builder View上点击Execute XPath按钮,搜索结果会出现在ResultView里。

除了寻找一个模板的父方向的层次外,利用entry-children.xquery 和 entry-descendant.xquery可以寻找一个模板的子模板和子孙模板
比如:想知道有哪些模板继承了 <CActorModel default="1" id="ModelAnimationStyleContinuous">吗?
可以试试entry-children.xquery,方法是类似的。

## FAQ
Q:为什么使用2.0.6.25180版?
A:很惭愧,这是因为我个人的能力所限。最新版本的SC2似乎加了壳了,要破解的话会比较麻烦。(当然也不是不可能,等我有时间还是会去尝试)
就目前而言,我们已经有了2.x的数据模型,如果仅仅是希望对SC2的数据编辑器加深理解的话,这个目的已经达到,况且SC2一直在更新,也没有必要一定追求最新。

## END
最后,希望我的这次研究能帮助大家更深入的理解SC2编辑器,创建出更加有趣的地图。
发表于 2018-3-4 12:24:46 | 显示全部楼层
看的有点懵
回复

使用道具 举报

发表于 2018-3-4 14:57:53 | 显示全部楼层
老哥,要是能反编译SC2的话,能把官方的依赖项反编译成MOD么?
我发现一件事情,单纯的用虚空之遗战役做依赖项的话,加载速度有些偏慢,因为实际上等于加载了6个依赖项——自由之翼的两个,虫群之心的两个,虚空之遗的两个,标准依赖项和战役专属依赖项各一个
如果能专门抽取出来数据库的话,只需要用最简易的自由之翼依赖项,剩下的靠导入数据就能做成一个优化很多的依赖项了

点评

一般有两种办法吧: (1)不使用官方Mod(比如:自由之翼、虫群等),而是开发自己的Mod。自己的Mod只继承Core.SC2Mod,需要的资源按需导入,不用的时候就删除,这样来保证最小。 (2)基于自由之翼、虫群等Mo  详情 回复 发表于 2018-3-6 03:10
回复

使用道具 举报

 楼主| 发表于 2018-3-6 03:10:23 | 显示全部楼层
杰拉鲁星人 发表于 2018-3-4 14:57
老哥,要是能反编译SC2的话,能把官方的依赖项反编译成MOD么?
我发现一件事情,单纯的用虚空之遗战役做依 ...

一般有两种办法吧:

(1)不使用官方Mod(比如:自由之翼、虫群等),而是开发自己的Mod。自己的Mod只继承Core.SC2Mod,需要的资源按需导入,不用的时候就删除,这样来保证最小。

(2)基于自由之翼、虫群等Mod开发,等地图完成之后,再写一个分析器,把那些不用的那些资源统统砍掉,重新构造出一个最小Mod。这个说起来容易,做起来会很难,因为官方的这些Mod大量使用了const、token之类玩意,还有一些表达式嵌在XML属性里(如:OnTerms),这样会导致你的分析器比较难写。另外,你还得扫描galaxy代码(如果你还使用了字符串动态创建Unit的话就更麻烦了。。)

方法(2)几乎没什么意义,为了这点加载速度,付出的代价太大。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 点一下

本版积分规则

Archiver|移动端|小黑屋|地精研究院

GMT+8, 2024-12-23 03:07 , Processed in 0.347193 second(s), 22 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表