SwiftlyS2
Development

Core Events

SwiftlyS2 provides a core event system for engine and framework callbacks such as client lifecycle, entity hooks, convar updates, server startup, and tick/world updates.

Core events are not the same as game events.

Accessing Event Service

Core events are exposed through Core.Event.

public override void Load(bool hotReload)
{
    var events = Core.Event;
}

Listening to Core Events

There are two ways to register listeners.

public override void Load(bool hotReload)
{
    Core.Event.OnClientConnected += OnClientConnected;
}

private void OnClientConnected(IOnClientConnectedEvent @event)
{
    Console.WriteLine($"Client connected: {@event.PlayerId}");
}
[EventListener<EventDelegates.OnClientConnected>]
public void OnClientConnected(IOnClientConnectedEvent @event)
{
    Console.WriteLine($"Client connected: {@event.PlayerId}");
}

Delegate Signatures

Most core events pass one event-parameter interface. Some hot-path events have no parameters.

public delegate void EventDelegates.OnClientConnected(IOnClientConnectedEvent @event);
public delegate void EventDelegates.OnEntityTakeDamage(IOnEntityTakeDamageEvent @event);
public delegate void EventDelegates.OnTick();
public delegate void EventDelegates.OnWorldUpdate();

When using [EventListener&lt;T&gt;], your method signature must match the delegate exactly.

Working with Event Parameters

Each event parameter interface contains fields related to that event. For example, IOnClientConnectedEvent exposes PlayerId and Result.

[EventListener<EventDelegates.OnClientConnected>]
public void OnClientConnected(IOnClientConnectedEvent @event)
{
    if (@event.PlayerId <= 0)
    {
        return;
    }

    // Example: block client from joining based on your own validation.
    // @event.Result = HookResult.Stop;
}

Unsubscribing Method Listeners

For programatically added subscriptions (+=), you can manually unsubscribe (-=).

private EventDelegates.OnClientConnected? _onClientConnected;

public override void Load(bool hotReload)
{
    _onClientConnected = OnClientConnected;
    Core.Event.OnClientConnected += _onClientConnected;
}

public override void Unload(bool hotReload)
{
    if (_onClientConnected != null)
    {
        Core.Event.OnClientConnected -= _onClientConnected;
    }
}

private void OnClientConnected(IOnClientConnectedEvent @event)
{
    Console.WriteLine(@event.PlayerId);
}

On hot reload or unload, listeners are automatically cleaned up by the framework. Manual unsubscribe is still useful when you want to stop listening earlier.

Hot Path Events

Some events are called very frequently and should remain lightweight:

  • OnTick
  • OnWorldUpdate
  • OnClientProcessUsercmds

Avoid expensive operations in hot-path listeners. Keep them short and allocation-friendly.

Common Core Events

EventDelegate TypeParameter TypeNotes
Client connectedOnClientConnectedIOnClientConnectedEventClient lifecycle
Client disconnectedOnClientDisconnectedIOnClientDisconnectedEventClient lifecycle
Client put in serverOnClientPutInServerIOnClientPutInServerEventClient lifecycle
Entity createdOnEntityCreatedIOnEntityCreatedEventEntity lifecycle
Entity deletedOnEntityDeletedIOnEntityDeletedEventEntity lifecycle
Entity take damageOnEntityTakeDamageIOnEntityTakeDamageEventDamage callback
ConVar value changedOnConVarValueChangedIOnConVarValueChangedConvar tracking
TickOnTicknoneHot path
World updateOnWorldUpdatenoneHot path, runs in hibernation

Event Categories (Quick View)

Core events cover these areas:

  • Client events (OnClientConnected, OnClientVoice, OnClientKeyStateChanged, ...)
  • Entity events (OnEntityCreated, OnEntityTouch, OnEntityFireOutputHook, ...)
  • Command and console events (OnCommandExecuteHook, OnConsoleOutput, ...)
  • Convar events (OnConVarCreated, OnConVarValueChanged)
  • Server/runtime events (OnStartupServer, OnMapLoad, OnMapUnload, OnTick, OnWorldUpdate)

Reference

See IEventSubscriber for all subscribable events.

See EventDelegates for delegate signatures.

See EventListener<T> for attribute-based listeners.

On this page