29 #include "../idlib/precompiled.h"
46 #ifndef ASYNC_WRITE_TAGS
47 #define ASYNC_WRITE_TAGS 0
133 for ( i = 0; i <
num; i++ ) {
167 if ( decl ==
NULL ) {
176 outMsg.
Init( msgBuf,
sizeof( msgBuf ) );
197 if ( clientNum == -1 ) {
268 if ( pass[ 0 ] ==
'\0' ) {
269 common->
Warning(
"si_usepass is set but g_password is empty" );
281 Printf(
"Rejecting client %s from IP %s: invalid password\n", guid, IP );
293 common->
DPrintf(
"ServerClientConnect: remove old player entity\n" );
298 Printf(
"client %d connected.\n", clientNum );
314 outMsg.
Init( msgBuf,
sizeof( msgBuf ) );
326 outMsg.
Init( msgBuf,
sizeof( msgBuf ) );
344 outMsg.
Init( msgBuf,
sizeof( msgBuf ) );
389 outMsg.
Init( msgBuf,
sizeof( msgBuf ) );
399 outMsg.
Init( msgBuf,
sizeof( msgBuf ) );
415 outMsg.
Init( msgBuf,
sizeof( msgBuf ) );
419 for ( i = 0; i < numPortals; i++ ) {
437 event->event = eventId;
440 event->paramsSize = msg->
GetSize();
443 event->paramsSize = 0;
455 snapshot_t *snapshot, *lastSnapshot, *nextSnapshot;
458 for ( lastSnapshot =
NULL, snapshot =
clientSnapshots[clientNum]; snapshot; snapshot = nextSnapshot ) {
459 nextSnapshot = snapshot->
next;
460 if ( snapshot->
sequence < sequence ) {
465 if ( lastSnapshot ) {
466 lastSnapshot->
next = snapshot->
next;
472 lastSnapshot = snapshot;
483 snapshot_t *snapshot, *lastSnapshot, *nextSnapshot;
488 for ( lastSnapshot =
NULL, snapshot =
clientSnapshots[clientNum]; snapshot; snapshot = nextSnapshot ) {
489 nextSnapshot = snapshot->
next;
490 if ( snapshot->
sequence == sequence ) {
497 memcpy(
clientPVS[clientNum], snapshot->
pvs,
sizeof( snapshot->
pvs ) );
498 if ( lastSnapshot ) {
499 lastSnapshot->
next = nextSnapshot;
506 lastSnapshot = snapshot;
551 int i, msgSize, msgWriteBit;
579 memset( snapshot->
pvs, 0,
sizeof( snapshot->
pvs ) );
588 if ( portalSkyEnt.GetEntity() ) {
590 idEntity *skyEnt = portalSkyEnt.GetEntity();
664 if ( i < numSourceAreas ) {
699 memcpy( clientInPVS, snapshot->
pvs, ( numPVSClients + 7 ) >> 3 );
700 LittleRevBytes( clientInPVS,
sizeof(
int ),
sizeof( clientInPVS ) /
sizeof (
int ) );
725 length +=
idStr::snPrintf( buf+length,
sizeof(buf)-1-length,
"event %d for entity %d %d: ", event->
event, entityNum,
id );
726 va_start( argptr, fmt );
754 NetworkEventWarning( event,
"Entity does not exist any longer, or has not been spawned yet." );
768 assert( freedEvent == event );
782 outMsg.
Init( msgBuf,
sizeof( msgBuf ) );
835 bool vote = ( msg.
ReadByte() != 0 );
842 bool menuUp = ( msg.
ReadBits( 1 ) != 0 );
853 event->spawnId = msg.
ReadBits( 32 );
869 Warning(
"Unknown client->server reliable message: %d",
id );
946 for ( i = 2 *
Max( 0, 5 - ahead ); i < 2 * 5; i++ ) {
951 for ( i = 2 * 5; i < 2 * ( 5 +
Min( 10, -ahead ) ); i++ ) {
957 for ( i = LAGO_HEIGHT - 2 *
Min( 6, dupeUsercmds ); i <
LAGO_HEIGHT; i++ ) {
959 if ( dupeUsercmds <= 2 ) {
972 int i, typeNum, entityDefNumber, numBitsRead;
978 const char *classname;
989 common->
Printf(
"lagometer: UploadImage failed. turning off net_clientLagOMeter\n" );
1020 #if ASYNC_WRITE_TAGS
1049 Error(
"Unknown type number %d for entity %d with class number %d", typeNum, i, entityDefNumber );
1059 common->
Warning(
"ClientReadSnapshot: recycling client entity %d\n", i );
1067 args.
SetInt(
"spawn_entnum", i );
1068 args.
Set(
"name",
va(
"entity%d", i ) );
1070 if ( entityDefNumber >= 0 ) {
1075 args.
Set(
"classname", classname );
1077 Error(
"Failed to spawn entity with classname '%s' of type '%s'", classname, typeInfo->classname );
1082 Error(
"Failed to spawn entity of type '%s'", typeInfo->classname );
1099 #if ASYNC_WRITE_TAGS
1102 if ( entityDefNumber >= 0 && entityDefNumber < declManager->GetNumDecls(
DECL_ENTITYDEF ) ) {
1104 Error(
"write to and read from snapshot out of sync for classname '%s' of type '%s'", classname, typeInfo->classname );
1106 Error(
"write to and read from snapshot out of sync for type '%s'", typeInfo->classname );
1133 if ( portalSkyEnt.GetEntity() ) {
1135 idEntity *skyEnt = portalSkyEnt.GetEntity();
1150 sourceAreas[ i++ ] = 0;
1155 if ( memcmp( sourceAreas, serverPVS, idEntity::MAX_PVS_AREAS *
sizeof(
int ) ) ) {
1156 common->
Warning(
"client PVS areas != server PVS areas, sequence 0x%x", sequence );
1301 NetworkEventWarning( event,
"Entity does not exist any longer, or has not been spawned yet." );
1316 assert( freedEvent == event );
1348 if ( decl !=
NULL ) {
1414 event->spawnId = msg.
ReadBits( 32 );
1437 int newServerInfo = msg.
ReadBits(1);
1459 msg.
ReadString( voteString,
sizeof( voteString ) );
1473 for (
int i = 0;
i < numPortals;
i++ ) {
1481 assert( portal > 0 && portal <= gameRenderWorld->NumPortals() );
1494 Error(
"Unknown server->client reliable message: %d",
id );
1579 next = strchr( token,
';' );
1588 next = strchr( token,
';' );
1623 for ( i = 0; i < pakList.
Num(); i++ ) {
1627 if ( pakList[ i ][ 0 ] ==
'\0' ) {
1636 for ( j = 0; j < dlTable.
Num(); j++ ) {
1641 if ( j == dlTable.
Num() ) {
1642 common->
Printf(
"download for %s: pak not matched: %s\n", IP, pakList[ i ].c_str() );
1770 while ( cur && cur->
time > event->
time ) {
virtual void ServerWriteInitialReliableMessages(int clientNum)
static int snPrintf(char *dest, int size, const char *fmt,...) id_attribute((format(printf
virtual bool UploadImage(const char *imageName, const byte *data, int width, int height)=0
bool GetBounds(int currentTime, idBounds &bounds)
void ClientReadWarmupTime(const idBitMsg &msg)
int GetInt(const char *key, const char *defaultString="0") const
void ProcessVoiceChat(int clientNum, bool team, int index)
assert(prefInfo.fullscreenBtn)
int Cmp(const char *text) const
idCVarSystem * cvarSystem
static idTypeInfo * GetType(int num)
const int MAX_GLOBAL_SHADER_PARMS
idNetworkSystem * networkSystem
idVec3 GetCenter(void) const
void Tokenize(idStrList &out, const char *in)
void Printf(const char *fmt,...) const id_attribute((format(printf
virtual void ServerClientConnect(int clientNum, const char *guid)
struct idEntity::entityFlags_s fl
void FreeCurrentPVS(pvsHandle_t handle) const
type * GetEntity(void) const
const int MAX_EVENT_PARAM_SIZE
float GetFloat(void) const
void WriteGameStateToSnapshot(idBitMsgDelta &msg) const
int GetSpawnId(const idEntity *ent) const
void PlayGlobalSound(int to, snd_evt_t evt, const char *shader=NULL)
ID_INLINE T Max(T x, T y)
void void void void void Error(const char *fmt,...) const id_attribute((format(printf
virtual void SpawnPlayer(int clientNum)
void AssureSize(int newSize)
bool IsType(const idTypeInfo &c) const
void EnterGame(int clientNum)
int ClientRemapDecl(declType_t type, int index)
virtual int GetCVarInteger(const char *name) const =0
virtual void UnlinkClip(void)=0
void SaveWriteState(int &s, int &b) const
int spawnIds[MAX_GENTITIES]
idRenderSystem * renderSystem
void WantKilled(int clientNum)
void ReadByteAlign(void) const
static int GetTypeNumBits(void)
idFileSystem * fileSystem
void WriteBits(int value, int numBits)
void PrintMessageEvent(int to, msg_evt_t evt, int parm1=-1, int parm2=-1)
const char * GetName(void) const
void InitAsyncNetwork(void)
virtual bool ClientApplySnapshot(int clientNum, int sequence)
void FreeSnapshotsOlderThanSequence(int clientNum, int sequence)
virtual void FreeModelDef(void)
pvsHandle_t MergeCurrentPVS(pvsHandle_t pvs1, pvsHandle_t pvs2) const
GLuint GLuint GLsizei GLenum type
void void ServerProcessEntityNetworkEventQueue(void)
void UpdateLagometer(int aheadOfServer, int dupeUsercmds)
int ReadDeltaLong(int oldValue) const
int ReadString(char *buffer, int bufferSize) const
byte paramsBuf[MAX_EVENT_PARAM_SIZE]
void WriteString(const char *s, int maxLength=-1, bool make7Bit=true)
idLinkList< idEntity > snapshotEntities
void NetworkEventWarning(const entityNetEvent_t *event, const char *fmt,...) id_attribute((format(printf
void Set(const char *key, const char *value)
int ReadBits(int numBits) const
void ClientUpdateVote(vote_result_t result, int yesCount, int noCount)
static float Rint(float f)
virtual bool FilenameCompare(const char *s1, const char *s2) const =0
idCVar net_clientShowSnapshot("net_clientShowSnapshot","0", CVAR_GAME|CVAR_INTEGER,"", 0, 3, idCmdSystem::ArgCompletion_Integer< 0, 3 >)
void Free(entityNetEvent_t *event)
bool HasChanged(void) const
virtual void ClientPredictionThink(void)
int GetNumBitsRead(void) const
static const int MAX_PVS_AREAS
virtual int NumPortals(void) const =0
virtual void FreeLightDef(void)
virtual int GetNumDeclTypes(void) const =0
idBlockAlloc< entityState_t, 256 > entityStateAllocator
void Init(byte *data, int length)
int ReadData(void *data, int length) const
void InitLocalClient(int clientNum)
void WriteData(const void *data, int length)
struct entityNetEvent_s * prev
idEntity * SpawnEntityType(const idTypeInfo &classdef, const idDict *args=NULL, bool bIsClientReadSnapshot=false)
void void void Warning(const char *fmt,...) const id_attribute((format(printf
pvsHandle_t SetupCurrentPVS(const idVec3 &source, const pvsType_t type=PVS_NORMAL) const
virtual void BufferCommandText(cmdExecution_t exec, const char *text)=0
void ClientProcessEntityNetworkEventQueue(void)
virtual void SetPortalState(qhandle_t portal, int blockingBits)=0
int ServerRemapDecl(int clientNum, declType_t type, int index)
bool ReadDeltaDict(idDict &dict, const idDict *base) const
void Init(const idBitMsg *base, idBitMsg *newBase, idBitMsg *delta)
void ClientReadStartState(const idBitMsg &msg)
byte stateBuf[MAX_ENTITY_STATE_SIZE]
virtual void ServerClientBegin(int clientNum)
idPhysics * GetPhysics(void) const
void D_DrawDebugLines(void)
bool SpawnEntityDef(const idDict &args, idEntity **ent=NULL, bool setDefaults=true)
void AddChatLine(const char *fmt,...) id_attribute((format(printf
idCVar net_clientSelfSmoothing("net_clientSelfSmoothing","0.6", CVAR_GAME|CVAR_FLOAT,"smooth self position if network causes prediction error.", 0.0f, 0.95f)
virtual bool ServerApplySnapshot(int clientNum, int sequence)
void CastVote(int clientNum, bool vote)
bool IsPureReady(void) const
virtual renderEntity_t * GetRenderEntity(void)
idCVar net_clientLagOMeter("net_clientLagOMeter","1", CVAR_GAME|CVAR_BOOL|CVAR_NOCHEAT|CVAR_ARCHIVE,"draw prediction graph")
virtual void virtual void virtual void DWarning(const char *fmt,...) id_attribute((format(printf
bool GetBool(const char *key, const char *defaultString="0") const
virtual const char * GetCVarString(const char *name) const =0
void BeginReading(void) const
void LittleRevBytes(void *bp, int elsize, int elcount)
virtual void SetServerInfo(const idDict &serverInfo)
entityNetEvent_t * Dequeue(void)
void ServerSendChatMessage(int to, const char *name, const char *text)
virtual const idDecl * FindType(declType_t type, const char *name, bool makeDefault=true)=0
int GetInteger(void) const
static void Copynz(char *dest, const char *src, int destsize)
virtual allowReply_t ServerAllowClient(int numClients, const char *IP, const char *guid, const char *password, char reason[MAX_STRING_CHARS])
virtual void DebugClearLines(int time)=0
virtual void WriteToSnapshot(idBitMsgDelta &msg) const
void ServerSendDeclRemapToClient(int clientNum, declType_t type, int index)
void ShutdownAsyncNetwork(void)
virtual void ServerClientDisconnect(int clientNum)
virtual idAnimator * GetAnimator(void)
struct entityNetEvent_s * next
virtual void DrawText(const char *text, const idVec3 &origin, float scale, const idVec4 &color, const idMat3 &viewAxis, const int align=1, const int lifetime=0, bool depthTest=false)=0
bool PhysicsTeamInPVS(pvsHandle_t pvsHandle)
idLinkList< idEntity > spawnNode
idLinkList< idEntity > snapshotNode
virtual void ServerSendReliableMessage(int clientNum, const idBitMsg &msg)
virtual void ClientProcessReliableMessage(int clientNum, const idBitMsg &msg)
virtual int ClientGetTimeSinceLastPacket(void)
virtual const idSoundShader * SoundByIndex(int index, bool forceParse=true)=0
virtual void Printf(const char *fmt,...) id_attribute((format(printf
entityNetEvent_t * RemoveLast(void)
void ServerWriteInitialReliableMessages(int clientNum)
void SetSelfSmooth(bool b)
const int ENTITY_PVS_SIZE
idBounds Expand(const float d) const
static int BitsForInteger(int i)
void AppendPath(const char *text)
idLinkList< idEntity > spawnedEntities
void ClientStartVote(int clientNum, const char *voteString)
idCVar net_clientSmoothing("net_clientSmoothing","0.8", CVAR_GAME|CVAR_FLOAT,"smooth other clients angles and position.", 0.0f, 0.95f)
entityNetEvent_t * Alloc()
virtual const char * GetDeclNameFromType(declType_t type) const =0
idDeclManager * declManager
entityState_t * clientEntityStates[MAX_CLIENTS][MAX_GENTITIES]
void WriteToSnapshot(idBitMsgDelta &msg) const
void WritePlayerStateToSnapshot(idBitMsgDelta &msg) const
void ClientShowSnapshot(int clientNum) const
byte lagometer[LAGO_IMG_HEIGHT][LAGO_IMG_WIDTH][4]
idCVar net_clientShowSnapshotRadius("net_clientShowSnapshotRadius","128", CVAR_GAME|CVAR_FLOAT,"")
idEntity * entities[MAX_GENTITIES]
idDict userInfo[MAX_CLIENTS]
virtual bool ClientReceiveEvent(int event, int time, const idBitMsg &msg)
virtual void ClientReadSnapshot(int clientNum, int sequence, const int gameFrame, const int gameTime, const int dupeUsercmds, const int aheadOfServer, const idBitMsg &msg)
virtual int GetNumDecls(declType_t type)=0
void AddToEnd(idLinkList &node)
struct entityState_s * next
int Append(const type &obj)
void SetInt(const char *key, int val)
float globalShaderParms[MAX_GLOBAL_SHADER_PARMS]
static int static int vsnPrintf(char *dest, int size, const char *fmt, va_list argptr)
virtual gameReturn_t ClientPrediction(int clientNum, const usercmd_t *clientCmds, bool lastPredictFrame)
virtual const idDecl * DeclByIndex(declType_t type, int index, bool forceParse=true)=0
bool ApplySnapshot(int clientNum, int sequence)
void ProcessChatMessage(int clientNum, bool team, const char *name, const char *text, const char *sound)
void InitClientDeclRemap(int clientNum)
idList< int > clientDeclRemap[MAX_CLIENTS][DECL_MAX_TYPES]
void Append(const char a)
idMat3 ToMat3(void) const
bool IntersectsBounds(const idBounds &a) const
virtual const idBounds & GetAbsBounds(int id=-1) const =0
void RestoreWriteState(int s, int b)
usercmd_t usercmds[MAX_CLIENTS]
void ReadPlayerStateFromSnapshot(const idBitMsgDelta &msg)
virtual void ServerWriteSnapshot(int clientNum, int sequence, idBitMsg &msg, byte *clientInPVS, int numPVSClients)
GLsizei const GLcharARB const GLint * length
const char * GetName(void) const
static void ServiceEvents(void)
idEventQueue savedEventQueue
const char * c_str(void) const
void DropWeapon(int clientNum)
const int MAX_GAME_MESSAGE_SIZE
entityState_t * firstEntityState
virtual void DebugClearPolygons(int time)=0
int clientPVS[MAX_CLIENTS][ENTITY_PVS_SIZE]
void ReadGameStateFromSnapshot(const idBitMsgDelta &msg)
bool IsImplicit(void) const
void ReadFromSnapshot(const idBitMsgDelta &msg)
virtual bool GetCVarBool(const char *name) const =0
void SetBool(const bool value)
virtual int GetPortalState(qhandle_t portal)=0
char sessionCommand[MAX_STRING_CHARS]
entityNetEvent_t * Start(void)
const int * GetPVSAreas(void)
float ReadFloat(void) const
void WriteDeltaLong(int oldValue, int newValue)
idBlockAlloc< snapshot_t, 64 > snapshotAllocator
snapshot_t * clientSnapshots[MAX_CLIENTS]
const int NUM_RENDER_PORTAL_BITS
virtual bool DownloadRequest(const char *IP, const char *guid, const char *paks, char urls[MAX_STRING_CHARS])
virtual void DebugBounds(const idVec4 &color, const idBounds &bounds, const idVec3 &org=vec3_origin, const int lifetime=0)=0
idRenderWorld * gameRenderWorld
virtual void ServerProcessReliableMessage(int clientNum, const idBitMsg &msg)
char * va(const char *fmt,...)
void WriteBits(int value, int numBits)
void SaveEntityNetworkEvent(const idEntity *ent, int event, const idBitMsg *msg)
virtual void DPrintf(const char *fmt,...) id_attribute((format(printf
virtual bool ServerReceiveEvent(int event, int time, const idBitMsg &msg)
idCVar password("password","", CVAR_GAME|CVAR_NOCHEAT,"client password used when connecting")
idCVar net_clientMaxPrediction("net_clientMaxPrediction","1000", CVAR_SYSTEM|CVAR_INTEGER|CVAR_NOCHEAT,"maximum number of milliseconds a client can predict ahead of server.")
virtual void virtual void Warning(const char *fmt,...) id_attribute((format(printf
ID_INLINE T Min(T x, T y)
void ServerClientConnect(int clientNum)
int ReadBits(int numBits) const
virtual int BoundsInAreas(const idBounds &bounds, int *areas, int maxAreas) const =0
void ServerCallVote(int clientNum, const idBitMsg &msg)
virtual void ReadFromSnapshot(const idBitMsgDelta &msg)
void DisconnectClient(int clientNum)
idPhysics * GetPlayerPhysics(void)
int GetNumBitsWritten(void) const
void Enqueue(entityNetEvent_t *event, outOfOrderBehaviour_t oooBehaviour)
idBlockAlloc< entityNetEvent_t, 32 > eventAllocator