Where I left off
Short version for anyone new. I’m rebuilding the server for Fury, a 2007 online game that has been offline since 2008. I have the client (the program that ran on players’ PCs) and nothing else. No server, no source code, no documentation. The studio’s co-founder gave me his written blessing to work on it. The plan is to read the client’s code well enough to build a matching server from scratch.
I’ve done the first two stretches of that: poking the client to see what still runs, and then getting a decompiler to turn its code back into something readable. Both went well and there are posts about each.
But I’ve done all of it alone, and a couple of my early findings are the kind of thing the whole rest of the plan leans on. If they’re wrong, I want to know now, not in three months.
So this post is a favour ask. If you’ve ever reverse-engineered an old Unreal Engine game, or run a private server for a dead one, I’d love a second opinion on the stuff below.
What I tried
For the non-technical readers, three quick terms:
- A client is the program on the player’s PC. A server is the program in the data centre that everyone’s client connects to.
- Old Unreal Engine games ship a single program that can run as either one, depending on how you start it. A magic word on the command line, or a special tag on the connection address, flips it into “host a game” mode.
- A commandlet is a batch tool baked into that same program. You’d run
game.exe editororgame.exe maketo open the editor or recompile the code.
The whole point of my Phase 1 was: does this client still have any of those doors open? Because if it can host even a broken local game, that’s a massive shortcut. I wouldn’t have to rebuild the server from nothing.
I ran the shipped Fury.exe on Windows 11, on a copy of the install, and read
the logs after every attempt.
What broke
Every host door is bricked.
Fury.exe server <map>,editor,make,CalculateCRC: the program takes the first word after the exe name and tries to load it as a map. Soserverbecomes “please load the level called server”, which doesn’t exist, and it either writes a crash dump or throws a runtime error. The help text for all those batch tools is still sitting in the game’s text files. The tools themselves are gone.- Adding the “host a game” tag (
?listen) to an address that otherwise loads a full playable screen offline kills the process in about half a second. The log gets exactly as far as the startup banner and then the program relaunches its own patcher in “your install is corrupt, repair it” mode. Not a crash. A deliberate bail-out. Same thing on every map and mode I tried.
Everything that isn’t a host attempt works fine. The character-creation screen runs completely offline: real game logic, reading settings off the connection string, running its full login sequence with no server anywhere. The other maps load their logic and then hang, waiting for backend services that aren’t there.
So my conclusion was: there is no shortcut. The server has to be rebuilt from the decompiled code. Everything since has been built on that.
The technical version, if you do this kind of thing
This is the part I want checked. Full logs are in the Phase 1 wrap-up post.
Build: UE3, package FileVersion 407 / LicenseeVersion 36,
EngineVersion 2797, CookerVersion 0 (uncooked). Retail “Fury (DX9)” client, build
35256, April 2008. I have the compiled script (.u), configs, localization, all
content. No server binaries, no source, no protocol docs.
Observations from running the shipped Fury.exe:
No commandlet dispatch.
server/editor/make/CalculateCRCas the first arg all go straight to the map loader (UGOGameEngine::OnMapChangeStart> map='server'), fail, and minidump or VC++-abort. Stock[ServerCommandlet]/[MakeCommandlet]/[SmokeTestCommandlet]help text is still inEngine/Localization/INT/*.intbut inert.?listenaborts before any UnrealScript runs. Append?listento a known-good URL (AVA_Creation?game=gogame.goacgame, which otherwise loads a full playable offline screen) and the process dies in ~0.5s. Log has the build banner thenLog: CreateProc .../FuryLauncher.exe error corrupt-files, i.e. it re-execs its own updater in repair mode. NoOnMapChangeStart, no script. Reproduced across 2 maps and 2 game classes. That samecorrupt-filesre-exec is the client’s generic response to a fatal content error.Everything else works. Without
?listen, a complete local game for the char-creation map: real GameInfo,ParseOptionreading URL keys client-side, fullPreLogin -> Login -> PostLoginwith no server. Hub and arena maps load the GameInfo then hang on missing backend services.Login transport: the launcher opens a raw TLS 1.0 ClientHello on tcp/24000, OpenSSL 0.9.x-era cipher list, no extensions, no SNI.
libeay32.dll/ssleay32.dlland a pinnedtrusted.crtship inBinaries/.Package header quirk: every
.ufile carries an extra 4-byte field immediately after the 16-byte package GUID that stock UE3 v407 does not have (looks like a per-package checksum). Consume thatuint32and the rest parses as stock. (Since Phase 1 I’ve found a second one: an extra trailinguint32on every export table entry, and one extra operand byte on theEX_StructMemberbytecode token. All small, all local. There’s a whole post about that.)
What I’m asking:
- Is “retail licensee UE3 build ships with commandlet dispatch and
listen-server support gated out” the normal state of things for this era
(roughly 2007 to 2009), or does it point at a specific build config
(
WITH_SERVER_CODE=0, strippedUCommandletregistration, etc.)? - Has anyone gotten a retail UE3 client of this era to host, listen or dedicated, without the original server build? Any route I’m missing before I commit fully to rebuilding the server from decompiled script?
- The extra post-GUID
uint32in package headers: known Auran / licensee thing? Anyone have a UELib / UE Explorer build registration for (407, 36)? (I’ve since written one, it’s on the devlog, but I’d love to know if someone got there first.) - The
?listentocorrupt-filesre-exec: does that read as an anti-tamper / CRC gate specifically, or just the generic fatal handler catching an unsupported code path?
Happy to share raw Launch.log excerpts for any of it. Reply here, or the devlog
has a repo linked from the homepage.
Next up
Assuming nobody tells me I’ve missed an obvious front door, the work continues where it is: reading the decompiled server code and rebuilding the smallest possible arena server that a real client will connect to. But genuinely, if you see a hole in the above, say so. Better now than later.