Author Freddy, contributed by z411, minor contributions by Mario, LegendaryGuard and terencehill
///////////////////////////
// cvar constants
-const int CVAR_SAVE = 1;
-const int CVAR_NOTIFY = 2;
-const int CVAR_READONLY = 4;
+const int CVAR_SAVE = BIT(0);
+const int CVAR_NOTIFY = BIT(1);
+const int CVAR_READONLY = BIT(2);
// server flags
-const int SERVERFLAG_ALLOW_FULLBRIGHT = 1;
-const int SERVERFLAG_TEAMPLAY = 2;
-const int SERVERFLAG_PLAYERSTATS = 4;
+const int SERVERFLAG_ALLOW_FULLBRIGHT = BIT(0);
+const int SERVERFLAG_TEAMPLAY = BIT(1);
+const int SERVERFLAG_PLAYERSTATS = BIT(2);
+const int SERVERFLAG_PLAYERSTATS_CUSTOM = BIT(3);
const int SPECIES_HUMAN = 0;
const int SPECIES_ROBOT_SOLID = 1;
PlayerStats_GameReport_DelayMapVote = true;
serverflags |= SERVERFLAG_PLAYERSTATS;
+ if(autocvar_g_playerstats_gamereport_uri != cvar_defstring("g_playerstats_gamereport_uri"))
+ {
+ serverflags |= SERVERFLAG_PLAYERSTATS_CUSTOM;
+ }
PlayerStats_GameReport_AddEvent(PLAYERSTATS_ALIVETIME);
PlayerStats_GameReport_AddEvent(PLAYERSTATS_AVGLATENCY);
const int URI_GET_CURL = 17;
const int URI_GET_CURL_END = 32;
const int URI_GET_UPDATENOTIFICATION = 33;
+const int URI_GET_TOS = 34;
const int URI_GET_URLLIB = 128;
const int URI_GET_URLLIB_END = 191;
#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_termsofservice.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>
#include <menu/xonotic/dialog_singleplayer.qc>
#include <menu/xonotic/dialog_singleplayer_winner.qc>
#include <menu/xonotic/dialog_teamselect.qc>
+#include <menu/xonotic/dialog_termsofservice.qc>
#include <menu/xonotic/dialog_uid2name.qc>
#include <menu/xonotic/gametypelist.qc>
#include <menu/xonotic/hudskinlist.qc>
#include <menu/xonotic/statslist.qc>
#include <menu/xonotic/tab.qc>
#include <menu/xonotic/tabcontroller.qc>
+#include <menu/xonotic/textbox.qc>
#include <menu/xonotic/textlabel.qc>
#include <menu/xonotic/textslider.qc>
#include <menu/xonotic/util.qc>
#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_termsofservice.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>
#include <menu/xonotic/dialog_singleplayer.qh>
#include <menu/xonotic/dialog_singleplayer_winner.qh>
#include <menu/xonotic/dialog_teamselect.qh>
+#include <menu/xonotic/dialog_termsofservice.qh>
#include <menu/xonotic/dialog_uid2name.qh>
#include <menu/xonotic/gametypelist.qh>
#include <menu/xonotic/hudskinlist.qh>
#include <menu/xonotic/statslist.qh>
#include <menu/xonotic/tab.qh>
#include <menu/xonotic/tabcontroller.qh>
+#include <menu/xonotic/textbox.qh>
#include <menu/xonotic/textlabel.qh>
#include <menu/xonotic/textslider.qh>
#include <menu/xonotic/util.qh>
#include "charmap.qh"
#include "commandbutton.qh"
+bool XonoticFirstRunDialog_shouldShow()
+{
+ return cvar_string("_cl_name") == cvar_defstring("_cl_name");
+}
+
float CheckFirstRunButton(entity me)
{
if(cvar_string("_cl_name") != cvar_defstring("_cl_name"))
#include "rootdialog.qh"
CLASS(XonoticFirstRunDialog, XonoticRootDialog)
METHOD(XonoticFirstRunDialog, fill, void(entity));
+ METHOD(XonoticFirstRunDialog, shouldShow, bool());
ATTRIB(XonoticFirstRunDialog, title, string, _("Welcome"));
ATTRIB(XonoticFirstRunDialog, color, vector, SKINCOLOR_DIALOG_FIRSTRUN);
ATTRIB(XonoticFirstRunDialog, intendedWidth, float, 0.7);
#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_termsofservice.qh"
+
void XonoticServerInfoDialog_loadServerInfo(entity me, float i)
{
// Now, fill in the strings
// ==========================
me.currentServerName = strzone(gethostcachestring(SLIST_FIELD_NAME, i));
- me.nameLabel.setText(me.nameLabel, me.currentServerName);
+ me.infoTab.nameLabel.setText(me.infoTab.nameLabel, me.currentServerName);
me.currentServerCName = strzone(gethostcachestring(SLIST_FIELD_CNAME, i));
- me.cnameLabel.setText(me.cnameLabel, me.currentServerCName);
+ me.infoTab.cnameLabel.setText(me.infoTab.cnameLabel, me.currentServerCName);
pure_available = false;
pure_violations = -1;
freeslots = -1;
sflags = -1;
modname = "";
+ bool ToSSpecified = false;
for(int j = 2; j < m; ++j)
{
if(argv(j) == "")
pure_violations = stof(v);
}
else if(k == "S")
+ {
freeslots = stof(v);
+ }
else if(k == "F")
+ {
sflags = stof(v);
+ }
else if(k == "M")
+ {
modname = v;
+ }
+ else if(k == "T")
+ {
+ ToSSpecified = true;
+ string downloadurl = v;
+ LOG_INFOF("SERVERTOS DOWNLOADURL: %s", downloadurl);
+ if (downloadurl == "INVALID")
+ {
+ me.ToSTab.textBox.setText(me.ToSTab.textBox, _("No Terms of Service specified"));
+ }
+ else
+ {
+ downloadurl = strreplace("|", ":", downloadurl);
+ me.ToSTab.loadToS(me.ToSTab, downloadurl);
+ }
+ }
+ }
+
+ if (!ToSSpecified)
+ {
+ me.ToSTab.textBox.setText(me.ToSTab.textBox, _("No Terms of Service specified"));
}
#ifdef COMPAT_NO_MOD_IS_XONOTIC
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.infoTab.typeLabel.setText(me.infoTab.typeLabel, me.currentServerType);
me.currentServerMap = strzone(gethostcachestring(SLIST_FIELD_MAP, i));
- me.mapLabel.setText(me.mapLabel, me.currentServerMap);
+ me.infoTab.mapLabel.setText(me.infoTab.mapLabel, me.currentServerMap);
me.currentServerPlayers = strzone(gethostcachestring(SLIST_FIELD_PLAYERS, i));
- me.rawPlayerList.setPlayerList(me.rawPlayerList, me.currentServerPlayers);
+ me.infoTab.rawPlayerList.setPlayerList(me.infoTab.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);
+ me.infoTab.numPlayersLabel.setText(me.infoTab.numPlayersLabel, me.currentServerNumPlayers);
s = ftos(numb);
me.currentServerNumBots = strzone(s);
- me.numBotsLabel.setText(me.numBotsLabel, me.currentServerNumBots);
+ me.infoTab.numBotsLabel.setText(me.infoTab.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.infoTab.numFreeSlotsLabel.setText(me.infoTab.numFreeSlotsLabel, me.currentServerNumFreeSlots);
me.currentServerMod = ((modname == "Xonotic") ? ZCTX(_("MOD^Default")) : modname);
me.currentServerMod = strzone(me.currentServerMod);
- me.modLabel.setText(me.modLabel, me.currentServerMod);
+ me.infoTab.modLabel.setText(me.infoTab.modLabel, me.currentServerMod);
me.currentServerVersion = strzone(versionstr);
- me.versionLabel.setText(me.versionLabel, me.currentServerVersion);
+ me.infoTab.versionLabel.setText(me.infoTab.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);
+ me.infoTab.pureLabel.setText(me.infoTab.pureLabel, me.currentServerPure);
s = crypto_getencryptlevel(me.currentServerCName);
if(s == "")
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);
+ me.infoTab.encryptLabel.setText(me.infoTab.encryptLabel, me.currentServerEncrypt);
+ setZonedTooltip(me.infoTab.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);
+ me.infoTab.idLabel.setText(me.infoTab.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.infoTab.keyLabel.setText(me.infoTab.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.infoTab.statsLabel.setText(me.infoTab.statsLabel, me.currentServerStatsStatus);
}
void XonoticServerInfoDialog_fill(entity me)
{
- entity e;
+ entity mc, e;
+ mc = makeXonoticTabController(me.rows - 2);
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.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Status"), me.infoTab = makeXonoticServerInfoTab()));
+ me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Terms of Service"), me.ToSTab = makeXonoticServerToSTab()));
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.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 - 2, me.columns, mc);
me.gotoRC(me, me.rows - 1, 0);
me.TD(me, 1, me.columns/2, e = makeXonoticButton(_("Close"), '0 0 0'));
{
localcmd("connect ", me.currentServerCName, "\n");
}
+
#include "dialog.qh"
CLASS(XonoticServerInfoDialog, XonoticDialog)
- 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, rows, float, 18);
- ATTRIB(XonoticServerInfoDialog, columns, float, 6.2);
+ METHOD(XonoticServerInfoDialog, fill, void(entity));
+ ATTRIB(XonoticServerInfoDialog, title, string, _("Server Info"));
+ ATTRIB(XonoticServerInfoDialog, color, vector, SKINCOLOR_DIALOG_MULTIPLAYER);
+ ATTRIB(XonoticServerInfoDialog, intendedWidth, float, 0.96);
+ ATTRIB(XonoticServerInfoDialog, rows, float, 19);
+ 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(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(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);
ENDCLASS(XonoticServerInfoDialog)
void Join_Click(entity btn, entity me);
+
--- /dev/null
+#include "dialog_multiplayer_join_serverinfo.qh"
+#include "dialog_multiplayer_join_serverinfotab.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_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;
+}
+
--- /dev/null
+#pragma once
+
+#include "tab.qh"
+CLASS(XonoticServerInfoTab, XonoticTab)
+ METHOD(XonoticServerInfoTab, fill, void(entity));
+ 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, 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();
+
--- /dev/null
+#include "dialog_multiplayer_join_termsofservice.qh"
+
+#include "textbox.qh"
+#include <lib/urllib.qh>
+
+
+entity makeXonoticServerToSTab()
+{
+ entity me;
+ me = NEW(XonoticServerToSTab);
+ me.configureDialog(me);
+ return me;
+}
+
+void XonoticServerToSTab_loadToS(entity me, string downloadurl)
+{
+ url_single_fopen(downloadurl, FILE_READ, AdditionalServerInfo_OnGet, me);
+}
+
+void XonoticServerToSTab_fill(entity me)
+{
+ entity e;
+ me.TR(me);
+ me.TD(me, me.rows, me.columns, e = makeXonoticTextBox());
+ me.textBox = e;
+}
+
+void AdditionalServerInfo_OnGet(entity fh, entity me, int status)
+{
+ switch (status) {
+ case URL_READY_CLOSED:
+ {
+ break;
+ }
+ case URL_READY_ERROR:
+ {
+ me.text = strzone("Error reading ToS");
+ me.textBox.setText(me.textBox, me.text);
+ break;
+ }
+ case URL_READY_CANREAD:
+ {
+ strfree(me.text);
+ string temp = "";
+ for (string s; (s = url_fgets(fh)); )
+ {
+ if (temp != "")
+ temp = strcat(temp, "\n", s);
+ else
+ temp = s;
+ }
+ url_fclose(fh);
+ me.text = strzone(temp);
+ me.textBox.setText(me.textBox, me.text);
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+}
--- /dev/null
+#pragma once
+
+#include "tab.qh"
+CLASS(XonoticServerToSTab, XonoticTab)
+ METHOD(XonoticServerToSTab, fill, void(entity));
+ METHOD(XonoticServerToSTab, loadToS, void(entity, string));
+ 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, text, string);
+ ATTRIB(XonoticServerToSTab, textBox, entity);
+ENDCLASS(XonoticServerToSTab)
+entity makeXonoticServerToSTab();
+
+void AdditionalServerInfo_OnGet(entity fh, entity pass, int status);
--- /dev/null
+#include "dialog_termsofservice.qh"
+
+#include "../menu.qh"
+#include "mainwindow.qh"
+#include "dialog_firstrun.qh"
+#include "textbox.qh"
+#include "textlabel.qh"
+#include "button.qh"
+#include "util.qh"
+
+void Close_Clicked(entity btn, entity me)
+{
+ LOG_INFOF("Accepted ToS version %d", _Nex_ExtResponseSystem_NewToS);
+ cvar_set("_termsofservice_accepted", ftos(_Nex_ExtResponseSystem_NewToS));
+ localcmd("saveconfig\n");
+ if (main.firstRunDialog.shouldShow())
+ main.firstDraw = true;
+ Dialog_Close(btn, me);
+}
+
+void DontAccept_Clicked(entity btn, entity me)
+{
+ localcmd("quit\n");
+}
+
+void XonoticToSDialog_loadXonoticToS(entity me)
+{
+ url_single_fopen(termsofservice_url, FILE_READ, XonoticToS_OnGet, me);
+}
+
+void XonoticToS_OnGet(entity fh, entity me, int status)
+{
+ switch (status) {
+ case URL_READY_CLOSED:
+ {
+ break;
+ }
+ case URL_READY_ERROR:
+ {
+ me.text = strzone("Error reading ToS");
+ me.textBox.setText(me.textBox, me.text);
+ break;
+ }
+ case URL_READY_CANREAD:
+ {
+ strfree(me.text);
+ string temp = "";
+ for (string s; (s = url_fgets(fh)); )
+ {
+ if (temp != "")
+ temp = strcat(temp, "\n", s);
+ else
+ temp = s;
+ }
+ url_fclose(fh);
+ me.text = strzone(temp);
+ me.textBox.setText(me.textBox, me.text);
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+}
+
+bool XonoticToSDialog_shouldShow()
+{
+ return (_Nex_ExtResponseSystem_NewToS && _Nex_ExtResponseSystem_NewToS > autocvar__termsofservice_accepted);
+}
+
+void XonoticToSDialog_fill(entity me)
+{
+ entity e;
+ string subtitle;
+
+ if (autocvar__termsofservice_accepted > 0)
+ subtitle = _("Terms of Service have been updated. Please read them before continuing:");
+ else
+ subtitle = _("Welcome to Xonotic! Please read the following Terms of Service:");
+
+ me.TR(me);
+ me.TD(me, 1, 5, e = makeXonoticTextLabel(0, subtitle));
+ e.allowWrap = 1;
+
+ me.TR(me);
+ me.TR(me);
+ me.TD(me, me.rows - 4, me.columns, me.textBox = makeXonoticTextBox());
+ me.loadXonoticToS(me);
+
+ me.TR(me);
+ me.gotoRC(me, me.rows - 1, 0);
+
+ me.TD(me, 1, me.columns/2, e = makeXonoticButton(_("Accept"), '0 1 0'));
+ e.onClick = Close_Clicked;
+ e.onClickEntity = me;
+
+ me.TD(me, 1, me.columns/2, e = makeXonoticButton(_("Don't accept (quit the game)"), '1 0 0'));
+ e.onClick = DontAccept_Clicked;
+ e.onClickEntity = me;
+}
+
--- /dev/null
+#pragma once
+
+int autocvar__termsofservice_accepted;
+const string termsofservice_url = "http://update.xonotic.org/tos.txt";
+
+#include "rootdialog.qh"
+CLASS(XonoticToSDialog, XonoticRootDialog)
+ METHOD(XonoticToSDialog, shouldShow, bool());
+ METHOD(XonoticToSDialog, fill, void(entity));
+ METHOD(XonoticToSDialog, loadXonoticToS, void(entity));
+ ATTRIB(XonoticToSDialog, title, string, _("Terms of Service"));
+ ATTRIB(XonoticToSDialog, color, vector, SKINCOLOR_DIALOG_FIRSTRUN);
+ ATTRIB(XonoticToSDialog, intendedWidth, float, 0.8);
+ ATTRIB(XonoticToSDialog, rows, float, 16);
+ ATTRIB(XonoticToSDialog, columns, float, 6.2);
+ ATTRIB(XonoticToSDialog, name, string, "TermsOfService");
+
+ ATTRIB(XonoticToSDialog, text, string);
+ ATTRIB(XonoticToSDialog, textBox, entity);
+
+ ATTRIB(XonoticToSDialog, closable, float, 0);
+ENDCLASS(XonoticToSDialog)
+
+void XonoticToS_OnGet(entity fh, entity me, int status);
#include "nexposee.qh"
#include "inputbox.qh"
+#include "dialog_termsofservice.qh"
#include "dialog_firstrun.qh"
#include "dialog_hudsetup_exit.qh"
#include "dialog_hudpanel_notification.qh"
{
SUPER(MainWindow).draw(me);
- if(me.dialogToShow)
- {
- DialogOpenButton_Click_withCoords(NULL, me.dialogToShow, '0 0 0', eX * conwidth + eY * conheight);
- me.dialogToShow = NULL;
+ if (me.firstDraw) {
+ if (me.ToSDialog.shouldShow())
+ DialogOpenButton_Click_withCoords(NULL, me.ToSDialog, '0 0 0', eX * conwidth + eY * conheight);
+ else if(me.firstRunDialog.shouldShow())
+ DialogOpenButton_Click_withCoords(NULL, me.firstRunDialog, '0 0 0', eX * conwidth + eY * conheight);
+
+ me.firstDraw = false;
}
//-------------------------------------
{
entity n, i;
+ // terms of service dialog
+ me.ToSDialog = i = NEW(XonoticToSDialog);
+ i.configureDialog(i);
+ me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+
// dialog run upon startup
me.firstRunDialog = i = NEW(XonoticFirstRunDialog);
i.configureDialog(i);
// main dialogs/windows
me.mainNexposee = n = NEW(XonoticNexposee);
-
+
/*
if(checkextension("DP_GECKO_SUPPORT"))
{
n.setNexposee(n, i, '0.1 0.1 0', SKINALPHAS_MAINMENU_x, SKINALPHAS_MAINMENU_y);
}
*/
-
+
i = NEW(XonoticSingleplayerDialog);
i.configureDialog(i);
n.addItemCentered(n, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
me.initializeDialog(me, n);
me.disconnectDialogVisibility = 1;
-
- if(cvar_string("_cl_name") == cvar_defstring("_cl_name"))
- me.dialogToShow = me.firstRunDialog;
}
CLASS(MainWindow, ModalController)
METHOD(MainWindow, configureMainWindow, void(entity));
METHOD(MainWindow, draw, void(entity));
+ ATTRIB(MainWindow, ToSDialog, entity);
ATTRIB(MainWindow, firstRunDialog, entity);
ATTRIB(MainWindow, advancedDialog, entity);
ATTRIB(MainWindow, mutatorsDialog, entity);
ATTRIB(MainWindow, languageWarningDialog, entity);
ATTRIB(MainWindow, mainNexposee, entity);
ATTRIB(MainWindow, fadedAlpha, float, SKINALPHA_BEHIND);
- ATTRIB(MainWindow, dialogToShow, entity);
+ ATTRIB(MainWindow, firstDraw, bool, true);
ATTRIB(MainWindow, demostartconfirmDialog, entity);
ATTRIB(MainWindow, demotimeconfirmDialog, entity);
ATTRIB(MainWindow, resetDialog, entity);
.float realUpperMargin2;
-const float PLAYERPARM_SCORE = 0;
-const float PLAYERPARM_PING = 1;
-const float PLAYERPARM_TEAM = 2;
-const float PLAYERPARM_NAME = 3;
-const float PLAYERPARM_COUNT = 4;
+const int PLAYERPARM_SCORE = 0;
+const int PLAYERPARM_PING = 1;
+const int PLAYERPARM_TEAM = 2;
+const int PLAYERPARM_NAME = 3;
+const int PLAYERPARM_COUNT = 4;
entity makeXonoticPlayerList()
{
s = bufstr_get(buf, i * PLAYERPARM_COUNT + PLAYERPARM_NAME);
n = tokenize_console(s);
- if(n == 4)
+ if(n == PLAYERPARM_COUNT)
{
bufstr_set(buf, i * PLAYERPARM_COUNT + PLAYERPARM_SCORE, argv(0)); // -666
bufstr_set(buf, i * PLAYERPARM_COUNT + PLAYERPARM_PING, argv(1)); // 100
// Stats
if(sflags >= 0 && (sflags & SERVERFLAG_PLAYERSTATS))
- draw_Picture(iconPos, "icon_stats1", iconSize, '1 1 1', 1);
+ {
+ if (sflags & SERVERFLAG_PLAYERSTATS_CUSTOM)
+ {
+ draw_Picture(iconPos, "icon_mod_", iconSize, '1 1 1', 1); // TODO: icon
+ }
+ else
+ {
+ draw_Picture(iconPos, "icon_stats1", iconSize, '1 1 1', 1);
+ }
+ }
+ else
+ {
+ draw_Picture(iconPos, "icon_mod_jeff", iconSize, '1 1 1', 1); // TODO: icon
+ }
if(isFocused && me.mouseOverIcons && !me.tooltip)
{
if(pure_available)
t = strcat(t, sprintf(" (%s)", (pure) ? _("official settings") : _("modified settings")));
t = strcat(t, ", ");
- t = strcat(t, ((sflags >= 0 && (sflags & SERVERFLAG_PLAYERSTATS)) ? _("stats enabled") : _("stats disabled")));
+ t = strcat(t, ((sflags >= 0 && (sflags & SERVERFLAG_PLAYERSTATS)) ? ((sflags & SERVERFLAG_PLAYERSTATS_CUSTOM) ? _("custom stats server") : _("stats enabled")) : _("stats disabled")));
setZonedTooltip(me, t, string_null);
}
// --------------
--- /dev/null
+#include "textbox.qh"
+#include "../item/label.qh"
+
+entity makeXonoticTextBox()
+{
+ entity me;
+ me = NEW(XonoticTextBox);
+ me.configureXonoticListBox(me);
+ return me;
+}
+
+void XonoticTextBox_destroy(entity me)
+{
+ if (me.stringList >= 0)
+ {
+ buf_del(me.stringList);
+ me.stringList = -1;
+ }
+}
+
+void XonoticTextBox_setText(entity me, string text)
+{
+ if (me.stringList >= 0)
+ {
+ buf_del(me.stringList);
+ me.stringList = -1;
+ }
+
+ int buf;
+ int line = 0;
+
+ string t;
+
+ buf = buf_create();
+ for (int i = 0, n = tokenizebyseparator(text, "\n"); i < n; ++i)
+ {
+ t = substring(argv(i), 0, -1);
+ getWrappedLine_remaining = t;
+ while (getWrappedLine_remaining)
+ {
+ t = getWrappedLine(1, me.realFontSize, draw_TextWidth_WithColors);
+ bufstr_set(buf, line, t);
+ line++;
+ }
+ }
+
+ me.stringList = buf;
+ me.nItems = line+1;
+}
+
+string XonoticTextBox_getTextBoxLine(entity me, int i)
+{
+ if (me.stringList >= 0)
+ {
+ return bufstr_get(me.stringList, i);
+ }
+ return string_null;
+}
+
+// mostly copied from playerlist
+// FIXME: is this really needed
+void XonoticTextBox_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
+{
+ me.itemAbsSize = '0 0 0';
+ SUPER(XonoticTextBox).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
+
+ me.itemAbsSize.y = absSize.y * me.itemHeight;
+ me.itemAbsSize.x = absSize.x * (1 - me.controlWidth);
+ me.realFontSize.y = me.fontSize / me.itemAbsSize.y;
+ me.realFontSize.x = me.fontSize / me.itemAbsSize.x;
+ string temp = string_null;
+ for (int i = 0; i < me.nItems; ++i)
+ {
+ if (!temp)
+ {
+ temp = me.getTextBoxLine(me, i);
+ }
+ else
+ {
+ temp = strcat(temp, "\n", me.getTextBoxLine(me, i));
+ }
+ }
+ me.setText(me, temp);
+}
+
+void XonoticTextBox_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
+{
+ string s = me.getTextBoxLine(me, i);
+ draw_Text(vec2(0, 0), s, me.realFontSize, me.colorL, me.alpha, true);
+}
--- /dev/null
+#pragma once
+
+#include "listbox.qh"
+
+// slightly hacky multiline textbox with scrollbar
+CLASS(XonoticTextBox, XonoticListBox)
+ METHOD(XonoticTextBox, destroy, void(entity));
+ ATTRIB(XonoticTextBox, rowsPerItem, float, 1);
+ METHOD(XonoticTextBox, resizeNotify, void(entity, vector, vector, vector, vector));
+ METHOD(XonoticTextBox, drawListBoxItem, void(entity, int, vector, bool, bool));
+ ATTRIB(XonoticTextBox, allowFocusSound, float, 0);
+ ATTRIB(XonoticTextBox, alpha, float, SKINALPHA_TEXT);
+ ATTRIB(XonoticTextBox, fontSize, float, SKINFONTSIZE_NORMAL);
+ ATTRIB(XonoticTextBox, realFontSize, vector, '0 0 0');
+ ATTRIB(XonoticTextBox, itemAbsSize, vector, '0 0 0');
+ METHOD(XonoticTextBox, setText, void(entity, string));
+ METHOD(XonoticTextBox, getTextBoxLine, string(entity, int));
+ ATTRIB(XonoticTextBox, nItems, int, 0);
+ ATTRIB(XonoticTextBox, stringList, int, -1);
+ ATTRIB(XonoticTextBox, selectionDoesntMatter, bool, true);
+ENDCLASS(XonoticTextBox)
+entity makeXonoticTextBox();
+
string s;
string un_version = "";
+ string un_tosversion = "";
string un_download = "";
string un_url = "";
string un_bannedservers = "";
un_version = s;
break;
}
+ case "T":
+ {
+ un_tosversion = s;
+ break;
+ }
case "C":
{
un_compatexpire = s;
}
}
}
+
+ if(un_tosversion != "")
+ {
+ _Nex_ExtResponseSystem_NewToS = stof(un_tosversion);
+ LOG_INFOF("Latest ToS version is %d", _Nex_ExtResponseSystem_NewToS);
+ }
if(un_bannedservers != "")
{
draw_CenterText(mid - 1 * line, l1, fs, '1 0 0', 1, 0);
draw_CenterText(mid - 0 * line, l2, fs, '0 0 1', 1, 0);
}
+
if (!campaign_name_previous)
campaign_name_previous = strzone(strcat(campaign_name, "x")); // force unequal
if(campaign_name == campaign_name_previous)
float _Nex_ExtResponseSystem_PromotedServersNeedsRefresh;
string _Nex_ExtResponseSystem_RecommendedServers;
float _Nex_ExtResponseSystem_RecommendedServersNeedsRefresh;
+float _Nex_ExtResponseSystem_NewToS;
void CheckSendCvars(entity me, string cvarnamestring);
s = strcat(s, ":P", ftos(cvar_purechanges_count));
s = strcat(s, ":S", ftos(nJoinAllowed(this, NULL)));
s = strcat(s, ":F", ftos(serverflags));
+ s = strcat(s, ":T", sv_termsofservice_url_escaped);
s = strcat(s, ":M", modname);
s = strcat(s, "::", GetPlayerScoreString(NULL, (fullstatus ? 1 : 2)));
{
server_is_dedicated = boolean(stof(cvar_defstring("is_dedicated")));
+ if (autocvar_sv_termsofservice_url && autocvar_sv_termsofservice_url != "")
+ {
+ strcpy(sv_termsofservice_url_escaped, strreplace(":", "|", autocvar_sv_termsofservice_url));
+ }
+ else
+ {
+ strcpy(sv_termsofservice_url_escaped, "INVALID");
+ }
+
bool wantrestart = false;
{
if (!server_is_dedicated)
WeaponStats_Shutdown();
MapInfo_Shutdown();
+
+ strfree(sv_termsofservice_url_escaped);
}
else if(world_initialized == 0)
{
string record_type;
+string autocvar_sv_termsofservice_url;
+// only escape the terms of service url on map change
+string sv_termsofservice_url_escaped;
+
string clientstuff;
string matchid;
seta cl_allow_uidtracking 1 "-1 = ask if the player wants to disable/enable this feature, 0 = disable, 1 = enable uid tracking (allows associating your data with your player ID)"
seta cl_allow_uidranking 1 "0 = disable, 1 = enable uid ranking (allows statistics like elo to rank you in leaderboards)"
+// terms of service
+seta _termsofservice_accepted 0
+
// polygonoffset for submodel SUCKS SUCKS SUCKS (only a hack for quake1, we don't need that)
r_polygonoffset_submodel_offset 0
r_polygonoffset_submodel_factor 0