Гайд Безопасная инициализация и работа с SAMP [3]

  1. Создание ASI-плагина с нуля
  2. Хуки – что это такое и как с ними работать
  3. Безопасная инициализация и работа с SAMP
  4. Работа с рендером и Directx9
  5. Обработка событий окна + ImGui

В этом гайде будет рассказано как инициализироваться без потоков, а также как работать с SAMP'ом

При использовании на других ресурсах необходимо указание авторства и ссылки на оригинальную темы!

Все действия производились на Visual Studio 2019 с параметром /std:c++17, в других версиях интерфейс может отличаться.

И так, начнем:

Создаем новый проект, настраиваем его.
В свойствах проекта, в вкладке общие, стандарт языка C++ ставим /std:c++17

Добавляем sampapi в наш проект:

Первый способ:

  1. В верхнем меню жмем Git -> Создать репозиторий Git(Create git repository)
  2. В открывшемся окне выбираем либо github репозиторий, либо локальный репозиторий и жмем Создать.
  3. Снова жмем Git -> Открыть в командной строке (Open in command line).
  4. В консоли пишем git submodule add https://github.com/BlastHackNet/SAMP-API.git
  5. Ждем завершения операции и далее жмем Файл(File) -> Добавить(Add) -> Существующий проект (Existing projeect). Открываем папку с нашим проектом, заходим в папку SAMP-API и выбираем sampapi.vcxproj.
  6. Открываем настройки проекта, выбираем C/C++ -> Общие -> Дополнительные каталоги включаемых файлов(Additional directories of included files). Жмем изменить
    В открывшемся окне жмем на иконку файла со звездочкой, и жмем на появившуюся кнопку ...
    Переходим в директорию path_to_project\SAMP-API\include и жмем выбор папки.
  7. Переходим в настройки проекта sampapi
    Набор инструментов платформы(Build tools) - выбираем свое(у меня это v142
    Версия пакета SDK для Windows - выбираем свое(у меня это 10.0)
  8. Заходим в настройки нашего основного проекта, Компоновщик(Linker) -> Дополнительные каталоги библиотек(Additional library directories)
    Повторяем те же самые операции что в шаге 6, но выбираем папку path_to_project\SAMP-API\build\bin
  9. Далее переходим в вкладку Ввод(Input) и в поле Дополнительные зависимости(Additional dependecies) в начало вписываем Release\sampapi.lib; для Release конфигурации проект, и Debug\sampapi.lib;. Точка с запятой ОБЯЗАТЕЛЬНА
  10. Жмем правой кнопкой по проекту sampapi, Только проект -> Собрать только sampapi(делаем это для Release и Debug конфигураций)
Второй способ:
Скачиваем репозиторий, распаковываем по пути path_to_project
Повторяем шаги 5-10 из первого способа.

Готово, мы подключили sampapi

Теперь добавим библиотеку для хуков в наш проект:
Начну свое описание с подключения моей библиотеки для хуков - kthook
  1. Скачиваем kthook из репозитория и распаковываем в себе в папку с кодом(Пкм по проекту -> открыть папку в проводнике).
    Папку tests перекидывать к себе не нужно.
  2. Скачиваем ktsignal из репозитория и распаковываем содержимое ktsignal-master в папку kthook\ktsignal
  3. Жмем показать все файлы
    1631461120229.png
    ПКМ по папке kthook -> Включить в проект
  4. Т.к. мы не используем CMake, тогда мы должны вручную переназначить все зависимости для kthook
  5. Добавляем папку kthook в Дополнительные каталоги включаемых файлов(Additional directories of included files) (как в шаге 6 у sampapi)
  6. В kthook.hpp изменяем #include "ktsignal/ktsignal.hpp" на #include "ktsignal/include/ktsignal/ktsignal.hpp"
  7. Также ради собственного удобства добавляем kthook/include Дополнительные каталоги включаемых файлов(Additional directories of included files)

Вместо kthook могу посоветовать вам SRHook либо MinHook
SRHook подключается также как и kthook, MinHook можно подключить также двумя способами, как и sampapi.
Но я рекомендую установить его через vcpkg. vcpkg install minhook

И теперь перейдем к написанию кода:
SAMP инициализирует свои структуры в вызове CHud::DrawRadar, поэтому мы перехватим эту функцию, и после ее вызова будем уверены что самп инициализировался.
Для инициализации плагина лично я обычно использую хук на CTimer::Update
C++:
using CTimer__Update = void(__cdecl*)();
void* func_addr = reinterpret_cast<void*>(0x561B10);

Создаем хук:
C++:
#include "kthook/kthook.hpp"

using CHud__DrawRadar = void(__cdecl*)(); // Прототип CHud::DrawRadar

kthook::kthook_simple_t<CHud__DrawRadar> samp_init_hook{ reinterpret_cast<void*>(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; // отмечаем что иницализировались
    }
}
samp::RefChat() аналогичен 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 <windows.h>
#include "sampapi/CChat.h"
#include "kthook/kthook.hpp"

using CHud__DrawRadar = void(__cdecl*)(); // Прототип CHud::DrawRadar

kthook::kthook_simple_t<CHud__DrawRadar> samp_init_hook{ reinterpret_cast<void*>(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;
}

Компилируем, запускаем и видим:
1631464876180.png
 
Последнее редактирование:

EclipsedFlow

Известный
Проверенный
1,040
461
почему папка xbyak пуста, хотя от xbyak.h многое зависит (файл которого нет)?


Скачал с репозитория xbyak, закинул содержимое в папку с этим же названием. Все отлично, но есть одна проблема. EO135 пространство имен "kthook" не содержит члена "kthook_simple_t"
В зависимости от версии kthook'a название методов могут меняться.
 

ya_noob

Участник
57
7
почему папка xbyak пуста, хотя от xbyak.h многое зависит (файл которого нет)?


Скачал с репозитория xbyak, закинул содержимое в папку с этим же названием. Все отлично, но есть одна проблема. EO135 пространство имен "kthook" не содержит члена "kthook_simple_t"
Заметил что в пространствах имен kthook нет члена "kthook_simple_t", но есть "kthook_simple", "kthook_naked", "kthook_option", "kthook_signal". "kthook_simple_t" НЕ существует в природе, убрав t на конце, Visual Studio ругается на "kthook::kthook_simple<CHud_DrawRadar, kthook::kNone> не содержит члена "after""

Заметил что в пространствах имен kthook нет члена "kthook_simple_t", но есть "kthook_simple", "kthook_naked", "kthook_option", "kthook_signal". "kthook_simple_t" НЕ существует в природе, убрав t на конце, Visual Studio ругается на "kthook::kthook_simple<CHud_DrawRadar, kthook::kNone> не содержит члена "after""
член after находится в kthook_impl.hpp, и в этом самом "kthook_impl.hpp" 231 ошибки, первые ошибки которые увидел это "std::uint32_t", подключил <cstdint>, осталось 126 ошибок. При этом эти ошибки ссылаются на саму Visual Studio. kin4stat решил потроллить?

Почему в kthook_impl.hpp 231 ошибка?
 

Вложения

  • Снимок экрана (192).png
    Снимок экрана (192).png
    120.2 KB · Просмотры: 45
Последнее редактирование:
  • Нравится
Реакции: isaacrulz23

Musaigen

abobusnik
Проверенный
1,582
1,301
kthook::kthook_simple<CHud_DrawRadar, kthook::kNone> не содержит члена "after""
У симпловых хуков нет before/after, кинчстат понасоздавал классов, но не обновил примеры что на гите, что тут
Почему в kthook_impl.hpp 231 ошибка?
Потому что не умеешь пользоваться гитом, скорее всего у тебя багается интеллисенс из-за не подключенного ktsignal(скорее всего он не установлен у тебя), больше добавить не могу
 

ya_noob

Участник
57
7
У симпловых хуков нет before/after, кинчстат понасоздавал классов, но не обновил примеры что на гите, что тут

Потому что не умеешь пользоваться гитом, скорее всего у тебя багается интеллисенс из-за не подключенного ktsignal(скорее всего он не установлен у тебя), больше добавить не могу
std 17. ktsignal и xbyak скачал с репозитория, пути к ним указал в настройках проекта, вставил готовый код, ошибка в одном файле, а из него ошибка в другом файле, эффект домино. kthook_simple_t заменил на kthook_simple. Впрочем сделал все по инструкции в гайде, он не работает нормально. SRHook ошибок не выдает.
 

Вложения

  • Снимок экрана (227).png
    Снимок экрана (227).png
    172.5 KB · Просмотры: 34

Musaigen

abobusnik
Проверенный
1,582
1,301
std 17. ktsignal и xbyak скачал с репозитория, пути к ним указал в настройках проекта, вставил готовый код, ошибка в одном файле, а из него ошибка в другом файле, эффект домино. kthook_simple_t заменил на kthook_simple. Впрочем сделал все по инструкции в гайде, он не работает нормально. SRHook ошибок не выдает.
ты читаешь вообще?

У симпловых хуков нет before/after, кинчстат понасоздавал классов, но не обновил примеры что на гите, что тут