Offset m_hOwnerEntity error

Колян

Участник
Сообщения
180
Реакции
5
PHP:
public OnEntityCreated(entity, const String:classname[]) 
{ 
    if (IsValidEntity(entity) && StrEqual(classname, "flashbang_projectile"))
    {
        CreateTimer(0.85, OnValidSpawn, entity);
    }
}

public Action:OnValidSpawn(Handle:timer, any:entity) 
{ 
    if (entity == -1 || !IsValidEntity(entity)) return Plugin_Stop; 
    new client = GetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity"); //это 116 строка!!!
}

PHP:
L 10/21/2016 - 00:28:31: [SM] Blaming: Mod.smx
L 10/21/2016 - 00:28:31: [SM] Call stack trace:
L 10/21/2016 - 00:28:31: [SM]   [0] GetEntPropEnt
L 10/21/2016 - 00:28:31: [SM]   [1] Line 116, C:\Users\Ya!\Desktop\hib.sp::OnValidSpawn

Хочу заметить что на CSS такой ошибки не светит... а на КСГО в 20% случаев... (т.е не всегда).. в чем может быть дело и как это исправить?
 

AlmazON

Не путать с самим yand3xmail
Сообщения
5,099
Реакции
2,755
CreateTimer(0.85, OnValidSpawn, entity);
PHP:
CreateTimer(0.85, OnValidSpawn, EntIndexToEntRef(entity), TIMER_FLAG_NO_MAPCHANGE);
if (entity == -1 || !IsValidEntity(entity)) return Plugin_Stop;
PHP:
if ((entity = EntRefToEntIndex(entity)) == INVALID_ENT_REFERENCE) return Plugin_Stop;
И лучше сразу делай через оффсет:
PHP:
FindSendPropInfo("CBaseEntity", "m_hOwnerEntity");
 

Колян

Участник
Сообщения
180
Реакции
5
PHP:
CreateTimer(0.85, OnValidSpawn, EntIndexToEntRef(entity), TIMER_FLAG_NO_MAPCHANGE);
PHP:
if ((entity = EntRefToEntIndex(entity)) == INVALID_ENT_REFERENCE) return Plugin_Stop;
И лучше сразу делай через оффсет:
PHP:
FindSendPropInfo("CBaseEntity", "m_hOwnerEntity");
применить сразу для ксс и ксго это? или для ксс раз нет такой ошибки - оставить как есть?
 

Колян

Участник
Сообщения
180
Реакции
5
PHP:
public OnEntityCreated(entity, const String:classname[]) 
{ 
 if (IsValidEntity(entity) && StrEqual(classname, "flashbang_projectile"))
 {
 CreateTimer(0.85, OnValidSpawn, EntIndexToEntRef(entity));
 }
}

public Action:OnValidSpawn(Handle:timer, any:entity) 
{ 
 if (entity == -1 || !IsValidEntity(entity) || ((entity = EntRefToEntIndex(entity)) == INVALID_ENT_REFERENCE)) return Plugin_Stop; 

 new client = FindSendPropInfo("CBaseEntity", "m_hOwnerEntity");
}

как-то так должно быть?))
 

AlmazON

Не путать с самим yand3xmail
Сообщения
5,099
Реакции
2,755
PHP:
new offs_Owner;

public OnPluginStart()
{
	if ((offs_Owner = FindSendPropInfo("CBaseEntity", "m_hOwnerEntity")) < 1) SetFailState("Offset not found!");
}

public OnEntityCreated(entity, const String:classname[]) 
{
	if (entity != -1 && strcmp(classname, "flashbang_projectile") == 0)
	{
		CreateTimer(0.85, OnValidSpawn, EntIndexToEntRef(entity), TIMER_FLAG_NO_MAPCHANGE);
	}
}

public Action:OnValidSpawn(Handle:timer, any:entity) 
{
	if (((entity = EntRefToEntIndex(entity)) != INVALID_ENT_REFERENCE))
	{
		new client = GetEntDataEnt2(entity, offs_Owner);
	}
	return Plugin_Stop;
}
 

Vit_ amin

Добрая душа
Сообщения
1,525
Реакции
688
Подниму тему (по делу)
@AlmazON, Почему ты считаешь, что лучше делать NetProp операции через оффсеты ?
--- Добавлено позже ---
@AlmazON,
То есть по сути SetEntProp - использует CPU (так как приходится искать нужное смещение и использовать значение)
А FindPropSend... - использует RAM (так как все данные уже получены и хранятся в памяти сервера)
Я прав ?
 
Последнее редактирование:

Vit_ amin

Добрая душа
Сообщения
1,525
Реакции
688
Никогда не использовал FindSendProp, считаю все же лучше использовать однократно какую-либо CPU, нежели постоянно обращать в память (хотя все зависит от конкретного случая конечно же)
 

FrozDark

Участник
Сообщения
1,769
Реакции
2,050
Подниму тему (по делу)
@AlmazON, Почему ты считаешь, что лучше делать NetProp операции через оффсеты ?
--- Добавлено позже ---
@AlmazON,
То есть по сути SetEntProp - использует CPU (так как приходится искать нужное смещение и использовать значение)
А FindPropSend... - использует RAM (так как все данные уже получены и хранятся в памяти сервера)
Я прав ?
что значит "использует CPU" и "использует RAM"?
Если я правильно тебя понял (CPU нагрузка процессора, RAM нагрузка ОЗУ), то они оба используют CPU и RAM
 

AlmazON

Не путать с самим yand3xmail
Сообщения
5,099
Реакции
2,755
они оба используют CPU и RAM
Да понятно. Даже обычная переменная вызывает какие-то минимальные действия со стороны CPU, связывая плагин с RAM.
А по делу, есть какие-то мысли или обоснования?
 

FrozDark

Участник
Сообщения
1,769
Реакции
2,050
Да понятно. Даже обычная переменная вызывает какие-то минимальные действия со стороны CPU, связывая плагин с RAM.
А по делу, есть какие-то мысли или обоснования?
Обоснование что к чему?
Согласно комментариям к SM коду, то SetEntProp и GetEntProp оффсеты кеширует, получая индекс оффсета. FindSendProp заного ищет возвращая индекс оффсета (двойная работа)
 

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #16
@Vit_ amin, @FrozDark, @AlmazON, собственно:

PHP:
static cell_t SetEntProp(IPluginContext *pContext, const cell_t *params)
{
    CBaseEntity *pEntity;
    char *prop;
    int offset;
    edict_t *pEdict;
    int bit_count;

    int element = 0;
    if (params[0] >= 6)
    {
        element = params[6];
    }

    if (!IndexToAThings(params[1], &pEntity, &pEdict))
    {
        return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
    }

    pContext->LocalToString(params[3], &prop);

    switch (params[2])
    {
    case Prop_Data:
        {
            typedescription_t *td;

            FIND_PROP_DATA(td);

            if ((bit_count = MatchTypeDescAsInteger(td->fieldType, td->flags)) == 0)
            {
                return pContext->ThrowNativeError("Data field %s is not an integer (%d)",
                    prop,
                    td->fieldType);
            }

            CHECK_SET_PROP_DATA_OFFSET();

            if (td->fieldType == FIELD_CUSTOM && (td->flags & FTYPEDESC_OUTPUT) == FTYPEDESC_OUTPUT)
            {
                auto *pVariant = (variant_t *)((intptr_t)pEntity + offset);
                // These are the only three int-ish types that variants support. If set to valid one that isn't
                // (32-bit) integer, leave it alone. It's probably the intended type.
                if (pVariant->fieldType != FIELD_COLOR32 && pVariant->fieldType != FIELD_BOOLEAN)
                {
                    pVariant->fieldType = FIELD_INTEGER;
                }

                bit_count = MatchTypeDescAsInteger(pVariant->fieldType, 0);
            }

            SET_TYPE_IF_VARIANT(FIELD_INTEGER);

            break;
        }
    case Prop_Send:
        {
            FIND_PROP_SEND(DPT_Int, "integer");
            if (!CanSetPropName(prop))
            {
                return pContext->ThrowNativeError("Cannot set %s with \"FollowCSGOServerGuidelines\" option enabled.", prop);
            }

            // This isn't in CS:S yet, but will be, doesn't hurt to add now, and will save us a build later
#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS \
    || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_TF2 \
    || SOURCE_ENGINE == SE_CSGO
            if (pProp->GetFlags() & SPROP_VARINT)
            {
                bit_count = sizeof(int) * 8;
            }
#endif
            break;
        }
    default:
        {
            return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
        }
    }

    if (bit_count < 1)
    {
        bit_count = params[5] * 8;
    }

    if (bit_count >= 17)
    {
        *(int32_t *)((uint8_t *)pEntity + offset) = params[4];
    }
    else if (bit_count >= 9)
    {
        *(int16_t *)((uint8_t *)pEntity + offset) = (int16_t)params[4];
    }
    else if (bit_count >= 2)
    {
        *(int8_t *)((uint8_t *)pEntity + offset) = (int8_t)params[4];
    }
    else
    {
        *(bool *)((uint8_t *)pEntity + offset) = params[4] ? true : false;
    }
    
    if (params[2] == Prop_Send && (pEdict != NULL))
    {
        g_HL2.SetEdictStateChanged(pEdict, offset);
    }

    return 0;
}

PHP:
static cell_t SetEntData(IPluginContext *pContext, const cell_t *params)
{
    CBaseEntity *pEntity;
    edict_t *pEdict;

    if (!IndexToAThings(params[1], &pEntity, &pEdict))
    {
        return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
    }

    int offset = params[2];
    if (offset <= 0 || offset > 32768)
    {
        return pContext->ThrowNativeError("Offset %d is invalid", offset);
    }

    if (params[5] && (pEdict != NULL))
    {
        g_HL2.SetEdictStateChanged(pEdict, offset);
    }

    switch (params[4])
    {
    case 4:
        {
            *(int *)((uint8_t *)pEntity + offset) = params[3];
            break;
        }
    case 2:
        {
            *(short *)((uint8_t *)pEntity + offset) = params[3];
            break;
        }
    case 1:
        {
            *((uint8_t *)pEntity + offset) = params[3];
            break;
        }
    default:
        return pContext->ThrowNativeError("Integer size %d is invalid", params[4]);
    }

    return 1;
}
 

FrozDark

Участник
Сообщения
1,769
Реакции
2,050
@Vit_ amin, @FrozDark, @AlmazON, собственно:

PHP:
static cell_t SetEntProp(IPluginContext *pContext, const cell_t *params)
{
    CBaseEntity *pEntity;
    char *prop;
    int offset;
    edict_t *pEdict;
    int bit_count;

    int element = 0;
    if (params[0] >= 6)
    {
        element = params[6];
    }

    if (!IndexToAThings(params[1], &pEntity, &pEdict))
    {
        return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
    }

    pContext->LocalToString(params[3], &prop);

    switch (params[2])
    {
    case Prop_Data:
        {
            typedescription_t *td;

            FIND_PROP_DATA(td);

            if ((bit_count = MatchTypeDescAsInteger(td->fieldType, td->flags)) == 0)
            {
                return pContext->ThrowNativeError("Data field %s is not an integer (%d)",
                    prop,
                    td->fieldType);
            }

            CHECK_SET_PROP_DATA_OFFSET();

            if (td->fieldType == FIELD_CUSTOM && (td->flags & FTYPEDESC_OUTPUT) == FTYPEDESC_OUTPUT)
            {
                auto *pVariant = (variant_t *)((intptr_t)pEntity + offset);
                // These are the only three int-ish types that variants support. If set to valid one that isn't
                // (32-bit) integer, leave it alone. It's probably the intended type.
                if (pVariant->fieldType != FIELD_COLOR32 && pVariant->fieldType != FIELD_BOOLEAN)
                {
                    pVariant->fieldType = FIELD_INTEGER;
                }

                bit_count = MatchTypeDescAsInteger(pVariant->fieldType, 0);
            }

            SET_TYPE_IF_VARIANT(FIELD_INTEGER);

            break;
        }
    case Prop_Send:
        {
            FIND_PROP_SEND(DPT_Int, "integer");
            if (!CanSetPropName(prop))
            {
                return pContext->ThrowNativeError("Cannot set %s with \"FollowCSGOServerGuidelines\" option enabled.", prop);
            }

            // This isn't in CS:S yet, but will be, doesn't hurt to add now, and will save us a build later
#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS \
    || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_TF2 \
    || SOURCE_ENGINE == SE_CSGO
            if (pProp->GetFlags() & SPROP_VARINT)
            {
                bit_count = sizeof(int) * 8;
            }
#endif
            break;
        }
    default:
        {
            return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
        }
    }

    if (bit_count < 1)
    {
        bit_count = params[5] * 8;
    }

    if (bit_count >= 17)
    {
        *(int32_t *)((uint8_t *)pEntity + offset) = params[4];
    }
    else if (bit_count >= 9)
    {
        *(int16_t *)((uint8_t *)pEntity + offset) = (int16_t)params[4];
    }
    else if (bit_count >= 2)
    {
        *(int8_t *)((uint8_t *)pEntity + offset) = (int8_t)params[4];
    }
    else
    {
        *(bool *)((uint8_t *)pEntity + offset) = params[4] ? true : false;
    }
   
    if (params[2] == Prop_Send && (pEdict != NULL))
    {
        g_HL2.SetEdictStateChanged(pEdict, offset);
    }

    return 0;
}

PHP:
static cell_t SetEntData(IPluginContext *pContext, const cell_t *params)
{
    CBaseEntity *pEntity;
    edict_t *pEdict;

    if (!IndexToAThings(params[1], &pEntity, &pEdict))
    {
        return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
    }

    int offset = params[2];
    if (offset <= 0 || offset > 32768)
    {
        return pContext->ThrowNativeError("Offset %d is invalid", offset);
    }

    if (params[5] && (pEdict != NULL))
    {
        g_HL2.SetEdictStateChanged(pEdict, offset);
    }

    switch (params[4])
    {
    case 4:
        {
            *(int *)((uint8_t *)pEntity + offset) = params[3];
            break;
        }
    case 2:
        {
            *(short *)((uint8_t *)pEntity + offset) = params[3];
            break;
        }
    case 1:
        {
            *((uint8_t *)pEntity + offset) = params[3];
            break;
        }
    default:
        return pContext->ThrowNativeError("Integer size %d is invalid", params[4]);
    }

    return 1;
}
Только со вторым, нужно сначала получить оффсет. Конечно на код, второй выглядит оптимальнее
 

FrozDark

Участник
Сообщения
1,769
Реакции
2,050
Ну так 1 же раз, а не каждый
дай ссылку на исходник, потому что в варианте первом он ищет оффсет в кеше. Хочу посмотреть как он это делает
Второй вариант же ищет всё с нуля по всем пропам должно быть
 
Сверху Снизу