Skip to content
Gothic Multiplayer
Gothic MP Wiki

JavaScript (window.gmp)

The JavaScript side of the in-game web UI - window.gmp.trigger / on / off, how values are converted between JavaScript and Lua, a TypeScript declaration.

Every page opened in the game (the main document of a Browser, not its iframes) has the global object window.gmp before its own scripts run. It is the page's only link to the game; the Lua side is the page's Browser object. The Web UI guide shows it in whole examples.

gmp.trigger

gmp.trigger(name, ...args)

Sends an event to the client script: the functions registered with browser:on(name, fn) are called with args. Nothing is returned - the script answers with an event of its own (browser:trigger) when it has something to say.

gmp.trigger("ready");                                   // the page registered its gmp.on handlers
gmp.trigger("buy", "ItMi_Gold", 5);                     // browser:on("buy", function(item, amount) ... end)
gmp.trigger("login", { user: "lorem", password: "ipsum" });   // in Lua: data.user, data.password

gmp.on

gmp.on(name, handler)

Registers a function called when the script calls browser:trigger(name, ...); it gets the script's arguments. Several functions for one name are called in the order of registration; an exception in one of them is written to the log and does not stop the others.

gmp.on("stats", (s) => {
  document.querySelector("#health").textContent = `${s.health} / ${s.maxHealth}`;
});

Events the script sends before the page registered its handler are lost - register the handlers first, then send gmp.trigger("ready").

gmp.off

gmp.off(name, handler)

Removes a function registered with gmp.on (the same function object) - e.g. when a component of a framework is unmounted.

Values between JavaScript and Lua

Arguments are converted like JSON (JSON.stringify in the page, a JSON decoder in the game):

JavaScriptLuaNotes
numbernumberwhole numbers become Lua integers
stringstringUTF-8
true / falseboolean
null, undefinednilundefined in an array becomes null
array [1, 2, 3]table {1, 2, 3}
object { a: 1 }table { a = 1 }
Date, Map, Set, class instancesas JSON.stringify makes themsend plain objects
functions, Symbolnot sent

From Lua: a table with keys 1..n only becomes an array, any other table an object; an empty table is {}. Lua functions, characters and other objects cannot be sent - send ids (ch:getId()) and plain data. One browser:trigger / browser:execute carries at most 4 MB.

TypeScript

src/gmp.ts
type Handler = (...args: any[]) => void;

interface Gmp {
  trigger(name: string, ...args: unknown[]): void;
  on(name: string, handler: Handler): void;
  off(name: string, handler: Handler): void;
}

declare global {
  interface Window { gmp?: Gmp }
}

// in the game window.gmp exists; in a normal browser (npm run dev) a stand-in prints the events
export const gmp: Gmp = window.gmp ?? {
  trigger: (name, ...args) => console.log("gmp.trigger", name, ...args),
  on: () => {},
  off: () => {},
};

What a page can and cannot do

  • Everything of a modern Chromium: ES modules, fetch of the server's own files (fetch("./data.json")), localStorage (kept while the game runs), 2D canvas, SVG, CSS animations and transitions, web fonts from the server's files. Pages are drawn without the GPU (the game owns it) - prefer CSS and 2D canvas to WebGL.
  • No internet: requests to other addresses are blocked (see the guide).
  • No new windows, no navigation away from the server's files; alert / confirm / prompt show nothing (the text goes to the log).
  • console.log and errors go to the player's GROnline log (client_debug.log, [WEB] lines).