onfoot packet read

Smeruxa

t.me/smeruxa
Автор темы
Проверенный
1,391
735
Функция с чтением пакета: https://gitlab.com/blasthack/raksamp/-/blob/master/client/src/netgame.cpp#L127
Что я делаю не так? Почему не могу никак записать нормально синхру на плюсах?
8 бит я игнорирую в самом начале, перед getData
C++:
nlohmann::json getData(RakNet::BitStream* bs) {
    nlohmann::json data;

    uint16_t playerId;
    bool bHasLR, bHasUD, bHasSurfInfo, bAnimation;

    bs->Read(playerId);

    if (playerId < 0 || playerId > 1004) return data;
    sampapi::v037r1::Synchronization::OnfootData onfoot;
    memset(&onfoot, 0, sizeof(sampapi::v037r1::Synchronization::OnfootData));

    bs->Read(bHasLR);
    if (bHasLR) bs->Read(onfoot.m_controllerState.m_sLeftStickX);

    bs->Read(bHasUD);
    if (bHasUD) bs->Read(onfoot.m_controllerState.m_sLeftStickY);

    bs->Read(onfoot.m_controllerState.m_value);

    bs->Read(onfoot.m_position.x);
    bs->Read(onfoot.m_position.y);
    bs->Read(onfoot.m_position.z);

    bs->ReadNormQuat(
        onfoot.m_fQuaternion[0],
        onfoot.m_fQuaternion[1],
        onfoot.m_fQuaternion[2],
        onfoot.m_fQuaternion[3]
    );

    BYTE byteHealthArmour;
    bs->Read(byteHealthArmour);
    BYTE byteArmTemp = (byteHealthArmour & 0x0F);
    BYTE byteHlTemp = (byteHealthArmour >> 4);

    BYTE byteHealth = (byteHlTemp == 0xF) ? 100 : (byteHlTemp == 0 ? 0 : byteHlTemp * 7);
    BYTE byteArmour = (byteArmTemp == 0xF) ? 100 : (byteArmTemp == 0 ? 0 : byteArmTemp * 7);

    onfoot.m_nHealth = byteHealth;
    onfoot.m_nArmor = byteArmour;

    bs->Read(onfoot.m_nCurrentWeapon);
    bs->Read(onfoot.m_nSpecialAction);

    bs->ReadVector(
        onfoot.m_speed.x,
        onfoot.m_speed.y,
        onfoot.m_speed.z
    );

    bs->Read(bHasSurfInfo);
    if (bHasSurfInfo) {
        bs->Read(onfoot.m_nSurfingVehicleId);
        bs->Read(onfoot.m_surfingOffset.x);
        bs->Read(onfoot.m_surfingOffset.y);
        bs->Read(onfoot.m_surfingOffset.z);
    }
    else {
        onfoot.m_nSurfingVehicleId = -1;
    }

    uint16_t animId;
    bs->Read(bAnimation);
    if (bAnimation) {
        bs->Read(animId);
    }

    data["playerId"] = playerId;
    data["lrAnalog"] = (bHasLR) ? onfoot.m_controllerState.m_sLeftStickX : 0;
    data["udAnalog"] = (bHasUD) ? onfoot.m_controllerState.m_sLeftStickY : 0;
    data["wKeys"] = onfoot.m_controllerState.m_value;
    data["position"] = { onfoot.m_position.x, onfoot.m_position.y, onfoot.m_position.z };
    data["quaternion"] = { onfoot.m_fQuaternion[0], onfoot.m_fQuaternion[1], onfoot.m_fQuaternion[2], onfoot.m_fQuaternion[3] };
    data["health"] = onfoot.m_nHealth;
    data["armour"] = onfoot.m_nArmor;
    data["weapon"] = onfoot.m_nCurrentWeapon;
    data["specialAction"] = onfoot.m_nSpecialAction;
    data["moveSpeed"] = { onfoot.m_speed.x, onfoot.m_speed.y, onfoot.m_speed.z };
    data["surfingOffsets"] = (bHasSurfInfo) ?
        nlohmann::json::array({ onfoot.m_surfingOffset.x, onfoot.m_surfingOffset.y, onfoot.m_surfingOffset.z }) :
        nlohmann::json::array({ 0, 0, 0 });
    data["surfingVehicleId"] = (bHasSurfInfo) ? onfoot.m_nSurfingVehicleId : -1;
    data["animationId"] = (bAnimation) ? animId : 0;

    return data;
}
 

whyega52

Гений, миллионер, плейбой, долбаеб
Модератор
2,814
2,693
  • Нравится
Реакции: Smeruxa

whyega52

Гений, миллионер, плейбой, долбаеб
Модератор
2,814
2,693
  • Нравится
Реакции: Smeruxa

AdCKuY_DpO4uLa

Адский дрочер
Друг
327
684
слив сурсов триложи сампа. не рекомендую использовать json для хранения синхронизации, ибо это очень затратно по ресурсам, входящая синхра приходит обычно каждые ~15мс, но если это прям жизненно необходимо, то тогда лучше использовать уже заранее созданный объект nlohmann::json и уже в нем перезаписывать все данные.

C++:
    std::uint16_t playerId;
    bool bHasLR, bHasUD, bHasSurfInfo, bAnimation;
    stOnFootData OnFootData{};
    //The packet received from server is different

    bsPlayerSync.IgnoreBits(8); //ignore the packet id
    bsPlayerSync.Read(playerId);

    if (playerId >= SAMP_MAX_PLAYERS)
        return;

    auto& it = pNetGame->pools.mPlayerPool.find(playerId);
    if (it == pNetGame->pools.mPlayerPool.end())
        return;

    // LEFT/RIGHT KEYS
    bsPlayerSync.Read(bHasLR);
    if (bHasLR) bsPlayerSync.Read(OnFootData.m_ControllerState.m_sLeftStickX);

    // UP/DOWN KEYS
    bsPlayerSync.Read(bHasUD);
    if (bHasUD) bsPlayerSync.Read(OnFootData.m_ControllerState.m_sLeftStickY);

    // GENERAL KEYS
    bsPlayerSync.Read(OnFootData.m_ControllerState.m_value);


    // VECTOR POS
    bsPlayerSync.Read(OnFootData.m_Position.m_fPos[0]);
    bsPlayerSync.Read(OnFootData.m_Position.m_fPos[1]);
    bsPlayerSync.Read(OnFootData.m_Position.m_fPos[2]);

    // ROTATION
    bsPlayerSync.ReadNormQuat(
        OnFootData.m_Quaternion.m_fQuaternion[0],
        OnFootData.m_Quaternion.m_fQuaternion[1],
        OnFootData.m_Quaternion.m_fQuaternion[2],
        OnFootData.m_Quaternion.m_fQuaternion[3]);

    // HEALTH/Armor (COMPRESSED INTO 1 BYTE)
    std::uint8_t byteHealthArmor{}, byteHealth{}, byteArmor{}, byteArmTemp{}, byteHlTemp{};

    bsPlayerSync.Read(byteHealthArmor);
    byteArmTemp = (byteHealthArmor & 0x0F);
    byteHlTemp = (byteHealthArmor >> 4);

    if (byteArmTemp == 0xF) byteArmor = 100;
    else if (byteArmTemp == 0) byteArmor = 0;
    else byteArmor = byteArmTemp * 7;

    if (byteHlTemp == 0xF) byteHealth = 100;
    else if (byteHlTemp == 0) byteHealth = 0;
    else byteHealth = byteHlTemp * 7;

    OnFootData.m_Health = byteHealth;
    OnFootData.m_Armor = byteArmor;

    // CURRENT WEAPON
    bsPlayerSync.Read(OnFootData.m_CurrentWeapon);

    // Special Action
    bsPlayerSync.Read(OnFootData.m_SpecialAction);

    // READ MOVESPEED VECTORS
    bsPlayerSync.ReadVector(
        OnFootData.m_Speed.m_fPos[0],
        OnFootData.m_Speed.m_fPos[1],
        OnFootData.m_Speed.m_fPos[2]);

    bsPlayerSync.Read(bHasSurfInfo);
    if (bHasSurfInfo) {
        bsPlayerSync.Read(OnFootData.m_SurfingOffset.m_fPos[0]);
        bsPlayerSync.Read(OnFootData.m_SurfingOffset.m_fPos[1]);
        bsPlayerSync.Read(OnFootData.m_SurfingOffset.m_fPos[2]);
        bsPlayerSync.Read(OnFootData.m_SurfingVehicleId);
    }
    else
        OnFootData.m_SurfingVehicleId = -1;

    bsPlayerSync.Read(bAnimation);
    if (bAnimation)
        bsPlayerSync.Read(OnFootData.m_Animation.m_value);
 
  • Влюблен
  • Нравится
Реакции: Smeruxa и whyega52

Smeruxa

t.me/smeruxa
Автор темы
Проверенный
1,391
735
Я считал, что у меня проблема заключается в чтении, но на самом деле в воспроизведении
При воспроизведении записанного маршрута игра просто крашится, что бы я туда не записывал (я уже по разному пробовал на самом деле, и структуру onfoot записывать - sampapi::v037r1::Synchronization::OnfootData, но что-то безуспешно)

Что передаю ИД первым, что не передаю, дело особо не меняется, делая по структуре из events библиотеки тоже криво-косо идет
У имринга видел эмуляцию пакета, но это не то что мне нужно, но саму запись просто в безнадежных попытках решил скопировать

Прошу подсказать в чем действительно может быть дело, потому что я в тупике, кто поможет с воспроизведением и все будет работать, тому заплачу 300 рублей :)
C++:
 auto recordedData = gConfig->data["ways"][playWayName][index];

                                    RakNet::BitStream bs;

                                    float             vec[3] = { recordedData["position"][0].get<float>(), recordedData["position"][1].get<float>(), recordedData["position"][2].get<float>() };
                                    float             quat[4] = { 0 };

                                    bs.Write<unsigned char>(ID_PLAYER_SYNC);
                                    bs.Write<unsigned short>(sampapi::v037r1::RefNetGame()->GetPlayerPool()->m_localInfo.m_nId);  // playerId
                                    bs.Write0();                  // w/o leftRightKeys
                                    bs.Write0();                  // w/o upDownKeys
                                    bs.Write<unsigned short>(0);  // keysData
                                    bs.Write(vec);                // position
                                    bs.Write(quat);               // quaternion
                                    bs.Write<unsigned char>(255); // health & armor
                                    bs.Write<unsigned char>(0);   // weapon
                                    bs.Write<unsigned char>(0);   // specialAction
                                    bs.Write<float>(0);           // moveSpeed
                                    bs.Write0();                  // w/o surfingVehicleId & surfingOffsets
                                    bs.Write0();                  // w/o animationId & animationFlags

                                    rakhook::send(&bs, PacketPriority::HIGH_PRIORITY, PacketReliability::RELIABLE_ORDERED, (char)0);
 

Smeruxa

t.me/smeruxa
Автор темы
Проверенный
1,391
735
C++:
stOnFootData data{};

// fill struct

data.m_Armor = (std::uint8_t)pPed->m_fArmour;
data.m_Health = (std::uint8_t)pPed->m_fHealth;

// etc...

BitStream bs;
bs.Write<std::uint8_t>(ID_PLAYER_SYNC);
bs.Write((PCHAR)&data, sizeof(stOnFootData));
pNetGame->SendPacket(&bs);
Все тоже самое, краш, может это структура sampapi отличается от твоей? Что ты используешь? stOnFootData - это откуда?
C++:
if (gConfig->data["ways"].contains(playWayName)) {
    std::thread([playWayName]() {
        play = true;

        sampapi::v037r1::RefChat()->AddMessage(-1, std::string("Проигрываем маршрут: " + playWayName).c_str());
        auto start = std::chrono::steady_clock::now();
        size_t index = 0;
        while (index < gConfig->data["ways"][playWayName].size()) {
            auto packetTime = gConfig->data["ways"][playWayName][index]["time"].get<int>();
            auto currentTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start).count();
            if (currentTime >= packetTime) {

                auto recordedData = gConfig->data["ways"][playWayName][index];

                sampapi::v037r1::Synchronization::OnfootData data{};

                data.m_position = {
                    recordedData["position"][0].get<float>(),
                    recordedData["position"][1].get<float>(),
                    recordedData["position"][2].get<float>(),
                };

                RakNet::BitStream bs;
                bs.Write<std::uint8_t>(ID_PLAYER_SYNC);
                bs.Write((PCHAR)&data, sizeof(sampapi::v037r1::Synchronization::OnfootData));

                rakhook::send(&bs, PacketPriority::HIGH_PRIORITY, PacketReliability::RELIABLE_ORDERED, (char)0);

                ++index;
            }
        }
        sampapi::v037r1::RefChat()->AddMessage(-1, "Маршрут завершен.");
        play = false;
    }).detach();
}

UPD, выяснил, что это происходит именно при воспроизведении, обычная отправка ошибок не вызывает 🥲🥲🥲🥲
Пойду пытаться делать очередь

UPD. ЗАБЕГАЛО

UPD, В общем, все так-то у меня было нормально, что-то с воспроизведением было не так
Видимо ему не понравилось, что я это делал внутри rakhook'а и отдельным потоком

Создал при помощи ktcore очередь и по красоте расписал все, и ура, РАБОТАЕТ!
Спасибо всем, кто пытался помочь, проблема оказалась вообще в третьем, вместо первого и второго :(
 
Последнее редактирование:
  • Нравится
Реакции: whyega52

whyega52

Гений, миллионер, плейбой, долбаеб
Модератор
2,814
2,693
  • Нравится
Реакции: AdCKuY_DpO4uLa и Smeruxa

AdCKuY_DpO4uLa

Адский дрочер
Друг
327
684
Все тоже самое, краш, может это структура sampapi отличается от твоей? Что ты используешь? stOnFootData - это откуда?
C++:
if (gConfig->data["ways"].contains(playWayName)) {
    std::thread([playWayName]() {
        play = true;

        sampapi::v037r1::RefChat()->AddMessage(-1, std::string("Проигрываем маршрут: " + playWayName).c_str());
        auto start = std::chrono::steady_clock::now();
        size_t index = 0;
        while (index < gConfig->data["ways"][playWayName].size()) {
            auto packetTime = gConfig->data["ways"][playWayName][index]["time"].get<int>();
            auto currentTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start).count();
            if (currentTime >= packetTime) {

                auto recordedData = gConfig->data["ways"][playWayName][index];

                sampapi::v037r1::Synchronization::OnfootData data{};

                data.m_position = {
                    recordedData["position"][0].get<float>(),
                    recordedData["position"][1].get<float>(),
                    recordedData["position"][2].get<float>(),
                };

                RakNet::BitStream bs;
                bs.Write<std::uint8_t>(ID_PLAYER_SYNC);
                bs.Write((PCHAR)&data, sizeof(sampapi::v037r1::Synchronization::OnfootData));

                rakhook::send(&bs, PacketPriority::HIGH_PRIORITY, PacketReliability::RELIABLE_ORDERED, (char)0);

                ++index;
            }
        }
        sampapi::v037r1::RefChat()->AddMessage(-1, "Маршрут завершен.");
        play = false;
    }).detach();
}

UPD, выяснил, что это происходит именно при воспроизведении, обычная отправка ошибок не вызывает 🥲🥲🥲🥲
Пойду пытаться делать очередь

UPD. ЗАБЕГАЛО

UPD, В общем, все так-то у меня было нормально, что-то с воспроизведением было не так
Видимо ему не понравилось, что я это делал внутри rakhook'а и отдельным потоком

Создал при помощи ktcore очередь и по красоте расписал все, и ура, РАБОТАЕТ!
Спасибо всем, кто пытался помочь, проблема оказалась вообще в третьем, вместо первого и второго :(
В следующий раз кидай полный код. Из-за того, что у тебя не было синхронизации потоков, хотя возможно ещё что-то повлияло на это, все пошло по пятой точке. У меня лично такое было, даже когда я просто пытался вывести сообщение в чат в отдельном потоке без синхронизации
 
  • Нравится
Реакции: Smeruxa

Smeruxa

t.me/smeruxa
Автор темы
Проверенный
1,391
735
  • Грустно
Реакции: Lance_Sterling

whyega52

Гений, миллионер, плейбой, долбаеб
Модератор
2,814
2,693
Да, но это бы не помогло, сейчас уже все решено
если ты пишешь что-то вроде рекордера, то, возможно, и вправду, лучше хранить данные в бинарном формате, это будет и занимать меньше места, и IO будет происходить быстрее
 
  • Нравится
Реакции: Smeruxa