Transformer
A transformer decides which pooled RemoteEvent a carrier's traffic rides on, and
it is the switch that turns a group of carriers off. Create one with
Pigeon.Transformer.
Most games never touch this object. Every carrier makes its own transformer from its channel name, so it is already handled. You only need one when you want several channels to share a remote, or to drop several channels in one call. See the Transformers guide for when that is worth doing.
Properties
transformer.uuid: string
The identity of the transformer. This string is hashed to pick a remote, so two transformers with the same uuid always land on the same one. If you build a transformer on both the server and the client, pass the same uuid to both.
transformer.destroyed: boolean
false until Destroy is called, then
true forever. Carriers read this to decide whether they are still
allowed to send.
Methods
Track
transformer:Track(disconnect: () -> ()) -> () -> ()
Registers a function to run when the transformer is destroyed, and returns a handle that removes it again.
This is how a group teardown works. Anything that subscribes on the transformer's behalf hands its disconnect function here, so destroying the transformer runs all of them at once. Every carrier riding on a transformer tracks its own cleanup this way.
| Parameter | Type | What it is |
|---|---|---|
disconnect | () -> () | Runs once when the transformer is destroyed. |
Returns a function. Call it to remove your teardown again.
local transformer = Pigeon.Transformer("Combat")
local connection = someSignal:Connect(onHit)
local untrack = transformer:Track(function()
connection:Disconnect()
end)
-- Later, if you disconnect early, drop the teardown too.
connection:Disconnect()
untrack()
Note
Call the returned handle whenever you unsubscribe early. If you do not, the list keeps growing by one entry for every subscription you ever made, and it holds those functions in memory until the transformer is destroyed.
Tracking on a dead transformer
If the transformer is already destroyed, your function runs straight away and the handle you get back does nothing. That is on purpose. It means a late registration can never leave a live connection behind.
local transformer = Pigeon.Transformer()
transformer:Destroy()
transformer:Track(function()
print("this runs right now, not later")
end)
Destroy
transformer:Destroy() -> ()
Runs every tracked teardown, marks the transformer as destroyed, and lets the remote pool shrink again.
Every carrier built on this transformer is dropped as part of that. This is the one call that turns off a whole group of channels.
local combat = Pigeon.Transformer("Combat")
local damage = Pigeon.new("Damage", { Transformer = combat })
local status = Pigeon.new("Status", { Transformer = combat })
local effects = Pigeon.new("Effects", { Transformer = combat })
-- One call drops all three channels and every listener on them.
combat:Destroy()
Calling it twice does nothing the second time. Teardowns run once, and the count the remote pool is sized from is only lowered once.
A failing teardown does not stop the rest
Each teardown runs on its own. If one of them errors, Pigeon warns and carries on with the next. One broken cleanup function cannot leave the others connected.
Ownership
Who destroys the transformer depends on who made it.
| How the carrier got it | Who owns it | What carrier:Destroy() does |
|---|---|---|
Pigeon.new("Shop") |
The carrier | Destroys the transformer too. |
Pigeon.new("Shop", { Transformer = t }) |
You | Leaves the transformer alone. |
The rule is simple. A transformer a carrier made for itself has no other owner, so it goes when the carrier goes. One you passed in belongs to you, so Pigeon does not touch it.
-- Owned by the carrier.
local shop = Pigeon.new("Shop")
shop:Destroy()
print(shop._transformer.destroyed) --> true
-- Owned by you.
local mine = Pigeon.Transformer("Mine")
local other = Pigeon.new("Other", { Transformer = mine })
other:Destroy()
print(mine.destroyed) --> false
Building a carrier on a dead transformer
If you pass in a transformer that is already destroyed, the carrier you get back is inert from the moment it is made. It will not send and it will not receive. It does not error, because tearing things down often races with work already in flight and an error there would spread.
local transformer = Pigeon.Transformer()
transformer:Destroy()
local carrier = Pigeon.new("TooLate", { Transformer = transformer })
carrier:Emit("Anything") -- does nothing, does not error