Cross-platform (including wasm) persistent key value store plugin for rust games/apps

Overview

bevy_pkv

crates.io MIT/Apache 2.0 docs.rs ci

bevy_pkv is a cross-platform persistent key value store for rust apps.

Use it for storing things like settings, save games etc.

Currently, it does not depend on bevy, so it may be used in other games/apps as well.

Usage

Add a store resource to your app

App::new()
    .add_plugins(DefaultPlugins)
    .insert_resource(PkvStore::new("FooCompany", "BarGame"))
    .run();

This will create or load a store in the appropriate location for your system, and make it available to bevy systems:

fn setup(mut pkv: ResMut<PkvStore>) {
    if let Ok(username) = pkv.get::<String>("username") {
        info!("Welcome back {username}");
    } else {
        pkv.set_string("username", "alice")
            .expect("failed to store username");

        // alternatively, using the slightly less efficient generic api:
        pkv.set("username", &"alice".to_string())
            .expect("failed to store username");
    }
}

Using your own types implementing serde::Serialize and Deserialize:

#[derive(Serialize, Deserialize)]
struct User {
    name: String,
}

fn setup(mut pkv: ResMut<PkvStore>) {
    if let Ok(user) = pkv.get::<User>("user") {
        info!("Welcome back {}", user.name);
    } else {
        let user = User {
            name: "bob".to_string(),
        };
        pkv.set("user", &user).expect("failed to store user");
    }
}

See the examples for further usage

Implementation details

Native

sled and rmp_serde (MessagePack) is used for storage. It's creating a sled db in bevy_pkv in the appropriate application data directory for your system.

Wasm

Window.localStorage and serde_json is used for storage. Perhaps IndexedDb and something else would have been a better choice, but its API is complicated, and I wanted a simple implementation and a simple synchronous API.

Bevy version support

The main branch targets the latest bevy release.

I intend to support the main branch of Bevy in the bevy-main branch.

bevy bevy_pkv
any 0.5, main
0.7 0.2, 0.3, 0.4
0.6 0.1

License

MIT or Apache-2.0

Comments
  • PkvStore Resource fix

    PkvStore Resource fix

    My attempt at fixing PkvStore not being a resource. Not sure if it is possible to add something smaller than bevy_ecs to dependencies. The error is PkvStore: bevy::prelude::Resource is not satisfied for Res<PkvStore>, ResMut<PkvStore>, ect.

    enhancement 
    opened by Aultus-defora 5
  • Support clear method?

    Support clear method?

    In some situation,it may need to clear kv data when logout app ,sled and localstorage both support clear function,so can you support it or can i create a PR?

    enhancement 
    opened by nickming 2
  • set_string on WASM splits the value on dots

    set_string on WASM splits the value on dots

    On WASM, when I use pkv.set_string to store a string with a dot (.) in it (in the value, not in the key), it splits on the dot and stores an array instead. Needless to say, trying to load that value fails because the type is wrong.

    This only happens with set_string - using set stores the value correctly.

    This only happens on WASM - on native set_string works properly.

    I'm using the version from the latest commit (02c18d117ff7a299ac6e439549aba242b81887bb)

    opened by idanarye 1
  • Put bevy plugin behind a feature/define scope?

    Put bevy plugin behind a feature/define scope?

    There isn't that much bevy specific code in this crate.

    Doing so would perhaps make the crate useful for other cross-platform game engines/apps as well.

    enhancement question 
    opened by johanhelsing 1
  • Add a scope setting for avoiding conflicts in localstorage

    Add a scope setting for avoiding conflicts in localstorage

    If the same protocol-domain-port triplet is used by multiple libraries or apps, the keys may conflict with each other. i.e. it's currently probably a bad idea to use generic names like "user".

    Perhaps it would make sense to add a store-wide setting for adding a prefix or "name" to keys in order to prevents collisions

    enhancement good first issue wasm 
    opened by johanhelsing 0
  • Platform specific paths for sled db

    Platform specific paths for sled db

    Currently the sled db is created in the current working directory. It should probably be put in some meaningful folder depending on the platform.

    Like $HOME/AppData/LocalLow/Developer/Game on windows and ~/.local/share/developer/game on linux.

    enhancement good first issue native 
    opened by johanhelsing 0
  • Wasm support

    Wasm support

    ~~The store is now a NonSend resource... which is a bit unfortunate, not sure what we can do about that... Maybe we can make it a special system param that is nonsend on wasm only?~~

    ~~The implementation is a bit messy now... Probably would be a good idea to move platform specific implementations into separate files...~~

    The error types are currently different based on platform... Maybe not ideal?

    opened by johanhelsing 0
  • Default and/or Insert, onboarding.

    Default and/or Insert, onboarding.

    The first time an application is run, using a default value appears clunky. Catching the NotFound Error is natural enough to have specific helpers for that case. There is also an argument that this is not an error and get should return an Result<Option<_>... sounds interesting.

    Notice the examples are bad(delete those b4 someone copies them), they just roll through any errors by treating any error as the NotFound condition.

    Similar to: https://github.com/hwchen/keyring-rs/issues/103

    It would be nice if there were rust conventions surrounding these APIs, if you look at std they almost always returns an Option... noting the difference that IO errors are not a thing for HashMap.

        let h: PkvStore;
    
        let _limits: Option<Limits> =
            h.get("limits")
                .or_else(|x| -> Result<_, Box<dyn std::error::Error>> {
                    if matches!(x, bevy_pkv::GetError::NotFound) {
                        h.set("limits", &Option::<Limits>::None)?;
                        Ok(None) /// Indicating the user has not seen the wizard for this.
                    } else {
                        Err(x)?
                    }
                })?;
    
        let _old_boot_id: Option<u64> = h.get("boot_id").map(Option::Some).or_else(
            |x| -> Result<_, Box<dyn std::error::Error>> {
                if matches!(x, bevy_pkv::GetError::NotFound) {
                    Ok(None) /// Value set in next block.
                } else {
                    Err(x)?
                }
            },
        )?;
    
        let boot_id: u64 = rand::thread_rng().gen();
        h.set("boot_id", &boot_id)?;
    

    I think there are better ways to write this, suggestions welcome.

    opened by cheako 3
  • Need more than 5Mb cache size

    Need more than 5Mb cache size

    There's a hard limit on chrome of 5Mb which is utf16 so typically you'll have 2.5mb to play with.

    IndexedDb seems to have a minimum of 10x the size by default but looks to be much bigger if you have a large storage size.

    It would be great if there was a feature to use indexeddb.

    enhancement wasm 
    opened by gilescope 3
  • Custom serializers

    Custom serializers

    It would be nice it was possible to customize what kind of serializer is used.

    Currently it's hard-coded to rmp-serde (messagepack with struct maps) on native and serde_json on wasm.

    enhancement 
    opened by johanhelsing 1
Releases(v0.6.0)
  • v0.6.0(Nov 14, 2022)

    What's Changed

    • Support clear data by @nickming in https://github.com/johanhelsing/bevy_pkv/pull/12
    • Bevy 0.9 Resource support by @Aultus-defora in https://github.com/johanhelsing/bevy_pkv/pull/16
    • Crate level rustdocs

    New Contributors

    • @nickming made their first contribution in https://github.com/johanhelsing/bevy_pkv/pull/12
    • @Aultus-defora made their first contribution in https://github.com/johanhelsing/bevy_pkv/pull/16

    Full Changelog: https://github.com/johanhelsing/bevy_pkv/compare/v0.5.0...v0.6.0

    Source code(tar.gz)
    Source code(zip)
  • v0.5.0(May 11, 2022)

    What's Changed

    • Native: Use MessagePack instead of bincode https://github.com/johanhelsing/bevy_pkv/pull/5
    • Native: Place db in platform specific project data dir https://github.com/johanhelsing/bevy_pkv/pull/8
    • Wasm: Add app-specific local storage prefix https://github.com/johanhelsing/bevy_pkv/pull/8
    • Remove dependency on Bevy https://github.com/johanhelsing/bevy_pkv/pull/8

    Bug fixes

    • Wasm: set_string was broken on Wasm https://github.com/johanhelsing/bevy_pkv/pull/10

    Full Changelog: https://github.com/johanhelsing/bevy_pkv/compare/v0.4.0...v0.5.0

    Source code(tar.gz)
    Source code(zip)
  • v0.4.0(May 3, 2022)

    • Wasm support https://github.com/johanhelsing/bevy_pkv/pull/1

    Full Changelog: https://github.com/johanhelsing/bevy_pkv/compare/v0.3.0...v0.4.0

    Source code(tar.gz)
    Source code(zip)
Owner
Johan Klokkhammer Helsing
Making names and taking games
Johan Klokkhammer Helsing
A frontend to Assets purchased on Epic Games Store

Epic-Asset-Manager A frontend to Assets purchased on Epic Games Store Current Screenshot Install Arch Linux Use the AUR package Build flatpak meson _b

Acheta Games 202 Jan 3, 2023
A single-threaded polling-based Rust async executor suitable for use in games, embedded systems or WASM.

simple async local executor An Enlightware® software. Overview A single-threaded polling-based executor suitable for use in games, embedded systems or

Enlightware GmbH 16 Nov 15, 2022
A cross platform (wasm included) networking library!

bootleg_networking A cross platform (wasm included) networking library! A networking plugin for the Bevy game engine that wraps around bevy_networking

William Batista 51 Jan 1, 2023
Library for managing persistent user settings in the Bevy engine.

bevy_basic_prefs This crate provides basic preferences support for Bevy applications. The word "preferences" in this context is used to mean user sett

Talin 6 Sep 21, 2024
Library for managing persistent user settings in the Bevy engine.

bevy_basic_prefs This crate provides basic preferences support for Bevy applications. The word "preferences" in this context is used to mean user sett

Talin 6 Sep 21, 2024
A Quoridor implementation in Rust, including different AIs

Quoridor in Rust Quoridor is a zero-sum strategic board game with complete information. It was initially designed by Marko Marchesi based on Blockade

canta slaus 2 Sep 8, 2022
Cross-platform game engine in Rust.

Cross-platform game engine in Rust.

Fedor Logachev 1.9k Jan 3, 2023
Neutral cross-platform Rust game template

Rust Game Template Neutral cross-platform Rust game template. Build tool This project uses cargo-make task runner. It's required to build the project.

null 0 Feb 5, 2022
Cross platform rendering in Rust

Miniquad Miniquad is a manifestation of a dream in a world where we do not need a deep dependencies tree and thousands lines of code to draw things wi

Fedor Logachev 937 Jan 4, 2023
A cross platform classic RPG game creator written in Rust.

Eldiron - Classic RPG Creation Create RPGs for every platform with Eldiron. Eldiron v1 will be able to create games similar to the classic Ultima seri

Markus Moenig 164 Jan 2, 2023
A safe, fast and cross-platform 2D component-based game framework written in rust

shura shura is a safe, fast and cross-platform 2D component-based game framework written in rust. shura helps you to manage big games with a component

Andri 28 Jan 17, 2023
A Rust promise for games and immediate mode GUIs

⌛ poll-promise A Rust promise for games and immediate mode GUIs Description poll-promise is a Rust crate for polling the result of a concurrent (e.g.

Embark 82 Dec 17, 2022
Wein2D.js bindings for creating browser games in Rust using WebAssembly.

Wein2D.js-WASM Wein2D.js bindings for creating browser games in Rust using WebAssembly. Wein2D.js-WASM requires Wein2d.js to be loaded in the same doc

DevTaube 1 Apr 14, 2022
Tiny cross-platform webview library for C/C++/Golang. Uses WebKit (Gtk/Cocoa) and Edge (Windows)

webview A tiny cross-platform webview library for C/C++/Golang to build modern cross-platform GUIs. Also, there are Rust bindings, Python bindings, Ni

webview 10.8k Jan 9, 2023
IDE for cross-platform software development

Diversity Space IDE for cross-platform software development | 日本語 | English | Русский | READMEの英語版とロシア語版はDeepl翻訳を使用して翻訳されています Английская и русская вер

latteS 0 Feb 23, 2022
This is a cross-platform tool to historicize different branches/depots/manifests and generating pseudocode for it to compare different game updates

CSHP This is a cross-platform tool to historicize different branches/depots/manifests and generating pseudocode for it to compare different game updat

raizo 6 Jan 28, 2022
A lightweight, cross-platform epub reader.

Pend Pend is a program for reading EPUB files. Check out the web demo! Preview Image(s) Installation Building Pend is simple & easy. You should be abl

bx100 11 Oct 17, 2022
Cross-platform GPU-accelerated viewer for the Mandelbrot set and similar (escape-time) fractals

fractal_viewer A cross-platform, GPU-accelerated viewer for the Mandelbrot Set and related fractals. Try it online! Usage Scroll wheel to zoom, click

null 5 Jan 8, 2023
Cross-platform compute shader engine

wgpu-compute-toy This is the compute shader engine for https://compute.toys As well as running on the web via WebAssembly and WebGPU, it can run nativ

compute.toys 37 May 9, 2023