SendProp SendPropQuaternion( const char *pVarName, int offset, int sizeofVar, int nBits, // Number of bits to use when encoding. int flags, float fLowValue, // For floating point, low and high values. float fHighValue, // High value. If HIGH_DEFAULT, it's (1<<nBits). SendVarProxyFn varProxy ) { SendProp ret; if(varProxy == SendProxy_QuaternionToQuaternion) { Assert(sizeofVar == sizeof(Quaternion)); } if ( nBits == 32 ) flags |= SPROP_NOSCALE; ret.m_Type = DPT_Quaternion; ret.m_pVarName = pVarName; ret.SetOffset( offset ); ret.m_nBits = nBits; ret.SetFlags( flags ); ret.m_fLowValue = fLowValue; ret.m_fHighValue = fHighValue; ret.m_fHighLowMul = AssignRangeMultiplier( ret.m_nBits, ret.m_fHighValue - ret.m_fLowValue ); ret.SetProxyFn( varProxy ); if( ret.GetFlags() & (SPROP_COORD | SPROP_NOSCALE | SPROP_NORMAL | SPROP_COORD_MP | SPROP_COORD_MP_LOWPRECISION | SPROP_COORD_MP_INTEGRAL) ) ret.m_nBits = 0; return ret; }
bool UTIL_FindInSendTable(SendTable *pTable, const char *name, sm_sendprop_info_t *info, unsigned int offset) { const char *pname; int props = pTable->GetNumProps(); SendProp *prop; for (int i=0; i<props; i++) { prop = pTable->GetProp(i); pname = prop->GetName(); if (pname && strcmp(name, pname) == 0) { info->prop = prop; info->actual_offset = offset + info->prop->GetOffset(); return true; } if (prop->GetDataTable()) { if (UTIL_FindInSendTable(prop->GetDataTable(), name, info, offset + prop->GetOffset()) ) { return true; } } } return false; }
void SendTable_PrintStats( void ) { int numTables = 0; int numFloats = 0; int numStrings = 0; int numArrays = 0; int numInts = 0; int numVecs = 0; int numSubTables = 0; int numSendProps = 0; int numFlatProps = 0; int numExcludeProps = 0; for ( int i=0; i < g_SendTables.Count(); i++ ) { SendTable *st = g_SendTables[i]; numTables++; numSendProps += st->GetNumProps(); numFlatProps += st->m_pPrecalc->GetNumProps(); for ( int j=0; j < st->GetNumProps(); j++ ) { SendProp* sp = st->GetProp( j ); if ( sp->IsExcludeProp() ) { numExcludeProps++; continue; // no real sendprops } if ( sp->IsInsideArray() ) continue; switch( sp->GetType() ) { case DPT_Int : numInts++; break; case DPT_Float : numFloats++; break; case DPT_Vector : numVecs++; break; case DPT_String : numStrings++; break; case DPT_Array : numArrays++; break; case DPT_DataTable : numSubTables++; break; } } } Msg("Total Send Table stats\n"); Msg("Send Tables : %i\n", numTables ); Msg("Send Props : %i\n", numSendProps ); Msg("Flat Props : %i\n", numFlatProps ); Msg("Int Props : %i\n", numInts ); Msg("Float Props : %i\n", numFloats ); Msg("Vector Props: %i\n", numVecs ); Msg("String Props: %i\n", numStrings ); Msg("Array Props : %i\n", numArrays ); Msg("Table Props : %i\n", numSubTables ); Msg("Exclu Props : %i\n", numExcludeProps ); }
// ============================================================================ // >> HELPER FUNCTIONS // ============================================================================ SendTable* GetNextSendTable(SendTable* pTable) { for (int i=0; i < pTable->GetNumProps(); ++i) { SendProp* pProp = pTable->GetProp(i); if (strcmp(pProp->GetName(), "baseclass") != 0) continue; return pProp->GetDataTable(); } return NULL; }
SendProp SendPropExclude( char *pDataTableName, // Data table name (given to BEGIN_SEND_TABLE and BEGIN_RECV_TABLE). char *pPropName // Name of the property to exclude. ) { SendProp ret; ret.SetFlags( SPROP_EXCLUDE ); ret.m_pExcludeDTName = pDataTableName; ret.m_pVarName = pPropName; return ret; }
void Array_SkipProp( const SendProp *pProp, bf_read *pIn ) { SendProp *pArrayProp = pProp->GetArrayProp(); AssertMsg( pArrayProp, ("Array_SkipProp: missing m_pArrayProp for a property.") ); int nElements = pIn->ReadUBitLong( pProp->GetNumArrayLengthBits() ); for ( int i=0; i < nElements; i++ ) { // skip over data g_PropTypeFns[pArrayProp->GetType()].SkipProp( pArrayProp, pIn ); } }
static cell_t GetTeamClientCount(IPluginContext *pContext, const cell_t *params) { int teamindex = params[1]; if (teamindex >= (int)g_Teams.size() || !g_Teams[teamindex].ClassName) { return pContext->ThrowNativeError("Team index %d is invalid", teamindex); } SendProp *pProp = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "\"player_array\""); ArrayLengthSendProxyFn fn = pProp->GetArrayLengthProxy(); return fn(g_Teams[teamindex].pEnt, 0); }
SendProp SendPropFloat( const char *pVarName, // Variable name. int offset, // Offset into container structure. int sizeofVar, int nBits, // Number of bits to use when encoding. int flags, float fLowValue, // For floating point, low and high values. float fHighValue, // High value. If HIGH_DEFAULT, it's (1<<nBits). SendVarProxyFn varProxy ) { SendProp ret; if ( varProxy == SendProxy_FloatToFloat ) { Assert( sizeofVar == 0 || sizeofVar == 4 ); } if ( nBits <= 0 || nBits == 32 ) { flags |= SPROP_NOSCALE; fLowValue = 0.f; fHighValue = 0.f; } else { if(fHighValue == HIGH_DEFAULT) fHighValue = (1 << nBits); if (flags & SPROP_ROUNDDOWN) fHighValue = fHighValue - ((fHighValue - fLowValue) / (1 << nBits)); else if (flags & SPROP_ROUNDUP) fLowValue = fLowValue + ((fHighValue - fLowValue) / (1 << nBits)); } ret.m_Type = DPT_Float; ret.m_pVarName = pVarName; ret.SetOffset( offset ); ret.m_nBits = nBits; ret.SetFlags( flags ); ret.m_fLowValue = fLowValue; ret.m_fHighValue = fHighValue; ret.m_fHighLowMul = AssignRangeMultiplier( ret.m_nBits, ret.m_fHighValue - ret.m_fLowValue ); ret.SetProxyFn( varProxy ); if( ret.GetFlags() & (SPROP_COORD | SPROP_NOSCALE | SPROP_NORMAL | SPROP_COORD_MP | SPROP_COORD_MP_LOWPRECISION | SPROP_COORD_MP_INTEGRAL ) ) ret.m_nBits = 0; return ret; }
void DataTable_ClearWriteFlags_R( SendTable *pTable ) { pTable->SetWriteFlag( false ); for(int i=0; i < pTable->m_nProps; i++) { SendProp *pProp = &pTable->m_pProps[i]; if( pProp->m_Type == DPT_DataTable ) { DataTable_ClearWriteFlags_R( pProp->GetDataTable() ); } } }
CTeamplayRoundBasedRules *GetTeamplayRoundBasedGameRulesPointer() { SendProp *pSendProp = SCHelpers::GetPropFromClassAndTable( "CTFGameRulesProxy", "DT_TeamplayRoundBasedRulesProxy", "teamplayroundbased_gamerules_data" ); if ( pSendProp ) { SendTableProxyFn proxyfn = pSendProp->GetDataTableProxyFn(); if ( proxyfn ) { CSendProxyRecipients recp; void *pGameRules = proxyfn( NULL, NULL, NULL, &recp, 0 ); return reinterpret_cast<CTeamplayRoundBasedRules*>(pGameRules); } } return NULL; }
// Calls DataTable_MaybeWriteSendTable recursively. void DataTable_MaybeWriteSendTableBuffer_R( SendTable *pTable, bf_write *pBuf ) { DataTable_MaybeWriteSendTableBuffer( pTable, pBuf, false ); // Make sure we send child send tables.. for(int i=0; i < pTable->m_nProps; i++) { SendProp *pProp = &pTable->m_pProps[i]; if( pProp->m_Type == DPT_DataTable ) { DataTable_MaybeWriteSendTableBuffer_R( pProp->GetDataTable(), pBuf ); } } }
void DataTable_MaybeCreateReceiveTable_R( CUtlVector< SendTable * >& visited, SendTable *pTable ) { DataTable_MaybeCreateReceiveTable( visited, pTable, false ); // Make sure we send child send tables.. for(int i=0; i < pTable->m_nProps; i++) { SendProp *pProp = &pTable->m_pProps[i]; if( pProp->m_Type == DPT_DataTable ) { DataTable_MaybeCreateReceiveTable_R( visited, pProp->GetDataTable() ); } } }
bool Array_IsEncodedZero( const SendProp *pProp, bf_read *pIn ) { SendProp *pArrayProp = pProp->GetArrayProp(); AssertMsg( pArrayProp, ("Array_IsEncodedZero: missing m_pArrayProp for a property.") ); int nElements = pIn->ReadUBitLong( pProp->GetNumArrayLengthBits() ); for ( int i=0; i < nElements; i++ ) { // skip over data g_PropTypeFns[pArrayProp->GetType()].IsEncodedZero( pArrayProp, pIn ); } return nElements == 0;; }
cell_t GetOffset(IPluginContext *pContext, const cell_t *params) { Handle_t hndl = static_cast<Handle_t>(params[1]); HandleError err; HandleSecurity sec; sec.pOwner = NULL; sec.pIdentity = myself->GetIdentity(); SendProp *pProp; if ((err=g_pHandleSys->ReadHandle(hndl, g_SendTableHandle, &sec, (void **)&pProp)) != HandleError_None) { return pContext->ThrowNativeError("Invalid SendProp handle %x (error %d)", hndl, err); } return pProp->GetOffset(); }
void UTIL_DrawSendTable(FILE *fp, SendTable *pTable, int level) { char spaces[255]; for (int i=0; i<level; i++) spaces[i] = ' '; spaces[level] = '\0'; const char *name, *type; SendProp *pProp; fprintf(fp, "%sSub-Class Table (%d Deep): %s\n", spaces, level, pTable->GetName()); for (int i=0; i<pTable->GetNumProps(); i++) { pProp = pTable->GetProp(i); name = pProp->GetName(); if (pProp->GetDataTable()) { UTIL_DrawSendTable(fp, pProp->GetDataTable(), level + 1); } else { type = GetDTTypeName(pProp->GetType()); if (type != NULL) { fprintf(fp, "%s-Member: %s (offset %d) (type %s) (bits %d)\n", spaces, pProp->GetName(), pProp->GetOffset(), type, pProp->m_nBits); } else { fprintf(fp, "%s-Member: %s (offset %d) (type %d) (bits %d)\n", spaces, pProp->GetName(), pProp->GetOffset(), pProp->GetType(), pProp->m_nBits); } } } }
void AddSendTable(SendTable* pTable, OffsetsMap& offsets, int offset=0, const char* baseName=NULL) { for (int i=0; i < pTable->GetNumProps(); ++i) { SendProp* pProp = pTable->GetProp(i); if (strcmp(pProp->GetName(), "baseclass") == 0) continue; int currentOffset = offset + pProp->GetOffset(); char* currentName = NULL; if (baseName == NULL) { currentName = (char*) pProp->GetName(); } else { char tempName[256]; sprintf(tempName, "%s.%s", baseName, pProp->GetName()); currentName = strdup(tempName); } if (pProp->GetType() == DPT_DataTable) { AddSendTable(pProp->GetDataTable(), offsets, currentOffset, currentName); } else { offsets.insert(std::make_pair(currentName, currentOffset)); } } }
SendProp SendPropString( char *pVarName, int offset, int bufferLen, int flags, SendVarProxyFn varProxy) { SendProp ret; Assert( bufferLen <= DT_MAX_STRING_BUFFERSIZE ); // You can only have strings with 8-bits worth of length. ret.m_Type = DPT_String; ret.m_pVarName = pVarName; ret.SetOffset( offset ); ret.SetFlags( flags ); ret.SetProxyFn( varProxy ); return ret; }
const char *tools_GetTeamName(int team) { if (size_t(team) >= g_Teams.size()) return NULL; if (g_teamname_offset == 0) return NULL; if (g_teamname_offset == -1) { SendProp *prop = g_pGameHelpers->FindInSendTable(g_Teams[team].ClassName, "m_szTeamname"); if (prop == NULL) { g_teamname_offset = 0; return NULL; } g_teamname_offset = prop->GetOffset(); } return (const char *)((unsigned char *)g_Teams[team].pEnt + g_teamname_offset); }
static cell_t SetTeamScore(IPluginContext *pContext, const cell_t *params) { if (!g_pSM->IsMapRunning()) { return pContext->ThrowNativeError("Cannot set team score when no map is running"); } int teamindex = params[1]; if (teamindex >= (int)g_Teams.size() || !g_Teams[teamindex].ClassName) { return pContext->ThrowNativeError("Team index %d is invalid", teamindex); } if (m_iScore == NULL) { m_iScore = g_pGameConf->GetKeyValue("m_iScore"); if (m_iScore == NULL) { return pContext->ThrowNativeError("Failed to get m_iScore key"); } } static int offset = -1; if (offset == -1) { SendProp *prop = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, m_iScore); if (!prop) { return pContext->ThrowNativeError("Failed to get m_iScore prop"); } offset = prop->GetOffset(); } CBaseEntity *pTeam = g_Teams[teamindex].pEnt; *(int *)((unsigned char *)pTeam + offset) = params[2]; edict_t *pEdict = gameents->BaseEntityToEdict(pTeam); gamehelpers->SetEdictStateChanged(pEdict, offset); return 1; }
void UTIL_DrawSendTable_XML(FILE *fp, SendTable *pTable, int space_count) { char spaces[255]; for (int i = 0; i < space_count; i++) { spaces[i] = ' '; } spaces[space_count] = '\0'; const char *type_name; SendTable *pOtherTable; SendProp *pProp; fprintf(fp, " %s<sendtable name=\"%s\">\n", spaces, pTable->GetName()); for (int i = 0; i < pTable->GetNumProps(); i++) { pProp = pTable->GetProp(i); fprintf(fp, " %s<property name=\"%s\">\n", spaces, pProp->GetName()); if ((type_name = GetDTTypeName(pProp->GetType())) != NULL) { fprintf(fp, " %s<type>%s</type>\n", spaces, type_name); } else { fprintf(fp, " %s<type>%d</type>\n", spaces, pProp->GetType()); } fprintf(fp, " %s<offset>%d</offset>\n", spaces, pProp->GetOffset()); fprintf(fp, " %s<bits>%d</bits>\n", spaces, pProp->m_nBits); if ((pOtherTable = pTable->GetProp(i)->GetDataTable()) != NULL) { UTIL_DrawSendTable_XML(fp, pOtherTable, space_count + 3); } fprintf(fp, " %s</property>\n", spaces); } fprintf(fp, " %s</sendtable>\n", spaces); }
SendProp InternalSendPropArray( const int elementCount, const int elementStride, char *pName, ArrayLengthSendProxyFn arrayLengthFn ) { SendProp ret; ret.m_Type = DPT_Array; ret.m_nElements = elementCount; ret.m_ElementStride = elementStride; ret.m_pVarName = pName; ret.SetProxyFn( SendProxy_Empty ); ret.m_pArrayProp = NULL; // This gets set in SendTable_InitTable. It always points at the property that precedes // this one in the datatable's list. ret.SetArrayLengthProxy( arrayLengthFn ); return ret; }
SendProp SendPropDataTable( char *pVarName, int offset, SendTable *pTable, SendTableProxyFn varProxy ) { SendProp ret; ret.m_Type = DPT_DataTable; ret.m_pVarName = pVarName; ret.SetOffset( offset ); ret.SetDataTable( pTable ); ret.SetDataTableProxyFn( varProxy ); // Handle special proxy types where they always let all clients get the results. if ( varProxy == SendProxy_DataTableToDataTable || varProxy == SendProxy_DataTablePtrToDataTable ) { ret.SetFlags( SPROP_PROXY_ALWAYS_YES ); } if ( varProxy == SendProxy_DataTableToDataTable && offset == 0 ) { ret.SetFlags( SPROP_COLLAPSIBLE ); } return ret; }
void InitTeamNatives() { g_Teams.clear(); g_Teams.resize(1); int edictCount = gpGlobals->maxEntities; for (int i=0; i<edictCount; i++) { edict_t *pEdict = PEntityOfEntIndex(i); if (!pEdict || pEdict->IsFree()) { continue; } if (!pEdict->GetNetworkable()) { continue; } ServerClass *pClass = pEdict->GetNetworkable()->GetServerClass(); if (FindNestedDataTable(pClass->m_pTable, "DT_Team")) { SendProp *pTeamNumProp = g_pGameHelpers->FindInSendTable(pClass->GetName(), "m_iTeamNum"); if (pTeamNumProp != NULL) { int offset = pTeamNumProp->GetOffset(); CBaseEntity *pEnt = pEdict->GetUnknown()->GetBaseEntity(); int TeamIndex = *(int *)((unsigned char *)pEnt + offset); if (TeamIndex >= (int)g_Teams.size()) { g_Teams.resize(TeamIndex+1); } g_Teams[TeamIndex].ClassName = pClass->GetName(); g_Teams[TeamIndex].pEnt = pEnt; } } } }
void EntityProp::getOffset(SendTable * table, istringstream & propPathLeft) { // Get the next step into the props table string pathNextStep; getline(propPathLeft, pathNextStep, '.'); //Msg("Scanning %s...\n", propPathLeft.c_str()); int nbrProps = table->GetNumProps(); int i=0; while(i<nbrProps) { SendProp * sProp = table->GetProp(i); if (pathNextStep == sProp->GetName()) { offset += sProp->GetOffset(); switch(sProp->GetType()) { case DPT_Int: case DPT_Float: case DPT_Vector: case DPT_String: case DPT_Array: // Found the prop itself, the offset is up to date i = nbrProps; // break break; case DPT_DataTable: // Step reached, go to the next step getOffset(sProp->GetDataTable(), propPathLeft); break; default: // Prop not found offset = 0; i = nbrProps; // break } } i++; } }
void Array_Encode( const unsigned char *pStruct, DVariant *pVar, const SendProp *pProp, bf_write *pOut, int objectID ) { SendProp *pArrayProp = pProp->GetArrayProp(); AssertMsg( pArrayProp, ("Array_Encode: missing m_pArrayProp for SendProp '%s'.", pProp->m_pVarName) ); int nElements = Array_GetLength( pStruct, pProp, objectID ); // Write the number of elements. pOut->WriteUBitLong( nElements, pProp->GetNumArrayLengthBits() ); unsigned char *pCurStructOffset = (unsigned char*)pStruct + pArrayProp->GetOffset(); for ( int iElement=0; iElement < nElements; iElement++ ) { DVariant var; // Call the proxy to get the value, then encode. pArrayProp->GetProxyFn()( pArrayProp, pStruct, pCurStructOffset, &var, iElement, objectID ); g_PropTypeFns[pArrayProp->GetType()].Encode( pStruct, &var, pArrayProp, pOut, objectID ); pCurStructOffset += pProp->GetElementStride(); } }
void SDKTools::OnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax) { g_Teams.clear(); g_Teams.resize(1); for (int i=0; i<edictCount; i++) { edict_t *pEdict = engine->PEntityOfEntIndex(i); if (!pEdict || pEdict->IsFree()) { continue; } if (!pEdict->GetNetworkable()) { continue; } ServerClass *pClass = pEdict->GetNetworkable()->GetServerClass(); if (FindTeamEntities(pClass->m_pTable, "DT_Team")) { SendProp *pTeamNumProp = g_pGameHelpers->FindInSendTable(pClass->GetName(), "m_iTeamNum"); if (pTeamNumProp != NULL) { int offset = pTeamNumProp->GetOffset(); CBaseEntity *pEnt = pEdict->GetUnknown()->GetBaseEntity(); int TeamIndex = *(int *)((unsigned char *)pEnt + offset); if (TeamIndex >= (int)g_Teams.size()) { g_Teams.resize(TeamIndex+1); } g_Teams[TeamIndex].ClassName = pClass->GetName(); g_Teams[TeamIndex].pEnt = pEnt; } } } }
//--------------------------------------------------------------------------------- // Purpose: used by the GetPropOffsetFromTable func to get a specific table //--------------------------------------------------------------------------------- SendTable *GetDataTable( const char *pTableName, SendTable *pTable ) { if (!pTable) return NULL; if ( FStrEq( pTableName, pTable->GetName() ) ) return pTable; int num = pTable->GetNumProps(); for (int i = 0; i < num; i++) { SendProp *pProp = pTable->GetProp(i); if (pProp) { SendTable *pSubTable = GetDataTable( pTableName, pProp->GetDataTable() ); if (pSubTable == NULL) continue; if ( FStrEq(pSubTable->GetName(), pTableName) ) return pSubTable; } } return NULL; }
cell_t GetTypeString(IPluginContext *pContext, const cell_t *params) { Handle_t hndl = static_cast<Handle_t>(params[1]); HandleError err; HandleSecurity sec; sec.pOwner = NULL; sec.pIdentity = myself->GetIdentity(); SendProp *pProp; if ((err=g_pHandleSys->ReadHandle(hndl, g_SendTableHandle, &sec, (void **)&pProp)) != HandleError_None) { return pContext->ThrowNativeError("Invalid SendProp handle %x (error %d)", hndl, err); } const char *sType = GetDTTypeName(pProp->GetType()); if(sType != NULL) { pContext->StringToLocal(params[2], params[3], sType); return strlen(sType); } return 0; }
static void SendTable_CalcNextVectorElems( SendTable *pTable ) { for ( int i=0; i < pTable->GetNumProps(); i++ ) { SendProp *pProp = pTable->GetProp( i ); if ( pProp->GetType() == DPT_DataTable ) { SendTable_CalcNextVectorElems( pProp->GetDataTable() ); } else if ( pProp->GetOffset() < 0 ) { pProp->SetOffset( -pProp->GetOffset() ); pProp->SetFlags( pProp->GetFlags() | SPROP_IS_A_VECTOR_ELEM ); } } }
bool FindNestedDataTable(SendTable *pTable, const char *name) { if (strcmp(pTable->GetName(), name) == 0) { return true; } int props = pTable->GetNumProps(); SendProp *prop; for (int i=0; i<props; i++) { prop = pTable->GetProp(i); if (prop->GetDataTable()) { if (FindNestedDataTable(prop->GetDataTable(), name)) { return true; } } } return false; }