Playing with Fire: My Contributions to Pyrogenesis and the Game 0 AD
Last Updated: 2025 February 13 (2025 Feb 11)
View 5 comment(s).- Documentation: Building Pyrogenesis on Void Linux
- Game crashes when audio files are corrupted/incorrect #7150
- Add hotkey for releasing mousegrab #6790
- Crash when using ‘/kick’ or ‘/ban’ commands in single-player mode #7467
- Some models trigger black screen issues. #6714
- Looking Forward
I joined Wildfire Games as a contributor in December 2024.1 About two weeks later the city two hours north of me (Los Angeles) catches on fire.
Wildfire Games develops and maintains 0 AD, a real-time strategy game released under a combination of copyleft and permissive licenses. They have a self-hosted instance of Gitea at https://gitea.wildfiregames.com.
I started with simple tasks shortly before the release of Alpha 27. As of that release, I am in the credits2 as one of the (many) programmers. I develop the game from Linux, and a continuous integration tool (CI) compiles and verifies builds for Windows and MacOS.
gdb
for debugging issue #7467.
Documentation: Building Pyrogenesis on Void Linux
In file included from ../../../source/lobby/XmppClient.h:23, from ../../../source/lobby/scripting/GlooxScriptConversions.cpp:23: ../../../source/lib/external_libraries/gloox.h:41:10: fatal error: gloox/client.h: No such file or directory
41 | #include <gloox/client.h>
sudo xbps-install gloox-devel
note: re-run ./update_workspaces.sh or there will be a wall of linker errors
— my notes
My first contribution to 0 AD was updating documentation for building the game on Void Linux, a somewhat rare distro. (Side note: Void is alright for gaming, and set-up is simple as long as the motherboard doesn’t need a master boot record.)
noted that
wx-config
iswx-config-gtk
on Void (64ba6b07a9)updated the dependency list to include
subversion
andgloox-devel
, also removing the instruction to compilegloox-devel
(7ace9aeade)noted that the system version of Spidermonkey 115 and premake5 can be used (this saves time when running
update-workspaces.sh
andbuild-source-libs.sh
) (ebc547f487)
In hindsight, I was maybe too cautious about updating the documentation in splitting my edits across different commits to the wiki.
Game crashes when audio files are corrupted/incorrect #7150
Reproduced by opening ui_button_click.ogg
in a text
editor, corrupting it by typing ‘asdf’ somewhere and clicking any menu
item. The part where the game crashes is noted to be at
ogg.cpp:240
.
const int ret = ov_open_callbacks(&adapter, &vf, 0, 0, callbacks);
if(ret != 0)
(LibErrorFromVorbis(ret)); WARN_RETURN
If ov_open_callbacks
opens a normal file, it returns 0
and doesn’t trigger the condition, but when the file is corrupted, the
return value is negative3 and the assertation
fails. I launched the game with gdb
to see the value of
ret
.
gdb | break ogg.cpp:240
gdb | run
gdb | print ret
The result was ret = -133
. -133 lines up with the
error OV_EBADHEADER
.4
The simple fix was to add a condition for
OV_EBADHEADER
but I got suggestions to handle most other
cases except OV_EFAULT
(99ebeeb39b).
Add hotkey for releasing mousegrab #6790
When in windowed mode the user should have a convenient way to release the mouse if grabbed. Suggest to add a hotkey to toggle grab. Auto grabbing on clicking into the window might also be considered.
— sera, the one who opened the issue
As this was an enhancement, not a bug, I didn’t have a debugger to
direct me to a file. In this case,
grep -rn source/ -e "hotkey"
leads to
main.cpp
. There is a block to read inputs for taking
screenshots. This appears to be a close enough fit categorically, so I
added another condition.
else if (hotkey == "mousegrabtoggle")
{
* const window{g_VideoMode.GetWindow()};
SDL_Windowconst SDL_bool willGrabMouse{SDL_GetWindowGrab(window) ? SDL_FALSE : SDL_TRUE};
(window, willGrabMouse);
SDL_SetWindowGrab}
Wildfire Games prefers brace-list initializations.5 Other changes in the pull request were updating JSON files.
sera and I had different opinions on mouse grabbing. However, I noticed I never had my mouse drift out of the window for a first-person shooter or any other game where the cursor “sinks” into the game world and comes up again when the menu is opened.
<scuti> sera some other game doesnt grab on the main menu but starts grabbing when the player gets in the game, then also releases when the game is paused. is that familiar to anyone?
<sera> sounds like a reasonable solution to me as well
There was a pause after I wrote that, like an epiphany had dawned on the channel.
Crash when using ‘/kick’ or ‘/ban’ commands in single-player mode #7467
When using the /kick or /ban network command in a single-player game, the game crashes.
— Langbart
I ended up fixing an unreported bug while working on this issue.
Here, I started by looking at network.js
which calls a
function from source/.../JSInterface_Network.cpp
.
void KickPlayer(const CStrW& playerName, bool ban) {
{
(g_NetClient);
ENSURE...
When /kick
is sent in a singleplayer game,
playerName = L""
, ban = false
,
g_NetClient = NULL
, then the assertation fails. I changed
the function definition to include the script request, so there’s
feedback in-game when it fails.
void KickPlayer(const ScriptRequest& rq, const CStrW& playerName, bool ban)
{
if (!g_NetClient)
{
::Raise(rq, "g_NetClient is null.");
ScriptExceptionreturn;
}
...
Later, I noticed I couldn’t get any system messages to print.
This works.
addChatMessage({ "type": "clientlist" })
But this doesn’t.
function kickError()
{addChatMessage({
"type": "system",
"text": translate("Only the host can kick clients!")
;
}) }
Tracing where functions were defined, I had found the typo
return msg.txt
in the function handleMessage
from public/gui/session/chat/ChatMessageHandler.js
.6
I wrote in javascript to fix the bug I spotted and prevent the C++ function from being called if the match is not online.
Some models trigger black screen issues. #6714
Skinned models with unweighted vertices might cause black screen issues. Ideally the problem should be handled at the root by the artist, but we need them to be aware of it.
From my little understanding the issue is that geometry bound to such vertices makes huge triangles because those vertices are put at the origin of the map. If the triangle is big enough then the screen gets black.
So it would be nice if
- Checkrefs would print an error when encountering such DAEs
— Stan
The broken model needed to be checked out from an old commit.
git checkout ce875e675e5bbd7aee45c40aae6a45f27a95d787^ -- binaries/data/mods/public/art/actors/props/structures/romans/trireme_fore_sail.xml
I haven’t been able to reproduce the bug. After asking for more information, the issue got updated, and I was told about a python script that hasn’t yet been integrated (P293) 7.
P293 introduces the requirement pycollada
; however,
pip3 install pycollada
results in the following from
invoking the collada constructor.
<class ‘AttributeError’>
np.unicode_
was removed in the NumPy 2.0 release. Usenp.str_
instead.8
Therefore, the versions must be specified:
pip3 install pycollada==0.8 numpy==1.26.4
. (It looks like
pycollada
is updated for Numpy 2.0, but the current
package isn’t yet.)9
After, I defined an object DaeValidator to initialize logging (to conform to the format in other validation scripts) and search paths. So now the CI validates meshes when a pull request is updated.
Looking Forward
In summary, what I had done so far:
- update documentation for building the game on Void Linux, saving trouble for anyone on that distro who also wants to contribute
- improve the stability of the game engine in the case of corrupted audio or network commands in non-networked sessions
- add a hotkey | feature to enhance the playing experience for players that use windowed mode
- integrate a script that enables artists to verify their 3D models before erroneous models cause issues in-game.
I anticipate doing small tasks for now will let me make bigger changes later as I familiarize with the codebase. I look forward to bringing the moddable, free culture real-time strategy game out of alpha to Release 28. Give 0 AD a shot and experience the reconstructed ancient world at https://play0ad.com/.
0ad/programming.json at main - https://gitea.wildfiregames.com/0ad/0ad/commit/faa063ee42b11e0e616992d8af29eccf35bb4493↩︎
https://xiph.org/vorbis/doc/vorbisfile/ov_open_callbacks.html↩︎
https://github.com/xiph/vorbis/blob/master/include/vorbis/codec.h#L230↩︎
https://isocpp.org/blog/2016/05/quick-q-why-is-list-initialization-using-curly-braces-better-than-the-alter↩︎
Fixed messages of type ‘system’ not-printing. - Commit 490c3eb22b↩︎
Find broken animated meshes - https://code.wildfiregames.com/P293↩︎
https://gitea.wildfiregames.com/0ad/0ad/actions/runs/4293/jobs/0#jobstep-8-36↩︎
Fix compatibility with NumPy 2.0 (#147) - https://github.com/pycollada/pycollada/commit/39cabd78c4bdbdab763a510be3c2ff378ee9d75b↩︎
Thanks for reading! Who doesn't love comments? Let me know what you think on my guestbook by e-mail or neocities.