ESX.Trace = function(msg) if Config.EnableDebug then print(('[es_extended] [^2TRACE^7] %s^7'):format(msg)) end end ESX.SetTimeout = function(msec, cb) local id = ESX.TimeoutCount + 1 SetTimeout(msec, function() if ESX.CancelledTimeouts[id] then ESX.CancelledTimeouts[id] = nil else cb() end end) ESX.TimeoutCount = id return id end ESX.ClearTimeout = function(id) ESX.CancelledTimeouts[id] = true end ESX.RegisterServerCallback = function(name, cb) ESX.ServerCallbacks[name] = cb end ESX.TriggerServerCallback = function(name, requestId, source, cb, ...) if ESX.ServerCallbacks[name] ~= nil then ESX.ServerCallbacks[name](source, cb, ...) else print(('[es_extended] [^3WARNING^7] Server callback "%s" does not exist. Make sure that the server sided file really is loading, an error in that file might cause it to not load.'):format(name)) end end ESX.SavePlayer = function(xPlayer, cb) local asyncTasks = {} xPlayer.setLastPosition(xPlayer.getCoords()) -- User accounts for k,v in ipairs(xPlayer.accounts) do if ESX.LastPlayerData[xPlayer.source].accounts[v.name] ~= v.money then table.insert(asyncTasks, function(cb) MySQL.Async.execute('UPDATE user_accounts SET money = @money WHERE identifier = @identifier AND name = @name', { ['@money'] = v.money, ['@identifier'] = xPlayer.identifier, ['@name'] = v.name }, function(rowsChanged) cb() end) end) ESX.LastPlayerData[xPlayer.source].accounts[v.name] = v.money end end -- Inventory items for k,v in ipairs(xPlayer.inventory) do if ESX.LastPlayerData[xPlayer.source].items[v.name] ~= v.count then table.insert(asyncTasks, function(cb) MySQL.Async.execute('UPDATE user_inventory SET count = @count WHERE identifier = @identifier AND item = @item', { ['@count'] = v.count, ['@identifier'] = xPlayer.identifier, ['@item'] = v.name }, function(rowsChanged) cb() end) end) ESX.LastPlayerData[xPlayer.source].items[v.name] = v.count end end -- Job, loadout and position table.insert(asyncTasks, function(cb) MySQL.Async.execute('UPDATE users SET job = @job, job_grade = @job_grade, loadout = @loadout, position = @position WHERE identifier = @identifier', { ['@job'] = xPlayer.job.name, ['@job_grade'] = xPlayer.job.grade, ['@loadout'] = json.encode(xPlayer.getLoadout()), ['@position'] = json.encode(xPlayer.getLastPosition()), ['@identifier'] = xPlayer.identifier }, function(rowsChanged) cb() end) end) Async.parallel(asyncTasks, function(results) print(('[es_extended] [^2INFO^7] Saved %s'):format(xPlayer.getName())) if cb ~= nil then cb() end end) end ESX.SavePlayers = function(cb) local asyncTasks = {} local xPlayers = ESX.GetPlayers() for i=1, #xPlayers, 1 do table.insert(asyncTasks, function(cb) local xPlayer = ESX.GetPlayerFromId(xPlayers[i]) ESX.SavePlayer(xPlayer, cb) end) end Async.parallelLimit(asyncTasks, 8, function(results) print(('[es_extended] [^2INFO^7] Saved %s player(s)'):format(#xPlayers)) if cb ~= nil then cb() end end) end ESX.StartDBSync = function() function saveData() ESX.SavePlayers() SetTimeout(10 * 60 * 1000, saveData) end SetTimeout(10 * 60 * 1000, saveData) end ESX.GetPlayers = function() local sources = {} for k,v in pairs(ESX.Players) do table.insert(sources, k) end return sources end ESX.GetPlayerFromId = function(source) return ESX.Players[tonumber(source)] end ESX.GetPlayerFromIdentifier = function(identifier) for k,v in pairs(ESX.Players) do if v.identifier == identifier then return v end end end ESX.RegisterUsableItem = function(item, cb) ESX.UsableItemsCallbacks[item] = cb end ESX.UseItem = function(source, item) ESX.UsableItemsCallbacks[item](source) end ESX.GetItemLabel = function(item) if ESX.Items[item] ~= nil then return ESX.Items[item].label end end ESX.CreatePickup = function(type, name, count, label, playerId, components) local pickupId = (ESX.PickupId == 65635 and 0 or ESX.PickupId + 1) local xPlayer = ESX.GetPlayerFromId(playerId) ESX.Pickups[pickupId] = { type = type, name = name, count = count, label = label, coords = xPlayer.getCoords(), } if type == 'item_weapon' then ESX.Pickups[pickupId].components = components end TriggerClientEvent('esx:createPickup', -1, pickupId, label, playerId, type, name, components) ESX.PickupId = pickupId end ESX.DoesJobExist = function(job, grade) grade = tostring(grade) if job and grade then if ESX.Jobs[job] and ESX.Jobs[job].grades[grade] then return true end end return false end