2 CLASS(XonoticServerList) EXTENDS(XonoticListBox)
3 METHOD(XonoticServerList, configureXonoticServerList, void(entity))
4 ATTRIB(XonoticServerList, rowsPerItem, float, 1)
5 METHOD(XonoticServerList, draw, void(entity))
6 METHOD(XonoticServerList, drawListBoxItem, void(entity, float, vector, float))
7 METHOD(XonoticServerList, clickListBoxItem, void(entity, float, vector))
8 METHOD(XonoticServerList, resizeNotify, void(entity, vector, vector, vector, vector))
9 METHOD(XonoticServerList, keyDown, float(entity, float, float, float))
11 ATTRIB(XonoticServerList, iconsSizeFactor, float, 0.85)
13 ATTRIB(XonoticServerList, realFontSize, vector, '0 0 0')
14 ATTRIB(XonoticServerList, realUpperMargin, float, 0)
15 ATTRIB(XonoticServerList, columnIconsOrigin, float, 0)
16 ATTRIB(XonoticServerList, columnIconsSize, float, 0)
17 ATTRIB(XonoticServerList, columnPingOrigin, float, 0)
18 ATTRIB(XonoticServerList, columnPingSize, float, 0)
19 ATTRIB(XonoticServerList, columnNameOrigin, float, 0)
20 ATTRIB(XonoticServerList, columnNameSize, float, 0)
21 ATTRIB(XonoticServerList, columnMapOrigin, float, 0)
22 ATTRIB(XonoticServerList, columnMapSize, float, 0)
23 ATTRIB(XonoticServerList, columnTypeOrigin, float, 0)
24 ATTRIB(XonoticServerList, columnTypeSize, float, 0)
25 ATTRIB(XonoticServerList, columnPlayersOrigin, float, 0)
26 ATTRIB(XonoticServerList, columnPlayersSize, float, 0)
28 ATTRIB(XonoticServerList, selectedServer, string, string_null) // to restore selected server when needed
29 METHOD(XonoticServerList, setSelected, void(entity, float))
30 METHOD(XonoticServerList, setSortOrder, void(entity, float, float))
31 ATTRIB(XonoticServerList, filterShowEmpty, float, 1)
32 ATTRIB(XonoticServerList, filterShowFull, float, 1)
33 ATTRIB(XonoticServerList, filterString, string, string_null)
34 ATTRIB(XonoticServerList, controlledTextbox, entity, NULL)
35 ATTRIB(XonoticServerList, ipAddressBox, entity, NULL)
36 ATTRIB(XonoticServerList, favoriteButton, entity, NULL)
37 ATTRIB(XonoticServerList, nextRefreshTime, float, 0)
38 METHOD(XonoticServerList, refreshServerList, void(entity, float)) // refresh mode: 0 = just reparametrize, 1 = send new requests, 2 = clear
39 ATTRIB(XonoticServerList, needsRefresh, float, 1)
40 METHOD(XonoticServerList, focusEnter, void(entity))
41 METHOD(XonoticServerList, positionSortButton, void(entity, entity, float, float, string, void(entity, entity)))
42 ATTRIB(XonoticServerList, sortButton1, entity, NULL)
43 ATTRIB(XonoticServerList, sortButton2, entity, NULL)
44 ATTRIB(XonoticServerList, sortButton3, entity, NULL)
45 ATTRIB(XonoticServerList, sortButton4, entity, NULL)
46 ATTRIB(XonoticServerList, sortButton5, entity, NULL)
47 ATTRIB(XonoticServerList, connectButton, entity, NULL)
48 ATTRIB(XonoticServerList, infoButton, entity, NULL)
49 ATTRIB(XonoticServerList, currentSortOrder, float, 0)
50 ATTRIB(XonoticServerList, currentSortField, float, -1)
51 ATTRIB(XonoticServerList, lastClickedServer, float, -1)
52 ATTRIB(XonoticServerList, lastClickedTime, float, 0)
54 ATTRIB(XonoticServerList, ipAddressBoxFocused, float, -1)
56 ATTRIB(XonoticServerList, seenIPv4, float, 0)
57 ATTRIB(XonoticServerList, seenIPv6, float, 0)
58 ENDCLASS(XonoticServerList)
59 entity makeXonoticServerList();
60 void ServerList_Connect_Click(entity btn, entity me);
61 void ServerList_ShowEmpty_Click(entity box, entity me);
62 void ServerList_ShowFull_Click(entity box, entity me);
63 void ServerList_Filter_Change(entity box, entity me);
64 void ServerList_Favorite_Click(entity btn, entity me);
65 void ServerList_Info_Click(entity btn, entity me);
66 void ServerList_Update_favoriteButton(entity btn, entity me);
70 float SLIST_FIELD_CNAME;
71 float SLIST_FIELD_PING;
72 float SLIST_FIELD_GAME;
73 float SLIST_FIELD_MOD;
74 float SLIST_FIELD_MAP;
75 float SLIST_FIELD_NAME;
76 float SLIST_FIELD_MAXPLAYERS;
77 float SLIST_FIELD_NUMPLAYERS;
78 float SLIST_FIELD_NUMHUMANS;
79 float SLIST_FIELD_NUMBOTS;
80 float SLIST_FIELD_PROTOCOL;
81 float SLIST_FIELD_FREESLOTS;
82 float SLIST_FIELD_PLAYERS;
83 float SLIST_FIELD_QCSTATUS;
84 float SLIST_FIELD_ISFAVORITE;
85 void ServerList_UpdateFieldIDs()
87 SLIST_FIELD_CNAME = gethostcacheindexforkey( "cname" );
88 SLIST_FIELD_PING = gethostcacheindexforkey( "ping" );
89 SLIST_FIELD_GAME = gethostcacheindexforkey( "game" );
90 SLIST_FIELD_MOD = gethostcacheindexforkey( "mod" );
91 SLIST_FIELD_MAP = gethostcacheindexforkey( "map" );
92 SLIST_FIELD_NAME = gethostcacheindexforkey( "name" );
93 SLIST_FIELD_MAXPLAYERS = gethostcacheindexforkey( "maxplayers" );
94 SLIST_FIELD_NUMPLAYERS = gethostcacheindexforkey( "numplayers" );
95 SLIST_FIELD_NUMHUMANS = gethostcacheindexforkey( "numhumans" );
96 SLIST_FIELD_NUMBOTS = gethostcacheindexforkey( "numbots" );
97 SLIST_FIELD_PROTOCOL = gethostcacheindexforkey( "protocol" );
98 SLIST_FIELD_FREESLOTS = gethostcacheindexforkey( "freeslots" );
99 SLIST_FIELD_PLAYERS = gethostcacheindexforkey( "players" );
100 SLIST_FIELD_QCSTATUS = gethostcacheindexforkey( "qcstatus" );
101 SLIST_FIELD_ISFAVORITE = gethostcacheindexforkey( "isfavorite" );
104 float IsFavorite(string srv)
110 srv = netaddress_resolve(srv, 26000);
113 p = crypto_getidfp(srv);
114 n = tokenize_console(cvar_string("net_slist_favorites"));
115 for(i = 0; i < n; ++i)
117 if(substring(argv(i), 0, 1) != "[" && strlen(argv(i)) == 44 && strstrofs(argv(i), ".", 0) < 0)
125 if(srv == netaddress_resolve(argv(i), 26000))
132 void ToggleFavorite(string srv)
134 string s, s0, s1, s2, srv_resolved, p;
136 srv_resolved = netaddress_resolve(srv, 26000);
137 p = crypto_getidfp(srv_resolved);
138 s = cvar_string("net_slist_favorites");
139 n = tokenize_console(s);
141 for(i = 0; i < n; ++i)
143 if(substring(argv(i), 0, 1) != "[" && strlen(argv(i)) == 44 && strstrofs(argv(i), ".", 0) < 0)
151 if(srv_resolved != netaddress_resolve(argv(i), 26000))
156 s0 = substring(s, 0, argv_end_index(i - 1));
158 s2 = substring(s, argv_start_index(i + 1), -1);
159 if(s0 != "" && s2 != "")
161 cvar_set("net_slist_favorites", strcat(s0, s1, s2));
162 s = cvar_string("net_slist_favorites");
163 n = tokenize_console(s);
174 cvar_set("net_slist_favorites", strcat(s, s1, p));
176 cvar_set("net_slist_favorites", strcat(s, s1, srv));
182 void ServerList_Update_favoriteButton(entity btn, entity me)
184 if(IsFavorite(me.ipAddressBox.text))
185 me.favoriteButton.setText(me.favoriteButton, _("Remove"));
187 me.favoriteButton.setText(me.favoriteButton, _("Bookmark"));
190 entity makeXonoticServerList()
193 me = spawnXonoticServerList();
194 me.configureXonoticServerList(me);
197 void XonoticServerList_configureXonoticServerList(entity me)
199 me.configureXonoticListBox(me);
201 ServerList_UpdateFieldIDs();
205 void XonoticServerList_setSelected(entity me, float i)
208 save = me.selectedItem;
209 SUPER(XonoticServerList).setSelected(me, i);
211 if(me.selectedItem == save)
216 if(gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT) != me.nItems)
217 return; // sorry, it would be wrong
219 if(me.selectedServer)
220 strunzone(me.selectedServer);
221 me.selectedServer = strzone(gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
223 me.ipAddressBox.setText(me.ipAddressBox, me.selectedServer);
224 me.ipAddressBox.cursorPos = strlen(me.selectedServer);
225 me.ipAddressBoxFocused = -1;
227 void XonoticServerList_refreshServerList(entity me, float mode)
229 // 0: just reparametrize
230 // 1: also ask for new servers
232 //print("refresh of type ", ftos(mode), "\n");
233 /* if(mode == 2) // borken
236 localcmd("net_slist\n");
237 me.needsRefresh = 1; // net_slist kills sort order, so we need to restore it later
242 string s, typestr, modstr;
245 m = strstrofs(s, ":", 0);
248 typestr = substring(s, 0, m);
249 s = substring(s, m + 1, strlen(s) - m - 1);
250 while(substring(s, 0, 1) == " ")
251 s = substring(s, 1, strlen(s) - 1);
256 modstr = cvar_string("menu_slist_modfilter");
258 m = SLIST_MASK_AND - 1;
259 resethostcachemasks();
260 if(!me.filterShowFull)
262 sethostcachemasknumber(++m, SLIST_FIELD_FREESLOTS, 1, SLIST_TEST_GREATEREQUAL); // legacy
263 sethostcachemaskstring(++m, SLIST_FIELD_QCSTATUS, ":S0:", SLIST_TEST_NOTCONTAIN); // g_maxplayers support
265 if(!me.filterShowEmpty)
266 sethostcachemasknumber(++m, SLIST_FIELD_NUMHUMANS, 1, SLIST_TEST_GREATEREQUAL);
268 sethostcachemaskstring(++m, SLIST_FIELD_QCSTATUS, strcat(typestr, ":"), SLIST_TEST_STARTSWITH);
271 if(substring(modstr, 0, 1) == "!")
272 sethostcachemaskstring(++m, SLIST_FIELD_MOD, resolvemod(substring(modstr, 1, strlen(modstr) - 1)), SLIST_TEST_NOTEQUAL);
274 sethostcachemaskstring(++m, SLIST_FIELD_MOD, resolvemod(modstr), SLIST_TEST_EQUAL);
276 m = SLIST_MASK_OR - 1;
279 sethostcachemaskstring(++m, SLIST_FIELD_NAME, s, SLIST_TEST_CONTAINS);
280 sethostcachemaskstring(++m, SLIST_FIELD_MAP, s, SLIST_TEST_CONTAINS);
281 sethostcachemaskstring(++m, SLIST_FIELD_PLAYERS, s, SLIST_TEST_CONTAINS);
282 sethostcachemaskstring(++m, SLIST_FIELD_QCSTATUS, strcat(s, ":"), SLIST_TEST_STARTSWITH);
284 o = 2; // favorites first
285 if(me.currentSortOrder < 0)
286 o |= 1; // descending
287 sethostcachesort(me.currentSortField, o);
293 void XonoticServerList_focusEnter(entity me)
295 if(time < me.nextRefreshTime)
297 //print("sorry, no refresh yet\n");
300 me.nextRefreshTime = time + 10;
301 me.refreshServerList(me, 1);
303 void XonoticServerList_draw(entity me)
305 float i, found, owned;
307 if(me.currentSortField == -1)
309 me.setSortOrder(me, SLIST_FIELD_PING, +1);
310 me.refreshServerList(me, 2);
312 else if(me.needsRefresh == 1)
314 me.needsRefresh = 2; // delay by one frame to make sure "slist" has been executed
316 else if(me.needsRefresh == 2)
319 me.refreshServerList(me, 0);
322 owned = ((me.selectedServer == me.ipAddressBox.text) && (me.ipAddressBox.text != ""));
324 me.nItems = gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT);
326 me.connectButton.disabled = ((me.nItems == 0) && (me.ipAddressBox.text == ""));
327 me.infoButton.disabled = ((me.nItems == 0) || !owned);
328 me.favoriteButton.disabled = ((me.nItems == 0) && (me.ipAddressBox.text == ""));
331 if(me.selectedServer)
333 for(i = 0; i < me.nItems; ++i)
334 if(gethostcachestring(SLIST_FIELD_CNAME, i) == me.selectedServer)
336 if(i != me.selectedItem)
338 me.lastClickedServer = -1;
348 if(me.selectedItem >= me.nItems)
349 me.selectedItem = me.nItems - 1;
350 if(me.selectedServer)
351 strunzone(me.selectedServer);
352 me.selectedServer = strzone(gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
357 if(me.selectedServer != me.ipAddressBox.text)
359 me.ipAddressBox.setText(me.ipAddressBox, me.selectedServer);
360 me.ipAddressBox.cursorPos = strlen(me.selectedServer);
361 me.ipAddressBoxFocused = -1;
365 if(me.ipAddressBoxFocused != me.ipAddressBox.focused)
367 if(me.ipAddressBox.focused || me.ipAddressBoxFocused < 0)
368 ServerList_Update_favoriteButton(NULL, me);
369 me.ipAddressBoxFocused = me.ipAddressBox.focused;
372 SUPER(XonoticServerList).draw(me);
374 void ServerList_PingSort_Click(entity btn, entity me)
376 me.setSortOrder(me, SLIST_FIELD_PING, +1);
378 void ServerList_NameSort_Click(entity btn, entity me)
380 me.setSortOrder(me, SLIST_FIELD_NAME, -1); // why?
382 void ServerList_MapSort_Click(entity btn, entity me)
384 me.setSortOrder(me, SLIST_FIELD_MAP, -1); // why?
386 void ServerList_PlayerSort_Click(entity btn, entity me)
388 me.setSortOrder(me, SLIST_FIELD_NUMHUMANS, -1);
390 void ServerList_TypeSort_Click(entity btn, entity me)
395 m = strstrofs(s, ":", 0);
398 s = substring(s, 0, m);
399 while(substring(s, m+1, 1) == " ") // skip spaces
405 for(i = 1; ; ++i) // 20 modes ought to be enough for anyone
407 t = GametypeNameFromType(i);
409 if(t == GametypeNameFromType(0)) // it repeats (default case)
412 // choose the first one
416 if(s == GametypeNameFromType(i))
418 // the type was found
419 // choose the next one
420 s = GametypeNameFromType(i + 1);
421 if(s == GametypeNameFromType(0))
429 s = strcat(s, substring(me.filterString, m+1, strlen(me.filterString) - m - 1));
431 me.controlledTextbox.setText(me.controlledTextbox, s);
432 me.controlledTextbox.keyDown(me.controlledTextbox, K_END, 0, 0);
433 me.controlledTextbox.keyUp(me.controlledTextbox, K_END, 0, 0);
434 //ServerList_Filter_Change(me.controlledTextbox, me);
436 void ServerList_Filter_Change(entity box, entity me)
439 strunzone(me.filterString);
441 me.filterString = strzone(box.text);
443 me.filterString = string_null;
444 me.refreshServerList(me, 0);
446 me.ipAddressBox.setText(me.ipAddressBox, "");
447 me.ipAddressBox.cursorPos = 0;
448 me.ipAddressBoxFocused = -1;
450 void ServerList_ShowEmpty_Click(entity box, entity me)
452 box.setChecked(box, me.filterShowEmpty = !me.filterShowEmpty);
453 me.refreshServerList(me, 0);
455 me.ipAddressBox.setText(me.ipAddressBox, "");
456 me.ipAddressBox.cursorPos = 0;
457 me.ipAddressBoxFocused = -1;
459 void ServerList_ShowFull_Click(entity box, entity me)
461 box.setChecked(box, me.filterShowFull = !me.filterShowFull);
462 me.refreshServerList(me, 0);
464 me.ipAddressBox.setText(me.ipAddressBox, "");
465 me.ipAddressBox.cursorPos = 0;
466 me.ipAddressBoxFocused = -1;
468 void XonoticServerList_setSortOrder(entity me, float field, float direction)
470 if(me.currentSortField == field)
471 direction = -me.currentSortOrder;
472 me.currentSortOrder = direction;
473 me.currentSortField = field;
474 me.sortButton1.forcePressed = (field == SLIST_FIELD_PING);
475 me.sortButton2.forcePressed = (field == SLIST_FIELD_NAME);
476 me.sortButton3.forcePressed = (field == SLIST_FIELD_MAP);
477 me.sortButton4.forcePressed = 0;
478 me.sortButton5.forcePressed = (field == SLIST_FIELD_NUMHUMANS);
480 if(me.selectedServer)
481 strunzone(me.selectedServer);
482 me.selectedServer = string_null;
483 me.refreshServerList(me, 0);
485 void XonoticServerList_positionSortButton(entity me, entity btn, float theOrigin, float theSize, string theTitle, void(entity, entity) theFunc)
487 vector originInLBSpace, sizeInLBSpace;
488 originInLBSpace = eY * (-me.itemHeight);
489 sizeInLBSpace = eY * me.itemHeight + eX * (1 - me.controlWidth);
491 vector originInDialogSpace, sizeInDialogSpace;
492 originInDialogSpace = boxToGlobal(originInLBSpace, me.Container_origin, me.Container_size);
493 sizeInDialogSpace = boxToGlobalSize(sizeInLBSpace, me.Container_size);
495 btn.Container_origin_x = originInDialogSpace_x + sizeInDialogSpace_x * theOrigin;
496 btn.Container_size_x = sizeInDialogSpace_x * theSize;
497 btn.setText(btn, theTitle);
498 btn.onClick = theFunc;
499 btn.onClickEntity = me;
502 void XonoticServerList_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
504 SUPER(XonoticServerList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
506 me.realFontSize_y = me.fontSize / (absSize_y * me.itemHeight);
507 me.realFontSize_x = me.fontSize / (absSize_x * (1 - me.controlWidth));
508 me.realUpperMargin = 0.5 * (1 - me.realFontSize_y);
510 me.columnIconsOrigin = 0;
511 me.columnIconsSize = me.realFontSize_x * 3 * me.iconsSizeFactor;
512 me.columnPingSize = me.realFontSize_x * 3;
513 me.columnMapSize = me.realFontSize_x * 10;
514 me.columnTypeSize = me.realFontSize_x * 4;
515 me.columnPlayersSize = me.realFontSize_x * 5;
516 me.columnNameSize = 1 - me.columnPlayersSize - me.columnMapSize - me.columnPingSize - me.columnIconsSize - me.columnTypeSize - 5 * me.realFontSize_x;
517 me.columnPingOrigin = me.columnIconsOrigin + me.columnIconsSize + me.realFontSize_x;
518 me.columnNameOrigin = me.columnPingOrigin + me.columnPingSize + me.realFontSize_x;
519 me.columnMapOrigin = me.columnNameOrigin + me.columnNameSize + me.realFontSize_x;
520 me.columnTypeOrigin = me.columnMapOrigin + me.columnMapSize + me.realFontSize_x;
521 me.columnPlayersOrigin = me.columnTypeOrigin + me.columnTypeSize + me.realFontSize_x;
523 me.positionSortButton(me, me.sortButton1, me.columnPingOrigin, me.columnPingSize, _("Ping"), ServerList_PingSort_Click);
524 me.positionSortButton(me, me.sortButton2, me.columnNameOrigin, me.columnNameSize, _("Host name"), ServerList_NameSort_Click);
525 me.positionSortButton(me, me.sortButton3, me.columnMapOrigin, me.columnMapSize, _("Map"), ServerList_MapSort_Click);
526 me.positionSortButton(me, me.sortButton4, me.columnTypeOrigin, me.columnTypeSize, _("Type"), ServerList_TypeSort_Click);
527 me.positionSortButton(me, me.sortButton5, me.columnPlayersOrigin, me.columnPlayersSize, _("Players"), ServerList_PlayerSort_Click);
530 f = me.currentSortField;
533 me.currentSortField = -1;
534 me.setSortOrder(me, f, me.currentSortOrder); // force resetting the sort order
537 void ServerList_Connect_Click(entity btn, entity me)
539 if(me.ipAddressBox.text == "")
540 localcmd("connect ", me.selectedServer, "\n");
542 localcmd("connect ", me.ipAddressBox.text, "\n");
544 void ServerList_Favorite_Click(entity btn, entity me)
547 ipstr = netaddress_resolve(me.ipAddressBox.text, 26000);
550 ToggleFavorite(me.ipAddressBox.text);
551 me.ipAddressBoxFocused = -1;
554 void ServerList_Info_Click(entity btn, entity me)
556 main.serverInfoDialog.loadServerInfo(main.serverInfoDialog, me.selectedItem);
557 DialogOpenButton_Click(me, main.serverInfoDialog);
559 void XonoticServerList_clickListBoxItem(entity me, float i, vector where)
561 if(i == me.lastClickedServer)
562 if(time < me.lastClickedTime + 0.3)
565 ServerList_Connect_Click(NULL, me);
567 me.lastClickedServer = i;
568 me.lastClickedTime = time;
570 void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
572 // layout: Ping, Server name, Map name, NP, TP, MP
580 draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
582 if(gethostcachenumber(SLIST_FIELD_FREESLOTS, i) <= 0)
583 theAlpha = SKINALPHA_SERVERLIST_FULL;
584 else if(strstrofs(gethostcachestring(SLIST_FIELD_QCSTATUS, i), ":S0:", 0) >= 0)
585 theAlpha = SKINALPHA_SERVERLIST_FULL; // g_maxplayers support
586 else if not(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i))
587 theAlpha = SKINALPHA_SERVERLIST_EMPTY;
591 p = gethostcachenumber(SLIST_FIELD_PING, i);
594 #define PING_HIGH 500
596 theColor = SKINCOLOR_SERVERLIST_LOWPING + (SKINCOLOR_SERVERLIST_MEDPING - SKINCOLOR_SERVERLIST_LOWPING) * (p / PING_LOW);
597 else if(p < PING_MED)
598 theColor = SKINCOLOR_SERVERLIST_MEDPING + (SKINCOLOR_SERVERLIST_HIGHPING - SKINCOLOR_SERVERLIST_MEDPING) * ((p - PING_LOW) / (PING_MED - PING_LOW));
599 else if(p < PING_HIGH)
601 theColor = SKINCOLOR_SERVERLIST_HIGHPING;
602 theAlpha *= 1 + (SKINALPHA_SERVERLIST_HIGHPING - 1) * ((p - PING_MED) / (PING_HIGH - PING_MED));
607 theAlpha *= SKINALPHA_SERVERLIST_HIGHPING;
610 if(gethostcachenumber(SLIST_FIELD_ISFAVORITE, i))
612 theColor = theColor * (1 - SKINALPHA_SERVERLIST_FAVORITE) + SKINCOLOR_SERVERLIST_FAVORITE * SKINALPHA_SERVERLIST_FAVORITE;
613 theAlpha = theAlpha * (1 - SKINALPHA_SERVERLIST_FAVORITE) + SKINALPHA_SERVERLIST_FAVORITE;
616 s = gethostcachestring(SLIST_FIELD_CNAME, i);
619 if(substring(s, 0, 1) == "[")
624 else if(strstrofs("0123456789", substring(s, 0, 1), 0) >= 0)
630 q = stof(substring(crypto_getencryptlevel(s), 0, 1));
631 if((q <= 0 && cvar("crypto_aeslevel") >= 3) || (q >= 3 && cvar("crypto_aeslevel") <= 0))
633 theColor = SKINCOLOR_SERVERLIST_IMPOSSIBLE;
634 theAlpha = SKINALPHA_SERVERLIST_IMPOSSIBLE;
639 if(cvar("crypto_aeslevel") >= 2)
644 if(cvar("crypto_aeslevel") >= 1)
654 // 2: AES recommended but not available
655 // 3: AES possible and will be used
656 // 4: AES recommended and will be used
659 s = gethostcachestring(SLIST_FIELD_QCSTATUS, i);
662 iconSize_y = me.realFontSize_y * me.iconsSizeFactor;
663 iconSize_x = me.realFontSize_x * me.iconsSizeFactor;
666 iconPos_x = (me.columnIconsSize - 3 * iconSize_x) * 0.5;
667 iconPos_y = (1 - iconSize_y) * 0.5;
669 if not(me.seenIPv4 && me.seenIPv6)
671 iconPos_x += iconSize_x * 0.5;
673 else if(me.seenIPv4 && me.seenIPv6)
676 draw_Picture(iconPos, strcat(SKINGFX_SERVERLIST_ICON, "_ipv6"), iconSize, '1 1 1', 1);
678 draw_Picture(iconPos, strcat(SKINGFX_SERVERLIST_ICON, "_ipv4"), iconSize, '1 1 1', 1);
679 iconPos_x += iconSize_x;
682 draw_Picture(iconPos, strcat(SKINGFX_SERVERLIST_ICON, "_aeslevel", ftos(q)), iconSize, '1 1 1', 1);
683 iconPos_x += iconSize_x;
685 draw_Picture(iconPos, strcat(SKINGFX_SERVERLIST_ICON, "_pure", ftos(strstrofs(s, ":P0:", 0) >= 0)), iconSize, '1 1 1', 1);
686 iconPos_x += iconSize_x;
690 draw_Text(me.realUpperMargin * eY + (me.columnPingOrigin + me.columnPingSize - draw_TextWidth(s, 0, me.realFontSize)) * eX, s, me.realFontSize, theColor, theAlpha, 0);
691 s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_NAME, i), me.columnNameSize, 0, me.realFontSize);
692 draw_Text(me.realUpperMargin * eY + me.columnNameOrigin * eX, s, me.realFontSize, theColor, theAlpha, 0);
693 s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_MAP, i), me.columnMapSize, 0, me.realFontSize);
694 draw_Text(me.realUpperMargin * eY + (me.columnMapOrigin + (me.columnMapSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0);
695 s = gethostcachestring(SLIST_FIELD_QCSTATUS, i);
696 p = strstrofs(s, ":", 0);
698 s = substring(s, 0, p);
701 s = draw_TextShortenToWidth(s, me.columnMapSize, 0, me.realFontSize);
702 draw_Text(me.realUpperMargin * eY + (me.columnTypeOrigin + (me.columnTypeSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0);
703 s = strcat(ftos(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i)), "/", ftos(gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i)));
704 draw_Text(me.realUpperMargin * eY + (me.columnPlayersOrigin + (me.columnPlayersSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0);
707 float XonoticServerList_keyDown(entity me, float scan, float ascii, float shift)
712 org = boxToGlobal(eY * (me.selectedItem * me.itemHeight - me.scrollPos), me.origin, me.size);
713 sz = boxToGlobalSize(eY * me.itemHeight + eX * (1 - me.controlWidth), me.size);
715 if(scan == K_ENTER || scan == K_KP_ENTER)
717 ServerList_Connect_Click(NULL, me);
720 else if(scan == K_MOUSE2 || scan == K_SPACE)
724 main.serverInfoDialog.loadServerInfo(main.serverInfoDialog, me.selectedItem);
725 DialogOpenButton_Click_withCoords(me, main.serverInfoDialog, org, sz);
728 else if(scan == K_INS || scan == K_MOUSE3 || scan == K_KP_INS)
733 ToggleFavorite(me.selectedServer);
734 me.ipAddressBoxFocused = -1;
737 else if(SUPER(XonoticServerList).keyDown(me, scan, ascii, shift))
739 else if(!me.controlledTextbox)
742 return me.controlledTextbox.keyDown(me.controlledTextbox, scan, ascii, shift);