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, nextRefreshTime, float, 0)
27 METHOD(NexuizServerList, refreshServerList, void(entity, float)) // refresh mode: 0 = just reparametrize, 1 = send new requests, 2 = clear
28 ATTRIB(NexuizServerList, needsRefresh, float, 1)
29 METHOD(NexuizServerList, focusEnter, void(entity))
30 METHOD(NexuizServerList, positionSortButton, void(entity, entity, float, float, string, void(entity, entity)))
31 ATTRIB(NexuizServerList, sortButton1, entity, NULL)
32 ATTRIB(NexuizServerList, sortButton2, entity, NULL)
33 ATTRIB(NexuizServerList, sortButton3, entity, NULL)
34 ATTRIB(NexuizServerList, sortButton4, entity, NULL)
35 ATTRIB(NexuizServerList, connectButton, entity, NULL)
36 ATTRIB(NexuizServerList, currentSortOrder, float, 0)
37 ATTRIB(NexuizServerList, currentSortField, float, -1)
38 ATTRIB(NexuizServerList, lastClickedServer, float, -1)
39 ATTRIB(NexuizServerList, lastClickedTime, float, 0)
40 ENDCLASS(NexuizServerList)
41 entity makeNexuizServerList();
42 void ServerList_Connect_Click(entity btn, entity me);
43 void ServerList_Refresh_Click(entity btn, entity me);
44 void ServerList_ShowEmpty_Click(entity box, entity me);
45 void ServerList_ShowFull_Click(entity box, entity me);
49 float SLIST_FIELD_CNAME;
50 float SLIST_FIELD_PING;
51 float SLIST_FIELD_GAME;
52 float SLIST_FIELD_MOD;
53 float SLIST_FIELD_MAP;
54 float SLIST_FIELD_NAME;
55 float SLIST_FIELD_MAXPLAYERS;
56 float SLIST_FIELD_NUMPLAYERS;
57 float SLIST_FIELD_NUMHUMANS;
58 float SLIST_FIELD_NUMBOTS;
59 float SLIST_FIELD_PROTOCOL;
60 float SLIST_FIELD_FREESLOTS;
61 void ServerList_UpdateFieldIDs()
63 SLIST_FIELD_CNAME = gethostcacheindexforkey( "cname" );
64 SLIST_FIELD_PING = gethostcacheindexforkey( "ping" );
65 SLIST_FIELD_GAME = gethostcacheindexforkey( "game" );
66 SLIST_FIELD_MOD = gethostcacheindexforkey( "mod" );
67 SLIST_FIELD_MAP = gethostcacheindexforkey( "map" );
68 SLIST_FIELD_NAME = gethostcacheindexforkey( "name" );
69 SLIST_FIELD_MAXPLAYERS = gethostcacheindexforkey( "maxplayers" );
70 SLIST_FIELD_NUMPLAYERS = gethostcacheindexforkey( "numplayers" );
71 SLIST_FIELD_NUMHUMANS = gethostcacheindexforkey( "numhumans" );
72 SLIST_FIELD_NUMBOTS = gethostcacheindexforkey( "numbots" );
73 SLIST_FIELD_PROTOCOL = gethostcacheindexforkey( "protocol" );
74 SLIST_FIELD_FREESLOTS = gethostcacheindexforkey( "freeslots" );
77 entity makeNexuizServerList()
80 me = spawnNexuizServerList();
81 me.configureNexuizServerList(me);
84 void configureNexuizServerListNexuizServerList(entity me)
86 me.configureNexuizListBox(me);
88 ServerList_UpdateFieldIDs();
92 void setSelectedNexuizServerList(entity me, float i)
95 save = me.selectedItem;
96 setSelectedListBox(me, i);
98 if(me.selectedItem == save)
103 if(gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT) != me.nItems)
104 return; // sorry, it would be wrong
105 if(me.selectedServer)
106 strunzone(me.selectedServer);
107 me.selectedServer = strzone(gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
109 void refreshServerListNexuizServerList(entity me, float mode)
111 // 0: just reparametrize
112 // 1: also ask for new servers
114 print("refresh of type ", ftos(mode), "\n");
115 /* if(mode == 2) // borken
118 localcmd("net_slist\n");
119 me.needsRefresh = 1; // net_slist kills sort order, so we need to restore it later
125 resethostcachemasks();
126 if(!me.filterShowFull)
127 sethostcachemasknumber(m++, SLIST_FIELD_FREESLOTS, 1, SLIST_TEST_GREATEREQUAL);
128 if(!me.filterShowEmpty)
129 sethostcachemasknumber(m++, SLIST_FIELD_NUMHUMANS, 1, SLIST_TEST_GREATEREQUAL);
130 sethostcachesort(me.currentSortField, me.currentSortOrder < 0);
136 void focusEnterNexuizServerList(entity me)
138 if(time < me.nextRefreshTime)
140 print("sorry, no refresh yet\n");
143 me.nextRefreshTime = time + 60;
144 me.refreshServerList(me, 1);
146 void drawNexuizServerList(entity me)
150 if(me.currentSortField == -1)
152 me.setSortOrder(me, SLIST_FIELD_PING, +1);
153 me.refreshServerList(me, 2);
155 else if(me.needsRefresh == 1)
157 me.needsRefresh = 2; // delay by one frame to make sure "slist" has been executed
159 else if(me.needsRefresh == 2)
162 me.refreshServerList(me, 0);
165 me.nItems = gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT);
166 me.connectButton.disabled = (me.nItems == 0);
169 if(me.selectedServer)
171 for(i = 0; i < me.nItems; ++i)
172 if(gethostcachestring(SLIST_FIELD_CNAME, i) == me.selectedServer)
174 if(i != me.selectedItem)
176 me.lastClickedServer = -1;
186 if(me.selectedItem >= me.nItems)
187 me.selectedItem = me.nItems - 1;
188 if(me.selectedServer)
189 strunzone(me.selectedServer);
190 me.selectedServer = strzone(gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
195 void ServerList_PingSort_Click(entity btn, entity me)
197 me.setSortOrder(me, SLIST_FIELD_PING, +1);
199 void ServerList_NameSort_Click(entity btn, entity me)
201 me.setSortOrder(me, SLIST_FIELD_NAME, -1); // why?
203 void ServerList_MapSort_Click(entity btn, entity me)
205 me.setSortOrder(me, SLIST_FIELD_MAP, -1); // why?
207 void ServerList_PlayerSort_Click(entity btn, entity me)
209 me.setSortOrder(me, SLIST_FIELD_NUMHUMANS, -1);
211 void ServerList_ShowEmpty_Click(entity box, entity me)
213 box.checked = me.filterShowEmpty = !me.filterShowEmpty;
214 me.refreshServerList(me, 0);
216 void ServerList_ShowFull_Click(entity box, entity me)
218 box.checked = me.filterShowFull = !me.filterShowFull;
219 me.refreshServerList(me, 0);
221 void setSortOrderNexuizServerList(entity me, float field, float direction)
223 if(me.currentSortField == field)
224 direction = -me.currentSortOrder;
225 me.currentSortOrder = direction;
226 me.currentSortField = field;
228 me.sortButton1.forcePressed = (field == SLIST_FIELD_PING);
229 me.sortButton2.forcePressed = (field == SLIST_FIELD_NAME);
230 me.sortButton3.forcePressed = (field == SLIST_FIELD_MAP);
231 me.sortButton4.forcePressed = (field == SLIST_FIELD_NUMHUMANS);
233 if(me.selectedServer)
234 strunzone(me.selectedServer);
235 me.selectedServer = string_null;
237 void positionSortButtonNexuizServerList(entity me, entity btn, float theOrigin, float theSize, string theTitle, void(entity, entity) theFunc)
239 vector originInLBSpace, sizeInLBSpace;
240 originInLBSpace = eY * (-me.itemHeight);
241 sizeInLBSpace = eY * me.itemHeight + eX * (1 - me.controlWidth);
243 vector originInDialogSpace, sizeInDialogSpace;
244 originInDialogSpace = boxToGlobal(originInLBSpace, me.Container_origin, me.Container_size);
245 sizeInDialogSpace = boxToGlobalSize(sizeInLBSpace, me.Container_size);
247 btn.Container_origin_x = originInDialogSpace_x + sizeInDialogSpace_x * theOrigin;
248 btn.Container_size_x = sizeInDialogSpace_x * theSize;
249 btn.setText(btn, theTitle);
250 btn.onClick = theFunc;
251 btn.onClickEntity = me;
254 void resizeNotifyNexuizServerList(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
256 resizeNotifyNexuizListBox(me, relOrigin, relSize, absOrigin, absSize);
258 me.realFontSize_y = me.fontSize / (absSize_y * me.itemHeight);
259 me.realFontSize_x = me.fontSize / (absSize_x * (1 - me.controlWidth));
260 me.realUpperMargin = 0.5 * (1 - me.realFontSize_y);
262 me.columnPingOrigin = 0;
263 me.columnPingSize = me.realFontSize_x * 4;
264 me.columnMapSize = me.realFontSize_x * 12;
265 me.columnPlayersSize = me.realFontSize_x * 6;
266 me.columnNameSize = 1 - me.columnPlayersSize - me.columnMapSize - me.columnPingSize - 3 * me.realFontSize_x;
267 me.columnNameOrigin = me.columnPingOrigin + me.columnPingSize + me.realFontSize_x;
268 me.columnMapOrigin = me.columnNameOrigin + me.columnNameSize + me.realFontSize_x;
269 me.columnPlayersOrigin = me.columnMapOrigin + me.columnMapSize + me.realFontSize_x;
271 me.positionSortButton(me, me.sortButton1, me.columnPingOrigin, me.columnPingSize, "Ping", ServerList_PingSort_Click);
272 me.positionSortButton(me, me.sortButton2, me.columnNameOrigin, me.columnNameSize, "Host name", ServerList_NameSort_Click);
273 me.positionSortButton(me, me.sortButton3, me.columnMapOrigin, me.columnMapSize, "Map", ServerList_MapSort_Click);
274 me.positionSortButton(me, me.sortButton4, me.columnPlayersOrigin, me.columnPlayersSize, "Players", ServerList_PlayerSort_Click);
277 f = me.currentSortField;
278 me.currentSortField = -1;
279 me.setSortOrder(me, f, me.currentSortOrder); // force resetting the sort order
281 void ServerList_Connect_Click(entity btn, entity me)
284 localcmd("connect ", me.selectedServer, "\n");
286 void ServerList_Refresh_Click(entity btn, entity me)
290 void clickListBoxItemNexuizServerList(entity me, float i, vector where)
292 if(i == me.lastClickedServer)
293 if(time < me.lastClickedTime + 0.3)
296 ServerList_Connect_Click(NULL, me);
298 me.lastClickedServer = i;
299 me.lastClickedTime = time;
301 void drawListBoxItemNexuizServerList(entity me, float i, vector absSize, float isSelected)
303 // layout: Ping, Server name, Map name, NP, TP, MP
310 draw_Fill('0 0 0', '1 1 0', '0 0 1', 0.5);
312 if(gethostcachenumber(SLIST_FIELD_NUMPLAYERS, i) >= gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i))
314 else if not(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i))
319 p = gethostcachenumber(SLIST_FIELD_PING, i);
321 theColor = eX * (p / 50) + eY;
323 theColor = eX + eY * ((150 - p) / 100);
327 theAlpha *= 0.1 + 0.9 * (650 - p) / 500;
336 draw_Text(me.realUpperMargin * eY + (me.columnPingSize - draw_TextWidth(s) * me.realFontSize_x) * eX, s, me.realFontSize, theColor, theAlpha);
337 s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_NAME, i), me.columnNameSize / me.realFontSize_x);
338 draw_Text(me.realUpperMargin * eY + me.columnNameOrigin * eX, s, me.realFontSize, theColor, theAlpha);
339 s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_MAP, i), me.columnMapSize / me.realFontSize_x);
340 draw_Text(me.realUpperMargin * eY + (me.columnMapOrigin + (me.columnMapSize - draw_TextWidth(s) * me.realFontSize_x) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha);
341 s = strcat(ftos(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i)), "/", ftos(gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i)));
342 draw_Text(me.realUpperMargin * eY + (me.columnPlayersOrigin + (me.columnPlayersSize - draw_TextWidth(s) * me.realFontSize_x) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha);