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);
167 for(i = 0; i < me.nItems; ++i)
168 if(gethostcachestring(SLIST_FIELD_CNAME, i) == me.selectedServer)
170 if(i != me.selectedItem)
172 me.lastClickedServer = -1;
179 void ServerList_PingSort_Click(entity btn, entity me)
181 me.setSortOrder(me, SLIST_FIELD_PING, +1);
183 void ServerList_NameSort_Click(entity btn, entity me)
185 me.setSortOrder(me, SLIST_FIELD_NAME, -1); // why?
187 void ServerList_MapSort_Click(entity btn, entity me)
189 me.setSortOrder(me, SLIST_FIELD_MAP, -1); // why?
191 void ServerList_PlayerSort_Click(entity btn, entity me)
193 me.setSortOrder(me, SLIST_FIELD_NUMHUMANS, -1);
195 void ServerList_ShowEmpty_Click(entity box, entity me)
197 box.checked = me.filterShowEmpty = !me.filterShowEmpty;
198 me.refreshServerList(me, 0);
200 void ServerList_ShowFull_Click(entity box, entity me)
202 box.checked = me.filterShowFull = !me.filterShowFull;
203 me.refreshServerList(me, 0);
205 void setSortOrderNexuizServerList(entity me, float field, float direction)
207 if(me.currentSortField == field)
208 direction = -me.currentSortOrder;
209 me.currentSortOrder = direction;
210 me.currentSortField = field;
212 me.sortButton1.forcePressed = (field == SLIST_FIELD_PING);
213 me.sortButton2.forcePressed = (field == SLIST_FIELD_NAME);
214 me.sortButton3.forcePressed = (field == SLIST_FIELD_MAP);
215 me.sortButton4.forcePressed = (field == SLIST_FIELD_NUMHUMANS);
217 if(me.selectedServer)
218 strunzone(me.selectedServer);
219 me.selectedServer = string_null;
221 void positionSortButtonNexuizServerList(entity me, entity btn, float theOrigin, float theSize, string theTitle, void(entity, entity) theFunc)
223 vector originInLBSpace, sizeInLBSpace;
224 originInLBSpace = eY * (-me.itemHeight);
225 sizeInLBSpace = eY * me.itemHeight + eX * (1 - me.controlWidth);
227 vector originInDialogSpace, sizeInDialogSpace;
228 originInDialogSpace = boxToGlobal(originInLBSpace, me.Container_origin, me.Container_size);
229 sizeInDialogSpace = boxToGlobalSize(sizeInLBSpace, me.Container_size);
231 btn.Container_origin_x = originInDialogSpace_x + sizeInDialogSpace_x * theOrigin;
232 btn.Container_size_x = sizeInDialogSpace_x * theSize;
233 btn.setText(btn, theTitle);
234 btn.onClick = theFunc;
235 btn.onClickEntity = me;
238 void resizeNotifyNexuizServerList(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
240 resizeNotifyNexuizListBox(me, relOrigin, relSize, absOrigin, absSize);
242 me.realFontSize_y = me.fontSize / (absSize_y * me.itemHeight);
243 me.realFontSize_x = me.fontSize / (absSize_x * (1 - me.controlWidth));
244 me.realUpperMargin = 0.5 * (1 - me.realFontSize_y);
246 me.columnPingOrigin = 0;
247 me.columnPingSize = me.realFontSize_x * 4;
248 me.columnMapSize = me.realFontSize_x * 12;
249 me.columnPlayersSize = me.realFontSize_x * 6;
250 me.columnNameSize = 1 - me.columnPlayersSize - me.columnMapSize - me.columnPingSize - 3 * me.realFontSize_x;
251 me.columnNameOrigin = me.columnPingOrigin + me.columnPingSize + me.realFontSize_x;
252 me.columnMapOrigin = me.columnNameOrigin + me.columnNameSize + me.realFontSize_x;
253 me.columnPlayersOrigin = me.columnMapOrigin + me.columnMapSize + me.realFontSize_x;
255 me.positionSortButton(me, me.sortButton1, me.columnPingOrigin, me.columnPingSize, "Ping", ServerList_PingSort_Click);
256 me.positionSortButton(me, me.sortButton2, me.columnNameOrigin, me.columnNameSize, "Host name", ServerList_NameSort_Click);
257 me.positionSortButton(me, me.sortButton3, me.columnMapOrigin, me.columnMapSize, "Map", ServerList_MapSort_Click);
258 me.positionSortButton(me, me.sortButton4, me.columnPlayersOrigin, me.columnPlayersSize, "Players", ServerList_PlayerSort_Click);
261 f = me.currentSortField;
262 me.currentSortField = -1;
263 me.setSortOrder(me, f, me.currentSortOrder); // force resetting the sort order
265 void ServerList_Connect_Click(entity btn, entity me)
268 localcmd("connect ", me.selectedServer, "\n");
270 void ServerList_Refresh_Click(entity btn, entity me)
274 void clickListBoxItemNexuizServerList(entity me, float i, vector where)
276 if(i == me.lastClickedServer)
277 if(time < me.lastClickedTime + 0.3)
280 ServerList_Connect_Click(NULL, me);
282 me.lastClickedServer = i;
283 me.lastClickedTime = time;
285 void drawListBoxItemNexuizServerList(entity me, float i, vector absSize, float isSelected)
287 // layout: Ping, Server name, Map name, NP, TP, MP
294 draw_Fill('0 0 0', '1 1 0', '0 0 1', 0.5);
296 if(gethostcachenumber(SLIST_FIELD_NUMPLAYERS, i) >= gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i))
298 else if not(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i))
303 p = gethostcachenumber(SLIST_FIELD_PING, i);
305 theColor = eX * (p / 50) + eY;
307 theColor = eX + eY * ((150 - p) / 100);
311 theAlpha *= 0.1 + 0.9 * (650 - p) / 500;
320 draw_Text(me.realUpperMargin * eY + (me.columnPingSize - draw_TextWidth(s) * me.realFontSize_x) * eX, s, me.realFontSize, theColor, theAlpha);
321 s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_NAME, i), me.columnNameSize / me.realFontSize_x);
322 draw_Text(me.realUpperMargin * eY + me.columnNameOrigin * eX, s, me.realFontSize, theColor, theAlpha);
323 s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_MAP, i), me.columnMapSize / me.realFontSize_x);
324 draw_Text(me.realUpperMargin * eY + (me.columnMapOrigin + (me.columnMapSize - draw_TextWidth(s) * me.realFontSize_x) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha);
325 s = strcat(ftos(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i)), "/", ftos(gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i)));
326 draw_Text(me.realUpperMargin * eY + (me.columnPlayersOrigin + (me.columnPlayersSize - draw_TextWidth(s) * me.realFontSize_x) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha);