@@ -1795,6 +1795,7 @@ static inline void DoTransmitPVSCheck(edict_t* pEdict, CBaseEntity* pEnt, const
17951795 }
17961796}
17971797
1798+ static ConVar networking_verifyshit (" holylib_networking_verifyshit" , " 1" , 0 , " Experimental" );
17981799static ConVar networking_fastpath (" holylib_networking_fastpath" , " 0" , 0 , " Experimental - If two players are in the same area, then it will reuse the transmit state of the first calculated player saving a lot of time" );
17991800static ConVar networking_fastpath_usecluster (" holylib_networking_fastpath_usecluster" , " 1" , 0 , " Experimental - When using the fastpatth, it will compate against clients in the same cluster instead of area" );
18001801bool New_CServerGameEnts_CheckTransmit (IServerGameEnts* gameents, CCheckTransmitInfo *pInfo, const unsigned short *pEdictIndices, int nEdicts)
@@ -2085,15 +2086,112 @@ bool New_CServerGameEnts_CheckTransmit(IServerGameEnts* gameents, CCheckTransmit
20852086#endif
20862087
20872088#if 1 // I don't like this, useful for testing but not for actual prod
2088- for ( int i= 0 ; i<MAX_EDICTS; ++i )
2089+ if (networking_verifyshit. GetBool () )
20892090 {
2090- if (pInfo->m_pTransmitEdict ->IsBitSet (i) && !g_pEntityCache[i])
2091- { // g_pEntityCache is basically just a quicker form of (CBaseEntity*)(&world_edict[i])->GetUnknown();
2092- Warning (PROJECT_NAME " - networking: Tried to network an Entity that does not exist! (%i)\n " , i);
2093- pInfo->m_pTransmitEdict ->Clear (i);
2094- if (bIsHLTV)
2095- pInfo->m_pTransmitAlways ->Clear (i);
2091+ for (int i=0 ; i<MAX_EDICTS; ++i)
2092+ {
2093+ if (pInfo->m_pTransmitEdict ->IsBitSet (i) && !g_pEntityCache[i])
2094+ { // g_pEntityCache is basically just a quicker form of (CBaseEntity*)(&world_edict[i])->GetUnknown();
2095+ Warning (PROJECT_NAME " - networking: Tried to network an Entity that does not exist! (%i)\n " , i);
2096+ pInfo->m_pTransmitEdict ->Clear (i);
2097+ if (bIsHLTV)
2098+ pInfo->m_pTransmitAlways ->Clear (i);
2099+ }
20962100 }
2101+
2102+ CBitVec<MAX_EDICTS> pCurrentTransmit;
2103+ pInfo->m_pTransmitEdict ->CopyTo (&pCurrentTransmit);
2104+ pInfo->m_pTransmitEdict ->ClearAll ();
2105+
2106+ // Now we do a second transmit to compare against.
2107+
2108+ for ( int i=0 ; i < nEdicts; ++i )
2109+ {
2110+ int iEdict = pEdictIndices[i];
2111+
2112+ edict_t *pEdict = &world_edict[iEdict]; // world_edict is already cached.
2113+ // Assert( pEdict == engine->PEntityOfEntIndex( iEdict ) );
2114+ int nFlags = pEdict->m_fStateFlags & (FL_EDICT_DONTSEND|FL_EDICT_ALWAYS|FL_EDICT_PVSCHECK|FL_EDICT_FULLCHECK);
2115+
2116+ if ( iEdict == clientEntIndex )
2117+ {
2118+ pInfo->m_pTransmitEdict ->CopyTo (&pClientCache);
2119+ bWasTransmitToPlayer = true ;
2120+ } else if ( bWasTransmitToPlayer ) {
2121+ // We Xor it so that the pClientCache contains all bits / entities
2122+ // that were sent specifically to our client in it's transmit check.
2123+ pInfo->m_pTransmitEdict ->Xor (pClientCache, &pClientCache);
2124+ bWasTransmitToPlayer = false ;
2125+ }
2126+
2127+ // entity needs no transmit
2128+ if ( nFlags & FL_EDICT_DONTSEND )
2129+ continue ;
2130+
2131+ // entity is already marked for sending
2132+ if ( pInfo->m_pTransmitEdict ->Get ( iEdict ) )
2133+ continue ;
2134+
2135+ if ( g_pDontTransmitCache.Get (iEdict) ) // Implements gmod's SetPreventTransmit but far faster.
2136+ continue ;
2137+
2138+ if ( nFlags & FL_EDICT_ALWAYS )
2139+ {
2140+ // FIXME: Hey! Shouldn't this be using SetTransmit so as
2141+ // to also force network down dependent entities?
2142+ while ( true )
2143+ {
2144+ // mark entity for sending
2145+ pInfo->m_pTransmitEdict ->Set ( iEdict );
2146+ // g_pGlobalTransmitTickCache.g_pAlwaysTransmitCacheBitVec.Set( iEdict );
2147+
2148+ if ( bIsHLTV )
2149+ pInfo->m_pTransmitAlways ->Set ( iEdict );
2150+
2151+ CCServerNetworkProperty *pEnt = static_cast <CCServerNetworkProperty*>( pEdict->GetNetworkable () );
2152+ if ( !pEnt )
2153+ break ;
2154+
2155+ CCServerNetworkProperty *pParent = pEnt->GetNetworkParent ();
2156+ if ( !pParent )
2157+ break ;
2158+
2159+ pEdict = pParent->edict ();
2160+ iEdict = pEdict->m_EdictIndex ;
2161+ }
2162+ continue ;
2163+ }
2164+
2165+ // FIXME: Would like to remove all dependencies
2166+ CBaseEntity *pEnt = g_pEntityCache[iEdict];
2167+ if ( nFlags == FL_EDICT_FULLCHECK )
2168+ {
2169+ // do a full ShouldTransmit() check, may return FL_EDICT_CHECKPVS
2170+ nFlags = pEnt->ShouldTransmit ( pInfo );
2171+
2172+ if ( nFlags & FL_EDICT_ALWAYS )
2173+ {
2174+ pEnt->SetTransmit ( pInfo, true );
2175+ // g_pAlwaysTransmitCacheBitVec.Set( iEdict ); We do NOT do this since view models and such would also be included.
2176+ continue ;
2177+ }
2178+ }
2179+
2180+ // don't send this entity
2181+ if ( !( nFlags & FL_EDICT_PVSCHECK ) )
2182+ continue ;
2183+
2184+ DoTransmitPVSCheck (pEdict, pEnt, bIsHLTV, pInfo, bForceTransmit, skyBoxArea);
2185+ }
2186+
2187+ for (int i=0 ; i<MAX_EDICTS; ++i)
2188+ {
2189+ if (pCurrentTransmit.IsBitSet (i) != pInfo->m_pTransmitEdict ->IsBitSet (i))
2190+ Msg (PROJECT_NAME " - networking: Entity failed our transmit code! Index %i (State: %i)\n " , i, (&world_edict[i])->m_fStateFlags & (FL_EDICT_DONTSEND|FL_EDICT_ALWAYS|FL_EDICT_PVSCHECK|FL_EDICT_FULLCHECK));
2191+ }
2192+
2193+ // Use OUR transmit!
2194+ pCurrentTransmit.CopyTo (pInfo->m_pTransmitEdict );
20972195 }
20982196#endif
20992197
0 commit comments