diff --git a/content/docs/scripting-reference/runtimes/csharp/functions/TriggerClientEvent.md b/content/docs/scripting-reference/runtimes/csharp/functions/TriggerClientEvent.md new file mode 100644 index 000000000..a2b990bf6 --- /dev/null +++ b/content/docs/scripting-reference/runtimes/csharp/functions/TriggerClientEvent.md @@ -0,0 +1,136 @@ +--- +title: TriggerClientEvent (server, C#) +weight: 20 +--- + +Sends an event from the **server** to one or more clients. + +This is commonly used to: + +- send chat messages or notifications, +- update UI state on specific players, +- broadcast information to everyone on the server. + +> Note +> This page describes the C# server usage. Make sure your client script is listening for the event name you use. + +## Syntax + +```csharp +// Broadcast to all players +TriggerClientEvent(string eventName, params object[] args); + +// Send only to one player +player.TriggerEvent(string eventName, params object[] args); +``` + +- `eventName`: the name of the client event to trigger (for example `"chat:addMessage"` or your own custom name). +- `args`: values that will be passed to the client event handler. + +## Basic broadcast example + +Sends a green chat message to all players when a server event is triggered. + +```csharp +using System; +using CitizenFX.Core; + +public class AnnounceServerScript : BaseScript +{ + public AnnounceServerScript() + { + EventHandlers["server:announce"] += new Action(OnServerAnnounce); + } + + private void OnServerAnnounce(string message) + { + TriggerClientEvent("chat:addMessage", new + { + args = new[] { "^2[Server]", message }, + color = new[] { 0, 255, 0 } + }); + } +} +``` + +Client-side (Lua example) listening for the event: + +```lua +RegisterNetEvent("chat:addMessage") +AddEventHandler("chat:addMessage", function(data) + TriggerEvent("chat:addMessage", data) +end) +``` + +In many setups the chat resource already handles `chat:addMessage` for you, so you only need to trigger it from C#. + +## Targeting a specific player + +To send an event only to one player, use the `Player` instance: + +```csharp +using CitizenFX.Core; + +public class PrivateMessageScript : BaseScript +{ + public void SendPrivateMessage(Player target, string message) + { + if (target == null) + { + Debug.WriteLine("[PrivateMessageScript] Target player is null."); + return; + } + + target.TriggerEvent("chat:addMessage", new + { + args = new[] { "^3[Server]", message }, + color = new[] { 255, 255, 0 } + }); + } +} +``` + +On the client, your handler just needs to accept the payload you send (in this example, an anonymous object with +`args` and `color` fields). + +## Sending custom data + +You can send simple values (strings, numbers, booleans) or small objects/arrays. Keep payloads compact so they are +cheap to send and easy to reason about. + +```csharp +using System; +using CitizenFX.Core; + +public class CustomDataScript : BaseScript +{ + public CustomDataScript() + { + EventHandlers["server:notifyStatus"] += new Action(OnNotifyStatus); + } + + private void OnNotifyStatus(int health, string status) + { + TriggerClientEvent("client:updateStatus", new + { + health, + status + }); + } +} +``` + +Client-side (Lua) handler for the custom event might look like this: + +```lua +RegisterNetEvent("client:updateStatus") +AddEventHandler("client:updateStatus", function(data) + print(("Health: %s, Status: %s"):format(data.health, data.status)) +end) +``` + +## Common pitfalls + +- The client must **register and handle** the event name you use, otherwise nothing visible will happen. +- Make sure you use the correct runtime on the client (Lua/JS/C#) and that the parameter order matches what you send. +- Avoid sending very large objects or big JSON blobs on every tick; design your events around small, meaningful updates. diff --git a/content/docs/scripting-reference/runtimes/csharp/server-functions.md b/content/docs/scripting-reference/runtimes/csharp/server-functions.md index cf858237e..64106bd22 100644 --- a/content/docs/scripting-reference/runtimes/csharp/server-functions.md +++ b/content/docs/scripting-reference/runtimes/csharp/server-functions.md @@ -8,4 +8,174 @@ There's a few ways to easily tell what functions exist in C# pending manual docu 1. You can use Visual Studio's IntelliSense functionality to view most functions, or use the 'class browser' feature to view the public-exposed API. 2. Natives exist in `CitizenFX.Core.Native.API`, check the [native reference](/natives/) to find out more. - (do make sure to filter by server) + (do make sure to filter by server). + +This page documents common **runtime-specific server functions** you are likely to use in day‑to‑day C# resources. It +is deliberately focused on practical examples rather than being an exhaustive reference. + +## Runtime-specific functions + +The following helpers are provided by the C# runtime and are not regular game natives. + +- [TriggerClientEvent (server, C#)](/docs/scripting-reference/runtimes/csharp/functions/TriggerClientEvent/) + +### Registering and handling server events + +Use `EventHandlers` to subscribe to server events such as `playerConnecting`, `playerDropped`, or your own custom +network events. + +```csharp +using System; +using System.Collections.Generic; +using CitizenFX.Core; + +public class MyServerScript : BaseScript +{ + public MyServerScript() + { + // Built-in event fired when a player is connecting to the server + EventHandlers["playerConnecting"] += new Action(OnPlayerConnecting); + + // Custom event you trigger from clients with TriggerServerEvent("myCustomEvent", ...) + EventHandlers["myCustomEvent"] += new Action(OnMyCustomEvent); + } + + private void OnPlayerConnecting([FromSource] Player player, string playerName, dynamic setKickReason, dynamic deferrals) + { + Debug.WriteLine($"[MyServerScript] {playerName} is connecting ({player?.Handle})."); + // You can use deferrals here if needed to perform async checks before allowing the player in. + } + + private void OnMyCustomEvent([FromSource] Player player, int someValue) + { + Debug.WriteLine($"Received myCustomEvent from {player?.Name} with value {someValue}."); + } +} +``` + +> Note +> The `[FromSource]` attribute tells the runtime to bind the first argument to the player that triggered the event. + +### Triggering client events from the server + +To send events from the server to one or more clients, use `TriggerClientEvent`. You can +broadcast to everyone or target specific players. + +```csharp +using CitizenFX.Core; + +public class MyServerEvents : BaseScript +{ + public MyServerEvents() + { + EventHandlers["announceToEveryone"] += new Action(OnAnnounceToEveryone); + } + + private void OnAnnounceToEveryone(string message) + { + // Broadcast to all connected players + TriggerClientEvent("chat:addMessage", new + { + args = new[] { "^2[Server]", message }, + color = new[] { 0, 255, 0 } + }); + } + + public void SendPrivateMessage(Player target, string message) + { + // Send only to a specific player + target.TriggerEvent("chat:addMessage", new + { + args = new[] { "^3[Server]", message }, + color = new[] { 255, 255, 0 } + }); + } +} +``` + +### Triggering server events from the server + +You can also trigger server events from other server code (for example from another resource or helper class). + +```csharp +using CitizenFX.Core; + +public class MyServerTriggers : BaseScript +{ + public void DoSomething() + { + // Will call any EventHandlers["myServerEvent"] subscribers on the server + TriggerEvent("myServerEvent", 42, "hello"); + } +} +``` + +> Note +> For client → server events, use `TriggerServerEvent` on the client side. On the server you continue to use +> `EventHandlers[...]` to handle them. + +### HTTP requests from the server + +Although many integrations are better handled by dedicated services, you can perform simple HTTP requests directly from +a C# server script using `System.Net.Http.HttpClient`. + +```csharp +using System.Net.Http; +using System.Threading.Tasks; +using CitizenFX.Core; + +public class MyHttpExample : BaseScript +{ + private static readonly HttpClient Http = new HttpClient(); + + public MyHttpExample() + { + EventHandlers["myHttpCheck"] += new Action(Player>(OnMyHttpCheck); + } + + private async void OnMyHttpCheck([FromSource] Player player) + { + var url = "https://httpbin.org/get"; + Debug.WriteLine($"Requesting {url} for {player?.Name}..."); + + var response = await Http.GetAsync(url); + var body = await response.Content.ReadAsStringAsync(); + + Debug.WriteLine($"HTTP { (int)response.StatusCode } from {url}"); + Debug.WriteLine(body); + } +} +``` + +> Tip +> For more advanced scenarios you might want to move HTTP calls into a separate service class and reuse a single +> `HttpClient` instance for the whole resource. + +### Working with players + +You can use `Players` (on `BaseScript`) to iterate over connected players and read basic information. + +```csharp +using System.Linq; +using CitizenFX.Core; + +public class MyPlayerHelpers : BaseScript +{ + [Command("listplayers")] + public void ListPlayersCommand(Player source, string[] args) + { + foreach (var player in Players) + { + Debug.WriteLine($"Player {player.Name} (id={player.ServerId})"); + } + + var count = Players.Count(); + Debug.WriteLine($"There are currently {count} players online."); + } +} +``` + +## Native functions + +Refer to the [FiveM Native Reference](/natives/) for game functions. Filter by **C#** and **server** in the +reference UI, or use `CitizenFX.Core.Native.API` directly from your code.