Опять вопрос по работе с памятью

ChаtGPT

Активный
Автор темы
390
95
Версия MoonLoader
.026-beta
Здравствуйте, можете, пожалуйста, объяснить, как правильно работать со структурами? Вот опять тот же вопрос с текстдравами. Есть структура текстдрава, я получаю пул текстдрава и могу работать с его текстом: получать и изменять. С получением всё ок, а вот с изменением есть проблема. Если я меняю текст, он не меняется сразу, а где-то через 0.1 мс, и в этот момент на экране виден старый текст, который потом заменяется на новый. Получается визуальное мигание, когда сначала показывается старый текст, а потом он обновляется. Это довольно раздражает.

Текстдрав обновляется на сервере через время, и из-за этого появляется этот эффект мигания. Есть ли способ это исправить? Или так работает система: сначала создается текстдрав, а потом можно получить его пул? То есть за эти 0.1 мс как раз всё обновляется? В теории можно использовать задержку рендера, чтобы не показывать текстдрав, пока он полностью не обновится (текст), но всё равно возникнет такой же эффект.

Использовал родной sampTextdrawSetString(в беск.цикле конечно же), всё такой-же эффект
(ИЛИ вопрос с другой стороны, почему при использовании sampTextdrawSetString(или sampTextdrawDelete и тому подобных) не обрабатываются моментально?)

Буду рад, если подскажете, как это можно решить!

Lua:
local ffi = require "ffi"

ffi.cdef[[
    struct CTextDrawData {
        float          m_fLetterWidth;
        float          m_fLetterHeight;
        unsigned long  m_letterColor;
        unsigned char  unknown;
        unsigned char  m_bCenter;
        unsigned char  m_bBox;
        float          m_fBoxSizeX;
        float          m_fBoxSizeY;
        unsigned long  m_boxColor;
        unsigned char  m_nProportional;
        unsigned long  m_backgroundColor;
        unsigned char  m_nShadow;
        unsigned char  m_nOutline;
        unsigned char  m_bLeft;
        unsigned char  m_bRight;
        int            m_nStyle;
        float          m_fX;
        float          m_fY;
        unsigned char  pad_[8];
        unsigned long  field_99B;
        unsigned long  field_99F;
        unsigned long  m_nIndex;
        unsigned char  field_9A7;
        unsigned short m_nModel;
        float          m_rotation[3];
        float          m_fZoom;
        unsigned short m_aColor[2];
        unsigned char  field_9BE;
        unsigned char  field_9BF;
        unsigned char  field_9C0;
        unsigned long  field_9C1;
        unsigned long  field_9C5;
        unsigned long  field_9C9;
        unsigned long  field_9CD;
        unsigned char  field_9D1;
        unsigned long  field_9D2;
    }__attribute__ ((packed));

    struct CTextDraw {
        char m_szText[801];
        char m_szString[1602];
        struct CTextDrawData m_data;
    }__attribute__ ((packed));

    struct CTextDrawPool {
        int       m_bNotEmpty[2048 + 256];
        struct CTextDraw* m_pObject[2048 + 256];
    }__attribute__ ((packed));
]]

ТОЛЬКО НЕ САМПЕВЕНС

да и если использовать sampTextdrawSetString (просто для примера) в хуке onShowTextDraw, то всё ВОвремя обновляется, КАК ЭТО РАБОТАЕТ?
хук приостанавливает обновление текстдрава до его нового обновления? :/

Lua:
function ev.onShowTextDraw(id, data)
    local text = data.text
    if text:find(dapi.cyrillic('Аптечка')) then
        print(id) -- 2089
        sampTextdrawSetString(2089, "SOSOSOSOSOSO")
    end
end
p.s: какого-то хрена, если вместо 2089 указать параметр id, ничего не обновится, а print(id) выводит 2089 :/

😤
 
Последнее редактирование:

Tema05

Известный
1,474
439
Вообще непонятно что написал. В начале говоришь про работу с тектдравами через память, но ничего из этого не показал как и что ты делаешь.

Если говорить про событие то оно срабатывает до того как текстдрав будет в памяти. Поэтому на момент события текстдрав может не существовать, значит и текст менять негде, а если существует, то это созданный ранее с таким же айди. В таком случаи вероятно использование функции изменения текста препятствует работе создания текстдрава и текст меняется как это например случается в серверМесседж. А вообще для изменения текста текстдрава есть отдельное событие текстдравСетСтринг

Непонятно толком а что ты хочешь сделать?
 
  • Нравится
Реакции: Vintik

ChаtGPT

Активный
Автор темы
390
95
Не понимаю, что тут может быть неясного. Я вроде всё подробно описал, но объясню ещё раз.
Текст изменяю следующим образом:

Lua:
local pool = ffi.cast("struct CTextDrawPool*", sampGetTextdrawPoolPtr())
local pObject = pool.m_pObject[2089]
pObject.m_szText = "text"

Использую это, конечно же, в бесконечном цикле. Проблема в том, что текст изменяется не сразу, а визуально с задержкой примерно в 0.1 мс. В этот момент на экране видно старый текст текстдрава, который затем заменяется на новый.

Есть ещё функция sampTextdrawSetString, которая работает аналогично коду выше, с тем же эффектом. Поэтому предполагаю, что по сути код выше и sampTextdrawSetString является одним и тем же.

Если они делают одно и тоже, тогда вопрос вот в чём: почему при использовании sampTextdrawSetString, или, например, при удалении текстдравов в цикле через sampTextdrawDelete, эти действия происходят не моментально? В случае с sampTextdrawSetString возникает эффект мигания. А в случае с sampTextdrawDelete наблюдается аналогичная проблема: текстдрав появляется на долю секунды перед удалением.

(Уточню, текстдравы у меня динамически обновляются при взаимодействии.)

Если я читаю текстдрав прямо из памяти, почему происходит эта задержка?
 
Последнее редактирование:

ChаtGPT

Активный
Автор темы
390
95
Вот сама демонстрация мигания:
Создал на pawn текстдрав, который обновляется каждые 2 секунды

Скрипт изменяет текст "TEXT" на "1" следующим образом:
Lua:
while true do
    wait(0)

    if sampTextdrawIsExists(3) then
        sampTextdrawSetString(3, "1")
    end
end
 

Lance_Sterling

Известный
977
341
Lua:
function ev.onShowTextDraw(id, data)
    local text = data.text
    if text:find(dapi.cyrillic('Аптечка')) then
        data.text = "yappi door";
        return {id, data}
    end
end

Текстдрав обновляется на сервере через время, и из-за этого появляется этот эффект мигания. Есть ли способ это исправить?
Есть в самп луа что то типо onTextDrawSetString
 

chromiusj

Известный
Модератор
5,651
3,953
  • Нравится
Реакции: ChаtGPT

Lance_Sterling

Известный
977
341
из памяти лучше, всё динамически изменяется
ну конечно, меняй в памяти братишка, если хочешь и дальше видеть 1 кадр свой прошлый текст который установился сервером
 

trefa

3d print
Всефорумный модератор
2,111
1,272
Здравствуйте, можете, пожалуйста, объяснить, как правильно работать со структурами? Вот опять тот же вопрос с текстдравами. Есть структура текстдрава, я получаю пул текстдрава и могу работать с его текстом: получать и изменять. С получением всё ок, а вот с изменением есть проблема. Если я меняю текст, он не меняется сразу, а где-то через 0.1 мс, и в этот момент на экране виден старый текст, который потом заменяется на новый. Получается визуальное мигание, когда сначала показывается старый текст, а потом он обновляется. Это довольно раздражает.

Текстдрав обновляется на сервере через время, и из-за этого появляется этот эффект мигания. Есть ли способ это исправить? Или так работает система: сначала создается текстдрав, а потом можно получить его пул? То есть за эти 0.1 мс как раз всё обновляется? В теории можно использовать задержку рендера, чтобы не показывать текстдрав, пока он полностью не обновится (текст), но всё равно возникнет такой же эффект.

Использовал родной sampTextdrawSetString(в беск.цикле конечно же), всё такой-же эффект
(ИЛИ вопрос с другой стороны, почему при использовании sampTextdrawSetString(или sampTextdrawDelete и тому подобных) не обрабатываются моментально?)

Буду рад, если подскажете, как это можно решить!

Lua:
local ffi = require "ffi"

ffi.cdef[[
    struct CTextDrawData {
        float          m_fLetterWidth;
        float          m_fLetterHeight;
        unsigned long  m_letterColor;
        unsigned char  unknown;
        unsigned char  m_bCenter;
        unsigned char  m_bBox;
        float          m_fBoxSizeX;
        float          m_fBoxSizeY;
        unsigned long  m_boxColor;
        unsigned char  m_nProportional;
        unsigned long  m_backgroundColor;
        unsigned char  m_nShadow;
        unsigned char  m_nOutline;
        unsigned char  m_bLeft;
        unsigned char  m_bRight;
        int            m_nStyle;
        float          m_fX;
        float          m_fY;
        unsigned char  pad_[8];
        unsigned long  field_99B;
        unsigned long  field_99F;
        unsigned long  m_nIndex;
        unsigned char  field_9A7;
        unsigned short m_nModel;
        float          m_rotation[3];
        float          m_fZoom;
        unsigned short m_aColor[2];
        unsigned char  field_9BE;
        unsigned char  field_9BF;
        unsigned char  field_9C0;
        unsigned long  field_9C1;
        unsigned long  field_9C5;
        unsigned long  field_9C9;
        unsigned long  field_9CD;
        unsigned char  field_9D1;
        unsigned long  field_9D2;
    }__attribute__ ((packed));

    struct CTextDraw {
        char m_szText[801];
        char m_szString[1602];
        struct CTextDrawData m_data;
    }__attribute__ ((packed));

    struct CTextDrawPool {
        int       m_bNotEmpty[2048 + 256];
        struct CTextDraw* m_pObject[2048 + 256];
    }__attribute__ ((packed));
]]

ТОЛЬКО НЕ САМПЕВЕНС

да и если использовать sampTextdrawSetString (просто для примера) в хуке onShowTextDraw, то всё ВОвремя обновляется, КАК ЭТО РАБОТАЕТ?
хук приостанавливает обновление текстдрава до его нового обновления? :/

Lua:
function ev.onShowTextDraw(id, data)
    local text = data.text
    if text:find(dapi.cyrillic('Аптечка')) then
        print(id) -- 2089
        sampTextdrawSetString(2089, "SOSOSOSOSOSO")
    end
end
p.s: какого-то хрена, если вместо 2089 указать параметр id, ничего не обновится, а print(id) выводит 2089 :/

😤
От спайса отойдешь, напишешь
А если так то зачем ты пытаешься поменять текстдрав который даже не создан? Тебе надо изменять пакет(что выше тебе и скинули), а не то что уже записано.
 

Орк

Известный
268
170
Хук?
Lua:
function SetText_dd(this, szText)
    local text = ffi.string(szText)
    -- print(text)
    if text:find('FOREVER') then szText = 'text' end
    SetText_dd(this, szText)
end
SetText_dd = hook.jmp.new("void(__thiscall*)(uintptr_t, const char* text)", SetText_dd, getModuleHandle("samp.dll") + 0xB26D0) -- r3
1733865201592.png

всё моментально при обновлении текстдрава
 
  • Нравится
Реакции: ChаtGPT, ARMOR и Vintik

Tema05

Известный
1,474
439
Хук?
Lua:
function SetText_dd(this, szText)
    local text = ffi.string(szText)
    -- print(text)
    if text:find('FOREVER') then szText = 'text' end
    SetText_dd(this, szText)
end
SetText_dd = hook.jmp.new("void(__thiscall*)(uintptr_t, const char* text)", SetText_dd, getModuleHandle("samp.dll") + 0xB26D0) -- r3
Посмотреть вложение 259230
всё моментально при обновлении текстдрава
Вот только без хуков давайте.

Может ещё лучше отследить вызов лишний и пропатчить в памяти код игры?
 

Vintik

Через тернии к звёздам
Проверенный
1,554
1,026
Так ты запускаешь в параллельном потоке бесконечный цикл и пытаешься оттуда изменить строку текстдрава?
Да, оно будет реагировать не сразу, цикл же все равно имеет какое-то время итерации.

То, что ты не понимаешь и пишешь про работу с памятью, подозреваю ровно то же самое, только функции изменения текста текстдрава самописные, который ты слямзил откуда-то, да?
Так ничего не изменилось: цикл, задержки — мерцание.

Тебе нужно перехватывать создание текстдрава (либо на этапе RPC, либо на этапе непосредственно создания).
Второй вариант — это попасть в игровой цикл gameloop, и, скорее всего, проблемы не будет.
Адреса хука геймлупа я не знаю.
 
Последнее редактирование:
  • Нравится
Реакции: ChаtGPT

ARMOR

011110000111100101101001
Модератор
4,967
6,886
Хук?
Lua:
function SetText_dd(this, szText)
    local text = ffi.string(szText)
    -- print(text)
    if text:find('FOREVER') then szText = 'text' end
    SetText_dd(this, szText)
end
SetText_dd = hook.jmp.new("void(__thiscall*)(uintptr_t, const char* text)", SetText_dd, getModuleHandle("samp.dll") + 0xB26D0) -- r3
Посмотреть вложение 259230
всё моментально при обновлении текстдрава
Имхо лучше хукать CTextDraw::Draw, как я уже писал этому челу в прошлой теме.
 
  • Нравится
Реакции: Орк