Custom network events new¶
Custom events are the object-less, typed sibling of a per-object RPC (design
02 §17). Where lattice_rpc always names a netid, an
event may be global / session-scoped (pass netid 0) or optionally object-scoped (pass a
live netid, used for OWNER / ALL_BUT_OWNER routing exactly like an RPC).
lattice_send_event¶
LATTICE_API lattice_result lattice_send_event(lattice_runner* r, uint16_t event_id,
lattice_event_target target, lattice_netid netid,
uint64_t peer, const uint8_t* payload,
uint32_t len, int reliable);
Send a custom event. Role: both (for a client, target is implicitly the authority).
| Param | Meaning |
|---|---|
event_id |
The typed event tag, delivered verbatim to on_event. |
target |
A lattice_event_target. SERVER/OWNER/ALL/ALL_BUT_OWNER fan out per the same §16 policy as RPC; PEER sends to exactly one connection (the peer argument). |
netid |
0 for a global event, or an object's netid for an object-scoped event. |
peer |
The destination connection id for LATTICE_EVENT_PEER (ignored otherwise). |
payload / len |
Arbitrary serialized bytes (e.g. from a lattice_bw_* writer or an INetworkSerializable); may be NULL when len == 0. Delivered byte-exact. |
reliable |
Non-zero ⇒ the event rides a reliable channel (exactly-once; ordered on the reliable-ordered channel). Zero ⇒ best-effort / unreliable. |
Returns: LATTICE_OK on accept, or an error (e.g. LATTICE_ERR_NOT_CONNECTED for a client
with no session). Like RPC, events are queued onto the transport and delivered to the remote
on_event callback during its lattice_runner_tick().
lattice_event_target¶
typedef enum {
LATTICE_EVENT_SERVER = 0, /* client -> authority only (object-less: just the host) */
LATTICE_EVENT_OWNER = 1, /* authority -> the (optional) object's owner */
LATTICE_EVENT_ALL = 2, /* authority -> every peer */
LATTICE_EVENT_ALL_BUT_OWNER = 3, /* authority -> every peer except the owner */
LATTICE_EVENT_PEER = 4 /* authority -> one specific connection (see peer arg) */
} lattice_event_target;
The shared values deliberately mirror lattice_rpc_target so the
routing policy is one decision, not two.
Receiving — on_event¶
void (*on_event)(void* user_data, uint16_t event_id, lattice_netid netid,
uint64_t sender, const uint8_t* payload, uint32_t len);
Fires synchronously inside lattice_runner_tick(). event_id is the typed tag; netid is 0
for a global/session-scoped event or the owning object's netid for an object-scoped event;
sender is the peer id the event originated from (0 == the local authority); payload/len
is the byte-exact blob the sender serialized (may be empty). The pointer is owned by the core and
valid only for the duration of the call.
Example — a global "match started" broadcast¶
/* Authority -> every peer, reliable, object-less. */
uint8_t buf[8];
lattice_bitwriter* w = lattice_bw_create();
lattice_bw_write_int(w, match_id);
lattice_bw_write_byte(w, mode_byte);
lattice_send_event(r, /*event_id*/ EV_MATCH_STARTED, LATTICE_EVENT_ALL,
/*netid*/ 0, /*peer*/ 0,
lattice_bw_data(w), lattice_bw_byte_count(w), /*reliable*/ 1);
lattice_bw_destroy(w);
/* Receiver */
static void on_event(void* u, uint16_t event_id, lattice_netid netid,
uint64_t sender, const uint8_t* payload, uint32_t len) {
if (event_id == EV_MATCH_STARTED) {
lattice_bitreader* rd = lattice_br_create(payload, len);
int32_t match_id = lattice_br_read_int(rd);
uint8_t mode = lattice_br_read_byte(rd);
lattice_br_destroy(rd);
/* ... */
}
}