]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/menu-div0test/nexuiz/serverlist.c
It can join servers now!
[divverent/nexuiz.git] / data / qcsrc / menu-div0test / nexuiz / serverlist.c
1 #ifdef INTERFACE
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
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)
20
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         METHOD(NexuizServerList, positionSortButton, void(entity, entity, float, float, string, void(entity, entity)))
25         ATTRIB(NexuizServerList, sortButton1, entity, NULL)
26         ATTRIB(NexuizServerList, sortButton2, entity, NULL)
27         ATTRIB(NexuizServerList, sortButton3, entity, NULL)
28         ATTRIB(NexuizServerList, sortButton4, entity, NULL)
29         ATTRIB(NexuizServerList, connectButton, entity, NULL)
30         ATTRIB(NexuizServerList, currentSortOrder, float, 0)
31         ATTRIB(NexuizServerList, currentSortField, float, 0)
32         ATTRIB(NexuizServerList, lastClickedServer, float, 0)
33         ATTRIB(NexuizServerList, lastClickedTime, float, 0)
34 ENDCLASS(NexuizServerList)
35 entity makeNexuizServerList();
36 void ServerList_Connect_Click(entity btn, entity me);
37 void ServerList_Refresh_Click(entity btn, entity me);
38 #endif
39
40 #ifdef IMPLEMENTATION
41 float SLIST_FIELD_CNAME;
42 float SLIST_FIELD_PING;
43 float SLIST_FIELD_GAME;
44 float SLIST_FIELD_MOD;
45 float SLIST_FIELD_MAP;
46 float SLIST_FIELD_NAME;
47 float SLIST_FIELD_MAXPLAYERS;
48 float SLIST_FIELD_NUMPLAYERS;
49 float SLIST_FIELD_NUMHUMANS;
50 float SLIST_FIELD_NUMBOTS;
51 float SLIST_FIELD_PROTOCOL;
52 float SLIST_FIELD_FREESLOTS;
53 void ServerList_UpdateFieldIDs()
54 {
55         SLIST_FIELD_CNAME = gethostcacheindexforkey( "cname" );
56         SLIST_FIELD_PING = gethostcacheindexforkey( "ping" );
57         SLIST_FIELD_GAME = gethostcacheindexforkey( "game" );
58         SLIST_FIELD_MOD = gethostcacheindexforkey( "mod" );
59         SLIST_FIELD_MAP = gethostcacheindexforkey( "map" );
60         SLIST_FIELD_NAME = gethostcacheindexforkey( "name" );
61         SLIST_FIELD_MAXPLAYERS = gethostcacheindexforkey( "maxplayers" );
62         SLIST_FIELD_NUMPLAYERS = gethostcacheindexforkey( "numplayers" );
63         SLIST_FIELD_NUMHUMANS = gethostcacheindexforkey( "numhumans" );
64         SLIST_FIELD_NUMBOTS = gethostcacheindexforkey( "numbots" );
65         SLIST_FIELD_PROTOCOL = gethostcacheindexforkey( "protocol" );
66         SLIST_FIELD_FREESLOTS = gethostcacheindexforkey( "freeslots" );
67 }
68
69 entity makeNexuizServerList()
70 {
71         entity me;
72         me = spawnNexuizServerList();
73         me.configureNexuizServerList(me);
74         return me;
75 }
76 void configureNexuizServerListNexuizServerList(entity me)
77 {
78         me.configureNexuizListBox(me);
79
80         ServerList_UpdateFieldIDs();
81         resethostcachemasks();
82         me.currentSortField = -1;
83
84         me.nItems = 0;
85 }
86 void setSelectedNexuizServerList(entity me, float i)
87 {
88         float save;
89         save = me.selectedItem;
90         setSelectedListBox(me, i);
91         /*
92         if(me.selectedItem == save)
93                 return;
94         */
95         if(me.nItems == 0)
96                 return;
97         if(gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT) != me.nItems)
98                 return; // sorry, it would be wrong
99         if(me.selectedServer)
100                 strunzone(me.selectedServer);
101         me.selectedServer = strzone(gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
102 }
103 void drawNexuizServerList(entity me)
104 {
105         float i;
106
107         if(me.currentSortField == -1)
108         {
109                 refreshhostcache();
110                 me.setSortOrder(me, SLIST_FIELD_PING, +1);
111         }
112
113         me.nItems = gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT);
114         me.connectButton.disabled = (me.nItems == 0);
115         for(i = 0; i < me.nItems; ++i)
116         {
117                 if(gethostcachestring(SLIST_FIELD_CNAME, i) == me.selectedServer)
118                 {
119                         me.selectedItem = i;
120                         break;
121                 }
122         }
123         drawListBox(me);
124 }
125 void ServerList_PingSort_Click(entity btn, entity me)
126 {
127         me.setSortOrder(me, SLIST_FIELD_PING, +1);
128 }
129 void ServerList_NameSort_Click(entity btn, entity me)
130 {
131         me.setSortOrder(me, SLIST_FIELD_NAME, -1); // why?
132 }
133 void ServerList_MapSort_Click(entity btn, entity me)
134 {
135         me.setSortOrder(me, SLIST_FIELD_MAP, -1); // why?
136 }
137 void ServerList_PlayerSort_Click(entity btn, entity me)
138 {
139         me.setSortOrder(me, SLIST_FIELD_NUMHUMANS, -1);
140 }
141 void setSortOrderNexuizServerList(entity me, float field, float direction)
142 {
143         if(me.currentSortField == field)
144                 direction = -me.currentSortOrder;
145         me.currentSortOrder = direction;
146         me.currentSortField = field;
147         sethostcachesort(field, direction < 0);
148         resorthostcache();
149         me.sortButton1.forcePressed = (field == SLIST_FIELD_PING);
150         me.sortButton2.forcePressed = (field == SLIST_FIELD_NAME);
151         me.sortButton3.forcePressed = (field == SLIST_FIELD_MAP);
152         me.sortButton4.forcePressed = (field == SLIST_FIELD_NUMHUMANS);
153         me.selectedItem = 0;
154         if(me.selectedServer)
155                 strunzone(me.selectedServer);
156         me.selectedServer = string_null;
157 }
158 void positionSortButtonNexuizServerList(entity me, entity btn, float theOrigin, float theSize, string theTitle, void(entity, entity) theFunc)
159 {
160         vector originInLBSpace, sizeInLBSpace;
161         originInLBSpace = eY * (-me.itemHeight);
162         sizeInLBSpace = eY * me.itemHeight + eX * (1 - me.controlWidth);
163
164         vector originInDialogSpace, sizeInDialogSpace;
165         originInDialogSpace = boxToGlobal(originInLBSpace, me.Container_origin, me.Container_size);
166         sizeInDialogSpace = boxToGlobalSize(sizeInLBSpace, me.Container_size);
167
168         btn.Container_origin_x = originInDialogSpace_x + sizeInDialogSpace_x * theOrigin;
169         btn.Container_size_x   =                         sizeInDialogSpace_x * theSize;
170         btn.setText(btn, theTitle);
171         btn.onClick = theFunc;
172         btn.onClickEntity = me;
173         btn.resized = 1;
174 }
175 void resizeNotifyNexuizServerList(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
176 {
177         resizeNotifyNexuizListBox(me, relOrigin, relSize, absOrigin, absSize);
178
179         me.realFontSize_y = me.fontSize / (absSize_y * me.itemHeight);
180         me.realFontSize_x = me.fontSize / (absSize_x * (1 - me.controlWidth));
181         me.realUpperMargin = 0.5 * (1 - me.realFontSize_y);
182
183         me.columnPingOrigin = 0;
184         me.columnPingSize = me.realFontSize_x * 4;
185         me.columnMapSize = me.realFontSize_x * 12;
186         me.columnPlayersSize = me.realFontSize_x * 6;
187         me.columnNameSize = 1 - me.columnPlayersSize - me.columnMapSize - me.columnPingSize - 3 * me.realFontSize_x;
188         me.columnNameOrigin = me.columnPingOrigin + me.columnPingSize + me.realFontSize_x;
189         me.columnMapOrigin = me.columnNameOrigin + me.columnNameSize + me.realFontSize_x;
190         me.columnPlayersOrigin = me.columnMapOrigin + me.columnMapSize + me.realFontSize_x;
191
192         me.positionSortButton(me, me.sortButton1, me.columnPingOrigin, me.columnPingSize, "Ping", ServerList_PingSort_Click);
193         me.positionSortButton(me, me.sortButton2, me.columnNameOrigin, me.columnNameSize, "Host name", ServerList_NameSort_Click);
194         me.positionSortButton(me, me.sortButton3, me.columnMapOrigin, me.columnMapSize, "Map", ServerList_MapSort_Click);
195         me.positionSortButton(me, me.sortButton4, me.columnPlayersOrigin, me.columnPlayersSize, "Players", ServerList_PlayerSort_Click);
196
197         float f;
198         f = me.currentSortField;
199         me.currentSortField = -1;
200         me.setSortOrder(me, f, me.currentSortOrder); // force resetting the sort order
201 }
202 void ServerList_Connect_Click(entity btn, entity me)
203 {
204         if(me.nItems > 0)
205                 localcmd("connect ", me.selectedServer, "\n");
206 }
207 void ServerList_Refresh_Click(entity btn, entity me)
208 {
209         refreshhostcache();
210 }
211 void clickListBoxItemNexuizServerList(entity me, float i, vector where)
212 {
213         if(i == me.lastClickedServer)
214                 if(time < me.lastClickedTime + 0.3)
215                 {
216                         // DOUBLE CLICK!
217                         ServerList_Connect_Click(NULL, me);
218                 }
219         me.lastClickedServer = i;
220         me.lastClickedTime = time;
221 }
222 void drawListBoxItemNexuizServerList(entity me, float i, vector absSize, float isSelected)
223 {
224         // layout: Ping, Server name, Map name, NP, TP, MP
225         string s;
226         float p;
227         vector theColor;
228         float theAlpha;
229
230         if(isSelected)
231                 draw_Fill('0 0 0', '1 1 0', '0 0 1', 0.5);
232
233         if(gethostcachenumber(SLIST_FIELD_NUMPLAYERS, i) >= gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i))
234                 theAlpha = 0.2;
235         else if(!gethostcachenumber(SLIST_FIELD_NUMHUMANS, i))
236                 theAlpha = 0.5;
237         else
238                 theAlpha = 1;
239         
240         p = gethostcachenumber(SLIST_FIELD_PING, i);
241         if(p < 50)
242                 theColor = eX * (p / 50) + eY;
243         else if(p < 150)
244                 theColor = eX + eY * ((150 - p) / 100);
245         else if(p < 650)
246         {
247                 theColor = eX;
248                 theAlpha *= 0.1 + 0.9 * (650 - p) / 500;
249         }
250         else
251         {
252                 theColor = eX;
253                 theAlpha *= 0.1;
254         }
255         
256         s = ftos(p);
257         draw_Text(me.realUpperMargin * eY + (me.columnPingSize - draw_TextWidth(s) * me.realFontSize_x) * eX, s, me.realFontSize, theColor, theAlpha);
258         s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_NAME, i), me.columnNameSize / me.realFontSize_x);
259         draw_Text(me.realUpperMargin * eY + me.columnNameOrigin * eX, s, me.realFontSize, theColor, theAlpha);
260         s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_MAP, i), me.columnMapSize / me.realFontSize_x);
261         draw_Text(me.realUpperMargin * eY + (me.columnMapOrigin + (me.columnMapSize - draw_TextWidth(s) * me.realFontSize_x) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha);
262         s = strcat(ftos(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i)), "/", ftos(gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i)));
263         draw_Text(me.realUpperMargin * eY + (me.columnPlayersOrigin + (me.columnPlayersSize - draw_TextWidth(s) * me.realFontSize_x) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha);
264 }
265 #endif