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
123 resethostcachemasks();
124 if(!me.filterShowEmpty)
125 sethostcachemasknumber(SLIST_MASK_AND + 0, SLIST_FIELD_NUMHUMANS, 1, SLIST_TEST_GREATEREQUAL);
126 if(!me.filterShowFull)
127 sethostcachemasknumber(SLIST_MASK_AND + 1, SLIST_FIELD_FREESLOTS, 1, SLIST_TEST_GREATEREQUAL);
128 sethostcachesort(me.currentSortField, me.currentSortOrder < 0);
134 void focusEnterNexuizServerList(entity me)
136 if(time < me.nextRefreshTime)
138 print("sorry, no refresh yet\n");
141 me.nextRefreshTime = time + 60;
142 me.refreshServerList(me, 1);
144 void drawNexuizServerList(entity me)
148 if(me.currentSortField == -1)
150 me.setSortOrder(me, SLIST_FIELD_PING, +1);
151 me.refreshServerList(me, 2);
153 else if(me.needsRefresh == 1)
155 me.needsRefresh = 2; // delay by one frame to make sure "slist" has been executed
157 else if(me.needsRefresh == 2)
160 me.refreshServerList(me, 0);
163 me.nItems = gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT);
164 me.connectButton.disabled = (me.nItems == 0);
165 for(i = 0; i < me.nItems; ++i)
166 if(gethostcachestring(SLIST_FIELD_CNAME, i) == me.selectedServer)
168 if(i != me.selectedItem)
170 me.lastClickedServer = -1;
177 void ServerList_PingSort_Click(entity btn, entity me)
179 me.setSortOrder(me, SLIST_FIELD_PING, +1);
181 void ServerList_NameSort_Click(entity btn, entity me)
183 me.setSortOrder(me, SLIST_FIELD_NAME, -1); // why?
185 void ServerList_MapSort_Click(entity btn, entity me)
187 me.setSortOrder(me, SLIST_FIELD_MAP, -1); // why?
189 void ServerList_PlayerSort_Click(entity btn, entity me)
191 me.setSortOrder(me, SLIST_FIELD_NUMHUMANS, -1);
193 void ServerList_ShowEmpty_Click(entity box, entity me)
195 box.checked = me.filterShowEmpty = !me.filterShowEmpty;
196 me.refreshServerList(me, 0);
198 void ServerList_ShowFull_Click(entity box, entity me)
200 box.checked = me.filterShowFull = !me.filterShowFull;
201 me.refreshServerList(me, 0);
203 void setSortOrderNexuizServerList(entity me, float field, float direction)
205 if(me.currentSortField == field)
206 direction = -me.currentSortOrder;
207 me.currentSortOrder = direction;
208 me.currentSortField = field;
210 me.sortButton1.forcePressed = (field == SLIST_FIELD_PING);
211 me.sortButton2.forcePressed = (field == SLIST_FIELD_NAME);
212 me.sortButton3.forcePressed = (field == SLIST_FIELD_MAP);
213 me.sortButton4.forcePressed = (field == SLIST_FIELD_NUMHUMANS);
215 if(me.selectedServer)
216 strunzone(me.selectedServer);
217 me.selectedServer = string_null;
219 void positionSortButtonNexuizServerList(entity me, entity btn, float theOrigin, float theSize, string theTitle, void(entity, entity) theFunc)
221 vector originInLBSpace, sizeInLBSpace;
222 originInLBSpace = eY * (-me.itemHeight);
223 sizeInLBSpace = eY * me.itemHeight + eX * (1 - me.controlWidth);
225 vector originInDialogSpace, sizeInDialogSpace;
226 originInDialogSpace = boxToGlobal(originInLBSpace, me.Container_origin, me.Container_size);
227 sizeInDialogSpace = boxToGlobalSize(sizeInLBSpace, me.Container_size);
229 btn.Container_origin_x = originInDialogSpace_x + sizeInDialogSpace_x * theOrigin;
230 btn.Container_size_x = sizeInDialogSpace_x * theSize;
231 btn.setText(btn, theTitle);
232 btn.onClick = theFunc;
233 btn.onClickEntity = me;
236 void resizeNotifyNexuizServerList(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
238 resizeNotifyNexuizListBox(me, relOrigin, relSize, absOrigin, absSize);
240 me.realFontSize_y = me.fontSize / (absSize_y * me.itemHeight);
241 me.realFontSize_x = me.fontSize / (absSize_x * (1 - me.controlWidth));
242 me.realUpperMargin = 0.5 * (1 - me.realFontSize_y);
244 me.columnPingOrigin = 0;
245 me.columnPingSize = me.realFontSize_x * 4;
246 me.columnMapSize = me.realFontSize_x * 12;
247 me.columnPlayersSize = me.realFontSize_x * 6;
248 me.columnNameSize = 1 - me.columnPlayersSize - me.columnMapSize - me.columnPingSize - 3 * me.realFontSize_x;
249 me.columnNameOrigin = me.columnPingOrigin + me.columnPingSize + me.realFontSize_x;
250 me.columnMapOrigin = me.columnNameOrigin + me.columnNameSize + me.realFontSize_x;
251 me.columnPlayersOrigin = me.columnMapOrigin + me.columnMapSize + me.realFontSize_x;
253 me.positionSortButton(me, me.sortButton1, me.columnPingOrigin, me.columnPingSize, "Ping", ServerList_PingSort_Click);
254 me.positionSortButton(me, me.sortButton2, me.columnNameOrigin, me.columnNameSize, "Host name", ServerList_NameSort_Click);
255 me.positionSortButton(me, me.sortButton3, me.columnMapOrigin, me.columnMapSize, "Map", ServerList_MapSort_Click);
256 me.positionSortButton(me, me.sortButton4, me.columnPlayersOrigin, me.columnPlayersSize, "Players", ServerList_PlayerSort_Click);
259 f = me.currentSortField;
260 me.currentSortField = -1;
261 me.setSortOrder(me, f, me.currentSortOrder); // force resetting the sort order
263 void ServerList_Connect_Click(entity btn, entity me)
266 localcmd("connect ", me.selectedServer, "\n");
268 void ServerList_Refresh_Click(entity btn, entity me)
272 void clickListBoxItemNexuizServerList(entity me, float i, vector where)
274 if(i == me.lastClickedServer)
275 if(time < me.lastClickedTime + 0.3)
278 ServerList_Connect_Click(NULL, me);
280 me.lastClickedServer = i;
281 me.lastClickedTime = time;
283 void drawListBoxItemNexuizServerList(entity me, float i, vector absSize, float isSelected)
285 // layout: Ping, Server name, Map name, NP, TP, MP
292 draw_Fill('0 0 0', '1 1 0', '0 0 1', 0.5);
294 if(gethostcachenumber(SLIST_FIELD_NUMPLAYERS, i) >= gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i))
296 else if not(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i))
301 p = gethostcachenumber(SLIST_FIELD_PING, i);
303 theColor = eX * (p / 50) + eY;
305 theColor = eX + eY * ((150 - p) / 100);
309 theAlpha *= 0.1 + 0.9 * (650 - p) / 500;
318 draw_Text(me.realUpperMargin * eY + (me.columnPingSize - draw_TextWidth(s) * me.realFontSize_x) * eX, s, me.realFontSize, theColor, theAlpha);
319 s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_NAME, i), me.columnNameSize / me.realFontSize_x);
320 draw_Text(me.realUpperMargin * eY + me.columnNameOrigin * eX, s, me.realFontSize, theColor, theAlpha);
321 s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_MAP, i), me.columnMapSize / me.realFontSize_x);
322 draw_Text(me.realUpperMargin * eY + (me.columnMapOrigin + (me.columnMapSize - draw_TextWidth(s) * me.realFontSize_x) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha);
323 s = strcat(ftos(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i)), "/", ftos(gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i)));
324 draw_Text(me.realUpperMargin * eY + (me.columnPlayersOrigin + (me.columnPlayersSize - draw_TextWidth(s) * me.realFontSize_x) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha);