IMIsle Modkit
Pages in this area

NUI pages

NUI is the browser UI of a resource. A client script opens an HTML page from its own resource. The page is drawn over the game with the Chromium build that ships with The Isle (CEF 90). You write normal HTML, CSS and JavaScript.

A minimal page

manifest.lua

client "client.lua"
files { "ui/*" }

ui/index.html

<!doctype html>
<meta charset="utf-8">
<style>
  html, body { margin: 0; background: transparent; color: #fff; font-family: sans-serif; }
  #box { position: absolute; top: 24px; left: 24px; padding: 12px 16px; background: rgba(0, 0, 0, 0.8); }
</style>
<div id="box">
  <span id="status">waiting</span>
  <button id="ok">OK</button>
</div>
<script>
  modkit.events.add("setStatus", (text, count) => {
    document.getElementById("status").textContent = text + " (" + count + ")";
  });
  document.getElementById("ok").onclick = () => modkit.trigger("okClicked", Date.now());
  modkit.trigger("uiReady");
</script>

client.lua

local ui

modkit.events.add("onClientReady", function()
  ui = modkit.browser.add("ui/index.html")
  if not ui then print("browser could not be created") return end

  ui:on("uiReady", function()
    ui:call("setStatus", "hello from Lua", 3)
  end)

  ui:on("okClicked", function(timestamp)
    print("button clicked at " .. tostring(timestamp))
    modkit.gui.cursor.show(false, false)
    ui:setActive(false)
  end)
end)

modkit.keys.on("F5", function(down)
  if not down or not ui then return end
  ui:setActive(true)
  modkit.gui.cursor.show(true, true)
end)

Keep the background transparent. A page with a solid background covers the whole game.

Wait for a message from the page (uiReady above) before you call into it. A call that arrives before the page has loaded is lost.

The page side

The client mod inserts a small script in front of every HTML file. It creates window.modkit.

Page API Meaning
modkit.id id of this browser
modkit.events.add(name, fn) handle a browser:call(name, ...) from Lua
modkit.events.remove(name [, fn]) remove one handler or all handlers of a name
modkit.events.reset() remove all handlers
modkit.trigger(name, ...) send an event to the client script. modkit.events.call is the same function.

modkit.trigger sends the event with an HTTP POST to the client mod on 127.0.0.1. Strings, numbers and booleans arrive in Lua with their type. Objects and arrays arrive as JSON text.

Input focus

A page never receives mouse or keyboard input by itself. Two things have to be true.

  1. The script asked for it with browser:setActive(true).
  2. The cursor is on, modkit.gui.cursor.show(freeze, true).

Without the cursor every page is click-through, so no page can catch input in secret. With freeze = true the game controls are off while the cursor is visible. With freeze = false the game and the page both get input.

A full screen page that has focus swallows every click, also on transparent areas. Turn the focus off as soon as the player is done. If you forget, the player can not control the dinosaur any more.

modkit.gui.cursor.show(false, false)
ui:setActive(false)

Permissions

Camera, location, screen capture, MIDI, USB, serial, Bluetooth and payment are blocked for every page. The microphone is blocked unless the player allowed it for this server and resource. There is no script function yet that asks the player, so for now the microphone is always blocked.

Files and URLs

Pages are served from memory by a small HTTP server inside the client mod on 127.0.0.1:30121. The URL of a file is /<resource>/<path>. Relative links inside your page work. Known content types are html, js, css, json, png, jpg, svg and woff2.

modkit.browser.add("ui/index.html") opens a page of your own resource. A path with a leading slash, for example "/shared/ui/hud.html", opens a page of another resource.

Reference: nui natives.