Lua Advance [Advance RP] CEF Monitoring

kyrtion

\0
Автор темы
Проверенный
1,494
609
Скрипт CEF Monitoring собирает полученные/отправленные пакеты, затем расшифрует и показывает в окно.

screenshot 2026.09.19-22.03.26.683.jpg

Скрипт может распознавать пакеты для CEF в Advance RP. И они так выглядят:
Код:
[SEND] CEF -> 13; cef:tasksRequest; menu | ...
[GET] CEF -> 12; cef:tasks; {"tasks":[{"group":0,"slot":0,"name":"Перенести на складе","target":15,"item":" грузов","progress":0.0,"status":0},{"group":0,"slot":1,"name":"Увеличить силу на","target":2,"item":" ед.","progress":0.0,"status":0},{"group":0,"slot":2,"name":"Набрать в соревнованиях по стрельбе","target":22,"item":" очков","progress":0.0,"status":0},{"group":0,"slot":3,"name":"Подмести в Cluckin Bell","target":15,"item":" кв. м полов","progress":0.0,"status":0},{"group":0,"slot":4,"name":"Сыграть в кости с","target":2,"item":" разными игроками","progress":0.0,"status":0},{"group":0,"slot":5,"name":"Добыть","target":299,"item":" кг руды","progress":0.0,"status":0},{"group":1,"slot":0,"name":"Заправить автомехаником","target":33,"item":" автомобилей","progress":0.0,"status":0},{"group":1,"slot":1,"name":"Сыграть в рулетку","target":33,"item":" раз(а)","progress":0.0,"status":0},{"group":1,"slot":2,"name":"Выпить безалкогольных напитков","target":121,"item":" шт.","progress":0.0,"status":0},{"group":1,"slot":3,"name":"Заработать на заводе продуктов","target":91817,"item":"$","progress":0.0,"status":0}]},"battlePass":{"level":2,"exp":10000,"need":11800,"days":35,"pass":0,"maxLevel":50}} | ...

[SEND] CEF -> 13; cef:tasksRequest; menu | ...

ЗначениеОбъясняю
* GET или SENDGET - вы получили от сервера
SEND - вы отправили пакет на сервере, чтобы он прочитал ваши пакеты
* CEF ->Обозначает что пакет получен/отправлен для обработки в CEF
12 или 1312 (0x0C) - как GET (получен)
13 (0x0D) - как SEND (отправлен)
cef:tasksRequestНазвание событие
menuАргументы событие (payload)
...Байты (не входит для обработки CEF)
* - необязательно указать для отправки

Важно!
Кодировка
пакета является CP1251 (Windows 1251), но не UTF-8. Поэтому работаете с пакетами в скрипт без перекодировки.

Код:
Lua:
local ffi = require("ffi")

local CEF_PACKET_ID = 0xFA    -- 250
local CEF_MAX_PACKET = 0x2000 -- 8192
local CEF_EVENT_GET = 0x0C    -- 12
local CEF_EVENT_SEND = 0x0D   -- 13

local function readPacketBytes(bs)
    if bs == nil or bs == 0 then return "" end
    local size = raknetBitStreamGetNumberOfBytesUsed(bs)
    if not size or size <= 0 or size > CEF_MAX_PACKET then return "" end

    local savedOffset = raknetBitStreamGetReadOffset(bs)
    local buffer = ffi.new("uint8_t[?]", size)
    raknetBitStreamResetReadPointer(bs)

    local dest = tonumber(ffi.cast("intptr_t", buffer))
    raknetBitStreamReadBuffer(bs, dest, size) ---@diagnostic disable-line: param-type-mismatch
    raknetBitStreamSetReadOffset(bs, savedOffset)
    raknetBitStreamResetReadPointer(bs)

    return ffi.string(buffer, size)
end

local function parseCefEvent(bs)
    local raw = readPacketBytes(bs)
    if #raw < 6 then return nil end

    local index = 2

    local typ = raw:byte(index) -- in/out event
    index = index + 1

    local name_len = raw:byte(index)
    if not name_len or name_len <= 0 or name_len > 63 then return nil end
    index = index + 1

    local name_len_end = index + name_len - 1
    if name_len_end + 2 > #raw then return nil end
    local event_name = raw:sub(index, name_len_end)
    index = name_len_end + 1

    local payload_len = raw:byte(index) + raw:byte(index + 1) * 256
    index = index + 2
    if payload_len < 0 or index + payload_len - 1 > #raw then return nil end

    return typ, event_name, raw:sub(index, index + payload_len - 1)
end

local function sendCefEvent(event_name, payload)
    local bs = raknetNewBitStream()
    raknetBitStreamWriteInt8(bs, CEF_PACKET_ID)
    raknetBitStreamWriteInt8(bs, CEF_EVENT_SEND)
    raknetBitStreamWriteInt8(bs, #event_name)
    raknetBitStreamWriteString(bs, event_name)
    raknetBitStreamWriteInt16(bs, #payload)
    raknetBitStreamWriteString(bs, payload)
    raknetSendBitStreamEx(bs, 1, 9, 0)
    raknetDeleteBitStream(bs)
end

local function emulCefEvent(is_event_get, event_name, payload)
    is_event_get = is_event_get and CEF_EVENT_GET or CEF_EVENT_SEND
    local bs = raknetNewBitStream()
    raknetBitStreamWriteInt8(bs, CEF_EVENT_GET)
    raknetBitStreamWriteInt8(bs, #event_name)
    raknetBitStreamWriteString(bs, event_name)
    raknetBitStreamWriteInt16(bs, #payload)
    raknetBitStreamWriteString(bs, payload)
    raknetEmulPacketReceiveBitStream(CEF_PACKET_ID, bs)
    raknetDeleteBitStream(bs)
end

addEventHandler("onReceivePacket", function(id, bs)
    if id ~= CEF_PACKET_ID then return end

    local typ, event_name, payload = parseCefEvent(bs)
    if not typ or typ ~= CEF_EVENT_GET then return end

    print(" -> GET", typ, event_name, payload)
end)

addEventHandler("onSendPacket", function(id, bs)
    if id ~= CEF_PACKET_ID then return end

    local typ, event_name, payload = parseCefEvent(bs)
    if not typ or typ ~= CEF_EVENT_SEND then return end

    print(" <- SEND", typ, event_name, payload)
end)

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end

    sampRegisterChatCommand("test_send_event", function(arg)
        local event, payload = arg:match("^(%S+)%s*(.*)$")
        if not event then
            sampAddChatMessage("Usage: /test_send_event <event> [payload]", -1)
            return
        end
        sendCefEvent(event, payload)
    end)

    while true do
        wait(250)
    end
end

Пример для получение список тасков в CEF:
Lua:
sendCefEvent("cef:tasksRequest", "menu")
-- или /test_send_event cef:tasksRequest menu
Вывод (смотри в код onReceivePacket сверху):
Код:
typ = 12
event_name = cef:tasks
payload = {"tasks":[{"group":0,"slot":0,"name":"Перенести на складе","target":15,"item":" грузов","progress":0.0,"status":0},...

Пример как эмулировать после отредактирования в диалог после получения CEF-пакет:
Lua:
addEventHandler("onReceivePacket", function(id, bs)
    if id ~= CEF_PACKET_ID then return end

    local typ, event_name, payload = parseCefEvent(bs)
    if not typ or typ ~= CEF_EVENT_GET or not event_name or not payload then return end
    if event_name ~= "cef:dialog" or not payload:find([["DIALOG_HEADER":%s*"{%x+}Тут могло быть заголовка диалога"]]) then return end

    local decoded_payload = decodeJson(payload) -- распакуем строка-значение в таблице Lua
    decoded_payload.DIALOG_TEXT = decoded_payload.DIALOG_TEXT:gsub("Возвраст", "В штате") -- заменяем Возраст на В штате
    -- или полностью                                                        -- нужно менять табуляция на элементы <tbl> и тд
    decoded_payload.DIALOG_TEXT = ("С уважением,\nтвой разраб\t{4287F5}lua"):gsub("\t", "<tbl>"):gsub("\n", "<br>")
  
    -- запакуем обратно из таблицы в строка и эмулируем
    local encoded_payload = encodeJson(decoded_payload)
    emulCefEvent(true, "cef:dialog", encoded_payload)

    return false -- скрываем старый диалог
end)

К сожалению, способ на cef eval не нашел. Пытался, но не вышло. Только отправлять и эмулировать пакетов без евала.

Благодарности:
- @Rice. за готовый скрипт
- @Back1ng за то нашел способ чтение/отправки пакеты в CEF
 

Вложения

  • [ADV] CEF Monitoring.lua
    19.2 KB · Просмотры: 1
Последнее редактирование: