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