PDA

Просмотр полной версии : [Вопрос] Можно ли сделать так, чтоб перехват срабатывал после обработки функции, а не до?



Geebrox
28.11.2016, 19:10
Можно ли сделать так, что бы мой перехват срабатывал после всех остальных, а если их нет, то после самого колбека/функции?

DeimoS
28.11.2016, 19:44
public Function(Args)
{
#if defined Prefix_Function
Prefix_Function(Args);
#endif

//Тут твой код
return 1;
}
#if defined _ALS_Function
#undef Function
#else
#define _ALS_Function
#endif

#define Function Prefix_Function
#if defined Prefix_Function
forward Prefix_Function(Args);
#endif
Но и перехват должен быть самым последним среди всех.

А вообще в таких ситуациях лучше создавать функцию и прописывать её вызов в коллбэке, который перехватываешь. Так ты точно можешь контролировать момент, когда твой код будет обработан

Daniel_Cortez
28.11.2016, 19:54
Если не секрет, для чего вообще может понадобиться делать перехват именно самым последним? Просто интересно, ибо ни разу не встречал таких ситуаций. Вполне возможно, что и в вашем случае можно сделать так, чтобы перехват не зависел от всей остальной цепочки вызовов.

Geebrox
28.11.2016, 20:03
public Function(Args)
{
#if defined Prefix_Function
Prefix_Function(Args);
#endif

//Тут твой код
return 1;
}
#if defined _ALS_Function
#undef Function
#else
#define _ALS_Function
#endif

#define Function Prefix_Function
#if defined Prefix_Function
forward Prefix_Function(Args);
#endif
Но и перехват должен быть самым последним среди всех.

А вообще в таких ситуациях лучше создавать функцию и прописывать её вызов в коллбэке, который перехватываешь. Так ты точно можешь контролировать момент, когда твой код будет обработан

я такой же код делал:

http://i.imgur.com/EjdObNJ.jpg

Но не был уверен, а если в самом колбеке или в других перехватах стоит завершение кода (return), мой код ниже сработает?



Если не секрет, для чего вообще может понадобиться делать перехват именно самым последним? Просто интересно, ибо ни разу не встречал таких ситуаций. Вполне возможно, что и в вашем случае можно сделать так, чтобы перехват не зависел от всей остальной цепочки вызовов.

Мне нужно чтобы определенная функция вызывалась после OnPlayerConnect (точнее в конце). Доступ к самому колбеку не имею.

DeimoS
28.11.2016, 20:45
я такой же код делал:

http://i.imgur.com/EjdObNJ.jpg

Но не был уверен, а если в самом колбеке или в других перехватах стоит завершение кода (return), мой код ниже сработает?

Ну так return Обычно вызывает следующий перехват. Для чего в перехватах есть такие строки, по-твоему?

#if defined Prefix_Function
return Prefix_Function(Args);
#else
return 1;
#endif

Geebrox
28.11.2016, 22:10
Понятно, а есть ещё другие варианты, быть может я не смогу поставить свой перехват последним? Или никаких выходов больше нет? (Кроме таймеров)

Nexius_Tailer
28.11.2016, 23:32
Элементарно. Чуть более года назад что-то подобное делал (https://github.com/NexiusTailer/Nex-AC/blob/master/src/v1.9/v1.9.10/r2/nex-ac.inc#L2801-L2817). Понадобилось лично мне для того, чтобы выводить сообщения при загрузке и выгрузке всех инклуд независимо от порядка подключения последним (варнинг о несовпадении версии при загрузке и статистика при выгрузке).

Geebrox
28.11.2016, 23:45
Элементарно. Чуть более года назад что-то подобное делал (https://github.com/NexiusTailer/Nex-AC/blob/master/src/v1.9/v1.9.10/r2/nex-ac.inc#L2801-L2817). Понадобилось лично мне для того, чтобы выводить сообщения при загрузке и выгрузке всех инклуд независимо от порядка подключения последним (варнинг о несовпадении версии при загрузке и статистика при выгрузке).

и чем же твой вариант отличается от нашего? Кроме проверок на подключение y_hooks?

Nexius_Tailer
28.11.2016, 23:48
и чем же твой вариант отличается от нашего? Кроме проверок на подключение y_hooks?
Наличием переменной, в которую записывается результат подменяемой функции, и, если таковой нет, возвратом единицы как по умолчанию. Соответственно это учитывает, если функция вернёт не 1, то и подменённая функция также вернёт это же значение

DeimoS
28.11.2016, 23:51
Понятно, а есть ещё другие варианты, быть может я не смогу поставить свой перехват последним? Или никаких выходов больше нет? (Кроме таймеров)

А чем тебя наши варианты не устраивают?

Geebrox
29.11.2016, 00:12
А чем тебя наши варианты не устраивают?

перечитай:


быть может я не смогу поставить свой перехват последним

Nexius_Tailer
29.11.2016, 00:14
перечитай:
С чего вдруг? Если ты про тот return - то он обрывает действия только в той функции, в которой используется, но не в тех, в которых эта функция вызывается. Всё прекрасно работает в общем

Geebrox
29.11.2016, 00:18
С чего вдруг? Если ты про тот return - то он обрывает действия только в той функции, в которой используется, но не в тех, в которых эта функция вызывается. Всё прекрасно работает в общем

Нет, ты не понял, вот если я перехвачу OnPlayerConnect с такими условиями, далее еще раз в другом месте но чуть ниже будет перехват с обычными проверками, то уже мой перехват не будет выполняться последним?

Nexius_Tailer
29.11.2016, 00:44
Нет, ты не понял, вот если я перехвачу OnPlayerConnect с такими условиями, далее еще раз в другом месте но чуть ниже будет перехват с обычными проверками, то уже мой перехват не будет выполняться последним?
Будет. И вот почему:

У нас есть, к примеру, такой код

//=============[1]=============
#if defined _inc_y_hooks || defined _INC_y_hooks
hook OnGameModeInit()
#else
public OnGameModeInit()
#endif
{
new a = 1;
#if !defined _inc_y_hooks && !defined _INC_y_hooks\
&& defined h_OnGameModeInit
a = h_OnGameModeInit();
#endif
print("Include 1 loaded!");
return a;
}

#if !defined _inc_y_hooks && !defined _INC_y_hooks
#if defined _ALS_OnGameModeInit
#undef OnGameModeInit
#else
#define _ALS_OnGameModeInit
#endif
#define OnGameModeInit h_OnGameModeInit
#if defined h_OnGameModeInit
forward h_OnGameModeInit();
#endif
#endif

//=============[2]=============
#if defined _inc_y_hooks || defined _INC_y_hooks
hook OnGameModeInit()
#else
public OnGameModeInit()
#endif
{
print("Include 2 loaded!");
#if !defined _inc_y_hooks && !defined _INC_y_hooks\
&& defined hh_OnGameModeInit
return hh_OnGameModeInit();
#else
return 1;
#endif
}

#if !defined _inc_y_hooks && !defined _INC_y_hooks
#if defined _ALS_OnGameModeInit
#undef OnGameModeInit
#else
#define _ALS_OnGameModeInit
#endif
#define OnGameModeInit hh_OnGameModeInit
#if defined hh_OnGameModeInit
forward hh_OnGameModeInit();
#endif
#endif

//=============[3]=============
#if defined _inc_y_hooks || defined _INC_y_hooks
hook OnGameModeInit()
#else
public OnGameModeInit()
#endif
{
print("Include 3 loaded!");
#if !defined _inc_y_hooks && !defined _INC_y_hooks\
&& defined hhh_OnGameModeInit
return hhh_OnGameModeInit();
#else
return 1;
#endif
}

#if !defined _inc_y_hooks && !defined _INC_y_hooks
#if defined _ALS_OnGameModeInit
#undef OnGameModeInit
#else
#define _ALS_OnGameModeInit
#endif
#define OnGameModeInit hhh_OnGameModeInit
#if defined hhh_OnGameModeInit
forward hhh_OnGameModeInit();
#endif
#endif

А теперь представим этот как некое количество спойлеров друг в друге:

//=============[1]=============
#if defined _inc_y_hooks || defined _INC_y_hooks
hook OnGameModeInit()
#else
public OnGameModeInit()
#endif
{
new a = 1;
#if !defined _inc_y_hooks && !defined _INC_y_hooks\
&& defined h_OnGameModeInit
a =
//=============[2]=============
#if defined _inc_y_hooks || defined _INC_y_hooks
hook OnGameModeInit()
#else
public OnGameModeInit()
#endif
{
print("Include 2 loaded!");
#if !defined _inc_y_hooks && !defined _INC_y_hooks\
&& defined hh_OnGameModeInit
return
//=============[3]=============
#if defined _inc_y_hooks || defined _INC_y_hooks
hook OnGameModeInit()
#else
public OnGameModeInit()
#endif
{
print("Include 3 loaded!");
#if !defined _inc_y_hooks && !defined _INC_y_hooks\
&& defined hhh_OnGameModeInit
return hhh_OnGameModeInit(); //Оригинальная функция
#else
return 1;
#endif
}

#if !defined _inc_y_hooks && !defined _INC_y_hooks
#if defined _ALS_OnGameModeInit
#undef OnGameModeInit
#else
#define _ALS_OnGameModeInit
#endif
#define OnGameModeInit hhh_OnGameModeInit
#if defined hhh_OnGameModeInit
forward hhh_OnGameModeInit();
#endif
#endif
;
#else
return 1;
#endif
}

#if !defined _inc_y_hooks && !defined _INC_y_hooks
#if defined _ALS_OnGameModeInit
#undef OnGameModeInit
#else
#define _ALS_OnGameModeInit
#endif
#define OnGameModeInit hh_OnGameModeInit
#if defined hh_OnGameModeInit
forward hh_OnGameModeInit();
#endif
#endif
;
#endif
print("Include 1 loaded!");
return a;
}

#if !defined _inc_y_hooks && !defined _INC_y_hooks
#if defined _ALS_OnGameModeInit
#undef OnGameModeInit
#else
#define _ALS_OnGameModeInit
#endif
#define OnGameModeInit h_OnGameModeInit
#if defined h_OnGameModeInit
forward h_OnGameModeInit();
#endif
#endif

Результаты:

Include 2 loaded!
Include 3 loaded!
Include 1 loaded!

Geebrox
29.11.2016, 00:46
Спасибо, я это и хотел узнать) Тему можно закрывать

DeimoS
29.11.2016, 00:56
Нет, ты не понял, вот если я перехвачу OnPlayerConnect с такими условиями, далее еще раз в другом месте но чуть ниже будет перехват с обычными проверками, то уже мой перехват не будет выполняться последним?

Что тебе мешает просто взять и проверить, если наши слова ты понять не можешь? =\


main()
{
TestFunc();
}


public TestFunc()
{
print("Перехват #1");
#if defined test1_TestFunc
return test1_TestFunc();
#else
return 1;
#endif
}
#if defined _ALS_TestFunc
#undef TestFunc
#else
#define _ALS_TestFunc
#endif

#define TestFunc test1_TestFunc
#if defined test1_TestFunc
forward test1_TestFunc();
#endif


public TestFunc()
{
print("Перехват #2");
#if defined test2_TestFunc
return test2_TestFunc();
#else
return 1;
#endif
}
#if defined _ALS_TestFunc
#undef TestFunc
#else
#define _ALS_TestFunc
#endif

#define TestFunc test2_TestFunc
#if defined test2_TestFunc
forward test2_TestFunc();
#endif


public TestFunc()
{
#if defined test3_TestFunc
test3_TestFunc();
#endif
print("Перехват #3");

return 1;
}
#if defined _ALS_TestFunc
#undef TestFunc
#else
#define _ALS_TestFunc
#endif

#define TestFunc test3_TestFunc
#if defined test3_TestFunc
forward test3_TestFunc();
#endif


public TestFunc()
{
print("Перехват #4");
#if defined test4_TestFunc
return test4_TestFunc();
#else
return 1;
#endif
}
#if defined _ALS_TestFunc
#undef TestFunc
#else
#define _ALS_TestFunc
#endif

#define TestFunc test4_TestFunc
#if defined test4_TestFunc
forward test4_TestFunc();
#endif



forward TestFunc();
public TestFunc()
{
print("Оригинальная функция");
return 1;
}

Вызов прекратится на каком-то из перехватов только в том случае, если ты вернёшь, например, единицу, а не вызовешь перехваченную функцию:

return test4_TestFunc();