Sped up native impl. of FindEntityByClassname (bug 4963, r=fyren).
Sped up native impl. of FindEntityByClassname (
bug 4963, r=fyren).
1.1 --- a/extensions/sdktools/vnatives.cpp Fri Jul 08 07:55:20 2011 -0400
1.2 +++ b/extensions/sdktools/vnatives.cpp Tue Jul 12 19:48:28 2011 -0400
1.3 @@ -40,7 +40,6 @@
1.4 #include <inetchannel.h>
1.5 #include <iclient.h>
1.6 #include "iserver.h"
1.7 -#include <iserverentity.h>
1.8
1.9 SourceHook::List<ValveCall *> g_RegCalls;
1.10 SourceHook::List<ICallWrapper *> g_CallWraps;
1.11 @@ -632,7 +631,7 @@
1.12 }
1.13
1.14 #if SOURCE_ENGINE >= SE_ORANGEBOX
1.15 -static cell_t FindEntityByClassname(IPluginContext *pContext, const cell_t *params)
1.16 +static cell_t NativeFindEntityByClassname(IPluginContext *pContext, const cell_t *params)
1.17 {
1.18 char *searchname;
1.19 CBaseEntity *pEntity;
1.20 @@ -653,36 +652,48 @@
1.21 pEntity = (CBaseEntity *)servertools->NextEntity(pEntity);
1.22 }
1.23
1.24 + // it's tough to find a good ent these days
1.25 + if (!pEntity)
1.26 + {
1.27 + return -1;
1.28 + }
1.29 +
1.30 pContext->LocalToString(params[2], &searchname);
1.31
1.32 - char buffer[128];
1.33 - const char *classname = buffer;
1.34 - int lastcharpos;
1.35 - bool ismatch = false;
1.36 + const char *classname;
1.37 + int lastletterpos;
1.38 +
1.39 + static int offset = -1;
1.40 + if (offset == -1)
1.41 + {
1.42 + offset = GetTypeDescOffs(
1.43 + gamehelpers->FindInDataMap(gamehelpers->GetDataMap(pEntity),
1.44 + "m_iClassname")
1.45 + );
1.46 + }
1.47 +
1.48 + string_t s;
1.49
1.50 while (pEntity)
1.51 {
1.52 - if (!servertools->GetKeyValue(pEntity, "classname", buffer, sizeof(buffer)))
1.53 + if ((s = *(string_t *)((uint8_t *)pEntity + offset)) == NULL_STRING)
1.54 {
1.55 pEntity = (CBaseEntity *)servertools->NextEntity(pEntity);
1.56 continue;
1.57 }
1.58
1.59 - lastcharpos = strlen(searchname);
1.60 - if (searchname[lastcharpos-1] == '*')
1.61 + classname = STRING(s);
1.62 +
1.63 + lastletterpos = strlen(searchname) - 1;
1.64 + if (searchname[lastletterpos] == '*')
1.65 {
1.66 - if (strncasecmp(searchname, classname, lastcharpos-1) == 0)
1.67 + if (strncasecmp(searchname, classname, lastletterpos) == 0)
1.68 {
1.69 - ismatch = true;
1.70 + return gamehelpers->EntityToBCompatRef(pEntity);
1.71 }
1.72 }
1.73 else if (strcasecmp(searchname, classname) == 0)
1.74 {
1.75 - ismatch = true;
1.76 - }
1.77 -
1.78 - if (ismatch)
1.79 - {
1.80 return gamehelpers->EntityToBCompatRef(pEntity);
1.81 }
1.82
1.83 @@ -691,21 +702,48 @@
1.84
1.85 return -1;
1.86 }
1.87 -#else
1.88 +#endif
1.89 +
1.90 static cell_t FindEntityByClassname(IPluginContext *pContext, const cell_t *params)
1.91 {
1.92 static ValveCall *pCall = NULL;
1.93 + static bool bProbablyNoFEBC = false;
1.94 +
1.95 +#if SOURCE_ENGINE >= SE_ORANGEBOX
1.96 + if (bProbablyNoFEBC)
1.97 + {
1.98 + return NativeFindEntityByClassname(pContext, params);
1.99 + }
1.100 +#endif
1.101 +
1.102 if (!pCall)
1.103 {
1.104 ValvePassInfo pass[3];
1.105 InitPass(pass[0], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL, VDECODE_FLAG_ALLOWNULL|VDECODE_FLAG_ALLOWWORLD);
1.106 InitPass(pass[1], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
1.107 InitPass(pass[2], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL);
1.108 +
1.109 + char error[256];
1.110 + error[0] = '\0';
1.111 if (!CreateBaseCall("FindEntityByClassname", ValveCall_EntityList, &pass[2], pass, 2, &pCall))
1.112 {
1.113 - return pContext->ThrowNativeError("\"FindEntityByClassname\" not supported by this mod");
1.114 + g_pSM->Format(error, sizeof(error), "\"FindEntityByClassname\" not supported by this mod");
1.115 } else if (!pCall) {
1.116 - return pContext->ThrowNativeError("\"FindEntityByClassname\" wrapper failed to initialize");
1.117 + g_pSM->Format(error, sizeof(error), "\"FindEntityByClassname\" wrapper failed to initialize");
1.118 + }
1.119 +
1.120 + if (error[0] != '\0')
1.121 + {
1.122 +#if SOURCE_ENGINE >= SE_ORANGEBOX
1.123 + if (!bProbablyNoFEBC)
1.124 + {
1.125 + bProbablyNoFEBC = true;
1.126 + g_pSM->LogError(myself, "%s, falling back to IServerTools method.", error);
1.127 + }
1.128 + return NativeFindEntityByClassname(pContext, params);
1.129 +#else
1.130 + return pContext->ThrowNativeError("%s", error);
1.131 +#endif
1.132 }
1.133 }
1.134
1.135 @@ -718,7 +756,6 @@
1.136
1.137 return gamehelpers->EntityToBCompatRef(pEntity);
1.138 }
1.139 -#endif
1.140
1.141 #if SOURCE_ENGINE >= SE_ORANGEBOX
1.142 static cell_t CreateEntityByName(IPluginContext *pContext, const cell_t *params)