Гайд RakNet в собейте и в SF! (SAMP 0.3.7)

Тема в разделе "C/C++", создана пользователем fiigaro, 19 июл 2018.

Метки:
  1. fiigaro

    fiigaro Потрачен

    Регистрация:
    8 июн 2017
    Сообщения:
    37
    Симпатии:
    57
    RakNet. На версии SAMP 0.3.7

    Кратко и понятно о движке и его использовании в собейте и сампфункц!

    И так RakNet это сетевой движок для связи клиента с сервером и наоборот. Общаются они с помощью обычных пакетов и RPC.

    Для понятности, представим себе посылку, которую мы будем отправлять. upload_2018-7-19_20-6-16.png



    Как и обычная посылка, пакет должен иметь свой ID. Например это будет ID_PLAYER_SYNC он равен 207. В нём будут такие параметры как позиция игрока, скорость и другие, вот полная структура:
    upload_2018-7-19_20-6-3.png




    Прежде чем отправить эту посылку нужно заполнить её вот этой структурой, запишем позицию скорость и здоровье, остальное оставим по нулям. Чтоб не записывать в каждое поле ноль можно просто написать после обьявления структуры ZeroMemory(&название вашей струкуты, sizeof(stOnFootData));

    upload_2018-7-19_20-6-32.png

    Вот мы обьявили структуру как data, обнулили все значения(*образно*) и записали в позицию координаты Groove Street а в скорость записали ускорение в сторону поворота игрока(небольшое чтоб было заметней нужно домножить на 10 и поднять педа, тоесть data.fPosition[2]+=1.5)

    Так же есть fQuaternion, это такая вещь, что то типа замены матрицы, которая отвечает за поворот игрока.

    Тут я не буду обьяснять как перевести матрицу поворота в кватернион, но возможно в скором будущем обьясню.

    Ну вот мы подготовили груз к отправке теперь его нужно положить в коробку. Коробка это выражение образное ,на самом деле в RakNet это последовательность битов(байтов) так называемый BitStream.

    Создаём битстрим строчкой <BitStream bs;>

    И так, как говорилось ранее сначало нужно записать ID нашего пакета, тоесть ID_PLAYER_SYNC, делается это просто <bs.Write((BYTE)ID_PLAYER_SYNC);>

    Записали в битстрим байт с идом пакета, затем записываем всю структуру, так называемый груз который мы подготавливали ранее. Выглядит это таким образом <bs.Write((PCHAR)&data, sizeof(stOnFootData));>

    Ну вот как говорится и рыбку сьели и на хуй сели, теперь можно отправлять наш пакет на сервер, делается это так: <g_RakClient->Send(&bs);> (в случае собейта) а если у вас сф, то делается это так <SF->getRakNet()->SendPacket(&bsOnfootSync);>

    И на выходе вы получите такую картину:

    upload_2018-7-19_20-6-54.png

    ~Не обращайте на приставку LQ_ внимания, это обозначение битстрима в LiquidMod в который я это решил пихнуть, у вас же будет просто BitStream.~

    Но что же произойдёт после того как мы отправили пакет? Ну начнём с того что отправим мы его один раз, а пакеты PLAYER_SYNC отправляются довольно часто самим самп клиентом, примерно каждую секунду когда вы стоите, и очень быстро когда двигаетесь. Но на выходе вы получите быстрый телепорт на грув с ускорением в сторону которую вы смотрите и телепорт обратно. (!Важная инфа) Синхра она на то и синхра что вы её не видите, увидят этот телепорт только остальные люди!

    RakNet хуки!

    Как вы уже знаете, пакеты не только исходят от нас но и приходят к нам, всё тот же PLAYER, BULLET, VEHICLE и т.д и мы их уже умеем отправлять НО! Что если мы хотим не отправлять пакеты сами, а заменять те которые уже исходят от нас? В этом нам помогут хуки!

    Хук исходящей синхры.

    ~Для тех у кого сф пример будет потом, наберитесь терпения~

    В собейте(mod_sa на 0.3.7 R1-R2 etc.) есть уже готовый хук исходящей синхры, он находится в файле cheat_samp.cpp и является функцией bool OnSendPacket(BitStream *parameters, PacketPriority priority, PacketReliability reliability, char orderingChannel){ … }

    И так всякий раз когда мы отправляем пакет, в собейте вызывается функция OnSendPacket

    Ловится битстрим, как мы говорили в прошлом примере коробка и выполняются некие действия с ними. Рассмотрим простой пример GhostMod, когда другие игроки смогут проходить сквозь нас. Принцип простой: Ловим пакет, заменяем параметр byteSpecialAction на 3. И так начнём.

    Для начала узнаем какой пакет у нас отловился, для этого пишем <parameters->ResetReadPointer();

    parameters->Read(packetId);>

    ResetReadPointer обозначает то что мы сдвинули указатель чтения пакета в 0, это можно сравнить с курсором в текстовом редакторе.
    upload_2018-7-19_20-12-43.png
    Теперь после обнуления перед курсором стоит ид пакета, после прочтения которого, «курсор»

    сдвинется за него. Далее мы проверяем если ид пакета равен 207 (ID_PLAYER_SYNC) то начинаем редактировать.

    Чтоб не читать всё подряд то нужного нам значения, мы поставим нужный нам сдвиг байтов, тоесть переместим его сами. Для этого есть функция SetReadOffset(int offset). Чтоб узнать на каком оффсете расположен byteSpecialAction нужно посчитать сколько было байт информации до него. Я этого делать не буду так как у меня есть сосчитаные оффсеты, которые я приложу к данному «гайду».

    И так оффсет у нас равен 37, пишем parameters->SetReadOffset(37);

    Отлично, мы сдвинули курсор в нужное нам место, теперь картина выглядит примерно вот так:
    upload_2018-7-19_20-11-3.png
    Можно прочитать byteSpecialAction в какую нибудь переменную например:

    uint8_t sAction;

    parameters->Read(sAction);

    Но нам же нужно просто заменить?

    Тогда делаем parameters->SetWriteOffset(37);

    WriteOffset это уже курсор записи, а не чтения.

    Запись выглядит так, будто был нажат Insert поэтому после записи какого то значения, остальное не сдвинется а заменится тем что вводили. И так поставили мы оффсет теперь parameters->Write((uint8_t)3);

    Отлично! Мы заменили наше значение, теперь отпускам пакет на свободу return true;

    Получилось примерно следущее:

    upload_2018-7-19_20-8-22.png

    А теперь главный вопрос: Как же быть с SF?

    А всё очень просто, мы просто создадим такую же функу как в собейте.



    Сначала регистрируем коллбэк функи в mainloop (там где вся инициализация)

    SF->getRakNet()->registerRakNetCallback( RakNetScriptHookType::RAKHOOK_TYPE_OUTCOMING_PACKET, OnSendPacket );
    Затем создаём функу

    bool CALLBACK outcomingData( stRakNetHookParams *params ){

    }


    Теперь у нас есть удобная структурка в отличии от собейта где мы сразу можем достать ид пакета, вот так: if(params->packetId == ID_PLAYER_SYNC){ … }

    Битстрим идёт отдельно как params->bitStream НО! В нём по прежднему лежит пакет айди, не стоит думать что он отдельно! Дальше всё происходит так же только вместа parameters мы пишем params->bitStream

    Хук входящей синхры.
    upload_2018-7-19_20-8-35.png
    Как я уже говорил, пакеты идут не только от нас, но и к нам! Поэтому логично тебе подумать что входящие пакеты тоже можно ловить. И да, это так! Можно стопануть например унок синхру(она нужна для синхронизации пустых машин, исходят когда ты толкаешь машину) и пояснить за позицию например.

    Чтобы не ебаться лишний раз с оффсетами мы прочитаем всю структуру разом. Функа для хука входящих пакетов в собейте находится в файле cheat_samp.cpp и является функцией bool OnReceivePacket(Packet *p){...}

    Для начала получим пакет айди, он находится в p->data[0] и проверяем

    if(p->data[0] == ID_UNOCCUPIED_SYNC){ … }

    Затем нам нужно из пакета получить битстрим, делаем это так: BitStream bsUnoData((unsigned char *)p->data, p->length, false);

    Получили битстрим затем читаем его в структуру UnoData(назвать можно как угодно хоть huimorzha)





    stUnoccupiedData UnoData;

    bsUnoData.IgnoreBits(8);

    bsUnoData.Read(playerId);

    bsUnoData.Read((PCHAR)&UnoData, sizeof(stUnoccupiedData));

    Теперь просим пакет пояснить за позицию которую он шлёт, делается это так

    if(UnoData.fPosition[2] > 20000 || UnoData.fPosition[2] < -20000){

    return false;

    }

    проверяем если позиция больше 20000 или меньше -20000 значит пакет плохой и тот кто его отправил юзает крашер и хочет нас крашнуть. Значит нам нужно как то игнорировать этот пакет, тоесть не пустить его к нам в клиент дабы избежать краша. Можно просто написать return false; а можно написать p->data[0] = 255; что в принципе даст одно и тоже.



    Что же делать в SF? Ну тут опять же всё просто, регистрируем коллбэк в mainloop инициализации:

    SF->getRakNet()->registerRakNetCallback( RakNetScriptHookType::RAKHOOK_TYPE_INCOMING_PACKET, OnRecivePacket );

    И создаём функу приёма пакета.

    bool CALLBACK OnRecivePacket( stRakNetHookParams *params ){
    ...
    }

    Далее всё делается ещё проще, битстрим лежит всё там же в params->bitStream и пакет айди тоже. Читаем как исходящий а чтоб не пустить его, так же как в исходящем пишем return false;





    На этом по ракнету у меня всё, RPC лень писать, возможно мне припрёт и я напишу про них, удачного кодинга вашего собейта/сфплагина

    с вами был zH.F11GAR0





















    Thanks to:

    FYP – for SF and mod_sa source

    MasterZero – for motivation to make cheats

    GH0ST – for help with sobeit and c++

    DR8GUN8V – for testing my shit

    0pc0d3r – for good nastroenie and motivation to reverce injenering shit and (?)

    Zeta-Hack team – for motivation to fuCK SAMP JAJAJA
     

    Вложения:

    #1 fiigaro, 19 июл 2018
    Последнее редактирование: 20 июл 2018
    Classic., suic1de, LaRossa и 24 другим нравится это.
  2. kawa operand

    kawa operand перерывпятьминут

    Регистрация:
    15 апр 2017
    Сообщения:
    621
    Симпатии:
    369
    лайк за рисунки вообще круто описал офигенно четко красава репспект

    (однако сейчас придет дарккнайт тебя обсирать наверное будь готов)
     
    Romelo, mkrn и fiigaro нравится это.
  3. Toopie

    Toopie Активный участник

    Регистрация:
    21 янв 2018
    Сообщения:
    28
    Симпатии:
    6
    мене нравицо я 2 клас ставит))))
     
  4. ArtzEs

    ArtzEs Участник

    Регистрация:
    9 июл 2017
    Сообщения:
    7
    Симпатии:
    2
    так себе тутор, для новичков надо расписывать все конкретно ,каждую частичку кода
     
  5. Musaigen

    Musaigen мой проект лайкнул пиксель
    Проверенный

    Регистрация:
    1 апр 2018
    Сообщения:
    763
    Симпатии:
    278
    Плохой пакет начинается в принципе уже с 10000.0, лимиты карты гта са это 2600 и -2600 кроме оси Z, дальше уже идут краши или попытки телепортировать в загрузку
     
  6. praiki

    praiki Участник

    Регистрация:
    20 апр 2018
    Сообщения:
    13
    Симпатии:
    0
    make a tutorial for english please
     
  7. fiigaro

    fiigaro Потрачен

    Регистрация:
    8 июн 2017
    Сообщения:
    37
    Симпатии:
    57
    WorldBounds 20000 являются пределами, за которыми хуярит лоад, 2600 и -2600 это только края карты, по Z стрим бесконечный однако при больших значениях тоже лоад, вообще пример тривиальный но от некоторых крашеров из ликвида спасёт)
     
  8. AlexDrift

    AlexDrift Активный участник

    Регистрация:
    12 апр 2013
    Сообщения:
    43
    Симпатии:
    25
    лимит по кордам до 19999, дальше лоад
     
  9. fiigaro

    fiigaro Потрачен

    Регистрация:
    8 июн 2017
    Сообщения:
    37
    Симпатии:
    57
    I will do in the near future!
     
    praiki нравится это.
  10. Dark_Knight

    Dark_Knight Режим чтения

    Регистрация:
    18 мар 2013
    Сообщения:
    3.367
    Симпатии:
    1.669
    Традициям изменять нельзя. Кеша, ты нубососяра.
    По теме, красиво.
     
    *Raymond* и shinoa нравится это.
  11. Revalto

    Revalto Свой человек

    Регистрация:
    13 фев 2016
    Сообщения:
    330
    Симпатии:
    69
    Годно :D
    Но код бы мог закинуть в специальный код
    [​IMG]
     
  12. uryukhai

    uryukhai Интересующийся

    Регистрация:
    1 июл 2017
    Сообщения:
    167
    Симпатии:
    49
    где лоад?
    upload_2018-7-20_8-42-26.png
     
  13. Azller Lollison

    Azller Lollison Lua Dev | vk.com/azller
    Друг

    Регистрация:
    20 июл 2017
    Сообщения:
    687
    Симпатии:
    535
  14. fiigaro

    fiigaro Потрачен

    Регистрация:
    8 июн 2017
    Сообщения:
    37
    Симпатии:
    57
    бесполезно обьяснять что то юзерам слономойки, их украшь в нулину они всёравно скажут что краш не от позиции)
     
    Azller Lollison нравится это.
  15. kawa operand

    kawa operand перерывпятьминут

    Регистрация:
    15 апр 2017
    Сообщения:
    621
    Симпатии:
    369
    да вы хоть вплавь туда на чистой гта доберитесь вас никто в загрузку не кинет :/
     
  16. fiigaro

    fiigaro Потрачен

    Регистрация:
    8 июн 2017
    Сообщения:
    37
    Симпатии:
    57
    пошли угбейз проверим?)
     
  17. kawa operand

    kawa operand перерывпятьминут

    Регистрация:
    15 апр 2017
    Сообщения:
    621
    Симпатии:
    369
    {$cleo .cs}
    0000: NOP
    
    while true
        wait 0
        if 0ADC:   test_cheat "6"
        then
            actor.PutAt($PLAYER_ACTOR, 1000032.56, 1000016.38, 9999985.00)
        end
    end
    сам зайди проверь
     
  18. fiigaro

    fiigaro Потрачен

    Регистрация:
    8 июн 2017
    Сообщения:
    37
    Симпатии:
    57
    upload_2018-7-20_12-36-47.png
    специально для вас, дорогуши
     
  19. kawa operand

    kawa operand перерывпятьминут

    Регистрация:
    15 апр 2017
    Сообщения:
    621
    Симпатии:
    369
    ну и где загрузка
     
  20. fiigaro

    fiigaro Потрачен

    Регистрация:
    8 июн 2017
    Сообщения:
    37
    Симпатии:
    57
    видимо у нас разные понятия лоада
     
  21. AlexDrift

    AlexDrift Активный участник

    Регистрация:
    12 апр 2013
    Сообщения:
    43
    Симпатии:
    25
    Границы мира заканчиваются на 19999 и не ебет, там уже как шлюху ксаиобет
     
    Devil1606 нравится это.
  22. T1cK

    T1cK Интересующийся

    Регистрация:
    27 апр 2015
    Сообщения:
    137
    Симпатии:
    21
    Неплохой гайд! Внатуре неплохой!
    Всё расписано до мелочей, со сравнениями, а не просто "ну крч вот код, ебитес"
     
    fiigaro нравится это.