From a4f4da621f44d630882ba23fc6074dbf5ea96d30 Mon Sep 17 00:00:00 2001 From: Linden Date: Mon, 17 May 2021 20:33:25 +1000 Subject: [PATCH 01/36] feat(legacy/multichar): Added support for esx_multicharacter; applied minor changes to spawning --- client/main.lua | 50 +++++++++---- config.lua | 1 + server/classes/player.lua | 7 +- server/main.lua | 149 ++++++++++++++++++++++++++++++-------- 4 files changed, 158 insertions(+), 49 deletions(-) diff --git a/client/main.lua b/client/main.lua index c62cab8b..3524c5cb 100644 --- a/client/main.lua +++ b/client/main.lua @@ -1,8 +1,9 @@ local isPaused, isDead, pickups = false, false, {} Citizen.CreateThread(function() - while NetworkIsPlayerActive(PlayerId()) do + while NetworkIsPlayerActive(PlayerId()) and not Config.Multichar do Citizen.Wait(5) + DoScreenFadeOut(500) TriggerServerEvent('esx:onPlayerJoined') break end @@ -42,25 +43,42 @@ AddEventHandler('esx:playerLoaded', function(playerData, isNew) }) end - exports.spawnmanager:spawnPlayer({ - x = playerData.coords.x, - y = playerData.coords.y, - z = playerData.coords.z + 0.25, - heading = playerData.coords.heading, - model = `mp_m_freemode_01`, - skipFade = false - }, function() - TriggerEvent('esx:onPlayerSpawn') - TriggerEvent('playerSpawned') -- compatibility with old scripts, will be removed soon. - TriggerEvent('esx:restoreLoadout') - + if Config.Multichar then + TriggerEvent('esx_multicharacter:SpawnCharacter', playerData.coords, isNew, playerData.skin) Citizen.Wait(4000) + else + exports.spawnmanager:spawnPlayer({ + x = playerData.coords.x, + y = playerData.coords.y, + z = playerData.coords.z + 0.25, + heading = playerData.coords.heading, + model = `mp_m_freemode_01`, + skipFade = true + }, function() + TriggerEvent('esx:onPlayerSpawn') + TriggerEvent('playerSpawned') -- compatibility with old scripts + TriggerEvent('esx:restoreLoadout') + end) + Citizen.Wait(1000) + if isNew then + if playerData.skin.sex == 0 then + TriggerEvent('skinchanger:loadDefaultModel', true) + else + TriggerEvent('skinchanger:loadDefaultModel', false) + end + elseif playerData.skin then TriggerEvent('skinchanger:loadSkin', playerData.skin) end ShutdownLoadingScreen() ShutdownLoadingScreenNui() + TriggerEvent('esx:loadingScreenOff') + DoScreenFadeIn(500) FreezeEntityPosition(ESX.PlayerData.ped, false) - StartServerSyncLoops() - end) - TriggerEvent('esx:loadingScreenOff') -- compatibility with old scripts, will be removed soon. + end + StartServerSyncLoops() +end) + +RegisterNetEvent('esx:onPlayerLogout') +AddEventHandler('esx:onPlayerLogout', function() + ESX.PlayerLoaded = false end) RegisterNetEvent('esx:setMaxWeight') diff --git a/config.lua b/config.lua index 89fbb379..194cd219 100644 --- a/config.lua +++ b/config.lua @@ -18,3 +18,4 @@ Config.EnableDefaultInventory = true -- Display the default Inventory ( F2 ) Config.EnableWantedLevel = false -- Use Normal GTA wanted Level? Config.EnablePVP = true -- Allow Player to player combat +Config.Multichar = true -- Requires esx_multicharacter diff --git a/server/classes/player.lua b/server/classes/player.lua index 64d6c1f9..148210b4 100644 --- a/server/classes/player.lua +++ b/server/classes/player.lua @@ -14,8 +14,9 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, self.variables = {} self.weight = weight self.maxWeight = Config.MaxWeight + if Config.Multichar then self.license = 'license'..string.sub(identifier, 6) else self.license = 'license:'..identifier end - ExecuteCommand(('add_principal identifier.license:%s group.%s'):format(self.identifier, self.group)) + ExecuteCommand(('add_principal identifier.%s group.%s'):format(self.license, self.group)) self.triggerEvent = function(eventName, ...) TriggerClientEvent(eventName, self.source, ...) @@ -66,9 +67,9 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, end self.setGroup = function(newGroup) - ExecuteCommand(('remove_principal identifier.license:%s group.%s'):format(self.identifier, self.group)) + ExecuteCommand(('remove_principal identifier.%s group.%s'):format(self.license, self.group)) self.group = newGroup - ExecuteCommand(('add_principal identifier.license:%s group.%s'):format(self.identifier, self.group)) + ExecuteCommand(('add_principal identifier.%s group.%s'):format(self.license, self.group)) end self.getGroup = function() diff --git a/server/main.lua b/server/main.lua index df1a7e18..b82382b3 100644 --- a/server/main.lua +++ b/server/main.lua @@ -3,47 +3,41 @@ Citizen.CreateThread(function() SetGameType('ESX Roleplay') end) +local awaitingRegistration = {} RegisterNetEvent('esx:onPlayerJoined') -AddEventHandler('esx:onPlayerJoined', function() - if not ESX.Players[source] then - onPlayerJoined(source) - end -end) +if Config.Multichar then + AddEventHandler('esx_identity:completedRegistration', function(playerId, data) + awaitingRegistration[playerId] = data + end) + AddEventHandler('esx:onPlayerJoined', function(src, char, isNew) + if not ESX.Players[src] then + onPlayerJoined(src, char, isNew) + end + end) +else + AddEventHandler('esx:onPlayerJoined', function() + if not ESX.Players[source] then + onPlayerJoined(source) + end + end) +end -function onPlayerJoined(playerId) +function onPlayerJoined(playerId, char, isNew) local identifier = ESX.GetIdentifier(playerId) + if char then identifier = 'char'..char..':'..identifier end if identifier then if ESX.GetPlayerFromIdentifier(identifier) then DropPlayer(playerId, ('there was an error loading your character!\nError code: identifier-active-ingame\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same Rockstar account.\n\nYour Rockstar identifier: %s'):format(identifier)) + elseif Config.Multichar and isNew then + createESXPlayer(identifier, playerId) else MySQL.Async.fetchScalar('SELECT 1 FROM users WHERE identifier = @identifier', { ['@identifier'] = identifier }, function(result) if result then loadESXPlayer(identifier, playerId, false) - else - local accounts = {} - - for account,money in pairs(Config.StartingAccountMoney) do - accounts[account] = money - end - - if IsPlayerAceAllowed(playerId, "command") then - print(('^2[INFO] ^0 Player ^5%s ^0Has been granted admin permissions via ^5Ace Perms.^7'):format(playerId)) - defaultGroup = "admin" - else - defaultGroup = "user" - end - - MySQL.Async.execute('INSERT INTO users (`accounts`, `identifier`, `group`) VALUES (@accounts, @identifier, @group)', { - ['@accounts'] = json.encode(accounts), - ['@identifier'] = identifier, - ['@group'] = defaultGroup - }, function(rowsChanged) - loadESXPlayer(identifier, playerId, true) - end) - end + else createESXPlayer(identifier, playerId) end end) end else @@ -51,6 +45,51 @@ function onPlayerJoined(playerId) end end +function createESXPlayer(identifier, playerId) + local accounts = {} + + for account,money in pairs(Config.StartingAccountMoney) do + accounts[account] = money + end + + if IsPlayerAceAllowed(playerId, "command") then + print(('^2[INFO] ^0 Player ^5%s ^0Has been granted admin permissions via ^5Ace Perms.^7'):format(playerId)) + defaultGroup = "admin" + else + defaultGroup = "user" + end + + if not Config.Multichar then + MySQL.Async.execute('INSERT INTO users (`accounts`, `identifier`, `group`) VALUES (@accounts, @identifier, @group)', { + ['@accounts'] = json.encode(accounts), + ['@identifier'] = identifier, + ['@group'] = defaultGroup + }, function(rowsChanged) + loadESXPlayer(identifier, playerId, true) + end) + else + local data + awaitingRegistration[playerId] = true + while true do + Citizen.Wait(250) + if awaitingRegistration[playerId] ~= true then data = awaitingRegistration[playerId] break end + end + awaitingRegistration[playerId] = nil + MySQL.Async.execute('INSERT INTO users (`accounts`, `identifier`, `group`, `firstname`, `lastname`, `dateofbirth`, `sex`, `height`) VALUES (@accounts, @identifier, @group, @firstname, @lastname, @dateofbirth, @sex, @height)', { + ['@accounts'] = json.encode(accounts), + ['@identifier'] = identifier, + ['@group'] = defaultGroup, + ['@firstname'] = data.firstname, + ['@lastname'] = data.lastname, + ['@dateofbirth'] = data.dateofbirth, + ['@sex'] = data.sex, + ['@height'] = data.height, + }, function(rowsChanged) + loadESXPlayer(identifier, playerId, true) + end) + end +end + AddEventHandler('playerConnecting', function(name, setCallback, deferrals) deferrals.defer() local playerId = source @@ -81,7 +120,13 @@ function loadESXPlayer(identifier, playerId, isNew) } table.insert(tasks, function(cb) - MySQL.Async.fetchAll('SELECT accounts, job, job_grade, `group`, loadout, position, inventory FROM users WHERE identifier = @identifier', { + local query + if Config.Multichar then + query = 'SELECT `accounts`, `job`, `job_grade`, `group`, `loadout`, `position`, `inventory`, `skin`, `firstname`, `lastname`, `dateofbirth`, `sex`, `height` FROM `users` WHERE identifier = @identifier' + else + query = 'SELECT `accounts`, `job`, `job_grade`, `group`, `loadout`, `position`, `inventory`, `skin` FROM `users` WHERE identifier = @identifier' + end + MySQL.Async.fetchAll(query, { ['@identifier'] = identifier }, function(result) local job, grade, jobObject, gradeObject = result[1].job, tostring(result[1].job_grade) @@ -203,6 +248,25 @@ function loadESXPlayer(identifier, playerId, isNew) userData.coords = {x = -269.4, y = -955.3, z = 31.2, heading = 205.8} end + -- Skin + if result[1].skin and result[1].skin ~= '' then + userData.skin = json.decode(result[1].skin) + elseif userData.sex then + if userData.sex == 'f' then userData.skin = {sex=1} else userData.skin = {sex=0} end + end + + -- Identity + if Config.Multichar then + if result[1].firstname and result[1].firstname ~= '' then + userData.firstname = result[1].firstname + userData.lastname = result[1].lastname + userData.playerName = userData.firstname..' '..userData.lastname + if result[1].dateofbirth then userData.dateofbirth = result[1].dateofbirth end + if result[1].sex then userData.sex = result[1].sex end + if result[1].height then userData.height = result[1].height end + end + end + cb() end) end) @@ -210,6 +274,15 @@ function loadESXPlayer(identifier, playerId, isNew) Async.parallel(tasks, function(results) local xPlayer = CreateExtendedPlayer(playerId, identifier, userData.group, userData.accounts, userData.inventory, userData.weight, userData.job, userData.loadout, userData.playerName, userData.coords) ESX.Players[playerId] = xPlayer + + if Config.Multichar and userData.firstname then + xPlayer.set('firstName', userData.firstname) + xPlayer.set('lastName', userData.lastname) + if userData.dateofbirth then xPlayer.set('dateofbirth', userData.dateofbirth) end + if userData.sex then xPlayer.set('sex', userData.sex) end + if userData.height then xPlayer.set('height', userData.height) end + end + TriggerEvent('esx:playerLoaded', playerId, xPlayer, isNew) xPlayer.triggerEvent('esx:playerLoaded', { @@ -220,7 +293,8 @@ function loadESXPlayer(identifier, playerId, isNew) job = xPlayer.getJob(), loadout = xPlayer.getLoadout(), maxWeight = xPlayer.getMaxWeight(), - money = xPlayer.getMoney() + money = xPlayer.getMoney(), + skin = userData.skin }, isNew) xPlayer.triggerEvent('esx:createMissingPickups', ESX.Pickups) @@ -250,6 +324,21 @@ AddEventHandler('playerDropped', function(reason) end end) +if Config.Multichar then + AddEventHandler('esx:playerLogout', function(playerId) + local xPlayer = ESX.GetPlayerFromId(playerId) + awaitingRegistration[playerId] = nil + if xPlayer then + TriggerEvent('esx:playerDropped', playerId, reason) + + ESX.SavePlayer(xPlayer, function() + ESX.Players[playerId] = nil + end) + end + TriggerClientEvent("esx:onPlayerLogout", playerId) + end) +end + RegisterNetEvent('esx:updateCoords') AddEventHandler('esx:updateCoords', function(coords) local xPlayer = ESX.GetPlayerFromId(source) From 2555ea734506c73594483388798daaa1ff088f93 Mon Sep 17 00:00:00 2001 From: Linden Date: Mon, 17 May 2021 20:50:44 +1000 Subject: [PATCH 02/36] improvement(legacy/multichar): Fade screen to black instantly --- client/main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/main.lua b/client/main.lua index 3524c5cb..76e8b784 100644 --- a/client/main.lua +++ b/client/main.lua @@ -3,7 +3,7 @@ local isPaused, isDead, pickups = false, false, {} Citizen.CreateThread(function() while NetworkIsPlayerActive(PlayerId()) and not Config.Multichar do Citizen.Wait(5) - DoScreenFadeOut(500) + DoScreenFadeOut(0) TriggerServerEvent('esx:onPlayerJoined') break end From 46f2b2c28bdae1e2a1462b55321f8fc26becb9dc Mon Sep 17 00:00:00 2001 From: Linden Date: Tue, 18 May 2021 01:00:30 +1000 Subject: [PATCH 03/36] fix(legacy/multichar): Remove HUD components if player logs out --- client/functions.lua | 10 ++++++++++ client/main.lua | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/client/functions.lua b/client/functions.lua index f90318d3..4410ba43 100644 --- a/client/functions.lua +++ b/client/functions.lua @@ -141,6 +141,16 @@ ESX.UI.HUD.RemoveElement = function(name) }) end +ESX.UI.HUD.Reset = function() + for i=1, #ESX.UI.HUD.RegisteredElements, 1 do + SendNUIMessage({ + action = 'deleteHUDElement', + name = ESX.UI.HUD.RegisteredElements[i] + }) + end + ESX.UI.HUD.RegisteredElements = {} +end + ESX.UI.HUD.UpdateElement = function(name, data) SendNUIMessage({ action = 'updateHUDElement', diff --git a/client/main.lua b/client/main.lua index 76e8b784..2a4e14a3 100644 --- a/client/main.lua +++ b/client/main.lua @@ -16,7 +16,6 @@ AddEventHandler('esx:playerLoaded', function(playerData, isNew) ESX.PlayerData = playerData ESX.PlayerData.ped = ESX.PlayerData.ped - FreezeEntityPosition(ESX.PlayerData.ped, true) -- enable PVP @@ -79,6 +78,7 @@ end) RegisterNetEvent('esx:onPlayerLogout') AddEventHandler('esx:onPlayerLogout', function() ESX.PlayerLoaded = false + if Config.EnableHud then ESX.UI.HUD.Reset() end end) RegisterNetEvent('esx:setMaxWeight') From 4bb90c2848e7b2635dd7bf18b8eb5272180cfd67 Mon Sep 17 00:00:00 2001 From: Linden Date: Tue, 18 May 2021 03:39:05 +1000 Subject: [PATCH 04/36] fix(legacy/server): Resolve an issue when setting default skin --- server/main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/main.lua b/server/main.lua index b82382b3..1500c535 100644 --- a/server/main.lua +++ b/server/main.lua @@ -251,7 +251,7 @@ function loadESXPlayer(identifier, playerId, isNew) -- Skin if result[1].skin and result[1].skin ~= '' then userData.skin = json.decode(result[1].skin) - elseif userData.sex then + else if userData.sex == 'f' then userData.skin = {sex=1} else userData.skin = {sex=0} end end From 827f2453b5c318657c26a58752f07b8949d7fa4b Mon Sep 17 00:00:00 2001 From: Linden Date: Fri, 21 May 2021 07:14:12 +1000 Subject: [PATCH 05/36] refactor(command): Remove unneeded variable --- client/functions.lua | 8 ++++---- server/commands.lua | 5 +---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/client/functions.lua b/client/functions.lua index 4410ba43..0fe22b66 100644 --- a/client/functions.lua +++ b/client/functions.lua @@ -324,7 +324,7 @@ ESX.Game.Teleport = function(entity, coords, cb) if DoesEntityExist(entity) then RequestCollisionAtCoord(vector.xyz) while not HasCollisionLoadedAroundEntity(entity) do - Wait(0) + Citizen.Wait(0) end SetEntityCoords(entity, vector.xyz, false, false, false, false) @@ -342,7 +342,7 @@ ESX.Game.SpawnObject = function(object, coords, cb, networked, dynamic) networked = networked == nil and true or false dynamic = dynamic ~= nil and true or false - CreateThread(function() + Citizen.CreateThread(function() ESX.Streaming.RequestModel(model) -- The below has to be done just for CreateObject since for some reason CreateObjects model argument is set @@ -374,7 +374,7 @@ ESX.Game.SpawnVehicle = function(vehicle, coords, heading, cb, networked) local model = (type(vehicle) == 'number' and vehicle or GetHashKey(vehicle)) local vector = type(coords) == "vector3" and coords or vec(coords.x, coords.y, coords.z) networked = networked == nil and true or false - CreateThread(function() + Citizen.CreateThread(function() ESX.Streaming.RequestModel(model) local vehicle = CreateVehicle(model, vector.xyz, heading, networked, false) @@ -391,7 +391,7 @@ ESX.Game.SpawnVehicle = function(vehicle, coords, heading, cb, networked) RequestCollisionAtCoord(vector.xyz) while not HasCollisionLoadedAroundEntity(vehicle) do - Wait(0) + Citizen.Wait(0) end if cb then diff --git a/server/commands.lua b/server/commands.lua index b3adaa9f..56874a37 100644 --- a/server/commands.lua +++ b/server/commands.lua @@ -1,4 +1,3 @@ -local crash = false ESX.RegisterCommand('setcoords', 'admin', function(xPlayer, args, showError) xPlayer.setCoords({x = args.x, y = args.y, z = args.z}) end, false, {help = _U('command_setcoords'), validate = true, arguments = { @@ -169,9 +168,7 @@ ESX.RegisterCommand('sv_restart', "admin", function(xPlayer, args, showError) DropPlayer(playerId, "Server Restart") end print('^2[INFO] ^1 Server Restarting, Please Wait :)') - crash = true - while crash do - end + while true do end end) end, true) From 819f5b4372daf8a099082e3074c67d470287509f Mon Sep 17 00:00:00 2001 From: Linden Date: Fri, 21 May 2021 21:33:11 +1000 Subject: [PATCH 06/36] fix(legacy/server): Store job data in a temporary table until grades have been applied --- server/common.lua | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/server/common.lua b/server/common.lua index bd69ae09..26373d40 100644 --- a/server/common.lua +++ b/server/common.lua @@ -30,16 +30,17 @@ MySQL.ready(function() end end) + local Jobs = {} MySQL.Async.fetchAll('SELECT * FROM jobs', {}, function(jobs) for k,v in ipairs(jobs) do - ESX.Jobs[v.name] = v - ESX.Jobs[v.name].grades = {} + Jobs[v.name] = v + Jobs[v.name].grades = {} end MySQL.Async.fetchAll('SELECT * FROM job_grades', {}, function(jobGrades) for k,v in ipairs(jobGrades) do - if ESX.Jobs[v.job_name] then - ESX.Jobs[v.job_name].grades[tostring(v.grade)] = v + if Jobs[v.job_name] then + Jobs[v.job_name].grades[tostring(v.grade)] = v else print(('[^3WARNING^7] Ignoring job grades for ^5"%s"^0 due to missing job'):format(v.job_name)) end @@ -47,10 +48,11 @@ MySQL.ready(function() for k2,v2 in pairs(ESX.Jobs) do if ESX.Table.SizeOf(v2.grades) == 0 then - ESX.Jobs[v2.name] = nil + Jobs[v2.name] = nil print(('[^3WARNING^7] Ignoring job ^5"%s"^0due to no job grades found'):format(v2.name)) end end + ESX.Jobs = Jobs end) end) From aecc6e552c92373e72ee4bb1e377adff81e09682 Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Sat, 22 May 2021 17:13:31 +1000 Subject: [PATCH 07/36] fix(server/common): Fixed check for jobs without grades --- server/common.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/common.lua b/server/common.lua index 26373d40..95a2ff6a 100644 --- a/server/common.lua +++ b/server/common.lua @@ -46,7 +46,7 @@ MySQL.ready(function() end end - for k2,v2 in pairs(ESX.Jobs) do + for k2,v2 in pairs(Jobs) do if ESX.Table.SizeOf(v2.grades) == 0 then Jobs[v2.name] = nil print(('[^3WARNING^7] Ignoring job ^5"%s"^0due to no job grades found'):format(v2.name)) From e4954e6693db8be8b09e0b4336754ab641db8232 Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Sat, 22 May 2021 18:04:01 +1000 Subject: [PATCH 08/36] improvement(server/main): Allow setting identity without using multicharacter --- server/main.lua | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/server/main.lua b/server/main.lua index 1500c535..c1f03ecc 100644 --- a/server/main.lua +++ b/server/main.lua @@ -120,13 +120,7 @@ function loadESXPlayer(identifier, playerId, isNew) } table.insert(tasks, function(cb) - local query - if Config.Multichar then - query = 'SELECT `accounts`, `job`, `job_grade`, `group`, `loadout`, `position`, `inventory`, `skin`, `firstname`, `lastname`, `dateofbirth`, `sex`, `height` FROM `users` WHERE identifier = @identifier' - else - query = 'SELECT `accounts`, `job`, `job_grade`, `group`, `loadout`, `position`, `inventory`, `skin` FROM `users` WHERE identifier = @identifier' - end - MySQL.Async.fetchAll(query, { + MySQL.Async.fetchAll('SELECT `accounts`, `job`, `job_grade`, `group`, `loadout`, `position`, `inventory`, `skin`, `firstname`, `lastname`, `dateofbirth`, `sex`, `height` FROM `users` WHERE identifier = @identifier', { ['@identifier'] = identifier }, function(result) local job, grade, jobObject, gradeObject = result[1].job, tostring(result[1].job_grade) @@ -256,15 +250,13 @@ function loadESXPlayer(identifier, playerId, isNew) end -- Identity - if Config.Multichar then - if result[1].firstname and result[1].firstname ~= '' then - userData.firstname = result[1].firstname - userData.lastname = result[1].lastname - userData.playerName = userData.firstname..' '..userData.lastname - if result[1].dateofbirth then userData.dateofbirth = result[1].dateofbirth end - if result[1].sex then userData.sex = result[1].sex end - if result[1].height then userData.height = result[1].height end - end + if result[1].firstname and result[1].firstname ~= '' then + userData.firstname = result[1].firstname + userData.lastname = result[1].lastname + userData.playerName = userData.firstname..' '..userData.lastname + if result[1].dateofbirth then userData.dateofbirth = result[1].dateofbirth end + if result[1].sex then userData.sex = result[1].sex end + if result[1].height then userData.height = result[1].height end end cb() @@ -275,7 +267,7 @@ function loadESXPlayer(identifier, playerId, isNew) local xPlayer = CreateExtendedPlayer(playerId, identifier, userData.group, userData.accounts, userData.inventory, userData.weight, userData.job, userData.loadout, userData.playerName, userData.coords) ESX.Players[playerId] = xPlayer - if Config.Multichar and userData.firstname then + if userData.firstname then xPlayer.set('firstName', userData.firstname) xPlayer.set('lastName', userData.lastname) if userData.dateofbirth then xPlayer.set('dateofbirth', userData.dateofbirth) end From b88930674cf2894d571cc7a6d023311099f65a33 Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Sun, 23 May 2021 00:05:11 +1000 Subject: [PATCH 09/36] chore(config): Set multichar to false by default --- config.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.lua b/config.lua index 194cd219..fd72412e 100644 --- a/config.lua +++ b/config.lua @@ -18,4 +18,4 @@ Config.EnableDefaultInventory = true -- Display the default Inventory ( F2 ) Config.EnableWantedLevel = false -- Use Normal GTA wanted Level? Config.EnablePVP = true -- Allow Player to player combat -Config.Multichar = true -- Requires esx_multicharacter +Config.Multichar = false -- Requires esx_multicharacter From bc13c9d34b40f9dda959111b61a3b34749cb5aa0 Mon Sep 17 00:00:00 2001 From: Linden Date: Sun, 23 May 2021 22:18:27 +1000 Subject: [PATCH 10/36] feat(server/functions): Add a function to retrieve all xPlayer data If people need to loop through xPlayers, they should use this --- server/functions.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/server/functions.lua b/server/functions.lua index 46993bde..4e8da7ea 100644 --- a/server/functions.lua +++ b/server/functions.lua @@ -227,6 +227,16 @@ ESX.GetPlayers = function() return sources end +ESX.GetExtendedPlayers = function() + local xPlayers = {} + + for k,v in pairs(ESX.Players) do + xPlayers[k] = v + end + + return xPlayers +end + ESX.GetPlayerFromId = function(source) return ESX.Players[tonumber(source)] end From 7d84e805397d4fcca911b7957f9470c8edfc762b Mon Sep 17 00:00:00 2001 From: Linden Date: Sun, 23 May 2021 23:18:16 +1000 Subject: [PATCH 11/36] chore(legacy/fxmanifest): List spawnmanager as a dependency --- fxmanifest.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fxmanifest.lua b/fxmanifest.lua index f762a77f..7d8dbe12 100644 --- a/fxmanifest.lua +++ b/fxmanifest.lua @@ -101,5 +101,6 @@ server_exports { dependencies { 'mysql-async', - 'async' -} + 'async', + 'spawnmanager', +} \ No newline at end of file From 67965129f405cd03987f87d53b82c452f7b8e36e Mon Sep 17 00:00:00 2001 From: Linden Date: Fri, 28 May 2021 05:18:19 +1000 Subject: [PATCH 12/36] fix(client/main): Move events after spawning into the spawnmanager callback; do not skip spawnmanager fade --- client/main.lua | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/client/main.lua b/client/main.lua index 2a4e14a3..263b1e79 100644 --- a/client/main.lua +++ b/client/main.lua @@ -43,8 +43,8 @@ AddEventHandler('esx:playerLoaded', function(playerData, isNew) end if Config.Multichar then - TriggerEvent('esx_multicharacter:SpawnCharacter', playerData.coords, isNew, playerData.skin) - Citizen.Wait(4000) + TriggerEvent('esx_multicharacter:SpawnCharacter', playerData.coords, isNew) + Citizen.Wait(3000) else exports.spawnmanager:spawnPlayer({ x = playerData.coords.x, @@ -52,25 +52,21 @@ AddEventHandler('esx:playerLoaded', function(playerData, isNew) z = playerData.coords.z + 0.25, heading = playerData.coords.heading, model = `mp_m_freemode_01`, - skipFade = true + skipFade = false }, function() TriggerEvent('esx:onPlayerSpawn') TriggerEvent('playerSpawned') -- compatibility with old scripts TriggerEvent('esx:restoreLoadout') + if isNew then + if playerData.skin.sex == 0 then + TriggerEvent('skinchanger:loadDefaultModel', true) + else + TriggerEvent('skinchanger:loadDefaultModel', false) + end + elseif playerData.skin then TriggerEvent('skinchanger:loadSkin', playerData.skin) end + TriggerEvent('esx:loadingScreenOff') + FreezeEntityPosition(ESX.PlayerData.ped, false) end) - Citizen.Wait(1000) - if isNew then - if playerData.skin.sex == 0 then - TriggerEvent('skinchanger:loadDefaultModel', true) - else - TriggerEvent('skinchanger:loadDefaultModel', false) - end - elseif playerData.skin then TriggerEvent('skinchanger:loadSkin', playerData.skin) end - ShutdownLoadingScreen() - ShutdownLoadingScreenNui() - TriggerEvent('esx:loadingScreenOff') - DoScreenFadeIn(500) - FreezeEntityPosition(ESX.PlayerData.ped, false) end StartServerSyncLoops() end) From 20fa7ae52f18bdd55aa69c39852dedbf2b987eb2 Mon Sep 17 00:00:00 2001 From: Linden Date: Fri, 28 May 2021 05:51:05 +1000 Subject: [PATCH 13/36] fix(client/functions): Fix DrawText3D scaling This was how the function previously worked, minus the rectangle and vector setting. --- client/functions.lua | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/client/functions.lua b/client/functions.lua index 0fe22b66..0ec7eca1 100644 --- a/client/functions.lua +++ b/client/functions.lua @@ -709,13 +709,20 @@ ESX.Game.SetVehicleProperties = function(vehicle, props) end end -ESX.Game.Utils.DrawText3D = function(coords, text, scale, font) +ESX.Game.Utils.DrawText3D = function(coords, text, size, font) local vector = type(coords) == "vector3" and coords or vec(coords.x, coords.y, coords.z) - if not scale then scale = 0.35 end - if not font then font = 4 end + local camCoords = GetGameplayCamCoords() + local distance = #(vector - camCoords) - SetTextScale(scale, scale) + if not size then size = 1 end + if not font then font = 0 end + + local scale = (size / distance) * 2 + local fov = (1 / GetGameplayCamFov()) * 100 + scale = scale * fov + + SetTextScale(0.0 * scale, 0.55 * scale) SetTextFont(font) SetTextProportional(1) SetTextColour(255, 255, 255, 215) @@ -724,8 +731,8 @@ ESX.Game.Utils.DrawText3D = function(coords, text, scale, font) AddTextComponentString(text) SetDrawOrigin(vector.xyz, 0) DrawText(0.0, 0.0) - local scaleFactor = scale / 0.35 - DrawRect(0.0, 0.0 + 0.0111 * scaleFactor, 0.017 + (string.len(text) / 370) * scaleFactor, 0.03 * scaleFactor, 0, 0, 0, 75) + local scaleFactor = scale * fov + DrawRect(0.0, 0.01 * scaleFactor, (string.len(text) / 220) * scaleFactor, 0.02 * scaleFactor, 0, 0, 0, 75) ClearDrawOrigin() end From 2cc58b6e097d2b6e8b0b09055fce0f38061b0793 Mon Sep 17 00:00:00 2001 From: Linden Date: Fri, 28 May 2021 05:54:28 +1000 Subject: [PATCH 14/36] improvement(client/hud): Setup a proper function for clearing the hud, instead of sending multiple NUI messages --- client/functions.lua | 9 +++------ html/js/app.js | 10 ++++++++++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/client/functions.lua b/client/functions.lua index 0ec7eca1..580f5fa1 100644 --- a/client/functions.lua +++ b/client/functions.lua @@ -142,12 +142,9 @@ ESX.UI.HUD.RemoveElement = function(name) end ESX.UI.HUD.Reset = function() - for i=1, #ESX.UI.HUD.RegisteredElements, 1 do - SendNUIMessage({ - action = 'deleteHUDElement', - name = ESX.UI.HUD.RegisteredElements[i] - }) - end + SendNUIMessage({ + action = 'resetHUDElements' + }) ESX.UI.HUD.RegisteredElements = {} end diff --git a/html/js/app.js b/html/js/app.js index 7705334c..dce07feb 100644 --- a/html/js/app.js +++ b/html/js/app.js @@ -41,6 +41,11 @@ ESX.refreshHUD(); }; + ESX.resetHUDElements = function () { + ESX.HUDElements = []; + ESX.refreshHUD(); + }; + ESX.refreshHUD = function () { $('#hud').html(''); @@ -95,6 +100,11 @@ break; } + case 'resetHUDElements': { + ESX.resetHUDElements(); + break; + } + case 'inventoryNotification': { ESX.inventoryNotification(data.add, data.item, data.count); } From 0bfe39d527edd78e09f791340dd0805608214b30 Mon Sep 17 00:00:00 2001 From: Linden Date: Fri, 28 May 2021 06:05:53 +1000 Subject: [PATCH 15/36] refactor(server/commands): Remove sv_restart --- server/commands.lua | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/server/commands.lua b/server/commands.lua index 56874a37..b20ccec1 100644 --- a/server/commands.lua +++ b/server/commands.lua @@ -161,17 +161,6 @@ ESX.RegisterCommand('coords', "admin", function(xPlayer, args, showError) print("".. xPlayer.getName().. ": ^5".. xPlayer.getCoords(true)) end, true) -ESX.RegisterCommand('sv_restart', "admin", function(xPlayer, args, showError) - Citizen.CreateThread(function() - ESX.SavePlayers() - for _, playerId in ipairs(GetPlayers()) do - DropPlayer(playerId, "Server Restart") - end - print('^2[INFO] ^1 Server Restarting, Please Wait :)') - while true do end - end) -end, true) - ESX.RegisterCommand('tpm', "admin", function(xPlayer, args, showError) xPlayer.triggerEvent("esx:tpm") end, true) From bccca2b8e00c8b82de1428bc795478cbd2edbaf0 Mon Sep 17 00:00:00 2001 From: Linden Date: Fri, 28 May 2021 07:45:43 +1000 Subject: [PATCH 16/36] improvement(server/main): Create a stored query for creating new users --- server/main.lua | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/server/main.lua b/server/main.lua index c1f03ecc..d4e8e8ae 100644 --- a/server/main.lua +++ b/server/main.lua @@ -1,6 +1,10 @@ +local NewPlayer = -1 Citizen.CreateThread(function() SetMapName('San Andreas') SetGameType('ESX Roleplay') + MySQL.Async.store("INSERT INTO users SET ?", function(storeId) + NewPlayer = storeId + end) end) local awaitingRegistration = {} @@ -24,7 +28,7 @@ end function onPlayerJoined(playerId, char, isNew) local identifier = ESX.GetIdentifier(playerId) - if char then identifier = 'char'..char..':'..identifier end + if char then identifier = char..':'..identifier end if identifier then if ESX.GetPlayerFromIdentifier(identifier) then @@ -60,10 +64,12 @@ function createESXPlayer(identifier, playerId) end if not Config.Multichar then - MySQL.Async.execute('INSERT INTO users (`accounts`, `identifier`, `group`) VALUES (@accounts, @identifier, @group)', { - ['@accounts'] = json.encode(accounts), - ['@identifier'] = identifier, - ['@group'] = defaultGroup + MySQL.Async.execute(NewPlayer, { + { + ['accounts'] = json.encode(accounts), + ['identifier'] = identifier, + ['group'] = defaultGroup, + } }, function(rowsChanged) loadESXPlayer(identifier, playerId, true) end) @@ -75,15 +81,17 @@ function createESXPlayer(identifier, playerId) if awaitingRegistration[playerId] ~= true then data = awaitingRegistration[playerId] break end end awaitingRegistration[playerId] = nil - MySQL.Async.execute('INSERT INTO users (`accounts`, `identifier`, `group`, `firstname`, `lastname`, `dateofbirth`, `sex`, `height`) VALUES (@accounts, @identifier, @group, @firstname, @lastname, @dateofbirth, @sex, @height)', { - ['@accounts'] = json.encode(accounts), - ['@identifier'] = identifier, - ['@group'] = defaultGroup, - ['@firstname'] = data.firstname, - ['@lastname'] = data.lastname, - ['@dateofbirth'] = data.dateofbirth, - ['@sex'] = data.sex, - ['@height'] = data.height, + MySQL.Async.execute(NewPlayer, { + { + ['accounts'] = json.encode(accounts), + ['identifier'] = identifier, + ['group'] = defaultGroup, + ['firstname'] = data.firstname, + ['lastname'] = data.lastname, + ['dateofbirth'] = data.dateofbirth, + ['sex'] = data.sex, + ['height'] = data.height, + } }, function(rowsChanged) loadESXPlayer(identifier, playerId, true) end) From ebafc8bcb41c5d23582d83fea05f8cd29c5673ae Mon Sep 17 00:00:00 2001 From: Linden Date: Fri, 28 May 2021 08:09:56 +1000 Subject: [PATCH 17/36] chore(legacy/version): Update commit version to 1.3.0 --- client/functions.lua | 3 ++- version.json | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/client/functions.lua b/client/functions.lua index 580f5fa1..c13ae23d 100644 --- a/client/functions.lua +++ b/client/functions.lua @@ -729,7 +729,8 @@ ESX.Game.Utils.DrawText3D = function(coords, text, size, font) SetDrawOrigin(vector.xyz, 0) DrawText(0.0, 0.0) local scaleFactor = scale * fov - DrawRect(0.0, 0.01 * scaleFactor, (string.len(text) / 220) * scaleFactor, 0.02 * scaleFactor, 0, 0, 0, 75) + local length = string.len(string.gsub(text, "(~[rbgypcmuosh]~)", "")) + DrawRect(0.0, 0.0 + 0.0111 * scaleFactor, 0.027 + (length / 260) * scaleFactor, 0.03 * scaleFactor, 0, 0, 0, 75) ClearDrawOrigin() end diff --git a/version.json b/version.json index 4b7d21a6..223aae62 100644 --- a/version.json +++ b/version.json @@ -1,5 +1,5 @@ { "version": "legacy", - "commit" : "1.2.0", - "changelog": "Preserve compatibility for getting hashes; store player ped and death in PlayerData; resolve typos and outdated prints" + "commit" : "1.3.0", + "changelog": "Multicharacter support; improved spawning and skin loading; minor fixes and optimisation" } From b13e44939cb5ee1f832462980b57c2120a998fdb Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Fri, 28 May 2021 11:42:22 +1000 Subject: [PATCH 18/36] improvement(server/main): Create a stored query for saving players --- server/functions.lua | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/server/functions.lua b/server/functions.lua index 4e8da7ea..be623867 100644 --- a/server/functions.lua +++ b/server/functions.lua @@ -163,19 +163,25 @@ ESX.TriggerServerCallback = function(name, requestId, source, cb, ...) end end +local savePlayers = -1 +Citizen.CreateThread(function() + savePlayers = MySQL.Sync.store("UPDATE users SET ? WHERE ?") +end) + ESX.SavePlayer = function(xPlayer, cb) local asyncTasks = {} table.insert(asyncTasks, function(cb2) - MySQL.Async.execute('UPDATE users SET accounts = @accounts, job = @job, job_grade = @job_grade, `group` = @group, loadout = @loadout, position = @position, inventory = @inventory WHERE identifier = @identifier', { - ['@accounts'] = json.encode(xPlayer.getAccounts(true)), - ['@job'] = xPlayer.job.name, - ['@job_grade'] = xPlayer.job.grade, - ['@group'] = xPlayer.getGroup(), - ['@loadout'] = json.encode(xPlayer.getLoadout(true)), - ['@position'] = json.encode(xPlayer.getCoords()), - ['@identifier'] = xPlayer.getIdentifier(), - ['@inventory'] = json.encode(xPlayer.getInventory(true)) + MySQL.Async.execute(savePlayers, { + { + ['accounts'] = json.encode(xPlayer.getAccounts(true)), + ['job'] = xPlayer.job.name, + ['job_grade'] = xPlayer.job.grade, + ['group'] = xPlayer.getGroup(), + ['loadout'] = json.encode(xPlayer.getLoadout(true)), + ['position'] = json.encode(xPlayer.getCoords()), + ['inventory'] = json.encode(xPlayer.getInventory(true)) + }, {['identifier'] = xPlayer.getIdentifier()} }, function(rowsChanged) cb2() end) From 67b2be90069e12c9683066e140fabad06f7a5ac8 Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Fri, 28 May 2021 12:48:37 +1000 Subject: [PATCH 19/36] fix(client/functions): Fixed the distance scaling for DrawRect; added rect as an option DrawRect was only added in the last month so this shouldn't affect anyone --- client/functions.lua | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/functions.lua b/client/functions.lua index c13ae23d..e8479cc5 100644 --- a/client/functions.lua +++ b/client/functions.lua @@ -706,7 +706,7 @@ ESX.Game.SetVehicleProperties = function(vehicle, props) end end -ESX.Game.Utils.DrawText3D = function(coords, text, size, font) +ESX.Game.Utils.DrawText3D = function(coords, text, size, font, rect) local vector = type(coords) == "vector3" and coords or vec(coords.x, coords.y, coords.z) local camCoords = GetGameplayCamCoords() @@ -728,9 +728,10 @@ ESX.Game.Utils.DrawText3D = function(coords, text, size, font) AddTextComponentString(text) SetDrawOrigin(vector.xyz, 0) DrawText(0.0, 0.0) - local scaleFactor = scale * fov - local length = string.len(string.gsub(text, "(~[rbgypcmuosh]~)", "")) - DrawRect(0.0, 0.0 + 0.0111 * scaleFactor, 0.027 + (length / 260) * scaleFactor, 0.03 * scaleFactor, 0, 0, 0, 75) + if rect then + local length = string.len(text:gsub('~.-~', ''))/13.5 + DrawRect(0.0, 0.18 / distance, length / distance, 0.04 * scale , 0,0,0, 75) + end ClearDrawOrigin() end From f633b98a9ca121c467e4b22e021597cb347f62de Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Sat, 29 May 2021 04:41:47 +1000 Subject: [PATCH 20/36] refactor(client/main): Cleaned up variables --- client/main.lua | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/client/main.lua b/client/main.lua index 263b1e79..278f80ac 100644 --- a/client/main.lua +++ b/client/main.lua @@ -1,4 +1,4 @@ -local isPaused, isDead, pickups = false, false, {} +local pickups = {} Citizen.CreateThread(function() while NetworkIsPlayerActive(PlayerId()) and not Config.Multichar do @@ -84,14 +84,12 @@ AddEventHandler('esx:onPlayerSpawn', function() local playerPed = PlayerPedId() if ESX.PlayerData.ped ~= playerPed then ESX.SetPlayerData('ped', playerPed) end ESX.SetPlayerData('dead', false) - isDead = false end) AddEventHandler('esx:onPlayerDeath', function() local playerPed = PlayerPedId() if ESX.PlayerData.ped ~= playerPed then ESX.SetPlayerData('ped', playerPed) end ESX.SetPlayerData('dead', true) - isDead = true end) AddEventHandler('skinchanger:modelLoaded', function() @@ -349,6 +347,7 @@ end) -- Pause menu disables HUD display if Config.EnableHud then Citizen.CreateThread(function() + local isPaused = false while true do Citizen.Wait(300) @@ -418,7 +417,7 @@ end if Config.EnableDefaultInventory then RegisterCommand('showinv', function() - if not isDead and not ESX.UI.Menu.IsOpen('default', 'es_extended', 'inventory') then + if not ESX.PlayerData.dead and not ESX.UI.Menu.IsOpen('default', 'es_extended', 'inventory') then ESX.ShowInventory() end end) From 976922f43a4bdeed6c1a94bb3948d6f4d1228b45 Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Mon, 31 May 2021 01:52:09 +1000 Subject: [PATCH 21/36] fix(client/main): Add back trigger and natives for compatibility --- client/main.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/main.lua b/client/main.lua index 278f80ac..d811dab4 100644 --- a/client/main.lua +++ b/client/main.lua @@ -54,6 +54,7 @@ AddEventHandler('esx:playerLoaded', function(playerData, isNew) model = `mp_m_freemode_01`, skipFade = false }, function() + TriggerServerEvent('esx:onPlayerSpawn') TriggerEvent('esx:onPlayerSpawn') TriggerEvent('playerSpawned') -- compatibility with old scripts TriggerEvent('esx:restoreLoadout') @@ -65,6 +66,8 @@ AddEventHandler('esx:playerLoaded', function(playerData, isNew) end elseif playerData.skin then TriggerEvent('skinchanger:loadSkin', playerData.skin) end TriggerEvent('esx:loadingScreenOff') + ShutdownLoadingScreen() + ShutdownLoadingScreenNui() FreezeEntityPosition(ESX.PlayerData.ped, false) end) end From 1b75d9cf5443b410b7fd493855490e1cc8cc7633 Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Mon, 31 May 2021 04:04:27 +1000 Subject: [PATCH 22/36] refactor(client/functions): Remove rect from DrawText3D It doesn't scale well with different fonts and text size - was only recently added and has not worked correctly --- client/functions.lua | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/client/functions.lua b/client/functions.lua index e8479cc5..80b6a34b 100644 --- a/client/functions.lua +++ b/client/functions.lua @@ -706,7 +706,7 @@ ESX.Game.SetVehicleProperties = function(vehicle, props) end end -ESX.Game.Utils.DrawText3D = function(coords, text, size, font, rect) +ESX.Game.Utils.DrawText3D = function(coords, text, size, font) local vector = type(coords) == "vector3" and coords or vec(coords.x, coords.y, coords.z) local camCoords = GetGameplayCamCoords() @@ -728,10 +728,6 @@ ESX.Game.Utils.DrawText3D = function(coords, text, size, font, rect) AddTextComponentString(text) SetDrawOrigin(vector.xyz, 0) DrawText(0.0, 0.0) - if rect then - local length = string.len(text:gsub('~.-~', ''))/13.5 - DrawRect(0.0, 0.18 / distance, length / distance, 0.04 * scale , 0,0,0, 75) - end ClearDrawOrigin() end From ee711ff9a82bd50f7140a0470ac3165c9e4fc93f Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Mon, 31 May 2021 20:52:09 +1000 Subject: [PATCH 23/36] fix(client/main): Set PlayerData.ped initial value correctly --- client/main.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/main.lua b/client/main.lua index d811dab4..45151796 100644 --- a/client/main.lua +++ b/client/main.lua @@ -9,12 +9,12 @@ Citizen.CreateThread(function() end end) - +fix(client/main): Set PlayerData.ped correctly RegisterNetEvent('esx:playerLoaded') AddEventHandler('esx:playerLoaded', function(playerData, isNew) ESX.PlayerLoaded = true ESX.PlayerData = playerData - ESX.PlayerData.ped = ESX.PlayerData.ped + ESX.PlayerData.ped = PlayerPedId() FreezeEntityPosition(ESX.PlayerData.ped, true) From a325f96c643f5294f0aaa4ee26185b40938f2550 Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Wed, 2 Jun 2021 11:56:22 +1000 Subject: [PATCH 24/36] tweak(client/main): Set PVP and hud after the player has spawned --- client/main.lua | 53 ++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/client/main.lua b/client/main.lua index 45151796..1182cd2b 100644 --- a/client/main.lua +++ b/client/main.lua @@ -9,38 +9,12 @@ Citizen.CreateThread(function() end end) -fix(client/main): Set PlayerData.ped correctly RegisterNetEvent('esx:playerLoaded') AddEventHandler('esx:playerLoaded', function(playerData, isNew) ESX.PlayerLoaded = true ESX.PlayerData = playerData - ESX.PlayerData.ped = PlayerPedId() - FreezeEntityPosition(ESX.PlayerData.ped, true) - - -- enable PVP - if Config.EnablePVP then - SetCanAttackFriendly(ESX.PlayerData.ped, true, false) - NetworkSetFriendlyFireOption(true) - end - - if Config.EnableHud then - for k,v in ipairs(playerData.accounts) do - local accountTpl = '
 {{money}}
' - ESX.UI.HUD.RegisterElement('account_' .. v.name, k, 0, accountTpl, {money = ESX.Math.GroupDigits(v.money)}) - end - - local jobTpl = '
{{job_label}} - {{grade_label}}
' - - if playerData.job.grade_label == '' or playerData.job.grade_label == playerData.job.label then - jobTpl = '
{{job_label}}
' - end - - ESX.UI.HUD.RegisterElement('job', #playerData.accounts, 0, jobTpl, { - job_label = playerData.job.label, - grade_label = playerData.job.grade_label - }) - end + FreezeEntityPosition(PlayerPedId(), true) if Config.Multichar then TriggerEvent('esx_multicharacter:SpawnCharacter', playerData.coords, isNew) @@ -71,6 +45,31 @@ AddEventHandler('esx:playerLoaded', function(playerData, isNew) FreezeEntityPosition(ESX.PlayerData.ped, false) end) end + + while ESX.PlayerData.ped == nil do Citizen.Wait(20) end + -- enable PVP + if Config.EnablePVP then + SetCanAttackFriendly(ESX.PlayerData.ped, true, false) + NetworkSetFriendlyFireOption(true) + end + + if Config.EnableHud then + for k,v in ipairs(playerData.accounts) do + local accountTpl = '
 {{money}}
' + ESX.UI.HUD.RegisterElement('account_' .. v.name, k, 0, accountTpl, {money = ESX.Math.GroupDigits(v.money)}) + end + + local jobTpl = '
{{job_label}} - {{grade_label}}
' + + if playerData.job.grade_label == '' or playerData.job.grade_label == playerData.job.label then + jobTpl = '
{{job_label}}
' + end + + ESX.UI.HUD.RegisterElement('job', #playerData.accounts, 0, jobTpl, { + job_label = playerData.job.label, + grade_label = playerData.job.grade_label + }) + end StartServerSyncLoops() end) From 74f01944f1ff82e18c964c576d59ab7d8be4cee0 Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Wed, 2 Jun 2021 12:41:46 +1000 Subject: [PATCH 25/36] improvement+fix(client/main): Save weapon ammo properly; create a timer for saving ammo instead of triggering an event every frame --- client/main.lua | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/client/main.lua b/client/main.lua index 1182cd2b..0cdcc21e 100644 --- a/client/main.lua +++ b/client/main.lua @@ -371,10 +371,17 @@ end function StartServerSyncLoops() -- keep track of ammo Citizen.CreateThread(function() + local currentWeapon = {timer=0} while ESX.PlayerLoaded do - Citizen.Wait(1000) + local sleep = 5 - local letSleep = true + if currentWeapon.timer == sleep then + local ammoCount = GetAmmoInPedWeapon(ESX.PlayerData.ped, currentWeapon.hash) + TriggerServerEvent('esx:updateWeaponAmmo', currentWeapon.name, ammoCount) + currentWeapon.timer = 0 + elseif currentWeapon.timer > sleep then + currentWeapon.timer = currentWeapon.timer - sleep + end if IsPedArmed(ESX.PlayerData.ped, 4) then if IsPedShooting(ESX.PlayerData.ped) then @@ -382,14 +389,15 @@ function StartServerSyncLoops() local weapon = ESX.GetWeaponFromHash(weaponHash) if weapon then - local ammoCount = GetAmmoInPedWeapon(ESX.PlayerData.ped, weaponHash) - TriggerServerEvent('esx:updateWeaponAmmo', weapon.name, ammoCount) + currentWeapon.name = weapon.name + currentWeapon.hash = weaponHash + currentWeapon.timer = 100 * sleep end end + else + sleep = 200 end - if letSleep then - Citizen.Wait(500) - end + Citizen.Wait(sleep) end end) From ca6462ad6a66e5429c89a598fb6de7ed45a1e67f Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Wed, 2 Jun 2021 18:08:32 +1000 Subject: [PATCH 26/36] refactor(server/functions): Return ESX.Players directly, no need to loop --- server/functions.lua | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/server/functions.lua b/server/functions.lua index be623867..1732c0c9 100644 --- a/server/functions.lua +++ b/server/functions.lua @@ -234,13 +234,7 @@ ESX.GetPlayers = function() end ESX.GetExtendedPlayers = function() - local xPlayers = {} - - for k,v in pairs(ESX.Players) do - xPlayers[k] = v - end - - return xPlayers + return ESX.Players end ESX.GetPlayerFromId = function(source) From 3ff2f4ac746a94426a8f20292ba9b345e3845e9f Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Thu, 3 Jun 2021 19:38:29 +1000 Subject: [PATCH 27/36] fix(server/commands): /clearloadout will properly wipe all weapons Loadout indexes are being updated while the loop runs causing it to break after removing a few weapons. This reverts the command to how it worked prior to ESX 1.2 --- server/commands.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/commands.lua b/server/commands.lua index b20ccec1..5b6491b0 100644 --- a/server/commands.lua +++ b/server/commands.lua @@ -117,8 +117,8 @@ end, true, {help = _U('command_clearinventory'), validate = true, arguments = { }}) ESX.RegisterCommand('clearloadout', 'admin', function(xPlayer, args, showError) - for k,v in ipairs(args.playerId.loadout) do - args.playerId.removeWeapon(v.name) + for i=#args.playerId.loadout, 1, -1 do + xPlayer.removeWeapon(args.playerId.loadout[i].name) end end, true, {help = _U('command_clearloadout'), validate = true, arguments = { {name = 'playerId', help = _U('commandgeneric_playerid'), type = 'player'} From 2ff383616f059bfc17cc1720c9d2520423920915 Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Thu, 3 Jun 2021 23:21:31 +1000 Subject: [PATCH 28/36] improvements(server/main): Set the initial value for PlayerData.dead; use MySQL.store for loadESXPlayer --- server/main.lua | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/server/main.lua b/server/main.lua index d4e8e8ae..0ba04c18 100644 --- a/server/main.lua +++ b/server/main.lua @@ -1,10 +1,13 @@ -local NewPlayer = -1 +local NewPlayer, LoadPlayer = -1, -1 Citizen.CreateThread(function() SetMapName('San Andreas') SetGameType('ESX Roleplay') MySQL.Async.store("INSERT INTO users SET ?", function(storeId) NewPlayer = storeId end) + MySQL.Async.store("SELECT `accounts`, `job`, `job_grade`, `group`, `position`, `inventory`, `skin`, `firstname`, `lastname`, `dateofbirth`, `sex`, `height`, `is_dead` FROM `users` WHERE ?? LIKE ?", function(storeId) + LoadPlayer = storeId + end) end) local awaitingRegistration = {} @@ -128,7 +131,7 @@ function loadESXPlayer(identifier, playerId, isNew) } table.insert(tasks, function(cb) - MySQL.Async.fetchAll('SELECT `accounts`, `job`, `job_grade`, `group`, `loadout`, `position`, `inventory`, `skin`, `firstname`, `lastname`, `dateofbirth`, `sex`, `height` FROM `users` WHERE identifier = @identifier', { + MySQL.Async.fetchAll(LoadPlayer, {'identifier', {identifier} ['@identifier'] = identifier }, function(result) local job, grade, jobObject, gradeObject = result[1].job, tostring(result[1].job_grade) @@ -266,6 +269,13 @@ function loadESXPlayer(identifier, playerId, isNew) if result[1].sex then userData.sex = result[1].sex end if result[1].height then userData.height = result[1].height end end + + -- Death + if result[1].is_dead and result[1].is_dead ~= '' then + userData.is_dead = result[1].is_dead + else + userData.is_dead = 0 + end cb() end) @@ -294,7 +304,8 @@ function loadESXPlayer(identifier, playerId, isNew) loadout = xPlayer.getLoadout(), maxWeight = xPlayer.getMaxWeight(), money = xPlayer.getMoney(), - skin = userData.skin + skin = userData.skin, + dead = userData.dead }, isNew) xPlayer.triggerEvent('esx:createMissingPickups', ESX.Pickups) From 7a62980c2714711af361cc14ce8b93245749a4d9 Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Thu, 3 Jun 2021 23:22:25 +1000 Subject: [PATCH 29/36] Update version.json --- version.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.json b/version.json index 223aae62..98f31f8d 100644 --- a/version.json +++ b/version.json @@ -1,5 +1,5 @@ { "version": "legacy", - "commit" : "1.3.0", - "changelog": "Multicharacter support; improved spawning and skin loading; minor fixes and optimisation" + "commit" : "1.3.1", + "changelog": "\n- Improved spawn event triggers\n- Improved support for relogging\n- Set PlayerData.dead initial value based on `is_dead` column (or 0)\n- Added a MySQL.store for the loadESXPlayer function\n- Ammo sync now waits for the player to stop shooting before sending a server event\n- /clearloadout now clears all player weapons on the first try\n- Minor fixes and optimisations" } From 64652e466192a8cec7a706e8742f3cd005022929 Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Thu, 3 Jun 2021 23:26:16 +1000 Subject: [PATCH 30/36] refactor(server/main): Do not store skin in PlayerData, send it separately --- server/main.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/main.lua b/server/main.lua index 0ba04c18..95ed6d83 100644 --- a/server/main.lua +++ b/server/main.lua @@ -304,9 +304,8 @@ function loadESXPlayer(identifier, playerId, isNew) loadout = xPlayer.getLoadout(), maxWeight = xPlayer.getMaxWeight(), money = xPlayer.getMoney(), - skin = userData.skin, dead = userData.dead - }, isNew) + }, isNew, userData.skin) xPlayer.triggerEvent('esx:createMissingPickups', ESX.Pickups) xPlayer.triggerEvent('esx:registerSuggestions', ESX.RegisteredCommands) From 25970b55ba50e969ddfe188e56342afc40ddcdf2 Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Thu, 3 Jun 2021 23:29:09 +1000 Subject: [PATCH 31/36] refactor(client/main): Skin is no longer stored in PlayerData --- client/main.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/main.lua b/client/main.lua index 0cdcc21e..4409d4a5 100644 --- a/client/main.lua +++ b/client/main.lua @@ -10,7 +10,7 @@ Citizen.CreateThread(function() end) RegisterNetEvent('esx:playerLoaded') -AddEventHandler('esx:playerLoaded', function(playerData, isNew) +AddEventHandler('esx:playerLoaded', function(playerData, isNew, skin) ESX.PlayerLoaded = true ESX.PlayerData = playerData @@ -33,12 +33,12 @@ AddEventHandler('esx:playerLoaded', function(playerData, isNew) TriggerEvent('playerSpawned') -- compatibility with old scripts TriggerEvent('esx:restoreLoadout') if isNew then - if playerData.skin.sex == 0 then + if skin.sex == 0 then TriggerEvent('skinchanger:loadDefaultModel', true) else TriggerEvent('skinchanger:loadDefaultModel', false) end - elseif playerData.skin then TriggerEvent('skinchanger:loadSkin', playerData.skin) end + elseif skin then TriggerEvent('skinchanger:loadSkin', skin) end TriggerEvent('esx:loadingScreenOff') ShutdownLoadingScreen() ShutdownLoadingScreenNui() From 30de47e09ddf22d484ebc919ed7b4ecbff792c1b Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Fri, 4 Jun 2021 01:02:24 +1000 Subject: [PATCH 32/36] fix(server/commands): Use the correct variable for clearloadout --- server/commands.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/commands.lua b/server/commands.lua index 5b6491b0..cdc668aa 100644 --- a/server/commands.lua +++ b/server/commands.lua @@ -118,7 +118,7 @@ end, true, {help = _U('command_clearinventory'), validate = true, arguments = { ESX.RegisterCommand('clearloadout', 'admin', function(xPlayer, args, showError) for i=#args.playerId.loadout, 1, -1 do - xPlayer.removeWeapon(args.playerId.loadout[i].name) + args.playerId.removeWeapon(args.playerId.loadout[i].name) end end, true, {help = _U('command_clearloadout'), validate = true, arguments = { {name = 'playerId', help = _U('commandgeneric_playerid'), type = 'player'} From 55edd9ad663d6e20c62f847a66acfc9aca68b9b2 Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Fri, 4 Jun 2021 20:55:05 +1000 Subject: [PATCH 33/36] refactor(client/functions): Don't send events for inventory and loadout - While most resources for ESX will utilise PlayerData in some way, few will require up-to-date inventory and loadout data. - Those that do use the getter or a server callback, anyway. --- client/functions.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/functions.lua b/client/functions.lua index 80b6a34b..7bc1d3b7 100644 --- a/client/functions.lua +++ b/client/functions.lua @@ -42,7 +42,9 @@ end ESX.SetPlayerData = function(key, val) ESX.PlayerData[key] = val - TriggerEvent('esx:setPlayerData', key, val) + if key ~= 'inventory' and key ~= 'loadout' then + TriggerEvent('esx:setPlayerData', key, val) + end end ESX.ShowNotification = function(msg) From 776004ff43914bcd7b64e4fb54cfd48e5de3f07b Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Sat, 5 Jun 2021 01:18:11 +1000 Subject: [PATCH 34/36] fix(server/main): Remove leftover code from updating query --- server/main.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/server/main.lua b/server/main.lua index 95ed6d83..c380e4bc 100644 --- a/server/main.lua +++ b/server/main.lua @@ -132,7 +132,6 @@ function loadESXPlayer(identifier, playerId, isNew) table.insert(tasks, function(cb) MySQL.Async.fetchAll(LoadPlayer, {'identifier', {identifier} - ['@identifier'] = identifier }, function(result) local job, grade, jobObject, gradeObject = result[1].job, tostring(result[1].job_grade) local foundAccounts, foundItems = {}, {} From 8a5765504dda7a813f39af65bc4adbc6eaff9fa5 Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Sat, 5 Jun 2021 09:12:33 +1000 Subject: [PATCH 35/36] chore(config): Add option to enable identity integration --- config.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config.lua b/config.lua index fd72412e..6d9f4203 100644 --- a/config.lua +++ b/config.lua @@ -18,4 +18,5 @@ Config.EnableDefaultInventory = true -- Display the default Inventory ( F2 ) Config.EnableWantedLevel = false -- Use Normal GTA wanted Level? Config.EnablePVP = true -- Allow Player to player combat -Config.Multichar = false -- Requires esx_multicharacter +Config.Multichar = false -- Enable support for esx_multicharacter +Config.Identity = true -- Select a characters identity data before they have loaded in (this happens by default with multichar) From 150db2feacf7284342dfd8c769c6c5a92ca11e13 Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Sat, 5 Jun 2021 09:13:45 +1000 Subject: [PATCH 36/36] refactor(server/main): Require identity or multichar config options to load player data; always set the initial death value to 0 --- server/main.lua | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/server/main.lua b/server/main.lua index c380e4bc..924b5f25 100644 --- a/server/main.lua +++ b/server/main.lua @@ -5,7 +5,11 @@ Citizen.CreateThread(function() MySQL.Async.store("INSERT INTO users SET ?", function(storeId) NewPlayer = storeId end) - MySQL.Async.store("SELECT `accounts`, `job`, `job_grade`, `group`, `position`, `inventory`, `skin`, `firstname`, `lastname`, `dateofbirth`, `sex`, `height`, `is_dead` FROM `users` WHERE ?? LIKE ?", function(storeId) + + local query = '`accounts`, `job`, `job_grade`, `group`, `position`, `inventory`, `skin`' + if Config.Multichar or Config.Identity then query = query..', `firstname`, `lastname`, `dateofbirth`, `sex`, `height`' end + + MySQL.Async.store("SELECT "..query.." FROM `users` WHERE ?? LIKE ?", function(storeId) LoadPlayer = storeId end) end) @@ -268,13 +272,6 @@ function loadESXPlayer(identifier, playerId, isNew) if result[1].sex then userData.sex = result[1].sex end if result[1].height then userData.height = result[1].height end end - - -- Death - if result[1].is_dead and result[1].is_dead ~= '' then - userData.is_dead = result[1].is_dead - else - userData.is_dead = 0 - end cb() end) @@ -303,7 +300,7 @@ function loadESXPlayer(identifier, playerId, isNew) loadout = xPlayer.getLoadout(), maxWeight = xPlayer.getMaxWeight(), money = xPlayer.getMoney(), - dead = userData.dead + dead = 0 }, isNew, userData.skin) xPlayer.triggerEvent('esx:createMissingPickups', ESX.Pickups) @@ -623,7 +620,7 @@ Citizen.CreateThread( ([[ ^1---------------------------------------------------------------------- -^1URGENT: YOUR ES-EXTENDED IS OUTDATED! +^1URGENT: YOUR ES_EXTENDED IS OUTDATED! ^1COMMIT UPDATE: ^5%s AVAILABLE ^1DOWNLOAD:^5 https://github.com/esx-framework/es_extended/tree/legacy ^1CHANGELOG:^5 %s @@ -638,7 +635,7 @@ Citizen.CreateThread( ([[ ^8------------------------------------------------------- -^2Your Es-extended is the latest version! +^2Your es_extended is the latest version! ^5Version:^0 %s ^5COMMIT:^0 %s ^5CHANGELOG:^0 %s @@ -654,7 +651,7 @@ Citizen.CreateThread( print( ([[ ^1---------------------------------------------------------------------- -^1URGENT: YOUR ES-EXTENDED IS OUTDATATED!!! +^1URGENT: YOUR ES_EXTENDED IS OUTDATATED!!! ^1COMMIT UPDATE: ^5%s AVAILABLE ^1DOWNLOAD:^5 https://github.com/esx-framework/es_extended/tree/legacy ^1CHANGELOG:^5 %s @@ -666,7 +663,7 @@ Citizen.CreateThread( ) end else - print('[^1ERROR^0] Es-Extended unable to check version!') + print('[^1ERROR^0] es_extended unable to check version!') end end, 'GET'