Hi everyone,
I’m working on CAVS, an open-source toolkit for smaller game updates, patch generation, and runtime content delivery.
Repository: GitHub - orelvis15/cavs: Content-addressed delivery for game updates, assets, and engine packs — smaller downloads, persistent cache reuse, and byte-identical reconstruction. · GitHub
Docs / website: CAVS — Content-addressed delivery for game updates
I’m currently focusing mainly on Godot.
The part I’m most interested in testing is dynamic content updates: downloading an updated .pck, verifying it, and mounting it at runtime with ProjectSettings.load_resource_pack().
A minimal Godot-side example would look something like this:
var cavs := CavsClient.new()
await cavs.update_pack({
"server_url": "http://localhost:8990",
"asset": "game_content",
"version": "1.0.1",
"cache_dir": "user://cavs_cache",
"output_path": "user://packs/game_content_1.0.1.pck"
})
ProjectSettings.load_resource_pack("user://packs/game_content_1.0.1.pck")
The idea is that the game can request updated content, download only what is needed, reconstruct the updated .pck, verify it, and then mount it as an additional resource pack.
Why this may be useful for Godot developers
Godot projects often ship content through .pck files or additional resource packs. Depending on how the project is exported or packed, a small change can sometimes produce a much larger update than expected.
CAVS tries to help with two related problems:
-
Runtime content updates
Useful when the game itself downloads or updates content after launch. -
Build/update analysis
Useful for understanding why a.pckupdate is large and whether the build layout could be improved.
It can help answer questions like:
- Why did this small change create a large update?
- Which part of the
.pckchanged? - Would splitting content into extra resource packs help?
- How much would players need to download?
- Can previous installed data be reused instead of downloading everything again?
Minimal CLI flow
The CLI side can be very small for a basic test:
cavs pack game_content_v1.pck --asset game_content --version 1.0.0 -o release_1.0.0.cavs
cavs pack game_content_v2.pck --asset game_content --version 1.0.1 --prev release_1.0.0.cavs -o release_1.0.1.cavs
cavs serve ./releases --port 8990
Then the Godot client can request the new version and mount the reconstructed .pck.
There are more advanced commands for analysis, benchmarking, signatures, SDK integration, and pipeline usage, but I’m trying to keep the first Godot workflow as simple as possible.
Plugin vs platform-level patching
A Godot plugin is not always required.
If a launcher or platform updates the game before it starts, the game itself does not need to understand the patch format.
But if the game should download or update content while running, then a Godot plugin becomes useful. That is the area I’m focusing on: runtime content updates, extra .pck / resource-pack delivery, and workflows where the game can request or mount updated content.
What CAVS currently includes
CAVS currently provides:
- Godot PCK analysis.
- Runtime-oriented update flow for additional
.pckcontent. - CLI tools for packing, previewing, applying, and verifying updates.
- Offline
.cavsplanupdate plans. - Signature and verification tools.
- Pack-file analysis for shifted data, scattered changes, compressed blobs, large packs, and TOC/offset issues.
- Benchmarks against full downloads, butler offline, bsdiff, xdelta3, and fixed-chunk models.
- SDKs that wrap the Rust core libraries for pipeline integration.
- A local development server for testing update workflows.
Looking for feedback
CAVS is still a young project, and I know there are many real-world Godot cases I have not tested yet.
I would really appreciate feedback from anyone willing to try it with a small Godot project, a .pck export, or a simple update comparison.
Useful feedback could include:
- Testing CAVS with real Godot
.pckfiles. - Testing runtime content update workflows.
- Comparing full update size vs CAVS update size.
- Testing extra resource-pack or DLC-style workflows.
- Reporting confusing CLI behavior.
- Reporting missing documentation.
- Sharing cases where CAVS works well.
- Sharing cases where it does not work well.
Even small feedback would help a lot at this stage.
Thanks for reading, and I’d be grateful for any thoughts from the Godot community.
