2 CLASS(NexuizServerList) EXTENDS(NexuizListBox)
3 METHOD(NexuizServerList, configureNexuizServerList, void(entity))
4 ATTRIB(NexuizServerList, rowsPerItem, float, 1)
5 METHOD(NexuizServerList, draw, void(entity))
6 METHOD(NexuizServerList, drawListBoxItem, void(entity, float, vector, float))
7 METHOD(NexuizServerList, clickListBoxItem, void(entity, float, vector))
8 METHOD(NexuizServerList, resizeNotify, void(entity, vector, vector, vector, vector))
9 METHOD(NexuizServerList, keyDown, float(entity, float, float, float))
11 ATTRIB(NexuizServerList, realFontSize, vector, '0 0 0')
12 ATTRIB(NexuizServerList, realUpperMargin, float, 0)
13 ATTRIB(NexuizServerList, columnPingOrigin, float, 0)
14 ATTRIB(NexuizServerList, columnPingSize, float, 0)
15 ATTRIB(NexuizServerList, columnNameOrigin, float, 0)
16 ATTRIB(NexuizServerList, columnNameSize, float, 0)
17 ATTRIB(NexuizServerList, columnMapOrigin, float, 0)
18 ATTRIB(NexuizServerList, columnMapSize, float, 0)
19 ATTRIB(NexuizServerList, columnPlayersOrigin, float, 0)
20 ATTRIB(NexuizServerList, columnPlayersSize, float, 0)
22 ATTRIB(NexuizServerList, selectedServer, string, string_null) // to restore selected server when needed
23 METHOD(NexuizServerList, setSelected, void(entity, float))
24 METHOD(NexuizServerList, setSortOrder, void(entity, float, float))
25 ATTRIB(NexuizServerList, filterShowEmpty, float, 1)
26 ATTRIB(NexuizServerList, filterShowFull, float, 1)
27 ATTRIB(NexuizServerList, filterString, string, string_null)
28 ATTRIB(NexuizServerList, nextRefreshTime, float, 0)
29 METHOD(NexuizServerList, refreshServerList, void(entity, float)) // refresh mode: 0 = just reparametrize, 1 = send new requests, 2 = clear
30 ATTRIB(NexuizServerList, needsRefresh, float, 1)
31 METHOD(NexuizServerList, focusEnter, void(entity))
32 METHOD(NexuizServerList, positionSortButton, void(entity, entity, float, float, string, void(entity, entity)))
33 ATTRIB(NexuizServerList, sortButton1, entity, NULL)
34 ATTRIB(NexuizServerList, sortButton2, entity, NULL)
35 ATTRIB(NexuizServerList, sortButton3, entity, NULL)
36 ATTRIB(NexuizServerList, sortButton4, entity, NULL)
37 ATTRIB(NexuizServerList, connectButton, entity, NULL)
38 ATTRIB(NexuizServerList, currentSortOrder, float, 0)
39 ATTRIB(NexuizServerList, currentSortField, float, -1)
40 ATTRIB(NexuizServerList, lastClickedServer, float, -1)
41 ATTRIB(NexuizServerList, lastClickedTime, float, 0)
42 ENDCLASS(NexuizServerList)
43 entity makeNexuizServerList();
44 void ServerList_Connect_Click(entity btn, entity me);
45 void ServerList_ShowEmpty_Click(entity box, entity me);
46 void ServerList_ShowFull_Click(entity box, entity me);
47 void ServerList_Filter_Change(entity box, entity me);
51 float SLIST_FIELD_CNAME;
52 float SLIST_FIELD_PING;
53 float SLIST_FIELD_GAME;
54 float SLIST_FIELD_MOD;
55 float SLIST_FIELD_MAP;
56 float SLIST_FIELD_NAME;
57 float SLIST_FIELD_MAXPLAYERS;
58 float SLIST_FIELD_NUMPLAYERS;
59 float SLIST_FIELD_NUMHUMANS;
60 float SLIST_FIELD_NUMBOTS;
61 float SLIST_FIELD_PROTOCOL;
62 float SLIST_FIELD_FREESLOTS;
63 void ServerList_UpdateFieldIDs()
65 SLIST_FIELD_CNAME = gethostcacheindexforkey( "cname" );
66 SLIST_FIELD_PING = gethostcacheindexforkey( "ping" );
67 SLIST_FIELD_GAME = gethostcacheindexforkey( "game" );
68 SLIST_FIELD_MOD = gethostcacheindexforkey( "mod" );
69 SLIST_FIELD_MAP = gethostcacheindexforkey( "map" );
70 SLIST_FIELD_NAME = gethostcacheindexforkey( "name" );
71 SLIST_FIELD_MAXPLAYERS = gethostcacheindexforkey( "maxplayers" );
72 SLIST_FIELD_NUMPLAYERS = gethostcacheindexforkey( "numplayers" );
73 SLIST_FIELD_NUMHUMANS = gethostcacheindexforkey( "numhumans" );
74 SLIST_FIELD_NUMBOTS = gethostcacheindexforkey( "numbots" );
75 SLIST_FIELD_PROTOCOL = gethostcacheindexforkey( "protocol" );
76 SLIST_FIELD_FREESLOTS = gethostcacheindexforkey( "freeslots" );
79 entity makeNexuizServerList()
82 me = spawnNexuizServerList();
83 me.configureNexuizServerList(me);
86 void configureNexuizServerListNexuizServerList(entity me)
88 me.configureNexuizListBox(me);
90 ServerList_UpdateFieldIDs();
94 void setSelectedNexuizServerList(entity me, float i)
97 save = me.selectedItem;
98 setSelectedListBox(me, i);
100 if(me.selectedItem == save)
105 if(gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT) != me.nItems)
106 return; // sorry, it would be wrong
107 if(me.selectedServer)
108 strunzone(me.selectedServer);
109 me.selectedServer = strzone(gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
111 void refreshServerListNexuizServerList(entity me, float mode)
113 // 0: just reparametrize
114 // 1: also ask for new servers
116 //print("refresh of type ", ftos(mode), "\n");
117 /* if(mode == 2) // borken
120 localcmd("net_slist\n");
121 me.needsRefresh = 1; // net_slist kills sort order, so we need to restore it later
127 resethostcachemasks();
128 if(!me.filterShowFull)
129 sethostcachemasknumber(m++, SLIST_FIELD_FREESLOTS, 1, SLIST_TEST_GREATEREQUAL);
130 if(!me.filterShowEmpty)
131 sethostcachemasknumber(m++, SLIST_FIELD_NUMHUMANS, 1, SLIST_TEST_GREATEREQUAL);
135 sethostcachemaskstring(m++, SLIST_FIELD_NAME, me.filterString, SLIST_TEST_CONTAINS);
136 sethostcachemaskstring(m++, SLIST_FIELD_MAP, me.filterString, SLIST_TEST_CONTAINS);
138 sethostcachesort(me.currentSortField, me.currentSortOrder < 0);
144 void focusEnterNexuizServerList(entity me)
146 if(time < me.nextRefreshTime)
148 //print("sorry, no refresh yet\n");
151 me.nextRefreshTime = time + 10;
152 me.refreshServerList(me, 1);
154 void drawNexuizServerList(entity me)
158 if(me.currentSortField == -1)
160 me.setSortOrder(me, SLIST_FIELD_PING, +1);
161 me.refreshServerList(me, 2);
163 else if(me.needsRefresh == 1)
165 me.needsRefresh = 2; // delay by one frame to make sure "slist" has been executed
167 else if(me.needsRefresh == 2)
170 me.refreshServerList(me, 0);
173 me.nItems = gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT);
174 me.connectButton.disabled = (me.nItems == 0);
177 if(me.selectedServer)
179 for(i = 0; i < me.nItems; ++i)
180 if(gethostcachestring(SLIST_FIELD_CNAME, i) == me.selectedServer)
182 if(i != me.selectedItem)
184 me.lastClickedServer = -1;
194 if(me.selectedItem >= me.nItems)
195 me.selectedItem = me.nItems - 1;
196 if(me.selectedServer)
197 strunzone(me.selectedServer);
198 me.selectedServer = strzone(gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
203 void ServerList_PingSort_Click(entity btn, entity me)
205 me.setSortOrder(me, SLIST_FIELD_PING, +1);
207 void ServerList_NameSort_Click(entity btn, entity me)
209 me.setSortOrder(me, SLIST_FIELD_NAME, -1); // why?
211 void ServerList_MapSort_Click(entity btn, entity me)
213 me.setSortOrder(me, SLIST_FIELD_MAP, -1); // why?
215 void ServerList_PlayerSort_Click(entity btn, entity me)
217 me.setSortOrder(me, SLIST_FIELD_NUMHUMANS, -1);
219 void ServerList_Filter_Change(entity box, entity me)
222 strunzone(me.filterString);
224 me.filterString = strzone(box.text);
226 me.filterString = string_null;
227 me.refreshServerList(me, 0);
229 void ServerList_ShowEmpty_Click(entity box, entity me)
231 box.checked = me.filterShowEmpty = !me.filterShowEmpty;
232 me.refreshServerList(me, 0);
234 void ServerList_ShowFull_Click(entity box, entity me)
236 box.checked = me.filterShowFull = !me.filterShowFull;
237 me.refreshServerList(me, 0);
239 void setSortOrderNexuizServerList(entity me, float field, float direction)
241 if(me.currentSortField == field)
242 direction = -me.currentSortOrder;
243 me.currentSortOrder = direction;
244 me.currentSortField = field;
245 me.sortButton1.forcePressed = (field == SLIST_FIELD_PING);
246 me.sortButton2.forcePressed = (field == SLIST_FIELD_NAME);
247 me.sortButton3.forcePressed = (field == SLIST_FIELD_MAP);
248 me.sortButton4.forcePressed = (field == SLIST_FIELD_NUMHUMANS);
250 if(me.selectedServer)
251 strunzone(me.selectedServer);
252 me.selectedServer = string_null;
253 me.refreshServerList(me, 0);
255 void positionSortButtonNexuizServerList(entity me, entity btn, float theOrigin, float theSize, string theTitle, void(entity, entity) theFunc)
257 vector originInLBSpace, sizeInLBSpace;
258 originInLBSpace = eY * (-me.itemHeight);
259 sizeInLBSpace = eY * me.itemHeight + eX * (1 - me.controlWidth);
261 vector originInDialogSpace, sizeInDialogSpace;
262 originInDialogSpace = boxToGlobal(originInLBSpace, me.Container_origin, me.Container_size);
263 sizeInDialogSpace = boxToGlobalSize(sizeInLBSpace, me.Container_size);
265 btn.Container_origin_x = originInDialogSpace_x + sizeInDialogSpace_x * theOrigin;
266 btn.Container_size_x = sizeInDialogSpace_x * theSize;
267 btn.setText(btn, theTitle);
268 btn.onClick = theFunc;
269 btn.onClickEntity = me;
272 void resizeNotifyNexuizServerList(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
274 resizeNotifyNexuizListBox(me, relOrigin, relSize, absOrigin, absSize);
276 me.realFontSize_y = me.fontSize / (absSize_y * me.itemHeight);
277 me.realFontSize_x = me.fontSize / (absSize_x * (1 - me.controlWidth));
278 me.realUpperMargin = 0.5 * (1 - me.realFontSize_y);
280 me.columnPingOrigin = 0;
281 me.columnPingSize = me.realFontSize_x * 4;
282 me.columnMapSize = me.realFontSize_x * 12;
283 me.columnPlayersSize = me.realFontSize_x * 6;
284 me.columnNameSize = 1 - me.columnPlayersSize - me.columnMapSize - me.columnPingSize - 3 * me.realFontSize_x;
285 me.columnNameOrigin = me.columnPingOrigin + me.columnPingSize + me.realFontSize_x;
286 me.columnMapOrigin = me.columnNameOrigin + me.columnNameSize + me.realFontSize_x;
287 me.columnPlayersOrigin = me.columnMapOrigin + me.columnMapSize + me.realFontSize_x;
289 me.positionSortButton(me, me.sortButton1, me.columnPingOrigin, me.columnPingSize, "Ping", ServerList_PingSort_Click);
290 me.positionSortButton(me, me.sortButton2, me.columnNameOrigin, me.columnNameSize, "Host name", ServerList_NameSort_Click);
291 me.positionSortButton(me, me.sortButton3, me.columnMapOrigin, me.columnMapSize, "Map", ServerList_MapSort_Click);
292 me.positionSortButton(me, me.sortButton4, me.columnPlayersOrigin, me.columnPlayersSize, "Players", ServerList_PlayerSort_Click);
295 f = me.currentSortField;
298 me.currentSortField = -1;
299 me.setSortOrder(me, f, me.currentSortOrder); // force resetting the sort order
302 void ServerList_Connect_Click(entity btn, entity me)
305 localcmd("connect ", me.selectedServer, "\n");
307 void clickListBoxItemNexuizServerList(entity me, float i, vector where)
309 if(i == me.lastClickedServer)
310 if(time < me.lastClickedTime + 0.3)
313 ServerList_Connect_Click(NULL, me);
315 me.lastClickedServer = i;
316 me.lastClickedTime = time;
318 void drawListBoxItemNexuizServerList(entity me, float i, vector absSize, float isSelected)
320 // layout: Ping, Server name, Map name, NP, TP, MP
327 draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
329 if(gethostcachenumber(SLIST_FIELD_NUMPLAYERS, i) >= gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i))
330 theAlpha = SKINALPHA_SERVERLIST_FULL;
331 else if not(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i))
332 theAlpha = SKINALPHA_SERVERLIST_EMPTY;
336 p = gethostcachenumber(SLIST_FIELD_PING, i);
338 theColor = SKINCOLOR_SERVERLIST_LOWPING + (SKINCOLOR_SERVERLIST_MEDPING - SKINCOLOR_SERVERLIST_LOWPING) * (p / 50);
340 theColor = SKINCOLOR_SERVERLIST_MEDPING + (SKINCOLOR_SERVERLIST_HIGHPING - SKINCOLOR_SERVERLIST_MEDPING) * ((p - 50) / 100);
343 theColor = SKINCOLOR_SERVERLIST_HIGHPING;
344 theAlpha *= 1 + (SKINALPHA_SERVERLIST_HIGHPING - 1) * ((p - 150) / 500);
349 theAlpha *= SKINALPHA_SERVERLIST_HIGHPING;
353 draw_Text(me.realUpperMargin * eY + (me.columnPingSize - draw_TextWidth(s, 0) * me.realFontSize_x) * eX, s, me.realFontSize, theColor, theAlpha, 0);
354 s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_NAME, i), me.columnNameSize / me.realFontSize_x, 0);
355 draw_Text(me.realUpperMargin * eY + me.columnNameOrigin * eX, s, me.realFontSize, theColor, theAlpha, 0);
356 s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_MAP, i), me.columnMapSize / me.realFontSize_x, 0);
357 draw_Text(me.realUpperMargin * eY + (me.columnMapOrigin + (me.columnMapSize - draw_TextWidth(s, 0) * me.realFontSize_x) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0);
358 s = strcat(ftos(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i)), "/", ftos(gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i)));
359 draw_Text(me.realUpperMargin * eY + (me.columnPlayersOrigin + (me.columnPlayersSize - draw_TextWidth(s, 0) * me.realFontSize_x) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0);
362 float keyDownNexuizServerList(entity me, float scan, float ascii, float shift)
364 if(scan == K_ENTER || scan == K_SPACE)
365 ServerList_Connect_Click(NULL, me);
367 return keyDownListBox(me, scan, ascii, shift);