dst 1

阅读DST源码的前置

路径结构

默认情况下,DST有两个根目录。

  • 游戏安装根目录:存储安装或初始化时所需的执行文件、静态资源等。一般情况下为xxx/Don't Starve Together,如果是steam用户则xxx为steam安装路径/steamapps/common。为描述方便,后续将以/dst_main指代游戏安装根目录。
  • 游戏数据根目录:存储运行时数据,包含存档、日志等。一般情况下为xxx/Klei/DoNotStarveTogether,如果是windows则xxx为C:/Users/用户名/Documents。为描述方便,后续将以/dst_data指代游戏数据根目录。

/dst_main目录结构

1
2
3
4
5
6
7
8
9
10
bin: 可执行文件(含dll)
bin64: 64位可执行文件(含dll)
cached_mods: mod缓存相关
cached_mod_manifests: mod缓存相关
data: 核心,含源码、静态资源等
DXRedist: 未知
installscript_new.vdf: 未知
mods: mod相关
VCRedist: 未知
version.txt:版本号

/dst_main/version.txt示例。单纯只有一行,与官方更新日志的编号保持一致

1
658642

/dst_main/data目录结构

1
2
3
4
5
6
7
8
9
10
11
12
anim: 未知
bigportraits: 未知
databundles: 核心,存储源码及部分静态资源
fx: 未知
images: 未知
levels: 未知
minimap: 未知
movies: 未知
scripts_readme.txt: scripts介绍(目前/dst_main/data/databundles/scripts.zip的优先级高于/dst_main/data/scripts)
sound: 未知
unsafedata: 可写入的静态资源(主要给mod开发者使用)
unsafedata_readme.txt: unsafedata介绍

/dst_main/data/databundles目录结构

1
2
3
4
5
6
7
8
anim_dynamic.zip: 未知
bigportraits.zip: 未知
fonts.zip: 未知
hashes.txt: 用于检查下载的完整性和正确性
images.zip: 未知
klump.zip: 未知
scripts.zip: 源码
shaders.zip: 未知

/dst_main/data/databundles/hashes.txt示例。首行的两个字段可能代表文件和对应的hash值,在本地用certutil -hashfile <filepath> <algorithm>尝试md2、md4、md5、sha1、sha256等算法后发现都不一致?甚至结果长度也不一致?第二行的值由版本号计算得到,计算过程猜测为是切割版本号的每个数字得到一个数组,将数组中所有元素的左侧加3,按索引增加顺序合并所有元素,如果结果不满16位则在左侧补充0

1
2
databundles/scripts.zip BFACF8EFF2D91219
revision 0000363538363432

如何debug

dst采用lua进行开发,dst mod official dev doc, 因此首先需要安装lua,windows平台也可以选择lua-for-windows,结束后用lua -v检查一下
提供一段测试代码,使用lua xxx.lua运行

1
2
3
4
5
6
7
8
9
10
11
12
13
-- 打开文件并读取内容
local file = io.open("hashes.txt", "r")
local content = file:read("*a") -- *a 表示读取整个文件
file:close()
x = 10
local y = 20
debug.debug() -- 运行到这里会进行交互模式
-- 处理内容
print("File content:")
print(content)

-- 计算字符串长度
print("Length of content:", #content)

一些注意点

  • debug.debug()的交互模式不同与lua命令行的交互模式,前者只能使用完整的lua语句,后者可以用= x等缩写
  • 交互模式下不能直接读写栈上变量(用local声明的),需要使用debug.getlocal(level,index)debug.setlocal(level,index,new_value)
  • 假设使用lua test.lua启动上述测试代码并成功进入debug的交互模式,则对应的入栈先后顺序为lua本体->test.lua->lua.debug本体->在debug交互模式下输入的代码

dst源码开放,理论上可以直接在必要停顿处插入debug.debug()语句来进行断点调试,但实际上存在一部分核心组件用引擎实现的,引擎底层是c++(猜测是公司内部引擎),因此在单独摘取scripts文件夹时,并直接执行lua main.lua并不能成功,其中的TheSim、TheNet等组件在调用其方法时会报空值错误attempt to index global 'TheSim' (a nil value)论坛上列出的引擎组件/方法清单

暂时没有找到优雅的解决方法(从main文件成功启动debug),临时解决如下:1.摘取部分目标代码,另起一个test文件进行debug;2.将TheSim等组件进行Mock;