Add string_t SetEntPropString support for ep1 (fixes #1287)

This commit is contained in:
Nick Hastings 2020-06-25 21:20:56 -04:00
parent 2ebbf2774b
commit 4c8103a4e1
4 changed files with 71 additions and 13 deletions

View File

@ -1367,8 +1367,36 @@ bool CHalfLife2::IsMapValid(const char *map)
return FindMap(map) != SMFindMapResult::NotFound; return FindMap(map) != SMFindMapResult::NotFound;
} }
// TODO: Add ep1 support for this. (No IServerTools available there) #if SOURCE_ENGINE == SE_EPISODEONE
#if SOURCE_ENGINE >= SE_ORANGEBOX class VKeyValuesSS_Helper {};
static bool VKeyValuesSS(CBaseEntity* pThisPtr, const char *pszKey, const char *pszValue, int offset)
{
void** this_ptr = *reinterpret_cast<void***>(&pThisPtr);
void** vtable = *reinterpret_cast<void***>(pThisPtr);
void* vfunc = vtable[offset];
union
{
bool (VKeyValuesSS_Helper::* mfpnew)(const char *, const char *);
#ifndef PLATFORM_POSIX
void* addr;
} u;
u.addr = vfunc;
#else
struct
{
void* addr;
intptr_t adjustor;
} s;
} u;
u.s.addr = vfunc;
u.s.adjustor = 0;
#endif
return (bool)(reinterpret_cast<VKeyValuesSS_Helper*>(this_ptr)->*u.mfpnew)(pszKey, pszValue);
}
#endif
string_t CHalfLife2::AllocPooledString(const char *pszValue) string_t CHalfLife2::AllocPooledString(const char *pszValue)
{ {
// This is admittedly a giant hack, but it's a relatively safe method for // This is admittedly a giant hack, but it's a relatively safe method for
@ -1378,28 +1406,58 @@ string_t CHalfLife2::AllocPooledString(const char *pszValue)
// current targetname string_t, set it to our string to insert via SetKeyValue, // current targetname string_t, set it to our string to insert via SetKeyValue,
// read back the new targetname value, restore the old value, and return the new one. // read back the new targetname value, restore the old value, and return the new one.
#if SOURCE_ENGINE == SE_EPISODEONE
CBaseEntity* pEntity = nullptr;
for (int i = 0; i < gpGlobals->maxEntities; ++i)
{
pEntity = ReferenceToEntity(i);
if (pEntity)
{
break;
}
}
if (!pEntity)
{
logger->LogError("Failed to locate a valid entity for AllocPooledString.");
return NULL_STRING;
}
#else
CBaseEntity *pEntity = ((IServerUnknown *) servertools->FirstEntity())->GetBaseEntity(); CBaseEntity *pEntity = ((IServerUnknown *) servertools->FirstEntity())->GetBaseEntity();
#endif
auto *pDataMap = GetDataMap(pEntity); auto *pDataMap = GetDataMap(pEntity);
assert(pDataMap); assert(pDataMap);
static int offset = -1; static int iNameOffset = -1;
if (offset == -1) if (iNameOffset == -1)
{ {
sm_datatable_info_t info; sm_datatable_info_t info;
bool found = FindDataMapInfo(pDataMap, "m_iName", &info); bool found = FindDataMapInfo(pDataMap, "m_iName", &info);
assert(found); assert(found);
offset = info.actual_offset; iNameOffset = info.actual_offset;
} }
string_t *pProp = (string_t *) ((intp) pEntity + offset); string_t* pProp = (string_t*)((intp)pEntity + iNameOffset);
string_t backup = *pProp; string_t backup = *pProp;
#if SOURCE_ENGINE == SE_EPISODEONE
static int iFuncOffset;
if (!g_pGameConf->GetOffset("DispatchKeyValue", &iFuncOffset) || !iFuncOffset)
{
logger->LogError("Failed to locate DispatchKeyValue in core gamedata. AllocPooledString unsupported.");
return NULL_STRING;
}
VKeyValuesSS(pEntity, "targetname", pszValue, iFuncOffset);
#else
servertools->SetKeyValue(pEntity, "targetname", pszValue); servertools->SetKeyValue(pEntity, "targetname", pszValue);
#endif
string_t newString = *pProp; string_t newString = *pProp;
*pProp = backup; *pProp = backup;
return newString; return newString;
} }
#endif
bool CHalfLife2::GetServerSteam3Id(char *pszOut, size_t len) const bool CHalfLife2::GetServerSteam3Id(char *pszOut, size_t len) const
{ {

View File

@ -239,9 +239,7 @@ public: //IGameHelpers
void FreeUtlVectorUtlString(CUtlVector<CUtlString, CUtlMemoryGlobalMalloc<CUtlString>> &vec); void FreeUtlVectorUtlString(CUtlVector<CUtlString, CUtlMemoryGlobalMalloc<CUtlString>> &vec);
#endif #endif
bool GetMapDisplayName(const char *pMapName, char *pDisplayname, size_t nMapNameMax); bool GetMapDisplayName(const char *pMapName, char *pDisplayname, size_t nMapNameMax);
#if SOURCE_ENGINE >= SE_ORANGEBOX
string_t AllocPooledString(const char *pszValue); string_t AllocPooledString(const char *pszValue);
#endif
bool GetServerSteam3Id(char *pszOut, size_t len) const override; bool GetServerSteam3Id(char *pszOut, size_t len) const override;
uint64_t GetServerSteamId64() const override; uint64_t GetServerSteamId64() const override;
public: public:

View File

@ -2380,12 +2380,8 @@ static cell_t SetEntPropString(IPluginContext *pContext, const cell_t *params)
if (bIsStringIndex) if (bIsStringIndex)
{ {
#if SOURCE_ENGINE < SE_ORANGEBOX
return pContext->ThrowNativeError("Cannot set %s. Setting string_t values not supported on this game.", prop);
#else
*(string_t *) ((intptr_t) pEntity + offset) = g_HL2.AllocPooledString(src); *(string_t *) ((intptr_t) pEntity + offset) = g_HL2.AllocPooledString(src);
len = strlen(src); len = strlen(src);
#endif
} }
else else
{ {

View File

@ -41,6 +41,12 @@
"windows" "4" "windows" "4"
"linux" "4" "linux" "4"
} }
/* For AllocPooledString. KeyValue(const char *, const char *) */
"DispatchKeyValue"
{
"windows" "35"
}
} }
"Keys" "Keys"