Important notice regarding repository status
mastercitizenfx/fivem repository, while examples and legacy resources will move to a separate new repository.repository·master·Indexed 19 days ago
https://github.com/citizenfx/cfx-server-dataThe data repository for Cfx.re servers, containing essential resources and examples required for server operation. It includes example implementations for money systems, such as currency management exports (addMoney, removeMoney, getMoney), money fountain mechanics using GlobalState and Player State, and ped money drop systems using gameEventTriggered.
citizenfx/fivem repository, while examples and legacy resources will move to a separate new repository.resources/[local]/ directory.For advanced setups, you can include this repository as a submodule within your own Git repository and use a symbolic link (or junction on Windows) to map the resources directory. This allows you to manage the server data as a dependency while keeping your own resources separate.
# Linux
git submodule add https://github.com/citizenfx/cfx-server-data.git vendor/server-data
ln -s ../vendor/server-data/resources/ 'resources/[base]/'
# Windows
git submodule add https://github.com/citizenfx/cfx-server-data.git vendor/server-data
mklink /d resources\[base] ..\vendor\server-data\resourcesTo use this repository, clone it directly using Git. Avoid using the 'Download ZIP' option from GitHub, as cloning allows you to easily update to newer versions using standard Git commands.
git clone https://github.com/citizenfx/cfx-server-data.gitThe player-data resource automatically attaches the player's unique account ID to their player state bag. This allows other resources to access the ID without calling exports, provided they have access to the player's state.
State Bag Key: cfx.re/playerData@id
-- Example of accessing the ID via state bags on the server
local playerId = Player(source).state['cfx.re/playerData@id']The money fountain mechanic synchronizes data using GlobalState and Player State:
GlobalState['fountain_' .. data.id]. This value is synced across all clients.LocalPlayer.state['fountain_nextUse'] against GetNetworkTime() to determine if a fountain is currently on cooldown.LocalPlayer.state['money_cash'] to determine if the player has enough funds to interact with the fountain.The money fountain system synchronizes the current balance of each fountain to the GlobalState so it can be accessed by other resources or clients.
Fountain balances are stored in GlobalState using the following key pattern:
fountain_<fountainId>
Note that the value stored in GlobalState is an integer representing the amount in cents (multiplied by 100).
The Chat UI responds to window.postMessage events. When sending data from the client-side (Lua/JS) to the Chat UI, ensure the object contains a type field that matches one of the supported event handlers.
Supported event types:
ON_OPEN: Shows the input field and chat window.ON_MESSAGE: Adds a new Message to the chat.ON_CLEAR: Clears all current messages.ON_SUGGESTION_ADD: Adds a new command suggestion.ON_SUGGESTION_REMOVE: Removes a command suggestion by name.ON_MODE_ADD / ON_MODE_REMOVE: Manages available chat modes/channels.ON_TEMPLATE_ADD: Adds a new HTML template.ON_UPDATE_THEMES: Updates the entire UI theme.ON_SCREEN_STATE_CHANGE: Adjusts visibility based on screen state.ON_CLEAR: Clears the message history.playerConnecting event to prevent new connections when the server reaches its capacity. It retrieves the maximum allowed clients using GetConvarInt('sv_maxclients', 32). If the current playerCount is greater than or equal to this value, the connection is rejected using CancelEvent() and the player is notified with the reason: This server is full (past [sv_maxclients] players).The cooldown period between fountain interactions (pickup or place) is controlled by a server convar.
Convar Name: moneyFountain_cooldown
Unit: Milliseconds (ms)
Default: 5000 (5 seconds)
You can implement a money drop mechanic by listening to the gameEventTriggered event and filtering for CEventNetworkEntityDamage. When a victim (ped) dies, you can spawn a visual pickup using CreatePickupRotate and monitor the player's proximity to that pickup to trigger a server-side collection event.
Workflow:
CEventNetworkEntityDamage via AddEventHandler.args[4] == 1).CreatePickupRotate with the PICKUP_MONEY_VARIABLE model.CreateThread loop to check if the player is within a specific distance (e.g., 2.5 units) and if the pickup has been collected.money:tryPickup) to process the transaction.SetTimeout to automatically remove the pickup after a duration (e.g., 15000ms) to prevent clutter.AddEventHandler('gameEventTriggered', function(eventName, args)
if eventName == 'CEventNetworkEntityDamage' then
local victim = args[1]
local culprit = args[2]
local isDead = args[4] == 1
if isDead then
local origCoords = GetEntityCoords(victim)
local pickup = CreatePickupRotate(`PICKUP_MONEY_VARIABLE`, origCoords.x, origCoords.y, origCoords.z - 0.7, 0.0, 0.0, 0.0, 512, 0, false, 0)
local netId = PedToNet(victim)
local undoStuff = { false }
CreateThread(function()
local self = PlayerPedId()
while not undoStuff[1] do
Wait(50)
if #(GetEntityCoords(self) - origCoords) < 2.5 and HasPickupBeenCollected(pickup) then
TriggerServerEvent('money:tryPickup', netId)
RemovePickup(pickup)
break
end
end
undoStuff[1] = true
end)
SetTimeout(15000, function()
if not undoStuff[1] then
RemovePickup(pickup)
undoStuff[1] = true
end
end)
TriggerServerEvent('money:allowPickupNear', netId)
end
end
end)This example demonstrates a server-side pattern for rewarding players when they interact with a deceased ped. The logic follows these steps:
money:allowPickupNear event to register the coordinates of a ped that has low health (e.g., after being killed).money:tryPickup, the server verifies that the player is within a specific distance (e.g., 2.5 units) of the registered coordinates.exports['money']:addMoney to reward the player and clear the position from the cache.entityRemoved event handler to ensure that if a ped is deleted from the world, its associated money position is removed from the safePositions table to prevent memory leaks or invalid lookups.-- Example logic flow for a money drop
RegisterNetEvent('money:allowPickupNear')
AddEventHandler('money:allowPickupNear', function(pedId)
local entity = NetworkGetEntityFromNetworkId(pedId)
Wait(250)
if DoesEntityExist(entity) and GetEntityHealth(entity) <= 100 then
local coords = GetEntityCoords(entity)
safePositions[pedId] = coords
end
end)
RegisterNetEvent('money:tryPickup')
AddEventHandler('money:tryPickup', function(entity)
if safePositions[entity] then
local source = source
local playerPed = GetPlayerPed(source)
local coords = GetEntityCoords(playerPed)
if #(safePositions[entity] - coords) < 2.5 then
exports['money']:addMoney(source, 'cash', 40)
end
safePositions[entity] = nil
end
end)