Skip to main content

Server events

Every built-in event the server fires to its scripts. Register a handler with Event.Add in any server or shared script; see Events for how handlers, cancelling and custom events work. Messages sent by clients with Net.Send are not events of this list, see Net.

Available on: Server

Shared scripts also run on the client, where a different set of events fires: see Client events. OnResourceStart, OnResourceStop, OnPlayerJoin, OnPlayerQuit, OnChat, OnPlayerTeleport, OnPlayerDamage, OnPlayerKilled, OnVehicleDamage and OnVehicleDestroy exist on both sides, with differences described on each page.

Unless an event says otherwise:

  • it can't be cancelled (Event.Cancel() has no effect),
  • what the handler returns is ignored,
  • it runs on the server's main loop, so a slow handler delays the whole server tick.
EventWhen
OnResourceStarta resource started on the server
OnResourceStopa resource is stopping on the server
OnPreTickstart of every server tick
OnPostTickend of every server tick
OnPlayerJoina player finished joining
OnPlayerQuita joined player left
OnPlayerResourceActiona player's client started or stopped a resource
OnChata player sent a chat message (cancellable)
OnPlayerTeleporta player finished a teleport or respawn
OnPlayerVehicleEntera player entered a vehicle seat
OnPlayerVehicleExita player left a vehicle seat
OnPlayerDamagea player was damaged (cancellable)
OnPlayerKilleda player's health reached 0
OnVehicleDamagea vehicle was damaged (cancellable)
OnVehicleDestroya vehicle's health reached 0

Resources​

OnResourceStart(name)​

Fires when a resource has started on the server: all its server and shared scripts have run their top level without errors. It fires in every running resource, including the one that just started (its scripts already ran, so their handlers are registered), so compare name with Resource.Name to react only to your own start. It doesn't fire for resources that were already running when your resource started.

A resource starts when the server boots, from the server console (start, reload) or from a script (see Resources). A start asked for from inside an event handler happens at the next resource update. A restart fires OnResourceStop and then OnResourceStart.

Parameters

NameTypeDescription
namestringThe name of the resource that started (its folder name).

Frequency: once per resource start.

Example

Event.Add("OnResourceStart", function(name)
if name == Resource.Name then
print("my resource is up")
else
print("resource " .. name .. " started")
end
end)

OnResourceStop(name)​

Fires when a resource is about to stop, before its scripts are shut down: its own handlers still run, and the objects it spawned still exist (they are destroyed right after). It fires in every running resource, including the one that is stopping. Use it to save state or tell clients that something is going away.

A resource stops from the server console (stop, reload), from a script, or for every running resource when the server shuts down.

Parameters

NameTypeDescription
namestringThe name of the resource that is stopping.

Frequency: once per resource stop.

Example

local kills = {}

Event.Add("OnResourceStop", function(name)
if name == Resource.Name then
-- persist the session's kills before the Lua state is closed
for user_id, count in pairs(kills) do
print(user_id .. " got " .. count .. " kills")
end
end
end)

Server loop​

OnPreTick()​

Fires at the very start of every server tick, before the server reads the network packets received since the last tick, updates the world (streaming, ownership) and runs the resource update (timers, queued resource actions).

The server loop runs a tick and then sleeps about 4 ms, so this fires a few hundred times per second at most. The real rate depends on the machine and on how long each tick takes: don't count ticks to measure time, use Timer or compare times.

Parameters none.

Frequency: every server tick.

Example

local last = os.clock()

Event.Add("OnPreTick", function()
local now = os.clock()

if now - last >= 1 then
last = now
-- once per second of server CPU time
end
end)

OnPostTick()​

Fires at the very end of every server tick, after the packets of the tick have been handled (so after the Net handlers and the player events they caused), the world has been updated and timers have run. Changes you make here are sent with the next updates.

Parameters none.

Frequency: every server tick, right after the work of OnPreTick's tick.

Example

local pending = {}

-- other handlers queue work during the tick...
Event.Add("ScoreChanged", function(name) pending[name] = true end)

-- ...and it is flushed once at the end of the tick
Event.Add("OnPostTick", function()
for name in pairs(pending) do
Net.Broadcast("score_dirty", name)
end

pending = {}
end)

Players​

OnPlayerJoin(client)​

Fires when a player has finished joining: it passed authentication, its client downloaded and started the server's resources, and it is now part of the world. The player's character object already exists, so client:GetPlayer() returns it. The server's own join work (sending the current weather...) is done before scripts get the event.

The resources a client starts while joining fire OnPlayerResourceAction before this event.

Parameters

NameTypeDescription
clientPlayerHandleThe player that joined (the connection: name, Steam ID, ACL...). See Player.

Frequency: once per player connection.

Example

Event.Add("OnPlayerJoin", function(client)
Chat.Broadcast(client:GetName() .. " joined the server")

local player = client:GetPlayer()

if player then
player:AsPlayer():Respawn(vec3(2370, 300, 1210))
end
end)

OnPlayerQuit(client)​

Fires when a player that had joined leaves the server, by disconnecting, timing out or being kicked or banned. The player and its character object still exist while the handlers run, so you can still read its name, data and position. Before the event, the server already took the player out of the vehicle it was driving and the mounted gun it was using (no OnPlayerVehicleExit fires for that).

Players that disconnect before finishing the join never fire it (and never fired OnPlayerJoin).

Parameters

NameTypeDescription
clientPlayerHandleThe player that is leaving.

Frequency: once per joined player that leaves.

Example

Event.Add("OnPlayerQuit", function(client)
Chat.Broadcast(client:GetName() .. " left the server")
end)

OnPlayerResourceAction(client, name, action)​

Fires when a player's client tells the server it started or stopped one of its resources. Clients start the resources the server is running when they join and every time the server starts, restarts or updates one, and they stop them when the server stops them. It starts arriving as soon as the player is authenticated, so the resources a joining client starts come before OnPlayerJoin, while the player has no character yet (client:GetPlayer() returns nil).

Use it to know when a client-side part of your resource is ready to receive Net messages, for example to send it its initial state.

The resource name is whatever the client sent: treat it as untrusted input.

Parameters

NameTypeDescription
clientPlayerHandleThe player whose client acted.
namestringThe resource's name.
actionResourceActionResourceAction.Start or ResourceAction.Stop. A restart on the client arrives as a Stop followed by a Start. See Resources.

Frequency: once per resource start or stop on each client.

Example

Event.Add("OnPlayerResourceAction", function(client, name, action)
-- our client script is running on this player's game: send it the current round
if name == Resource.Name and action == ResourceAction.Start then
Net.SendToPlayer(client, "round_state", currentRound)
end
end)

Chat​

OnChat(client, text)​

Fires when a player sends a chat message to the server, before it is relayed. If no handler cancels it, the server broadcasts it to every joined player as "<name>: <text>" (which fires OnChat on their clients, see Client events) and logs it in the server console. Messages broadcast by scripts with Chat.Broadcast don't fire this event.

Parameters

NameTypeDescription
clientPlayerHandleThe player that sent the message.
textstringThe message as the player typed it, without the name prefix (at most 1023 bytes).

Cancellable: yes. Cancelling it drops the message: it is not broadcast to anyone and not logged.

Frequency: once per message.

Example

-- simple commands typed in the chat
Event.Add("OnChat", function(client, text)
if text == "/kill" then
Event.Cancel()

local player = client:GetPlayer()

if player then
player:SetHealth(0)
end
end
end)

Player character​

OnPlayerTeleport(player)​

Fires when a player's game has finished moving its character after a script called player:Teleport(...) or player:Respawn(...) (see Player). The server then tells that player and the players near it that the teleport is complete, which fires OnPlayerTeleport on their clients too. Moves the server makes for other reasons don't fire it.

Parameters

NameTypeDescription
playerPlayerObjectHandleThe player's character.

Frequency: once per scripted teleport or respawn.

Example

Event.Add("OnPlayerTeleport", function(player)
local client = player:GetClient()

if client then
print(client:GetName() .. " arrived at " .. tostring(player:GetPosition()))
end
end)

OnPlayerVehicleEnter(player, vehicle, seat, previous)​

Fires when a player gets into a seat of a vehicle, as reported by the player's game. It doesn't fire when the vehicle is already destroyed or when the player is already in that seat. When it fires, the server hasn't updated the vehicle's occupants yet, so the vehicle still shows the previous occupant of that seat; right after the handlers, the player becomes the occupant and, in the driver seat, takes over the vehicle's synchronization.

Parameters

NameTypeDescription
playerPlayerObjectHandleThe player's character.
vehicleVehicleHandleThe vehicle. See Vehicle.
seatintegerThe seat, a VehicleSeat value (e.g. VehicleSeat.DriverSeat). See Enums.
previousPlayerObjectHandle or nilThe player the server had in that seat before (for example the driver being hijacked), nil if it was empty.

Frequency: once per vehicle entry.

Example

Event.Add("OnPlayerVehicleEnter", function(player, vehicle, seat, previous)
if seat == VehicleSeat.DriverSeat and previous then
local thief = player:GetClient()
local victim = previous:GetClient()

if thief and victim then
Chat.Broadcast(thief:GetName() .. " hijacked " .. victim:GetName())
end
end
end)

OnPlayerVehicleExit(player, vehicle, seat)​

Fires when a player leaves a vehicle seat, as reported by the player's game (any exit: normal, stunt, parachute...). When it fires, the server still has the player in the vehicle; right after, the player is removed from the seat and, in the driver seat, the vehicle's synchronization is released. It doesn't fire for the seat a player had when it quits the server.

Parameters

NameTypeDescription
playerPlayerObjectHandleThe player's character.
vehicleVehicleHandleThe vehicle.
seatintegerThe seat the player left, a VehicleSeat value.

Frequency: once per vehicle exit.

Example

Event.Add("OnPlayerVehicleExit", function(player, vehicle, seat)
if seat == VehicleSeat.DriverSeat then
vehicle:SetData("last_driver", player:GetNetId())
end
end)

Damage​

The four damage events share the same arguments. A damage event fires in two situations:

  • A hit was reported. Damage between players and vehicles is detected by the game of the player who caused it and reported to the server. The server fires the damage event (OnPlayerDamage or OnVehicleDamage) before applying it. If no handler cancels it, the server lowers the health, relays the hit to the players that see the victim (which fires the same events on their clients) and, if the hit took the health from above 0 to 0, fires the death event (OnPlayerKilled or OnVehicleDestroy). Hits on a player that is already dead are ignored.
  • The health dropped without a hit, for example because a script lowered it with SetHealth or the object's owner reported a lower health. The damage event fires after the health changed, with no damager and weapon 0, and cancelling it has no effect. The death event fires if the health went from above 0 to 0.

The death event fires once per death or destruction: later hits on an object that is already dead or destroyed don't fire it again, while the damage events still fire for every hit. A player that respawns can be killed again, which fires OnPlayerKilled again.

OnPlayerDamage(player, damager, damage, weapon, position)​

Fires when a player's character is damaged, see Damage above.

Parameters

NameTypeDescription
playerPlayerObjectHandleThe damaged player's character.
damagerPlayerObjectHandle, VehicleHandle, MountedGunHandle, RigidObjectHandle, NPCHandle, TetherHandle, SandstormHandle or nilWhat caused the damage, as its typed handle (a player that shot, a vehicle that ran it over...). nil when unknown or when the health dropped without a hit.
damagenumberThe health lost, as a fraction of the maximum health (health goes from 0 to 1, so 0.25 is a quarter of it).
weaponintegerThe game's 32-bit hash of the weapon's name (see Hash), 0 when there's none.
positionvec3Where the hit landed, in world coordinates. When the health dropped without a hit, the player's position.

Cancellable: yes, for reported hits. Cancelling it doesn't apply the damage: the health doesn't change, the hit isn't relayed to any client and OnPlayerKilled doesn't fire.

Frequency: once per hit (an automatic weapon fires it many times per second).

Example

-- friendly fire off
Event.Add("OnPlayerDamage", function(player, damager, damage, weapon, position)
local attacker = damager and damager:AsPlayer()

if attacker and attacker:GetNetId() ~= player:GetNetId() and attacker:GetData("team") == player:GetData("team") then
Event.Cancel()
end
end)

OnPlayerKilled(player, damager, damage, weapon, position)​

Fires when a hit takes a player's health from above 0 to 0, right after the OnPlayerDamage that killed it, with the same arguments. It doesn't fire again until the player is alive again. The player stays dead until a script revives it, usually with player:Respawn(...) (see Player).

Parameters

NameTypeDescription
playerPlayerObjectHandleThe player that died.
damagertyped handle or nilWhat dealt the killing damage, nil when unknown.
damagenumberThe health lost by the killing hit (fraction of the maximum).
weaponintegerThe weapon's name hash (see Hash), 0 when there's none.
positionvec3Where the killing hit landed.

Frequency: once per death.

Example

Event.Add("OnPlayerKilled", function(player, damager, damage, weapon, position)
local killer = damager and damager:AsPlayer()
local victim = player:GetClient()

if killer and killer:GetNetId() ~= player:GetNetId() and victim then
local killer_client = killer:GetClient()

if killer_client then
Chat.Broadcast(killer_client:GetName() .. " killed " .. victim:GetName())
end
end

-- respawn 5 seconds later
Timer.Set(function()
player:Respawn(vec3(2370, 300, 1210))
end, 5000, 1)
end)

OnVehicleDamage(vehicle, damager, damage, weapon, position)​

Fires when a vehicle is damaged, see Damage above. Melee hits on vehicles are not reported.

Parameters

NameTypeDescription
vehicleVehicleHandleThe damaged vehicle.
damagertyped handle or nilWhat caused the damage (a player, another vehicle...), nil when unknown or when the health dropped without a hit.
damagenumberThe health lost, as a fraction of the vehicle's maximum health.
weaponintegerThe weapon's name hash (see Hash), 0 when there's none.
positionvec3Where the hit landed (the vehicle's position when the game gave none).

Cancellable: yes, for reported hits. Cancelling it doesn't apply the damage: the health doesn't change, the hit isn't relayed to any client and OnVehicleDestroy doesn't fire.

Frequency: once per hit.

Example

-- vehicles marked as protected can't be damaged
Event.Add("OnVehicleDamage", function(vehicle, damager, damage, weapon, position)
if vehicle:GetData("protected") then
Event.Cancel()
end
end)

OnVehicleDestroy(vehicle, damager, damage, weapon, position)​

Fires when a hit takes a vehicle's health from above 0 to 0, right after the OnVehicleDamage that destroyed it, with the same arguments. Further hits on the destroyed vehicle still fire OnVehicleDamage, but not OnVehicleDestroy again.

Parameters

NameTypeDescription
vehicleVehicleHandleThe destroyed vehicle.
damagertyped handle or nilWhat dealt the final damage, nil when unknown.
damagenumberThe health lost by the final hit (fraction of the maximum).
weaponintegerThe weapon's name hash (see Hash), 0 when there's none.
positionvec3Where the final hit landed.

Frequency: once per destruction.

Example

Event.Add("OnVehicleDestroy", function(vehicle)
-- remove the wreck after 30 seconds
Timer.Set(function()
World.Destroy(vehicle)
end, 30000, 1)
end)