/* * TVM_ShutdownRelay */ void TVM_ShutdownRelay( tvm_relay_t *relay ) { assert( relay ); TVM_Printf( "==== TVM_ShutdownRelay ====\n" ); TVM_Free( relay ); }
/* * TVM_Init * * This will be called when the dll is first loaded */ void TVM_Init( const char *game, unsigned int maxclients ) { TVM_Printf( "==== TVM_Init ====\n" ); developer = trap_Cvar_Get( "developer", "0", 0 ); // chase cam mode for spawning specs, 'carriers' by default tv_chasemode = trap_Cvar_Get( "tv_chasemode", "6", 0 ); memset( &tvm, 0, sizeof( tvm ) ); tvm.maxclients = maxclients; }
/* * TVM_InitRelay */ tvm_relay_t *TVM_InitRelay( relay_t *relay_server, unsigned int snapFrameTime, int playernum ) { tvm_relay_t *relay; int i; assert( playernum >= -1 && playernum < MAX_CLIENTS ); TVM_Printf( "==== TVM_InitRelay ====\n" ); relay = TVM_Malloc( relay_server, sizeof( tvm_relay_t ) ); relay->server = relay_server; relay->playernum = playernum; relay->snapFrameTime = snapFrameTime; // initialize all entities for this game relay->maxentities = MAX_EDICTS; relay->maxclients = MAX_CLIENTS; relay->edicts = TVM_Malloc( relay_server, relay->maxentities * sizeof( relay->edicts[0] ) ); relay->clients = TVM_Malloc( relay_server, relay->maxclients * sizeof( relay->clients[0] ) ); relay->numentities = 0; // set relay for( i = 0; i < relay->maxentities; i++ ) relay->edicts[i].relay = relay; trap_LocateEntities( relay, relay->edicts, sizeof( relay->edicts[0] ), relay->numentities, relay->maxentities ); // initialize local entities relay->local_maxentities = MAX_EDICTS; relay->local_maxclients = tvm.maxclients; relay->local_edicts = TVM_Malloc( relay_server, relay->local_maxentities * sizeof( relay->local_edicts[0] ) ); relay->local_clients = TVM_Malloc( relay_server, relay->local_maxclients * sizeof( relay->local_clients[0] ) ); relay->local_numentities = relay->local_maxclients; // set relay and local for( i = 0; i < relay->local_maxentities; i++ ) { relay->local_edicts[i].local = true; relay->local_edicts[i].relay = relay; } // set client fields on player ents for( i = 0; i < relay->local_maxclients; i++ ) relay->local_edicts[i].r.client = relay->local_clients + i; trap_LocateLocalEntities( relay, relay->local_edicts, sizeof( relay->local_edicts[0] ), relay->local_numentities, relay->local_maxclients ); return relay; }
/* * TVM_Shutdown */ void TVM_Shutdown( void ) { TVM_Printf( "==== TVM_Shutdown ====\n" ); }
void GClip_LinkEntity( tvm_relay_t *relay, edict_t *ent ) { int leafs[MAX_TOTAL_ENT_LEAFS]; int clusters[MAX_TOTAL_ENT_LEAFS]; int num_leafs; int i, j; int area; int topnode; if( ent->r.area.prev ) GClip_UnlinkEntity( relay, ent ); // unlink from old position if( ent == ent->relay->edicts ) return; // don't add the world if( !ent->r.inuse ) return; // set the size VectorSubtract( ent->r.maxs, ent->r.mins, ent->r.size ); // set the abs box if( ent->s.solid == SOLID_BMODEL && ( ent->s.angles[0] || ent->s.angles[1] || ent->s.angles[2] ) ) { // expand for rotation float radius; radius = RadiusFromBounds( ent->r.mins, ent->r.maxs ); for( i = 0; i < 3; i++ ) { ent->r.absmin[i] = ent->s.origin[i] - radius; ent->r.absmax[i] = ent->s.origin[i] + radius; } } else { // normal VectorAdd( ent->s.origin, ent->r.mins, ent->r.absmin ); VectorAdd( ent->s.origin, ent->r.maxs, ent->r.absmax ); } // because movement is clipped an epsilon away from an actual edge, // we must fully check even when bounding boxes don't quite touch ent->r.absmin[0] -= 1; ent->r.absmin[1] -= 1; ent->r.absmin[2] -= 1; ent->r.absmax[0] += 1; ent->r.absmax[1] += 1; ent->r.absmax[2] += 1; // link to PVS leafs ent->r.num_clusters = 0; ent->r.areanum = ent->r.areanum2 = -1; // get all leafs, including solids num_leafs = trap_CM_BoxLeafnums( relay, ent->r.absmin, ent->r.absmax, leafs, MAX_TOTAL_ENT_LEAFS, &topnode ); // set areas for( i = 0; i < num_leafs; i++ ) { clusters[i] = trap_CM_LeafCluster( relay, leafs[i] ); area = trap_CM_LeafArea( relay, leafs[i] ); if( area > -1 ) { // doors may legally straggle two areas, // but nothing should ever need more than that if( ent->r.areanum > -1 && ent->r.areanum != area ) { if( ent->r.areanum2 > -1 && ent->r.areanum2 != area ) { TVM_Printf( "Object touching 3 areas at %f %f %f\n", ent->r.absmin[0], ent->r.absmin[1], ent->r.absmin[2] ); } ent->r.areanum2 = area; } else ent->r.areanum = area; } } if( num_leafs >= MAX_TOTAL_ENT_LEAFS ) { // assume we missed some leafs, and mark by headnode ent->r.num_clusters = -1; ent->r.headnode = topnode; } else { ent->r.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->r.num_clusters == MAX_ENT_CLUSTERS ) { // assume we missed some leafs, and mark by headnode ent->r.num_clusters = -1; ent->r.headnode = topnode; break; } ent->r.clusternums[ent->r.num_clusters++] = clusters[i]; } } } // if first time, make sure old_origin is valid if( !ent->r.linkcount && !( ent->r.svflags & SVF_TRANSMITORIGIN2 ) ) { VectorCopy( ent->s.origin, ent->s.old_origin ); //ent->olds = ent->s; } ent->r.linkcount++; }