示例#1
0
static void demoFramePack( msg_t *msg, const demoFrame_t *newFrame, const demoFrame_t *oldFrame ) {
	int i;
	/* Full or delta frame marker */
	MSG_WriteBits( msg, oldFrame ? 0 : 1, 1 );
	MSG_WriteLong( msg, newFrame->serverTime );
	/* Add the config strings */
	for (i = 0;i<MAX_CONFIGSTRINGS;i++) {
		const char *oldString = !oldFrame ? "" : &oldFrame->string.data[oldFrame->string.offsets[i]];
		const char *newString = newFrame->string.data + newFrame->string.offsets[i];
		if (strcmp( oldString, newString)) {
			MSG_WriteShort( msg, i );
			MSG_WriteBigString( msg, newString );
		}
	}
	MSG_WriteShort( msg, MAX_CONFIGSTRINGS );
	/* Add the playerstates */
	for (i=0; i<MAX_CLIENTS; i++) {
		const playerState_t *oldPlayer, *newPlayer;
		if (!newFrame->clientData[i])
			continue;
		oldPlayer = (!oldFrame || !oldFrame->clientData[i]) ? &demoNullPlayerState : &oldFrame->clients[i];
		newPlayer = &newFrame->clients[i];
		MSG_WriteByte( msg, i );
		MSG_WriteDeltaPlayerstate( msg, oldPlayer, newPlayer );
	}
	MSG_WriteByte( msg, MAX_CLIENTS );
	/* Add the entities */
	for (i=0; i<MAX_GENTITIES-1; i++) {
		const entityState_t *oldEntity, *newEntity;
		newEntity = &newFrame->entities[i];
		if (oldFrame) {
			oldEntity = &oldFrame->entities[i];
			if (oldEntity->number == (MAX_GENTITIES -1))
				oldEntity = 0;
		} else {
			oldEntity = 0;
		}
		if (newEntity->number != i || newEntity->number >= (MAX_GENTITIES -1)) {
			newEntity = 0;
		} else {
			if (!oldEntity) {
				oldEntity = &demoNullEntityState;
			}
		}
		MSG_WriteDeltaEntity( msg, oldEntity, newEntity, qfalse );
	}
	MSG_WriteBits( msg, (MAX_GENTITIES-1), GENTITYNUM_BITS );
	/* Add the area mask */
	MSG_WriteByte( msg, newFrame->areaUsed );
	MSG_WriteData( msg, newFrame->areamask, newFrame->areaUsed );
	/* Add the command string data */
	MSG_WriteLong( msg, newFrame->commandUsed );
	MSG_WriteData( msg, newFrame->commandData, newFrame->commandUsed );
}
示例#2
0
/*
==================
SV_WriteSnapshotToClient
==================
*/
static void SV_WriteSnapshotToClient(client_t *client, msg_t *msg)
{
    clientSnapshot_t *frame, *oldframe;
    int lastframe;
    int i;
    int snapFlags;

    // this is the snapshot we are creating
    frame = &client->frames[client->netchan.outgoingSequence & PACKET_MASK];

    // try to use a previous frame as the source for delta compressing the snapshot
    if (client->deltaMessage <= 0 || client->state != CS_ACTIVE)
    {
        // client is asking for a retransmit
        oldframe = NULL;
        lastframe = 0;
    }
    else if (client->netchan.outgoingSequence - client->deltaMessage >= (PACKET_BACKUP - 3))
    {
        // client hasn't gotten a good message through in a long time
        Com_DPrintf("%s: Delta request from out of date packet.\n", client->name);
        oldframe = NULL;
        lastframe = 0;
    }
    else
    {
        // we have a valid snapshot to delta from
        oldframe = &client->frames[client->deltaMessage & PACKET_MASK];
        lastframe = client->netchan.outgoingSequence - client->deltaMessage;

        // the snapshot's entities may still have rolled off the buffer, though
        if (oldframe->first_entity <= svs.nextSnapshotEntities - svs.numSnapshotEntities)
        {
            Com_DPrintf("%s: Delta request from out of date entities.\n", client->name);
            oldframe = NULL;
            lastframe = 0;
        }
    }

    MSG_WriteByte(msg, svc_snapshot);

    // NOTE, MRE: now sent at the start of every message from server to client
    // let the client know which reliable clientCommands we have received
    // MSG_WriteLong( msg, client->lastClientCommand );

    // send over the current server time so the client can drift
    // its view of time to try to match
    if (client->oldServerTime)
    {
        // The server has not yet got an acknowledgement of the
        // new gamestate from this client, so continue to send it
        // a time as if the server has not restarted. Note from
        // the client's perspective this time is strictly speaking
        // incorrect, but since it'll be busy loading a map at
        // the time it doesn't really matter.
        MSG_WriteLong(msg, sv.time + client->oldServerTime);
    }
    else
    {
        MSG_WriteLong(msg, sv.time);
    }

    // what we are delta'ing from
    MSG_WriteByte(msg, lastframe);

    snapFlags = svs.snapFlagServerBit;
    if (client->rateDelayed)
    {
        snapFlags |= SNAPFLAG_RATE_DELAYED;
    }
    if (client->state != CS_ACTIVE)
    {
        snapFlags |= SNAPFLAG_NOT_ACTIVE;
    }

    MSG_WriteByte(msg, snapFlags);

    // send over the areabits
    MSG_WriteByte(msg, frame->areabytes);
    MSG_WriteData(msg, frame->areabits, frame->areabytes);

    // delta encode the playerstate
    if (oldframe)
    {
        MSG_WriteDeltaPlayerstate(client->netchan.alternateProtocol, msg, &oldframe->ps, &frame->ps);
    }
    else
    {
        MSG_WriteDeltaPlayerstate(client->netchan.alternateProtocol, msg, NULL, &frame->ps);
    }

    // delta encode the entities
    SV_EmitPacketEntities(client->netchan.alternateProtocol, oldframe, frame, msg);

    // padding for rate debugging
    if (sv_padPackets->integer)
    {
        for (i = 0; i < sv_padPackets->integer; i++)
        {
            MSG_WriteByte(msg, svc_nop);
        }
    }
}
示例#3
0
__cdecl void SV_WriteSnapshotToClient(client_t* client, msg_t* msg){

    snapshotInfo_t snapInfo;
    int lastframe;
    int from_num_entities;
    int newindex, oldindex, newnum, oldnum;
    clientState_ts *newcs, *oldcs;
    entityState_t *newent, *oldent;
    clientSnapshot_t *frame, *oldframe;
    int i;
    int snapFlags;
    int var_x, from_first_entity, from_num_clients, from_first_client;

    snapInfo.clnum = client - svsHeader.clients;
    snapInfo.cl = (void*)client;
    snapInfo.var_01 = 0;
    snapInfo.var_02 = 0;
    snapInfo.var_03 = 0;

    frame = &client->frames[client->netchan.outgoingSequence & PACKET_MASK];
    frame->var_03 = svsHeader.time;

    if(client->deltaMessage <= 0 ||  client->state != CS_ACTIVE) {
        oldframe = NULL;
        lastframe = 0;
        var_x = 0;

    } else if(client->netchan.outgoingSequence - client->deltaMessage >= PACKET_BACKUP - 3) {
        Com_DPrintf("%s: Delta request from out of date packet.\n", client->name);
        oldframe = NULL;
        lastframe = 0;
        var_x = 0;

    } else if(client->demoDeltaFrameCount <= 0 && client->demorecording){

        oldframe = NULL;
        lastframe = 0;
        var_x = 0;
        client->demowaiting = qfalse;
        Com_DPrintf("Force a nondelta frame for %s for demo recording\n", client->name);

        if(client->demoMaxDeltaFrames < 1024)
        {
            client->demoMaxDeltaFrames <<= 1;
        }
        client->demoDeltaFrameCount = client->demoMaxDeltaFrames;


    } else {
        oldframe = &client->frames[client->deltaMessage & PACKET_MASK];
        lastframe = client->netchan.outgoingSequence - client->deltaMessage;
        var_x = oldframe->var_03;
        client->demoDeltaFrameCount--;

        if(oldframe->first_entity <  svsHeader.nextSnapshotEntities - svsHeader.numSnapshotEntities) {
            Com_PrintWarning("%s: Delta request from out of date entities - delta against entity %i, oldest is %i, current is %i.  Their old snapshot had %i entities in it\n",
                            client->name, oldframe->first_entity, svs.nextSnapshotEntities - svs.numSnapshotEntities, svs.nextSnapshotEntities, oldframe->num_entities );
            oldframe = NULL;
            lastframe = 0;
            var_x = 0;

        } else if(oldframe->first_client <  svsHeader.nextSnapshotClients - svsHeader.numSnapshotClients) {

            Com_PrintWarning("%s: Delta request from out of date clients - delta against client %i, oldest is %i, current is %i.  Their old snapshot had %i clients in it\n", 
                            client->name, oldframe->first_client, svs.nextSnapshotClients - svs.numSnapshotClients, svs.nextSnapshotClients, oldframe->num_clients);
            oldframe = NULL;
            lastframe = 0;
            var_x = 0;
        }
    }


    MSG_WriteByte(msg, svc_snapshot);
    MSG_WriteLong(msg, svsHeader.time);
    MSG_WriteByte(msg, lastframe);
    snapInfo.var_01 = var_x;

    snapFlags = svsHeader.snapFlagServerBit;

    if(client->rateDelayed){
	snapFlags |= 1;
    }

    if(client->state == CS_ACTIVE) {

	client->unksnapshotvar = 1;

    } else {
	if(client->state != CS_ZOMBIE){
		client->unksnapshotvar = 0;
	}
    }

    if(!client->unksnapshotvar){
	snapFlags |= 2;
    }

    MSG_WriteByte(msg, snapFlags);

    if(oldframe) {
		MSG_WriteDeltaPlayerstate( &snapInfo, msg, svsHeader.time, &oldframe->ps, &frame->ps);
		from_num_entities = oldframe->num_entities;
		from_first_entity = oldframe->first_entity;
		from_num_clients = oldframe->num_clients;
		from_first_client = oldframe->first_client;
    } else {
	        MSG_WriteDeltaPlayerstate( &snapInfo, msg, svsHeader.time, 0, &frame->ps);
		from_num_entities = 0;
		from_first_entity = 0;
		from_num_clients = 0;
		from_first_client = 0;
    }

    MSG_ClearLastReferencedEntity(msg);


    newindex = 0;
    oldindex = 0;

//    Com_Printf("\nDelta client: %i:\n", snapInfo.clnum);


    while ( newindex < frame->num_entities || oldindex < from_num_entities){
	if ( newindex >= frame->num_entities ) {
		newnum = 9999;
		newent = NULL;
	} else {
		newent = &svsHeader.snapshotEntities[( frame->first_entity + newindex ) % svsHeader.numSnapshotEntities];
		newnum = newent->number;
	}

	if ( oldindex >= from_num_entities ) {
		oldnum = 9999;
		oldent = NULL;
	} else {
		oldent = &svsHeader.snapshotEntities[( from_first_entity + oldindex ) % svsHeader.numSnapshotEntities];
		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
//		if(newent->number < 64 || oldent->number < 64)
//			Com_Printf("   Delta Update Entity - New delta: %i, %x  Old delta: %i, %x\n", newent->number, newent, oldent->number, oldent);
		MSG_WriteDeltaEntity( &snapInfo, msg, svsHeader.time, oldent, newent, qfalse );
		oldindex++;
		newindex++;
		continue;
	}

	if ( newnum < oldnum ) {
		// this is a new entity, send it from the baseline
		snapInfo.var_02 = 1;
//		if(newent->number < 64)
//			Com_Printf("   Delta Add Entity: %i, %x\n", newent->number, newent);
		MSG_WriteDeltaEntity( &snapInfo, msg, svsHeader.time, &svsHeader.svEntities[newnum].baseline, newent, qtrue );
		snapInfo.var_02 = 0;
		newindex++;
		continue;
	}

	if ( newnum > oldnum ) {
		// the old entity isn't present in the new message
//		if(oldent->number < 64)
//			Com_Printf("   Delta Remove Entity: %i, %x\n", oldent->number, oldent);
		MSG_WriteDeltaEntity( &snapInfo, msg, svsHeader.time, oldent, NULL, qtrue );
		oldindex++;
		continue;
	}
    }


    MSG_WriteEntityIndex(&snapInfo, msg, ( MAX_GENTITIES - 1 ), GENTITYNUM_BITS);
    MSG_ClearLastReferencedEntity(msg);

    newindex = 0;
    oldindex = 0;

    while(newindex < frame->num_clients || oldindex < from_num_clients){
	if(newindex >= frame->num_clients){
		newnum = 9999;
		newcs = NULL;
	}else{

		newcs = &svsHeader.snapshotClients[(frame->first_client + newindex) % svsHeader.numSnapshotClients];
		newnum = newcs->number;
	}

	if(oldindex >= from_num_clients){
		oldnum = 9999;
		oldcs = NULL;
	}else{

		oldcs = &svsHeader.snapshotClients[(from_first_client + oldindex) % svsHeader.numSnapshotClients];
		oldnum = oldcs->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_WriteDeltaClient( &snapInfo, msg, svsHeader.time, oldcs, newcs, qfalse );
		oldindex++;
		newindex++;
		continue;
	}

	if ( newnum < oldnum ) {
		MSG_WriteDeltaClient( &snapInfo, msg, svsHeader.time, NULL, newcs, qtrue );
		newindex++;
		continue;
	}

	if ( newnum > oldnum ) {
		MSG_WriteDeltaClient( &snapInfo, msg, svsHeader.time, oldcs, NULL, qtrue );
		oldindex++;
		continue;
	}
    }

    MSG_WriteBit0(msg);

    if(sv_padPackets->integer){
	for( i=0 ; i < sv_padPackets->integer ; i++){
		MSG_WriteByte( msg, 0); //svc_nop
	}
    }
}
示例#4
0
/*
==================
SV_WriteSnapshotToClient
==================
*/
static void SV_WriteSnapshotToClient( client_t *client, msg_t *msg ) {
	clientSnapshot_t	*frame, *oldframe;
	int					lastframe;
	int					snapFlags;

	// this is the snapshot we are creating
	frame = &client->frames[ client->netchan.outgoingSequence & PACKET_MASK ];

	// try to use a previous frame as the source for delta compressing the snapshot
	if ( client->deltaMessage <= 0 || client->state != CS_ACTIVE ) {
		// client is asking for a retransmit
		oldframe = NULL;
		lastframe = 0;
	} else if ( client->netchan.outgoingSequence - client->deltaMessage 
		>= (PACKET_BACKUP - 3) ) {
		// client hasn't gotten a good message through in a long time
		Com_DPrintf ("%s: Delta request from out of date packet.\n", client->name);
		oldframe = NULL;
		lastframe = 0;
	} else {
		// we have a valid snapshot to delta from
		oldframe = &client->frames[ client->deltaMessage & PACKET_MASK ];
		lastframe = client->netchan.outgoingSequence - client->deltaMessage;

		// the snapshot's entities may still have rolled off the buffer, though
		if ( oldframe->first_entity <= svs.nextSnapshotEntities - svs.numSnapshotEntities ) {
			Com_DPrintf ("%s: Delta request from out of date entities.\n", client->name);
			oldframe = NULL;
			lastframe = 0;
		}
	}

	MSG_WriteByte (msg, svc_snapshot);

	// let the client know which reliable clientCommands we have received
	MSG_WriteLong( msg, client->lastClientCommand );

	// send over the current server time so the client can drift
	// its view of time to try to match
	MSG_WriteLong (msg, sv.time);

	// we must write a message number, because recorded demos won't have
	// the same network message sequences
	MSG_WriteLong (msg, client->netchan.outgoingSequence );
	MSG_WriteByte (msg, lastframe);				// what we are delta'ing from
	MSG_WriteLong (msg, client->cmdNum);		// we have executed up to here

	snapFlags = client->rateDelayed | ( client->droppedCommands << 1 );
	client->droppedCommands = 0;

	MSG_WriteByte (msg, snapFlags);

	// send over the areabits
	MSG_WriteByte (msg, frame->areabytes);
	MSG_WriteData (msg, frame->areabits, frame->areabytes);

	// delta encode the playerstate
	if ( oldframe ) {
		MSG_WriteDeltaPlayerstate( msg, &oldframe->ps, &frame->ps );
	} else {
		MSG_WriteDeltaPlayerstate( msg, NULL, &frame->ps );
	}

	// delta encode the entities
	SV_EmitPacketEntities (oldframe, frame, msg);
}
示例#5
0
/*
==================
SV_WriteSnapshotToClient
==================
*/
static void SV_WriteSnapshotToClient( client_t *client, msg_t *msg ) {
	clientSnapshot_t	*frame, *oldframe;
	int					lastframe;
	int					i;
	int					snapFlags;

	// this is the snapshot we are creating
	frame = &client->frames[ client->netchan.outgoingSequence & PACKET_MASK ];

	// try to use a previous frame as the source for delta compressing the snapshot
	if ( client->deltaMessage <= 0 || client->state != CS_ACTIVE ) {
		// client is asking for a retransmit
		oldframe = NULL;
		lastframe = 0;
	} else if ( client->netchan.outgoingSequence - client->deltaMessage 
		>= (PACKET_BACKUP - 3) ) {
		// client hasn't gotten a good message through in a long time
		Com_DPrintf ("%s: Delta request from out of date packet.\n", client->name);
		oldframe = NULL;
		lastframe = 0;
	} else {
		// we have a valid snapshot to delta from
		oldframe = &client->frames[ client->deltaMessage & PACKET_MASK ];
		lastframe = client->netchan.outgoingSequence - client->deltaMessage;

		// the snapshot's entities may still have rolled off the buffer, though
		if ( oldframe->first_entity <= svs.nextSnapshotEntities - svs.numSnapshotEntities ) {
			Com_DPrintf ("%s: Delta request from out of date entities.\n", client->name);
			oldframe = NULL;
			lastframe = 0;
		}
	}

	MSG_WriteByte (msg, svc_snapshot);

	// NOTE, MRE: now sent at the start of every message from server to client
	// let the client know which reliable clientCommands we have received
	//MSG_WriteLong( msg, client->lastClientCommand );

	// send over the current server time so the client can drift
	// its view of time to try to match
	MSG_WriteLong (msg, svs.time);

	// what we are delta'ing from
	MSG_WriteByte (msg, lastframe);

	snapFlags = svs.snapFlagServerBit;
	if ( client->rateDelayed ) {
		snapFlags |= SNAPFLAG_RATE_DELAYED;
	}
	if ( client->state != CS_ACTIVE ) {
		snapFlags |= SNAPFLAG_NOT_ACTIVE;
	}

	MSG_WriteByte (msg, snapFlags);

	// send over the areabits
	MSG_WriteByte (msg, frame->areabytes);
	MSG_WriteData (msg, frame->areabits, frame->areabytes);

	// delta encode the playerstate
	if ( oldframe ) {
#ifdef _ONEBIT_COMBO
		MSG_WriteDeltaPlayerstate( msg, &oldframe->ps, &frame->ps, frame->pDeltaOneBit, frame->pDeltaNumBit );
#else
		MSG_WriteDeltaPlayerstate( msg, &oldframe->ps, &frame->ps );
#endif
		if (frame->ps.m_iVehicleNum)
		{ //then write the vehicle's playerstate too
			if (!oldframe->ps.m_iVehicleNum)
			{ //if last frame didn't have vehicle, then the old vps isn't gonna delta
				//properly (because our vps on the client could be anything)
#ifdef _ONEBIT_COMBO
				MSG_WriteDeltaPlayerstate( msg, NULL, &frame->vps, NULL, NULL, qtrue );
#else
				MSG_WriteDeltaPlayerstate( msg, NULL, &frame->vps, qtrue );
#endif
			}
			else
			{
#ifdef _ONEBIT_COMBO
				MSG_WriteDeltaPlayerstate( msg, &oldframe->vps, &frame->vps, frame->pDeltaOneBitVeh, frame->pDeltaNumBitVeh, qtrue );
#else
				MSG_WriteDeltaPlayerstate( msg, &oldframe->vps, &frame->vps, qtrue );
#endif
			}
		}
	} else {
#ifdef _ONEBIT_COMBO
		MSG_WriteDeltaPlayerstate( msg, NULL, &frame->ps, NULL, NULL );
#else
		MSG_WriteDeltaPlayerstate( msg, NULL, &frame->ps );
#endif
		if (frame->ps.m_iVehicleNum)
		{ //then write the vehicle's playerstate too
#ifdef _ONEBIT_COMBO
			MSG_WriteDeltaPlayerstate( msg, NULL, &frame->vps, NULL, NULL, qtrue );
#else
			MSG_WriteDeltaPlayerstate( msg, NULL, &frame->vps, qtrue );
#endif
		}
	}

	// delta encode the entities
	SV_EmitPacketEntities (oldframe, frame, msg);

	// padding for rate debugging
	if ( sv_padPackets->integer ) {
		for ( i = 0 ; i < sv_padPackets->integer ; i++ ) {
			MSG_WriteByte (msg, svc_nop);
		}
	}
}
示例#6
0
/*
==================
SV_WriteSnapshotToClient
==================
*/
static void SV_WriteSnapshotToClient( client_t *client, msg_t *msg ) {
	clientSnapshot_t	*frame, *oldframe;
	int					lastframe;
	int					i;
	int					snapFlags;
	int					deltaMessage;

	// this is the snapshot we are creating
	frame = &client->frames[ client->netchan.outgoingSequence & PACKET_MASK ];

	// bots never acknowledge, but it doesn't matter since the only use case is for serverside demos
	// in which case we can delta against the very last message every time
	deltaMessage = client->deltaMessage;
	if ( client->demo.isBot ) {
		client->deltaMessage = client->netchan.outgoingSequence;
	}

	// try to use a previous frame as the source for delta compressing the snapshot
	if ( deltaMessage <= 0 || client->state != CS_ACTIVE ) {
		// client is asking for a retransmit
		oldframe = NULL;
		lastframe = 0;
	} else if ( client->netchan.outgoingSequence - deltaMessage
		>= (PACKET_BACKUP - 3) ) {
		// client hasn't gotten a good message through in a long time
		Com_DPrintf ("%s: Delta request from out of date packet.\n", client->name);
		oldframe = NULL;
		lastframe = 0;
	} else if ( client->demo.demorecording && client->demo.demowaiting ) {
		// demo is waiting for a non-delta-compressed frame for this client, so don't delta compress
		oldframe = NULL;
		lastframe = 0;
	} else if ( client->demo.minDeltaFrame > deltaMessage ) {
		// we saved a non-delta frame to the demo and sent it to the client, but the client didn't ack it
		// we can't delta against an old frame that's not in the demo without breaking the demo.  so send
		// non-delta frames until the client acks.
		oldframe = NULL;
		lastframe = 0;
	} else {
		// we have a valid snapshot to delta from
		oldframe = &client->frames[ deltaMessage & PACKET_MASK ];
		lastframe = client->netchan.outgoingSequence - deltaMessage;

		// the snapshot's entities may still have rolled off the buffer, though
		if ( oldframe->first_entity <= svs.nextSnapshotEntities - svs.numSnapshotEntities ) {
			Com_DPrintf ("%s: Delta request from out of date entities.\n", client->name);
			oldframe = NULL;
			lastframe = 0;
		}
	}

	if ( oldframe == NULL ) {
		if ( client->demo.demowaiting ) {
			// this is a non-delta frame, so we can delta against it in the demo
			client->demo.minDeltaFrame = client->netchan.outgoingSequence;
		}
		client->demo.demowaiting = qfalse;
	}

	MSG_WriteByte (msg, svc_snapshot);

	// NOTE, MRE: now sent at the start of every message from server to client
	// let the client know which reliable clientCommands we have received
	//MSG_WriteLong( msg, client->lastClientCommand );

	// send over the current server time so the client can drift
	// its view of time to try to match
	if( client->oldServerTime &&
		!( client->demo.demorecording && client->demo.isBot ) ) {
		// The server has not yet got an acknowledgement of the
		// new gamestate from this client, so continue to send it
		// a time as if the server has not restarted. Note from
		// the client's perspective this time is strictly speaking
		// incorrect, but since it'll be busy loading a map at
		// the time it doesn't really matter.
		MSG_WriteLong (msg, sv.time + client->oldServerTime);
	} else {
		MSG_WriteLong (msg, sv.time);
	}

	// what we are delta'ing from
	MSG_WriteByte (msg, lastframe);

	snapFlags = svs.snapFlagServerBit;
	if ( client->rateDelayed ) {
		snapFlags |= SNAPFLAG_RATE_DELAYED;
	}
	if ( client->state != CS_ACTIVE ) {
		snapFlags |= SNAPFLAG_NOT_ACTIVE;
	}

	MSG_WriteByte (msg, snapFlags);

	// send over the areabits
	MSG_WriteByte (msg, frame->areabytes);
	MSG_WriteData (msg, frame->areabits, frame->areabytes);

	// delta encode the playerstate
	if ( oldframe ) {
#ifdef _ONEBIT_COMBO
		MSG_WriteDeltaPlayerstate( msg, &oldframe->ps, &frame->ps, frame->pDeltaOneBit, frame->pDeltaNumBit );
#else
		MSG_WriteDeltaPlayerstate( msg, &oldframe->ps, &frame->ps );
#endif
		if (frame->ps.m_iVehicleNum)
		{ //then write the vehicle's playerstate too
			if (!oldframe->ps.m_iVehicleNum)
			{ //if last frame didn't have vehicle, then the old vps isn't gonna delta
				//properly (because our vps on the client could be anything)
#ifdef _ONEBIT_COMBO
				MSG_WriteDeltaPlayerstate( msg, NULL, &frame->vps, NULL, NULL, qtrue );
#else
				MSG_WriteDeltaPlayerstate( msg, NULL, &frame->vps, qtrue );
#endif
			}
			else
			{
#ifdef _ONEBIT_COMBO
				MSG_WriteDeltaPlayerstate( msg, &oldframe->vps, &frame->vps, frame->pDeltaOneBitVeh, frame->pDeltaNumBitVeh, qtrue );
#else
				MSG_WriteDeltaPlayerstate( msg, &oldframe->vps, &frame->vps, qtrue );
#endif
			}
		}
	} else {
#ifdef _ONEBIT_COMBO
		MSG_WriteDeltaPlayerstate( msg, NULL, &frame->ps, NULL, NULL );
#else
		MSG_WriteDeltaPlayerstate( msg, NULL, &frame->ps );
#endif
		if (frame->ps.m_iVehicleNum)
		{ //then write the vehicle's playerstate too
#ifdef _ONEBIT_COMBO
			MSG_WriteDeltaPlayerstate( msg, NULL, &frame->vps, NULL, NULL, qtrue );
#else
			MSG_WriteDeltaPlayerstate( msg, NULL, &frame->vps, qtrue );
#endif
		}
	}

	// delta encode the entities
	SV_EmitPacketEntities (oldframe, frame, msg);

	// padding for rate debugging
	if ( sv_padPackets->integer ) {
		for ( i = 0 ; i < sv_padPackets->integer ; i++ ) {
			MSG_WriteByte (msg, svc_nop);
		}
	}
}
示例#7
0
/*
==================
SV_WriteSnapshotToClient
==================
*/
static void SV_WriteSnapshotToClient(client_t *client, msg_t *msg)
{
	clientSnapshot_t *frame, *oldframe;
	int              lastframe;
	int              snapFlags;

	// this is the snapshot we are creating
	frame = &client->frames[client->netchan.outgoingSequence & PACKET_MASK];

	// try to use a previous frame as the source for delta compressing the snapshot
	if (client->deltaMessage <= 0 || client->state != CS_ACTIVE)
	{
		// client is asking for a retransmit
		oldframe  = NULL;
		lastframe = 0;
	}
	else if (client->netchan.outgoingSequence - client->deltaMessage >= (PACKET_BACKUP - 3))
	{
		// client hasn't gotten a good message through in a long time
		Com_DPrintf("%s: Delta request from out of date packet.\n", client->name);
		oldframe  = NULL;
		lastframe = 0;
	}
	else
	{
		// we have a valid snapshot to delta from
		oldframe  = &client->frames[client->deltaMessage & PACKET_MASK];
		lastframe = client->netchan.outgoingSequence - client->deltaMessage;

		// the snapshot's entities may still have rolled off the buffer, though
		if (oldframe->first_entity <= svs.nextSnapshotEntities - svs.numSnapshotEntities)
		{
			Com_DPrintf("%s: Delta request from out of date entities.\n", client->name);
			oldframe  = NULL;
			lastframe = 0;
		}
	}

	MSG_WriteByte(msg, svc_snapshot);

	// NOTE, MRE: now sent at the start of every message from server to client
	// let the client know which reliable clientCommands we have received
	//MSG_WriteLong( msg, client->lastClientCommand );

	// send over the current server time so the client can drift
	// its view of time to try to match
	MSG_WriteLong(msg, svs.time);

	// what we are delta'ing from
	MSG_WriteByte(msg, lastframe);

	snapFlags = svs.snapFlagServerBit;
	if (client->rateDelayed)
	{
		snapFlags |= SNAPFLAG_RATE_DELAYED;
	}
	if (client->state != CS_ACTIVE)
	{
		snapFlags |= SNAPFLAG_NOT_ACTIVE;
	}

	MSG_WriteByte(msg, snapFlags);

	// send over the areabits
	MSG_WriteByte(msg, frame->areabytes);
	MSG_WriteData(msg, frame->areabits, frame->areabytes);

	//{
	//int sz = msg->cursize;
	//int usz = msg->uncompsize;

	// delta encode the playerstate
	if (oldframe)
	{
		MSG_WriteDeltaPlayerstate(msg, &oldframe->ps, &frame->ps);
	}
	else
	{
		MSG_WriteDeltaPlayerstate(msg, NULL, &frame->ps);
	}

	//Com_Printf( "Playerstate delta size: %f\n", ((msg->cursize - sz) * sv_fps->integer) / 8.f );
	//}

	// delta encode the entities
	SV_EmitPacketEntities(oldframe, frame, msg);

	// padding for rate debugging
	if (sv_padPackets->integer)
	{
		int i;

		for (i = 0 ; i < sv_padPackets->integer ; i++)
		{
			MSG_WriteByte(msg, svc_nop);
		}
	}
}
示例#8
0
void demoCutWriteDeltaSnapshot(int firstServerCommand, fileHandle_t f, qboolean forceNonDelta, clientConnection_t *clcCut, clientActive_t *clCut) {
	msg_t			msgImpl, *msg = &msgImpl;
	byte			msgData[MAX_MSGLEN];
	clSnapshot_t	*frame, *oldframe;
	int				lastframe = 0;
	int				snapFlags;
	MSG_Init(msg, msgData, sizeof(msgData));
	MSG_Bitstream(msg);
	MSG_WriteLong(msg, clcCut->reliableSequence);
	// copy over any commands
	for (int serverCommand = firstServerCommand; serverCommand <= clcCut->serverCommandSequence; serverCommand++) {
		char *command = clcCut->serverCommands[serverCommand & (MAX_RELIABLE_COMMANDS - 1)];
		MSG_WriteByte(msg, svc_serverCommand);
		MSG_WriteLong(msg, serverCommand/* + serverCommandOffset*/);
		MSG_WriteString(msg, command);
	}
	// this is the snapshot we are creating
	frame = &clCut->snap;
	if (clCut->snap.messageNum > 0 && !forceNonDelta) {
		lastframe = 1;
		oldframe = &clCut->snapshots[(clCut->snap.messageNum - 1) & PACKET_MASK]; // 1 frame previous
		if (!oldframe->valid) {
			// not yet set
			lastframe = 0;
			oldframe = NULL;
		}
	} else {
		lastframe = 0;
		oldframe = NULL;
	}
	MSG_WriteByte(msg, svc_snapshot);
	// send over the current server time so the client can drift
	// its view of time to try to match
	MSG_WriteLong(msg, frame->serverTime);
	// what we are delta'ing from
	MSG_WriteByte(msg, lastframe);
	snapFlags = frame->snapFlags;
	MSG_WriteByte(msg, snapFlags);
	// send over the areabits
	MSG_WriteByte(msg, sizeof(frame->areamask));
	MSG_WriteData(msg, frame->areamask, sizeof(frame->areamask));
	// delta encode the playerstate
	if (oldframe) {
#ifdef _ONEBIT_COMBO
		MSG_WriteDeltaPlayerstate(msg, &oldframe->ps, &frame->ps, frame->pDeltaOneBit, frame->pDeltaNumBit);
#else
		MSG_WriteDeltaPlayerstate(msg, &oldframe->ps, &frame->ps);
#endif
		if (frame->ps.m_iVehicleNum) {
		//then write the vehicle's playerstate too
			if (!oldframe->ps.m_iVehicleNum) {
			//if last frame didn't have vehicle, then the old vps isn't gonna delta
			//properly (because our vps on the client could be anything)
#ifdef _ONEBIT_COMBO
				MSG_WriteDeltaPlayerstate(msg, NULL, &frame->vps, NULL, NULL, qtrue);
#else
				MSG_WriteDeltaPlayerstate(msg, NULL, &frame->vps, qtrue);
#endif
			} else {
#ifdef _ONEBIT_COMBO
				MSG_WriteDeltaPlayerstate(msg, &oldframe->vps, &frame->vps, frame->pDeltaOneBitVeh, frame->pDeltaNumBitVeh, qtrue);
#else
				MSG_WriteDeltaPlayerstate(msg, &oldframe->vps, &frame->vps, qtrue);
#endif
			}
		}
	} else {
#ifdef _ONEBIT_COMBO
		MSG_WriteDeltaPlayerstate(msg, NULL, &frame->ps, NULL, NULL);
#else
		MSG_WriteDeltaPlayerstate(msg, NULL, &frame->ps);
#endif
		if (frame->ps.m_iVehicleNum) {
		//then write the vehicle's playerstate too
#ifdef _ONEBIT_COMBO
			MSG_WriteDeltaPlayerstate(msg, NULL, &frame->vps, NULL, NULL, qtrue);
#else
			MSG_WriteDeltaPlayerstate(msg, NULL, &frame->vps, qtrue);
#endif
		}
	}
	// delta encode the entities
	demoCutEmitPacketEntities(oldframe, frame, msg, clCut);
	MSG_WriteByte(msg, svc_EOF);
	demoCutWriteDemoMessage(msg, f, clcCut);
}