Schema
Channels and events, frozen before networking starts. Both ends compare its fingerprint before any event is accepted.
Library active
DreamWeave's networking substrate: secure UDP between authenticated peers, with reliable-ordered and unreliable event channels and a schema handshake.
cargo add dream-netA multiplayer engine needs two kinds of traffic. A chat line, a spell cast or an inventory change must arrive exactly once and in order, however many packets the network loses. An actor’s position is stale the moment the next one exists, and resending it is worse than useless. Both kinds have to share one encrypted connection, reach only peers that proved who they are, and never let a hostile peer grow the server’s memory or crash it.
dream-net is that transport for the DreamWeave engine. It moves opaque event payloads between authenticated peers and stops there: it knows event ids, channels, peers and bytes, and never what an event means. Who may send what, and where it goes next, is decided above it.
The host hands dream-net an event id and bytes. They cross in a packet that many events share, inside an encrypted netcode datagram, and come out of the other host's poll with the sender attached.
Checks the event and its size against the schema, and copies the bytes into its channel's queue before returning.
Packs events from every channel into packets sized to one datagram. reliable numbers and acknowledges them; netcode encrypts them and sends them over UDP.
On the other host, after its update: lifecycle records and events in arrival order, with the authenticated sender.
Channels and events, frozen before networking starts. Both ends compare its fingerprint before any event is accepted.
Packet sizes, timers, and the byte budgets that bound every queue.
It is built on the Más Bandwidth crates, pinned exactly: netcode for connect tokens, encryption, replay protection and client slots; reliable for packet acknowledgement, fragmentation and link statistics; and serialize for bit-packing. dream-net adds the part they leave out: channels of events, packed many to a datagram.
update, poll, send,
flush. Nothing calls into the host from inside the transport.PeerId comes from the authenticated netcode slot and
carries a generation, so a handle to a peer that left never reaches the next one in its slot.use dream_net::{ChannelConfig, Schema, Server, ServerConfig, ServerEvent, TransportConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut schema = Schema::builder(1);
let reliable = schema.channel(ChannelConfig::reliable_ordered("reliable"))?;
let state = schema.channel(ChannelConfig::unreliable_unordered("state"))?;
schema.event("Chat", reliable, 256)?;
schema.event("ActorPosition", state, 28)?;
let schema = schema.build()?;
let chat = schema.event_id("Chat").expect("declared above");
let config = ServerConfig {
public_address: "127.0.0.1:0".parse()?,
protocol_id: 0x4452_4541_4d00_0001,
max_clients: 16,
transport: TransportConfig::default(),
};
let mut server = Server::new(config, &dream_net::generate_key(), schema, 0.0)?;
let mut buffer = [0u8; 256];
// once per frame, in one network phase
server.update(1.0 / 60.0);
while let Some(event) = server.poll_into(&mut buffer)? {
match event {
ServerEvent::Connected { peer, .. } => server.send(peer, chat, b"welcome")?,
ServerEvent::Message { peer, event, payload, .. } => {
println!("{peer} sent {event}: {:?}", &buffer[..payload]);
}
ServerEvent::Disconnected { .. } | ServerEvent::Rejected { .. } => {}
}
}
server.flush();
Ok(())
}
Luau scripts reach it through l3i, which binds dream-net as
the @dream/net module. The host still creates servers in Rust: the private key never reaches a
script.
Rust crate · 1.1.0
From your project's directory:
cargo add dream-net
Or by hand, in Cargo.toml:
[dependencies]
dream-net = "1.1.0"
Cargo reads a bare version as "this or any compatible newer release" and records the exact one in Cargo.lock.
[dependencies]
dream-net = { git = "https://github.com/DreamWeave-MP/dream-net" }
Cargo pins the commit it fetched in Cargo.lock; cargo update -p dream-net moves it forward.
A peer is announced before its first event, captures without payloads keep their lengths, and the codec’s decode errors are standard Rust errors.
wire::DecodeError and wire::Malformed implement std::error::Error, and DecodeError implements Display, like the crate’s other errors: a malformed packet prints its reason, which is also its source(), and a mismatch prints the foreign hello.Server and Client queued Connected after the events of the packet that completed the handshake, so a host could poll a peer’s Message before its Connected. Connected now comes first.CaptureWriter without payloads wrote each event’s length from its payload, so a capture read back and written again recorded every event as zero bytes. It now writes the record’s len.The same digest as the crates.io index's checksum, which Cargo checks on every download.
First release: secure UDP between authenticated peers, reliable-ordered and unreliable event channels, and a schema handshake, over the Más Bandwidth netcode, reliable and serialize crates.
Schema of channels and events: event ids from sorted names, never registration order, and a 128-bit fingerprint (truncated SHA-256) peers compare before any event is accepted.Server and Client over netcode: connect tokens, encryption, generation-checked PeerId handles, and polled lifecycle events, including schema and protocol mismatches reported with both fingerprints on both ends.max_pending_bytes + 2 * max_parked_bytes held per connection on receive.Connection independent of sockets, and a deterministic link simulator for tests and benchmarks.The same digest as the crates.io index's checksum, which Cargo checks on every download.