小黑盒游戏新闻 ( ) • 2024-05-01 21:48

你好,

欢迎回到来我们的事实世界。

统计

你和我们一样喜欢看你的生产图表增长吗?

蓄电器图表

当你从蒸汽动力过渡到太阳能电池板和蓄电池时,要知道你的系统是否有足够的容量来度过寒冷的黑夜,这有点棘手。通常你可能会等到晚上,看看你的工厂是否停电,如果是这样,建造更多的太阳能和蓄电池。

查看蓄电池充电水平的统计数据会很有帮助和方便,所以我们添加了这样的信息:


它更重要的主要原因是,在Fulgora,夜间闪电的产生是不太可预测的,所以看到蓄电池充电的时间表就更重要了。


科学图表

你可以在生产图表用户界面中跟踪科学包的消耗,但这并不包括生产力模块和新的研究生产力技术。所以我们在生产统计中增加了一个新的特殊项目,显示生产的最终“科学”总数。

每地面产量

在最初的星球和平台游戏测试中,所有的生产统计数据都是全球性的,这是可以忍受的。然而,当你想让你的游戏越来越精确,并试图优化每个部分时,这就变得非常必要了。

例如,在平台上,我们需要知道我们是否生产了足够的燃料和弹药来维持旅程:

当一些物品在许多地方制作时,检查一个特定的星球是否生产足够的物品时,它非常有帮助。

我们还添加了一个复选框来切换到“全球统计”视图,因此玩家可以使用所有可能性。


质量图表

更进一步,我们想通过生产的产品质量来剖析我们的生产。

那么你觉得呢?2.0还有其他统计改进吗?


Linux 历险

到目前为止,我已经出现在一些FFF中,但我从未正式介绍过自己。我的名字是raiGuard。我从2017年6月开始玩异星工厂,从2019年3月0.17版本开始为游戏制作模组,我最终于2023年3月加入了WUBE。我在公司的主要角色是扩展编程和Linux支持,以及模组社区的倡导者。多年来,我一直在日常驾驶Linux,并越来越深地陷入定制和极简主义的黑洞。

“为什么大多数游戏不支持macOS和Linux?”“这是我经常在互联网上看到的一种观点。支持一个新平台不仅仅是更改一些标志和点击编译。Windows、macOS、Linux和Nintendo Switch都使用不同的编译器,C++标准库的不同实现,并且有不同的实现怪癖、错误和特性。你需要为新平台设置CI,扩展你的构建系统以支持新的编译器和架构,并且团队中至少有一个人足够关心平台以积极维护它。如果你是一个视频游戏,你可能还需要添加对另一个图形后端(Vulkan或OpenGL)的支持,因为DirectX是Windows独有的。

许多开发者会看一眼视窗市场份额 (https://gs.statcounter.com/os-market-share/desktop/worldwide),然后决定不值得费心支持其他平台。此外,随着蒸汽甲板和质子的迅速崛起,游戏开发者比以往任何时候都更容易忽视Linux支持,因为阀门做了一些黑魔法,让他们的游戏无论如何都能运行。

异星工厂非常支持macOS和Linux,因为WUBE一直有人积极使用这些平台,并愿意承担支持它的负担。我们本地的苹果硅支持 (https://factorio.com/blog/post/fff-371) 就是一个很好的例子。今天,我将带你经历一些我在维护异星工厂Linux支持方面的冒险。

Wayland

我加入团队后的第一个自封任务是在游戏中添加Wayland (https://wayland.freedesktop.org/) 支持。Wayland是一种新的显示协议,正在开发中,以取代过时且不安全的X11(https://en.wikipedia.org/wiki/X_Window_System) 系统。现代Linux发行版开始默认切换到Wayland,因此在异星工厂中支持它至关重要。

我们利用SDL (https://www.libsdl.org/) 库,它巧妙地处理大多数低级系统交互,并将它们抽象成一个通用接口。SDL支持Wayland,所以理论上我需要做的就是在启用Wayland的情况下构建SDL,它会“”“正常工作”“然而,这不是一个非常简单的即插即用。Wayland以XML文件的形式提供“协议”,然后您可以使用wayland-scanner二进制文件将其转换为C程序和头文件。

当时对C++来说相对较新,我最初的解决方案很复杂,包括将生成的韦兰协议检查到我们的源代码树中,每次我们更新SDL时手动重新生成。几个月前,凭借一年的经验,我改进了这个工作流程,将文件作为构建过程的一部分自动生成,因此它们始终与SDL附带的协议XML文件保持同步。

异星工厂从1.1.77开始就支持Wayland,但需要通过在您的环境中设置SDL_VIDEODRIVER=wayland来显式启用它。对于异星工厂 2.0,我添加了一个下拉列表来在GUI中选择您的偏好:

X11(up)vs. Wayland(down),桌面显示比例设置为125%。请注意游戏在Wayland下运行时如何以显示器的原始分辨率呈现。客户端窗口装饰

客户端窗口装饰

一旦Wayland支持实现,我收到了一个错误的报告 (https://forums.factorio.com/105512),说窗口在GNOME (https://www.gnome.org/) 上运行时缺少标题栏和关闭按钮(称为“窗口装饰”)。大多数桌面环境将允许窗口根据需要提供自己的装饰,但会在服务器端提供默认实现作为替代方案。GNOME以其无限的智慧决定所有客户端都必须提供自己的装饰,如果一个客户端不提供,他们就会简单地丢失。我不同意这个决定;异星工厂不需要在任何其他平台上提供装饰,不,在任何其他桌面环境上,但GNOME可以(ab)利用其流行度来迫使程序符合其特质或被抛在后面。

为了解决这个问题,我必须引入另一个依赖项libdecor (https://gitlab.freedesktop.org/libdecor/libdecor)。它可以运行,SDL甚至支持它,但视频游戏一开始就不应该提供窗口装饰。

游戏现在有装饰,但主题不匹配。谢谢GNOME!

窗口大小癫痫发作

一个视频胜过千言万语:


星期五报道#408 - 统计改进,Linux 历险 视频 (光敏警告:快速闪烁的图像)


我使用了Sway (https://swaywm.org/) 窗口管理器,这个窗口管理器的一个特殊性是它会自动将浮动窗口的大小调整到它们最后提交的帧的大小。这揭示了我们图形堆栈的一个问题:游戏需要三帧才能正确响应窗口大小的调整。结果是一场快速的拔河,摇摆发送了大量的调整大小事件,而异星工厂用过时的帧缓冲区大小进行响应,导致了上面捕捉到的混乱。我花了整整两天时间盯着我们的图形代码,但无法解释为什么会发生这种情况,所以这项工作仍在进行中。由于这个问题只发生在Sway下的Wayland上运行游戏时,所以这不是一个很大的优先事项,但它太有趣了,不能不分享。

动态链接库

在C++程序中,有三种方法可以加载/包含库: 

⚙ 通过将其包含在源二进制文件中(静态链接)

⚙ 让系统在程序启动时加载它(动态链接)

⚙ 您的程序在启动后显式加载它(“动态加载”或我所说的“运行时链接”)

我们有很多静态链接的库,比如SDL、FontStash和Lua,但异星工厂 1.1也有很多动态链接的库:

rai@tantal ~/games/factorio

$ ldd bin/x64/factorio

linux-vdso.so.1 (0x00007ffc123b1000)

libdl.so.2 => /lib64/libdl.so.2 (0x00007fc182f70000)

librt.so.1 => /lib64/librt.so.1 (0x00007fc182f6b000)

libresolv.so.2 => /lib64/libresolv.so.2 (0x00007fc182f5a000)

libX11.so.6 => /lib64/libX11.so.6 (0x00007fc182e13000)

libXext.so.6 => /lib64/libXext.so.6 (0x00007fc182dff000)

libGL.so.1 => /lib64/libGL.so.1 (0x00007fc182d78000)

libXinerama.so.1 => /lib64/libXinerama.so.1 (0x00007fc182d71000)

libXrandr.so.2 => /lib64/libXrandr.so.2 (0x00007fc182d64000)

libXcursor.so.1 => /lib64/libXcursor.so.1 (0x00007fc182d57000)

libasound.so.2 => /lib64/libasound.so.2 (0x00007fc182c43000)

libpulse.so.0 => /lib64/libpulse.so.0 (0x00007fc182bf1000)

libpulse-simple.so.0 => /lib64/libpulse-simple.so.0 (0x00007fc182bea000)

libm.so.6 => /lib64/libm.so.6 (0x00007fc182b07000)

libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fc182b02000)

libc.so.6 => /lib64/libc.so.6 (0x00007fc182920000)

/lib64/ld-linux-x86-64.so.2 (0x00007fc182f91000)

libxcb.so.1 => /lib64/libxcb.so.1 (0x00007fc1828f5000)

libGLX.so.0 => /lib64/libGLX.so.0 (0x00007fc1828c2000)

libGLdispatch.so.0 => /lib64/libGLdispatch.so.0 (0x00007fc18280a000)

libXrender.so.1 => /lib64/libXrender.so.1 (0x00007fc1827fc000)

libXfixes.so.3 => /lib64/libXfixes.so.3 (0x00007fc1827f4000)

libpulsecommon-16.1.so => /usr/lib64/pulseaudio/libpulsecommon-16.1.so (0x00007fc18276f000)

libdbus-1.so.3 => /lib64/libdbus-1.so.3 (0x00007fc18271a000)

libXau.so.6 => /lib64/libXau.so.6 (0x00007fc182714000)

libsndfile.so.1 => /lib64/libsndfile.so.1 (0x00007fc182694000)

libsystemd.so.0 => /lib64/libsystemd.so.0 (0x00007fc1825a1000)

libasyncns.so.0 => /lib64/libasyncns.so.0 (0x00007fc182599000)

libgsm.so.1 => /lib64/libgsm.so.1 (0x00007fc18258a000)

libFLAC.so.12 => /lib64/libFLAC.so.12 (0x00007fc182524000)

libvorbis.so.0 => /lib64/libvorbis.so.0 (0x00007fc1824f5000)

libvorbisenc.so.2 => /lib64/libvorbisenc.so.2 (0x00007fc182448000)

libopus.so.0 => /lib64/libopus.so.0 (0x00007fc1823ec000)

libogg.so.0 => /lib64/libogg.so.0 (0x00007fc1823e2000)

libmpg123.so.0 => /lib64/libmpg123.so.0 (0x00007fc182385000)

libmp3lame.so.0 => /lib64/libmp3lame.so.0 (0x00007fc18230d000)

libcap.so.2 => /lib64/libcap.so.2 (0x00007fc182303000)

liblz4.so.1 => /lib64/liblz4.so.1 (0x00007fc1822df000)

liblzma.so.5 => /lib64/liblzma.so.5 (0x00007fc1822ac000)

libzstd.so.1 => /lib64/libzstd.so.1 (0x00007fc1821f0000)

libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fc1821cc000)

这些库中有X11和PulseAudio,它们分别被Wayland和PipeWire弃用。这会导致兼容性噩梦,因为如果缺少任何动态依赖项,游戏将无法启动。这显然不行!

这些依赖关系的存在让我感到困惑,因为我们将SDL用于大多数低级系统调用、音频和视频,而SDL完全依赖于运行时链接。一项调查显示,这些依赖关系的大部分来源是Allegro (https://liballeg.org/),我们在异星工厂的大部分alpha阶段都使用了这个低级库,但后来我们用SDL取代了它。Allegro在2.0中唯一剩下的用途是作为辅助音频后端,以防用户遇到SDL音频后端的问题,但SDL后端已经稳定了很长时间,因此删除它的时机已经成熟。这消除了游戏中的123,024行代码,并大大减少了动态依赖关系的数量:

rai@tantal ~/dev/wube/factorio (master)

$ ldd bin/FinalReleasex64Clang/factorio

linux-vdso.so.1 (0x00007fff96ff2000)

libresolv.so.2 => /lib64/libresolv.so.2 (0x00007fd2df8a9000)

libm.so.6 => /lib64/libm.so.6 (0x00007fd2df7c8000)

libc.so.6 => /lib64/libc.so.6 (0x00007fd2df5e6000)

/lib64/ld-linux-x86-64.so.2 (0x00007fd2df8d6000)

剪贴板困境

事实证明,Allegro并不是唯一需要我们与X11联系的东西。早在2017年,我们就收到了一份错误报告 (https://forums.factorio.com/46802),称用户无法将大型蓝图字符串粘贴到游戏中,Oxyd通过向我们的图形用户界面后端的剪贴板处理程序添加对X11增量剪贴板传输 (https://tronche.com/gui/x/icccm/sec-2.html#s-2.50) 的支持来解决这个问题。

我希望利用SDL的内置剪贴板功能,但不幸的是SDL不支持增量传输。这意味着有三种选择:

⚙ 继续链接X11,要求用户在他们的系统上安装X11才能运行游戏(我不想弄乱静态链接)。 

⚙ 弄清楚如何进行运行时链接并实现它。 

⚙ 将我们的增量传输代码上游到SDL中,这样我们就可以利用SDL的剪贴板功能,其他基于SDL的游戏可以从我们的工作中受益。

正如你可能猜到的,我选择了第三个选项。我们代码上游的工作正在进行中,但应该会在异星工厂 2.0发布之前及时完成。

异步保存

你们中的许多人可能不知道异星工厂支持在后台保存游戏,而不会在保存时冻结。此功能隐藏在隐藏设置中,仅适用于macOS和Linux。这是利用平台功能使游戏受益的一个很好的例子,如果我们只是通过质子,我们就无法获得这些功能。

异步保存通过使用fork系统 (https://man7.org/linux/man-pages/man2/fork.2.html) 调用来基本复制游戏。主实例——您与之交互的实例——继续玩,但新分叉的子实例运行保存过程,然后在完成时退出。我已经使用它很多年了,从来没有遇到过问题,但设置仍然是隐藏的,因为它有一些未解决的问题,并且需要大量的RAM才能工作。

我很乐意将此功能从2.0中的隐藏状态中推广出去。如果您在Linux或macOS上玩,请启用异步保存(ctrl+alt+单击设置->“其余”->非阻塞保存)并报告您发现的任何问题。我对重现过程结束时发生的看似随机的冻结 (https://forums.factorio.com/108738) 特别感兴趣。提前感谢!

持续发展

这只是我为确保异星工厂Linux所做工作的一瞥。仍然有许多公开的错误报告和其他问题,但我总体上对现状感到满意,并且可以自信地说异星工厂有很大的Linux支持。