I built a second self-updating game database, this time for Hytale

Updated:  /  Home Lab

In my previous home-lab post, I wrote about the first game database my NAS rebuilds on its own: unturnedlord.com, built from Unturned’s server files every time the game gets patched. On 14 November, the second one went live: HyCitadel, a fan reference site for Hytale with every item, block, recipe, mob and server command in the game.

It uses the same recipe: a timer on the NAS, an extractor, Astro, a Cloudflare Worker, gates that refuse bad data, and a page for every update. So I won’t repeat any of that here. In this post, I will show you what was different the second time, because Hytale turned out to be a very different game to read data from.

Like the first one, I built it together with Claude Code. I made the calls (the name, what goes on the site, what stays off it), and Claude wrote most of the code. From picking the game to a live site with 4,367 pages took one day.

Why Hytale

Hytale came out in early access in January 2026, and it gets updated a lot: a major update every one to three months, plus smaller patch builds almost every week. The Hytale item lists I found were either hand-edited wikis or guides from the January launch, and none of them say which version of the game they describe. That’s exactly the gap a self-updating site fills.

Here’s what was new this time:

  • The official downloader, with an OAuth login that has to stay alive, instead of an anonymous SteamCMD.
  • Maven as the version check, because patch builds ship without any announcement.
  • Assets that inherit from each other through a Parent field.
  • Drop chances checked against the decompiled server code, not guessed from the files.
  • Commands read from the real server, booted once offline for each new version.
  • Two patchlines: the live release and a pre-release, each with its own pages.
  • World-generation files that moved between two versions of the game.

1. A downloader that needs a login (and a way to keep it alive)

Unturned’s dedicated server is free on Steam, and SteamCMD downloads it with an anonymous login. Hytale isn’t on Steam. Its game files come from the official hytale-downloader tool, and it only works for an account that owns the game. So the first step was buying a licence, which I did.

The login is an OAuth device code: the tool prints a short code, you approve it once in a browser, and from then on the tool refreshes its own token. That part is great for automation. The catch is in Hypixel’s server documentation: every refresh issues a new refresh token and invalidates the old one, and a token that isn’t used for 30 days dies. For a site that only needs to download something when the game changes, that’s a real risk. A quiet month would log the NAS out.

There are a few ways to deal with this, but I decided to make the token boring:

  • The update script runs a keep-alive every day (the downloader’s -print-version), even when nothing changed, so the token never gets close to 30 days old.
  • The credentials file is backed up after every good run.
  • A lock file stops two copies of the downloader from running at the same time. With rotating tokens, the second copy would refresh a token the first one just made invalid.
  • If the token dies anyway, the script gives up after 60 seconds instead of waiting for a browser approval that will never come, and sends me a Telegram message with the exact command to log in again.

The download itself is fast: the game zip is about 1.6 GB and comes down in about a minute. Inside, there’s an Assets.zip of 3.9 GB, but most of that is art: models, textures and icons. The site only needs the facts, so the script unpacks just the server data (JSON files) and the English names. That’s 14,671 files and 71 MB for the release build. The art never leaves the zip.

2. Checking for updates when nobody announces them

With Unturned, the fingerprint came from Steam. For Hytale, the obvious place to look is the official news feed, because every big update has a post with patch notes. But look at the dates: the last three patch builds of the current release (0.7.5, 0.7.6 and 0.7.7) shipped without any news post at all. A feed-based check would have missed every one of them.

What does change every time is Hypixel’s public Maven repository, where they publish the server jar for modders. Its maven-metadata.xml has the latest version in a <release> tag, and reading it needs no login:

curl -fsS https://maven.hytale.com/release/com/hypixel/hytale/Server/maven-metadata.xml \
  | grep -o '<release>[^<]*</release>'

The same file exists for the pre-release channel. So the daily run (05:47 on the NAS, a systemd user timer like last time) reads both, compares them with what the site already has, and in most cases stops there. The first real run with nothing new took 11 seconds.

3. Items that inherit from other items

Unturned’s item files are flat: everything about an item is in its own file. Hytale’s are JSON, and many of them start with a Parent. A copper sword can inherit most of its values from a generic sword and only set what’s different. So you can’t read one file and know what the item does. The extractor has to resolve the whole chain first.

It isn’t a simple “copy everything from the parent”, though. The server writes a schema that marks which fields are inherited. Tags, durability or max stack size are inherited, and objects merge key by key. A recipe, a name, an item’s quality, or its weapon and armor stats are not. If the extractor got that wrong, items would show their parent’s recipe, or their parent’s stats.

That’s why I like this gate the most: the extractor’s recipe count has to match the number of crafting recipes the real server loads (2,051 in version 0.7.7). If the inheritance logic ever drifts, the counts stop matching and nothing gets published. The other gates are the same as on UnturnedLord: zero files that fail to parse, and no count dropping by more than 5% or to zero.

4. Drop chances, checked against the server code

Drop tables were the part I trusted the least. The files describe them as nested containers with weights, and it’s easy to read them one way when the game rolls them another way. A wrong drop chance on a reference site is worse than no drop chance.

Hypixel says on its own blog that the server isn’t obfuscated and that you can decompile it, so that’s what we did. The server jar was decompiled (with Vineflower, in a throwaway Docker container on the NAS), and the extractor follows the server’s own container classes. In short:

  • in a Multiple container, every child is rolled on its own, and its weight is its percent chance;
  • a Choice container picks exactly one child by weight;
  • an Empty child inside a Choice is a weighted chance of getting nothing.

That last one matters: ignore it, and a drop looks more likely than it really is. Each mob page now shows the chance of getting at least one of each drop per kill, plus the amount.

Then we spot-checked 14 facts (recipes, mob health, drops) against other sources and found no contradictions. For a few “not craftable in this version” facts there’s no other public source either way, so those pages simply say they’re per the game files of that version.

The decompiled code stays on the NAS. Only the facts end up on the site.

5. Commands from one offline boot of the real server

The Hytale commands page was the one I wanted to get right, because a list with commands that don’t exist is worse than no list. The jar contains the descriptions, but not the arguments or permissions in a readable form.

So, for every new version, the script boots the real server once, offline, in a throwaway container on the NAS. It boots in about 12 seconds. That one boot gives the extractor:

  • the command classes the server actually registers: 173 commands and 528 subcommands, each with its arguments, aliases and permission node;
  • the config schema and --help output, for every config key and launch option;
  • the server’s own asset counts, which feed the recipe gate above.

The same boot is where the facts on the Hytale server hosting page come from: it needs Java 25, it listens on UDP port 5520, and it used about 2.4 GB of RAM with a 4 GB heap. The rest comes from the official server manual, not from other people’s guides.

6. Two patchlines, two kinds of update pages

Hytale has a pre-release channel where the next big update can be tested for weeks before it goes live. Right now, that’s Update 8. Searches for Hytale jump around every update, so I wanted it on the site, but I didn’t want pre-release data to replace the live numbers.

So the two patchlines work differently:

  • A release moves the whole site to the new version and writes a diff page against the previous release.
  • A pre-release doesn’t touch the item pages. It only writes a diff page against the current release, clearly marked as a preview, and a new preview page comes with each new pre-release build.

The first one is already live: the Update 8 pre-release changes, with 8 items added, 1 removed and 168 changed, plus 10 new commands. When Update 8 reaches the release channel, its real page writes itself on the morning after.

Testing went the same way as with UnturnedLord: a dry run on the NAS on a separate branch, simulated version bumps on a copy of the data, and a re-run that should (and did) publish nothing. This time I also checked that the extract on the NAS was byte-identical to the one on my Mac.

7. What breaking a block gives, and where mobs spawn

On the same day, we added three more things to the site: what breaking each block gives, which blocks give an item, and where each mob spawns (zone, map region, time of day and light). Potions and food now also say what they actually do.

It works the same way as the drop chances: the rules come from the decompiled server, not from guessing at the JSON. A few of them surprised me:

  • A block that doesn’t name a drop drops itself.
  • A ripe crop’s harvest isn’t in the crop block. It’s in the state of its last growth stage.
  • Spawn hours use the game’s own clock, where 6 is sunrise and 18 is sunset, and spawn light is a percent of the 0 to 15 light level.

My favourite is the Greater Health Potion. It heals 25% at once and another 50% after 5 seconds, but getting hit cancels the second part. That rule isn’t in the potion at all. It sits in the weapon-damage interaction, which clears those effects from whoever gets hit. Reading only the potion files, you’d never find it.

The tricky part came from Update 8. Its pre-release moved all the world-generation files from Server/World/Default/Zones to a new Server/WorldGen layout. On top of that, these files are lenient JSON, with comments and trailing commas, so a strict JSON parser fails on them. Instead of parsing them, the reader scans them for environment IDs and ties each one to the named region folder it sits in. That works for both layouts.

I also added a gate for it: if no environment maps to a region, the update fails. So the next time the files move, the spawn tables (like the one on the Grizzly Bear page) can’t quietly go empty.

We cross-checked 7 of these facts against public guides and wikis and found no contradictions. The potion numbers match what players wrote in their guides exactly.

The first bug wasn’t in the pipeline

The first real bug of the launch had nothing to do with the game data: the site didn’t load for me.

The domain has no server behind it, only the Cloudflare Worker, so it needs placeholder DNS records for the Worker route to catch the traffic. We’d added an IPv6 one (AAAA 100::, the address Cloudflare suggests), and every check from the session passed. But on my network, hycitadel.com didn’t open at all. It turned out that every resolver we asked (1.1.1.1, 8.8.8.8 and my router) returned an IPv6 answer for the apex and no IPv4 answer, so any IPv4-only network couldn’t reach it. Adding a proxied A 192.0.2.1 record next to it fixed it right away.

It’s a good reminder that “it works from here” is one network’s opinion.

That’s it! Every morning, my NAS keeps its Hytale login alive, checks both patchlines, and when a new build appears, the site rebuilds, checks itself against the real server and deploys without me.

Closing remarks

  • The login is the weak spot. With SteamCMD, there was nothing to expire. Here, if the NAS is off for a month, the token dies and I have to approve a new code in a browser. The daily keep-alive and the Telegram message make that unlikely and quick to fix, but it’s still a step only I can do.
  • No game art, on purpose. Hypixel owns the art, and the EULA doesn’t allow sharing the game’s files. So the site has no icons, textures or screenshots and no raw data downloads, only facts in our own tables, and a clear note that it isn’t affiliated with Hypixel Studios.
  • The second site was much faster. UnturnedLord’s setup (the gates, the deploy check, the Uptime Kuma push monitor, the update pages) was reused almost as-is, and most of the new work went into the parts listed above.

If you’ve built something similar for Hytale, or you know a better way to keep a device-code login alive, let me know.