mirror of
https://github.com/ND-Framework/ND_Core.git
synced 2026-08-16 21:46:03 +01:00
feat: user data for db & character fetching
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
CREATE TABLE IF NOT EXISTS `nd_characters` (
|
CREATE TABLE IF NOT EXISTS `nd_characters` (
|
||||||
`charid` INT(10) NOT NULL AUTO_INCREMENT,
|
`charid` INT(10) NOT NULL AUTO_INCREMENT,
|
||||||
|
`user_id` INT(11) DEFAULT NULL,
|
||||||
`identifier` VARCHAR(200) NOT NULL DEFAULT '0',
|
`identifier` VARCHAR(200) NOT NULL DEFAULT '0',
|
||||||
`name` VARCHAR(50) DEFAULT NULL,
|
`name` VARCHAR(50) DEFAULT NULL,
|
||||||
`firstname` VARCHAR(50) DEFAULT NULL,
|
`firstname` VARCHAR(50) DEFAULT NULL,
|
||||||
@@ -9,8 +10,11 @@ CREATE TABLE IF NOT EXISTS `nd_characters` (
|
|||||||
`cash` INT(10) DEFAULT '0',
|
`cash` INT(10) DEFAULT '0',
|
||||||
`bank` INT(10) DEFAULT '0',
|
`bank` INT(10) DEFAULT '0',
|
||||||
`phonenumber` VARCHAR(20) DEFAULT NULL,
|
`phonenumber` VARCHAR(20) DEFAULT NULL,
|
||||||
|
`deleted_at` DATETIME NULL DEFAULT NULL,
|
||||||
`groups` LONGTEXT DEFAULT ('[]'),
|
`groups` LONGTEXT DEFAULT ('[]'),
|
||||||
`metadata` LONGTEXT DEFAULT ('[]'),
|
`metadata` LONGTEXT DEFAULT ('[]'),
|
||||||
`inventory` LONGTEXT DEFAULT ('[]'),
|
`inventory` LONGTEXT DEFAULT ('[]'),
|
||||||
PRIMARY KEY (`charid`) USING BTREE
|
PRIMARY KEY (`charid`) USING BTREE,
|
||||||
|
INDEX `idx_nd_characters_user_id` (`user_id`),
|
||||||
|
CONSTRAINT `fk_nd_characters_user_id` FOREIGN KEY (`user_id`) REFERENCES `nd_users` (`user_id`) ON UPDATE CASCADE ON DELETE SET NULL
|
||||||
);
|
);
|
||||||
|
|||||||
12
database/users.sql
Normal file
12
database/users.sql
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS `nd_users` (
|
||||||
|
`user_id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`id_steam` LONGTEXT NULL DEFAULT NULL,
|
||||||
|
`id_discord` LONGTEXT NULL DEFAULT NULL,
|
||||||
|
`id_xbl` LONGTEXT NULL DEFAULT NULL,
|
||||||
|
`id_live` LONGTEXT NULL DEFAULT NULL,
|
||||||
|
`id_license` LONGTEXT NULL DEFAULT NULL,
|
||||||
|
`id_license2` LONGTEXT NULL DEFAULT NULL,
|
||||||
|
`id_fivem` LONGTEXT NULL DEFAULT NULL,
|
||||||
|
`id_ip` LONGTEXT NULL DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`user_id`) USING BTREE
|
||||||
|
) COLLATE='utf8mb4_unicode_ci';
|
||||||
@@ -17,6 +17,7 @@ Config = {
|
|||||||
discordActionText2 = GetConvar("core:discordActionText2", "STORE"),
|
discordActionText2 = GetConvar("core:discordActionText2", "STORE"),
|
||||||
discordActionLink2 = GetConvar("core:discordActionLink2", "https://andyyy.tebex.io/category/fivem-scripts"),
|
discordActionLink2 = GetConvar("core:discordActionLink2", "https://andyyy.tebex.io/category/fivem-scripts"),
|
||||||
characterIdentifier = GetConvar("core:characterIdentifier", "license"),
|
characterIdentifier = GetConvar("core:characterIdentifier", "license"),
|
||||||
|
selectIdentifiers = json.decode(GetConvar("core:selectIdentifiers", '["discord", "license", "license2", "fivem"]')),
|
||||||
discordGuildId = GetConvar("core:discordGuildId", "false"),
|
discordGuildId = GetConvar("core:discordGuildId", "false"),
|
||||||
discordBotToken = GetConvar("core:discordBotToken", "false"),
|
discordBotToken = GetConvar("core:discordBotToken", "false"),
|
||||||
randomUnlockedVehicleChance = GetConvarInt("core:randomUnlockedVehicleChance", 30),
|
randomUnlockedVehicleChance = GetConvarInt("core:randomUnlockedVehicleChance", 30),
|
||||||
@@ -66,6 +67,71 @@ AddEventHandler("playerJoining", function(oldId)
|
|||||||
lib.addPrincipal(("player.%s"):format(src), "group.admin")
|
lib.addPrincipal(("player.%s"):format(src), "group.admin")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local identifiers = PlayersInfo[src] and PlayersInfo[src].identifiers or getIdentifierList(src)
|
||||||
|
|
||||||
|
local whereParts = {}
|
||||||
|
local params = {}
|
||||||
|
|
||||||
|
for identifierType, identifier in pairs(identifiers) do
|
||||||
|
local isSelected = false
|
||||||
|
for i=1, #Config.selectIdentifiers do
|
||||||
|
local selectedType = Config.selectIdentifiers[i]
|
||||||
|
if identifierType == selectedType then
|
||||||
|
isSelected = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if isSelected then
|
||||||
|
local columnName = "id_" .. identifierType
|
||||||
|
local cleanId = identifier:gsub("^[^:]*:", "")
|
||||||
|
table.insert(whereParts, columnName .. " = ?")
|
||||||
|
table.insert(params, cleanId)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local user = nil
|
||||||
|
if #whereParts > 0 then
|
||||||
|
local query = "SELECT user_id FROM nd_users WHERE " .. table.concat(whereParts, " OR ") .. " LIMIT 1"
|
||||||
|
user = MySQL.query.await(query, params)
|
||||||
|
end
|
||||||
|
|
||||||
|
if user and user[1] then
|
||||||
|
PlayersInfo[src].userId = user[1].user_id
|
||||||
|
|
||||||
|
local updateParts = {}
|
||||||
|
local updateParams = {}
|
||||||
|
|
||||||
|
for identifierType, identifier in pairs(identifiers) do
|
||||||
|
local columnName = "id_" .. identifierType
|
||||||
|
local cleanId = identifier:gsub("^[^:]*:", "")
|
||||||
|
table.insert(updateParts, columnName .. " = ?")
|
||||||
|
table.insert(updateParams, cleanId)
|
||||||
|
end
|
||||||
|
|
||||||
|
if #updateParts > 0 then
|
||||||
|
table.insert(updateParams, user[1].user_id)
|
||||||
|
local updateQuery = "UPDATE nd_users SET " .. table.concat(updateParts, ", ") .. " WHERE user_id = ?"
|
||||||
|
MySQL.update.await(updateQuery, updateParams)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local columns = {}
|
||||||
|
local values = {}
|
||||||
|
local insertParams = {}
|
||||||
|
|
||||||
|
for identifierType, identifier in pairs(identifiers) do
|
||||||
|
local columnName = "id_" .. identifierType
|
||||||
|
local cleanId = identifier:gsub("^[^:]*:", "")
|
||||||
|
table.insert(columns, columnName)
|
||||||
|
table.insert(values, "?")
|
||||||
|
table.insert(insertParams, cleanId)
|
||||||
|
end
|
||||||
|
|
||||||
|
local insertQuery = "INSERT INTO nd_users (" .. table.concat(columns, ", ") .. ") VALUES (" .. table.concat(values, ", ") .. ")"
|
||||||
|
local user_id = MySQL.insert.await(insertQuery, insertParams)
|
||||||
|
PlayersInfo[src].userId = user_id
|
||||||
|
end
|
||||||
|
|
||||||
if Config.multiCharacter then return end
|
if Config.multiCharacter then return end
|
||||||
Wait(3000)
|
Wait(3000)
|
||||||
|
|
||||||
@@ -164,14 +230,6 @@ AddEventHandler("onResourceStop", function(name)
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
MySQL.ready(function()
|
|
||||||
Wait(100)
|
|
||||||
NDCore.loadSQL({
|
|
||||||
"database/characters.sql",
|
|
||||||
"database/vehicles.sql"
|
|
||||||
}, resourceName)
|
|
||||||
end)
|
|
||||||
|
|
||||||
RegisterNetEvent("ND:playerEliminated", function(info)
|
RegisterNetEvent("ND:playerEliminated", function(info)
|
||||||
local src = source
|
local src = source
|
||||||
local player = NDCore.getPlayer(src)
|
local player = NDCore.getPlayer(src)
|
||||||
@@ -188,3 +246,17 @@ RegisterNetEvent("ND:updateClothing", function(clothing)
|
|||||||
if not player or not clothing or type(clothing) ~= "table" then return end
|
if not player or not clothing or type(clothing) ~= "table" then return end
|
||||||
player.setMetadata("clothing", clothing)
|
player.setMetadata("clothing", clothing)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
MySQL.ready(function()
|
||||||
|
Wait(100)
|
||||||
|
NDCore.loadSQL({
|
||||||
|
"database/users.sql",
|
||||||
|
"database/characters.sql",
|
||||||
|
"database/vehicles.sql",
|
||||||
|
}, resourceName)
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Hourly cron, purge soft-deleted characters older than 30 days.
|
||||||
|
lib.cron.new("0 * * * *", function()
|
||||||
|
MySQL.update.await("DELETE FROM nd_characters WHERE deleted_at IS NOT NULL AND deleted_at < DATE_SUB(NOW(), INTERVAL 30 DAY)")
|
||||||
|
end)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ local function createCharacterTable(info)
|
|||||||
id = info.id,
|
id = info.id,
|
||||||
source = info.source,
|
source = info.source,
|
||||||
identifier = info.identifier,
|
identifier = info.identifier,
|
||||||
|
user_id = info.user_id,
|
||||||
identifiers = playerInfo.identifiers or {},
|
identifiers = playerInfo.identifiers or {},
|
||||||
discord = playerInfo.discord or {},
|
discord = playerInfo.discord or {},
|
||||||
name = info.name,
|
name = info.name,
|
||||||
@@ -135,9 +136,9 @@ local function createCharacterTable(info)
|
|||||||
return self.metadata
|
return self.metadata
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Completely delete character
|
-- Mark character deleted
|
||||||
function self.delete()
|
function self.delete()
|
||||||
local result = MySQL.query.await("DELETE FROM nd_characters WHERE charid = ?", {self.id})
|
local result = MySQL.update.await("UPDATE nd_characters SET deleted_at = NOW() WHERE charid = ?", {self.id})
|
||||||
if result and NDCore.players[self.source] then
|
if result and NDCore.players[self.source] then
|
||||||
NDCore.players[self.source] = nil
|
NDCore.players[self.source] = nil
|
||||||
end
|
end
|
||||||
@@ -201,7 +202,8 @@ local function createCharacterTable(info)
|
|||||||
return affectedRows > 0
|
return affectedRows > 0
|
||||||
end
|
end
|
||||||
|
|
||||||
local affectedRows = MySQL.update.await("UPDATE nd_characters SET name = ?, firstname = ?, lastname = ?, dob = ?, gender = ?, cash = ?, bank = ?, phonenumber = ?, `groups` = ?, metadata = ? WHERE charid = ?", {
|
local affectedRows = MySQL.update.await("UPDATE nd_characters SET user_id = ?, name = ?, firstname = ?, lastname = ?, dob = ?, gender = ?, cash = ?, bank = ?, phonenumber = ?, `groups` = ?, metadata = ? WHERE charid = ?", {
|
||||||
|
self.user_id,
|
||||||
self.name,
|
self.name,
|
||||||
self.firstname,
|
self.firstname,
|
||||||
self.lastname,
|
self.lastname,
|
||||||
@@ -488,9 +490,12 @@ function NDCore.newCharacter(src, info)
|
|||||||
local identifier = NDCore.getPlayerIdentifierByType(src, Config.characterIdentifier)
|
local identifier = NDCore.getPlayerIdentifierByType(src, Config.characterIdentifier)
|
||||||
if not identifier then return end
|
if not identifier then return end
|
||||||
|
|
||||||
|
local userId = PlayersInfo[src] and PlayersInfo[src].userId
|
||||||
|
|
||||||
local charInfo = {
|
local charInfo = {
|
||||||
source = src,
|
source = src,
|
||||||
identifier = identifier,
|
identifier = identifier,
|
||||||
|
user_id = userId,
|
||||||
name = GetPlayerName(src) or "",
|
name = GetPlayerName(src) or "",
|
||||||
firstname = info.firstname or "",
|
firstname = info.firstname or "",
|
||||||
lastname = info.lastname or "",
|
lastname = info.lastname or "",
|
||||||
@@ -516,8 +521,9 @@ function NDCore.newCharacter(src, info)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
charInfo.id = MySQL.insert.await("INSERT INTO nd_characters (identifier, name, firstname, lastname, dob, gender, cash, bank, phonenumber, `groups`, metadata, inventory) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", {
|
charInfo.id = MySQL.insert.await("INSERT INTO nd_characters (identifier, user_id, name, firstname, lastname, dob, gender, cash, bank, phonenumber, `groups`, metadata, inventory) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", {
|
||||||
identifier,
|
identifier,
|
||||||
|
userId,
|
||||||
charInfo.name,
|
charInfo.name,
|
||||||
charInfo.firstname,
|
charInfo.firstname,
|
||||||
charInfo.lastname,
|
charInfo.lastname,
|
||||||
@@ -539,17 +545,30 @@ end
|
|||||||
function NDCore.fetchCharacter(id, src)
|
function NDCore.fetchCharacter(id, src)
|
||||||
local result
|
local result
|
||||||
if src then
|
if src then
|
||||||
result = MySQL.query.await("SELECT * FROM nd_characters WHERE charid = ? and identifier = ?", {id, NDCore.getPlayerIdentifierByType(src, Config.characterIdentifier)})
|
local identifier = NDCore.getPlayerIdentifierByType(src, Config.characterIdentifier)
|
||||||
|
local userId = PlayersInfo[src] and PlayersInfo[src].userId
|
||||||
|
result = MySQL.query.await("SELECT * FROM nd_characters WHERE charid = ? AND (identifier = ? OR user_id = ?)", {id, identifier, userId})
|
||||||
else
|
else
|
||||||
result = MySQL.query.await("SELECT * FROM nd_characters WHERE charid = ?", {id})
|
result = MySQL.query.await("SELECT * FROM nd_characters WHERE charid = ?", {id})
|
||||||
end
|
end
|
||||||
|
|
||||||
if not result then return end
|
local info = result?[1]
|
||||||
local info = result[1]
|
if not info then return end
|
||||||
|
|
||||||
|
-- Check if character has user_id, if not assign it
|
||||||
|
if not info.user_id and src then
|
||||||
|
local userId = PlayersInfo[src] and PlayersInfo[src].userId
|
||||||
|
if userId then
|
||||||
|
MySQL.update.await("UPDATE nd_characters SET user_id = ? WHERE charid = ?", {userId, info.charid})
|
||||||
|
info.user_id = userId
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return createCharacterTable({
|
return createCharacterTable({
|
||||||
source = src,
|
source = src,
|
||||||
id = info.charid,
|
id = info.charid,
|
||||||
identifier = info.identifier,
|
identifier = info.identifier,
|
||||||
|
user_id = info.user_id,
|
||||||
name = info.name,
|
name = info.name,
|
||||||
firstname = info.firstname,
|
firstname = info.firstname,
|
||||||
lastname = info.lastname,
|
lastname = info.lastname,
|
||||||
@@ -567,15 +586,27 @@ end
|
|||||||
---@param src number
|
---@param src number
|
||||||
---@return table
|
---@return table
|
||||||
function NDCore.fetchAllCharacters(src)
|
function NDCore.fetchAllCharacters(src)
|
||||||
|
local userId = PlayersInfo[src] and PlayersInfo[src].userId
|
||||||
|
local identifier = NDCore.getPlayerIdentifierByType(src, Config.characterIdentifier)
|
||||||
local characters = {}
|
local characters = {}
|
||||||
local result = MySQL.query.await("SELECT * FROM nd_characters WHERE identifier = ?", {NDCore.getPlayerIdentifierByType(src, Config.characterIdentifier)})
|
|
||||||
|
-- Query by either identifier OR user_id, excluding deleted characters
|
||||||
|
local result = MySQL.query.await("SELECT * FROM nd_characters WHERE (identifier = ? OR user_id = ?) AND deleted_at IS NULL", {identifier, userId})
|
||||||
|
|
||||||
for i=1, #result do
|
for i=1, #result do
|
||||||
local info = result[i]
|
local info = result[i]
|
||||||
|
|
||||||
|
-- Check if character has user_id, if not assign it
|
||||||
|
if not info.user_id and userId then
|
||||||
|
MySQL.update.await("UPDATE nd_characters SET user_id = ? WHERE charid = ?", {userId, info.charid})
|
||||||
|
info.user_id = userId
|
||||||
|
end
|
||||||
|
|
||||||
characters[info.charid] = createCharacterTable({
|
characters[info.charid] = createCharacterTable({
|
||||||
source = src,
|
source = src,
|
||||||
id = info.charid,
|
id = info.charid,
|
||||||
identifier = info.identifier,
|
identifier = info.identifier,
|
||||||
|
user_id = info.user_id,
|
||||||
name = info.name,
|
name = info.name,
|
||||||
firstname = info.firstname,
|
firstname = info.firstname,
|
||||||
lastname = info.lastname,
|
lastname = info.lastname,
|
||||||
|
|||||||
Reference in New Issue
Block a user