Работа с браузером CEF

Lev Angel

Developer
Команда форума
Скриптер
RAGE MP позволяет использовать встроенный браузер на основе движка chromium - CEF. Благодаря этому в игре можно создавать интерфейсы любой сложности, использовать любые библиотеки и фреймворки, которые используются в обычном вебе.
Браузер работает только на клиентской стороне, поэтому все необходимые файлы для веб странички будут лежать в папке client_packages.

Создание браузера

Для примера создадим простую страничку в текстом и выведем ее в игре. Создадим файлик client_packages/index.html с таким содержимым:
HTML:
<h1>Hello world</h1>

Эту страничку мы и будем показывать. Добавляем в client_packages/index.js создание нового экземпляра браузера:
JavaScript:
browser = mp.browsers.new('package://index.html');
rage mp cef
В правом верхнем углу видим нашу надпись. Поскольку это у нас пустая html страничка без стилей, то текст соответственно выравнивается по левую сторону.

Также внутри html странички мы можем использовать обычный javascript код и css стили. Например:
HTML:
<h1 style="color:blueviolet">Hello world</h1>

<script>
    alert('Привет, мир!');
</script>

1592123697682.png
1592123746842.png

Взаимодействие с браузером

Очень важная вещь, которая будет часто использоваться в интерактивных интерфейсах - это возможность отправить что-то из javascript кода html странички в клиентский код ragemp. Это делается очень легко при помощи событий.
Например, мы хотим нарисовать кнопку и при клике по ней в чат должен выводиться определенный текст.
Добавим кнопку в наш index.html и обработчик, который будет срабатывать при клике по этой кнопке.
HTML:
<button onclick="buttonClick()">Нажми меня</button>
<script>
    function buttonClick(){
    
    }
</script>
В джаваскрипте который работает в браузере есть встроенный объект mp. Он содержит методы, которые позволяют взаимодействовать с ragemp. Чтобы передать что-то на клиент нам нужно дернуть какое-то событие. Например, назовем это событие cefClick и в нем будем передавать один текстовый параметр - тот текст что нужно вывести в чат.
JavaScript:
mp.trigger('cefClick', 'Привет жестокий мир');
Еще нам как-то нужно будет нажать на эту кнопку, для этого нужно показать курсор. Это можно также сделать из браузерного js кода, но добавим мы его не в обработчик клика, а в общую область видимости чтобы курсор появился сразу после загрузки.
HTML:
<button onclick="buttonClick()">Нажми меня</button>
<script>
     mp.invoke('focus', true); // показыываем курсор
  
    function buttonClick(){ // обработчик клика
        mp.trigger('cefClick', 'Привет жестокий мир');
    }
</script>
Теперь нам осталось только добавить обработчик события cefClick на клиентской стороне:
JavaScript:
mp.events.add('cefClick', function(message) {
    mp.gui.chat.push(message);
});
Можно проверять :)
1592125590293.png

Также мы можем взаимодействовать и наоборот. Из клиентского кода ragemp выполнять javascript в браузере. У объекта браузера есть метод execute. Он принимает один аргумент - это строка в которой должен быть javascript код.
JavaScript:
browser.execute(`alert(\`It's a test.\`);`);


Дополнение 1: browser.call вместо browser.execute
Дополнение 2: Правильный порядок взаимодействия с браузером после его создания
 
Последнее редактирование:

Lev Angel

Developer
Команда форума
Скриптер
Как и в обычном html файле мы можем подключать другие ресурсы - стили, скрипты, картинки и т. п. При этом файл может быть как локальный (лежит в пределах client_packages), так и внешний (просто ссылка на файл в интернете).
Ссылка на локальный файл начинается с указания протокола package:// и остальной путь относительно папки client_packages. В следующем примере у нас будет загружено две картинки и один файл стилей. Одна картинки внешняя, а другая картинка и стили локальные и лежат в папке client_packages/assets
HTML:
    <link rel="stylesheet" href="package://assets/style.css" />
    <img src="http://cdn1.iconfinder.com/data/icons/bluecoral/Left.png" alt="GTA 5 logo" />
    <img src="package://assets/gta.png" alt="gta logo" />

rage mp cef картинки и стили
 

Misterio

New member
Большое спасибо за подробную статью! Побольше бы такого материала. Вот в рускоязычном сегменте нигде кроме вашего форума про интерфейсы rage не смог найти инфу!
 

Lev Angel

Developer
Команда форума
Скриптер
@Misterio спасибо за обратную связь! Я рад что смог помочь. Если есть идеи для новых статей, можешь написать в идеи ;)
 

Lev Angel

Developer
Команда форума
Скриптер
Проблема: Вводишь текст в поле ввода в cef браузере и когда попадается символ "t", то открывается поле ввода чата и вводимый текст дублируется в поле чата.

Решение: Чтобы заблокировать открытие чата используем mp.gui.chat.activate(false);. И потом возвращаем обратно передав true.
 

Lev Angel

Developer
Команда форума
Скриптер
В rage mp 1.1 вместо browser.execute() удобно использовать browser.call() и объявлять event в браузерном js коде.

Например, было так:
Клиент
JavaScript:
browser.execute('browserCursor(true)');
Браузер
JavaScript:
function browserCursor(isVisible){
    mp.invoke('focus', isVisible);
}

Можно сделать так
Клиент
JavaScript:
browser.call('browserCursor', true);
Браузер
JavaScript:
mp.events.add("browserCursor", (isVisible) => {
    mp.invoke('focus', isVisible);
});

На первый взгляд особо нет разницы. Проблема в том что при browser.execute мы передаем весь код который нужно выполнить в браузере в виде js строки вместе со всеми аргументами. В примере мы передаем всего один аргумент в функцию в браузер. Но к примеру если там будет несколько аргументов, то при вызове через browser.execute будет уже выглядеть не так красиво + нужно не забывать про экранирование кавычек.
JavaScript:
browser.execute('sayHello("John", "Smith", 123, true)');
vs
JavaScript:
browser.call('sayHello', "John", "Smith", 123, true);

Также при browser.call удобнее подставлять переменные в аргументы.
JavaScript:
browser.execute(`sayHello("${firstName}", "${surname}", ${id}, ${isOk)`);
vs
JavaScript:
browser.call('sayHello', firstName, surname, id, isOk);
 
Последнее редактирование:

Lev Angel

Developer
Команда форума
Скриптер
пишу к примеру, <h1>Hello world</h1> дальше сохраняю, и захожу обратно а там, &lt;h1&gt;Hello world&lt;/h1&gt;
А в чем пишешь код? Похоже или редактор добавляет форматирование или при вставке кода с форума он сохраняет это форматирование.
 

Lev Angel

Developer
Команда форума
Скриптер
Мне кажется там проблема не с DOCTYPE, а именно с тем что в коде html странички символы <> заменены на их html аналоги &lt; и &gt;
Такое делается например чтобы выводить код на странице сайта и чтобы он не интерпретировался как html, а как простой текст.
 

Lev Angel

Developer
Команда форума
Скриптер
Fun fact: если создать браузер и дальше сразу пробовать делать browser.execute или browser.call, то игра виснет намертво :unsure:

Лучше начинать взаимодействовать браузер только по событию browserCreated или browserDomReady
JavaScript:
// Код курильщика
browser = mp.browsers.new('package://index.html');
browser.call('browserCursor', true);


// А так будет норм
browser = mp.browsers.new('package://index.html');
mp.events.add('browserDomReady', (_browser) => {
    if(browser == _browser){
        browser.call('browserCursor', true);
    }
});
 

Rodion15

New member
RAGE MP позволяет использовать встроенный браузер на основе движка chromium - CEF. Благодаря этому в игре можно создавать интерфейсы любой сложности, использовать любые библиотеки и фреймворки, которые используются в обычном вебе.
Браузер работает только на клиентской стороне, поэтому все необходимые файлы для веб странички будут лежать в папке client_packages.

Создание браузера

Для примера создадим простую страничку в текстом и выведем ее в игре. Создадим файлик client_packages/index.html с таким содержимым:
HTML:
<h1>Hello world</h1>

Эту страничку мы и будем показывать. Добавляем в client_packages/index.js создание нового экземпляра браузера:
JavaScript:
browser = mp.browsers.new('package://index.html');
В правом верхнем углу видим нашу надпись. Поскольку это у нас пустая html страничка без стилей, то текст соответственно выравнивается по левую сторону.

Также внутри html странички мы можем использовать обычный javascript код и css стили. Например:
HTML:
<h1 style="color:blueviolet">Hello world</h1>

<script>
    alert('Привет, мир!');
</script>


Взаимодействие с браузером

Очень важная вещь, которая будет часто использоваться в интерактивных интерфейсах - это возможность отправить что-то из javascript кода html странички в клиентский код ragemp. Это делается очень легко при помощи событий.
Например, мы хотим нарисовать кнопку и при клике по ней в чат должен выводиться определенный текст.
Добавим кнопку в наш index.html и обработчик, который будет срабатывать при клике по этой кнопке.
HTML:
<button onclick="buttonClick()">Нажми меня</button>
<script>
    function buttonClick(){
   
    }
</script>
В джаваскрипте который работает в браузере есть встроенный объект mp. Он содержит методы, которые позволяют взаимодействовать с ragemp. Чтобы передать что-то на клиент нам нужно дернуть какое-то событие. Например, назовем это событие cefClick и в нем будем передавать один текстовый параметр - тот текст что нужно вывести в чат.
JavaScript:
mp.trigger('cefClick', 'Привет жестокий мир');
Еще нам как-то нужно будет нажать на эту кнопку, для этого нужно показать курсор. Это можно также сделать из браузерного js кода, но добавим мы его не в обработчик клика, а в общую область видимости чтобы курсор появился сразу после загрузки.
HTML:
<button onclick="buttonClick()">Нажми меня</button>
<script>
     mp.invoke('focus', true); // показыываем курсор
 
    function buttonClick(){ // обработчик клика
        mp.trigger('cefClick', 'Привет жестокий мир');
    }
</script>
Теперь нам осталось только добавить обработчик события cefClick на клиентской стороне:
JavaScript:
mp.events.add('cefClick', function(message) {
    mp.gui.chat.push(message);
});
Можно проверять :)
Посмотреть вложение 42

Также мы можем взаимодействовать и наоборот. Из клиентского кода ragemp выполнять javascript в браузере. У объекта браузера есть метод execute. Он принимает один аргумент - это строка в которой должен быть javascript код.
JavaScript:
browser.execute(`alert(\`It's a test.\`);`);


Дополнение 1: browser.call вместо browser.execute
Дополнение 2: Правильный порядок взаимодействия с браузером после его создания

Создание браузера

Для примера создадим простую страничку в текстом и выведем ее в игре. Создадим файлик client_packages/index.html с таким содержимым:
HTML:
HTML:
<h1>Hello world</h1>

Эту страничку мы и будем показывать. Добавляем в client_packages/index.js создание нового экземпляра браузера:
JavaScript:
browser = mp.browsers.new('package://index.html');

Я все сделал, и также в игре ничего не показывает. Почему так?
 
Яндекс.Метрика
Верх