Revision Difference
EventSystem#560518
<cat>Code.Misc</cat>⤶
<title>Event System</title>⤶
⤶
The event system is like the Hook system in Garry's Mod. It allows you to register functions on classes to receive a callback on certain global events.⤶
⤶
## Setting up your Class⤶
⤶
Entities and panels are automatically registered/unregistered for you - for everything else, you just need to call `Event.Register` and `Event.Unregister`:⤶
⤶
```⤶
public class TeamManager⤶
{⤶
public TeamManager()⤶
{⤶
Event.Register( this ); // Do this on things that aren't entities or panels⤶
}⤶
⤶
[GameEvent.Tick]⤶
public void OnTick() ⤶
{⤶
Log.Trace( "blah" );⤶
}⤶
⤶
~TeamManager()⤶
{⤶
Event.Unregister( this );⤶
}⤶
}⤶
```⤶
⤶
Static callback methods will be invoked by the event system without needing to register an instance.⤶
⤶
```⤶
[GameEvent.Tick.Server]⤶
public static void OnServerTick()⤶
{⤶
// Will start being called as soon as whatever package contains this code is loaded.⤶
}⤶
```⤶
⤶
## Registering a Callback⤶
⤶
Adding a `[GameEvent.*]` or `[Event.*]` attribute will add it to the list to be called.⤶
⤶
```⤶
[GameEvent.Tick.Server]⤶
public void MyCallback()⤶
{⤶
// will get called every server tick⤶
}⤶
```⤶
⤶
## Built-in Events⤶
⤶
The various events called from the engine currently:⤶
⤶
### Build Input⤶
⤶
Called clientside every frame to process input and encode outputs into a user command.⤶
⤶
```csharp⤶
[GameEvent.Client.BuildInput]⤶
public void MyBuildInput()⤶
{⤶
⤶
}⤶
```⤶
⤶
### Client Disconnect⤶
⤶
Called when a client disconnects.⤶
⤶
```csharp⤶
[GameEvent.Server.ClientDisconnect]⤶
private void ClientDisconnect( ClientDisconnectEvent e )⤶
{⤶
Log.Info( e.Client );⤶
}⤶
```⤶
⤶
⤶
### Client Joined⤶
⤶
Called when a client joins.⤶
⤶
```csharp⤶
[GameEvent.Server.ClientJoined]⤶
private void ClientJoined( ClientJoinedEvent e )⤶
{⤶
Log.Info( e.Client );⤶
}⤶
```⤶
⤶
⤶
### Frame⤶
⤶
Called just before the beginning of a rendering frame.⤶
⤶
```csharp⤶
[GameEvent.Client.Frame]⤶
```⤶
⤶
⤶
### Tick⤶
⤶
Called every <page text="server or client tick">GameLoop#everytick</page> (60 times a second by default).⤶
⤶
```csharp⤶
[GameEvent.Tick]⤶
[GameEvent.Tick.Server]⤶
[GameEvent.Tick.Client]⤶
```⤶
⤶
⤶
### Physics Step⤶
⤶
Called before each physics step, this is usually every tick but can be more depending on <page text="Global.PhysicsSubSteps">Sandbox.Global.PhysicsSubSteps</page>.⤶
⤶
```csharp⤶
[GameEvent.Physics.PreStep]⤶
```⤶
⤶
Called after each physics step.⤶
⤶
```csharp⤶
[GameEvent.Physics.PostStep]⤶
```⤶
⤶
### Hotload⤶
⤶
Called each time your C# is hotloaded after a successful recompile.⤶
⤶
```csharp⤶
[Event.Hotload]⤶
```⤶
⤶
⤶
### Post Entity Spawn⤶
⤶
Called after all map entities have spawned in, including after map cleanups.⤶
⤶
```csharp⤶
[GameEvent.Entity.PostSpawn]⤶
```⤶
⤶
## Custom Events⤶
⤶
You can register your own custom event callbacks and call them.⤶
⤶
```csharp⤶
[Event( "mygame.gameover" )]⤶
public void OnGameOver()⤶
{⤶
}⤶
⤶
public void DoGameOver()⤶
{⤶
Event.Run( "mygame.gameover" )⤶
}⤶
```⤶
⤶
⤶
### Event Arguments⤶
⤶
Events can pass up to three arguments too.⤶
⤶
```csharp⤶
[Event( "mygame.gameover" )]⤶
public void OnGameOver( Player winner )⤶
{⤶
}⤶
⤶
public void DoGameOver( Player winner )⤶
{⤶
Event.Run( "mygame.gameover", winner )⤶
}⤶
```⤶
⤶
### Event Attributes⤶
⤶
If you want, you can also make your own custom EventAttributes (like `[Event.Tick]`) and use them to register handlers. The behavior is the same as raw event names but they have all the benefits of a type (picked up by IntelliSense, checked at compile time, etc.)⤶
⤶
```csharp⤶
// Defining the event type⤶
public static class GameEvent⤶
{⤶
public const string Custom = "custom";⤶
⤶
public class CustomAttribute : EventAttribute⤶
{⤶
public CustomAttribute() : base( Custom ) { }⤶
}⤶
}⤶
⤶
// Register it like this⤶
[GameEvent.Custom]⤶
public void OnCustomEvent()⤶
{⤶
// do something⤶
}⤶
⤶
// Fire it like this⤶
Event.Run( GameEvent.Custom );⤶
```⤶
⤶
### Defining Method Arguments⤶
⤶
When using custom event attributes you can define the required method arguments. This way, any methods that listen for this event *must* have matching arguments.⤶
⤶
```csharp⤶
// This event requires a string as the first argument.⤶
[MethodArguments( typeof( string ) )]⤶
public class CustomAttribute : EventAttribute⤶
{⤶
public CustomAttribute() : base( Custom ) { }⤶
}⤶
```⤶
⤶
```csharp⤶
// Requiring multiple arguments looks like this⤶
[MethodArguments( typeof( int ), typeof( Entity ), typeof( bool ) )]⤶
public class AnotherCustomEventAttribute : EventAttribute⤶
{⤶
public AnotherCustomEventAttribute() : base( AnotherCustom ) { }⤶
}⤶
```⤶