Unreal Tournament '99 server
- 3 Devlogs
- 16 Total hours
An Unreal Tournament ’99 server - inside of a Docker container (with mod support through RedeeMOD)
An Unreal Tournament ’99 server - inside of a Docker container (with mod support through RedeeMOD)
You can connect to it by opening ut99.domax.lt on Unreal Tournament ’99 (has to be OldUnreal-patched)
Very little. I added a README, and reorganized the environment variables.
I also implemented server setting replacement logic, which empties unset values if they have no defaults on startup.
This was done to leave no stale settings lingering inside of the .ini file.
It’s an only-deathmatch server with a plugin to vote for maps at the end of round, nothing more, so a pretty vanilla experience. Bots are tuned to be 6/8 difficulty, so you’ll have to practice a bit ;)
If something’s malfunctioning, reach out to me on Slack, and I’ll try to help fixing the problem.
How I integrated mod support into the server (I’m very excited)
Adding mods would seem a fairly easy task, regarding that I had already built a mod launcher that supports CLI. Most of that time was spent debugging why the server image stopped immediately after starting.
RULE NUMBER 1: Learn from my mistakes, always check if your entrypoint process continues, or if it exits.
Turns out, my CLI app spawned a process… And exited! Which means that no matter what else was running, since the main container process no longer exists, the whole container shuts down.
The solution was to monitor the container’s SIGTERM/SIGINT signals that are handed upon stopping, and only THEN kill the RedeeMOD task. Otherwise, keeping it alive is necessary.
That was simple. I exchanged the executable from base UT99 server binary to RedeeMOD’s CLI and limited Python to disallow exiting early.
RedeeMOD handles everything natively, making me only supply the mod folders and nothing more.
The server runs, there’s just one annoying bug, but I believe it’s an issue in the executable itself. Using open {map_name} through server console instead of servertravel {map_name}?game=BotPack.{game_type} makes the whole server throw a segmentation fault and require a manual restart.
And the web admin panel is quite poor in terms of functionality. Some time in the future I might write an updated web panel and try to get a PR merged to OldUnreal’s upstream, but that’s not a priority for now.
Other than that, I’m feeling confident, and no more major overhauls await. Just the integration of GitHub actions for automated container builds, and some automation stuff (like pre-commit hooks).
After the success of RedeeMOD, my other project (a mod launcher for games), I decided I want to make an easier way of running dedicated Unreal Tournament ’99 servers.
My plan was to create a Docker container, mostly for portability. Since the server itself was already implemented by Epic Games back in 1999, all I have to do it to package it for Docker.
Thankfully, Epic back in the day supported Linux and included official binaries, which are still maintained by a volunteering group called OldUnreal. This meant I didn’t have to think about integrating Wine/Proton into the container!
And while a docker container for UT99 was previously made by someone, lack of updates disappointed me. I decided to make my own because of a couple reasons:
Having experience in UT99 modding, I decided to use Python since I could use RedeeMOD as a source for code templates.
Having coded a modding tool for this game was also trivial while asking AI - my own repos were heavily used as context.
In the near future I’m also planning to bake-in RedeeMOD for mod support for servers, providing great use of something I had already made!
Today I have built a strong foundation for the server - it builds, validates and applies environment variables (through .ini patching) and runs the server with provided config. Within its run pipeline also has a place for near-future addition of modding.
Web panel works, LAN discovery too!
It has no CI/CD pipelines yet, but that’s one of the main things I’ll be taking a look at in the next day or so.