A server hands a client a manifest; the client downloads what it is missing, verifies it, and mounts it — on Windows, macOS, Linux, Android, iOS and in the browser.
Requires dot-core.
var cloud := DotCloudClient.new()
add_child(cloud)
cloud.config = DotCloudConfig.new()
cloud.config.trusted_keys = {"default": PUBLIC_KEY_PEM}
await cloud.start()
cloud.phase_changed.connect(func(_p, text): status_label.text = text)
cloud.progress_changed.connect(func(p): bar.value = p.fraction * 100.0)
var res := await cloud.acquire("https://cdn.example.com/dm_arena/manifest.json")
if res.ok:
get_tree().change_scene_to_file(res.value)
Publishing is a headless CLI that produces a static directory — a
manifest.json plus an objects/ tree — that any web server or CDN hosts with
no configuration:
godot --headless --path . --script addons/dot_cloud/publish/dot_cloud_cli.gd -- \
keygen --private keys/content.key --public keys/content.pub
godot --headless --path . --script addons/dot_cloud/publish/dot_cloud_cli.gd -- \
publish --source content/dm_arena --out dist/dm_arena \
--id dm_arena --version 1.2.0 --entry arena.tscn --key keys/content.key
The two constraints that shaped everything
Godot cannot unmount a resource pack. Not slowly, not with a workaround —
the API does not exist. So every content set gets its own versioned path,
res://<root>/<content_id>/<version>/, and nothing ever needs replacing.
“Unloading” means dropping references, not reclaiming the file table. That one
fact is why swapping games at run time works at all.
Unsigned content is remote code execution. A Godot pack can contain scripts,
so a manifest decides what gets executed. require_signed_manifests defaults to
on and the config refuses to validate without a trusted key. You can turn it off
for a LAN or a first-party server; it warns every time.
What it does
- Content-addressed cache. Files are stored under their SHA-256, so two games sharing an asset download it once and republishing re-downloads only what changed.
- Resumable parallel downloads. Mirror failover, HTTP range resume, a circuit breaker per source, bandwidth throttling, honest progress and ETA.
- Three sources. HTTP/CDN, a local directory (development, LAN, bundled content), and in-band over the game connection for a server with no web host.
- Quota awareness. Browser storage estimates, mobile ceilings, and least-recently-used eviction that never evicts content currently in use.
Where a game plugs in
- DotCloudSource subclass
source_name(),is_supported(),can_serve(manifest),fetch(...). Three ship —DotCloudSourceHttp,DotCloudSourceLocal,DotCloudSourceNetchan— and a fourth is yours: a torrent, a platform-specific CDN, a signed S3 URL minter.A
fetchmust write toDotCloudStore.partial_pathfor the file’s hash, resume frompartial_sizewhere it can, and finish throughcommit_partial. That is the only place the hash is verified, and writing into the object directory directly is exactly how unverified content gets mounted.- can_serve() vs is_supported()
The distinction earns its keep. A source can be perfectly healthy and still have no way to reach this manifest — an HTTP source with no
base_urlsagainst a manifest carrying no mirrors. Returning a failure fromcan_servemeans “skip me for this manifest, and say why”, and is not recorded against the circuit breaker.- priorityint
On every source. Lower runs first; the in-band fallback deliberately sits last.
- DotCloudConfig
trusted_keys,require_signed_manifests,cache_bytes,mobile_cache_bytes,web_quota_fraction,parallel_downloads,max_attempts_per_file,throttle_bytes_per_sec,mount_root,verify_before_mount,resume_downloads. Layered like everyDotConfig.- Signals
phase_changed,progress_changed,file_finished,sync_finished,content_ready,content_released,failed.
The content interface other addons expect
Register a DotCloudClient and it publishes itself under dot_cloud_client.
dot-map’s loader and dot-server’s game change both reach it through that
name and call:
ensure(content_id: String, version: String) -> DotResult
is_mounted(content_id: String, version: String) -> bool
An absent cloud client is a legitimate configuration
Every call site treats “no dot_cloud_client” as “this deployment ships its
content inside the build” — which is true for most of them, and is therefore
indistinguishable from a client that failed to register. When a delivered map or
a delivered game silently does nothing, check the registry first.
