Exemple #1
0
/*
=============
SV_EmitPacketEntities

Writes a delta update of an entityState_t list to the message.
=============
*/
static void SV_EmitPacketEntities( clientSnapshot_t *from, clientSnapshot_t *to, msg_t *msg ) {
	sharedEntityState_t	*oldent, *newent;
	int		oldindex, newindex;
	int		oldnum, newnum;
	int		from_num_entities;

	// generate the delta update
	if ( !from ) {
		from_num_entities = 0;
	} else {
		from_num_entities = from->num_entities;
	}

	newent = NULL;
	oldent = NULL;
	newindex = 0;
	oldindex = 0;
	while ( newindex < to->num_entities || oldindex < from_num_entities ) {
		if ( newindex >= to->num_entities ) {
			newnum = 9999;
		} else {
			newent = SV_SnapshotEntity( to->first_entity + newindex );
			newnum = newent->number;
		}

		if ( oldindex >= from_num_entities ) {
			oldnum = 9999;
		} else {
			oldent = SV_SnapshotEntity( from->first_entity + oldindex );
			oldnum = oldent->number;
		}

		if ( newnum == oldnum ) {
			// delta update from old position
			// because the force parm is qfalse, this will not result
			// in any bytes being emited if the entity has not changed at all
			MSG_WriteDeltaEntity (msg, oldent, newent, qfalse );
			oldindex++;
			newindex++;
			continue;
		}

		if ( newnum < oldnum ) {
			// this is a new entity, send it from the baseline
			MSG_WriteDeltaEntity (msg, DA_ElementPointer( sv.svEntitiesBaseline, newnum ), newent, qtrue );
			newindex++;
			continue;
		}

		if ( newnum > oldnum ) {
			// the old entity isn't present in the new message
			MSG_WriteDeltaEntity (msg, oldent, NULL, qtrue );
			oldindex++;
			continue;
		}
	}

	MSG_WriteBits( msg, (MAX_GENTITIES-1), GENTITYNUM_BITS );	// end of packetentities
}
Exemple #2
0
/*
==================
CL_ParseBaseline
==================
*/
void CL_ParseBaseline( msg_t *msg ) {
	sharedEntityState_t	*es;
	int					newnum;

	if ( !cgvm ) {
		Com_Error( ERR_DROP, "Received unexpected baseline" );
	}

	if ( !cl.entityBaselines.pointer ) {
		Com_Error( ERR_DROP, "cgame needs to call trap_SetNetFields" );
	}

	newnum = MSG_ReadBits( msg, GENTITYNUM_BITS );
	if ( newnum < 0 || newnum >= MAX_GENTITIES ) {
		Com_Error( ERR_DROP, "Baseline number out of range: %i", newnum );
	}
	es = DA_ElementPointer( cl.entityBaselines, newnum );
	MSG_ReadDeltaEntity( msg, NULL, es, newnum );
}
Exemple #3
0
/*
==================
SV_WriteBaselineToClient
==================
*/
void SV_WriteBaselineToClient( client_t *client, msg_t *msg ) {
	sharedEntityState_t	*base;
	int					start;

	if ( !client->needBaseline ) {
		return;
	}

	client->needBaseline = qfalse;

	// write the baselines
	for ( start = 0 ; start < MAX_GENTITIES; start++ ) {
		base = (sharedEntityState_t *)DA_ElementPointer( sv.svEntitiesBaseline, start );
		if ( !base->number ) {
			continue;
		}
		MSG_WriteByte( msg, svc_baseline );
		MSG_WriteDeltaEntity( msg, NULL, base, qtrue );
	}
}
Exemple #4
0
/*
=============
SV_SnapshotPlayer

Get pointer to beginning of player state.
=============
*/
sharedPlayerState_t *SV_SnapshotPlayer( clientSnapshot_t *snap, int num ) {
	return DA_ElementPointer( snap->playerStates, num );
}
Exemple #5
0
/*
=============
SV_SnapshotEntity

Get pointer to beginning of entity state.
=============
*/
sharedEntityState_t *SV_SnapshotEntity( int num ) {
	return DA_ElementPointer( svs.snapshotEntities, num % svs.numSnapshotEntities );
}
Exemple #6
0
/*
==================
CL_ParseEntityState

Client only looks at shared part of entityState_t
==================
*/
sharedEntityState_t *CL_ParseEntityState( int num ) {
	return DA_ElementPointer( cl.parseEntities, num % cl.parseEntities.maxElements );
}
Exemple #7
0
/*
================
CL_ParseSnapshot

If the snapshot is parsed properly, it will be copied to
cl.snap and saved in cl.snapshots[].  If the snapshot is invalid
for any reason, no changes to the state will be made at all.
================
*/
void CL_ParseSnapshot( msg_t *msg ) {
	int			len;
	clSnapshot_t	*old;
	clSnapshot_t	newSnap;
	sharedPlayerState_t *newPS, *oldPS;
	int			deltaNum;
	int			oldMessageNum;
	int			i, packetNum;

	if ( !cgvm ) {
		Com_Error( ERR_DROP, "Received unexpected snapshot" );
	}

	if ( !cl.cgamePlayerStateSize || !cl.cgameEntityStateSize ) {
		Com_Error( ERR_DROP, "cgame needs to call trap_SetNetFields" );
	}

	// get the reliable sequence acknowledge number
	// NOTE: now sent with all server to client messages
	//clc.reliableAcknowledge = MSG_ReadLong( msg );

	// read in the new snapshot to a temporary buffer
	// we will only copy to cl.snap if it is valid
	Com_Memset (&newSnap, 0, sizeof(newSnap));

	// we will have read any new server commands in this
	// message before we got to svc_snapshot
	newSnap.serverCommandNum = clc.serverCommandSequence;

	newSnap.serverTime = MSG_ReadLong( msg );

	// if we were just unpaused, we can only *now* really let the
	// change come into effect or the client hangs.
	cl_paused->modified = 0;

	newSnap.messageNum = clc.serverMessageSequence;

	deltaNum = MSG_ReadByte( msg );
	if ( !deltaNum ) {
		newSnap.deltaNum = -1;
	} else {
		newSnap.deltaNum = newSnap.messageNum - deltaNum;
	}
	newSnap.snapFlags = MSG_ReadByte( msg );

	// If the frame is delta compressed from data that we
	// no longer have available, we must suck up the rest of
	// the frame, but not use it, then ask for a non-compressed
	// message 
	if ( newSnap.deltaNum <= 0 ) {
		newSnap.valid = qtrue;		// uncompressed frame
		old = NULL;
		clc.demowaiting = qfalse;	// we can start recording now
	} else {
		old = &cl.snapshots[newSnap.deltaNum & PACKET_MASK];
		if ( !old->valid ) {
			// should never happen
			Com_Printf ("Delta from invalid frame (not supposed to happen!).\n");
		} else if ( old->messageNum != newSnap.deltaNum ) {
			// The frame that the server did the delta from
			// is too old, so we can't reconstruct it properly.
			Com_Printf ("Delta frame too old.\n");
		} else if ( cl.parseEntitiesNum - old->parseEntitiesNum > cl.parseEntities.maxElements - MAX_SNAPSHOT_ENTITIES * CL_MAX_SPLITVIEW ) {
			Com_Printf ("Delta parseEntitiesNum too old.\n");
		} else {
			newSnap.valid = qtrue;	// valid delta parse
		}
	}

	DA_Clear( &cl.tempSnapshotPS );

	// read playerinfo
	SHOWNET( msg, "playerstate" );

	newSnap.numPSs = MSG_ReadByte( msg );
	if (newSnap.numPSs > MAX_SPLITVIEW) {
		Com_DPrintf(S_COLOR_YELLOW "Warning: Got numPSs as %d (max=%d)\n", newSnap.numPSs, MAX_SPLITVIEW);
		newSnap.numPSs = MAX_SPLITVIEW;
	}

	for (i = 0; i < MAX_SPLITVIEW; i++) {
		newSnap.localPlayerIndex[i] = MSG_ReadByte( msg );
		newSnap.playerNums[i] = MSG_ReadByte( msg );

		// -1 gets converted to 255 should be set to -1 (and so should all invalid values)
		if ( newSnap.localPlayerIndex[i] >= newSnap.numPSs || newSnap.playerNums[i] >= MAX_CLIENTS ) {
			newSnap.localPlayerIndex[i] = -1;
			newSnap.playerNums[i] = -1;
		}

		// read areamask
		len = MSG_ReadByte( msg );

		if(len > sizeof(newSnap.areamask[0]))
		{
			Com_Error (ERR_DROP,"CL_ParseSnapshot: Invalid size %d for areamask", len);
			return;
		}

		MSG_ReadData( msg, &newSnap.areamask[i], len);
	}

	for (i = 0; i < MAX_SPLITVIEW; i++) {
		// Read player states
		if (newSnap.localPlayerIndex[i] != -1) {
			newPS = (sharedPlayerState_t *) DA_ElementPointer( cl.tempSnapshotPS, newSnap.localPlayerIndex[i] );

			if ( old && old->valid && old->localPlayerIndex[i] != -1 ) {
				oldPS = (sharedPlayerState_t *) DA_ElementPointer( old->playerStates, old->localPlayerIndex[i] );

				MSG_ReadDeltaPlayerstate( msg, oldPS, newPS, newSnap.playerNums[i] );
			} else {
				MSG_ReadDeltaPlayerstate( msg, NULL, newPS, newSnap.playerNums[i] );
			}
		}

		// Server added or removed local player
		if ( old && old->playerNums[i] != newSnap.playerNums[i] ) {
			CL_LocalPlayerRemoved( i );

			if ( newSnap.playerNums[i] != -1 ) {
				CL_LocalPlayerAdded( i, newSnap.playerNums[i] );
			}
		}
	}

	// read packet entities
	SHOWNET( msg, "packet entities" );
	CL_ParsePacketEntities( msg, old, &newSnap );

	// if not valid, dump the entire thing now that it has
	// been properly read
	if ( !newSnap.valid ) {
		return;
	}

	// clear the valid flags of any snapshots between the last
	// received and this one, so if there was a dropped packet
	// it won't look like something valid to delta from next
	// time we wrap around in the buffer
	oldMessageNum = cl.snap.messageNum + 1;

	if ( newSnap.messageNum - oldMessageNum >= PACKET_BACKUP ) {
		oldMessageNum = newSnap.messageNum - ( PACKET_BACKUP - 1 );
	}
	for ( ; oldMessageNum < newSnap.messageNum ; oldMessageNum++ ) {
		cl.snapshots[oldMessageNum & PACKET_MASK].valid = qfalse;
	}

	// copy player states from temp to snapshot
	DA_Copy( cl.tempSnapshotPS, &cl.snapshots[newSnap.messageNum & PACKET_MASK].playerStates );
	newSnap.playerStates = cl.snapshots[newSnap.messageNum & PACKET_MASK].playerStates;

	// copy to the current good spot
	cl.snap = newSnap;
	cl.snap.ping = 999;
	// calculate ping time
	for ( i = 0 ; i < PACKET_BACKUP ; i++ ) {
		packetNum = ( clc.netchan.outgoingSequence - 1 - i ) & PACKET_MASK;
		newPS = (sharedPlayerState_t *) DA_ElementPointer( cl.snap.playerStates, 0 );
		if ( newPS->commandTime >= cl.outPackets[ packetNum ].p_serverTime ) {
			cl.snap.ping = cls.realtime - cl.outPackets[ packetNum ].p_realtime;
			break;
		}
	}
	// save the frame off in the backup array for later delta comparisons
	cl.snapshots[cl.snap.messageNum & PACKET_MASK] = cl.snap;

	if (cl_shownet->integer == 3) {
		Com_Printf( "   snapshot:%i  delta:%i  ping:%i\n", cl.snap.messageNum,
		cl.snap.deltaNum, cl.snap.ping );
	}

	cl.newSnapshots = qtrue;
}
Exemple #8
0
/*
==================
CL_ParsePacketEntities

==================
*/
void CL_ParsePacketEntities( msg_t *msg, clSnapshot_t *oldframe, clSnapshot_t *newframe) {
	int			newnum;
	sharedEntityState_t	*oldstate;
	int			oldindex, oldnum;

	newframe->parseEntitiesNum = cl.parseEntitiesNum;
	newframe->numEntities = 0;

	// delta from the entities present in oldframe
	oldindex = 0;
	oldstate = NULL;
	if (!oldframe) {
		oldnum = 99999;
	} else {
		if ( oldindex >= oldframe->numEntities ) {
			oldnum = 99999;
		} else {
			oldstate = CL_ParseEntityState(oldframe->parseEntitiesNum + oldindex);
			oldnum = oldstate->number;
		}
	}

	while ( 1 ) {
		// read the entity index number
		newnum = MSG_ReadBits( msg, GENTITYNUM_BITS );

		if ( newnum == (MAX_GENTITIES-1) ) {
			break;
		}

		if ( msg->readcount > msg->cursize ) {
			Com_Error (ERR_DROP,"CL_ParsePacketEntities: end of message");
		}

		while ( oldnum < newnum ) {
			// one or more entities from the old packet are unchanged
			if ( cl_shownet->integer == 3 ) {
				Com_Printf ("%3i:  unchanged: %i\n", msg->readcount, oldnum);
			}
			CL_DeltaEntity( msg, newframe, oldnum, oldstate, qtrue );
			
			oldindex++;

			if ( oldindex >= oldframe->numEntities ) {
				oldnum = 99999;
			} else {
				oldstate = CL_ParseEntityState(oldframe->parseEntitiesNum + oldindex);
				oldnum = oldstate->number;
			}
		}
		if (oldnum == newnum) {
			// delta from previous state
			if ( cl_shownet->integer == 3 ) {
				Com_Printf ("%3i:  delta: %i\n", msg->readcount, newnum);
			}
			CL_DeltaEntity( msg, newframe, newnum, oldstate, qfalse );

			oldindex++;

			if ( oldindex >= oldframe->numEntities ) {
				oldnum = 99999;
			} else {
				oldstate = CL_ParseEntityState(oldframe->parseEntitiesNum + oldindex);
				oldnum = oldstate->number;
			}
			continue;
		}

		if ( oldnum > newnum ) {
			// delta from baseline
			if ( cl_shownet->integer == 3 ) {
				Com_Printf ("%3i:  baseline: %i\n", msg->readcount, newnum);
			}
			CL_DeltaEntity( msg, newframe, newnum, DA_ElementPointer( cl.entityBaselines, newnum ), qfalse );
			continue;
		}

	}

	// any remaining entities in the old frame are copied over
	while ( oldnum != 99999 ) {
		// one or more entities from the old packet are unchanged
		if ( cl_shownet->integer == 3 ) {
			Com_Printf ("%3i:  unchanged: %i\n", msg->readcount, oldnum);
		}
		CL_DeltaEntity( msg, newframe, oldnum, oldstate, qtrue );
		
		oldindex++;

		if ( oldindex >= oldframe->numEntities ) {
			oldnum = 99999;
		} else {
			oldstate = CL_ParseEntityState(oldframe->parseEntitiesNum + oldindex);
			oldnum = oldstate->number;
		}
	}
}