SV Queue
SV Queue
local Queue = {}
Queue.MaxPlayers = GetConvarInt("sv_maxclients")
Queue.Debug = GetConvar("sv_debugqueue", "true") == "true" and true or false
Queue.DisplayQueue = GetConvar("sv_displayqueue", "true") == "true" and true or
false
Queue.InitHostName = GetConvar("sv_hostname")
-- This is needed because msgpack will break when tables are too large
local _Queue = {}
_Queue.QueueList = {}
_Queue.PlayerList = {}
_Queue.PlayerCount = 0
_Queue.Priority = {}
_Queue.Connecting = {}
_Queue.JoinCbs = {}
_Queue.TempPriority = {}
_Queue.JoinDelay = GetGameTimer() + 2500
local SqlPriorities = {}
for id, power in pairs(Config.Priority) do
_Queue.Priority[string_lower(id)] = power
end
MySQL.ready(function ()
MySQL.Async.fetchAll("SELECT * FROM hacker_priority",{}, function(data)
if data ~= nil then
for k,v in pairs(data) do
_Queue.Priority[string_lower(v.SteamID)] = v.Power
end
Wait(400)
debug('Priority List Loaded')
end
end)
end)
RegisterServerEvent('hacker_queue:addpriority')
AddEventHandler('hacker_queue:addpriority', function(steam,days,power)
local _source = source
local identifier = GetPlayerIdentifier(_source)
local expiration = days * 86400
if expiration < os.time() then
expiration = os.time()+expiration
end
local base = MySQL.Sync.fetchAll("SELECT name FROM `users` WHERE identifier
= @identifier",{['@identifier'] = steam})
local data = MySQL.Sync.fetchAll("SELECT * FROM `hacker_priority` WHERE
SteamID = @SteamID ",{['@SteamID'] = steam})
local name
if #base > 0 then
name = base[1].name
end
if #data < 1 then
MySQL.Async.execute('INSERT INTO hacker_priority (SteamID, Power,
Adder, Expire, SteamName) VALUES (@SteamID, @Power, @Adder, @Expire, @SteamName)',
{
['@SteamID'] = steam,
['@Power'] = tonumber(power),
['@Adder'] = identifier,
['@Expire'] = expiration,
['@SteamName'] = name,
}, function (change)
if change > 0 then
sendToDiscord('Add Priority', '**Staff Name:**\
n```'..GetPlayerName(_source)..'[SteamID:'..identifier..']```\n**Add Priority to
Player:**\n```'..name..'[SteamID:'..steam..']```\n**Days:**\n```'..days..'```\
n**Power:**\n```'..power..'```', math.random(1000,5000))
end
end)
_Queue.Priority[string_lower(steam)] = tonumber(power)
TriggerClientEvent('esx:showNotification', _source, '~bold~~r~Priority
~r~Succeffully to added!\n~y~PlayerName: ~w~'..name)
else
MySQL.Async.execute('UPDATE hacker_priority SET Power = @Power, Expire
= @Expire, SteamName = @SteamName, Adder = @Adder WHERE SteamID = @SteamID',
{
['@Adder'] = identifier,
['@SteamName'] = name,
['@SteamID'] = steam,
['@Power'] = power,
['@Expire'] = expiration
}, function(change)
if change > 0 then
sendToDiscord('Update Priority', '**Staff Name:**\
n```'..GetPlayerName(_source)..'[SteamID:'..identifier..']```\n**Update Priority to
Player:**\n```'..name..'[SteamID:'..steam..']```\n**Days:**\n```'..days..'```\
n**Power:**\n```'..power..'```', math.random(1000,5000))
end
end)
_Queue.Priority[string_lower(steam)] = tonumber(power)
TriggerClientEvent('esx:showNotification', _source, '~bold~~r~Priority
~r~Succeffully Updated!\n~y~PlayerName: ~w~'..name)
end
end)
RegisterServerEvent('hacker_queue:removepriority')
AddEventHandler('hacker_queue:removepriority', function(steam)
local _source = source
MySQL.Async.fetchAll("SELECT * FROM hacker_priority WHERE SteamID =
@SteamID",{['@SteamID'] = steam}, function(data)
sendToDiscord('Remove Priority', '**Staff Name:**\
n```'..GetPlayerName(_source)..'[SteamID:'..GetPlayerIdentifier(_source)..']```\
n**Remove Priority to Player:**\
n```'..data[1].SteamName..'[SteamID:'..steam..']```', math.random(1000,5000))
end)
MySQL.Async.execute('DELETE FROM hacker_priority WHERE SteamID = @SteamID',
{
['@SteamID'] = steam
},function(change)
if change > 0 then
Queue.RemovePriority(string_lower(steam))
end
end)
end)
function Queue:HexIdToSteamId(hexId)
local cid = math_floor(tonumber(string_sub(hexId, 7), 16))
local steam64 = math_floor(tonumber(string_sub( cid, 2)))
local a = steam64 % 2 == 0 and 0 or 1
local b = math_floor(math_abs(6561197960265728 - steam64 - a) / 2)
local sid = "steam_0:"..a..":"..(a == 1 and b -1 or b)
return sid
end
function Queue:IsSteamRunning(src)
for _, id in ipairs(GetPlayerIdentifiers(src)) do
if string_sub(id, 1, 5) == "steam" then
return true
end
end
return false
end
function Queue:GetPlayerCount()
return _Queue.PlayerCount
end
function Queue:GetSize()
return #_Queue.QueueList
end
function Queue:ConnectingSize()
return #_Queue.Connecting
end
function Queue:GetQueueList()
return _Queue.QueueList
end
function Queue:GetPriorityList()
return _Queue.Priority
end
function Queue:GetPlayerList()
return _Queue.PlayerList
end
function Queue:GetTempPriorityList()
return _Queue.TempPriority
end
function Queue:GetConnectingList()
return _Queue.Connecting
end
if inQueue then
if rtnTbl then
return genericKey1, connecting and connList[genericKey1] or
queueList[genericKey1]
end
return true
end
end
return false
end
function Queue:IsPriority(ids)
local prio = false
local tempPower, tempEnd = Queue:HasTempPriority(ids)
local prioList = Queue:GetPriorityList()
for _, id in ipairs(ids) do
id = string_lower(id)
return false
end
function Queue:HasTempPriority(ids)
local tmpPrio = Queue:GetTempPriorityList()
for _, id in pairs(ids) do
id = string_lower(id)
return false
end
function Queue:AddToQueue(ids, connectTime, name, src, deferrals)
if Queue:IsInQueue(ids) then return end
local tmp = {
source = src,
ids = ids,
name = name,
priority = Queue:IsPriority(ids) or (src == "debug" and math_random(0,
15)),
timeout = 0,
deferrals = deferrals,
firstconnect = connectTime,
queuetime = function() return (os_time() - connectTime) end
}
if _pos then
break
end
end
end
if byIndex then
if queueList[byIndex] then
table_remove(queueList, byIndex)
end
return
end
return true
end
if byIndex then
if connList[byIndex] then
table_remove(connList, byIndex)
end
return
end
if inConnecting then
table_remove(connList, genericKey1)
return true
end
end
return false
end
function Queue:AddToConnecting(ids, ignorePos, autoRemove, done)
local function remove()
if not autoRemove then return end
done(Config.Connect.connecterror)
Queue:RemoveFromConnecting(ids)
Queue:RemoveFromQueue(ids)
end
local connList = Queue:GetConnectingList()
table_insert(connList, data)
Queue:RemoveFromQueue(ids)
return true
end
function Queue:GetIds(src)
local ids = GetPlayerIdentifiers(src)
local ip = GetPlayerEndpoint(src)
ids = (ids and ids[1]) and ids or (ip and {"ip:" .. ip} or false)
ids = ids ~= nil and ids or false
return ids
end
return true
end
if temp then
local tempPower, tempEnd, tempId = Queue:HasTempPriority({id})
id = tempId or id
return true
end
function Queue:RemovePriority(id)
if not id then return false end
id = string_lower(id)
Queue:GetPriorityList()[id] = nil
return true
end
function Queue:NotFull(firstJoin)
local canJoin = Queue:GetPlayerCount() + Queue:ConnectingSize() <
Queue.MaxPlayers
if firstJoin and canJoin then canJoin = Queue:GetSize() <= 1 end
return canJoin
end
table_remove(queueList, pos)
table_insert(queueList, newPos, data)
end
data.func(src, function(reason)
if reason and type(reason) == "string" then allow = false cb(reason)
end
await = false
end)
exports("GetQueueExports", function()
return Queue
end)
deferrals.defer()
Citizen.CreateThread(function()
while connecting do
Citizen.Wait(100)
if not connecting then return end
deferrals.update(Config.Connect.connect)
end
end)
if Config.ConnectLog then
local prio = _Queue.Priority[ids[1]]
if prio == nil then
prio = 0
end
debug('Player: '..GetPlayerName(source)..' Connect With Priority Power:
'..prio)
end
Citizen.Wait(500)
return
end
local allow
Queue:CanJoin(src, function(reason)
if reason == nil or allow ~= nil then return end
if reason == false or #_Queue.JoinCbs <= 0 then allow = true return end
if reason then
-- prevent joining
allow = false
done(reason and tostring(reason) or "You were blocked from joining")
Queue:RemoveFromQueue(ids)
Queue:RemoveFromConnecting(ids)
CancelEvent()
return
end
allow = true
end)
if Queue:NotFull() then
-- let them in the server
return
else
rejoined = true
end
end
if Queue:IsInQueue(ids) then
rejoined = true
Queue:UpdatePosData(src, ids, deferrals)
else
Queue:AddToQueue(ids, connectTime, name, src, deferrals)
if rejoined then
Queue:SetPos(ids, 1)
rejoined = false
end
end
Queue:RemoveFromQueue(ids)
Queue:RemoveFromConnecting(ids)
CancelEvent()
return
end
while true do
Citizen.Wait(500)
Queue:RemoveFromQueue(data.source, true)
Queue:RemoveFromConnecting(data.source, true)
else
Queue:RemoveFromQueue(ids)
Queue:RemoveFromConnecting(ids)
end
end
update(Config.Connect.join, data.deferrals)
Citizen.Wait(500)
done(nil, data.deferrals)
Queue:RemoveFromQueue(ids)
return
end
while true do
Citizen.Wait(1000)
local i = 1
data.timeout = data.timeout + 1
if ((data.timeout >= 300 and not endPoint) or data.timeout >= 600) and
data.source ~= "debug" and os_time() - data.firstconnect > 5 then
remove(data)
else
i = i + 1
end
end
Queue.MaxPlayers = GetConvarInt("sv_maxclients")
Queue.Debug = GetConvar("sv_debugqueue", "true") == "true" and true or
false
Queue.DisplayQueue = GetConvar("sv_displayqueue", "true") == "true" and
true or false
if Queue.DisplayQueue then
if Queue.InitHostName then
SetConvar("sv_hostname", (qCount > 0 and "[" .. tostring(qCount) ..
"] " or "") .. Queue.InitHostName)
else
Queue.InitHostName = GetConvar("sv_hostname")
Queue.InitHostName = Queue.InitHostName ~= "default FXServer" and
Queue.InitHostName or false
end
end
end
end)
RegisterServerEvent("Queue:playerActivated")
AddEventHandler("Queue:playerActivated", function()
local src = source
local ids = Queue:GetIds(src)
AddEventHandler("playerDropped", function()
local src = source
local ids = Queue:GetIds(src)
if Queue:GetPlayerList()[src] then
_Queue.PlayerCount = Queue:GetPlayerCount() - 1
Queue:GetPlayerList()[src] = nil
Queue:RemoveFromQueue(ids)
Queue:RemoveFromConnecting(ids)
--[[ if Config.EnableGrace then Queue:AddPriority(ids[1],
Config.GracePower, Config.GraceTime) end ]]
end
end)
AddEventHandler("onResourceStop", function(resource)
if Queue.DisplayQueue and Queue.InitHostName and resource ==
GetCurrentResourceName() then SetConvar("sv_hostname", Queue.InitHostName) end
if Config.DisableHardCap then
AddEventHandler("onResourceStarting", function(resource)
if resource == "hardcap" then CancelEvent() return end
end)
StopResource("hardcap")
end
local testAdds = 0
local commands = {}
commands.addq = function()
Queue:AddToQueue({"steam:00000000"..testAdds}, os_time(), "TestAdd: " ..
testAdds, "debug")
testAdds = testAdds + 1
end
commands.removeq = function(args)
args[1] = tonumber(args[1])
local name = Queue:GetQueueList()[args[1]] and Queue:GetQueueList()
[args[1]].name or nil
Queue:RemoveFromQueue(nil, nil, args[1])
end
commands.printq = function()
commands.addc = function()
Queue:AddToConnecting({"debug"})
end
commands.removec = function(args)
args[1] = tonumber(args[1])
local name = Queue:GetConnectingList()[args[1]] and Queue:GetConnectingList()
[args[1]].name or nil
Queue:RemoveFromConnecting(nil, nil, args[1])
end
commands.printc = function()
for pos, data in ipairs(Queue:GetConnectingList()) do
end
end
commands.printl = function()
for k, joined in pairs(Queue:GetPlayerList()) do
end
end
commands.printp = function()
for id, power in pairs(Queue:GetPriorityList()) do
end
end
commands.printcount = function()
end
commands.printtp = function()
commands.removetp = function(args)
if not args[1] then return end
Queue:GetTempPriorityList()[args[1]] = nil
end
commands.setpos = function(args)
if not args[1] or not args[2] then return end
Queue:SetPos(data.ids, args[2])
end
commands.setdata = function(args)
if not args[1] or not args[2] or not args[3] then return end
args[1] = tonumber(args[1])
commands.commands = function()
for cmd, func in pairs(commands) do
end
end