mirror of
https://github.com/esx-framework/esx_core.git
synced 2026-08-29 01:08:54 +00:00
Merge branch 'dev' into feature/argument-isValid-on-register-command
This commit is contained in:
@@ -157,7 +157,7 @@ end
|
||||
---@param position? string The position of the notification
|
||||
---@return nil
|
||||
function ESX.ShowNotification(message, notifyType, length, title, position)
|
||||
return IsResourceFound('esx_notify') and exports['esx_notify']:Notify(notifyType, length, message, title, position)
|
||||
return IsResourceFound('esx_notify') and exports['esx_notify']:Notify(notifyType or "info", length or 5000, message, title, position)
|
||||
end
|
||||
|
||||
function ESX.TextUI(...)
|
||||
|
||||
@@ -35,7 +35,9 @@ server_scripts {
|
||||
|
||||
'server/bridge/**/*.lua',
|
||||
'server/modules/npwd.lua',
|
||||
'server/modules/createJob.lua'
|
||||
'server/modules/createJob.lua',
|
||||
'server/migration/**/main.lua',
|
||||
'server/migration/main.lua',
|
||||
}
|
||||
|
||||
client_scripts {
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
---@field hash string|number # Component hash or identifier.
|
||||
|
||||
---@class StaticPlayer
|
||||
---@field src number # Player's server ID.
|
||||
--- Money Functions
|
||||
---@field setMoney fun(money: number) # Set player's cash balance.
|
||||
---@field getMoney fun(): number # Get player's current cash balance.
|
||||
|
||||
@@ -826,8 +826,9 @@ function Core.IsPlayerAdmin(playerSrc)
|
||||
end
|
||||
|
||||
-- Generates a unique 9-digit SSN in dashed format (XXX-XX-XXXX).
|
||||
---@param skipUniqueCheck boolean?
|
||||
---@return string
|
||||
function Core.generateSSN()
|
||||
function Core.generateSSN(skipUniqueCheck)
|
||||
local reservedSSNs = {
|
||||
["078-05-1120"] = true,
|
||||
["219-09-9999"] = true,
|
||||
@@ -860,6 +861,10 @@ function Core.generateSSN()
|
||||
goto continue
|
||||
end
|
||||
|
||||
if skipUniqueCheck then
|
||||
return candidate
|
||||
end
|
||||
|
||||
local exists = MySQL.scalar.await("SELECT 1 FROM `users` WHERE `ssn` = ? LIMIT 1", { candidate })
|
||||
|
||||
if not exists then
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
RegisterCommand("resetmigrations", function(src)
|
||||
if src > 0 then
|
||||
print("^1[ERROR]^7 This command can only be run from the server console.")
|
||||
return
|
||||
end
|
||||
|
||||
for version, _ in pairs(Core.Migrations or {}) do
|
||||
DeleteResourceKvp(("esx_migration:%s"):format(version))
|
||||
end
|
||||
print("^2[SUCCESS]^7 Reset all migrations. This will re-run all migrations on the next server start.")
|
||||
end)
|
||||
|
||||
local migrationsRan = 0
|
||||
local restartRequired = false
|
||||
|
||||
for esxVersion, migrations in pairs(Core.Migrations or {}) do
|
||||
---@cast esxVersion string
|
||||
---@cast migrations table<string, function>
|
||||
|
||||
if ESX.Table.SizeOf(migrations) > 0 then
|
||||
print(("^4[INFO]^7 Running migrations for ESX version %s"):format(esxVersion))
|
||||
|
||||
for migrationName, migration in pairs(migrations) do
|
||||
local success, result = pcall(migration)
|
||||
if not success then
|
||||
local err = result --[[@as string]]
|
||||
error(("^1[ERROR]^7 Failed migration ^4['%s.%s']^7: %s"):format(esxVersion, migrationName, err))
|
||||
end
|
||||
|
||||
local migrationRequiresRestart = result --[[@as boolean]]
|
||||
|
||||
if not restartRequired and migrationRequiresRestart then
|
||||
restartRequired = true
|
||||
end
|
||||
end
|
||||
|
||||
SetResourceKvpInt(("esx_migration:%s"):format(esxVersion), 1)
|
||||
print(("^2[SUCCESS]^7 Successfully completed migrations for ESX version %s"):format(esxVersion))
|
||||
migrationsRan += 1
|
||||
end
|
||||
end
|
||||
|
||||
while restartRequired do
|
||||
print(("^4[INFO]^7 Ran migrations for %d ESX version(s). ^1Server restart required!^7"):format(migrationsRan))
|
||||
Wait(500)
|
||||
end
|
||||
@@ -0,0 +1,70 @@
|
||||
local esxVersion = "v1.13.3"
|
||||
|
||||
Core.Migrations = Core.Migrations or {}
|
||||
Core.Migrations[esxVersion] = Core.Migrations[esxVersion] or {}
|
||||
|
||||
if GetResourceKvpInt(("esx_migration:%s"):format(esxVersion)) == 1 then
|
||||
return
|
||||
end
|
||||
|
||||
---@return boolean restartRequired
|
||||
Core.Migrations[esxVersion].ssn = function()
|
||||
print("^4[esx_migration:v.1.13.3:ssn]^7 Adding SSN column to users table.")
|
||||
local col = MySQL.scalar.await([[
|
||||
SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'users'
|
||||
AND COLUMN_NAME = 'ssn'
|
||||
]])
|
||||
|
||||
local idx = MySQL.scalar.await([[
|
||||
SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'users'
|
||||
AND INDEX_NAME = 'unique_ssn'
|
||||
]])
|
||||
|
||||
if col == 0 and idx == 0 then
|
||||
MySQL.update.await([[
|
||||
ALTER TABLE `users`
|
||||
ADD COLUMN `ssn` VARCHAR(11) NULL DEFAULT NULL AFTER `identifier`,
|
||||
ADD UNIQUE KEY `unique_ssn` (`ssn`)
|
||||
]])
|
||||
elseif col == 0 then
|
||||
MySQL.update.await("ALTER TABLE `users` ADD COLUMN `ssn` VARCHAR(11) NULL DEFAULT NULL AFTER `identifier`")
|
||||
elseif idx == 0 then
|
||||
MySQL.update.await("ALTER TABLE `users` ADD UNIQUE KEY `unique_ssn` (`ssn`)")
|
||||
end
|
||||
|
||||
|
||||
local Result = MySQL.query.await("SELECT `identifier` FROM `users` WHERE `ssn` IS NULL")
|
||||
if #Result == 0 then
|
||||
print("^4[esx_migration:v.1.13.3:ssn]^7 No users found without SSN, migration not needed.")
|
||||
return false
|
||||
end
|
||||
|
||||
print("^4[esx_migration:v.1.13.3:ssn]^7 Generating SSN for existing users.")
|
||||
local GeneratedSSNs = {}
|
||||
local Parameters = {}
|
||||
for i = 1, #Result do
|
||||
local ssn
|
||||
repeat
|
||||
ssn = Core.generateSSN(true)
|
||||
until not GeneratedSSNs[ssn]
|
||||
|
||||
GeneratedSSNs[ssn] = true
|
||||
Parameters[i] = { ssn, Result[i].identifier }
|
||||
end
|
||||
|
||||
print("^4[esx_migration:v.1.13.3:ssn]^7 Updating users with generated SSN. This may take a minute...")
|
||||
MySQL.prepare.await("UPDATE `users` SET `ssn` = ? WHERE `identifier` = ?", Parameters)
|
||||
|
||||
print("^4[esx_migration:v.1.13.3:ssn]^7 Removing SSN default value.")
|
||||
MySQL.update.await("ALTER TABLE `users` MODIFY `ssn` VARCHAR(11) NOT NULL")
|
||||
|
||||
print(("^4[esx_migration:v.1.13.3:ssn]^7 Successfully migrated %d users."):format(#Parameters))
|
||||
|
||||
return true
|
||||
end
|
||||
+169
-162
@@ -12,6 +12,8 @@ local function deleteIdentityFromDatabase(xPlayer)
|
||||
end
|
||||
end
|
||||
|
||||
---@param xPlayer StaticPlayer|xPlayer
|
||||
---@param data {firstName:string?, lastName:string?, dateOfBirth:string?, height:number?, sex:"m"|"f"?}
|
||||
function SetPlayerData(xPlayer, data)
|
||||
local name = ("%s %s"):format(data.firstName, data.lastName)
|
||||
xPlayer.setName(name)
|
||||
@@ -21,7 +23,7 @@ function SetPlayerData(xPlayer, data)
|
||||
xPlayer.set("sex", data.sex)
|
||||
xPlayer.set("height", data.height)
|
||||
|
||||
local state = Player(xPlayer.source).state
|
||||
local state = Player(xPlayer.getSource()).state
|
||||
state:set("name", name, true)
|
||||
state:set("firstName", data.firstName, true)
|
||||
state:set("lastName", data.lastName, true)
|
||||
@@ -30,12 +32,13 @@ function SetPlayerData(xPlayer, data)
|
||||
state:set("height", data.height, true)
|
||||
end
|
||||
|
||||
---@param xPlayer xPlayer
|
||||
local function deleteIdentity(xPlayer)
|
||||
if not alreadyRegistered[xPlayer.identifier] then
|
||||
return
|
||||
end
|
||||
|
||||
SetPlayerData(xPlayer, {firstName = nil, lastName = nil, dateOfBirth = nil, sex = nil, height = nil})
|
||||
SetPlayerData(xPlayer, { firstName = nil, lastName = nil, dateOfBirth = nil, sex = nil, height = nil })
|
||||
deleteIdentityFromDatabase(xPlayer)
|
||||
end
|
||||
|
||||
@@ -69,7 +72,7 @@ local function checkDOBFormat(dob)
|
||||
local minYear = currentYear - Config.MaxAge
|
||||
local maxYear = currentYear - 18
|
||||
|
||||
if year < minYear or year > maxYear then return false end
|
||||
if year < minYear or year > maxYear then return false end
|
||||
if month < 1 or month > 12 then return false end
|
||||
|
||||
-- Days in each month (starting from January.)
|
||||
@@ -124,33 +127,76 @@ local function formatName(name)
|
||||
return convertFirstLetterToUpper(loweredName)
|
||||
end
|
||||
|
||||
---@param xPlayer StaticPlayer
|
||||
local function setIdentity(xPlayer)
|
||||
if not alreadyRegistered[xPlayer.identifier] then
|
||||
return
|
||||
end
|
||||
local currentIdentity = playerIdentity[xPlayer.identifier]
|
||||
SetPlayerData(xPlayer, currentIdentity)
|
||||
local playerIdentifier = xPlayer.getIdentifier()
|
||||
if not alreadyRegistered[playerIdentifier] then
|
||||
return
|
||||
end
|
||||
local currentIdentity = playerIdentity[playerIdentifier]
|
||||
SetPlayerData(xPlayer, currentIdentity)
|
||||
|
||||
TriggerClientEvent("esx_identity:setPlayerData", xPlayer.source, currentIdentity)
|
||||
if currentIdentity.saveToDatabase then
|
||||
saveIdentityToDatabase(xPlayer.identifier, currentIdentity)
|
||||
end
|
||||
TriggerClientEvent("esx_identity:setPlayerData", xPlayer.src, currentIdentity)
|
||||
if currentIdentity.saveToDatabase then
|
||||
saveIdentityToDatabase(playerIdentifier, currentIdentity)
|
||||
end
|
||||
|
||||
playerIdentity[xPlayer.identifier] = nil
|
||||
playerIdentity[playerIdentifier] = nil
|
||||
end
|
||||
|
||||
local function checkIdentity(xPlayer)
|
||||
MySQL.single("SELECT firstname, lastname, dateofbirth, sex, height FROM users WHERE identifier = ?", { xPlayer.identifier }, function(result)
|
||||
---@param xPlayer StaticPlayer
|
||||
local function checkIdentity(xPlayer)
|
||||
local playerIdentifier = xPlayer.getIdentifier()
|
||||
MySQL.single("SELECT firstname, lastname, dateofbirth, sex, height FROM users WHERE identifier = ?", { playerIdentifier }, function(result)
|
||||
if not result then
|
||||
return TriggerClientEvent("esx_identity:showRegisterIdentity", xPlayer.src)
|
||||
end
|
||||
if not result.firstname then
|
||||
playerIdentity[playerIdentifier] = nil
|
||||
alreadyRegistered[playerIdentifier] = false
|
||||
return TriggerClientEvent("esx_identity:showRegisterIdentity", xPlayer.src)
|
||||
end
|
||||
|
||||
playerIdentity[playerIdentifier] = {
|
||||
firstName = result.firstname,
|
||||
lastName = result.lastname,
|
||||
dateOfBirth = result.dateofbirth,
|
||||
sex = result.sex,
|
||||
height = result.height,
|
||||
}
|
||||
|
||||
alreadyRegistered[playerIdentifier] = true
|
||||
setIdentity(xPlayer)
|
||||
end)
|
||||
end
|
||||
|
||||
if not multichar then
|
||||
AddEventHandler("playerConnecting", function(_, _, deferrals)
|
||||
deferrals.defer()
|
||||
local _, identifier = source, nil
|
||||
|
||||
local correctLicense, _ = pcall(function()
|
||||
identifier = ESX.GetIdentifier(source)
|
||||
end)
|
||||
|
||||
Wait(40)
|
||||
|
||||
if not identifier or not correctLicense then
|
||||
return deferrals.done(TranslateCap("no_identifier"))
|
||||
end
|
||||
MySQL.single("SELECT firstname, lastname, dateofbirth, sex, height FROM users WHERE identifier = ?", { identifier }, function(result)
|
||||
if not result then
|
||||
return TriggerClientEvent("esx_identity:showRegisterIdentity", xPlayer.source)
|
||||
playerIdentity[identifier] = nil
|
||||
alreadyRegistered[identifier] = false
|
||||
return deferrals.done()
|
||||
end
|
||||
if not result.firstname then
|
||||
playerIdentity[xPlayer.identifier] = nil
|
||||
alreadyRegistered[xPlayer.identifier] = false
|
||||
return TriggerClientEvent("esx_identity:showRegisterIdentity", xPlayer.source)
|
||||
playerIdentity[identifier] = nil
|
||||
alreadyRegistered[identifier] = false
|
||||
return deferrals.done()
|
||||
end
|
||||
|
||||
playerIdentity[xPlayer.identifier] = {
|
||||
playerIdentity[identifier] = {
|
||||
firstName = result.firstname,
|
||||
lastName = result.lastname,
|
||||
dateOfBirth = result.dateofbirth,
|
||||
@@ -158,166 +204,127 @@ end
|
||||
height = result.height,
|
||||
}
|
||||
|
||||
alreadyRegistered[xPlayer.identifier] = true
|
||||
setIdentity(xPlayer)
|
||||
alreadyRegistered[identifier] = true
|
||||
|
||||
deferrals.done()
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
if not multichar then
|
||||
AddEventHandler("playerConnecting", function(_, _, deferrals)
|
||||
deferrals.defer()
|
||||
local _, identifier = source, nil
|
||||
|
||||
local correctLicense, _ = pcall(function()
|
||||
identifier = ESX.GetIdentifier(source)
|
||||
end)
|
||||
|
||||
Wait(40)
|
||||
|
||||
if not identifier or not correctLicense then
|
||||
return deferrals.done(TranslateCap("no_identifier"))
|
||||
end
|
||||
MySQL.single("SELECT firstname, lastname, dateofbirth, sex, height FROM users WHERE identifier = ?", { identifier }, function(result)
|
||||
if not result then
|
||||
playerIdentity[identifier] = nil
|
||||
alreadyRegistered[identifier] = false
|
||||
return deferrals.done()
|
||||
end
|
||||
if not result.firstname then
|
||||
playerIdentity[identifier] = nil
|
||||
alreadyRegistered[identifier] = false
|
||||
return deferrals.done()
|
||||
end
|
||||
|
||||
playerIdentity[identifier] = {
|
||||
firstName = result.firstname,
|
||||
lastName = result.lastname,
|
||||
dateOfBirth = result.dateofbirth,
|
||||
sex = result.sex,
|
||||
height = result.height,
|
||||
}
|
||||
|
||||
alreadyRegistered[identifier] = true
|
||||
|
||||
deferrals.done()
|
||||
end)
|
||||
end)
|
||||
|
||||
AddEventHandler("onResourceStart", function(resource)
|
||||
if resource ~= GetCurrentResourceName() then
|
||||
return
|
||||
end
|
||||
Wait(300)
|
||||
|
||||
while not ESX do
|
||||
Wait(0)
|
||||
end
|
||||
|
||||
local xPlayers = ESX.GetExtendedPlayers()
|
||||
|
||||
for i = 1, #xPlayers do
|
||||
if xPlayers[i] then
|
||||
checkIdentity(xPlayers[i])
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent("esx:playerLoaded", function(_, xPlayer)
|
||||
local currentIdentity = playerIdentity[xPlayer.identifier]
|
||||
|
||||
if currentIdentity and alreadyRegistered[xPlayer.identifier] then
|
||||
SetPlayerData(xPlayer, currentIdentity)
|
||||
|
||||
TriggerClientEvent("esx_identity:setPlayerData", xPlayer.source, currentIdentity)
|
||||
if currentIdentity.saveToDatabase then
|
||||
saveIdentityToDatabase(xPlayer.identifier, currentIdentity)
|
||||
end
|
||||
|
||||
Wait(0)
|
||||
|
||||
TriggerClientEvent("esx_identity:alreadyRegistered", xPlayer.source)
|
||||
|
||||
playerIdentity[xPlayer.identifier] = nil
|
||||
else
|
||||
TriggerClientEvent("esx_identity:showRegisterIdentity", xPlayer.source)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
ESX.RegisterServerCallback("esx_identity:registerIdentity", function(source, cb, data)
|
||||
local xPlayer = ESX.Player(source)
|
||||
|
||||
if not checkNameFormat(data.firstname) then
|
||||
TriggerClientEvent("esx:showNotification", source, TranslateCap("invalid_firstname_format"), "error")
|
||||
return cb(false)
|
||||
AddEventHandler("onResourceStart", function(resource)
|
||||
if resource ~= GetCurrentResourceName() then
|
||||
return
|
||||
end
|
||||
if not checkNameFormat(data.lastname) then
|
||||
TriggerClientEvent("esx:showNotification", source, TranslateCap("invalid_lastname_format"), "error")
|
||||
return cb(false)
|
||||
end
|
||||
if not checkSexFormat(data.sex) then
|
||||
TriggerClientEvent("esx:showNotification", source, TranslateCap("invalid_sex_format"), "error")
|
||||
return cb(false)
|
||||
end
|
||||
if not checkDOBFormat(data.dateofbirth) then
|
||||
TriggerClientEvent("esx:showNotification", source, TranslateCap("invalid_dob_format"), "error")
|
||||
return cb(false)
|
||||
end
|
||||
if not checkHeightFormat(data.height) then
|
||||
TriggerClientEvent("esx:showNotification", source, TranslateCap("invalid_height_format"), "error")
|
||||
return cb(false)
|
||||
Wait(300)
|
||||
|
||||
while not ESX do
|
||||
Wait(0)
|
||||
end
|
||||
|
||||
if xPlayer then
|
||||
local identifier = xPlayer.getIdentifier()
|
||||
if alreadyRegistered[identifier] then
|
||||
xPlayer.showNotification(TranslateCap("already_registered"), "error")
|
||||
return cb(false)
|
||||
local xPlayers = ESX.ExtendedPlayers() --[=[@as StaticPlayer[]]=]
|
||||
|
||||
for i = 1, #xPlayers do
|
||||
if xPlayers[i] then
|
||||
checkIdentity(xPlayers[i])
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
playerIdentity[identifier] = {
|
||||
firstName = formatName(data.firstname),
|
||||
lastName = formatName(data.lastname),
|
||||
dateOfBirth = formatDate(data.dateofbirth),
|
||||
sex = data.sex,
|
||||
height = data.height,
|
||||
}
|
||||
|
||||
local currentIdentity = playerIdentity[identifier]
|
||||
RegisterNetEvent("esx:playerLoaded", function(_, xPlayer)
|
||||
local currentIdentity = playerIdentity[xPlayer.identifier]
|
||||
|
||||
if currentIdentity and alreadyRegistered[xPlayer.identifier] then
|
||||
SetPlayerData(xPlayer, currentIdentity)
|
||||
|
||||
TriggerClientEvent("esx_identity:setPlayerData", xPlayer.src, currentIdentity)
|
||||
saveIdentityToDatabase(identifier, currentIdentity)
|
||||
alreadyRegistered[identifier] = true
|
||||
playerIdentity[identifier] = nil
|
||||
return cb(true)
|
||||
end
|
||||
TriggerClientEvent("esx_identity:setPlayerData", xPlayer.source, currentIdentity)
|
||||
if currentIdentity.saveToDatabase then
|
||||
saveIdentityToDatabase(xPlayer.identifier, currentIdentity)
|
||||
end
|
||||
|
||||
if not multichar then
|
||||
TriggerClientEvent("esx:showNotification", source, TranslateCap("data_incorrect"), "error")
|
||||
Wait(0)
|
||||
|
||||
TriggerClientEvent("esx_identity:alreadyRegistered", xPlayer.source)
|
||||
|
||||
playerIdentity[xPlayer.identifier] = nil
|
||||
else
|
||||
TriggerClientEvent("esx_identity:showRegisterIdentity", xPlayer.source)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
ESX.RegisterServerCallback("esx_identity:registerIdentity", function(source, cb, data)
|
||||
local xPlayer = ESX.Player(source)
|
||||
|
||||
if not checkNameFormat(data.firstname) then
|
||||
TriggerClientEvent("esx:showNotification", source, TranslateCap("invalid_firstname_format"), "error")
|
||||
return cb(false)
|
||||
end
|
||||
if not checkNameFormat(data.lastname) then
|
||||
TriggerClientEvent("esx:showNotification", source, TranslateCap("invalid_lastname_format"), "error")
|
||||
return cb(false)
|
||||
end
|
||||
if not checkSexFormat(data.sex) then
|
||||
TriggerClientEvent("esx:showNotification", source, TranslateCap("invalid_sex_format"), "error")
|
||||
return cb(false)
|
||||
end
|
||||
if not checkDOBFormat(data.dateofbirth) then
|
||||
TriggerClientEvent("esx:showNotification", source, TranslateCap("invalid_dob_format"), "error")
|
||||
return cb(false)
|
||||
end
|
||||
if not checkHeightFormat(data.height) then
|
||||
TriggerClientEvent("esx:showNotification", source, TranslateCap("invalid_height_format"), "error")
|
||||
return cb(false)
|
||||
end
|
||||
|
||||
if xPlayer then
|
||||
local identifier = xPlayer.getIdentifier()
|
||||
if alreadyRegistered[identifier] then
|
||||
xPlayer.showNotification(TranslateCap("already_registered"), "error")
|
||||
return cb(false)
|
||||
end
|
||||
|
||||
local formattedFirstName = formatName(data.firstname)
|
||||
local formattedLastName = formatName(data.lastname)
|
||||
local formattedDate = formatDate(data.dateofbirth)
|
||||
|
||||
data.firstname = formattedFirstName
|
||||
data.lastname = formattedLastName
|
||||
data.dateofbirth = formattedDate
|
||||
local Identity = {
|
||||
firstName = formattedFirstName,
|
||||
lastName = formattedLastName,
|
||||
dateOfBirth = formattedDate,
|
||||
playerIdentity[identifier] = {
|
||||
firstName = formatName(data.firstname),
|
||||
lastName = formatName(data.lastname),
|
||||
dateOfBirth = formatDate(data.dateofbirth),
|
||||
sex = data.sex,
|
||||
height = data.height,
|
||||
}
|
||||
|
||||
TriggerEvent("esx_identity:completedRegistration", source, data)
|
||||
TriggerClientEvent("esx_identity:setPlayerData", source, Identity)
|
||||
cb(true)
|
||||
end)
|
||||
local currentIdentity = playerIdentity[identifier]
|
||||
|
||||
SetPlayerData(xPlayer, currentIdentity)
|
||||
|
||||
TriggerClientEvent("esx_identity:setPlayerData", xPlayer.src, currentIdentity)
|
||||
saveIdentityToDatabase(identifier, currentIdentity)
|
||||
alreadyRegistered[identifier] = true
|
||||
playerIdentity[identifier] = nil
|
||||
return cb(true)
|
||||
end
|
||||
|
||||
if not multichar then
|
||||
TriggerClientEvent("esx:showNotification", source, TranslateCap("data_incorrect"), "error")
|
||||
return cb(false)
|
||||
end
|
||||
|
||||
local formattedFirstName = formatName(data.firstname)
|
||||
local formattedLastName = formatName(data.lastname)
|
||||
local formattedDate = formatDate(data.dateofbirth)
|
||||
|
||||
data.firstname = formattedFirstName
|
||||
data.lastname = formattedLastName
|
||||
data.dateofbirth = formattedDate
|
||||
local Identity = {
|
||||
firstName = formattedFirstName,
|
||||
lastName = formattedLastName,
|
||||
dateOfBirth = formattedDate,
|
||||
sex = data.sex,
|
||||
height = data.height,
|
||||
}
|
||||
|
||||
TriggerEvent("esx_identity:completedRegistration", source, data)
|
||||
TriggerClientEvent("esx_identity:setPlayerData", source, Identity)
|
||||
cb(true)
|
||||
end)
|
||||
|
||||
if Config.EnableCommands then
|
||||
ESX.RegisterCommand("char", "user", function(xPlayer)
|
||||
|
||||
Reference in New Issue
Block a user