Skip to content

billyb2/bootleg_networking

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

bootleg_networking

A cross platform (wasm included) networking library!

A networking plugin for the Bevy game engine that wraps around bevy_networking_turbulence and a custom TCP/UDP network server in order to make writing cross-platform multiplayer games fun and easy!

Getting started

Currently, the library is not published on crates.io, due to a few forks of other popular libraries it currently uses. Because of this, in order to use the libary, you must specify it as a git dependency

[dependencies]
bootleg_networking = { version = "0.2", git = "https://github.com/billyb2/bootleg_networking" }

If you want to use this library with wasm, you should disable the native feature and enable the web feature

[dependencies]
bootleg_networking = { version = "0.2", git = "https://github.com/billyb2/bootleg_networking", default-features = false, features = ["web"]}

I recommend pinning to a specific version, since library stability can change at any time.

Below is an example of how to use this library. It mainly shows how to setup a basic server, although a client is nearly identical

use std::sync::Arc;

use bevy::prelude::*;
use bevy::tasks::IoTaskPool;
use bootleg_networking::*;

const MESSAGE_CHANNEL_ID: MessageChannelID = MessageChannelID::new(0);
const MESSAGE_SETTINGS: MessageChannelSettings = MessageChannelSettings {
    channel: MESSAGE_CHANNEL_ID.id,
    channel_mode: MessageChannelMode::Unreliable {
		settings: turbulence::unreliable_channel::Settings {
			bandwidth: 4096,
			burst_bandwidth: 1024,
		},
		max_message_len: 256,	
	},
    message_buffer_size: 256,
    packet_buffer_size: 256,
};

fn main() {
    let mut app = App::new();
    app
    .add_plugins(MinimalPlugins)
    .add_plugin(NetworkingPlugin)
    .add_startup_system(setup)
    .add_system(send)
    .add_system(receive);

    //Uncomment the line below!
    //app.run();
}

fn setup(mut commands: Commands, tokio_rt: Res<Runtime>, task_pool: Res<IoTaskPool>) {
    // First we need to actually initiate the NetworkReource. In this case, it's a server
    // We could use the new_client function if wanted a client
    let mut net = NetworkResource::new_server(tokio_rt.clone(), task_pool.0.clone());

    // Next, we need tell the server to setup listening
    // The equivalent function for clients is connect
    // Listen on ports 9000 for TCP and 9001 for UDP, and 9003
    // The first address is the one that the connect() function needs to use, and the other two are for WebRTC
    // Finally, the last argument is the maximum size of each packet. That argument is only necessary for native builds
    let listen_config = ListenConfig {
        tcp_addr: "127.0.0.1:9000",
        udp_addr: "127.0.0.1:9001",
        naia_addr: "127.0.0.1:9003",
        webrtc_listen_addr: "127.0.0.1:9004",
        public_webrtc_listen_addr: "127.0.0.1:9004",
    };

    net.listen(listen_config, Some(2048));
    // If we were calling net.connect, the first argument we would either have 9000 or 9003 as the port, depending on whether we were a native client or a web client
    // The second argument is only necessary on native builds, and it's asking for the UDP server SocketAddr
    /* let connect_config = ConnectConfig {
     *      addr: "127.0.0.1:9000",
     *      udp_addr: Some("127.0.0.1:9001"),
     * };
     *
     * net.connect(connect_config, Some(2048));
    */

    // We need to register for the native tcp/udp server and for naia seperately
    // Native registration
    net.register_message_channel_native(MESSAGE_SETTINGS, &MESSAGE_CHANNEL_ID).unwrap();
    // Naia registration
    net.set_channels_builder(|builder: &mut ConnectionChannelsBuilder| {
        builder
            .register::<String>(MESSAGE_SETTINGS)
            .unwrap();
    });

    // Finally, insert the network resource so it can be used by other systems
    commands.insert_resource(net);

}

// The following two functions are equivalent for both clients and servers, provided you've set up the NetworkResource properly

fn send(mut net: ResMut<NetworkResource>) {
    let message = String::from("Hello world");
    net.broadcast_message(&message, &MESSAGE_CHANNEL_ID).unwrap();

}

fn receive(mut net: ResMut<NetworkResource>) {
    let messages = net.view_messages::<String>(&MESSAGE_CHANNEL_ID).unwrap();

    for (_handle, message) in messages.iter() {
        println!("{}", message);

    }

}

Warning about sending messages larger than 1095 bytes

@totalkrill noticed that when attempting to send a message larger than 1095 bytes, the message wouldn't go through. This is due to a limitation in WebRTC that doesn't allow messages larger than 1200 bytes (which 1095 bytes + any overhead in the WebRTC protocol and anything Naia adds would definetly do). The NetworkResource will return an error upon trying to send a message above that size when sending it through Naia, though there isn't an issue on the TCP/UDP front. Just be warned though, that if you're trying to have cross platform compatibility, messages should be under that size.

If the crate isn't published on crates.io, how do I view the documentation?

Simply run cargo doc in the terminal. If you want to view the documentation for the web version of this crate, then run cargo doc --no-default-features --features web

Why make this crate

While working with the wonderful bevy_networking_turbulence library, I realized that I wasn't able to create network clients on anything other than wasm. While it is doable using the fantastic new WebRTC-rs library (and I even attempted it, it still currently isn't possible. After a lot of effort, I eventually gave up, and decided instead to write this library. While initially, it was just for internal use in a project I'm workin on, I realized that it would have a lot of potential as a public library.

Releases

No releases published

Languages