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, controlledTextbox, entity, NULL)
29 ATTRIB(NexuizServerList, nextRefreshTime, float, 0)
30 METHOD(NexuizServerList, refreshServerList, void(entity, float)) // refresh mode: 0 = just reparametrize, 1 = send new requests, 2 = clear
31 ATTRIB(NexuizServerList, needsRefresh, float, 1)
32 METHOD(NexuizServerList, focusEnter, void(entity))
33 METHOD(NexuizServerList, positionSortButton, void(entity, entity, float, float, string, void(entity, entity)))
34 ATTRIB(NexuizServerList, sortButton1, entity, NULL)
35 ATTRIB(NexuizServerList, sortButton2, entity, NULL)
36 ATTRIB(NexuizServerList, sortButton3, entity, NULL)
37 ATTRIB(NexuizServerList, sortButton4, entity, NULL)
38 ATTRIB(NexuizServerList, connectButton, entity, NULL)
39 ATTRIB(NexuizServerList, currentSortOrder, float, 0)
40 ATTRIB(NexuizServerList, currentSortField, float, -1)
41 ATTRIB(NexuizServerList, lastClickedServer, float, -1)
42 ATTRIB(NexuizServerList, lastClickedTime, float, 0)
43 ENDCLASS(NexuizServerList)
44 entity makeNexuizServerList();
45 void ServerList_Connect_Click(entity btn, entity me);
46 void ServerList_ShowEmpty_Click(entity box, entity me);
47 void ServerList_ShowFull_Click(entity box, entity me);
48 void ServerList_Filter_Change(entity box, entity me);
52 float SLIST_FIELD_CNAME;
53 float SLIST_FIELD_PING;
54 float SLIST_FIELD_GAME;
55 float SLIST_FIELD_MOD;
56 float SLIST_FIELD_MAP;
57 float SLIST_FIELD_NAME;
58 float SLIST_FIELD_MAXPLAYERS;
59 float SLIST_FIELD_NUMPLAYERS;
60 float SLIST_FIELD_NUMHUMANS;
61 float SLIST_FIELD_NUMBOTS;
62 float SLIST_FIELD_PROTOCOL;
63 float SLIST_FIELD_FREESLOTS;
64 void ServerList_UpdateFieldIDs()
66 SLIST_FIELD_CNAME = gethostcacheindexforkey( "cname" );
67 SLIST_FIELD_PING = gethostcacheindexforkey( "ping" );
68 SLIST_FIELD_GAME = gethostcacheindexforkey( "game" );
69 SLIST_FIELD_MOD = gethostcacheindexforkey( "mod" );
70 SLIST_FIELD_MAP = gethostcacheindexforkey( "map" );
71 SLIST_FIELD_NAME = gethostcacheindexforkey( "name" );
72 SLIST_FIELD_MAXPLAYERS = gethostcacheindexforkey( "maxplayers" );
73 SLIST_FIELD_NUMPLAYERS = gethostcacheindexforkey( "numplayers" );
74 SLIST_FIELD_NUMHUMANS = gethostcacheindexforkey( "numhumans" );
75 SLIST_FIELD_NUMBOTS = gethostcacheindexforkey( "numbots" );
76 SLIST_FIELD_PROTOCOL = gethostcacheindexforkey( "protocol" );
77 SLIST_FIELD_FREESLOTS = gethostcacheindexforkey( "freeslots" );
80 entity makeNexuizServerList()
83 me = spawnNexuizServerList();
84 me.configureNexuizServerList(me);
87 void configureNexuizServerListNexuizServerList(entity me)
89 me.configureNexuizListBox(me);
91 ServerList_UpdateFieldIDs();
95 void setSelectedNexuizServerList(entity me, float i)
98 save = me.selectedItem;
99 setSelectedListBox(me, i);
101 if(me.selectedItem == save)
106 if(gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT) != me.nItems)
107 return; // sorry, it would be wrong
108 if(me.selectedServer)
109 strunzone(me.selectedServer);
110 me.selectedServer = strzone(gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
112 void refreshServerListNexuizServerList(entity me, float mode)
114 // 0: just reparametrize
115 // 1: also ask for new servers
117 //print("refresh of type ", ftos(mode), "\n");
118 /* if(mode == 2) // borken
121 localcmd("net_slist\n");
122 me.needsRefresh = 1; // net_slist kills sort order, so we need to restore it later
128 resethostcachemasks();
129 if(!me.filterShowFull)
130 sethostcachemasknumber(m++, SLIST_FIELD_FREESLOTS, 1, SLIST_TEST_GREATEREQUAL);
131 if(!me.filterShowEmpty)
132 sethostcachemasknumber(m++, SLIST_FIELD_NUMHUMANS, 1, SLIST_TEST_GREATEREQUAL);
136 sethostcachemaskstring(m++, SLIST_FIELD_NAME, me.filterString, SLIST_TEST_CONTAINS);
137 sethostcachemaskstring(m++, SLIST_FIELD_MAP, me.filterString, SLIST_TEST_CONTAINS);
139 sethostcachesort(me.currentSortField, me.currentSortOrder < 0);
145 void focusEnterNexuizServerList(entity me)
147 if(time < me.nextRefreshTime)
149 //print("sorry, no refresh yet\n");
152 me.nextRefreshTime = time + 10;
153 me.refreshServerList(me, 1);
155 void drawNexuizServerList(entity me)
159 if(me.currentSortField == -1)
161 me.setSortOrder(me, SLIST_FIELD_PING, +1);
162 me.refreshServerList(me, 2);
164 else if(me.needsRefresh == 1)
166 me.needsRefresh = 2; // delay by one frame to make sure "slist" has been executed
168 else if(me.needsRefresh == 2)
171 me.refreshServerList(me, 0);
174 me.nItems = gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT);
175 me.connectButton.disabled = (me.nItems == 0);
178 if(me.selectedServer)
180 for(i = 0; i < me.nItems; ++i)
181 if(gethostcachestring(SLIST_FIELD_CNAME, i) == me.selectedServer)
183 if(i != me.selectedItem)
185 me.lastClickedServer = -1;
195 if(me.selectedItem >= me.nItems)
196 me.selectedItem = me.nItems - 1;
197 if(me.selectedServer)
198 strunzone(me.selectedServer);
199 me.selectedServer = strzone(gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
204 void ServerList_PingSort_Click(entity btn, entity me)
206 me.setSortOrder(me, SLIST_FIELD_PING, +1);
208 void ServerList_NameSort_Click(entity btn, entity me)
210 me.setSortOrder(me, SLIST_FIELD_NAME, -1); // why?
212 void ServerList_MapSort_Click(entity btn, entity me)
214 me.setSortOrder(me, SLIST_FIELD_MAP, -1); // why?
216 void ServerList_PlayerSort_Click(entity btn, entity me)
218 me.setSortOrder(me, SLIST_FIELD_NUMHUMANS, -1);
220 void ServerList_Filter_Change(entity box, entity me)
223 strunzone(me.filterString);
225 me.filterString = strzone(box.text);
227 me.filterString = string_null;
228 me.refreshServerList(me, 0);
230 void ServerList_ShowEmpty_Click(entity box, entity me)
232 box.checked = me.filterShowEmpty = !me.filterShowEmpty;
233 me.refreshServerList(me, 0);
235 void ServerList_ShowFull_Click(entity box, entity me)
237 box.checked = me.filterShowFull = !me.filterShowFull;
238 me.refreshServerList(me, 0);
240 void setSortOrderNexuizServerList(entity me, float field, float direction)
242 if(me.currentSortField == field)
243 direction = -me.currentSortOrder;
244 me.currentSortOrder = direction;
245 me.currentSortField = field;
246 me.sortButton1.forcePressed = (field == SLIST_FIELD_PING);
247 me.sortButton2.forcePressed = (field == SLIST_FIELD_NAME);
248 me.sortButton3.forcePressed = (field == SLIST_FIELD_MAP);
249 me.sortButton4.forcePressed = (field == SLIST_FIELD_NUMHUMANS);
251 if(me.selectedServer)
252 strunzone(me.selectedServer);
253 me.selectedServer = string_null;
254 me.refreshServerList(me, 0);
256 void positionSortButtonNexuizServerList(entity me, entity btn, float theOrigin, float theSize, string theTitle, void(entity, entity) theFunc)
258 vector originInLBSpace, sizeInLBSpace;
259 originInLBSpace = eY * (-me.itemHeight);
260 sizeInLBSpace = eY * me.itemHeight + eX * (1 - me.controlWidth);
262 vector originInDialogSpace, sizeInDialogSpace;
263 originInDialogSpace = boxToGlobal(originInLBSpace, me.Container_origin, me.Container_size);
264 sizeInDialogSpace = boxToGlobalSize(sizeInLBSpace, me.Container_size);
266 btn.Container_origin_x = originInDialogSpace_x + sizeInDialogSpace_x * theOrigin;
267 btn.Container_size_x = sizeInDialogSpace_x * theSize;
268 btn.setText(btn, theTitle);
269 btn.onClick = theFunc;
270 btn.onClickEntity = me;
273 void resizeNotifyNexuizServerList(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
275 resizeNotifyNexuizListBox(me, relOrigin, relSize, absOrigin, absSize);
277 me.realFontSize_y = me.fontSize / (absSize_y * me.itemHeight);
278 me.realFontSize_x = me.fontSize / (absSize_x * (1 - me.controlWidth));
279 me.realUpperMargin = 0.5 * (1 - me.realFontSize_y);
281 me.columnPingOrigin = 0;
282 me.columnPingSize = me.realFontSize_x * 4;
283 me.columnMapSize = me.realFontSize_x * 12;
284 me.columnPlayersSize = me.realFontSize_x * 6;
285 me.columnNameSize = 1 - me.columnPlayersSize - me.columnMapSize - me.columnPingSize - 3 * me.realFontSize_x;
286 me.columnNameOrigin = me.columnPingOrigin + me.columnPingSize + me.realFontSize_x;
287 me.columnMapOrigin = me.columnNameOrigin + me.columnNameSize + me.realFontSize_x;
288 me.columnPlayersOrigin = me.columnMapOrigin + me.columnMapSize + me.realFontSize_x;
290 me.positionSortButton(me, me.sortButton1, me.columnPingOrigin, me.columnPingSize, "Ping", ServerList_PingSort_Click);
291 me.positionSortButton(me, me.sortButton2, me.columnNameOrigin, me.columnNameSize, "Host name", ServerList_NameSort_Click);
292 me.positionSortButton(me, me.sortButton3, me.columnMapOrigin, me.columnMapSize, "Map", ServerList_MapSort_Click);
293 me.positionSortButton(me, me.sortButton4, me.columnPlayersOrigin, me.columnPlayersSize, "Players", ServerList_PlayerSort_Click);
296 f = me.currentSortField;
299 me.currentSortField = -1;
300 me.setSortOrder(me, f, me.currentSortOrder); // force resetting the sort order
303 void ServerList_Connect_Click(entity btn, entity me)
306 localcmd("connect ", me.selectedServer, "\n");
308 void clickListBoxItemNexuizServerList(entity me, float i, vector where)
310 if(i == me.lastClickedServer)
311 if(time < me.lastClickedTime + 0.3)
314 ServerList_Connect_Click(NULL, me);
316 me.lastClickedServer = i;
317 me.lastClickedTime = time;
319 void drawListBoxItemNexuizServerList(entity me, float i, vector absSize, float isSelected)
321 // layout: Ping, Server name, Map name, NP, TP, MP
328 draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
330 if(gethostcachenumber(SLIST_FIELD_NUMPLAYERS, i) >= gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i))
331 theAlpha = SKINALPHA_SERVERLIST_FULL;
332 else if not(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i))
333 theAlpha = SKINALPHA_SERVERLIST_EMPTY;
337 p = gethostcachenumber(SLIST_FIELD_PING, i);
339 theColor = SKINCOLOR_SERVERLIST_LOWPING + (SKINCOLOR_SERVERLIST_MEDPING - SKINCOLOR_SERVERLIST_LOWPING) * (p / 50);
341 theColor = SKINCOLOR_SERVERLIST_MEDPING + (SKINCOLOR_SERVERLIST_HIGHPING - SKINCOLOR_SERVERLIST_MEDPING) * ((p - 50) / 100);
344 theColor = SKINCOLOR_SERVERLIST_HIGHPING;
345 theAlpha *= 1 + (SKINALPHA_SERVERLIST_HIGHPING - 1) * ((p - 150) / 500);
350 theAlpha *= SKINALPHA_SERVERLIST_HIGHPING;
354 draw_Text(me.realUpperMargin * eY + (me.columnPingSize - draw_TextWidth(s, 0) * me.realFontSize_x) * eX, s, me.realFontSize, theColor, theAlpha, 0);
355 s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_NAME, i), me.columnNameSize / me.realFontSize_x, 0);
356 draw_Text(me.realUpperMargin * eY + me.columnNameOrigin * eX, s, me.realFontSize, theColor, theAlpha, 0);
357 s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_MAP, i), me.columnMapSize / me.realFontSize_x, 0);
358 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);
359 s = strcat(ftos(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i)), "/", ftos(gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i)));
360 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);
363 float keyDownNexuizServerList(entity me, float scan, float ascii, float shift)
367 ServerList_Connect_Click(NULL, me);
370 else if(keyDownListBox(me, scan, ascii, shift))
372 else if(!me.controlledTextbox)
375 return me.controlledTextbox.keyDown(me.controlledTextbox, scan, ascii, shift);