Skip to content

Creating and using browsers

Eva edited this page Jul 13, 2021 · 1 revision

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:
    • 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:

#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:

<!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/ZOTTCE/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.

Clone this wiki locally