Skip to content
云风 edited this page May 7, 2024 · 7 revisions

Ant 程序

如果用默认编译脚本编译引擎,会在 bin 目录下找到编译好的执行文件 ant.exe ,根据编译器和编译选项不同,会放在不同子目录下。例如,使用 mingw 编译的 release 版,位于 bin/mingw/release/ant.exe , vc 编译的 debug 版位于 bin/msvc/debug/ant.exe

这个程序实际是标准 Lua 5.4 并打包有 Ant 相关的 C 模块。运行这个二进制程序,会加载同一目录下的 main.lua 并运行它。

注:bin 目录下的 main.lua 是从 runtime/common/main.lua 由构建脚本复制过去的,所以不要直接修改它,而应该修改源文件并运行 luamake 复制。构建脚本位于 runtime/make.lua

Ant 程序在启动时,加载 main.lua 之前会加载所有的相关 C 模块。C 模块的入口全部列在 runtime/common/modules.c 中,如果游戏需要链接额外的 C 模块,需要修改构建脚本,或采用标准 Lua 可以接受的动态链接库的形式。modules.c 中的 ant_loadmodules() 函数最后会初始化 VFS 模块。这会改变标准 Lua 所带的 IO 函数的行为。

VFS 由 C 和 Lua 混合实现,C 入口在 clibs/vfs/vfs.cpp 。Lua 代码以字符串形式嵌入在源代码中,我们可以看到它替换了 dofile/loadfile/require 等行为,以支持 Ant 的文件系统。

本地模式和运行模式

Ant 的文件系统可以放在本地,也可以通过网络映射。我们把通过网络映射的虚拟文件系统称为 RUNTIME 模式,在 PC 上启动引擎,默认使用本地模式,但可以通过命令行参数 -rt 切换为运行模式(实现见 clibs/vfs/vfs.cpp)。在手机上运行,一定处于运行模式。

运行模式

在运行模式下,所有文件请求都会通过网络发往文件服务器,或使用本地缓存。本地缓存可以提前打包成 zip ,也可以是上一次和文件服务器同步的结果。如果缓存中缺少文件,会产生一个网络请求到文件服务器。注:连接文件服务器只会在程序启动时尝试一次,一旦无法连接,便会进入离线模式,只使用本地缓存。

文件服务器本身也是一个 Ant 引擎驱动的程序,其启动入口在 tools/fileserver/main.lua。通常,我们必须用本地模式启动文件服务器。

由于运行模式本身需要额外的代码实现客户端协议和文件服务器对接。这些代码也是用 Lua 实现,但无法放在本地系统中。所以,构建脚本会把相关 Lua 的源代码编译在执行文件里。这些相关代码位于 engine/firmware 下。虽然它们都是 lua 文件,但一旦修改它们,必须重新运行 luamake 构建,把这些文本编译进引擎的执行文件中。

运行模式下工作,不再依赖其它本地文件。

本地模式

日常 PC 开发推荐使用本地模式,它从本地文件系统中加载文件。但由于 VFS 还承担了 Asset 的自动构建工作,所以在同一个项目目录下同时运行多个程序时,会产生冲突。本地模式不运行在同一个项目目录下同时运行多份。

如果需要启动多份游戏,可以在项目目录下以本地模式启动一份文件服务器。然后以运行模式启动游戏则不受限制(甚至可以不在同一台机器上)。

编辑器模式

Ant 引擎为编辑器做了一些特殊化处理。本地模式下,如果项目名为 editor,就会变成编辑器模式。例如,以下启动方式会进入编辑器模式:

ant.exe tools/editor/main.lua test/simple/

编辑器模式相对于本地模式的特殊之处有:

  1. 定义了全局变量__ANT_EDITOR__为arg[1],也就是第一个参数
  2. 将__ANT_EDITOR__指向的目录下的.mount也会被加载
  3. 资源编译不会缓存结果(资源编译后被修改,再次加载时,本地模式不会重新编译,编辑器模式则会)
  4. 可以读取资源的原始文件,而本地模式读取资源的原始文件会失败(因为已经被视为目录)

上面的启动实例中,会设置有:

ANT_EDITOR=test/simple/

同时,tools/editor/test/simple/ 两个目录下的 .mount 都会被加载。

引擎的初始化

如前文所述,和执行文件同目录的 main.lua (源码在 runtime/common/main.lua) 是引擎在本地模式下运行的第一个 Lua 程序。它会加载 engine/firmware/bootstrap.lua 并将命令行传入的 lua 程序名转发给它。而在运行模式下,不依赖额外的 main.lua ,直接加载已被编译进执行文件的 engine/firmware/bootstrap.lua

如果运行在本地模式下,我们必须保证当前目录的位置,让 engine/firmware/bootstrap.lua 是合法的路径。你可以额外编写 shell 脚本在启动执行文件前把进程的当前路径切换到正确的路径下,这通常相对于执行文件的目录 ../../../ ;也可以自定义启动文件 main.lua ,在里面使用内置的 bee.filesystem 模块。

例如,可以参考 vaststars 项目的启动文件处理方法:https://github.com/ejoy/vaststars/blob/master/clibs/bootstrap.lua#L54-L61

默认的启动脚本 main.lua 会将命令行参数中的文件名转发给 engine/firmware/bootstrap.lua ,这个文件所在的目录会被当做项目的根目录。如果的启动流程会切换当前路径,注意这个文件最好使用绝对路径,或在你自定义的启动流程中做做正确的转换,让引擎可以计算出正确的项目根目录。

以下有一个简易的游戏项目启动脚本可供参考。假设游戏项目完全由 Lua 编写,没有任何 C 代码,那么你不需要编写额外的构建脚本,把游戏项目放在和 ant 同级的目录下。在游戏目录下运行这个脚本,它会先用 realpath 计算出当前目录下 main.lua 的完整路径,并将当前目录切换到 ../lua 并运行 ../ant/bin/mingw/release/ant.exe 传入带有完整路径的 main.lua 。

#!/bin/bash

ANT=../ant
ANTBIN=$ANT/bin/mingw/release/ant.exe
STARTUP=`realpath main.lua`

cd $ANT
$ANTBIN $STARTUP

VFS 启动

VFS 有一套自己的路径映射规则,以实现 Mod 特性,并支持 Asset 的自动编译。

在本地模式启动时,会初始化 ant.vfs 这个 Package 中的 mount 子模块 ( 代码位于 pkg/ant.vfs/mount.lua ) 。它会做一些默认的路径映射,也可以在项目根目录下放置一个 DataList 格式的 .mount 文件改写默认规则。

在 .mount 规则中,可以使用 %engine% 指代引擎根路径,它指引擎启动时的当前路径;可以使用 %project% 指代项目根路径,它指命令行传入的启动程序所在的路径。默认的映射规则如下:

mount:
    /engine/ %engine%/engine
    /pkg/    %engine%/pkg
    /        %project%
    /        %project%/mod

ltask

Ant 引擎工作在 ActorModel 下,这是由 ltask 实现的。引擎在 engine/firmware/bootstrap.lua 中会启动 ltask ,加载必要的服务:io 、timer、logger 。

其中,所有的 VFS 请求都会通过 io 服务,包括引擎自身的代码;timer 和 logger 时 ltask 必要的基础设施。

命令行传入的 lua 文件将以一个服务的形式启动,所以你可以在这个文件中使用 ltask 的 api 。

Clone this wiki locally