Skip to content

v1.0.0 – stable API, tabs, scroll panes, feeds and Bedrock

Choose a tag to compare

@flyingfinger1 flyingfinger1 released this 27 Oct 19:21
· 6 commits to main since this release

1.0: the API, the menu format and config.yml are now stable (see "Compatibility" in the
README). Before that promise some names were cleaned up; plugins built against 0.9 need these
changes, YAML menus and configs keep working (old keys are still read, with a hint in the log).

  • Renamed (API): ListView.onSelect → onClick; Choice.onSelect, Checkbox.onToggle and
    Tabs.onSelect → onChange; Button.textColor and Checkbox.textColor → color;
    Grid.label / labelColor → text / color; Bar.color → fill; Tabs.tint →
    inactiveTint; DisplayMode.SIMPLE → PLAIN (stored choices carry over).

  • Changed (API): visible, enabled and checked take a Predicate<View>; sliders and form
    numbers use double (Form.Values.number returns a double); form fields are the final classes
    Form.TextField, CheckboxField, SliderField, ChoiceField; Label.DARK is gone, a label
    without color (null, the default) uses the skin's text color; Click.openUrl accepts only
    http/https; Scene.Builder.build() rejects two lists, grids, tabs or scroll panes with the same id.

  • New (API): Click.page(listId, n), tab(tabsId, tabId) and scroll(scrollId, offset);
    @NullMarked package; @ApiStatus.Internal on renderer getters, @ApiStatus.Experimental on
    tabs, scroll panes, big heads, text styles, item tooltips, the own plain view and redrawAfter.

  • Renamed (YAML): button text-color → color, bar color → fill, tabs tint →
    inactive-tint. The input: action now splits at | with spaces, like require:.

  • Cooldowns need an id (unique in the menu) or a cooldown-key: before, an element without
    them was keyed by its position, so adding an element moved cooldowns to other buttons. Stored is
    when a key was last used; each element waits its own time from then (a key used with different
    times is mentioned in the log). Running cooldowns of 0.9 start anew.

  • Values from outside are text: feed and web entries, %item_...% and %input% can no longer
    add MiniMessage tags (colors, click events) or be filled in as another placeholder; |raw keeps
    the tags for a source you trust. Placeholders of a text are filled in one pass.

  • Checks when loading menus: an unknown filter (%x|dat%) or an invalid alias is an error;
    frames the skin does not have, missing pictures, open: / give-item: targets without a menu
    and a command used by two menus are hints, in the log and after /glyphwork reload.

  • config.yml cleaned up (config-version: 1): max-height → pack.min-height,
    fallback → plain-dialog, icons / icon-source-pack → icons.enabled /
    icons.source-pack, feeds.date-format → date-format; the pack prompt text lives only in the
    language files (pack.prompt). Unknown or misspelled keys are reported. "Simple" is called
    "plain" everywhere (/glyphwork display plain, /glyphwork test plain; the old words still work).
    Edited language files: cmd.simple → cmd.plain, display.simple / display.info-simple →
    display.plain / display.info-plain, fallback.* → plain.* (the log names old keys).

  • Lists, grids, tabs and scroll panes without an id get one that is unique in the whole menu;
    before, the same element in several tabs shared its page.

  • Own plain view: plain: in a menu (API Scene.Builder.plain(...)) defines the dialog for
    players without the pack and Bedrock players by hand, with columns: 1|2; same variables as the
    pixel GUI.

  • Grayed-out buttons in the plain dialog stay visible in gray; a click sends their tooltip
    (e.g. the remaining cooldown) instead of doing nothing visible.

  • Pack from your server or proxy: pack.hosting: provided sends no pack; merge
    plugins/Glyphwork/pack/glyphwork.zip into the pack your server or proxy (Velocity) sends.
    pack.provided-loaded: always (a required pack) or server-pack (the server.properties answer)
    tells Glyphwork who has it.

  • Designer: a dashed area marks the room for the page buttons below lists and grids, with a hint
    when another element is in the way.

  • Plain dialog with pictures: players without the pack see item icons in front of button, list
    and grid texts (sprite components the client draws from its own textures), and long button texts
    switch the buttons to one wide column instead of cutting them (measured over all tabs, so the
    layout stays when switching). Tabs become a clickable line above the buttons of the active tab
    (on Bedrock: tab buttons and a divider).

  • Bedrock players (Geyser, optionally Floodgate; found without a hard dependency) always get the
    plain dialog, which Geyser turns into a Bedrock form, and no Java pack request; join menus open
    at once for them. Their buttons show the first tooltip line below the text (forms have no
    tooltips), and their forms close after a click until the server sends the next one, so a
    quick second click can no longer hit a button of the previous screen and closing a menu closes
    it (Geyser's waiting form could not be removed from the server). Timed redraws (cooldowns,
    refresh, loading feeds) send a new form only when something visible changed, instead of closing
    and reopening it every second (and at most one every 5 s).

  • Text formatting: labels, buttons and list entries understand MiniMessage for parts of their
    text (<b>, <i>, <u>, <st>, colors); labels also have bold, italic, underline and
    strikethrough for the whole text. Bold counts 1 px per character when cutting, centering and
    wrapping; underline and strikethrough are drawn as pixel-exact lines of their own. API:
    markup(true) on Label, Button and ListView, plus the four switches on Label. |discord now turns
    Discord markdown into this formatting; |discord-plain keeps the old plain text.

  • Fix: a line break inside a value (chat messages, web data, PlaceholderAPI, %input%) no
    longer breaks the layout of the whole menu; single-line text shows it as a space.

  • Clearer web errors: refused requests (401/403) say what to check, e.g. that Discord needs
    Authorization: "Bot <token>", without showing the token.

  • Placeholder filters: |date formats dates (ISO, RFC, Unix time) and |discord makes Discord
    markup readable (mentions, emojis, timestamps, markdown), for %item_...%, %menu_...% and
    %web_...%. docs/menus.md shows a Discord channel as a web source.

  • JSON web sources: web: in config.yml (url, every, optional headers) and
    %web_<name>_<path>% in any text (%web_status_players.online%, indexes and length for arrays);
    items-from: "web:<name>.<path>" turns a JSON array into list entries (%item_<key>%, nested keys
    with dots). Loaded in the background with the same limits as feeds.

  • Feeds: items-from: "rss:https://..." fills lists and grids from an RSS or Atom feed (title,
    text, date, link, author), loaded in the background, cached (feeds.cache, date-format
    in config.yml), safe against external entities and limited to 1 MB / 50 entries. The menu
    draws itself again when a feed arrives for the first time.

  • Detail views: %item_text% of a feed is the whole text with paragraphs (up to 4000
    characters), %item_summary% the short one-line version; selected-if on list and grid entries
    highlights e.g. the clicked one (API ListView/Grid.selectedIf); a scroll pane id with
    placeholders keeps one position per content. Together: list on the left, article on the right.

  • Action url: shows a web address in a small native dialog with Open and Back
    (url: %item_link% for feed entries); API Click.openUrl.

  • Scroll panes: type: scroll / Scroll.of(...) shows part of its elements in a window with a
    scroll bar (▲ / ▼ by step px, a click on the track jumps there) while the rest of the menu stays
    in place. Only what fits completely is drawn and clickable; any element works inside. The plain
    dialog lists all of them, the designer shows and scrolls the pane.

  • Long menus: the pack height now follows the tallest YAML menu (rounded up to 32 px, at most
    2048 px), so frames are drawn in menus of any height and the dialog scrolls them natively, mouse
    wheel included. pack.min-height is only the minimum (for scenes of plugins); small servers keep the
    small pack.

  • Tabs: type: tabs / Tabs.of(...) puts tabs on top of a panel; the active tab merges with
    the panel into one frame, the others sit slightly lower and darker behind it. Only the active
    tab's elements are drawn and clickable, a click on another tab switches. Elements inside a tab are
    placed relative to the panel and can be anything (templates, show-if and cooldowns included);
    var keeps the active tab in a menu variable. The designer draws and switches tabs too.

  • Action add: counts: add: points 1, add: amount -1 min 1 max 64 (amounts and limits may
    be placeholders, decimals work) and redraws the menu like set:.

  • Saved variables: persist: true (or a list of names) keeps menu variables in the player's
    data, so they survive logouts and restarts; set: name without a value removes the saved value.

  • Cooldowns: cooldown: 1h (30s, 5m, 1d 12h …) on buttons, hitboxes, icons, panels,
    pictures and heads: each player can use the element once per period, kept in the player's data.
    A button on cooldown is grayed out with the remaining time as tooltip; cooldown-key shares one
    cooldown between elements; a failed require does not use it up. While a cooldown runs, the
    open menu redraws itself when the shown time changes and when it ends (API: View.redrawAfter).
    Texts: cooldown.tooltip / cooldown.wait in the language files, or per element
    cooldown-tooltip / cooldown-message with %cooldown%.

  • Menus that open by themselves: open-on: { join: true } (or first) opens a menu when a
    player joins, once the Glyphwork pack is loaded; open-on: { item: compass } (or with name,
    lore, slot) hands out a menu item that opens it on right-click, cannot be dropped and comes back
    after death (give: join|first|no, keep: true|false; /glyphwork item <menu> [player] and the
    action give-item: hand it out on request). on-open / on-close actions run when the menu opens (before drawing) and when the
    player closes it; API Scene.Builder.onOpen / onClose. The designer has fields for all of it.

  • Own dialog warning button: dialog-warning.icon / icon-hover in config.yml replace the
    warning sign next to every dialog title with one of your pictures, and
    dialog.warning-tooltip in the language files replaces its tooltip text (written into the pack
    for every locale of that language). See docs/skin-format.md.

  • Big heads: type: head / Head.of(x, y, player).size(32) paints a player's face pixel by
    pixel from the skin, 8 to 32 px, at any position, for any player without changing the pack;
    head-size on lists and grids does the same for their head: icons. Skins load in the
    background (Paper profile, Mojang lookup for other names) and are cached; until then the small
    client head stands in and the menu redraws when the face arrives.

  • Own pictures: PNGs in plugins/Glyphwork/images/ (folders too) go into the pack and are
    placed with type: image / Image.of(x, y, "logo"), pixel exact and at their own size; names
    may use placeholders (ranks/%menu_rank%), tint multiplies the colors. Pictures of any size
    are cut into tiles of at most 128 x 128 px (the client cannot load bigger glyphs). Logos,
    banners, rank badges and big player heads are all just pictures. The designer shows them once you
    load the PNGs (or the folder) into it.

  • Progress bars: type: bar / Bar.of(...) fills pixel exact from value / max
    (placeholders work), in any color, 8 or 16 px high, with an optional text in the middle. The
    plain dialog shows ten blocks plus the text.

  • Item tooltips: item-tooltip: true on icons, lists and grids (API itemTooltip(true))
    shows the item's own vanilla tooltip when hovering; plugins can pass a full ItemStack with
    enchantments and lore. The example trader uses it.

  • Text blocks: labels with wrap: true and a width break into lines at spaces
    (line-height, default 10); \n starts a new line in any label.

  • The menu designer knows all three.

  • Button text is centered on the width that is drawn (frames are whole tiles: a 22 px button is
    16 px wide); before, it sat to the right.