]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/menu/xonotic/serverlist.c
Merge remote-tracking branch 'origin/master' into samual/updatecommands
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / xonotic / serverlist.c
index ce9676f3781dbafaf81d8f267917d4ebcbfdbbfa..f02d747cc91f1f0e229c56074c217dc2609e2c5e 100644 (file)
@@ -8,6 +8,8 @@ CLASS(XonoticServerList) EXTENDS(XonoticListBox)
        METHOD(XonoticServerList, resizeNotify, void(entity, vector, vector, vector, vector))
        METHOD(XonoticServerList, keyDown, float(entity, float, float, float))
 
+       ATTRIB(XonoticServerList, iconsSizeFactor, float, 0.85)
+
        ATTRIB(XonoticServerList, realFontSize, vector, '0 0 0')
        ATTRIB(XonoticServerList, realUpperMargin, float, 0)
        ATTRIB(XonoticServerList, columnIconsOrigin, float, 0)
@@ -50,6 +52,9 @@ CLASS(XonoticServerList) EXTENDS(XonoticListBox)
        ATTRIB(XonoticServerList, lastClickedTime, float, 0)
 
        ATTRIB(XonoticServerList, ipAddressBoxFocused, float, -1)
+
+       ATTRIB(XonoticServerList, seenIPv4, float, 0)
+       ATTRIB(XonoticServerList, seenIPv6, float, 0)
 ENDCLASS(XonoticServerList)
 entity makeXonoticServerList();
 void ServerList_Connect_Click(entity btn, entity me);
@@ -58,6 +63,7 @@ void ServerList_ShowFull_Click(entity box, entity me);
 void ServerList_Filter_Change(entity box, entity me);
 void ServerList_Favorite_Click(entity btn, entity me);
 void ServerList_Info_Click(entity btn, entity me);
+void ServerList_Update_favoriteButton(entity btn, entity me);
 #endif
 
 #ifdef IMPLEMENTATION
@@ -102,6 +108,8 @@ float IsFavorite(string srv)
        if(srv == "")
                return FALSE;
        srv = netaddress_resolve(srv, 26000);
+       if(srv == "")
+               return FALSE;
        p = crypto_getidfp(srv);
        n = tokenize_console(cvar_string("net_slist_favorites"));
        for(i = 0; i < n; ++i)
@@ -171,6 +179,14 @@ void ToggleFavorite(string srv)
        resorthostcache();
 }
 
+void ServerList_Update_favoriteButton(entity btn, entity me)
+{
+       if(IsFavorite(me.ipAddressBox.text))
+               me.favoriteButton.setText(me.favoriteButton, _("Remove"));
+       else
+               me.favoriteButton.setText(me.favoriteButton, _("Bookmark"));
+}
+
 entity makeXonoticServerList()
 {
        entity me;
@@ -222,7 +238,7 @@ void XonoticServerList_refreshServerList(entity me, float mode)
        }
        else */
        {
-               float m, o;
+               float m, o, i, n; // moin moin
                string s, typestr, modstr;
                s = me.filterString;
 
@@ -241,12 +257,26 @@ void XonoticServerList_refreshServerList(entity me, float mode)
 
                m = SLIST_MASK_AND - 1;
                resethostcachemasks();
+
+               // ping: reject negative ping (no idea why this happens in the first place, engine bug)
+               sethostcachemasknumber(++m, SLIST_FIELD_PING, 0, SLIST_TEST_GREATEREQUAL);
+
+               // show full button
                if(!me.filterShowFull)
-                       sethostcachemasknumber(++m, SLIST_FIELD_FREESLOTS, 1, SLIST_TEST_GREATEREQUAL);
+               {
+                       sethostcachemasknumber(++m, SLIST_FIELD_FREESLOTS, 1, SLIST_TEST_GREATEREQUAL); // legacy
+                       sethostcachemaskstring(++m, SLIST_FIELD_QCSTATUS, ":S0:", SLIST_TEST_NOTCONTAIN); // g_maxplayers support
+               }
+
+               // show empty button
                if(!me.filterShowEmpty)
                        sethostcachemasknumber(++m, SLIST_FIELD_NUMHUMANS, 1, SLIST_TEST_GREATEREQUAL);
+
+               // gametype filtering
                if(typestr != "")
                        sethostcachemaskstring(++m, SLIST_FIELD_QCSTATUS, strcat(typestr, ":"), SLIST_TEST_STARTSWITH);
+
+               // mod filtering
                if(modstr != "")
                {
                        if(substring(modstr, 0, 1) == "!")
@@ -254,6 +284,13 @@ void XonoticServerList_refreshServerList(entity me, float mode)
                        else
                                sethostcachemaskstring(++m, SLIST_FIELD_MOD, resolvemod(modstr), SLIST_TEST_EQUAL);
                }
+
+               // server banning
+               n = tokenizebyseparator(_Nex_ExtResponseSystem_BannedServers, " ");
+               for(i = 0; i < n; ++i)
+                       if(argv(i) != "")
+                               sethostcachemaskstring(++m, SLIST_FIELD_CNAME, argv(i), SLIST_TEST_NOTSTARTSWITH);
+
                m = SLIST_MASK_OR - 1;
                if(s != "")
                {
@@ -285,6 +322,13 @@ void XonoticServerList_draw(entity me)
 {
        float i, found, owned;
 
+       if(_Nex_ExtResponseSystem_BannedServersNeedsRefresh)
+       {
+               if(!me.needsRefresh)
+                       me.needsRefresh = 2;
+               _Nex_ExtResponseSystem_BannedServersNeedsRefresh = 0;
+       }
+
        if(me.currentSortField == -1)
        {
                me.setSortOrder(me, SLIST_FIELD_PING, +1);
@@ -306,6 +350,7 @@ void XonoticServerList_draw(entity me)
 
        me.connectButton.disabled = ((me.nItems == 0) && (me.ipAddressBox.text == ""));
        me.infoButton.disabled = ((me.nItems == 0) || !owned);
+       me.favoriteButton.disabled = ((me.nItems == 0) && (me.ipAddressBox.text == ""));
 
        found = 0;
        if(me.selectedServer)
@@ -345,12 +390,7 @@ void XonoticServerList_draw(entity me)
        if(me.ipAddressBoxFocused != me.ipAddressBox.focused)
        {
                if(me.ipAddressBox.focused || me.ipAddressBoxFocused < 0)
-               {
-                       if(IsFavorite(me.ipAddressBox.text))
-                               me.favoriteButton.setText(me.favoriteButton, "Remove");
-                       else
-                               me.favoriteButton.setText(me.favoriteButton, "Bookmark");
-               }
+                       ServerList_Update_favoriteButton(NULL, me);
                me.ipAddressBoxFocused = me.ipAddressBox.focused;
        }
 
@@ -450,17 +490,17 @@ void ServerList_ShowFull_Click(entity box, entity me)
        me.ipAddressBox.cursorPos = 0;
        me.ipAddressBoxFocused = -1;
 }
-void XonoticServerList_setSortOrder(entity me, float field, float direction)
+void XonoticServerList_setSortOrder(entity me, float fld, float direction)
 {
-       if(me.currentSortField == field)
+       if(me.currentSortField == fld)
                direction = -me.currentSortOrder;
        me.currentSortOrder = direction;
-       me.currentSortField = field;
-       me.sortButton1.forcePressed = (field == SLIST_FIELD_PING);
-       me.sortButton2.forcePressed = (field == SLIST_FIELD_NAME);
-       me.sortButton3.forcePressed = (field == SLIST_FIELD_MAP);
+       me.currentSortField = fld;
+       me.sortButton1.forcePressed = (fld == SLIST_FIELD_PING);
+       me.sortButton2.forcePressed = (fld == SLIST_FIELD_NAME);
+       me.sortButton3.forcePressed = (fld == SLIST_FIELD_MAP);
        me.sortButton4.forcePressed = 0;
-       me.sortButton5.forcePressed = (field == SLIST_FIELD_NUMHUMANS);
+       me.sortButton5.forcePressed = (fld == SLIST_FIELD_NUMHUMANS);
        me.selectedItem = 0;
        if(me.selectedServer)
                strunzone(me.selectedServer);
@@ -493,11 +533,11 @@ void XonoticServerList_resizeNotify(entity me, vector relOrigin, vector relSize,
        me.realUpperMargin = 0.5 * (1 - me.realFontSize_y);
 
        me.columnIconsOrigin = 0;
-       me.columnIconsSize = me.realFontSize_x * 2;
-       me.columnPingSize = me.realFontSize_x * 4;
-       me.columnMapSize = me.realFontSize_x * 12;
+       me.columnIconsSize = me.realFontSize_x * 3 * me.iconsSizeFactor;
+       me.columnPingSize = me.realFontSize_x * 3;
+       me.columnMapSize = me.realFontSize_x * 10;
        me.columnTypeSize = me.realFontSize_x * 4;
-       me.columnPlayersSize = me.realFontSize_x * 6;
+       me.columnPlayersSize = me.realFontSize_x * 5;
        me.columnNameSize = 1 - me.columnPlayersSize - me.columnMapSize - me.columnPingSize - me.columnIconsSize - me.columnTypeSize - 5 * me.realFontSize_x;
        me.columnPingOrigin = me.columnIconsOrigin + me.columnIconsSize + me.realFontSize_x;
        me.columnNameOrigin = me.columnPingOrigin + me.columnPingSize + me.realFontSize_x;
@@ -505,11 +545,11 @@ void XonoticServerList_resizeNotify(entity me, vector relOrigin, vector relSize,
        me.columnTypeOrigin = me.columnMapOrigin + me.columnMapSize + me.realFontSize_x;
        me.columnPlayersOrigin = me.columnTypeOrigin + me.columnTypeSize + me.realFontSize_x;
 
-       me.positionSortButton(me, me.sortButton1, me.columnPingOrigin, me.columnPingSize, "Ping", ServerList_PingSort_Click);
-       me.positionSortButton(me, me.sortButton2, me.columnNameOrigin, me.columnNameSize, "Host name", ServerList_NameSort_Click);
-       me.positionSortButton(me, me.sortButton3, me.columnMapOrigin, me.columnMapSize, "Map", ServerList_MapSort_Click);
-       me.positionSortButton(me, me.sortButton4, me.columnTypeOrigin, me.columnTypeSize, "Type", ServerList_TypeSort_Click);
-       me.positionSortButton(me, me.sortButton5, me.columnPlayersOrigin, me.columnPlayersSize, "Players", ServerList_PlayerSort_Click);
+       me.positionSortButton(me, me.sortButton1, me.columnPingOrigin, me.columnPingSize, _("Ping"), ServerList_PingSort_Click);
+       me.positionSortButton(me, me.sortButton2, me.columnNameOrigin, me.columnNameSize, _("Host name"), ServerList_NameSort_Click);
+       me.positionSortButton(me, me.sortButton3, me.columnMapOrigin, me.columnMapSize, _("Map"), ServerList_MapSort_Click);
+       me.positionSortButton(me, me.sortButton4, me.columnTypeOrigin, me.columnTypeSize, _("Type"), ServerList_TypeSort_Click);
+       me.positionSortButton(me, me.sortButton5, me.columnPlayersOrigin, me.columnPlayersSize, _("Players"), ServerList_PlayerSort_Click);
 
        float f;
        f = me.currentSortField;
@@ -557,14 +597,17 @@ void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float
        // layout: Ping, Server name, Map name, NP, TP, MP
        string s;
        float p, q;
+       float isv4, isv6;
        vector theColor;
        float theAlpha;
 
        if(isSelected)
                draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
 
-       if(gethostcachenumber(SLIST_FIELD_NUMPLAYERS, i) >= gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i))
+       if(gethostcachenumber(SLIST_FIELD_FREESLOTS, i) <= 0)
                theAlpha = SKINALPHA_SERVERLIST_FULL;
+       else if(strstrofs(gethostcachestring(SLIST_FIELD_QCSTATUS, i), ":S0:", 0) >= 0)
+               theAlpha = SKINALPHA_SERVERLIST_FULL; // g_maxplayers support
        else if not(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i))
                theAlpha = SKINALPHA_SERVERLIST_EMPTY;
        else
@@ -596,6 +639,19 @@ void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float
        }
 
        s = gethostcachestring(SLIST_FIELD_CNAME, i);
+
+       isv4 = isv6 = 0;
+       if(substring(s, 0, 1) == "[")
+       {
+               isv6 = 1;
+               me.seenIPv6 += 1;
+       }
+       else if(strstrofs("0123456789", substring(s, 0, 1), 0) >= 0)
+       {
+               isv4 = 1;
+               me.seenIPv4 += 1;
+       }
+
        q = stof(substring(crypto_getencryptlevel(s), 0, 1));
        if((q <= 0 && cvar("crypto_aeslevel") >= 3) || (q >= 3 && cvar("crypto_aeslevel") <= 0))
        {
@@ -628,21 +684,35 @@ void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float
        s = gethostcachestring(SLIST_FIELD_QCSTATUS, i);
        {
                vector iconSize;
-               iconSize_y = 1;
-               iconSize_x = iconSize_y * (absSize_y / absSize_x);
+               iconSize_y = me.realFontSize_y * me.iconsSizeFactor;
+               iconSize_x = me.realFontSize_x * me.iconsSizeFactor;
 
                vector iconPos;
-               iconPos_x = (me.columnIconsSize - 2 * iconSize_x) * 0.5;
+               iconPos_x = (me.columnIconsSize - 3 * iconSize_x) * 0.5;
                iconPos_y = (1 - iconSize_y) * 0.5;
 
-               draw_Picture(iconPos, strcat(SKINGFX_SERVERLIST_ICON, "_pure", ftos(strstrofs(s, ":P0:", 0) >= 0)), iconSize, '1 1 1', 1);
+               if not(me.seenIPv4 && me.seenIPv6)
+               {
+                       iconPos_x += iconSize_x * 0.5;
+               }
+               else if(me.seenIPv4 && me.seenIPv6)
+               {
+                       if(isv6)
+                               draw_Picture(iconPos, strcat(SKINGFX_SERVERLIST_ICON, "_ipv6"), iconSize, '1 1 1', 1);
+                       else if(isv4)
+                               draw_Picture(iconPos, strcat(SKINGFX_SERVERLIST_ICON, "_ipv4"), iconSize, '1 1 1', 1);
+                       iconPos_x += iconSize_x;
+               }
 
-               iconPos_x += iconSize_x;
                draw_Picture(iconPos, strcat(SKINGFX_SERVERLIST_ICON, "_aeslevel", ftos(q)), iconSize, '1 1 1', 1);
+               iconPos_x += iconSize_x;
+
+               draw_Picture(iconPos, strcat(SKINGFX_SERVERLIST_ICON, "_pure", ftos(strstrofs(s, ":P0:", 0) >= 0)), iconSize, '1 1 1', 1);
+               iconPos_x += iconSize_x;
        }
 
        s = ftos(p);
-       draw_Text(me.realUpperMargin * eY + (me.columnPingSize - draw_TextWidth(s, 0, me.realFontSize)) * eX, s, me.realFontSize, theColor, theAlpha, 0);
+       draw_Text(me.realUpperMargin * eY + (me.columnPingOrigin + me.columnPingSize - draw_TextWidth(s, 0, me.realFontSize)) * eX, s, me.realFontSize, theColor, theAlpha, 0);
        s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_NAME, i), me.columnNameSize, 0, me.realFontSize);
        draw_Text(me.realUpperMargin * eY + me.columnNameOrigin * eX, s, me.realFontSize, theColor, theAlpha, 0);
        s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_MAP, i), me.columnMapSize, 0, me.realFontSize);
@@ -674,8 +744,11 @@ float XonoticServerList_keyDown(entity me, float scan, float ascii, float shift)
        }
        else if(scan == K_MOUSE2 || scan == K_SPACE)
        {
-               main.serverInfoDialog.loadServerInfo(main.serverInfoDialog, me.selectedItem);
-               DialogOpenButton_Click_withCoords(me, main.serverInfoDialog, org, sz);
+               if(me.nItems != 0)
+               {
+                       main.serverInfoDialog.loadServerInfo(main.serverInfoDialog, me.selectedItem);
+                       DialogOpenButton_Click_withCoords(me, main.serverInfoDialog, org, sz);
+               }
        }
        else if(scan == K_INS || scan == K_MOUSE3 || scan == K_KP_INS)
        {