RegisterNetEvent('esx:playerJoined') AddEventHandler('esx:playerJoined', function() onPlayerJoined(source) end) function onPlayerJoined(playerId) local identifier for k,v in ipairs(GetPlayerIdentifiers(playerId)) do if string.match(v, 'license:') then identifier = string.sub(v, 9) break end end if identifier then MySQL.Async.fetchScalar('SELECT 1 FROM users WHERE identifier = @identifier', { ['@identifier'] = identifier }, function(result) if result then loadESXPlayer(identifier, playerId) else local accounts = {} for account,money in pairs(Config.StartingAccountMoney) do accounts[account] = money end MySQL.Async.execute('INSERT INTO users (accounts, identifier) VALUES (@accounts, @identifier)', { ['@accounts'] = json.encode(accounts), ['@identifier'] = identifier }, function(rowsChanged) loadESXPlayer(identifier, playerId) end) end end) else DropPlayer(playerId, 'Your Rockstar license could not be found') end end function loadESXPlayer(identifier, playerId) local tasks = {} local userData = { accounts = {}, inventory = {}, job = {}, loadout = {}, playerName = GetPlayerName(playerId) } table.insert(tasks, function(cb) MySQL.Async.fetchAll('SELECT accounts, job, job_grade, `group`, loadout, position, inventory FROM users WHERE identifier = @identifier', { ['@identifier'] = identifier }, function(result) local job, grade, jobObject, gradeObject = result[1].job, tostring(result[1].job_grade) local fonudAccounts, foundItems = {}, {} -- Accounts if result[1].accounts and result[1].accounts ~= '' then local accounts = json.decode(result[1].accounts) for account,money in pairs(accounts) do fonudAccounts[account] = money end end for account,label in pairs(Config.Accounts) do table.insert(userData.accounts, { name = account, money = fonudAccounts[account] or Config.StartingAccountMoney[account] or 0, label = label }) end -- Job if ESX.DoesJobExist(job, grade) then jobObject, gradeObject = ESX.Jobs[job], ESX.Jobs[job].grades[grade] else print(('[es_extended] [^3WARNING^7] Ignoring invalid job for %s [job: %s, grade: %s]'):format(identifier, job, grade)) job, grade = 'unemployed', '0' jobObject, gradeObject = ESX.Jobs[job], ESX.Jobs[job].grades[grade] end userData.job.id = jobObject.id userData.job.name = jobObject.name userData.job.label = jobObject.label userData.job.grade = tonumber(grade) userData.job.grade_name = gradeObject.name userData.job.grade_label = gradeObject.label userData.job.grade_salary = gradeObject.salary userData.job.skin_male = {} userData.job.skin_female = {} if gradeObject.skin_male then userData.job.skin_male = json.decode(gradeObject.skin_male) end if gradeObject.skin_female then userData.job.skin_female = json.decode(gradeObject.skin_female) end -- Inventory if result[1].inventory and result[1].inventory ~= '' then local inventory = json.decode(result[1].inventory) for name,count in pairs(inventory) do local item = ESX.Items[name] if item then foundItems[name] = count else print(('[es_extended] [^3WARNING^7] Ignoring invalid item "%s" for "%s"'):format(name, identifier)) end end end for name,item in pairs(ESX.Items) do local count = foundItems[name] or 0 table.insert(userData.inventory, { name = name, count = count, label = item.label, weight = item.weight, usable = ESX.UsableItemsCallbacks[name] ~= nil, rare = item.rare, canRemove = item.canRemove }) end -- Group if result[1].group then userData.group = result[1].group else userData.group = 'user' end table.sort(userData.inventory, function(a, b) return a.label < b.label end) -- Loadout if result[1].loadout and result[1].loadout ~= '' then local loadout = json.decode(result[1].loadout) for name,weapon in pairs(loadout) do local label = ESX.GetWeaponLabel(name) if label then if not weapon.components then weapon.components = {} end if not weapon.tintIndex then weapon.tintIndex = 0 end table.insert(userData.loadout, { name = name, ammo = weapon.ammo, label = label, components = weapon.components, tintIndex = weapon.tintIndex }) end end end -- Position if result[1].position and result[1].position ~= '' then userData.coords = json.decode(result[1].position) else print('[es_extended] [^3WARNING^7] Column "position" in "users" table is missing required default value. Using backup coords, fix your database.') userData.coords = {x = -269.4, y = -955.3, z = 31.2, heading = 205.8} end cb() end) end) Async.parallel(tasks, function(results) local xPlayer = CreateExtendedPlayer(playerId, identifier, userData.group, userData.accounts, userData.inventory, userData.job, userData.loadout, userData.playerName, userData.coords) ESX.Players[playerId] = xPlayer TriggerEvent('esx:playerLoaded', playerId, xPlayer) xPlayer.triggerEvent('esx:playerLoaded', { accounts = xPlayer.getAccounts(), coords = xPlayer.getCoords(), identifier = xPlayer.identifier, inventory = xPlayer.getInventory(), job = xPlayer.getJob(), loadout = xPlayer.getLoadout(), maxWeight = xPlayer.maxWeight, money = xPlayer.getMoney(), }) xPlayer.triggerEvent('esx:createMissingPickups', ESX.Pickups) xPlayer.triggerEvent('esx:registerSuggestions', ESX.RegisteredCommands) end) end AddEventHandler('playerDropped', function(reason) local playerId = source local xPlayer = ESX.GetPlayerFromId(playerId) if xPlayer then TriggerEvent('esx:playerDropped', playerId, reason) ESX.SavePlayer(xPlayer, function() ESX.Players[playerId] = nil end) end end) RegisterNetEvent('esx:updateCoords') AddEventHandler('esx:updateCoords', function(coords) local xPlayer = ESX.GetPlayerFromId(source) if xPlayer then xPlayer.updateCoords(coords) end end) RegisterNetEvent('esx:updateLoadout') AddEventHandler('esx:updateLoadout', function(loadout) local xPlayer = ESX.GetPlayerFromId(source) xPlayer.loadout = loadout end) RegisterNetEvent('esx:giveInventoryItem') AddEventHandler('esx:giveInventoryItem', function(target, type, itemName, itemCount) local playerId = source local sourceXPlayer = ESX.GetPlayerFromId(playerId) local targetXPlayer = ESX.GetPlayerFromId(target) if type == 'item_standard' then local sourceItem = sourceXPlayer.getInventoryItem(itemName) local targetItem = targetXPlayer.getInventoryItem(itemName) if itemCount > 0 and sourceItem.count >= itemCount then if targetXPlayer.canCarryItem(itemName, itemCount) then sourceXPlayer.removeInventoryItem(itemName, itemCount) targetXPlayer.addInventoryItem (itemName, itemCount) sourceXPlayer.showNotification(_U('gave_item', itemCount, sourceItem.label, targetXPlayer.name)) targetXPlayer.showNotification(_U('received_item', itemCount, sourceItem.label, sourceXPlayer.name)) else sourceXPlayer.showNotification(_U('ex_inv_lim', targetXPlayer.name)) end else sourceXPlayer.showNotification(_U('imp_invalid_quantity')) end elseif type == 'item_account' then if itemCount > 0 and sourceXPlayer.getAccount(itemName).money >= itemCount then sourceXPlayer.removeAccountMoney(itemName, itemCount) targetXPlayer.addAccountMoney (itemName, itemCount) sourceXPlayer.showNotification(_U('gave_account_money', ESX.Math.GroupDigits(itemCount), Config.Accounts[itemName], targetXPlayer.name)) targetXPlayer.showNotification(_U('received_account_money', ESX.Math.GroupDigits(itemCount), Config.Accounts[itemName], sourceXPlayer.name)) else sourceXPlayer.showNotification(_U('imp_invalid_amount')) end elseif type == 'item_weapon' then if sourceXPlayer.hasWeapon(itemName) then local weaponLabel = ESX.GetWeaponLabel(itemName) if not targetXPlayer.hasWeapon(itemName) then local _, weapon = sourceXPlayer.getWeapon(itemName) local _, weaponObject = ESX.GetWeapon(itemName) itemCount = weapon.ammo sourceXPlayer.removeWeapon(itemName) targetXPlayer.addWeapon(itemName, itemCount) if weaponObject.ammo and itemCount > 0 then local ammoLabel = weaponObject.ammo.label sourceXPlayer.showNotification(_U('gave_weapon_withammo', weaponLabel, itemCount, ammoLabel, targetXPlayer.name)) targetXPlayer.showNotification(_U('received_weapon_withammo', weaponLabel, itemCount, ammoLabel, sourceXPlayer.name)) else sourceXPlayer.showNotification(_U('gave_weapon', weaponLabel, targetXPlayer.name)) targetXPlayer.showNotification(_U('received_weapon', weaponLabel, sourceXPlayer.name)) end else sourceXPlayer.showNotification(_U('gave_weapon_hasalready', targetXPlayer.name, weaponLabel)) targetXPlayer.showNotification(_U('received_weapon_hasalready', sourceXPlayer.name, weaponLabel)) end end elseif type == 'item_ammo' then if sourceXPlayer.hasWeapon(itemName) then local weaponNum, weapon = sourceXPlayer.getWeapon(itemName) if targetXPlayer.hasWeapon(itemName) then local _, weaponObject = ESX.GetWeapon(itemName) if weaponObject.ammo then local ammoLabel = weaponObject.ammo.label if weapon.ammo >= itemCount then sourceXPlayer.removeWeaponAmmo(itemName, itemCount) targetXPlayer.addWeaponAmmo(itemName, itemCount) sourceXPlayer.showNotification(_U('gave_weapon_ammo', itemCount, ammoLabel, weapon.label, targetXPlayer.name)) targetXPlayer.showNotification(_U('received_weapon_ammo', itemCount, ammoLabel, weapon.label, sourceXPlayer.name)) end end else sourceXPlayer.showNotification(_U('gave_weapon_noweapon', targetXPlayer.name)) targetXPlayer.showNotification(_U('received_weapon_noweapon', sourceXPlayer.name, weapon.label)) end end end end) RegisterNetEvent('esx:removeInventoryItem') AddEventHandler('esx:removeInventoryItem', function(type, itemName, itemCount) local playerId = source local xPlayer = ESX.GetPlayerFromId(source) if type == 'item_standard' then if itemCount == nil or itemCount < 1 then xPlayer.showNotification(_U('imp_invalid_quantity')) else local xItem = xPlayer.getInventoryItem(itemName) if (itemCount > xItem.count or xItem.count < 1) then xPlayer.showNotification(_U('imp_invalid_quantity')) else xPlayer.removeInventoryItem(itemName, itemCount) local pickupLabel = ('~y~%s~s~ [~b~%s~s~]'):format(xItem.label, itemCount) ESX.CreatePickup('item_standard', itemName, itemCount, pickupLabel, playerId) xPlayer.showNotification(_U('threw_standard', itemCount, xItem.label)) end end elseif type == 'item_account' then if itemCount == nil or itemCount < 1 then xPlayer.showNotification(_U('imp_invalid_amount')) else local account = xPlayer.getAccount(itemName) if (itemCount > account.money or account.money < 1) then xPlayer.showNotification(_U('imp_invalid_amount')) else xPlayer.removeAccountMoney(itemName, itemCount) local pickupLabel = ('~y~%s~s~ [~g~%s~s~]'):format(account.label, _U('locale_currency', ESX.Math.GroupDigits(itemCount))) ESX.CreatePickup('item_account', itemName, itemCount, pickupLabel, playerId) xPlayer.showNotification(_U('threw_account', ESX.Math.GroupDigits(itemCount), string.lower(account.label))) end end elseif type == 'item_weapon' then itemName = string.upper(itemName) if xPlayer.hasWeapon(itemName) then local _, weapon = xPlayer.getWeapon(itemName) local _, weaponObject = ESX.GetWeapon(itemName) local pickupLabel xPlayer.removeWeapon(itemName) if weaponObject.ammo and weapon.ammo > 0 then local ammoLabel = weaponObject.ammo.label pickupLabel = ('~y~%s~s~ [~g~%s~s~ %s]'):format(weapon.label, weapon.ammo, ammoLabel) xPlayer.showNotification(_U('threw_weapon_ammo', weapon.label, weapon.ammo, ammoLabel)) else pickupLabel = ('~y~%s~s~'):format(weapon.label) xPlayer.showNotification(_U('threw_weapon', weapon.label)) end ESX.CreatePickup('item_weapon', itemName, weapon.ammo, pickupLabel, playerId, weapon.components, weapon.tintIndex) end end end) RegisterNetEvent('esx:useItem') AddEventHandler('esx:useItem', function(itemName) local xPlayer = ESX.GetPlayerFromId(source) local count = xPlayer.getInventoryItem(itemName).count if count > 0 then ESX.UseItem(source, itemName) else xPlayer.showNotification(_U('act_imp')) end end) RegisterNetEvent('esx:onPickup') AddEventHandler('esx:onPickup', function(id) local pickup, xPlayer, success = ESX.Pickups[id], ESX.GetPlayerFromId(source) if pickup then if pickup.type == 'item_standard' then if xPlayer.canCarryItem(pickup.name, pickup.count) then xPlayer.addInventoryItem(pickup.name, pickup.count) success = true else xPlayer.showNotification(_U('threw_cannot_pickup')) end elseif pickup.type == 'item_account' then success = true xPlayer.addAccountMoney(pickup.name, pickup.count) elseif pickup.type == 'item_weapon' then if xPlayer.hasWeapon(pickup.name) then xPlayer.showNotification(_U('threw_weapon_already')) else success = true xPlayer.addWeapon(pickup.name, pickup.count) xPlayer.setWeaponTint(pickup.name, pickup.tintIndex) for k,v in ipairs(pickup.components) do xPlayer.addWeaponComponent(pickup.name, v) end end end if success then ESX.Pickups[id] = nil TriggerClientEvent('esx:removePickup', -1, id) end end end) ESX.RegisterServerCallback('esx:getPlayerData', function(source, cb) local xPlayer = ESX.GetPlayerFromId(source) cb({ identifier = xPlayer.identifier, accounts = xPlayer.getAccounts(), inventory = xPlayer.getInventory(), job = xPlayer.getJob(), loadout = xPlayer.getLoadout(), money = xPlayer.getMoney() }) end) ESX.RegisterServerCallback('esx:getOtherPlayerData', function(source, cb, target) local xPlayer = ESX.GetPlayerFromId(target) cb({ identifier = xPlayer.identifier, accounts = xPlayer.getAccounts(), inventory = xPlayer.getInventory(), job = xPlayer.getJob(), loadout = xPlayer.getLoadout(), money = xPlayer.getMoney() }) end) ESX.RegisterServerCallback('esx:getPlayerNames', function(source, cb, players) players[source] = nil for playerId,v in pairs(players) do local xPlayer = ESX.GetPlayerFromId(playerId) if xPlayer then players[playerId] = xPlayer.getName() else players[playerId] = nil end end cb(players) end) ESX.StartDBSync() ESX.StartPayCheck()