Code Monkey home page Code Monkey logo

bevy_spicy_networking's Introduction

Spicy Networking for Bevy

crates.io docs.rs spicy

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


Using tokio as the asynchronous backend, it fully integrates into bevy to allow you to quickly add networking to your game. Simply add either the server/client plugins, register the types of messages you plan on receiving and listen for them as events!

It is meant as a unifying crate for networking. Other crates can extend your game by registering their own messages. This is achieved through the amazing typetag crate.


Contents

Documentation

You can check out the online documentation, or build it yourself by cloning this repo and running cargo doc -p bevy_spicy_networking.

For examples, check out the examples directory.

  • In server.rs you will find a simple chat server, that broadcasts the messages it receives from clients
  • In client.rs you will find a simple graphical chat client, where you can connect to a server and send messages to

(Note: Since bevy does not include a text input widget, it is a very simplified demo. This should be easy to extend once the UI part of bevy is more complete.)

Quickstart

  1. Add bevy_spicy_networking, serde_derive and typetag to your Cargo.toml
  2. Create the messages you wish to exchange beetween a client and server, or vice-versa.
    • Implement Serialize and Deserialize from Serde on it
    • Implement NetworkMessage, and make sure to annotate it with typetag::serde
    • Implement ServerMessage when it is sent to the server from a client
    • Implement ClientMessage when it is sent to a client from the server
#[derive(Serialize, Deserialize)]
struct WhisperMessage {
    recipient: UserId,
    message: String,
}

#[typetag::serde]
impl NetworkMessage for WhisperMessage {}

// In this case, its a client sending a message to a server
impl ServerMessage for WhisperMessage {
    const NAME: &'static str = "example:WhisperMessage"; // This name needs to be unique!
    // Otherwise, the recipient will mix up the messages
}
  1. On the recipient side, register the type to be received
use bevy_spicy_networking::AppNetworkServerMessage;

let appbuilder: &mut AppBuilder = /* Get an AppBuilder, which is returned by bevy from App::build() */;


// Now whenever a client sends a `WhisperMessage` the server will generate an event of
// `NetworkData<WhisperMessage>` which your application can then handle
appbuilder.listen_for_server_message::<WhisperMessage>();
  1. Listen for events of that type
fn handle_incoming_whisper_messages(
    mut whisper_messages: EventReader<NetworkMessage<WhisperMessage>>,
) {
    for whisper_message in whisper_messages.iter() {
        // Handle the whisper
    }
}
  1. Enjoy easy and 🌶 networking in your game!

Bevy Version Compatibility

Simply pick the version compatible to your bevy version:

Bevy Spicy Networking Bevy
0.5 0.5

Any version that is not compatible with the latest bevy version is in maintenance mode. It will only receive minor bug fixes from my side, or community supplied ones.

Supported Platforms

Currently only Linux and Windows are officially supported, I don't see why MacOS wouldn't be, but I do not have a Mac to test. If you have a Mac, and wish to test it out and report back, please let me know!

Roadmap

Currently bevy_spicy_networking uses TCP only. This will change at some point, with individual messages being able to specify how they should be delivered. This change will be compatible, or with only minor changes necessary.

Crates using bevy_spicy_networking

Currently none, you can help by expanding this list. Just send a PR and add it to the table below!

Name Version
- -

Contributing

To contribute, simply fork the repository and send a PR. Feel free to chat me up on the bevy discord under @Hemera#2040 if you have any questions or suggestions.

bevy_spicy_networking's People

Contributors

theneikos avatar kuspa avatar

Stargazers

 avatar David J. Kordsmeier avatar Nicholas Molen avatar  avatar David M. Golembiowski avatar  avatar Marcin Seredyński avatar Amar Sood avatar  avatar Ethereumdegen avatar Lewis Weinberger avatar Ziloka avatar 0xF812 avatar Rehatbir Singh avatar ElliotB256 avatar Alexi Chepura avatar David J. Felix avatar Iggy Zuk avatar archsolar avatar Arto Bendiken avatar  avatar lionMac avatar Dave Lage avatar  avatar mpw avatar  avatar  avatar Thales Macedo Garitezi avatar Karnotxo avatar Allen Garrett Gelwick III avatar James Youngblood avatar undersquire avatar Mihai avatar axyie avatar Steve Troetti avatar Billy Batista avatar  avatar Union avatar  avatar Pepper avatar Marko Lazić avatar Johann Woelper avatar orzogc avatar John Barker avatar Jamie Hall avatar Shane Sveller avatar Josh Taylor avatar Jackson R avatar Junichi Sugiura avatar  avatar  avatar Euan Rochester avatar Max Holder avatar Daniel Porteous (dport) avatar  avatar Benjamin Falk avatar Robert Gabriel Jakabosky avatar Romain Théry avatar Lee Olayvar avatar Evan Fiddes avatar Domi avatar  avatar Alexander Zaitsev avatar Dan Bruder avatar doomy avatar Connor Carpenter avatar Njuguna Mureithi avatar zbv avatar Will Hart avatar Lucas Arriesse avatar Vladyslav Batyrenko avatar Youngkyoung Lee avatar  avatar  avatar killswitch avatar Mikołaj Radkowski avatar Erlend Sogge Heggen avatar

Watchers

James Cloos avatar  avatar Benjamin Falk avatar  avatar  avatar

bevy_spicy_networking's Issues

It's impossible to aquire ownership of incoming `MyData`

Since NetworkData does not implement Clone, it is impossible to acquire ownership of inner as one has only access through EventReader::iter() which hides e behind a reference. Thus, into_inner cannot be called.

fn handle(mut incoming: EventReader<NetworkData<MyData>>){
    for e in incoming.iter(){ // e:&NetworkData<MyData>
        // I want to retrieve e (and use it elsewhere)
        let data: MyData = e.into_inner(); // errors: cannot move
        let data: MyData = e.inner; // errors: inner is private
    }
}

I would propose making inner public.

edit: What I want is to clone inner :)

Other Stream Types

Currently Spicy Networking is very cool, but is bound to only using TCPStream, I don't think it will be to turn this crate into a driver for different providers of streams and such, mainly because the Server and Client are essentially holding JoinHandles for tasks that could be swapped out for tasks using different channel types. I'm going to play around with this and see where it goes.

Cannot send message with String value

I'm unable to receive messages through bevy_spicy_networking that contain strings- I've sent and received empty messages and messages with u8 values, and so far this issue only occurs with string messages (video).

See this issue that I submitted to erased-serde for error messages etc. I'm not sure if I've done something wrong, if this is an issue with bevy_spicy_networking or erased-serde.

If it's a bug it seems like a bad one. You can clone and build warfare-rs (at this commit) if you need to reproduce. The messages are defined in networking/messages.rs, and the actual send/receive code is in systems/network.rs.

(there are some dependencies to build warfare, check the readme)

`bincode` breaks `Enums`

The change from JSON to bincode introduced here breaks Enum transmissions. Upon receiving one gets the error

ERROR bevy_spicy_networking::client: Failed to decode network packet from [127.0.0.1:9999]: Bincode does not support Deserializer::deserialize_identifier

I set up a small example for verification here.

Reproduce

run

cargo run --package server

run

cargo run --package client

click on the grey server bevy app. Every click broadcasts an MyEnum::A wich cannot be parsed from the client.

Module `error` is private

I need to handle network errors in a separate method
maybe it is required to add pub use crate::error::NetworkError

Feature: bare bones client for sending messages to server

I am wanting to receive messages on a bevy 'game', which works as advertised, however, i am wanting to create clients are not necessarily running within a bevy run loop, and it is not obvious how this is done.

I tried creating a NetworkClient directly, however it appears that this is intrinsically bound up with code in handle_connection_event, (including setting the net_res.server connection directly, which is private :| ).

This is obviously do-able, but apparently not with NetworkClient, perhaps a StandaloneNetworkClient which includes relevant code from handle_connection_event?

I'm a bit confused at this point, any pointers would be appreciated.

Thanks

Can a server receive it's own messages?

I'm working on a game in which players can play with each other on a LAN, with anyone acting as the server. Practically, what this means is that the server is also acting as a client, and should react to messages broadcast by itself exactly as a client would.

I've experimented a little with different arrangements, but there's a lot of code duplication because the server can't receive it's own messages. If NetworkData had a public new method, for example, I could insert the events myself when they are sent, and then the same systems that the client is using to receive messages would be used for reacting to local messages.

I can't find any easy way to do this that doesn't look like a maintenance nightmare down the road. Does anyone have any pointers?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.