diff --git a/client/main.lua b/client/main.lua index 22292f4e..48285d2b 100644 --- a/client/main.lua +++ b/client/main.lua @@ -1,6 +1,4 @@ - -local isLoadoutLoaded, isPaused, isPlayerSpawned, isDead = false, false, false, false -local lastLoadout, pickups = {}, {} +local isLoadoutLoaded, isPaused, isDead, isFirstSpawn, pickups = false, false, false, true, {} RegisterNetEvent('esx:playerLoaded') AddEventHandler('esx:playerLoaded', function(xPlayer) @@ -47,33 +45,26 @@ end) AddEventHandler('playerSpawned', function() while not ESX.PlayerLoaded do - Citizen.Wait(1) + Citizen.Wait(10) end - local playerPed = PlayerPedId() + TriggerEvent('esx:restoreLoadout') - -- Restore position - if ESX.PlayerData.lastPosition then - SetEntityCoords(playerPed, ESX.PlayerData.lastPosition.x, ESX.PlayerData.lastPosition.y, ESX.PlayerData.lastPosition.z) + if isFirstSpawn then + ESX.Game.Teleport(PlayerPedId(), ESX.PlayerData.coords) + isFirstSpawn = false end - TriggerEvent('esx:restoreLoadout') -- restore loadout - - isLoadoutLoaded, isPlayerSpawned, isDead = true, true, false + isLoadoutLoaded, isDead = true, false if Config.EnablePvP then - SetCanAttackFriendly(playerPed, true, false) + SetCanAttackFriendly(PlayerPedId(), true, false) NetworkSetFriendlyFireOption(true) end end) -AddEventHandler('esx:onPlayerDeath', function() - isDead = true -end) - -AddEventHandler('skinchanger:loadDefaultModel', function() - isLoadoutLoaded = false -end) +AddEventHandler('esx:onPlayerDeath', function() isDead = true end) +AddEventHandler('skinchanger:loadDefaultModel', function() isLoadoutLoaded = false end) AddEventHandler('skinchanger:modelLoaded', function() while not ESX.PlayerLoaded do @@ -175,7 +166,6 @@ AddEventHandler('esx:addWeapon', function(weaponName, ammo) local weaponHash = GetHashKey(weaponName) GiveWeaponToPed(playerPed, weaponHash, ammo, false, false) - --AddAmmoToPed(playerPed, weaponHash, ammo) possibly not needed end) RegisterNetEvent('esx:addWeaponComponent') @@ -211,7 +201,6 @@ AddEventHandler('esx:removeWeapon', function(weaponName, ammo) end end) - RegisterNetEvent('esx:removeWeaponComponent') AddEventHandler('esx:removeWeaponComponent', function(weaponName, weaponComponent) local playerPed = PlayerPedId() @@ -221,21 +210,16 @@ AddEventHandler('esx:removeWeaponComponent', function(weaponName, weaponComponen RemoveWeaponComponentFromPed(playerPed, weaponHash, componentHash) end) --- Commands RegisterNetEvent('esx:teleport') -AddEventHandler('esx:teleport', function(pos) - pos.x = pos.x + 0.0 - pos.y = pos.y + 0.0 - pos.z = pos.z + 0.0 +AddEventHandler('esx:teleport', function(coords) + local playerPed = PlayerPedId() - RequestCollisionAtCoord(pos.x, pos.y, pos.z) + -- ensure decmial number + coords.x = coords.x + 0.0 + coords.y = coords.y + 0.0 + coords.z = coords.z + 0.0 - while not HasCollisionLoadedAroundEntity(PlayerPedId()) do - RequestCollisionAtCoord(pos.x, pos.y, pos.z) - Citizen.Wait(1) - end - - SetEntityCoords(PlayerPedId(), pos.x, pos.y, pos.z) + ESX.Game.Teleport(playerPed, coords) end) RegisterNetEvent('esx:setJob') @@ -384,7 +368,7 @@ AddEventHandler('esx:deleteVehicle', function(radius) end end) --- Pause menu disable HUD display +-- Pause menu disables HUD display if Config.EnableHud then Citizen.CreateThread(function() while true do @@ -405,12 +389,11 @@ end -- Save loadout Citizen.CreateThread(function() + local lastLoadout = {} + while true do Citizen.Wait(5000) - - local playerPed = PlayerPedId() - local loadout = {} - local loadoutChanged = false + local playerPed, loadout, loadoutChanged = PlayerPedId(), {}, false for k,v in ipairs(Config.Weapons) do local weaponName = v.name @@ -469,8 +452,8 @@ if Config.DisableWantedLevel then Citizen.CreateThread(function() while true do Citizen.Wait(0) - local playerId = PlayerId() + if GetPlayerWantedLevel(playerId) ~= 0 then SetPlayerWantedLevel(playerId, 0, false) SetPlayerWantedLevelNow(playerId, false) @@ -528,22 +511,26 @@ Citizen.CreateThread(function() end end) --- Last position +-- Update current player coords Citizen.CreateThread(function() - while true do + local previousCoords = vector3(0, 0, 0) + + -- wait for player to restore coords + while not isLoadoutLoaded do Citizen.Wait(1000) + end + + while true do + Citizen.Wait(Config.CoordsSyncInterval) local playerPed = PlayerPedId() + local playerCoords = GetEntityCoords(playerPed) + local distance = #(playerCoords - previousCoords) - if ESX.PlayerLoaded and isPlayerSpawned then - local coords = GetEntityCoords(playerPed) - - if not IsEntityDead(playerPed) then - ESX.PlayerData.lastPosition = {x = coords.x, y = coords.y, z = coords.z} - end - end - - if IsEntityDead(playerPed) and isPlayerSpawned then - isPlayerSpawned = false + if distance > 10 then + previousCoords = playerCoords + local playerHeading = ESX.Math.Round(GetEntityHeading(playerPed), 1) + local formattedCoords = {x = ESX.Math.Round(playerCoords.x, 1), y = ESX.Math.Round(playerCoords.y, 1), z = ESX.Math.Round(playerCoords.z, 1), heading = playerHeading} + TriggerServerEvent('esx:updateCoords', formattedCoords) end end end) diff --git a/config.lua b/config.lua index a332cf44..5dfee80f 100644 --- a/config.lua +++ b/config.lua @@ -10,6 +10,7 @@ Config.EnableHud = true -- enable the default hud? Display current jo Config.EnablePvP = true -- enable pvp? Config.MaxWeight = 24 -- the max inventory weight without backpack -Config.PaycheckInterval = 7 * 60000 +Config.PaycheckInterval = 7 * 60000 -- how often to recieve pay checks in milliseconds +Config.CoordsSyncInterval = 2 * 60000 -- how often to sync coords with server in milliseconds Config.EnableDebug = false diff --git a/es_extended.sql b/es_extended.sql index 52534684..4cab101a 100644 --- a/es_extended.sql +++ b/es_extended.sql @@ -6,7 +6,7 @@ ALTER TABLE `users` ADD COLUMN `job` VARCHAR(50) NULL DEFAULT 'unemployed' AFTER `skin`, ADD COLUMN `job_grade` INT NULL DEFAULT 0 AFTER `job`, ADD COLUMN `loadout` LONGTEXT NULL AFTER `job_grade`, - ADD COLUMN `position` VARCHAR(36) NULL AFTER `loadout` + ADD COLUMN `position` VARCHAR(53) NULL DEFAULT '{"x":-269.4,"y":-955.3,"z":31.2,"heading":205.8}' AFTER `loadout` ; CREATE TABLE `items` ( diff --git a/server/classes/player.lua b/server/classes/player.lua index fe1cf5e0..851bb397 100644 --- a/server/classes/player.lua +++ b/server/classes/player.lua @@ -1,4 +1,4 @@ -function CreateExtendedPlayer(player, accounts, inventory, job, loadout, name, lastPosition) +function CreateExtendedPlayer(player, accounts, inventory, job, loadout, name, coords) local self = {} self.player = player @@ -7,8 +7,8 @@ function CreateExtendedPlayer(player, accounts, inventory, job, loadout, name, l self.job = job self.loadout = loadout self.name = name - self.lastPosition = lastPosition self.maxWeight = Config.MaxWeight + self.coords = coords self.source = self.player.get('source') self.identifier = self.player.get('identifier') @@ -41,23 +41,25 @@ function CreateExtendedPlayer(player, accounts, inventory, job, loadout, name, l return self.player.get('bank') end - self.getCoords = function(vectorType) - local coords = self.player.get('coords') - coords = {x = ESX.Math.Round(coords.x, 1), y = ESX.Math.Round(coords.y, 1), z = ESX.Math.Round(coords.z, 1)} + self.setCoords = function(coords) + self.updateCoords(coords) + self.triggerEvent('esx:teleport', coords) + end - if vectorType then - return vector3(coords.x, coords.y, coords.z) + self.updateCoords = function(coords) + self.coords = {x = ESX.Math.Round(coords.x, 1), y = ESX.Math.Round(coords.y, 1), z = ESX.Math.Round(coords.z, 1), heading = ESX.Math.Round(coords.heading, 1)} + end + + self.getCoords = function(vector) + if vector then + return vector3(self.coords.x, self.coords.y, self.coords.z) else - return coords + return self.coords end end - self.setCoords = function(x, y, z) - self.player.coords = {x = x, y = y, z = z} - end - self.kick = function(reason) - self.player.kick(reason) + DropPlayer(self.source, reason) end self.addMoney = function(money) @@ -194,20 +196,6 @@ function CreateExtendedPlayer(player, accounts, inventory, job, loadout, name, l self.name = newName end - self.getLastPosition = function() - if self.lastPosition and self.lastPosition.x and self.lastPosition.y and self.lastPosition.z then - self.lastPosition.x = ESX.Math.Round(self.lastPosition.x, 1) - self.lastPosition.y = ESX.Math.Round(self.lastPosition.y, 1) - self.lastPosition.z = ESX.Math.Round(self.lastPosition.z, 1) - end - - return self.lastPosition - end - - self.setLastPosition = function(position) - self.lastPosition = position - end - self.getMissingAccounts = function(cb) MySQL.Async.fetchAll('SELECT name FROM user_accounts WHERE identifier = @identifier', { ['@identifier'] = self.getIdentifier() @@ -262,7 +250,7 @@ function CreateExtendedPlayer(player, accounts, inventory, job, loadout, name, l self.set('bank', newMoney) end - TriggerClientEvent('esx:setAccountMoney', self.source, account) + self.triggerEvent('esx:setAccountMoney', account) end end end @@ -279,7 +267,7 @@ function CreateExtendedPlayer(player, accounts, inventory, job, loadout, name, l self.set('bank', newMoney) end - TriggerClientEvent('esx:setAccountMoney', self.source, account) + self.triggerEvent('esx:setAccountMoney', account) end end end @@ -296,7 +284,7 @@ function CreateExtendedPlayer(player, accounts, inventory, job, loadout, name, l self.set('bank', newMoney) end - TriggerClientEvent('esx:setAccountMoney', self.source, account) + self.triggerEvent('esx:setAccountMoney', account) end end end @@ -319,7 +307,7 @@ function CreateExtendedPlayer(player, accounts, inventory, job, loadout, name, l item.count = newCount TriggerEvent('esx:onAddInventoryItem', self.source, item, count) - TriggerClientEvent('esx:addInventoryItem', self.source, item, count) + self.triggerEvent('esx:addInventoryItem', item, count) end end @@ -333,7 +321,7 @@ function CreateExtendedPlayer(player, accounts, inventory, job, loadout, name, l item.count = newCount TriggerEvent('esx:onRemoveInventoryItem', self.source, item, count) - TriggerClientEvent('esx:removeInventoryItem', self.source, item, count) + self.triggerEvent('esx:removeInventoryItem', item, count) end end end @@ -347,10 +335,10 @@ function CreateExtendedPlayer(player, accounts, inventory, job, loadout, name, l if oldCount > item.count then TriggerEvent('esx:onRemoveInventoryItem', self.source, item, oldCount - item.count) - TriggerClientEvent('esx:removeInventoryItem', self.source, item, oldCount - item.count) + self.triggerEvent('esx:removeInventoryItem', item, oldCount - item.count) else TriggerEvent('esx:onAddInventoryItem', self.source, item, item.count - oldCount) - TriggerClientEvent('esx:addInventoryItem', self.source, item, item.count - oldCount) + self.triggerEvent('esx:addInventoryItem', item, item.count - oldCount) end end end @@ -388,7 +376,7 @@ function CreateExtendedPlayer(player, accounts, inventory, job, loadout, name, l self.setMaxWeight = function(newWeight) self.maxWeight = newWeight - TriggerClientEvent('esx:setMaxWeight', self.source, self.maxWeight) + self.triggerEvent('esx:setMaxWeight', self.maxWeight) end self.setJob = function(job, grade) @@ -419,7 +407,7 @@ function CreateExtendedPlayer(player, accounts, inventory, job, loadout, name, l end TriggerEvent('esx:setJob', self.source, self.job, lastJob) - TriggerClientEvent('esx:setJob', self.source, self.job) + self.triggerEvent('esx:setJob', self.job) else print(('[es_extended] [^3WARNING^7] Ignoring invalid .setJob() usage for "%s"'):format(self.identifier)) end @@ -436,8 +424,8 @@ function CreateExtendedPlayer(player, accounts, inventory, job, loadout, name, l components = {} }) - TriggerClientEvent('esx:addWeapon', self.source, weaponName, ammo) - TriggerClientEvent('esx:addInventoryItem', self.source, {label = weaponLabel}, 1) + self.triggerEvent('esx:addWeapon', weaponName, ammo) + self.triggerEvent('esx:addInventoryItem', {label = weaponLabel}, 1) end end @@ -447,7 +435,7 @@ function CreateExtendedPlayer(player, accounts, inventory, job, loadout, name, l if weapon then if not self.hasWeaponComponent(weaponName, weaponComponent) then table.insert(self.loadout[loadoutNum].components, weaponComponent) - TriggerClientEvent('esx:addWeaponComponent', self.source, weaponName, weaponComponent) + self.triggerEvent('esx:addWeaponComponent', weaponName, weaponComponent) end end end @@ -457,7 +445,7 @@ function CreateExtendedPlayer(player, accounts, inventory, job, loadout, name, l if weapon then weapon.ammo = weapon.ammo + ammoCount - TriggerClientEvent('esx:setWeaponAmmo', self.source, weaponName, weapon.ammo) + self.triggerEvent('esx:setWeaponAmmo', weaponName, weapon.ammo) end end @@ -469,7 +457,7 @@ function CreateExtendedPlayer(player, accounts, inventory, job, loadout, name, l weaponLabel = v.label for k2,v2 in ipairs(v.components) do - TriggerClientEvent('esx:removeWeaponComponent', self.source, weaponName, v2) + self.triggerEvent('esx:removeWeaponComponent', weaponName, v2) end table.remove(self.loadout, k) @@ -478,8 +466,8 @@ function CreateExtendedPlayer(player, accounts, inventory, job, loadout, name, l end if weaponLabel then - TriggerClientEvent('esx:removeWeapon', self.source, weaponName, ammo) - TriggerClientEvent('esx:removeInventoryItem', self.source, {label = weaponLabel}, 1) + self.triggerEvent('esx:removeWeapon', weaponName, ammo) + self.triggerEvent('esx:removeInventoryItem', {label = weaponLabel}, 1) end end @@ -494,7 +482,7 @@ function CreateExtendedPlayer(player, accounts, inventory, job, loadout, name, l end end - TriggerClientEvent('esx:removeWeaponComponent', self.source, weaponName, weaponComponent) + self.triggerEvent('esx:removeWeaponComponent', weaponName, weaponComponent) end end @@ -503,7 +491,7 @@ function CreateExtendedPlayer(player, accounts, inventory, job, loadout, name, l if weapon then weapon.ammo = weapon.ammo - ammoCount - TriggerClientEvent('esx:setWeaponAmmo', self.source, weaponName, weapon.ammo) + self.triggerEvent('esx:setWeaponAmmo', weaponName, weapon.ammo) end end @@ -544,11 +532,11 @@ function CreateExtendedPlayer(player, accounts, inventory, job, loadout, name, l end self.showNotification = function(msg) - TriggerClientEvent('esx:showNotification', self.source, msg) + self.triggerEvent('esx:showNotification', msg) end self.showHelpNotification = function(msg) - TriggerClientEvent('esx:showHelpNotification', self.source, msg) + self.triggerEvent('esx:showHelpNotification', msg) end return self diff --git a/server/functions.lua b/server/functions.lua index 5bd0008f..2a20eeea 100644 --- a/server/functions.lua +++ b/server/functions.lua @@ -38,7 +38,6 @@ end ESX.SavePlayer = function(xPlayer, cb) local asyncTasks = {} - xPlayer.setLastPosition(xPlayer.getCoords()) -- User accounts for k,v in ipairs(xPlayer.accounts) do @@ -80,7 +79,7 @@ ESX.SavePlayer = function(xPlayer, cb) ['@job'] = xPlayer.job.name, ['@job_grade'] = xPlayer.job.grade, ['@loadout'] = json.encode(xPlayer.getLoadout()), - ['@position'] = json.encode(xPlayer.getLastPosition()), + ['@position'] = json.encode(xPlayer.getCoords()), ['@identifier'] = xPlayer.identifier }, function(rowsChanged) cb() @@ -88,7 +87,7 @@ ESX.SavePlayer = function(xPlayer, cb) end) Async.parallel(asyncTasks, function(results) - print(('[es_extended] [^2INFO^7] Saved %s'):format(xPlayer.getName())) + print(('[es_extended] [^2INFO^7] Saved player "%s^7"'):format(xPlayer.getName())) if cb ~= nil then cb() @@ -190,4 +189,4 @@ ESX.DoesJobExist = function(job, grade) end return false -end \ No newline at end of file +end diff --git a/server/main.lua b/server/main.lua index b6e1806d..49fb94fe 100644 --- a/server/main.lua +++ b/server/main.lua @@ -1,233 +1,225 @@ -AddEventHandler('es:playerLoaded', function(source, _player) - local playerId = source - local tasks = {} +AddEventHandler('es:playerLoaded', function(playerId, player) + local tasks = {} local userData = { - accounts = {}, - inventory = {}, - job = {}, - loadout = {}, - playerName = GetPlayerName(playerId), - lastPosition = nil + accounts = {}, + inventory = {}, + job = {}, + loadout = {}, + playerName = GetPlayerName(playerId), + coords = nil } - TriggerEvent('es:getPlayerFromId', playerId, function(player) - -- Update user name in DB - table.insert(tasks, function(cb) - MySQL.Async.execute('UPDATE users SET name = @name WHERE identifier = @identifier', { - ['@identifier'] = player.getIdentifier(), - ['@name'] = userData.playerName - }, function(rowsChanged) - cb() - end) + -- Update user name in DB + table.insert(tasks, function(cb) + MySQL.Async.execute('UPDATE users SET name = @name WHERE identifier = @identifier', { + ['@identifier'] = player.getIdentifier(), + ['@name'] = userData.playerName + }, function(rowsChanged) + cb() end) + end) - -- Get accounts - table.insert(tasks, function(cb) - MySQL.Async.fetchAll('SELECT name, money FROM user_accounts WHERE identifier = @identifier', { - ['@identifier'] = player.getIdentifier() - }, function(accounts) - local validAccounts = ESX.Table.Set(Config.Accounts) - for k,v in ipairs(accounts) do - if validAccounts[v.name] then - table.insert(userData.accounts, { - name = v.name, - money = v.money, - label = Config.AccountLabels[v.name] - }) - end + -- Get accounts + table.insert(tasks, function(cb) + MySQL.Async.fetchAll('SELECT name, money FROM user_accounts WHERE identifier = @identifier', { + ['@identifier'] = player.getIdentifier() + }, function(accounts) + local validAccounts = ESX.Table.Set(Config.Accounts) + for k,v in ipairs(accounts) do + if validAccounts[v.name] then + table.insert(userData.accounts, { + name = v.name, + money = v.money, + label = Config.AccountLabels[v.name] + }) end + end - cb() - end) + cb() end) + end) - -- Get inventory - table.insert(tasks, function(cb) + -- Get inventory + table.insert(tasks, function(cb) + MySQL.Async.fetchAll('SELECT item, count FROM user_inventory WHERE identifier = @identifier', { + ['@identifier'] = player.getIdentifier() + }, function(inventory) + local tasks2, foundItems = {}, {} - MySQL.Async.fetchAll('SELECT item, count FROM user_inventory WHERE identifier = @identifier', { - ['@identifier'] = player.getIdentifier() - }, function(inventory) - local tasks2, foundItems = {}, {} + for k,v in ipairs(inventory) do + local item = ESX.Items[v.item] - for k,v in ipairs(inventory) do - local item = ESX.Items[v.item] + if item then + foundItems[v.item] = true - if item then - foundItems[v.item] = true - - table.insert(userData.inventory, { - name = v.item, - count = v.count, - label = item.label, - weight = item.weight, - usable = ESX.UsableItemsCallbacks[v.item] ~= nil, - rare = item.rare, - canRemove = item.canRemove - }) - else - print(('[es_extended] [^3WARNING^7] Ignoring invalid item "%s" for "%s"'):format(v.item, player.getIdentifier())) - end + table.insert(userData.inventory, { + name = v.item, + count = v.count, + label = item.label, + weight = item.weight, + usable = ESX.UsableItemsCallbacks[v.item] ~= nil, + rare = item.rare, + canRemove = item.canRemove + }) + else + print(('[es_extended] [^3WARNING^7] Ignoring invalid item "%s" for "%s"'):format(v.item, player.getIdentifier())) end + end - for itemName,item in pairs(ESX.Items) do - if not foundItems[itemName] then - table.insert(userData.inventory, { - name = itemName, - count = 0, - label = item.label, - weight = item.weight, - usable = ESX.UsableItemsCallbacks[itemName] ~= nil, - rare = item.rare, - canRemove = item.canRemove - }) + for name,item in pairs(ESX.Items) do + if not foundItems[name] then + table.insert(userData.inventory, { + name = name, + count = 0, + label = item.label, + weight = item.weight, + usable = ESX.UsableItemsCallbacks[name] ~= nil, + rare = item.rare, + canRemove = item.canRemove + }) - local scope = function(item, identifier) - table.insert(tasks2, function(cb2) - MySQL.Async.execute('INSERT INTO user_inventory (identifier, item, count) VALUES (@identifier, @item, @count)', { - ['@identifier'] = identifier, - ['@item'] = item, - ['@count'] = 0 - }, function(rowsChanged) - cb2() - end) + local scope = function(item, identifier) + table.insert(tasks2, function(cb2) + MySQL.Async.execute('INSERT INTO user_inventory (identifier, item, count) VALUES (@identifier, @item, @count)', { + ['@identifier'] = identifier, + ['@item'] = item, + ['@count'] = 0 + }, function(rowsChanged) + cb2() end) - end + end) + end - scope(itemName, player.getIdentifier()) + scope(name, player.getIdentifier()) + end + end + + Async.parallelLimit(tasks2, 5, function(results) end) + + table.sort(userData.inventory, function(a,b) + return a.label < b.label + end) + + cb() + end) + + end) + + -- Get job and loadout + table.insert(tasks, function(cb) + + local tasks2 = {} + + -- Get job name, grade and coords + table.insert(tasks2, function(cb2) + + MySQL.Async.fetchAll('SELECT job, job_grade, loadout, position FROM users WHERE identifier = @identifier', { + ['@identifier'] = player.getIdentifier() + }, function(result) + local job, grade = result[1].job, tostring(result[1].job_grade) + + if ESX.DoesJobExist(job, grade) then + local jobObject, gradeObject = ESX.Jobs[job], ESX.Jobs[job].grades[grade] + + userData.job = {} + + 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 + else + print(('[es_extended] [^3WARNING^7] Ignoring invalid job for %s [job: %s, grade: %s]'):format(player.getIdentifier(), job, grade)) + + local job, grade = 'unemployed', '0' + local jobObject, gradeObject = ESX.Jobs[job], ESX.Jobs[job].grades[grade] + + userData.job = {} + + 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 = {} + end + + if result[1].loadout then + userData.loadout = json.decode(result[1].loadout) + + -- Compatibility with old loadouts prior to components update + for k,v in ipairs(userData.loadout) do + if v.components == nil then + v.components = {} + end end end - Async.parallelLimit(tasks2, 5, function(results) end) - - table.sort(userData.inventory, function(a,b) - return a.label < b.label - end) - - cb() + userData.coords = json.decode(result[1].position) + cb2() end) end) - -- Get job and loadout - table.insert(tasks, function(cb) + Async.series(tasks2, cb) - local tasks2 = {} + end) - -- Get job name, grade and last position - table.insert(tasks2, function(cb2) + -- Run Tasks + Async.parallel(tasks, function(results) + local xPlayer = CreateExtendedPlayer(player, userData.accounts, userData.inventory, userData.job, userData.loadout, userData.playerName, userData.coords) - MySQL.Async.fetchAll('SELECT job, job_grade, loadout, position FROM users WHERE identifier = @identifier', { - ['@identifier'] = player.getIdentifier() - }, function(result) - local job, grade = result[1].job, tostring(result[1].job_grade) - - if ESX.DoesJobExist(job, grade) then - local jobObject, gradeObject = ESX.Jobs[job], ESX.Jobs[job].grades[grade] - - userData.job = {} - - 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 ~= nil then - userData.job.skin_male = json.decode(gradeObject.skin_male) - end - - if gradeObject.skin_female ~= nil then - userData.job.skin_female = json.decode(gradeObject.skin_female) - end - else - print(('[es_extended] [^3WARNING^7] Ignoring invalid job for %s [job: %s, grade: %s]'):format(player.getIdentifier(), job, grade)) - - local job, grade = 'unemployed', '0' - local jobObject, gradeObject = ESX.Jobs[job], ESX.Jobs[job].grades[grade] - - userData.job = {} - - 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 = {} - end - - if result[1].loadout ~= nil then - userData.loadout = json.decode(result[1].loadout) - - -- Compatibility with old loadouts prior to components update - for k,v in ipairs(userData.loadout) do - if v.components == nil then - v.components = {} - end - end - end - - if result[1].position ~= nil then - userData.lastPosition = json.decode(result[1].position) - end - - cb2() - end) - - end) - - Async.series(tasks2, cb) - - end) - - -- Run Tasks - Async.parallel(tasks, function(results) - local xPlayer = CreateExtendedPlayer(player, userData.accounts, userData.inventory, userData.job, userData.loadout, userData.playerName, userData.lastPosition) - - xPlayer.getMissingAccounts(function(missingAccounts) - if #missingAccounts > 0 then - for i=1, #missingAccounts, 1 do - table.insert(xPlayer.accounts, { - name = missingAccounts[i], - money = 0, - label = Config.AccountLabels[missingAccounts[i]] - }) - end - - xPlayer.createAccounts(missingAccounts) + xPlayer.getMissingAccounts(function(missingAccounts) + if #missingAccounts > 0 then + for i=1, #missingAccounts, 1 do + table.insert(xPlayer.accounts, { + name = missingAccounts[i], + money = 0, + label = Config.AccountLabels[missingAccounts[i]] + }) end - ESX.Players[playerId] = xPlayer + xPlayer.createAccounts(missingAccounts) + end - TriggerEvent('esx:playerLoaded', playerId, xPlayer) + ESX.Players[playerId] = xPlayer - TriggerClientEvent('esx:playerLoaded', playerId, { - identifier = xPlayer.identifier, - accounts = xPlayer.getAccounts(), - inventory = xPlayer.getInventory(), - job = xPlayer.getJob(), - loadout = xPlayer.getLoadout(), - lastPosition = xPlayer.getLastPosition(), - money = xPlayer.getMoney(), - maxWeight = xPlayer.maxWeight - }) + TriggerEvent('esx:playerLoaded', playerId, xPlayer) - xPlayer.displayMoney(xPlayer.getMoney()) - TriggerClientEvent('esx:createMissingPickups', playerId, ESX.Pickups) - end) + xPlayer.triggerEvent('esx:playerLoaded', { + identifier = xPlayer.identifier, + accounts = xPlayer.getAccounts(), + coords = xPlayer.getCoords(), + inventory = xPlayer.getInventory(), + job = xPlayer.getJob(), + loadout = xPlayer.getLoadout(), + money = xPlayer.getMoney(), + maxWeight = xPlayer.maxWeight + }) + + xPlayer.displayMoney(xPlayer.getMoney()) + xPlayer.triggerEvent('esx:createMissingPickups', ESX.Pickups) end) - end) end) @@ -245,15 +237,16 @@ AddEventHandler('playerDropped', function(reason) end end) +RegisterNetEvent('esx:updateCoords') +AddEventHandler('esx:updateCoords', function(coords) local xPlayer = ESX.GetPlayerFromId(source) -RegisterServerEvent('esx:updateLastPosition') -AddEventHandler('esx:updateLastPosition', function(position) - local xPlayer = ESX.GetPlayerFromId(source) - xPlayer.setLastPosition(position) + if xPlayer then + xPlayer.updateCoords(coords) + end end) -RegisterServerEvent('esx:giveInventoryItem') +RegisterNetEvent('esx:giveInventoryItem') AddEventHandler('esx:giveInventoryItem', function(target, type, itemName, itemCount) local playerId = source local sourceXPlayer = ESX.GetPlayerFromId(playerId) @@ -306,7 +299,7 @@ AddEventHandler('esx:giveInventoryItem', function(target, type, itemName, itemCo sourceXPlayer.removeWeapon(itemName) targetXPlayer.addWeapon(itemName, itemCount) - + if itemCount > 0 then sourceXPlayer.showNotification(_U('gave_weapon_withammo', weaponLabel, itemCount, targetXPlayer.name)) targetXPlayer.showNotification(_U('received_weapon_withammo', weaponLabel, itemCount, sourceXPlayer.name)) @@ -339,7 +332,7 @@ AddEventHandler('esx:giveInventoryItem', function(target, type, itemName, itemCo end end) -RegisterServerEvent('esx:removeInventoryItem') +RegisterNetEvent('esx:removeInventoryItem') AddEventHandler('esx:removeInventoryItem', function(type, itemName, itemCount) local playerId = source local xPlayer = ESX.GetPlayerFromId(source) @@ -406,7 +399,7 @@ AddEventHandler('esx:removeInventoryItem', function(type, itemName, itemCount) end end) -RegisterServerEvent('esx:useItem') +RegisterNetEvent('esx:useItem') AddEventHandler('esx:useItem', function(itemName) local xPlayer = ESX.GetPlayerFromId(source) local count = xPlayer.getInventoryItem(itemName).count @@ -418,7 +411,7 @@ AddEventHandler('esx:useItem', function(itemName) end end) -RegisterServerEvent('esx:onPickup') +RegisterNetEvent('esx:onPickup') AddEventHandler('esx:onPickup', function(id) local pickup, xPlayer, success = ESX.Pickups[id], ESX.GetPlayerFromId(source) @@ -465,7 +458,6 @@ ESX.RegisterServerCallback('esx:getPlayerData', function(source, cb) inventory = xPlayer.getInventory(), job = xPlayer.getJob(), loadout = xPlayer.getLoadout(), - lastPosition = xPlayer.getLastPosition(), money = xPlayer.getMoney() }) end) @@ -479,7 +471,6 @@ ESX.RegisterServerCallback('esx:getOtherPlayerData', function(source, cb, target inventory = xPlayer.getInventory(), job = xPlayer.getJob(), loadout = xPlayer.getLoadout(), - lastPosition = xPlayer.getLastPosition(), money = xPlayer.getMoney() }) end)