Skip to main content

Entity I/O

Namespace: DeadworksManaged.Api

Hook into the Valve entity I/O system to observe or intercept output firings and input dispatches by entity designer name.

EntityIO

Hooking Outputs

Subscribe to outputs fired by entities with a given designer name:

var handle = EntityIO.HookOutput("trigger_multiple", "OnTrigger", ev =>
{
Console.WriteLine($"Output {ev.OutputName} fired by {ev.CallerClass} (entity {ev.Caller?.EntityIndex})");
Console.WriteLine($"Activator: {ev.Activator?.Classname}");
});

// Cancel later
handle.Cancel();

Hooking Inputs

Subscribe to inputs dispatched to entities:

var handle = EntityIO.HookInput("func_button", "Kill", ev =>
{
Console.WriteLine($"Kill input received by {ev.Entity.Classname}");
Console.WriteLine($"Value: {ev.Value.AsString()}");
});

Blocking Inputs and Outputs

Each hook has two overloads. Pass a handler that returns HookResult to run pre (before the original) — returning HookResult.Stop blocks the input/output entirely. Pass an Action<...> handler to run post (observe-only, after the original):

// Pre hook: veto the Kill input so the button never kills its activator
EntityIO.HookInput("func_button", "Kill", ev =>
{
return HookResult.Stop;
});

// Post hook: observe only, cannot block
EntityIO.HookInput("func_button", "Kill", ev =>
{
Console.WriteLine("Kill input already processed");
});

Class and input/output names support "*" as a wildcard. Hooks are matched against four keys in priority order: (class, name), (class, "*"), ("*", name), ("*", "*").

Methods

MethodReturnsDescription
HookOutput(string className, string outputName, Func<EntityOutputEvent, HookResult> handler, HookMode mode = HookMode.Pre)IHandlePre-mode hook; return HookResult.Stop to block the output
HookOutput(string className, string outputName, Action<EntityOutputEvent> handler)IHandlePost-mode hook; observe-only
HookInput(string className, string inputName, Func<EntityInputEvent, HookResult> handler, HookMode mode = HookMode.Pre)IHandlePre-mode hook; return HookResult.Stop to block the input
HookInput(string className, string inputName, Action<EntityInputEvent> handler)IHandlePost-mode hook; observe-only

All return an IHandle that cancels the hook when cancelled. Hooks are also auto-cancelled on plugin unload.

Attribute Registration

Instead of calling HookOutput/HookInput in OnLoad, you can annotate plugin methods — they are auto-registered on load and dropped on unload. Pre handlers must return HookResult; post handlers must return void:

[EntityOutputHook("trigger_multiple", "OnStartTouch")]
public HookResult OnTriggerTouched(EntityOutputEvent e)
{
return HookResult.Continue;
}

[EntityInputHook("*", "Toggle", HookMode.Post)]
public void OnToggleObserved(EntityInputEvent e) { /* observer only */ }
Limited Entity I/O Support

Entity I/O hooks work with map-placed entities that use the Source 2 I/O system (e.g. trigger_multiple, func_button). Player entities ("player") do not fire standard I/O outputs like "OnDeath" — use OnTakeDamage or GameEvents.AddListener("player_death") instead for player death detection.

EntityOutputEvent

Data for a fired entity output.

PropertyTypeDescription
CallerClassstringDesigner name of the entity firing the output (e.g. "trigger_multiple")
OutputNamestringName of the output being fired (e.g. "OnTrigger")
ActivatorCBaseEntity?The entity that triggered the output (typically a player pawn)
CallerCBaseEntity?The entity that fired the output
ValueEntityIOValueThe typed variant value carried by the output
DelayfloatDelay (seconds) before the output's connected inputs fire

EntityInputEvent

Data for a received entity input.

PropertyTypeDescription
EntityCBaseEntityThe entity receiving the input
ClassNamestringDesigner name of the receiving entity (cheaper than reading Entity.DesignerName)
InputNamestringName of the input (e.g. "Kill")
ActivatorCBaseEntity?The activating entity, if any
CallerCBaseEntity?The calling entity, if any
ValueEntityIOValueThe typed variant value carried by the input

EntityIOValue

Typed accessor for the variant value carried by an input or output. Call the accessor matching the value's type — or AsString(), which formats any variant type:

MemberType / ReturnsDescription
TypeFieldTypeSource 2 field type of the variant (FieldType.Void for null)
IsNullboolTrue if the variant is null or holds no value
AsString()stringFormats any variant type as a string
AsInt() / AsInt64() / AsUInt()int / long / uintInteger conversions; 0 if unsupported
AsFloat() / AsDouble()float / doubleFloat conversions; 0 if unsupported
AsBool()boolBoolean conversion
AsVector2() / AsVector3() / AsVector4()Vector2/3/4Vector reads; zero for other types
AsColor()ColorRGBA color; transparent black for non-color variants
AsEntity()CBaseEntity?Resolves ehandle variants; null otherwise
Do not retain past the callback

EntityIOValue wraps a native pointer that is only valid for the duration of the hook callback. If you need the value later, call the typed accessor (e.g. AsString()) inside the callback and store the result.

AcceptInput

You can also fire inputs directly on entities. See Entities:

entity.AcceptInput("Start", activator: null, caller: null, value: "");
entity.AcceptInput("Kill", activator: null, caller: null, value: "");

See Also