MantisBT - Zandronum
View Issue Details
0001799Zandronum[All Projects] Suggestionpublic2014-05-10 03:292014-11-28 18:22
Watermelon 
 
normalfeatureN/A
newopen 
 
 
0001799: Overhaul of the join queue
The join queue we currently have works, but is quite limited (especially in the way of team stuff). As I'm trying to solve another ticket, the join queue's limitations are getting in the way. I figure instead of adding more code to correct for the current mess, I would re-write it from the ground up in a properly structured class. This leads to four things:

1) Code clarity and new ease of use

2) Allow me to do another ticket without adding more hacky stuff on top of the current implementation (see linked ticket)

3) Allow saving of positions in line, which annoys people who are waiting to get into (for example) a duel server for 20+ minutes and accidentally timeout/disconnect [this occurs more frequently than one would think]

4) Can be used in the event system now easily (see linked ticket)
No tags attached.
related to 0000350new  sv_maxplayersperteam 
related to 0001794closed Torr Samaho New script type EVENT 
Issue History
2014-05-10 03:29WatermelonNew Issue
2014-05-10 03:30WatermelonNote Added: 0008766
2014-05-10 03:30WatermelonRelationship addedrelated to 0000350
2014-05-10 03:31WatermelonRelationship addedrelated to 0001794
2014-05-10 03:31WatermelonRelationship deletedrelated to 0001794
2014-05-10 03:31WatermelonRelationship addedchild of 0001794
2014-05-10 03:32WatermelonNote Edited: 0008766bug_revision_view_page.php?bugnote_id=8766#r4748
2014-05-10 03:35WatermelonDescription Updatedbug_revision_view_page.php?rev_id=4750#r4750
2014-05-10 07:15HypnotoadNote Added: 0008767
2014-05-10 13:17WatermelonNote Edited: 0008766bug_revision_view_page.php?bugnote_id=8766#r4751
2014-05-10 15:22WatermelonNote View State: 0008766: private
2014-05-10 15:23WatermelonNote Added: 0008772
2014-05-10 15:24WatermelonNote Edited: 0008766bug_revision_view_page.php?bugnote_id=8766#r4756
2014-05-10 15:25WatermelonNote Edited: 0008766bug_revision_view_page.php?bugnote_id=8766#r4757
2014-05-10 15:25WatermelonNote View State: 0008766: public
2014-05-10 21:02WatermelonNote Edited: 0008772bug_revision_view_page.php?bugnote_id=8772#r4759
2014-05-10 21:02WatermelonNote Edited: 0008772bug_revision_view_page.php?bugnote_id=8772#r4760
2014-05-10 21:03WatermelonNote Edited: 0008766bug_revision_view_page.php?bugnote_id=8766#r4761
2014-05-10 21:04WatermelonNote Edited: 0008772bug_revision_view_page.php?bugnote_id=8772#r4762
2014-05-10 21:04WatermelonNote Edited: 0008772bug_revision_view_page.php?bugnote_id=8772#r4763
2014-06-02 03:11WatermelonAssigned To => Watermelon
2014-06-02 03:11WatermelonStatusnew => assigned
2014-06-02 03:11WatermelonNote Added: 0008835
2014-06-08 18:40WatermelonNote Added: 0008931
2014-06-09 14:06Konar6Note Added: 0008958
2014-10-05 22:32DuskRelationship replacedrelated to 0001794
2014-10-09 00:02WatermelonNote Added: 0010392
2014-10-09 00:02WatermelonAssigned ToWatermelon =>
2014-10-09 00:02WatermelonStatusassigned => new
2014-11-28 18:22WatermelonTarget Version2.0 =>

Notes
(0008766)
Watermelon   
2014-05-10 03:30   
(edited on: 2014-05-10 21:03)
Here is an outline of what I have in mind and (mostly) coded so far:


#include <deque>
#include <vector>
#include "doomtype.h"
#include "networkshared.h"
#include "sv_main.h"
#include "zstring.h"

//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------

#define JOINQUEUE_DEFAULT_TIMEOUT (5 * 60 * TICRATE)
#define JOINQUEUE_NOT_IN_LINE -1
#define JOINQUEUE_NO_POSITION -1

//-----------------------------------------------------------------------------
// Enums
//-----------------------------------------------------------------------------
typedef enum {
    JQPRIORITY_ANY = 0, // The first player found (either random or specific team)
    JQPRIORITY_RANDOM = 1, // Priority given to random's
    JQPRIORITY_SPECIFIC = 2, // Priority given to people who want that specific team
} JoinQueueTeamPriorityType_e;

//-----------------------------------------------------------------------------
// Structures
//-----------------------------------------------------------------------------

// Encapsulates a join entry
typedef struct {

    // The player identifier
    ULONG ulPlayer;

    // The team the player wishes to join
    ULONG ulTeam;

    // The address the player was connected with (to see if they reconnect)
    NETADDRESS_s netAddress;

    // The gametic the user joined the queue with
    int gameticJoinedQueue;

} JoinQueueEntry_t;

//-----------------------------------------------------------------------------
// Classes
//-----------------------------------------------------------------------------

// A class that contains operations for a functioning join queue
// The front of the queue holds the players who are first in line to be picked
class JoinQueue {
private:
    std::deque<JoinQueueEntry_t> queue; // The queue that holds all the players who want to join
    LONG timeoutTicThreshold; // How long until a disconnected player is purged

    bool popIntoGame(const ULONG ulPosition);

public:
    JoinQueue();
    ~JoinQueue();

    void addPlayerToFrontOfQueue(JoinQueueEntry_t playerEntry);
    void addPlayerToBackOfQueue(JoinQueueEntry_t playerEntry);
    bool addPlayerToQueuePosition(JoinQueueEntry_t playerEntry, const ULONG ulPosition);
    
    bool popPlayerIntoGame(const ULONG ulPlayer);
    bool popPositionIntoGame(const ULONG ulPosition);
    bool popTeamIntoGame(const ULONG ulTeam, JoinQueueTeamPriorityType_e priorityEnum);

    int getQueuePosition(ULONG ulPlayer);

    JoinQueueEntry_t getFrontOfQueue();
    JoinQueueEntry_t getBackOfQueue();
    JoinQueueEntry_t getQueueEntryAt(const ULONG ulPosition);
    JoinQueueEntry_t getQueueEntryForPlayer(const ULONG ulPlayer);
    std::vector<JoinQueueEntry_t> getPlayersForTeam(const ULONG ulTeam);

    bool removePlayerFromQueue(const ULONG ulPlayer, const bool bBroadcast);
    bool removePlayerFromQueueFront(const bool bBroadcast);
    bool removePlayerFromQueueBack(const bool bBroadcast);
    bool removePlayerFromQueueAt(const ULONG ulPosition, const bool bBroadcast);

    void handleSpectatorLeftGame(const ULONG ulPlayer, const bool bWantPop);
    void handlePlayerLeftGame(const ULONG ulPlayer, const bool bBroadcast = true);

    bool isPlayerInLine(const ULONG ulPlayer);
    LONG getPositionInLine(const ULONG ulPlayer);

    void setTimeoutThreshold(const LONG ticAmount);
    LONG getTimeoutThreshold();

    bool attemptToRestorePlayer(const ULONG ulPlayer, NETADDRESS_s netAddress);

    ULONG getSize();
    bool isEmpty();

    void purgeMissingPlayers(const bool bBroadcast);
    void clearQueue();

    FString getPrintableJoinQueue();
};

//-----------------------------------------------------------------------------
// Extern variables
//-----------------------------------------------------------------------------

extern JoinQueue g_joinQueue;

//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------

void JOINQUEUE_CLIENT_SetPositionInLine(LONG lPosition);


(0008767)
Hypnotoad   
2014-05-10 07:15   
Since you're rewriting the join queue, can I request that this gets looked into?'http://zandronum.com/tracker/view.php?id=1689 [^]'
(0008772)
Watermelon   
2014-05-10 15:23   
(edited on: 2014-05-10 21:04)
I don't know where my post went, it seems to have vanished.
For your ticket, because of what it's requesting... it'd be best if Torr looked into that.



I pushed the latest (non-working) code to the repo in it's own branch.

EDIT:
After pushing again, I think it needs some re-writing and trimming of the fat that doesn't need to be in there.

There's some stuff that needs fixing fr sure, one of which is where I return weird structs (incomplete). I'll find a better solution later.

I'm also really happy to see that deque's indices are O(1)! I thought it was O(n) complexity. Thank you STL

(0008835)
Watermelon   
2014-06-02 03:11   
I'm changing the API of this class because there's a ton of methods that no one will use anyways.

It will have the basics and we're good to go.
(0008931)
Watermelon   
2014-06-08 18:40   
Need input:

How do we handle people with the same IP? Like brothers who play. The question is, how does the remembering of stats work? Is it based on port as well as IP?

I'm trying to figure out this one last issue before proceeding with completion of the new join queue.
(0008958)
Konar6   
2014-06-09 14:06   
Remembering frags works with the player name and IP:port.
(0010392)
Watermelon   
2014-10-09 00:02   
Will resume when I complete other tickets