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);
69 float SLIST_FIELD_CNAME;
70 float SLIST_FIELD_PING;
71 float SLIST_FIELD_GAME;
72 float SLIST_FIELD_MOD;
73 float SLIST_FIELD_MAP;
74 float SLIST_FIELD_NAME;
75 float SLIST_FIELD_MAXPLAYERS;
76 float SLIST_FIELD_NUMPLAYERS;
77 float SLIST_FIELD_NUMHUMANS;
78 float SLIST_FIELD_NUMBOTS;
79 float SLIST_FIELD_PROTOCOL;
80 float SLIST_FIELD_FREESLOTS;
81 float SLIST_FIELD_PLAYERS;
82 float SLIST_FIELD_QCSTATUS;
83 float SLIST_FIELD_ISFAVORITE;
84 void ServerList_UpdateFieldIDs()
86 SLIST_FIELD_CNAME = gethostcacheindexforkey( "cname" );
87 SLIST_FIELD_PING = gethostcacheindexforkey( "ping" );
88 SLIST_FIELD_GAME = gethostcacheindexforkey( "game" );
89 SLIST_FIELD_MOD = gethostcacheindexforkey( "mod" );
90 SLIST_FIELD_MAP = gethostcacheindexforkey( "map" );
91 SLIST_FIELD_NAME = gethostcacheindexforkey( "name" );
92 SLIST_FIELD_MAXPLAYERS = gethostcacheindexforkey( "maxplayers" );
93 SLIST_FIELD_NUMPLAYERS = gethostcacheindexforkey( "numplayers" );
94 SLIST_FIELD_NUMHUMANS = gethostcacheindexforkey( "numhumans" );
95 SLIST_FIELD_NUMBOTS = gethostcacheindexforkey( "numbots" );
96 SLIST_FIELD_PROTOCOL = gethostcacheindexforkey( "protocol" );
97 SLIST_FIELD_FREESLOTS = gethostcacheindexforkey( "freeslots" );
98 SLIST_FIELD_PLAYERS = gethostcacheindexforkey( "players" );
99 SLIST_FIELD_QCSTATUS = gethostcacheindexforkey( "qcstatus" );
100 SLIST_FIELD_ISFAVORITE = gethostcacheindexforkey( "isfavorite" );
103 float IsFavorite(string srv)
109 srv = netaddress_resolve(srv, 26000);
112 p = crypto_getidfp(srv);
113 n = tokenize_console(cvar_string("net_slist_favorites"));
114 for(i = 0; i < n; ++i)
116 if(substring(argv(i), 0, 1) != "[" && strlen(argv(i)) == 44 && strstrofs(argv(i), ".", 0) < 0)
124 if(srv == netaddress_resolve(argv(i), 26000))
131 void ToggleFavorite(string srv)
133 string s, s0, s1, s2, srv_resolved, p;
135 srv_resolved = netaddress_resolve(srv, 26000);
136 p = crypto_getidfp(srv_resolved);
137 s = cvar_string("net_slist_favorites");
138 n = tokenize_console(s);
140 for(i = 0; i < n; ++i)
142 if(substring(argv(i), 0, 1) != "[" && strlen(argv(i)) == 44 && strstrofs(argv(i), ".", 0) < 0)
150 if(srv_resolved != netaddress_resolve(argv(i), 26000))
155 s0 = substring(s, 0, argv_end_index(i - 1));
157 s2 = substring(s, argv_start_index(i + 1), -1);
158 if(s0 != "" && s2 != "")
160 cvar_set("net_slist_favorites", strcat(s0, s1, s2));
161 s = cvar_string("net_slist_favorites");
162 n = tokenize_console(s);
173 cvar_set("net_slist_favorites", strcat(s, s1, p));
175 cvar_set("net_slist_favorites", strcat(s, s1, srv));
181 entity makeXonoticServerList()
184 me = spawnXonoticServerList();
185 me.configureXonoticServerList(me);
188 void XonoticServerList_configureXonoticServerList(entity me)
190 me.configureXonoticListBox(me);
192 ServerList_UpdateFieldIDs();
196 void XonoticServerList_setSelected(entity me, float i)
199 save = me.selectedItem;
200 SUPER(XonoticServerList).setSelected(me, i);
202 if(me.selectedItem == save)
207 if(gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT) != me.nItems)
208 return; // sorry, it would be wrong
210 if(me.selectedServer)
211 strunzone(me.selectedServer);
212 me.selectedServer = strzone(gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
214 me.ipAddressBox.setText(me.ipAddressBox, me.selectedServer);
215 me.ipAddressBox.cursorPos = strlen(me.selectedServer);
216 me.ipAddressBoxFocused = -1;
218 void XonoticServerList_refreshServerList(entity me, float mode)
220 // 0: just reparametrize
221 // 1: also ask for new servers
223 //print("refresh of type ", ftos(mode), "\n");
224 /* if(mode == 2) // borken
227 localcmd("net_slist\n");
228 me.needsRefresh = 1; // net_slist kills sort order, so we need to restore it later
233 string s, typestr, modstr;
236 m = strstrofs(s, ":", 0);
239 typestr = substring(s, 0, m);
240 s = substring(s, m + 1, strlen(s) - m - 1);
241 while(substring(s, 0, 1) == " ")
242 s = substring(s, 1, strlen(s) - 1);
247 modstr = cvar_string("menu_slist_modfilter");
249 m = SLIST_MASK_AND - 1;
250 resethostcachemasks();
251 if(!me.filterShowFull)
253 sethostcachemasknumber(++m, SLIST_FIELD_FREESLOTS, 1, SLIST_TEST_GREATEREQUAL); // legacy
254 sethostcachemaskstring(++m, SLIST_FIELD_QCSTATUS, ":S0:", SLIST_TEST_NOTCONTAIN); // g_maxplayers support
256 if(!me.filterShowEmpty)
257 sethostcachemasknumber(++m, SLIST_FIELD_NUMHUMANS, 1, SLIST_TEST_GREATEREQUAL);
259 sethostcachemaskstring(++m, SLIST_FIELD_QCSTATUS, strcat(typestr, ":"), SLIST_TEST_STARTSWITH);
262 if(substring(modstr, 0, 1) == "!")
263 sethostcachemaskstring(++m, SLIST_FIELD_MOD, resolvemod(substring(modstr, 1, strlen(modstr) - 1)), SLIST_TEST_NOTEQUAL);
265 sethostcachemaskstring(++m, SLIST_FIELD_MOD, resolvemod(modstr), SLIST_TEST_EQUAL);
267 m = SLIST_MASK_OR - 1;
270 sethostcachemaskstring(++m, SLIST_FIELD_NAME, s, SLIST_TEST_CONTAINS);
271 sethostcachemaskstring(++m, SLIST_FIELD_MAP, s, SLIST_TEST_CONTAINS);
272 sethostcachemaskstring(++m, SLIST_FIELD_PLAYERS, s, SLIST_TEST_CONTAINS);
273 sethostcachemaskstring(++m, SLIST_FIELD_QCSTATUS, strcat(s, ":"), SLIST_TEST_STARTSWITH);
275 o = 2; // favorites first
276 if(me.currentSortOrder < 0)
277 o |= 1; // descending
278 sethostcachesort(me.currentSortField, o);
284 void XonoticServerList_focusEnter(entity me)
286 if(time < me.nextRefreshTime)
288 //print("sorry, no refresh yet\n");
291 me.nextRefreshTime = time + 10;
292 me.refreshServerList(me, 1);
294 void XonoticServerList_draw(entity me)
296 float i, found, owned;
298 if(me.currentSortField == -1)
300 me.setSortOrder(me, SLIST_FIELD_PING, +1);
301 me.refreshServerList(me, 2);
303 else if(me.needsRefresh == 1)
305 me.needsRefresh = 2; // delay by one frame to make sure "slist" has been executed
307 else if(me.needsRefresh == 2)
310 me.refreshServerList(me, 0);
313 owned = ((me.selectedServer == me.ipAddressBox.text) && (me.ipAddressBox.text != ""));
315 me.nItems = gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT);
317 me.connectButton.disabled = ((me.nItems == 0) && (me.ipAddressBox.text == ""));
318 me.infoButton.disabled = ((me.nItems == 0) || !owned);
321 if(me.selectedServer)
323 for(i = 0; i < me.nItems; ++i)
324 if(gethostcachestring(SLIST_FIELD_CNAME, i) == me.selectedServer)
326 if(i != me.selectedItem)
328 me.lastClickedServer = -1;
338 if(me.selectedItem >= me.nItems)
339 me.selectedItem = me.nItems - 1;
340 if(me.selectedServer)
341 strunzone(me.selectedServer);
342 me.selectedServer = strzone(gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
347 if(me.selectedServer != me.ipAddressBox.text)
349 me.ipAddressBox.setText(me.ipAddressBox, me.selectedServer);
350 me.ipAddressBox.cursorPos = strlen(me.selectedServer);
351 me.ipAddressBoxFocused = -1;
355 if(me.ipAddressBoxFocused != me.ipAddressBox.focused)
357 if(me.ipAddressBox.focused || me.ipAddressBoxFocused < 0)
359 if(IsFavorite(me.ipAddressBox.text))
360 me.favoriteButton.setText(me.favoriteButton, _("Remove"));
362 me.favoriteButton.setText(me.favoriteButton, _("Bookmark"));
364 me.ipAddressBoxFocused = me.ipAddressBox.focused;
367 SUPER(XonoticServerList).draw(me);
369 void ServerList_PingSort_Click(entity btn, entity me)
371 me.setSortOrder(me, SLIST_FIELD_PING, +1);
373 void ServerList_NameSort_Click(entity btn, entity me)
375 me.setSortOrder(me, SLIST_FIELD_NAME, -1); // why?
377 void ServerList_MapSort_Click(entity btn, entity me)
379 me.setSortOrder(me, SLIST_FIELD_MAP, -1); // why?
381 void ServerList_PlayerSort_Click(entity btn, entity me)
383 me.setSortOrder(me, SLIST_FIELD_NUMHUMANS, -1);
385 void ServerList_TypeSort_Click(entity btn, entity me)
390 m = strstrofs(s, ":", 0);
393 s = substring(s, 0, m);
394 while(substring(s, m+1, 1) == " ") // skip spaces
400 for(i = 1; ; ++i) // 20 modes ought to be enough for anyone
402 t = GametypeNameFromType(i);
404 if(t == GametypeNameFromType(0)) // it repeats (default case)
407 // choose the first one
411 if(s == GametypeNameFromType(i))
413 // the type was found
414 // choose the next one
415 s = GametypeNameFromType(i + 1);
416 if(s == GametypeNameFromType(0))
424 s = strcat(s, substring(me.filterString, m+1, strlen(me.filterString) - m - 1));
426 me.controlledTextbox.setText(me.controlledTextbox, s);
427 me.controlledTextbox.keyDown(me.controlledTextbox, K_END, 0, 0);
428 me.controlledTextbox.keyUp(me.controlledTextbox, K_END, 0, 0);
429 //ServerList_Filter_Change(me.controlledTextbox, me);
431 void ServerList_Filter_Change(entity box, entity me)
434 strunzone(me.filterString);
436 me.filterString = strzone(box.text);
438 me.filterString = string_null;
439 me.refreshServerList(me, 0);
441 me.ipAddressBox.setText(me.ipAddressBox, "");
442 me.ipAddressBox.cursorPos = 0;
443 me.ipAddressBoxFocused = -1;
445 void ServerList_ShowEmpty_Click(entity box, entity me)
447 box.setChecked(box, me.filterShowEmpty = !me.filterShowEmpty);
448 me.refreshServerList(me, 0);
450 me.ipAddressBox.setText(me.ipAddressBox, "");
451 me.ipAddressBox.cursorPos = 0;
452 me.ipAddressBoxFocused = -1;
454 void ServerList_ShowFull_Click(entity box, entity me)
456 box.setChecked(box, me.filterShowFull = !me.filterShowFull);
457 me.refreshServerList(me, 0);
459 me.ipAddressBox.setText(me.ipAddressBox, "");
460 me.ipAddressBox.cursorPos = 0;
461 me.ipAddressBoxFocused = -1;
463 void XonoticServerList_setSortOrder(entity me, float field, float direction)
465 if(me.currentSortField == field)
466 direction = -me.currentSortOrder;
467 me.currentSortOrder = direction;
468 me.currentSortField = field;
469 me.sortButton1.forcePressed = (field == SLIST_FIELD_PING);
470 me.sortButton2.forcePressed = (field == SLIST_FIELD_NAME);
471 me.sortButton3.forcePressed = (field == SLIST_FIELD_MAP);
472 me.sortButton4.forcePressed = 0;
473 me.sortButton5.forcePressed = (field == SLIST_FIELD_NUMHUMANS);
475 if(me.selectedServer)
476 strunzone(me.selectedServer);
477 me.selectedServer = string_null;
478 me.refreshServerList(me, 0);
480 void XonoticServerList_positionSortButton(entity me, entity btn, float theOrigin, float theSize, string theTitle, void(entity, entity) theFunc)
482 vector originInLBSpace, sizeInLBSpace;
483 originInLBSpace = eY * (-me.itemHeight);
484 sizeInLBSpace = eY * me.itemHeight + eX * (1 - me.controlWidth);
486 vector originInDialogSpace, sizeInDialogSpace;
487 originInDialogSpace = boxToGlobal(originInLBSpace, me.Container_origin, me.Container_size);
488 sizeInDialogSpace = boxToGlobalSize(sizeInLBSpace, me.Container_size);
490 btn.Container_origin_x = originInDialogSpace_x + sizeInDialogSpace_x * theOrigin;
491 btn.Container_size_x = sizeInDialogSpace_x * theSize;
492 btn.setText(btn, theTitle);
493 btn.onClick = theFunc;
494 btn.onClickEntity = me;
497 void XonoticServerList_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
499 SUPER(XonoticServerList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
501 me.realFontSize_y = me.fontSize / (absSize_y * me.itemHeight);
502 me.realFontSize_x = me.fontSize / (absSize_x * (1 - me.controlWidth));
503 me.realUpperMargin = 0.5 * (1 - me.realFontSize_y);
505 me.columnIconsOrigin = 0;
506 me.columnIconsSize = me.realFontSize_x * 3 * me.iconsSizeFactor;
507 me.columnPingSize = me.realFontSize_x * 3;
508 me.columnMapSize = me.realFontSize_x * 10;
509 me.columnTypeSize = me.realFontSize_x * 4;
510 me.columnPlayersSize = me.realFontSize_x * 5;
511 me.columnNameSize = 1 - me.columnPlayersSize - me.columnMapSize - me.columnPingSize - me.columnIconsSize - me.columnTypeSize - 5 * me.realFontSize_x;
512 me.columnPingOrigin = me.columnIconsOrigin + me.columnIconsSize + me.realFontSize_x;
513 me.columnNameOrigin = me.columnPingOrigin + me.columnPingSize + me.realFontSize_x;
514 me.columnMapOrigin = me.columnNameOrigin + me.columnNameSize + me.realFontSize_x;
515 me.columnTypeOrigin = me.columnMapOrigin + me.columnMapSize + me.realFontSize_x;
516 me.columnPlayersOrigin = me.columnTypeOrigin + me.columnTypeSize + me.realFontSize_x;
518 me.positionSortButton(me, me.sortButton1, me.columnPingOrigin, me.columnPingSize, _("Ping"), ServerList_PingSort_Click);
519 me.positionSortButton(me, me.sortButton2, me.columnNameOrigin, me.columnNameSize, _("Host name"), ServerList_NameSort_Click);
520 me.positionSortButton(me, me.sortButton3, me.columnMapOrigin, me.columnMapSize, _("Map"), ServerList_MapSort_Click);
521 me.positionSortButton(me, me.sortButton4, me.columnTypeOrigin, me.columnTypeSize, _("Type"), ServerList_TypeSort_Click);
522 me.positionSortButton(me, me.sortButton5, me.columnPlayersOrigin, me.columnPlayersSize, _("Players"), ServerList_PlayerSort_Click);
525 f = me.currentSortField;
528 me.currentSortField = -1;
529 me.setSortOrder(me, f, me.currentSortOrder); // force resetting the sort order
532 void ServerList_Connect_Click(entity btn, entity me)
534 if(me.ipAddressBox.text == "")
535 localcmd("connect ", me.selectedServer, "\n");
537 localcmd("connect ", me.ipAddressBox.text, "\n");
539 void ServerList_Favorite_Click(entity btn, entity me)
542 ipstr = netaddress_resolve(me.ipAddressBox.text, 26000);
545 ToggleFavorite(me.ipAddressBox.text);
546 me.ipAddressBoxFocused = -1;
549 void ServerList_Info_Click(entity btn, entity me)
551 main.serverInfoDialog.loadServerInfo(main.serverInfoDialog, me.selectedItem);
552 DialogOpenButton_Click(me, main.serverInfoDialog);
554 void XonoticServerList_clickListBoxItem(entity me, float i, vector where)
556 if(i == me.lastClickedServer)
557 if(time < me.lastClickedTime + 0.3)
560 ServerList_Connect_Click(NULL, me);
562 me.lastClickedServer = i;
563 me.lastClickedTime = time;
565 void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
567 // layout: Ping, Server name, Map name, NP, TP, MP
575 draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
577 if(gethostcachenumber(SLIST_FIELD_FREESLOTS, i) <= 0)
578 theAlpha = SKINALPHA_SERVERLIST_FULL;
579 else if(strstrofs(gethostcachestring(SLIST_FIELD_QCSTATUS, i), ":S0:", 0) >= 0)
580 theAlpha = SKINALPHA_SERVERLIST_FULL; // g_maxplayers support
581 else if not(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i))
582 theAlpha = SKINALPHA_SERVERLIST_EMPTY;
586 p = gethostcachenumber(SLIST_FIELD_PING, i);
589 #define PING_HIGH 500
591 theColor = SKINCOLOR_SERVERLIST_LOWPING + (SKINCOLOR_SERVERLIST_MEDPING - SKINCOLOR_SERVERLIST_LOWPING) * (p / PING_LOW);
592 else if(p < PING_MED)
593 theColor = SKINCOLOR_SERVERLIST_MEDPING + (SKINCOLOR_SERVERLIST_HIGHPING - SKINCOLOR_SERVERLIST_MEDPING) * ((p - PING_LOW) / (PING_MED - PING_LOW));
594 else if(p < PING_HIGH)
596 theColor = SKINCOLOR_SERVERLIST_HIGHPING;
597 theAlpha *= 1 + (SKINALPHA_SERVERLIST_HIGHPING - 1) * ((p - PING_MED) / (PING_HIGH - PING_MED));
602 theAlpha *= SKINALPHA_SERVERLIST_HIGHPING;
605 if(gethostcachenumber(SLIST_FIELD_ISFAVORITE, i))
607 theColor = theColor * (1 - SKINALPHA_SERVERLIST_FAVORITE) + SKINCOLOR_SERVERLIST_FAVORITE * SKINALPHA_SERVERLIST_FAVORITE;
608 theAlpha = theAlpha * (1 - SKINALPHA_SERVERLIST_FAVORITE) + SKINALPHA_SERVERLIST_FAVORITE;
611 s = gethostcachestring(SLIST_FIELD_CNAME, i);
614 if(substring(s, 0, 1) == "[")
619 else if(strstrofs("0123456789", substring(s, 0, 1), 0) >= 0)
625 q = stof(substring(crypto_getencryptlevel(s), 0, 1));
626 if((q <= 0 && cvar("crypto_aeslevel") >= 3) || (q >= 3 && cvar("crypto_aeslevel") <= 0))
628 theColor = SKINCOLOR_SERVERLIST_IMPOSSIBLE;
629 theAlpha = SKINALPHA_SERVERLIST_IMPOSSIBLE;
634 if(cvar("crypto_aeslevel") >= 2)
639 if(cvar("crypto_aeslevel") >= 1)
649 // 2: AES recommended but not available
650 // 3: AES possible and will be used
651 // 4: AES recommended and will be used
654 s = gethostcachestring(SLIST_FIELD_QCSTATUS, i);
657 iconSize_y = me.realFontSize_y * me.iconsSizeFactor;
658 iconSize_x = me.realFontSize_x * me.iconsSizeFactor;
661 iconPos_x = (me.columnIconsSize - 3 * iconSize_x) * 0.5;
662 iconPos_y = (1 - iconSize_y) * 0.5;
664 if not(me.seenIPv4 && me.seenIPv6)
666 iconPos_x += iconSize_x * 0.5;
668 else if(me.seenIPv4 && me.seenIPv6)
671 draw_Picture(iconPos, strcat(SKINGFX_SERVERLIST_ICON, "_ipv6"), iconSize, '1 1 1', 1);
673 draw_Picture(iconPos, strcat(SKINGFX_SERVERLIST_ICON, "_ipv4"), iconSize, '1 1 1', 1);
674 iconPos_x += iconSize_x;
677 draw_Picture(iconPos, strcat(SKINGFX_SERVERLIST_ICON, "_aeslevel", ftos(q)), iconSize, '1 1 1', 1);
678 iconPos_x += iconSize_x;
680 draw_Picture(iconPos, strcat(SKINGFX_SERVERLIST_ICON, "_pure", ftos(strstrofs(s, ":P0:", 0) >= 0)), iconSize, '1 1 1', 1);
681 iconPos_x += iconSize_x;
685 draw_Text(me.realUpperMargin * eY + (me.columnPingOrigin + me.columnPingSize - draw_TextWidth(s, 0, me.realFontSize)) * eX, s, me.realFontSize, theColor, theAlpha, 0);
686 s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_NAME, i), me.columnNameSize, 0, me.realFontSize);
687 draw_Text(me.realUpperMargin * eY + me.columnNameOrigin * eX, s, me.realFontSize, theColor, theAlpha, 0);
688 s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_MAP, i), me.columnMapSize, 0, me.realFontSize);
689 draw_Text(me.realUpperMargin * eY + (me.columnMapOrigin + (me.columnMapSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0);
690 s = gethostcachestring(SLIST_FIELD_QCSTATUS, i);
691 p = strstrofs(s, ":", 0);
693 s = substring(s, 0, p);
696 s = draw_TextShortenToWidth(s, me.columnMapSize, 0, me.realFontSize);
697 draw_Text(me.realUpperMargin * eY + (me.columnTypeOrigin + (me.columnTypeSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0);
698 s = strcat(ftos(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i)), "/", ftos(gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i)));
699 draw_Text(me.realUpperMargin * eY + (me.columnPlayersOrigin + (me.columnPlayersSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0);
702 float XonoticServerList_keyDown(entity me, float scan, float ascii, float shift)
707 org = boxToGlobal(eY * (me.selectedItem * me.itemHeight - me.scrollPos), me.origin, me.size);
708 sz = boxToGlobalSize(eY * me.itemHeight + eX * (1 - me.controlWidth), me.size);
710 if(scan == K_ENTER || scan == K_KP_ENTER)
712 ServerList_Connect_Click(NULL, me);
715 else if(scan == K_MOUSE2 || scan == K_SPACE)
719 main.serverInfoDialog.loadServerInfo(main.serverInfoDialog, me.selectedItem);
720 DialogOpenButton_Click_withCoords(me, main.serverInfoDialog, org, sz);
723 else if(scan == K_INS || scan == K_MOUSE3 || scan == K_KP_INS)
728 ToggleFavorite(me.selectedServer);
729 me.ipAddressBoxFocused = -1;
732 else if(SUPER(XonoticServerList).keyDown(me, scan, ascii, shift))
734 else if(!me.controlledTextbox)
737 return me.controlledTextbox.keyDown(me.controlledTextbox, scan, ascii, shift);