]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Add empty Terms of Service tab to serverinfo dialog
authorFreddy <schro.sb@gmail.com>
Sun, 29 Dec 2019 21:57:39 +0000 (22:57 +0100)
committerFreddy <schro.sb@gmail.com>
Tue, 31 Dec 2019 19:22:06 +0000 (20:22 +0100)
qcsrc/menu/xonotic/_mod.inc
qcsrc/menu/xonotic/_mod.qh
qcsrc/menu/xonotic/dialog_multiplayer_join_ToS.qc [new file with mode: 0644]
qcsrc/menu/xonotic/dialog_multiplayer_join_ToS.qh [new file with mode: 0644]
qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc
qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qh
qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfotab.qc [new file with mode: 0644]
qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfotab.qh [new file with mode: 0644]

index e77af222bcbad51502f4e6f521e2cd19cbca9d6b..75d37e4fc28400868ef8af2bc303edc3982977dc 100644 (file)
@@ -48,6 +48,8 @@
 #include <menu/xonotic/dialog_multiplayer_create_mutators.qc>
 #include <menu/xonotic/dialog_multiplayer_join.qc>
 #include <menu/xonotic/dialog_multiplayer_join_serverinfo.qc>
+#include <menu/xonotic/dialog_multiplayer_join_serverinfotab.qc>
+#include <menu/xonotic/dialog_multiplayer_join_ToS.qc>
 #include <menu/xonotic/dialog_multiplayer_media.qc>
 #include <menu/xonotic/dialog_multiplayer_media_demo.qc>
 #include <menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qc>
index 50eabce95999675614d4700f4fbea7191adbc6b1..452c566581656bb9c7b3192c556ecf07daa694d7 100644 (file)
@@ -48,6 +48,8 @@
 #include <menu/xonotic/dialog_multiplayer_create_mutators.qh>
 #include <menu/xonotic/dialog_multiplayer_join.qh>
 #include <menu/xonotic/dialog_multiplayer_join_serverinfo.qh>
+#include <menu/xonotic/dialog_multiplayer_join_serverinfotab.qh>
+#include <menu/xonotic/dialog_multiplayer_join_ToS.qh>
 #include <menu/xonotic/dialog_multiplayer_media.qh>
 #include <menu/xonotic/dialog_multiplayer_media_demo.qh>
 #include <menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qh>
diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_join_ToS.qc b/qcsrc/menu/xonotic/dialog_multiplayer_join_ToS.qc
new file mode 100644 (file)
index 0000000..a340ed2
--- /dev/null
@@ -0,0 +1,32 @@
+#include "dialog_multiplayer_join_ToS.qh"
+
+#include "textlabel.qh"
+#include <lib/urllib.qh>
+
+
+entity makeXonoticServerToSTab()
+{
+       entity me;
+       me = NEW(XonoticServerToSTab);
+       me.configureDialog(me);
+       return me;
+}
+
+void XonoticServerToSTab_loadToS(entity me, float i)
+{
+    //TODO: download ToS from server
+    localcmd("echo test1");
+}
+
+void XonoticServerToSTab_fill(entity me)
+{
+       entity e;
+    me.TR(me);
+        me.TD(me, 1, 6.2, e = makeXonoticTextLabel(0, _("ToS")));
+        me.nameLabel = e;
+}
+
+void AdditionalServerInfo_OnGet(entity fh, entity pass, int status)
+{
+    localcmd("echo test2");
+}
diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_join_ToS.qh b/qcsrc/menu/xonotic/dialog_multiplayer_join_ToS.qh
new file mode 100644 (file)
index 0000000..2f8d11b
--- /dev/null
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "tab.qh"
+CLASS(XonoticServerToSTab, XonoticTab)
+       METHOD(XonoticServerToSTab, fill, void(entity));
+       METHOD(XonoticServerToSTab, loadToS, void(entity, float));
+       ATTRIB(XonoticServerToSTab, title, string, _("Terms of Service"));
+       ATTRIB(XonoticServerToSTab, color, vector, SKINCOLOR_DIALOG_SERVERINFO);
+       ATTRIB(XonoticServerToSTab, intendedWidth, float, 0.8);
+       ATTRIB(XonoticServerToSTab, rows, float, 17);
+       ATTRIB(XonoticServerToSTab, columns, float, 6.2);
+
+       ATTRIB(XonoticServerToSTab, nameLabel, entity);
+ENDCLASS(XonoticServerToSTab)
+entity makeXonoticServerToSTab();
+
+void AdditionalServerInfo_OnGet(entity fh, entity pass, int status);
index 3f39077c82143dd13fdce4dae390bc1df1fb89ca..c6fada86f4b78a92fe2f5d93731799457f065884 100644 (file)
 #include "dialog_multiplayer_join_serverinfo.qh"
-#include <common/mapinfo.qh>
 
+#include "tabcontroller.qh"
 #include "serverlist.qh"
 #include "playerlist.qh"
 #include "inputbox.qh"
 #include "textlabel.qh"
 #include "button.qh"
+#include "dialog_multiplayer_join_serverinfotab.qh"
+#include "dialog_multiplayer_join_ToS.qh"
+
 
 void XonoticServerInfoDialog_loadServerInfo(entity me, float i)
 {
-       bool pure_available;
-       float m, pure_violations, freeslots, numh, maxp, numb, sflags;
-       string s, typestr, versionstr, k, v, modname;
-
-       // ====================================
-       //  First clear and unzone the strings
-       // ====================================
-       strfree(me.currentServerName);
-       strfree(me.currentServerCName);
-       strfree(me.currentServerType);
-       strfree(me.currentServerMap);
-       strfree(me.currentServerPlayers);
-       strfree(me.currentServerNumPlayers);
-       strfree(me.currentServerNumBots);
-       strfree(me.currentServerNumFreeSlots);
-       strfree(me.currentServerMod);
-       strfree(me.currentServerVersion);
-       // not zoned!
-       //      strfree(me.currentServerEncrypt);
-       strfree(me.currentServerPure);
-       strfree(me.currentServerKey);
-       strfree(me.currentServerID);
-
-       // ==========================
-       //  Now, fill in the strings
-       // ==========================
-       me.currentServerName = strzone(gethostcachestring(SLIST_FIELD_NAME, i));
-       me.nameLabel.setText(me.nameLabel, me.currentServerName);
-
-       me.currentServerCName = strzone(gethostcachestring(SLIST_FIELD_CNAME, i));
-       me.cnameLabel.setText(me.cnameLabel, me.currentServerCName);
-
-       pure_available = false;
-       pure_violations = -1;
-       typestr = _("N/A");
-       versionstr = _("N/A");
-
-       s = gethostcachestring(SLIST_FIELD_QCSTATUS, i);
-       m = tokenizebyseparator(s, ":");
-       if(m >= 2)
-       {
-               typestr = argv(0);
-               versionstr = argv(1);
-       }
-       freeslots = -1;
-       sflags = -1;
-       modname = "";
-       for(int j = 2; j < m; ++j)
-       {
-               if(argv(j) == "")
-                       break;
-               k = substring(argv(j), 0, 1);
-               v = substring(argv(j), 1, -1);
-               if(k == "P")
-               {
-                       pure_available = true;
-                       pure_violations = stof(v);
-               }
-               else if(k == "S")
-                       freeslots = stof(v);
-               else if(k == "F")
-                       sflags = stof(v);
-               else if(k == "M")
-                       modname = v;
-       }
-
-#ifdef COMPAT_NO_MOD_IS_XONOTIC
-       if(modname == "")
-               modname = "Xonotic";
-#endif
-
-       s = gethostcachestring(SLIST_FIELD_MOD, i);
-       if(s != "data")
-               modname = sprintf("%s (%s)", modname, s);
-
-       Gametype j = MapInfo_Type_FromString(typestr); // try and get the real name of the game type
-       if(j) { typestr = MapInfo_Type_ToText(j); } // only set it if we actually found it
-
-       me.currentServerType = strzone(typestr);
-       me.typeLabel.setText(me.typeLabel, me.currentServerType);
-
-       me.currentServerMap = strzone(gethostcachestring(SLIST_FIELD_MAP, i));
-       me.mapLabel.setText(me.mapLabel, me.currentServerMap);
-
-       me.currentServerPlayers = strzone(gethostcachestring(SLIST_FIELD_PLAYERS, i));
-       me.rawPlayerList.setPlayerList(me.rawPlayerList, me.currentServerPlayers);
-
-       numh = gethostcachenumber(SLIST_FIELD_NUMHUMANS, i);
-       maxp = gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i);
-       numb = gethostcachenumber(SLIST_FIELD_NUMBOTS, i);
-       me.currentServerNumPlayers = strzone(sprintf("%d/%d", numh, maxp));
-       me.numPlayersLabel.setText(me.numPlayersLabel, me.currentServerNumPlayers);
-
-       s = ftos(numb);
-       me.currentServerNumBots = strzone(s);
-       me.numBotsLabel.setText(me.numBotsLabel, me.currentServerNumBots);
-
-       if(freeslots < 0) { freeslots = maxp - numh - numb; }
-       s = ftos(freeslots);
-       me.currentServerNumFreeSlots = strzone(s);
-       me.numFreeSlotsLabel.setText(me.numFreeSlotsLabel, me.currentServerNumFreeSlots);
-
-       me.currentServerMod = ((modname == "Xonotic") ? ZCTX(_("MOD^Default")) : modname);
-       me.currentServerMod = strzone(me.currentServerMod);
-       me.modLabel.setText(me.modLabel, me.currentServerMod);
-
-       me.currentServerVersion = strzone(versionstr);
-       me.versionLabel.setText(me.versionLabel, me.currentServerVersion);
-
-       me.currentServerPure = ((!pure_available) ? _("N/A") : (pure_violations == 0) ? _("Official") : sprintf(_("%d modified"), pure_violations));
-       me.currentServerPure = strzone(me.currentServerPure);
-       me.pureLabel.setText(me.pureLabel, me.currentServerPure);
-
-       s = crypto_getencryptlevel(me.currentServerCName);
-       if(s == "")
-       {
-               if(cvar("crypto_aeslevel") >= 3)
-                       me.currentServerEncrypt = _("N/A (auth library missing, can't connect)");
-               else
-                       me.currentServerEncrypt = _("N/A (auth library missing)");
-       }
-       else switch(stof(substring(s, 0, 1)))
-       {
-               case 0:
-                       if(cvar("crypto_aeslevel") >= 3)
-                               me.currentServerEncrypt = _("Not supported (can't connect)");
-                       else
-                               me.currentServerEncrypt = _("Not supported (won't encrypt)");
-                       break;
-               case 1:
-                       if(cvar("crypto_aeslevel") >= 2)
-                               me.currentServerEncrypt = _("Supported (will encrypt)");
-                       else
-                               me.currentServerEncrypt = _("Supported (won't encrypt)");
-                       break;
-               case 2:
-                       if(cvar("crypto_aeslevel") >= 1)
-                               me.currentServerEncrypt = _("Requested (will encrypt)");
-                       else
-                               me.currentServerEncrypt = _("Requested (won't encrypt)");
-                       break;
-               case 3:
-                       if(cvar("crypto_aeslevel") <= 0)
-                               me.currentServerEncrypt = _("Required (can't connect)");
-                       else
-                               me.currentServerEncrypt = _("Required (will encrypt)");
-                       break;
-       }
-       me.encryptLabel.setText(me.encryptLabel, me.currentServerEncrypt);
-       setZonedTooltip(me.encryptLabel, _("Use the `crypto_aeslevel` cvar to change your preferences"), string_null);
-
-       s = crypto_getidfp(me.currentServerCName);
-       if (!s) { s = _("N/A"); }
-       me.currentServerID = strzone(s);
-       me.idLabel.setText(me.idLabel, me.currentServerID);
-
-       s = crypto_getkeyfp(me.currentServerCName);
-       if (!s) { s = _("N/A"); }
-       me.currentServerKey = strzone(s);
-       me.keyLabel.setText(me.keyLabel, me.currentServerKey);
-
-       me.currentServerStatsStatus = ((sflags >= 0 && (sflags & SERVERFLAG_PLAYERSTATS)) ? ((sflags & SERVERFLAG_PLAYERSTATS_CUSTOM) ? _("custom stats server") : _("stats enabled")) : _("stats disabled"));
-       me.currentServerStatsStatus = strzone(me.currentServerStatsStatus);
-       me.statsLabel.setText(me.statsLabel, me.currentServerStatsStatus);
+    me.infoTab.loadServerInfo(me.infoTab, i);
 }
 
 void XonoticServerInfoDialog_fill(entity me)
 {
-       entity e;
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Hostname:")));
-               me.TD(me, 1, 4.6, e = makeXonoticTextLabel(0.5, ""));
-               e.colorL = SKINCOLOR_SERVERINFO_NAME;
-               e.allowCut = 1;
-               me.nameLabel = e;
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Address:")));
-               me.TD(me, 1, 4.6, e = makeXonoticTextLabel(0.5, ""));
-               e.colorL = SKINCOLOR_SERVERINFO_IP;
-               e.allowCut = 1;
-               me.cnameLabel = e;
-
-       me.TR(me);
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Gametype:")));
-               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
-               e.allowCut = 1;
-               me.typeLabel = e;
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Map:")));
-               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
-               e.allowCut = 1;
-               me.mapLabel = e;
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Mod:")));
-               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
-               e.allowCut = 1;
-               me.modLabel = e;
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Version:")));
-               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
-               e.allowCut = 1;
-               me.versionLabel = e;
+       entity mc, e;
+       mc = makeXonoticTabController(me.rows - 1);
        me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Settings:")));
-               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
-               e.allowCut = 1;
-               me.pureLabel = e;
+               me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Status"), me.infoTab = makeXonoticServerInfoTab()));
+               me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Terms of Service"), makeXonoticServerToSTab()));
 
        me.TR(me);
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Players:")));
-               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
-               e.allowCut = 1;
-               me.numPlayersLabel = e;
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Bots:")));
-               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
-               e.allowCut = 1;
-               me.numBotsLabel = e;
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Free slots:")));
-               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
-               e.allowCut = 1;
-               me.numFreeSlotsLabel = e;
-
-       me.gotoRC(me, me.rows - 5, 0);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Encryption:")));
-               me.TD(me, 1, 5.4, e = makeXonoticTextLabel(0, ""));
-                       e.allowCut = 1;
-                       me.encryptLabel = e;
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("ID:")));
-               me.TD(me, 1, 5.4, e = makeXonoticTextLabel(0, ""));
-                       e.allowCut = 1;
-                       me.keyLabel = e;
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Key:")));
-               me.TD(me, 1, 5.4, e = makeXonoticTextLabel(0, ""));
-                       e.allowCut = 1;
-                       me.idLabel = e;
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Stats:")));
-               me.TD(me, 1, 5.4, e = makeXonoticTextLabel(0, ""));
-                       e.allowCut = 1;
-                       me.statsLabel = e;
-
-       me.gotoRC(me, 2, 2.2); me.setFirstColumn(me, me.currentColumn);
-               me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Players:")));
-       me.TR(me);
-               me.TD(me, me.rows - 8, 4, e = makeXonoticPlayerList());
-                       me.rawPlayerList = e;
+               me.TD(me, me.rows - 1, me.columns, mc);
 
        me.gotoRC(me, me.rows - 1, 0);
                me.TD(me, 1, me.columns/2, e = makeXonoticButton(_("Close"), '0 0 0'));
@@ -277,5 +41,6 @@ void XonoticServerInfoDialog_fill(entity me)
 
 void Join_Click(entity btn, entity me)
 {
-       localcmd("connect ", me.currentServerCName, "\n");
+       localcmd("connect ", me.infoTab.currentServerCName, "\n");
 }
+
index f4f422991aa968a440926626416280745219e979..3eaf9123715f7aa6bde55b72f513eede7687ac0e 100644 (file)
@@ -2,46 +2,17 @@
 
 #include "dialog.qh"
 CLASS(XonoticServerInfoDialog, XonoticDialog)
+    METHOD(XonoticServerInfoDialog, loadServerInfo, void(entity, float));
        METHOD(XonoticServerInfoDialog, fill, void(entity));
-       METHOD(XonoticServerInfoDialog, loadServerInfo, void(entity, float));
-       ATTRIB(XonoticServerInfoDialog, title, string, _("Server Information"));
-       ATTRIB(XonoticServerInfoDialog, color, vector, SKINCOLOR_DIALOG_SERVERINFO);
-       ATTRIB(XonoticServerInfoDialog, intendedWidth, float, 0.8);
+       ATTRIB(XonoticServerInfoDialog, title, string, _("Server Info"));
+       ATTRIB(XonoticServerInfoDialog, color, vector, SKINCOLOR_DIALOG_MULTIPLAYER);
+       ATTRIB(XonoticServerInfoDialog, intendedWidth, float, 0.96);
        ATTRIB(XonoticServerInfoDialog, rows, float, 18);
-       ATTRIB(XonoticServerInfoDialog, columns, float, 6.2);
+       ATTRIB(XonoticServerInfoDialog, columns, float, 2);
+    ATTRIB(XonoticServerInfoDialog, infoTab, entity);
+    ATTRIB(XonoticServerInfoDialog, ToSTab, entity);
 
-       ATTRIB(XonoticServerInfoDialog, currentServerName, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerCName, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerType, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerMap, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerPlayers, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerNumPlayers, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerNumBots, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerNumFreeSlots, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerMod, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerVersion, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerKey, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerID, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerEncrypt, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerPure, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerStatsStatus, string);
-
-       ATTRIB(XonoticServerInfoDialog, nameLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, cnameLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, typeLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, mapLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, rawPlayerList, entity);
-       ATTRIB(XonoticServerInfoDialog, numPlayersLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, numBotsLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, numFreeSlotsLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, modLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, versionLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, keyLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, idLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, encryptLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, canConnectLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, pureLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, statsLabel, entity);
 ENDCLASS(XonoticServerInfoDialog)
 
 void Join_Click(entity btn, entity me);
+
diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfotab.qc b/qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfotab.qc
new file mode 100644 (file)
index 0000000..2d81f77
--- /dev/null
@@ -0,0 +1,274 @@
+#include "dialog_multiplayer_join_serverinfo.qh"
+#include <common/mapinfo.qh>
+
+#include "serverlist.qh"
+#include "playerlist.qh"
+#include "inputbox.qh"
+#include "textlabel.qh"
+#include "button.qh"
+
+
+entity makeXonoticServerInfoTab()
+{
+       entity me;
+       me = NEW(XonoticServerInfoTab);
+       me.configureDialog(me);
+       return me;
+}
+
+void XonoticServerInfoTab_loadServerInfo(entity me, float i)
+{
+       bool pure_available;
+       float m, pure_violations, freeslots, numh, maxp, numb, sflags;
+       string s, typestr, versionstr, k, v, modname;
+
+       // ====================================
+       //  First clear and unzone the strings
+       // ====================================
+       strfree(me.currentServerName);
+       strfree(me.currentServerCName);
+       strfree(me.currentServerType);
+       strfree(me.currentServerMap);
+       strfree(me.currentServerPlayers);
+       strfree(me.currentServerNumPlayers);
+       strfree(me.currentServerNumBots);
+       strfree(me.currentServerNumFreeSlots);
+       strfree(me.currentServerMod);
+       strfree(me.currentServerVersion);
+       // not zoned!
+       //      strfree(me.currentServerEncrypt);
+       strfree(me.currentServerPure);
+       strfree(me.currentServerKey);
+       strfree(me.currentServerID);
+
+       // ==========================
+       //  Now, fill in the strings
+       // ==========================
+       me.currentServerName = strzone(gethostcachestring(SLIST_FIELD_NAME, i));
+       me.nameLabel.setText(me.nameLabel, me.currentServerName);
+
+       me.currentServerCName = strzone(gethostcachestring(SLIST_FIELD_CNAME, i));
+       me.cnameLabel.setText(me.cnameLabel, me.currentServerCName);
+
+       pure_available = false;
+       pure_violations = -1;
+       typestr = _("N/A");
+       versionstr = _("N/A");
+
+       s = gethostcachestring(SLIST_FIELD_QCSTATUS, i);
+       m = tokenizebyseparator(s, ":");
+       if(m >= 2)
+       {
+               typestr = argv(0);
+               versionstr = argv(1);
+       }
+       freeslots = -1;
+       sflags = -1;
+       modname = "";
+       for(int j = 2; j < m; ++j)
+       {
+               if(argv(j) == "")
+                       break;
+               k = substring(argv(j), 0, 1);
+               v = substring(argv(j), 1, -1);
+               if(k == "P")
+               {
+                       pure_available = true;
+                       pure_violations = stof(v);
+               }
+               else if(k == "S")
+                       freeslots = stof(v);
+               else if(k == "F")
+                       sflags = stof(v);
+               else if(k == "M")
+                       modname = v;
+       }
+
+#ifdef COMPAT_NO_MOD_IS_XONOTIC
+       if(modname == "")
+               modname = "Xonotic";
+#endif
+
+       s = gethostcachestring(SLIST_FIELD_MOD, i);
+       if(s != "data")
+               modname = sprintf("%s (%s)", modname, s);
+
+       Gametype j = MapInfo_Type_FromString(typestr); // try and get the real name of the game type
+       if(j) { typestr = MapInfo_Type_ToText(j); } // only set it if we actually found it
+
+       me.currentServerType = strzone(typestr);
+       me.typeLabel.setText(me.typeLabel, me.currentServerType);
+
+       me.currentServerMap = strzone(gethostcachestring(SLIST_FIELD_MAP, i));
+       me.mapLabel.setText(me.mapLabel, me.currentServerMap);
+
+       me.currentServerPlayers = strzone(gethostcachestring(SLIST_FIELD_PLAYERS, i));
+       me.rawPlayerList.setPlayerList(me.rawPlayerList, me.currentServerPlayers);
+
+       numh = gethostcachenumber(SLIST_FIELD_NUMHUMANS, i);
+       maxp = gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i);
+       numb = gethostcachenumber(SLIST_FIELD_NUMBOTS, i);
+       me.currentServerNumPlayers = strzone(sprintf("%d/%d", numh, maxp));
+       me.numPlayersLabel.setText(me.numPlayersLabel, me.currentServerNumPlayers);
+
+       s = ftos(numb);
+       me.currentServerNumBots = strzone(s);
+       me.numBotsLabel.setText(me.numBotsLabel, me.currentServerNumBots);
+
+       if(freeslots < 0) { freeslots = maxp - numh - numb; }
+       s = ftos(freeslots);
+       me.currentServerNumFreeSlots = strzone(s);
+       me.numFreeSlotsLabel.setText(me.numFreeSlotsLabel, me.currentServerNumFreeSlots);
+
+       me.currentServerMod = ((modname == "Xonotic") ? ZCTX(_("MOD^Default")) : modname);
+       me.currentServerMod = strzone(me.currentServerMod);
+       me.modLabel.setText(me.modLabel, me.currentServerMod);
+
+       me.currentServerVersion = strzone(versionstr);
+       me.versionLabel.setText(me.versionLabel, me.currentServerVersion);
+
+       me.currentServerPure = ((!pure_available) ? _("N/A") : (pure_violations == 0) ? _("Official") : sprintf(_("%d modified"), pure_violations));
+       me.currentServerPure = strzone(me.currentServerPure);
+       me.pureLabel.setText(me.pureLabel, me.currentServerPure);
+
+       s = crypto_getencryptlevel(me.currentServerCName);
+       if(s == "")
+       {
+               if(cvar("crypto_aeslevel") >= 3)
+                       me.currentServerEncrypt = _("N/A (auth library missing, can't connect)");
+               else
+                       me.currentServerEncrypt = _("N/A (auth library missing)");
+       }
+       else switch(stof(substring(s, 0, 1)))
+       {
+               case 0:
+                       if(cvar("crypto_aeslevel") >= 3)
+                               me.currentServerEncrypt = _("Not supported (can't connect)");
+                       else
+                               me.currentServerEncrypt = _("Not supported (won't encrypt)");
+                       break;
+               case 1:
+                       if(cvar("crypto_aeslevel") >= 2)
+                               me.currentServerEncrypt = _("Supported (will encrypt)");
+                       else
+                               me.currentServerEncrypt = _("Supported (won't encrypt)");
+                       break;
+               case 2:
+                       if(cvar("crypto_aeslevel") >= 1)
+                               me.currentServerEncrypt = _("Requested (will encrypt)");
+                       else
+                               me.currentServerEncrypt = _("Requested (won't encrypt)");
+                       break;
+               case 3:
+                       if(cvar("crypto_aeslevel") <= 0)
+                               me.currentServerEncrypt = _("Required (can't connect)");
+                       else
+                               me.currentServerEncrypt = _("Required (will encrypt)");
+                       break;
+       }
+       me.encryptLabel.setText(me.encryptLabel, me.currentServerEncrypt);
+       setZonedTooltip(me.encryptLabel, _("Use the `crypto_aeslevel` cvar to change your preferences"), string_null);
+
+       s = crypto_getidfp(me.currentServerCName);
+       if (!s) { s = _("N/A"); }
+       me.currentServerID = strzone(s);
+       me.idLabel.setText(me.idLabel, me.currentServerID);
+
+       s = crypto_getkeyfp(me.currentServerCName);
+       if (!s) { s = _("N/A"); }
+       me.currentServerKey = strzone(s);
+       me.keyLabel.setText(me.keyLabel, me.currentServerKey);
+
+       me.currentServerStatsStatus = ((sflags >= 0 && (sflags & SERVERFLAG_PLAYERSTATS)) ? ((sflags & SERVERFLAG_PLAYERSTATS_CUSTOM) ? _("custom stats server") : _("stats enabled")) : _("stats disabled"));
+       me.currentServerStatsStatus = strzone(me.currentServerStatsStatus);
+       me.statsLabel.setText(me.statsLabel, me.currentServerStatsStatus);
+}
+
+void XonoticServerInfoTab_fill(entity me)
+{
+       entity e;
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Hostname:")));
+               me.TD(me, 1, 4.6, e = makeXonoticTextLabel(0.5, ""));
+               e.colorL = SKINCOLOR_SERVERINFO_NAME;
+               e.allowCut = 1;
+               me.nameLabel = e;
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Address:")));
+               me.TD(me, 1, 4.6, e = makeXonoticTextLabel(0.5, ""));
+               e.colorL = SKINCOLOR_SERVERINFO_IP;
+               e.allowCut = 1;
+               me.cnameLabel = e;
+
+       me.TR(me);
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Gametype:")));
+               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
+               e.allowCut = 1;
+               me.typeLabel = e;
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Map:")));
+               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
+               e.allowCut = 1;
+               me.mapLabel = e;
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Mod:")));
+               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
+               e.allowCut = 1;
+               me.modLabel = e;
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Version:")));
+               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
+               e.allowCut = 1;
+               me.versionLabel = e;
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Settings:")));
+               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
+               e.allowCut = 1;
+               me.pureLabel = e;
+
+       me.TR(me);
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Players:")));
+               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
+               e.allowCut = 1;
+               me.numPlayersLabel = e;
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Bots:")));
+               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
+               e.allowCut = 1;
+               me.numBotsLabel = e;
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Free slots:")));
+               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
+               e.allowCut = 1;
+               me.numFreeSlotsLabel = e;
+
+       me.gotoRC(me, me.rows - 5, 0);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Encryption:")));
+               me.TD(me, 1, 5.4, e = makeXonoticTextLabel(0, ""));
+                       e.allowCut = 1;
+                       me.encryptLabel = e;
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("ID:")));
+               me.TD(me, 1, 5.4, e = makeXonoticTextLabel(0, ""));
+                       e.allowCut = 1;
+                       me.keyLabel = e;
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Key:")));
+               me.TD(me, 1, 5.4, e = makeXonoticTextLabel(0, ""));
+                       e.allowCut = 1;
+                       me.idLabel = e;
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Stats:")));
+               me.TD(me, 1, 5.4, e = makeXonoticTextLabel(0, ""));
+                       e.allowCut = 1;
+                       me.statsLabel = e;
+
+       me.gotoRC(me, 2, 2.2); me.setFirstColumn(me, me.currentColumn);
+               me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Players:")));
+       me.TR(me);
+               me.TD(me, me.rows - 8, 4, e = makeXonoticPlayerList());
+                       me.rawPlayerList = e;
+}
+
diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfotab.qh b/qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfotab.qh
new file mode 100644 (file)
index 0000000..8962c35
--- /dev/null
@@ -0,0 +1,47 @@
+#pragma once
+
+#include "tab.qh"
+CLASS(XonoticServerInfoTab, XonoticTab)
+       METHOD(XonoticServerInfoTab, fill, void(entity));
+       METHOD(XonoticServerInfoTab, loadServerInfo, void(entity, float));
+       ATTRIB(XonoticServerInfoTab, title, string, _("Server Information"));
+       ATTRIB(XonoticServerInfoTab, color, vector, SKINCOLOR_DIALOG_SERVERINFO);
+       ATTRIB(XonoticServerInfoTab, intendedWidth, float, 0.8);
+       ATTRIB(XonoticServerInfoTab, rows, float, 17);
+       ATTRIB(XonoticServerInfoTab, columns, float, 6.2);
+
+       ATTRIB(XonoticServerInfoTab, currentServerName, string);
+       ATTRIB(XonoticServerInfoTab, currentServerCName, string);
+       ATTRIB(XonoticServerInfoTab, currentServerType, string);
+       ATTRIB(XonoticServerInfoTab, currentServerMap, string);
+       ATTRIB(XonoticServerInfoTab, currentServerPlayers, string);
+       ATTRIB(XonoticServerInfoTab, currentServerNumPlayers, string);
+       ATTRIB(XonoticServerInfoTab, currentServerNumBots, string);
+       ATTRIB(XonoticServerInfoTab, currentServerNumFreeSlots, string);
+       ATTRIB(XonoticServerInfoTab, currentServerMod, string);
+       ATTRIB(XonoticServerInfoTab, currentServerVersion, string);
+       ATTRIB(XonoticServerInfoTab, currentServerKey, string);
+       ATTRIB(XonoticServerInfoTab, currentServerID, string);
+       ATTRIB(XonoticServerInfoTab, currentServerEncrypt, string);
+       ATTRIB(XonoticServerInfoTab, currentServerPure, string);
+       ATTRIB(XonoticServerInfoTab, currentServerStatsStatus, string);
+
+       ATTRIB(XonoticServerInfoTab, nameLabel, entity);
+       ATTRIB(XonoticServerInfoTab, cnameLabel, entity);
+       ATTRIB(XonoticServerInfoTab, typeLabel, entity);
+       ATTRIB(XonoticServerInfoTab, mapLabel, entity);
+       ATTRIB(XonoticServerInfoTab, rawPlayerList, entity);
+       ATTRIB(XonoticServerInfoTab, numPlayersLabel, entity);
+       ATTRIB(XonoticServerInfoTab, numBotsLabel, entity);
+       ATTRIB(XonoticServerInfoTab, numFreeSlotsLabel, entity);
+       ATTRIB(XonoticServerInfoTab, modLabel, entity);
+       ATTRIB(XonoticServerInfoTab, versionLabel, entity);
+       ATTRIB(XonoticServerInfoTab, keyLabel, entity);
+       ATTRIB(XonoticServerInfoTab, idLabel, entity);
+       ATTRIB(XonoticServerInfoTab, encryptLabel, entity);
+       ATTRIB(XonoticServerInfoTab, canConnectLabel, entity);
+       ATTRIB(XonoticServerInfoTab, pureLabel, entity);
+       ATTRIB(XonoticServerInfoTab, statsLabel, entity);
+ENDCLASS(XonoticServerInfoTab)
+entity makeXonoticServerInfoTab();
+