]> icculus.org git repositories - taylor/freespace2.git/blob - src/network/multi_ping.cpp
Initial revision
[taylor/freespace2.git] / src / network / multi_ping.cpp
1 /*
2  * $Logfile: /Freespace2/code/Network/multi_ping.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  * 5     8/19/99 10:59a Dave
13  * Packet loss detection.
14  * 
15  * 4     11/17/98 11:12a Dave
16  * Removed player identification by address. Now assign explicit id #'s.
17  * 
18  * 3     11/05/98 5:55p Dave
19  * Big pass at reducing #includes
20  * 
21  * 2     10/07/98 10:53a Dave
22  * Initial checkin.
23  * 
24  * 1     10/07/98 10:50a Dave
25  * 
26  * 4     6/30/98 2:17p Dave
27  * Revised object update system. Removed updates for all weapons. Put
28  * button info back into control info packet.
29  * 
30  * 3     6/12/98 2:49p Dave
31  * Patch 1.02 changes.
32  * 
33  * 2     3/15/98 4:17p Dave
34  * Fixed oberver hud problems. Put in handy netplayer macros. Reduced size
35  * of network orientation matrices.
36  * 
37  * 1     3/03/98 5:09p Dave
38  *  
39  * $NoKeywords: $
40  */
41
42 #include "multi.h"
43 #include "multi_ping.h"
44 #include "multimsgs.h"
45 #include "timer.h"
46
47 // ------------------------------------------------------------------------------------
48 // MULTIPLAYER PING DEFINES/VARS
49 //
50
51
52 // ------------------------------------------------------------------------------------
53 // MULTIPLAYER PING FUNCTIONS
54 //
55
56 // initialize all player ping times
57 void multi_ping_reset_players()
58 {
59         int idx;
60
61         // reset the pings for all players
62         for(idx=0;idx<MAX_PLAYERS;idx++){
63                 multi_ping_reset(&Net_players[idx].s_info.ping);
64         }
65 }
66
67 // initialize the given ping struct
68 void multi_ping_reset(ping_struct *ps)
69 {
70         // blast the struct clear
71         memset(ps,0,sizeof(ping_struct));
72
73         ps->ping_add = 0;
74
75         // set the ping start to be -1
76         ps->ping_start = -1.0f;
77
78         ps->ping_avg = -1;
79
80         ps->num_pings = 0;
81 }
82
83 // evaluate a pong return on the given struct
84 void multi_ping_eval_pong(ping_struct *ps)
85 {       
86         int idx;
87         float ping_sum;
88         
89         // if the ping technically hasn't started,
90         if(ps->ping_start < 0.0f){
91                 nprintf(("Network","Processing pong for ping which hasn't started yet!\n"));
92                 return;
93         }
94         
95         // if we still have room to add a ping
96         if(ps->num_pings < MAX_PINGS){
97                 ps->ping_times[ps->ping_add++] = f2fl(timer_get_fixed_seconds()) - ps->ping_start;              
98                 ps->num_pings++;
99         } 
100         // otherwise if we've wrapped around
101         else {          
102                 // increment the place to add the ping time
103                 if(ps->ping_add >= MAX_PINGS - 1){
104                         ps->ping_add = 0;
105                 } else {
106                         ps->ping_add++;
107                 }
108
109                 ps->ping_times[ps->ping_add] = f2fl(timer_get_fixed_seconds()) - ps->ping_start;
110         }
111
112         // calculate the average ping time
113         ping_sum = 0.0f;
114         for(idx=0;idx<ps->num_pings;idx++){
115                 ping_sum += ps->ping_times[idx];
116         }
117         ps->ping_avg = (int)(1000.0f * (ping_sum / (float)ps->num_pings));      
118 }
119
120 // start a ping - call this when sending a ping packet
121 void multi_ping_start(ping_struct *ps)
122 {
123         ps->ping_start = f2fl(timer_get_fixed_seconds());
124 }
125
126 // send a ping to a specific player
127 void multi_ping_send(net_player *p)
128 {
129         multi_ping_start(&p->s_info.ping);
130         send_ping(&p->p_info.addr);
131 }
132
133 // send a ping to the specified address
134 void multi_ping_send(net_addr *addr,ping_struct *ps)
135 {
136         multi_ping_start(ps);
137         send_ping(addr);
138 }
139
140 // send a ping to all players
141 void multi_ping_send_all()
142 {
143         int idx;
144         for(idx = 0;idx < MAX_PLAYERS;idx++){
145                 if(MULTI_CONNECTED(Net_players[idx]) && (Net_player != NULL) && (Net_player->player_id != Net_players[idx].player_id)){
146                         // start the ping
147                         multi_ping_start(&Net_players[idx].s_info.ping);                        
148
149                         // send the ping packet
150                         send_ping(&Net_players[idx].p_info.addr);
151                 }
152         }
153 }
154
155 // get the lowest existing ping in the ping struct, returning -1 if no pings
156 int multi_ping_get_lowest(ping_struct *ps)
157 {
158         int idx, lowest_index;
159         float lowest;
160         
161         // if there are no recorded pings, return -1
162         if(ps->num_pings == 0){
163                 return -1;
164         }
165
166         // otherwise find the lowest
167         lowest = -1.0f;
168         for(idx=0;idx<ps->num_pings;idx++){
169                 // if we found a lower value
170                 if((lowest == -1) || (ps->ping_times[idx] < lowest)){
171                         lowest = ps->ping_times[idx];
172                         lowest_index = idx;
173                 }
174         }
175
176         // return the lowest val
177         return lowest < 0.0f ? -1 : (int)(lowest * 1000.0f)/2;
178 }
179
180 // (average ping + lowest ping)/2
181 int multi_ping_lowest_avg(ping_struct *ps)
182 {
183         int lowest = multi_ping_get_lowest(ps);
184
185         // if we couldn't get a valid lowest ping, bail
186         if(lowest == -1){
187                 return -1;
188         }
189
190         // if we have no average ping, bail
191         if(ps->ping_avg == -1){
192                 return -1;
193         }
194
195         // otherwise return the average of the 2
196         return (lowest + ps->ping_avg)/2;
197 }