
12.09.2021, 20:42
|
|
Флудер
Регистрация: 06.11.2017
Сообщений: 2,759
С нами:
4483143
Репутация:
183
|
|
- Создание ASI-плагина с нуля
- Хуки – что это такое и как с ними работать
- Безопасная инициализация и работа с SAMP
- Работа с рендером и Directx9
- Обработка событий окна + ImGui
В этом гайде будет рассказано как инициализироваться без потоков, а также как работать с SAMP'ом
При использовании на других ресурсах необходимо указание авторства и ссылки на оригинальную темы!
Все действия производились на Visual Studio 2019 с параметром
, в других версиях интерфейс может отличаться.
И так, начнем:
Создаем новый проект, настраиваем его.
В свойствах проекта, в вкладке общие, стандарт языка C++ ставим /std:c++17
Добавляем sampapi в наш проект:
Первый способ:
- В верхнем меню жмем Git -> Создать репозиторий Git(Create git repository)
- В открывшемся окне выбираем либо github репозиторий, либо локальный репозиторий и жмем Создать.
- Снова жмем Git -> Открыть в командной строке (Open in command line).
- В консоли пишем
Код:
git submodule add https://github.com/BlastHackNet/SAMP-API.git
- Ждем завершения операции и далее жмем Файл(File) -> Добавить(Add) -> Существующий проект (Existing projeect). Открываем папку с нашим проектом, заходим в папку SAMP-API и выбираем sampapi.vcxproj.
- Открываем настройки проекта, выбираем C/C++ -> Общие -> Дополнительные каталоги включаемых файлов(Additional directories of included files). Жмем изменить
В открывшемся окне жмем на иконку файла со звездочкой, и жмем на появившуюся кнопку
Переходим в директорию
Код:
path_to_project\SAMP-API\include
и жмем выбор папки.
- Переходим в настройки проекта
Набор инструментов платформы(Build tools) - выбираем свое(у меня это v142
Версия пакета SDK для Windows - выбираем свое(у меня это 10.0)
- Заходим в настройки нашего основного проекта, Компоновщик(Linker) -> Дополнительные каталоги библиотек(Additional library directories)
Повторяем те же самые операции что в шаге 6, но выбираем папку
Код:
path_to_project\SAMP-API\build\bin
- Далее переходим в вкладку Ввод(Input) и в поле Дополнительные зависимости(Additional dependecies) в начало вписываем
Код:
Release\sampapi.lib;
для Release конфигурации проект, и
. Точка с запятой ОБЯЗАТЕЛЬНА
- Жмем правой кнопкой по проекту sampapi, Только проект -> Собрать только sampapi(делаем это для Release и Debug конфигураций)
Второй способ:
Скачиваем репозиторий, распаковываем по пути
Повторяем шаги 5-10 из первого способа.
Готово, мы подключили sampapi
Теперь добавим библиотеку для хуков в наш проект:
Начну свое описание с подключения моей библиотеки для хуков - kthook
- Скачиваем kthook из репозитория и распаковываем в себе в папку с кодом(Пкм по проекту -> открыть папку в проводнике).
Папку tests перекидывать к себе не нужно.
- Скачиваем ktsignal из репозитория и распаковываем содержимое
в папку
- Жмем показать все файлы
ПКМ по папке kthook -> Включить в проект
- Т.к. мы не используем CMake, тогда мы должны вручную переназначить все зависимости для kthook
- Добавляем папку kthook в Дополнительные каталоги включаемых файлов(Additional directories of included files) (как в шаге 6 у sampapi)
- В kthook.hpp изменяем
Код:
#include "ktsignal/ktsignal.hpp"
на
Код:
#include "ktsignal/include/ktsignal/ktsignal.hpp"
- Также ради собственного удобства добавляем
Дополнительные каталоги включаемых файлов(Additional directories of included files)
Вместо kthook могу посоветовать вам SRHook либо MinHook
SRHook подключается также как и kthook, MinHook можно подключить также двумя способами, как и sampapi.
Но я рекомендую установить его через vcpkg.
Код:
vcpkg install minhook
И теперь перейдем к написанию кода:
SAMP инициализирует свои структуры в вызове
, поэтому мы перехватим эту функцию, и после ее вызова будем уверены что самп инициализировался.
Для инициализации плагина лично я обычно использую хук на
Сообщение от Спойлер
C++:
Код:
using
CTimer__Update
=
void
(
__cdecl
*
)
(
)
;
void
*
func_addr
=
reinterpret_cast
(
0x561B10
)
;
Создаем хук:
C++:
Код:
#include "kthook/kthook.hpp"
using
CHud__DrawRadar
=
void
(
__cdecl
*
)
(
)
;
// Прототип CHud::DrawRadar
kthook
::
kthook_simple_t
samp_init_hook
{
reinterpret_cast
(
0x58A330
)
}
;
// хук на CHud::DrawRadar
Создаем функцию-коллбэк для хука:
C++:
Код:
#include "sampapi/CChat.h"
void
HOOK_after_samp_init
(
)
{
static
bool
inited
=
false
;
// переменная инициализации
namespace
samp
=
sampapi
::
v037r3
;
// Ваша версия сампа, у меня это 037r3
if
(
!
inited
&&
samp
::
RefChat
(
)
!=
nullptr
)
{
// если еще не инициализировались, и чат сампа уже инициализировался
samp
::
RefChat
(
)
->
AddMessage
(
0xFFFFFFFF
,
"Этот текст выведен после инициализации сампа"
)
;
// Выводим сообщение
samp
::
RefChat
(
)
->
m_debugColor
=
0xFFFF0000
;
// Меняем цвет системных сообщений сампа на красный
inited
=
true
;
// отмечаем что иницализировались
}
}
аналогичен
Код:
SF->getSAMP()->getChat()
Подключаем нашу функцию к хуку:
C++:
Код:
BOOL APIENTRY
DllMain
(
HMODULE hModule
,
DWORD ul_reason_for_call
,
LPVOID lpReserved
)
{
switch
(
ul_reason_for_call
)
{
case
DLL_PROCESS_ATTACH
:
DisableThreadLibraryCalls
(
hModule
)
;
samp_init_hook
.
after
.
connect
(
HOOK_after_samp_init
)
;
// Подключаем нашу функцию-коллбэк после вызова CHud::DrawRadar
break
;
case
DLL_PROCESS_DETACH
:
break
;
}
return
TRUE
;
}
Сообщение от Спойлер
C++:
Код:
#include
#include "sampapi/CChat.h"
#include "kthook/kthook.hpp"
using
CHud__DrawRadar
=
void
(
__cdecl
*
)
(
)
;
// Прототип CHud::DrawRadar
kthook
::
kthook_simple_t
samp_init_hook
{
reinterpret_cast
(
0x58A330
)
}
;
// хук на CHud::DrawRadar
void
HOOK_after_samp_init
(
)
{
static
bool
inited
=
false
;
// переменная инициализации
namespace
samp
=
sampapi
::
v037r3
;
// Ваша версия сампа, у меня это 037r3
if
(
!
inited
&&
samp
::
RefChat
(
)
!=
nullptr
)
{
// если еще не инициализировались, и чат сампа уже инициализировался
samp
::
RefChat
(
)
->
AddMessage
(
0xFFFFFFFF
,
"Этот текст выведен после инициализации сампа"
)
;
// Выводим сообщение
samp
::
RefChat
(
)
->
m_debugColor
=
0xFFFF0000
;
// Меняем цвет системных сообщений сампа на красный
inited
=
true
;
// отмечаем что иницализировались
}
}
BOOL APIENTRY
DllMain
(
HMODULE hModule
,
DWORD ul_reason_for_call
,
LPVOID lpReserved
)
{
switch
(
ul_reason_for_call
)
{
case
DLL_PROCESS_ATTACH
:
DisableThreadLibraryCalls
(
hModule
)
;
samp_init_hook
.
after
.
connect
(
HOOK_after_samp_init
)
;
// Подключаем нашу функцию-коллбэк после вызова CHud::DrawRadar
break
;
case
DLL_PROCESS_DETACH
:
break
;
}
return
TRUE
;
}
Компилируем, запускаем и видим:
|
|
|
|
|
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
|
|
|
|