diff options
author | Andrey Nazarov <skuller@skuller.net> | 2007-09-12 21:58:46 +0000 |
---|---|---|
committer | Andrey Nazarov <skuller@skuller.net> | 2007-09-12 21:58:46 +0000 |
commit | 0ef58160f7b4bacc57c8e7397996f0e368417272 (patch) | |
tree | 148e7ab1929383ec7e4ef259284293ecb1cd08db /source/mvd_parse.c | |
parent | 10267d9ca8d73eac8e01f7a1ec1d0e27bfca4b5b (diff) |
Improved server side handling of entity relative sounds.
Reduced memory usage of MVD delta codec (currently MVDs are broken :)).
Fixed zero viewangles being sent so server is some cases (RJ scripts now work).
Added screenshotpng command, renamed screenshotJPEG to screenshotjpg.
Added gl_screenshot_compression cvar.
Fixed too large startup messages being written to client demos.
Other misc changes.
Diffstat (limited to 'source/mvd_parse.c')
-rw-r--r-- | source/mvd_parse.c | 825 |
1 files changed, 139 insertions, 686 deletions
diff --git a/source/mvd_parse.c b/source/mvd_parse.c index 738b010..7637ce4 100644 --- a/source/mvd_parse.c +++ b/source/mvd_parse.c @@ -66,135 +66,44 @@ const char *MVD_ServerCommandString( int cmd ) { return s; } -static void MVD_LinkEntity( mvd_t *mvd, entityStateEx_t *ent ) { - vec3_t mins, maxs; - cleaf_t *leafs[MAX_TOTAL_ENT_LEAFS]; - int clusters[MAX_TOTAL_ENT_LEAFS]; - int num_leafs; - int i, j; - int area; - cnode_t *topnode; - int modelindex; +static void MVD_LinkEdict( mvd_t *mvd, edict_t *ent ) { + int index; cmodel_t *cm; int x, zd, zu; - cmcache_t *cache; - - cache = mvd->cm.cache; + cmcache_t *cache = mvd->cm.cache; + if( !cache ) { return; - } + if( ent->s.solid == 31 ) { - modelindex = ent->s.modelindex; - if( modelindex < 1 || modelindex > cache->numcmodels ) { - Com_WPrintf( "MVD_LinkEntity: entity %d: " - "bad inline model index: %d\n", - ent->s.number, modelindex ); - ent->linked = qfalse; + index = ent->s.modelindex; + if( index < 1 || index > cache->numcmodels ) { + Com_WPrintf( "%s: entity %d: bad inline model index: %d\n", + __func__, ent->s.number, index ); return; } - cm = &cache->cmodels[ modelindex - 1 ]; - VectorCopy( cm->mins, mins ); - VectorCopy( cm->maxs, maxs ); + cm = &cache->cmodels[ index - 1 ]; + VectorCopy( cm->mins, ent->mins ); + VectorCopy( cm->maxs, ent->maxs ); + ent->solid = SOLID_BSP; } else if( ent->s.solid ) { x = 8 * ( ent->s.solid & 31 ); zd = 8 * ( ( ent->s.solid >> 5 ) & 31 ); zu = 8 * ( ( ent->s.solid >> 10 ) & 63 ) - 32; - mins[0] = mins[1] = -x; - maxs[0] = maxs[1] = x; - mins[2] = -zd; - maxs[2] = zu; - } else { - VectorClear( mins ); - VectorClear( maxs ); - } - -// set the abs box - if( ent->s.solid == 31 && - ( ent->s.angles[0] || ent->s.angles[1] || ent->s.angles[2] ) ) - { // expand for rotation - float max, v; - int i; - - max = 0; - for( i = 0; i < 3; i++ ) { - v = fabs( mins[i] ); - if( v > max ) - max = v; - v = fabs( maxs[i] ); - if( v > max ) - max = v; - } - for( i = 0; i < 3; i++ ) { - mins[i] = ent->s.origin[i] - max; - maxs[i] = ent->s.origin[i] + max; - } + ent->mins[0] = ent->mins[1] = -x; + ent->maxs[0] = ent->maxs[1] = x; + ent->mins[2] = -zd; + ent->maxs[2] = zu; + ent->solid = SOLID_BBOX; } else { - // normal - VectorAdd( mins, ent->s.origin, mins ); - VectorAdd( maxs, ent->s.origin, maxs ); + VectorClear( ent->mins ); + VectorClear( ent->maxs ); + ent->solid = SOLID_NOT; } - // because movement is clipped an epsilon away from an actual edge, - // we must fully check even when bounding boxes don't quite touch - mins[0] -= 1; - mins[1] -= 1; - mins[2] -= 1; - maxs[0] += 1; - maxs[1] += 1; - maxs[2] += 1; - - // link to PVS leafs - ent->num_clusters = 0; - ent->areanum = 0; - ent->areanum2 = 0; - - // get all leafs, including solids - num_leafs = CM_BoxLeafs( &mvd->cm, mins, maxs, - leafs, MAX_TOTAL_ENT_LEAFS, &topnode ); - - // set areas - for( i = 0; i < num_leafs; i++ ) { - clusters[i] = CM_LeafCluster( leafs[i] ); - area = CM_LeafArea( leafs[i] ); - if( area ) { - // doors may legally straggle two areas, - // but nothing should evern need more than that - if( ent->areanum && ent->areanum != area ) { - ent->areanum2 = area; - } else { - ent->areanum = area; - } - } - } - - if( num_leafs >= MAX_TOTAL_ENT_LEAFS ) { - // assume we missed some leafs, and mark by headnode - ent->num_clusters = -1; - ent->headnode = topnode; - } else { - ent->num_clusters = 0; - for( i = 0; i < num_leafs; i++ ) { - if( clusters[i] == -1 ) - continue; // not a visible leaf - for( j = 0; j < i; j++ ) - if( clusters[j] == clusters[i] ) - break; - if( j == i ) { - if ( ent->num_clusters == MAX_ENT_CLUSTERS ) { - // assume we missed some leafs, and mark by headnode - ent->num_clusters = -1; - ent->headnode = topnode; - break; - } - - ent->clusternums[ent->num_clusters++] = clusters[i]; - } - } - } - - ent->linked = qtrue; + SV_LinkEdict( &mvd->cm, ent ); } static void MVD_ParseEntityString( mvd_t *mvd ) { @@ -205,8 +114,6 @@ static void MVD_ParseEntityString( mvd_t *mvd ) { vec3_t origin; vec3_t angles; - mvd->spawnSet = qfalse; - if( !mvd->cm.cache ) { return; } @@ -282,27 +189,17 @@ static void MVD_ParseEntityString( mvd_t *mvd ) { if( !strcmp( classname + 12, "intermission" ) ) { VectorCopy( origin, mvd->spawnOrigin ); VectorCopy( angles, mvd->spawnAngles ); - mvd->spawnSet = qtrue; - continue; + break; } - if( mvd->spawnSet ) { - continue; - } - if( !strcmp( classname + 12, "start" ) || !strcmp( classname + 12, "deathmatch" ) ) { VectorCopy( origin, mvd->spawnOrigin ); VectorCopy( angles, mvd->spawnAngles ); - mvd->spawnSet = qtrue; } } - - if( !mvd->spawnSet ) { - Com_WPrintf( "Couldn't find spawn point for MVD spectators\n" ); - } } static void MVD_ParseMulticast( mvd_t *mvd, mvd_ops_t op, int extrabits ) { @@ -396,24 +293,24 @@ static void MVD_ParseUnicast( mvd_t *mvd, mvd_ops_t op, int extrabits ) { int clientNum, length, last; int flags; udpClient_t *client; - mvdPlayer_t *player; + mvd_player_t *player; clstate_t minstate; int i, c; char *s; qboolean gotLayout, wantLayout; - mvdConfigstring_t *cs; + mvd_cs_t *cs; length = MSG_ReadByte(); length |= extrabits << 8; clientNum = MSG_ReadByte(); if( clientNum < 0 || clientNum >= MAX_CLIENTS ) { - MVD_Destroy( mvd, "Bad unicast clientNum" ); + MVD_Destroy( mvd, "%s: bad number: %d", __func__, clientNum ); } last = msg_read.readcount + length; if( last > msg_read.cursize ) { - MVD_Destroy( mvd, "Read past end of message" ); + MVD_Destroy( mvd, "%s: read past end of message", __func__ ); } player = &mvd->players[clientNum]; @@ -424,7 +321,7 @@ static void MVD_ParseUnicast( mvd_t *mvd, mvd_ops_t op, int extrabits ) { // layouts, etc. Give up as soon as unknown command byte is encountered. while( 1 ) { if( msg_read.readcount > last ) { - MVD_Destroy( mvd, "Read past end of unicast" ); + MVD_Destroy( mvd, "%s: read past end of unicast", __func__ ); } if( msg_read.readcount == last ) { @@ -450,7 +347,7 @@ static void MVD_ParseUnicast( mvd_t *mvd, mvd_ops_t op, int extrabits ) { i = MSG_ReadShort(); s = MSG_ReadString(); if( i < 0 || i >= MAX_CONFIGSTRINGS ) { - MVD_Destroy( mvd, "bad configstring index" ); + MVD_Destroy( mvd, "%s: bad configstring index: %d", __func__, i ); } length = strlen( s ); if( length > MAX_QPATH - 1 ) { @@ -518,17 +415,14 @@ breakOut: { wantLayout = qtrue; } - if( !client->following ) { + if( !client->target ) { if( clientNum == mvd->clientNum ) { SV_ClientAddMessage( client->cl, flags ); } continue; } - if( client->followClientNum == clientNum ) { + if( client->target == player ) { SV_ClientAddMessage( client->cl, flags ); - if( client->scoreboard == SBOARD_FOLLOW ) { - wantLayout = qtrue; - } } } @@ -551,34 +445,11 @@ breakOut: SV_ClientAddMessage( client->cl, flags ); continue; } - if( client->followClientNum == clientNum && - client->scoreboard == SBOARD_FOLLOW ) - { - SV_ClientAddMessage( client->cl, flags ); - } } SZ_Clear( &msg_write ); } -static qboolean MVD_EdictPV( mvd_t *mvd, entityStateEx_t *ent, byte *mask ) { - int i, l; - - if( ent->num_clusters == -1 ) { - // too many leafs for individual check, go by headnode - return CM_HeadnodeVisible( ent->headnode, mask ); - } - - // check individual leafs - for( i = 0; i < ent->num_clusters; i++ ) { - l = ent->clusternums[i]; - if( Q_IsBitSet( mask, l ) ) { - return qtrue; - } - } - return qfalse; // not visible -} - /* MVD_ParseSound @@ -587,19 +458,8 @@ explicitly specified on entities out of client PVS, and not all clients are able to postition sounds on BSP models properly. */ static void MVD_ParseSound( mvd_t *mvd, int extrabits ) { - vec3_t origin, clientorg; - int channel, entnum, sendchan; - int flags, index; - int volume = 0, attenuation = 0, offset = 0; - entityStateEx_t *entity = NULL; - udpClient_t *client; - int i, j; - cleaf_t *leaf; - int area, cluster; - byte *mask; - mvdFrame_t *frame; - int modelindex; - cmodel_t *cm; + int flags, index; + int volume, attenuation, offset, sendchan; flags = MSG_ReadByte(); index = MSG_ReadByte(); @@ -613,107 +473,8 @@ static void MVD_ParseSound( mvd_t *mvd, int extrabits ) { // entity relative sendchan = MSG_ReadShort(); - entnum = sendchan >> 3; - if( entnum < 0 || entnum >= MAX_EDICTS ) - MVD_Destroy( mvd, "MVD_ParseSound: bad entnum %d", entnum ); - channel = sendchan & 7; - - // find this entity in frame - frame = &mvd->frames[mvd->framenum & MVD_UPDATE_MASK]; - for( i = 0; i < frame->numEntities; i++ ) { - j = ( frame->firstEntity + i ) & MVD_ENTITIES_MASK; - entity = &mvd->entityStates[j]; - if( entity->s.number == entnum ) { - break; - } - } - if( i == frame->numEntities ) { - Com_WPrintf( "MVD_ParseSound: entity %d not found in frame\n", entnum ); - return; - } - - // use the entity origin unless it is a bmodel - if( entity->s.solid == 31 ) { - modelindex = entity->s.modelindex; - if( modelindex < 1 || modelindex > mvd->cm.cache->numcmodels ) { - Com_WPrintf( "MVD_PaseSound: entity %d has bad inline model index %d\n", - entity->s.number, modelindex ); - return; - } - cm = &mvd->cm.cache->cmodels[ modelindex - 1 ]; - VectorAvg( cm->mins, cm->maxs, origin ); - VectorAdd( entity->s.origin, origin, origin ); - } else { - VectorCopy( entity->s.origin, origin ); - } - LIST_FOR_EACH( udpClient_t, client, &mvd->udpClients, entry ) { - // do not send sounds to connecting clients - if( client->cl->state != cs_spawned || client->cl->download || client->cl->nodata ) { - continue; - } - - // default client doesn't know that bmodels have weird origins - if( entity->s.solid == 31 && client->cl->protocol == PROTOCOL_VERSION_DEFAULT ) { - flags |= SND_POS; - } - - //if( entity != client->edict ) { - // get client viewpos - VectorMA( client->ps.viewoffset, 0.125f, - client->ps.pmove.origin, clientorg ); - - // PHS cull this sound - if( ( extrabits & 1 ) == 0 ) { - leaf = CM_PointLeaf( &mvd->cm, clientorg ); - area = CM_LeafArea( leaf ); - if( !CM_AreasConnected( &mvd->cm, area, entity->areanum ) ) { - // doors can legally straddle two areas, so - // we may need to check another one - if( !entity->areanum2 || !CM_AreasConnected( &mvd->cm, area, entity->areanum2 ) ) { - continue; // blocked by a door - } - } - cluster = CM_LeafCluster( leaf ); - mask = CM_ClusterPHS( &mvd->cm, cluster ); - if( !MVD_EdictPV( mvd, entity, mask ) ) { - continue; // not in PHS - } - } - - // check if position needs to be explicitly sent - if( ( flags & SND_POS ) == 0 ) { - mask = CM_FatPVS( &mvd->cm, clientorg ); - if( !MVD_EdictPV( mvd, entity, mask ) ) { - flags |= SND_POS; // not in PVS - } - } -// } - - MSG_WriteByte( svc_sound ); - MSG_WriteByte( flags ); - MSG_WriteByte( index ); - - if( flags & SND_VOLUME ) - MSG_WriteByte( volume ); - if( flags & SND_ATTENUATION ) - MSG_WriteByte( attenuation ); - if( flags & SND_OFFSET ) - MSG_WriteByte( offset ); - - MSG_WriteShort( sendchan ); - - if( flags & SND_POS ) - MSG_WritePos( origin ); - - flags &= ~SND_POS; - - if( extrabits & 2 ) { - SV_ClientAddMessage( client->cl, MSG_RELIABLE|MSG_CLEAR ); - } else { - SV_ClientAddMessage( client->cl, MSG_CLEAR ); - } - } + //PF_StartSound( ent, channel, index, volume, attenuation, offset ); } static void MVD_ParseConfigstring( mvd_t *mvd ) { @@ -724,13 +485,13 @@ static void MVD_ParseConfigstring( mvd_t *mvd ) { index = MSG_ReadShort(); if( index < 0 || index >= MAX_CONFIGSTRINGS ) { - MVD_Destroy( mvd, "Bad configstring index: %d", index ); + MVD_Destroy( mvd, "%s: bad index: %d", __func__, index ); } string = MSG_ReadStringLength( &length ); if( MAX_QPATH * index + length >= sizeof( mvd->configstrings ) ) { - MVD_Destroy( mvd, "Oversize configstring" ); + MVD_Destroy( mvd, "%s: oversize configstring: %d", __func__, index ); } if( !strcmp( mvd->configstrings[index], string ) ) { @@ -758,276 +519,94 @@ static void MVD_ParseConfigstring( mvd_t *mvd ) { Fix origin and angles on each player entity by extracting data from player state. */ -static void MVD_FixEntityStates( mvd_t *mvd, mvdFrame_t *frame ) { - entityStateEx_t *currStates[MAX_CLIENTS]; - entityStateEx_t *state; - player_state_t *ps; - int i, j; - int playerNum; - - for( i = 0; i < MAX_CLIENTS; i++ ) { - currStates[i] = NULL; - } - - for( i = 0; i < frame->numEntities; i++ ) { - j = ( frame->firstEntity + i ) & MVD_ENTITIES_MASK; - state = &mvd->entityStates[j]; - - if( state->s.number < 1 || state->s.number >= MAX_EDICTS ) { - MVD_Destroy( mvd, "Bad entity number" ); - } - - if( state->s.number <= MAX_CLIENTS ) { - currStates[ state->s.number - 1 ] = state; - } - } +static void MVD_PlayerToEntityStates( mvd_t *mvd ) { + mvd_player_t *player; + edict_t *edict; + int i; - for( i = 0; i < frame->numPlayers; i++ ) { - j = ( frame->firstPlayer + i ) & MVD_PLAYERS_MASK; - ps = &mvd->playerStates[j]; - playerNum = ps->pmove.pm_flags; - - if( ps->pmove.pm_type >= PM_DEAD ) { + for( i = 0, player = mvd->players; i < mvd->maxclients; i++, player++ ) { + if( !player->inuse ) { + continue; + } + if( player->ps.pmove.pm_type >= PM_DEAD ) { continue; } - state = currStates[playerNum]; - if( !state ) { + + edict = &mvd->edicts[ i + 1 ]; + if( !edict->inuse ) { continue; // not present in this frame } - VectorCopy( state->s.origin, state->s.old_origin ); + VectorCopy( edict->s.origin, edict->s.old_origin ); - VectorScale( ps->pmove.origin, 0.125f, state->s.origin ); - VectorCopy( ps->viewangles, state->s.angles ); + VectorScale( player->ps.pmove.origin, 0.125f, edict->s.origin ); + VectorCopy( player->ps.viewangles, edict->s.angles ); - if( state->s.angles[PITCH] > 180 ) { - state->s.angles[PITCH] -= 360; + if( edict->s.angles[PITCH] > 180 ) { + edict->s.angles[PITCH] -= 360; } - state->s.angles[PITCH] = state->s.angles[PITCH] / 3; + edict->s.angles[PITCH] = edict->s.angles[PITCH] / 3; - MVD_LinkEntity( mvd, state ); + MVD_LinkEdict( mvd, edict ); } } -/* -================== -MVD_ParseDeltaEntity -================== -*/ #define RELINK_MASK (U_MODEL|U_ORIGIN1|U_ORIGIN2|U_ORIGIN3|U_SOLID) -static inline void MVD_ParseDeltaEntity( mvd_t *mvd, - mvdFrame_t *frame, - int newnum, - entityStateEx_t *old, - int bits ) -{ - entityStateEx_t *state; - int i; - - i = mvd->nextEntityStates & MVD_ENTITIES_MASK; - state = &mvd->entityStates[i]; - mvd->nextEntityStates++; - frame->numEntities++; - - if( mvd_shownet->integer > 2 ) { - MSG_ShowDeltaEntityBits( bits ); - } - - MSG_ParseDeltaEntity( &old->s, &state->s, newnum, bits ); - - if( newnum > mvd->maxclients ) { - if( !old || !old->linked || ( bits & RELINK_MASK ) ) { - MVD_LinkEntity( mvd, state ); - } else { - state->linked = qtrue; - state->num_clusters = old->num_clusters; - state->headnode = old->headnode; - state->areanum = old->areanum; - state->areanum2 = old->areanum2; - for( i = 0; i < state->num_clusters; i++ ) { - state->clusternums[i] = old->clusternums[i]; - } - } - } -} /* ================== MVD_ParsePacketEntities ================== */ -static void MVD_ParsePacketEntities( mvd_t *mvd, - mvdFrame_t *oldframe, - mvdFrame_t *frame ) -{ - int newnum; +static void MVD_ParsePacketEntities( mvd_t *mvd ) { + int number; int bits; - entityStateEx_t *oldstate, *base; - int oldindex, oldnum; - int i; - - frame->firstEntity = mvd->nextEntityStates; - frame->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 { - i = oldframe->firstEntity + oldindex; - oldstate = &mvd->entityStates[i & MVD_ENTITIES_MASK]; - oldnum = oldstate->s.number; - } - } + edict_t *ent; while( 1 ) { - newnum = MSG_ParseEntityBits( &bits ); if( msg_read.readcount > msg_read.cursize ) { - MVD_Destroy( mvd, "Read past end of message" ); + MVD_Destroy( mvd, "%s: read past end of message", __func__ ); } - if( newnum < 0 || newnum >= MAX_EDICTS ) { - MVD_Destroy( mvd, "Bad packetentity number: %d", newnum ); + number = MSG_ParseEntityBits( &bits ); + if( number < 0 || number >= MAX_EDICTS ) { + MVD_Destroy( mvd, "%s: bad number: %d", __func__, number ); } - if( !newnum ) { + if( !number ) { break; } - while( oldnum < newnum ) { - // one or more entities from the old packet are unchanged - if( mvd_shownet->integer > 2 ) { - Com_Printf( " unchanged: %i\n", oldnum ); - } - MVD_ParseDeltaEntity( mvd, frame, oldnum, oldstate, 0 ); - - oldindex++; - - if( oldindex >= oldframe->numEntities ) { - oldnum = 99999; - } else { - i = oldframe->firstEntity + oldindex; - oldstate = &mvd->entityStates[i & MVD_ENTITIES_MASK]; - oldnum = oldstate->s.number; - } - } + ent = &mvd->edicts[number]; if( bits & U_REMOVE ) { - // the entity present in oldframe is not in the current frame - if( mvd_shownet->integer > 2 ) { - Com_Printf( " remove: %i\n", newnum ); - } - if( oldnum != newnum ) { - Com_DPrintf( "U_REMOVE: oldnum != newnum\n" ); - } - if( !oldframe ) { - MVD_Destroy( mvd, "U_REMOVE: NULL oldframe" ); - } - - oldindex++; - - if( oldindex >= oldframe->numEntities ) { - oldnum = 99999; - } else { - i = oldframe->firstEntity + oldindex; - oldstate = &mvd->entityStates[i & MVD_ENTITIES_MASK]; - oldnum = oldstate->s.number; - } - continue; - } - - if( oldnum == newnum ) { - // delta from previous state if( mvd_shownet->integer > 2 ) { - Com_Printf( " delta: %i ", newnum ); - } - MVD_ParseDeltaEntity( mvd, frame, newnum, oldstate, bits ); - if( mvd_shownet->integer > 2 ) { - Com_Printf( "\n" ); - } - - oldindex++; - - if( oldindex >= oldframe->numEntities ) { - oldnum = 99999; - } else { - i = oldframe->firstEntity + oldindex; - oldstate = &mvd->entityStates[i & MVD_ENTITIES_MASK]; - oldnum = oldstate->s.number; + Com_Printf( " remove: %d\n", number ); } + ent->inuse = qfalse; continue; } - if( oldnum > newnum ) { - // delta from baseline - if( mvd_shownet->integer > 2 ) { - Com_Printf( " baseline: %i ", newnum ); - } - base = mvd->baselines[newnum >> SV_BASELINES_SHIFT]; - if( base ) { - base += newnum & SV_BASELINES_MASK; - } - MVD_ParseDeltaEntity( mvd, frame, newnum, base, bits ); - if( mvd_shownet->integer > 2 ) { - Com_Printf( "\n" ); - } - 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( mvd_shownet->integer > 2 ) { - Com_Printf( " unchanged: %i\n", oldnum ); - } - MVD_ParseDeltaEntity( mvd, frame, oldnum, oldstate, 0 ); - - oldindex++; - - if( oldindex >= oldframe->numEntities ) { - oldnum = 99999; - } else { - i = oldframe->firstEntity + oldindex; - oldstate = &mvd->entityStates[i & MVD_ENTITIES_MASK]; - oldnum = oldstate->s.number; - } - } -} + if( mvd_shownet->integer > 2 ) { + Com_Printf( " %s: %d ", ent->inuse ? + "delta" : "baseline", number ); + MSG_ShowDeltaEntityBits( bits ); + Com_Printf( "\n" ); + } -/* -================== -MVD_ParseDeltaPlayer -================== -*/ -static inline void MVD_ParseDeltaPlayer( mvd_t *mvd, - mvdFrame_t *frame, - int newnum, - player_state_t *old, - int bits ) -{ - player_state_t *state; - int i; + MSG_ParseDeltaEntity( &ent->s, &ent->s, number, bits ); - i = mvd->nextPlayerStates & MVD_PLAYERS_MASK; - state = &mvd->playerStates[i]; - mvd->nextPlayerStates++; - frame->numPlayers++; + ent->inuse = qtrue; + if( number >= mvd->pool.num_edicts ) { + mvd->pool.num_edicts = number + 1; + } - if( mvd_shownet->integer > 2 ) { - MSG_ShowDeltaPlayerstateBits_Packet( bits ); + if( number > mvd->maxclients && ( bits & RELINK_MASK ) ) { + MVD_LinkEdict( mvd, ent ); + } } - MSG_ParseDeltaPlayerstate_Packet( old, state, bits ); - - // save player number - state->pmove.pm_flags = newnum; } /* @@ -1035,144 +614,48 @@ static inline void MVD_ParseDeltaPlayer( mvd_t *mvd, MVD_ParsePacketPlayers ================== */ -static void MVD_ParsePacketPlayers( mvd_t *mvd, - mvdFrame_t *oldframe, - mvdFrame_t *frame ) -{ - int newnum; +static void MVD_ParsePacketPlayers( mvd_t *mvd ) { + int number; int bits; - player_state_t *oldstate; - int oldindex, oldnum; - int i; - - frame->firstPlayer = mvd->nextPlayerStates; - frame->numPlayers = 0; - - // delta from the players present in oldframe - oldindex = 0; - oldstate = NULL; - if( !oldframe ) { - oldnum = 99999; - } else { - if( oldindex >= oldframe->numPlayers ) { - oldnum = 99999; - } else { - i = oldframe->firstPlayer + oldindex; - oldstate = &mvd->playerStates[i & MVD_PLAYERS_MASK]; - oldnum = PPS_NUM( oldstate ); - } - } + mvd_player_t *player; while( 1 ) { - newnum = MSG_ReadByte(); if( msg_read.readcount > msg_read.cursize ) { - MVD_Destroy( mvd, "Read past end of message" ); - } - - if( newnum < 0 || newnum >= MAX_CLIENTS ) { - MVD_Destroy( mvd, "Bad packetplayer number: %d", newnum ); + MVD_Destroy( mvd, "%s: read past end of message", __func__ ); } - if( newnum == CLIENTNUM_NONE ) { + number = MSG_ReadByte(); + if( number == CLIENTNUM_NONE ) { break; } - bits = MSG_ReadShort(); - - while( oldnum < newnum ) { - // one or more players from the old packet are unchanged - if( mvd_shownet->integer > 2 ) { - Com_Printf( " unchanged: %i\n", oldnum ); - } - MVD_ParseDeltaPlayer( mvd, frame, oldnum, oldstate, 0 ); - - oldindex++; - - if( oldindex >= oldframe->numPlayers ) { - oldnum = 99999; - } else { - i = oldframe->firstPlayer + oldindex; - oldstate = &mvd->playerStates[i & MVD_PLAYERS_MASK]; - oldnum = PPS_NUM( oldstate ); - } + if( number < 0 || number >= mvd->maxclients ) { + MVD_Destroy( mvd, "%s: bad number: %d", __func__, number ); } - if( bits & PPS_REMOVE ) { - // the player present in oldframe is not in the current frame - if( mvd_shownet->integer > 2 ) { - Com_Printf( " remove: %i\n", newnum ); - } - if( oldnum != newnum ) { - Com_DPrintf( "PPS_REMOVE: oldnum != newnum\n" ); - } - if( !oldframe ) { - MVD_Destroy( mvd, "PPS_REMOVE: NULL oldframe" ); - } - - oldindex++; + player = &mvd->players[number]; - if( oldindex >= oldframe->numPlayers ) { - oldnum = 99999; - } else { - i = oldframe->firstPlayer + oldindex; - oldstate = &mvd->playerStates[i & MVD_PLAYERS_MASK]; - oldnum = PPS_NUM( oldstate ); - } - continue; - } + bits = MSG_ReadShort(); - if( oldnum == newnum ) { - // delta from previous state - if( mvd_shownet->integer > 2 ) { - Com_Printf( " delta: %i ", newnum ); - } - MVD_ParseDeltaPlayer( mvd, frame, newnum, oldstate, bits ); + if( bits & PPS_REMOVE ) { if( mvd_shownet->integer > 2 ) { - Com_Printf( "\n" ); - } - - oldindex++; - - if( oldindex >= oldframe->numPlayers ) { - oldnum = 99999; - } else { - i = oldframe->firstPlayer + oldindex; - oldstate = &mvd->playerStates[i & MVD_PLAYERS_MASK]; - oldnum = PPS_NUM( oldstate ); + Com_Printf( " remove: %d\n", number ); } + player->inuse = qfalse; continue; } - if( oldnum > newnum ) { - // delta from baseline - if( mvd_shownet->integer > 2 ) { - Com_Printf( " baseline: %i ", newnum ); - } - MVD_ParseDeltaPlayer( mvd, frame, newnum, NULL, bits ); - if( mvd_shownet->integer > 2 ) { - Com_Printf( "\n" ); - } - continue; - } + if( mvd_shownet->integer > 2 ) { + Com_Printf( " %s: %d ", player->inuse ? + "delta" : "baseline", number ); + MSG_ShowDeltaPlayerstateBits_Packet( bits ); + Com_Printf( "\n" ); + } - } + MSG_ParseDeltaPlayerstate_Packet( &player->ps, &player->ps, bits ); - while( oldnum != 99999 ) { - if( mvd_shownet->integer > 2 ) { - Com_Printf( " unchanged: %i\n", oldnum ); - } - MVD_ParseDeltaPlayer( mvd, frame, oldnum, oldstate, 0 ); - - oldindex++; - - if( oldindex >= oldframe->numPlayers ) { - oldnum = 99999; - } else { - i = oldframe->firstPlayer + oldindex; - oldstate = &mvd->playerStates[i & MVD_PLAYERS_MASK]; - oldnum = PPS_NUM( oldstate ); - } - } + player->inuse = qtrue; + } } /* @@ -1180,32 +663,17 @@ static void MVD_ParsePacketPlayers( mvd_t *mvd, MVD_ParseFrame ================ */ -static void MVD_ParseFrame( mvd_t *mvd, qboolean delta ) { - mvdFrame_t *oldframe, *frame; +static void MVD_ParseFrame( mvd_t *mvd ) { int length; - // allocate new frame - frame = &mvd->frames[++mvd->framenum & MVD_UPDATE_MASK]; - frame->serverFrame = MSG_ReadLong(); - frame->number = mvd->framenum; - - if( delta ) { - oldframe = &mvd->frames[( mvd->framenum - 1 ) & MVD_UPDATE_MASK]; - if( oldframe->number != mvd->framenum - 1 ) { - MVD_Destroy( mvd, "Delta from invalid frame" ); - } - } else { - oldframe = NULL; // uncompressed frame - } - // read portalbits length = MSG_ReadByte(); if( length ) { if( length < 0 || msg_read.readcount + length > msg_read.cursize ) { - MVD_Destroy( mvd, "Read past end of message" ); + MVD_Destroy( mvd, "%s: read past end of message", __func__ ); } if( length > MAX_MAP_AREAS/8 ) { - MVD_Destroy( mvd, "Bad portalbits length" ); + MVD_Destroy( mvd, "%s: bad portalbits length: %d", __func__, length ); } CM_SetPortalStates( &mvd->cm, msg_read.data + msg_read.readcount, length ); @@ -1218,28 +686,27 @@ static void MVD_ParseFrame( mvd_t *mvd, qboolean delta ) { Com_Printf( "%3i:playerinfo\n", msg_read.readcount - 1 ); } - MVD_ParsePacketPlayers( mvd, oldframe, frame ); + MVD_ParsePacketPlayers( mvd ); if( mvd_shownet->integer > 1 ) { Com_Printf( "%3i:packetentities\n", msg_read.readcount - 1 ); } - MVD_ParsePacketEntities( mvd, oldframe, frame ); + MVD_ParsePacketEntities( mvd ); if( mvd_shownet->integer > 1 ) { - Com_Printf( "%3i: frame:%i delta:%i\n", - msg_read.readcount - 1, mvd->framenum, delta ); + Com_Printf( "%3i: frame:%i\n", msg_read.readcount - 1, mvd->framenum ); } - MVD_FixEntityStates( mvd, frame ); + MVD_PlayerToEntityStates( mvd ); + + mvd->framenum++; } static void MVD_ParseServerData( mvd_t *mvd ) { - int protocol, clientNum; + int protocol; int length, index; char *gamedir, *string; - entityStateEx_t *base, **chunk; - int entnum, bits; uint32 checksum; // clear the leftover from previous level @@ -1260,11 +727,7 @@ static void MVD_ParseServerData( mvd_t *mvd ) { mvd->servercount = MSG_ReadLong(); gamedir = MSG_ReadString(); - clientNum = MSG_ReadShort(); - if( clientNum < 0 || clientNum >= MAX_CLIENTS ) { - MVD_Destroy( mvd, "Invalid client num: %d", clientNum ); - } - mvd->clientNum = clientNum; + mvd->clientNum = MSG_ReadShort(); // change gamedir unless playing a demo Q_strncpyz( mvd->gamedir, gamedir, sizeof( mvd->gamedir ) ); @@ -1299,8 +762,26 @@ static void MVD_ParseServerData( mvd_t *mvd ) { } } - mvd->maxclients = atoi( mvd->configstrings[CS_MAXCLIENTS] ); + // parse maxclients + index = atoi( mvd->configstrings[CS_MAXCLIENTS] ); + if( index < 1 || index > MAX_CLIENTS ) { + MVD_Destroy( mvd, "Invalid maxclients" ); + } + if( !mvd->players ) { + mvd->players = MVD_Malloc( sizeof( mvd_player_t ) * index ); + mvd->maxclients = index; + } else if( index != mvd->maxclients ) { + MVD_Destroy( mvd, "Unexpected maxclients change" ); + } + + // validate clientNum + if( mvd->clientNum < 0 || mvd->clientNum >= mvd->maxclients ) { + MVD_Destroy( mvd, "Invalid client num: %d", mvd->clientNum ); + } + mvd->dummy = mvd->players + mvd->clientNum; + + // parse world model string = mvd->configstrings[ CS_MODELS + 1]; length = strlen( string ); if( length <= 9 ) { @@ -1320,37 +801,8 @@ static void MVD_ParseServerData( mvd_t *mvd ) { // get the spawn point for spectators MVD_ParseEntityString( mvd ); - // parse baselines - while( 1 ) { - entnum = MSG_ParseEntityBits( &bits ); - if( !entnum ) { - break; - } - - if( entnum < 0 || entnum >= MAX_EDICTS ) { - MVD_Destroy( mvd, "Bad baseline number: %d", entnum ); - } - - chunk = &mvd->baselines[entnum >> SV_BASELINES_SHIFT]; - if( *chunk == NULL ) { - *chunk = MVD_Mallocz( sizeof( *base ) * SV_BASELINES_PER_CHUNK ); - } - - base = *chunk + ( entnum & SV_BASELINES_MASK ); - MSG_ParseDeltaEntity( NULL, &base->s, entnum, bits ); - - MVD_LinkEntity( mvd, base ); - - if( msg_read.readcount > msg_read.cursize ) { - MVD_Destroy( mvd, "Read past end of message" ); - } - } - - // parse uncompressed frame - if( MSG_ReadByte() != mvd_frame_nodelta ) { - MVD_Destroy( mvd, "Expected uncompressed frame" ); - } - MVD_ParseFrame( mvd, qfalse ); + // parse baseline frame + MVD_ParseFrame( mvd ); if( mvd->state < MVD_WAITING ) { List_Append( &mvd_ready, &mvd->ready ); @@ -1458,11 +910,12 @@ static qboolean MVD_ParseMessage( mvd_t *mvd, fifo_t *fifo ) { MVD_ParseConfigstring( mvd ); break; case mvd_frame: - MVD_ParseFrame( mvd, qtrue ); - break; - case mvd_frame_nodelta: - MVD_ParseFrame( mvd, qfalse ); + MVD_ParseFrame( mvd ); break; + //case mvd_frame_nodelta: + //MVD_ResetFrame( mvd ); + //MVD_ParseFrame( mvd ); + //break; case mvd_sound: MVD_ParseSound( mvd, extrabits ); break; |