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
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
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
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
An ergonomic physics API for bevy games.

Heron An ergonomic physics API for 2d and 3d bevy games. (powered by rapier) How it looks like fn main() { App::build() .add_plugins(DefaultPlug

Jonathan Cornaz 313 Dec 16, 2022
A framework for making games using Macroquad.

Omegaquad A framework for making games using Macroquad. After writing maybe 5 games and finding myself always going to the previous project to copy-pa

null 14 Oct 13, 2022
Synchronize games from other platforms into your Steam library

BoilR Description This little tool will synchronize games from other platforms into your Steam library, using the Steam Shortcuts feature. The goal is

Philip Kristoffersen 823 Jan 9, 2023
A simple camera for properly displaying tile-based low resolution pixel perfect 2D games in bevy.

Bevy Tiled Camera A simple camera for properly displaying low resolution pixel perfect 2D games in bevy. The camera will adjust the viewport to scale

sark 10 Oct 5, 2022
A single-threaded executor for deferred async code for games.

This crate provides a single-threaded, sequential, parameterized async runtime. In other words, this creates coroutines, specifically targeting video game logic, though cosync is suitable for creating any sequences of directions which take time.

Jonathan Spira 49 Dec 9, 2022
Using USBPcap to side-step anticheat in games, in order to reroute rumble packets to sex toys via The Buttplug Sex Toy Control Library

Using USBPcap to side-step anticheat in games, in order to reroute rumble packets to sex toys via The Buttplug Sex Toy Control Library.

qDot 23 Jan 3, 2023
A sandbox library for making FAST voxel games

voxelize WIP A well-optimized web-based voxel engine. Development Before starting, make sure to install the following: rust node.js cargo-watch # clon

Ian Huang (Shaoru) 146 Dec 30, 2022
A framework for modding and instrumenting games.

me3 A framework for modifying and instrumenting games. Explore the docs » Report Bug · Request Feature About The Project Built With Getting Started Pr

Gary Tierney 13 Dec 18, 2022