-
Notifications
You must be signed in to change notification settings - Fork 3
Mod Integration Gate
The Gate primitive can silence a living player's voice in Tasks, Meeting, or Exile. It covers role behaviors such as "mute this player while a modifier is active" and "mute living speakers while a system effect is active."
API 1.1 exposes a per-speaker Muffle verdict, but does not currently route that verdict to an audible filter. Use one of the working muffle alternatives instead.
Back to Mod Integration
Register a cheap callback that is evaluated for each player at voice-snapshot cadence, about 20 times per second:
PerfectCommsApi.RegisterVoiceRule("com.me.mymod", ctx =>
{
// Gate mute is currently enforced only for living speakers in
// Tasks, Meeting, and Exile.
if (ctx.IsDead)
return VoiceRuleResult.Pass;
if (ctx.Phase == VoicePhaseKind.Meeting &&
MyRoles.IsGagged(ctx.Player))
{
return VoiceRuleResult.Mute("Gagged");
}
return VoiceRuleResult.Pass;
});| Verdict | API 1.1 behavior |
|---|---|
VoiceRuleResult.Mute(reason) |
The living speaker is silenced in a supported phase. The reason is available to the local transmit-block status. |
VoiceRuleResult.Pass |
No opinion; built-in rules and other integrations continue to decide. |
VoiceRuleResult.Muffle(reason) |
Recorded, but its per-speaker low-pass effect is not currently routed. Do not depend on it. |
Rules are evaluated in registration order. A Muffle result does not stop evaluation, and any later Mute overrides it. The first Mute encountered ends rule evaluation and supplies the mute reason. Return Pass whenever your role does not apply.
For a synchronized effect that mutes every living speaker in one supported phase, register a phase-scoped global gate:
PerfectCommsApi.RegisterGlobalGate(
"com.me.mymod",
VoicePhaseKind.Tasks,
() => MySystems.IsJamActive,
"Jammed");The predicate is called as voice state is evaluated, so keep it cheap and throw-free. Register separate gates for each phase you support:
PerfectCommsApi.RegisterGlobalGate(
"com.me.mymod",
VoicePhaseKind.Meeting,
() => MySystems.IsJamActive,
"Jammed");
PerfectCommsApi.RegisterGlobalGate(
"com.me.mymod",
VoicePhaseKind.Exile,
() => MySystems.IsJamActive,
"Jammed");Registering a Meeting gate does not also register an Exile gate; they are distinct API phase values.
- Supported speakers and phases: Gate mute is enforced for living speakers in Tasks, Meeting, and Exile.
- Unsupported boundaries: Gate mute is not enforced in Lobby or for dead speakers, even though callbacks can observe those context values.
- The local microphone is gated too: when a supported rule mutes the living local player, Perfect Comms blocks their transmit path.
-
Audio failures are neutral: a throwing global predicate is treated as inactive; a throwing per-player rule is treated as
Pass. The rest of the voice frame continues. - Evaluation is local, not synchronization: clients agree only when your mod has already synchronized the relevant role/effect state and each client runs compatible integration code.
-
Built-in rules still apply:
Passnever bypasses Perfect Comms' normal routing or another mod's restriction.
RegisterListenerFilter applies the working listener low-pass filter to all incoming audio for the local player:
PerfectCommsApi.RegisterListenerFilter("com.me.mymod", local =>
MyRoles.ShouldHearMuffledAudio(local));This is listener-wide, not per-speaker. The callback receives only the local PlayerControl, so it cannot read host options through a VoiceRuleContext.
A custom channel can use the working channel filter:
return new VoiceChannelResult(
"cursed-radio",
TwoWay: true,
Shape: VoiceAudioShape.Muffle);Only players who resolve the same namespaced channel key receive that route. See Channels for membership and routing rules.
Mute a living player during Tasks while a modifier is present:
PerfectCommsApi.RegisterVoiceRule("com.me.mymod", ctx =>
ctx.Phase == VoicePhaseKind.Tasks &&
!ctx.IsDead &&
ctx.Player.GetModifier<SilencedModifier>() != null
? VoiceRuleResult.Mute("Silenced")
: VoiceRuleResult.Pass);Mute only the living local player during a Meeting:
PerfectCommsApi.RegisterVoiceRule("com.me.mymod", ctx =>
ctx.Phase == VoicePhaseKind.Meeting &&
ctx.IsLocal &&
!ctx.IsDead &&
MyState.SelfMuted
? VoiceRuleResult.Mute("Muted")
: VoiceRuleResult.Pass);Gate behind a host option (see Host Options):
PerfectCommsApi.RegisterVoiceRule("com.me.mymod", ctx =>
ctx.Phase == VoicePhaseKind.Meeting &&
!ctx.IsDead &&
ctx.GetOption("MuteSilenced") &&
MyRoles.IsSilenced(ctx.Player)
? VoiceRuleResult.Mute("Silenced")
: VoiceRuleResult.Pass);- Examples - complete Gate recipes with coherent setup.
- Channels - working two-way private routes and channel muffle.
- Host Options & Tabs - make a rule host-configurable.