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);
319 me.favoriteButton.disabled = ((me.nItems == 0) && (me.ipAddressBox.text == ""));
322 if(me.selectedServer)
324 for(i = 0; i < me.nItems; ++i)
325 if(gethostcachestring(SLIST_FIELD_CNAME, i) == me.selectedServer)
327 if(i != me.selectedItem)
329 me.lastClickedServer = -1;
339 if(me.selectedItem >= me.nItems)
340 me.selectedItem = me.nItems - 1;
341 if(me.selectedServer)
342 strunzone(me.selectedServer);
343 me.selectedServer = strzone(gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
348 if(me.selectedServer != me.ipAddressBox.text)
350 me.ipAddressBox.setText(me.ipAddressBox, me.selectedServer);
351 me.ipAddressBox.cursorPos = strlen(me.selectedServer);
352 me.ipAddressBoxFocused = -1;
356 if(me.ipAddressBoxFocused != me.ipAddressBox.focused)
358 if(me.ipAddressBox.focused || me.ipAddressBoxFocused < 0)
360 if(IsFavorite(me.ipAddressBox.text))
361 me.favoriteButton.setText(me.favoriteButton, _("Remove"));
363 me.favoriteButton.setText(me.favoriteButton, _("Bookmark"));
365 me.ipAddressBoxFocused = me.ipAddressBox.focused;
368 SUPER(XonoticServerList).draw(me);
370 void ServerList_PingSort_Click(entity btn, entity me)
372 me.setSortOrder(me, SLIST_FIELD_PING, +1);
374 void ServerList_NameSort_Click(entity btn, entity me)
376 me.setSortOrder(me, SLIST_FIELD_NAME, -1); // why?
378 void ServerList_MapSort_Click(entity btn, entity me)
380 me.setSortOrder(me, SLIST_FIELD_MAP, -1); // why?
382 void ServerList_PlayerSort_Click(entity btn, entity me)
384 me.setSortOrder(me, SLIST_FIELD_NUMHUMANS, -1);
386 void ServerList_TypeSort_Click(entity btn, entity me)
391 m = strstrofs(s, ":", 0);
394 s = substring(s, 0, m);
395 while(substring(s, m+1, 1) == " ") // skip spaces
401 for(i = 1; ; ++i) // 20 modes ought to be enough for anyone
403 t = GametypeNameFromType(i);
405 if(t == GametypeNameFromType(0)) // it repeats (default case)
408 // choose the first one
412 if(s == GametypeNameFromType(i))
414 // the type was found
415 // choose the next one
416 s = GametypeNameFromType(i + 1);
417 if(s == GametypeNameFromType(0))
425 s = strcat(s, substring(me.filterString, m+1, strlen(me.filterString) - m - 1));
427 me.controlledTextbox.setText(me.controlledTextbox, s);
428 me.controlledTextbox.keyDown(me.controlledTextbox, K_END, 0, 0);
429 me.controlledTextbox.keyUp(me.controlledTextbox, K_END, 0, 0);
430 //ServerList_Filter_Change(me.controlledTextbox, me);
432 void ServerList_Filter_Change(entity box, entity me)
435 strunzone(me.filterString);
437 me.filterString = strzone(box.text);
439 me.filterString = string_null;
440 me.refreshServerList(me, 0);
442 me.ipAddressBox.setText(me.ipAddressBox, "");
443 me.ipAddressBox.cursorPos = 0;
444 me.ipAddressBoxFocused = -1;
446 void ServerList_ShowEmpty_Click(entity box, entity me)
448 box.setChecked(box, me.filterShowEmpty = !me.filterShowEmpty);
449 me.refreshServerList(me, 0);
451 me.ipAddressBox.setText(me.ipAddressBox, "");
452 me.ipAddressBox.cursorPos = 0;
453 me.ipAddressBoxFocused = -1;
455 void ServerList_ShowFull_Click(entity box, entity me)
457 box.setChecked(box, me.filterShowFull = !me.filterShowFull);
458 me.refreshServerList(me, 0);
460 me.ipAddressBox.setText(me.ipAddressBox, "");
461 me.ipAddressBox.cursorPos = 0;
462 me.ipAddressBoxFocused = -1;
464 void XonoticServerList_setSortOrder(entity me, float field, float direction)
466 if(me.currentSortField == field)
467 direction = -me.currentSortOrder;
468 me.currentSortOrder = direction;
469 me.currentSortField = field;
470 me.sortButton1.forcePressed = (field == SLIST_FIELD_PING);
471 me.sortButton2.forcePressed = (field == SLIST_FIELD_NAME);
472 me.sortButton3.forcePressed = (field == SLIST_FIELD_MAP);
473 me.sortButton4.forcePressed = 0;
474 me.sortButton5.forcePressed = (field == SLIST_FIELD_NUMHUMANS);
476 if(me.selectedServer)
477 strunzone(me.selectedServer);
478 me.selectedServer = string_null;
479 me.refreshServerList(me, 0);
481 void XonoticServerList_positionSortButton(entity me, entity btn, float theOrigin, float theSize, string theTitle, void(entity, entity) theFunc)
483 vector originInLBSpace, sizeInLBSpace;
484 originInLBSpace = eY * (-me.itemHeight);
485 sizeInLBSpace = eY * me.itemHeight + eX * (1 - me.controlWidth);
487 vector originInDialogSpace, sizeInDialogSpace;
488 originInDialogSpace = boxToGlobal(originInLBSpace, me.Container_origin, me.Container_size);
489 sizeInDialogSpace = boxToGlobalSize(sizeInLBSpace, me.Container_size);
491 btn.Container_origin_x = originInDialogSpace_x + sizeInDialogSpace_x * theOrigin;
492 btn.Container_size_x = sizeInDialogSpace_x * theSize;
493 btn.setText(btn, theTitle);
494 btn.onClick = theFunc;
495 btn.onClickEntity = me;
498 void XonoticServerList_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
500 SUPER(XonoticServerList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
502 me.realFontSize_y = me.fontSize / (absSize_y * me.itemHeight);
503 me.realFontSize_x = me.fontSize / (absSize_x * (1 - me.controlWidth));
504 me.realUpperMargin = 0.5 * (1 - me.realFontSize_y);
506 me.columnIconsOrigin = 0;
507 me.columnIconsSize = me.realFontSize_x * 3 * me.iconsSizeFactor;
508 me.columnPingSize = me.realFontSize_x * 3;
509 me.columnMapSize = me.realFontSize_x * 10;
510 me.columnTypeSize = me.realFontSize_x * 4;
511 me.columnPlayersSize = me.realFontSize_x * 5;
512 me.columnNameSize = 1 - me.columnPlayersSize - me.columnMapSize - me.columnPingSize - me.columnIconsSize - me.columnTypeSize - 5 * me.realFontSize_x;
513 me.columnPingOrigin = me.columnIconsOrigin + me.columnIconsSize + me.realFontSize_x;
514 me.columnNameOrigin = me.columnPingOrigin + me.columnPingSize + me.realFontSize_x;
515 me.columnMapOrigin = me.columnNameOrigin + me.columnNameSize + me.realFontSize_x;
516 me.columnTypeOrigin = me.columnMapOrigin + me.columnMapSize + me.realFontSize_x;
517 me.columnPlayersOrigin = me.columnTypeOrigin + me.columnTypeSize + me.realFontSize_x;
519 me.positionSortButton(me, me.sortButton1, me.columnPingOrigin, me.columnPingSize, _("Ping"), ServerList_PingSort_Click);
520 me.positionSortButton(me, me.sortButton2, me.columnNameOrigin, me.columnNameSize, _("Host name"), ServerList_NameSort_Click);
521 me.positionSortButton(me, me.sortButton3, me.columnMapOrigin, me.columnMapSize, _("Map"), ServerList_MapSort_Click);
522 me.positionSortButton(me, me.sortButton4, me.columnTypeOrigin, me.columnTypeSize, _("Type"), ServerList_TypeSort_Click);
523 me.positionSortButton(me, me.sortButton5, me.columnPlayersOrigin, me.columnPlayersSize, _("Players"), ServerList_PlayerSort_Click);
526 f = me.currentSortField;
529 me.currentSortField = -1;
530 me.setSortOrder(me, f, me.currentSortOrder); // force resetting the sort order
533 void ServerList_Connect_Click(entity btn, entity me)
535 if(me.ipAddressBox.text == "")
536 localcmd("connect ", me.selectedServer, "\n");
538 localcmd("connect ", me.ipAddressBox.text, "\n");
540 void ServerList_Favorite_Click(entity btn, entity me)
543 ipstr = netaddress_resolve(me.ipAddressBox.text, 26000);
546 ToggleFavorite(me.ipAddressBox.text);
547 me.ipAddressBoxFocused = -1;
550 void ServerList_Info_Click(entity btn, entity me)
552 main.serverInfoDialog.loadServerInfo(main.serverInfoDialog, me.selectedItem);
553 DialogOpenButton_Click(me, main.serverInfoDialog);
555 void XonoticServerList_clickListBoxItem(entity me, float i, vector where)
557 if(i == me.lastClickedServer)
558 if(time < me.lastClickedTime + 0.3)
561 ServerList_Connect_Click(NULL, me);
563 me.lastClickedServer = i;
564 me.lastClickedTime = time;
566 void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
568 // layout: Ping, Server name, Map name, NP, TP, MP
576 draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
578 if(gethostcachenumber(SLIST_FIELD_FREESLOTS, i) <= 0)
579 theAlpha = SKINALPHA_SERVERLIST_FULL;
580 else if(strstrofs(gethostcachestring(SLIST_FIELD_QCSTATUS, i), ":S0:", 0) >= 0)
581 theAlpha = SKINALPHA_SERVERLIST_FULL; // g_maxplayers support
582 else if not(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i))
583 theAlpha = SKINALPHA_SERVERLIST_EMPTY;
587 p = gethostcachenumber(SLIST_FIELD_PING, i);
590 #define PING_HIGH 500
592 theColor = SKINCOLOR_SERVERLIST_LOWPING + (SKINCOLOR_SERVERLIST_MEDPING - SKINCOLOR_SERVERLIST_LOWPING) * (p / PING_LOW);
593 else if(p < PING_MED)
594 theColor = SKINCOLOR_SERVERLIST_MEDPING + (SKINCOLOR_SERVERLIST_HIGHPING - SKINCOLOR_SERVERLIST_MEDPING) * ((p - PING_LOW) / (PING_MED - PING_LOW));
595 else if(p < PING_HIGH)
597 theColor = SKINCOLOR_SERVERLIST_HIGHPING;
598 theAlpha *= 1 + (SKINALPHA_SERVERLIST_HIGHPING - 1) * ((p - PING_MED) / (PING_HIGH - PING_MED));
603 theAlpha *= SKINALPHA_SERVERLIST_HIGHPING;
606 if(gethostcachenumber(SLIST_FIELD_ISFAVORITE, i))
608 theColor = theColor * (1 - SKINALPHA_SERVERLIST_FAVORITE) + SKINCOLOR_SERVERLIST_FAVORITE * SKINALPHA_SERVERLIST_FAVORITE;
609 theAlpha = theAlpha * (1 - SKINALPHA_SERVERLIST_FAVORITE) + SKINALPHA_SERVERLIST_FAVORITE;
612 s = gethostcachestring(SLIST_FIELD_CNAME, i);
615 if(substring(s, 0, 1) == "[")
620 else if(strstrofs("0123456789", substring(s, 0, 1), 0) >= 0)
626 q = stof(substring(crypto_getencryptlevel(s), 0, 1));
627 if((q <= 0 && cvar("crypto_aeslevel") >= 3) || (q >= 3 && cvar("crypto_aeslevel") <= 0))
629 theColor = SKINCOLOR_SERVERLIST_IMPOSSIBLE;
630 theAlpha = SKINALPHA_SERVERLIST_IMPOSSIBLE;
635 if(cvar("crypto_aeslevel") >= 2)
640 if(cvar("crypto_aeslevel") >= 1)
650 // 2: AES recommended but not available
651 // 3: AES possible and will be used
652 // 4: AES recommended and will be used
655 s = gethostcachestring(SLIST_FIELD_QCSTATUS, i);
658 iconSize_y = me.realFontSize_y * me.iconsSizeFactor;
659 iconSize_x = me.realFontSize_x * me.iconsSizeFactor;
662 iconPos_x = (me.columnIconsSize - 3 * iconSize_x) * 0.5;
663 iconPos_y = (1 - iconSize_y) * 0.5;
665 if not(me.seenIPv4 && me.seenIPv6)
667 iconPos_x += iconSize_x * 0.5;
669 else if(me.seenIPv4 && me.seenIPv6)
672 draw_Picture(iconPos, strcat(SKINGFX_SERVERLIST_ICON, "_ipv6"), iconSize, '1 1 1', 1);
674 draw_Picture(iconPos, strcat(SKINGFX_SERVERLIST_ICON, "_ipv4"), iconSize, '1 1 1', 1);
675 iconPos_x += iconSize_x;
678 draw_Picture(iconPos, strcat(SKINGFX_SERVERLIST_ICON, "_aeslevel", ftos(q)), iconSize, '1 1 1', 1);
679 iconPos_x += iconSize_x;
681 draw_Picture(iconPos, strcat(SKINGFX_SERVERLIST_ICON, "_pure", ftos(strstrofs(s, ":P0:", 0) >= 0)), iconSize, '1 1 1', 1);
682 iconPos_x += iconSize_x;
686 draw_Text(me.realUpperMargin * eY + (me.columnPingOrigin + me.columnPingSize - draw_TextWidth(s, 0, me.realFontSize)) * eX, s, me.realFontSize, theColor, theAlpha, 0);
687 s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_NAME, i), me.columnNameSize, 0, me.realFontSize);
688 draw_Text(me.realUpperMargin * eY + me.columnNameOrigin * eX, s, me.realFontSize, theColor, theAlpha, 0);
689 s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_MAP, i), me.columnMapSize, 0, me.realFontSize);
690 draw_Text(me.realUpperMargin * eY + (me.columnMapOrigin + (me.columnMapSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0);
691 s = gethostcachestring(SLIST_FIELD_QCSTATUS, i);
692 p = strstrofs(s, ":", 0);
694 s = substring(s, 0, p);
697 s = draw_TextShortenToWidth(s, me.columnMapSize, 0, me.realFontSize);
698 draw_Text(me.realUpperMargin * eY + (me.columnTypeOrigin + (me.columnTypeSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0);
699 s = strcat(ftos(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i)), "/", ftos(gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i)));
700 draw_Text(me.realUpperMargin * eY + (me.columnPlayersOrigin + (me.columnPlayersSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0);
703 float XonoticServerList_keyDown(entity me, float scan, float ascii, float shift)
708 org = boxToGlobal(eY * (me.selectedItem * me.itemHeight - me.scrollPos), me.origin, me.size);
709 sz = boxToGlobalSize(eY * me.itemHeight + eX * (1 - me.controlWidth), me.size);
711 if(scan == K_ENTER || scan == K_KP_ENTER)
713 ServerList_Connect_Click(NULL, me);
716 else if(scan == K_MOUSE2 || scan == K_SPACE)
720 main.serverInfoDialog.loadServerInfo(main.serverInfoDialog, me.selectedItem);
721 DialogOpenButton_Click_withCoords(me, main.serverInfoDialog, org, sz);
724 else if(scan == K_INS || scan == K_MOUSE3 || scan == K_KP_INS)
729 ToggleFavorite(me.selectedServer);
730 me.ipAddressBoxFocused = -1;
733 else if(SUPER(XonoticServerList).keyDown(me, scan, ascii, shift))
735 else if(!me.controlledTextbox)
738 return me.controlledTextbox.keyDown(me.controlledTextbox, scan, ascii, shift);