Bevy plugin for the GGRS P2P rollback networking library.

Overview

Bevy_GGRS

Bevy plugin for the ๐Ÿ‘‰ GGRS P2P rollback networking library. The plugin creates a custom stage with a separate schedule, which handles correctly advancing the gamestate, including rollbacks. It efficiently handles saving and loading of the gamestate by only snapshotting relevant parts of the world, as defined by the user. It is supposed to work with the latest released version of bevy.

For explanation on how to use it, check the ๐Ÿ‘‰ examples!

How it works

The GGRS plugin creates a custom GGRSStage which owns a separate schedule. Inside this schedule, the user can add stages and systems as they wish. When the default schedule runs the GGRSStage, it polls the session and executes resulting GGRSRequests, such as loading, saving and advancing the gamestate.

  • advancing the gamestate is done by running the internal schedule once.
  • saving the gamestate is done by creating a snapshot of entities tagged with a bevy_ggrs::Rollback component and saving only the components that were registered through register_rollback_type::(). The plugin internally keeps track of the snapshots together with the GGRS session.
  • loading the gamestate applies the snapshot by overwriting, creating and deleting entities tagged with a bevy_ggrs::Rollback component and updating the registered components values.

Since bevy_ggrs operates with a separate schedule, compatibility with other plugins might be complicated to achieve out of the box, as all gamestate-relevant systems needs to somehow end up inside the internal GGRS schedule to be updated together the rest of the game systems.

Development Status

โš ๏ธ Disclaimer โš ๏ธ : bevy_ggrs is in a very early stage. This plugin currently depends on the latest bevy developments and is thus incompatible with bevy releases on crates.io. Once bevy 0.6 releases, I will also make a stable release!

Licensing

Bevy_GGRS is dual-licensed under either

at your option.

Comments
  • Invalidated Entity's

    Invalidated Entity's

    To answer your side question:

    GGRS rewinds by loading an old state and overwriting current values. When loading a snapshot, items that have been deleted will have to be recreated and thus get a new entity id. In the same time, your inventory will be overwritten with the entity id vector it had at that point in time. These IDs will then probably be invalid.

    Originally posted by @gschup in https://github.com/gschup/bevy_ggrs/issues/11#issuecomment-1306735337


    I started a new thread to avoid cluttering the other one.

    So, if the entities in an inventory component could end up invalidated by the rollback, does that mean Bevy's hierarchy could get corrupted too?

    Because the hierarchy works by having Parent and Children components where Entitys are used for references, similar to an inventory.

    opened by zicklag 6
  • Map Entity IDs When Writing Snapshot to World

    Map Entity IDs When Writing Snapshot to World

    Resolves #29.

    I haven't really tested this yet, but this should fix entity mapping and hierarchy problems.

    If this works it'd be good to have some documentation on how this effects types that store entities.

    For instance, if you create your own Inventory component that needs to be synced, you must implement and reflect MapEntities for it, so that it will get the new entity IDs when the snapshots are applied.

    opened by zicklag 5
  • [Question] What Will Be the New Snapshot Strategy?

    [Question] What Will Be the New Snapshot Strategy?

    Hey there!

    I saw this in the README:

    Since I am not happy with using bevy-reflect to save and load snapshots of the world, I am looking forward to this refactoring!

    I've been working on and exploring some Bevy networking stuff and I ended up using Reflect and a custom CompactReflectSerializer/Deserializer to serialize byte-efficient versions of all the components for snapshots.

    It sounds like you were using Reflect too, but aren't going to be anymore and I was curious how you were going to do the snapshots when the new stageless implementation lands, if it isn't going to use reflection.

    I might be able to make use of whatever it is.

    opened by zicklag 2
  • update for 0.8 with some more changes

    update for 0.8 with some more changes

    I tried to get #25 working and ran into some more issues. I don't know how to add more changes to someone else's PR, so here's a new one.

    Apparently a bevy 0.8 TypeRegistry contains some primitive types by default, which caused a "Unregistered Type in GGRS Type Registry" panic. I couldn't find a convenient way to construct a TypeRegistryArc that's actually empty in the new docs, so we have to construct one directly?

    I also had into short_name and type_name on a TypeRegistration actually returning different names for the same type. This made write_to_world overlook the components that were saved in the snapshot and delete them from the world instead.

    opened by thwischm 2
  • Trouble implementing the Config trait

    Trouble implementing the Config trait

    Describe the bug I'm having trouble implementing Config and wonder if something unusual is being required by this trait or some of it's dependencies. Maybe the bytemuck version fixing, though I don't know for sure.

    error[E0599]: the function or associated item `new` exists for struct `GGRSPlugin<GGRSConfig>`, but its trait bounds were not satisfied
       --> src/main.rs:79:31
        |
    63  | pub struct GGRSConfig;
        | ---------------------- doesn't satisfy `GGRSConfig: ggrs::Config`
    ...
    79  |     GGRSPlugin::<GGRSConfig>::new()
        |                               ^^^ function or associated item cannot be called on `GGRSPlugin<GGRSConfig>` due to unsatisfied trait bounds
        |
        = note: the following trait bounds were not satisfied:
                `GGRSConfig: ggrs::Config`
    note: the following trait must be implemented
       --> /Users/paul/.cargo/git/checkouts/ggrs-151f8bd9eb75dc5d/37b83c3/src/lib.rs:178:1
        |
    178 | / pub trait Config: 'static + Send + Sync {
    179 | |     /// The input type for a session. This is the only game-related data
    180 | |     /// transmitted over the network.
    181 | |     ///
    ...   |
    193 | |     type Address: Clone + PartialEq + Eq + Hash + Send + Sync;
    194 | | }
        | |_^
    
    error[E0277]: the trait bound `GGRSConfig: ggrs::Config` is not satisfied
      --> src/main.rs:79:5
       |
    79 |     GGRSPlugin::<GGRSConfig>::new()
       |     ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `ggrs::Config` is not implemented for `GGRSConfig`
       |
    note: required by a bound in `GGRSPlugin`
      --> /Users/paul/.cargo/git/checkouts/bevy_ggrs-8ac41541d9ef4c9f/928376d/src/lib.rs:73:26
       |
    73 | pub struct GGRSPlugin<T: Config + Send + Sync> {
       |                          ^^^^^^ required by this bound in `GGRSPlugin`
    

    To Reproduce Steps to reproduce the behavior:

    1. Update bevy_ggrs_demo to use bevy 0.7, and update ggrs and bevy_ggrs to git based versions.
    2. Try to run the project with cargo run

    Updated Cargo.toml in the bevy_ggrs_demo:

    [package]
    name = "bevy_ggrs_demo"
    version = "0.1.0"
    edition = "2021"
    
    # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
    
    [dependencies]
    bevy_asset_loader = "0.8"
    bevy = "0.7"
    bytemuck = {version="1.7.3", features= ["derive"]}
    ggrs = { git = "https://github.com/gschup/ggrs", features=["sync-send"], rev="37b83c3478114e2876c133f255bc00b29c6af796" }
    bevy_ggrs = {git = "https://github.com/gschup/bevy_ggrs", rev="928376df6b37f391ef6593e0355ba5a737ec1492"}
    matchbox_socket = { git = "https://github.com/johanhelsing/matchbox", features = ["ggrs-socket"], rev="50c1e69e9f1c0f1e07e0ffd5161db0ce3f9267b5" }
    log = "0.4"
    
    [target.'cfg(target_arch = "wasm32")'.dependencies]
    ggrs = { git = "https://github.com/gschup/ggrs", features=["sync-send", "wasm-bindgen"], rev="37b83c3478114e2876c133f255bc00b29c6af796" }
    bevy_ggrs = {git = "https://github.com/gschup/bevy_ggrs", features=["wasm-bindgen"], rev="928376df6b37f391ef6593e0355ba5a737ec1492"}
    bevy-web-resizer = "0.1.0"
    web-sys = "0.3"
    

    Expected behavior Errors only related to the bevy 0.6 -> 0.7 upgrade.

    Desktop (please complete the following information):

    • OS: Only tested w/ an M1 Macbook.
    bug 
    opened by paul-english 2
  • Docs are broken

    Docs are broken

    Describe the bug The newest docs are broken

    To Reproduce Steps to reproduce the behavior:

    1. Go to https://docs.rs/crate/bevy_ggrs/latest
    2. See error

    Expected behavior I see the newest docs

    Screenshots image

    Desktop (please complete the following information):

    • OS: macOS
    • Browser [e.g. chrome, safari]: Firefox Nightly
    • Version [e.g. 22]: 101.0a1 (2022-04-29)

    Additional context Last working docs were 0.1.3

    bug 
    opened by janhohenheim 2
  • Fix Component Apply in Certain Cases

    Fix Component Apply in Certain Cases

    Removes and re-inserts components during snapshot restore, instead of using apply() which does an "update" not a "replace" of the current component data.

    For example, an apply() will do an in-place update such that apply an array to an array will add items to the array instead of completely replacing the current array with the new one.

    In Jumpy this caused a difficult to trace bug when updating the Children component for the Bevy hierarchy, where setting children to an empty array, actually left the component un-modified.

    opened by zicklag 1
  • Re-export `ggrs` Crate

    Re-export `ggrs` Crate

    This makes it easier to make sure your version of ggrs is the one compatible with bevy_ggrs and saves you from adding an extra dependency to your Cargo.toml.

    opened by zicklag 1
  • Only Depend on Bevy `bevy_render` not `render`

    Only Depend on Bevy `bevy_render` not `render`

    This removes this crate's dependency on the Bevy renderers such as bevy_text/ui/pbr, etc.

    It definitely was a little unintuitive that the render feature is different than the bevy_render feature.

    opened by zicklag 1
  • Despawned entities do not get respawned properly

    Despawned entities do not get respawned properly

    Describe the bug Despawned entities do not get respawned properly. this issue came up during the bevy_jam and is here to remind myself to look into it later.

    bug 
    opened by gschup 1
  • Fix title bar/window size in example

    Fix title bar/window size in example

    Bevy's DefaultPlugins read the window title immediately when loaded, so the initial WindowDescriptor needs to be loaded before the DefaultPlugins to take effect.

    opened by weswigham 1
  • Document Non-Synced Bevy Gotcha's ( Events, etc. )

    Document Non-Synced Bevy Gotcha's ( Events, etc. )

    Is your feature request related to a problem? Please describe. The current design of Bevy GGRS doesn't snapshot and restore Bevy events, so events that are handled in a frame may not get handled again if the frame is rolled back to.

    Describe the solution you'd like We might need a custom event resource type that is compatible with the rollback and snapshot system.

    Describe alternatives you've considered A quick attempt to snapshot the Events<T> resource from Bevy didn't turn out so well. Events<T> isn't Clone even if T: Clone, which presents challenges, and the exposed public API doesn't allow us enough access to reasonably snapshot and restore it. Even if we could, we'd have to have a way to reset the read counters on the Local<ManualEventReader<T>> storage that powers the EventReader<T> system param.

    Essentially bevy's built-in event system probably just isn't suitable for snapshot and restore, and we need some alternative, or we just have to make this as a caveat and say that you have to use components for sending events or something like that.

    Additional context I'm actually a little confused why some events in my game seem to be working fine after rollback and restore. I'm still debugging. I'm still trying to get my game working in the SyncTest mode, and things get a little confusing to debug when the world is rolling back and forth the whole time. :D

    There's a small chance that I'm misunderstanding something and events could work fine without changes, but I highly doubt it.

    enhancement 
    opened by zicklag 3
  • Add a RollbackEventHook Trait

    Add a RollbackEventHook Trait

    This allows you to register functions that will be called in response to GGRS messages.

    I think I'm going to need this or something like it for my game, but I haven't tested it yet, so it's pending evaluation. I just wanted to get it up so you could look at it and give your thoughts on the idea.

    opened by zicklag 3
  • RollbackIdProvider needs a smarter solution

    RollbackIdProvider needs a smarter solution

    Is your feature request related to a problem? Please describe. Currently, when the RollbackIdProvider reaches u32::MAX, it simply panics. Since no sensible application should have that many rollbackable entitites at the same time, there should be a smarter way to provide unique (within the rollback frame window) IDs for entities.

    Additional context The relevant code is found here.

    enhancement 
    opened by gschup 5
Releases(v0.10.0)
Owner
Georg Friedrich Schuppe
PhD Student @ KTH Stockholm
Georg Friedrich Schuppe
Lightweight p2p library. Support build robust stable connection on p2p/distributed network.

Chamomile Build a robust stable connection on p2p network features Support build a robust stable connection between two peers on the p2p network. Supp

CympleTech 88 Nov 11, 2022
A simple message based networking library for the bevy framework

Spicy Networking for Bevy bevy_spicy_networking is a solution to the "How do I connect multiple clients to a single server" problem in your bevy games

Cabbit Studios 65 Nov 17, 2022
Cross-platform, low level networking using the Rust programming language.

libpnet Linux โˆช OS X Build Status: Windows Build Status: Discussion and support: #libpnet on freenode / #rust-networking on irc.mozilla.org / #rust on

null 1.8k Dec 1, 2022
A runtime for writing reliable asynchronous applications with Rust. Provides I/O, networking, scheduling, timers, ...

Tokio A runtime for writing reliable, asynchronous, and slim applications with the Rust programming language. It is: Fast: Tokio's zero-cost abstracti

Tokio 18.3k Nov 26, 2022
The Rust Implementation of libp2p networking stack.

Central repository for work on libp2p This repository is the central place for Rust development of the libp2p spec. Warning: While we are trying our b

libp2p 2.9k Dec 3, 2022
Painless peer-to-peer WebRTC networking for rust wasm

Matchbox Painless peer-to-peer WebRTC networking for rust wasm applications. The goal of the Matchbox project is to enable udp-like, unordered, unreli

Johan Klokkhammer Helsing 350 Dec 1, 2022
Final Project for "Computer Networking Security": A Layer-3 VPN implementation over TLS

Final Project for "Computer Networking Security": A Layer-3 VPN implementation over TLS

Siger Yang 2 Jun 7, 2022
a decentralized p2p chatroom app built for practice

Yosup is an app made for the purpose of learning libp2p technology, asynchronous rust, ways to incorporate a single protocol over multiple interfaces, and cryptography.

Louis Birla 2 Jan 14, 2022
Reliable p2p network connections in Rust with NAT traversal

Reliable p2p network connections in Rust with NAT traversal. One of the most needed libraries for any server-less / decentralised projects

MaidSafe-Archive 946 Nov 10, 2022
Prototype for Koru, a parametrized p2p monetary system.Checkout

Koru About This is a prototype for Koru, a parametrized p2p monetary system consisting of: Mutual credit Voting and decision making platform (for econ

Koru 6 Oct 9, 2022
Reliable p2p network connections in Rust with NAT traversal

Reliable p2p network connections in Rust with NAT traversal. One of the most needed libraries for any server-less, decentralised project.

MaidSafe-Archive 946 Nov 10, 2022
A Rust compiler plugin and support library to annotate overflow behavior

overflower This project contains a compiler plugin and supporting library to allow the programmer to annotate their code to declare how integer overfl

null 102 Nov 12, 2022
Barebones egui_baseview vst2 plugin with basic parameter control

egui_baseview_test_vst2 Based on baseview_test_vst2 Barebones baseview/egui_baseview vst2 plugin. It implements an egui ui for the vst gain effect exa

null 16 Aug 6, 2022
Barebones imgui_baseview vst2 plugin with basic parameter control

imgui_baseview_test_vst2 Based on baseview_test_vst2 Barebones baseview/imgui_baseview vst2 plugin. It implements a imgui-rs ui for the vst gain effec

null 3 Nov 16, 2021
A WireGuard UWP VPN plugin.

WireGuard UWP A Universal Windows Platform (UWP) VPN Plug-in for WireGuardยฎ written in Rust. Windows provides a plug-in based model for adding 3rd-par

Luqman Aden 91 Dec 4, 2022
Hammerspoon plugin and API to interact with Yabai socket directly

Yabai.spoon NOTE: no longer using it or intending to maintain it see #2. Yabai.spoon is lua 5.4 library to interact with yabai socket directly within

null 2 May 17, 2022
Bevy asset loader that transparently supports loading over http(s)

Bevy Web Asset This is a tiny crate that that wraps the standard bevy asset loader, and adds the ability to load assets from http and https urls. Supp

Johan Klokkhammer Helsing 25 Nov 21, 2022
Client-server architecture for Bevy

Sabi Opinionated client-server architecture for Bevy Goals: Prediction based on inputs Replication by a simple derive and adding a system to server/cl

Aceeri 10 Nov 14, 2022
The gRPC library for Rust built on C Core library and futures

gRPC-rs gRPC-rs is a Rust wrapper of gRPC Core. gRPC is a high performance, open source universal RPC framework that puts mobile and HTTP/2 first. Sta

TiKV Project 1.6k Nov 25, 2022