Skip to content

Client library

Vendor umm_client.js into your mod if you would rather call UMM.register({ ..., onChange }) than write inline bus code. It speaks the same umm:1 protocol as the snippet.

Where it earns its keep is the bookkeeping. The snippet makes you guard group and descend into checks yourself in the default loop; the library does both, so onChange only ever sees real values.

Download umm_client.js, put it in your mod’s src/panorama/scripts/, and include it from your layout ahead of your own script:

<scripts>
<include src="s2r://panorama/scripts/umm_client.vjs_c" />
<include src="s2r://panorama/scripts/your_mod.vjs_c" />
</scripts>
var settings = UMM.register({
id: "your_mod", // stable; namespaces your stored values
name: "Your Mod", // shown as the tab title
settings: [
{ id: "enabled", type: "toggle", label: "Enabled", default: true,
description: "Optional. Shown as a tooltip when the row is hovered." },
{ id: "opacity", type: "slider", label: "Opacity",
min: 20, max: 100, step: 5, default: 90, unit: "%" },
{ id: "corner", type: "select", label: "Corner", default: "tl",
options: [ { value: "tl", label: "Top Left" },
{ value: "tr", label: "Top Right" } ] }
],
onChange: function (key, value, all) { /* apply it */ }
});
settings.get("opacity"); // current value, or the declared default
settings.all(); // every value, keyed by setting id

register() fires onChange once per setting straight away, carrying your declared default, so your mod runs on its defaults whether or not UMM is installed. If UMM is there, it answers the announce with a set per setting a moment later and onChange fires again for every value that differs from the default. As with the snippet’s applySetting, that leaves exactly one code path to write, and it has to be idempotent for the same reason.

It never fires for a group, and a checks row arrives as one call per option id rather than one for the row, matching how those values are stored. So the key you receive is always something you can switch on.

onChange is called inside a try/catch: a throw is logged with a [UMM] prefix and swallowed, so one bad setting cannot take down the rest of your mod.

The worked example walks through a shipping mod’s integration and ends by rewriting it against this library, so you can read the same settings both ways and judge which suits you.