3339 lines
82 KiB
C
3339 lines
82 KiB
C
|
/*
|
|||
|
Copyright (C) 1994-1995 Apogee Software, Ltd.
|
|||
|
|
|||
|
This program is free software; you can redistribute it and/or
|
|||
|
modify it under the terms of the GNU General Public License
|
|||
|
as published by the Free Software Foundation; either version 2
|
|||
|
of the License, or (at your option) any later version.
|
|||
|
|
|||
|
This program is distributed in the hope that it will be useful,
|
|||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|||
|
|
|||
|
See the GNU General Public License for more details.
|
|||
|
|
|||
|
You should have received a copy of the GNU General Public License
|
|||
|
along with this program; if not, write to the Free Software
|
|||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
|
|||
|
*/
|
|||
|
|
|||
|
#include <string.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <stdio.h>
|
|||
|
#include <fcntl.h>
|
|||
|
|
|||
|
#ifdef DOS
|
|||
|
#include <dos.h>
|
|||
|
#include <io.h>
|
|||
|
#endif
|
|||
|
|
|||
|
#include "rt_def.h"
|
|||
|
#include "rt_main.h"
|
|||
|
#include "rt_net.h"
|
|||
|
#include "rt_com.h"
|
|||
|
#include "_rt_net.h"
|
|||
|
#include "rt_actor.h"
|
|||
|
#include "rt_playr.h"
|
|||
|
#include "isr.h"
|
|||
|
#include "z_zone.h"
|
|||
|
#include "develop.h"
|
|||
|
#include "rottnet.h"
|
|||
|
#include "rt_msg.h"
|
|||
|
#include "rt_sound.h"
|
|||
|
#include "rt_menu.h"
|
|||
|
#include "rt_util.h"
|
|||
|
#include "rt_rand.h"
|
|||
|
#include "rt_game.h"
|
|||
|
#include "rt_draw.h"
|
|||
|
#include "myprint.h"
|
|||
|
#include "rt_debug.h"
|
|||
|
#include "rt_view.h"
|
|||
|
#include "rt_battl.h"
|
|||
|
#include "rt_dmand.h"
|
|||
|
//MED
|
|||
|
#include "memcheck.h"
|
|||
|
|
|||
|
#if (SYNCCHECK == 1)
|
|||
|
int lastsynccheck;
|
|||
|
COM_CheckSyncType PlayerSync[MAXPLAYERS];
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
CommandType * LocalCmds;
|
|||
|
CommandType * ServerCmds;
|
|||
|
|
|||
|
|
|||
|
int controlupdatestartedtime=-1;
|
|||
|
int controlupdatetime=-1;
|
|||
|
int serverupdatetime=-1;
|
|||
|
int controlupdatestarted=0;
|
|||
|
boolean GamePaused=false;
|
|||
|
|
|||
|
boolean modemgame;
|
|||
|
boolean networkgame;
|
|||
|
int numplayers;
|
|||
|
int server;
|
|||
|
boolean IsServer;
|
|||
|
boolean standalone;
|
|||
|
boolean restartgame=false;
|
|||
|
boolean respawnactive=false;
|
|||
|
boolean playerdead=false;
|
|||
|
boolean controlschanged=true;
|
|||
|
boolean battlegibs=false;
|
|||
|
boolean remoteridicule = false;
|
|||
|
/*
|
|||
|
=============================================================================
|
|||
|
|
|||
|
LOCAL FUNCTION PROTOTYPES and VARIABLES
|
|||
|
|
|||
|
=============================================================================
|
|||
|
*/
|
|||
|
boolean demorecord,
|
|||
|
demoplayback;
|
|||
|
byte *demoptr,
|
|||
|
*lastdemoptr,
|
|||
|
*demobuffer=NULL;
|
|||
|
boolean demodone = false;
|
|||
|
int predemo_violence = -1;
|
|||
|
int oldmomx;
|
|||
|
int oldmomy;
|
|||
|
int oldspdang;
|
|||
|
|
|||
|
static boolean GameCommandsStarted=false;
|
|||
|
|
|||
|
static int oldcontrolbuf[3];
|
|||
|
static int oldbuttonbits;
|
|||
|
static CommandType * PlayerCmds[MAXPLAYERS];
|
|||
|
static CommandType * ClientCmds[MAXPLAYERS];
|
|||
|
|
|||
|
static boolean GotPlayersDesc[MAXPLAYERS];
|
|||
|
static boolean PlayersReady[MAXPLAYERS];
|
|||
|
static int LastCommandTime[MAXPLAYERS];
|
|||
|
|
|||
|
static CommandStatusType * CommandState[MAXPLAYERS+1];
|
|||
|
|
|||
|
static boolean InProcessServer=false;
|
|||
|
static int lastcontrolupdatetime;
|
|||
|
static int largesttime;
|
|||
|
static int PlayerStatus[MAXPLAYERS];
|
|||
|
//static int syncservertime;
|
|||
|
//static boolean FixingPackets;
|
|||
|
static int controldivisor=1;
|
|||
|
static int nextupdatetime;
|
|||
|
static boolean UpdateServer=true;
|
|||
|
|
|||
|
void CheckForPacket ( void );
|
|||
|
void PrepareLocalPacket ( void );
|
|||
|
void SendSyncCheckPacket ( void );
|
|||
|
void AddModemSubPacket(void * incoming);
|
|||
|
void SetPlayerDescription( void * pkt );
|
|||
|
void UpdateDemoPlayback (int time);
|
|||
|
int GetTypeSize (int type);
|
|||
|
int MaxSpeedForCharacter(playertype *pstate);
|
|||
|
|
|||
|
/*
|
|||
|
=============================================================================
|
|||
|
|
|||
|
Game Command Section
|
|||
|
|
|||
|
=============================================================================
|
|||
|
*/
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// ComError ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
#define ComError SoftError
|
|||
|
#if 0
|
|||
|
void ComError (char *error, ...)
|
|||
|
{
|
|||
|
#if 0
|
|||
|
va_list argptr;
|
|||
|
#endif
|
|||
|
|
|||
|
SoftError(error);
|
|||
|
#if 0
|
|||
|
if (standalone==true)
|
|||
|
{
|
|||
|
va_start (argptr, error);
|
|||
|
vprintf (error, argptr);
|
|||
|
va_end (argptr);
|
|||
|
}
|
|||
|
#endif
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// ConsoleIsServer()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
boolean ConsoleIsServer ( void )
|
|||
|
{
|
|||
|
if (modemgame==true)
|
|||
|
{
|
|||
|
if (networkgame==true)
|
|||
|
{
|
|||
|
if (rottcom->client==0)
|
|||
|
{
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// GamePacketSize()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
int GamePacketSize( void )
|
|||
|
{
|
|||
|
if ((remoteridicule == true) || (ConsoleIsServer() == true))
|
|||
|
{
|
|||
|
return GetTypeSize(COM_SOUNDANDDELTA);
|
|||
|
}
|
|||
|
else
|
|||
|
return GetTypeSize(COM_TEXT);
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// InitializeGameCommands()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
void InitializeGameCommands( void )
|
|||
|
{
|
|||
|
int i;
|
|||
|
int j;
|
|||
|
|
|||
|
// default to player 0
|
|||
|
|
|||
|
if (GameCommandsStarted==true)
|
|||
|
return;
|
|||
|
|
|||
|
GameCommandsStarted=true;
|
|||
|
|
|||
|
if ((modemgame==true))
|
|||
|
controldivisor=rottcom->ticstep;
|
|||
|
|
|||
|
standalone=false;
|
|||
|
IsServer=false;
|
|||
|
|
|||
|
if (modemgame==true)
|
|||
|
{
|
|||
|
consoleplayer=rottcom->consoleplayer;
|
|||
|
|
|||
|
if (networkgame==true)
|
|||
|
{
|
|||
|
if (rottcom->client==0)
|
|||
|
{
|
|||
|
IsServer=true;
|
|||
|
// turn it on absolutely for the server
|
|||
|
remoteridicule = true;
|
|||
|
if (consoleplayer==0)
|
|||
|
standalone=true;
|
|||
|
}
|
|||
|
if (consoleplayer>0)
|
|||
|
consoleplayer--; // playernumber fixup
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (standalone==false)
|
|||
|
{
|
|||
|
int size;
|
|||
|
|
|||
|
size = GamePacketSize ();
|
|||
|
|
|||
|
for (i=0;i<numplayers;i++)
|
|||
|
{
|
|||
|
PlayerCmds[i]=(CommandType *)SafeLevelMalloc(sizeof(CommandType));
|
|||
|
for (j=0;j<MAXCMDS;j++)
|
|||
|
{
|
|||
|
PlayerCommand(i,j)=SafeLevelMalloc(size);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// allocate local commands
|
|||
|
|
|||
|
LocalCmds=(CommandType *)SafeLevelMalloc(sizeof(CommandType));
|
|||
|
for (j=0;j<MAXCMDS;j++)
|
|||
|
{
|
|||
|
int size;
|
|||
|
|
|||
|
size = GamePacketSize();
|
|||
|
|
|||
|
LocalCommand(j)=SafeLevelMalloc(size);
|
|||
|
memset(LocalCommand(j),COM_DELTANULL,size);
|
|||
|
}
|
|||
|
|
|||
|
CommandState[0]=(CommandStatusType *)SafeLevelMalloc(sizeof(CommandStatusType));
|
|||
|
|
|||
|
if (modemgame==true)
|
|||
|
{
|
|||
|
for (i=0;i<numplayers;i++)
|
|||
|
{
|
|||
|
PlayerStatus[i]=player_ingame;
|
|||
|
}
|
|||
|
if (networkgame==true)
|
|||
|
{
|
|||
|
server=1;
|
|||
|
|
|||
|
// initialize the Server
|
|||
|
|
|||
|
if (IsServer==true)
|
|||
|
{
|
|||
|
server=0;
|
|||
|
ServerCmds=(CommandType *)SafeMalloc(sizeof(CommandType));
|
|||
|
for (j=0;j<MAXCMDS;j++)
|
|||
|
{
|
|||
|
int size;
|
|||
|
size=( (numplayers * GetTypeSize(COM_TEXT)) +
|
|||
|
GetTypeSize(COM_SOUNDANDDELTA) +
|
|||
|
sizeof(COM_ServerHeaderType) -
|
|||
|
sizeof(byte)
|
|||
|
);
|
|||
|
ServerCommand(j)=SafeMalloc( size );
|
|||
|
memset(ServerCommand(j),COM_DELTANULL,size);
|
|||
|
}
|
|||
|
for (i=1;i<=numplayers;i++)
|
|||
|
{
|
|||
|
CommandState[i]=(CommandStatusType *)
|
|||
|
SafeMalloc(sizeof(CommandStatusType));
|
|||
|
}
|
|||
|
for (i=0;i<numplayers;i++)
|
|||
|
{
|
|||
|
ClientCmds[i]=(CommandType *)SafeMalloc(sizeof(CommandType));
|
|||
|
for (j=0;j<MAXCMDS;j++)
|
|||
|
{
|
|||
|
int size;
|
|||
|
|
|||
|
size=GetTypeSize(COM_SOUNDANDDELTA);
|
|||
|
ClientCommand(i,j)=SafeMalloc(size);
|
|||
|
memset(ClientCommand(i,j),COM_DELTANULL,size);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else // must be a two player game
|
|||
|
{
|
|||
|
server=consoleplayer^1;
|
|||
|
}
|
|||
|
}
|
|||
|
#if 0
|
|||
|
#if (DEVELOPMENT == 1)
|
|||
|
if (IsServer)
|
|||
|
ComError("I am the server\n");
|
|||
|
ComError("consoleplayer=%ld\n",consoleplayer);
|
|||
|
ComError("server=%ld mynumber=%ld\n",server,consoleplayer);
|
|||
|
#endif
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// ShutdownGameCommands()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
void ShutdownGameCommands( void )
|
|||
|
{
|
|||
|
int i;
|
|||
|
int j;
|
|||
|
|
|||
|
if (GameCommandsStarted==false)
|
|||
|
return;
|
|||
|
|
|||
|
GameCommandsStarted=false;
|
|||
|
|
|||
|
// free up playercmds;
|
|||
|
if (standalone==false)
|
|||
|
{
|
|||
|
for (i=0;i<numplayers;i++)
|
|||
|
{
|
|||
|
for (j=0;j<MAXCMDS;j++)
|
|||
|
{
|
|||
|
if (PlayerCommand(i,j))
|
|||
|
{
|
|||
|
SafeFree(PlayerCommand(i,j));
|
|||
|
PlayerCommand(i,j)=NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
SafeFree( PlayerCmds[i] );
|
|||
|
PlayerCmds[i]=NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// free up command status
|
|||
|
|
|||
|
SafeFree(CommandState[0]);
|
|||
|
CommandState[0]=NULL;
|
|||
|
|
|||
|
if (modemgame==true)
|
|||
|
{
|
|||
|
|
|||
|
// free up local commands
|
|||
|
|
|||
|
for (j=0;j<MAXCMDS;j++)
|
|||
|
{
|
|||
|
if (LocalCommand(j))
|
|||
|
{
|
|||
|
SafeFree(LocalCommand(j));
|
|||
|
LocalCommand(j)=NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
SafeFree(LocalCmds);
|
|||
|
LocalCmds=NULL;
|
|||
|
|
|||
|
|
|||
|
// free up Server
|
|||
|
|
|||
|
if (networkgame==true)
|
|||
|
{
|
|||
|
if (IsServer==true)
|
|||
|
{
|
|||
|
for (j=0;j<MAXCMDS;j++)
|
|||
|
{
|
|||
|
if (ServerCommand(j))
|
|||
|
{
|
|||
|
SafeFree(ServerCommand(j));
|
|||
|
ServerCommand(j)=NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
SafeFree(ServerCmds);
|
|||
|
ServerCmds=NULL;
|
|||
|
for (i=1;i<=numplayers;i++)
|
|||
|
{
|
|||
|
SafeFree(CommandState[i]);
|
|||
|
CommandState[i]=NULL;
|
|||
|
}
|
|||
|
for (i=0;i<numplayers;i++)
|
|||
|
{
|
|||
|
for (j=0;j<MAXCMDS;j++)
|
|||
|
{
|
|||
|
if (ClientCommand(i,j))
|
|||
|
{
|
|||
|
SafeFree(ClientCommand(i,j));
|
|||
|
ClientCommand(i,j)=NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
SafeFree( ClientCmds[i] );
|
|||
|
ClientCmds[i]=NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
=============================================================================
|
|||
|
|
|||
|
Client Controls Section
|
|||
|
|
|||
|
=============================================================================
|
|||
|
*/
|
|||
|
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// ShutdownClientControls ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void ShutdownClientControls ( void )
|
|||
|
{
|
|||
|
int i;
|
|||
|
#if (DEVELOPMENT == 1)
|
|||
|
SoftError ("LARGEST time difference=%ld\n",largesttime);
|
|||
|
#endif
|
|||
|
controlupdatestarted=0;
|
|||
|
for (i=0;i<numplayers;i++)
|
|||
|
{
|
|||
|
if (PlayerStatus[i] == player_leftgame)
|
|||
|
PlayerStatus[i]=player_ingame;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// StartupClientControls ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void StartupClientControls ( void )
|
|||
|
{
|
|||
|
int i,j;
|
|||
|
|
|||
|
if (controlupdatestarted==1)
|
|||
|
return;
|
|||
|
|
|||
|
controlupdatestarted=1;
|
|||
|
|
|||
|
memset(oldcontrolbuf,-1,sizeof(oldcontrolbuf));
|
|||
|
oldbuttonbits=-1;
|
|||
|
controlschanged=true;
|
|||
|
|
|||
|
INL_GetMouseDelta(&i,&i);
|
|||
|
|
|||
|
|
|||
|
locplayerstate->dmomx = 0;
|
|||
|
locplayerstate->dmomy = 0;
|
|||
|
locplayerstate->angle = 0;
|
|||
|
locplayerstate->topspeed=MaxSpeedForCharacter(locplayerstate);
|
|||
|
|
|||
|
|
|||
|
CalcTics();
|
|||
|
CalcTics();
|
|||
|
|
|||
|
// FixingPackets=false;
|
|||
|
|
|||
|
memset (controlbuf, 0, sizeof (controlbuf));
|
|||
|
buttonbits = 0;
|
|||
|
lastpolltime=-1;
|
|||
|
IN_ClearKeyboardQueue ();
|
|||
|
|
|||
|
if (modemgame==true)
|
|||
|
{
|
|||
|
controlupdatetime=controlsynctime+(VBLCOUNTER*2);
|
|||
|
SoftError("Controls started at %d\n",controlupdatetime);
|
|||
|
}
|
|||
|
else if (demoplayback || demorecord)
|
|||
|
{
|
|||
|
ISR_SetTime(20);
|
|||
|
oldtime = 20;
|
|||
|
controlupdatetime=20;
|
|||
|
}
|
|||
|
else
|
|||
|
controlupdatetime=GetTicCount();
|
|||
|
|
|||
|
controlupdatetime-=(controlupdatetime%controldivisor);
|
|||
|
|
|||
|
serverupdatetime=controlupdatetime;
|
|||
|
oldpolltime=controlupdatetime;
|
|||
|
nextupdatetime=oldpolltime;
|
|||
|
#if (SYNCCHECK == 1)
|
|||
|
lastsynccheck=oldpolltime+CHECKSYNCTIME;
|
|||
|
#endif
|
|||
|
controlupdatestartedtime=controlupdatetime;
|
|||
|
|
|||
|
for( j = 0; j < numplayers; j++ )
|
|||
|
{
|
|||
|
memset( PLAYERSTATE[ j ].buttonheld, 0,
|
|||
|
sizeof( PLAYERSTATE[ j ].buttonheld ) );
|
|||
|
memset( PLAYERSTATE[ j ].buttonstate, 0,
|
|||
|
sizeof( PLAYERSTATE[ j ].buttonstate ) );
|
|||
|
}
|
|||
|
|
|||
|
for (i=0;i<MAXCMDS;i++)
|
|||
|
{
|
|||
|
ServerCommandNumberStatus( i ) = cs_notarrived;
|
|||
|
}
|
|||
|
|
|||
|
LastCommandTime[0]=controlupdatetime-controldivisor;
|
|||
|
if (IsServer==true)
|
|||
|
{
|
|||
|
int size;
|
|||
|
|
|||
|
UpdateServer=true;
|
|||
|
size=( (numplayers * GetTypeSize(COM_TEXT)) +
|
|||
|
GetTypeSize(COM_SOUNDANDDELTA) +
|
|||
|
sizeof(COM_ServerHeaderType) -
|
|||
|
sizeof(byte)
|
|||
|
);
|
|||
|
|
|||
|
for (j=0;j<numplayers;j++)
|
|||
|
{
|
|||
|
for (i=0;i<MAXCMDS;i++)
|
|||
|
{
|
|||
|
ClientCommandNumberStatus( j , i ) = cs_notarrived;
|
|||
|
}
|
|||
|
LastCommandTime[j]=controlupdatetime-controldivisor;
|
|||
|
}
|
|||
|
for (i=0;i<MAXCMDS;i++)
|
|||
|
memset(ServerCommand(i),COM_DELTANULL,size);
|
|||
|
}
|
|||
|
else if (modemgame==true)
|
|||
|
{
|
|||
|
int nump;
|
|||
|
|
|||
|
nump=numplayers;
|
|||
|
if (nump<2) nump=2;
|
|||
|
|
|||
|
for (i=0;i<nump;i++)
|
|||
|
{
|
|||
|
LastCommandTime[i]=controlupdatetime-controldivisor;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#if (DEVELOPMENT == 1)
|
|||
|
// ComError("StartupClientControls: GetTicCount()=%ld oldtime=%ld controlupdatetime=%ld\n",GetTicCount(),oldtime,controlupdatetime);
|
|||
|
#endif
|
|||
|
|
|||
|
if ((demoplayback==false) && (standalone==false))
|
|||
|
{
|
|||
|
if (modemgame==true)
|
|||
|
{
|
|||
|
while (GetTicCount()<(controlupdatetime-10))
|
|||
|
{
|
|||
|
CalcTics();
|
|||
|
}
|
|||
|
}
|
|||
|
lastcontrolupdatetime=GetTicCount();
|
|||
|
largesttime=0;
|
|||
|
PollControls();
|
|||
|
}
|
|||
|
if (standalone==true)
|
|||
|
printf("Packet Server started\n");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// UpdateClientControls ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
static boolean InUCC=false;
|
|||
|
void UpdateClientControls ( void )
|
|||
|
{
|
|||
|
int time;
|
|||
|
// int delta;
|
|||
|
|
|||
|
if (controlupdatestarted==0)
|
|||
|
return;
|
|||
|
|
|||
|
if (InUCC)
|
|||
|
return;
|
|||
|
else
|
|||
|
InUCC = true;
|
|||
|
|
|||
|
wami(6);
|
|||
|
|
|||
|
#if 0
|
|||
|
|
|||
|
delta=GetTicCount()-lastcontrolupdatetime;
|
|||
|
if (delta>largesttime)
|
|||
|
{
|
|||
|
if (delta>10)
|
|||
|
largesttime=delta;
|
|||
|
largesttime=delta;
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
lastcontrolupdatetime=GetTicCount();
|
|||
|
|
|||
|
if (standalone==false)
|
|||
|
{
|
|||
|
time=GetTicCount();
|
|||
|
|
|||
|
// if we are a fixing the current packet stop update of deltas
|
|||
|
// in non-network games.
|
|||
|
if (
|
|||
|
(networkgame == false) &&
|
|||
|
(ServerCommandStatus(oldpolltime)==cs_fixing)
|
|||
|
)
|
|||
|
{
|
|||
|
time=controlupdatetime-controldivisor;
|
|||
|
}
|
|||
|
|
|||
|
while (time>=controlupdatetime)
|
|||
|
{
|
|||
|
MoveType * Delta;
|
|||
|
boolean soundready;
|
|||
|
|
|||
|
soundready = SD_SoundDataReady();
|
|||
|
|
|||
|
if (demoplayback==true)
|
|||
|
{
|
|||
|
UpdateDemoPlayback(controlupdatetime);
|
|||
|
}
|
|||
|
// else
|
|||
|
// {
|
|||
|
// PollControls();
|
|||
|
// }
|
|||
|
|
|||
|
if (
|
|||
|
(memcmp(&controlbuf[0],&oldcontrolbuf[0],sizeof(controlbuf))!=0) ||
|
|||
|
(buttonbits!=oldbuttonbits)
|
|||
|
)
|
|||
|
{
|
|||
|
controlschanged=true;
|
|||
|
memcpy(&oldcontrolbuf[0],&controlbuf[0],sizeof(controlbuf));
|
|||
|
oldbuttonbits=buttonbits;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
controlschanged=false;
|
|||
|
}
|
|||
|
|
|||
|
if ((controlschanged==false) && (soundready==false))
|
|||
|
{
|
|||
|
NullMoveType * NullDelta;
|
|||
|
|
|||
|
NullDelta=(NullMoveType *)NextLocalCommand();
|
|||
|
NullDelta->type=COM_DELTANULL;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Delta=(MoveType *)NextLocalCommand();
|
|||
|
Delta->type=COM_DELTA;
|
|||
|
Delta->momx=(controlbuf[0]>>1);
|
|||
|
Delta->momy=(controlbuf[1]>>1);
|
|||
|
Delta->dangle=controlbuf[2]>>11;
|
|||
|
Delta->buttons=buttonbits;
|
|||
|
|
|||
|
// See if we need to update sound packet
|
|||
|
|
|||
|
if (soundready==true)
|
|||
|
{
|
|||
|
COM_SoundType * sndpkt;
|
|||
|
recordstate status;
|
|||
|
|
|||
|
if (remoteridicule == false)
|
|||
|
Error("Attempt to record Remote Ridicule without adequate storage");
|
|||
|
sndpkt=(COM_SoundType *)Delta->Sounddata;
|
|||
|
|
|||
|
// Turn the packet into a COM_SOUNDANDDELTA packet
|
|||
|
|
|||
|
Delta->type=COM_SOUNDANDDELTA;
|
|||
|
status = SD_GetSoundData ( &(sndpkt->data[0]),
|
|||
|
COM_SOUND_BUFFERSIZE );
|
|||
|
switch (status)
|
|||
|
{
|
|||
|
case rs_nodata:
|
|||
|
Delta->type=COM_DELTA;
|
|||
|
break;
|
|||
|
case rs_newsound:
|
|||
|
sndpkt->type=COM_SOUND_START_TRANSMISSION;
|
|||
|
break;
|
|||
|
case rs_endsound:
|
|||
|
sndpkt->type=COM_SOUND_END_TRANSMISSION;
|
|||
|
break;
|
|||
|
case rs_data:
|
|||
|
sndpkt->type=COM_SOUND_NORMAL_TRANSMISSION;
|
|||
|
break;
|
|||
|
default:
|
|||
|
Error("Illegal return value for SD_GetSoundData");
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
if (demorecord==true)
|
|||
|
RecordDemoCmd();
|
|||
|
}
|
|||
|
PrepareLocalPacket();
|
|||
|
|
|||
|
if (
|
|||
|
(controlupdatetime != -1) &&
|
|||
|
(controlupdatetime > (lastpolltime+MAXPOLLTICS)) &&
|
|||
|
(demoplayback==false)
|
|||
|
)
|
|||
|
{
|
|||
|
controlbuf[0] = controlbuf[1] = controlbuf[2] = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
if (modemgame==true)
|
|||
|
{
|
|||
|
CheckForPacket ();
|
|||
|
}
|
|||
|
|
|||
|
if ((standalone == false) && (IsServer==true) && (UpdateServer==true))
|
|||
|
ProcessServer();
|
|||
|
|
|||
|
// take out
|
|||
|
if (modemgame==true)
|
|||
|
{
|
|||
|
//#if (DEVELOPMENT == 1)
|
|||
|
if (PanicPressed==true)
|
|||
|
{
|
|||
|
Error("Game Aborted. Scroll Lock pressed\n");
|
|||
|
}
|
|||
|
//#endif
|
|||
|
if (Keyboard[sc_Insert] && Keyboard[sc_Q])
|
|||
|
Error("Game Aborted. Insert->Q pressed\n");
|
|||
|
}
|
|||
|
|
|||
|
InUCC = false;
|
|||
|
|
|||
|
waminot();
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// PlayerInGame()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
boolean PlayerInGame ( int p )
|
|||
|
{
|
|||
|
if (PlayerStatus[p]!=player_ingame)
|
|||
|
return false;
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
=============================================================================
|
|||
|
|
|||
|
Packet Section
|
|||
|
|
|||
|
=============================================================================
|
|||
|
*/
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// CheckForPacket()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
void CheckForPacket ( void )
|
|||
|
{
|
|||
|
wami(7);
|
|||
|
while (ReadPacket()==true)
|
|||
|
{
|
|||
|
if (badpacket==0)
|
|||
|
{
|
|||
|
ProcessPacket(&ROTTpacket[0], rottcom->remotenode);
|
|||
|
#if (DEVELOPMENT == 1)
|
|||
|
// ComError("CheckForPacket: from=%ld\n",rottcom->remotenode);
|
|||
|
#endif
|
|||
|
}
|
|||
|
else
|
|||
|
RequestPacket (LastCommandTime[rottcom->remotenode]+controldivisor, rottcom->remotenode, controldivisor);
|
|||
|
}
|
|||
|
waminot();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// AddRemoteRidiculeCommand()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
void AddRemoteRidiculeCommand ( int player, int towho, int num )
|
|||
|
{
|
|||
|
((COM_RemoteRidiculeType *)NextLocalCommand())->type=COM_REMRID;
|
|||
|
((COM_RemoteRidiculeType *)NextLocalCommand())->num=num;
|
|||
|
((COM_RemoteRidiculeType *)NextLocalCommand())->player=player;
|
|||
|
((COM_RemoteRidiculeType *)NextLocalCommand())->towho=towho;
|
|||
|
|
|||
|
PrepareLocalPacket();
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// ProcessRemoteRidicule()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
void ProcessRemoteRidicule ( void * pkt )
|
|||
|
{
|
|||
|
COM_RemoteRidiculeType * remrot;
|
|||
|
char name[ 50 ];
|
|||
|
int from;
|
|||
|
int who;
|
|||
|
|
|||
|
remrot = (COM_RemoteRidiculeType *)pkt;
|
|||
|
from = remrot->player;
|
|||
|
who = remrot->towho;
|
|||
|
if ( ( who == consoleplayer ) || ( who == MSG_DIRECTED_TO_ALL ) ||
|
|||
|
( ( who == MSG_DIRECTED_TO_TEAM ) && ( BATTLE_Team[ from ] ==
|
|||
|
BATTLE_Team[ consoleplayer ] ) ) )
|
|||
|
{
|
|||
|
strcpy( name, "(<28> RR from " );
|
|||
|
strcat( name, PLAYERSTATE[from].codename );
|
|||
|
strcat( name, ")" );
|
|||
|
AddMessage( name, MSG_REMOTERIDICULE );
|
|||
|
|
|||
|
SD_Play( SD_REMOTEM1SND + remrot->num );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// AddEndGameCommand()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
void AddEndGameCommand ( void )
|
|||
|
{
|
|||
|
((COM_EndGameType *)NextLocalCommand())->type=COM_ENDGAME;
|
|||
|
|
|||
|
PrepareLocalPacket();
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// AddGameEndCommand()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
void AddGameEndCommand ( void )
|
|||
|
{
|
|||
|
((COM_GameEndType *)NextLocalCommand())->type=COM_GAMEEND;
|
|||
|
|
|||
|
PrepareLocalPacket();
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// AddQuitCommand()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
void AddQuitCommand ( void )
|
|||
|
{
|
|||
|
((COM_QuitType *)NextLocalCommand())->type=COM_QUIT;
|
|||
|
PrepareLocalPacket();
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// AddExitCommand()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
void AddExitCommand ( void )
|
|||
|
{
|
|||
|
((COM_ExitType *)NextLocalCommand())->type=COM_EXIT;
|
|||
|
PrepareLocalPacket();
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// AddPauseStateCommand()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
void AddPauseStateCommand ( int type )
|
|||
|
{
|
|||
|
((COM_PauseType *)NextLocalCommand())->type=type;
|
|||
|
|
|||
|
PrepareLocalPacket();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// AddRespawnCommand()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
void AddRespawnCommand ( void )
|
|||
|
{
|
|||
|
if (respawnactive==true)
|
|||
|
return;
|
|||
|
|
|||
|
respawnactive=true;
|
|||
|
|
|||
|
((COM_RespawnType *)NextLocalCommand())->type=COM_RESPAWN;
|
|||
|
|
|||
|
PrepareLocalPacket();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// AddTextMessage()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
void AddTextMessage
|
|||
|
(
|
|||
|
char *message,
|
|||
|
int length,
|
|||
|
int towho
|
|||
|
)
|
|||
|
|
|||
|
{
|
|||
|
COM_TextType *Text;
|
|||
|
|
|||
|
Text = ( COM_TextType * )NextLocalCommand();
|
|||
|
|
|||
|
Text->type = COM_TEXT;
|
|||
|
memset( &Text->string[ 0 ], 0, COM_MAXTEXTSTRINGLENGTH );
|
|||
|
|
|||
|
if ( length >= COM_MAXTEXTSTRINGLENGTH )
|
|||
|
{
|
|||
|
length = COM_MAXTEXTSTRINGLENGTH - 1;
|
|||
|
}
|
|||
|
|
|||
|
memcpy( &Text->string[ 0 ], message, length );
|
|||
|
|
|||
|
Text->towho = towho;
|
|||
|
|
|||
|
PrepareLocalPacket();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// PrepareLocalPacket
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void PrepareLocalPacket ( void )
|
|||
|
{
|
|||
|
MoveType * pkt;
|
|||
|
|
|||
|
wami(8);
|
|||
|
|
|||
|
pkt=(MoveType *)NextLocalCommand();
|
|||
|
|
|||
|
pkt->time=controlupdatetime;
|
|||
|
|
|||
|
if (networkgame==false) // Whether it is a modem game or not we do this
|
|||
|
{
|
|||
|
AddClientPacket (pkt, consoleplayer);
|
|||
|
if (modemgame==false)
|
|||
|
{
|
|||
|
ServerCommandStatus ( controlupdatetime ) = cs_ready;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (modemgame==true)
|
|||
|
SendPacket (pkt, server);
|
|||
|
|
|||
|
#if (DEVELOPMENT == 1)
|
|||
|
// ComError("packet sent: realtime=%ld time=%ld type=%ld dest=%ld\n",GetTicCount(),pkt->time,pkt->type,server);
|
|||
|
#endif
|
|||
|
|
|||
|
controlupdatetime+=controldivisor;
|
|||
|
waminot();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// GetPacketSize ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
int GetPacketSize (void * pkt)
|
|||
|
{
|
|||
|
int size;
|
|||
|
|
|||
|
switch (((MoveType *)pkt)->type)
|
|||
|
{
|
|||
|
case COM_DELTA:
|
|||
|
size=sizeof(MoveType);
|
|||
|
break;
|
|||
|
case COM_DELTANULL:
|
|||
|
size=sizeof(NullMoveType);
|
|||
|
break;
|
|||
|
case COM_REQUEST:
|
|||
|
size=sizeof(COM_RequestType);
|
|||
|
break;
|
|||
|
case COM_FIXUP:
|
|||
|
size=sizeof(COM_FixupType);
|
|||
|
break;
|
|||
|
case COM_TEXT:
|
|||
|
size=sizeof(COM_TextType);
|
|||
|
break;
|
|||
|
case COM_PAUSE:
|
|||
|
size=sizeof(COM_PauseType);
|
|||
|
break;
|
|||
|
case COM_QUIT:
|
|||
|
size=sizeof(COM_QuitType);
|
|||
|
break;
|
|||
|
case COM_EXIT:
|
|||
|
size=sizeof(COM_ExitType);
|
|||
|
break;
|
|||
|
case COM_REMRID:
|
|||
|
size=sizeof(COM_RemoteRidiculeType);
|
|||
|
break;
|
|||
|
case COM_RESPAWN:
|
|||
|
size=sizeof(COM_RespawnType);
|
|||
|
break;
|
|||
|
case COM_UNPAUSE:
|
|||
|
size=sizeof(COM_UnPauseType);
|
|||
|
break;
|
|||
|
case COM_SERVER:
|
|||
|
size=sizeof(COM_ServerHeaderType);
|
|||
|
size-=sizeof(byte);
|
|||
|
break;
|
|||
|
case COM_GAMEDESC:
|
|||
|
size=sizeof(COM_GamePlayerType);
|
|||
|
break;
|
|||
|
case COM_GAMEEND:
|
|||
|
size=sizeof(COM_GameEndType);
|
|||
|
break;
|
|||
|
case COM_GAMEPLAY:
|
|||
|
size=DUMMYPACKETSIZE;
|
|||
|
break;
|
|||
|
case COM_GAMEACK:
|
|||
|
size=sizeof(COM_GameAckType);
|
|||
|
break;
|
|||
|
case COM_GAMEMASTER:
|
|||
|
size=sizeof(COM_GameMasterType);
|
|||
|
break;
|
|||
|
case COM_ENDGAME:
|
|||
|
size=sizeof(COM_EndGameType);
|
|||
|
break;
|
|||
|
case COM_SYNCTIME:
|
|||
|
size=sizeof(COM_SyncType);
|
|||
|
break;
|
|||
|
#if (SYNCCHECK == 1)
|
|||
|
case COM_SYNCCHECK:
|
|||
|
size=sizeof(COM_CheckSyncType);
|
|||
|
break;
|
|||
|
#endif
|
|||
|
case COM_SOUNDANDDELTA:
|
|||
|
size=sizeof(MoveType)+sizeof(COM_SoundType);
|
|||
|
break;
|
|||
|
default:
|
|||
|
Error("Unhandled packet type in GetPacketSize type=%d",((MoveType *)pkt)->type);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return size;
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// GetTypeSize ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
int GetTypeSize (int type)
|
|||
|
{
|
|||
|
byte pkt[2];
|
|||
|
|
|||
|
pkt[0]=(byte)type;
|
|||
|
return ( GetPacketSize(&(pkt[0])) );
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// GetServerPacketSize ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
int GetServerPacketSize (void * pkt)
|
|||
|
{
|
|||
|
int i;
|
|||
|
byte * ptr;
|
|||
|
COM_ServerHeaderType * serverpkt;
|
|||
|
|
|||
|
serverpkt=(COM_ServerHeaderType *)pkt;
|
|||
|
if (serverpkt->type==COM_SERVER)
|
|||
|
{
|
|||
|
ptr=&serverpkt->data;
|
|||
|
|
|||
|
for (i=0;i<serverpkt->numpackets;i++)
|
|||
|
{
|
|||
|
ptr+=GetPacketSize(ptr);
|
|||
|
}
|
|||
|
return ((byte *)ptr-(byte *)pkt);
|
|||
|
}
|
|||
|
else
|
|||
|
return GetPacketSize(pkt);
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// SendPacket ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void SendPacket (void * pkt, int dest)
|
|||
|
{
|
|||
|
if ((networkgame==false) && (PlayerStatus[dest]!=player_ingame))
|
|||
|
return;
|
|||
|
if ((IsServer==true) && (dest==server) && (standalone==false)) // must be client on top of server
|
|||
|
ProcessPacket(pkt,dest);
|
|||
|
else if ((IsServer==false) && (dest!=server) && (standalone==false)) // We shouldn't be sending as client to anyone else
|
|||
|
ComError("SendPacket:Problems\n");
|
|||
|
else
|
|||
|
WritePacket(pkt,GetPacketSize(pkt),dest);
|
|||
|
#if (DEVELOPMENT == 1)
|
|||
|
// ComError( "SendPacket: time=%ld dest=%ld\n",((MoveType *)pkt)->time,dest);
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// ResetCurrentCommand ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void ResetCurrentCommand ( void )
|
|||
|
{
|
|||
|
ServerCommandStatus(oldpolltime)=cs_notarrived;
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// BroadcastServerPacket ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void BroadcastServerPacket (void * pkt, int size)
|
|||
|
{
|
|||
|
int i;
|
|||
|
|
|||
|
|
|||
|
for (i=0;i<numplayers;i++)
|
|||
|
{
|
|||
|
if (PlayerStatus[i]!=player_ingame)
|
|||
|
continue;
|
|||
|
// if ((standalone==false) && (i==consoleplayer))
|
|||
|
// ProcessPacket(pkt,i);
|
|||
|
// else
|
|||
|
WritePacket((byte *)pkt,size,i);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// ResendLocalPackets ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void ResendLocalPackets (int time, int dest, int numpackets)
|
|||
|
{
|
|||
|
int cmd;
|
|||
|
MoveType * pkt;
|
|||
|
|
|||
|
cmd = CommandAddress(time);
|
|||
|
|
|||
|
#if 0
|
|||
|
if (networkgame==false)
|
|||
|
{
|
|||
|
int nump;
|
|||
|
nump=controlupdatetime-time;
|
|||
|
if (nump>numpackets)
|
|||
|
numpackets=nump;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
if (controlupdatetime<=time)
|
|||
|
return;
|
|||
|
|
|||
|
pkt = (MoveType *)LocalCommand(cmd);
|
|||
|
|
|||
|
if (pkt->time!=time)
|
|||
|
{
|
|||
|
Error( "CLIENT: Could not find packet to resend\ntime=%d packettime=%d controlupdatetime=%d\n",
|
|||
|
time, pkt->time, controlupdatetime);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
byte * tempbuf;
|
|||
|
byte * tempptr;
|
|||
|
byte * tempstart;
|
|||
|
COM_FixupType * fixup;
|
|||
|
int i;
|
|||
|
int starti;
|
|||
|
int size;
|
|||
|
boolean done;
|
|||
|
|
|||
|
// allocate some space
|
|||
|
|
|||
|
tempbuf=SafeMalloc(MAXCOMBUFFERSIZE);
|
|||
|
|
|||
|
fixup=(COM_FixupType *)tempbuf;
|
|||
|
|
|||
|
fixup->type=COM_FIXUP;
|
|||
|
tempstart=&(fixup->data);
|
|||
|
|
|||
|
done=false;
|
|||
|
i=0;
|
|||
|
while (done==false)
|
|||
|
{
|
|||
|
tempptr=tempstart;
|
|||
|
starti=i;
|
|||
|
fixup->time=( (MoveType *)LocalCommand(cmd) )->time;
|
|||
|
for (;i<numpackets;i++)
|
|||
|
{
|
|||
|
pkt = (MoveType *)LocalCommand(cmd);
|
|||
|
size=GetPacketSize(pkt);
|
|||
|
|
|||
|
if (((tempptr+size)-tempbuf)>MAXCOMBUFFERSIZE)
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
memcpy(tempptr,pkt,size);
|
|||
|
tempptr+=size;
|
|||
|
cmd = (cmd + controldivisor) & (MAXCMDS-1);
|
|||
|
}
|
|||
|
fixup->numpackets=i-starti;
|
|||
|
WritePacket(tempbuf,tempptr-tempbuf,dest);
|
|||
|
if (i==numpackets)
|
|||
|
done=true;
|
|||
|
}
|
|||
|
|
|||
|
SafeFree(tempbuf);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// ResendServerPackets ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void ResendServerPackets (int time, int dest, int numpackets)
|
|||
|
{
|
|||
|
int cmd;
|
|||
|
COM_ServerHeaderType * serverpkt;
|
|||
|
|
|||
|
|
|||
|
cmd = CommandAddress(time);
|
|||
|
|
|||
|
if (serverupdatetime<=time)
|
|||
|
return;
|
|||
|
|
|||
|
serverpkt = (COM_ServerHeaderType *)ServerCommand(cmd);
|
|||
|
|
|||
|
if (serverpkt->time!=time)
|
|||
|
{
|
|||
|
Error( "SERVER: Could not find packet to resend\ntime=%d packettime=%d serverupdatetime=%d\n",
|
|||
|
time, serverpkt->time,serverupdatetime);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
byte * tempbuf;
|
|||
|
byte * tempptr;
|
|||
|
byte * tempstart;
|
|||
|
COM_FixupType * fixup;
|
|||
|
int i;
|
|||
|
int starti;
|
|||
|
int size;
|
|||
|
boolean done;
|
|||
|
|
|||
|
// allocate some space
|
|||
|
|
|||
|
tempbuf=SafeMalloc(MAXCOMBUFFERSIZE);
|
|||
|
|
|||
|
fixup=(COM_FixupType *)tempbuf;
|
|||
|
|
|||
|
fixup->type=COM_FIXUP;
|
|||
|
tempstart=&(fixup->data);
|
|||
|
|
|||
|
done=false;
|
|||
|
i=0;
|
|||
|
while (done==false)
|
|||
|
{
|
|||
|
tempptr=tempstart;
|
|||
|
starti=i;
|
|||
|
fixup->time=( (MoveType *)ServerCommand(cmd) )->time;
|
|||
|
for (;i<numpackets;i++)
|
|||
|
{
|
|||
|
serverpkt = (COM_ServerHeaderType *)ServerCommand(cmd);
|
|||
|
size=GetServerPacketSize(serverpkt);
|
|||
|
|
|||
|
if (((tempptr+size)-tempbuf)>MAXCOMBUFFERSIZE)
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
memcpy(tempptr,serverpkt,size);
|
|||
|
tempptr+=size;
|
|||
|
cmd = (cmd + controldivisor) & (MAXCMDS-1);
|
|||
|
}
|
|||
|
fixup->numpackets=i-starti;
|
|||
|
WritePacket(tempbuf,tempptr-tempbuf,dest);
|
|||
|
if (i==numpackets)
|
|||
|
done=true;
|
|||
|
}
|
|||
|
|
|||
|
SafeFree(tempbuf);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// ResendPacket (incoming packet, whoever requested it)
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void ResendPacket (void * pkt, int dest)
|
|||
|
{
|
|||
|
int time;
|
|||
|
COM_RequestType * request;
|
|||
|
|
|||
|
if ((networkgame==false) && (PlayerStatus[dest]!=player_ingame))
|
|||
|
return;
|
|||
|
|
|||
|
request=(COM_RequestType * )pkt;
|
|||
|
time=request->time;
|
|||
|
|
|||
|
ComError( "RESEND request received at %d\n packet time=%d dest=%d numpackets=%d\n",
|
|||
|
GetTicCount(), time, dest, request->numpackets);
|
|||
|
|
|||
|
if (IsServer==true)
|
|||
|
{
|
|||
|
if ((dest==server) && (standalone==false))
|
|||
|
Error("Trying to resend packets to client on top of server\n");
|
|||
|
ComError( "RESEND SERVER serverupdatetime=%d\n",serverupdatetime);
|
|||
|
if (IsServerCommandReady ( time ) == true)
|
|||
|
ResendServerPackets(time,dest,request->numpackets);
|
|||
|
else
|
|||
|
ComError( "RESEND SERVER time=%d is not ready\n",time);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ResendLocalPackets(time,dest,request->numpackets);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// FixupPacket ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void FixupPacket (void * pkt, int src)
|
|||
|
{
|
|||
|
COM_FixupType * fix;
|
|||
|
int i;
|
|||
|
int time;
|
|||
|
byte * ptr;
|
|||
|
|
|||
|
fix=(COM_FixupType *)pkt;
|
|||
|
|
|||
|
ComError( "Fixup received at %d, time=%d numpackets=%d\n", GetTicCount(), fix->time, fix->numpackets);
|
|||
|
#if 0
|
|||
|
if (networkgame==false)
|
|||
|
FixingPackets=false;
|
|||
|
#endif
|
|||
|
time=fix->time;
|
|||
|
ptr=&(fix->data);
|
|||
|
|
|||
|
for (i=0;i<fix->numpackets;i++,time+=controldivisor)
|
|||
|
{
|
|||
|
if (time == (LastCommandTime[src]+controldivisor))
|
|||
|
LastCommandTime[src]=time;
|
|||
|
|
|||
|
if (IsServer==true)
|
|||
|
{
|
|||
|
if (ClientCommandStatus(src, time)!=cs_fixing)
|
|||
|
{
|
|||
|
ComError("Server Received fixup with no bad packet time=%d from %d\n",time,src);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
AddSubPacket(ptr, src);
|
|||
|
}
|
|||
|
ptr+=GetPacketSize(ptr);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (ServerCommandStatus(time)!=cs_fixing)
|
|||
|
{
|
|||
|
ComError("Client Received fixup with no bad packet time=%d from %d\n",time,src);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (networkgame==true)
|
|||
|
{
|
|||
|
AddServerSubPacket( (COM_ServerHeaderType *)ptr );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
AddModemSubPacket(ptr);
|
|||
|
}
|
|||
|
}
|
|||
|
ptr+=GetServerPacketSize(ptr);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#if (SYNCCHECK == 1)
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// CheckForSyncCheck
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void CheckForSyncCheck ( void )
|
|||
|
{
|
|||
|
int i;
|
|||
|
|
|||
|
|
|||
|
if (modemgame==true)
|
|||
|
{
|
|||
|
if (oldpolltime==lastsynccheck)
|
|||
|
{
|
|||
|
for (i=0;i<numplayers;i++)
|
|||
|
{
|
|||
|
PlayerSync[i].x=PLAYER[i]->x;
|
|||
|
PlayerSync[i].y=PLAYER[i]->y;
|
|||
|
PlayerSync[i].z=PLAYER[i]->z;
|
|||
|
PlayerSync[i].angle=PLAYER[i]->angle;
|
|||
|
}
|
|||
|
PlayerSync[0].randomindex=GetRNGindex();
|
|||
|
PlayerSync[0].synctime=lastsynccheck;
|
|||
|
SendSyncCheckPacket();
|
|||
|
lastsynccheck+=CHECKSYNCTIME;
|
|||
|
}
|
|||
|
if (oldpolltime>lastsynccheck)
|
|||
|
{
|
|||
|
Error("Missed a player sync check time=%d\n",oldpolltime);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// ProcessSyncTimePacket
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void ProcessSyncTimePacket (void * pkt)
|
|||
|
{
|
|||
|
COM_SyncType * sync;
|
|||
|
|
|||
|
sync=(COM_SyncType *)pkt;
|
|||
|
ISR_SetTime(sync->synctime);
|
|||
|
}
|
|||
|
|
|||
|
#if (SYNCCHECK == 1)
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// ProcessSyncCheckPacket
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void ProcessSyncCheckPacket (void * pkt, int src)
|
|||
|
{
|
|||
|
COM_CheckSyncType * sync;
|
|||
|
|
|||
|
sync=(COM_CheckSyncType *)pkt;
|
|||
|
// SoftError("Sync packet time=%ld\n",sync->synctime);
|
|||
|
if (sync->synctime!=PlayerSync[0].synctime)
|
|||
|
{
|
|||
|
SoftError("Old sync packet received\n");
|
|||
|
return;
|
|||
|
}
|
|||
|
if (sync->randomindex!=PlayerSync[0].randomindex)
|
|||
|
{
|
|||
|
Error("Player %d is unsynced localindex=%d remoteindex=%d\n"
|
|||
|
"Unsynced Player x=%x y=%x a=%d z=%d name=%s\n",
|
|||
|
src, PlayerSync[0].randomindex, sync->randomindex,
|
|||
|
PlayerSync[src].x, PlayerSync[src].y, PlayerSync[src].angle,
|
|||
|
PlayerSync[src].z,PLAYERSTATE[src].codename);
|
|||
|
}
|
|||
|
if (sync->x!=PlayerSync[src].x)
|
|||
|
{
|
|||
|
Error("Player %d is unsynced local x=%d remote x=%d\n"
|
|||
|
"Unsynced Player x=%x y=%x a=%d z=%d name=%s\n",
|
|||
|
src,PlayerSync[src].x,sync->x,
|
|||
|
PlayerSync[src].x, PlayerSync[src].y, PlayerSync[src].angle,
|
|||
|
PlayerSync[src].z,PLAYERSTATE[src].codename);
|
|||
|
}
|
|||
|
if (sync->y!=PlayerSync[src].y)
|
|||
|
{
|
|||
|
Error("Player %d is unsynced local y=%d remote y=%d\n"
|
|||
|
"Unsynced Player x=%x y=%x a=%d z=%d name=%s\n",
|
|||
|
src,PlayerSync[src].y,sync->y,
|
|||
|
PlayerSync[src].x, PlayerSync[src].y, PlayerSync[src].angle,
|
|||
|
PlayerSync[src].z,PLAYERSTATE[src].codename);
|
|||
|
}
|
|||
|
if (sync->z!=PlayerSync[src].z)
|
|||
|
{
|
|||
|
Error("Player %d is unsynced local z=%d remote z=%d\n"
|
|||
|
"Unsynced Player x=%x y=%x a=%d z=%d name=%s\n",
|
|||
|
src,PlayerSync[src].z,sync->z,
|
|||
|
PlayerSync[src].x, PlayerSync[src].y, PlayerSync[src].angle,
|
|||
|
PlayerSync[src].z,PLAYERSTATE[src].codename);
|
|||
|
}
|
|||
|
if (sync->angle!=PlayerSync[src].angle)
|
|||
|
{
|
|||
|
Error("Player %d is unsynced local angle=%d remote angle=%d\n"
|
|||
|
"Unsynced Player x=%x y=%x a=%d z=%d name=%s\n",
|
|||
|
src,PlayerSync[src].angle,sync->angle,
|
|||
|
PlayerSync[src].x, PlayerSync[src].y, PlayerSync[src].angle,
|
|||
|
PlayerSync[src].z,PLAYERSTATE[src].codename);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// SendSyncCheckPacket
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void SendSyncCheckPacket ( void )
|
|||
|
{
|
|||
|
((COM_CheckSyncType *)NextLocalCommand())->type=COM_SYNCCHECK;
|
|||
|
((COM_CheckSyncType *)NextLocalCommand())->synctime=PlayerSync[0].synctime;
|
|||
|
((COM_CheckSyncType *)NextLocalCommand())->x=PlayerSync[consoleplayer].x;
|
|||
|
((COM_CheckSyncType *)NextLocalCommand())->y=PlayerSync[consoleplayer].y;
|
|||
|
((COM_CheckSyncType *)NextLocalCommand())->z=PlayerSync[consoleplayer].z;
|
|||
|
((COM_CheckSyncType *)NextLocalCommand())->angle=PlayerSync[consoleplayer].angle;
|
|||
|
((COM_CheckSyncType *)NextLocalCommand())->randomindex=PlayerSync[0].randomindex;
|
|||
|
|
|||
|
PrepareLocalPacket();
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
#if 0
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// CheckForSyncTime
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void CheckForSyncTime ( void )
|
|||
|
{
|
|||
|
if ((modemgame==true) && (networkgame==false) && (consoleplayer==0))
|
|||
|
{
|
|||
|
if (controlupdatetime>=syncservertime)
|
|||
|
{
|
|||
|
SendSyncTimePacket();
|
|||
|
syncservertime+=MODEMSYNCSERVERTIME;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
#if 0
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// SendSyncTimePacket
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void SendSyncTimePacket ( void )
|
|||
|
{
|
|||
|
int i;
|
|||
|
COM_SyncType sync;
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
sync.type=COM_SYNCTIME;
|
|||
|
|
|||
|
if (networkgame==true)
|
|||
|
{
|
|||
|
for (i=0;i<numplayers;i++)
|
|||
|
{
|
|||
|
if ((PlayerStatus[i]!=player_ingame) || ( (i==consoleplayer) && (standalone==false) ) )
|
|||
|
continue;
|
|||
|
sync.synctime=GetTicCount()+GetTransitTime(i);
|
|||
|
WritePacket ( &sync.type, GetPacketSize(&sync.type), i);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (PlayerStatus[server]==player_ingame)
|
|||
|
{
|
|||
|
sync.synctime=GetTicCount()+GetTransitTime(server);
|
|||
|
WritePacket ( &sync.type, GetPacketSize(&sync.type), server);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// ProcessSoundAndDeltaPacket
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void ProcessSoundAndDeltaPacket (void * pkt, int src)
|
|||
|
{
|
|||
|
MoveType * packet;
|
|||
|
COM_SoundType * sndpkt;
|
|||
|
byte oldtype;
|
|||
|
|
|||
|
packet = (MoveType *)pkt;
|
|||
|
|
|||
|
// Trick packet into being a normal delta packet
|
|||
|
|
|||
|
oldtype=packet->type;
|
|||
|
packet->type=COM_DELTA;
|
|||
|
AddClientPacket (pkt,src);
|
|||
|
packet->type=oldtype;
|
|||
|
|
|||
|
// Don't process sound if it is from us
|
|||
|
if (src==consoleplayer)
|
|||
|
return;
|
|||
|
|
|||
|
sndpkt = (COM_SoundType *) (packet->Sounddata);
|
|||
|
|
|||
|
if (sndpkt->type==COM_SOUND_START_TRANSMISSION)
|
|||
|
{
|
|||
|
SD_StartIncomingSound ();
|
|||
|
}
|
|||
|
if (sndpkt->type==COM_SOUND_END_TRANSMISSION)
|
|||
|
{
|
|||
|
SD_StopIncomingSound();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
SD_UpdateIncomingSound (&(sndpkt->data[0]), COM_SOUND_BUFFERSIZE);
|
|||
|
}
|
|||
|
}
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// SyncToServer
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
#define NETWORKTIMEAHEADOFSERVER (1)
|
|||
|
#define MODEMTIMEAHEADOFSERVER (2)
|
|||
|
void SyncToServer( void )
|
|||
|
{
|
|||
|
int diff;
|
|||
|
|
|||
|
if ((networkgame==false) && (consoleplayer==0))
|
|||
|
return;
|
|||
|
if (IsServer==true)
|
|||
|
return;
|
|||
|
// if (networkgame==true)
|
|||
|
// {
|
|||
|
// diff = (GetTicCount()-controldivisor-LastCommandTime[0])/controldivisor;
|
|||
|
// SoftError("diff=%ld\n",diff);
|
|||
|
// if (abs(diff)>1)
|
|||
|
// ISR_SetTime(GetTicCount()-diff);
|
|||
|
#if 0
|
|||
|
diff = controlupdatetime-LastCommandTime[0];
|
|||
|
if (diff>3)
|
|||
|
{
|
|||
|
ISR_SetTime(GetTicCount()-1);
|
|||
|
}
|
|||
|
else if (diff<-3)
|
|||
|
{
|
|||
|
ISR_SetTime(GetTicCount()+1);
|
|||
|
}
|
|||
|
#endif
|
|||
|
// }
|
|||
|
// else
|
|||
|
// {
|
|||
|
diff = (GetTicCount()-controldivisor-LastCommandTime[server])/controldivisor;
|
|||
|
if (abs(diff)>0)
|
|||
|
ISR_SetTime(GetTicCount()-diff);
|
|||
|
// }
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// ProcessPacket
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void ProcessPacket (void * pkt, int src)
|
|||
|
{
|
|||
|
switch (((MoveType *)pkt)->type)
|
|||
|
{
|
|||
|
case COM_DELTA:
|
|||
|
case COM_DELTANULL:
|
|||
|
case COM_TEXT:
|
|||
|
case COM_PAUSE:
|
|||
|
case COM_QUIT:
|
|||
|
case COM_EXIT:
|
|||
|
case COM_REMRID:
|
|||
|
case COM_RESPAWN:
|
|||
|
case COM_UNPAUSE:
|
|||
|
case COM_ENDGAME:
|
|||
|
#if (SYNCCHECK == 1)
|
|||
|
case COM_SYNCCHECK:
|
|||
|
#endif
|
|||
|
// if (FixingPackets==false)
|
|||
|
AddPacket(pkt,src);
|
|||
|
break;
|
|||
|
case COM_SOUNDANDDELTA:
|
|||
|
if (remoteridicule == false )
|
|||
|
{
|
|||
|
((MoveType *)pkt)->type = COM_DELTA;
|
|||
|
}
|
|||
|
AddPacket(pkt,src);
|
|||
|
break;
|
|||
|
case COM_SERVER:
|
|||
|
AddServerPacket(pkt,src);
|
|||
|
break;
|
|||
|
|
|||
|
case COM_REQUEST:
|
|||
|
ResendPacket(pkt, src);
|
|||
|
break;
|
|||
|
|
|||
|
case COM_FIXUP:
|
|||
|
FixupPacket(pkt, src);
|
|||
|
break;
|
|||
|
|
|||
|
case COM_SYNCTIME:
|
|||
|
ProcessSyncTimePacket(pkt);
|
|||
|
break;
|
|||
|
|
|||
|
case COM_GAMEEND:
|
|||
|
case COM_GAMEDESC:
|
|||
|
case COM_GAMEACK:
|
|||
|
case COM_GAMEMASTER:
|
|||
|
if (standalone==true)
|
|||
|
restartgame=true;
|
|||
|
break;
|
|||
|
|
|||
|
case COM_START:
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
Error("ProcessPacket: Unknown packet type=%d\n",((MoveType *)pkt)->type);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// AddServerSubPacket
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void AddServerSubPacket(COM_ServerHeaderType * serverpkt)
|
|||
|
{
|
|||
|
byte * pkt;
|
|||
|
int i;
|
|||
|
|
|||
|
ServerCommandStatus(serverpkt->time)=cs_ready;
|
|||
|
|
|||
|
pkt=&serverpkt->data;
|
|||
|
for (i=0;i<serverpkt->numpackets;i++)
|
|||
|
{
|
|||
|
AddClientPacket(pkt,i);
|
|||
|
pkt+=GetPacketSize(pkt);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// AddModemSubPacket
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void AddModemSubPacket(void * incoming)
|
|||
|
{
|
|||
|
MoveType * pkt;
|
|||
|
|
|||
|
pkt=(MoveType *)incoming;
|
|||
|
ServerCommandStatus(pkt->time)=cs_ready;
|
|||
|
|
|||
|
AddClientPacket(incoming,server);
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// AddServerPacket
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void AddServerPacket(void * pkt, int src)
|
|||
|
{
|
|||
|
COM_ServerHeaderType * serverpkt;
|
|||
|
|
|||
|
// The server uses the client's lgts for communicating
|
|||
|
|
|||
|
// Last good time can be set even for the client/server combo
|
|||
|
|
|||
|
if (standalone==true)
|
|||
|
{
|
|||
|
Error("standalone should not be here\n");
|
|||
|
}
|
|||
|
|
|||
|
if (src!=server)
|
|||
|
{
|
|||
|
Error("Received server packet from non-server src=%d\n",src);
|
|||
|
}
|
|||
|
|
|||
|
serverpkt=(COM_ServerHeaderType *)pkt;
|
|||
|
|
|||
|
// if (networkgame==false)
|
|||
|
// SyncToServer(serverpkt->time);
|
|||
|
|
|||
|
LastCommandTime[src]+=controldivisor;
|
|||
|
|
|||
|
if (serverpkt->time != LastCommandTime[src])
|
|||
|
{
|
|||
|
int numpackets;
|
|||
|
|
|||
|
numpackets=serverpkt->time-LastCommandTime[src];
|
|||
|
if (ServerCommandStatus(LastCommandTime[src])!=cs_fixing)
|
|||
|
{
|
|||
|
RequestPacket ( LastCommandTime[src] , src , numpackets );
|
|||
|
|
|||
|
ComError("AddServerPacket: Request packet time=%d lct=%d numpackets=%d\n",
|
|||
|
serverpkt->time, LastCommandTime[src], numpackets
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
LastCommandTime[src]+=numpackets;
|
|||
|
}
|
|||
|
|
|||
|
AddServerSubPacket( serverpkt );
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// AddClientPacket
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void AddClientPacket (void * pkt, int src)
|
|||
|
{
|
|||
|
int size;
|
|||
|
MoveType * packet;
|
|||
|
|
|||
|
packet=(MoveType *)pkt;
|
|||
|
|
|||
|
switch (packet->type)
|
|||
|
{
|
|||
|
case COM_DELTA:
|
|||
|
case COM_DELTANULL:
|
|||
|
case COM_TEXT:
|
|||
|
case COM_REMRID:
|
|||
|
case COM_PAUSE:
|
|||
|
case COM_QUIT:
|
|||
|
case COM_EXIT:
|
|||
|
case COM_RESPAWN:
|
|||
|
case COM_UNPAUSE:
|
|||
|
#if (SYNCCHECK == 1)
|
|||
|
case COM_SYNCCHECK:
|
|||
|
#endif
|
|||
|
case COM_ENDGAME:
|
|||
|
size=GetPacketSize(packet);
|
|||
|
memcpy(PlayerCommand(src,CommandAddress(packet->time)),packet,size);
|
|||
|
break;
|
|||
|
case COM_SOUNDANDDELTA:
|
|||
|
ProcessSoundAndDeltaPacket(packet, src);
|
|||
|
break;
|
|||
|
default:
|
|||
|
Error("AddClientPacket: Unknown packet type = %d\n",packet->type);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// AddSubPacket
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void AddSubPacket (void * pkt, int src)
|
|||
|
{
|
|||
|
MoveType * packet;
|
|||
|
|
|||
|
if (networkgame==false)
|
|||
|
Error("Modem game should not be here in AddSubPacket\n");
|
|||
|
|
|||
|
packet = (MoveType *) pkt;
|
|||
|
|
|||
|
ClientCommandStatus(src, packet->time)=cs_ready;
|
|||
|
|
|||
|
memcpy (
|
|||
|
ClientTimeCommand(src,packet->time),
|
|||
|
pkt,
|
|||
|
GetPacketSize(packet)
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// AddPacket
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void AddPacket (void * pkt, int src)
|
|||
|
{
|
|||
|
MoveType * packet;
|
|||
|
|
|||
|
// should only be called by server in network game
|
|||
|
// in modem game we fall through the first condition
|
|||
|
// all packets should be sequential
|
|||
|
|
|||
|
if ((IsServer==true) && (PlayerStatus[src]!=player_ingame))
|
|||
|
return;
|
|||
|
packet = (MoveType *) pkt;
|
|||
|
|
|||
|
// if ((networkgame==false) && (consoleplayer!=0))
|
|||
|
// SyncToServer();
|
|||
|
|
|||
|
if (!((src==server) && (standalone==false) && (IsServer==true)))
|
|||
|
{
|
|||
|
LastCommandTime[src]+=controldivisor;
|
|||
|
|
|||
|
if (packet->time != LastCommandTime[src])
|
|||
|
{
|
|||
|
int numpackets;
|
|||
|
|
|||
|
numpackets=packet->time-LastCommandTime[src];
|
|||
|
if ( ( (networkgame==false) &&
|
|||
|
(ServerCommandStatus(LastCommandTime[src])!=cs_fixing)
|
|||
|
)
|
|||
|
||
|
|||
|
( (networkgame==true) &&
|
|||
|
(ClientCommandStatus(src,LastCommandTime[src])!=cs_fixing)
|
|||
|
)
|
|||
|
)
|
|||
|
{
|
|||
|
RequestPacket ( LastCommandTime[src] , src , numpackets );
|
|||
|
|
|||
|
ComError("AddPacket: Request packet time=%d lct=%d numpackets=%d\n",
|
|||
|
packet->time, LastCommandTime[src], numpackets
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
LastCommandTime[src]+=numpackets;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (networkgame==true)
|
|||
|
{
|
|||
|
AddSubPacket ( packet, src );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
AddModemSubPacket(packet);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// RequestPacket ( int time, int dest )
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void RequestPacket (int time, int dest, int numpackets)
|
|||
|
{
|
|||
|
COM_RequestType request;
|
|||
|
int i;
|
|||
|
|
|||
|
|
|||
|
#if (DEVELOPMENT == 1)
|
|||
|
if (modemgame==false)
|
|||
|
Error("Called Request Packet outside of modem game\n");
|
|||
|
#endif
|
|||
|
|
|||
|
request.type=COM_REQUEST;
|
|||
|
request.time=time;
|
|||
|
request.numpackets=numpackets/controldivisor;
|
|||
|
|
|||
|
if (IsServer==true)
|
|||
|
{
|
|||
|
if ((dest==server) && (standalone==false))
|
|||
|
{
|
|||
|
Error("Requesting packet from client on top of server\n");
|
|||
|
}
|
|||
|
if (PlayerStatus[dest]!=player_ingame)
|
|||
|
return;
|
|||
|
for (i=0;i<numpackets;i+=controldivisor)
|
|||
|
{
|
|||
|
ClientCommandStatus( dest , (time+i) ) = cs_fixing;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if ((networkgame==false) && (PlayerStatus[dest]!=player_ingame))
|
|||
|
return;
|
|||
|
for (i=0;i<numpackets;i+=controldivisor)
|
|||
|
{
|
|||
|
ServerCommandStatus( (time+i) ) = cs_fixing;
|
|||
|
}
|
|||
|
}
|
|||
|
// if (networkgame==false)
|
|||
|
// FixingPackets=true;
|
|||
|
|
|||
|
// send out the packet
|
|||
|
|
|||
|
WritePacket (&request, GetPacketSize(&request), dest);
|
|||
|
|
|||
|
#if (DEVELOPMENT == 1)
|
|||
|
// ComError( "BADPKT, request sent at %ld lgt=%ld dest=%ld\n",GetTicCount(),time,dest);
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// IsServerCommandReady ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
boolean IsServerCommandReady ( int time )
|
|||
|
{
|
|||
|
|
|||
|
if (
|
|||
|
(
|
|||
|
(COM_ServerHeaderType *)
|
|||
|
ServerCommand(CommandAddress (time) ) )->time==time)
|
|||
|
return true;
|
|||
|
else
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// AreClientsReady ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
boolean AreClientsReady ( void )
|
|||
|
{
|
|||
|
int i;
|
|||
|
int timeindex;
|
|||
|
int status;
|
|||
|
|
|||
|
timeindex=CommandAddress(serverupdatetime);
|
|||
|
|
|||
|
for (i=0;i<numplayers;i++)
|
|||
|
{
|
|||
|
if (PlayerStatus[i]!=player_ingame)
|
|||
|
continue;
|
|||
|
status=ClientCommandStatus(i, serverupdatetime);
|
|||
|
if (status==cs_notarrived)
|
|||
|
return false;
|
|||
|
else if (status==cs_fixing)
|
|||
|
{
|
|||
|
// RequestPacket ( serverupdatetime , i , controldivisor );
|
|||
|
return false;
|
|||
|
}
|
|||
|
else if (((MoveType *)ClientCommand(i, timeindex))->time != serverupdatetime)
|
|||
|
return false;
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// IsPlayerCommandReady ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
boolean IsPlayerCommandReady (int num, int time)
|
|||
|
{
|
|||
|
MoveType * cmd;
|
|||
|
|
|||
|
cmd=(MoveType *)PlayerCommand(num,CommandAddress(time));
|
|||
|
|
|||
|
if (cmd->time==time)
|
|||
|
return true;
|
|||
|
else
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// ResetClientCommands ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
void ResetClientCommands ( int player )
|
|||
|
{
|
|||
|
int j;
|
|||
|
|
|||
|
for (j=0;j<MAXCMDS;j++)
|
|||
|
{
|
|||
|
memset(ClientCommand(player,j),COM_DELTA,GamePacketSize());
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// SendFullServerPacket ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
void SendFullServerPacket ( void )
|
|||
|
{
|
|||
|
int i;
|
|||
|
int size;
|
|||
|
byte * pkt;
|
|||
|
COM_ServerHeaderType * spkt;
|
|||
|
int timeindex;
|
|||
|
int playerstatus[MAXPLAYERS];
|
|||
|
|
|||
|
timeindex=CommandAddress(serverupdatetime);
|
|||
|
|
|||
|
spkt=(COM_ServerHeaderType *)ServerCommand(timeindex);
|
|||
|
|
|||
|
pkt=&spkt->data;
|
|||
|
spkt->time=serverupdatetime;
|
|||
|
spkt->type=COM_SERVER;
|
|||
|
spkt->numpackets=numplayers;
|
|||
|
|
|||
|
|
|||
|
memset(playerstatus,-1,sizeof(playerstatus));
|
|||
|
for (i=0;i<numplayers;i++)
|
|||
|
{
|
|||
|
size=GetPacketSize(ClientCommand(i,timeindex));
|
|||
|
if (((MoveType *)ClientCommand(i,timeindex))->type == COM_QUIT)
|
|||
|
{
|
|||
|
playerstatus[i]=player_quitgame;
|
|||
|
}
|
|||
|
if (((MoveType *)ClientCommand(i,timeindex))->type == COM_ENDGAME)
|
|||
|
{
|
|||
|
playerstatus[i]=player_leftgame;
|
|||
|
}
|
|||
|
memcpy(pkt,
|
|||
|
ClientCommand(i,timeindex),
|
|||
|
size
|
|||
|
);
|
|||
|
pkt+=size;
|
|||
|
ClientCommandNumberStatus(i,timeindex)=cs_notarrived;
|
|||
|
}
|
|||
|
BroadcastServerPacket((void *)spkt,(pkt-(byte *)spkt));
|
|||
|
serverupdatetime+=controldivisor;
|
|||
|
|
|||
|
for (i=0;i<numplayers;i++)
|
|||
|
{
|
|||
|
if (playerstatus[i]!=-1)
|
|||
|
{
|
|||
|
if ((standalone==false) && (consoleplayer==i))
|
|||
|
{
|
|||
|
UpdateServer=false;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ResetClientCommands(i);
|
|||
|
PlayerStatus[i]=playerstatus[i];
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// ProcessServer ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void ProcessServer ( void )
|
|||
|
{
|
|||
|
boolean done;
|
|||
|
boolean exit;
|
|||
|
int i;
|
|||
|
int time;
|
|||
|
int quittime;
|
|||
|
|
|||
|
if (InProcessServer==true)
|
|||
|
return;
|
|||
|
|
|||
|
InProcessServer=true;
|
|||
|
|
|||
|
if (GetTicCount()<serverupdatetime)
|
|||
|
goto exitProcessServer;
|
|||
|
|
|||
|
time=GetTicCount();
|
|||
|
quittime=GetTicCount()+SERVERTIMEOUT;
|
|||
|
exit=false;
|
|||
|
|
|||
|
while (time>=serverupdatetime)
|
|||
|
{
|
|||
|
int savetime;
|
|||
|
|
|||
|
savetime=GetTicCount()+NETWORKTIMEOUT;
|
|||
|
done = false;
|
|||
|
while (done == false)
|
|||
|
{
|
|||
|
if (standalone==true)
|
|||
|
AbortCheck("GameServer aborted\n");
|
|||
|
|
|||
|
done = AreClientsReady ();
|
|||
|
|
|||
|
if ( (standalone==false) && (serverupdatetime>=(controlupdatetime-controldivisor)) && (done==false) )
|
|||
|
break;
|
|||
|
|
|||
|
CheckForPacket ();
|
|||
|
|
|||
|
if (standalone==false)
|
|||
|
UpdateClientControls();
|
|||
|
|
|||
|
if (restartgame==true)
|
|||
|
break;
|
|||
|
if (GetTicCount()>savetime)
|
|||
|
{
|
|||
|
for (i=0;i<numplayers;i++)
|
|||
|
{
|
|||
|
int val;
|
|||
|
|
|||
|
val=ClientCommandStatus(i, serverupdatetime);
|
|||
|
if ((val!=cs_ready) && (PlayerStatus[i]==player_ingame))
|
|||
|
{
|
|||
|
SoftError("Server timeout\n");
|
|||
|
RequestPacket(serverupdatetime, i , controldivisor);
|
|||
|
}
|
|||
|
}
|
|||
|
savetime=GetTicCount()+NETWORKTIMEOUT;
|
|||
|
}
|
|||
|
// if (GetTicCount()>quittime)
|
|||
|
// {
|
|||
|
// Error("Server aborting after %ld seconds\n",SERVERTIMEOUT/VBLCOUNTER);
|
|||
|
// }
|
|||
|
if ((standalone==false) && (done==false))
|
|||
|
{
|
|||
|
exit=true;
|
|||
|
done=true;
|
|||
|
}
|
|||
|
}
|
|||
|
if (exit==true)
|
|||
|
break;
|
|||
|
if ( (serverupdatetime>=(controlupdatetime-controldivisor)) && (standalone==false))
|
|||
|
break;
|
|||
|
if (restartgame==true)
|
|||
|
break;
|
|||
|
SendFullServerPacket();
|
|||
|
#if 0
|
|||
|
if (serverupdatetime>=syncservertime)
|
|||
|
{
|
|||
|
SendSyncTimePacket();
|
|||
|
syncservertime+=NETSYNCSERVERTIME;
|
|||
|
}
|
|||
|
#endif
|
|||
|
}
|
|||
|
exitProcessServer:
|
|||
|
InProcessServer=false;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// SetupCheckForPacket()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
int SetupCheckForPacket ( void )
|
|||
|
{
|
|||
|
int retval=scfp_nodata;
|
|||
|
|
|||
|
if ((ReadPacket()==true) && (badpacket==0))
|
|||
|
{
|
|||
|
MoveType * pkt;
|
|||
|
|
|||
|
retval=scfp_data;
|
|||
|
pkt=(MoveType *)&ROTTpacket[0];
|
|||
|
if ((IsServer==true) && (standalone==true))
|
|||
|
{
|
|||
|
switch (pkt->type)
|
|||
|
{
|
|||
|
case COM_GAMEEND:
|
|||
|
break;
|
|||
|
case COM_GAMEDESC:
|
|||
|
if (standalone==true)
|
|||
|
printf("Received GameDescription from player#%ld\n",(long int)rottcom->remotenode);
|
|||
|
WritePacket(&ROTTpacket[0],GetPacketSize(pkt),0); // Send to player 0
|
|||
|
break;
|
|||
|
case COM_GAMEACK:
|
|||
|
if (standalone==true)
|
|||
|
printf("Received GameAcknowledgement from player#%ld\n",(long int)rottcom->remotenode);
|
|||
|
WritePacket(&ROTTpacket[0],GetPacketSize(pkt),0); // Send to player 0
|
|||
|
break;
|
|||
|
case COM_GAMEMASTER:
|
|||
|
if (standalone==true)
|
|||
|
printf("Received GameMasterPacket from player#%ld\n",(long int)rottcom->remotenode);
|
|||
|
BroadcastServerPacket(&ROTTpacket[0],GetPacketSize(pkt)); // Send to all
|
|||
|
break;
|
|||
|
case COM_GAMEPLAY:
|
|||
|
if (standalone==true)
|
|||
|
printf("Received StartGamePacket from player#%ld\n",(long int)rottcom->remotenode);
|
|||
|
BroadcastServerPacket(&ROTTpacket[0],GetPacketSize(pkt)); // Send to all
|
|||
|
retval=scfp_done;
|
|||
|
break;
|
|||
|
default:
|
|||
|
ComError("Server received unknown packet in Game preamble\n");
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
switch (pkt->type)
|
|||
|
{
|
|||
|
case COM_GAMEPLAY:
|
|||
|
retval=scfp_done;
|
|||
|
break;
|
|||
|
case COM_GAMEMASTER:
|
|||
|
SetGameDescription(pkt);
|
|||
|
retval=scfp_gameready;
|
|||
|
break;
|
|||
|
case COM_GAMEACK:
|
|||
|
PlayersReady[((COM_GameAckType *)pkt)->player]=true;
|
|||
|
break;
|
|||
|
case COM_GAMEDESC:
|
|||
|
GotPlayersDesc[((COM_GamePlayerType *)pkt)->player]=true;
|
|||
|
SetPlayerDescription(pkt);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return retval;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// ServerLoop ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
void ServerLoop( void )
|
|||
|
{
|
|||
|
boolean done;
|
|||
|
|
|||
|
while (1)
|
|||
|
{
|
|||
|
ShutdownClientControls();
|
|||
|
restartgame=false;
|
|||
|
|
|||
|
done=false;
|
|||
|
while (done==false)
|
|||
|
{
|
|||
|
AbortCheck("SetupGameServer aborted\n");
|
|||
|
|
|||
|
if (SetupCheckForPacket()==scfp_done)
|
|||
|
done=true;
|
|||
|
}
|
|||
|
ComSetTime();
|
|||
|
StartupClientControls();
|
|||
|
while(1)
|
|||
|
{
|
|||
|
ProcessServer();
|
|||
|
#if (DEVELOPMENT == 1)
|
|||
|
Z_CheckHeap();
|
|||
|
#endif
|
|||
|
CalcTics();
|
|||
|
if (restartgame==true)
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// ProcessPlayerCommand()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
void ProcessPlayerCommand( int player )
|
|||
|
{
|
|||
|
MoveType * cmd;
|
|||
|
|
|||
|
cmd=(MoveType *)PlayerCommand(player,CommandAddress(oldpolltime));
|
|||
|
|
|||
|
if (cmd->type==COM_DELTA)
|
|||
|
{
|
|||
|
UpdatePlayerObj(player);
|
|||
|
}
|
|||
|
else if (cmd->type==COM_RESPAWN)
|
|||
|
{
|
|||
|
if (player==consoleplayer) // reset spawn state
|
|||
|
respawnactive=false;
|
|||
|
RespawnPlayerobj(PLAYER[player]);
|
|||
|
}
|
|||
|
else if (cmd->type==COM_ENDGAME)
|
|||
|
{
|
|||
|
playstate = ex_battledone;
|
|||
|
}
|
|||
|
else if (cmd->type==COM_QUIT)
|
|||
|
{
|
|||
|
if (player==consoleplayer)
|
|||
|
QuitGame();
|
|||
|
else
|
|||
|
{
|
|||
|
char str[50]="Player #";
|
|||
|
char str2[10];
|
|||
|
|
|||
|
strcat(str,itoa(player+1,str2,10));
|
|||
|
strcat(str,", ");
|
|||
|
strcat(str,PLAYERSTATE[player].codename);
|
|||
|
strcat(str," has left the game.");
|
|||
|
AddMessage(str,MSG_REMOTE);
|
|||
|
PlayerStatus[player]=player_quitgame;
|
|||
|
}
|
|||
|
}
|
|||
|
else if (cmd->type==COM_EXIT)
|
|||
|
{
|
|||
|
QuitGame();
|
|||
|
}
|
|||
|
else if (cmd->type==COM_REMRID)
|
|||
|
{
|
|||
|
ProcessRemoteRidicule (cmd);
|
|||
|
}
|
|||
|
else if (cmd->type==COM_TEXT)
|
|||
|
{
|
|||
|
int who;
|
|||
|
|
|||
|
who = ( ( COM_TextType * )cmd )->towho;
|
|||
|
if ( ( who == consoleplayer ) ||
|
|||
|
( who == MSG_DIRECTED_TO_ALL ) ||
|
|||
|
( ( who == MSG_DIRECTED_TO_TEAM ) &&
|
|||
|
( BATTLE_Team[ player ] == BATTLE_Team[ consoleplayer ] ) ) )
|
|||
|
{
|
|||
|
char string[ 50 ];
|
|||
|
|
|||
|
strcpy( string, "\\N9" );
|
|||
|
strcat( string, PLAYERSTATE[player].codename );
|
|||
|
strcat( string, ":\\NF" );
|
|||
|
strcat( string, ((COM_TextType *)cmd)->string );
|
|||
|
SD_PlayPitchedSound ( SD_ENDBONUS1SND, 255, 1200 );
|
|||
|
|
|||
|
AddMessage( string, MSG_REMOTE );
|
|||
|
}
|
|||
|
}
|
|||
|
#if (SYNCCHECK == 1)
|
|||
|
else if (cmd->type==COM_SYNCCHECK)
|
|||
|
{
|
|||
|
ProcessSyncCheckPacket(cmd, player);
|
|||
|
}
|
|||
|
#endif
|
|||
|
else if (cmd->type==COM_PAUSE)
|
|||
|
{
|
|||
|
MUSIC_Pause();
|
|||
|
GamePaused=true;
|
|||
|
pausedstartedticcount = oldpolltime;
|
|||
|
}
|
|||
|
else if (cmd->type==COM_UNPAUSE)
|
|||
|
{
|
|||
|
GamePaused=false;
|
|||
|
MUSIC_Continue ();
|
|||
|
if (RefreshPause == false) // screen is blanked
|
|||
|
{
|
|||
|
ShutdownScreenSaver();
|
|||
|
SetupScreen (true);
|
|||
|
RefreshPause = true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// CheckUnPause ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
void CheckUnPause ( void )
|
|||
|
{
|
|||
|
if (oldpolltime==nextupdatetime)
|
|||
|
{
|
|||
|
nextupdatetime=oldpolltime+controldivisor;
|
|||
|
while (1)
|
|||
|
{
|
|||
|
if (ServerCommandStatus(oldpolltime)==cs_ready)
|
|||
|
{
|
|||
|
int j;
|
|||
|
|
|||
|
for (j=0;j<numplayers;j++)
|
|||
|
{
|
|||
|
if (PlayerStatus[j]==player_ingame)
|
|||
|
ProcessPlayerCommand( j );
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
UpdateClientControls();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// ControlPlayerObj ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
void ControlPlayerObj (objtype * ob)
|
|||
|
{
|
|||
|
playertype * pstate;
|
|||
|
int num;
|
|||
|
int savetime;
|
|||
|
// boolean asked;
|
|||
|
|
|||
|
// if (GamePaused==true)
|
|||
|
// return;
|
|||
|
|
|||
|
M_LINKSTATE(ob,pstate);
|
|||
|
|
|||
|
// get player number
|
|||
|
|
|||
|
num=ob->dirchoosetime;
|
|||
|
|
|||
|
memcpy (pstate->buttonheld, pstate->buttonstate, sizeof(pstate->buttonstate));
|
|||
|
|
|||
|
if (oldpolltime==nextupdatetime)
|
|||
|
{
|
|||
|
if (num==numplayers-1)
|
|||
|
nextupdatetime=oldpolltime+controldivisor;
|
|||
|
if (networkgame==true)
|
|||
|
savetime=GetTicCount()+NETWORKTIMEOUT;
|
|||
|
else
|
|||
|
savetime=GetTicCount()+MODEMTIMEOUT;
|
|||
|
|
|||
|
if (PlayerStatus[num]!=player_ingame)
|
|||
|
return;
|
|||
|
|
|||
|
// asked=false;
|
|||
|
|
|||
|
// copy previous state of buttons
|
|||
|
|
|||
|
|
|||
|
while (1)
|
|||
|
{
|
|||
|
if (ServerCommandStatus(oldpolltime)==cs_ready)
|
|||
|
{
|
|||
|
ProcessPlayerCommand (num);
|
|||
|
if (demoplayback||demorecord) {
|
|||
|
SoftError("x=%4x y=%4x a=%4x time=%5d\n",player->x,player->y,player->angle,oldpolltime);
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
// else if ((ServerCommandStatus(oldpolltime)==cs_fixing) &&
|
|||
|
// (networkgame==false) &&
|
|||
|
// (asked==false)
|
|||
|
// )
|
|||
|
// {
|
|||
|
// asked=true;
|
|||
|
// RequestPacket(oldpolltime, server, controldivisor);
|
|||
|
// }
|
|||
|
else
|
|||
|
{
|
|||
|
UpdateClientControls();
|
|||
|
}
|
|||
|
|
|||
|
if (GetTicCount()>savetime)
|
|||
|
{
|
|||
|
SoftError("Client timeout oldpolltime=%d\n",oldpolltime);
|
|||
|
if (IsServer==false)
|
|||
|
RequestPacket(oldpolltime, server, controldivisor);
|
|||
|
if (networkgame==true)
|
|||
|
savetime=GetTicCount()+NETWORKTIMEOUT;
|
|||
|
else
|
|||
|
savetime=GetTicCount()+MODEMTIMEOUT;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!(ob->flags&FL_DYING))
|
|||
|
{
|
|||
|
if (ob->flags&FL_PUSHED)
|
|||
|
{
|
|||
|
ob->flags&=~FL_PUSHED;
|
|||
|
#if 0
|
|||
|
if (abs(ob->momentumx)>0)
|
|||
|
{
|
|||
|
if (abs(ob->momentumx+pstate->dmomx)>=abs(ob->momentumx))
|
|||
|
{
|
|||
|
ob->momentumx += pstate->dmomx;
|
|||
|
ob->momentumy += pstate->dmomy;
|
|||
|
}
|
|||
|
}
|
|||
|
else if (abs(ob->momentumy+pstate->dmomy)>=abs(ob->momentumy))
|
|||
|
{
|
|||
|
ob->momentumx += pstate->dmomx;
|
|||
|
ob->momentumy += pstate->dmomy;
|
|||
|
}
|
|||
|
#endif
|
|||
|
if (abs(ob->momentumx+pstate->dmomx)>=abs(ob->momentumx))
|
|||
|
{
|
|||
|
ob->momentumx += pstate->dmomx;
|
|||
|
}
|
|||
|
if (abs(ob->momentumy+pstate->dmomy)>=abs(ob->momentumy))
|
|||
|
{
|
|||
|
ob->momentumy += pstate->dmomy;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ob->momentumx += pstate->dmomx;
|
|||
|
ob->momentumy += pstate->dmomy;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// MaxSpeedForCharacter ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
int MaxSpeedForCharacter(playertype*pstate)
|
|||
|
{
|
|||
|
if (BATTLEMODE && (gamestate.BattleOptions.Speed == bo_fast_speed))
|
|||
|
{
|
|||
|
return( FASTSPEED );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (pstate->buttonstate[bt_run])
|
|||
|
return (characters[pstate->player].toprunspeed);
|
|||
|
else
|
|||
|
return (characters[pstate->player].topspeed);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// UpdatePlayerObj ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void UpdatePlayerObj ( int player )
|
|||
|
{
|
|||
|
int i, buttonbits;
|
|||
|
playertype * pstate;
|
|||
|
MoveType * MoveCmd;
|
|||
|
|
|||
|
MoveCmd=(MoveType *)PlayerCommand(player,CommandAddress(oldpolltime));
|
|||
|
|
|||
|
pstate=&PLAYERSTATE[player];
|
|||
|
|
|||
|
buttonbits = MoveCmd->buttons;
|
|||
|
for (i = 0; i < NUMTXBUTTONS; i++)
|
|||
|
{
|
|||
|
pstate->buttonstate[i] = buttonbits & 1;
|
|||
|
buttonbits >>= 1;
|
|||
|
}
|
|||
|
|
|||
|
pstate->dmomx = (int)(MoveCmd->momx)<<1;
|
|||
|
pstate->dmomy = (int)(MoveCmd->momy)<<1;
|
|||
|
pstate->angle = MoveCmd->dangle;
|
|||
|
pstate->angle <<= 11;
|
|||
|
pstate->topspeed=MaxSpeedForCharacter(pstate);
|
|||
|
|
|||
|
if (demoplayback||demorecord) {
|
|||
|
SoftError(" dmx=%4x dmy=%4x da=%4x time=%5d\n",pstate->dmomx,pstate->dmomy,pstate->angle>>11,oldpolltime);
|
|||
|
}
|
|||
|
#if 0
|
|||
|
#if (DEVELOPMENT == 1)
|
|||
|
if ((modemgame==true) || (demoplayback==true) || (demorecord==true))
|
|||
|
{
|
|||
|
ComError( "player#%2ld\n",player);
|
|||
|
ComError( "momx = %6ld\n", PLAYER[player]->momentumx);
|
|||
|
ComError( "momy = %6ld\n", PLAYER[player]->momentumy);
|
|||
|
ComError( " x = %6ld\n", PLAYER[player]->x);
|
|||
|
ComError( " y = %6ld\n", PLAYER[player]->y);
|
|||
|
ComError( " z = %6ld\n", PLAYER[player]->z);
|
|||
|
ComError( " a = %6ld\n", PLAYER[player]->angle);
|
|||
|
if (pstate->buttonstate[bt_attack])
|
|||
|
ComError( "FIRING\n");
|
|||
|
}
|
|||
|
#endif
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// SendPlayerDescription ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void SendPlayerDescription( void )
|
|||
|
{
|
|||
|
byte * temp;
|
|||
|
COM_GamePlayerType * desc;
|
|||
|
int length;
|
|||
|
|
|||
|
length=sizeof(COM_GamePlayerType);
|
|||
|
temp=SafeMalloc(length);
|
|||
|
|
|||
|
memset(temp,0,length);
|
|||
|
|
|||
|
desc=(COM_GamePlayerType *)temp;
|
|||
|
desc->type=(byte)COM_GAMEDESC;
|
|||
|
desc->player=consoleplayer;
|
|||
|
desc->violence=gamestate.violence;
|
|||
|
desc->Version = gamestate.Version;
|
|||
|
desc->Product = gamestate.Product;
|
|||
|
desc->playerdescription.character=locplayerstate->player;
|
|||
|
desc->playerdescription.uniformcolor=locplayerstate->uniformcolor;
|
|||
|
strcpy(&(desc->playerdescription.codename[0]),
|
|||
|
&locplayerstate->codename[0]);
|
|||
|
|
|||
|
WritePacket(temp,length,server);
|
|||
|
|
|||
|
SafeFree(temp);
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// SendGameDescription ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void SendGameDescription( void )
|
|||
|
{
|
|||
|
byte * temp;
|
|||
|
COM_GameMasterType * desc;
|
|||
|
int length;
|
|||
|
int i;
|
|||
|
|
|||
|
length=sizeof(COM_GameMasterType);
|
|||
|
temp=SafeMalloc(length);
|
|||
|
|
|||
|
memset(temp,0,length);
|
|||
|
|
|||
|
desc=(COM_GameMasterType *)temp;
|
|||
|
desc->type=(byte)COM_GAMEMASTER;
|
|||
|
desc->level=gamestate.mapon;
|
|||
|
desc->mapcrc=GetMapCRC (gamestate.mapon);
|
|||
|
desc->mode=gamestate.battlemode;
|
|||
|
desc->violence=gamestate.violence;
|
|||
|
desc->Version = gamestate.Version;
|
|||
|
desc->Product = gamestate.Product;
|
|||
|
desc->teamplay = gamestate.teamplay;
|
|||
|
memcpy( &desc->SpecialsTimes, &gamestate.SpecialsTimes, sizeof( specials ) );
|
|||
|
BATTLE_GetOptions( &( desc->options ) );
|
|||
|
GetMapFileName( &(desc->battlefilename[0]) );
|
|||
|
desc->randomseed=GetRNGindex ( );
|
|||
|
gamestate.randomseed=desc->randomseed;
|
|||
|
desc->ludicrousgibs=battlegibs;
|
|||
|
ludicrousgibs=battlegibs;
|
|||
|
// SetRNGindex ( gamestate.randomseed );
|
|||
|
for (i=0;i<numplayers;i++)
|
|||
|
{
|
|||
|
if (gamestate.Product == ROTT_SHAREWARE)
|
|||
|
PLAYERSTATE[i].player = 0;
|
|||
|
desc->players[i].character =PLAYERSTATE[i].player;
|
|||
|
desc->players[i].uniformcolor =PLAYERSTATE[i].uniformcolor;
|
|||
|
strcpy ( &(desc->players[i].codename[0]),&(PLAYERSTATE[i].codename[0]));
|
|||
|
}
|
|||
|
|
|||
|
if (!networkgame)
|
|||
|
AssignTeams();
|
|||
|
|
|||
|
if (IsServer==false)
|
|||
|
{
|
|||
|
WritePacket(temp,length,server);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
BroadcastServerPacket(temp,length); // Send to all
|
|||
|
}
|
|||
|
|
|||
|
SafeFree(temp);
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// SetGameDescription ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void SetGameDescription( void * pkt )
|
|||
|
{
|
|||
|
COM_GameMasterType * desc;
|
|||
|
word localcrc;
|
|||
|
int i;
|
|||
|
|
|||
|
desc=(COM_GameMasterType *)pkt;
|
|||
|
gamestate.mapon=desc->level;
|
|||
|
gamestate.battlemode=desc->mode;
|
|||
|
gamestate.violence=desc->violence;
|
|||
|
gamestate.Version = desc->Version;
|
|||
|
gamestate.Product = desc->Product;
|
|||
|
gamestate.teamplay = desc->teamplay;
|
|||
|
memcpy( &gamestate.SpecialsTimes, &desc->SpecialsTimes, sizeof( specials ) );
|
|||
|
BATTLE_SetOptions( &( desc->options ) );
|
|||
|
gamestate.randomseed=desc->randomseed;
|
|||
|
SetRNGindex ( gamestate.randomseed );
|
|||
|
SetBattleMapFileName( &(desc->battlefilename[0]) );
|
|||
|
localcrc=GetMapCRC (gamestate.mapon);
|
|||
|
ludicrousgibs=desc->ludicrousgibs;
|
|||
|
if (localcrc!=desc->mapcrc)
|
|||
|
Error("You have different maps on your system\n");
|
|||
|
for (i=0;i<numplayers;i++)
|
|||
|
{
|
|||
|
PLAYERSTATE[i].player=desc->players[i].character;
|
|||
|
PLAYERSTATE[i].uniformcolor=desc->players[i].uniformcolor;
|
|||
|
strcpy ( &(PLAYERSTATE[i].codename[0]),
|
|||
|
&(desc->players[i].codename[0])
|
|||
|
);
|
|||
|
}
|
|||
|
AssignTeams();
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// SetPlayerDescription ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void SetPlayerDescription( void * pkt )
|
|||
|
{
|
|||
|
COM_GamePlayerType * desc;
|
|||
|
|
|||
|
desc=(COM_GamePlayerType *)pkt;
|
|||
|
PLAYERSTATE[desc->player].player=desc->playerdescription.character;
|
|||
|
PLAYERSTATE[desc->player].uniformcolor=desc->playerdescription.uniformcolor;
|
|||
|
strcpy ( &(PLAYERSTATE[desc->player].codename[0]),
|
|||
|
&(desc->playerdescription.codename[0])
|
|||
|
);
|
|||
|
if ( gamestate.Version != desc->Version )
|
|||
|
{
|
|||
|
Error("Player %s is using a different version of ROTT\n",PLAYERSTATE[desc->player].codename);
|
|||
|
// gamestate.Version = desc->Version;
|
|||
|
}
|
|||
|
|
|||
|
if ( gamestate.violence > desc->violence )
|
|||
|
{
|
|||
|
gamestate.violence = desc->violence;
|
|||
|
}
|
|||
|
|
|||
|
if ( gamestate.Product > desc->Product )
|
|||
|
{
|
|||
|
gamestate.Product = desc->Product;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// SendGameAck ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void SendGameAck( void )
|
|||
|
{
|
|||
|
byte * temp;
|
|||
|
int length;
|
|||
|
COM_GameAckType * desc;
|
|||
|
|
|||
|
length=sizeof(COM_GameAckType);
|
|||
|
temp=SafeMalloc(length);
|
|||
|
desc=(COM_GameAckType *)temp;
|
|||
|
desc->type=COM_GAMEACK;
|
|||
|
desc->player=consoleplayer;
|
|||
|
|
|||
|
WritePacket(temp,length,server);
|
|||
|
|
|||
|
SafeFree(temp);
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// SendGameStart ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void SendGameStart( void )
|
|||
|
{
|
|||
|
byte * temp;
|
|||
|
int length;
|
|||
|
|
|||
|
length=DUMMYPACKETSIZE;
|
|||
|
temp=SafeMalloc(length);
|
|||
|
*(temp)=(byte)COM_GAMEPLAY;
|
|||
|
|
|||
|
if (IsServer==false)
|
|||
|
{
|
|||
|
WritePacket(temp,length,server);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
BroadcastServerPacket(temp,length); // Send to all
|
|||
|
}
|
|||
|
|
|||
|
SafeFree(temp);
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// SetupGamePlayer ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
void SetupGamePlayer ( void )
|
|||
|
{
|
|||
|
int savetime;
|
|||
|
boolean done;
|
|||
|
boolean gameready;
|
|||
|
|
|||
|
savetime=GetTicCount();
|
|||
|
|
|||
|
done=false;
|
|||
|
gameready=false;
|
|||
|
|
|||
|
while (done==false)
|
|||
|
{
|
|||
|
// Setup individual player
|
|||
|
AbortCheck("SetupGamePlayer aborted\n");
|
|||
|
|
|||
|
// send Player Description
|
|||
|
if (GetTicCount() >= savetime)
|
|||
|
{
|
|||
|
savetime=GetTicCount()+SETUPTIME;
|
|||
|
if (gameready==false)
|
|||
|
SendPlayerDescription();
|
|||
|
else
|
|||
|
SendGameAck();
|
|||
|
}
|
|||
|
switch (SetupCheckForPacket())
|
|||
|
{
|
|||
|
case scfp_done:
|
|||
|
done=true;
|
|||
|
break;
|
|||
|
case scfp_gameready:
|
|||
|
gameready=true;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
savetime=GetTicCount()+(VBLCOUNTER/2);
|
|||
|
|
|||
|
while (GetTicCount()<savetime)
|
|||
|
{
|
|||
|
SetupCheckForPacket ();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// AllPlayersReady ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
boolean AllPlayersReady ( void )
|
|||
|
{
|
|||
|
int i;
|
|||
|
|
|||
|
for (i=0;i<numplayers;i++)
|
|||
|
if ((PlayersReady[i]==false) && (PlayerStatus[i]==player_ingame))
|
|||
|
return false;
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// GotAllPlayerDescriptions ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
boolean GotAllPlayerDescriptions ( void )
|
|||
|
{
|
|||
|
int i;
|
|||
|
|
|||
|
for (i=0;i<numplayers;i++)
|
|||
|
if ((GotPlayersDesc[i]==false) && (PlayerStatus[i]==player_ingame))
|
|||
|
return false;
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// SetupGameMaster ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
void SetupGameMaster ( void )
|
|||
|
{
|
|||
|
int savetime;
|
|||
|
boolean done;
|
|||
|
|
|||
|
memset(GotPlayersDesc,false,sizeof(GotPlayersDesc));
|
|||
|
GotPlayersDesc[consoleplayer]=true;
|
|||
|
|
|||
|
memset(PlayersReady,false,sizeof(PlayersReady));
|
|||
|
PlayersReady[consoleplayer]=true;
|
|||
|
|
|||
|
savetime=GetTicCount();
|
|||
|
|
|||
|
done=false;
|
|||
|
|
|||
|
InitializeRNG ();
|
|||
|
|
|||
|
while (done==false)
|
|||
|
{
|
|||
|
// Setup individual player
|
|||
|
|
|||
|
AbortCheck("SetupGameMaster aborted\n");
|
|||
|
|
|||
|
// send Game Description
|
|||
|
if (GetTicCount() >= savetime)
|
|||
|
{
|
|||
|
savetime=GetTicCount()+SETUPTIME;
|
|||
|
if (GotAllPlayerDescriptions()==true)
|
|||
|
SendGameDescription();
|
|||
|
}
|
|||
|
if (AllPlayersReady ()==true)
|
|||
|
{
|
|||
|
SendGameStart();
|
|||
|
SendGameStart();
|
|||
|
done=true;
|
|||
|
}
|
|||
|
SetupCheckForPacket();
|
|||
|
}
|
|||
|
savetime=GetTicCount()+(VBLCOUNTER/2);
|
|||
|
|
|||
|
while (GetTicCount()<savetime)
|
|||
|
{
|
|||
|
SetupCheckForPacket ();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
=============================================================================
|
|||
|
|
|||
|
DEMO CODE
|
|||
|
|
|||
|
=============================================================================
|
|||
|
*/
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// GetDemoFilename ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void GetDemoFilename (int demonumber, char * filename)
|
|||
|
{
|
|||
|
strcpy(filename,DATADIR "DEMO0_0.DMO\0");
|
|||
|
|
|||
|
filename[4 + strlen(DATADIR)] = (char)('0' + (byte)demonumber);
|
|||
|
filename[6 + strlen(DATADIR)] = (char)('0' + (byte)gamestate.violence);
|
|||
|
FixFilePath(filename);
|
|||
|
}
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// DemoExists ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
boolean DemoExists (int demonumber)
|
|||
|
{
|
|||
|
char demo[20 + sizeof(DATADIR)];
|
|||
|
|
|||
|
GetDemoFilename (demonumber, &demo[0]);
|
|||
|
if (access (demo, F_OK) == 0)
|
|||
|
return true;
|
|||
|
else
|
|||
|
{
|
|||
|
/* Saves the users violence level, only do this once, otherwise
|
|||
|
we might override the saved level with one already modified by us */
|
|||
|
if (predemo_violence == -1)
|
|||
|
predemo_violence = gamestate.violence;
|
|||
|
/* The demos distributed with rott are all for a violence level of 3 */
|
|||
|
gamestate.violence = 3;
|
|||
|
GetDemoFilename (demonumber, &demo[0]);
|
|||
|
if (access (demo, F_OK) == 0)
|
|||
|
return true;
|
|||
|
else
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// SaveDemo ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void SaveDemo (int demonumber)
|
|||
|
{
|
|||
|
char demo[20 + sizeof(DATADIR)];
|
|||
|
|
|||
|
RecordDemoCmd ();
|
|||
|
GetDemoFilename (demonumber, &demo[0]);
|
|||
|
SaveFile (demo, demobuffer, (demoptr-demobuffer));
|
|||
|
FreeDemo();
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// LoadDemo ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void LoadDemo (int demonumber)
|
|||
|
{
|
|||
|
char demo[20 + sizeof(DATADIR)];
|
|||
|
int size;
|
|||
|
|
|||
|
GetDemoFilename (demonumber, demo);
|
|||
|
if (demobuffer!=NULL)
|
|||
|
FreeDemo();
|
|||
|
size = LoadFile (demo, (void **)&demobuffer);
|
|||
|
playstate = ex_demoplayback;
|
|||
|
demoptr = demobuffer;
|
|||
|
lastdemoptr = (demoptr+size);
|
|||
|
locplayerstate->player=0;
|
|||
|
InitializeWeapons(locplayerstate);
|
|||
|
ResetPlayerstate(locplayerstate);
|
|||
|
InitCharacter();
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// RecordDemo ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void RecordDemo ( void )
|
|||
|
{
|
|||
|
DemoHeaderType * DemoHeader;
|
|||
|
int level;
|
|||
|
|
|||
|
if (demobuffer!=NULL)
|
|||
|
FreeDemo();
|
|||
|
godmode=0;
|
|||
|
demobuffer = SafeMalloc (DEMOBUFFSIZE);
|
|||
|
demoptr = demobuffer;
|
|||
|
lastdemoptr = demobuffer+DEMOBUFFSIZE;
|
|||
|
|
|||
|
// Save off level number
|
|||
|
|
|||
|
DemoHeader=(DemoHeaderType *)demoptr;
|
|||
|
demoptr+=sizeof(gamestate);
|
|||
|
memcpy(&(DemoHeader->demostate),&gamestate,sizeof(gamestate));
|
|||
|
demorecord = true;
|
|||
|
locplayerstate->player=0;
|
|||
|
InitializeWeapons(locplayerstate);
|
|||
|
ResetPlayerstate(locplayerstate);
|
|||
|
level=gamestate.mapon;
|
|||
|
InitCharacter();
|
|||
|
gamestate.mapon=level;
|
|||
|
SoftError(">>>>>>>>>>>>Start demo record\n");
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// SetupDemo ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void SetupDemo ( void )
|
|||
|
{
|
|||
|
DemoHeaderType * DemoHeader;
|
|||
|
|
|||
|
demoplayback = true;
|
|||
|
godmode=0;
|
|||
|
|
|||
|
DemoHeader=(DemoHeaderType *)demoptr;
|
|||
|
demoptr+=sizeof(gamestate);
|
|||
|
// if (gamestate.violence!=DemoHeader->demostate.violence)
|
|||
|
// Error ("This demo has a different difficulty level than your current settings\n");
|
|||
|
memcpy(&gamestate,&(DemoHeader->demostate),sizeof(gamestate));
|
|||
|
SoftError(">>>>>>>>>>>>Start demo playback\n");
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// FreeDemo ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void FreeDemo ( void )
|
|||
|
{
|
|||
|
demoplayback = false;
|
|||
|
demorecord = false;
|
|||
|
SafeFree (demobuffer);
|
|||
|
demobuffer=NULL;
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// CheckForDemoDone ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void CheckForDemoDone ( void )
|
|||
|
{
|
|||
|
if ((demoplayback==true) && (demoptr >= lastdemoptr))
|
|||
|
{
|
|||
|
FreeDemo();
|
|||
|
playstate = ex_demodone;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// CheckForDemoOverflowed ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void CheckForDemoOverflowed ( void )
|
|||
|
{
|
|||
|
if (demoptr >= (lastdemoptr-sizeof(DemoType)))
|
|||
|
{
|
|||
|
playstate = ex_completed; // demo is done
|
|||
|
EndDemo();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// RecordDemoCmd ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void RecordDemoCmd (void)
|
|||
|
{
|
|||
|
DemoType * dtime;
|
|||
|
|
|||
|
SoftError("Demo command recorded at %d\n",controlupdatetime);
|
|||
|
dtime=(DemoType *)demoptr;
|
|||
|
dtime->time = controlupdatetime;
|
|||
|
dtime->momx = (controlbuf[0]>>1);
|
|||
|
dtime->momy = (controlbuf[1]>>1);
|
|||
|
dtime->dangle = controlbuf[2]>>11;
|
|||
|
dtime->buttons = buttonbits;
|
|||
|
|
|||
|
demoptr+=sizeof(DemoType);
|
|||
|
|
|||
|
CheckForDemoOverflowed();
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// AddDemoCmd ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void AddDemoCmd (void)
|
|||
|
{
|
|||
|
DemoType * dtime;
|
|||
|
|
|||
|
//
|
|||
|
// get info from demo buffer
|
|||
|
//
|
|||
|
|
|||
|
SoftError("Demo command played at %d\n",controlupdatetime);
|
|||
|
if (demoplayback==true)
|
|||
|
{
|
|||
|
dtime=(DemoType *)demoptr;
|
|||
|
controlbuf[0]=dtime->momx<<1;
|
|||
|
controlbuf[1]=dtime->momy<<1;
|
|||
|
controlbuf[2]=dtime->dangle<<11;
|
|||
|
buttonbits =dtime->buttons;
|
|||
|
demoptr+=sizeof(DemoType);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// GetNextDemoTime ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
int GetNextDemoTime (void)
|
|||
|
{
|
|||
|
DemoType * dtime;
|
|||
|
|
|||
|
CheckForDemoDone();
|
|||
|
dtime=(DemoType *)demoptr;
|
|||
|
if (demoplayback)
|
|||
|
return dtime->time;
|
|||
|
else
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
//****************************************************************************
|
|||
|
//
|
|||
|
// UpdateDemoPlayback ()
|
|||
|
//
|
|||
|
//****************************************************************************
|
|||
|
|
|||
|
void UpdateDemoPlayback (int time)
|
|||
|
{
|
|||
|
if (demoplayback)
|
|||
|
{
|
|||
|
if (GetNextDemoTime()==time)
|
|||
|
AddDemoCmd();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|