跳至正文

12 月:一台虚拟机统领所有!

· 9 分钟读完
Gabriel • SyedMuhammad
lead developer™

一统天下的 Lua 虚拟机!

单一 Lua 虚拟机​

经过大量分析、研究和重构。我高兴地介绍包的新工作方式!这主要是由于缺乏以简单方式创建扩展或自定义项目的可能性。

除了上次新的实体系统更新之外,这一变化将大大增加 nanos world 的模组和脚本能力的可能性!

信息

这些更改旨在产生尽可能小的影响和破坏性更改,到目前为止我做的所有测试都确保一切仍然向后兼容!

到目前为止,我们为每个包创建了一个 VM(虚拟机 - 或 lua_State)。这导致每个包彼此完全隔离。因此有必要为包之间的通信创建机制,例如 Events 和 Package.Export/Package.Call 方法,它们允许(以有限的方式)包之间相互通信。

但如前所述,这带来了许多限制,例如包无法直接访问其他包的变量或调用函数,甚至更糟(从上次实体系统更新中变得更加明显):无法在包之间共享自定义类!

但现在所有这一切都将得到解决!我重做了整个内部脚本系统,现在不再为每个包创建新的虚拟机,而是将拥有一个虚拟化的沙盒环境(使用 Lua 环境 _ENV 特性),分离每个包的作用域,但允许它们访问全局共享环境!

这将允许包全局定义类、暴露函数和共享库!这样其他所有人都可以使用,而无需变通机制!

现在,例如你可以只加载额外的脚本与 sandbox 游戏模式一起,加载自定义的工具或武器类,它们将自动出现在生成菜单中,不再需要手动添加它们!

每个包仍将拥有自己的子全局环境,因此定义全局变量或函数不会立即使它们对其他包可用。

调用与导出​

Package.Call 和 Package.Export 不再以传统方式必要。由于现在我们可以共享全局环境,我们可以定义方法并暴露它们以直接调用,而无需 Package.Call 它们。

Package.Export 仍将存在并以类似方式工作。但现在可以将任何值“暴露”到全局作用域!示例:

local my_table = { 123, 456 }

function DoSomething(var1)
return var1 + 123
end

Package.Export("MyTable", my_table)
Package.Export("DoSomething", DoSomething)
Console.Log(MyTable[1])
-- 123

Console.Log(DoSomething(456))
-- 579

继承类​

现在所有继承类将对所有包可用,因为它们将被自动创建并暴露到全局作用域。

它的第一个参数现在将用作在全局作用域中设置类的变量名。此外,它刚获得一个新的可选第二参数,用于定义包含自定义值的自定义表,以在创建类表之前设置在其中:

-- 注意我们将 Inherit 的返回值赋值给一个名为
-- MyPropClassLocal 的变量,但 MyPropClass 也将在全局定义
-- 作为我们的类,两个变量都指向同一个类表
MyPropClassLocal = Prop.Inherit("MyPropClass", {
"my_custom_value" = 123,
"my_another_value" = "hello"
})

local val = MyPropClass.my_custom_value
-- val == 123

我们还添加了一个新的静态事件,用于在注册新继承类时获取:ClassRegister:

Prop.Subscribe("ClassRegister", function(class)
-- 对新类做一些事情
end)

库包类型​

有了这种新的包工作方式,不再需要 library 类型。由于现在我们可以通过暴露的全局方法直接与其他包通信,我们只需定义要使用 Package.Export 导出的方法,并随时使用它们。

这样我们将只有两种“Lua 脚本”包类型:game-mode 和 script。所有现有的 library 包在加载时将自动转换为 script。

RequirePackage​

因此,Package.RequirePackage 也将变得不必要。由于我们现在可以全局重用相同的脚本,此方法将被弃用,改为将你的包添加到包的 Package.toml 中的 package_dependencies 列表中。

需要包的默认 nanos-world-vehicles 或 nanos-world-weapons 将作为独立包加载,因为它们现在全局导出 NanosWorldWeapons 和 NanosWorldVehicles 表。

游戏模式设置​

我们正在引入游戏模式自定义设置的概念!这些设置可以在 Package.toml 中这样定义:

# 游戏模式自定义设置配置
[custom_settings]
my_toggle = { label = "启用 PVP", type = "boolean", description = "是否启用 PVP", default = true }
my_text_input = { label = "输入任何内容", type = "text", description = "自定义文本!", default = "hello world!" }

这些设置可以通过服务器参数 --custom_settings "my_toggle = true, my_text_input = 'awesome text!', ..." 配置,或通过新游戏屏幕配置,该屏幕在创建新游戏时动态解析并显示配置:

定义的值可以通过新方法 Server.GetCustomSettings() 访问。

请参阅更新的文档页面以获取更多信息。

配置文件​

正如之前博客中所宣布的,配置文件的格式将在下一次更新中更改!

提示

所有旧格式的 Package.toml 和 Assets.toml 在首次加载时将自动转换为新格式。

元数据块​

现在我们在所有 Assets.toml 和 Package.toml 之间有了一个新的通用头部:[meta]。

它将具有以下格式,用于定义主要由商店使用的一般配置:

_meta.toml
loading...

Package​

对于包,我们将有一个新格式来区分它们的类型。每种包类型将拥有一个独立且不同的配置块。现在包类型将通过定义块 [game_mode]、[script] 或 [loading-screen] 来确定。

这是游戏模式 Package.toml 的样子:

_game_mode.toml
loading...

配置图片​

你可能已经注意到,Package.toml 中不再有 image 设置,Assets.toml 以及 Config.toml 中的服务器图像也是如此。

现在,图像应物理放置在 .toml 文件旁边,名称为 Package.jpg、Assets.jpg 或 Server.jpg。

这是一种标准化,用于解决商店和配置文件之间的图像不一致问题,并避免放置外部和恶意链接。但这带来了一个缺点,从现在起只有专用服务器才能在服务器列表中显示图像。

新的静态类​

我们终于发布了包含所有静态类重构的更新!这将为我们在文档中查找内容提供一个很好的新组织,因为现在特定方法将被分组到具有合理名称的类中!

所有新静态类列表:

此外,🕹️ 输入 也从 Client 获得了许多新方法和事件。

来自 ⌨️ Client 和旧 🌍 World 的许多方法已迁移到这些类中!查看它们的页面以获取准确信息!

重命名的事件​

根据我们上次的投票,我们开始更改所有名称错误的事件的名称。我们正在将它们标准化为现在时,例如像 CharacterEntered 这样的事件将被重命名为 CharacterEnter。

所有更改将保持旧事件作为弃用继续工作。请注意新的警告,将它们更新到较新版本!

资产插件内容​

现在可以从插件内容创建资产包,这将成为从现在起创建内容的首选方式,因为它可以防止资产路径与其他资产冲突。

为此,我们在 Assets.toml 中添加了一个新设置来定义资产包是否为插件内容:is_plugin_content。

请参阅更新的文档页面以获取更多信息。

商店改进​

上个月 MegaThorx 发布了商店更新,大大改善了新版本的上传流程。现在我们有了进度条,以及用于验证语法错误和潜在问题的特殊脚本。将来还会添加更多功能!

结语​

我对 nanos world 处理模组和脚本可能性的方式不太满意。脚本编写者必须让包之间相互通信的方式感觉非常有限和不自然,它不允许太多的自定义或扩展性。

随着上个月的实体系统以及现在包工作方式的改变,我感觉一扇巨大的可能性之门进一步打开了,这将为新事物的添加提供良好的呼吸空间!

现在可以实现的一个很好的例子是创建一个空白的 script 包,其中包含一个自定义的特殊继承武器,只需将沙盒游戏模式与你的脚本一起加载即可使其显示在生成菜单中,无需任何特殊调用或变通方法!这是巨大的,并且将所有剩余的结都系好了! 🥳

这种向单一 VM 的转变是一个巨大的变化,起初我以为它不会成功,但完成并进行测试后,我对结果感到非常惊讶和高兴!现在我们必须进一步细化和改进它!

模组制作起飞!!感谢支持!下个月见! 💪💪