STYGION Documentation Search the docs

Keystone in the player's game: screens, HUD and themes

What the client half draws from 0.3: Keystone Settings, themes as a small subset of CSS, the HUD, notices, a modpack's look for the game's own screens, and the public ClientToolkit for addons.

Keystone 0.2.8 Updated 5 min read
On this page 7 parts
  1. Keystone Settings
  2. Themes
  3. The HUD
  4. Notices
  5. Chat
  6. A modpack's look for the game's own screens
  7. For addons: ClientToolkit

Keystone in the player's game: screens, HUD and themes

From 0.3 the client half - the same jar in the player's mods/, see the client half for what the client and the server say - draws real screens and a HUD. The module client on the server is off by default. A player without the client half loses nothing: every screen has its chat or chest version. Nothing here depends on STYGION.

Keystone Settings

#

Opened with K (rebindable), /keystone settings, or the Config button in the mod list. Tabs Chat, HUD, Ultimine, Notifications and Theme, each with a live preview. Everything is kept on the player's own machine (config/keystone-client.json) and never sent anywhere; what the server locked is shown as locked.

Themes

#

A theme is data, never code: a small subset of CSS that the client draws natively - no browser, no script - so a shared theme can change colours and nothing else.

Code
:root { --accent: #e8913a; }
panel { background: #0f0d0b / 88%; border: 1px solid #5c2e14; radius: 3px; shadow: 2px 2px 0 #000000; }
tab:selected { background: var(--accent); color: #24110a; }
badge[legend] { background: linear-gradient(90deg, #a8204a, #ffca36); }

A selector is a word with optional .part, [key] and :state; a property falls back from the most specific selector to the bare word, then to the theme's default. Anything not understood is skipped, never an error; a file is read up to 16 KB.

  • Four come with the jar: Night (the default), STYGION, Mist and High contrast. A server adds its own as config/keystone/themes/<name>.kcss.
  • theme.default is the look a new player starts with; theme.offered the themes a player may pick.
  • theme.own (on) lets a player edit a theme of their own and share it as a code starting KS1:, which another player pastes in Settings.

The HUD

#

A small panel that covers nothing. By default only the quests are shown, in the top-right corner: a heading such as TODAY · 2 / 3 with when they reset, at most three quests (hud.quests.rows), the count on the right and one thin bar under the first unfinished quest. A quest finished while you play says done in green for a few seconds and folds away. A panel is never wider than hud.width percent of the screen (22 by default); a long name wraps onto a second line, it is never cut off. At a large GUI scale the HUD stays as small as at GUI scale 2.

The other elements are off until the player turns them on (Settings → HUD, key K): position (coordinates, biome, facing, time, world, whose claim), server (ping, TPS, players, the next restart, today's vote and streak), player (coins, keys, rank and time to the next, badges), lists (pinned lists) and panels (the owner's own, menus). The player drags, scales and hides what the server did not lock (Settings → HUD → Move panels).

It keeps out of the way. Each panel takes the first free place, starting at its own corner and sliding along the edge, then trying the other corners, and moves again when something appears: the effect icons, boss bars, Jade's tooltip, the chat (more of it while it is open), the scoreboard, the hotbar, the ultimine panel, and the JourneyMap and FTB Chunks minimaps where their own settings put them (read from their config files; neither mod is needed). For any other mod, hud.avoid names a place to keep clear: a corner and a size in GUI pixels or percent of the screen's height, optionally moved in from the corner — top-right 120x90, top-right 120x90+0+20, top-left 30%x35%. A pack can add the same lines to its own file (below). A panel the player dragged stays exactly where they put it.

client.toml: hud.enabled, hud.every (2 s; values are sent only when they changed), hud.elements (what exists), hud.shown (what a new player sees; quests), hud.locked (what may not be moved or hidden), hud.anchor.<element>, hud.quests.rows (3), hud.width (22), hud.avoid, hud.position.claim, hud.position.biome. The values and their keys: HUD values.

Notices

#

Short notices slide in at a corner for a badge, a quest done, a mention, a team list, a job, the restart or a vote. toasts.kinds says which kinds the server sends at all; each player picks which they see.

Chat

#

chat.images (on): pictures and GIFs posted on Discord show in the game chat, fetched by the server from Discord's own addresses only, never by the players. chat.heads (on): chat lines show the speaker's head.

A modpack's look for the game's own screens

#

config/keystone-pack.json belongs to the pack, not the player, and changes nothing when missing:

Code
{"hud": {
  "background": "#E61A0C06", "border": "#FF5C2E14", "title": "#FFFFCA36", "text": "#FFF8E9CC",
  "muted": "#FFB9A184", "bar": "#FFE8913A", "track": "#FF2F170A", "done": "#FFA9C25A",
  "avoid": ["top-left 120x60"]
 },
 "gui": {
  "container-label-color": "#F8E9CC",
  "container-label-screens": ["com.example.SomeScreen"],
  "tooltip": {"background": "#F01A0C06", "border-top": "#FFFFCA36", "border-bottom": "#FFA8204A"}
}}

Colours are written the way the game writes them: #AARRGGBB (alpha first) or #RRGGBB. hud sets the HUD's colours over the player's theme (each key optional) and adds places to keep clear; gui colours the labels of container screens (every screen of the game's own, and the classes listed) and tooltips.

The label colour applies to the game's own container screens and to the screen classes listed, so a mod's screen with light textures keeps its dark labels. Tooltip colours apply on Minecraft 1.21.x; 26.x draws tooltips from sprites, which a resource pack retextures instead. Other mods' screens are never restyled.

For addons: ClientToolkit

#

ModuleContext.client() gives a module or an addon the client half as data, never code:

  • send(player, topic, data) - data under a topic (lower-case words with dots), at most 512 KiB.
  • open(player, screen, data) - one of the client's screens (quests, market, crate, changelog, menu, lists, jobs, settings, vote); returns false for a player without the client half, so the caller answers in chat.
  • notify(player, kind, title, text, icon) - a notice.
  • onAction(topic, handler) - what client halves send back, already size-limited (8 KiB) and parsed; every value is to be checked like a command argument.
  • hud(key, value) - a HUD value, asked every refresh on the server thread; it must be a cheap look-up.

Every call is a no-op for a player without the client half. Player.runCommand runs a command as a player with their own permissions. GET /v1/client/hud (scope players.read) lists the HUD keys and the layout the server suggests.

Did this page help?

Opens the feedback panel with this page attached. It lands in the same queue as everything else.