ATTRIB(XonoticServerList, seenIPv4, float, 0)
ATTRIB(XonoticServerList, seenIPv6, float, 0)
+ ATTRIB(XonoticServerList, categoriesHeight, float, 1.25)
+
+ METHOD(XonoticServerList, getTotalHeight, float(entity))
+ METHOD(XonoticServerList, getItemAtPos, float(entity, float))
+ METHOD(XonoticServerList, getItemStart, float(entity, float))
+ METHOD(XonoticServerList, getItemHeight, float(entity, float))
ENDCLASS(XonoticServerList)
entity makeXonoticServerList();
var float autocvar_menu_slist_categories = TRUE;
var float autocvar_menu_slist_categories_onlyifmultiple = TRUE;
var float autocvar_menu_slist_purethreshold = 10;
-var string autocvar_menu_slist_recommended = "76.124.107.5:26004";
+var float autocvar_menu_slist_modimpurity = 10;
+var float autocvar_menu_slist_recommendations = 2;
+var float autocvar_menu_slist_recommendations_maxping = 150;
+var float autocvar_menu_slist_recommendations_minfreeslots = 1;
+var float autocvar_menu_slist_recommendations_minhumans = 1;
+var float autocvar_menu_slist_recommendations_purethreshold = -1;
+//var string autocvar_menu_slist_recommended = "76.124.107.5:26004";
// server cache fields
#define SLIST_FIELDS \
SLIST_FIELDS
#undef SLIST_FIELD
-// sort flags
-const float SLSF_DESCENDING = 1;
-const float SLSF_FAVORITES = 2;
-const float SLSF_CATEGORIES = 4;
-
const float REFRESHSERVERLIST_RESORT = 0; // sort the server list again to update for changes to e.g. favorite status, categories
const float REFRESHSERVERLIST_REFILTER = 1; // ..., also update filter and sort criteria
const float REFRESHSERVERLIST_ASK = 2; // ..., also suggest querying servers now
const float REFRESHSERVERLIST_RESET = 3; // ..., also clear the list first
// function declarations
-float Get_Cat_Num_FromString(string input);
-entity Get_Cat_Ent(float catnum);
+entity RetrieveCategoryEnt(float catnum);
float IsServerInList(string list, string srv);
#define IsFavorite(srv) IsServerInList(cvar_string("net_slist_favorites"), srv)
-#define IsRecommended(srv) IsServerInList(cvar_string("menu_slist_recommended"), srv) // todo: use update notification instead of cvar
+#define IsRecommended(srv) IsServerInList(_Nex_ExtResponseSystem_RecommendedServers, srv)
float CheckCategoryOverride(float cat);
float CheckCategoryForEntry(float entry);
-float m_getserverlistentrycategory(float entry) { return CheckCategoryOverride(CheckCategoryForEntry(entry)); }
+float m_gethostcachecategory(float entry) { return CheckCategoryOverride(CheckCategoryForEntry(entry)); }
void RegisterSLCategories();
float category_draw_count;
#define SLIST_CATEGORIES \
- SLIST_CATEGORY(CAT_FAVORITED, "", "", _("Favorites")) \
- SLIST_CATEGORY(CAT_RECOMMENDED, "", "CAT_SERVERS", _("Recommended")) \
- SLIST_CATEGORY(CAT_NORMAL, "", "CAT_SERVERS", _("Normal Servers")) \
- SLIST_CATEGORY(CAT_SERVERS, "CAT_NORMAL", "CAT_SERVERS", _("Servers")) \
- SLIST_CATEGORY(CAT_XPM, "CAT_NORMAL", "CAT_SERVERS", _("Competitive Mode")) \
- SLIST_CATEGORY(CAT_MODIFIED, "", "CAT_SERVERS", _("Modified Servers")) \
- SLIST_CATEGORY(CAT_OVERKILL, "", "CAT_SERVERS", _("Overkill Mode")) \
- SLIST_CATEGORY(CAT_MINSTAGIB, "", "CAT_SERVERS", _("MinstaGib Mode")) \
- SLIST_CATEGORY(CAT_DEFRAG, "", "CAT_SERVERS", _("Defrag Mode"))
+ SLIST_CATEGORY(CAT_FAVORITED, "", "", ZCTX(_("SLCAT^Favorites"))) \
+ SLIST_CATEGORY(CAT_RECOMMENDED, "", "CAT_SERVERS", ZCTX(_("SLCAT^Recommended"))) \
+ SLIST_CATEGORY(CAT_NORMAL, "", "CAT_SERVERS", ZCTX(_("SLCAT^Normal Servers"))) \
+ SLIST_CATEGORY(CAT_SERVERS, "CAT_NORMAL", "CAT_SERVERS", ZCTX(_("SLCAT^Servers"))) \
+ SLIST_CATEGORY(CAT_XPM, "CAT_NORMAL", "CAT_SERVERS", ZCTX(_("SLCAT^Competitive Mode"))) \
+ SLIST_CATEGORY(CAT_MODIFIED, "", "CAT_SERVERS", ZCTX(_("SLCAT^Modified Servers"))) \
+ SLIST_CATEGORY(CAT_OVERKILL, "", "CAT_SERVERS", ZCTX(_("SLCAT^Overkill Mode"))) \
+ SLIST_CATEGORY(CAT_MINSTAGIB, "", "CAT_SERVERS", ZCTX(_("SLCAT^MinstaGib Mode"))) \
+ SLIST_CATEGORY(CAT_DEFRAG, "", "CAT_SERVERS", ZCTX(_("SLCAT^Defrag Mode")))
#define SLIST_CATEGORY_AUTOCVAR(name) autocvar_menu_slist_categories_##name##_override
#define SLIST_CATEGORY(name,enoverride,dioverride,str) \
SLIST_CATEGORIES
#undef SLIST_CATEGORY
- float i, catnum;
+ float i, x, catnum;
string s;
#define PROCESS_OVERRIDE(override_string,override_field) \
s = categories[i].override_string; \
if((s != "") && (s != categories[i].cat_name)) \
{ \
- catnum = Get_Cat_Num_FromString(s); \
+ catnum = 0; \
+ for(x = 0; x < category_ent_count; ++x) \
+ { if(categories[x].cat_name == s) { \
+ catnum = (x+1); \
+ break; \
+ } } \
if(catnum) \
{ \
strunzone(categories[i].override_string); \
categories[i].override_field = catnum; \
continue; \
} \
+ else \
+ { \
+ print(sprintf( \
+ "RegisterSLCategories(): Improper override '%s' for category '%s'!\n", \
+ s, \
+ categories[i].cat_name \
+ )); \
+ } \
} \
strunzone(categories[i].override_string); \
categories[i].override_field = 0; \
}
// Supporting Functions
-float Get_Cat_Num_FromString(string input)
-{
- float i;
- for(i = 0; i < category_ent_count; ++i) { if(categories[i].cat_name == input) { return (i + 1); } }
- print(sprintf("Get_Cat_Num_FromString('%s'): Improper category name!\n", input));
- return 0;
-}
-entity Get_Cat_Ent(float catnum)
+entity RetrieveCategoryEnt(float catnum)
{
if((catnum > 0) && (catnum <= category_ent_count))
{
}
else
{
- error(sprintf("Get_Cat_Ent(%d): Improper category number!\n", catnum));
+ error(sprintf("RetrieveCategoryEnt(%d): Improper category number!\n", catnum));
return world;
}
}
float CheckCategoryOverride(float cat)
{
- entity catent = Get_Cat_Ent(cat);
+ entity catent = RetrieveCategoryEnt(cat);
if(catent)
{
float override = (autocvar_menu_slist_categories ? catent.cat_enoverride : catent.cat_dioverride);
float CheckCategoryForEntry(float entry)
{
string s, k, v, modtype = "";
- float j, m, impure = 0;
+ float j, m, impure = 0, freeslots = 0, sflags = 0;
s = gethostcachestring(SLIST_FIELD_QCSTATUS, entry);
m = tokenizebyseparator(s, ":");
for(j = 2; j < m; ++j)
{
- if(argv(j) == "")
- break;
+ if(argv(j) == "") { break; }
k = substring(argv(j), 0, 1);
v = substring(argv(j), 1, -1);
- if(k == "P") { impure = stof(v); }
- else if(k == "M") { modtype = strtolower(v); }
+ switch(k)
+ {
+ case "P": { impure = stof(v); break; }
+ case "S": { freeslots = stof(v); break; }
+ case "F": { sflags = stof(v); break; }
+ case "M": { modtype = strtolower(v); break; }
+ }
}
- if(impure > autocvar_menu_slist_purethreshold) { impure = TRUE; }
- else { impure = FALSE; }
+ if(modtype != "xonotic") { impure += autocvar_menu_slist_modimpurity; }
+ // check if this server is favorited
if(gethostcachenumber(SLIST_FIELD_ISFAVORITE, entry)) { return CAT_FAVORITED; }
- if(IsRecommended(gethostcachestring(SLIST_FIELD_CNAME, entry))) { return CAT_RECOMMENDED; }
- else if(modtype != "xonotic")
+
+ // now check if it's recommended
+ if(autocvar_menu_slist_recommendations)
+ {
+ float recommended = 0;
+ if(autocvar_menu_slist_recommendations & 1)
+ {
+ if(IsRecommended(gethostcachestring(SLIST_FIELD_CNAME, entry)))
+ { ++recommended; }
+ else
+ { --recommended; }
+ }
+ if(autocvar_menu_slist_recommendations & 2)
+ {
+ if(
+ (freeslots >= autocvar_menu_slist_recommendations_minfreeslots)
+ &&
+ (
+ (autocvar_menu_slist_recommendations_purethreshold < 0)
+ ||
+ (impure <= autocvar_menu_slist_recommendations_purethreshold)
+ )
+ &&
+ (
+ gethostcachenumber(SLIST_FIELD_NUMHUMANS, entry)
+ >=
+ autocvar_menu_slist_recommendations_minhumans
+ )
+ &&
+ (
+ gethostcachenumber(SLIST_FIELD_PING, entry)
+ <=
+ autocvar_menu_slist_recommendations_maxping
+ )
+ )
+ { ++recommended; }
+ else
+ { --recommended; }
+ }
+ if(recommended > 0) { return CAT_RECOMMENDED; }
+ }
+
+ // if not favorited or recommended, check modname
+ if(modtype != "xonotic")
{
switch(modtype)
{
default: { dprint(sprintf("Found strange mod type: %s\n", modtype)); return CAT_MODIFIED; }
}
}
- else { return (impure ? CAT_MODIFIED : CAT_NORMAL); }
-
- // should never hit this point
- error(sprintf("CheckCategoryForEntry(%d): Function fell through without normal return!\n", entry));
- return FALSE;
-}
-
-float CheckItemNumber(float num)
-{
- float i, n;
-
- if not(category_draw_count) { return num; } // there are no categories to process
-
- for(i = 0, n = 1; n <= category_draw_count; ++i, ++n)
- {
- if(category_item[i] == (num - i)) { return -category_name[i]; }
- else if(n == category_draw_count) { return (num - n); }
- else if((num - i) <= category_item[n]) { return (num - n); }
- }
- // should never hit this point
- error(sprintf("CheckItemNumber(%d): Function fell through without normal return!\n", num));
- return FALSE;
+ // must be normal or impure server
+ return ((impure > autocvar_menu_slist_purethreshold) ? CAT_MODIFIED : CAT_NORMAL);
}
void XonoticServerList_toggleFavorite(entity me, string srv)
{
me.favoriteButton.setText(me.favoriteButton,
(IsFavorite(me.ipAddressBox.text) ?
- _("Remove") : _("Bookmark")
+ _("Remove") : _("Favorite")
)
);
}
// clear list
me.nItems = 0;
-
- // build categories
- RegisterSLCategories();
}
void XonoticServerList_setSelected(entity me, float i)
{
- // todo: add logic to skip categories
- float save, num;
+ float save;
save = me.selectedItem;
SUPER(XonoticServerList).setSelected(me, i);
/*
*/
if(me.nItems == 0)
return;
+ if(gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT) != me.nItems)
+ return; // sorry, it would be wrong
- //if(gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT) != CheckItemNumber(me.nItems))
- // { error("^1XonoticServerList_setSelected(); ERROR: ^7Host cache viewcount mismatches nItems!\n"); return; } // sorry, it would be wrong
- // ^ todo: make this work somehow?
-
- #define SET_SELECTED_SERVER(cachenum) \
- if(me.selectedServer) { strunzone(me.selectedServer); } \
- me.selectedServer = strzone(gethostcachestring(SLIST_FIELD_CNAME, cachenum)); \
- me.ipAddressBox.setText(me.ipAddressBox, me.selectedServer); \
- me.ipAddressBox.cursorPos = strlen(me.selectedServer); \
- me.ipAddressBoxFocused = -1; \
- return;
-
- num = CheckItemNumber(me.selectedItem);
+ if(me.selectedServer)
+ strunzone(me.selectedServer);
+ me.selectedServer = strzone(gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
- if(num >= 0) { SET_SELECTED_SERVER(num); }
- else if(save > me.selectedItem)
- {
- if(me.selectedItem == 0) { return; }
- else
- {
- if(me.lastClickedTime >= me.lastBumpSelectTime)
- {
- SUPER(XonoticServerList).setSelected(me, me.selectedItem - 1);
- num = CheckItemNumber(me.selectedItem);
- if(num >= 0)
- {
- me.lastBumpSelectTime = time;
- SET_SELECTED_SERVER(num);
- }
- }
- }
- }
- else if(save < me.selectedItem)
- {
- if(me.selectedItem == me.nItems) { return; }
- else
- {
- if(me.lastClickedTime >= me.lastBumpSelectTime)
- {
- SUPER(XonoticServerList).setSelected(me, me.selectedItem + 1);
- num = CheckItemNumber(me.selectedItem);
- if(num >= 0)
- {
- me.lastBumpSelectTime = time;
- SET_SELECTED_SERVER(num);
- }
- }
- }
- }
+ me.ipAddressBox.setText(me.ipAddressBox, me.selectedServer);
+ me.ipAddressBox.cursorPos = strlen(me.selectedServer);
+ me.ipAddressBoxFocused = -1;
}
-
void XonoticServerList_refreshServerList(entity me, float mode)
{
//print("refresh of type ", ftos(mode), "\n");
void XonoticServerList_draw(entity me)
{
- float i, found, owned, num;
+ float i, found, owned;
if(_Nex_ExtResponseSystem_BannedServersNeedsRefresh)
{
_Nex_ExtResponseSystem_BannedServersNeedsRefresh = 0;
}
+ if(_Nex_ExtResponseSystem_RecommendedServersNeedsRefresh)
+ {
+ if(!me.needsRefresh)
+ me.needsRefresh = 3;
+ _Nex_ExtResponseSystem_RecommendedServersNeedsRefresh = 0;
+ }
+
if(me.currentSortField == -1)
{
me.setSortOrder(me, SLIST_FIELD_PING, +1);
me.needsRefresh = 0;
me.refreshServerList(me, REFRESHSERVERLIST_REFILTER);
}
+ else if(me.needsRefresh == 3)
+ {
+ me.needsRefresh = 0;
+ me.refreshServerList(me, REFRESHSERVERLIST_RESORT);
+ }
owned = ((me.selectedServer == me.ipAddressBox.text) && (me.ipAddressBox.text != ""));
// ^ unfortunately no such optimization can be made-- we must process through the
// entire list, otherwise there is no way to know which item is first in its category.
- float cat, x;
- for(i = 0; i < itemcount; ++i)
- {
- cat = gethostcachenumber(SLIST_FIELD_CATEGORY, i);
- if(cat)
- {
- if(category_draw_count == 0)
- {
- category_name[category_draw_count] = cat;
- category_item[category_draw_count] = i;
+ // binary search method suggested by div
+ float x;
+ float begin = 0;
+ for(x = 1; x <= category_ent_count; ++x) {
+ float first = begin;
+ float last = (itemcount - 1);
+ if (first > last) {
+ // List is empty.
+ break;
+ }
+ float catf = gethostcachenumber(SLIST_FIELD_CATEGORY, first);
+ float catl = gethostcachenumber(SLIST_FIELD_CATEGORY, last);
+ if (catf > x) {
+ // The first one is already > x.
+ // Therefore, category x does not exist.
+ // Higher numbered categories do exist though.
+ } else if (catl < x) {
+ // The last one is < x.
+ // Thus this category - and any following -
+ // don't exist.
+ break;
+ } else if (catf == x) {
+ // Starts at first. This breaks the loop
+ // invariant in the binary search and thus has
+ // to be handled separately.
+ if(gethostcachenumber(SLIST_FIELD_CATEGORY, first) != x)
+ error("Category mismatch I");
+ if(first > 0)
+ if(gethostcachenumber(SLIST_FIELD_CATEGORY, first - 1) == x)
+ error("Category mismatch II");
+ category_name[category_draw_count] = x;
+ category_item[category_draw_count] = first;
+ ++category_draw_count;
+ begin = first + 1;
+ } else {
+ // At this point, catf <= x < catl, thus
+ // catf < catl, thus first < last.
+ // INVARIANTS:
+ // last - first >= 1
+ // catf == gethostcachenumber(SLIST_FIELD_CATEGORY(first)
+ // catl == gethostcachenumber(SLIST_FIELD_CATEGORY(last)
+ // catf < x
+ // catl >= x
+ while (last - first > 1) {
+ float middle = floor((first + last) / 2);
+ // By loop condition, middle != first && middle != last.
+ float cat = gethostcachenumber(SLIST_FIELD_CATEGORY, middle);
+ if (cat >= x) {
+ last = middle;
+ catl = cat;
+ } else {
+ first = middle;
+ catf = cat;
+ }
+ }
+ if (catl == x) {
+ if(gethostcachenumber(SLIST_FIELD_CATEGORY, last) != x)
+ error("Category mismatch III");
+ if(last > 0)
+ if(gethostcachenumber(SLIST_FIELD_CATEGORY, last - 1) == x)
+ error("Category mismatch IV");
+ category_name[category_draw_count] = x;
+ category_item[category_draw_count] = last;
++category_draw_count;
- ++me.nItems;
+ begin = last + 1; // already scanned through these, skip 'em
}
else
- {
- found = 0;
- for(x = 0; x < category_draw_count; ++x) { if(cat == category_name[x]) { found = 1; } }
- if not(found)
- {
- category_name[category_draw_count] = cat;
- category_item[category_draw_count] = i;
- ++category_draw_count;
- ++me.nItems;
- }
- }
+ begin = last; // already scanned through these, skip 'em
}
}
if(autocvar_menu_slist_categories_onlyifmultiple && (category_draw_count == 1))
{
for(i = 0; i < me.nItems; ++i)
{
- num = CheckItemNumber(i);
- if(num >= 0)
+ if(gethostcachestring(SLIST_FIELD_CNAME, i) == me.selectedServer)
{
- if(gethostcachestring(SLIST_FIELD_CNAME, num) == me.selectedServer)
+ if(i != me.selectedItem)
{
- if(i != me.selectedItem)
- {
- me.lastClickedServer = -1;
- me.selectedItem = i;
- }
- found = 1;
- break;
+ me.lastClickedServer = -1;
+ me.selectedItem = i;
}
+ found = 1;
+ break;
}
}
}
{
if(me.nItems > 0)
{
- if(me.selectedItem >= me.nItems) { me.selectedItem = me.nItems - 1; }
- if(me.selectedServer) { strunzone(me.selectedServer); }
-
- num = CheckItemNumber(me.selectedItem);
- if(num >= 0) { me.selectedServer = strzone(gethostcachestring(SLIST_FIELD_CNAME, num)); }
+ if(me.selectedItem >= me.nItems)
+ me.selectedItem = me.nItems - 1;
+ if(me.selectedServer)
+ strunzone(me.selectedServer);
+ me.selectedServer = strzone(gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
}
}
void ServerList_Categories_Click(entity box, entity me)
{
box.setChecked(box, autocvar_menu_slist_categories = !autocvar_menu_slist_categories);
- ///refreshhostcache(TRUE);
-
- //cvar_set("net_slist_pause", "0");
- //Destroy_Category_Entities();
- //CALL_ACCUMULATED_FUNCTION(RegisterSLCategories);
- //me.refreshServerList(me, REFRESHSERVERLIST_REFILTER);
-
me.refreshServerList(me, REFRESHSERVERLIST_RESORT);
me.ipAddressBox.setText(me.ipAddressBox, "");
}
void ServerList_Info_Click(entity btn, entity me)
{
- main.serverInfoDialog.loadServerInfo(main.serverInfoDialog, CheckItemNumber(me.selectedItem));
+ if (me.nItems != 0)
+ main.serverInfoDialog.loadServerInfo(main.serverInfoDialog, me.selectedItem);
DialogOpenButton_Click(me, main.serverInfoDialog);
}
void XonoticServerList_clickListBoxItem(entity me, float i, vector where)
{
- float num = CheckItemNumber(i);
- if(num >= 0)
- {
- if(num == me.lastClickedServer)
- if(time < me.lastClickedTime + 0.3)
- {
- // DOUBLE CLICK!
- ServerList_Connect_Click(NULL, me);
- }
- me.lastClickedServer = num;
- me.lastClickedTime = time;
- }
+ if(i == me.lastClickedServer)
+ if(time < me.lastClickedTime + 0.3)
+ {
+ // DOUBLE CLICK!
+ ServerList_Connect_Click(NULL, me);
+ }
+ me.lastClickedServer = i;
+ me.lastClickedTime = time;
}
void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
{
float m, pure, freeslots, j, sflags;
string s, typestr, versionstr, k, v, modname;
- float item = CheckItemNumber(i);
//print(sprintf("time: %f, i: %d, item: %d, nitems: %d\n", time, i, item, me.nItems));
-
- if(item < 0)
+
+ vector oldscale = draw_scale;
+ vector oldshift = draw_shift;
+#define SET_YRANGE(start,end) \
+ draw_scale = boxToGlobalSize(eX * 1 + eY * (end - start), oldscale); \
+ draw_shift = boxToGlobal(eY * start, oldshift, oldscale);
+
+ for (j = 0; j < category_draw_count; ++j) {
+ // Matches exactly the headings with increased height.
+ if (i == category_item[j])
+ break;
+ }
+
+ if (j < category_draw_count)
{
- entity catent = Get_Cat_Ent(-item);
+ entity catent = RetrieveCategoryEnt(category_name[j]);
if(catent)
{
+ SET_YRANGE(
+ (me.categoriesHeight - 1) / (me.categoriesHeight + 1),
+ me.categoriesHeight / (me.categoriesHeight + 1)
+ );
draw_Text(
eY * me.realUpperMargin
+
+#if 0
eX * (me.columnNameOrigin + (me.columnNameSize - draw_TextWidth(catent.cat_string, 0, me.realFontSize)) * 0.5),
catent.cat_string,
+#else
+ eX * (me.columnNameOrigin),
+ strcat(catent.cat_string, ":"),
+#endif
me.realFontSize,
'1 1 1',
SKINALPHA_TEXT,
0
);
- return;
+ SET_YRANGE(me.categoriesHeight / (me.categoriesHeight + 1), 1);
}
}
if(isSelected)
draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
- s = gethostcachestring(SLIST_FIELD_QCSTATUS, item);
+ s = gethostcachestring(SLIST_FIELD_QCSTATUS, i);
m = tokenizebyseparator(s, ":");
typestr = "";
if(m >= 2)
/*
SLIST_FIELD_MOD = gethostcacheindexforkey("mod");
- s = gethostcachestring(SLIST_FIELD_MOD, item);
+ s = gethostcachestring(SLIST_FIELD_MOD, i);
if(s != "data")
if(modname == "Xonotic")
modname = s;
if(modname != "NewToys")
pure = 0;
- if(gethostcachenumber(SLIST_FIELD_FREESLOTS, item) <= 0)
+ if(gethostcachenumber(SLIST_FIELD_FREESLOTS, i) <= 0)
theAlpha = SKINALPHA_SERVERLIST_FULL;
else if(freeslots == 0)
theAlpha = SKINALPHA_SERVERLIST_FULL; // g_maxplayers support
- else if not(gethostcachenumber(SLIST_FIELD_NUMHUMANS, item))
+ else if not(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i))
theAlpha = SKINALPHA_SERVERLIST_EMPTY;
else
theAlpha = 1;
- p = gethostcachenumber(SLIST_FIELD_PING, item);
+ p = gethostcachenumber(SLIST_FIELD_PING, i);
#define PING_LOW 75
#define PING_MED 200
#define PING_HIGH 500
theAlpha *= SKINALPHA_SERVERLIST_HIGHPING;
}
- if(gethostcachenumber(SLIST_FIELD_ISFAVORITE, item))
+ if(gethostcachenumber(SLIST_FIELD_ISFAVORITE, i))
{
theColor = theColor * (1 - SKINALPHA_SERVERLIST_FAVORITE) + SKINCOLOR_SERVERLIST_FAVORITE * SKINALPHA_SERVERLIST_FAVORITE;
theAlpha = theAlpha * (1 - SKINALPHA_SERVERLIST_FAVORITE) + SKINALPHA_SERVERLIST_FAVORITE;
}
- s = gethostcachestring(SLIST_FIELD_CNAME, item);
+ s = gethostcachestring(SLIST_FIELD_CNAME, i);
isv4 = isv6 = 0;
if(substring(s, 0, 1) == "[")
draw_Text(me.realUpperMargin * eY + (me.columnPingOrigin + me.columnPingSize - draw_TextWidth(s, 0, me.realFontSize)) * eX, s, me.realFontSize, theColor, theAlpha, 0);
// server name
- s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_NAME, item), me.columnNameSize, 0, me.realFontSize);
+ 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);
// server map
- s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_MAP, item), me.columnMapSize, 0, me.realFontSize);
+ s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_MAP, i), me.columnMapSize, 0, me.realFontSize);
draw_Text(me.realUpperMargin * eY + (me.columnMapOrigin + (me.columnMapSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0);
// server gametype
draw_Text(me.realUpperMargin * eY + (me.columnTypeOrigin + (me.columnTypeSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0);
// server playercount
- s = strcat(ftos(gethostcachenumber(SLIST_FIELD_NUMHUMANS, item)), "/", ftos(gethostcachenumber(SLIST_FIELD_MAXPLAYERS, item)));
+ s = strcat(ftos(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i)), "/", ftos(gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i)));
draw_Text(me.realUpperMargin * eY + (me.columnPlayersOrigin + (me.columnPlayersSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0);
}
float XonoticServerList_keyDown(entity me, float scan, float ascii, float shift)
{
- float i = CheckItemNumber(me.selectedItem);
+ float i = me.selectedItem;
vector org, sz;
org = boxToGlobal(eY * (me.selectedItem * me.itemHeight - me.scrollPos), me.origin, me.size);
}
else if(scan == K_MOUSE2 || scan == K_SPACE)
{
- if((me.nItems != 0) && (i >= 0))
+ if(me.nItems != 0)
{
main.serverInfoDialog.loadServerInfo(main.serverInfoDialog, i);
DialogOpenButton_Click_withCoords(me, main.serverInfoDialog, org, sz);
}
else if(scan == K_INS || scan == K_MOUSE3 || scan == K_KP_INS)
{
- if((me.nItems != 0) && (i >= 0))
+ if(me.nItems != 0)
{
me.toggleFavorite(me, me.selectedServer);
me.ipAddressBoxFocused = -1;
else
return me.controlledTextbox.keyDown(me.controlledTextbox, scan, ascii, shift);
}
+
+float XonoticServerList_getTotalHeight(entity me) {
+ float num_normal_rows = me.nItems;
+ float num_headers = category_draw_count;
+ return me.itemHeight * (num_normal_rows + me.categoriesHeight * num_headers);
+}
+float XonoticServerList_getItemAtPos(entity me, float pos) {
+ pos = pos / me.itemHeight;
+ float i;
+ for (i = category_draw_count - 1; i >= 0; --i) {
+ float itemidx = category_item[i];
+ float itempos = i * me.categoriesHeight + category_item[i];
+ if (pos >= itempos + me.categoriesHeight + 1)
+ return itemidx + 1 + floor(pos - (itempos + me.categoriesHeight + 1));
+ if (pos >= itempos)
+ return itemidx;
+ }
+ // No category matches? Note that category 0 is... 0. Therefore no headings exist at all.
+ return floor(pos);
+}
+float XonoticServerList_getItemStart(entity me, float item) {
+ float i;
+ for (i = category_draw_count - 1; i >= 0; --i) {
+ float itemidx = category_item[i];
+ float itempos = i * me.categoriesHeight + category_item[i];
+ if (item >= itemidx + 1)
+ return (itempos + me.categoriesHeight + 1 + item - (itemidx + 1)) * me.itemHeight;
+ if (item >= itemidx)
+ return itempos * me.itemHeight;
+ }
+ // No category matches? Note that category 0 is... 0. Therefore no headings exist at all.
+ return item * me.itemHeight;
+}
+float XonoticServerList_getItemHeight(entity me, float item) {
+ float i;
+ for (i = 0; i < category_draw_count; ++i) {
+ // Matches exactly the headings with increased height.
+ if (item == category_item[i])
+ return me.itemHeight * (me.categoriesHeight + 1);
+ }
+ return me.itemHeight;
+}
+
#endif