samp cef docs - zBreno - 28/09/2023
pdf https://drive.google.com/drive/folders/1E2sBaBNaY1Rt4UPE1yck5DfEEaAhnojU?usp=sharing
help in https://pawn.wiki/index.php?/topic/53574-samp-cef/ projects https://pawn.wiki/index.php?/forum/137-cef/
read_md
This project embeds CEF into SA:MP expanding abilities to express yourself with beauty in-game interfaces using HTML / CSS / JavaScript.
It is a FRAMEWORK (or SDK), not something that you download and use. To be able to create you should have some webdev basics (JS / HTML / CSS).
• What you can do
Create browser views from a gamemode or from client-side plugins (C ABI).
Place browsers on objects (with kind-of spatial sound)
Send and receive custom defined events from / to clients.
• Crates
Citar:- `cef` - Rust wrappers around CEF C API.
- `cef-api` - Rust wrappers to build client plugins using CEF.
- `cef-interface` - example of a Rust plugin.
- `cef-sys` - bindings for CEF C API.
- `client` - client CEF plugin.
- `d3dx9` - bindings to DirectX SDK.
- `loader` - small loader that makes it work (should be named `cef.asi`).
- `messages` - protobuf messages to communicate with server on net.
- `network` - quinn glue (laminar like).
- `proto` - raw proto files.
- `renderer` - glue between CEF renderer process and main logic.
- `server` - server side plugin.
• Download
Latest builds from the master branch are placed in the Actions https://github.com/Pycckue-Bnepeg/samp-cef/actions
Currently there is those OS:
CentOS 7 (cef-centos-7.so)
Debian 9, 10, 11 (cef-debian-*.so)
Ubuntu 18.04, 20.04 (cef-ubuntu-*.so)
Windows (cef-windows.dll)
And also all client-side parts (cef.asi, client.dll, renderer.exe).
• Building
Dependencies
Rust compiler (nightly) with i686-windows-pc-msvc toolchain https://rust-lang.org
Prebuilt CEF with proprietary codes (if you wanna use streams). I had one for you in releases. (Client only)
Environment variable `CEF_PATH` that points to `libcef.lib` (client only).
In powershell it's like `$env:CEF_PATH="C:/some/path"`
Then build
Notes...
If you get a linker error, you should change hard-coded links in the source code
client/build.rs - path to DirectX SDK (default one)
• Running Rust
and now
rustup toolchain install nightly-i686
cargo +nightly-i686 build --release
also the client plugin can be built using OpenAL for sound rodio https://crates.io/crates/rodio by default). to do that compile the client without default features. for example:
cargo +nightly-i686 build --release --package client --no-default-features
to make it work you should place openal.dll as sound.dll in the cef` folder. I do not remember what version is used exactly ... but I have it on the release page.
to build specific part you can add --package <NAME>
for example if you will try to build ALL crates on linux, you will get an error. so, pass --package server to build only server on linux.
• CEF version
Current versions of CEF and Chromium: 89.0.5+gc1f90d8+chromium-89.0.4389.40 release branch 4389
Date: February 26, 2021
CEF Version: 89.0.5+gc1f90d8+chromium-89.0.4389.40
CEF URL: https://bitbucket.org/chromiumembedded/cef.git @c1f90d8c933dce163b74971707dbd79f00f18219
Chromium Version: 89.0.4389.40
Chromium URL: https://chromium.googlesource.com/chromium/src.git @2c3400a2b467aa3cf67b4942740db29e60feecb8
• Docs
docs/main_ru.md https://github.com/Pycckue-Bnepeg/samp-cef/blob/master/docs/main_ru.md
docs/main_en.md it's better to google translate russian one... https://github.com/Pycckue-Bnepeg/samp-cef/blob/master/docs/main_en.md
Also, check out wiki on github. https://github.com/Pycckue-Bnepeg/samp-cef/wiki
Video examples
https://www.youtube.com/watch?v=Jh9IBlOKoVM goblin for the whole house
https://www.youtube.com/watch?v=jU-O8_t1AfI simple interfaces
https://www.youtube.com/watch?v=qs7n8LoVYs4 castle interface of gta
https://www.youtube.com/watch?v=vcyTjn3RJhs voice chat
https://www.youtube.com/watch?v=6OnCSHKcOGU kitchen on tv
BIG TODO: EXAMPLES
But it's similar to fivem or ragemp implementations.
main_en
• File structure
The cef.asi should be in the game root folder (builded as loader.dll).
Also cef folder should be placed there.
There is a CEF dir at `Documents/GTA San Andreas User Files/CEF/`, where is Chromium cookies, caches and so on.
Citar:gta_sa.exe
cef.asi`
cef/
- client.dll
- libcef.dll
- renderer.exe
- etc…
Tips and some limitations
You should have one browser for all your interfaces to achieve best performance. They can communicate using built-in event system.
If there is plugins that use relative paths, it could lead to some unexpected things (like `cleo_text` and `cleo_saves` may be placed at `cef` folder). So, please, use absolute paths!
Pawn API
Código: cef_create_browser(player_id, browser_id, const url[], hidden, focused)
- Creates a browser for a player. browser_id can be any ID (like in SAMP dialogs). focused means it hooks all input and passes it in the browser.
cef_destroy_browser(player_id, browser_id)
- Deletes a browser.
cef_hide_browser(player_id, browser_id, hide)
- Hides a browser.
cef_emit_event(player_id, const event_name[], args…)
- Call a client event. Supported types of arguments: string, integer, float
cef_subscribe(const event_name[], const callback[])
- Subscribe for client events. Callback signature: Callback(player_id, const arguments[]), arguments is a string, delimiter of arguments is a space
cef_player_has_plugin(player_id)
Check if a player has the plugin.
cef_create_ext_browser(player_id, browser_id, const texture[], const url[], scale)
Creates a browser that will be shown on a texture of an object in the future. scale arg multiplies texture by this value. 250x30 will be 1250x150 if scale is 5.
cef_append_to_object(player_id, browser_id, object_id)
Changes a texture on an object with browser one. The browser should be created with cef_create_ext_browser.
cef_remove_from_object(player_id, browser_id, object_id)
Return the default texture for an object.
cef_toggle_dev_tools(player_id, browser_id, enabled)
Toggles dev tools.
native cef_set_audio_settings(player_id, browser_id, Float:max_distance, Float:reference_distance)
Changes audio settings of a browser. reference_distance - distance while volume will be 1.0. Then decreases till max_distance when it will be 0.
cef_focus_browser(player_id, browser_id, focused)
Makes a browser focused as it would be on creation with focused = true.
cef_always_listen_keys(player_id, browser_id, listen)
The browser starts listen to player input even if it is not focused. This allows you to add a JS key handler on background (window.addEventListener("keyup") for example).
cef_load_url(player_id, browser_id, const url[])
Loads a new page with a given url (faster than destroy and recreate browser).
Handlers:
forward OnCefBrowserCreated(player_id, browser_id, status_code)
Called when a player has created a browser (from a server or a plugin). status_code will be 0 if there is some error. otherwise it is a HTTP response code (200, 404, etc).
forward OnCefInitialize(player_id, success)
Called when a player connected to the server with a plugin (or timed-out if there is no installed plugin). Kind of automatic cef_player_has_plugin.
Browser API:
cef.set_focus(focused)
Set a focus on a browser. It will be rendered last (means have high Z coord). Also can receive mouse and keyboard events.
cef.on(event_name, callback)
Subscribes for events from a server / client plugins.
cef.off(event_name, callback)
Unsub from an event.
cef.hide(hide)
Hides a browser and mutes it.
cef.emit(event_name, args…)
Triggers an event with a given name. Arguments can be anything. BUT! On the server it will be a string splited by spaces. In client plugins there is full functionality.
• C API
THIS IS DEPRECATED AND NOT WORKING AT ALL!
Check an rust example using C API (cef-interface crate) and client/external.rs to check the API.
C++
Código PHP: #include <cstdint> // Do not call next event handlers for this event. static const int EXTERNAL_BREAK = 1;
// Continue handling. If all handlers returns this, server will got the event. static const int EXTERNAL_CONTINUE = 0; using BrowserReadyCallback = void(*)(uint32_t); using EventCallback = int(*)(const char*, cef_list_value_t*); extern "C" { // Check if a browser exists. bool cef_browser_exists(uint32_t browser);
// Is a browser ready (created and the page is loaded) bool cef_browser_ready(uint32_t browser);
// Make a request to create a browser. void cef_create_browser(uint32_t id, const char *url, bool hidden, bool focused);
// Create `CefListValue`. THE CLIENT OWNS IT!!! cef_list_value_t *cef_create_list();
// Destroy a browser. void cef_destroy_browser(uint32_t id);
// Trigger an event with given args. void cef_emit_event(const char *event, cef_list_value_t *list);
// Focus a browser. void cef_focus_browser(uint32_t id, bool focus);
// Check if a GTA window is active. bool cef_gta_window_active();
// Hide a browser. void cef_hide_browser(uint32_t id, bool hide);
// Can a browser receive input events now. bool cef_input_available(uint32_t browser);
// Subscribe on browser ready events (like pawn one). void cef_on_browser_ready(uint32_t browser, BrowserReadyCallback callback);
// Kind of deprecated bool cef_ready();
// Subscribe on an event. void cef_subscribe(const char *event, EventCallback callback);
// cef_input_available + cef_focus_browser, but atomic. This function should be used in this cases. bool cef_try_focus_browser(uint32_t browser); }
Wiki - Browsers on objects, Creating and using browsers, Tips and Working with events.
• Browsers on objects
Browsers also can be rendered as textures of objects.
To make it work you should use player objects (and also no streamer, because it changes object ids all the time).
Choose an object and its texture (here for example). In this case, I will use an old TV (14772) that has CJ_TV_SCREEN texture. The texture has 128x128 size, so let's pass the scale as 7 to make it 896x896.
https://dev.prineside.com/en/gtasa_samp_model_id/
https://dev.prineside.com/en/gtasa_samp_model_id/model/14772-int3int_LOW_TV/
https://files.prineside.com/gtasa_samp_game_texture//png/int_brothelint3.CJ_TV_SCREEN.png
Código PHP: new object = CreatePlayerObject(playerid, 14772, 2039.0, 1338.9792, 12.0, 0.0, 0.0, 0.0); cef_create_ext_browser(playerid, 1, "CJ_TV_SCREEN", "https://www.youtube.com/embed/Gqa8_5bWzQQ?autoplay=1&controls=0", 7); // it is also good to put it in OnCefBrowserCreated cef_append_to_object(playerid, 1, object);
Now you can see something like this, but with another video. https://www.youtube.com/watch?v=6OnCSHKcOGU
These browsers are created for every player on their PC, which means there is no sync from the box. If you want to develop something like cinema you should use services that allows you to create rooms with synchronized videos. This can be done using twitch/youtube streams.
• Creating and using browsers
You can create a browser after OnCefInitialize(player_id, success) with success = 1. This callback is called when a player has established a connection with a CEF server.
cef_player_has_plugin will return always 0 before that. Also, your server should be able to listen to the 7779 UDP port (make sure your provider doesn't drop packets).
To create a browser call cef_create_browser(player_id, browser_id, const url[], hidden, focused) function. browser_id can be any integer value (kind of SAMP dialogs or player text draws / objects).
When focused is true, the player is able to input in a browser context but not in the game. You should define a function that will set cef.set_focus(false) in your JS file, otherwise, the player will be stuck on this page forever.
Currently, there is no option to load your custom web pages from local files, which means those web pages should be hosted somewhere.
For example, we will replace the default GTA interface with our cool-looking new one (it's not ...)
The first step is to install plugins.
Copy server.dll (rename it as you wish) into the server plugins folder.
Create a new ZIP archive that you will distribute to your players (and for yourself of course). It should look like this:
Citar:myarchive.zip
cef.asi
cef/
client.dll
renderer.exe
libcef.dll
<... other files ...>
plugins/
cef-interface.dll
cef.asi, client.dll and renderer.exe can be found here or compiled from the source (ouput files are loader.dll, client.dll, renderer.exe).
cef-interface.dll is not a part of a core, so it is should be compiled manually.
libcef.dll and other files are here in cef.zip archive.
To make it work let's create a browser from our game mode:
Código PHP: #include <cef> #define INTERFACE_BROWSER_ID 0xABCDE #define INTERFACE_BROWSER_URL "http://your-hosting.com" public OnCefInitialize(player_id, success) { if (success == 1) { // it is not hidden and not focused, we should be able to see it but cannot input from mouse / keyboard to it. cef_create_browser(player_id, INTERFACE_BROWSER_ID, INTERFACE_BROWSER_URL, false, false); return; } SendClientMessage(player_id, -1, "Ahh to bad you cannot see our new cool interface ..."); }
Then create a web page index.html with this code:
Código PHP: <!DOCTYPE html> <html> <head> <style> .box { position: absolute; top: 500px; } </style> </head> <body> <div class="box"> <span>hp:</span><span id="hp">0</span> <span>max_hp:</span><span id="max_hp">0</span> <span>arm:</span><span id="arm">0</span> <span>breath:</span><span id="breath">0</span> <span>wanted:</span><span id="wanted">0</span> <span>weapon:</span><span id="weapon">0</span> <span>ammo:</span><span id="ammo">0</span> <span>max_ammo:</span><span id="max_ammo">0</span> <span>money:</span><span id="money">0</span> <span>speed:</span><span id="speed">0</span> </div> <script> // tell our plugin which default components we want to hide ("interface" means all components) // list of all components are here: https://github.com/Pycckue-Bnepeg/samp-cef/blob/664179f058706d84d7757b01094e8ac9ce08b82a/cef-interface/src/components.rs#L47
// (ammo, weapon, health, etc) cef.emit("game:hud:setComponentVisible", "interface", false);
// ask the plugin to call our "game:data:playerStats" event every 50 ms. (pass false to stop it) cef.emit("game:data:pollPlayerStats", true, 50);
// subscribe to an event that triggered from the plugin // arm = armour cef.on("game:data:playerStats", (hp, max_hp, arm, breath, wanted, weapon, ammo, max_ammo, money, speed) => { document.getElementById("hp").innerText = `${hp}`; document.getElementById("max_hp").innerText = `${max_hp}`; document.getElementById("arm").innerText = `${arm}`; document.getElementById("breath").innerText = `${breath}`; document.getElementById("wanted").innerText = `${wanted}`; document.getElementById("weapon").innerText = `${weapon}`; document.getElementById("ammo").innerText = `${ammo}`; document.getElementById("max_ammo").innerText = `${max_ammo}`; document.getElementById("money").innerText = `${money}`; document.getElementById("speed").innerText = `${speed}`; }); </script> </body> </html>
The plugin itself does nothing but just hides HUD components and sends an event with the player's stats. It is a native plugin because we cannot hide the interface from game mode.
Now host this web page somewhere and replace http://your-hosting.com with an actual HTTP address.
That's all, now you're able to see a new interface in the game! Do some tweaks to the index.html to make it look better.
• Tips
Using developer tools
To open chromium developer tools you can use Pawn function native cef_toggle_dev_tools(player_id, browser_id, bool:enabled).
It may be not responding. That's expected behavior. To fix that use SAMPFUNCS (https://www.blast.hk/threads/17/) with the antipause=true setting.
• Place files on client-side
Also, chromium allows you to use file:///path/to/index.html. There is one question how do find out where are those files.
If you use a custom launcher (without it I do not recommend you use file: protocol) you can send a packet (using RakNet) with a path to the game and then open it using Pawn functions.
In case you have no such ability in your launcher you can create a plugin that will get the current path and open a browser using the C API that this CEF plugin exposes.
The idea of using client local storage is tricky. You should figure out where to place these files, how to update them, make sure that all clients use the same pages at this time, and so on.
I do not like launchers. That means I will not support them and have no desire to add such functionality.
• Working with events
With this CEF plugin, you can communicate between your game mode and clients' web pages. Events can make your page alive!
Pawn API:
Código: cef_emit_event(player_id, const event_name[], args…)
cef_subscribe(const event_name[], const callback[])
Browser (JS) API:
cef.on(event_name, callback)
cef.emit(event_name, args…)
We will create a login page for example.
Start with a game mode:
Código PHP: #include <cef> #define LOGIN_BROWSER_ID 0x12345 #define LOGIN_BROWSER_URL "http://your-hosting.com" forward OnLogin(player_id, const arguments[]); public OnCefInitialize(player_id, success) { if (success == 1) { cef_create_browser(player_id, LOGIN_BROWSER_ID, LOGIN_BROWSER_URL, false, true); return; } SendClientMessage(player_id, -1, "Ahh to bad you cannot see our new login page ..."); // show a dialog as you would do without a plugin } public OnCefBrowserCreated(player_id, browser_id, status_code) { if (browser_id == LOGIN_BROWSER_ID) { if (status_code != 200) { // fallback to dialogs ... return; } // subscribe on a login event cef_subscribe("loginpage:login", "OnLogin"); } } public OnLogin(player_id, const arguments[]) { // get a user password and compare it with a passed string new success = compare_player_password(player_id, arguments); // send a response status to the player // CEFINT(value) is a function to convert a string to a number cef_emit_event(player_id, "loginpage:response", success ? "success" : "failed"); }
RE: samp cef docs - kye - 06/10/2023
what's the point of reposting it without proper formatting
it's barely readable
RE: samp cef docs - White_Blue - 06/10/2023
Please, when posting a topic, always pay attention to its formatting. For code blocks with syntax highlighting, place the code between the 'php' tag, and for regular code without syntax highlighting, enclose it within 'code' tags. When quoting, always use the 'quote' tag. Thank you for your attention in advance.
Citar:Tradução PT-BR(PT-BR translation):
Por favor, ao postar um tópico, sempre preste atenção à formatação. Para blocos de código com realce de sintaxe, coloque o código entre as tags "php". Para código regular sem realce de sintaxe, coloque-o entre as tags "code". Ao fazer citações, sempre utilize a tag "quote". Agradecemos antecipadamente pela sua atenção.
|