S&box Wiki

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