EndCore Framework

Player API

The player object and its Functions, plus every en-core server and client export for players, characters, shared data and lookups.

This page covers how other resources read and change a player through en-core. There are two ways in:

  • The player object, fetched with exports['en-core']:GetPlayer(source). It carries the full PlayerData and a Functions table of methods.
  • Per-source exports such as GetMoney(source, 'cash') or GetPlayerMetadata(source, 'hunger'). They return just one value and are much cheaper to call often.

Exports for groups, XP, survival and content have their own pages: Groups, XP and levels, Survival system and Content registry.

The player object

lua
Player = {
    PlayerData = PlayerData, -- see the Player data page
    Offline = false,         -- true for objects from GetOfflinePlayer
    Functions = { ... },
}

Every function that changes state calls UpdatePlayerData(), which sends the full PlayerData to that player's client. Unless the player is offline, it also fires a server event encore:server:<event> with (source, ...) and a client event encore:client:<event> with (...). The event names are listed with each function below and on the Events page.

Warning

GetPlayer copies the whole object across the export boundary. It is fine for one-off actions, but avoid calling it every frame or inside large loops. Use the lightweight exports further down this page instead.

Player functions

Jobs and duty

FunctionReturnsNotes
SetJob(jobName, grade?, skipUpdate?)booleanfalse if the job or grade does not exist. Resets onduty to the job's defaultDuty, records jobs[jobName] = grade, fires onJobUpdate(job).
SetDuty(onduty?)boolean (the new duty state)Toggles when called with no argument. Fires onDutyUpdate(onduty).

Money

FunctionReturnsNotes
AddMoney(moneyType, amount, reason?)booleanfalse for an unknown type or an amount of 0 or less after rounding. Fires onMoneyChange(moneyType, amount, 'add', reason, balance).
RemoveMoney(moneyType, amount, reason?)booleanfalse if it would go below 0 on a protected type, or the player does not carry enough cash item. Action 'remove'.
SetMoney(moneyType, amount, reason?)booleanAction 'set'
GetMoney(moneyType)numberWhen cash is an item, counts the carried item in the inventory and worn backpack

See Money and cash for the rules.

Metadata

FunctionReturnsNotes
SetMetadata(key, value, save?)nothingWith save = true the character is saved too. Fires onSetMetaData(key, value).
SetMetadataBulk(values)nothingOne client sync, then onSetMetaData fires once per key
GetMetadata(key)any

XP

FunctionReturnsNotes
AddXP(amount, reason?)booleanfalse when offline
RemoveXP(amount, reason?)booleanfalse when offline
GetXP()numberTotal XP
GetLevel()number

Survival

FunctionReturnsNotes
AddRadiation(amount, reason?) / RemoveRadiation(amount, reason?)booleanfalse if amount is 0 or less. Clamped. Fires onRadiationChange(newValue, action, reason).
SetRadiation(amount, reason?)nothingFires onRadiationChange(newValue, 'set', reason)
GetRadiation()number
AddInfection / RemoveInfection / SetInfection / GetInfectionsame as radiationFires onInfectionChange
AddImmunity / RemoveImmunity / GetImmunitysame as radiationFires onImmunityChange. There is no SetImmunity.
SetTemperature(amount, reason?)nothingClamped to 70–120 °F. Fires onTemperatureChange(temp, 'set', reason).
GetTemperature()number
AddHunger(amount) / RemoveHunger(amount)booleanClamped 0–100. No reason and no dedicated event, only a PlayerData update.
AddThirst(amount) / RemoveThirst(amount)booleanSame as hunger

For the stat events, the first value is the resulting stat, not the amount that was added.

Inventory

These pass through to the library's inventory interface, which en-inventory implements. Without an inventory running they return nil, 0 or false.

FunctionReturnsNotes
GetItemByName(name){ name, label, count } or nilnil when offline or the count is 0
GetItemCount(name)number
AddItem(name, count, metadata?)boolean
RemoveItem(name, count, metadata?)boolean

Saving and session

FunctionReturnsNotes
UpdatePlayerData()nothingSends encore:client:playerDataUpdate with the full PlayerData. Does nothing when offline.
Save()booleanReads the ped position on the server (skipping 0, 0, 0) and writes the row
Logout()nothingSame as the Logout export. Does nothing when offline.

When the QB bridge is active, it also adds Functions.SetGang, which does nothing. See Compatibility bridges.

Server exports

All server exports are called as exports['en-core']:Name(...).

Players and sessions

ExportArgumentsReturns
GetPlayers()nonetable<source, Player>, the online registry
GetPlayer(source)sourcePlayer or nil
GetPlayerByCitizenId(citizenid)citizenidPlayer or nil (online only)
GetPlayerByIdentifier(license)licensePlayer or nil. Only matches PlayerData.license, despite the name.
GetOfflinePlayer(citizenid)citizenidPlayer with Offline = true, or nil
Login(source, citizenid)source, citizenidPlayer or nil, err
CreateCharacter(source, newData)source, { charinfo = {...} }Player or nil, err
Logout(source, skipSave?)source, skipSavenothing
SaveAllPlayers()nonenumber of players saved

Login checks that the character belongs to the connecting license, attaches the player's group, and fires encore:server:onPlayerLoaded(source, playerData) and encore:client:onPlayerLoaded(playerData). Error codes:

ErrorMeaning
no_licenseThe player has no license identifier
no_citizenidNo citizenid was passed
character_not_foundNo character with that citizenid
not_your_characterThe character belongs to another license
character_already_onlineThe character is already in use

CreateCharacter accepts { charinfo = {...} } or a bare charinfo table. It inserts the row but does not put the character in the world; call Login next. Error codes: no_license, no_slots_available, citizenid_generation_failed, insert_failed.

Logout saves the character (unless skipSave is true), removes it from the registry, and fires encore:server:onPlayerUnload(source, playerData) and encore:client:onPlayerUnload.

Offline players. Changes to an object from GetOfflinePlayer are only written when you call player.Functions.Save().

en-multicharacter is the resource that calls Login, CreateCharacter and DeleteCharacter for you.

Characters

ExportArgumentsReturns
GetCharacters(license)licenseArray of decoded character rows, oldest first
GetCharacterSlots(license)licensenumber
DeleteCharacter(citizenid)citizenidboolean. Removes the character from its group first (leadership passes on), then deletes the row.
LicenseOwnsCharacter(citizenid, license)citizenid, licenseboolean
Danger

Never trust a citizenid sent by a client. Check it with LicenseOwnsCharacter against the sender's license before you load, delete or change that character.

Lightweight lookups

These touch only the value you ask for, so they are the right choice for polling and hot paths.

ExportArgumentsReturns
GetCitizenId(source)sourcestring or nil
IsPlayerLoaded(source)sourceboolean
GetCharacterName(source)source"First Last" or nil
GetPlayerMetadata(source, key?)source, keyThe value, or the whole metadata table when key is nil
SetPlayerMetadata(source, key, value)source, key, valueboolean
AddMoney(source, moneyType, amount, reason?)source, moneyType, amount, reasonboolean
RemoveMoney(source, moneyType, amount, reason?)source, moneyType, amount, reasonboolean
GetMoney(source, moneyType)source, moneyTypenumber (0 if not loaded)

SetPlayerMetadata sends only encore:client:onSetMetaData(key, value) to the client and fires encore:server:onSetMetaData(source, key, value). It does not push the whole PlayerData. The value is saved with the character as usual.

Shared data and config

ExportReturns
GetJobs()The job table from shared/jobs.lua
GetVehicles()The vehicle table from shared/vehicles.lua
GetWeapons()The weapon table from shared/weapons.lua
GetSharedConfig()config/shared.lua
GetServerConfig()config/server.lua
GetGroupSettings()shared/groups.lua
GetLevels()shared/levels.lua

Identifiers and logging

ExportArgumentsReturns
GetIdentifier(source, idType)source, 'license' / 'discord' / ...string or nil. Prefix-anchored, so 'license' never matches license2:.
GetAllIdentifiers(source)sourcetable<type, identifier>
Log(channel, message)channel, messagenothing. Prints and posts to the channel's webhook, falling back to default.

Client exports

ExportReturns
GetPlayerData()The local PlayerData, or nil before login
IsLoggedIn()boolean
GetMetadata(key?)One value, or the whole metadata table. A stored false is returned correctly.
GetLevelProgress(){ xp, level, into, needed, max }
Notify(data)Wraps encore.notify(data)
GetVehicles()The vehicle table
GetVehiclesByName(name)A vehicle entry, matched on its display name, case-insensitive
GetVehiclesByHash(hash)A vehicle entry
GetWeapons() / GetWeapon(name)The weapon table or one weapon
GetJobs()The job table

The client global ENC (with ENC.PlayerData and helpers) is only visible inside en-core's own client scripts. Other resources should use the exports above.

Examples

Pay a player for a sale and promote them:

lua
local player = exports['en-core']:GetPlayer(source)
if not player then return end

if player.Functions.AddMoney('cash', 250, 'Sold scrap') then
    player.Functions.SetJob('scavenger', 1)
end

Cheap checks from a loop:

lua
for _, src in ipairs(GetPlayers()) do
    src = tonumber(src)
    if exports['en-core']:IsPlayerLoaded(src) then
        local hunger = exports['en-core']:GetPlayerMetadata(src, 'hunger')
        if hunger and hunger < 10 then
            encore.notify(src, { description = 'Your stomach is cramping.', type = 'warning' })
        end
    end
end

Charge by source without fetching the player object:

lua
if not exports['en-core']:RemoveMoney(source, 'bank', 100, 'Repair fee') then
    encore.notify(source, { description = 'You cannot afford the repair.', type = 'error' })
end

Create a character and log in, as a character screen would:

lua
local created, err = exports['en-core']:CreateCharacter(source, { charinfo = {
    firstname = 'Ada', lastname = 'Reyes', birthdate = '1994-03-02', gender = 1, nationality = 'American',
} })

if not created then
    print('create failed: ' .. err)
    return
end

local player, loginErr = exports['en-core']:Login(source, created.PlayerData.citizenid)

Edit an offline character:

lua
local player = exports['en-core']:GetOfflinePlayer('ENCAB12CD34')
if player then
    player.Functions.SetMetadata('radiation', 0)
    player.Functions.Save()
end

Read data on the client:

lua
local data = exports['en-core']:GetPlayerData()
if data then
    print(data.job.label, data.metadata.radiation)
end