Другое С/С++ Вопрос - Ответ

вайега52

cache miss
Модератор
3,060
3,294
Вопрос по поводу RakClient.h
Как правильно работать с Receive? То-есть, как правильно получать пакеты исходящие от сервера?
Вопрос в том, где это делать? В игровом цикле? Нужна ли какая-то задержка?

RakNet:
virtual Packet* Receive(void);
P.S. Прикол в том, что когда я использую Receive, то как будто я перехватываю пакет, и дальше уже никакие пакеты от клиента на сервер не идут.
Ты это делаешь внутри своего самп клиента или хукаешь самп.длл?

Если второй вариант, то тебе надо хукать вызов RakClient::Receive - вызывать оригинал, сохранять результат (полученный пакет), обрабатывать его, если это нужный тебе пакет и уже в зависимости от нужд возвращать из Хука либо nullptr (самп его не прочитает), либо результат вызова оригинала
 

swlm

Участник
63
33
Ты это делаешь внутри своего самп клиента или хукаешь самп.длл?

Если второй вариант, то тебе надо хукать вызов RakClient::Receive - вызывать оригинал, сохранять результат (полученный пакет), обрабатывать его, если это нужный тебе пакет и уже в зависимости от нужд возвращать из Хука либо nullptr (самп его не прочитает), либо результат вызова оригинала
P.S. Я это делал в своём самп-клиенте.

Спасибо. Я так и думал, что нужно хукать вызов RakClient::Receive.
А теперь вопрос, как правильно хукать вызов RakClient::Receive?
Посмотрел в IDA PRO (sampr3.idb)
Я так понимаю, там нужно мутить что-то с RakClientInterface_vtbl?
Получать указатель на RakClientInterface, а потом с помощью оффсетов хукать функцию Receive?
 
Последнее редактирование:

вайега52

cache miss
Модератор
3,060
3,294
P.S. Я это делал в своём самп-клиенте.

Спасибо. Я так и думал, что нужно хукать вызов RakClient::Receive.
А теперь вопрос, как правильно хукать вызов RakClient::Receive?
Посмотрел в IDA PRO (sampr3.idb)
Я так понимаю, там нужно мутить что-то с RakClientInterface_vtbl?
Получать указатель на RakClientInterface, а потом с помощью оффсетов хукать функцию Receive?
в структуре CNetGame есть указатель на RakClientInterface (pNetGame + 0x2C на R3), можешь от туда его получить и изменять указатель на метод внутри самой вмт. Либо же можешь найти адрес самой функции и хукать ее (samp.dll + 0x34AC0 на R3)
 

вайега52

cache miss
Модератор
3,060
3,294
как полностью отключить pause mune ( esc )? пробовал отключить рендер по итогу при esc экран черный и выйти из esc не получалось
Из самого простого - хукнуть WNDPROC и не пропускать сообщение для VK_ESCAPE
 
  • Нравится
Реакции: tanksoftik

swlm

Участник
63
33
в структуре CNetGame есть указатель на RakClientInterface (pNetGame + 0x2C на R3), можешь от туда его получить и изменять указатель на метод внутри самой вмт. Либо же можешь найти адрес самой функции и хукать ее (samp.dll + 0x34AC0 на R3)
Вот, смотри, я сделал вот так:


C++:
bool Hooks::HookReceive() {
    void** vtable = reinterpret_cast<void**>(AVSSync::getRakClientIntf());
    if (!vtable) {
        return false;
    }

    void* receiveAddr = vtable[9];

    MH_STATUS createStatus = MH_CreateHook(receiveAddr, &HookedReceive, reinterpret_cast<void**>(&originalReceive));
    if (createStatus != MH_OK) {
        return false;
    }

    MH_STATUS enableStatus = MH_EnableHook(receiveAddr);
    if (enableStatus != MH_OK) {
        return false;
    }

    std::cout << "Receive hooked successfully!" << std::endl;
    return true;
}

Это правильно? getRakClientIntf() возвращает указатель на RakClientInterface*
 

вайега52

cache miss
Модератор
3,060
3,294
Вот, смотри, я сделал вот так:


C++:
bool Hooks::HookReceive() {
    void** vtable = reinterpret_cast<void**>(AVSSync::getRakClientIntf());
    if (!vtable) {
        return false;
    }

    void* receiveAddr = vtable[9];

    MH_STATUS createStatus = MH_CreateHook(receiveAddr, &HookedReceive, reinterpret_cast<void**>(&originalReceive));
    if (createStatus != MH_OK) {
        return false;
    }

    MH_STATUS enableStatus = MH_EnableHook(receiveAddr);
    if (enableStatus != MH_OK) {
        return false;
    }

    std::cout << "Receive hooked successfully!" << std::endl;
    return true;
}

Это правильно? getRakClientIntf() возвращает указатель на RakClientInterface*
Ты на какой версии сампа? Если р3, то receiveAddr - samp.dll должен совпадать 0x34AC0
 

swlm

Участник
63
33
Во, сделал так:
И хук заработал, только как теперь работать с пакетами, когда я пытаюсь получить что-то из пакета, происходит краш.


C++:
bool Hooks::HookReceive() {
    Packet* __fastcall HookedReceive(RakClientInterface__vtable* thisPtr, void* edx) {
        Packet* packet = originalReceive(thisPtr);

        return packet;
    }


    HMODULE sampModule = GetModuleHandleA("samp.dll");
    if (!sampModule) {
        return false;
    }

    // Получаем указатель на рак клиент
    RakClientInterface** rakclient = reinterpret_cast<RakClientInterface**>(AVSSync::getRakClientIntf());
    if (!rakclient) {
        return false;
    }

    DWORD* vTable = *reinterpret_cast<DWORD**>(rakclient);
    LPVOID target = reinterpret_cast<LPVOID>(vTable[8]);

    MH_STATUS createStatus = MH_CreateHook(target, &HookedReceive, reinterpret_cast<void**>(&originalReceive));
    if (createStatus != MH_OK) {
        return false;
    }

    MH_STATUS enableStatus = MH_EnableHook(target);
    if (enableStatus != MH_OK) {
        return false;
    }

    std::cout << "Receive hooked successfully!" << std::endl;
    return true;
}

Ты на какой версии сампа? Если р3, то receiveAddr - samp.dll должен совпадать 0x34AC0
На R3, но нет, не совпадает: 0x5CAF637A
 
Последнее редактирование:

AdCKuY_DpO4uLa

Адский дрочер
Друг
405
865
 

swlm

Участник
63
33
ладно, сделаю тогда на функцию сразу...
 

вайега52

cache miss
Модератор
3,060
3,294
получить что-то из пакета, происходит краш.
Потому-что эта функция вызывается в бесконечном цикле игры и не морозит основной поток, т.е. если нет пакета для получения, возвращается nullptr (под капотом там обычное получение пакета из потокобезопасной очереди, которая пополняется внутри ракпира). Делай проверку на nullptr и должно работать
 

swlm

Участник
63
33
Потому-что эта функция вызывается в бесконечном цикле игры и не морозит основной поток, т.е. если нет пакета для получения, возвращается nullptr (под капотом там обычное получение пакета из потокобезопасной очереди, которая пополняется внутри ракпира). Делай проверку на nullptr и должно работать
Да, сяб, проверил и всё работает.

Получается этот вариант хука правильный?
C++:
bool Hooks::HookReceive() {
    HMODULE sampModule = GetModuleHandleA("samp.dll");
    if (!sampModule) {
        return false;
    }

    // Получаем указатель на рак клиент
    RakClientInterface** rakclient = reinterpret_cast<RakClientInterface**>(AVSSync::getRakClientIntf());
    if (!rakclient) {
        return false;
    }

    DWORD* vTable = *reinterpret_cast<DWORD**>(rakclient);
    LPVOID target = reinterpret_cast<LPVOID>(vTable[8]);

    MH_STATUS createStatus = MH_CreateHook(target, &HookedReceive, reinterpret_cast<void**>(&originalReceive));
    if (createStatus != MH_OK) {
        return false;
    }

    MH_STATUS enableStatus = MH_EnableHook(target);
    if (enableStatus != MH_OK) {
        return false;
    }

    std::cout << "Receive hooked successfully!" << std::endl;
    return true;
}
 
  • Нравится
Реакции: вайега52

вайега52

cache miss
Модератор
3,060
3,294
Да, сяб, проверил и всё работает.

Получается этот вариант хука правильный?
C++:
bool Hooks::HookReceive() {
    HMODULE sampModule = GetModuleHandleA("samp.dll");
    if (!sampModule) {
        return false;
    }

    // Получаем указатель на рак клиент
    RakClientInterface** rakclient = reinterpret_cast<RakClientInterface**>(AVSSync::getRakClientIntf());
    if (!rakclient) {
        return false;
    }

    DWORD* vTable = *reinterpret_cast<DWORD**>(rakclient);
    LPVOID target = reinterpret_cast<LPVOID>(vTable[8]);

    MH_STATUS createStatus = MH_CreateHook(target, &HookedReceive, reinterpret_cast<void**>(&originalReceive));
    if (createStatus != MH_OK) {
        return false;
    }

    MH_STATUS enableStatus = MH_EnableHook(target);
    if (enableStatus != MH_OK) {
        return false;
    }

    std::cout << "Receive hooked successfully!" << std::endl;
    return true;
}
Если указатель на ракклиент верный, то да по сути (я минхуком не пользовался, не знаю,умеет ли он в вмт)
 
  • Нравится
Реакции: swlm

swlm

Участник
63
33
Пытаюсь получить координаты локального игрока в мире, но почему-то они постоянно 0.
Что не так?


cpp:
Это R3

CVector* pos = samp->getPos();
printf("x: %f, y: %f, z: %f\n", pos->x, pos->y, pos->z);

uintptr_t* getPlayerEntity() {
    uintptr_t player_pool = getPlayerPool();
    uintptr_t local_info = player_pool + 0x2F14;

    return reinterpret_cast<uintptr_t*>(local_info + 0x2A4);
}

CVector* getPos() {
    uintptr_t* gamePed = getPlayerEntity();
    if (gamePed != nullptr) {
        return reinterpret_cast<CVector*(__thiscall*)(uintptr_t*)>(0x4043A0)(gamePed);
    }

    //return CVector(1.0, 5.0, 10.0);
}

// 0x4043A0
CSimpleTransform *__thiscall CEntity::GetPosition(CEntity *this) - функция в IDA PRO
 

вайега52

cache miss
Модератор
3,060
3,294
Пытаюсь получить координаты локального игрока в мире, но почему-то они постоянно 0.
Что не так?


cpp:
Это R3

CVector* pos = samp->getPos();
printf("x: %f, y: %f, z: %f\n", pos->x, pos->y, pos->z);

uintptr_t* getPlayerEntity() {
    uintptr_t player_pool = getPlayerPool();
    uintptr_t local_info = player_pool + 0x2F14;

    return reinterpret_cast<uintptr_t*>(local_info + 0x2A4);
}

CVector* getPos() {
    uintptr_t* gamePed = getPlayerEntity();
    if (gamePed != nullptr) {
        return reinterpret_cast<CVector*(__thiscall*)(uintptr_t*)>(0x4043A0)(gamePed);
    }

    //return CVector(1.0, 5.0, 10.0);
}

// 0x4043A0
CSimpleTransform *__thiscall CEntity::GetPosition(CEntity *this) - функция в IDA PRO
Лучше используй псдк, получай CPed* локального игрока через FindPlayerPed() и из него доставай матрицу (вроде даже есть метод GetPosition)
 

swlm

Участник
63
33
Лучше используй псдк, получай CPed* локального игрока через FindPlayerPed() и из него доставай матрицу (вроде даже есть метод GetPosition)
Не могу, у меня проект создан отдельно от plugin-sdk, если я его добавлю в ручную - то он работать не будет