Skip to content

Commit fc49dcb

Browse files
committed
feat(es_extended): add SSN
1 parent 224d06f commit fc49dcb

File tree

5 files changed

+69
-7
lines changed

5 files changed

+69
-7
lines changed

[SQL]/legacy.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@ CREATE TABLE `society_moneywash` (
385385

386386
CREATE TABLE `users` (
387387
`identifier` varchar(60) NOT NULL,
388+
`ssn` VARCHAR(11) NOT NULL,
388389
`accounts` longtext DEFAULT NULL,
389390
`group` varchar(50) DEFAULT 'user',
390391
`inventory` longtext DEFAULT NULL,
@@ -847,6 +848,9 @@ ALTER TABLE `users`
847848
ADD PRIMARY KEY (`identifier`),
848849
ADD UNIQUE KEY `id` (`id`);
849850

851+
ALTER TABLE `users`
852+
ADD UNIQUE KEY `unique_ssn` (`ssn`);
853+
850854
--
851855
-- Indexes for table `user_licenses`
852856
--

[core]/es_extended/es_extended.sql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ USE `es_extended`;
1010

1111
CREATE TABLE `users` (
1212
`identifier` VARCHAR(60) NOT NULL,
13+
`ssn` VARCHAR(11) NOT NULL,
1314
`accounts` LONGTEXT NULL DEFAULT NULL,
1415
`group` VARCHAR(50) NULL DEFAULT 'user',
1516
`inventory` LONGTEXT NULL DEFAULT NULL,
@@ -19,7 +20,8 @@ CREATE TABLE `users` (
1920
`metadata` LONGTEXT NULL DEFAULT NULL,
2021
`position` longtext NULL DEFAULT NULL,
2122

22-
PRIMARY KEY (`identifier`)
23+
PRIMARY KEY (`identifier`),
24+
UNIQUE KEY `unique_ssn` (`ssn`)
2325
) ENGINE=InnoDB;
2426

2527
CREATE TABLE `items` (

[core]/es_extended/server/classes/player.lua

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
---@param playerId number
2121
---@param identifier string
22+
---@param ssn string
2223
---@param group string
2324
---@param accounts table
2425
---@param inventory table
@@ -28,14 +29,15 @@
2829
---@param name string
2930
---@param coords table | vector4
3031
---@param metadata table
31-
function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, weight, job, loadout, name, coords, metadata)
32+
function CreateExtendedPlayer(playerId, identifier, ssn, group, accounts, inventory, weight, job, loadout, name, coords, metadata)
3233
---@class xPlayer
3334
local self = {}
3435

3536
self.accounts = accounts
3637
self.coords = coords
3738
self.group = group
3839
self.identifier = identifier
40+
self.ssn = ssn
3941
self.inventory = inventory
4042
self.job = job
4143
self.loadout = loadout
@@ -173,6 +175,11 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory,
173175
return self.identifier
174176
end
175177

178+
---@return string
179+
function self.getSSN()
180+
return self.ssn
181+
end
182+
176183
---@param newGroup string
177184
---@return nil
178185
function self.setGroup(newGroup)

[core]/es_extended/server/functions.lua

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,51 @@ function Core.IsPlayerAdmin(playerSrc)
804804
return xPlayer and Config.AdminGroups[xPlayer.getGroup()] or false
805805
end
806806

807+
-- Generates a unique 9-digit SSN in dashed format (XXX-XX-XXXX).
808+
---@return string
809+
function Core.generateSSN()
810+
local reservedSSNs = {
811+
["078-05-1120"] = true,
812+
["219-09-9999"] = true,
813+
["123-45-6789"] = true
814+
}
815+
816+
while true do
817+
-- Generate the first part (area number)
818+
local area = math.random(1, 899)
819+
820+
-- 666 is never assigned
821+
if area == 666 then
822+
goto continue
823+
end
824+
825+
-- Generate the second part (group number)
826+
local group = math.random(1, 99)
827+
828+
-- Generate the last part (serial number)
829+
local serial = math.random(1, 9999)
830+
831+
-- Skip reserved SSN range (987-65-4320..4329)
832+
if area == 987 and group == 65 and serial >= 4320 and serial <= 4329 then
833+
goto continue
834+
end
835+
836+
local candidate = string.format("%03d-%02d-%04d", area, group, serial)
837+
838+
if reservedSSNs[candidate] then
839+
goto continue
840+
end
841+
842+
local exists = MySQL.scalar.await("SELECT 1 FROM `users` WHERE `ssn` = ? LIMIT 1", { candidate })
843+
844+
if not exists then
845+
return candidate
846+
end
847+
848+
::continue::
849+
end
850+
end
851+
807852
---@param owner string
808853
---@param plate string
809854
---@param coords vector4

[core]/es_extended/server/main.lua

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ SetMapName("San Andreas")
22
SetGameType("ESX Legacy")
33

44
local oneSyncState = GetConvar("onesync", "off")
5-
local newPlayer = "INSERT INTO `users` SET `accounts` = ?, `identifier` = ?, `group` = ?"
6-
local loadPlayer = "SELECT `accounts`, `job`, `job_grade`, `group`, `position`, `inventory`, `skin`, `loadout`, `metadata`"
5+
local newPlayer = "INSERT INTO `users` SET `accounts` = ?, `identifier` = ?, `ssn` = ?, `group` = ?"
6+
local loadPlayer = "SELECT `accounts`, `ssn`, `job`, `job_grade`, `group`, `position`, `inventory`, `skin`, `loadout`, `metadata`"
77

88
if Config.Multichar then
99
newPlayer = newPlayer .. ", `firstname` = ?, `lastname` = ?, `dateofbirth` = ?, `sex` = ?, `height` = ?"
@@ -31,8 +31,9 @@ local function createESXPlayer(identifier, playerId, data)
3131
print(("[^2INFO^0] Player ^5%s^0 Has been granted admin permissions via ^5Ace Perms^7."):format(playerId))
3232
defaultGroup = "admin"
3333
end
34-
35-
local parameters = Config.Multichar and { json.encode(accounts), identifier, defaultGroup, data.firstname, data.lastname, data.dateofbirth, data.sex, data.height } or { json.encode(accounts), identifier, defaultGroup }
34+
local parameters = Config.Multichar and
35+
{ json.encode(accounts), identifier, Core.generateSSN(), defaultGroup, data.firstname, data.lastname, data.dateofbirth, data.sex, data.height }
36+
or { json.encode(accounts), identifier, Core.generateSSN(), defaultGroup }
3637

3738
if Config.StartingInventoryItems then
3839
table.insert(parameters, json.encode(Config.StartingInventoryItems))
@@ -216,6 +217,9 @@ function loadESXPlayer(identifier, playerId, isNew)
216217
}
217218
end
218219

220+
-- SSN
221+
userData.ssn = result.ssn
222+
219223
-- Job
220224
local job, grade = result.job, tostring(result.job_grade)
221225

@@ -308,7 +312,7 @@ function loadESXPlayer(identifier, playerId, isNew)
308312
userData.metadata = (result.metadata and result.metadata ~= "") and json.decode(result.metadata) or {}
309313

310314
-- xPlayer Creation
311-
local xPlayer = CreateExtendedPlayer(playerId, identifier, userData.group, userData.accounts, userData.inventory, userData.weight, userData.job, userData.loadout, GetPlayerName(playerId), userData.coords, userData.metadata)
315+
local xPlayer = CreateExtendedPlayer(playerId, identifier, userData.ssn, userData.group, userData.accounts, userData.inventory, userData.weight, userData.job, userData.loadout, GetPlayerName(playerId), userData.coords, userData.metadata)
312316

313317
GlobalState["playerCount"] = GlobalState["playerCount"] + 1
314318
ESX.Players[playerId] = xPlayer

0 commit comments

Comments
 (0)