1 /*
2 Copyright (C) 1994-1995 Apogee Software, Ltd.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21 #include <string.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <fcntl.h>
25
26 #ifdef DOS
27 #include <dos.h>
28 #include <io.h>
29 #endif
30
31 #include "rt_def.h"
32 #include "rt_main.h"
33 #include "rt_net.h"
34 #include "rt_com.h"
35 #include "_rt_net.h"
36 #include "rt_actor.h"
37 #include "rt_playr.h"
38 #include "isr.h"
39 #include "z_zone.h"
40 #include "develop.h"
41 #include "rottnet.h"
42 #include "rt_msg.h"
43 #include "rt_sound.h"
44 #include "rt_menu.h"
45 #include "rt_util.h"
46 #include "rt_rand.h"
47 #include "rt_game.h"
48 #include "rt_draw.h"
49 #include "myprint.h"
50 #include "rt_debug.h"
51 #include "rt_view.h"
52 #include "rt_battl.h"
53 #include "rt_dmand.h"
54 //MED
55 #include "memcheck.h"
56
57 #if (SYNCCHECK == 1)
58 int lastsynccheck;
59 COM_CheckSyncType PlayerSync[MAXPLAYERS];
60 #endif
61
62
63 CommandType * LocalCmds;
64 CommandType * ServerCmds;
65
66
67 int controlupdatestartedtime=-1;
68 int controlupdatetime=-1;
69 int serverupdatetime=-1;
70 int controlupdatestarted=0;
71 boolean GamePaused=false;
72
73 boolean modemgame;
74 boolean networkgame;
75 int numplayers;
76 int server;
77 boolean IsServer;
78 boolean standalone;
79 boolean restartgame=false;
80 boolean respawnactive=false;
81 boolean playerdead=false;
82 boolean controlschanged=true;
83 boolean battlegibs=false;
84 boolean remoteridicule = false;
85 /*
86 =============================================================================
87
88 LOCAL FUNCTION PROTOTYPES and VARIABLES
89
90 =============================================================================
91 */
92 boolean demorecord,
93 demoplayback;
94 byte *demoptr,
95 *lastdemoptr,
96 *demobuffer=NULL;
97 boolean demodone = false;
98 int oldmomx;
99 int oldmomy;
100 int oldspdang;
101
102 static boolean GameCommandsStarted=false;
103
104 static int oldcontrolbuf[3];
105 static int oldbuttonbits;
106 static CommandType * PlayerCmds[MAXPLAYERS];
107 static CommandType * ClientCmds[MAXPLAYERS];
108
109 static boolean GotPlayersDesc[MAXPLAYERS];
110 static boolean PlayersReady[MAXPLAYERS];
111 static int LastCommandTime[MAXPLAYERS];
112
113 static CommandStatusType * CommandState[MAXPLAYERS+1];
114
115 static boolean InProcessServer=false;
116 static int lastcontrolupdatetime;
117 static int largesttime;
118 static int PlayerStatus[MAXPLAYERS];
119 //static int syncservertime;
120 //static boolean FixingPackets;
121 static int controldivisor=1;
122 static int nextupdatetime;
123 static boolean UpdateServer=true;
124
125 void CheckForPacket ( void );
126 void PrepareLocalPacket ( void );
127 void SendSyncCheckPacket ( void );
128 void AddModemSubPacket(void * incoming);
129 void SetPlayerDescription( void * pkt );
130 void UpdateDemoPlayback (int time);
131 int GetTypeSize (int type);
132 int MaxSpeedForCharacter(playertype *pstate);
133
134 /*
135 =============================================================================
136
137 Game Command Section
138
139 =============================================================================
140 */
141
142 //****************************************************************************
143 //
144 // ComError ()
145 //
146 //****************************************************************************
147
148 #define ComError SoftError
149 #if 0
150 void ComError (char *error, ...)
151 {
152 #if 0
153 va_list argptr;
154 #endif
155
156 SoftError(error);
157 #if 0
158 if (standalone==true)
159 {
160 va_start (argptr, error);
161 vprintf (error, argptr);
162 va_end (argptr);
163 }
164 #endif
165 }
166 #endif
167
168 //****************************************************************************
169 //
170 // ConsoleIsServer()
171 //
172 //****************************************************************************
ConsoleIsServer(void)173 boolean ConsoleIsServer ( void )
174 {
175 if (modemgame==true)
176 {
177 if (networkgame==true)
178 {
179 if (rottcom->client==0)
180 {
181 return true;
182 }
183 }
184 }
185 return false;
186 }
187
188 //****************************************************************************
189 //
190 // GamePacketSize()
191 //
192 //****************************************************************************
GamePacketSize(void)193 int GamePacketSize( void )
194 {
195 if ((remoteridicule == true) || (ConsoleIsServer() == true))
196 {
197 return GetTypeSize(COM_SOUNDANDDELTA);
198 }
199 else
200 return GetTypeSize(COM_TEXT);
201 }
202
203 //****************************************************************************
204 //
205 // InitializeGameCommands()
206 //
207 //****************************************************************************
InitializeGameCommands(void)208 void InitializeGameCommands( void )
209 {
210 int i;
211 int j;
212
213 // default to player 0
214
215 if (GameCommandsStarted==true)
216 return;
217
218 GameCommandsStarted=true;
219
220 if ((modemgame==true))
221 controldivisor=rottcom->ticstep;
222
223 standalone=false;
224 IsServer=false;
225
226 if (modemgame==true)
227 {
228 consoleplayer=rottcom->consoleplayer;
229
230 if (networkgame==true)
231 {
232 if (rottcom->client==0)
233 {
234 IsServer=true;
235 // turn it on absolutely for the server
236 remoteridicule = true;
237 if (consoleplayer==0)
238 standalone=true;
239 }
240 if (consoleplayer>0)
241 consoleplayer--; // playernumber fixup
242 }
243 }
244
245 if (standalone==false)
246 {
247 int size;
248
249 size = GamePacketSize ();
250
251 for (i=0;i<numplayers;i++)
252 {
253 PlayerCmds[i]=(CommandType *)SafeLevelMalloc(sizeof(CommandType));
254 for (j=0;j<MAXCMDS;j++)
255 {
256 PlayerCommand(i,j)=SafeLevelMalloc(size);
257 }
258 }
259 }
260
261
262 // allocate local commands
263
264 LocalCmds=(CommandType *)SafeLevelMalloc(sizeof(CommandType));
265 for (j=0;j<MAXCMDS;j++)
266 {
267 int size;
268
269 size = GamePacketSize();
270
271 LocalCommand(j)=SafeLevelMalloc(size);
272 memset(LocalCommand(j),COM_DELTANULL,size);
273 }
274
275 CommandState[0]=(CommandStatusType *)SafeLevelMalloc(sizeof(CommandStatusType));
276
277 if (modemgame==true)
278 {
279 for (i=0;i<numplayers;i++)
280 {
281 PlayerStatus[i]=player_ingame;
282 }
283 if (networkgame==true)
284 {
285 server=1;
286
287 // initialize the Server
288
289 if (IsServer==true)
290 {
291 server=0;
292 ServerCmds=(CommandType *)SafeMalloc(sizeof(CommandType));
293 for (j=0;j<MAXCMDS;j++)
294 {
295 int size;
296 size=( (numplayers * GetTypeSize(COM_TEXT)) +
297 GetTypeSize(COM_SOUNDANDDELTA) +
298 sizeof(COM_ServerHeaderType) -
299 sizeof(byte)
300 );
301 ServerCommand(j)=SafeMalloc( size );
302 memset(ServerCommand(j),COM_DELTANULL,size);
303 }
304 for (i=1;i<=numplayers;i++)
305 {
306 CommandState[i]=(CommandStatusType *)
307 SafeMalloc(sizeof(CommandStatusType));
308 }
309 for (i=0;i<numplayers;i++)
310 {
311 ClientCmds[i]=(CommandType *)SafeMalloc(sizeof(CommandType));
312 for (j=0;j<MAXCMDS;j++)
313 {
314 int size;
315
316 size=GetTypeSize(COM_SOUNDANDDELTA);
317 ClientCommand(i,j)=SafeMalloc(size);
318 memset(ClientCommand(i,j),COM_DELTANULL,size);
319 }
320 }
321 }
322 }
323 else // must be a two player game
324 {
325 server=consoleplayer^1;
326 }
327 }
328 #if 0
329 #if (DEVELOPMENT == 1)
330 if (IsServer)
331 ComError("I am the server\n");
332 ComError("consoleplayer=%ld\n",consoleplayer);
333 ComError("server=%ld mynumber=%ld\n",server,consoleplayer);
334 #endif
335 #endif
336 }
337
338
339 //****************************************************************************
340 //
341 // ShutdownGameCommands()
342 //
343 //****************************************************************************
ShutdownGameCommands(void)344 void ShutdownGameCommands( void )
345 {
346 int i;
347 int j;
348
349 if (GameCommandsStarted==false)
350 return;
351
352 GameCommandsStarted=false;
353
354 // free up playercmds;
355 if (standalone==false)
356 {
357 for (i=0;i<numplayers;i++)
358 {
359 for (j=0;j<MAXCMDS;j++)
360 {
361 if (PlayerCommand(i,j))
362 {
363 SafeFree(PlayerCommand(i,j));
364 PlayerCommand(i,j)=NULL;
365 }
366 }
367 SafeFree( PlayerCmds[i] );
368 PlayerCmds[i]=NULL;
369 }
370 }
371
372 // free up command status
373
374 SafeFree(CommandState[0]);
375 CommandState[0]=NULL;
376
377 if (modemgame==true)
378 {
379
380 // free up local commands
381
382 for (j=0;j<MAXCMDS;j++)
383 {
384 if (LocalCommand(j))
385 {
386 SafeFree(LocalCommand(j));
387 LocalCommand(j)=NULL;
388 }
389 }
390 SafeFree(LocalCmds);
391 LocalCmds=NULL;
392
393
394 // free up Server
395
396 if (networkgame==true)
397 {
398 if (IsServer==true)
399 {
400 for (j=0;j<MAXCMDS;j++)
401 {
402 if (ServerCommand(j))
403 {
404 SafeFree(ServerCommand(j));
405 ServerCommand(j)=NULL;
406 }
407 }
408 SafeFree(ServerCmds);
409 ServerCmds=NULL;
410 for (i=1;i<=numplayers;i++)
411 {
412 SafeFree(CommandState[i]);
413 CommandState[i]=NULL;
414 }
415 for (i=0;i<numplayers;i++)
416 {
417 for (j=0;j<MAXCMDS;j++)
418 {
419 if (ClientCommand(i,j))
420 {
421 SafeFree(ClientCommand(i,j));
422 ClientCommand(i,j)=NULL;
423 }
424 }
425 SafeFree( ClientCmds[i] );
426 ClientCmds[i]=NULL;
427 }
428 }
429 }
430 }
431 }
432
433
434
435
436 /*
437 =============================================================================
438
439 Client Controls Section
440
441 =============================================================================
442 */
443
444
445 //****************************************************************************
446 //
447 // ShutdownClientControls ()
448 //
449 //****************************************************************************
450
ShutdownClientControls(void)451 void ShutdownClientControls ( void )
452 {
453 int i;
454 #if (DEVELOPMENT == 1)
455 SoftError ("LARGEST time difference=%ld\n",largesttime);
456 #endif
457 controlupdatestarted=0;
458 for (i=0;i<numplayers;i++)
459 {
460 if (PlayerStatus[i] == player_leftgame)
461 PlayerStatus[i]=player_ingame;
462 }
463 }
464
465
466 //****************************************************************************
467 //
468 // StartupClientControls ()
469 //
470 //****************************************************************************
471
StartupClientControls(void)472 void StartupClientControls ( void )
473 {
474 int i,j;
475
476 if (controlupdatestarted==1)
477 return;
478
479 controlupdatestarted=1;
480
481 memset(oldcontrolbuf,-1,sizeof(oldcontrolbuf));
482 oldbuttonbits=-1;
483 controlschanged=true;
484
485 INL_GetMouseDelta(&i,&i);
486
487
488 locplayerstate->dmomx = 0;
489 locplayerstate->dmomy = 0;
490 locplayerstate->angle = 0;
491 locplayerstate->topspeed=MaxSpeedForCharacter(locplayerstate);
492
493
494 CalcTics();
495 CalcTics();
496
497 // FixingPackets=false;
498
499 memset (controlbuf, 0, sizeof (controlbuf));
500 buttonbits = 0;
501 lastpolltime=-1;
502 IN_ClearKeyboardQueue ();
503
504 if (modemgame==true)
505 {
506 controlupdatetime=controlsynctime+(VBLCOUNTER*2);
507 SoftError("Controls started at %ld\n",controlupdatetime);
508 }
509 else if (demoplayback || demorecord)
510 {
511 ISR_SetTime(20);
512 oldtime = 20;
513 controlupdatetime=20;
514 }
515 else
516 controlupdatetime=GetTicCount();
517
518 controlupdatetime-=(controlupdatetime%controldivisor);
519
520 serverupdatetime=controlupdatetime;
521 oldpolltime=controlupdatetime;
522 nextupdatetime=oldpolltime;
523 #if (SYNCCHECK == 1)
524 lastsynccheck=oldpolltime+CHECKSYNCTIME;
525 #endif
526 controlupdatestartedtime=controlupdatetime;
527
528 for( j = 0; j < numplayers; j++ )
529 {
530 memset( PLAYERSTATE[ j ].buttonheld, 0,
531 sizeof( PLAYERSTATE[ j ].buttonheld ) );
532 memset( PLAYERSTATE[ j ].buttonstate, 0,
533 sizeof( PLAYERSTATE[ j ].buttonstate ) );
534 }
535
536 for (i=0;i<MAXCMDS;i++)
537 {
538 ServerCommandNumberStatus( i ) = cs_notarrived;
539 }
540
541 LastCommandTime[0]=controlupdatetime-controldivisor;
542 if (IsServer==true)
543 {
544 int size;
545
546 UpdateServer=true;
547 size=( (numplayers * GetTypeSize(COM_TEXT)) +
548 GetTypeSize(COM_SOUNDANDDELTA) +
549 sizeof(COM_ServerHeaderType) -
550 sizeof(byte)
551 );
552
553 for (j=0;j<numplayers;j++)
554 {
555 for (i=0;i<MAXCMDS;i++)
556 {
557 ClientCommandNumberStatus( j , i ) = cs_notarrived;
558 }
559 LastCommandTime[j]=controlupdatetime-controldivisor;
560 }
561 for (i=0;i<MAXCMDS;i++)
562 memset(ServerCommand(i),COM_DELTANULL,size);
563 }
564 else if (modemgame==true)
565 {
566 int nump;
567
568 nump=numplayers;
569 if (nump<2) nump=2;
570
571 for (i=0;i<nump;i++)
572 {
573 LastCommandTime[i]=controlupdatetime-controldivisor;
574 }
575 }
576
577
578 #if (DEVELOPMENT == 1)
579 // ComError("StartupClientControls: GetTicCount()=%ld oldtime=%ld controlupdatetime=%ld\n",GetTicCount(),oldtime,controlupdatetime);
580 #endif
581
582 if ((demoplayback==false) && (standalone==false))
583 {
584 if (modemgame==true)
585 {
586 while (GetTicCount()<(controlupdatetime-10))
587 {
588 CalcTics();
589 }
590 }
591 lastcontrolupdatetime=GetTicCount();
592 largesttime=0;
593 PollControls();
594 }
595 if (standalone==true)
596 printf("Packet Server started\n");
597 }
598
599
600
601 //****************************************************************************
602 //
603 // UpdateClientControls ()
604 //
605 //****************************************************************************
606
607 static boolean InUCC=false;
UpdateClientControls(void)608 void UpdateClientControls ( void )
609 {
610 int time;
611 // int delta;
612
613 if (controlupdatestarted==0)
614 return;
615
616 if (InUCC)
617 return;
618 else
619 InUCC = true;
620
621 wami(6);
622
623 #if 0
624
625 delta=GetTicCount()-lastcontrolupdatetime;
626 if (delta>largesttime)
627 {
628 if (delta>10)
629 largesttime=delta;
630 largesttime=delta;
631 }
632
633 #endif
634 lastcontrolupdatetime=GetTicCount();
635
636 if (standalone==false)
637 {
638 time=GetTicCount();
639
640 // if we are a fixing the current packet stop update of deltas
641 // in non-network games.
642 if (
643 (networkgame == false) &&
644 (ServerCommandStatus(oldpolltime)==cs_fixing)
645 )
646 {
647 time=controlupdatetime-controldivisor;
648 }
649
650 while (time>=controlupdatetime)
651 {
652 MoveType * Delta;
653 boolean soundready;
654
655 soundready = SD_SoundDataReady();
656
657 if (demoplayback==true)
658 {
659 UpdateDemoPlayback(controlupdatetime);
660 }
661 // else
662 // {
663 // PollControls();
664 // }
665
666 if (
667 (memcmp(&controlbuf[0],&oldcontrolbuf[0],sizeof(controlbuf))!=0) ||
668 (buttonbits!=oldbuttonbits)
669 )
670 {
671 controlschanged=true;
672 memcpy(&oldcontrolbuf[0],&controlbuf[0],sizeof(controlbuf));
673 oldbuttonbits=buttonbits;
674 }
675 else
676 {
677 controlschanged=false;
678 }
679
680 if ((controlschanged==false) && (soundready==false))
681 {
682 NullMoveType * NullDelta;
683
684 NullDelta=(NullMoveType *)NextLocalCommand();
685 NullDelta->type=COM_DELTANULL;
686 }
687 else
688 {
689 Delta=(MoveType *)NextLocalCommand();
690 Delta->type=COM_DELTA;
691 Delta->momx=(controlbuf[0]>>1);
692 Delta->momy=(controlbuf[1]>>1);
693 Delta->dangle=controlbuf[2]>>11;
694 Delta->buttons=buttonbits;
695
696 // See if we need to update sound packet
697
698 if (soundready==true)
699 {
700 COM_SoundType * sndpkt;
701 recordstate status;
702
703 if (remoteridicule == false)
704 Error("Attempt to record Remote Ridicule without adequate storage");
705 sndpkt=(COM_SoundType *)Delta->Sounddata;
706
707 // Turn the packet into a COM_SOUNDANDDELTA packet
708
709 Delta->type=COM_SOUNDANDDELTA;
710 status = SD_GetSoundData ( &(sndpkt->data[0]),
711 COM_SOUND_BUFFERSIZE );
712 switch (status)
713 {
714 case rs_nodata:
715 Delta->type=COM_DELTA;
716 break;
717 case rs_newsound:
718 sndpkt->type=COM_SOUND_START_TRANSMISSION;
719 break;
720 case rs_endsound:
721 sndpkt->type=COM_SOUND_END_TRANSMISSION;
722 break;
723 case rs_data:
724 sndpkt->type=COM_SOUND_NORMAL_TRANSMISSION;
725 break;
726 default:
727 Error("Illegal return value for SD_GetSoundData");
728 break;
729 }
730 }
731 if (demorecord==true)
732 RecordDemoCmd();
733 }
734 PrepareLocalPacket();
735
736 if (
737 (controlupdatetime != -1) &&
738 (controlupdatetime > (lastpolltime+MAXPOLLTICS)) &&
739 (demoplayback==false)
740 )
741 {
742 controlbuf[0] = controlbuf[1] = controlbuf[2] = 0;
743 }
744 }
745 }
746 if (modemgame==true)
747 {
748 CheckForPacket ();
749 }
750
751 if ((standalone == false) && (IsServer==true) && (UpdateServer==true))
752 ProcessServer();
753
754 // take out
755 if (modemgame==true)
756 {
757 //#if (DEVELOPMENT == 1)
758 if (PanicPressed==true)
759 {
760 Error("Game Aborted. Scroll Lock pressed\n");
761 }
762 //#endif
763 if (Keyboard[sc_Insert] && Keyboard[sc_Q])
764 Error("Game Aborted. Insert->Q pressed\n");
765 }
766
767 InUCC = false;
768
769 waminot();
770 }
771
772 //****************************************************************************
773 //
774 // PlayerInGame()
775 //
776 //****************************************************************************
PlayerInGame(int p)777 boolean PlayerInGame ( int p )
778 {
779 if (PlayerStatus[p]!=player_ingame)
780 return false;
781 return true;
782 }
783
784 /*
785 =============================================================================
786
787 Packet Section
788
789 =============================================================================
790 */
791
792 //****************************************************************************
793 //
794 // CheckForPacket()
795 //
796 //****************************************************************************
CheckForPacket(void)797 void CheckForPacket ( void )
798 {
799 wami(7);
800 while (ReadPacket()==true)
801 {
802 if (badpacket==0)
803 {
804 ProcessPacket(&ROTTpacket[0], rottcom->remotenode);
805 #if (DEVELOPMENT == 1)
806 // ComError("CheckForPacket: from=%ld\n",rottcom->remotenode);
807 #endif
808 }
809 else
810 RequestPacket (LastCommandTime[rottcom->remotenode]+controldivisor, rottcom->remotenode, controldivisor);
811 }
812 waminot();
813 }
814
815
816 //****************************************************************************
817 //
818 // AddRemoteRidiculeCommand()
819 //
820 //****************************************************************************
AddRemoteRidiculeCommand(int player,int towho,int num)821 void AddRemoteRidiculeCommand ( int player, int towho, int num )
822 {
823 ((COM_RemoteRidiculeType *)NextLocalCommand())->type=COM_REMRID;
824 ((COM_RemoteRidiculeType *)NextLocalCommand())->num=num;
825 ((COM_RemoteRidiculeType *)NextLocalCommand())->player=player;
826 ((COM_RemoteRidiculeType *)NextLocalCommand())->towho=towho;
827
828 PrepareLocalPacket();
829 }
830
831 //****************************************************************************
832 //
833 // ProcessRemoteRidicule()
834 //
835 //****************************************************************************
ProcessRemoteRidicule(void * pkt)836 void ProcessRemoteRidicule ( void * pkt )
837 {
838 COM_RemoteRidiculeType * remrot;
839 char name[ 50 ];
840 int from;
841 int who;
842
843 remrot = (COM_RemoteRidiculeType *)pkt;
844 from = remrot->player;
845 who = remrot->towho;
846 if ( ( who == consoleplayer ) || ( who == MSG_DIRECTED_TO_ALL ) ||
847 ( ( who == MSG_DIRECTED_TO_TEAM ) && ( BATTLE_Team[ from ] ==
848 BATTLE_Team[ consoleplayer ] ) ) )
849 {
850 strcpy( name, "(� RR from " );
851 strcat( name, PLAYERSTATE[from].codename );
852 strcat( name, ")" );
853 AddMessage( name, MSG_REMOTERIDICULE );
854
855 SD_Play( SD_REMOTEM1SND + remrot->num );
856 }
857 }
858
859 //****************************************************************************
860 //
861 // AddEndGameCommand()
862 //
863 //****************************************************************************
AddEndGameCommand(void)864 void AddEndGameCommand ( void )
865 {
866 ((COM_EndGameType *)NextLocalCommand())->type=COM_ENDGAME;
867
868 PrepareLocalPacket();
869 }
870
871 //****************************************************************************
872 //
873 // AddGameEndCommand()
874 //
875 //****************************************************************************
AddGameEndCommand(void)876 void AddGameEndCommand ( void )
877 {
878 ((COM_GameEndType *)NextLocalCommand())->type=COM_GAMEEND;
879
880 PrepareLocalPacket();
881 }
882
883 //****************************************************************************
884 //
885 // AddQuitCommand()
886 //
887 //****************************************************************************
AddQuitCommand(void)888 void AddQuitCommand ( void )
889 {
890 ((COM_QuitType *)NextLocalCommand())->type=COM_QUIT;
891 PrepareLocalPacket();
892 }
893
894 //****************************************************************************
895 //
896 // AddExitCommand()
897 //
898 //****************************************************************************
AddExitCommand(void)899 void AddExitCommand ( void )
900 {
901 ((COM_ExitType *)NextLocalCommand())->type=COM_EXIT;
902 PrepareLocalPacket();
903 }
904
905 //****************************************************************************
906 //
907 // AddPauseStateCommand()
908 //
909 //****************************************************************************
AddPauseStateCommand(int type)910 void AddPauseStateCommand ( int type )
911 {
912 ((COM_PauseType *)NextLocalCommand())->type=type;
913
914 PrepareLocalPacket();
915 }
916
917
918 //****************************************************************************
919 //
920 // AddRespawnCommand()
921 //
922 //****************************************************************************
AddRespawnCommand(void)923 void AddRespawnCommand ( void )
924 {
925 if (respawnactive==true)
926 return;
927
928 respawnactive=true;
929
930 ((COM_RespawnType *)NextLocalCommand())->type=COM_RESPAWN;
931
932 PrepareLocalPacket();
933 }
934
935
936 //****************************************************************************
937 //
938 // AddTextMessage()
939 //
940 //****************************************************************************
AddTextMessage(char * message,int length,int towho)941 void AddTextMessage
942 (
943 char *message,
944 int length,
945 int towho
946 )
947
948 {
949 COM_TextType *Text;
950
951 Text = ( COM_TextType * )NextLocalCommand();
952
953 Text->type = COM_TEXT;
954 memset( &Text->string[ 0 ], 0, COM_MAXTEXTSTRINGLENGTH );
955
956 if ( length >= COM_MAXTEXTSTRINGLENGTH )
957 {
958 length = COM_MAXTEXTSTRINGLENGTH - 1;
959 }
960
961 memcpy( &Text->string[ 0 ], message, length );
962
963 Text->towho = towho;
964
965 PrepareLocalPacket();
966 }
967
968
969 //****************************************************************************
970 //
971 // PrepareLocalPacket
972 //
973 //****************************************************************************
974
PrepareLocalPacket(void)975 void PrepareLocalPacket ( void )
976 {
977 MoveType * pkt;
978
979 wami(8);
980
981 pkt=(MoveType *)NextLocalCommand();
982
983 pkt->time=controlupdatetime;
984
985 if (networkgame==false) // Whether it is a modem game or not we do this
986 {
987 AddClientPacket (pkt, consoleplayer);
988 if (modemgame==false)
989 {
990 ServerCommandStatus ( controlupdatetime ) = cs_ready;
991 }
992 }
993
994 if (modemgame==true)
995 SendPacket (pkt, server);
996
997 #if (DEVELOPMENT == 1)
998 // ComError("packet sent: realtime=%ld time=%ld type=%ld dest=%ld\n",GetTicCount(),pkt->time,pkt->type,server);
999 #endif
1000
1001 controlupdatetime+=controldivisor;
1002 waminot();
1003 }
1004
1005
1006
1007 //****************************************************************************
1008 //
1009 // GetPacketSize ()
1010 //
1011 //****************************************************************************
1012
GetPacketSize(void * pkt)1013 int GetPacketSize (void * pkt)
1014 {
1015 int size;
1016
1017 switch (((MoveType *)pkt)->type)
1018 {
1019 case COM_DELTA:
1020 size=sizeof(MoveType);
1021 break;
1022 case COM_DELTANULL:
1023 size=sizeof(NullMoveType);
1024 break;
1025 case COM_REQUEST:
1026 size=sizeof(COM_RequestType);
1027 break;
1028 case COM_FIXUP:
1029 size=sizeof(COM_FixupType);
1030 break;
1031 case COM_TEXT:
1032 size=sizeof(COM_TextType);
1033 break;
1034 case COM_PAUSE:
1035 size=sizeof(COM_PauseType);
1036 break;
1037 case COM_QUIT:
1038 size=sizeof(COM_QuitType);
1039 break;
1040 case COM_EXIT:
1041 size=sizeof(COM_ExitType);
1042 break;
1043 case COM_REMRID:
1044 size=sizeof(COM_RemoteRidiculeType);
1045 break;
1046 case COM_RESPAWN:
1047 size=sizeof(COM_RespawnType);
1048 break;
1049 case COM_UNPAUSE:
1050 size=sizeof(COM_UnPauseType);
1051 break;
1052 case COM_SERVER:
1053 size=sizeof(COM_ServerHeaderType);
1054 size-=sizeof(byte);
1055 break;
1056 case COM_GAMEDESC:
1057 size=sizeof(COM_GamePlayerType);
1058 break;
1059 case COM_GAMEEND:
1060 size=sizeof(COM_GameEndType);
1061 break;
1062 case COM_GAMEPLAY:
1063 size=DUMMYPACKETSIZE;
1064 break;
1065 case COM_GAMEACK:
1066 size=sizeof(COM_GameAckType);
1067 break;
1068 case COM_GAMEMASTER:
1069 size=sizeof(COM_GameMasterType);
1070 break;
1071 case COM_ENDGAME:
1072 size=sizeof(COM_EndGameType);
1073 break;
1074 case COM_SYNCTIME:
1075 size=sizeof(COM_SyncType);
1076 break;
1077 #if (SYNCCHECK == 1)
1078 case COM_SYNCCHECK:
1079 size=sizeof(COM_CheckSyncType);
1080 break;
1081 #endif
1082 case COM_SOUNDANDDELTA:
1083 size=sizeof(MoveType)+sizeof(COM_SoundType);
1084 break;
1085 default:
1086 Error("Unhandled packet type in GetPacketSize type=%ld",((MoveType *)pkt)->type);
1087 break;
1088 }
1089
1090 return size;
1091 }
1092
1093 //****************************************************************************
1094 //
1095 // GetTypeSize ()
1096 //
1097 //****************************************************************************
1098
GetTypeSize(int type)1099 int GetTypeSize (int type)
1100 {
1101 byte pkt[2];
1102
1103 pkt[0]=(byte)type;
1104 return ( GetPacketSize(&(pkt[0])) );
1105 }
1106
1107 //****************************************************************************
1108 //
1109 // GetServerPacketSize ()
1110 //
1111 //****************************************************************************
1112
GetServerPacketSize(void * pkt)1113 int GetServerPacketSize (void * pkt)
1114 {
1115 int i;
1116 byte * ptr;
1117 COM_ServerHeaderType * serverpkt;
1118
1119 serverpkt=(COM_ServerHeaderType *)pkt;
1120 if (serverpkt->type==COM_SERVER)
1121 {
1122 ptr=&serverpkt->data;
1123
1124 for (i=0;i<serverpkt->numpackets;i++)
1125 {
1126 ptr+=GetPacketSize(ptr);
1127 }
1128 return ((byte *)ptr-(byte *)pkt);
1129 }
1130 else
1131 return GetPacketSize(pkt);
1132 }
1133
1134 //****************************************************************************
1135 //
1136 // SendPacket ()
1137 //
1138 //****************************************************************************
1139
SendPacket(void * pkt,int dest)1140 void SendPacket (void * pkt, int dest)
1141 {
1142 if ((networkgame==false) && (PlayerStatus[dest]!=player_ingame))
1143 return;
1144 if ((IsServer==true) && (dest==server) && (standalone==false)) // must be client on top of server
1145 ProcessPacket(pkt,dest);
1146 else if ((IsServer==false) && (dest!=server) && (standalone==false)) // We shouldn't be sending as client to anyone else
1147 ComError("SendPacket:Problems\n");
1148 else
1149 WritePacket(pkt,GetPacketSize(pkt),dest);
1150 #if (DEVELOPMENT == 1)
1151 // ComError( "SendPacket: time=%ld dest=%ld\n",((MoveType *)pkt)->time,dest);
1152 #endif
1153 }
1154
1155 //****************************************************************************
1156 //
1157 // ResetCurrentCommand ()
1158 //
1159 //****************************************************************************
1160
ResetCurrentCommand(void)1161 void ResetCurrentCommand ( void )
1162 {
1163 ServerCommandStatus(oldpolltime)=cs_notarrived;
1164 }
1165
1166 //****************************************************************************
1167 //
1168 // BroadcastServerPacket ()
1169 //
1170 //****************************************************************************
1171
BroadcastServerPacket(void * pkt,int size)1172 void BroadcastServerPacket (void * pkt, int size)
1173 {
1174 int i;
1175
1176
1177 for (i=0;i<numplayers;i++)
1178 {
1179 if (PlayerStatus[i]!=player_ingame)
1180 continue;
1181 // if ((standalone==false) && (i==consoleplayer))
1182 // ProcessPacket(pkt,i);
1183 // else
1184 WritePacket((byte *)pkt,size,i);
1185 }
1186 }
1187
1188
1189 //****************************************************************************
1190 //
1191 // ResendLocalPackets ()
1192 //
1193 //****************************************************************************
1194
ResendLocalPackets(int time,int dest,int numpackets)1195 void ResendLocalPackets (int time, int dest, int numpackets)
1196 {
1197 int cmd;
1198 MoveType * pkt;
1199
1200 cmd = CommandAddress(time);
1201
1202 #if 0
1203 if (networkgame==false)
1204 {
1205 int nump;
1206 nump=controlupdatetime-time;
1207 if (nump>numpackets)
1208 numpackets=nump;
1209 }
1210 #endif
1211
1212 if (controlupdatetime<=time)
1213 return;
1214
1215 pkt = (MoveType *)LocalCommand(cmd);
1216
1217 if (pkt->time!=time)
1218 {
1219 Error( "CLIENT: Could not find packet to resend\ntime=%ld packettime=%ld controlupdatetime=%ld\n",
1220 time, pkt->time, controlupdatetime);
1221 }
1222 else
1223 {
1224 byte * tempbuf;
1225 byte * tempptr;
1226 byte * tempstart;
1227 COM_FixupType * fixup;
1228 int i;
1229 int starti;
1230 int size;
1231 boolean done;
1232
1233 // allocate some space
1234
1235 tempbuf=SafeMalloc(MAXCOMBUFFERSIZE);
1236
1237 fixup=(COM_FixupType *)tempbuf;
1238
1239 fixup->type=COM_FIXUP;
1240 tempstart=&(fixup->data);
1241
1242 done=false;
1243 i=0;
1244 while (done==false)
1245 {
1246 tempptr=tempstart;
1247 starti=i;
1248 fixup->time=( (MoveType *)LocalCommand(cmd) )->time;
1249 for (;i<numpackets;i++)
1250 {
1251 pkt = (MoveType *)LocalCommand(cmd);
1252 size=GetPacketSize(pkt);
1253
1254 if (((tempptr+size)-tempbuf)>MAXCOMBUFFERSIZE)
1255 {
1256 break;
1257 }
1258 memcpy(tempptr,pkt,size);
1259 tempptr+=size;
1260 cmd = (cmd + controldivisor) & (MAXCMDS-1);
1261 }
1262 fixup->numpackets=i-starti;
1263 WritePacket(tempbuf,tempptr-tempbuf,dest);
1264 if (i==numpackets)
1265 done=true;
1266 }
1267
1268 SafeFree(tempbuf);
1269 }
1270 }
1271
1272 //****************************************************************************
1273 //
1274 // ResendServerPackets ()
1275 //
1276 //****************************************************************************
1277
ResendServerPackets(int time,int dest,int numpackets)1278 void ResendServerPackets (int time, int dest, int numpackets)
1279 {
1280 int cmd;
1281 COM_ServerHeaderType * serverpkt;
1282
1283
1284 cmd = CommandAddress(time);
1285
1286 if (serverupdatetime<=time)
1287 return;
1288
1289 serverpkt = (COM_ServerHeaderType *)ServerCommand(cmd);
1290
1291 if (serverpkt->time!=time)
1292 {
1293 Error( "SERVER: Could not find packet to resend\ntime=%ld packettime=%ld serverupdatetime=%ld\n",
1294 time, serverpkt->time,serverupdatetime);
1295 }
1296 else
1297 {
1298 byte * tempbuf;
1299 byte * tempptr;
1300 byte * tempstart;
1301 COM_FixupType * fixup;
1302 int i;
1303 int starti;
1304 int size;
1305 boolean done;
1306
1307 // allocate some space
1308
1309 tempbuf=SafeMalloc(MAXCOMBUFFERSIZE);
1310
1311 fixup=(COM_FixupType *)tempbuf;
1312
1313 fixup->type=COM_FIXUP;
1314 tempstart=&(fixup->data);
1315
1316 done=false;
1317 i=0;
1318 while (done==false)
1319 {
1320 tempptr=tempstart;
1321 starti=i;
1322 fixup->time=( (MoveType *)ServerCommand(cmd) )->time;
1323 for (;i<numpackets;i++)
1324 {
1325 serverpkt = (COM_ServerHeaderType *)ServerCommand(cmd);
1326 size=GetServerPacketSize(serverpkt);
1327
1328 if (((tempptr+size)-tempbuf)>MAXCOMBUFFERSIZE)
1329 {
1330 break;
1331 }
1332 memcpy(tempptr,serverpkt,size);
1333 tempptr+=size;
1334 cmd = (cmd + controldivisor) & (MAXCMDS-1);
1335 }
1336 fixup->numpackets=i-starti;
1337 WritePacket(tempbuf,tempptr-tempbuf,dest);
1338 if (i==numpackets)
1339 done=true;
1340 }
1341
1342 SafeFree(tempbuf);
1343 }
1344 }
1345
1346
1347 //****************************************************************************
1348 //
1349 // ResendPacket (incoming packet, whoever requested it)
1350 //
1351 //****************************************************************************
1352
ResendPacket(void * pkt,int dest)1353 void ResendPacket (void * pkt, int dest)
1354 {
1355 int time;
1356 COM_RequestType * request;
1357
1358 if ((networkgame==false) && (PlayerStatus[dest]!=player_ingame))
1359 return;
1360
1361 request=(COM_RequestType * )pkt;
1362 time=request->time;
1363
1364 ComError( "RESEND request received at %ld\n packet time=%ld dest=%ld numpackets=%ld\n",
1365 GetTicCount(), time, dest, request->numpackets);
1366
1367 if (IsServer==true)
1368 {
1369 if ((dest==server) && (standalone==false))
1370 Error("Trying to resend packets to client on top of server\n");
1371 ComError( "RESEND SERVER serverupdatetime=%ld\n",serverupdatetime);
1372 if (IsServerCommandReady ( time ) == true)
1373 ResendServerPackets(time,dest,request->numpackets);
1374 else
1375 ComError( "RESEND SERVER time=%ld is not ready\n",time);
1376 }
1377 else
1378 {
1379 ResendLocalPackets(time,dest,request->numpackets);
1380 }
1381 }
1382
1383 //****************************************************************************
1384 //
1385 // FixupPacket ()
1386 //
1387 //****************************************************************************
1388
FixupPacket(void * pkt,int src)1389 void FixupPacket (void * pkt, int src)
1390 {
1391 COM_FixupType * fix;
1392 int i;
1393 int time;
1394 byte * ptr;
1395
1396 fix=(COM_FixupType *)pkt;
1397
1398 ComError( "Fixup received at %ld, time=%ld numpackets=%ld\n", GetTicCount(), fix->time, fix->numpackets);
1399 #if 0
1400 if (networkgame==false)
1401 FixingPackets=false;
1402 #endif
1403 time=fix->time;
1404 ptr=&(fix->data);
1405
1406 for (i=0;i<fix->numpackets;i++,time+=controldivisor)
1407 {
1408 if (time == (LastCommandTime[src]+controldivisor))
1409 LastCommandTime[src]=time;
1410
1411 if (IsServer==true)
1412 {
1413 if (ClientCommandStatus(src, time)!=cs_fixing)
1414 {
1415 ComError("Server Received fixup with no bad packet time=%ld from %ld\n",time,src);
1416 }
1417 else
1418 {
1419 AddSubPacket(ptr, src);
1420 }
1421 ptr+=GetPacketSize(ptr);
1422 }
1423 else
1424 {
1425 if (ServerCommandStatus(time)!=cs_fixing)
1426 {
1427 ComError("Client Received fixup with no bad packet time=%ld from %ld\n",time,src);
1428 }
1429 else
1430 {
1431 if (networkgame==true)
1432 {
1433 AddServerSubPacket( (COM_ServerHeaderType *)ptr );
1434 }
1435 else
1436 {
1437 AddModemSubPacket(ptr);
1438 }
1439 }
1440 ptr+=GetServerPacketSize(ptr);
1441 }
1442 }
1443 }
1444
1445 #if (SYNCCHECK == 1)
1446 //****************************************************************************
1447 //
1448 // CheckForSyncCheck
1449 //
1450 //****************************************************************************
1451
CheckForSyncCheck(void)1452 void CheckForSyncCheck ( void )
1453 {
1454 int i;
1455
1456
1457 if (modemgame==true)
1458 {
1459 if (oldpolltime==lastsynccheck)
1460 {
1461 for (i=0;i<numplayers;i++)
1462 {
1463 PlayerSync[i].x=PLAYER[i]->x;
1464 PlayerSync[i].y=PLAYER[i]->y;
1465 PlayerSync[i].z=PLAYER[i]->z;
1466 PlayerSync[i].angle=PLAYER[i]->angle;
1467 }
1468 PlayerSync[0].randomindex=GetRNGindex();
1469 PlayerSync[0].synctime=lastsynccheck;
1470 SendSyncCheckPacket();
1471 lastsynccheck+=CHECKSYNCTIME;
1472 }
1473 if (oldpolltime>lastsynccheck)
1474 {
1475 Error("Missed a player sync check time=%ld\n",oldpolltime);
1476 }
1477 }
1478 }
1479 #endif
1480
1481 //****************************************************************************
1482 //
1483 // ProcessSyncTimePacket
1484 //
1485 //****************************************************************************
1486
ProcessSyncTimePacket(void * pkt)1487 void ProcessSyncTimePacket (void * pkt)
1488 {
1489 COM_SyncType * sync;
1490
1491 sync=(COM_SyncType *)pkt;
1492 ISR_SetTime(sync->synctime);
1493 }
1494
1495 #if (SYNCCHECK == 1)
1496 //****************************************************************************
1497 //
1498 // ProcessSyncCheckPacket
1499 //
1500 //****************************************************************************
1501
ProcessSyncCheckPacket(void * pkt,int src)1502 void ProcessSyncCheckPacket (void * pkt, int src)
1503 {
1504 COM_CheckSyncType * sync;
1505
1506 sync=(COM_CheckSyncType *)pkt;
1507 // SoftError("Sync packet time=%ld\n",sync->synctime);
1508 if (sync->synctime!=PlayerSync[0].synctime)
1509 {
1510 SoftError("Old sync packet received\n");
1511 return;
1512 }
1513 if (sync->randomindex!=PlayerSync[0].randomindex)
1514 {
1515 Error("Player %ld is unsynced localindex=%ld remoteindex=%ld\n"
1516 "Unsynced Player x=%x y=%x a=%ld z=%ld name=%s\n",
1517 src, PlayerSync[0].randomindex, sync->randomindex,
1518 PlayerSync[src].x, PlayerSync[src].y, PlayerSync[src].angle,
1519 PlayerSync[src].z,PLAYERSTATE[src].codename);
1520 }
1521 if (sync->x!=PlayerSync[src].x)
1522 {
1523 Error("Player %ld is unsynced local x=%ld remote x=%ld\n"
1524 "Unsynced Player x=%x y=%x a=%ld z=%ld name=%s\n",
1525 src,PlayerSync[src].x,sync->x,
1526 PlayerSync[src].x, PlayerSync[src].y, PlayerSync[src].angle,
1527 PlayerSync[src].z,PLAYERSTATE[src].codename);
1528 }
1529 if (sync->y!=PlayerSync[src].y)
1530 {
1531 Error("Player %ld is unsynced local y=%ld remote y=%ld\n"
1532 "Unsynced Player x=%x y=%x a=%ld z=%ld name=%s\n",
1533 src,PlayerSync[src].y,sync->y,
1534 PlayerSync[src].x, PlayerSync[src].y, PlayerSync[src].angle,
1535 PlayerSync[src].z,PLAYERSTATE[src].codename);
1536 }
1537 if (sync->z!=PlayerSync[src].z)
1538 {
1539 Error("Player %ld is unsynced local z=%ld remote z=%ld\n"
1540 "Unsynced Player x=%x y=%x a=%ld z=%ld name=%s\n",
1541 src,PlayerSync[src].z,sync->z,
1542 PlayerSync[src].x, PlayerSync[src].y, PlayerSync[src].angle,
1543 PlayerSync[src].z,PLAYERSTATE[src].codename);
1544 }
1545 if (sync->angle!=PlayerSync[src].angle)
1546 {
1547 Error("Player %ld is unsynced local angle=%ld remote angle=%ld\n"
1548 "Unsynced Player x=%x y=%x a=%ld z=%ld name=%s\n",
1549 src,PlayerSync[src].angle,sync->angle,
1550 PlayerSync[src].x, PlayerSync[src].y, PlayerSync[src].angle,
1551 PlayerSync[src].z,PLAYERSTATE[src].codename);
1552 }
1553 }
1554
1555 //****************************************************************************
1556 //
1557 // SendSyncCheckPacket
1558 //
1559 //****************************************************************************
1560
SendSyncCheckPacket(void)1561 void SendSyncCheckPacket ( void )
1562 {
1563 ((COM_CheckSyncType *)NextLocalCommand())->type=COM_SYNCCHECK;
1564 ((COM_CheckSyncType *)NextLocalCommand())->synctime=PlayerSync[0].synctime;
1565 ((COM_CheckSyncType *)NextLocalCommand())->x=PlayerSync[consoleplayer].x;
1566 ((COM_CheckSyncType *)NextLocalCommand())->y=PlayerSync[consoleplayer].y;
1567 ((COM_CheckSyncType *)NextLocalCommand())->z=PlayerSync[consoleplayer].z;
1568 ((COM_CheckSyncType *)NextLocalCommand())->angle=PlayerSync[consoleplayer].angle;
1569 ((COM_CheckSyncType *)NextLocalCommand())->randomindex=PlayerSync[0].randomindex;
1570
1571 PrepareLocalPacket();
1572 }
1573 #endif
1574
1575 #if 0
1576
1577 //****************************************************************************
1578 //
1579 // CheckForSyncTime
1580 //
1581 //****************************************************************************
1582
1583 void CheckForSyncTime ( void )
1584 {
1585 if ((modemgame==true) && (networkgame==false) && (consoleplayer==0))
1586 {
1587 if (controlupdatetime>=syncservertime)
1588 {
1589 SendSyncTimePacket();
1590 syncservertime+=MODEMSYNCSERVERTIME;
1591 }
1592 }
1593 }
1594 #endif
1595
1596 #if 0
1597 //****************************************************************************
1598 //
1599 // SendSyncTimePacket
1600 //
1601 //****************************************************************************
1602
1603 void SendSyncTimePacket ( void )
1604 {
1605 int i;
1606 COM_SyncType sync;
1607
1608 return;
1609
1610 sync.type=COM_SYNCTIME;
1611
1612 if (networkgame==true)
1613 {
1614 for (i=0;i<numplayers;i++)
1615 {
1616 if ((PlayerStatus[i]!=player_ingame) || ( (i==consoleplayer) && (standalone==false) ) )
1617 continue;
1618 sync.synctime=GetTicCount()+GetTransitTime(i);
1619 WritePacket ( &sync.type, GetPacketSize(&sync.type), i);
1620 }
1621 }
1622 else
1623 {
1624 if (PlayerStatus[server]==player_ingame)
1625 {
1626 sync.synctime=GetTicCount()+GetTransitTime(server);
1627 WritePacket ( &sync.type, GetPacketSize(&sync.type), server);
1628 }
1629 }
1630 }
1631 #endif
1632
1633 //****************************************************************************
1634 //
1635 // ProcessSoundAndDeltaPacket
1636 //
1637 //****************************************************************************
1638
ProcessSoundAndDeltaPacket(void * pkt,int src)1639 void ProcessSoundAndDeltaPacket (void * pkt, int src)
1640 {
1641 MoveType * packet;
1642 COM_SoundType * sndpkt;
1643 byte oldtype;
1644
1645 packet = (MoveType *)pkt;
1646
1647 // Trick packet into being a normal delta packet
1648
1649 oldtype=packet->type;
1650 packet->type=COM_DELTA;
1651 AddClientPacket (pkt,src);
1652 packet->type=oldtype;
1653
1654 // Don't process sound if it is from us
1655 if (src==consoleplayer)
1656 return;
1657
1658 sndpkt = (COM_SoundType *) (packet->Sounddata);
1659
1660 if (sndpkt->type==COM_SOUND_START_TRANSMISSION)
1661 {
1662 SD_StartIncomingSound ();
1663 }
1664 if (sndpkt->type==COM_SOUND_END_TRANSMISSION)
1665 {
1666 SD_StopIncomingSound();
1667 }
1668 else
1669 {
1670 SD_UpdateIncomingSound (&(sndpkt->data[0]), COM_SOUND_BUFFERSIZE);
1671 }
1672 }
1673 //****************************************************************************
1674 //
1675 // SyncToServer
1676 //
1677 //****************************************************************************
1678 #define NETWORKTIMEAHEADOFSERVER (1)
1679 #define MODEMTIMEAHEADOFSERVER (2)
SyncToServer(void)1680 void SyncToServer( void )
1681 {
1682 int diff;
1683
1684 if ((networkgame==false) && (consoleplayer==0))
1685 return;
1686 if (IsServer==true)
1687 return;
1688 // if (networkgame==true)
1689 // {
1690 // diff = (GetTicCount()-controldivisor-LastCommandTime[0])/controldivisor;
1691 // SoftError("diff=%ld\n",diff);
1692 // if (abs(diff)>1)
1693 // ISR_SetTime(GetTicCount()-diff);
1694 #if 0
1695 diff = controlupdatetime-LastCommandTime[0];
1696 if (diff>3)
1697 {
1698 ISR_SetTime(GetTicCount()-1);
1699 }
1700 else if (diff<-3)
1701 {
1702 ISR_SetTime(GetTicCount()+1);
1703 }
1704 #endif
1705 // }
1706 // else
1707 // {
1708 diff = (GetTicCount()-controldivisor-LastCommandTime[server])/controldivisor;
1709 if (abs(diff)>0)
1710 ISR_SetTime(GetTicCount()-diff);
1711 // }
1712 }
1713
1714 //****************************************************************************
1715 //
1716 // ProcessPacket
1717 //
1718 //****************************************************************************
1719
ProcessPacket(void * pkt,int src)1720 void ProcessPacket (void * pkt, int src)
1721 {
1722 switch (((MoveType *)pkt)->type)
1723 {
1724 case COM_DELTA:
1725 case COM_DELTANULL:
1726 case COM_TEXT:
1727 case COM_PAUSE:
1728 case COM_QUIT:
1729 case COM_EXIT:
1730 case COM_REMRID:
1731 case COM_RESPAWN:
1732 case COM_UNPAUSE:
1733 case COM_ENDGAME:
1734 #if (SYNCCHECK == 1)
1735 case COM_SYNCCHECK:
1736 #endif
1737 // if (FixingPackets==false)
1738 AddPacket(pkt,src);
1739 break;
1740 case COM_SOUNDANDDELTA:
1741 if (remoteridicule == false )
1742 {
1743 ((MoveType *)pkt)->type = COM_DELTA;
1744 }
1745 AddPacket(pkt,src);
1746 break;
1747 case COM_SERVER:
1748 AddServerPacket(pkt,src);
1749 break;
1750
1751 case COM_REQUEST:
1752 ResendPacket(pkt, src);
1753 break;
1754
1755 case COM_FIXUP:
1756 FixupPacket(pkt, src);
1757 break;
1758
1759 case COM_SYNCTIME:
1760 ProcessSyncTimePacket(pkt);
1761 break;
1762
1763 case COM_GAMEEND:
1764 case COM_GAMEDESC:
1765 case COM_GAMEACK:
1766 case COM_GAMEMASTER:
1767 if (standalone==true)
1768 restartgame=true;
1769 break;
1770
1771 case COM_START:
1772 break;
1773
1774 default:
1775 Error("ProcessPacket: Unknown packet type=%ld\n",((MoveType *)pkt)->type);
1776 }
1777 }
1778
1779
1780 //****************************************************************************
1781 //
1782 // AddServerSubPacket
1783 //
1784 //****************************************************************************
1785
AddServerSubPacket(COM_ServerHeaderType * serverpkt)1786 void AddServerSubPacket(COM_ServerHeaderType * serverpkt)
1787 {
1788 byte * pkt;
1789 int i;
1790
1791 ServerCommandStatus(serverpkt->time)=cs_ready;
1792
1793 pkt=&serverpkt->data;
1794 for (i=0;i<serverpkt->numpackets;i++)
1795 {
1796 AddClientPacket(pkt,i);
1797 pkt+=GetPacketSize(pkt);
1798 }
1799 }
1800
1801 //****************************************************************************
1802 //
1803 // AddModemSubPacket
1804 //
1805 //****************************************************************************
1806
AddModemSubPacket(void * incoming)1807 void AddModemSubPacket(void * incoming)
1808 {
1809 MoveType * pkt;
1810
1811 pkt=(MoveType *)incoming;
1812 ServerCommandStatus(pkt->time)=cs_ready;
1813
1814 AddClientPacket(incoming,server);
1815 }
1816
1817 //****************************************************************************
1818 //
1819 // AddServerPacket
1820 //
1821 //****************************************************************************
1822
AddServerPacket(void * pkt,int src)1823 void AddServerPacket(void * pkt, int src)
1824 {
1825 COM_ServerHeaderType * serverpkt;
1826
1827 // The server uses the client's lgts for communicating
1828
1829 // Last good time can be set even for the client/server combo
1830
1831 if (standalone==true)
1832 {
1833 Error("standalone should not be here\n");
1834 }
1835
1836 if (src!=server)
1837 {
1838 Error("Received server packet from non-server src=%ld\n",src);
1839 }
1840
1841 serverpkt=(COM_ServerHeaderType *)pkt;
1842
1843 // if (networkgame==false)
1844 // SyncToServer(serverpkt->time);
1845
1846 LastCommandTime[src]+=controldivisor;
1847
1848 if (serverpkt->time != LastCommandTime[src])
1849 {
1850 int numpackets;
1851
1852 numpackets=serverpkt->time-LastCommandTime[src];
1853 if (ServerCommandStatus(LastCommandTime[src])!=cs_fixing)
1854 {
1855 RequestPacket ( LastCommandTime[src] , src , numpackets );
1856
1857 ComError("AddServerPacket: Request packet time=%ld lct=%ld numpackets=%ld\n",
1858 serverpkt->time, LastCommandTime[src], numpackets
1859 );
1860 }
1861
1862 LastCommandTime[src]+=numpackets;
1863 }
1864
1865 AddServerSubPacket( serverpkt );
1866 }
1867
1868 //****************************************************************************
1869 //
1870 // AddClientPacket
1871 //
1872 //****************************************************************************
1873
AddClientPacket(void * pkt,int src)1874 void AddClientPacket (void * pkt, int src)
1875 {
1876 int size;
1877 MoveType * packet;
1878
1879 packet=(MoveType *)pkt;
1880
1881 switch (packet->type)
1882 {
1883 case COM_DELTA:
1884 case COM_DELTANULL:
1885 case COM_TEXT:
1886 case COM_REMRID:
1887 case COM_PAUSE:
1888 case COM_QUIT:
1889 case COM_EXIT:
1890 case COM_RESPAWN:
1891 case COM_UNPAUSE:
1892 #if (SYNCCHECK == 1)
1893 case COM_SYNCCHECK:
1894 #endif
1895 case COM_ENDGAME:
1896 size=GetPacketSize(packet);
1897 memcpy(PlayerCommand(src,CommandAddress(packet->time)),packet,size);
1898 break;
1899 case COM_SOUNDANDDELTA:
1900 ProcessSoundAndDeltaPacket(packet, src);
1901 break;
1902 default:
1903 Error("AddClientPacket: Unknown packet type = %ld\n",packet->type);
1904 }
1905 }
1906
1907 //****************************************************************************
1908 //
1909 // AddSubPacket
1910 //
1911 //****************************************************************************
1912
AddSubPacket(void * pkt,int src)1913 void AddSubPacket (void * pkt, int src)
1914 {
1915 MoveType * packet;
1916
1917 if (networkgame==false)
1918 Error("Modem game should not be here in AddSubPacket\n");
1919
1920 packet = (MoveType *) pkt;
1921
1922 ClientCommandStatus(src, packet->time)=cs_ready;
1923
1924 memcpy (
1925 ClientTimeCommand(src,packet->time),
1926 pkt,
1927 GetPacketSize(packet)
1928 );
1929 }
1930
1931 //****************************************************************************
1932 //
1933 // AddPacket
1934 //
1935 //****************************************************************************
1936
AddPacket(void * pkt,int src)1937 void AddPacket (void * pkt, int src)
1938 {
1939 MoveType * packet;
1940
1941 // should only be called by server in network game
1942 // in modem game we fall through the first condition
1943 // all packets should be sequential
1944
1945 if ((IsServer==true) && (PlayerStatus[src]!=player_ingame))
1946 return;
1947 packet = (MoveType *) pkt;
1948
1949 // if ((networkgame==false) && (consoleplayer!=0))
1950 // SyncToServer();
1951
1952 if (!((src==server) && (standalone==false) && (IsServer==true)))
1953 {
1954 LastCommandTime[src]+=controldivisor;
1955
1956 if (packet->time != LastCommandTime[src])
1957 {
1958 int numpackets;
1959
1960 numpackets=packet->time-LastCommandTime[src];
1961 if ( ( (networkgame==false) &&
1962 (ServerCommandStatus(LastCommandTime[src])!=cs_fixing)
1963 )
1964 ||
1965 ( (networkgame==true) &&
1966 (ClientCommandStatus(src,LastCommandTime[src])!=cs_fixing)
1967 )
1968 )
1969 {
1970 RequestPacket ( LastCommandTime[src] , src , numpackets );
1971
1972 ComError("AddPacket: Request packet time=%ld lct=%ld numpackets=%ld\n",
1973 packet->time, LastCommandTime[src], numpackets
1974 );
1975 }
1976
1977 LastCommandTime[src]+=numpackets;
1978 }
1979 }
1980
1981 if (networkgame==true)
1982 {
1983 AddSubPacket ( packet, src );
1984 }
1985 else
1986 {
1987 AddModemSubPacket(packet);
1988 }
1989 }
1990
1991
1992 //****************************************************************************
1993 //
1994 // RequestPacket ( int time, int dest )
1995 //
1996 //****************************************************************************
1997
RequestPacket(int time,int dest,int numpackets)1998 void RequestPacket (int time, int dest, int numpackets)
1999 {
2000 COM_RequestType request;
2001 int i;
2002
2003
2004 #if (DEVELOPMENT == 1)
2005 if (modemgame==false)
2006 Error("Called Request Packet outside of modem game\n");
2007 #endif
2008
2009 request.type=COM_REQUEST;
2010 request.time=time;
2011 request.numpackets=numpackets/controldivisor;
2012
2013 if (IsServer==true)
2014 {
2015 if ((dest==server) && (standalone==false))
2016 {
2017 Error("Requesting packet from client on top of server\n");
2018 }
2019 if (PlayerStatus[dest]!=player_ingame)
2020 return;
2021 for (i=0;i<numpackets;i+=controldivisor)
2022 {
2023 ClientCommandStatus( dest , (time+i) ) = cs_fixing;
2024 }
2025 }
2026 else
2027 {
2028 if ((networkgame==false) && (PlayerStatus[dest]!=player_ingame))
2029 return;
2030 for (i=0;i<numpackets;i+=controldivisor)
2031 {
2032 ServerCommandStatus( (time+i) ) = cs_fixing;
2033 }
2034 }
2035 // if (networkgame==false)
2036 // FixingPackets=true;
2037
2038 // send out the packet
2039
2040 WritePacket (&request, GetPacketSize(&request), dest);
2041
2042 #if (DEVELOPMENT == 1)
2043 // ComError( "BADPKT, request sent at %ld lgt=%ld dest=%ld\n",GetTicCount(),time,dest);
2044 #endif
2045 }
2046
2047 //****************************************************************************
2048 //
2049 // IsServerCommandReady ()
2050 //
2051 //****************************************************************************
IsServerCommandReady(int time)2052 boolean IsServerCommandReady ( int time )
2053 {
2054
2055 if (
2056 (
2057 (COM_ServerHeaderType *)
2058 ServerCommand(CommandAddress (time) ) )->time==time)
2059 return true;
2060 else
2061 {
2062 return false;
2063 }
2064 }
2065
2066 //****************************************************************************
2067 //
2068 // AreClientsReady ()
2069 //
2070 //****************************************************************************
AreClientsReady(void)2071 boolean AreClientsReady ( void )
2072 {
2073 int i;
2074 int timeindex;
2075 int status;
2076
2077 timeindex=CommandAddress(serverupdatetime);
2078
2079 for (i=0;i<numplayers;i++)
2080 {
2081 if (PlayerStatus[i]!=player_ingame)
2082 continue;
2083 status=ClientCommandStatus(i, serverupdatetime);
2084 if (status==cs_notarrived)
2085 return false;
2086 else if (status==cs_fixing)
2087 {
2088 // RequestPacket ( serverupdatetime , i , controldivisor );
2089 return false;
2090 }
2091 else if (((MoveType *)ClientCommand(i, timeindex))->time != serverupdatetime)
2092 return false;
2093 }
2094 return true;
2095 }
2096
2097 //****************************************************************************
2098 //
2099 // IsPlayerCommandReady ()
2100 //
2101 //****************************************************************************
IsPlayerCommandReady(int num,int time)2102 boolean IsPlayerCommandReady (int num, int time)
2103 {
2104 MoveType * cmd;
2105
2106 cmd=(MoveType *)PlayerCommand(num,CommandAddress(time));
2107
2108 if (cmd->time==time)
2109 return true;
2110 else
2111 return false;
2112 }
2113
2114 //****************************************************************************
2115 //
2116 // ResetClientCommands ()
2117 //
2118 //****************************************************************************
ResetClientCommands(int player)2119 void ResetClientCommands ( int player )
2120 {
2121 int j;
2122
2123 for (j=0;j<MAXCMDS;j++)
2124 {
2125 memset(ClientCommand(player,j),COM_DELTA,GamePacketSize());
2126 }
2127 }
2128
2129 //****************************************************************************
2130 //
2131 // SendFullServerPacket ()
2132 //
2133 //****************************************************************************
SendFullServerPacket(void)2134 void SendFullServerPacket ( void )
2135 {
2136 int i;
2137 int size;
2138 byte * pkt;
2139 COM_ServerHeaderType * spkt;
2140 int timeindex;
2141 int playerstatus[MAXPLAYERS];
2142
2143 timeindex=CommandAddress(serverupdatetime);
2144
2145 spkt=(COM_ServerHeaderType *)ServerCommand(timeindex);
2146
2147 pkt=&spkt->data;
2148 spkt->time=serverupdatetime;
2149 spkt->type=COM_SERVER;
2150 spkt->numpackets=numplayers;
2151
2152
2153 memset(playerstatus,-1,sizeof(playerstatus));
2154 for (i=0;i<numplayers;i++)
2155 {
2156 size=GetPacketSize(ClientCommand(i,timeindex));
2157 if (((MoveType *)ClientCommand(i,timeindex))->type == COM_QUIT)
2158 {
2159 playerstatus[i]=player_quitgame;
2160 }
2161 if (((MoveType *)ClientCommand(i,timeindex))->type == COM_ENDGAME)
2162 {
2163 playerstatus[i]=player_leftgame;
2164 }
2165 memcpy(pkt,
2166 ClientCommand(i,timeindex),
2167 size
2168 );
2169 pkt+=size;
2170 ClientCommandNumberStatus(i,timeindex)=cs_notarrived;
2171 }
2172 BroadcastServerPacket((void *)spkt,(pkt-(byte *)spkt));
2173 serverupdatetime+=controldivisor;
2174
2175 for (i=0;i<numplayers;i++)
2176 {
2177 if (playerstatus[i]!=-1)
2178 {
2179 if ((standalone==false) && (consoleplayer==i))
2180 {
2181 UpdateServer=false;
2182 }
2183 else
2184 {
2185 ResetClientCommands(i);
2186 PlayerStatus[i]=playerstatus[i];
2187 }
2188 }
2189 }
2190 }
2191
2192
2193
2194 //****************************************************************************
2195 //
2196 // ProcessServer ()
2197 //
2198 //****************************************************************************
2199
ProcessServer(void)2200 void ProcessServer ( void )
2201 {
2202 boolean done;
2203 boolean exit;
2204 int i;
2205 int time;
2206 int quittime;
2207
2208 if (InProcessServer==true)
2209 return;
2210
2211 InProcessServer=true;
2212
2213 if (GetTicCount()<serverupdatetime)
2214 goto exitProcessServer;
2215
2216 time=GetTicCount();
2217 quittime=GetTicCount()+SERVERTIMEOUT;
2218 exit=false;
2219
2220 while (time>=serverupdatetime)
2221 {
2222 int savetime;
2223
2224 savetime=GetTicCount()+NETWORKTIMEOUT;
2225 done = false;
2226 while (done == false)
2227 {
2228 if (standalone==true)
2229 AbortCheck("GameServer aborted\n");
2230
2231 done = AreClientsReady ();
2232
2233 if ( (standalone==false) && (serverupdatetime>=(controlupdatetime-controldivisor)) && (done==false) )
2234 break;
2235
2236 CheckForPacket ();
2237
2238 if (standalone==false)
2239 UpdateClientControls();
2240
2241 if (restartgame==true)
2242 break;
2243 if (GetTicCount()>savetime)
2244 {
2245 for (i=0;i<numplayers;i++)
2246 {
2247 int val;
2248
2249 val=ClientCommandStatus(i, serverupdatetime);
2250 if ((val!=cs_ready) && (PlayerStatus[i]==player_ingame))
2251 {
2252 SoftError("Server timeout\n");
2253 RequestPacket(serverupdatetime, i , controldivisor);
2254 }
2255 }
2256 savetime=GetTicCount()+NETWORKTIMEOUT;
2257 }
2258 // if (GetTicCount()>quittime)
2259 // {
2260 // Error("Server aborting after %ld seconds\n",SERVERTIMEOUT/VBLCOUNTER);
2261 // }
2262 if ((standalone==false) && (done==false))
2263 {
2264 exit=true;
2265 done=true;
2266 }
2267 }
2268 if (exit==true)
2269 break;
2270 if ( (serverupdatetime>=(controlupdatetime-controldivisor)) && (standalone==false))
2271 break;
2272 if (restartgame==true)
2273 break;
2274 SendFullServerPacket();
2275 #if 0
2276 if (serverupdatetime>=syncservertime)
2277 {
2278 SendSyncTimePacket();
2279 syncservertime+=NETSYNCSERVERTIME;
2280 }
2281 #endif
2282 }
2283 exitProcessServer:
2284 InProcessServer=false;
2285 }
2286
2287
2288 //****************************************************************************
2289 //
2290 // SetupCheckForPacket()
2291 //
2292 //****************************************************************************
SetupCheckForPacket(void)2293 int SetupCheckForPacket ( void )
2294 {
2295 int retval=scfp_nodata;
2296
2297 if ((ReadPacket()==true) && (badpacket==0))
2298 {
2299 MoveType * pkt;
2300
2301 retval=scfp_data;
2302 pkt=(MoveType *)&ROTTpacket[0];
2303 if ((IsServer==true) && (standalone==true))
2304 {
2305 switch (pkt->type)
2306 {
2307 case COM_GAMEEND:
2308 break;
2309 case COM_GAMEDESC:
2310 if (standalone==true)
2311 printf("Received GameDescription from player#%ld\n",(long int)rottcom->remotenode);
2312 WritePacket(&ROTTpacket[0],GetPacketSize(pkt),0); // Send to player 0
2313 break;
2314 case COM_GAMEACK:
2315 if (standalone==true)
2316 printf("Received GameAcknowledgement from player#%ld\n",(long int)rottcom->remotenode);
2317 WritePacket(&ROTTpacket[0],GetPacketSize(pkt),0); // Send to player 0
2318 break;
2319 case COM_GAMEMASTER:
2320 if (standalone==true)
2321 printf("Received GameMasterPacket from player#%ld\n",(long int)rottcom->remotenode);
2322 BroadcastServerPacket(&ROTTpacket[0],GetPacketSize(pkt)); // Send to all
2323 break;
2324 case COM_GAMEPLAY:
2325 if (standalone==true)
2326 printf("Received StartGamePacket from player#%ld\n",(long int)rottcom->remotenode);
2327 BroadcastServerPacket(&ROTTpacket[0],GetPacketSize(pkt)); // Send to all
2328 retval=scfp_done;
2329 break;
2330 default:
2331 ComError("Server received unknown packet in Game preamble\n");
2332 break;
2333 }
2334 }
2335 else
2336 {
2337 switch (pkt->type)
2338 {
2339 case COM_GAMEPLAY:
2340 retval=scfp_done;
2341 break;
2342 case COM_GAMEMASTER:
2343 SetGameDescription(pkt);
2344 retval=scfp_gameready;
2345 break;
2346 case COM_GAMEACK:
2347 PlayersReady[((COM_GameAckType *)pkt)->player]=true;
2348 break;
2349 case COM_GAMEDESC:
2350 GotPlayersDesc[((COM_GamePlayerType *)pkt)->player]=true;
2351 SetPlayerDescription(pkt);
2352 break;
2353 }
2354 }
2355 }
2356 return retval;
2357 }
2358
2359
2360 //****************************************************************************
2361 //
2362 // ServerLoop ()
2363 //
2364 //****************************************************************************
ServerLoop(void)2365 void ServerLoop( void )
2366 {
2367 boolean done;
2368
2369 while (1)
2370 {
2371 ShutdownClientControls();
2372 restartgame=false;
2373
2374 done=false;
2375 while (done==false)
2376 {
2377 AbortCheck("SetupGameServer aborted\n");
2378
2379 if (SetupCheckForPacket()==scfp_done)
2380 done=true;
2381 }
2382 ComSetTime();
2383 StartupClientControls();
2384 while(1)
2385 {
2386 ProcessServer();
2387 #if (DEVELOPMENT == 1)
2388 Z_CheckHeap();
2389 #endif
2390 CalcTics();
2391 if (restartgame==true)
2392 break;
2393 }
2394 }
2395 }
2396
2397 //****************************************************************************
2398 //
2399 // ProcessPlayerCommand()
2400 //
2401 //****************************************************************************
ProcessPlayerCommand(int player)2402 void ProcessPlayerCommand( int player )
2403 {
2404 MoveType * cmd;
2405
2406 cmd=(MoveType *)PlayerCommand(player,CommandAddress(oldpolltime));
2407
2408 if (cmd->type==COM_DELTA)
2409 {
2410 UpdatePlayerObj(player);
2411 }
2412 else if (cmd->type==COM_RESPAWN)
2413 {
2414 if (player==consoleplayer) // reset spawn state
2415 respawnactive=false;
2416 RespawnPlayerobj(PLAYER[player]);
2417 }
2418 else if (cmd->type==COM_ENDGAME)
2419 {
2420 playstate = ex_battledone;
2421 }
2422 else if (cmd->type==COM_QUIT)
2423 {
2424 if (player==consoleplayer)
2425 QuitGame();
2426 else
2427 {
2428 char str[50]="Player #";
2429 char str2[10];
2430
2431 strcat(str,itoa(player+1,str2,10));
2432 strcat(str,", ");
2433 strcat(str,PLAYERSTATE[player].codename);
2434 strcat(str," has left the game.");
2435 AddMessage(str,MSG_REMOTE);
2436 PlayerStatus[player]=player_quitgame;
2437 }
2438 }
2439 else if (cmd->type==COM_EXIT)
2440 {
2441 QuitGame();
2442 }
2443 else if (cmd->type==COM_REMRID)
2444 {
2445 ProcessRemoteRidicule (cmd);
2446 }
2447 else if (cmd->type==COM_TEXT)
2448 {
2449 int who;
2450
2451 who = ( ( COM_TextType * )cmd )->towho;
2452 if ( ( who == consoleplayer ) ||
2453 ( who == MSG_DIRECTED_TO_ALL ) ||
2454 ( ( who == MSG_DIRECTED_TO_TEAM ) &&
2455 ( BATTLE_Team[ player ] == BATTLE_Team[ consoleplayer ] ) ) )
2456 {
2457 char string[ 50 ];
2458
2459 strcpy( string, "\\N9" );
2460 strcat( string, PLAYERSTATE[player].codename );
2461 strcat( string, ":\\NF" );
2462 strcat( string, ((COM_TextType *)cmd)->string );
2463 SD_PlayPitchedSound ( SD_ENDBONUS1SND, 255, 1200 );
2464
2465 AddMessage( string, MSG_REMOTE );
2466 }
2467 }
2468 #if (SYNCCHECK == 1)
2469 else if (cmd->type==COM_SYNCCHECK)
2470 {
2471 ProcessSyncCheckPacket(cmd, player);
2472 }
2473 #endif
2474 else if (cmd->type==COM_PAUSE)
2475 {
2476 MUSIC_Pause();
2477 GamePaused=true;
2478 pausedstartedticcount = oldpolltime;
2479 }
2480 else if (cmd->type==COM_UNPAUSE)
2481 {
2482 GamePaused=false;
2483 MUSIC_Continue ();
2484 if (RefreshPause == false) // screen is blanked
2485 {
2486 ShutdownScreenSaver();
2487 SetupScreen (true);
2488 RefreshPause = true;
2489 }
2490 }
2491 }
2492
2493 //****************************************************************************
2494 //
2495 // CheckUnPause ()
2496 //
2497 //****************************************************************************
CheckUnPause(void)2498 void CheckUnPause ( void )
2499 {
2500 if (oldpolltime==nextupdatetime)
2501 {
2502 nextupdatetime=oldpolltime+controldivisor;
2503 while (1)
2504 {
2505 if (ServerCommandStatus(oldpolltime)==cs_ready)
2506 {
2507 int j;
2508
2509 for (j=0;j<numplayers;j++)
2510 {
2511 if (PlayerStatus[j]==player_ingame)
2512 ProcessPlayerCommand( j );
2513 }
2514 break;
2515 }
2516 else
2517 {
2518 UpdateClientControls();
2519 }
2520 }
2521 }
2522 }
2523
2524
2525 //****************************************************************************
2526 //
2527 // ControlPlayerObj ()
2528 //
2529 //****************************************************************************
ControlPlayerObj(objtype * ob)2530 void ControlPlayerObj (objtype * ob)
2531 {
2532 playertype * pstate;
2533 int num;
2534 int savetime;
2535 // boolean asked;
2536
2537 // if (GamePaused==true)
2538 // return;
2539
2540 M_LINKSTATE(ob,pstate);
2541
2542 // get player number
2543
2544 num=ob->dirchoosetime;
2545
2546 memcpy (pstate->buttonheld, pstate->buttonstate, sizeof(pstate->buttonstate));
2547
2548 if (oldpolltime==nextupdatetime)
2549 {
2550 if (num==numplayers-1)
2551 nextupdatetime=oldpolltime+controldivisor;
2552 if (networkgame==true)
2553 savetime=GetTicCount()+NETWORKTIMEOUT;
2554 else
2555 savetime=GetTicCount()+MODEMTIMEOUT;
2556
2557 if (PlayerStatus[num]!=player_ingame)
2558 return;
2559
2560 // asked=false;
2561
2562 // copy previous state of buttons
2563
2564
2565 while (1)
2566 {
2567 if (ServerCommandStatus(oldpolltime)==cs_ready)
2568 {
2569 ProcessPlayerCommand (num);
2570 if (demoplayback||demorecord) {
2571 SoftError("x=%4lx y=%4lx a=%4lx time=%5ld\n",player->x,player->y,player->angle,oldpolltime);
2572 }
2573 break;
2574 }
2575 // else if ((ServerCommandStatus(oldpolltime)==cs_fixing) &&
2576 // (networkgame==false) &&
2577 // (asked==false)
2578 // )
2579 // {
2580 // asked=true;
2581 // RequestPacket(oldpolltime, server, controldivisor);
2582 // }
2583 else
2584 {
2585 UpdateClientControls();
2586 }
2587
2588 if (GetTicCount()>savetime)
2589 {
2590 SoftError("Client timeout oldpolltime=%ld\n",oldpolltime);
2591 if (IsServer==false)
2592 RequestPacket(oldpolltime, server, controldivisor);
2593 if (networkgame==true)
2594 savetime=GetTicCount()+NETWORKTIMEOUT;
2595 else
2596 savetime=GetTicCount()+MODEMTIMEOUT;
2597 }
2598 }
2599 }
2600
2601 if (!(ob->flags&FL_DYING))
2602 {
2603 if (ob->flags&FL_PUSHED)
2604 {
2605 ob->flags&=~FL_PUSHED;
2606 #if 0
2607 if (abs(ob->momentumx)>0)
2608 {
2609 if (abs(ob->momentumx+pstate->dmomx)>=abs(ob->momentumx))
2610 {
2611 ob->momentumx += pstate->dmomx;
2612 ob->momentumy += pstate->dmomy;
2613 }
2614 }
2615 else if (abs(ob->momentumy+pstate->dmomy)>=abs(ob->momentumy))
2616 {
2617 ob->momentumx += pstate->dmomx;
2618 ob->momentumy += pstate->dmomy;
2619 }
2620 #endif
2621 if (abs(ob->momentumx+pstate->dmomx)>=abs(ob->momentumx))
2622 {
2623 ob->momentumx += pstate->dmomx;
2624 }
2625 if (abs(ob->momentumy+pstate->dmomy)>=abs(ob->momentumy))
2626 {
2627 ob->momentumy += pstate->dmomy;
2628 }
2629 }
2630 else
2631 {
2632 ob->momentumx += pstate->dmomx;
2633 ob->momentumy += pstate->dmomy;
2634 }
2635 }
2636 }
2637
2638 //****************************************************************************
2639 //
2640 // MaxSpeedForCharacter ()
2641 //
2642 //****************************************************************************
2643
MaxSpeedForCharacter(playertype * pstate)2644 int MaxSpeedForCharacter(playertype*pstate)
2645 {
2646 if (BATTLEMODE && (gamestate.BattleOptions.Speed == bo_fast_speed))
2647 {
2648 return( FASTSPEED );
2649 }
2650 else
2651 {
2652 if (pstate->buttonstate[bt_run])
2653 return (characters[pstate->player].toprunspeed);
2654 else
2655 return (characters[pstate->player].topspeed);
2656 }
2657 }
2658
2659 //****************************************************************************
2660 //
2661 // UpdatePlayerObj ()
2662 //
2663 //****************************************************************************
2664
UpdatePlayerObj(int player)2665 void UpdatePlayerObj ( int player )
2666 {
2667 int i, buttonbits;
2668 playertype * pstate;
2669 MoveType * MoveCmd;
2670
2671 MoveCmd=(MoveType *)PlayerCommand(player,CommandAddress(oldpolltime));
2672
2673 pstate=&PLAYERSTATE[player];
2674
2675 buttonbits = MoveCmd->buttons;
2676 for (i = 0; i < NUMTXBUTTONS; i++)
2677 {
2678 pstate->buttonstate[i] = buttonbits & 1;
2679 buttonbits >>= 1;
2680 }
2681
2682 pstate->dmomx = (int)(MoveCmd->momx)<<1;
2683 pstate->dmomy = (int)(MoveCmd->momy)<<1;
2684 pstate->angle = MoveCmd->dangle;
2685 pstate->angle <<= 11;
2686 pstate->topspeed=MaxSpeedForCharacter(pstate);
2687
2688 if (demoplayback||demorecord) {
2689 SoftError(" dmx=%4lx dmy=%4lx da=%4lx time=%5ld\n",pstate->dmomx,pstate->dmomy,pstate->angle>>11,oldpolltime);
2690 }
2691 #if 0
2692 #if (DEVELOPMENT == 1)
2693 if ((modemgame==true) || (demoplayback==true) || (demorecord==true))
2694 {
2695 ComError( "player#%2ld\n",player);
2696 ComError( "momx = %6ld\n", PLAYER[player]->momentumx);
2697 ComError( "momy = %6ld\n", PLAYER[player]->momentumy);
2698 ComError( " x = %6ld\n", PLAYER[player]->x);
2699 ComError( " y = %6ld\n", PLAYER[player]->y);
2700 ComError( " z = %6ld\n", PLAYER[player]->z);
2701 ComError( " a = %6ld\n", PLAYER[player]->angle);
2702 if (pstate->buttonstate[bt_attack])
2703 ComError( "FIRING\n");
2704 }
2705 #endif
2706 #endif
2707 }
2708
2709
2710 //****************************************************************************
2711 //
2712 // SendPlayerDescription ()
2713 //
2714 //****************************************************************************
2715
SendPlayerDescription(void)2716 void SendPlayerDescription( void )
2717 {
2718 byte * temp;
2719 COM_GamePlayerType * desc;
2720 int length;
2721
2722 length=sizeof(COM_GamePlayerType);
2723 temp=SafeMalloc(length);
2724
2725 memset(temp,0,length);
2726
2727 desc=(COM_GamePlayerType *)temp;
2728 desc->type=(byte)COM_GAMEDESC;
2729 desc->player=consoleplayer;
2730 desc->violence=gamestate.violence;
2731 desc->Version = gamestate.Version;
2732 desc->Product = gamestate.Product;
2733 desc->playerdescription.character=locplayerstate->player;
2734 desc->playerdescription.uniformcolor=locplayerstate->uniformcolor;
2735 strcpy(&(desc->playerdescription.codename[0]),
2736 &locplayerstate->codename[0]);
2737
2738 WritePacket(temp,length,server);
2739
2740 SafeFree(temp);
2741 }
2742
2743 //****************************************************************************
2744 //
2745 // SendGameDescription ()
2746 //
2747 //****************************************************************************
2748
SendGameDescription(void)2749 void SendGameDescription( void )
2750 {
2751 byte * temp;
2752 COM_GameMasterType * desc;
2753 int length;
2754 int i;
2755
2756 length=sizeof(COM_GameMasterType);
2757 temp=SafeMalloc(length);
2758
2759 memset(temp,0,length);
2760
2761 desc=(COM_GameMasterType *)temp;
2762 desc->type=(byte)COM_GAMEMASTER;
2763 desc->level=gamestate.mapon;
2764 desc->mapcrc=GetMapCRC (gamestate.mapon);
2765 desc->mode=gamestate.battlemode;
2766 desc->violence=gamestate.violence;
2767 desc->Version = gamestate.Version;
2768 desc->Product = gamestate.Product;
2769 desc->teamplay = gamestate.teamplay;
2770 memcpy( &desc->SpecialsTimes, &gamestate.SpecialsTimes, sizeof( specials ) );
2771 BATTLE_GetOptions( &( desc->options ) );
2772 GetMapFileName( &(desc->battlefilename[0]) );
2773 desc->randomseed=GetRNGindex ( );
2774 gamestate.randomseed=desc->randomseed;
2775 desc->ludicrousgibs=battlegibs;
2776 ludicrousgibs=battlegibs;
2777 // SetRNGindex ( gamestate.randomseed );
2778 for (i=0;i<numplayers;i++)
2779 {
2780 if (gamestate.Product == ROTT_SHAREWARE)
2781 PLAYERSTATE[i].player = 0;
2782 desc->players[i].character =PLAYERSTATE[i].player;
2783 desc->players[i].uniformcolor =PLAYERSTATE[i].uniformcolor;
2784 strcpy ( &(desc->players[i].codename[0]),&(PLAYERSTATE[i].codename[0]));
2785 }
2786
2787 if (!networkgame)
2788 AssignTeams();
2789
2790 if (IsServer==false)
2791 {
2792 WritePacket(temp,length,server);
2793 }
2794 else
2795 {
2796 BroadcastServerPacket(temp,length); // Send to all
2797 }
2798
2799 SafeFree(temp);
2800 }
2801
2802 //****************************************************************************
2803 //
2804 // SetGameDescription ()
2805 //
2806 //****************************************************************************
2807
SetGameDescription(void * pkt)2808 void SetGameDescription( void * pkt )
2809 {
2810 COM_GameMasterType * desc;
2811 word localcrc;
2812 int i;
2813
2814 desc=(COM_GameMasterType *)pkt;
2815 gamestate.mapon=desc->level;
2816 gamestate.battlemode=desc->mode;
2817 gamestate.violence=desc->violence;
2818 gamestate.Version = desc->Version;
2819 gamestate.Product = desc->Product;
2820 gamestate.teamplay = desc->teamplay;
2821 memcpy( &gamestate.SpecialsTimes, &desc->SpecialsTimes, sizeof( specials ) );
2822 BATTLE_SetOptions( &( desc->options ) );
2823 gamestate.randomseed=desc->randomseed;
2824 SetRNGindex ( gamestate.randomseed );
2825 SetBattleMapFileName( &(desc->battlefilename[0]) );
2826 localcrc=GetMapCRC (gamestate.mapon);
2827 ludicrousgibs=desc->ludicrousgibs;
2828 if (localcrc!=desc->mapcrc)
2829 Error("You have different maps on your system\n");
2830 for (i=0;i<numplayers;i++)
2831 {
2832 PLAYERSTATE[i].player=desc->players[i].character;
2833 PLAYERSTATE[i].uniformcolor=desc->players[i].uniformcolor;
2834 strcpy ( &(PLAYERSTATE[i].codename[0]),
2835 &(desc->players[i].codename[0])
2836 );
2837 }
2838 AssignTeams();
2839 }
2840
2841 //****************************************************************************
2842 //
2843 // SetPlayerDescription ()
2844 //
2845 //****************************************************************************
2846
SetPlayerDescription(void * pkt)2847 void SetPlayerDescription( void * pkt )
2848 {
2849 COM_GamePlayerType * desc;
2850
2851 desc=(COM_GamePlayerType *)pkt;
2852 PLAYERSTATE[desc->player].player=desc->playerdescription.character;
2853 PLAYERSTATE[desc->player].uniformcolor=desc->playerdescription.uniformcolor;
2854 strcpy ( &(PLAYERSTATE[desc->player].codename[0]),
2855 &(desc->playerdescription.codename[0])
2856 );
2857 if ( gamestate.Version != desc->Version )
2858 {
2859 Error("Player %s is using a different version of ROTT\n",PLAYERSTATE[desc->player].codename);
2860 // gamestate.Version = desc->Version;
2861 }
2862
2863 if ( gamestate.violence > desc->violence )
2864 {
2865 gamestate.violence = desc->violence;
2866 }
2867
2868 if ( gamestate.Product > desc->Product )
2869 {
2870 gamestate.Product = desc->Product;
2871 }
2872 }
2873
2874 //****************************************************************************
2875 //
2876 // SendGameAck ()
2877 //
2878 //****************************************************************************
2879
SendGameAck(void)2880 void SendGameAck( void )
2881 {
2882 byte * temp;
2883 int length;
2884 COM_GameAckType * desc;
2885
2886 length=sizeof(COM_GameAckType);
2887 temp=SafeMalloc(length);
2888 desc=(COM_GameAckType *)temp;
2889 desc->type=COM_GAMEACK;
2890 desc->player=consoleplayer;
2891
2892 WritePacket(temp,length,server);
2893
2894 SafeFree(temp);
2895 }
2896
2897 //****************************************************************************
2898 //
2899 // SendGameStart ()
2900 //
2901 //****************************************************************************
2902
SendGameStart(void)2903 void SendGameStart( void )
2904 {
2905 byte * temp;
2906 int length;
2907
2908 length=DUMMYPACKETSIZE;
2909 temp=SafeMalloc(length);
2910 *(temp)=(byte)COM_GAMEPLAY;
2911
2912 if (IsServer==false)
2913 {
2914 WritePacket(temp,length,server);
2915 }
2916 else
2917 {
2918 BroadcastServerPacket(temp,length); // Send to all
2919 }
2920
2921 SafeFree(temp);
2922 }
2923
2924 //****************************************************************************
2925 //
2926 // SetupGamePlayer ()
2927 //
2928 //****************************************************************************
SetupGamePlayer(void)2929 void SetupGamePlayer ( void )
2930 {
2931 int savetime;
2932 boolean done;
2933 boolean gameready;
2934
2935 savetime=GetTicCount();
2936
2937 done=false;
2938 gameready=false;
2939
2940 while (done==false)
2941 {
2942 // Setup individual player
2943 AbortCheck("SetupGamePlayer aborted\n");
2944
2945 // send Player Description
2946 if (GetTicCount() >= savetime)
2947 {
2948 savetime=GetTicCount()+SETUPTIME;
2949 if (gameready==false)
2950 SendPlayerDescription();
2951 else
2952 SendGameAck();
2953 }
2954 switch (SetupCheckForPacket())
2955 {
2956 case scfp_done:
2957 done=true;
2958 break;
2959 case scfp_gameready:
2960 gameready=true;
2961 break;
2962 }
2963 }
2964 savetime=GetTicCount()+(VBLCOUNTER/2);
2965
2966 while (GetTicCount()<savetime)
2967 {
2968 SetupCheckForPacket ();
2969 }
2970 }
2971
2972 //****************************************************************************
2973 //
2974 // AllPlayersReady ()
2975 //
2976 //****************************************************************************
AllPlayersReady(void)2977 boolean AllPlayersReady ( void )
2978 {
2979 int i;
2980
2981 for (i=0;i<numplayers;i++)
2982 if ((PlayersReady[i]==false) && (PlayerStatus[i]==player_ingame))
2983 return false;
2984
2985 return true;
2986 }
2987
2988 //****************************************************************************
2989 //
2990 // GotAllPlayerDescriptions ()
2991 //
2992 //****************************************************************************
GotAllPlayerDescriptions(void)2993 boolean GotAllPlayerDescriptions ( void )
2994 {
2995 int i;
2996
2997 for (i=0;i<numplayers;i++)
2998 if ((GotPlayersDesc[i]==false) && (PlayerStatus[i]==player_ingame))
2999 return false;
3000
3001 return true;
3002 }
3003
3004 //****************************************************************************
3005 //
3006 // SetupGameMaster ()
3007 //
3008 //****************************************************************************
SetupGameMaster(void)3009 void SetupGameMaster ( void )
3010 {
3011 int savetime;
3012 boolean done;
3013
3014 memset(GotPlayersDesc,false,sizeof(GotPlayersDesc));
3015 GotPlayersDesc[consoleplayer]=true;
3016
3017 memset(PlayersReady,false,sizeof(PlayersReady));
3018 PlayersReady[consoleplayer]=true;
3019
3020 savetime=GetTicCount();
3021
3022 done=false;
3023
3024 InitializeRNG ();
3025
3026 while (done==false)
3027 {
3028 // Setup individual player
3029
3030 AbortCheck("SetupGameMaster aborted\n");
3031
3032 // send Game Description
3033 if (GetTicCount() >= savetime)
3034 {
3035 savetime=GetTicCount()+SETUPTIME;
3036 if (GotAllPlayerDescriptions()==true)
3037 SendGameDescription();
3038 }
3039 if (AllPlayersReady ()==true)
3040 {
3041 SendGameStart();
3042 SendGameStart();
3043 done=true;
3044 }
3045 SetupCheckForPacket();
3046 }
3047 savetime=GetTicCount()+(VBLCOUNTER/2);
3048
3049 while (GetTicCount()<savetime)
3050 {
3051 SetupCheckForPacket ();
3052 }
3053 }
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064 /*
3065 =============================================================================
3066
3067 DEMO CODE
3068
3069 =============================================================================
3070 */
3071 //****************************************************************************
3072 //
3073 // GetDemoFilename ()
3074 //
3075 //****************************************************************************
3076
GetDemoFilename(int demonumber,char * filename)3077 void GetDemoFilename (int demonumber, char * filename)
3078 {
3079 strcpy(filename,"demo0_0.dmo\0");
3080
3081 filename[4] = (char)('0' + (byte)demonumber);
3082 filename[6] = (char)('0' + (byte)gamestate.violence);
3083 }
3084 //****************************************************************************
3085 //
3086 // DemoExists ()
3087 //
3088 //****************************************************************************
3089
DemoExists(int demonumber)3090 boolean DemoExists (int demonumber)
3091 {
3092 char demo[20];
3093
3094 GetDemoFilename (demonumber, &demo[0]);
3095 if (access (demo, F_OK) == 0)
3096 return true;
3097 else
3098 return false;
3099
3100 }
3101
3102 //****************************************************************************
3103 //
3104 // SaveDemo ()
3105 //
3106 //****************************************************************************
3107
SaveDemo(int demonumber)3108 void SaveDemo (int demonumber)
3109 {
3110 char demo[20];
3111
3112 RecordDemoCmd ();
3113 GetDemoFilename (demonumber, &demo[0]);
3114 SaveFile (demo, demobuffer, (demoptr-demobuffer));
3115 FreeDemo();
3116 }
3117
3118 //****************************************************************************
3119 //
3120 // LoadDemo ()
3121 //
3122 //****************************************************************************
3123
LoadDemo(int demonumber)3124 void LoadDemo (int demonumber)
3125 {
3126 char demo[20];
3127 int size;
3128
3129 GetDemoFilename (demonumber, demo);
3130 if (demobuffer!=NULL)
3131 FreeDemo();
3132 size = LoadFile (demo, (void **)&demobuffer);
3133 playstate = ex_demoplayback;
3134 demoptr = demobuffer;
3135 lastdemoptr = (demoptr+size);
3136 locplayerstate->player=0;
3137 InitializeWeapons(locplayerstate);
3138 ResetPlayerstate(locplayerstate);
3139 InitCharacter();
3140 }
3141
3142 //****************************************************************************
3143 //
3144 // RecordDemo ()
3145 //
3146 //****************************************************************************
3147
RecordDemo(void)3148 void RecordDemo ( void )
3149 {
3150 DemoHeaderType * DemoHeader;
3151 int level;
3152
3153 if (demobuffer!=NULL)
3154 FreeDemo();
3155 godmode=0;
3156 demobuffer = SafeMalloc (DEMOBUFFSIZE);
3157 demoptr = demobuffer;
3158 lastdemoptr = demobuffer+DEMOBUFFSIZE;
3159
3160 // Save off level number
3161
3162 DemoHeader=(DemoHeaderType *)demoptr;
3163 demoptr+=sizeof(gamestate);
3164 memcpy(&(DemoHeader->demostate),&gamestate,sizeof(gamestate));
3165 demorecord = true;
3166 locplayerstate->player=0;
3167 InitializeWeapons(locplayerstate);
3168 ResetPlayerstate(locplayerstate);
3169 level=gamestate.mapon;
3170 InitCharacter();
3171 gamestate.mapon=level;
3172 SoftError(">>>>>>>>>>>>Start demo record\n");
3173 }
3174
3175 //****************************************************************************
3176 //
3177 // SetupDemo ()
3178 //
3179 //****************************************************************************
3180
SetupDemo(void)3181 void SetupDemo ( void )
3182 {
3183 DemoHeaderType * DemoHeader;
3184
3185 demoplayback = true;
3186 godmode=0;
3187
3188 DemoHeader=(DemoHeaderType *)demoptr;
3189 demoptr+=sizeof(gamestate);
3190 // if (gamestate.violence!=DemoHeader->demostate.violence)
3191 // Error ("This demo has a different difficulty level than your current settings\n");
3192 memcpy(&gamestate,&(DemoHeader->demostate),sizeof(gamestate));
3193 SoftError(">>>>>>>>>>>>Start demo playback\n");
3194 }
3195
3196 //****************************************************************************
3197 //
3198 // FreeDemo ()
3199 //
3200 //****************************************************************************
3201
FreeDemo(void)3202 void FreeDemo ( void )
3203 {
3204 demoplayback = false;
3205 demorecord = false;
3206 SafeFree (demobuffer);
3207 demobuffer=NULL;
3208 }
3209
3210 //****************************************************************************
3211 //
3212 // CheckForDemoDone ()
3213 //
3214 //****************************************************************************
3215
CheckForDemoDone(void)3216 void CheckForDemoDone ( void )
3217 {
3218 if ((demoplayback==true) && (demoptr >= lastdemoptr))
3219 {
3220 FreeDemo();
3221 playstate = ex_demodone;
3222 }
3223 }
3224
3225 //****************************************************************************
3226 //
3227 // CheckForDemoOverflowed ()
3228 //
3229 //****************************************************************************
3230
CheckForDemoOverflowed(void)3231 void CheckForDemoOverflowed ( void )
3232 {
3233 if (demoptr >= (lastdemoptr-sizeof(DemoType)))
3234 {
3235 playstate = ex_completed; // demo is done
3236 EndDemo();
3237 }
3238 }
3239
3240 //****************************************************************************
3241 //
3242 // RecordDemoCmd ()
3243 //
3244 //****************************************************************************
3245
RecordDemoCmd(void)3246 void RecordDemoCmd (void)
3247 {
3248 DemoType * dtime;
3249
3250 SoftError("Demo command recorded at %ld\n",controlupdatetime);
3251 dtime=(DemoType *)demoptr;
3252 dtime->time = controlupdatetime;
3253 dtime->momx = (controlbuf[0]>>1);
3254 dtime->momy = (controlbuf[1]>>1);
3255 dtime->dangle = controlbuf[2]>>11;
3256 dtime->buttons = buttonbits;
3257
3258 demoptr+=sizeof(DemoType);
3259
3260 CheckForDemoOverflowed();
3261 }
3262
3263 //****************************************************************************
3264 //
3265 // AddDemoCmd ()
3266 //
3267 //****************************************************************************
3268
AddDemoCmd(void)3269 void AddDemoCmd (void)
3270 {
3271 DemoType * dtime;
3272
3273 //
3274 // get info from demo buffer
3275 //
3276
3277 SoftError("Demo command played at %ld\n",controlupdatetime);
3278 if (demoplayback==true)
3279 {
3280 dtime=(DemoType *)demoptr;
3281 controlbuf[0]=dtime->momx<<1;
3282 controlbuf[1]=dtime->momy<<1;
3283 controlbuf[2]=dtime->dangle<<11;
3284 buttonbits =dtime->buttons;
3285 demoptr+=sizeof(DemoType);
3286 }
3287 }
3288
3289 //****************************************************************************
3290 //
3291 // GetNextDemoTime ()
3292 //
3293 //****************************************************************************
3294
GetNextDemoTime(void)3295 int GetNextDemoTime (void)
3296 {
3297 DemoType * dtime;
3298
3299 CheckForDemoDone();
3300 dtime=(DemoType *)demoptr;
3301 if (demoplayback)
3302 return dtime->time;
3303 else
3304 return -1;
3305 }
3306
3307 //****************************************************************************
3308 //
3309 // UpdateDemoPlayback ()
3310 //
3311 //****************************************************************************
3312
UpdateDemoPlayback(int time)3313 void UpdateDemoPlayback (int time)
3314 {
3315 if (demoplayback)
3316 {
3317 if (GetNextDemoTime()==time)
3318 AddDemoCmd();
3319 }
3320 }
3321
3322
3323
3324
3325
3326