FXServer 584 (Windows) Broke Our Queue!

I’m one of the developers for RPFirst, and we had a fairly well working queue system in place pre-version 584. Once we updated, our queue would no longer function.

Our queue used GetLastPlayerMsg() to detect when a player dropped connection/canceled connecting. With the new messaging method, the client doesn’t poll the server, which results in the server returning int32 max value for GetLastPlayerMsg() after 2 minutes, which is not nearly long enough for our needs. We frequently have people sitting in queue for 30+ minutes.

Perhaps I’m missing something, but is there a way to either change this 2 minute timeout to something larger, or some sort of workaround I can code to properly detect if someone disconnects without needing GetLastPlayerMsg()?

Much appreciated!

Try updating to any artifact 585+. I remember 584 having a critical bug for especially Windows 7 users.

That didn’t do it unfortunately. Tried 585 and 592, the GetPlayerLastMsg() call is still returning int32 max value after 2 minutes.

Use a different queue resource.

EasyAdmin. is a stable script.

Is this actually needed functionality - i.e. does your system need to know this for management of state to work? If so, we might be able to provide compatibility for this by faking out the client seen time at regular intervals, though it’s better to think about exposing cancellation callbacks and implementing those in proper ‘aware’ queue systems.

Do other player natives still return valid values for this kind of clients after ~2 minutes? It might be CanBeDead incorrectly returns true for fake clients, and the fake client times out. :confused:

Also, I see you tagged this post with vrp - are you actually using that resource, and if so, does this mean you’re making use of multiple-deferral support?

1 Like

This might be resolved by the following commit:

3 Likes

We were using EasyAdmin’s queue, but we are hoping to go completely first-party and only base our RP stuff on vRP.

I wasn’t aware there WERE cancellation callbacks. I had dug through the docs pretty hard on Friday evening. Could you point me at any documentation for this kind of thing? I would much prefer something like a proper callback to hoping that GetPlayerLastMsg() returns something valid. At this point the native functions appear to be accurate, but I haven’t tried any sort of huge set of them or anything.

And yes, we are using vRP. I’m considering messing around with it to keep the queue in a separate resource and forward the deferral to vRP so everything works, especially with the multiple deferrals thing, but I want to know that the queue works before I try extracting it to a new resource.

That might do it. I’ll have to give it a shot tonight.

They exist in the C++ side but currently aren’t exposed to deferral events, the post was rather mentioning ‘maybe they should be exposed to Lua’, however it seems this issue was ‘merely’ a case of client timeouts.

Basically, with this feature deferrals should be fully transparently functioning if used by multiple resources - so you shouldn’t have to mess with vRP’s built-in deferral whatsoever.

I think something like a cancellation callback would be very useful exposed to scripting. It would make it much easier to determine if someone timed out versus clicked disconnect, for sure.

As for multiple deferrals I’ll have to give that a shot too. I tried it over the weekend but once vRP hit deferrals.done() it loaded me into the game. Perhaps I was doing something wrong but that’s a question for another time.

That has done the trick. I appreciate everyone’s help and ideas! :grin:

I updated to 607 yesterday and i’m having issues with GetPlayerLastMsg() after the supposed fix.
I am using a lightly modified version of connectqueue.

Snippet of where it takes place in the script:

Snippet
        while i <= Queue:GetSize() do
            local data = Queue.QueueList[i]
            local lastMsg = GetPlayerLastMsg(data.source)

            if lastMsg == 0 or lastMsg >= 30000 then
                data.timeout = data.timeout + 1
            else
                data.timeout = 0
            end

            -- check just incase there is invalid data
            if not data.ids or not data.name or not data.firstconnect or data.priority == nil or not data.source then
                data.deferrals.done(Config.Language._err .. "[1]")
                table_remove(Queue.QueueList, i)
                Queue:DebugPrint(tostring(data.name) .. "[" .. tostring(data.ids[1]) .. "] was removed from the queue because it had invalid data")

            elseif (data.timeout >= 120) and data.source ~= "debug" and os_time() - data.firstconnect > 5 then
                -- remove by source incase they rejoined and were duped in the queue somehow
                data.deferrals.done(Config.Language._err .. "[2]")
                Queue:RemoveFromQueue(data.source, true)
                Queue:RemoveFromConnecting(data.source, true)
                Queue:DebugPrint(data.name .. "[" .. data.ids[1] .. "] was removed from the queue because they timed out")
            else
                i = i + 1
            end
        end

When looping through the queue with 13 people in it the last message displayed normal values except for number 10 but the timeout var was still increasing:


After this i started logging what their last message was before they got kicked:

QUEUE: Frazzle.[steam:1100001057052a0] was removed from the queue because they timed out | Last message: 0
QUEUE: Stop reconizing me BY Z[steam:1100001144f74cb] was removed from the queue because they timed out | Last message: 2147483647

And each time someone would be kicked the last message was either 0 or the maximum 32 bit integer
Another example:

QUEUE: Stylz[steam:11000011457b97e] was removed from the queue because they timed out | Last message: 2147483647
QUEUE: Frazzle.[steam:1100001057052a0] was removed from the queue because they timed out | Last message: 0

Hopefully i have explained this enough for you to work on fix.