avatar
scuti
got a warm welcome to game development.
https://scuti.neocities.org/

Playing with Fire: My Contributions to Pyrogenesis and the Game 0 AD

Last Updated: 2025 February 13 (2025 Feb 11)

View 5 comment(s).

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.

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.)

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)
        WARN_RETURN(LibErrorFromVorbis(ret));

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")
{
    SDL_Window* const window{g_VideoMode.GetWindow()};
    const SDL_bool willGrabMouse{SDL_GetWindowGrab(window) ? SDL_FALSE : SDL_TRUE};
    SDL_SetWindowGrab(window, willGrabMouse);
}

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) {
{
    ENSURE(g_NetClient);
    ...

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)
    {
        ScriptException::Raise(rq, "g_NetClient is null.");
        return;
    }
    ...

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

  1. 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. Use np.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:

  1. update documentation for building the game on Void Linux, saving trouble for anyone on that distro who also wants to contribute
  2. improve the stability of the game engine in the case of corrupted audio or network commands in non-networked sessions
  3. add a hotkey | feature to enhance the playing experience for players that use windowed mode
  4. 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/.


  1. https://gitea.wildfiregames.com/scuti↩︎

  2. 0ad/programming.json at main - https://gitea.wildfiregames.com/0ad/0ad/commit/faa063ee42b11e0e616992d8af29eccf35bb4493↩︎

  3. https://xiph.org/vorbis/doc/vorbisfile/ov_open_callbacks.html↩︎

  4. https://github.com/xiph/vorbis/blob/master/include/vorbis/codec.h#L230↩︎

  5. https://isocpp.org/blog/2016/05/quick-q-why-is-list-initialization-using-curly-braces-better-than-the-alter↩︎

  6. Fixed messages of type ‘system’ not-printing. - Commit 490c3eb22b↩︎

  7. Find broken animated meshes - https://code.wildfiregames.com/P293↩︎

  8. https://gitea.wildfiregames.com/0ad/0ad/actions/runs/4293/jobs/0#jobstep-8-36↩︎

  9. 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.


Comments (5)

Reply to any of the bulleted links to leave a comment.

#5 Thu, January 30, 2025

avatar
Listens to Baroque while coding murder.exe :newt: @newt
@scuti no, that's not what I mean. Fullscreen support in Linux is sorta weird and it's just easier to run games as borderless windows than true fullscreen.

#4 Thu, January 30, 2025

avatar
scuti @scuti
@newt XFCE and i3, as I've used, can toggle borderless fullscreen mode.

#3 Thu, January 30, 2025

avatar
Listens to Baroque while coding murder.exe :newt: @newt
@scuti linux gamers are too stuck with borderless. Just saying.

#2 Thu, January 30, 2025

avatar
scuti @scuti
My pull request:
https://gitea.wildfiregames.com/0ad/0ad/pulls/7556
My random idea that could be shortsighted:
Mouse grabbing, like borderless fullscreen mode and tabs, should be handled by the window manager or desktop environment instead of the application.
(Are Windows gamers still stuck with using Borderless Gaming to get borderless fullscreen mode?)
#0ad #linux #desktop

New hotkey to grab and release mouse

For #6790 Hotkey will cause window to capture the mouse or release it.

#1 Wed, December 18, 2024

avatar
scuti @scuti
Made my first (small) contribution to @play0ad / #0ad (documentation of building on #voidlinux ) 🎉
https://gitea.wildfiregames.com/0ad/0ad/issues/7327

Build Instructions on Void Linux

Based on: https://gitea.wildfiregames.com/0ad/0ad/wiki/BuildInstructions#voidlinux 1. `wx-config` on Void Linux is `wx-config-gtk3`; for this, I had to edit update-workspaces.sh 2. Dependency list is missing `gloox-devel`, running update-workspaces.sh before installing that results in linker er...