← Roadmap

EffectiveTextureMenu

Textured menus

Why

The standard chest window looks like a chest. If you want your own look — a shop frame, a crafting panel, a background with a logo — the only way without mods is to draw an image as a font glyph right in the inventory title, shifted so it lands over the window.

EffectiveTextureMenu is an EffectiveMenu whose title is assembled for you: shift left, the texture glyph, shift back, and plain text on top. The glyph is registered in the pack automatically.

Minimal example

Textured menu
object ShopMenu : EffectiveTextureMenu() {
    override fun getTextureGlyph() = EffectiveGlyph("textures/menu/shop.png", height = 128, ascent = 13)
    override fun getTitle() = "Shop"

    override fun getNamespacedData() = MyPlugin.instance to "shop"
    override fun getSlotsCount() = 27
    override fun getFreeSlotSymbol() = null
    override fun getPattern(whoOpen: Player?) = listOf(
        "         ",
        "    r    ",
        "         ",
    )
    override fun getSymbolsToItems(whoOpen: Player?) = mapOf(
        'r' to SlotData(RubyItem.createItemStack(), listOf(ClickData(ClickType.LEFT) { p -> Shop.buy(p) })),
    )
    override fun onSlotChanged(player: Player, slot: Int, item: ItemStack, wasPlaced: Boolean) = SlotChangeResult.ALLOW

    fun init() {}
}

Everything from EffectiveMenu is here too; getTextureGlyph and getTitle are added, getMenuTitle is assembled already. The texture is a PNG the size of the window (176 px wide for a chest, height by row count); blank pattern spots keep the window look while the texture covers it.

Fine alignment
override fun getTitleOffset() = -8

override fun getMenuTitle(): String =
    getBackspaces(-8) + ChatColor.WHITE + getTextureGlyph().charGlyph() +
    getBackspaces(-170) + ChatColor.DARK_GRAY + "Shop" +
    BackSpace.R32 * 2 + Forward.R4 + "v2"

getTitleOffset — texture shift in pixels (negative is left). For full control override getMenuTitle: getBackspaces(px) builds the shift from glyphs, BackSpace.R128/R32/R4/R1 and Forward.R* can be combined by hand (`R32 * 2` = 64 px left). The colour before the glyph must be white, otherwise the texture gets tinted.

What to override

  • getTextureGlyph() *
    The window texture glyph; registered in the pack for you
  • getTitle()
    Default: null
    Text over the texture
  • getTitleOffset()
    Default: -8
    Texture shift in pixels
  • getMenuTitle()
    Default: собран
    Override only for full control over the title

* required

Pitfalls

  • The inventory title is a string of limited width; too large a shift to the right gets clipped by the client.
  • The title glyph is bound by the font texture size limit (see EffectiveGlyph) — 176×166 for a window is fine, 1024×1024 will not load.
  • The glyph ascent is tuned by eye to the window height; changing the row count changes it too.
  • Shader packs do not interfere: this is a regular font, not a core shader.