Server events are the backbone of RSG Framework’s server-side communication system. They allow resources to listen for and respond to player actions, system events, and cross-resource communication.
Server events run on the server and can be triggered by clients using TriggerServerEvent or by other server-side code using TriggerEvent.
Triggered when a player successfully loads into the server after character selection.
Copy
-- SERVER SIDERegisterNetEvent('RSGCore:Server:OnPlayerLoaded', function() local src = source local Player = RSGCore.Functions.GetPlayer(src) if not Player then return end print('Player loaded:', Player.PlayerData.charinfo.firstname) -- Your custom logic here -- Example: Give welcome bonus Player.Functions.AddMoney('cash', 100, 'welcome-bonus')end)
Triggered when a player logs out or returns to character selection.
Copy
-- SERVER SIDERegisterNetEvent('RSGCore:Server:OnPlayerUnload', function() local src = source print('Player', src, 'logged out') -- Clean up player-specific data -- Remove from custom tables -- Save additional data if neededend)
Closes the server to non-whitelisted players with a custom reason.
Copy
-- SERVER SIDERegisterNetEvent('RSGCore:Server:CloseServer', function(reason) local src = source -- Permission check if not RSGCore.Functions.HasPermission(src, 'admin') then RSGCore.Functions.Kick(src, 'You don\'t have permissions for this', nil, nil) return end reason = reason or 'Server maintenance' RSGCore.Config.Server.Closed = true RSGCore.Config.Server.ClosedReason = reason -- Kick all non-whitelisted players for playerId in pairs(RSGCore.Players) do if not RSGCore.Functions.HasPermission(playerId, RSGCore.Config.Server.WhitelistPermission) then RSGCore.Functions.Kick(playerId, reason, nil, nil) end end print('Server closed:', reason)end)
Trigger from Client:
Copy
-- CLIENT SIDE (admin only)TriggerServerEvent('RSGCore:Server:CloseServer', 'Emergency maintenance')
-- SERVER SIDERegisterNetEvent('RSGCore:Server:OpenServer', function() local src = source if not RSGCore.Functions.HasPermission(src, 'admin') then RSGCore.Functions.Kick(src, 'You don\'t have permissions for this', nil, nil) return end RSGCore.Config.Server.Closed = false print('Server opened')end)
Trigger from Client:
Copy
-- CLIENT SIDE (admin only)TriggerServerEvent('RSGCore:Server:OpenServer')
Updates and saves player needs (hunger, thirst, cleanliness).
Copy
-- SERVER SIDERegisterNetEvent('RSGCore:UpdatePlayer', function() local src = source local Player = RSGCore.Functions.GetPlayer(src) if not Player then return end -- Decrease player needs local newHunger = math.max(0, Player.PlayerData.metadata.hunger - RSGCore.Config.Player.HungerRate) local newThirst = math.max(0, Player.PlayerData.metadata.thirst - RSGCore.Config.Player.ThirstRate) local newCleanliness = math.max(0, Player.PlayerData.metadata.cleanliness - RSGCore.Config.Player.CleanlinessRate) -- Update metadata Player.Functions.SetMetaData('hunger', newHunger) Player.Functions.SetMetaData('thirst', newThirst) Player.Functions.SetMetaData('cleanliness', newCleanliness) -- Notify client TriggerClientEvent('hud:client:UpdateNeeds', src, newHunger, newThirst, newCleanliness) -- Save player data Player.Functions.Save()end)
This event is typically called on a timer to gradually decrease player needs over time.
Complete Example with Timer:
Copy
-- SERVER SIDECreateThread(function() while true do Wait(RSGCore.Config.Player.UpdateInterval or 300000) -- 5 minutes default for src, Player in pairs(RSGCore.Players) do if Player then TriggerEvent('RSGCore:UpdatePlayer', src) end end endend)
Sets a specific metadata value for a player with validation.
Copy
-- SERVER SIDERegisterNetEvent('RSGCore:Server:SetMetaData', function(meta, data) local src = source local Player = RSGCore.Functions.GetPlayer(src) if not Player then return end -- Validate needs (cap at 100) if meta == 'hunger' or meta == 'thirst' or meta == 'cleanliness' then if data > 100 then data = 100 elseif data < 0 then data = 0 end end -- Update metadata Player.Functions.SetMetaData(meta, data) -- Update HUD TriggerClientEvent('hud:client:UpdateNeeds', src, Player.PlayerData.metadata.hunger, Player.PlayerData.metadata.thirst, Player.PlayerData.metadata.cleanliness )end)
-- SERVER SIDERegisterNetEvent('RSGCore:ToggleDuty', function() local src = source local Player = RSGCore.Functions.GetPlayer(src) if not Player then return end -- Check if job has duty system if not Player.PlayerData.job.name then return end -- Toggle duty local newDutyStatus = not Player.PlayerData.job.onduty Player.Functions.SetJobDuty(newDutyStatus) -- Notify player lib.notify(src, { description = newDutyStatus and 'You are now on duty' or 'You are now off duty', type = 'info' }) -- Trigger client event for additional logic TriggerClientEvent('RSGCore:Client:SetDuty', src, newDutyStatus)end)
-- SERVER SIDElocal dutyJobs = { ['police'] = true, ['doctor'] = true, ['mechanic'] = true}RegisterNetEvent('RSGCore:ToggleDuty', function() local src = source local Player = RSGCore.Functions.GetPlayer(src) if not Player then return end -- Check if job has duty system if not dutyJobs[Player.PlayerData.job.name] then lib.notify(src, { description = 'Your job doesn\'t have a duty system', type = 'error' }) return end -- Toggle duty local newDutyStatus = not Player.PlayerData.job.onduty Player.Functions.SetJobDuty(newDutyStatus) -- Job-specific logic if Player.PlayerData.job.name == 'police' then if newDutyStatus then -- Add police blip TriggerClientEvent('police:client:addBlip', src) else -- Remove police blip TriggerClientEvent('police:client:removeBlip', src) end end lib.notify(src, { description = newDutyStatus and 'Clocked in' or 'Clocked out', type = 'success' })end)
Handles server-side callback requests from clients.
Copy
-- SERVER SIDE (internal - used by callback system)RegisterNetEvent('RSGCore:Server:TriggerCallback', function(name, ...) local src = source if not RSGCore.ServerCallbacks[name] then print('^1[ERROR]^7 Callback', name, 'does not exist') return end RSGCore.ServerCallbacks[name](src, function(...) TriggerClientEvent('RSGCore:Client:TriggerCallback', src, name, ...) end, ...)end)
This is an internal event used by the callback system. Use RSGCore.Functions.CreateCallback instead of listening to this event directly.
Proper Usage:
Copy
-- SERVER SIDE - Create callbackRSGCore.Functions.CreateCallback('myCallback', function(source, cb, arg1) local Player = RSGCore.Functions.GetPlayer(source) if not Player then cb(nil) return end cb(Player.PlayerData.money.cash)end)
Copy
-- CLIENT SIDE - Trigger callbackRSGCore.Functions.TriggerCallback('myCallback', function(cashAmount) print('Player has $' .. cashAmount)end, someArgument)
Grants a permission level to a player (typically admin/god).
Copy
-- SERVER SIDERegisterNetEvent('RSGCore:Server:GivePermission', function(targetId, permission) local src = source -- Only admins can grant permissions if not RSGCore.Functions.HasPermission(src, 'god') then lib.notify(src, { description = 'You don\'t have permission to do this', type = 'error' }) return end local Target = RSGCore.Functions.GetPlayer(targetId) if not Target then lib.notify(src, { description = 'Player not found', type = 'error' }) return end -- Grant permission RSGCore.Functions.AddPermission(targetId, permission) lib.notify(src, { description = 'Granted ' .. permission .. ' to player', type = 'success' }) lib.notify(targetId, { description = 'You have been granted ' .. permission .. ' permissions', type = 'info' })end)
-- SERVER SIDERegisterNetEvent('RSGCore:Server:RemovePermission', function(targetId, permission) local src = source if not RSGCore.Functions.HasPermission(src, 'god') then lib.notify(src, { description = 'You don\'t have permission to do this', type = 'error' }) return end -- Remove permission RSGCore.Functions.RemovePermission(targetId, permission) lib.notify(src, { description = 'Removed ' .. permission .. ' from player', type = 'success' })end)
-- GOODRegisterNetEvent('myEvent', function(arg) local src = source local Player = RSGCore.Functions.GetPlayer(src) if not Player then return end -- Safe to use Playerend)-- BADRegisterNetEvent('myEvent', function(arg) local src = source local Player = RSGCore.Functions.GetPlayer(src) -- No check - will error if player doesn't exist! Player.Functions.AddMoney('cash', 100)end)
-- GOODRegisterNetEvent('shop:purchase', function(itemName, amount) local src = source local Player = RSGCore.Functions.GetPlayer(src) if not Player then return end -- Validate item exists if not RSGCore.Shared.Items[itemName] then return end -- Validate amount if type(amount) ~= 'number' or amount < 1 or amount > 100 then return end -- Process purchaseend)
-- GOODRegisterNetEvent('admin:giveWeapon', function(targetId, weapon) local src = source if not RSGCore.Functions.HasPermission(src, 'admin') then return -- Silent fail or notify end -- Admin actionend)
RegisterNetEvent('banking:server:deposit', function(amount) local src = source local Player = RSGCore.Functions.GetPlayer(src) if not Player then return end -- Validate amount if type(amount) ~= 'number' or amount < 1 then lib.notify(src, {description = 'Invalid amount', type = 'error'}) return end -- Check player has cash if Player.Functions.GetMoney('cash') < amount then lib.notify(src, {description = 'Not enough cash', type = 'error'}) return end -- Process deposit Player.Functions.RemoveMoney('cash', amount, 'bank-deposit') Player.Functions.AddMoney('bank', amount, 'bank-deposit') lib.notify(src, { description = 'Deposited $' .. amount, type = 'success' })end)
RegisterNetEvent('admin:giveItem', function(targetId, itemName, amount) local src = source -- Permission check if not RSGCore.Functions.HasPermission(src, 'admin') then return end -- Validate inputs local Target = RSGCore.Functions.GetPlayer(targetId) if not Target then return end if not RSGCore.Shared.Items[itemName] then return end amount = tonumber(amount) or 1 -- Give item exports['rsg-inventory']:AddItem(targetId, itemName, amount, nil, nil, 'admin-give') lib.notify(src, { description = 'Gave item to player', type = 'success' })end)
RegisterNetEvent('shop:server:purchase', function(shopId, itemName) local src = source local Player = RSGCore.Functions.GetPlayer(src) if not Player then return end -- Get shop location local shopCoords = Config.Shops[shopId].coords -- Check if player is near local ped = GetPlayerPed(src) local playerCoords = GetEntityCoords(ped) local distance = #(playerCoords - shopCoords) if distance > 5.0 then lib.notify(src, {description = 'Too far from shop', type = 'error'}) return end -- Process purchaseend)
-- Common issueRegisterNetEvent('myEvent', function() local src = source local Player = RSGCore.Functions.GetPlayer(src) if not Player then print('Player not loaded yet or disconnected') return endend)