Blob
A blob is a larger piece of data, such as a file, sent to one player. The framework compresses it, cuts it into pieces, sends the pieces, checks they all arrived intact and puts the blob back together on the other side.
NetBlob sends and receives large data
Call Send with a player, your mod’s id and a name to send a blob. Subscribe to Received to get one, and to Finished to hear whether your send arrived.
public static class NetBlob
{
public static event Action<ulong, string, string, byte[]> Received;
public static event Action<int, bool> Finished;
public static int Send(ulong peer, string modId, string name, byte[] data);
public static float Progress(int id);
public static float Progress(ulong peer, int id);
public static bool Cancel(int id);
}
| Method | Returns | What it does |
|---|---|---|
Send(peer, modId, name, data) | int | Starts sending data to one player. Returns the transfer id, or -1 when it could not start. |
Progress(id) | float | For a blob you are sending: how much was acknowledged, from 0 to 1. -1 when not active. |
Progress(peer, id) | float | For a blob you are receiving: how much has arrived, from 0 to 1. -1 when not active. |
Cancel(id) | bool | Stops a blob you are sending. Returns false when it is not active. |
| Event | Gives you | When it fires |
|---|---|---|
Received | The sender, the mod id, the name and the data. | A blob has arrived whole and intact. |
Finished | The transfer id, and true when it was delivered. | A blob you sent is done. true when the other player has every piece. |
Things to know
Sendtakes the blob and returns its transfer id. An empty blob is allowed. (It compressesdatawith gzip and sends it on the framework’sblobchannel, in base64 pieces that fitMaxPacketBytes.)Receivedruns on the other player once the whole blob has arrived and is intact. A blob that fails the check is dropped, and the sender’sFinishedgetsfalse. (It runs when every chunk has arrived, the gzip decodes and the CRC32 (a check number) of the uncompressed data matches.)- Any player can send any
modId, so check who sent a blob (thepeerargument) before your mod acts on it. Finishedruns on the sender when the transfer ends. It isfalseon a timeout, a rejection, a cancel, or when the player leaves the lobby.Progressis for a progress bar, andFinishedorReceivedis the final answer. Both versions return-1once the transfer is no longer active, so wait forFinishedorReceivedinstead of waiting for1.Cancel(id)stops a blob you are sending. It tells the other player and raisesFinished(id, false).- The sending is paced so it does not flood the connection. At most 120 packets a second go to each player, shared by all their transfers, and at most 32 pieces wait without acknowledgement for each player.
- The receiver acknowledges every 8 pieces. A sender with no progress for 2 seconds resends from the last acknowledged piece.
- Transfer ids are local to the sender. The receiver keeps its state by sender and id.
- The gzip and CRC32 path, the chunking, the receive limits and the progress timeouts are covered by a self-test. (It is
NetBlobSelfTest, which runs with[Debug] NetBlobSelfCheck.)
Limits
Sendreturns-1when it can’t start. That is when the player is not a checked peer, when the compressed blob would need more than 8192 pieces, when the blob is over 16 MB, or when 16 transfers are already running.modIdmust be a valid mod id andnamea name of 1 to 32 characters, orSendthrows.datamust not benull.Cancelreturnsfalsefor an id that is not active.- A transfer fails after 60 seconds with no acknowledged progress, and the log says why.
- The receiver drops a partial blob that gets no new piece for 60 seconds. A finished blob stops counting toward the 16 running transfers at once.
- A piece over 960 characters fails its transfer.
- The partial blobs of one player can use at most 16 MB of memory in total, so a second blob of the maximum size from the same player at the same time is refused. (Memory is counted at 2 bytes per character.)
- A player leaving the lobby ends its transfers in both directions.