Official Godot 4.x Client SDK (addons/forge_distro) and Publisher CLI (distro) for distro.dforge.ca by Digital Forge Studios Inc. (Canada).
Distro provides zero-egress build delivery, hot .pck resource patching, player cloud state persistence with offline caching, and remote runtime configuration for Godot 4.x and standalone applications.
addons/forge_distro/— Godot 4.x EditorPlugin andForgeDistroautoload singleton (DistroLoader.gd,ForgeDistro.gd,plugin.cfg). Ready for direct installation via the Godot Asset Library or submodule.crates/distro-cli/— ThedistroRust publisher CLI for hashing artifacts, requesting presigned Cloudflare R2 upload URLs, uploading builds, and registering release manifests.crates/distro-core/— Shared Rust types, SemVer comparison, SHA-256 verification helpers, and S3/R2 SigV4 presigning.tests/— Headless Godot 4.x test suite verifying SDK initialization, SemVer checks, offline cloud save caching, and API endpoint alignment.
- Copy
addons/forge_distrointo your Godot 4.x project'sres://addons/forge_distrodirectory (or install from the Godot Asset Library). - In Godot, open Project → Project Settings → Plugins and enable Distro SDK.
- Enabling the plugin automatically registers
ForgeDistro(res://addons/forge_distro/ForgeDistro.gd) as an Autoload singleton and addsforge_distro/config/*settings to yourproject.godot.
- Enabling the plugin automatically registers
- Configure your application in Project Settings → General → Forge Distro → Config:
forge_distro/config/app_id: Your application slug (e.g."my-game")forge_distro/config/client_key: Your public client key ("distro_pub_...")forge_distro/config/base_url:"https://distro.dforge.ca"forge_distro/config/auto_check_updates:true
func _ready() -> void:
var loader = ForgeDistro.get_default_loader()
loader.update_available.connect(_on_update_available)
loader.update_downloaded.connect(_on_update_downloaded)
ForgeDistro.check_for_updates()
func _on_update_available(version: String, notes: String, mandatory: bool, manifest: Dictionary) -> void:
print("Update v%s available: %s" % [version, notes])
ForgeDistro.start_download()
func _on_update_downloaded(file_path: String) -> void:
# SHA-256 checksum is automatically verified before update_downloaded is emitted.
# Hot-swap .pck in-memory or launch platform installer (.apk / .dmg / .exe):
ForgeDistro.apply_update(file_path)# Save dictionary payload to a named slot (cached locally first, then synced to Distro)
ForgeDistro.save_data("profile", {
"coins": 1250,
"unlocked_levels": ["stage_1", "stage_2"]
})
# Load slot (fetches from Distro and falls back to local cache if offline)
ForgeDistro.load_completed.connect(func(app_id: String, slot_key: String, data: Variant):
print("Loaded slot %s for %s: %s" % [slot_key, app_id, data])
)
ForgeDistro.load_data("profile")
# List or delete save slots
ForgeDistro.list_data()
ForgeDistro.delete_data("profile")ForgeDistro.config_loaded.connect(func(app_id: String, config: Dictionary):
var xp_multiplier: float = ForgeDistro.get_config("double_xp_weekend", 1.0)
print("Active XP Multiplier: ", xp_multiplier)
)
ForgeDistro.fetch_remote_config()Build and install from source using Cargo:
cargo install --git https://github.com/digitalforgeca/forge-distro distro-cli- Sign in at https://distro.dforge.ca via magic link to create an application and obtain your Publisher Secret Key (
distro_sec_...). - Publish your
.pck,.apk,.dmg, or.exeartifact:
export DISTRO_API_KEY="distro_sec_..."
distro publish \
--app my-game \
--version 0.1.0 \
--version-code 1 \
--file ./build/my-game.pck \
--channel stable \
--notes "Initial beta release"The CLI calculates the local SHA-256 digest, requests a presigned Cloudflare R2 upload URL from distro.dforge.ca, streams the binary directly to edge storage, and registers the new version manifest.
# Set a public configuration value
distro config set --app my-game --key motd --value '"Welcome to the Beta!"'
# Set a server-only secret value (excluded from public client config responses)
distro config set --app my-game --key webhook_secret --value "sec_..." --secret
# Inspect active manifest or config
distro manifest get --app my-game
distro config get --app my-game
distro statusAll Distro HTTP endpoints are unversioned and return a standard JSON envelope {"success": true, "data": ...}:
| Method | Endpoint | Auth Header | Description |
|---|---|---|---|
GET |
/health |
None | Service health status |
GET |
/{app_id}/manifest |
None / Public Key | Fetch active release manifest & artifact hashes |
POST |
/{app_id}/releases |
X-Distro-Key: distro_sec_... |
Register a new release manifest |
POST |
/{app_id}/storage/presigned-upload |
X-Distro-Key: distro_sec_... |
Generate a presigned R2 PUT upload URL |
GET |
/{app_id}/config |
None / Public Key | Fetch public runtime configuration |
POST |
/{app_id}/config |
X-Distro-Key: distro_sec_... |
Upsert a public or secret config entry |
POST |
/{app_id}/data/save |
X-Distro-Key: distro_pub_... |
Save player slot JSON + SHA-256 checksum |
GET |
/{app_id}/data/load/{user_id}/{slot_key} |
X-Distro-Key: distro_pub_... |
Load player slot JSON |
GET |
/{app_id}/data/list/{user_id} |
X-Distro-Key: distro_pub_... |
List all save slot metadata for a player |
DELETE |
/{app_id}/data/{user_id}/{slot_key} |
X-Distro-Key: distro_pub_... |
Delete a player save slot |
Always run tests with an explicit timeout:
# Rust workspace unit tests (manifest SemVer, SHA-256 checksums, S3 SigV4 presigning)
timeout 60 cargo test --workspace
# Godot 4.x headless SDK test suite
timeout 20 godot --headless --path . res://tests/TestDistroSdk.tscnMIT License — Copyright (c) 2026 Digital Forge Studios Inc. (Canada). See LICENSE for details.