From 0111ff3b6ea89f741170ba666553f12def88de79 Mon Sep 17 00:00:00 2001 From: atticl Date: Sat, 15 Nov 2025 00:20:57 +0100 Subject: [PATCH] character creation CLIENT/SERVER --- character/cl_character.lua | 136 +++++++++++++++++++++++++++++++++++++ character/db_character.lua | 0 character/sv_character.lua | 81 ++++++++++++++++++++++ fxmanifest.lua | 2 +- 4 files changed, 218 insertions(+), 1 deletion(-) create mode 100644 character/cl_character.lua create mode 100644 character/db_character.lua create mode 100644 character/sv_character.lua diff --git a/character/cl_character.lua b/character/cl_character.lua new file mode 100644 index 0000000..fb6cb81 --- /dev/null +++ b/character/cl_character.lua @@ -0,0 +1,136 @@ +local selectedCharacter = false +local camera = nil +local camera2 = nil + +local bannedNames = {} + +Citizen.CreateThread(function() + while true do + Citizen.Wait(0) + + if NetworkIsSessionStarted() then + TriggerServerEvent('gb-core:character:joined') + TriggerEvent('gb-core:character:startCamera') + TriggerEvent('gb-core:client:closeCharacterUI') + TriggerEvent('gb-core:playerLogin') + selectedCharacter(true) + return + end + end +end) + +RegisterNetEvent('gb-core:character:selecting') +AddEventHandler('gb-core:character:selecting', function() + selectedCharacter(true) +end) + +getCID = function(source, cb) + local src = source + TriggerServerEvent('gb-core:getID', src) +end + +RegisterNUICallback('createCharacter', function(data) + local characterData = data.CharacterData + for theData, value in pairs(characterData) do + if theData == 'firstname' or theData == 'lastname' then + reason = verifyName(value) + print(reason) -- Make sure this prints out correctly (comment // or remove later.) + + if reason ~= '' then + break + end + end + end + + if reason == '' then + TriggerServerEvent('gb-core:server:createCharacter', characterData) + end +end) + +function verifyName(name) + for k, v in ipairs(bannedNames) do + if name == v then + local reason = 'Trying to use an inappropriate name. Please think about your decisions.' + TriggerServerEvent('gb-admin:disconnect', reason) + end + end + + local nameLength = string.len(name) + if nameLength > 25 or nameLength < 2 then + local reason = 'Name too short.' + end + + let count = 0 + for i in name:gmatch("[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-]") do + count = count + 1 + end + if count ~= nameLength then + return "Your player name contains special characters. (a-z,A-Z add -)" + end + + local spacesInName = 0 + local spacesWithUpper = 0 + for word in string.gmatch(name, "%S+") do + if string.match(word, "%u") then + spacesWithUpper = spacesWithUpper + 1 + end + + spacesInName = spacesInName + 1 + end + + if spacesInName > 1 then + return "Name contains more then 1 space." + end + + if spacesWithUpper ~= spacesInName then + return "Name must start with a capital letter." + end + + return "" +end + +RegisterNUICallback('deleteCharacter', function(data) + local characterData = data + TriggerServerEvent('gb-core:deleteCharacter', characterData) +end) + +RegisterNetEvent('gb-core:character:setupCharacter') +AddEventHandler('gb-core:character:setupCharacter', fuction(data) + GB.Functions.TriggerServerCallback('gb-core:getCharacter', function(data) + SendNUIMessage({type = 'setupCharacters', characters = data}) + end) +end) + +RegisterNUICallback('selectCharacters', function(data) + local cid = tonumber(data.cid) + selectedCharacter(false) + TriggerServerEvent('gb-core:character:serverSelect', cid) + TriggerEvent('gb-core:openMenu') + SetTimecycleModifier('default') + SetCamActive(camera, false) + DestroyCam(camera, false) +end) + +RegisterNUICallback('closeCharacter', function(data) + selectedCharacter(false) +end) + +function selectedCharacter(value) + SetNuiFocus(value, value) + SendNUIMessage({ + type = 'characterSelect', + status = value + }) + selectingCharacter = false +end + +RegisterNetEvent('gb-core:character:startCamera') +AddEventHandler('gb-core:character:startCamera', function() + DoScreenFadeIn(10) + SetTimecycleModifier('hud_def_blur') + SetTimecycleModifierStrength(1.0) + FreezeEntityPosition(GetPlayerPed(-1), true) + cam = CreateCamWithParams("DEFAULT_SCRIPTED_CAMERA", -358.56, -981.96, 286.25, 320.00, 0.00, -50.00, 90.00, false, 0) + SetCamActive(camera, true) + RenderScriptCams(true, false, 1, true, true) +end) \ No newline at end of file diff --git a/character/db_character.lua b/character/db_character.lua new file mode 100644 index 0000000..e69de29 diff --git a/character/sv_character.lua b/character/sv_character.lua new file mode 100644 index 0000000..01b65e1 --- /dev/null +++ b/character/sv_character.lua @@ -0,0 +1,81 @@ +RegisterNetEvent('gb-core:character:join') +AddEventHandler('gb-core:character:join', function() + local src = source + local id + + for k, v in ipairs(GetPlayerIdentifier(src)) do + if string.sub(v, 1, string.len('discord:')) == 'discord:' then + id=v + break + end + end + + if not id then + DropPlayer(src, 'Identifier not found, Make sure discord is running and your are in the server.') + else + TriggerClientEvent('gb-core:character:setupCharacters', src) + end +end) + +RegisterNetEvent('gb-core:character:serverSelect') +AddEventHandler('gb-core:character:serverSelect', function(cid) -- CID is for character slot from UI + local src = source + local identifier = GetPlayerIdentifierByType(src, "discord") -- Get's discord id + local license = GetPlayerIdentifierByType(src, "fivem") -- Get's fivem license + + GB.DB.LoadCharacter(src, license, identifier, cid) -- ensure we get the correct player +end) + +GB.Functions.RegisterServerCallback('gb-core:getCharacter', function(source, cb) -- Send back every created character (by said person) + local id = GetPlayerIdentifierByType(src, "discord") -- Get's discord id + + exports['ghmattimysql']:execute('SELECT * FROM players WHERE identifier = @identifier', {['@identifier'] = id}, function(result) + if result then + cb(result) + end + end) +end) + +RegisterNetEvent('gb-core:deleteCharacter') +AddEventHandler('gb-core:deleteCharacter', function(characterData) + local cid = characterData.cid -- Passing right player slot + local name = 'First: ' .. characterData.firstname .. ' Last: ' .. characterData.lastname .. '' + local src = source + local identifier = GetPlayerIdentifierByType(src, "discord") + local characterName = 'First: ' .. characterData.firstname .. ' Last: ' .. characterData.lastname .. '' + + local citizenID = '' .. cid .. '-' .. identifier .. '' -- 1-Discord + + -- TODO: Add discord logs + + TriggerClientEvent('gb-core:character:setupCharacters', src) -- refresh menu +end) + +RegisterNetEvent('gb-core:server:createCharacter') +AddEventHandler('gb-core:server:createCharacter', function(cData) + local src = source + local identifier = GetPlayerIdentifierByType(src, "discord") + local license = GetPlayerIdentifierByType(src, "fivem") + local name = GetPlayerName(src) + local cid = cData.cid + local citizenId = '' .. cData.cid .. '-' .. identifier .. '' + local characterName = 'First: ' .. cData.firstname .. ' Last: ' .. cData.lastname .. '' + + exports['ghmattimysql']:execute('INSERT INTO players (`identifier`, `license`, `name`, `cid`, `cash`, `bank`, `firstname`, `lastname`, `sex`, `dob`, `citizenid`) VALUES (@identifier, @license, @name, @cid, @cash, @bank, @firstname, @lastname, @sex, @dob, @citizenid)'. { + ['identifier'] = identifier, + ['license'] = license, + ['name'] = name, + ['cid'] = cid, + ['cash'] = GB.Starting.Cash, + ['bank'] = GB.Starting.Bank, + ['firstname'] = cData.firstname, + ['lastname'] = cData.lastname, + ['sex'] = cData.sex, + ['dob'] = cData.dob, + ['citizenid'] = citizenid -- Used to callback everything related to sql and saving per player + }) + + -- TODO: Logs for creation + + TriggerClientEvent('gb-core:character:setupCharacters', src) -- refresh menu +end) \ No newline at end of file diff --git a/fxmanifest.lua b/fxmanifest.lua index 3c0aa04..a65906f 100644 --- a/fxmanifest.lua +++ b/fxmanifest.lua @@ -5,7 +5,7 @@ author 'gb-framework' description 'n/a' version '0.0.1' --- dependency 'ghmattimysql' +dependency 'ghmattimysql' client_scripts { 'core/cl_core.lua',