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