1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 1997, 2005 - 3D Realms Entertainment
4 
5 This file is part of Shadow Warrior version 1.2
6 
7 Shadow Warrior is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 
16 See the GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21 
22 Original Source: 1997 - Frank Maddin and Jim Norwood
23 Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
24 */
25 //-------------------------------------------------------------------------
26 #include "build.h"
27 #include "baselayer.h"
28 #include "mmulti.h"
29 
30 #include "keys.h"
31 #include "game.h"
32 #include "tags.h"
33 #include "names2.h"
34 #include "net.h"
35 #include "pal.h"
36 #include "demo.h"
37 
38 #include "weapon.h"
39 #include "text.h"
40 #include "menus.h"
41 
42 
43 /*
44 SYNC BUG NOTES:
45 
46     1.  Look at Prediction code first when player movement is involved.  If the
47     prediction code changes any variable not in the Player or Players
48     Sprite/User structure that effects movement then there will be a Out Of Sync
49     problem.
50 
51     EXAMPLE:  Prediction player was updating a sop->drive_oangvel making it
52     invalid for movement.  Look at DoPlayerBoatTurn for comment.
53 
54     2.  Changing movement variables in the draw code.  Because the draw code is
55     called at a variable rate this don't work.  This includes using RANDOM_RANGE
56     or RANDOM_P2 in the draw code.  This updates the random seed variable and is
57     only for movement code.  Use STD_RANDOM_RANGE for draw code.
58 
59     3.  Plain old bugs such as using uninitialized local variables.
60 
61 */
62 
63 //#undef MAXSYNCBYTES
64 //#define MAXSYNCBYTES 16
65 BYTE tempbuf[576], packbuf[576];
66 int PlayClock;
67 extern BOOL PauseKeySet;
68 extern char CommPlayerName[32];
69 
70 gNET gNet;
71 extern short PlayerQuitMenuLevel;
72 
73 #define TIMERUPDATESIZ 32
74 
75 //SW_PACKET fsync;
76 
77 //Local multiplayer variables
78 // should move this to a local scope of faketimerhandler - do it when able to test
79 SW_PACKET loc;
80 
81 //SW_PACKET oloc;
82 
83 BOOL ready2send = 0;
84 
85 BOOL CommEnabled = FALSE;
86 BYTE CommPlayers = 0;
87 int movefifoplc, movefifosendplc;//, movefifoend[MAX_SW_PLAYERS];
88 unsigned int MoveThingsCount;
89 
90 //int myminlag[MAX_SW_PLAYERS];
91 int mymaxlag, otherminlag, bufferjitter = 1;
92 extern CHAR sync_first[MAXSYNCBYTES][60];
93 extern int sync_found;
94 
95 //
96 // Tic Duplication - so you can move multiple times per packet
97 //
98 typedef struct
99     {
100     LONG vel;
101     LONG svel;
102     LONG angvel;
103     LONG aimvel;
104     LONG bits;
105     }SW_AVERAGE_PACKET;
106 
107 int MovesPerPacket = 1;
108 SW_AVERAGE_PACKET AveragePacket;
109 
110  // GAME.C sync state variables
111 BYTE syncstat[MAXSYNCBYTES];
112 //int syncvalhead[MAX_SW_PLAYERS];
113 int syncvaltail, syncvaltottail;
114 void GetSyncInfoFromPacket(BYTEp packbuf, int packbufleng, int *j, int otherconnectindex);
115 
116 // when you set totalclock to 0 also set this one
117 int ototalclock;
118 int smoothratio;
119 int save_totalclock;
120 
121 // must start out as 0
122 
123 BOOL GamePaused = FALSE;
124 BOOL NetBroadcastMode = TRUE;
125 BOOL NetModeOverride = FALSE;
126 
127 
netsendpacket(int ind,BYTEp buf,int len)128 void netsendpacket(int ind, BYTEp buf, int len)
129 {
130 	BYTE bbuf[ sizeof(packbuf) + sizeof(PACKET_PROXY) ];
131 	PACKET_PROXYp prx = (PACKET_PROXYp)bbuf;
132 	int i;
133 
134 	// send via master if in M/S mode and we are not the master, and the recipient is not the master and not ourselves
135 	if (!NetBroadcastMode && myconnectindex != connecthead && ind != myconnectindex && ind != connecthead) {
136 		if ((unsigned)len > sizeof(packbuf)) {
137 			debugprintf("netsendpacket(): packet length > %d!\n",(int)sizeof(packbuf));
138 			len = sizeof(packbuf);
139 		}
140 
141 		prx->PacketType = PACKET_TYPE_PROXY;
142 		prx->PlayerIndex = (BYTE)ind;
143 		memcpy(&prx[1], buf, len);	// &prx[1] == (char*)prx + sizeof(PACKET_PROXY)
144 		len += sizeof(PACKET_PROXY);
145 
146 		sendpacket(connecthead, bbuf, len);
147 		return;
148 	}
149 
150 	sendpacket(ind, buf, len);
151 }
152 
netbroadcastpacket(BYTEp buf,int len)153 void netbroadcastpacket(BYTEp buf, int len)
154 {
155 	int i;
156 	BYTE bbuf[ sizeof(packbuf) + sizeof(PACKET_PROXY) ];
157 	PACKET_PROXYp prx = (PACKET_PROXYp)bbuf;
158 
159 	// broadcast via master if in M/S mode and we are not the master
160 	if (!NetBroadcastMode && myconnectindex != connecthead) {
161 		if ((unsigned)len > sizeof(packbuf)) {
162 			debugprintf("netbroadcastpacket(): packet length > %d!\n",(int)sizeof(packbuf));
163 			len = sizeof(packbuf);
164 		}
165 
166 		prx->PacketType = PACKET_TYPE_PROXY;
167 		prx->PlayerIndex = (BYTE)(-1);
168 		memcpy(&prx[1], buf, len);
169 		len += sizeof(PACKET_PROXY);
170 
171 		sendpacket(connecthead, bbuf, len);
172 		return;
173 	}
174 
175 	TRAVERSE_CONNECT(i)
176 	{
177 		if (i == myconnectindex) continue;
178 		sendpacket(i, buf, len);
179 	}
180 }
181 
netgetpacket(int * ind,BYTEp buf)182 int netgetpacket(int *ind, BYTEp buf)
183 {
184 	int i;
185 	int len;
186 	PACKET_PROXYp prx;
187 
188 	len = getpacket(ind, buf);
189 	if ((unsigned)len < sizeof(PACKET_PROXY) || buf[0] != PACKET_TYPE_PROXY) {
190 		return len;
191 	}
192 
193 	prx = (PACKET_PROXYp)buf;
194 
195 	if (myconnectindex == connecthead) {
196 		// I am the master
197 
198 		if (prx->PlayerIndex == (BYTE)(-1)) {
199 			// broadcast
200 
201 			// Rewrite the player index to be the sender's connection number
202 			prx->PlayerIndex = (BYTE)*ind;
203 
204 			// Transmit to all the other players except ourselves and the sender
205 			TRAVERSE_CONNECT(i) {
206 				if (i == myconnectindex || i == *ind) continue;
207 				sendpacket(i, buf, len);
208 			}
209 
210 			// Return the packet payload to the caller
211 			len -= sizeof(PACKET_PROXY);
212 			memmove(buf, &prx[1], len);
213 			return len;
214 		} else {
215 			// proxy send to a specific player
216 
217 			i = prx->PlayerIndex;
218 
219 			// Rewrite the player index to be the sender's connection number
220 			prx->PlayerIndex = (BYTE)*ind;
221 
222 			// Transmit to the intended recipient
223 			if (i == myconnectindex) {
224 				len -= sizeof(PACKET_PROXY);
225 				memmove(buf, &prx[1], len);
226 				return len;
227 			}
228 
229             if (Player[i].IsDisconnected) return 0;
230 			sendpacket(i, buf, len);
231 			return 0;	// nothing for us to do
232 		}
233 	} else if (*ind == connecthead) {
234 		// I am a slave, and the proxy message came from the master
235 		*ind = prx->PlayerIndex;
236 		len -= sizeof(PACKET_PROXY);
237 		memmove(buf, &prx[1], len);
238 		return len;
239 	} else {
240 		debugprintf("netgetpacket(): proxy from peer %d\n",*ind);
241 	}
242 	return 0;
243 }
244 
245 
EncodeBits(SW_PACKET * pak,SW_PACKET * old_pak,BYTEp buf)246 int EncodeBits(SW_PACKET *pak, SW_PACKET *old_pak, BYTEp buf)
247     {
248     BYTEp base_ptr = buf;
249     unsigned i;
250 
251     // skipping the bits field sync test fake byte (Ed. Ken)
252     *buf = 0;
253     buf++;
254 
255     if (pak->vel != old_pak->vel)
256         {
257         *((short*)buf) = pak->vel;
258         buf += sizeof(pak->vel);
259         SET(*base_ptr, BIT(0));
260         }
261 
262     if (pak->svel != old_pak->svel)
263         {
264         *((short*)buf) = pak->svel;
265         buf += sizeof(pak->svel);
266         SET(*base_ptr, BIT(1));
267         }
268 
269     if (pak->angvel != old_pak->angvel)
270         {
271         *((char *)buf) = pak->angvel;
272         buf += sizeof(pak->angvel);
273         SET(*base_ptr, BIT(2));
274         }
275 
276     if (pak->aimvel != old_pak->aimvel)
277         {
278         *((char*)buf) = pak->aimvel;
279         buf += sizeof(pak->aimvel);
280         SET(*base_ptr, BIT(3));
281         }
282 
283     //won't work if > 4 bytes
284     for(i = 0; i < sizeof(pak->bits); i++)
285         {
286         if (TEST(pak->bits ^ old_pak->bits, 0xff<<(i<<3)))
287             {
288             *buf = (pak->bits>>(i<<3));
289             buf++;
290             SET(*base_ptr, BIT(i+4));
291             }
292         }
293 
294     return(buf - base_ptr);
295     }
296 
DecodeBits(SW_PACKET * pak,SW_PACKET * old_pak,BYTEp buf)297 int DecodeBits(SW_PACKET *pak, SW_PACKET *old_pak, BYTEp buf)
298     {
299     BYTEp base_ptr = buf;
300     unsigned i;
301 
302     // skipping the bits field sync test fake byte (Ed. Ken)
303     buf++;
304 
305     *pak = *old_pak;
306 
307     if (TEST(*base_ptr, BIT(0)))
308         {
309         pak->vel = *(short*)buf;
310         buf += sizeof(pak->vel);
311         }
312 
313     if (TEST(*base_ptr, BIT(1)))
314         {
315         pak->svel = *(short*)buf;
316         buf += sizeof(pak->svel);
317         }
318 
319     if (TEST(*base_ptr, BIT(2)))
320         {
321         pak->angvel = *(char*)buf;
322         buf += sizeof(pak->angvel);
323         }
324 
325     if (TEST(*base_ptr, BIT(3)))
326         {
327         pak->aimvel = *(char*)buf;
328         buf += sizeof(pak->aimvel);
329         }
330 
331     //won't work if > 4 bytes
332     for(i = 0; i < sizeof(pak->bits); i++)
333         {
334         if (TEST(*base_ptr, BIT(i+4)))
335             {
336             RESET(pak->bits, 0xff<<(i<<3));
337             SET(pak->bits, ((int)(*buf))<<(i<<3));
338             buf++;
339             }
340         }
341 
342     return( buf - base_ptr );
343     }
344 
345 VOID
PauseGame(VOID)346 PauseGame(VOID)
347     {
348     if (PauseKeySet)
349         return;
350 
351     if (DemoPlaying || DemoRecording)
352         return;
353 
354     if (GamePaused)
355         return;
356 
357     if (CommPlayers < 2)
358         GamePaused = TRUE;
359     }
360 
361 VOID
ResumeGame(VOID)362 ResumeGame(VOID)
363     {
364     if (PauseKeySet)
365         return;
366 
367     if (DemoPlaying || DemoRecording)
368         return;
369 
370     if (CommPlayers < 2)
371         GamePaused = FALSE;
372     }
373 
374 VOID
PauseAction(VOID)375 PauseAction(VOID)
376     {
377     ready2send = 0;
378     save_totalclock = totalclock;
379     }
380 
381 VOID
ResumeAction(VOID)382 ResumeAction(VOID)
383     {
384     ready2send = 1;
385     totalclock = save_totalclock;
386     }
387 
388 VOID
SendMessage(short pnum,char * text)389 SendMessage(short pnum, char *text)
390     {
391     if (!CommEnabled)
392         return;
393 
394     tempbuf[0] = PACKET_TYPE_MESSAGE;
395     strcpy((char *)&tempbuf[1], text);
396     netsendpacket(pnum, tempbuf, strlen(text) + 2);
397     }
398 
399 
400 VOID
InitNetPlayerOptions(VOID)401 InitNetPlayerOptions(VOID)
402     {
403     short pnum;
404     PLAYERp pp = Player + myconnectindex;
405     PACKET_OPTIONS p;
406 
407     // if you don't have a name :(
408     if (!CommPlayerName[0])
409         sprintf(CommPlayerName, "PLAYER %d", myconnectindex + 1);
410 
411     Bstrupr(CommPlayerName);
412     strcpy(pp->PlayerName, CommPlayerName);
413 
414     // myconnectindex palette
415     pp->TeamColor = gs.NetColor;
416     pp->SpriteP->pal = PALETTE_PLAYER0 + pp->TeamColor;
417     User[pp->SpriteP - sprite]->spal = pp->SpriteP->pal;
418 
419     if (CommEnabled)
420         {
421         memset(&p, 0, sizeof(p));
422         p.PacketType = PACKET_TYPE_PLAYER_OPTIONS;
423         p.AutoRun = gs.AutoRun;
424         p.MouseAimingOn = gs.MouseAimingOn;
425         p.Color = gs.NetColor;
426         strcpy(p.PlayerName, CommPlayerName);
427 
428         netbroadcastpacket((BYTEp)(&p), sizeof(p));
429         }
430     }
431 
432 VOID
SendMulitNameChange(char * new_name,int new_color)433 SendMulitNameChange(char *new_name, int new_color)
434     {
435     short pnum;
436     PLAYERp pp = Player + myconnectindex;
437     PACKET_NAME_CHANGE p;
438 
439     if (new_name)
440         {
441         strncpy(CommPlayerName, new_name, sizeof(CommPlayerName)-1);
442         CommPlayerName[sizeof(CommPlayerName)-1] = 0;
443         Bstrupr(CommPlayerName);
444         strcpy(pp->PlayerName, CommPlayerName);
445         SetRedrawScreen(pp);
446         }
447 
448     if (new_color >= 0)
449         {
450         gs.NetColor = new_color;
451         pp->TeamColor = gs.NetColor;
452         if (pp->SpriteP)
453             {
454             pp->SpriteP->pal = PALETTE_PLAYER0 + pp->TeamColor;
455             User[pp->SpriteP - sprite]->spal = pp->SpriteP->pal;
456             }
457         }
458 
459     if (CommEnabled)
460         {
461         memset(&p, 0, sizeof(p));
462         p.PacketType = PACKET_TYPE_NAME_CHANGE;
463         strcpy(p.PlayerName, CommPlayerName);
464         p.Color = gs.NetColor;
465 
466         netbroadcastpacket((BYTEp)(&p), sizeof(p));
467         }
468     }
469 
470 VOID
SendVersion(int version)471 SendVersion(int version)
472     {
473     short pnum;
474     PLAYERp pp = Player + myconnectindex;
475     PACKET_VERSION p;
476 
477     if (!CommEnabled)
478         return;
479 
480     pp->PlayerVersion = version;
481 
482     p.PacketType = PACKET_TYPE_VERSION;
483     p.Version = version;
484     netbroadcastpacket((BYTEp)(&p), sizeof(p));
485     }
486 
487 VOID
CheckVersion(int GameVersion)488 CheckVersion(int GameVersion)
489     {
490     short pnum;
491     PACKET_VERSION p;
492     #define VERSION_MSG "You cannot play with different versions!"
493 
494     if (!CommEnabled)
495         return;
496 
497     TRAVERSE_CONNECT(pnum)
498         {
499         if (pnum != myconnectindex)
500             {
501             if (GameVersion != Player[pnum].PlayerVersion)
502                 {
503                 buildprintf("CheckVersion(): player %d has version %d, expecting %d\n",
504                         pnum, Player[pnum].PlayerVersion, GameVersion);
505 
506                 adduserquote(VERSION_MSG);
507                 adduserquote(VERSION_MSG);
508                 adduserquote(VERSION_MSG);
509                 adduserquote(VERSION_MSG);
510                 adduserquote(VERSION_MSG);
511                 adduserquote(VERSION_MSG);
512 
513                 if (!Player[pnum].PlayerVersion)
514                     {
515                     SendMessage(pnum, VERSION_MSG);
516                     SendMessage(pnum, VERSION_MSG);
517                     SendMessage(pnum, VERSION_MSG);
518                     SendMessage(pnum, VERSION_MSG);
519                     SendMessage(pnum, VERSION_MSG);
520                     SendMessage(pnum, VERSION_MSG);
521                     }
522                 }
523             }
524         }
525     }
526 
527 VOID
Connect(VOID)528 Connect(VOID)
529     {
530     int players_found, i, yline;
531     short other;
532 
533     if (CommEnabled)
534         {
535         screenpeek = myconnectindex;
536         }
537 
538     //InitTimingVars();                   // resettiming();
539     }
540 
541 int wfe_Clock;
542 BOOL (*wfe_ExitCallback)(VOID);
543 
544 void
waitforeverybody(void)545 waitforeverybody(void)
546     {
547     int i, size = 1;
548     short other;
549 
550     if (!CommEnabled)
551         return;
552 
553     tempbuf[0] = PACKET_TYPE_PLAYER_READY;
554 #ifdef DEBUG
555     tempbuf[1] = Player[myconnectindex].playerreadyflag + 1;
556     size++;
557 #endif
558     netbroadcastpacket(tempbuf, size);
559 
560     #if 0
561     TRAVERSE_CONNECT(i)
562         {
563         if (i != myconnectindex)
564             {
565             DSPRINTF(ds,"Ready packet sent to %d", i);
566             DebugWriteString(ds);
567             }
568         }
569     #endif
570 
571     //KEY_PRESSED(KEYSC_ESC) = FALSE;
572     Player[myconnectindex].playerreadyflag++;
573 
574     while (TRUE)
575         {
576         if (PlayerQuitMenuLevel >= 0)
577             {
578             //DSPRINTF(ds,"%d, Player Quit Menu Level %d", myconnectindex, PlayerQuitMenuLevel);
579             //DebugWriteString(ds);
580 
581             MenuCommPlayerQuit(PlayerQuitMenuLevel);
582             PlayerQuitMenuLevel = -1;
583             }
584 
585 		handleevents();
586         getpackets();
587 
588         if (quitevent || (wfe_ExitCallback && wfe_ExitCallback()))
589             {
590             // allow exit
591             //if (KEY_PRESSED(KEYSC_ESC))
592                 {
593                 tempbuf[0] = PACKET_TYPE_MENU_LEVEL_QUIT;
594                 netbroadcastpacket(tempbuf, 1);
595 
596                 TerminateGame();
597                 exit(0);
598                 }
599             }
600 
601         #if 0
602         TRAVERSE_CONNECT(i)
603             {
604             DSPRINTF(ds,"myindex %d, myready %d, Player %d, Ready %d", myconnectindex, Player[myconnectindex].playerreadyflag, i, Player[i].playerreadyflag);
605             DebugWriteString(ds);
606             }
607         #endif
608 
609         TRAVERSE_CONNECT(i)
610             {
611             if (Player[i].playerreadyflag < Player[myconnectindex].playerreadyflag)
612                 break;
613             }
614 
615         if (i < 0)
616             {
617             return;
618             }
619         }
620     }
621 
622 
MyCommPlayerQuit(void)623 BOOL MyCommPlayerQuit(void)
624 {
625     PLAYERp pp;
626     short i;
627     extern BOOL QuitFlag;
628     short found = FALSE;
629 
630     TRAVERSE_CONNECT(i)
631         {
632         if (TEST_SYNC_KEY(Player + i, SK_QUIT_GAME))
633             {
634             found = TRUE;
635 
636             if (i != myconnectindex)
637                 {
638                 sprintf(ds,"%s has quit the game.",Player[i].PlayerName);
639                 adduserquote(ds);
640                 }
641             if (i == connecthead && !NetBroadcastMode)
642                 QuitFlag = TRUE;
643             }
644         }
645 
646     if (found)
647         {
648         TRAVERSE_CONNECT(i)
649             {
650             pp = Player + i;
651 
652             if (!TEST_SYNC_KEY(pp, SK_QUIT_GAME))
653                 continue;
654 
655             SET(pp->SpriteP->cstat, CSTAT_SPRITE_INVISIBLE);
656             RESET(pp->SpriteP->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN|CSTAT_SPRITE_BLOCK_MISSILE);
657             InitBloodSpray(pp->PlayerSprite,TRUE,-2);
658             InitBloodSpray(pp->PlayerSprite,FALSE,-2);
659             pp->SpriteP->ang = NORM_ANGLE(pp->SpriteP->ang + 1024);
660             InitBloodSpray(pp->PlayerSprite,FALSE,-1);
661             InitBloodSpray(pp->PlayerSprite,TRUE,-1);
662 
663             // if I get my own messages get out to DOS QUICKLY!!!
664             if (i == myconnectindex)
665                 {
666                 QuitFlag = TRUE;
667                 ready2send = 0;
668                 return(TRUE);
669                 }
670 
671             DSPRINTF(ds,"MyCommPlayerQuit %d", i);
672             DebugWriteString(ds);
673 
674             pp->IsDisconnected = TRUE;
675 
676             CommPlayers--;
677 
678             // for COOP mode
679             if (screenpeek == i)
680                 NextScreenPeek();
681             }
682         }
683 
684     return(FALSE);
685 }
686 
MenuCommPlayerQuit(short quit_player)687 BOOL MenuCommPlayerQuit(short quit_player)
688 {
689     PLAYERp pp;
690     short i;
691     extern BOOL QuitFlag;
692     short pnum;
693 
694     // tell everyone else you left the game
695     TRAVERSE_CONNECT(pnum)
696         {
697         if (pnum != quit_player)
698             {
699             sprintf(ds,"%s has quit the game.",Player[myconnectindex].PlayerName);
700             SendMessage(pnum, ds);
701             }
702         }
703 
704     TRAVERSE_CONNECT(i)
705         {
706         pp = Player + i;
707 
708         // have to reorder the connect list
709         if (i != quit_player)
710             continue;
711 
712         DSPRINTF(ds,"MenuPlayerQuit %d", quit_player);
713         DebugWriteString(ds);
714 
715         pp->IsDisconnected = TRUE;
716 
717         CommPlayers--;
718 
719         // for COOP mode
720         if (screenpeek == i)
721             NextScreenPeek();
722         }
723 
724     return(FALSE);
725 }
726 
ErrorCorrectionQuit(VOID)727 VOID ErrorCorrectionQuit(VOID)
728     {
729     int oldtotalclock;
730     short i,j;
731 
732     if (CommPlayers > 1)
733         {
734         for (j = 0; j < MAX_SW_PLAYERS; j++)
735             {
736             oldtotalclock = totalclock;
737             while (totalclock < oldtotalclock + synctics)
738                 {
739 				handleevents();
740                 getpackets();
741                 }
742 
743             tempbuf[0] = PACKET_TYPE_NULL_PACKET;
744             netbroadcastpacket(tempbuf, 1);
745             }
746         }
747     }
748 
749 VOID
InitNetVars(VOID)750 InitNetVars(VOID)
751     {
752     short pnum;
753     PLAYERp pp;
754 
755     memset(&loc, 0, sizeof(loc));
756 
757     TRAVERSE_CONNECT(pnum)
758         {
759         pp = Player + pnum;
760         pp->movefifoend = 0;
761         Player[pnum].syncvalhead = 0;
762         memset(pp->inputfifo,0,sizeof(pp->inputfifo));
763         }
764     movefifoplc = 0;
765     movefifosendplc = 0;
766     syncvaltail = 0;
767     syncvaltottail = 0;
768     predictmovefifoplc = 0;
769 
770     memset(&syncstat, 0, sizeof(syncstat));
771     syncstate = 0;
772     memset(sync_first, 0, sizeof(sync_first));
773     sync_found = FALSE;
774 
775     TRAVERSE_CONNECT(pnum)
776         {
777         Player[pnum].myminlag = 0;
778         }
779 
780     otherminlag = mymaxlag = 0;
781     }
782 
783 VOID
InitTimingVars(VOID)784 InitTimingVars(VOID)
785     {
786     PlayClock = 0;
787 
788     // resettiming();
789     totalsynctics = 0;
790     totalclock = 0;
791     ototalclock = 0;
792     randomseed = 17L;
793 
794     MoveSkip8 = 2;
795     MoveSkip2 = 0;
796     MoveSkip4 = 1;                      // start slightly offset so these
797                                         // don't move the same
798                                         // as the Skip2's
799     MoveThingsCount = 0;
800 
801     }
802 
803 
804 void
AddSyncInfoToPacket(int * j)805 AddSyncInfoToPacket(int *j)
806     {
807     int sb;
808 	int count = 0;
809 
810     // sync testing
811     while (Player[myconnectindex].syncvalhead != syncvaltail && count++ < 4)
812         {
813         for (sb = 0; sb < NumSyncBytes; sb++)
814             packbuf[(*j)++] = Player[myconnectindex].syncval[syncvaltail & (SYNCFIFOSIZ - 1)][sb];
815 
816         syncvaltail++;
817         }
818     }
819 
820 void
faketimerhandler(void)821 faketimerhandler(void)
822     {
823     short other, packbufleng;
824     int i, j, k, l;
825     PLAYERp pp;
826     short pnum;
827     void getinput(SW_PACKET *);
828     extern BOOL BotMode;
829 
830     #if 0
831     if (KEY_PRESSED(KEYSC_PERIOD))
832         {
833         extern unsigned int MoveThingsCount;
834         MoveThingsCount++;
835         MoveThingsCount--;
836         return;
837         }
838     #endif
839 
840 	sampletimer();
841     if ((totalclock < ototalclock + synctics))
842         return;
843 
844     if (!ready2send)
845         return;
846 
847     ototalclock += synctics;
848 
849     getpackets();
850 
851 
852 // TENSW: this way we are guaranteed that the most advanced player is no more
853 // than 200 frames ahead of the most laggy. We're more healthy if the queue
854 // doesn't overflow, that's for sure.
855     if (Player[myconnectindex].movefifoend - movefifoplc >= 100)
856         return;
857 
858     getinput(&loc);
859 
860     AveragePacket.vel += loc.vel;
861     AveragePacket.svel += loc.svel;
862     AveragePacket.angvel += loc.angvel;
863     AveragePacket.aimvel += loc.aimvel;
864     SET(AveragePacket.bits, loc.bits);
865 
866     pp = Player + myconnectindex;
867 
868     if (pp->movefifoend & (MovesPerPacket-1))
869         {
870         memcpy(&pp->inputfifo[pp->movefifoend & (MOVEFIFOSIZ - 1)],
871                &pp->inputfifo[(pp->movefifoend-1) & (MOVEFIFOSIZ - 1)],
872                sizeof(SW_PACKET));
873 
874         pp->movefifoend++;
875         return;
876         }
877 
878     loc.vel = AveragePacket.vel / MovesPerPacket;
879     loc.svel = AveragePacket.svel / MovesPerPacket;
880     loc.angvel = AveragePacket.angvel / MovesPerPacket;
881     loc.aimvel = AveragePacket.aimvel / MovesPerPacket;
882     loc.bits = AveragePacket.bits;
883 
884     memset(&AveragePacket, 0, sizeof(AveragePacket));
885 
886     pp->inputfifo[Player[myconnectindex].movefifoend & (MOVEFIFOSIZ - 1)] = loc;
887     pp->movefifoend++;
888 
889 #if 0
890 //  AI Bot stuff
891      if (CommPlayers > 1)
892      {
893         if (gNet.MultiGameType == MULTI_GAME_AI_BOTS)
894         {
895             TRAVERSE_CONNECT(i)
896             {
897                 if(i != myconnectindex)
898                 {
899                     if(BotMode && Player[i].IsAI == 1)  // Skip it if this player is not computer controlled!
900                     {
901                         computergetinput(i,&Player[i].inputfifo[Player[i].movefifoend&(MOVEFIFOSIZ-1)]);
902                         Player[i].movefifoend++;
903                     }
904                 }
905             }
906         }
907      }
908 // AI Bot stuff
909 #endif
910 
911     if (!CommEnabled)
912         {
913         TRAVERSE_CONNECT(i)
914             {
915             if (i != myconnectindex)
916                 {
917                 if (BotMode && Player[i].IsAI == 1)
918                 {
919                     computergetinput(i,&Player[i].inputfifo[Player[i].movefifoend&(MOVEFIFOSIZ-1)]);
920                 }
921                 else
922                     memset(&Player[i].inputfifo[Player[i].movefifoend & (MOVEFIFOSIZ - 1)], 0, sizeof(Player[i].inputfifo[0]));
923                 Player[i].movefifoend++;
924                 }
925             }
926         return;
927         }
928 
929     TRAVERSE_CONNECT(i)
930         {
931         if (i != myconnectindex)
932             {
933             k = (Player[myconnectindex].movefifoend - 1) - Player[i].movefifoend;
934             Player[i].myminlag = min(Player[i].myminlag, k);
935             mymaxlag = max(mymaxlag, k);
936             }
937         }
938 
939 	if (((Player[myconnectindex].movefifoend - 1) & (TIMERUPDATESIZ - 1)) == 0)
940         {
941         i = mymaxlag - bufferjitter;
942         mymaxlag = 0;
943         if (i > 0)
944             bufferjitter += ((2 + i) >> 2);
945         else if (i < 0)
946             bufferjitter -= ((2 - i) >> 2);
947         }
948 
949     if (NetBroadcastMode)
950         {
951         packbuf[0] = PACKET_TYPE_BROADCAST;
952         j = 1;
953 
954         if (((Player[myconnectindex].movefifoend - 1) & (TIMERUPDATESIZ - 1)) == 0)
955             {
956             if (myconnectindex == connecthead)
957                 {
958                 for (i = connectpoint2[connecthead]; i >= 0; i = connectpoint2[i])
959                     {
960                     if (Player[i].IsDisconnected)
961                         continue;
962                     packbuf[j++] = min(max(Player[i].myminlag, -128), 127);
963                     }
964                 }
965             else
966                 {
967                 i = Player[connecthead].myminlag - otherminlag;
968                 if (labs(i) > 2)
969                     {
970                     ////DSPRINTF(ds,"lag correction: %d,%d,%d",i,Player[connecthead].myminlag,otherminlag);
971                     //MONO_PRINT(ds);
972 
973                     if (labs(i) > 8)
974                         {
975                         if (i < 0)
976                             i++;
977                         i >>= 1;
978                         }
979                     else
980                         {
981                         if (i < 0)
982                             i = -1;
983                         if (i > 0)
984                             i = 1;
985                         }
986                     totalclock -= synctics * i;
987                     otherminlag += i;
988                     }
989                 }
990 
991             for (i = connecthead; i >= 0; i = connectpoint2[i])
992                 Player[i].myminlag = 0x7fffffff;
993             }
994 
995         pp = Player + myconnectindex;
996 
997         #if !BIT_CODEC
998         memcpy(&packbuf[j], &pp->inputfifo[(Player[myconnectindex].movefifoend - 1) & (MOVEFIFOSIZ - 1)], sizeof(SW_PACKET));
999         j += sizeof(SW_PACKET);
1000         #else
1001         j += EncodeBits(&pp->inputfifo[(Player[myconnectindex].movefifoend - 1) & (MOVEFIFOSIZ - 1)],
1002                    &pp->inputfifo[(Player[myconnectindex].movefifoend - 2) & (MOVEFIFOSIZ - 1)],
1003                    &packbuf[j]);
1004         #endif
1005 
1006         #if SYNC_TEST
1007         AddSyncInfoToPacket(&j);
1008         #endif
1009 
1010 		netbroadcastpacket(packbuf, j);
1011 
1012         return;
1013         } // NetBroadcastMode
1014 
1015     // SLAVE CODE
1016     if (myconnectindex != connecthead)  // I am the Slave
1017         {
1018         if (((Player[myconnectindex].movefifoend - 1) & (TIMERUPDATESIZ - 1)) == 0)
1019             {
1020             i = Player[connecthead].myminlag - otherminlag;
1021             if (labs(i) > 2)
1022                 {
1023                 if (labs(i) > 8)
1024                     {
1025                     if (i < 0)
1026                         i++;
1027                     i >>= 1;
1028                     }
1029                 else
1030                     {
1031                     if (i < 0)
1032                         i = -1;
1033                     if (i > 0)
1034                         i = 1;
1035                     }
1036                 totalclock -= synctics * i;
1037                 otherminlag += i;
1038                 }
1039 
1040             for (i = connecthead; i >= 0; i = connectpoint2[i])
1041                 {
1042                 Player[i].myminlag = 0x7fffffff;
1043                 }
1044             }
1045         packbuf[0] = PACKET_TYPE_SLAVE_TO_MASTER;
1046         j = 1;
1047 
1048         pp = Player + myconnectindex;
1049         #if !BIT_CODEC
1050         memcpy(&packbuf[j], &pp->inputfifo[(pp->movefifoend - 1) & (MOVEFIFOSIZ - 1)], sizeof(SW_PACKET));
1051         j += sizeof(SW_PACKET);
1052         #else
1053         j += EncodeBits(&pp->inputfifo[(pp->movefifoend - 1) & (MOVEFIFOSIZ - 1)],
1054                    &pp->inputfifo[(pp->movefifoend - 2) & (MOVEFIFOSIZ - 1)],
1055                    &packbuf[j]);
1056         #endif
1057 
1058         #if SYNC_TEST
1059         AddSyncInfoToPacket(&j);
1060         #endif
1061 
1062         netsendpacket(connecthead, packbuf, j);
1063         return;
1064         }
1065 
1066     // This allows packet-resends
1067     //for (i = connecthead; i >= 0; i = connectpoint2[i])
1068     //    {
1069     //    if ((Player[i].movefifoend <= movefifosendplc))
1070     //        {
1071     //        packbuf[0] = 127;
1072     //        for (i = connectpoint2[connecthead]; i >= 0; i = connectpoint2[i])
1073     //            {
1074     //            sendpacket(i, packbuf, 1);
1075     //            }
1076     //        return;
1077     //        }
1078     //    }
1079 
1080     // I am MASTER...
1081     while (1)
1082         {
1083         TRAVERSE_CONNECT(i)
1084             {
1085             if ((Player[i].movefifoend <= movefifosendplc))
1086                 return;
1087             }
1088 
1089         packbuf[0] = PACKET_TYPE_MASTER_TO_SLAVE;
1090         j = 1;
1091 
1092         // Fix timers and buffer/jitter value
1093         if ((movefifosendplc & (TIMERUPDATESIZ - 1)) == 0)
1094             {
1095             for (i = connectpoint2[connecthead]; i >= 0; i = connectpoint2[i])
1096                 {
1097                 if (Player[i].IsDisconnected)
1098                     continue;
1099                 packbuf[j++] = min(max(Player[i].myminlag, -128), 127);
1100                 }
1101 
1102             for (i = connecthead; i >= 0; i = connectpoint2[i])
1103                 Player[i].myminlag = 0x7fffffff;
1104             }
1105 
1106         TRAVERSE_CONNECT(i)
1107             {
1108             pp = Player + i;
1109 
1110             #if !BIT_CODEC
1111             memcpy(&packbuf[j], &pp->inputfifo[movefifosendplc & (MOVEFIFOSIZ - 1)], sizeof(SW_PACKET));
1112             j += sizeof(SW_PACKET);
1113             #else
1114             j += EncodeBits(&pp->inputfifo[(movefifosendplc) & (MOVEFIFOSIZ - 1)],
1115                        &pp->inputfifo[(movefifosendplc - 1) & (MOVEFIFOSIZ - 1)],
1116                        &packbuf[j]);
1117             #endif
1118             //pp->movefifoend++;
1119             }
1120 
1121         #if SYNC_TEST
1122         AddSyncInfoToPacket(&j);
1123         #endif
1124 
1125         for (i = connectpoint2[connecthead]; i >= 0; i = connectpoint2[i])
1126             {
1127             if (Player[i].IsDisconnected)
1128                 continue;
1129             netsendpacket(i, packbuf, j);
1130             /*
1131             pp = Player + i;
1132             if (TEST(pp->inputfifo[movefifosendplc & (MOVEFIFOSIZ - 1)].bits,QUITBIT)
1133                playerquitflag[i] = 1;
1134             */
1135             }
1136 
1137         movefifosendplc += MovesPerPacket;
1138         }
1139     }
1140 
1141 VOID
checkmasterslaveswitch(VOID)1142 checkmasterslaveswitch(VOID)
1143     {
1144     }
1145 
1146 VOID
getpackets(VOID)1147 getpackets(VOID)
1148     {
1149     int otherconnectindex, packbufleng;
1150     int i, j, k, l, fifoCheck, sb;
1151     PLAYERp pp;
1152     SW_PACKET tempinput;
1153 
1154 	sampletimer();
1155 
1156     if (!CommEnabled)
1157         return;
1158 
1159     while ((packbufleng = netgetpacket(&otherconnectindex, packbuf)) > 0)
1160         {
1161         switch (packbuf[0])
1162             {
1163         case PACKET_TYPE_BROADCAST:
1164 		case SERVER_GENERATED_BROADCAST:
1165             ////DSPRINTF(ds,"Receive Broadcast %d, ready2send %d",otherconnectindex, ready2send);
1166             //MONO_PRINT(ds);
1167 
1168             //ASSERT(ready2send);
1169             //if (!ready2send)
1170             //    break;
1171 
1172             j = 1;
1173 
1174             if ((Player[otherconnectindex].movefifoend & (TIMERUPDATESIZ - 1)) == 0)
1175                 {
1176                 if (otherconnectindex == connecthead)
1177                     {
1178                     for (i = connectpoint2[connecthead]; i >= 0; i = connectpoint2[i])
1179                         {
1180                         if (Player[i].IsDisconnected)
1181                             continue;
1182                         if (i == myconnectindex)
1183                             otherminlag = (int) ((signed char) packbuf[j]);
1184                         j++;
1185                         }
1186                     }
1187                 }
1188 
1189             pp = Player + otherconnectindex;
1190 
1191             #if !BIT_CODEC
1192             memcpy(&pp->inputfifo[pp->movefifoend & (MOVEFIFOSIZ - 1)], &packbuf[j], sizeof(SW_PACKET));
1193             j += sizeof(SW_PACKET);
1194             #else
1195             j += DecodeBits(&pp->inputfifo[(pp->movefifoend) & (MOVEFIFOSIZ - 1)],
1196                        &pp->inputfifo[(pp->movefifoend - 1) & (MOVEFIFOSIZ - 1)],
1197                        &packbuf[j]);
1198             #endif
1199 
1200             pp->movefifoend++;
1201 
1202             // Packet Duplication
1203             for (i = 1; i < MovesPerPacket; i++)
1204                 {
1205                 memcpy(
1206                     &pp->inputfifo[pp->movefifoend & (MOVEFIFOSIZ - 1)],
1207                     &pp->inputfifo[(pp->movefifoend-1) & (MOVEFIFOSIZ - 1)],
1208                     sizeof(SW_PACKET));
1209 
1210                 pp->movefifoend++;
1211                 }
1212 
1213             #if SYNC_TEST
1214             GetSyncInfoFromPacket(packbuf, packbufleng, &j, otherconnectindex);
1215             #endif
1216 
1217         //DSPRINTF(ds,"Receive packet size %d",j);
1218         //MONO_PRINT(ds);
1219 
1220             break;
1221 
1222         case PACKET_TYPE_MASTER_TO_SLAVE:
1223             // Here slave is receiving
1224             j = 1;
1225 
1226             if ((Player[otherconnectindex].movefifoend & (TIMERUPDATESIZ - 1)) == 0)
1227                 {
1228                 for (i = connectpoint2[connecthead]; i >= 0; i = connectpoint2[i])
1229                     {
1230                     if (Player[i].IsDisconnected)
1231                         continue;
1232                     if (i == myconnectindex)
1233                         otherminlag = (int) ((signed char) packbuf[j]);
1234                     j++;
1235                     }
1236                 }
1237 
1238             TRAVERSE_CONNECT(i)
1239                 {
1240                 pp = Player + i;
1241 
1242                 #if !BIT_CODEC
1243                 if (i != myconnectindex)
1244                     {
1245                     memcpy(&pp->inputfifo[pp->movefifoend & (MOVEFIFOSIZ - 1)], &packbuf[j], sizeof(SW_PACKET));
1246                     pp->movefifoend++;
1247                     }
1248                 j += sizeof(SW_PACKET);
1249                 #else
1250                 if (i == myconnectindex)
1251                     {
1252                     j += DecodeBits(&tempinput,
1253                                     &pp->inputfifo[(pp->movefifoend - 1) & (MOVEFIFOSIZ - 1)],
1254                                     &packbuf[j]);
1255                     }
1256                 else
1257                     {
1258                     j += DecodeBits(&pp->inputfifo[(pp->movefifoend) & (MOVEFIFOSIZ - 1)],
1259                                     &pp->inputfifo[(pp->movefifoend - 1) & (MOVEFIFOSIZ - 1)],
1260                                     &packbuf[j]);
1261                     pp->movefifoend++;
1262                     }
1263                 #endif
1264                 }
1265 
1266             while (j < packbufleng)
1267                 {
1268                 for (i = connecthead; i >= 0; i = connectpoint2[i])
1269                     {
1270                     if (i != myconnectindex)
1271                         {
1272                         for (sb = 0; sb < NumSyncBytes; sb++)
1273                             {
1274                             Player[i].syncval[Player[i].syncvalhead & (SYNCFIFOSIZ - 1)][sb] = packbuf[j + sb];
1275                             }
1276 
1277                         Player[i].syncvalhead++;
1278                         }
1279                     }
1280 
1281                 j += NumSyncBytes;
1282                 }
1283 
1284             // #if SYNC_TEST   //This doesn't work right in this case
1285             // GetSyncInfoFromPacket(packbufleng, &j, otherconnectindex);
1286             // #endif
1287 
1288             for(i=connecthead;i>=0;i=connectpoint2[i])
1289                 if (i != myconnectindex)
1290                     for(j=1;j<MovesPerPacket;j++)
1291                         {
1292                             pp = Player + i;
1293                             if (pp->IsDisconnected)
1294                                 continue;
1295 
1296                             memcpy(
1297                                 &pp->inputfifo[pp->movefifoend & (MOVEFIFOSIZ - 1)],
1298                                 &pp->inputfifo[(pp->movefifoend-1) & (MOVEFIFOSIZ - 1)],
1299                                 sizeof(SW_PACKET));
1300 
1301                             pp->movefifoend++;
1302                         }
1303 
1304             break;
1305 
1306         case PACKET_TYPE_SLAVE_TO_MASTER:
1307             // Here master is receiving
1308             pp = Player + otherconnectindex;
1309             j = 1;
1310 
1311             #if !BIT_CODEC
1312             memcpy(&pp->inputfifo[Player[otherconnectindex].movefifoend & (MOVEFIFOSIZ - 1)], &packbuf[j], sizeof(SW_PACKET));
1313             j += sizeof(SW_PACKET);
1314             #else
1315             j += DecodeBits(&pp->inputfifo[(Player[otherconnectindex].movefifoend) & (MOVEFIFOSIZ - 1)],
1316                        &pp->inputfifo[(Player[otherconnectindex].movefifoend - 1) & (MOVEFIFOSIZ - 1)],
1317                        &packbuf[j]);
1318             #endif
1319 
1320             Player[otherconnectindex].movefifoend++;
1321 
1322             #if SYNC_TEST
1323             GetSyncInfoFromPacket(packbuf, packbufleng, &j, otherconnectindex);
1324             #endif
1325 
1326             // Tic duping
1327             for (i = 1; i < MovesPerPacket; i++)
1328                 {
1329                 memcpy(&pp->inputfifo[(Player[otherconnectindex].movefifoend) & (MOVEFIFOSIZ - 1)],
1330                        &pp->inputfifo[(Player[otherconnectindex].movefifoend - 1) & (MOVEFIFOSIZ - 1)],
1331                        sizeof(SW_PACKET));
1332                 Player[otherconnectindex].movefifoend++;
1333                 }
1334 
1335             break;
1336 
1337         case PACKET_TYPE_MESSAGE:
1338             {
1339             PLAYERp tp = Player + myconnectindex;
1340 
1341             pp = Player + otherconnectindex;
1342 
1343             PlaySound(DIGI_PMESSAGE,&tp->posx,&tp->posy,&tp->posz,v3df_dontpan);
1344 
1345             memcpy(ds,&packbuf[3],packbufleng-3);
1346             ds[packbufleng-3] = 0;
1347             //sprintf(ds, "%s",&packbuf[3]);
1348             adduserquote(ds);
1349             break;
1350             }
1351 
1352         case PACKET_TYPE_RTS:
1353             {
1354             PACKET_RTSp p;
1355 
1356             p = (void *)&packbuf[0];
1357 
1358             PlaySoundRTS(p->RTSnum);
1359 
1360             break;
1361             }
1362 
1363 
1364         case PACKET_TYPE_NEW_GAME:
1365             {
1366             extern BOOL NewGame, ShortGameMode, DemoInitOnce;
1367             PACKET_NEW_GAMEp p;
1368             extern short TimeLimitTable[];
1369 
1370             pp = Player + otherconnectindex;
1371 
1372             // Dukes New Game Packet
1373             //level_number //volume_number //player_skill //monsters_off //respawn_monsters
1374             //respawn_items //respawn_inventory //coop //marker //friendlyfire //boardname
1375 
1376             p = (void *)&packbuf[0];
1377 
1378             ready2send = 0;
1379 
1380             Level = p->Level;
1381             Skill = p->Skill;
1382 
1383             gNet.HurtTeammate = p->HurtTeammate;
1384             gNet.SpawnMarkers = p->SpawnMarkers;
1385             gNet.TeamPlay   = p->TeamPlay;
1386             gNet.AutoAim    = p->AutoAim;
1387             gNet.Nuke       = p->Nuke;
1388             gNet.KillLimit          = p->KillLimit*10;
1389             gNet.TimeLimit          = TimeLimitTable[p->TimeLimit]*60*120;
1390 
1391             if (ShortGameMode)
1392                 {
1393                 gNet.KillLimit /= 10;
1394                 gNet.TimeLimit /= 2;
1395                 }
1396 
1397             gNet.TimeLimitClock = gNet.TimeLimit;
1398             gNet.MultiGameType = p->GameType+1;
1399 
1400             // settings for No Respawn Commbat mode
1401             if (gNet.MultiGameType == MULTI_GAME_COMMBAT_NO_RESPAWN)
1402                 {
1403                 gNet.MultiGameType = MULTI_GAME_COMMBAT;
1404                 gNet.NoRespawn = TRUE;
1405                 }
1406             else
1407                 {
1408                 gNet.NoRespawn = FALSE;
1409                 }
1410 
1411             ExitLevel = TRUE;
1412             NewGame = TRUE;
1413             // restart demo for multi-play mode
1414             DemoInitOnce = FALSE;
1415             ResetMenuInput();
1416 
1417             // send a dummy packet to see when it arrives
1418             //tempbuf[0] = PACKET_TYPE_DUMMY;
1419             //sendpacket(otherconnectindex, tempbuf, 1);
1420 
1421             ////DSPRINTF(ds,"Level %d, Skill %d, AutoAim %d",Level, Skill, gs.AutoAim);
1422             //MONO_PRINT(ds);
1423 
1424             break;
1425             }
1426 
1427         case PACKET_TYPE_DUMMY:
1428             ////DSPRINTF(ds,"Got Dummy Packet!!!");
1429             //MONO_PRINT(ds);
1430             break;
1431 
1432         case PACKET_TYPE_VERSION:
1433             {
1434             PACKET_VERSIONp p;
1435 
1436             pp = Player + otherconnectindex;
1437             p = (void *)&packbuf[0];
1438 
1439             pp->PlayerVersion = p->Version;
1440             break;
1441             }
1442 
1443         case PACKET_TYPE_PLAYER_OPTIONS:
1444             {
1445             PACKET_OPTIONSp p;
1446 
1447             pp = Player + otherconnectindex;
1448             p = (void *)&packbuf[0];
1449 
1450             // auto run
1451             if (p->AutoRun)
1452                 SET(pp->Flags, PF_LOCK_RUN);
1453             else
1454                 RESET(pp->Flags, PF_LOCK_RUN);
1455 
1456             // mouse aiming on
1457             if (p->MouseAimingOn)
1458                 SET(pp->Flags, PF_MOUSE_AIMING_ON);
1459             else
1460                 RESET(pp->Flags, PF_MOUSE_AIMING_ON);
1461 
1462             // palette
1463             pp->TeamColor = p->Color;
1464             pp->SpriteP->pal = PALETTE_PLAYER0 + pp->TeamColor;
1465             User[pp->SpriteP - sprite]->spal = pp->SpriteP->pal;
1466 
1467             // names
1468             strcpy(pp->PlayerName, p->PlayerName);
1469 
1470             break;
1471             }
1472 
1473         case PACKET_TYPE_NAME_CHANGE:
1474             {
1475             PACKET_NAME_CHANGEp p;
1476             pp = Player + otherconnectindex;
1477             p = (void *)&packbuf[0];
1478 
1479             // someone else has changed their name
1480 
1481             DSPRINTF(ds,"Recieved name: %s",p->PlayerName);
1482             MONO_PRINT(ds);
1483 
1484             strcpy(pp->PlayerName, p->PlayerName);
1485             SetRedrawScreen(Player+myconnectindex);
1486 
1487             // palette
1488             pp->TeamColor = p->Color;
1489             if (pp->SpriteP)
1490                 {
1491                 pp->SpriteP->pal = PALETTE_PLAYER0 + pp->TeamColor;
1492                 User[pp->SpriteP - sprite]->spal = pp->SpriteP->pal;
1493                 }
1494             break;
1495             }
1496 
1497 
1498         case PACKET_TYPE_MENU_LEVEL_QUIT:
1499             {
1500             PlayerQuitMenuLevel = otherconnectindex;
1501             break;
1502             }
1503 
1504         case PACKET_TYPE_PLAYER_READY:
1505             Player[otherconnectindex].playerreadyflag++;
1506 			// It's important to return from getpackets() when a ready packet comes in and
1507 			// you are inside waitforeverybody(). Otherwise multiple ready packets can come
1508 			// in inside one waitforeverybody() which causes havoc if that w4e is protecting
1509 			// an initialization step which (heh) for example resets the playerreadyflag count.
1510 			return;
1511             //break;
1512 
1513         case PACKET_TYPE_DONT_USE:
1514             break;
1515 
1516         case PACKET_TYPE_NULL_PACKET:
1517             break;
1518 
1519 	case PACKET_TYPE_PROXY:
1520 	    buildputs("getpackets(): nested proxy packets!?\n");
1521 	    break;
1522 
1523         default:
1524             DSPRINTF(ds,"Packet type unknown %d",packbuf[0]);
1525             MONO_PRINT(ds);
1526             }
1527         }
1528     }
1529