bevy-dlc 1.0.2

DLC (downloadable content) management for Bevy games
Documentation
bevy-dlc-1.0.2 has been yanked.

Crates.io docs.rs License: MIT

Encrypt and ship your DLC! Create your DLC logic and assets and securely unlock it at runtime with signed licenses (generated using bevy-dlc CLI).

Works with Bevy's asset pipeline.

Features

  • Pack assets into encrypted .dlc or .dlcpack containers
  • Sign licenses with Ed25519 (private key embeds the symmetric encryption key)
  • Verify signatures at runtime and unlock encrypted content
  • Lazy loading of labeled assets (e.g. pack.dlcpack#sprites/player.png)
  • Product binding — prevent token reuse across games

[!NOTE] .dlc will likely be removed in 1.1 in favor of the simpler .dlcpack format, which is a single encrypted archive instead of individual encrypted files. This will be a breaking change but simplifies the format and loading logic significantly. If you want to use the current .dlc format, lock to version 0.1.0. (.dlc was experimental anyways)

Install

Add to your Cargo.toml:

bevy-dlc = "0.1"

To use the CLI tool:

cargo install bevy-dlc

Then bevy-dlc --help for available commands.

Quick Start

Generate a license

bevy-dlc generate -o keys/ my-game expansion_1

This will generate two files in keys/:

  • expansion_1.slicense — a secure license token that can be safely embedded in your game binary (e.g. with secure::include_secure_str_aes!()) or stored securely on disk. This token contains the encrypted symmetric key needed to unlock the DLC, but can't be decrypted without the private key.
  • expansion_1.pubkey — the public key that your game uses to verify the license and extract the symmetric key to unlock the DLC.

Create a pack

bevy-dlc pack --product my-game --pack [-o dlc/expansion_1.dlcpack] expansionA -- assets/expansionA

  • --product — binds the pack to a product name (enforced by DlcManager)
  • assets/expansion_1 — directory of assets to pack
  • expansion_1 — DLC ID (used in licenses to unlock this pack)
  • --pack — create a single encrypted archive (.dlcpack) instead of individual encrypted files
  • -o expansion_1.dlcpack — output path for the pack (defaults to {dlc_id}.dlcpack)

This creates expansion_1.dlcpack and prints a signed license token.

Alternatively you can use bevy-dlc generate --help to review how to generate a signed license without packing, or bevy-dlc validate --help to verify it.

[!NOTE] bevy-dlc help <command> for detailed usage of each CLI command.

Load in your app

use bevy::prelude::*;
use bevy_dlc::prelude::*;

fn main() {
    let dlc_key = DlcKey::public(pubkey_base64).unwrap();
    let license = SignedLicense::from(secure_token_str);  // from CLI output or other secure source

    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(DlcPlugin::new(
            Product::from("my-game"),
            dlc_key,
            license,
        ))
        .register_dlc_type::<MyCustomType>()  // if your pack has custom types
        .run();
}

Load assets

Once unlocked, load assets from your pack like normal:

let pack: Handle<DlcPack> = asset_server.load("expansion_1.dlcpack");
let image: Handle<Image> = asset_server.load("expansion_1.dlcpack#sprites/player.png");

Review the examples for a complete example (run with cargo run --manifest-path bevy-dlc-examples/Cargo.toml).

Suggestions and Contributions

Contributions are very welcome! Please open an issue or submit a pull request with any improvements, bug fixes, PERFORMANCE IMPROVEMENTS, or new features.

License

MIT