```lua
addEventHandler('onReceivePacket', function (id, bs) 
    if id == 220 then
        raknetBitStreamIgnoreBits(bs, 8)
        if (raknetBitStreamReadInt8(bs) == 17) then
            raknetBitStreamIgnoreBits(bs, 32)
            array.onDisplayCEF(raknetBitStreamReadString(bs, raknetBitStreamReadInt32(bs)))
        end
    end
end)

addEventHandler('onSendPacket', function (id, bs, priority, reliability, orderingChannel) 
    if id == 220 then
        local id = raknetBitStreamReadInt8(bs)
        local packettype = raknetBitStreamReadInt8(bs)
        local strlen = raknetBitStreamReadInt8(bs)
        raknetBitStreamIgnoreBits(bs, 24)
        local str = raknetBitStreamReadString(bs, strlen)
        if packettype ~= 0 and packettype ~= 1 and #str > 2 then
            array.onSendCEF(str)
        end
    end
end)

array = {}
array.onDisplayCEF = function(array) return array end
array.onSendCEF = function(array) return array end
array.emulationCEF = function(str)
    local bs = raknetNewBitStream()
    raknetBitStreamWriteInt8(bs, 220)
    raknetBitStreamWriteInt8(bs, 18)
    raknetBitStreamWriteInt32(bs, #str)
    raknetBitStreamWriteString(bs, str)
    raknetBitStreamWriteInt32(bs, 0)
    raknetSendBitStream(bs)
    raknetDeleteBitStream(bs)
end
array.visualCEF = function(str)
    local bs = raknetNewBitStream()
    raknetBitStreamWriteInt8(bs, 17)
    raknetBitStreamWriteInt32(bs, 0)
    raknetBitStreamWriteInt32(bs, #str)
    raknetBitStreamWriteString(bs, str)
    raknetEmulPacketReceiveBitStream(220, bs)
    raknetDeleteBitStream(bs)
end
return array
```
Библиотека для событий CEF на Arizona.
Упрощает работу с CEF и помогает удобнее взаимодействовать с ним.

Установка: Файл "CEF Events.lua" перенести по пути moonloader/lib

Функционал:
Callback функция при получения CEF​
Callback функция при отправке CEF (например, выбор приложения в /phone)​
Функция для визуального вызова CEF (например, создавать подсказки со своими надписями)​
Функция для эмуляции CEF (например, ответить на новый диалог с NPC)​

Объясни как работать с библиотекой:
```lua
local cef = require('CEF Events')
local json = require('cjson')

local list = {}
local fontRender = renderCreateFont('Arial', 9, 13)

function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand('vcef', function()
        -->> Отправляет вам прикольную подсказку на экран
        -->> Она бесконечная, чтобы её убрать нужно вызвать метод window.executeEvent('cef.modals.closeModal', '["interactionSidebar"]'); через visualCEF
        local str = 'window.executeEvent(\'cef.modals.showModal\', \'["interactionSidebar",{"title": "Продать квартиру?","description":"Играй РП на Аризоне","timer":3,"buttons":[{"title": "Продать","keyTitle": "ALT + F4","buttonColor": "#ffffff","backgroundColor": "rgba(171, 171, 171, 0.15)"}]}]\');'
        cef.visualCEF(str)
    end)
    sampRegisterChatCommand('ecef', function()
        -->> Отправляет 0 кнопку в новом диалоге с начальным NPC персонажем
        local str = 'answer.npcDialog|0'
        cef.emulationCEF(str)
    end)
    while true do wait(0)
        for i = #list, 1, -1 do
            if renderFontDrawClickableText(list[i], 750 + (#list - i) * 20) then
                setClipboardText(list[i])
            end
        end
    end
end

function cef.onDisplayCEF(str)
    local header, body = str:match('^window.executeEvent%(\'(.-)\', \'(.-)\'%);$')
    local data = json.decode(body)
    -->> header - название события от Аризоны
    -->> body - содержание события от Аризоны
    -->> data - массив, сделанный из body (обязательно юзать cjson, если Вы умный и не хотите лишних зависимости, то переделывайте получение)
    -->> Eсли в body будет JSON, то вернется массив с его значениями. Иначе будет возвращен массив с ключом "1" (data[1]).

    table.insert(list, ('{ff0000}[%s] [GET] %s'):format(os.date('%X'), str))
end

function cef.onSendCEF(str)
    table.insert(list, ('{00ff00}[%s] [SEND] %s'):format(os.date('%X'), str) )
end

function renderFontDrawClickableText(text, posY)
	local cursorX, cursorY = getCursorPos()
	local lenght = renderGetFontDrawTextLength(fontRender, text)
	local height = renderGetFontDrawHeight(fontRender)
	local hovered, result = false, false
    local posX = 650

    if cursorX > posX and cursorY > posY and cursorX < posX + lenght and cursorY < posY + height then
        hovered = true
        if isKeyJustPressed(0x01) then result = true end
    end

    renderFontDrawText(fontRender, text, posX, posY, hovered and 0xFF6b6bd1 or 0xFF5151b3)

    return result
end
```