How to Implement Incremental Client Autoupdate on Your MU Online Server
Set up a launcher with incremental autoupdate for your MU Online server client: version manifest, file diffing, per-patch downloads, and integrity checks, avoiding full re-downloads on every update.
Every time you update your MU Online server's client — a new map, a custom item, a bug fix — the player needs to download that change before logging in. Without an incremental autoupdate system, this usually means downloading the entire client again, which drives away players with slower internet an
Every time you update your MU Online server's client — a new map, a custom item, a bug fix — the player needs to download that change before logging in. Without an incremental autoupdate system, this usually means downloading the entire client again, which drives away players with slower internet and creates traffic spikes on your file server. Incremental autoupdate solves this by comparing what the player already has with what changed, downloading only the difference. This tutorial covers the full architecture: manifest generation, integrity verification, selective downloading, and failure handling.
How incremental autoupdate works
The principle is simple: the server maintains a manifest — a list of every client file with its current hash and size. When it opens, the launcher downloads this manifest and compares it against a local manifest (generated from the files the player already has installed). Any file whose hash differs (or that doesn't exist locally) goes into the download queue. Identical files are skipped. The practical result: a 50 MB update on a 3 GB client downloads only those 50 MB, not the full 3 GB.
Prerequisites
- A launcher already working for your server (custom or based on some MU launcher framework).
- Access to a file server (CDN, VPS, or storage) to host the manifest and patches.
- A script or tool to hash all client files (can be done in PHP, Python, or C#).
- A test environment separate from the production client, to validate the flow without affecting real players.
Manifest structure
The manifest is typically a JSON file hosted alongside the patches, listing each relevant client file:
{
"version": "1.42.0",
"generated_at": "2026-07-20T14:00:00Z",
"files": [
{ "path": "Data/Item/Item1.bmd", "sha256": "a1b2c3...", "size": 184320 },
{ "path": "Data/Map/World1.map", "sha256": "d4e5f6...", "size": 942112 },
{ "path": "Main.exe", "sha256": "9f8e7d...", "size": 15728640 }
]
}
Generating this manifest should be an automated step every time you publish an update — never manual, because a single wrong hash invalidates the entire update for every player.
Generating the manifest on the server (example script)
#!/bin/bash
# generate_manifest.sh - walks the client folder and generates manifest.json
OUTPUT="manifest.json"
echo '{"version":"'$1'","generated_at":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","files":[' > $OUTPUT
find ./client -type f | while read -r file; do
hash=$(sha256sum "$file" | awk '{print $1}')
size=$(stat -c%s "$file")
relpath=$(echo "$file" | sed 's|^./client/||')
echo '{"path":"'$relpath'","sha256":"'$hash'","size":'$size'},' >> $OUTPUT
done
sed -i '$ s/,$//' $OUTPUT
echo ']}' >> $OUTPUT
Run this script as part of your publishing pipeline, always generating a fresh manifest before uploading patches to the file server.
Launcher logic (hash comparison)
On startup, the launcher needs to:
- Download the remote
manifest.json. - Calculate (or read from a local cache) the hash of each already-installed file.
- Compare both lists and build the queue of divergent or missing files.
- Download only the queued files, preferably in parallel (2-4 simultaneous connections).
- Validate the hash of each downloaded file before overwriting the original.
| Step | Recommended location | Note |
|---|---|---|
| Local hash cache | local_manifest.json file next to the executable | Avoids recalculating the hash of everything on every launch |
| Download | Temporary _update_tmp/ folder | Never writes directly to the final folder |
| Post-download validation | SHA-256 hash of the downloaded file | Only moves to the final folder if it matches |
| Update log | Log file with timestamp and list of updated files | Makes support easier in case of error |
Binary diffing for large files
For files like the main executable or large map packages, even a small change forces a full re-download of the file in the basic model. An additional optimization is binary diffing (tools like bsdiff/bspatch): the server generates a small patch containing only the binary difference between the old and new version, and the launcher applies that patch locally instead of downloading the complete file. This is more complex to implement, but worth it for large files that change with moderate frequency.
CDN and distribution
Hosting the manifest and patches on a CDN (instead of just the game server's VPS) reduces load on the main server during update spikes (for example, right after a new season is announced). Configure appropriate cache-control on the manifest (short, to reflect changes quickly) and on the patch files (long, since a file with a fixed hash never changes its content).
Handling download failures
Unstable connections are common among MU Online players in Brazil. The launcher should:
- Automatically retry (2-3 attempts) a file that failed, before marking the update as failed.
- Allow resuming from where it stopped (partial download) instead of restarting the file from scratch, especially for large files.
- Never apply a partially downloaded file — post-download hash validation is the final safeguard against this.
- Show the player a clear message (file name, progress, specific error) instead of a "generic update error."
Versioning and rollback
Keep the last 2-3 previous manifests accessible on the file server. If an update causes a serious problem (widespread crashes, a broken item), you need to be able to quickly revert the active manifest to the previous version, without depending on rebuilding the patches from scratch.
Testing before publishing
Always test the update in at least three scenarios before releasing to everyone: (1) a clean client with no prior installation; (2) a client on the immediately previous version; (3) a client on a much older version (several updates behind), to ensure the incremental system covers larger version jumps, not just the latest patch.
Common errors and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| Launcher downloads everything even though few files changed | Local manifest not generated or hash calculated incorrectly | Review local manifest generation and caching |
| Update gets stuck on a specific file | Large file with no resume support | Implement resumable downloads (range requests) |
| Client corrupted after update | File applied without post-download validation | Add a hash check before moving to the final folder |
| Old-version players don't update correctly | Incremental logic only covers the previous version, not larger jumps | Always generate the manifest with the full current list, not just the diff from the last version |
| Spike of 503 errors on the file server | All players downloading at once without a CDN | Distribute patches via CDN with proper caching |
Launch checklist
- Automated manifest-generation script in the publishing pipeline.
- Launcher correctly comparing local vs. remote hashes.
- Download to a temporary folder with post-download validation.
- Resumable download support for large files.
- CDN configured for manifest and patches.
- Manifest rollback tested and documented.
- Tests done on a clean client, previous version, and old version.
With incremental autoupdate working, publishing new updates stops being a risky event and becomes a natural part of the server's maintenance cycle — to review how this client connects to the project's overall infrastructure, see the guide on how to create a MU Online server.
Frequently asked questions
What's the difference between incremental autoupdate and a full download?
With a full download, every update downloads the entire client (several GB), even if only one file changed. With incremental updates, the launcher compares a version manifest and downloads only the changed files, cutting update time from hours to seconds or minutes in most cases.
Do I need to rewrite my launcher from scratch to get incremental autoupdate?
Not necessarily. Most MU launchers already have a version-checking routine; the main work is generating the manifest (a list of files with hashes) on the server and adjusting the launcher's logic to compare local vs. remote hashes instead of downloading everything.
Which hash algorithm should I use to compare files?
SHA-256 is the safest and currently recommended option. MD5 is still used by legacy launchers because it's faster to compute, but it has known theoretical collisions — for a MU client the practical risk is low, but SHA-256 is the more robust choice for new projects.
How do I handle very large files, like the main executable?
For large files that change frequently, consider using binary diffing (bsdiff/bspatch) instead of resending the entire file. This further reduces download volume when only a small part of the binary changes between versions.
What happens if the update fails partway through the download?
The launcher should validate each file's hash after download and, if it doesn't match, re-download only that file (not the entire update). Keep downloaded files in a temporary folder and only move them to the final folder after validation, avoiding a corrupted install if the connection drops.