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