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))
10 ATTRIB(NexuizServerList, realFontSize, vector, '0 0 0')
11 ATTRIB(NexuizServerList, realUpperMargin, float, 0)
12 ATTRIB(NexuizServerList, columnPingOrigin, float, 0)
13 ATTRIB(NexuizServerList, columnPingSize, float, 0)
14 ATTRIB(NexuizServerList, columnNameOrigin, float, 0)
15 ATTRIB(NexuizServerList, columnNameSize, float, 0)
16 ATTRIB(NexuizServerList, columnMapOrigin, float, 0)
17 ATTRIB(NexuizServerList, columnMapSize, float, 0)
18 ATTRIB(NexuizServerList, columnPlayersOrigin, float, 0)
19 ATTRIB(NexuizServerList, columnPlayersSize, float, 0)
21 ATTRIB(NexuizServerList, selectedServer, string, string_null) // to restore selected server when needed
22 METHOD(NexuizServerList, setSelected, void(entity, float))
23 METHOD(NexuizServerList, setSortOrder, void(entity, float, float))
24 ATTRIB(NexuizServerList, filterShowEmpty, float, 1)
25 ATTRIB(NexuizServerList, filterShowFull, float, 1)
26 ATTRIB(NexuizServerList, filterString, string, string_null)
27 ATTRIB(NexuizServerList, nextRefreshTime, float, 0)
28 METHOD(NexuizServerList, refreshServerList, void(entity, float)) // refresh mode: 0 = just reparametrize, 1 = send new requests, 2 = clear
29 ATTRIB(NexuizServerList, needsRefresh, float, 1)
30 METHOD(NexuizServerList, focusEnter, void(entity))
31 METHOD(NexuizServerList, positionSortButton, void(entity, entity, float, float, string, void(entity, entity)))
32 ATTRIB(NexuizServerList, sortButton1, entity, NULL)
33 ATTRIB(NexuizServerList, sortButton2, entity, NULL)
34 ATTRIB(NexuizServerList, sortButton3, entity, NULL)
35 ATTRIB(NexuizServerList, sortButton4, entity, NULL)
36 ATTRIB(NexuizServerList, connectButton, entity, NULL)
37 ATTRIB(NexuizServerList, currentSortOrder, float, 0)
38 ATTRIB(NexuizServerList, currentSortField, float, -1)
39 ATTRIB(NexuizServerList, lastClickedServer, float, -1)
40 ATTRIB(NexuizServerList, lastClickedTime, float, 0)
41 ENDCLASS(NexuizServerList)
42 entity makeNexuizServerList();
43 void ServerList_Connect_Click(entity btn, entity me);
44 void ServerList_ShowEmpty_Click(entity box, entity me);
45 void ServerList_ShowFull_Click(entity box, entity me);
46 void ServerList_Filter_Change(entity box, entity me);
50 float SLIST_FIELD_CNAME;
51 float SLIST_FIELD_PING;
52 float SLIST_FIELD_GAME;
53 float SLIST_FIELD_MOD;
54 float SLIST_FIELD_MAP;
55 float SLIST_FIELD_NAME;
56 float SLIST_FIELD_MAXPLAYERS;
57 float SLIST_FIELD_NUMPLAYERS;
58 float SLIST_FIELD_NUMHUMANS;
59 float SLIST_FIELD_NUMBOTS;
60 float SLIST_FIELD_PROTOCOL;
61 float SLIST_FIELD_FREESLOTS;
62 void ServerList_UpdateFieldIDs()
64 SLIST_FIELD_CNAME = gethostcacheindexforkey( "cname" );
65 SLIST_FIELD_PING = gethostcacheindexforkey( "ping" );
66 SLIST_FIELD_GAME = gethostcacheindexforkey( "game" );
67 SLIST_FIELD_MOD = gethostcacheindexforkey( "mod" );
68 SLIST_FIELD_MAP = gethostcacheindexforkey( "map" );
69 SLIST_FIELD_NAME = gethostcacheindexforkey( "name" );
70 SLIST_FIELD_MAXPLAYERS = gethostcacheindexforkey( "maxplayers" );
71 SLIST_FIELD_NUMPLAYERS = gethostcacheindexforkey( "numplayers" );
72 SLIST_FIELD_NUMHUMANS = gethostcacheindexforkey( "numhumans" );
73 SLIST_FIELD_NUMBOTS = gethostcacheindexforkey( "numbots" );
74 SLIST_FIELD_PROTOCOL = gethostcacheindexforkey( "protocol" );
75 SLIST_FIELD_FREESLOTS = gethostcacheindexforkey( "freeslots" );
78 entity makeNexuizServerList()
81 me = spawnNexuizServerList();
82 me.configureNexuizServerList(me);
85 void configureNexuizServerListNexuizServerList(entity me)
87 me.configureNexuizListBox(me);
89 ServerList_UpdateFieldIDs();
93 void setSelectedNexuizServerList(entity me, float i)
96 save = me.selectedItem;
97 setSelectedListBox(me, i);
99 if(me.selectedItem == save)
104 if(gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT) != me.nItems)
105 return; // sorry, it would be wrong
106 if(me.selectedServer)
107 strunzone(me.selectedServer);
108 me.selectedServer = strzone(gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
110 void refreshServerListNexuizServerList(entity me, float mode)
112 // 0: just reparametrize
113 // 1: also ask for new servers
115 print("refresh of type ", ftos(mode), "\n");
116 /* if(mode == 2) // borken
119 localcmd("net_slist\n");
120 me.needsRefresh = 1; // net_slist kills sort order, so we need to restore it later
126 resethostcachemasks();
127 if(!me.filterShowFull)
128 sethostcachemasknumber(m++, SLIST_FIELD_FREESLOTS, 1, SLIST_TEST_GREATEREQUAL);
129 if(!me.filterShowEmpty)
130 sethostcachemasknumber(m++, SLIST_FIELD_NUMHUMANS, 1, SLIST_TEST_GREATEREQUAL);
134 sethostcachemaskstring(m++, SLIST_FIELD_NAME, me.filterString, SLIST_TEST_CONTAINS);
135 sethostcachemaskstring(m++, SLIST_FIELD_MAP, me.filterString, SLIST_TEST_CONTAINS);
137 sethostcachesort(me.currentSortField, me.currentSortOrder < 0);
143 void focusEnterNexuizServerList(entity me)
145 if(time < me.nextRefreshTime)
147 print("sorry, no refresh yet\n");
150 me.nextRefreshTime = time + 10;
151 me.refreshServerList(me, 1);
153 void drawNexuizServerList(entity me)
157 if(me.currentSortField == -1)
159 me.setSortOrder(me, SLIST_FIELD_PING, +1);
160 me.refreshServerList(me, 2);
162 else if(me.needsRefresh == 1)
164 me.needsRefresh = 2; // delay by one frame to make sure "slist" has been executed
166 else if(me.needsRefresh == 2)
169 me.refreshServerList(me, 0);
172 me.nItems = gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT);
173 me.connectButton.disabled = (me.nItems == 0);
176 if(me.selectedServer)
178 for(i = 0; i < me.nItems; ++i)
179 if(gethostcachestring(SLIST_FIELD_CNAME, i) == me.selectedServer)
181 if(i != me.selectedItem)
183 me.lastClickedServer = -1;
193 if(me.selectedItem >= me.nItems)
194 me.selectedItem = me.nItems - 1;
195 if(me.selectedServer)
196 strunzone(me.selectedServer);
197 me.selectedServer = strzone(gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
202 void ServerList_PingSort_Click(entity btn, entity me)
204 me.setSortOrder(me, SLIST_FIELD_PING, +1);
206 void ServerList_NameSort_Click(entity btn, entity me)
208 me.setSortOrder(me, SLIST_FIELD_NAME, -1); // why?
210 void ServerList_MapSort_Click(entity btn, entity me)
212 me.setSortOrder(me, SLIST_FIELD_MAP, -1); // why?
214 void ServerList_PlayerSort_Click(entity btn, entity me)
216 me.setSortOrder(me, SLIST_FIELD_NUMHUMANS, -1);
218 void ServerList_Filter_Change(entity box, entity me)
221 strunzone(me.filterString);
223 me.filterString = strzone(box.text);
225 me.filterString = string_null;
226 me.refreshServerList(me, 0);
228 void ServerList_ShowEmpty_Click(entity box, entity me)
230 box.checked = me.filterShowEmpty = !me.filterShowEmpty;
231 me.refreshServerList(me, 0);
233 void ServerList_ShowFull_Click(entity box, entity me)
235 box.checked = me.filterShowFull = !me.filterShowFull;
236 me.refreshServerList(me, 0);
238 void setSortOrderNexuizServerList(entity me, float field, float direction)
240 if(me.currentSortField == field)
241 direction = -me.currentSortOrder;
242 me.currentSortOrder = direction;
243 me.currentSortField = field;
244 me.sortButton1.forcePressed = (field == SLIST_FIELD_PING);
245 me.sortButton2.forcePressed = (field == SLIST_FIELD_NAME);
246 me.sortButton3.forcePressed = (field == SLIST_FIELD_MAP);
247 me.sortButton4.forcePressed = (field == SLIST_FIELD_NUMHUMANS);
249 if(me.selectedServer)
250 strunzone(me.selectedServer);
251 me.selectedServer = string_null;
252 me.refreshServerList(me, 0);
254 void positionSortButtonNexuizServerList(entity me, entity btn, float theOrigin, float theSize, string theTitle, void(entity, entity) theFunc)
256 vector originInLBSpace, sizeInLBSpace;
257 originInLBSpace = eY * (-me.itemHeight);
258 sizeInLBSpace = eY * me.itemHeight + eX * (1 - me.controlWidth);
260 vector originInDialogSpace, sizeInDialogSpace;
261 originInDialogSpace = boxToGlobal(originInLBSpace, me.Container_origin, me.Container_size);
262 sizeInDialogSpace = boxToGlobalSize(sizeInLBSpace, me.Container_size);
264 btn.Container_origin_x = originInDialogSpace_x + sizeInDialogSpace_x * theOrigin;
265 btn.Container_size_x = sizeInDialogSpace_x * theSize;
266 btn.setText(btn, theTitle);
267 btn.onClick = theFunc;
268 btn.onClickEntity = me;
271 void resizeNotifyNexuizServerList(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
273 resizeNotifyNexuizListBox(me, relOrigin, relSize, absOrigin, absSize);
275 me.realFontSize_y = me.fontSize / (absSize_y * me.itemHeight);
276 me.realFontSize_x = me.fontSize / (absSize_x * (1 - me.controlWidth));
277 me.realUpperMargin = 0.5 * (1 - me.realFontSize_y);
279 me.columnPingOrigin = 0;
280 me.columnPingSize = me.realFontSize_x * 4;
281 me.columnMapSize = me.realFontSize_x * 12;
282 me.columnPlayersSize = me.realFontSize_x * 6;
283 me.columnNameSize = 1 - me.columnPlayersSize - me.columnMapSize - me.columnPingSize - 3 * me.realFontSize_x;
284 me.columnNameOrigin = me.columnPingOrigin + me.columnPingSize + me.realFontSize_x;
285 me.columnMapOrigin = me.columnNameOrigin + me.columnNameSize + me.realFontSize_x;
286 me.columnPlayersOrigin = me.columnMapOrigin + me.columnMapSize + me.realFontSize_x;
288 me.positionSortButton(me, me.sortButton1, me.columnPingOrigin, me.columnPingSize, "Ping", ServerList_PingSort_Click);
289 me.positionSortButton(me, me.sortButton2, me.columnNameOrigin, me.columnNameSize, "Host name", ServerList_NameSort_Click);
290 me.positionSortButton(me, me.sortButton3, me.columnMapOrigin, me.columnMapSize, "Map", ServerList_MapSort_Click);
291 me.positionSortButton(me, me.sortButton4, me.columnPlayersOrigin, me.columnPlayersSize, "Players", ServerList_PlayerSort_Click);
294 f = me.currentSortField;
295 me.currentSortField = -1;
296 me.setSortOrder(me, f, me.currentSortOrder); // force resetting the sort order
298 void ServerList_Connect_Click(entity btn, entity me)
301 localcmd("connect ", me.selectedServer, "\n");
303 void clickListBoxItemNexuizServerList(entity me, float i, vector where)
305 if(i == me.lastClickedServer)
306 if(time < me.lastClickedTime + 0.3)
309 ServerList_Connect_Click(NULL, me);
311 me.lastClickedServer = i;
312 me.lastClickedTime = time;
314 void drawListBoxItemNexuizServerList(entity me, float i, vector absSize, float isSelected)
316 // layout: Ping, Server name, Map name, NP, TP, MP
323 draw_Fill('0 0 0', '1 1 0', '0 0 1', 0.5);
325 if(gethostcachenumber(SLIST_FIELD_NUMPLAYERS, i) >= gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i))
327 else if not(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i))
332 p = gethostcachenumber(SLIST_FIELD_PING, i);
334 theColor = eX * (p / 50) + eY;
336 theColor = eX + eY * ((150 - p) / 100);
340 theAlpha *= 0.1 + 0.9 * (650 - p) / 500;
349 draw_Text(me.realUpperMargin * eY + (me.columnPingSize - draw_TextWidth(s, 0) * me.realFontSize_x) * eX, s, me.realFontSize, theColor, theAlpha, 0);
350 s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_NAME, i), me.columnNameSize / me.realFontSize_x, 0);
351 draw_Text(me.realUpperMargin * eY + me.columnNameOrigin * eX, s, me.realFontSize, theColor, theAlpha, 0);
352 s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_MAP, i), me.columnMapSize / me.realFontSize_x, 0);
353 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);
354 s = strcat(ftos(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i)), "/", ftos(gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i)));
355 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);