cfx-server-data

repository·master·Indexed 19 days ago

https://github.com/citizenfx/cfx-server-data

The 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.

Tokens
7.5K
Snippets
26
Records
35
Agent score
59%

What's inside cfx-server-data

  1. Important notice regarding repository status

    master
    This repository is currently considered finalized/immutable and is archived. While the contents are still safe to use, pull requests and issue reports may not be addressed. Future updates will see parts of this repository moved to the citizenfx/fivem repository, while examples and legacy resources will move to a separate new repository.
  2. Use cfx-server-data as a Git submodule

    master

    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\resources
  3. Install cfx-server-data via Git

    master

    To 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.git
  4. Access player account ID via State Bags

    master

    The 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']
  5. Access money fountain state via GlobalState and Player State

    master

    The money fountain mechanic synchronizes data using GlobalState and Player State:

    • Fountain Amount: Accessed via GlobalState['fountain_' .. data.id]. This value is synced across all clients.
    • Next Available Use: The client checks LocalPlayer.state['fountain_nextUse'] against GetNetworkTime() to determine if a fountain is currently on cooldown.
    • Player Cash: The client checks LocalPlayer.state['money_cash'] to determine if the player has enough funds to interact with the fountain.
  6. Access fountain money via GlobalState

    master

    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).

  7. Interact with the Chat UI via NUI Messages

    master

    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.
  8. How the hardcap system enforces sv_maxclients

    master
    The hardcap system monitors the 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).
  9. Implement a ped money drop mechanic using gameEventTriggered

    master

    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:

    1. Listen for CEventNetworkEntityDamage via AddEventHandler.
    2. Check if the victim is dead (args[4] == 1).
    3. Spawn a pickup at the victim's coordinates using CreatePickupRotate with the PICKUP_MONEY_VARIABLE model.
    4. Use a CreateThread loop to check if the player is within a specific distance (e.g., 2.5 units) and if the pickup has been collected.
    5. Trigger a server event (e.g., money:tryPickup) to process the transaction.
    6. Use 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)
  10. Implement a ped money drop mechanic

    master

    This example demonstrates a server-side pattern for rewarding players when they interact with a deceased ped. The logic follows these steps:

    1. Validation: Listen for a money:allowPickupNear event to register the coordinates of a ped that has low health (e.g., after being killed).
    2. Verification: When a player attempts to pick up money via money:tryPickup, the server verifies that the player is within a specific distance (e.g., 2.5 units) of the registered coordinates.
    3. Reward: If valid, use exports['money']:addMoney to reward the player and clear the position from the cache.
    4. Cleanup: Use the 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)