Skip to content

Commit

Permalink
feat: in-house queue system
Browse files Browse the repository at this point in the history
  • Loading branch information
D4isDAVID committed Dec 9, 2023
1 parent 41f8380 commit af92d06
Show file tree
Hide file tree
Showing 4 changed files with 410 additions and 3 deletions.
161 changes: 160 additions & 1 deletion config/server.lua
Original file line number Diff line number Diff line change
Expand Up @@ -136,5 +136,164 @@ return {

removeSocietyMoney = function(accountName, payment)
return exports.qbx_management:RemoveMoney(accountName, payment)
end
end,

queue = {
---Amount of time to wait for remove a player from the queue after disconnecting while waiting.
timeoutSeconds = 30,

---Amount of time to wait for remove a player from the queue after disconnecting when installing server data.
joinTimeoutSeconds = 30,

clockEmojis = {
'🕛',
'🕒',
'🕕',
'🕘',
},

---Queue types from most prioritized to least prioritized.
---The first queue without a predicate function will be used as the default.
---If a player doesn't pass any predicates and a queue without a predicate does not exist they will not be let into the server unless player slots are available.
---@type QueueType[]
queueTypes = {
{ name = 'Priority Queue', color = 'good', predicate = function(source) return source % 2 == 0 --[[HasPermission(source, 'admin')]] end },
{ name = 'Regular Queue' },
},

---Generator function for the queue adaptive card.
---@param queueType QueueType the queue type the player is in
---@param currentPos integer the current position of the player in the queue
---@param queueSize integer the size of the queue
---@param waitingTime integer in seconds
---@param clockEmoji string
---@return table card queue adaptive card
generateCard = function(queueType, currentPos, queueSize, waitingTime, clockEmoji)
local serverName = GetConvar('sv_projectName', GetConvar('sv_hostname', 'Server'))
local minutes = math.floor(waitingTime / 60)
local seconds = waitingTime % 60
local timeDisplay = ('%02d:%02d'):format(minutes, seconds)

local progressColumn = {
type = 'Column',
width = 'stretch',
items = {},
}

local progressAmount = 7
local progressColumns = {}

for i = 1, progressAmount + 2 do
progressColumns[i] = table.clone(progressColumn)
progressColumns[i].items = {}
end

progressColumns[1].items[1] = {
type = 'TextBlock',
text = 'Queue',
horizontalAlignment = 'center',
size = 'extralarge',
weight = 'lighter',
color = 'good',
}
for i = 1, progressAmount do
progressColumns[i + 1].items[1] = {
type = 'TextBlock',
text = '',
horizontalAlignment = 'center',
size = 'extralarge',
weight = 'lighter',
color = 'accent',
}
end
progressColumns[progressAmount + 2].items[1] = {
type = 'TextBlock',
text = 'Server',
horizontalAlignment = 'center',
size = 'extralarge',
weight = 'lighter',
color = 'good',
}

local playerColumn = currentPos == 1 and progressAmount or (progressAmount - math.ceil(currentPos / (queueSize / progressAmount)) + 1)
progressColumns[playerColumn + 1].items[1] = {
type = 'TextBlock',
text = 'You',
horizontalAlignment = 'center',
size = 'extralarge',
weight = 'lighter',
color = 'good',
}

return {
type = 'AdaptiveCard',
version = '1.6',
body = {
{
type = 'TextBlock',
text = 'In Line',
horizontalAlignment = 'center',
size = 'large',
weight = 'bolder',
},
{
type = 'TextBlock',
text = ('Joining %s'):format(serverName),
spacing = 'none',
horizontalAlignment = 'center',
size = 'medium',
weight = 'bolder',
},
{
type = 'ColumnSet',
spacing = 'large',
columns = progressColumns,
},
{
type = 'ColumnSet',
spacing = 'large',
columns = {
{
type = 'Column',
width = 'stretch',
items = {
{
type = 'TextBlock',
text = queueType.name,
color = queueType.color,
size = 'medium',
}
},
},
{
type = 'Column',
width = 'stretch',
items = {
{
type = 'TextBlock',
text = ('%d/%d'):format(currentPos, queueSize),
horizontalAlignment = 'center',
color = 'good',
size = 'medium',
}
},
},
{
type = 'Column',
width = 'stretch',
items = {
{
type = 'TextBlock',
text = ('%s %s'):format(timeDisplay, clockEmoji),
horizontalAlignment = 'right',
size = 'medium',
}
},
},
},
},
},
}
end,
},
}
3 changes: 2 additions & 1 deletion locale/en.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ local Translations = {
tp_error = 'Error While Teleporting.',
connecting_database_timeout = 'Connection to database timed out. (Is the SQL server on?)',
connecting_error = 'An error occurred while connecting to the server. (Check your server console)',
no_match_character_registration = 'Anything other than letters aren\'t allowed, trailing whitespaces aren\'t allowed either and words must start with a capital letter in input fields. You can however add words with spaces inbetween.'
no_match_character_registration = 'Anything other than letters aren\'t allowed, trailing whitespaces aren\'t allowed either and words must start with a capital letter in input fields. You can however add words with spaces inbetween.',
no_queue = 'You were not let in any queue.',
},
success = {
server_opened = 'The server has been opened',
Expand Down
10 changes: 9 additions & 1 deletion server/events.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
local serverConfig = require 'config.server'.server
local loggingConfig = require 'config.server'.logging
local logger = require 'modules.logger'
local queue = require 'server.queue'

-- Event Handler

Expand All @@ -19,6 +20,9 @@ AddEventHandler('playerJoining', function()
local src = source --[[@as string]]
local license = GetPlayerIdentifierByType(src, 'license2') or GetPlayerIdentifierByType(src, 'license')
if not license then return end
if queue then
queue.registerPlayerJoined(license)
end
if usedLicenses[license] then
Wait(0) -- mandatory wait for the drop reason to show up
DropPlayer(src, Lang:t('error.duplicate_license'))
Expand Down Expand Up @@ -108,7 +112,11 @@ local function onPlayerConnecting(name, _, deferrals)
-- wait for database to finish
databasePromise:next(function()
deferrals.update(string.format(Lang:t('info.join_server'), name))
deferrals.done()
if not queue then
deferrals.done()
return
end
queue.enqueue(src --[[@as Source]], license, deferrals)
end, function(err)
deferrals.done(Lang:t('error.connecting_error'))
lib.print.error(err)
Expand Down
Loading

0 comments on commit af92d06

Please sign in to comment.