S&box Wiki

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 ) { }⤶ }⤶ ```⤶