Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
serverlist.qc File Reference
#include "serverlist.qh"
#include "checkbox.qh"
#include "inputbox.qh"
#include "mainwindow.qh"
#include "dialog_multiplayer_join_serverinfo.qh"
#include <common/mapinfo.qh>
Include dependency graph for serverlist.qc:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define IsFavorite(srv)
#define IsPromoted(srv)
#define IsRecommended(srv)
#define SET_YRANGE(start, end)
#define SLIST_CATEGORY(name, enoverride, dioverride, str)
#define SLIST_FIELD(suffix, name)

Functions

int CategoryForEntry (int entry)
int CategoryOverride (int cat)
bool IsServerInList (string list, string srv)
float m_gethostcachecategory (float entry)
entity makeXonoticServerList ()
void RegisterSLCategories ()
entity RetrieveCategoryEnt (int catnum)
void ServerList_Categories_Click (entity box, entity me)
void ServerList_Connect_Click (entity btn, entity me)
void ServerList_Favorite_Click (entity btn, entity this)
void ServerList_Filter_Change (entity box, entity me)
void ServerList_Info_Click (entity btn, entity me)
void ServerList_MapSort_Click (entity btn, entity me)
void ServerList_NameSort_Click (entity btn, entity me)
void ServerList_PingSort_Click (entity btn, entity me)
void ServerList_PlayerSort_Click (entity btn, entity me)
void ServerList_ShowEmpty_Click (entity box, entity me)
void ServerList_ShowFull_Click (entity box, entity me)
void ServerList_ShowLaggy_Click (entity box, entity me)
void ServerList_TypeSort_Click (entity btn, entity me)
void ServerList_Update_favoriteButton (entity btn, entity me)
void SL_ProcessCategoryOverrides (.string override_field_string,.float override_field)
void XonoticServerList_configureXonoticServerList (entity me)
void XonoticServerList_doubleClickListBoxItem (entity me, int i, vector where)
void XonoticServerList_draw (entity me)
void XonoticServerList_drawListBoxItem (entity me, int i, vector absSize, bool isSelected, bool isFocused)
void XonoticServerList_focusedItemChangeNotify (entity me)
void XonoticServerList_focusEnter (entity me)
int XonoticServerList_getItemAtPos (entity me, float pos)
float XonoticServerList_getItemHeight (entity me, int item)
float XonoticServerList_getItemStart (entity me, int item)
float XonoticServerList_getTotalHeight (entity me)
bool XonoticServerList_keyDown (entity me, int scan, bool ascii, bool shift)
float XonoticServerList_mouseMove (entity me, vector pos)
void XonoticServerList_positionSortButton (entity me, entity btn, float theOrigin, float theSize, string theTitle, void(entity, entity) theFunc)
void XonoticServerList_refreshServerList (entity me, int mode)
void XonoticServerList_resizeNotify (entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
void XonoticServerList_setSelected (entity me, int i)
void XonoticServerList_setSortOrder (entity me, int fld, int direction)

Variables

int autocvar_hud_panel_scoreboard_ping_high
int autocvar_hud_panel_scoreboard_ping_low
int autocvar_hud_panel_scoreboard_ping_medium

Macro Definition Documentation

◆ IsFavorite

#define IsFavorite ( srv)
Value:
IsServerInList(cvar_string("net_slist_favorites"), srv)
const string cvar_string(string name)
bool IsServerInList(string list, string srv)
Definition serverlist.qc:76

Definition at line 9 of file serverlist.qc.

Referenced by ServerList_Update_favoriteButton().

◆ IsPromoted

#define IsPromoted ( srv)
Value:

Definition at line 10 of file serverlist.qc.

Referenced by CategoryForEntry().

◆ IsRecommended

#define IsRecommended ( srv)
Value:

Definition at line 11 of file serverlist.qc.

Referenced by CategoryForEntry().

◆ SET_YRANGE

#define SET_YRANGE ( start,
end )
Value:
draw_scale = boxToGlobalSize(eX + eY * ((end) - (start)), oldscale); \
draw_shift = boxToGlobal(eY * (start), oldshift, oldscale);
vector boxToGlobalSize(vector v, vector theScale)
Definition draw.qc:53
vector boxToGlobal(vector v, vector theOrigin, vector theScale)
Definition draw.qc:45
vector draw_shift
Definition draw.qh:7
vector draw_scale
Definition draw.qh:8
const vector eY
Definition vector.qh:45
const vector eX
Definition vector.qh:44

Referenced by XonoticServerList_drawListBoxItem().

◆ SLIST_CATEGORY

#define SLIST_CATEGORY ( name,
enoverride,
dioverride,
str )
Value:
CHECK_MAX_COUNT(name, MAX_CATEGORIES, category_ent_count, "SLIST_CATEGORY") \
cat = categories[name - 1] = new(slist_category); \
cat.cat_name = #name; \
cat.cat_enoverride_string = strzone(SLIST_CATEGORY_AUTOCVAR(name)); \
cat.cat_dioverride_string = strzone(dioverride); \
cat.cat_string = strzone(str);
#define SET_FIELD_COUNT(field, first, count)
Definition accumulate.qh:53
string name
Definition menu.qh:30
string strzone(string s)
int category_ent_count
const int MAX_CATEGORIES
const int CATEGORY_FIRST
entity categories[MAX_CATEGORIES]
#define SLIST_CATEGORY_AUTOCVAR(name)

◆ SLIST_FIELD

#define SLIST_FIELD ( suffix,
name )
Value:
SLIST_FIELD_##suffix = gethostcacheindexforkey(name);
float gethostcacheindexforkey(string key)

Function Documentation

◆ CategoryForEntry()

int CategoryForEntry ( int entry)

Definition at line 117 of file serverlist.qc.

118{
119 string s, k, v, modtype = "";
120 int j, m, impure = 0, freeslots = 0, sflags = 0;
121 s = gethostcachestring(SLIST_FIELD_QCSTATUS, entry);
122 m = tokenizebyseparator(s, ":");
123
124 for(j = 2; j < m; ++j)
125 {
126 if(argv(j) == "") { break; }
127 k = substring(argv(j), 0, 1);
128 v = substring(argv(j), 1, -1);
129 switch(k)
130 {
131 case "P": { impure = stof(v); break; }
132 case "S": { freeslots = stof(v); break; }
133 case "F": { sflags = stof(v); break; }
134 case "M": { modtype = strtolower(v); break; }
135 }
136 }
137
138 if(modtype != "xonotic") { impure += autocvar_menu_slist_modimpurity; }
139
140 // check if this server is favorited
141 if(gethostcachenumber(SLIST_FIELD_ISFAVORITE, entry)) { return CAT_FAVORITED; }
142
143 // now check if it's recommended
145 {
146 string cname = gethostcachestring(SLIST_FIELD_CNAME, entry);
147
148 if(IsPromoted(cname)) { return CAT_RECOMMENDED; }
149 else
150 {
151 float recommended = 0;
153 {
154 if(IsRecommended(cname)) { ++recommended; }
155 else { --recommended; }
156 }
158 {
159 if(
162
163 && // check for purity requirement
164 (
166 ||
168 )
169
170 && // check for minimum amount of humans
171 (
172 gethostcachenumber(SLIST_FIELD_NUMHUMANS, entry)
173 >=
175 )
176
177 && // check for maximum latency
178 (
179 gethostcachenumber(SLIST_FIELD_PING, entry)
180 <=
182 )
183 )
184 { ++recommended; }
185 else
186 { --recommended; }
187 }
188 if(recommended > 0) { return CAT_RECOMMENDED; }
189 }
190 }
191
192 // if not favorited or recommended, check modname
193 if(modtype != "xonotic")
194 {
195 switch(modtype)
196 {
197 // old servers which don't report their mod name are considered modified now
198 case "": { return CAT_MODIFIED; }
199
200 case "xpm": { return CAT_XPM; }
201 case "minstagib":
202 case "instagib": { return CAT_INSTAGIB; }
203 case "overkill": { return CAT_OVERKILL; }
204
205 // "cts" is allowed as compat, xdf is replacement
206 case "cts":
207 case "xdf": { return CAT_DEFRAG; }
208
209 default: { LOG_TRACEF("Found strange mod type: %s", modtype); return CAT_MODIFIED; }
210 }
211 }
212
213 // must be normal or impure server
214 //return ((impure > autocvar_menu_slist_purethreshold) ? CAT_MODIFIED : CAT_NORMAL);
215 return CAT_NORMAL; // don't separate normal and modified server categories
216}
string strtolower(string s)
#define tokenizebyseparator
#define LOG_TRACEF(...)
Definition log.qh:77
float stof(string val,...)
string substring(string s, float start, float length)
string gethostcachestring(float type, float hostnr)
float gethostcachenumber(float fld, float hostnr)
string argv(float n)
#define IsPromoted(srv)
Definition serverlist.qc:10
#define IsRecommended(srv)
Definition serverlist.qc:11
float autocvar_menu_slist_recommendations_maxping
float autocvar_menu_slist_recommendations_minfreeslots
float autocvar_menu_slist_recommendations_minhumans
float autocvar_menu_slist_recommendations_purethreshold
float autocvar_menu_slist_modimpurity
float autocvar_menu_slist_recommendations

References argv(), autocvar_menu_slist_modimpurity, autocvar_menu_slist_recommendations, autocvar_menu_slist_recommendations_maxping, autocvar_menu_slist_recommendations_minfreeslots, autocvar_menu_slist_recommendations_minhumans, autocvar_menu_slist_recommendations_purethreshold, gethostcachenumber(), gethostcachestring(), IsPromoted, IsRecommended, LOG_TRACEF, stof(), strtolower(), substring(), and tokenizebyseparator.

Referenced by CategoryForEntry(), and m_gethostcachecategory().

◆ CategoryOverride()

int CategoryOverride ( int cat)

Definition at line 101 of file serverlist.qc.

102{
103 entity catent = RetrieveCategoryEnt(cat);
104 if(catent)
105 {
106 int override = (autocvar_menu_slist_categories ? catent.cat_enoverride : catent.cat_dioverride);
107 if(override) { return override; }
108 else { return cat; }
109 }
110 else
111 {
112 error(sprintf("CategoryOverride(%d): Improper category number!\n", cat));
113 return cat;
114 }
115}
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
#define error
Definition pre.qh:6
entity RetrieveCategoryEnt(int catnum)
Definition serverlist.qc:63
SLIST_FIELDS float autocvar_menu_slist_categories

References autocvar_menu_slist_categories, entity(), error, and RetrieveCategoryEnt().

Referenced by m_gethostcachecategory().

◆ IsServerInList()

bool IsServerInList ( string list,
string srv )

Definition at line 76 of file serverlist.qc.

77{
78 if(srv == "")
79 return false;
80 srv = netaddress_resolve(srv, 26000);
81 if(srv == "")
82 return false;
83 string p = crypto_getidfp(srv);
84 int n = tokenize_console(list);
85 for(int i = 0; i < n; ++i)
86 {
87 if(substring(argv(i), 0, 1) != "[" && strlen(argv(i)) == 44 && strstrofs(argv(i), ".", 0) < 0)
88 {
89 if(p && argv(i) == p)
90 return true;
91 }
92 else
93 {
94 if(srv == netaddress_resolve(argv(i), 26000))
95 return true;
96 }
97 }
98 return false;
99}
#define strstrofs
#define strlen
#define tokenize_console

References argv(), strlen, strstrofs, substring(), and tokenize_console.

◆ m_gethostcachecategory()

float m_gethostcachecategory ( float entry)

Definition at line 13 of file serverlist.qc.

13{ return CategoryOverride(CategoryForEntry(entry)); }
int CategoryForEntry(int entry)
int CategoryOverride(int cat)

References CategoryForEntry(), and CategoryOverride().

◆ makeXonoticServerList()

entity makeXonoticServerList ( )

Definition at line 273 of file serverlist.qc.

274{
275 entity me;
277 me.configureXonoticServerList(me);
278 return me;
279}
#define NEW(cname,...)
Definition oo.qh:117

References entity(), and NEW.

Referenced by XonoticServerList::getItemHeight(), and XonoticServerListTab_fill().

◆ RegisterSLCategories()

void RegisterSLCategories ( )

Definition at line 44 of file serverlist.qc.

45{
46 entity cat;
47 #define SLIST_CATEGORY(name,enoverride,dioverride,str) \
48 SET_FIELD_COUNT(name, CATEGORY_FIRST, category_ent_count) \
49 CHECK_MAX_COUNT(name, MAX_CATEGORIES, category_ent_count, "SLIST_CATEGORY") \
50 cat = categories[name - 1] = new(slist_category); \
51 cat.cat_name = #name; \
52 cat.cat_enoverride_string = strzone(SLIST_CATEGORY_AUTOCVAR(name)); \
53 cat.cat_dioverride_string = strzone(dioverride); \
54 cat.cat_string = strzone(str);
56 #undef SLIST_CATEGORY
57
60}
void SL_ProcessCategoryOverrides(.string override_field_string,.float override_field)
Definition serverlist.qc:15
float cat_enoverride
#define SLIST_CATEGORIES
string cat_enoverride_string
string cat_dioverride_string
float cat_dioverride

References cat_dioverride, cat_dioverride_string, cat_enoverride, cat_enoverride_string, entity(), SL_ProcessCategoryOverrides(), and SLIST_CATEGORIES.

Referenced by XonoticServerList::getItemHeight(), and m_init().

◆ RetrieveCategoryEnt()

entity RetrieveCategoryEnt ( int catnum)

Definition at line 63 of file serverlist.qc.

64{
65 if((catnum > 0) && (catnum <= category_ent_count))
66 {
67 return categories[catnum - 1];
68 }
69 else
70 {
71 error(sprintf("RetrieveCategoryEnt(%d): Improper category number!\n", catnum));
72 return NULL;
73 }
74}
#define NULL
Definition post.qh:14

References categories, category_ent_count, entity(), error, and NULL.

Referenced by CategoryOverride(), and XonoticServerList_drawListBoxItem().

◆ ServerList_Categories_Click()

void ServerList_Categories_Click ( entity box,
entity me )

Definition at line 666 of file serverlist.qc.

667{
669 me.refreshServerList(me, REFRESHSERVERLIST_RESORT);
670
671 me.ipAddressBox.setText(me.ipAddressBox, "");
672 me.ipAddressBox.cursorPos = 0;
673 me.ipAddressBoxFocused = -1;
674}
const float REFRESHSERVERLIST_RESORT

References autocvar_menu_slist_categories, entity(), and REFRESHSERVERLIST_RESORT.

Referenced by CategoryForEntry(), and XonoticServerListTab_fill().

◆ ServerList_Connect_Click()

void ServerList_Connect_Click ( entity btn,
entity me )

Definition at line 767 of file serverlist.qc.

768{
769 if (me.ipAddressBox.text != "")
770 localcmd(sprintf("connect %s\n", me.ipAddressBox.text));
771}
void localcmd(string command,...)

References entity(), and localcmd().

Referenced by CategoryForEntry(), XonoticServerList_doubleClickListBoxItem(), XonoticServerList_keyDown(), and XonoticServerListTab_fill().

◆ ServerList_Favorite_Click()

void ServerList_Favorite_Click ( entity btn,
entity this )

Definition at line 772 of file serverlist.qc.

773{
774 string addr = this.ipAddressBox.text;
775 string ipstr = netaddress_resolve(addr, 26000);
776 if (ipstr == "") return;
778 this.toggleFavorite(this, addr);
779 this.ipAddressBoxFocused = -1;
780}
void m_play_click_sound(string soundfile)
Definition menu.qc:1106
const string MENU_SOUND_SELECT
Definition menu.qh:54

References entity(), m_play_click_sound(), and MENU_SOUND_SELECT.

Referenced by CategoryForEntry(), and XonoticServerListTab_fill().

◆ ServerList_Filter_Change()

void ServerList_Filter_Change ( entity box,
entity me )

Definition at line 655 of file serverlist.qc.

656{
657 strfree(me.filterString);
658 if(box.text != "")
659 me.filterString = strzone(box.text);
660 me.refreshServerList(me, REFRESHSERVERLIST_REFILTER);
661
662 me.ipAddressBox.setText(me.ipAddressBox, "");
663 me.ipAddressBox.cursorPos = 0;
664 me.ipAddressBoxFocused = -1;
665}
const float REFRESHSERVERLIST_REFILTER
#define strfree(this)
Definition string.qh:59

References entity(), REFRESHSERVERLIST_REFILTER, strfree, and strzone().

Referenced by CategoryForEntry(), and XonoticServerListTab_fill().

◆ ServerList_Info_Click()

void ServerList_Info_Click ( entity btn,
entity me )

Definition at line 781 of file serverlist.qc.

782{
783 if (me.nItems != 0)
784 main.serverInfoDialog.loadServerInfo(main.serverInfoDialog, me.selectedItem);
785
786 float thisPos = me.getItemStart(me, me.selectedItem);
787 float thisHeight = me.getItemHeight(me, me.selectedItem);
788 vector org = boxToGlobal(eY * (thisPos - me.scrollPos), me.origin, me.size);
789 vector sz = boxToGlobalSize(eY * thisHeight + eX * (1 - me.controlWidth), me.size);
790 DialogOpenButton_Click_withCoords(me, main.serverInfoDialog, org, sz);
791}
#define main
Definition _all.inc:202
void DialogOpenButton_Click_withCoords(entity button, entity tab, vector theOrigin, vector theSize)
vector
Definition self.qh:92
vector org
Definition self.qh:92

References boxToGlobal(), boxToGlobalSize(), DialogOpenButton_Click_withCoords(), entity(), eX, eY, main, org, and vector.

Referenced by CategoryForEntry(), and XonoticServerListTab_fill().

◆ ServerList_MapSort_Click()

void ServerList_MapSort_Click ( entity btn,
entity me )

Definition at line 610 of file serverlist.qc.

611{
612 me.setSortOrder(me, SLIST_FIELD_MAP, -1); // why?
613}

References entity().

Referenced by XonoticServerList_resizeNotify().

◆ ServerList_NameSort_Click()

void ServerList_NameSort_Click ( entity btn,
entity me )

Definition at line 606 of file serverlist.qc.

607{
608 me.setSortOrder(me, SLIST_FIELD_NAME, -1); // why?
609}

References entity().

Referenced by XonoticServerList_resizeNotify().

◆ ServerList_PingSort_Click()

void ServerList_PingSort_Click ( entity btn,
entity me )

Definition at line 602 of file serverlist.qc.

603{
604 me.setSortOrder(me, SLIST_FIELD_PING, +1);
605}

References entity().

Referenced by XonoticServerList_resizeNotify().

◆ ServerList_PlayerSort_Click()

void ServerList_PlayerSort_Click ( entity btn,
entity me )

Definition at line 614 of file serverlist.qc.

615{
616 me.setSortOrder(me, SLIST_FIELD_NUMHUMANS, -1);
617}

References entity().

Referenced by XonoticServerList_resizeNotify().

◆ ServerList_ShowEmpty_Click()

void ServerList_ShowEmpty_Click ( entity box,
entity me )

Definition at line 675 of file serverlist.qc.

676{
677 box.setChecked(box, me.filterShowEmpty = !me.filterShowEmpty);
678 me.refreshServerList(me, REFRESHSERVERLIST_REFILTER);
679
680 me.ipAddressBox.setText(me.ipAddressBox, "");
681 me.ipAddressBox.cursorPos = 0;
682 me.ipAddressBoxFocused = -1;
683}

References entity(), and REFRESHSERVERLIST_REFILTER.

Referenced by CategoryForEntry(), and XonoticServerListTab_fill().

◆ ServerList_ShowFull_Click()

void ServerList_ShowFull_Click ( entity box,
entity me )

Definition at line 684 of file serverlist.qc.

685{
686 box.setChecked(box, me.filterShowFull = !me.filterShowFull);
687 me.refreshServerList(me, REFRESHSERVERLIST_REFILTER);
688
689 me.ipAddressBox.setText(me.ipAddressBox, "");
690 me.ipAddressBox.cursorPos = 0;
691 me.ipAddressBoxFocused = -1;
692}

References entity(), and REFRESHSERVERLIST_REFILTER.

Referenced by CategoryForEntry(), and XonoticServerListTab_fill().

◆ ServerList_ShowLaggy_Click()

void ServerList_ShowLaggy_Click ( entity box,
entity me )

Definition at line 693 of file serverlist.qc.

694{
695 box.setChecked(box, me.filterShowLaggy = !me.filterShowLaggy);
696 me.refreshServerList(me, REFRESHSERVERLIST_REFILTER);
697
698 me.ipAddressBox.setText(me.ipAddressBox, "");
699 me.ipAddressBox.cursorPos = 0;
700 me.ipAddressBoxFocused = -1;
701}

References entity(), and REFRESHSERVERLIST_REFILTER.

Referenced by CategoryForEntry(), and XonoticServerListTab_fill().

◆ ServerList_TypeSort_Click()

void ServerList_TypeSort_Click ( entity btn,
entity me )

Definition at line 618 of file serverlist.qc.

619{
620 string s = me.filterString;
621 int m = strstrofs(s, ":", 0);
622 if(m >= 0)
623 {
624 s = substring(s, 0, m);
625 while(substring(s, m+1, 1) == " ") // skip spaces
626 ++m;
627 }
628 else
629 s = "";
630
631 Gametype first = NULL; FOREACH(Gametypes, !first, first = it; break);
632 bool flag = false;
633 FOREACH(Gametypes, s == MapInfo_Type_ToString(it), {
634 // the type was found
635 // choose the next one
636 flag = true;
637 s = MapInfo_Type_ToString(REGISTRY_GET(Gametypes, it.m_id + 1));
638 if (s == "") s = MapInfo_Type_ToString(first);
639 break;
640 });
641 if (!flag) {
642 // no type was found
643 // choose the first one
644 s = MapInfo_Type_ToString(first);
645 }
646
647 if(s != "") s = strcat(s, ":");
648 s = strcat(s, substring(me.filterString, m+1, strlen(me.filterString) - m - 1));
649
650 me.controlledTextbox.setText(me.controlledTextbox, s);
651 me.controlledTextbox.keyDown(me.controlledTextbox, K_END, 0, 0);
652 me.controlledTextbox.keyUp(me.controlledTextbox, K_END, 0, 0);
653 //ServerList_Filter_Change(me.controlledTextbox, me);
654}
#define FOREACH(list, cond, body)
Definition iter.qh:19
float K_END
Definition keycodes.qc:42
string MapInfo_Type_ToString(Gametype t)
Definition mapinfo.qc:656
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
#define REGISTRY_GET(id, i)
Definition registry.qh:43

References entity(), FOREACH, K_END, MapInfo_Type_ToString(), NULL, REGISTRY_GET, strcat(), strlen, strstrofs, and substring().

Referenced by XonoticServerList_resizeNotify().

◆ ServerList_Update_favoriteButton()

void ServerList_Update_favoriteButton ( entity btn,
entity me )

Definition at line 258 of file serverlist.qc.

259{
260 entity e = me.favoriteButton;
261 if(IsFavorite(me.ipAddressBox.text))
262 {
263 e.setText(e, ZCTX(_("SERVER^Remove favorite")));
264 setZonedTooltip(e, _("Remove the currently highlighted server from bookmarks"), string_null);
265 }
266 else
267 {
268 e.setText(e, ZCTX(_("SERVER^Favorite")));
269 setZonedTooltip(e, _("Bookmark the currently highlighted server so that it's faster to find in the future"), string_null);
270 }
271}
#define ZCTX(s)
Definition i18n.qh:68
void setZonedTooltip(entity e, string theTooltip, string theCvar)
Definition util.qc:257
string string_null
Definition nil.qh:9
#define IsFavorite(srv)
Definition serverlist.qc:9

References entity(), IsFavorite, setZonedTooltip(), string_null, and ZCTX.

Referenced by CategoryForEntry(), XonoticServerList_draw(), and XonoticServerListTab_fill().

◆ SL_ProcessCategoryOverrides()

void SL_ProcessCategoryOverrides ( .string override_field_string,
.float override_field )

Definition at line 15 of file serverlist.qc.

16{
17 for (int i = 0; i < category_ent_count; ++i)
18 {
19 string s = categories[i].override_field_string;
20 if (s != "" && s != categories[i].cat_name)
21 {
22 int catnum = 0;
23 for (int x = 0; x < category_ent_count; ++x)
24 {
25 if(categories[x].cat_name == s)
26 {
27 catnum = x + 1;
28 break;
29 }
30 }
31 if (catnum)
32 {
33 strfree(categories[i].override_field_string);
34 categories[i].override_field = catnum;
35 continue;
36 }
37 LOG_INFOF("RegisterSLCategories(): Improper override '%s' for category '%s'!", s, categories[i].cat_name);
38 }
39 strfree(categories[i].override_field_string);
40 categories[i].override_field = 0;
41 }
42}
#define LOG_INFOF(...)
Definition log.qh:66
string cat_name

References cat_name, categories, category_ent_count, LOG_INFOF, and strfree.

Referenced by RegisterSLCategories().

◆ XonoticServerList_configureXonoticServerList()

void XonoticServerList_configureXonoticServerList ( entity me)

Definition at line 280 of file serverlist.qc.

281{
282 me.configureXonoticListBox(me);
283
284 // update field ID's
285 #define SLIST_FIELD(suffix,name) SLIST_FIELD_##suffix = gethostcacheindexforkey(name);
287 #undef SLIST_FIELD
288
289 // clear list
290 me.nItems = 0;
291}
#define SLIST_FIELDS
Definition serverlist.qh:87

References entity(), and SLIST_FIELDS.

◆ XonoticServerList_doubleClickListBoxItem()

void XonoticServerList_doubleClickListBoxItem ( entity me,
int i,
vector where )

Definition at line 792 of file serverlist.qc.

793{
795}
void ServerList_Connect_Click(entity btn, entity me)

References entity(), NULL, ServerList_Connect_Click(), and vector.

◆ XonoticServerList_draw()

void XonoticServerList_draw ( entity me)

Definition at line 405 of file serverlist.qc.

406{
407 me.serversHeight = (autocvar_menu_slist_categories > 0 ? 1.0 : me.categoriesHeight);
408
410 {
411 if(!me.needsRefresh)
412 me.needsRefresh = 2;
414 }
415
417 {
418 if(!me.needsRefresh)
419 me.needsRefresh = 3;
421 }
422
424 {
425 if(!me.needsRefresh)
426 me.needsRefresh = 3;
428 }
429
430 if(me.currentSortField == -1)
431 {
432 me.setSortOrder(me, SLIST_FIELD_PING, +1);
433 me.refreshServerList(me, REFRESHSERVERLIST_RESET);
434 }
435 else if(me.needsRefresh == 1)
436 {
437 me.needsRefresh = 2; // delay by one frame to make sure "slist" has been executed
438 }
439 else if(me.needsRefresh == 2)
440 {
441 me.needsRefresh = 0;
442 me.refreshServerList(me, REFRESHSERVERLIST_REFILTER);
443 }
444 else if(me.needsRefresh == 3)
445 {
446 me.needsRefresh = 0;
447 me.refreshServerList(me, REFRESHSERVERLIST_RESORT);
448 }
449
450 bool owned = ((me.selectedServer == me.ipAddressBox.text) && (me.ipAddressBox.text != ""));
451
452 for(int i = 0; i < category_draw_count; ++i) { category_name[i] = -1; category_item[i] = -1; }
454
456
457 if(autocvar_menu_slist_categories >= 0) // if less than 0, don't even draw a category heading for favorites
458 {
459 int itemcount = me.nItems;
460
461 //float visible = floor(me.scrollPos / me.itemHeight);
462 // ^ unfortunately no such optimization can be made-- we must process through the
463 // entire list, otherwise there is no way to know which item is first in its category.
464
465 // binary search method suggested by div
466 float begin = 0;
467 for(int j = 1; j <= category_ent_count; ++j) {
468 float first = begin;
469 float last = (itemcount - 1);
470 if (first > last) {
471 // List is empty.
472 break;
473 }
474 float catf = gethostcachenumber(SLIST_FIELD_CATEGORY, first);
475 float catl = gethostcachenumber(SLIST_FIELD_CATEGORY, last);
476 if (catf > j) {
477 // The first one is already > j.
478 // Therefore, category j does not exist.
479 // Higher numbered categories do exist though.
480 } else if (catl < j) {
481 // The last one is < j.
482 // Thus this category - and any following -
483 // don't exist.
484 break;
485 } else if (catf == j) {
486 // Starts at first. This breaks the loop
487 // invariant in the binary search and thus has
488 // to be handled separately.
489 if(gethostcachenumber(SLIST_FIELD_CATEGORY, first) != j)
490 error("Category mismatch I");
491 if(first > 0)
492 if(gethostcachenumber(SLIST_FIELD_CATEGORY, first - 1) == j)
493 error("Category mismatch II");
497 begin = first + 1;
498 } else {
499 // At this point, catf <= j < catl, thus
500 // catf < catl, thus first < last.
501 // INVARIANTS:
502 // last - first >= 1
503 // catf == gethostcachenumber(SLIST_FIELD_CATEGORY(first)
504 // catl == gethostcachenumber(SLIST_FIELD_CATEGORY(last)
505 // catf < j
506 // catl >= j
507 while (last - first > 1) {
508 float middle = floor((first + last) / 2);
509 // By loop condition, middle != first && middle != last.
510 float cat = gethostcachenumber(SLIST_FIELD_CATEGORY, middle);
511 if (cat >= j) {
512 last = middle;
513 catl = cat;
514 } else {
515 first = middle;
516 catf = cat;
517 }
518 }
519 if (catl == j) {
520 if(gethostcachenumber(SLIST_FIELD_CATEGORY, last) != j)
521 error("Category mismatch III");
522 if(last > 0)
523 if(gethostcachenumber(SLIST_FIELD_CATEGORY, last - 1) == j)
524 error("Category mismatch IV");
528 begin = last + 1; // already scanned through these, skip 'em
529 }
530 else
531 begin = last; // already scanned through these, skip 'em
532 }
533 }
535 {
536 category_name[0] = -1;
537 category_item[0] = -1;
539 me.nItems = itemcount;
540 }
541 }
542
543 me.connectButton.disabled = (me.ipAddressBox.text == "");
544 me.infoButton.disabled = !owned;
545 me.favoriteButton.disabled = (me.ipAddressBox.text == "");
546
547 bool found = false;
548 if(me.lockedSelectedItem)
549 {
550 if(me.nItems > 0)
551 {
552 if(gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem) != me.selectedServer)
553 {
554 strcpy(me.selectedServer, gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
555 }
556 found = true;
557 }
558 }
559 else if(me.selectedServer)
560 {
561 for(int i = 0; i < me.nItems; ++i)
562 {
563 if(gethostcachestring(SLIST_FIELD_CNAME, i) == me.selectedServer)
564 {
565 // don't follow the selected item with SUPER(XonoticServerList).setSelected(me, i);
566 me.selectedItem = i;
567 found = true;
568 break;
569 }
570 }
571 }
572 if(!found)
573 {
574 if(me.nItems > 0)
575 {
576 // selected server disappeared, select the last server (scrolling to it)
577 if(me.selectedItem >= me.nItems)
578 SUPER(XonoticServerList).setSelected(me, me.nItems - 1);
579 strcpy(me.selectedServer, gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
580 }
581 }
582
583 if(owned)
584 {
585 if(me.selectedServer != me.ipAddressBox.text)
586 {
587 me.ipAddressBox.setText(me.ipAddressBox, me.selectedServer);
588 me.ipAddressBox.cursorPos = strlen(me.selectedServer);
589 me.ipAddressBoxFocused = -1;
590 }
591 }
592
593 if(me.ipAddressBoxFocused != me.ipAddressBox.focused)
594 {
595 if(me.ipAddressBox.focused || me.ipAddressBoxFocused < 0)
597 me.ipAddressBoxFocused = me.ipAddressBox.focused;
598 }
599
600 SUPER(XonoticServerList).draw(me);
601}
float _Nex_ExtResponseSystem_BannedServersNeedsRefresh
Definition util.qh:63
float _Nex_ExtResponseSystem_RecommendedServersNeedsRefresh
Definition util.qh:67
float _Nex_ExtResponseSystem_PromotedServersNeedsRefresh
Definition util.qh:65
float gethostcachevalue(float type)
float floor(float f)
float SLIST_HOSTCACHEVIEWCOUNT
Definition menudefs.qc:104
#define SUPER(cname)
Definition oo.qh:231
void ServerList_Update_favoriteButton(entity btn, entity me)
int category_item[MAX_CATEGORIES]
int category_name[MAX_CATEGORIES]
const float REFRESHSERVERLIST_RESET
int category_draw_count
float autocvar_menu_slist_categories_onlyifmultiple
#define strcpy(this, s)
Definition string.qh:52

References _Nex_ExtResponseSystem_BannedServersNeedsRefresh, _Nex_ExtResponseSystem_PromotedServersNeedsRefresh, _Nex_ExtResponseSystem_RecommendedServersNeedsRefresh, autocvar_menu_slist_categories, autocvar_menu_slist_categories_onlyifmultiple, category_draw_count, category_ent_count, category_item, category_name, entity(), error, floor(), gethostcachenumber(), gethostcachestring(), gethostcachevalue(), NULL, REFRESHSERVERLIST_REFILTER, REFRESHSERVERLIST_RESET, REFRESHSERVERLIST_RESORT, ServerList_Update_favoriteButton(), SLIST_HOSTCACHEVIEWCOUNT, strcpy, strlen, and SUPER.

◆ XonoticServerList_drawListBoxItem()

void XonoticServerList_drawListBoxItem ( entity me,
int i,
vector absSize,
bool isSelected,
bool isFocused )

Definition at line 799 of file serverlist.qc.

800{
801 vector oldscale = draw_scale;
802 vector oldshift = draw_shift;
803#define SET_YRANGE(start,end) \
804 draw_scale = boxToGlobalSize(eX + eY * ((end) - (start)), oldscale); \
805 draw_shift = boxToGlobal(eY * (start), oldshift, oldscale);
806
807 int c;
808 for (c = 0; c < category_draw_count; ++c) {
809 // Matches exactly the headings with increased height.
810 if (i == category_item[c])
811 break;
812 }
813
814 if (c < category_draw_count)
815 {
817 if(catent)
818 {
820 (me.categoriesHeight - me.realFontSize.y) / (me.categoriesHeight + me.serversHeight),
821 me.categoriesHeight / (me.categoriesHeight + me.serversHeight)
822 );
823 draw_Text(
824 eY * me.realUpperMargin
825 +
826#if 0
827 eX * (me.columnNameOrigin + (me.columnNameSize - draw_TextWidth(catent.cat_string, 0, me.realFontSize)) * 0.5),
828 catent.cat_string,
829#else
830 eX * (me.columnNameOrigin),
831 strcat(catent.cat_string, ":"),
832#endif
833 me.realFontSize,
834 SKINCOLOR_SERVERLIST_CATEGORY,
835 SKINALPHA_SERVERLIST_CATEGORY,
836 0
837 );
838 SET_YRANGE(me.categoriesHeight / (me.categoriesHeight + me.serversHeight), 1);
839 }
840 }
841
842 // Now categories are done. Set the Y range in stone.
843 oldscale = draw_scale;
844 oldshift = draw_shift;
845
846 if(isSelected && !me.lockedSelectedItem)
847 draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
848 else if(isFocused)
849 {
850 me.focusedItemAlpha = getFadedAlpha(me.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
851 draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, me.focusedItemAlpha);
852 }
853
854 string s = gethostcachestring(SLIST_FIELD_QCSTATUS, i);
855 int m = tokenizebyseparator(s, ":");
856 string typestr = "", versionstr = "";
857 if(m >= 2)
858 {
859 typestr = argv(0);
860 versionstr = argv(1);
861 }
862 bool pure = false, pure_available = false;
863 int qcfreeslots = -1, sflags = -1;
864 string modname = "";
865 for(int j = 2; j < m; ++j)
866 {
867 if(argv(j) == "")
868 break;
869 string key = substring(argv(j), 0, 1);
870 string value = substring(argv(j), 1, -1);
871 if(key == "P")
872 {
873 pure = (stof(value) == 0);
874 pure_available = true;
875 }
876 else if(key == "S")
877 qcfreeslots = stof(value); // from nJoinAllowed()
878 else if(key == "F")
879 sflags = stoi(value);
880 else if(key == "M")
881 modname = value;
882 }
883
884#ifdef COMPAT_NO_MOD_IS_XONOTIC
885 if(modname == "")
886 modname = "Xonotic";
887#endif
888
889 string original_modname = modname;
891
892 /*
893 SLIST_FIELD_MOD = gethostcacheindexforkey("mod");
894 s = gethostcachestring(SLIST_FIELD_MOD, i);
895 if(s != "data")
896 if(modname == "xonotic")
897 modname = s;
898 */
899
900 // list the mods here on which the pure server check actually works
901 if(modname != "xonotic")
902 if(modname != "instagib" || modname != "minstagib")
903 if(modname != "cts")
904 if(modname != "nix")
905 if(modname != "newtoys")
906 pure_available = false;
907
908 float theAlpha;
909 if(gethostcachenumber(SLIST_FIELD_FREESLOTS, i) <= 0) // can't connect
910 theAlpha = SKINALPHA_SERVERLIST_FULL;
911 else if(qcfreeslots == 0) // can connect but may not be able to play yet (duel, g_maxplayers, etc)
912 theAlpha = SKINALPHA_SERVERLIST_EMPTY;
913 else if (!gethostcachenumber(SLIST_FIELD_NUMHUMANS, i))
914 theAlpha = SKINALPHA_SERVERLIST_EMPTY;
915 else
916 theAlpha = 1;
917
918 float ping = gethostcachenumber(SLIST_FIELD_PING, i);
922 vector theColor;
923 // this colour selection code should match csqc Scoreboard_GetField()
924 if (ping < PING_LOW)
925 theColor = SKINCOLOR_SERVERLIST_LOWPING;
926 else if(ping < PING_MED)
927 theColor = SKINCOLOR_SERVERLIST_LOWPING + (SKINCOLOR_SERVERLIST_MEDPING - SKINCOLOR_SERVERLIST_LOWPING) * ((ping - PING_LOW) / (PING_MED - PING_LOW));
928 else if(ping < PING_HIGH)
929 theColor = SKINCOLOR_SERVERLIST_MEDPING + (SKINCOLOR_SERVERLIST_HIGHPING - SKINCOLOR_SERVERLIST_MEDPING) * ((ping - PING_MED) / (PING_HIGH - PING_MED));
930 else
931 {
932 theColor = eX;
933 theAlpha *= 1 + (SKINALPHA_SERVERLIST_HIGHPING - 1) * ((ping - PING_HIGH) / (PING_HIGH * 2 - PING_HIGH));
934 }
935
936 if(gethostcachenumber(SLIST_FIELD_ISFAVORITE, i))
937 {
938 theColor = theColor * (1 - SKINALPHA_SERVERLIST_FAVORITE) + SKINCOLOR_SERVERLIST_FAVORITE * SKINALPHA_SERVERLIST_FAVORITE;
939 if (gethostcachenumber(SLIST_FIELD_FREESLOTS, i) > 0) // can connect
940 theAlpha = theAlpha * (1 - SKINALPHA_SERVERLIST_FAVORITE) + SKINALPHA_SERVERLIST_FAVORITE;
941 }
942
943 s = gethostcachestring(SLIST_FIELD_CNAME, i);
944
945 bool isv4 = false, isv6 = false;
946 if(substring(s, 0, 1) == "[")
947 {
948 isv6 = true;
949 ++me.seenIPv6;
950 }
951 else if(IS_DIGIT(substring(s, 0, 1)))
952 {
953 isv4 = true;
954 ++me.seenIPv4;
955 }
956
957 int crypto = stof(substring(crypto_getencryptlevel(s), 0, 1));
958 if((crypto <= 0 && cvar("crypto_aeslevel") >= 3) || (crypto >= 3 && cvar("crypto_aeslevel") <= 0))
959 {
960 theColor = SKINCOLOR_SERVERLIST_IMPOSSIBLE;
961 theAlpha = SKINALPHA_SERVERLIST_IMPOSSIBLE;
962 }
963
964 if(crypto == 1)
965 {
966 if(cvar("crypto_aeslevel") >= 2)
967 crypto |= 4;
968 }
969 if(crypto == 2)
970 {
971 if(cvar("crypto_aeslevel") >= 1)
972 crypto |= 4;
973 }
974 if(crypto == 3)
975 crypto = 5;
976 else if(crypto >= 3)
977 crypto -= 2;
978 // possible status:
979 // 0: crypto off
980 // 1: AES possible
981 // 2: AES recommended but not available
982 // 3: AES possible and will be used
983 // 4: AES recommended and will be used
984 // 5: AES required
985
986 // --------------
987 // RENDER ICONS
988 // --------------
989 vector iconSize = '0 0 0';
990 iconSize_y = me.realFontSize.y * me.iconsSizeFactor / me.serversHeight;
991 iconSize_x = me.realFontSize.x * me.iconsSizeFactor;
992
993 vector iconPos = '0 0 0';
994 if(me.seenIPv4 && me.seenIPv6)
995 iconPos_x = (me.columnIconsSize - 4 * iconSize.x) * 0.5;
996 else
997 iconPos_x = (me.columnIconsSize - 3 * iconSize.x) * 0.5;
998 iconPos_y = (1 - iconSize.y) * 0.5;
999
1000 // IP
1001 if(me.seenIPv4 && me.seenIPv6)
1002 {
1003 if(isv6)
1004 draw_Picture(iconPos, "icon_ipv6", iconSize, '1 1 1', 1);
1005 else if(isv4)
1006 draw_Picture(iconPos, "icon_ipv4", iconSize, '1 1 1', 1);
1007
1008 iconPos.x += iconSize.x;
1009 }
1010
1011 // AES
1012 if(crypto > 0)
1013 draw_Picture(iconPos, strcat("icon_aeslevel", ftos(crypto)), iconSize, '1 1 1', 1);
1014
1015 iconPos.x += iconSize.x;
1016
1017 // Mod
1018 if(modname == "xonotic")
1019 {
1020 // Here, pure_available should always be set. If not, consider
1021 // it an impurity.
1022 if(pure_available && pure)
1023 draw_Picture(iconPos, "icon_pure1", iconSize, '1 1 1', 1);
1024 }
1025 else
1026 {
1027 string icon = strcat("icon_mod_", modname);
1028 if(draw_PreloadPicture(icon) == "")
1029 icon = "icon_mod_";
1030
1031 // In mods, pure_available not being present indicates
1032 // non-support of the feature. Just show the mod icon as is
1033 // then.
1034 if(pure_available && !pure)
1035 draw_Picture(iconPos, icon, iconSize, '1 1 1', SKINALPHA_SERVERLIST_ICON_NONPURE);
1036 else
1037 draw_Picture(iconPos, icon, iconSize, '1 1 1', 1);
1038 }
1039
1040 iconPos.x += iconSize.x;
1041
1042 // Stats
1043 if(sflags >= 0 && (sflags & SERVERFLAG_PLAYERSTATS))
1044 {
1045 if (sflags & SERVERFLAG_PLAYERSTATS_CUSTOM)
1046 draw_Picture(iconPos, "icon_mod_", iconSize, '1 1 1', 1); // TODO: custom stats server icon
1047 else
1048 draw_Picture(iconPos, "icon_stats1", iconSize, '1 1 1', 1);
1049 }
1050
1051 if(isFocused && me.mouseOverIcons && !me.tooltip)
1052 {
1053 string t = "";
1054 if(me.seenIPv4 && me.seenIPv6)
1055 t = strcat(t, (isv6) ? "IPv6, " : "IPv4, ");
1056 t = strcat(t, _("encryption:"), " ", (crypto ? sprintf(_("AES level %d"), crypto) : ZCTX(_("ENC^none"))), ", ");
1057 t = strcat(t, sprintf(_("mod: %s"), ((modname == "xonotic") ? ZCTX(_("MOD^Default")) : original_modname)));
1058 if(pure_available)
1059 t = strcat(t, sprintf(" (%s)", (pure) ? _("official settings") : _("modified settings")));
1060 t = strcat(t, ", ");
1061 t = strcat(t, ((sflags >= 0 && (sflags & SERVERFLAG_PLAYERSTATS)) ? ((sflags & SERVERFLAG_PLAYERSTATS_CUSTOM) ? _("custom stats server") : _("stats enabled")) : _("stats disabled")));
1063 }
1064 // --------------
1065 // RENDER TEXT
1066 // --------------
1067
1068 // Center it in the row.
1069 SET_YRANGE(
1070 0.5 - 0.5 / me.serversHeight,
1071 0.5 + 0.5 / me.serversHeight
1072 );
1073
1074 // ping
1075 s = ftos(ping);
1076 draw_Text(me.realUpperMargin * eY + (me.columnPingOrigin + me.columnPingSize - draw_TextWidth(s, 0, me.realFontSize)) * eX, s, me.realFontSize, theColor, theAlpha, 0);
1077
1078 // server name
1079 s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_NAME, i), me.columnNameSize, 0, me.realFontSize);
1080 draw_Text(me.realUpperMargin * eY + me.columnNameOrigin * eX, s, me.realFontSize, theColor, theAlpha, 0);
1081
1082 // server map
1083 s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_MAP, i), me.columnMapSize, 0, me.realFontSize);
1084 draw_Text(me.realUpperMargin * eY + (me.columnMapOrigin + (me.columnMapSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0);
1085
1086 // server gametype
1087 s = draw_TextShortenToWidth(typestr, me.columnTypeSize, 0, me.realFontSize);
1088 draw_Text(me.realUpperMargin * eY + (me.columnTypeOrigin + (me.columnTypeSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0);
1089
1090 // server playercount
1091 s = strcat(ftos(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i)), "/", ftos(gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i)));
1092 draw_Text(me.realUpperMargin * eY + (me.columnPlayersOrigin + (me.columnPlayersSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0);
1093}
float ping
Definition main.qh:169
const int SERVERFLAG_PLAYERSTATS
Definition constants.qh:18
const int SERVERFLAG_PLAYERSTATS_CUSTOM
Definition constants.qh:19
#define stoi(s)
Definition int.qh:4
string draw_TextShortenToWidth(string theText, float maxWidth, float ICanHasKallerz, vector SizeThxBye)
Definition draw.qc:377
void draw_Picture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha)
Definition draw.qc:72
void draw_Text(vector theOrigin, string theText, vector theSize, vector theColor, float theAlpha, float ICanHasKallerz)
Definition draw.qc:282
float draw_TextWidth(string theText, float ICanHasKallerz, vector SizeThxBye)
Definition draw.qc:304
void draw_Fill(vector theOrigin, vector theSize, vector theColor, float theAlpha)
Definition draw.qc:97
string draw_PreloadPicture(string pic)
Definition draw.qc:60
float getFadedAlpha(float currentAlpha, float startAlpha, float targetAlpha)
Definition util.qc:816
float cvar(string name)
string ftos(float f)
int autocvar_hud_panel_scoreboard_ping_high
int autocvar_hud_panel_scoreboard_ping_low
#define PING_LOW
#define PING_HIGH
#define PING_MED
int autocvar_hud_panel_scoreboard_ping_medium
#define SET_YRANGE(start, end)
#define IS_DIGIT(d)
Definition string.qh:576
string modname
Definition world.qh:49

References argv(), autocvar_hud_panel_scoreboard_ping_high, autocvar_hud_panel_scoreboard_ping_low, autocvar_hud_panel_scoreboard_ping_medium, category_draw_count, category_item, category_name, cvar(), draw_Fill(), draw_Picture(), draw_PreloadPicture(), draw_scale, draw_shift, draw_Text(), draw_TextShortenToWidth(), draw_TextWidth(), entity(), eX, eY, ftos(), getFadedAlpha(), gethostcachenumber(), gethostcachestring(), IS_DIGIT, modname, ping, PING_HIGH, PING_LOW, PING_MED, RetrieveCategoryEnt(), SERVERFLAG_PLAYERSTATS, SERVERFLAG_PLAYERSTATS_CUSTOM, SET_YRANGE, setZonedTooltip(), stof(), stoi, strcat(), string_null, strtolower(), substring(), tokenizebyseparator, vector, and ZCTX.

◆ XonoticServerList_focusedItemChangeNotify()

void XonoticServerList_focusedItemChangeNotify ( entity me)

Definition at line 1095 of file serverlist.qc.

1096{
1097 clearTooltip(me);
1098}
void clearTooltip(entity e)
Definition util.qc:277

References clearTooltip(), and entity().

◆ XonoticServerList_focusEnter()

void XonoticServerList_focusEnter ( entity me)

Definition at line 393 of file serverlist.qc.

394{
395 SUPER(XonoticServerList).focusEnter(me);
396 if(time < me.nextRefreshTime)
397 {
398 //print("sorry, no refresh yet\n");
399 return;
400 }
401 me.nextRefreshTime = time + 10;
402 me.refreshServerList(me, REFRESHSERVERLIST_ASK);
403}
float time
const float REFRESHSERVERLIST_ASK

References entity(), REFRESHSERVERLIST_ASK, SUPER, and time.

◆ XonoticServerList_getItemAtPos()

int XonoticServerList_getItemAtPos ( entity me,
float pos )

Definition at line 1167 of file serverlist.qc.

1168{
1169 pos = pos / me.itemHeight;
1170 for (int i = category_draw_count - 1; i >= 0; --i) {
1171 int itemidx = category_item[i];
1172 float itempos = i * me.categoriesHeight + itemidx * me.serversHeight;
1173 if (pos >= itempos + me.categoriesHeight + me.serversHeight)
1174 return itemidx + 1 + floor((pos - (itempos + me.categoriesHeight + me.serversHeight)) / me.serversHeight);
1175 if (pos >= itempos)
1176 return itemidx;
1177 }
1178 // No category matches? Note that category 0 is... 0. Therefore no headings exist at all.
1179 return floor(pos / me.serversHeight);
1180}

References category_draw_count, category_item, entity(), and floor().

◆ XonoticServerList_getItemHeight()

float XonoticServerList_getItemHeight ( entity me,
int item )

Definition at line 1194 of file serverlist.qc.

1195{
1196 for (int i = 0; i < category_draw_count; ++i) {
1197 // Matches exactly the headings with increased height.
1198 if (item == category_item[i])
1199 return me.itemHeight * (me.categoriesHeight + me.serversHeight);
1200 }
1201 return me.itemHeight * me.serversHeight;
1202}

References category_draw_count, category_item, and entity().

◆ XonoticServerList_getItemStart()

float XonoticServerList_getItemStart ( entity me,
int item )

Definition at line 1181 of file serverlist.qc.

1182{
1183 for (int i = category_draw_count - 1; i >= 0; --i) {
1184 int itemidx = category_item[i];
1185 float itempos = i * me.categoriesHeight + itemidx * me.serversHeight;
1186 if (item >= itemidx + 1)
1187 return (itempos + me.categoriesHeight + (1 + item - (itemidx + 1)) * me.serversHeight) * me.itemHeight;
1188 if (item >= itemidx)
1189 return itempos * me.itemHeight;
1190 }
1191 // No category matches? Note that category 0 is... 0. Therefore no headings exist at all.
1192 return item * me.serversHeight * me.itemHeight;
1193}

References category_draw_count, category_item, and entity().

◆ XonoticServerList_getTotalHeight()

float XonoticServerList_getTotalHeight ( entity me)

Definition at line 1161 of file serverlist.qc.

1162{
1163 float num_normal_rows = me.nItems;
1164 int num_headers = category_draw_count;
1165 return me.itemHeight * (me.serversHeight * num_normal_rows + me.categoriesHeight * num_headers);
1166}

References category_draw_count, and entity().

◆ XonoticServerList_keyDown()

bool XonoticServerList_keyDown ( entity me,
int scan,
bool ascii,
bool shift )

Definition at line 1121 of file serverlist.qc.

1122{
1123 if(scan == K_ENTER || scan == K_KP_ENTER)
1124 {
1126 return true;
1127 }
1128 else if(scan == K_MOUSE2 || scan == K_SPACE || ((shift & S_CTRL) && scan == K_MOUSE1))
1129 {
1130 if(me.nItems != 0)
1131 {
1132 float thisPos = me.getItemStart(me, me.selectedItem);
1133 float thisHeight = me.getItemHeight(me, me.selectedItem);
1134 vector org = boxToGlobal(eY * (thisPos - me.scrollPos), me.origin, me.size);
1135 vector sz = boxToGlobalSize(eY * thisHeight + eX * (1 - me.controlWidth), me.size);
1137 main.serverInfoDialog.loadServerInfo(main.serverInfoDialog, me.selectedItem);
1138 DialogOpenButton_Click_withCoords(me, main.serverInfoDialog, org, sz);
1139 return true;
1140 }
1141 return false;
1142 }
1143 else if(scan == K_INS || scan == K_MOUSE3 || scan == K_KP_INS)
1144 {
1145 if(me.nItems != 0)
1146 {
1147 me.toggleFavorite(me, me.selectedServer);
1148 me.ipAddressBoxFocused = -1;
1149 return true;
1150 }
1151 return false;
1152 }
1153 else if(SUPER(XonoticServerList).keyDown(me, scan, ascii, shift))
1154 return true;
1155 else if(!me.controlledTextbox)
1156 return false;
1157 else
1158 return me.controlledTextbox.keyDown(me.controlledTextbox, scan, ascii, shift);
1159}
const int S_CTRL
Definition hud.qh:130
float K_MOUSE1
Definition keycodes.qc:129
float K_MOUSE3
Definition keycodes.qc:131
float K_SPACE
Definition keycodes.qc:10
float K_ENTER
Definition keycodes.qc:8
float K_MOUSE2
Definition keycodes.qc:130
float K_KP_ENTER
Definition keycodes.qc:74
float K_INS
Definition keycodes.qc:37
float K_KP_INS
Definition keycodes.qc:49
const string MENU_SOUND_OPEN
Definition menu.qh:53

References boxToGlobal(), boxToGlobalSize(), DialogOpenButton_Click_withCoords(), entity(), eX, eY, K_ENTER, K_INS, K_KP_ENTER, K_KP_INS, K_MOUSE1, K_MOUSE2, K_MOUSE3, K_SPACE, m_play_click_sound(), main, MENU_SOUND_OPEN, NULL, org, S_CTRL, ServerList_Connect_Click(), SUPER, and vector.

◆ XonoticServerList_mouseMove()

float XonoticServerList_mouseMove ( entity me,
vector pos )

Definition at line 1100 of file serverlist.qc.

1101{
1102 if(!SUPER(XonoticServerList).mouseMove(me, pos))
1103 {
1104 me.mouseOverIcons = false;
1105 clearTooltip(me);
1106 return 1;
1107 }
1108
1109 float iconSize_x = me.realFontSize.x * me.iconsSizeFactor;
1110 float iconPos_x;
1111 if(me.seenIPv4 && me.seenIPv6)
1112 iconPos_x = (me.columnIconsSize - 4 * iconSize_x) * 0.5;
1113 else
1114 iconPos_x = (me.columnIconsSize - 3 * iconSize_x) * 0.5;
1115 me.mouseOverIcons = (pos.x >= me.columnIconsOrigin + iconPos_x && pos.x <= me.columnIconsOrigin + me.columnIconsSize - iconPos_x);
1116 if(!me.mouseOverIcons)
1117 clearTooltip(me);
1118 return 1;
1119}

References clearTooltip(), entity(), SUPER, and vector.

◆ XonoticServerList_positionSortButton()

void XonoticServerList_positionSortButton ( entity me,
entity btn,
float theOrigin,
float theSize,
string theTitle,
void(entity, entity) theFunc )

Definition at line 717 of file serverlist.qc.

718{
719 vector originInLBSpace = eY * (-me.itemHeight);
720 vector sizeInLBSpace = eY * me.itemHeight + eX * (1 - me.controlWidth);
721
722 vector originInDialogSpace = boxToGlobal(originInLBSpace, me.Container_origin, me.Container_size);
723 vector sizeInDialogSpace = boxToGlobalSize(sizeInLBSpace, me.Container_size);
724
725 btn.Container_origin_x = originInDialogSpace.x + sizeInDialogSpace.x * theOrigin;
726 btn.Container_size_x = sizeInDialogSpace.x * theSize;
727 btn.setText(btn, theTitle);
728 btn.onClick = theFunc;
729 btn.onClickEntity = me;
730 btn.resized = 1;
731}

References boxToGlobal(), boxToGlobalSize(), entity(), eX, eY, and vector.

◆ XonoticServerList_refreshServerList()

void XonoticServerList_refreshServerList ( entity me,
int mode )

Definition at line 312 of file serverlist.qc.

313{
314 //print("refresh of type ", ftos(mode), "\n");
315
317 {
318 string s = me.filterString;
319
320 string typestr;
321 int m = strstrofs(s, ":", 0);
322 if(m >= 0)
323 {
324 typestr = substring(s, 0, m);
325 s = substring(s, m + 1, strlen(s) - m - 1);
326 while(substring(s, 0, 1) == " ")
327 s = substring(s, 1, strlen(s) - 1);
328 }
329 else
330 typestr = "";
331
332 string modstr = cvar_string("menu_slist_modfilter");
333
334 m = SLIST_MASK_AND - 1;
336
337 // show full button
338 if(!me.filterShowFull)
339 {
340 sethostcachemasknumber(++m, SLIST_FIELD_FREESLOTS, 1, SLIST_TEST_GREATEREQUAL); // can connect
341 // There's several reasons to join a server where nJoinAllowed() reported 0 free slots, such as:
342 // to spec the match, chat, vote for a gametype with more players, or join your reserved tournament slot.
343 //sethostcachemaskstring(++m, SLIST_FIELD_QCSTATUS, ":S0:", SLIST_TEST_NOTCONTAIN); // g_maxplayers support
344 }
345
346 // show empty button
347 if(!me.filterShowEmpty)
348 sethostcachemasknumber(++m, SLIST_FIELD_NUMHUMANS, 1, SLIST_TEST_GREATEREQUAL);
349
350 // show laggy button
351 if(!me.filterShowLaggy && autocvar_menu_slist_maxping > 0)
353
354 // gametype filtering
355 if(typestr != "")
356 sethostcachemaskstring(++m, SLIST_FIELD_QCSTATUS, strcat(typestr, ":"), SLIST_TEST_STARTSWITH);
357
358 // mod filtering
359 if(modstr != "")
360 {
361 if(substring(modstr, 0, 1) == "!")
362 sethostcachemaskstring(++m, SLIST_FIELD_MOD, resolvemod(substring(modstr, 1, strlen(modstr) - 1)), SLIST_TEST_NOTEQUAL);
363 else
364 sethostcachemaskstring(++m, SLIST_FIELD_MOD, resolvemod(modstr), SLIST_TEST_EQUAL);
365 }
366
367 // server banning
369 for(int i = 0; i < n; ++i)
370 if(argv(i) != "")
371 sethostcachemaskstring(++m, SLIST_FIELD_CNAME, argv(i), SLIST_TEST_NOTSTARTSWITH);
372
373 m = SLIST_MASK_OR - 1;
374 if(s != "")
375 {
376 sethostcachemaskstring(++m, SLIST_FIELD_NAME, s, SLIST_TEST_CONTAINS);
377 sethostcachemaskstring(++m, SLIST_FIELD_MAP, s, SLIST_TEST_CONTAINS);
378 sethostcachemaskstring(++m, SLIST_FIELD_PLAYERS, s, SLIST_TEST_CONTAINS);
379 sethostcachemaskstring(++m, SLIST_FIELD_QCSTATUS, strcat(s, ":"), SLIST_TEST_STARTSWITH);
380 }
381
382 int sorting_flags = 0;
383 //sorting_flags |= SLSF_FAVORITES;
384 sorting_flags |= SLSF_CATEGORIES;
385 if(me.currentSortOrder < 0) { sorting_flags |= SLSF_DESCENDING; }
386 sethostcachesort(me.currentSortField, sorting_flags);
387 }
388
390 if(mode >= REFRESHSERVERLIST_ASK)
392}
string resolvemod(string m)
Definition util.qc:596
string _Nex_ExtResponseSystem_BannedServers
Definition util.qh:62
float SLIST_TEST_LESSEQUAL
Definition menudefs.qc:116
float SLSF_DESCENDING
Definition menudefs.qc:616
float SLIST_TEST_NOTSTARTSWITH
Definition menudefs.qc:123
void sethostcachesort(float fld, float slsf)
float SLIST_TEST_CONTAINS
Definition menudefs.qc:114
float SLIST_TEST_GREATEREQUAL
Definition menudefs.qc:120
float SLIST_TEST_NOTEQUAL
Definition menudefs.qc:121
float SLIST_MASK_OR
Definition menudefs.qc:125
void sethostcachemaskstring(float mask, float fld, string str, float op)
void resethostcachemasks(void)
float SLIST_TEST_STARTSWITH
Definition menudefs.qc:122
void refreshhostcache(...)
void resorthostcache(void)
float SLIST_TEST_EQUAL
Definition menudefs.qc:118
float SLSF_CATEGORIES
Definition menudefs.qc:618
void sethostcachemasknumber(float mask, float fld, float num, float op)
float SLIST_MASK_AND
Definition menudefs.qc:124
float autocvar_menu_slist_maxping

References _Nex_ExtResponseSystem_BannedServers, argv(), autocvar_menu_slist_maxping, cvar_string(), entity(), refreshhostcache(), REFRESHSERVERLIST_ASK, REFRESHSERVERLIST_REFILTER, REFRESHSERVERLIST_RESET, resethostcachemasks(), resolvemod(), resorthostcache(), sethostcachemasknumber(), sethostcachemaskstring(), sethostcachesort(), SLIST_MASK_AND, SLIST_MASK_OR, SLIST_TEST_CONTAINS, SLIST_TEST_EQUAL, SLIST_TEST_GREATEREQUAL, SLIST_TEST_LESSEQUAL, SLIST_TEST_NOTEQUAL, SLIST_TEST_NOTSTARTSWITH, SLIST_TEST_STARTSWITH, SLSF_CATEGORIES, SLSF_DESCENDING, strcat(), strlen, strstrofs, substring(), and tokenizebyseparator.

◆ XonoticServerList_resizeNotify()

void XonoticServerList_resizeNotify ( entity me,
vector relOrigin,
vector relSize,
vector absOrigin,
vector absSize )

Definition at line 732 of file serverlist.qc.

733{
734 SUPER(XonoticServerList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
735
736 me.realFontSize_y = me.fontSize / (absSize.y * me.itemHeight);
737 me.realFontSize_x = me.fontSize / (absSize.x * (1 - me.controlWidth));
738 me.realUpperMargin = 0.5 * (1 - me.realFontSize.y);
739
740 me.columnIconsOrigin = 0;
741 me.columnIconsSize = me.realFontSize.x * 5 * me.iconsSizeFactor;
742 me.columnPingSize = me.realFontSize.x * 3;
743 me.columnMapSize = me.realFontSize.x * 10;
744 me.columnTypeSize = me.realFontSize.x * 4;
745 me.columnPlayersSize = me.realFontSize.x * 5;
746 me.columnNameSize = 1 - me.columnPlayersSize - me.columnMapSize - me.columnPingSize - me.columnIconsSize - me.columnTypeSize - 4 * me.realFontSize.x;
747 // no me.realFontSize.x separation between icons and ping columns because in practice they are already separated
748 me.columnPingOrigin = me.columnIconsOrigin + me.columnIconsSize;
749 me.columnNameOrigin = me.columnPingOrigin + me.columnPingSize + me.realFontSize.x;
750 me.columnMapOrigin = me.columnNameOrigin + me.columnNameSize + me.realFontSize.x;
751 me.columnTypeOrigin = me.columnMapOrigin + me.columnMapSize + me.realFontSize.x;
752 me.columnPlayersOrigin = me.columnTypeOrigin + me.columnTypeSize + me.realFontSize.x;
753
754 me.positionSortButton(me, me.sortButton1, me.columnPingOrigin, me.columnPingSize, _("Ping"), ServerList_PingSort_Click);
755 me.positionSortButton(me, me.sortButton2, me.columnNameOrigin, me.columnNameSize, _("Hostname"), ServerList_NameSort_Click);
756 me.positionSortButton(me, me.sortButton3, me.columnMapOrigin, me.columnMapSize, _("Map"), ServerList_MapSort_Click);
757 me.positionSortButton(me, me.sortButton4, me.columnTypeOrigin, me.columnTypeSize, _("Type"), ServerList_TypeSort_Click);
758 me.positionSortButton(me, me.sortButton5, me.columnPlayersOrigin, me.columnPlayersSize, _("Players"), ServerList_PlayerSort_Click);
759
760 int f = me.currentSortField;
761 if(f >= 0)
762 {
763 me.currentSortField = -1;
764 me.setSortOrder(me, f, me.currentSortOrder); // force resetting the sort order
765 }
766}
void ServerList_PingSort_Click(entity btn, entity me)
void ServerList_NameSort_Click(entity btn, entity me)
void ServerList_TypeSort_Click(entity btn, entity me)
void ServerList_PlayerSort_Click(entity btn, entity me)
void ServerList_MapSort_Click(entity btn, entity me)

References entity(), ServerList_MapSort_Click(), ServerList_NameSort_Click(), ServerList_PingSort_Click(), ServerList_PlayerSort_Click(), ServerList_TypeSort_Click(), SUPER, and vector.

◆ XonoticServerList_setSelected()

void XonoticServerList_setSelected ( entity me,
int i )

Definition at line 292 of file serverlist.qc.

293{
294 me.lockedSelectedItem = false;
295 //int save = me.selectedItem;
296 SUPER(XonoticServerList).setSelected(me, i);
297 /*
298 if(me.selectedItem == save)
299 return;
300 */
301 if(me.nItems == 0)
302 return;
304 return; // sorry, it would be wrong
305
306 strcpy(me.selectedServer, gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
307
308 me.ipAddressBox.setText(me.ipAddressBox, me.selectedServer);
309 me.ipAddressBox.cursorPos = strlen(me.selectedServer);
310 me.ipAddressBoxFocused = -1;
311}

References entity(), gethostcachestring(), gethostcachevalue(), SLIST_HOSTCACHEVIEWCOUNT, strcpy, strlen, and SUPER.

◆ XonoticServerList_setSortOrder()

void XonoticServerList_setSortOrder ( entity me,
int fld,
int direction )

Definition at line 702 of file serverlist.qc.

703{
704 if(me.currentSortField == fld)
705 direction = -me.currentSortOrder;
706 me.currentSortOrder = direction;
707 me.currentSortField = fld;
708 me.sortButton1.forcePressed = (fld == SLIST_FIELD_PING);
709 me.sortButton2.forcePressed = (fld == SLIST_FIELD_NAME);
710 me.sortButton3.forcePressed = (fld == SLIST_FIELD_MAP);
711 me.sortButton4.forcePressed = false;
712 me.sortButton5.forcePressed = (fld == SLIST_FIELD_NUMHUMANS);
713 me.selectedItem = 0;
714 strfree(me.selectedServer);
715 me.refreshServerList(me, REFRESHSERVERLIST_REFILTER);
716}

References entity(), REFRESHSERVERLIST_REFILTER, and strfree.

Variable Documentation

◆ autocvar_hud_panel_scoreboard_ping_high

int autocvar_hud_panel_scoreboard_ping_high

Definition at line 798 of file serverlist.qc.

◆ autocvar_hud_panel_scoreboard_ping_low

int autocvar_hud_panel_scoreboard_ping_low

Definition at line 796 of file serverlist.qc.

◆ autocvar_hud_panel_scoreboard_ping_medium

int autocvar_hud_panel_scoreboard_ping_medium

Definition at line 797 of file serverlist.qc.