Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: in-house queue system #279

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 167 additions & 0 deletions config/queue.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
return {
---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 HasPermission(source, 'admin') end },
{ name = 'Regular Queue' },
},

---@class CardParams
---@field queueType QueueType the queue type the player is in
---@field currentPos integer the current position of the player in the queue
---@field queueSize integer the size of the queue
---@field waitingTime integer in seconds
---@field clockEmoji string

---Generator function for the queue adaptive card.
---@param params CardParams
---@return table card queue adaptive card
generateCard = function(params)
local queueType = params.queueType
local currentPos = params.currentPos
local queueSize = params.queueSize
local waitingTime = params.waitingTime
local clockEmoji = params.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,
}
4 changes: 2 additions & 2 deletions config/server.lua
Original file line number Diff line number Diff line change
Expand Up @@ -136,5 +136,5 @@ return {

removeSocietyMoney = function(accountName, payment)
return exports.qbx_management:RemoveMoney(accountName, payment)
end
}
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
Loading