m_szArmsModel crashes
laper32 opened this issue · comments
Here is the summary about why m_szArmsModel crashes.
First of all, the GetEntProp, with Prop_Send, the function is:
template<class T = cell_t>
T &EntProp(AutoEntity<CBaseEntity*> pEntity, decltype(Prop_Send), const char *prop, int size = sizeof(T), int element=0) {
assert(pEntity != nullptr);
sm_sendprop_info_t info = {};
IServerNetworkable* pNet = ((IServerUnknown*)pEntity)->GetNetworkable();
if (!pNet) throw std::runtime_error("Edict is not networkable");
if (!gamehelpers->FindSendPropInfo(pNet->GetServerClass()->GetName(), prop, &info)) throw std::runtime_error(std::string() + "Prop not found: " + prop);
SendProp* pProp = info.prop;
ptrdiff_t offset = info.actual_offset;
T* data = (T*)(reinterpret_cast<intptr_t>(static_cast<CBaseEntity*>(pEntity)) + offset);
return *data;
}
template<class T = cell_t>
const T &GetEntProp(AutoEntity<CBaseEntity*> pEntity, decltype(Prop_Send), const char *prop, int size=sizeof(T), int element=0) {
return EntProp<T>(pEntity, Prop_Send, prop, size, element);
}
Now we want to retrieve m_szArmsModel, that we will write it as:
static cell_t GetArm(IPluginContext* pContext, const cell_t* params) {
CBasePlayer* player = sm::ent_cast<CBasePlayer*>(params[1]);
if (!player)
{
pContext->ReportError("Player is nullptr. Index: %d", params[1]);
return 0;
}
const char* name = sm::GetEntProp<const char*>(player, sm::Prop_Send, "m_szArmsModel");
return pContext->StringToLocalUTF8(params[2], params[3], name, nullptr);
}
But this will crash.
Be comparing with smn_entities.cpp, we can find that it has several extra steps to retrieve the true result.
if (info.prop->GetProxyFn())
{
DVariant var;
info.prop->GetProxyFn()(info.prop, pEntity, (const void *) ((intptr_t) pEntity + offset), &var, element, params[1]);
src = var.m_pString;
}
else
{
src = *(char **) ((uint8_t *) pEntity + offset);
}
Now we add up these steps, it works correctly. 79
But the strange thing is that: Get crashes, but set works.
Further investigation is required.