]> icculus.org git repositories - taylor/freespace2.git/blob - src/network/multilag.cpp
myrand() fixes
[taylor/freespace2.git] / src / network / multilag.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/multilag.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * $Log$
16  * Revision 1.6  2004/07/04 11:39:06  taylor
17  * fix missing debrief text, crash on exit, path separator's, warning fixes, no GR_SOFT
18  *
19  * Revision 1.5  2002/06/09 04:41:24  relnev
20  * added copyright header
21  *
22  * Revision 1.4  2002/05/26 20:49:54  theoddone33
23  * More progress
24  *
25  * Revision 1.3  2002/05/26 20:22:48  theoddone33
26  * Most of network/ works
27  *
28  * Revision 1.2  2002/05/07 03:16:47  theoddone33
29  * The Great Newline Fix
30  *
31  * Revision 1.1.1.1  2002/05/03 03:28:10  root
32  * Initial import.
33  *
34  * 
35  * 4     11/19/98 8:03a Dave
36  * Full support for D3-style reliable sockets. Revamped packet lag/loss
37  * system, made it receiver side and at the lowest possible level.
38  * 
39  * 3     11/17/98 11:12a Dave
40  * Removed player identification by address. Now assign explicit id #'s.
41  * 
42  * 2     10/07/98 10:53a Dave
43  * Initial checkin.
44  * 
45  * 1     10/07/98 10:50a Dave
46  * 
47  * 15    6/05/98 9:54a Lawrance
48  * OEM changes
49  * 
50  * 14    4/27/98 6:02p Dave
51  * Modify how missile scoring works. Fixed a team select ui bug. Speed up
52  * multi_lag system. Put in new main hall.
53  * 
54  * 13    4/18/98 5:00p Dave
55  * Put in observer zoom key. Made mission sync screen more informative.
56  * 
57  * 12    4/06/98 12:37a Lawrance
58  * fix compile bug with demo
59  * 
60  * 11    4/04/98 8:42p Dave
61  * Tested and debugged UDP reliable socket layer. Modified lag system to
62  * take this into account. 
63  * 
64  * 10    4/02/98 6:29p Lawrance
65  * compile out multilag code for demo
66  * 
67  * 9     3/14/98 2:48p Dave
68  * Cleaned up observer joining code. Put in support for file xfers to
69  * ingame joiners (observers or not). Revamped and reinstalled pseudo
70  * lag/loss system.
71  * 
72  * 8     1/11/98 10:03p Allender
73  * removed <winsock.h> from headers which included it.  Made psnet_socket
74  * type which is defined just as SOCKET type is.
75  * 
76  * 7     12/29/97 5:21p Dave
77  * Put in object update sequencing for multiplayer.
78  * 
79  * 6     12/16/97 6:17p Dave
80  * Put in primary weapon support for multiplayer weapon select screen.
81  * 
82  * 5     12/10/97 4:45p Dave
83  * Added in more detailed support for multiplayer packet lag/loss. Fixed
84  * some multiplayer stuff. Added some controls to the standalone.
85  * 
86  * 4     12/01/97 4:59p Dave
87  * Synchronized multiplayer debris objects. Put in pilot popup in main
88  * hall. Optimized simulated multiplayer lag module. Fixed a potential
89  * file_xfer bug.
90  * 
91  * 3     11/28/97 7:04p Dave
92  * Emergency checkin due to big system crash.
93  * 
94  * 2     11/28/97 5:06p Dave
95  * Put in facilities for simulating multiplayer lag.
96  * 
97  * 1     11/28/97 4:38p Dave
98  * Initial Revision
99  * 
100  * $NoKeywords: $
101  */
102
103 #ifndef PLAT_UNIX
104 #include <winsock.h>
105 #include <wsipx.h>
106 #else
107 #include <sys/time.h>
108 #include <sys/types.h>
109 #include <sys/socket.h>
110 #include <netinet/in.h>
111 #include <arpa/inet.h>
112 #include <netdb.h>
113 #include <unistd.h>
114 #endif
115 #include "pstypes.h"
116 #include "multi.h"
117 #include "multilag.h"
118 #include "cmdline.h"
119 #include "timer.h"
120 #include "linklist.h"
121
122 // ----------------------------------------------------------------------------------------------------
123 // LAGLOSS DEFINES/VARS
124 //
125
126 // default LAGLOSS values
127 #define MULTI_LAGLOSS_DEF_LAG                           (-1)
128 #define MULTI_LAGLOSS_DEF_LAGMIN                        (-1)
129 #define MULTI_LAGLOSS_DEF_LAGMAX                        (-1)
130 #define MULTI_LAGLOSS_DEF_LOSS                  (-1.0f)
131 #define MULTI_LAGLOSS_DEF_LOSSMIN               (-1.0f)
132 #define MULTI_LAGLOSS_DEF_LOSSMAX               (-1.0f)
133 #define MULTI_LAGLOSS_DEF_STREAK                        (2500)
134
135 // if we're running
136 int Multi_lag_inited = 0;
137
138 // lag values (base - max and min)
139 int Multi_lag_base = -1;
140 int Multi_lag_min = -1;
141 int Multi_lag_max = -1;
142
143 // packet loss values (base - max and min)
144 float Multi_loss_base = -1.0f;
145 float Multi_loss_min = -1.0f;
146 float Multi_loss_max = -1.0f;
147
148 // streaks for lagging
149 int Multi_streak_stamp = -1;                            // timestamp telling when the streak of a certain lag is done
150 int Multi_streak_time = 0;                                      // how long each streak will last
151 int Multi_current_streak = -1;                  // what lag the current streak has
152
153 // struct for buffering stuff on receives
154 typedef struct lag_buf {
155         ubyte data[700];                                                        // the data from the packet
156         int data_len;                                                           // length of the data
157         uint socket;                                                            // this can be either a PSNET_SOCKET or a PSNET_SOCKET_RELIABLE
158         int stamp;                                                                      // when this expires, make this packet available        
159         SOCKADDR_IN ip_addr;                                            // ip address when in TCP
160 #ifndef PLAT_UNIX
161         SOCKADDR_IPX ipx_addr;                                  // ipx address when in IPX mode
162 #endif
163
164         struct  lag_buf * prev;                         // prev in the list
165         struct  lag_buf * next;                         // next in the list
166 } lag_buf;
167
168 // lag buffers - malloced
169 #ifdef NDEBUG
170         #define MAX_LAG_BUFFERS                 1               // only 1 buffer in non-debug builds
171 #else
172         #define MAX_LAG_BUFFERS                 1000
173 #endif
174 lag_buf *Lag_buffers[MAX_LAG_BUFFERS];
175 int Lag_buf_count = 0;                                          // how many lag_buf's are currently in use
176
177 lag_buf Lag_free_list;
178 lag_buf Lag_used_list;
179
180
181 // ----------------------------------------------------------------------------------------------------
182 // LAGLOSS FORWARD DECLARATIONS
183 //
184
185 // get a value to lag a packet with (in ms)
186 int multi_lag_get_random_lag();
187
188 // boolean yes or no - should this packet be lost?
189 int multi_lag_should_be_lost();             
190
191 // get a free packet buffer, return NULL on fail
192 lag_buf *multi_lag_get_free();
193
194 // put a lag buffer back
195 void multi_lag_put_free(lag_buf *buf);
196
197 // ----------------------------------------------------------------------------------------------------
198 // LAGLOSS FUNCTIONS
199 //
200
201 void multi_lag_init()
202 {       
203         // never do lag in a non-debug build
204 #if defined(NDEBUG) || !defined(MULTI_USE_LAG)
205         Multi_lag_inited = 0;
206 #else
207         int idx;
208
209         // if we're already inited, don't do anything
210         if(Multi_lag_inited){
211                 return;
212         }
213
214         // try and allocate lag bufs
215         for(idx=0; idx<MAX_LAG_BUFFERS; idx++){
216                 Lag_buffers[idx] = (lag_buf*)malloc(sizeof(lag_buf));
217                 if(Lag_buffers[idx] == NULL){
218                         return;
219                 }
220         }
221
222         // initialize lag buffer lists
223         list_init( &Lag_free_list );
224         list_init( &Lag_used_list );
225
226         // Link all object slots into the free list
227         for (idx=0; idx<MAX_LAG_BUFFERS; idx++) {
228                 list_append(&Lag_free_list, Lag_buffers[idx]);
229         }
230         
231         // set the default lag values
232         Multi_lag_base = MULTI_LAGLOSS_DEF_LAG;
233         Multi_lag_min = MULTI_LAGLOSS_DEF_LAGMIN;
234         Multi_lag_max = MULTI_LAGLOSS_DEF_LAGMAX;
235
236         // set the default loss values
237         Multi_loss_base = MULTI_LAGLOSS_DEF_LOSS;
238         Multi_loss_min  = MULTI_LAGLOSS_DEF_LOSSMIN;
239         Multi_loss_max = MULTI_LAGLOSS_DEF_LOSSMAX;
240
241         // set the default lag streak time      
242         Multi_streak_time = MULTI_LAGLOSS_DEF_STREAK;
243         
244         Multi_lag_inited = 1;
245 #endif
246 }
247
248 void multi_lag_close()
249 {       
250         int idx;
251
252         // if we're not inited already, don't do anything
253         if(!Multi_lag_inited){
254                 return;
255         }       
256
257         // free up lag buffers
258         for(idx=0; idx<MAX_LAG_BUFFERS; idx++){
259                 if(Lag_buffers[idx] != NULL){
260                         free(Lag_buffers[idx]);
261                         Lag_buffers[idx] = NULL;
262                 }
263         }
264
265         Multi_lag_inited = 0;
266 }
267
268 // select for multi_lag
269 int multi_lag_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *except_fds, timeval *timeout)
270 {               
271 #ifdef PLAT_UNIX
272         STUB_FUNCTION;
273 #else
274         char t_buf[1024];
275         int t_from_len;
276         SOCKADDR_IN ip_addr;
277 #ifndef PLAT_UNIX
278         SOCKADDR_IPX ipx_addr;
279 #endif
280         int ret_val;
281         lag_buf *moveup, *item;
282
283         Assert(readfds != NULL);
284         Assert(writefds == NULL);
285         Assert(except_fds == NULL);
286
287         // clear out addresses
288         memset(&ip_addr, 0, sizeof(SOCKADDR_IN));
289 #ifndef PLAT_UNIX
290         memset(&ipx_addr, 0, sizeof(SOCKADDR_IPX));
291 #endif
292
293         // if there's data on the socket, read it
294         if(select(nfds, readfds, writefds, except_fds, timeout)){               
295                 // read the data and stuff it
296                 if(Tcp_active){                                         
297                         t_from_len = sizeof(SOCKADDR_IN);
298                         ret_val = recvfrom(readfds->fd_array[0], t_buf, 1024, 0, (SOCKADDR*)&ip_addr, &t_from_len);
299 #ifndef PLAT_UNIX
300                 } else {
301                         t_from_len = sizeof(SOCKADDR_IPX);
302                         ret_val = recvfrom(readfds->fd_array[0], t_buf, 1024, 0, (SOCKADDR*)&ipx_addr, &t_from_len);
303 #endif
304                 }
305                         
306                 // wacky socket error
307                 if(ret_val == SOCKET_ERROR){
308                         return SOCKET_ERROR;
309                 }
310
311                 // if we should be dropping this packet
312                 if(!multi_lag_should_be_lost()){
313                         // get a free packet buf and stuff the data
314                         item = multi_lag_get_free();
315                         if(item){
316                                 Assert(ret_val < 700);
317                                 memcpy(item->data, t_buf, ret_val);                     
318                                 item->data_len = ret_val;
319                                 item->ip_addr = ip_addr;
320 #ifndef PLAT_UNIX
321                                 item->ipx_addr = ipx_addr;
322 #endif
323                                 item->socket = readfds->fd_array[0];
324                                 item->stamp = timestamp(multi_lag_get_random_lag());
325                         }               
326                 }
327         }
328
329         // always unset the readfds
330         readfds->fd_count = 0;
331
332         // now determine if we have any pending packets - find the first one
333         // NOTE : this _could_ be the packet we just read. In fact, with a 0 lag, this will always be the case
334         moveup=GET_FIRST(&Lag_used_list);
335         while ( moveup!=END_OF_LIST(&Lag_used_list) )   {               
336                 // if the timestamp has elapsed and we have a matching socket
337                 if((readfds->fd_array[0] == (SOCKET)moveup->socket) && ((moveup->stamp <= 0) || timestamp_elapsed(moveup->stamp))){
338                         // set this so we think select returned yes
339                         readfds->fd_count = 1;
340                         return 1;
341                 }
342
343                 moveup = GET_NEXT(moveup);
344         }
345
346 #endif
347         // no data
348         return 0;
349 }
350
351 // recvfrom for multilag
352 int multi_lag_recvfrom(uint s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen)
353 {
354         lag_buf *moveup = NULL;
355         lag_buf *item = NULL;
356
357         // now determine if we have any pending packets - find the first one
358         moveup=GET_FIRST(&Lag_used_list);
359         while ( moveup!=END_OF_LIST(&Lag_used_list) )   {               
360                 // if the timestamp has elapsed
361                 if(((int)s == (SOCKET)moveup->socket) && ((moveup->stamp <= 0) || timestamp_elapsed(moveup->stamp))){
362                         item = moveup;
363                         break;
364                 }
365
366                 moveup = GET_NEXT(moveup);
367         }
368
369         // if this happens, it means that the multi_lag_select() returned an improper value
370         Assert(item);
371         // stuff the data
372         Assert(item->data_len <= len);
373         memcpy(buf, item->data, item->data_len);
374         if(Tcp_active){
375                 memcpy(from, &item->ip_addr, sizeof(SOCKADDR_IN));
376 #ifndef PLAT_UNIX
377         } else {
378                 memcpy(from, &item->ipx_addr, sizeof(SOCKADDR_IPX));
379 #endif
380         }
381
382         // stick the item back on the free list
383         multi_lag_put_free(item);
384
385         // return the size in bytes
386         return item->data_len;
387 }
388
389 // ----------------------------------------------------------------------------------------------------
390 // LAGLOSS FORWARD DEFINITIONS
391 //
392
393 int multi_lag_get_random_lag()
394 {
395         // first determine the percentage we'll be checking against
396         int ret;
397         int mod;        
398
399         // if the lag system isn't inited, don't do anything (no lag)
400         if(!Multi_lag_inited){
401                 return 0;
402         }
403                 
404         // pick a value
405         // see if we should be going up or down (loss max/loss min)
406         mod = 0;
407         if((float)myrand()/(float)MY_RAND_MAX < 0.5){
408                 // down
409                 if(Multi_lag_min >= 0){
410                         mod = - (int)((float)(Multi_lag_base - Multi_lag_min) * ((float)myrand()/(float)MY_RAND_MAX));
411                 }
412         } else {
413                 // up
414                 if(Multi_lag_max >= 0){
415                         mod = (int)((float)(Multi_lag_max - Multi_lag_base) * ((float)myrand()/(float)MY_RAND_MAX));
416                 }
417         }
418         
419         // if the current streak has elapsed, calculate a new one
420         if((Multi_streak_stamp == -1) || (timestamp_elapsed(Multi_streak_stamp))){
421                 // timestamp the new streak
422                 Multi_streak_stamp = timestamp(Multi_streak_time);
423
424                 // set the return value
425                 ret = Multi_lag_base + mod;
426                 
427                 // set the lag value of this current streak
428                 Multi_current_streak = ret;
429         } 
430         // otherwise use the lag for the current streak
431         else {
432                 ret = Multi_current_streak;
433         }
434                         
435         return ret;     
436 }
437
438 // this _may_ be a bit heavyweight, but it _is_ debug code
439 int multi_lag_should_be_lost()
440 {       
441         // first determine the percentage we'll be checking against
442         float mod;      
443
444         // if the lag system isn't inited, don't do anything
445         if(!Multi_lag_inited){
446                 return 0;
447         }
448                 
449         // see if we should be going up or down (loss max/loss min)
450         mod = 0.0f;
451         if((float)myrand()/(float)MY_RAND_MAX < 0.5){
452                 // down
453                 if(Multi_loss_min >= 0.0f){
454                         mod = - ((Multi_loss_base - Multi_loss_min) * ((float)myrand()/(float)MY_RAND_MAX));
455                 }
456         } else {
457                 // up
458                 if(Multi_loss_max >= 0.0f){
459                         mod = ((Multi_loss_max - Multi_loss_base) * ((float)myrand()/(float)MY_RAND_MAX));
460                 }
461         }       
462         
463         if((float)myrand()/(float)MY_RAND_MAX <= Multi_loss_base + mod){
464                 return 1;
465         }       
466
467         return 0;
468 }
469
470 // get a free packet buffer, return NULL on fail
471 lag_buf *multi_lag_get_free()
472 {
473         lag_buf *lagp;
474
475         // if we're out of buffers
476         if(Lag_buf_count >= MAX_LAG_BUFFERS){
477                 nprintf(("Network", "Out of lag buffers!\n"));
478                 return NULL;
479         }
480
481         // get a free item
482         lagp = GET_FIRST(&Lag_free_list);
483         Assert( lagp != &Lag_free_list );               // shouldn't have the dummy element
484
485         // remove trailp from the free list
486         list_remove( &Lag_free_list, lagp );
487         
488         // insert trailp onto the end of used list
489         list_append( &Lag_used_list, lagp );
490
491         // increase the count
492         Lag_buf_count++;
493         return lagp;
494 }
495
496 // put a lag buffer back
497 void multi_lag_put_free(lag_buf *buf)
498 {
499         // remove objp from the used list
500         list_remove( &Lag_used_list, buf);
501
502         // add objp to the end of the free
503         list_append( &Lag_free_list, buf );
504
505         // decrement counter
506         Lag_buf_count--;
507 }
508
509 void multi_lagloss_dcf()
510 {
511         // if the lag system isn't inited, don't do anything
512         if(!Multi_lag_inited){
513                 dc_printf("Lag System Not Initialized!\n");
514                 return;
515         }
516
517         // display all available commands
518         dc_printf("Usage :\nlag <ms>  (-1 to disable)\nlag_min <ms>\nlag_max <ms>\nloss <0-100>  (-1 to disable)\nloss_min <0-100>\nloss_max <0-100>\nlag_streak <ms>\nlagloss\n");
519
520         // display lag settings
521         dc_printf("Lag : ");            
522         dc_printf("\n   Base %d\n   Min %d\n   Max %d\n   Streak %d\n", Multi_lag_base, Multi_lag_min, Multi_lag_max, Multi_streak_time);       
523
524         // display loss settings
525         dc_printf("Loss : ");           
526         dc_printf("\n   Base %f\n   Min %f\n   Max %f\n", Multi_loss_base, Multi_loss_min, Multi_loss_max);     
527 }
528
529 DCF(lag, "")
530 {
531         // if the lag system isn't inited, don't do anything
532         if(!Multi_lag_inited){
533                 dc_printf("Lag System Not Initialized!\n");
534                 return;
535         }
536
537         dc_get_arg(ARG_INT);            
538         // parse the argument and change things around accordingly
539         if(Dc_arg_type & ARG_INT){                      
540                 if(Dc_arg_int < 0){
541                         // switch the lag sim off
542                         Multi_lag_base = -1;
543                         Multi_lag_min = -1;
544                         Multi_lag_max = -1;
545                         dc_printf("Turning simulated lag off\n");
546                         multi_lagloss_dcf();
547                 } else if((Multi_lag_max >= 0) && (Dc_arg_int > Multi_lag_max)){
548                         dc_printf("Base value greater than max value, ignoring...");
549                 } else if((Multi_lag_min >= 0) && (Dc_arg_int < Multi_lag_min)){
550                         dc_printf("Base value smaller than min value, ignoring...");
551                 } else {
552                         Multi_lag_base = Dc_arg_int;
553                         multi_lagloss_dcf();
554                 }
555         }       
556 }
557
558 DCF(lag_min, "")
559 {
560         // if the lag system isn't inited, don't do anything
561         if(!Multi_lag_inited){
562                 dc_printf("Lag System Not Initialized!\n");
563                 return;
564         }
565
566         dc_get_arg(ARG_INT);            
567         // parse the argument and change things around accordingly
568         if(Dc_arg_type & ARG_INT){                      
569                 if(Dc_arg_int > Multi_lag_base){
570                         dc_printf("Min value greater than base value, ignoring...");
571                 } else {
572                         if(Dc_arg_int < 0){
573                                 Multi_lag_min = -1;
574                         } else {
575                                 Multi_lag_min = Dc_arg_int;
576                         }
577                         multi_lagloss_dcf();
578                 }
579         }                       
580 }
581
582 DCF(lag_max, "")
583 {
584         // if the lag system isn't inited, don't do anything
585         if(!Multi_lag_inited){
586                 dc_printf("Lag System Not Initialized!\n");
587                 return;
588         }
589
590         // parse the argument and change things around accordingly
591         dc_get_arg(ARG_INT);
592         if(Dc_arg_type & ARG_INT){                      
593                 if((Dc_arg >=0) && (Dc_arg_int < Multi_lag_base)){
594                         dc_printf("Max value smaller than base value, ignoring...");
595                 } else {
596                         if(Dc_arg_int < 0){
597                                 Multi_lag_max = -1;
598                         } else {
599                                 Multi_lag_max = Dc_arg_int;
600                         }
601                         multi_lagloss_dcf();
602                 }
603         }               
604 }
605
606 DCF(loss, "")
607 {
608         // if the lag system isn't inited, don't do anything
609         if(!Multi_lag_inited){
610                 dc_printf("Lag System Not Initialized!\n");
611                 return;
612         }
613
614         // parse the argument and change things around accordingly
615         dc_get_arg(ARG_INT);
616         if(Dc_arg_type & ARG_INT){
617                 float val = (float)Dc_arg_int / 100.0f;
618                         
619                 if(Dc_arg_int > 100){
620                         dc_printf("Illegal loss base value, ignoring...");
621                 } else if(Dc_arg_int < 0){
622                         // switch the loss sim off
623                         dc_printf("Turning simulated loss off\n");
624                         Multi_loss_base = -1.0f;
625                         Multi_loss_min = -1.0f;
626                         Multi_loss_max = -1.0f;
627                         multi_lagloss_dcf();
628                 } else if((Multi_loss_max >= 0.0f) && (val > Multi_loss_max)){
629                         dc_printf("Base value greater than max value, ignoring...");
630                 } else if((Multi_loss_min >= 0.0f) && (val < Multi_loss_min)){
631                         dc_printf("Base value smaller than min value, ignoring...");
632                 } else {
633                         Multi_loss_base = val;
634                         multi_lagloss_dcf();
635                 }
636         }                       
637 }
638
639 DCF(loss_min, "")
640 {
641         // if the lag system isn't inited, don't do anything
642         if(!Multi_lag_inited){
643                 dc_printf("Lag System Not Initialized!\n");
644                 return;
645         }
646
647         // parse the argument and change things around accordingly
648         dc_get_arg(ARG_INT);
649         if(Dc_arg_type & ARG_INT){                      
650       float val = (float)Dc_arg_int / 100.0f;
651
652                 if(val > Multi_loss_base){
653                         dc_printf("Min value greater than base value, ignoring...");
654                 } else {
655                         // otherwise set the value
656                         if(Dc_arg_int < 0){
657                                 Multi_loss_min = -1.0f;
658                         } else {
659                                 Multi_loss_min = val;
660                         }
661                         multi_lagloss_dcf();
662                 }
663         }
664 }
665
666 DCF(loss_max, "")
667 {       
668         // if the lag system isn't inited, don't do anything
669         if(!Multi_lag_inited){
670                 dc_printf("Lag System Not Initialized!\n");
671                 return;
672         }
673
674         // parse the argument and change things around accordingly
675         dc_get_arg(ARG_INT);
676         if(Dc_arg_type & ARG_INT){                      
677       float val = (float)Dc_arg_int / 100.0f;
678
679                 if(val < Multi_loss_base){
680                         dc_printf("Max value smaller than base value, ignoring...");
681                 } else {
682                         // otherwise set the value
683                         if(Dc_arg_int < 0){
684                                 Multi_loss_max = -1.0f;
685                         } else {
686                                 Multi_loss_min = val;
687                         }
688                         multi_lagloss_dcf();
689                 }
690         }                       
691 }
692
693 DCF(lagloss, "")
694 {
695         // if the lag system isn't inited, don't do anything
696         if(!Multi_lag_inited){
697                 dc_printf("Lag System Not Initialized!\n");
698                 return;
699         }
700
701         multi_lagloss_dcf();
702 }
703
704 DCF(lag_streak, "")
705 {
706         // if the lag system isn't inited, don't do anything
707         if(!Multi_lag_inited){
708                 dc_printf("Lag System Not Initialized!\n");
709                 return;
710         }
711
712         dc_get_arg(ARG_INT);
713         if(Dc_arg_type & ARG_INT){                                      
714                 if(Dc_arg_int >= 0){
715                         Multi_streak_time = Dc_arg_int;
716                 } 
717         }
718 }
719
720 DCF(lag_bad, "")
721 {
722         // if the lag system isn't inited, don't do anything
723         if(!Multi_lag_inited){
724                 dc_printf("Lag System Not Initialized!\n");
725                 return;
726         }
727
728         dc_printf("Setting bad lag/loss parameters\n");
729
730         // set good lagloss parameters
731         Multi_lag_base = 500;
732         Multi_lag_min = 400;
733         Multi_lag_max = 600;
734         
735         Multi_loss_base = 0.2f;
736         Multi_loss_min = 0.15f;
737         Multi_loss_max = 0.23f;
738
739         Multi_streak_time = 800;
740         Multi_streak_stamp = -1;
741         Multi_current_streak = -1;
742 }
743
744 DCF(lag_avg, "")
745 {
746         // if the lag system isn't inited, don't do anything
747         if(!Multi_lag_inited){
748                 dc_printf("Lag System Not Initialized!\n");
749                 return;
750         }
751
752         dc_printf("Setting avg lag/loss parameters\n");
753
754         // set good lagloss parameters
755         Multi_lag_base = 275;
756         Multi_lag_min = 200;
757         Multi_lag_max = 400;
758         
759         Multi_loss_base = 0.15f;
760         Multi_loss_min = 0.1f;
761         Multi_loss_max = 0.20f;
762
763         Multi_streak_time = 900;
764         Multi_streak_stamp = -1;
765         Multi_current_streak = -1;
766 }
767
768 DCF(lag_good, "")
769 {
770         // if the lag system isn't inited, don't do anything
771         if(!Multi_lag_inited){
772                 dc_printf("Lag System Not Initialized!\n");
773                 return;
774         }
775
776         dc_printf("Setting good lag/loss parameters\n");
777
778         // set good lagloss parameters
779         Multi_lag_base = 100;
780         Multi_lag_min = 35;
781         Multi_lag_max = 200;
782         
783         Multi_loss_base = 0.08f;
784         Multi_loss_min = 0.0f;
785         Multi_loss_max = 0.1f;
786
787         Multi_streak_time = 1000;
788         Multi_streak_stamp = -1;
789         Multi_current_streak = -1;
790 }
791