Skip to content
A simple semi-reliable UDP protocol for multiplayer games
Rust Other
  1. Rust 99.3%
  2. Other 0.7%
Branch: master
Clone or download
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
benches Change CRC32 to CRC16 in `protocol_version`. (#155) Mar 19, 2019
ci Implemented Arranging-Streams | Don't MERGE (#145) Feb 27, 2019
docs 0.3.0 release prep Jun 29, 2019
examples remove a number of warnings. Also changed a number of tests to be mor… Jun 27, 2019
src Implement heartbeat functionality (#224) Aug 12, 2019
tests remove a number of warnings. Also changed a number of tests to be mor… Jun 27, 2019
.gitignore Basic mdbook setup Oct 14, 2018
Cargo.toml remove the travis-ci badge. We don't use it anymore and it looks bad … Jun 29, 2019
Jenkinsfile comment out the mac test for now. Jun 20, 2019
README.md 0.3.0 release prep Jun 29, 2019
bors.toml Fix bors unable to clone staging.tmp issue Oct 28, 2018
codecov.yml
core Refactored some tests (#160) Mar 24, 2019
rustfmt.toml Formatted with stable cargo fmt Nov 11, 2018

README.md

Laminar

Build Status Latest Version docs.rs Join us on Discord MIT/Apache Lines of Code Coverage

Laminar is a semi-reliable UDP-based protocol for multiplayer games. This library implements wrappers around the UDP-protocol, and provides a lightweight, message-based interface which provides certain guarantees like reliability and ordering.

Laminar was designed to be used within the Amethyst game engine but is usable without it.

Concepts

This library is loosely based off of Gaffer on Games and shares features similar as RakNet, Steam Socket, netcode.io. The idea is to provide an in rust written, low-level UDP-protocol which supports the use of cases of video games that require multiplayer features. The library itself provides a few low-level types of packets that provide different types of guarantees. The most basic are unreliable and reliable packets. Also ordering, sequencing can be done on multiple streams. For more information, read the projects README.md, book, docs or examples.

Table of contents:

Features

These are the features this crate provides:

  • UDP-based Protocol
  • Connection Tracking
  • Automatic Fragmentation
  • Reliability Options: Unreliable and Reliable
  • Arranging Options: Sequenced, Unordered, and Ordered.
  • Arranging Streams
  • Protocol Versioning
  • RTT Estimation
  • Link conditioner to simulate packet loss and latency
  • Well-tested by integration and unit tests

Getting Stated

Add the laminar package to your Cargo.toml file.

[dependencies]
laminar = "0.3.0"

Useful Links

Examples

Please check out our examples for more information.

UDP API | see more

This is an example of how to use the UDP API.

Send packets

use laminar::{Socket, Packet};

// create the socket
let mut socket = Socket::bind("127.0.0.1:12345")?;
let packet_sender = socket.get_packet_sender();
// this will start the socket, which will start a poll mechanism to receive and send messages.
let _thread = thread::spawn(move || socket.start_polling());

// our data
let bytes = vec![...];

// You can create packets with different reliabilities
let unreliable = Packet::unreliable(destination, bytes);
let reliable = Packet::reliable_unordered(destination, bytes);

// We can specify on which stream and how to order our packets, checkout our book and documentation for more information
let unreliable = Packet::unreliable_sequenced(destination, bytes, Some(1));
let reliable_sequenced = Packet::reliable_sequenced(destination, bytes, Some(2));
let reliable_ordered = Packet::reliable_ordered(destination, bytes, Some(3));

// send the created packets
packet_sender.send(unreliable_sequenced).unwrap();
packet_sender.send(reliable).unwrap();
packet_sender.send(unreliable_sequenced).unwrap();
packet_sender.send(reliable_sequenced).unwrap();
packet_sender.send(reliable_ordered).unwrap();

Receive Packets

use laminar::{SocketEvent, Socket};

// create the socket
let socket = Socket::bind("127.0.0.1:12346")?;
let event_receiver = socket.get_event_receiver();
// this will start the socket, which will start a poll mechanism to receive and send messages.
let _thread = thread::spawn(move || socket.start_polling());

// wait until a socket event occurs
let result = event_receiver.recv();

match result {
    Ok(socket_event) => {
        match  socket_event {
            SocketEvent::Packet(packet) => {
                let endpoint: SocketAddr = packet.addr();
                let received_data: &[u8] = packet.payload();
            },
            SocketEvent::Connect(connect_event) => { /* a client connected */ },
            SocketEvent::Timeout(timeout_event) => { /* a client timed out */},
        }
    }
    Err(e) => {
        println!("Something went wrong when receiving, error: {:?}", e);
    }
}

Authors

Note

This library is not fully stable yet, and there may be breaking changes to the API. For more advanced examples of using laminar, you can check out the Amethyst-Network crate.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

License

Licensed under either of

You can’t perform that action at this time.