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<T>], 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:
OnTickOnWorldUpdateOnClientProcessUsercmds
Avoid expensive operations in hot-path listeners. Keep them short and allocation-friendly.
Common Core Events
| Event | Delegate Type | Parameter Type | Notes |
|---|---|---|---|
| Client connected | OnClientConnected | IOnClientConnectedEvent | Client lifecycle |
| Client disconnected | OnClientDisconnected | IOnClientDisconnectedEvent | Client lifecycle |
| Client put in server | OnClientPutInServer | IOnClientPutInServerEvent | Client lifecycle |
| Entity created | OnEntityCreated | IOnEntityCreatedEvent | Entity lifecycle |
| Entity deleted | OnEntityDeleted | IOnEntityDeletedEvent | Entity lifecycle |
| Entity take damage | OnEntityTakeDamage | IOnEntityTakeDamageEvent | Damage callback |
| ConVar value changed | OnConVarValueChanged | IOnConVarValueChanged | Convar tracking |
| Tick | OnTick | none | Hot path |
| World update | OnWorldUpdate | none | Hot 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.