Revision Difference
EventSystem#551435
<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 successful recompile.
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 ) )⤶
[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 ) { }⤶
}
```