0% found this document useful (0 votes)
132 views17 pages

FiveM Queue System Implementation

This document defines code for managing a queue system in a multiplayer game. It includes: 1. Functions for adding and removing players from the queue, checking if a player is in the queue, and getting information about the queue and players. 2. Code to assign priority levels to players based on admin-assigned priorities stored in a database, and to track temporary priority levels. 3. Event handlers for admin commands to add, update, or remove a player's priority level by interacting with the database. The queue system manages lists of players currently connecting and in the queue, tracking information like priority levels, time waited, and callbacks.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
132 views17 pages

FiveM Queue System Implementation

This document defines code for managing a queue system in a multiplayer game. It includes: 1. Functions for adding and removing players from the queue, checking if a player is in the queue, and getting information about the queue and players. 2. Code to assign priority levels to players based on admin-assigned priorities stored in a database, and to track temporary priority levels. 3. Event handlers for admin commands to add, update, or remove a player's priority level by interacting with the database. The queue system manages lists of players currently connecting and in the queue, tracking information like priority levels, time waited, and callbacks.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

ESX = nil

TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)

if not IsDuplicityVersion() then


[Link](function()
while true do
[Link](0)
if NetworkIsSessionStarted() then
TriggerServerEvent("Queue:playerActivated")
return
end
end
end)
return
end

local Queue = {}

[Link] = GetConvarInt("sv_maxclients")
[Link] = GetConvar("sv_debugqueue", "true") == "true" and true or false
[Link] = GetConvar("sv_displayqueue", "true") == "true" and true or
false
[Link] = 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 tostring = tostring


local tonumber = tonumber
local ipairs = ipairs
local pairs = pairs
local print = print
local string_len = [Link]
local string_sub = [Link]
local string_format = [Link]
local string_lower = [Link]
local math_abs = [Link]
local math_floor = [Link]
local math_random = [Link]
local os_time = [Link]
local table_insert = [Link]
local table_remove = [Link]

[Link] = [Link] ~= "default FXServer" and


[Link] or false

local SqlPriorities = {}
for id, power in pairs([Link]) do
_Queue.Priority[string_lower(id)] = power
end

[Link](function ()
[Link]("SELECT * FROM hacker_priority",{}, function(data)
if data ~= nil then
for k,v in pairs(data) do
_Queue.Priority[string_lower([Link])] = [Link]
end
Wait(400)
debug('Priority List Loaded')
end
end)
end)

local name = nil


RegisterServerEvent('hacker_queue:GetOfflineInfo')
AddEventHandler('hacker_queue:GetOfflineInfo', function(id)
local _source = source
name = id
end)

[Link]('hacker_queue:GetPriorities', function(source, cb)


local data = [Link]("SELECT * FROM `users` WHERE
LOWER(users.`name`) LIKE @name",{['@name'] =
"%"..[Link](tostring(name)).."%"})
cb(data)
name = nil
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 < [Link]() then
expiration = [Link]()+expiration
end
local base = [Link]("SELECT name FROM `users` WHERE identifier
= @identifier",{['@identifier'] = steam})
local data = [Link]("SELECT * FROM `hacker_priority` WHERE
SteamID = @SteamID ",{['@SteamID'] = steam})
local name
if #base > 0 then
name = base[1].name
end
if #data < 1 then
[Link]('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..'```', [Link](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
[Link]('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..'```', [Link](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
[Link]("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..']```', [Link](1000,5000))
end)
[Link]('DELETE FROM hacker_priority WHERE SteamID = @SteamID',
{
['@SteamID'] = steam
},function(change)
if change > 0 then
[Link](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

function Queue:IsInQueue(ids, rtnTbl, bySource, connecting)


local connList = Queue:GetConnectingList()
local queueList = Queue:GetQueueList()

for genericKey1, genericValue1 in ipairs(connecting and connList or queueList)


do
local inQueue = false

if not bySource then


for genericKey2, genericValue2 in ipairs([Link]) do
if inQueue then break end

for genericKey3, genericValue3 in ipairs(ids) do


if genericValue3 == genericValue2 then inQueue = true break end
end
end
else
inQueue = ids == [Link]
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)

if prioList[id] then prio = prioList[id] break end

if string_sub(id, 1, 5) == "steam" then


local steamid = Queue:HexIdToSteamId(id)
if prioList[steamid] then prio = prioList[steamid] break end
end
end

if tempPower or prio then


if tempPower and prio then
return tempPower > prio and tempPower or prio
else
return tempPower or prio
end
end

return false
end

function Queue:HasTempPriority(ids)
local tmpPrio = Queue:GetTempPriorityList()

for _, id in pairs(ids) do
id = string_lower(id)

if tmpPrio[id] then return tmpPrio[id].power, tmpPrio[id].endTime, id end

if string_sub(id, 1, 5) == "steam" then


local steamid = Queue:HexIdToSteamId(id)
if tmpPrio[steamid] then return tmpPrio[steamid].power,
tmpPrio[steamid].endTime, id end
end
end

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
}

local _pos = false


local queueCount = Queue:GetSize() + 1
local queueList = Queue:GetQueueList()

for pos, data in ipairs(queueList) do


if [Link] then
if not [Link] then
_pos = pos
else
if [Link] > [Link] then
_pos = pos
end
end

if _pos then
break
end
end
end

if not _pos then


_pos = Queue:GetSize() + 1
end

table_insert(queueList, _pos, tmp)


end

function Queue:RemoveFromQueue(ids, bySource, byIndex)


local queueList = Queue:GetQueueList()

if byIndex then
if queueList[byIndex] then
table_remove(queueList, byIndex)
end

return
end

if Queue:IsInQueue(ids, false, bySource) then


local pos, data = Queue:IsInQueue(ids, true, bySource)
table_remove(queueList, pos)
end
end
function Queue:TempSize()
local count = 0

for _pos, data in pairs(Queue:GetQueueList()) do


if Queue:HasTempPriority([Link]) then count = count +1 end
end

return count > 0 and count or false


end

function Queue:IsInConnecting(ids, bySource, refresh)


local inConnecting, tbl = Queue:IsInQueue(ids, refresh and true or false,
bySource and true or false, true)

if not inConnecting then return false end

if refresh and inConnecting and tbl then


Queue:GetConnectingList()[inConnecting].timeout = 0
end

return true
end

function Queue:RemoveFromConnecting(ids, bySource, byIndex)


local connList = Queue:GetConnectingList()

if byIndex then
if connList[byIndex] then
table_remove(connList, byIndex)
end

return
end

for genericKey1, genericValue1 in ipairs(connList) do


local inConnecting = false

if not bySource then


for genericKey2, genericValue2 in ipairs([Link]) do
if inConnecting then break end

for genericKey3, genericValue3 in ipairs(ids) do


if genericValue3 == genericValue2 then inConnecting = true
break end
end
end
else
inConnecting = ids == [Link]
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([Link])
Queue:RemoveFromConnecting(ids)
Queue:RemoveFromQueue(ids)
end
local connList = Queue:GetConnectingList()

if Queue:ConnectingSize() + Queue:GetPlayerCount() + 1 > [Link] then


remove() return false end

if ids[1] == "debug" then


table_insert(connList, {source = ids[1], ids = ids, name = ids[1],
firstconnect = ids[1], priority = ids[1], timeout = 0})
return true
end

if Queue:IsInConnecting(ids) then Queue:RemoveFromConnecting(ids) end

local pos, data = Queue:IsInQueue(ids, true)


if not ignorePos and (not pos or pos > 1) then remove() return false end

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

if ids and #ids > 1 then


for k, id in ipairs(ids) do
if string_sub(id, 1, 3) == "ip:" and not Queue:IsPriority({id}) then
table_remove(ids, k) end
end
end

return ids
end

function Queue:AddPriority(id, power, temp)


if not id then return false end

if type(id) == "table" then


for _id, power in pairs(id) do
if _id and type(_id) == "string" and power and type(power) == "number"
then
Queue:GetPriorityList()[_id] = power
else
return false
end
end

return true
end

power = (power and type(power) == "number") and power or 10

if temp then
local tempPower, tempEnd, tempId = Queue:HasTempPriority({id})
id = tempId or id

Queue:GetTempPriorityList()[string_lower(id)] = {power = power, endTime =


os_time() + temp}
else
Queue:GetPriorityList()[string_lower(id)] = power
end

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:UpdatePosData(src, ids, deferrals)


local pos, data = Queue:IsInQueue(ids, true)
[Link] = src
[Link] = ids
[Link] = 0
[Link] = os_time()
[Link] = GetPlayerName(src)
[Link] = deferrals
end

function Queue:NotFull(firstJoin)
local canJoin = Queue:GetPlayerCount() + Queue:ConnectingSize() <
[Link]
if firstJoin and canJoin then canJoin = Queue:GetSize() <= 1 end
return canJoin
end

function Queue:SetPos(ids, newPos)


if newPos <= 0 or newPos > Queue:GetSize() then return false end

local pos, data = Queue:IsInQueue(ids, true)


local queueList = Queue:GetQueueList()

table_remove(queueList, pos)
table_insert(queueList, newPos, data)
end

function Queue:CanJoin(src, cb)


local allow = true

for _, data in ipairs(_Queue.JoinCbs) do


local await = true

[Link](src, function(reason)
if reason and type(reason) == "string" then allow = false cb(reason)
end
await = false
end)

while await do [Link](0) end

if not allow then return end


end

if allow then cb(false) end


end

function Queue:OnJoin(cb, resource)


if not cb then return end

local tmp = {resource = resource, func = cb}


table_insert(_Queue.JoinCbs, tmp)
end

exports("GetQueueExports", function()
return Queue
end)

local function playerConnect(name, setKickReason, deferrals)


local src = source
local ids = Queue:GetIds(src)
local name = GetPlayerName(src)
local connectTime = os_time()
local connecting = true

[Link]()

[Link](function()
while connecting do
[Link](100)
if not connecting then return end
[Link]([Link])
end
end)
if [Link] then
local prio = _Queue.Priority[ids[1]]
if prio == nil then
prio = 0
end
debug('Player: '..GetPlayerName(source)..' Connect With Priority Power:
'..prio)
end
[Link](500)

local function done(msg, _deferrals)


connecting = false

local deferrals = _deferrals or deferrals

if msg then [Link](tostring(msg) or "") end


[Link](500)

if not msg then


[Link]()
--[[ if [Link] then Queue:AddPriority(ids[1],
[Link], [Link]) end ]]
else
[Link](tostring(msg) or "") CancelEvent()
end

return
end

local function update(msg, _deferrals)


local deferrals = _deferrals or deferrals
connecting = false
[Link](tostring(msg) or "")
end

if not ids then


-- prevent joining
done([Link])
CancelEvent()
return
end

if not Queue:IsSteamRunning(src) then


done([Link])
CancelEvent()
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)

while allow == nil do [Link](0) end


if not allow then return end

if [Link] and not Queue:IsPriority(ids) then


done([Link]) return end

local rejoined = false


if Queue:IsInConnecting(ids, false, true) then
Queue:RemoveFromConnecting(ids)

if Queue:NotFull() then
-- let them in the server

if not Queue:IsInQueue(ids) then


Queue:AddToQueue(ids, connectTime, name, src, deferrals)
end

local added = Queue:AddToConnecting(ids, true, true, done)


if not added then CancelEvent() return end
done()

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

local pos, data = Queue:IsInQueue(ids, true)

if not pos or not data then


done([Link] .. " [1]")

Queue:RemoveFromQueue(ids)
Queue:RemoveFromConnecting(ids)

CancelEvent()
return
end

if Queue:NotFull(true) and _Queue.JoinDelay <= GetGameTimer() then


-- let them in the server
local added = Queue:AddToConnecting(ids, true, true, done)
if not added then CancelEvent() return end
done()
return
end

update(string_format([Link] .. ((Queue:TempSize() and false)


and " (" .. Queue:TempSize() .. " temp)" or "00:00:00"), pos, Queue:GetSize(), ""))

if rejoined then return end

while true do
[Link](500)

local pos, data = Queue:IsInQueue(ids, true)

local function remove(msg)


if data then
if msg then
update(msg, [Link])
end

Queue:RemoveFromQueue([Link], true)
Queue:RemoveFromConnecting([Link], true)
else
Queue:RemoveFromQueue(ids)
Queue:RemoveFromConnecting(ids)
end
end

if not data or not [Link] or not [Link] or not pos then


remove("[Queue] Removed from queue, queue data invalid :(")
return
end

local endPoint = GetPlayerEndpoint([Link])


if not endPoint then [Link] = [Link] + 0.5 else [Link] =
0 end

if [Link] >= 90 and os_time() - connectTime > 5 then


remove("[Queue] Removed due to timeout")
return
end

if pos <= 1 and Queue:NotFull() and _Queue.JoinDelay <= GetGameTimer() then


-- let them in the server
local added = Queue:AddToConnecting(ids)

update([Link], [Link])
[Link](500)

if not added then


done([Link])
CancelEvent()
return
end

done(nil, [Link])

--[[ if [Link] then Queue:AddPriority(ids[1],


[Link], [Link]) end ]]

Queue:RemoveFromQueue(ids)
return
end

local seconds = [Link]()


local qTime = string_format("%02d", math_floor((seconds % 86400) /
3600)) .. ":" .. string_format("%02d", math_floor((seconds % 3600) / 60)) .. ":" ..
string_format("%02d", math_floor(seconds % 60))
local msg = string_format([Link] .. ((Queue:TempSize() and
false) and " (" .. Queue:TempSize() .. " temp)" or ""), pos, Queue:GetSize(),
qTime)
update(msg, [Link])
end
end
AddEventHandler("playerConnecting", playerConnect)
[Link](function()
local function remove(data, pos, msg)
if data and [Link] then
Queue:RemoveFromQueue([Link], true)
Queue:RemoveFromConnecting([Link], true)
elseif pos then
table_remove(Queue:GetQueueList(), pos)
end
end

while true do
[Link](1000)

local i = 1

while i <= Queue:ConnectingSize() do


local data = Queue:GetConnectingList()[i]

local endPoint = GetPlayerEndpoint([Link])

[Link] = [Link] + 1

if (([Link] >= 300 and not endPoint) or [Link] >= 600) and
[Link] ~= "debug" and os_time() - [Link] > 5 then
remove(data)
else
i = i + 1
end
end

for id, data in pairs(Queue:GetTempPriorityList()) do


if os_time() >= [Link] then
Queue:GetTempPriorityList()[id] = nil
end
end

[Link] = GetConvarInt("sv_maxclients")
[Link] = GetConvar("sv_debugqueue", "true") == "true" and true or
false
[Link] = GetConvar("sv_displayqueue", "true") == "true" and
true or false

local qCount = Queue:GetSize()

if [Link] then
if [Link] then
SetConvar("sv_hostname", (qCount > 0 and "[" .. tostring(qCount) ..
"] " or "") .. [Link])
else
[Link] = GetConvar("sv_hostname")
[Link] = [Link] ~= "default FXServer" and
[Link] or false
end
end
end
end)

RegisterServerEvent("Queue:playerActivated")
AddEventHandler("Queue:playerActivated", function()
local src = source
local ids = Queue:GetIds(src)

if not Queue:GetPlayerList()[src] then


_Queue.PlayerCount = Queue:GetPlayerCount() + 1
Queue:GetPlayerList()[src] = true
Queue:RemoveFromQueue(ids)
Queue:RemoveFromConnecting(ids)
end
end)

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 [Link] then Queue:AddPriority(ids[1],
[Link], [Link]) end ]]
end
end)

AddEventHandler("onResourceStop", function(resource)
if [Link] and [Link] and resource ==
GetCurrentResourceName() then SetConvar("sv_hostname", [Link]) end

for k, data in ipairs(_Queue.JoinCbs) do


if [Link] == resource then
table_remove(_Queue.JoinCbs, k)
end
end
end)

if [Link] then
AddEventHandler("onResourceStarting", function(resource)
if resource == "hardcap" then CancelEvent() return end
end)
StopResource("hardcap")
end

local testAdds = 0
local commands = {}

[Link] = function()
Queue:AddToQueue({"steam:00000000"..testAdds}, os_time(), "TestAdd: " ..
testAdds, "debug")
testAdds = testAdds + 1
end
[Link] = 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

[Link] = function()

for pos, data in ipairs(Queue:GetQueueList()) do


end
end

[Link] = function()
Queue:AddToConnecting({"debug"})
end

[Link] = 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

[Link] = function()
for pos, data in ipairs(Queue:GetConnectingList()) do
end
end

[Link] = function()
for k, joined in pairs(Queue:GetPlayerList()) do
end
end

[Link] = function()
for id, power in pairs(Queue:GetPriorityList()) do
end
end

[Link] = function()

end

[Link] = function()

for k, data in pairs(Queue:GetTempPriorityList()) do


end
end

[Link] = function(args)
if not args[1] then return end

Queue:GetTempPriorityList()[args[1]] = nil
end

[Link] = function(args)
if not args[1] or not args[2] then return end

args[1], args[2] = tonumber(args[1]), tonumber(args[2])


local data = Queue:GetQueueList()[args[1]]

Queue:SetPos([Link], args[2])
end

[Link] = function(args)
if not args[1] or not args[2] or not args[3] then return end
args[1] = tonumber(args[1])

local num = tonumber(args[3])


local data = Queue:GetQueueList()[args[1]]

if args[2] == "queuetime" then


local time = [Link]()
local dif = time - num

[Link] = [Link] + dif


[Link] = function() return (os_time() - [Link]) end
else
data[args[2]] = num and num or args[3]
end
end

[Link] = function()
for cmd, func in pairs(commands) do
end
end

AddEventHandler("rconCommand", function(command, args)


if command == "queue" and commands[args[1]] then
command = args[1]
table_remove(args, 1)
commands[command](args)
CancelEvent()
end
end)

You might also like