]> icculus.org git repositories - taylor/freespace2.git/blob - src/network/multi_rate.cpp
Initial revision
[taylor/freespace2.git] / src / network / multi_rate.cpp
1 /*
2  * $Logfile: /Freespace2/code/Network/multi_rate.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  * 
7  * $Log$
8  * Revision 1.1  2002/05/03 03:28:10  root
9  * Initial revision
10  *
11  * 
12  * 6     7/15/99 9:20a Andsager
13  * FS2_DEMO initial checkin
14  * 
15  * 5     4/25/99 3:02p Dave
16  * Build defines for the E3 build.
17  * 
18  * 4     4/09/99 2:21p Dave
19  * Multiplayer beta stuff. CD checking.
20  * 
21  * 3     3/20/99 5:09p Dave
22  * Fixed release build fred warnings and unhandled exception.
23  * 
24  * 2     3/09/99 6:24p Dave
25  * More work on object update revamping. Identified several sources of
26  * unnecessary bandwidth.
27  *  
28  *   
29  * $NoKeywords: $
30  */
31
32 #include "timer.h"
33 #include "2d.h"
34 #include "alphacolors.h"
35 #include "multi_rate.h"
36
37 // -----------------------------------------------------------------------------------------------------------------------
38 // MULTI RATE DEFINES/VARS
39 //
40
41 // keep this defined to compile in rate checking
42 #if !defined(NDEBUG) || defined(MULTIPLAYER_BETA_BUILD) || defined(FS2_DEMO)
43         #define MULTI_RATE
44 #endif
45
46 // how many records in the past we'll keep track of
47 #define NUM_UPDATE_RECORDS                                                      5
48
49 // rate monitoring info
50 typedef struct mr_info {
51         // type
52         char type[MAX_RATE_TYPE_LEN+1];
53
54         // all time info                
55         int total_bytes;                                                                                                // total bytes alltime
56
57         // per second info
58         int stamp_second;                                                                                               // stamp for one second
59         int bytes_second;                                                                                               // how many bytes we've sent in the last second 
60         int records_second[NUM_UPDATE_RECORDS];                         // records
61         int records_second_count;                                                                       // how many records we have
62         float avg_second;                                                                                               // avg bytes/sec
63
64         // per frame info
65         int bytes_frame;                                                                                                // how many bytes we've sent this frame 
66         int records_frame[NUM_UPDATE_RECORDS];                                  // records
67         int records_frame_count;                                                                        // how many records we have
68         float avg_frame;                                                                                                // avg bytes/frame                              
69 } mr_info;
70
71 #ifdef MULTI_RATE
72 // all records
73 mr_info Multi_rate[MAX_RATE_PLAYERS][MAX_RATE_TYPES];
74 #endif
75
76
77 // -----------------------------------------------------------------------------------------------------------------------
78 // MULTI RATE FUNCTIONS
79 //
80
81 // notify of a player join
82 void multi_rate_reset(int np_index)
83 {
84         // release builds
85 #ifndef MULTI_RATE
86         return;
87 #else
88         int idx;
89
90         // sanity checks
91         if((np_index < 0) || (np_index >= MAX_RATE_PLAYERS)){
92                 return;
93         }
94
95         // blast the index clear
96         for(idx=0; idx<MAX_RATE_TYPES; idx++){
97                 memset(&Multi_rate[np_index][idx], 0, sizeof(mr_info));
98                 Multi_rate[np_index][idx].stamp_second = -1;
99         }
100 #endif
101 }
102
103 // add data of the specified type to datarate processing, returns 0 on fail (if we ran out of types, etc, etc)
104 int multi_rate_add(int np_index, char *type, int size)
105 {       
106         // release builds
107 #ifndef MULTI_RATE
108         return 0;
109 #else
110         int idx;
111         mr_info *m;
112         // sanity checks
113         if((np_index < 0) || (np_index >= MAX_RATE_PLAYERS)){
114                 return 0;
115         }
116         if((type == NULL) || (strlen(type) <= 0)){
117                 return 0;
118         }
119
120         // see if the type already exists
121         for(idx=0; idx<MAX_RATE_TYPES; idx++){
122                 // empty slot
123                 if(strlen(Multi_rate[np_index][idx].type) <= 0){
124                         break;
125                 }
126                 // existing
127                 else if(!stricmp(Multi_rate[np_index][idx].type, type)){
128                         break;
129                 }
130         }
131
132         // if we couldn't find a slot
133         if(idx >= MAX_RATE_TYPES){
134                 return 0;
135         }
136
137         // otherwise add the data
138         m = &Multi_rate[np_index][idx];
139
140         // type string
141         strcpy(m->type, type);
142
143         // alltime
144         m->total_bytes += size;
145
146         // per-second
147         m->bytes_second += size;
148
149         // per-frame
150         m->bytes_frame += size;         
151
152         // success
153         return 1;
154 #endif
155 }
156
157 // process
158 #define R_AVG(ct, ar, avg)              do {int av_idx; float av_sum = 0.0f; if(ct == 0){ avg = 0;} else { for(av_idx=0; av_idx<ct; av_idx++){ av_sum += (float)ar[av_idx]; } avg = av_sum / (float)ct; } }while(0)
159 void multi_rate_process()
160 {
161         // release builds
162 #ifndef MULTI_RATE
163         return;
164 #else
165
166         int idx, s_idx;
167         mr_info *m;
168
169         // process all active players
170         for(idx=0; idx<MAX_RATE_PLAYERS; idx++){
171                 for(s_idx=0; s_idx<MAX_RATE_TYPES; s_idx++){
172                         m = &Multi_rate[idx][s_idx];
173
174                         // invalid entries
175                         if(strlen(m->type) <= 0){
176                                 continue;
177                         }
178
179                         // process alltime
180                         if(m->stamp_second == -1){
181                                 m->stamp_second = timestamp(1000);
182                         } else if(timestamp_elapsed(m->stamp_second)){
183                                 // if we've reached max records
184                                 if(m->records_second_count >= NUM_UPDATE_RECORDS){
185                                         memmove(m->records_second, m->records_second+1, sizeof(int) * (NUM_UPDATE_RECORDS - 1)); 
186                                         m->records_second[NUM_UPDATE_RECORDS-1] = m->bytes_second; 
187                                 }
188                                 // haven't reached max records
189                                 else {
190                                         m->records_second[m->records_second_count++] = m->bytes_second;
191                                 }
192
193                                 // recalculate the average
194                                 R_AVG(m->records_second_count, m->records_second, m->avg_second);
195
196                                 // reset bytes/second and timestamp
197                                 m->bytes_second = 0;
198                                 m->stamp_second = timestamp(1000);
199                         }
200
201                         // process per-frame
202                         // if we've reached max records
203                         if(m->records_frame_count >= NUM_UPDATE_RECORDS){
204                                 memmove(m->records_frame, m->records_frame+1, sizeof(int) * (NUM_UPDATE_RECORDS - 1)); 
205                                 m->records_frame[NUM_UPDATE_RECORDS-1] = m->bytes_frame; 
206                         }
207                         // haven't reached max records
208                         else {
209                                 m->records_frame[m->records_frame_count++] = m->bytes_frame;
210                         }
211
212                         // recalculate the average
213                         R_AVG(m->records_frame_count, m->records_frame, m->avg_frame);
214
215                         // reset bytes/frame
216                         m->bytes_frame = 0;                     
217                 }
218         }       
219 #endif
220 }
221
222 // display
223 void multi_rate_display(int np_index, int x, int y)
224 {       
225         // release builds
226 #ifndef MULTI_RATE
227         return;
228 #else
229
230         int idx;
231         mr_info *m;
232
233         // sanity checks
234         if((np_index < 0) || (np_index >= MAX_RATE_PLAYERS)){
235                 return;
236         }
237
238         // get info
239         for(idx=0; idx<MAX_RATE_TYPES; idx++){
240                 m = &Multi_rate[np_index][idx];
241
242                 // if we have a 0 length string, we're done
243                 if(strlen(m->type) <= 0){
244                         break;
245                 }
246
247                 // display
248                 gr_set_color_fast(&Color_red);
249                 gr_printf(x, y, "%s %d (%d/s) (%f/f)", m->type, m->total_bytes, (int)m->avg_second, m->avg_frame);
250                 y += 10;
251         }
252 #endif
253 }