Pingle is a networking library for Figura.
It acts as a wraper for pings and handles the annoying parts for you! key features include:
- Automatically Synced values
- Ping (size/count) limits
- Ping Compression
- Buffered Pings
- Network events
Host-only send APIs will error on clients, these include:
Pingle.synced.set(...)Pingle.event.emit(...)Pingle.immediate.send(...)
Its as simple as require-ing the script:
local Pingle = require "src.library.pingle-lib.pingle"(Optional) feel free to set debug output to show some useful info:
Pingle.debug = trueAnd thats it, your all set up!
local Pingle = require "src.library.pingle-lib.pingle"
-- Optional debug output
Pingle.debug = true
-- Synced value with receive callback
Pingle.synced.define("demo.counter", 0, function(value, key)
print("[demo] synced update", key, value)
end)
-- Event handler/listener
Pingle.event.register("demo.announce", function(data)
print("[demo] handler:", data.message)
end)
Pingle.event.listen("demo.announce", function(data)
print("[demo] listener:", data.message)
end)
events.INIT:register(function()
-- Host sends
if Pingle.isHost() then
Pingle.synced.set("demo.counter", 1)
Pingle.event.emit("demo.announce", { message = "Hello from host!" })
Pingle.immediate.send("demo.announce", { message = "Immediate ping path" })
end
end)Registers a synced key.
key(string) unique key name.initialValue(any pingable) local initial value.onReceive(function(value, key)_optional):- Non-Host: runs when an incoming packet changes the stored value (
old ~= new). - Host: after you call
synced.set, the value is updated before the ping echo; the echo often reapplies the same value, so the receive path skipsonReceiveto avoid doubles. By default the host also runsonReceivefromsynced.setright after queueing (seePingle.syncedFireOnHostSet).
- Non-Host: runs when an incoming packet changes the stored value (
Returns latest local value for a synced key, or nil.
Sets local value and queues it for non hosts to grab.
Notes:
- Only the latest value is sent. (if setting in rapid sucession)
- If unchanged (
==), the value is not re-queued. - If
Pingle.syncedFireOnHostSetistrue(default), theonReceivecallback runs once after a successful hostset.
- Default
true. Set tofalseif you only wantonReceiveon network apply (you will usually not see it on the host for your ownsetwhen the echoed value matches).
Registers the primary handler for event name.
name(string) event id.handler(function(dataTable)).
Adds an extra listener for that event name.
listener(function(dataTable)).
Queues buffered event packet.
dataTableshould be a small table (tables cost more bytes).
Queues an immediate-rate-limited send.
Use for urgent/lightweight messages that should not wait for buffered coalescing.
Returns whether this script instance is host. (is literally just host.isHost())
Internal tick/update function called from events.TICK.
You normally do not call this yourself.
Pingle is set just under Figura backend constraints:
- max backend limits are roughly
1024 bytes/secand32 pings/sec, - pingle defaults are conservative (
768 bytes/sec,28 pings/sec), - buffered channel flushes at
3times per second, - large payloads are chunked and reassembled.
Avoid sending huge tables frequently, instead send:
- numbers,
- booleans,
- short strings,
- segmented state updates,
- event payloads with only needed fields.
You can tweak these at runtime:
Pingle.bytesPerSecondBudget(default = 768)Pingle.pingsPerSecondBudget(default = 28)Pingle.bufferFlushPerSecond(default = 3)Pingle.maxChunkPayload(default = 240)Pingle.maxQueueRecords(default = 256)Pingle.maxTableDepth(default = 32)Pingle.maxTablePairs(default = 48)Pingle.maxStringLen(default = 8000)Pingle.syncedFireOnHostSet— whentrue(default),synced.seton the host also callsonReceiveafter queueing so the host sees the same path as clients.Pingle.debug
Setting config example:
Pingle.bufferFlushPerSecond = 3
Pingle.bytesPerSecondBudget = 768
Pingle.debug = true- Every viewer must run the same
Pingle.synced.define/Pingle.event.registersetup as the host does. If a friend’s client never executed that init,onReceivedoes not exist there and causes problems. - Use
Pingle.debugfor decode/sync hints (must be enabled in the receiver’s Lua, not only the host). - Keep event payload tables as small as possible to free up bandwith.
- If you need continuous state sync, use
syncedkeys (they segment very well). - Use
immediatefor short urgent messages, not bulk data. (this is effectively the same as a regular ping with safeguards) - If sending raw byte arrays, pack to strings (ASCII bytes) before sending.
