diff --git a/README.md b/README.md index cec80b0c..2d466b10 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,12 @@ start esx_identity - If you are using esx_policejob or esx_society, you need to enable the following in the scripts' `config.lua`: ```Config.EnableESXIdentity = true``` +### Commands +``` +/char +/chardel +``` + # Legal ### License esx_identity - rp characters diff --git a/client/main.lua b/client/main.lua new file mode 100644 index 00000000..238a485e --- /dev/null +++ b/client/main.lua @@ -0,0 +1,95 @@ +ESX = nil +local loadingScreenFinished = false + +Citizen.CreateThread(function() + while ESX == nil do + TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end) + Citizen.Wait(0) + end +end) + +RegisterNetEvent('esx_identity:alreadyRegistered') +AddEventHandler('esx_identity:alreadyRegistered', function() + while not loadingScreenFinished do + Citizen.Wait(100) + end + + TriggerEvent('esx_skin:playerRegistered') +end) + +AddEventHandler('esx:loadingScreenOff', function() + loadingScreenFinished = true +end) + +if not Config.UseDeferrals then + local guiEnabled, isDead = false, false + + AddEventHandler('esx:onPlayerDeath', function(data) + isDead = true + end) + + AddEventHandler('esx:onPlayerSpawn', function(spawn) + isDead = false + end) + + function EnableGui(state) + SetNuiFocus(state, state) + guiEnabled = state + + SendNUIMessage({ + type = "enableui", + enable = state + }) + end + + RegisterNetEvent('esx_identity:showRegisterIdentity') + AddEventHandler('esx_identity:showRegisterIdentity', function() + TriggerEvent('esx_skin:resetFirstSpawn') + + if not isDead then + EnableGui(true) + end + end) + + RegisterNUICallback('register', function(data, cb) + ESX.TriggerServerCallback('esx_identity:registerIdentity', function(callback) + if callback then + ESX.ShowNotification(_U('thank_you_for_registering')) + EnableGui(false) + TriggerEvent('esx_skin:playerRegistered') + else + ESX.ShowNotification(_U('registration_error')) + end + end, data) + end) + + Citizen.CreateThread(function() + while true do + Citizen.Wait(0) + + if guiEnabled then + DisableControlAction(0, 1, true) -- LookLeftRight + DisableControlAction(0, 2, true) -- LookUpDown + DisableControlAction(0, 106, true) -- VehicleMouseControlOverride + DisableControlAction(0, 142, true) -- MeleeAttackAlternate + DisableControlAction(0, 30, true) -- MoveLeftRight + DisableControlAction(0, 31, true) -- MoveUpDown + DisableControlAction(0, 21, true) -- disable sprint + DisableControlAction(0, 24, true) -- disable attack + DisableControlAction(0, 25, true) -- disable aim + DisableControlAction(0, 47, true) -- disable weapon + DisableControlAction(0, 58, true) -- disable weapon + DisableControlAction(0, 263, true) -- disable melee + DisableControlAction(0, 264, true) -- disable melee + DisableControlAction(0, 257, true) -- disable melee + DisableControlAction(0, 140, true) -- disable melee + DisableControlAction(0, 141, true) -- disable melee + DisableControlAction(0, 143, true) -- disable melee + DisableControlAction(0, 75, true) -- disable exit vehicle + DisableControlAction(27, 75, true) -- disable exit vehicle + else + Citizen.Wait(500) + end + end + end) +end diff --git a/config.lua b/config.lua index 96b0472d..3d37568a 100644 --- a/config.lua +++ b/config.lua @@ -1,7 +1,12 @@ Config = {} Config.Locale = 'en' -Config.MinHeight = 24 -- Minimum Height -Config.MaxHeight = 96 -- Maximum Height -Config.HighestYear = 2020 -- The highest year that can be used in date of birth -Config.LowestYear = 1900 -- The lowest year that can be used in date of birth -Config.MaxNameLength = 15 -- You must also change the SQL structure for 'firstname' and 'lastname' in the `users` table \ No newline at end of file +Config.EnableCommands = true +Config.UseSteamID = false +Config.UseDeferrals = true +Config.MaxNameLength = 16 +Config.MinHeight = 48 +Config.MaxHeight = 96 +Config.LowestYear = 1900 +Config.HighestYear = 2020 + +Config.EnableDebugging = false \ No newline at end of file diff --git a/esx_identity.sql b/esx_identity.sql index 56b88ae4..c9e411d5 100644 --- a/esx_identity.sql +++ b/esx_identity.sql @@ -1,9 +1,9 @@ USE `es_extended`; ALTER TABLE `users` - ADD COLUMN `firstname` VARCHAR(15) NULL DEFAULT NULL, - ADD COLUMN `lastname` VARCHAR(15) NULL DEFAULT NULL, + ADD COLUMN `firstname` VARCHAR(16) NULL DEFAULT NULL, + ADD COLUMN `lastname` VARCHAR(16) NULL DEFAULT NULL, ADD COLUMN `dateofbirth` VARCHAR(10) NULL DEFAULT NULL, ADD COLUMN `sex` VARCHAR(1) NULL DEFAULT NULL, - ADD COLUMN `height` VARCHAR(3) NULL DEFAULT NULL + ADD COLUMN `height` INT(2) NULL DEFAULT NULL ; \ No newline at end of file diff --git a/fxmanifest.lua b/fxmanifest.lua index 4917c8cb..09853b6a 100644 --- a/fxmanifest.lua +++ b/fxmanifest.lua @@ -4,7 +4,7 @@ game 'gta5' description 'ESX Identity' -version '1.3.0' +version '1.4.0' server_scripts { '@es_extended/locale.lua', @@ -15,4 +15,21 @@ server_scripts { 'server/main.lua' } +client_scripts { + '@es_extended/locale.lua', + 'locales/en.lua', + 'locales/cs.lua', + 'config.lua', + 'client/main.lua' +} + +ui_page 'html/index.html' + +files { + 'html/index.html', + 'html/js/script.js', + 'html/css/style.css', + 'html/img/esx_identity.png' +} + dependency 'es_extended' diff --git a/html/css/style.css b/html/css/style.css new file mode 100644 index 00000000..eaa2535e --- /dev/null +++ b/html/css/style.css @@ -0,0 +1,127 @@ +body { + font-family: sans-serif; + overflow: hidden; + display: none; + color: #000000; +} + +.dialog { + width: 332px; + opacity : 0.95; + position : absolute; + margin-left: auto; + margin-right: auto; + top : 30.0%; + padding: 10px; + left : 50%; /* à 50%/50% du parent référent */ + transform : translate(-50%); /* décalage de 50% de sa propre taille */ + background-color: #B7B7B7; + border-radius : 4px; + box-shadow: 0px 0px 50px 0px #000; + border-left:5px solid #000; + border:1px inset; + margin:5px; + margin-bottom:20px; + color: #000000; +} + +input { + width: 100%; + padding: 10px; + text-align:left; + color: #000000; +} + +::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */ + color: black; + opacity: 1; /* Firefox */ +} + +.radio-toolbar input[type="radio"] { + opacity: 0; + position: absolute; + width: 36%; +} + +.radio-toolbar label { + display: inline-block; + margin-top: 5px; + background-color: #ddd; + padding: 10px 20px; + font-family: sans-serif, Arial; + font-size: 16px; + color: #000000; + border: 2px solid #444; + border-radius: 4px; + width: 36%; +} + +.radio-toolbar input[type="radio"]:checked + label { + width: 36%; + background-color:#3399FF; + border-color: #0033FF; + color: #000000; +} + +.radio-toolbar input[type="radio"]:focus + label { + border: 2px solid #444; + width: 36%; + color: #000000; +} + +.radio-toolbar label:hover { + background-color: #dfd; + width: 36%; + color: #000000; +} + +button { + display: block; + margin-top: 5px; + padding: 10px; + background-color: #373737; + border: 2px solid #444; + color: #FFFFFF; + width: 100%; +} + +h1 { + display: block; + margin-top: 5px; + margin-right: 5px; + padding: 10px; + background-color: #506be6; + color: #000000; + width: 93%; + text-align: center; +} + +.range-wrap { + position: relative; + margin: 0 auto 3rem; +} + +.range { + width: 100%; +} + +.bubble { + background: #3399FF; + color: black; + padding: 4px 12px; + position: absolute; + border-radius: 4px; + left: 50%; + transform: translateX(-50%); +} + +.bubble::after { + content: ""; + position: absolute; + width: 2px; + height: 2px; + background: #3399FF; + color: black; + top: -1px; + left: 50%; +} \ No newline at end of file diff --git a/html/img/esx_identity.png b/html/img/esx_identity.png new file mode 100644 index 00000000..dcfc17c4 Binary files /dev/null and b/html/img/esx_identity.png differ diff --git a/html/index.html b/html/index.html new file mode 100644 index 00000000..182d344a --- /dev/null +++ b/html/index.html @@ -0,0 +1,163 @@ + + + + + + + + + +
+ +
+
+
+
+
+
+ + + + + +
+
+
+ + +
+ +
+
If the submit button doesn't work, please ensure that you've entered the fields correctly.
+
+ + + + diff --git a/html/index_heightslider.html b/html/index_heightslider.html new file mode 100644 index 00000000..182d344a --- /dev/null +++ b/html/index_heightslider.html @@ -0,0 +1,163 @@ + + + + + + + + + +
+ +
+
+
+
+
+
+ + + + + +
+
+
+ + +
+ +
+
If the submit button doesn't work, please ensure that you've entered the fields correctly.
+
+ + + + diff --git a/html/index_heighttext.html b/html/index_heighttext.html new file mode 100644 index 00000000..13896e58 --- /dev/null +++ b/html/index_heighttext.html @@ -0,0 +1,150 @@ + + + + + + + + + +
+ +
+
+
+
+
+
+
+ + + + + +
+
+ +
+
If the submit button doesn't work, please ensure that you've entered the fields correctly.
+
+ + + + diff --git a/html/index_options/index_heightslider.html b/html/index_options/index_heightslider.html new file mode 100644 index 00000000..182d344a --- /dev/null +++ b/html/index_options/index_heightslider.html @@ -0,0 +1,163 @@ + + + + + + + + + +
+ +
+
+
+
+
+
+ + + + + +
+
+
+ + +
+ +
+
If the submit button doesn't work, please ensure that you've entered the fields correctly.
+
+ + + + diff --git a/html/index_options/index_heighttext.html b/html/index_options/index_heighttext.html new file mode 100644 index 00000000..13896e58 --- /dev/null +++ b/html/index_options/index_heighttext.html @@ -0,0 +1,150 @@ + + + + + + + + + +
+ +
+
+
+
+
+
+
+ + + + + +
+
+ +
+
If the submit button doesn't work, please ensure that you've entered the fields correctly.
+
+ + + + diff --git a/html/js/script.js b/html/js/script.js new file mode 100644 index 00000000..a6a5afce --- /dev/null +++ b/html/js/script.js @@ -0,0 +1,34 @@ +$(function() { + window.addEventListener('message', function(event) { + if (event.data.type == "enableui") { + document.body.style.display = event.data.enable ? "block" : "none"; + } + }); + + $("#register").submit(function(event) { + event.preventDefault(); // Prevent form from submitting + + // Verify date + var date = $("#dateofbirth").val(); + var dateCheck = new Date($("#dateofbirth").val()); + + if (dateCheck == "Invalid Date") { + date == "invalid"; + } + else { + const ye = new Intl.DateTimeFormat('en', { year: 'numeric' }).format(dateCheck) + const mo = new Intl.DateTimeFormat('en', { month: '2-digit' }).format(dateCheck) + const da = new Intl.DateTimeFormat('en', { day: '2-digit' }).format(dateCheck) + + var formattedDate = `${mo}/${da}/${ye}`; + + $.post('http://esx_identity/register', JSON.stringify({ + firstname: $("#firstname").val(), + lastname: $("#lastname").val(), + dateofbirth: formattedDate, + sex: $("input[type='radio'][name='sex']:checked").val(), + height: $("#height").val() + })); + } + }); +}); diff --git a/html/localization/cs_index(outofdate).html b/html/localization/cs_index(outofdate).html new file mode 100644 index 00000000..1dd357a9 --- /dev/null +++ b/html/localization/cs_index(outofdate).html @@ -0,0 +1,22 @@ + + + + + + + +
+
+

Register

+
+
+
+
+ Male + Female
+ +
+
+ + + diff --git a/html/localization/fi_index(outofdate).html b/html/localization/fi_index(outofdate).html new file mode 100644 index 00000000..87ca250a --- /dev/null +++ b/html/localization/fi_index(outofdate).html @@ -0,0 +1,22 @@ + + + + + + + +
+
+

Rekistöröinti

+
+
+
+
+ Mies + Nainen
+ +
+
+ + + diff --git a/html/localization/ko_index(outofdate).html b/html/localization/ko_index(outofdate).html new file mode 100644 index 00000000..c04fe9b7 --- /dev/null +++ b/html/localization/ko_index(outofdate).html @@ -0,0 +1,22 @@ + + + + + + + +
+
+

등록

+
+
+
+
+ 남자 + 여자
+ +
+
+ + + \ No newline at end of file diff --git a/html/localization/sv_index(outofdate).html b/html/localization/sv_index(outofdate).html new file mode 100644 index 00000000..7706c17b --- /dev/null +++ b/html/localization/sv_index(outofdate).html @@ -0,0 +1,22 @@ + + + + + + + +
+
+

Registrera

+
+
+
+
+ Man + Kvinna
+ +
+
+ + + diff --git a/locales/cs.lua b/locales/cs.lua index 98172461..80c6a267 100644 --- a/locales/cs.lua +++ b/locales/cs.lua @@ -1,6 +1,11 @@ Locales['cs'] = { - ['data_incorrect'] = 'data byla zadána nesprávně. Prosím zkuste to znovu.', - ['invalid_format'] = 'data byla nesprávně naformátována. Prosím zkuste to znovu.', - ['no_identifier'] = 'there was an error loading your character!\nError code: identifier-missing\n\nThe cause of this error is not known, your identifier could not be found. Please come back later or report this problem to the server administration team.', - ['missing_identity'] = 'there was an error loading your character!\nError code: identity-missing\n\nIt seems like your identity is missing, try connecting again.', + ['show_registration'] = 'zobrazit registracni menu', + ['show_active_character'] = 'zobrazit aktivni postavy', + ['delete_character'] = 'smazat svou stavajici postavu a vytvorit novou', + ['deleted_character'] = 'vase postava byla smazana.', + ['not_registered'] = 'nemas zaregistrovanou postavu.', + ['active_character'] = '~b~aktivni postava:~s~ %s %s', + ['already_registered'] = 'jiz mas zaregistrovanou postavu.', + ['failed_identity'] = 'nastaveni vasi postavy selhalo, zkus to prosim znovu pozdeji nebo kontaktuj majitele serveru!', + ['create_a_character'] = 'aby jsi mohl/a hrat, tak se musis registrovat.' } diff --git a/locales/en.lua b/locales/en.lua index a8e381e4..165ee7ae 100644 --- a/locales/en.lua +++ b/locales/en.lua @@ -1,6 +1,33 @@ Locales['en'] = { - ['data_incorrect'] = 'data entered incorrectly. Please try again.', - ['invalid_format'] = 'data formatted incorrectly. Please try again.', - ['no_identifier'] = 'there was an error loading your character!\nError code: identifier-missing\n\nThe cause of this error is not known, your identifier could not be found. Please come back later or report this problem to the server administration team.', - ['missing_identity'] = 'there was an error loading your character!\nError code: identity-missing\n\nIt seems like your identity is missing, try connecting again.', + ['show_active_character'] = 'Show Active Character', + ['active_character'] = 'Active Character: ~b~%s~s~', + ['error_active_character'] = "There was an error retrieving your name. Please contact an admin.", + ['delete_character'] = 'Delete Your Character And Create A New One', + ['deleted_character'] = 'Your character has been deleted.', + ['error_delete_character'] = "There was an error deleting your character. Please contact an admin.", + ['thank_you_for_registering'] = "Thank you for registering. Have fun.", + ['registration_error'] = "There was an error during registration. Please contact an admin.", + ['debug_xPlayer_get_first_name'] = "Return Your First Name", + ['debug_xPlayer_get_last_name'] = "Return Your Last Name", + ['debug_xPlayer_get_full_name'] = "Return Your Full Name", + ['debug_xPlayer_get_sex'] = "Return Your Sex", + ['debug_xPlayer_get_dob'] = "Return Your DOB", + ['debug_xPlayer_get_height'] = "Return Your Height", + ['error_debug_xPlayer_get_first_name'] = "There was an error retrieving your first name.", + ['error_debug_xPlayer_get_last_name'] = "There was an error retrieving your last name.", + ['error_debug_xPlayer_get_full_name'] = "There was an error retrieving your full name.", + ['error_debug_xPlayer_get_sex'] = "There was an error retrieving your sex.", + ['error_debug_xPlayer_get_dob'] = "There was an error retrieving your date of birth.", + ['error_debug_xPlayer_get_height'] = "There was an error retrieving your height.", + ['return_debug_xPlayer_get_first_name'] = "First Name: ~b~%s", + ['return_debug_xPlayer_get_last_name'] = "Last Name: ~b~%s", + ['return_debug_xPlayer_get_full_name'] = "Full Name: ~b~%s", + ['return_debug_xPlayer_get_sex'] = "Sex: ~b~%s", + ['return_debug_xPlayer_get_dob'] = "DOB: ~b~%s", + ['return_debug_xPlayer_get_height'] = "Height: ~b~%s Inches", + ['data_incorrect'] = 'Data entered incorrectly. Please try again.', + ['invalid_format'] = 'Data formatted incorrectly. Please try again.', + ['no_identifier'] = 'There was an error loading your character!\nError code: identifier-missing\n\nThe cause of this error is not known, your identifier could not be found. Please come back later or report this problem to the server administration team.', + ['missing_identity'] = 'There was an error loading your character!\nError code: identity-missing\n\nIt seems like your identity is missing, try connecting again.', + ['deleted_identity'] = 'Your character has been deleted. Please login again in order to create a new character.' } diff --git a/server/main.lua b/server/main.lua index 3fbc4962..ede6b5bd 100644 --- a/server/main.lua +++ b/server/main.lua @@ -1,95 +1,455 @@ ESX = nil local playerIdentity = {} - +local alreadyRegistered = {} TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end) -AddEventHandler('playerConnecting', function(playerName, setKickReason, deferrals) - deferrals.defer() - local playerId, identifier = source - Citizen.Wait(100) - - for k,v in ipairs(GetPlayerIdentifiers(playerId)) do - if string.match(v, 'license:') then - identifier = string.sub(v, 9) - break +if Config.UseDeferrals then + AddEventHandler('playerConnecting', function(playerName, setKickReason, deferrals) + deferrals.defer() + local playerId, identifier = source + Citizen.Wait(100) + + if Config.UseSteamID then + for k,v in ipairs(GetPlayerIdentifiers(playerId)) do + if string.match(v, 'steam:') then + identifier = v + break + end + end + else + for k,v in ipairs(GetPlayerIdentifiers(playerId)) do + if string.match(v, 'license:') then + identifier = string.sub(v, 9) + break + end + end end - end + + if identifier then + MySQL.Async.fetchAll('SELECT firstname, lastname, dateofbirth, sex, height FROM users WHERE identifier = @identifier', { + ['@identifier'] = identifier + }, function(result) + if result[1] then + if result[1].firstname then + playerIdentity[identifier] = { + firstName = result[1].firstname, + lastName = result[1].lastname, + dateOfBirth = result[1].dateofbirth, + sex = result[1].sex, + height = result[1].height + } + + deferrals.done() + else + deferrals.presentCard([==[{"type": "AdaptiveCard","body":[{"type":"Container","items":[{"type":"ColumnSet","columns":[{"type":"Column","items":[{"type":"Input.Text","placeholder":"First Name","id":"firstname","maxLength":15},{"type":"Input.Text","placeholder":"Date of Birth (MM/DD/YYYY)","id":"dateofbirth","maxLength":10}],"width":"stretch"},{"type":"Column","width":"stretch","items":[{"type":"Input.Text","placeholder":"Last Name","id":"lastname","maxLength":15},{"type":"Input.Text","placeholder":"Height (48-96 inches)","id":"height","maxLength":2}]}]},{"type":"Input.ChoiceSet","placeholder":"Sex","choices":[{"title":"Male","value":"m"},{"title":"Female","value":"f"}],"style":"expanded","id":"sex"}]},{"type": "ActionSet","actions": [{"type":"Action.Submit","title":"Submit"}]}],"$schema": "http://adaptivecards.io/schemas/adaptive-card.json","version":"1.0"}]==], function(data, rawData) + if data.firstname == '' or data.lastname == '' or data.dateofbirth == '' or data.sex == '' or data.height == '' then + deferrals.done(_U('data_incorrect')) + else + if checkNameFormat(data.firstname) and checkNameFormat(data.lastname) and checkDOBFormat(data.dateofbirth) and checkSexFormat(data.sex) and checkHeightFormat(data.height) then + playerIdentity[identifier] = { + firstName = formatName(data.firstname), + lastName = formatName(data.lastname), + dateOfBirth = data.dateofbirth, + sex = data.sex, + height = tonumber(data.height), + saveToDatabase = true + } + + deferrals.done() + else + deferrals.done(_U('invalid_format')) + end + end + end) + end + else + deferrals.presentCard([==[{"type": "AdaptiveCard","body":[{"type":"Container","items":[{"type":"ColumnSet","columns":[{"type":"Column","items":[{"type":"Input.Text","placeholder":"First Name","id":"firstname","maxLength":15},{"type":"Input.Text","placeholder":"Date of Birth (MM/DD/YYYY)","id":"dateofbirth","maxLength":10}],"width":"stretch"},{"type":"Column","width":"stretch","items":[{"type":"Input.Text","placeholder":"Last Name","id":"lastname","maxLength":15},{"type":"Input.Text","placeholder":"Height (48-96 inches)","id":"height","maxLength":2}]}]},{"type":"Input.ChoiceSet","placeholder":"Sex","choices":[{"title":"Male","value":"m"},{"title":"Female","value":"f"}],"style":"expanded","id":"sex"}]},{"type": "ActionSet","actions": [{"type":"Action.Submit","title":"Submit"}]}],"$schema": "http://adaptivecards.io/schemas/adaptive-card.json","version":"1.0"}]==], function(data, rawData) + if data.firstname == '' or data.lastname == '' or data.dateofbirth == '' or data.sex == '' or data.height == '' then + deferrals.done(_U('data_incorrect')) + else + if checkNameFormat(data.firstname) and checkNameFormat(data.lastname) and checkDOBFormat(data.dateofbirth) and checkSexFormat(data.sex) and checkHeightFormat(data.height) then + playerIdentity[identifier] = { + firstName = formatName(data.firstname), + lastName = formatName(data.lastname), + dateOfBirth = data.dateofbirth, + sex = data.sex, + height = tonumber(data.height), + saveToDatabase = true + } + + deferrals.done() + else + deferrals.done(_U('invalid_format')) + end + end + end) + end + end) + else + deferrals.done(_U('no_identifier')) + end + end) + + RegisterNetEvent('esx:playerLoaded') + AddEventHandler('esx:playerLoaded', function(playerId, xPlayer) + if playerIdentity[xPlayer.identifier] then + local currentIdentity = playerIdentity[xPlayer.identifier] + + xPlayer.setName(('%s %s'):format(currentIdentity.firstName, currentIdentity.lastName)) + xPlayer.set('firstName', currentIdentity.firstName) + xPlayer.set('lastName', currentIdentity.lastName) + xPlayer.set('dateofbirth', currentIdentity.dateOfBirth) + xPlayer.set('sex', currentIdentity.sex) + xPlayer.set('height', currentIdentity.height) + + if currentIdentity.saveToDatabase then + saveIdentityToDatabase(xPlayer.identifier, currentIdentity) + end - if identifier then + Citizen.Wait(1000) + alreadyRegistered[xPlayer.identifier] = true + TriggerClientEvent('esx_identity:alreadyRegistered', xPlayer.source) + + playerIdentity[xPlayer.identifier] = nil + else + xPlayer.kick(_('missing_identity')) + end + end) +elseif not Config.UseDeferrals then + AddEventHandler('playerConnecting', function(playerName, setKickReason, deferrals) + deferrals.defer() + local playerId, identifier = source + Citizen.Wait(100) + + if Config.UseSteamID then + for k,v in ipairs(GetPlayerIdentifiers(playerId)) do + if string.match(v, 'steam:') then + identifier = v + break + end + end + else + for k,v in ipairs(GetPlayerIdentifiers(playerId)) do + if string.match(v, 'license:') then + identifier = string.sub(v, 9) + break + end + end + end + + if identifier then + MySQL.Async.fetchAll('SELECT firstname, lastname, dateofbirth, sex, height FROM users WHERE identifier = @identifier', { + ['@identifier'] = identifier + }, function(result) + if result[1] then + if result[1].firstname then + playerIdentity[identifier] = { + firstName = result[1].firstname, + lastName = result[1].lastname, + dateOfBirth = result[1].dateofbirth, + sex = result[1].sex, + height = result[1].height + } + + alreadyRegistered[identifier] = true + + deferrals.done() + else + playerIdentity[identifier] = nil + alreadyRegistered[identifier] = false + deferrals.done() + end + else + playerIdentity[identifier] = nil + alreadyRegistered[identifier] = false + deferrals.done() + end + end) + else + deferrals.done(_U('no_identifier')) + end + end) + + AddEventHandler('onResourceStart', function(resource) + if resource == GetCurrentResourceName() then + Citizen.Wait(1000) + + while not ESX do + Citizen.Wait(10) + end + + local xPlayers = ESX.GetPlayers() + + for i=1, #xPlayers, 1 do + local xPlayer = ESX.GetPlayerFromId(xPlayers[i]) + + if xPlayer then + checkIdentity(xPlayer) + end + end + end + end) + + RegisterNetEvent('esx:playerLoaded') + AddEventHandler('esx:playerLoaded', function(playerId, xPlayer) + if alreadyRegistered[xPlayer.identifier] == true then + local currentIdentity = playerIdentity[xPlayer.identifier] + + xPlayer.setName(('%s %s'):format(currentIdentity.firstName, currentIdentity.lastName)) + xPlayer.set('firstName', currentIdentity.firstName) + xPlayer.set('lastName', currentIdentity.lastName) + xPlayer.set('dateofbirth', currentIdentity.dateOfBirth) + xPlayer.set('sex', currentIdentity.sex) + xPlayer.set('height', currentIdentity.height) + + if currentIdentity.saveToDatabase then + saveIdentityToDatabase(xPlayer.identifier, currentIdentity) + end + + Citizen.Wait(1000) + TriggerClientEvent('esx_identity:alreadyRegistered', xPlayer.source) + + playerIdentity[xPlayer.identifier] = nil + else + TriggerClientEvent('esx_identity:showRegisterIdentity', xPlayer.source) + end + end) + + ESX.RegisterServerCallback('esx_identity:registerIdentity', function(source, cb, data) + local xPlayer = ESX.GetPlayerFromId(source) + + if xPlayer then + if not alreadyRegistered[xPlayer.identifier] then + if checkNameFormat(data.firstname) and checkNameFormat(data.lastname) and checkSexFormat(data.sex) and checkDOBFormat(data.dateofbirth) and checkHeightFormat(data.height) then + playerIdentity[xPlayer.identifier] = { + firstName = formatName(data.firstname), + lastName = formatName(data.lastname), + dateOfBirth = data.dateofbirth, + sex = data.sex, + height = data.height + } + + local currentIdentity = playerIdentity[xPlayer.identifier] + + xPlayer.setName(('%s %s'):format(currentIdentity.firstName, currentIdentity.lastName)) + xPlayer.set('firstName', currentIdentity.firstName) + xPlayer.set('lastName', currentIdentity.lastName) + xPlayer.set('dateofbirth', currentIdentity.dateOfBirth) + xPlayer.set('sex', currentIdentity.sex) + xPlayer.set('height', currentIdentity.height) + + saveIdentityToDatabase(xPlayer.identifier, currentIdentity) + alreadyRegistered[xPlayer.identifier] = true + + playerIdentity[xPlayer.identifier] = nil + cb(true) + else + cb(false) + end + else + cb(false) + end + end + end) + + function checkIdentity(xPlayer) MySQL.Async.fetchAll('SELECT firstname, lastname, dateofbirth, sex, height FROM users WHERE identifier = @identifier', { - ['@identifier'] = identifier + ['@identifier'] = xPlayer.identifier }, function(result) if result[1] then - playerIdentity[identifier] = { - firstName = result[1].firstname, - lastName = result[1].lastname, - dateOfBirth = result[1].dateofbirth, - sex = result[1].sex, - height = result[1].height - } + if result[1].firstname then + playerIdentity[xPlayer.identifier] = { + firstName = result[1].firstname, + lastName = result[1].lastname, + dateOfBirth = result[1].dateofbirth, + sex = result[1].sex, + height = result[1].height + } - deferrals.done() + alreadyRegistered[xPlayer.identifier] = true + + setIdentity(xPlayer) + else + playerIdentity[xPlayer.identifier] = nil + alreadyRegistered[xPlayer.identifier] = false + TriggerClientEvent('esx_identity:showRegisterIdentity', xPlayer.source) + end else - deferrals.presentCard([==[{"type":"AdaptiveCard","body":[{"type":"Container","items":[{"type":"TextBlock","text":"Identity Registration","horizontalAlignment":"Center","size":"Large","weight":"Bolder"},{"type":"ColumnSet","columns":[{"type":"Column","items":[{"type":"Input.Text","placeholder":"First Name","id":"firstname","maxLength":15}],"width":"stretch"},{"type":"Column","width":"stretch","items":[{"type":"Input.Text","placeholder":"Last Name","id":"lastname","maxLength":15}]}]},{"type":"ColumnSet","columns":[{"type":"Column","width":"stretch","items":[{"type":"Input.Text","placeholder":"Date of Birth (YYYY-MM-DD)","id":"dateofbirth","maxLength":10}],"style":"default"},{"type":"Column","width":"stretch","items":[{"type":"Input.Text","placeholder":"Height (24-96 inches)","id":"height","maxLength":2}]}]},{"type":"Input.ChoiceSet","placeholder":"Sex","choices":[{"title":"Male","value":"m"},{"title":"Female","value":"f"}],"style":"expanded","id":"sex"}],"style":"default","backgroundImage":"https://nischat.se/wp-content/uploads/Light-grey-background-1024x683.jpg"}],"actions":[{"type":"Action.Submit","title":"Submit"}],"$schema":"http://adaptivecards.io/schemas/adaptive-card.json","version":"1.0"}]==], function(data, rawData) - if - data.firstname == '' or - data.lastname == '' or - data.dateofbirth == '' or - data.sex == '' or - data.height == '' - then - deferrals.done(_U('data_incorrect')) - else - if - checkNameFormat(data.firstname) and - checkNameFormat(data.lastname) and - checkDOBFormat(data.dateofbirth) and - checkSexFormat(data.sex) and - checkHeightFormat(data.height) - then - playerIdentity[identifier] = { - firstName = formatName(data.firstname), - lastName = formatName(data.lastname), - dateOfBirth = data.dateofbirth, - sex = data.sex, - height = tonumber(data.height), - saveToDatabase = true - } - - deferrals.done() - else - deferrals.done(_U('invalid_format')) - end - end - end) + TriggerClientEvent('esx_identity:showRegisterIdentity', xPlayer.source) end end) - else - deferrals.done(_U('no_identifier')) end -end) -RegisterNetEvent('esx:playerLoaded') -AddEventHandler('esx:playerLoaded', function(playerId, xPlayer) - if playerIdentity[xPlayer.identifier] then - local currentIdentity = playerIdentity[xPlayer.identifier] + function setIdentity(xPlayer) + if alreadyRegistered[xPlayer.identifier] then + local currentIdentity = playerIdentity[xPlayer.identifier] - xPlayer.setName(('%s %s'):format(currentIdentity.firstName, currentIdentity.lastName)) - xPlayer.set('firstName', currentIdentity.firstName) - xPlayer.set('lastName', currentIdentity.lastName) - xPlayer.set('dateofbirth', currentIdentity.dateOfBirth) - xPlayer.set('sex', currentIdentity.sex) - xPlayer.set('height', currentIdentity.height) + xPlayer.setName(('%s %s'):format(currentIdentity.firstName, currentIdentity.lastName)) + xPlayer.set('firstName', currentIdentity.firstName) + xPlayer.set('lastName', currentIdentity.lastName) + xPlayer.set('dateofbirth', currentIdentity.dateOfBirth) + xPlayer.set('sex', currentIdentity.sex) + xPlayer.set('height', currentIdentity.height) - if currentIdentity.saveToDatabase then - SaveIdentityToDatabase(xPlayer.identifier, currentIdentity) + if currentIdentity.saveToDatabase then + saveIdentityToDatabase(xPlayer.identifier, currentIdentity) + end + + playerIdentity[xPlayer.identifier] = nil end - - playerIdentity[xPlayer.identifier] = nil - else - xPlayer.kick(_('missing_identity')) end -end) +end + +if Config.EnableCommands then + ESX.RegisterCommand('char', 'user', function(xPlayer, args, showError) + if xPlayer and xPlayer.getName() then + xPlayer.showNotification(_U('active_character', xPlayer.getName())) + else + xPlayer.showNotification(_U('error_active_character')) + end + end, false, {help = _U('show_active_character')}) + + ESX.RegisterCommand('chardel', 'user', function(xPlayer, args, showError) + if xPlayer and xPlayer.getName() then + if Config.UseDeferrals then + deleteIdentity(xPlayer) + xPlayer.showNotification(_U('deleted_character')) + playerIdentity[xPlayer.identifier] = nil + alreadyRegistered[xPlayer.identifier] = false + Citizen.Wait(2500) + xPlayer.kick(_('deleted_identity')) + else + deleteIdentity(xPlayer) + xPlayer.showNotification(_U('deleted_character')) + playerIdentity[xPlayer.identifier] = nil + alreadyRegistered[xPlayer.identifier] = false + TriggerClientEvent('esx_identity:showRegisterIdentity', xPlayer.source) + end + else + xPlayer.showNotification(_U('error_delete_character')) + end + end, false, {help = _U('delete_character')}) +end + +if Config.EnableDebugging then + ESX.RegisterCommand('xPlayerGetFirstName', 'user', function(xPlayer, args, showError) + if xPlayer and xPlayer.get('firstName') then + xPlayer.showNotification(_U('return_debug_xPlayer_get_first_name', xPlayer.get('firstName'))) + else + xPlayer.showNotification(_U('error_debug_xPlayer_get_first_name')) + end + end, false, {help = _U('debug_xPlayer_get_first_name')}) + + ESX.RegisterCommand('xPlayerGetLastName', 'user', function(xPlayer, args, showError) + if xPlayer and xPlayer.get('lastName') then + xPlayer.showNotification(_U('return_debug_xPlayer_get_last_name', xPlayer.get('lastName'))) + else + xPlayer.showNotification(_U('error_debug_xPlayer_get_last_name')) + end + end, false, {help = _U('debug_xPlayer_get_last_name')}) + + ESX.RegisterCommand('xPlayerGetFullName', 'user', function(xPlayer, args, showError) + if xPlayer and xPlayer.getName() then + xPlayer.showNotification(_U('return_debug_xPlayer_get_full_name', xPlayer.getName())) + else + xPlayer.showNotification(_U('error_debug_xPlayer_get_full_name')) + end + end, false, {help = _U('debug_xPlayer_get_full_name')}) + + ESX.RegisterCommand('xPlayerGetSex', 'user', function(xPlayer, args, showError) + if xPlayer and xPlayer.get('sex') then + xPlayer.showNotification(_U('return_debug_xPlayer_get_sex', xPlayer.get('sex'))) + else + xPlayer.showNotification(_U('error_debug_xPlayer_get_sex')) + end + end, false, {help = _U('debug_xPlayer_get_sex')}) + + ESX.RegisterCommand('xPlayerGetDOB', 'user', function(xPlayer, args, showError) + if xPlayer and xPlayer.get('dateofbirth') then + xPlayer.showNotification(_U('return_debug_xPlayer_get_dob', xPlayer.get('dateofbirth'))) + else + xPlayer.showNotification(_U('error_debug_xPlayer_get_dob')) + end + end, false, {help = _U('debug_xPlayer_get_dob')}) + + ESX.RegisterCommand('xPlayerGetHeight', 'user', function(xPlayer, args, showError) + if xPlayer and xPlayer.get('height') then + xPlayer.showNotification(_U('return_debug_xPlayer_get_height', xPlayer.get('height'))) + else + xPlayer.showNotification(_U('error_debug_xPlayer_get_height')) + end + end, false, {help = _U('debug_xPlayer_get_height')}) +end + +function deleteIdentity(xPlayer) + if alreadyRegistered[xPlayer.identifier] then + xPlayer.setName(('%s %s'):format(nil, nil)) + xPlayer.set('firstName', nil) + xPlayer.set('lastName', nil) + xPlayer.set('dateofbirth', nil) + xPlayer.set('sex', nil) + xPlayer.set('height', nil) + + deleteIdentityFromDatabase(xPlayer) + end +end + +function saveIdentityToDatabase(identifier, identity) + MySQL.Sync.execute('UPDATE users SET firstname = @firstname, lastname = @lastname, dateofbirth = @dateofbirth, sex = @sex, height = @height WHERE identifier = @identifier', { + ['@identifier'] = identifier, + ['@firstname'] = identity.firstName, + ['@lastname'] = identity.lastName, + ['@dateofbirth'] = identity.dateOfBirth, + ['@sex'] = identity.sex, + ['@height'] = identity.height + }) +end + +function deleteIdentityFromDatabase(xPlayer) + MySQL.Sync.execute('UPDATE users SET firstname = @firstname, lastname = @lastname, dateofbirth = @dateofbirth, sex = @sex, height = @height , skin = @skin WHERE identifier = @identifier', { + ['@identifier'] = xPlayer.identifier, + ['@firstname'] = NULL, + ['@lastname'] = NULL, + ['@dateofbirth'] = NULL, + ['@sex'] = NULL, + ['@height'] = NULL, + ['@skin'] = NULL + }) + + MySQL.Sync.execute('UPDATE addon_account_data SET money = 0 WHERE account_name = @account_name AND owner = @owner', { + ['@account_name'] = 'bank_savings', + ['@owner'] = xPlayer.identifier + }) + + MySQL.Sync.execute('UPDATE addon_account_data SET money = 0 WHERE account_name = @account_name AND owner = @owner', { + ['@account_name'] = 'caution', + ['@owner'] = xPlayer.identifier + }) + + MySQL.Sync.execute('UPDATE datastore_data SET data = @data WHERE name = @name AND owner = @owner', { + ['@data'] = '\'{}\'', + ['@name'] = 'user_ears', + ['@owner'] = xPlayer.identifier + }) + + MySQL.Sync.execute('UPDATE datastore_data SET data = @data WHERE name = @name AND owner = @owner', { + ['@data'] = '\'{}\'', + ['@name'] = 'user_glasses', + ['@owner'] = xPlayer.identifier + }) + + MySQL.Sync.execute('UPDATE datastore_data SET data = @data WHERE name = @name AND owner = @owner', { + ['@data'] = '\'{}\'', + ['@name'] = 'user_helmet', + ['@owner'] = xPlayer.identifier + }) + + MySQL.Sync.execute('UPDATE datastore_data SET data = @data WHERE name = @name AND owner = @owner', { + ['@data'] = '\'{}\'', + ['@name'] = 'user_mask', + ['@owner'] = xPlayer.identifier + }) +end function checkNameFormat(name) if not checkAlphanumeric(name) then @@ -157,11 +517,11 @@ function checkForNumbers(str) end function checkDate(str) - if string.match(str, '(%d%d%d%d)-(%d%d)-(%d%d)') ~= nil then - local y, m, d = string.match(str, '(%d+)-(%d+)-(%d+)') - y = tonumber(y) + if string.match(str, '(%d%d)/(%d%d)/(%d%d%d%d)') ~= nil then + local m, d, y = string.match(str, '(%d+)/(%d+)/(%d+)') m = tonumber(m) d = tonumber(d) + y = tonumber(y) if ((d <= 0) or (d > 31)) or ((m <= 0) or (m > 12)) or ((y <= Config.LowestYear) or (y > Config.HighestYear)) then return false elseif m == 4 or m == 6 or m == 9 or m == 11 then @@ -195,14 +555,3 @@ function checkDate(str) return false end end - -function SaveIdentityToDatabase(identifier, identity) - MySQL.Sync.execute('UPDATE users SET firstname = @firstname, lastname = @lastname, dateofbirth = @dateofbirth, sex = @sex, height = @height WHERE identifier = @identifier', { - ['@identifier'] = identifier, - ['@firstname'] = identity.firstName, - ['@lastname'] = identity.lastName, - ['@dateofbirth'] = identity.dateOfBirth, - ['@sex'] = identity.sex, - ['@height'] = identity.height - }) -end