### Generate Fonts Task Example Source: https://context7.com/lucyydotp/tinsel/llms.txt This example shows how a font is defined in JSON and how the Tinsel Gradle plugin automatically generates offset variants. The base font definition uses the vanilla Minecraft format. ```json { "providers": [ { "type": "bitmap", "file": "tinsel.example:textures/glyphs/background.png", "ascent": 8, "height": 16, "chars": ["\uE000"] } ] } ``` -------------------------------- ### Initialize Tinsel with Custom Fonts Source: https://context7.com/lucyydotp/tinsel/llms.txt Constructs a `Tinsel` instance, configuring bundled resource pack fonts and custom glyph fonts with specified offsets. This setup is required before drawing any text components. ```java import me.lucyydotp.tinsel.Tinsel; import me.lucyydotp.tinsel.font.FontFamily; import me.lucyydotp.tinsel.font.OffsetMap; import net.kyori.adventure.key.Key; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.ShadowColor; import net.kyori.adventure.text.format.Style; import java.nio.file.Path; // Build a Tinsel instance using the bundled pack plus a custom glyph font Key GLYPH_FONT = Key.key("myplugin:glyph"); Tinsel tinsel = Tinsel.builder() .withTinselPack() // registers vanilla offset fonts + spacing font .withFonts( FontFamily.fromResourcePack(Path.of("/server/plugins/myplugin/pack.zip")) .add(GLYPH_FONT, OffsetMap.offsets(GLYPH_FONT, 12, 24)) // offsets at +12 and +24 px .build() ) .build(); // Draw a 255-pixel-wide component with no shadow Component result = tinsel.draw(255, Style.style(ShadowColor.none()), ctx -> { ctx.drawAligned(Component.text("Left"), 0f); // left edge ctx.drawAligned(Component.text("Center"), 0.5f); // centred ctx.drawAligned(Component.text("Right"), 1f); // right edge }); // Send to a player's action bar player.sendActionBar(result); ``` -------------------------------- ### Tinsel - Main Entry Point and Builder Source: https://context7.com/lucyydotp/tinsel/llms.txt Demonstrates how to construct and configure the Tinsel class using its builder, including adding custom font families and drawing a basic component. ```APIDOC ## Tinsel ### Description `Tinsel` is the central class for the library. It is constructed via its builder, which allows for configuration of font families. You can then call `draw()` to produce a component with a fixed pixel width. The builder's `withTinselPack()` method conveniently registers the bundled Tinsel resource pack fonts. ### Method `Tinsel.builder()` ### Usage Example ```java import me.lucyydotp.tinsel.Tinsel; import me.lucyydotp.tinsel.font.FontFamily; import me.lucyydotp.tinsel.font.OffsetMap; import net.kyori.adventure.key.Key; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.Style; import java.nio.file.Path; // Build a Tinsel instance using the bundled pack plus a custom glyph font Key GLYPH_FONT = Key.key("myplugin:glyph"); Tinsel tinsel = Tinsel.builder() .withTinselPack() // registers vanilla offset fonts + spacing font .withFonts( FontFamily.fromResourcePack(Path.of("/server/plugins/myplugin/pack.zip")) .add(GLYPH_FONT, OffsetMap.offsets(GLYPH_FONT, 12, 24)) // offsets at +12 and +24 px .build() ) .build(); // Draw a 255-pixel-wide component with no shadow Component result = tinsel.draw(255, Style.style(ShadowColor.none()), ctx -> { ctx.drawAligned(Component.text("Left"), 0f); // left edge ctx.drawAligned(Component.text("Center"), 0.5f); // centred ctx.drawAligned(Component.text("Right"), 1f); // right edge }); // Send to a player's action bar // player.sendActionBar(result); ``` ``` -------------------------------- ### Build Offset Key Maps with OffsetMap.offsets() Source: https://context7.com/lucyydotp/tinsel/llms.txt Utility to generate `Map` for `FontFamily.vanillaWithOffsets()` and `FontFamily.ResourcePackBuilder.add()`. It creates keys like `ns:name_offset_n` for a base key and offset. ```java import me.lucyydotp.tinsel.font.OffsetMap; import net.kyori.adventure.key.Key; import java.util.Map; Key base = Key.key("myplugin", "hud"); // Generates: { -8 -> "myplugin:hud_offset_-8", 8 -> "myplugin:hud_offset_8", 16 -> "myplugin:hud_offset_16" } Map offsets = OffsetMap.offsets(base, -8, 8, 16); FontFamily family = FontFamily.vanillaWithOffsets(offsets); // The resource pack must contain fonts named myplugin:hud_offset_-8, etc. ``` -------------------------------- ### Gradle Plugin - Applying the Tinsel Gradle Plugin Source: https://context7.com/lucyydotp/tinsel/llms.txt Instructions on how to apply the Tinsel Gradle plugin to generate offset font JSON files and assemble Minecraft resource packs. ```APIDOC ## Gradle Plugin ### Applying the Tinsel Gradle Plugin The Tinsel Gradle plugin (`me.lucyydotp.tinsel`) generates offset font JSON files from a base font definition and assembles a Minecraft resource pack zip. It exposes the `tinsel` DSL extension, an `include` configuration for merging other packs, and a `resourcePack` consumable configuration. ```kotlin // build.gradle.kts (resource pack subproject) plugins { id("me.lucyydotp.tinsel") } tinsel { // Override the output zip filename (default: "resources.zip") packArchiveName = "my-server-pack.zip" // Declare a font family to generate offset variants for. // The name is a resource key: "namespace:path" // The base font JSON must exist at: // src/main/resources/assets//font/.json fonts.create("myplugin:hud") { offsets = setOf(-8, -16, 8, 16) // generate _offset_-8, _offset_8, etc. addedBitmapSpacing.set(2) // adds vertical padding to bitmap textures outputNamespace.set("myplugin") // output namespace (defaults to font namespace) } fonts.create("myplugin:icons") { offsets = setOf(12, 24) } } dependencies { // Merge the contents of another Tinsel resource pack subproject include(project(":resources")) } ``` Build tasks added by the plugin: ```bash # Generate all offset font JSON files into build/tinsel/ ./gradlew :mypack:generateFonts # Assemble the final resource pack zip into build/distributions/ ./gradlew :mypack:assembleResourcePack # Copy the assembled zip directly to the Minecraft resource packs folder MINECRAFT_RESOURCE_PACKS_FOLDER=~/.minecraft/resourcepacks ./gradlew :mypack:copyToMinecraft ``` ``` -------------------------------- ### FontFamily - Loading font families Source: https://context7.com/lucyydotp/tinsel/llms.txt Demonstrates various methods for loading FontFamily objects, including using the vanilla font, vanilla with offsets, from pre-generated JSON files, and from resource pack zips. ```APIDOC ## FontFamily — Loading font families `FontFamily` represents a group of resource-pack fonts sharing the same glyphs but with different ascent offsets, enabling vertical repositioning of text. It can be loaded from a Tinsel pre-generated definition file, directly from a resource pack zip, or constructed programmatically using vanilla metrics. ```java import me.lucyydotp.tinsel.font.FontFamily; import me.lucyydotp.tinsel.font.OffsetMap; import net.kyori.adventure.key.Key; import java.nio.file.Path; // 1. Use the built-in vanilla font (no offsets) FontFamily vanilla = FontFamily.vanilla(); // 2. Vanilla font augmented with offset variants from the Tinsel resource pack FontFamily vanillaOffsets = FontFamily.vanillaWithOffsets( OffsetMap.offsets(Key.key("tinsel", "default"), -4, -8, -12, 4, 8, 12) ); // 3. Load from a pre-generated Tinsel JSON font definition FontFamily preGenerated = FontFamily.fromPreGenerated( Path.of("/server/plugins/myplugin/fonts/myfont.json") ); // 4. Load one or more families directly from a resource pack zip Key glyphFont = Key.key("myplugin:ui"); Set packFamilies = FontFamily.fromResourcePack( Path.of("/server/plugins/myplugin/pack.zip") ) .add(glyphFont, OffsetMap.offsets(glyphFont, 8, 16, -8)) .add(Key.key("myplugin:icons")) // no offsets .build(); // Compose into a FontSet and use with Tinsel Tinsel tinsel = Tinsel.builder() .withFonts(packFamilies) .build(); ``` ``` -------------------------------- ### Load Font Families with FontFamily Source: https://context7.com/lucyydotp/tinsel/llms.txt Demonstrates loading font families programmatically. Use `FontFamily.vanilla()` for the default font, `vanillaWithOffsets` for offset variants, `fromPreGenerated` for JSON definitions, and `fromResourcePack` for zip files. ```java import me.lucyydotp.tinsel.font.FontFamily; import me.lucyydotp.tinsel.font.OffsetMap; import net.kyori.adventure.key.Key; import java.nio.file.Path; // 1. Use the built-in vanilla font (no offsets) FontFamily vanilla = FontFamily.vanilla(); // 2. Vanilla font augmented with offset variants from the Tinsel resource pack FontFamily vanillaOffsets = FontFamily.vanillaWithOffsets( OffsetMap.offsets(Key.key("tinsel", "default"), -4, -8, -12, 4, 8, 12) ); // 3. Load from a pre-generated Tinsel JSON font definition FontFamily preGenerated = FontFamily.fromPreGenerated( Path.of("/server/plugins/myplugin/fonts/myfont.json") ); // 4. Load one or more families directly from a resource pack zip Key glyphFont = Key.key("myplugin:ui"); Set packFamilies = FontFamily.fromResourcePack( Path.of("/server/plugins/myplugin/pack.zip") ) .add(glyphFont, OffsetMap.offsets(glyphFont, 8, 16, -8)) .add(Key.key("myplugin:icons")) // no offsets .build(); // Compose into a FontSet and use with Tinsel Tinsel tinsel = Tinsel.builder() .withFonts(packFamilies) .build(); ``` -------------------------------- ### Create Spacing Components with Spacing.spacing() Source: https://context7.com/lucyydotp/tinsel/llms.txt Generate Adventure Components that represent pixel spacing for cursor manipulation. Use positive values to advance and negative values to rewind the cursor. ```java import me.lucyydotp.tinsel.font.Spacing; // Advance 16 pixels to the right Component rightShift = Spacing.spacing(16); // Rewind 32 pixels to the left (overlap previous content) Component leftShift = Spacing.spacing(-32); // Manually compose a component with explicit spacing Component composed = Component.text() .append(Component.text("Left label")) .append(Spacing.spacing(-60)) // backtrack 60px .append(Component.text("Overlaid!").color(NamedTextColor.YELLOW)) .build(); // The Spacing FontFamily can also be registered into a FontSet FontSet fonts = FontSet.of(Spacing.font(), FontFamily.vanilla()); TextWidthMeasurer measurer = new TextWidthMeasurer(fonts); int measured = measurer.measure(Spacing.spacing(128)); // returns 128 ``` -------------------------------- ### Tinsel Gradle Plugin Build Tasks Source: https://context7.com/lucyydotp/tinsel/llms.txt Common Gradle tasks provided by the Tinsel plugin for resource pack management. Use `generateFonts` to create JSON files, `assembleResourcePack` to build the zip, and `copyToMinecraft` to deploy. ```bash # Generate all offset font JSON files into build/tinsel/ ./gradlew :mypack:generateFonts # Assemble the final resource pack zip into build/distributions/ ./gradlew :mypack:assembleResourcePack # Copy the assembled zip directly to the Minecraft resource packs folder MINECRAFT_RESOURCE_PACKS_FOLDER=~/.minecraft/resourcepacks ./gradlew :mypack:copyToMinecraft ``` -------------------------------- ### Configure Tinsel Gradle Plugin for Resource Packs Source: https://context7.com/lucyydotp/tinsel/llms.txt Apply the Tinsel Gradle plugin to generate offset font JSON and assemble resource packs. Configure font families, offsets, and output details via the `tinsel` DSL. ```kotlin // build.gradle.kts (resource pack subproject) plugins { id("me.lucyydotp.tinsel") } tinsel { // Override the output zip filename (default: "resources.zip") packArchiveName = "my-server-pack.zip" // Declare a font family to generate offset variants for. // The name is a resource key: "namespace:path" // The base font JSON must exist at: // src/main/resources/assets//font/.json fonts.create("myplugin:hud") { offsets = setOf(-8, -16, 8, 16) // generate _offset_-8, _offset_8, etc. addedBitmapSpacing.set(2) // adds vertical padding to bitmap textures outputNamespace.set("myplugin") // output namespace (defaults to font namespace) } fonts.create("myplugin:icons") { offsets = setOf(12, 24) } } dependencies { // Merge the contents of another Tinsel resource pack subproject include(project(":resources")) } ``` -------------------------------- ### OffsetMap.offsets() - Build offset key maps Source: https://context7.com/lucyydotp/tinsel/llms.txt Utility function to generate a map of integer offsets to Keys, used for creating font families with specific vertical positioning. ```APIDOC ## `OffsetMap.offsets()` — Build offset key maps `OffsetMap.offsets()` is a utility that generates the `Map` expected by `FontFamily.vanillaWithOffsets()` and `FontFamily.ResourcePackBuilder.add()`. For a base key `ns:name` and an offset `n`, it creates the key `ns:name_offset_n`. ```java import me.lucyydotp.tinsel.font.OffsetMap; import net.kyori.adventure.key.Key; import java.util.Map; Key base = Key.key("myplugin", "hud"); // Generates: { -8 -> "myplugin:hud_offset_-8", 8 -> "myplugin:hud_offset_8", 16 -> "myplugin:hud_offset_16" } Map offsets = OffsetMap.offsets(base, -8, 8, 16); FontFamily family = FontFamily.vanillaWithOffsets(offsets); // The resource pack must contain fonts named myplugin:hud_offset_-8, etc. ``` ``` -------------------------------- ### FontSet - Composing font collections Source: https://context7.com/lucyydotp/tinsel/llms.txt Details on creating and using FontSet objects, which are immutable collections of FontFamily objects used with Tinsel and TextWidthMeasurer. ```APIDOC ## `FontSet` — Composing font collections `FontSet` is an immutable collection of `FontFamily` objects, always guaranteed to include the default Minecraft font. It is the font registry passed to `Tinsel` and `TextWidthMeasurer`. ```java import me.lucyydotp.tinsel.font.FontSet; import me.lucyydotp.tinsel.font.Spacing; import me.lucyydotp.tinsel.font.FontFamily; // Create a font set from varargs FontSet simple = FontSet.of(FontFamily.vanilla(), Spacing.font()); // Create from an iterable of families List families = List.of(FontFamily.vanilla(), Spacing.font()); FontSet fromList = FontSet.of(families); // Access fonts FontFamily defaultFont = simple.defaultFont(); FontFamily maybeNull = simple.fontFamily(Key.key("myplugin:ui")); // null if absent Font specificFont = simple.font(Key.key("tinsel:default_offset_-8")); // null if absent Map all = simple.fontFamilies(); ``` ``` -------------------------------- ### Render Fixed-Width Text with Tinsel Source: https://context7.com/lucyydotp/tinsel/llms.txt Renders a text component within a specified total pixel width, applying a base style and executing a consumer for drawing text elements. The resulting component is padded with spacing glyphs to match the `totalWidth`. ```java // Render a victory screen overlay in a 255-pixel action bar Component victoryScreen = tinsel.draw(255, Style.style(ShadowColor.none()), ctx -> { // Draw a background glyph centred ctx.drawAligned(Component.text("\uE001").font(GLYPH_FONT), 0.5f); // Move cursor vertically to -8px (up) relative to baseline, keep X ctx.moveCursor(ctx.cursorX(), -8); ctx.drawAligned( Component.text("VICTORY!").color(NamedTextColor.GREEN).decorate(TextDecoration.BOLD), 0.5f ); // Stats row at Y=+8 ctx.moveCursor(24, 8); ctx.draw(Component.text("Kills")); ctx.moveCursor(102, 8); ctx.draw(Component.text("15").decorate(TextDecoration.BOLD), 1f); // right-align at x=102 ctx.moveCursor(153, 8); ctx.draw(Component.text("XP")); ctx.moveCursor(228, 8); ctx.draw( Component.text("+99999").color(NamedTextColor.LIGHT_PURPLE).decorate(TextDecoration.BOLD), 1f ); }); ``` -------------------------------- ### Measure Component Width with TextWidthMeasurer Source: https://context7.com/lucyydotp/tinsel/llms.txt Measure the pixel width of Adventure Components using TextWidthMeasurer. This is useful for manual layout, like centering text. It accounts for font styles like bold. ```java TextWidthMeasurer measurer = tinsel.textWidthMeasurer(); // Measure a plain text component Component label = Component.text("Score:"); int width = measurer.measure(label); // e.g. returns 30 // Measure a bold component (each glyph gets +1px) Component boldLabel = Component.text("SCORE:").decorate(TextDecoration.BOLD); int boldWidth = measurer.measure(boldLabel); // wider than plain // Use measurement to manually centre content Component value = Component.text("9999").color(NamedTextColor.GOLD); int valueWidth = measurer.measure(value); tinsel.draw(255, Style.empty(), ctx -> { ctx.moveCursor(ctx.cursorX() - valueWidth / 2, ctx.cursorY()); // manual centre ctx.drawWithWidth(value, valueWidth); }); // Standalone measurer (without a full Tinsel instance) TextWidthMeasurer standalone = new TextWidthMeasurer( FontSet.of(FontFamily.vanilla()) ); int vanillaWidth = standalone.measure(Component.text("The Quick Brown Fox")); // returns 101 ``` -------------------------------- ### Tinsel.draw() - Render a fixed-width text component Source: https://context7.com/lucyydotp/tinsel/llms.txt Renders a text component with a specified total width, applying a base style and executing a drawing context consumer for detailed layout. ```APIDOC ## Tinsel.draw() ### Description Invokes a `TextDrawContext` consumer and returns the resulting `Component`, padded to exactly `totalWidth` pixels with spacing glyphs. The `baseStyle` is applied to the root component. ### Method Signature `Component draw(int totalWidth, Style baseStyle, TextDrawContextConsumer consumer)` ### Parameters - **totalWidth** (int) - The exact pixel width the resulting component should occupy. - **baseStyle** (Style) - The base style to apply to the root component. - **consumer** (TextDrawContextConsumer) - A lambda function that receives a `TextDrawContext` to perform drawing operations. ### Usage Example ```java // Render a victory screen overlay in a 255-pixel action bar Component victoryScreen = tinsel.draw(255, Style.style(ShadowColor.none()), ctx -> { // Draw a background glyph centred ctx.drawAligned(Component.text("\uE001").font(GLYPH_FONT), 0.5f); // Move cursor vertically to -8px (up) relative to baseline, keep X ctx.moveCursor(ctx.cursorX(), -8); ctx.drawAligned( Component.text("VICTORY!").color(NamedTextColor.GREEN).decorate(TextDecoration.BOLD), 0.5f ); // Stats row at Y=+8 ctx.moveCursor(24, 8); ctx.draw(Component.text("Kills")); ctx.moveCursor(102, 8); ctx.draw(Component.text("15").decorate(TextDecoration.BOLD), 1f); // right-align at x=102 ctx.moveCursor(153, 8); ctx.draw(Component.text("XP")); ctx.moveCursor(228, 8); ctx.draw( Component.text("+99999").color(NamedTextColor.LIGHT_PURPLE).decorate(TextDecoration.BOLD), 1f ); }); ``` ``` -------------------------------- ### Compose Font Collections with FontSet Source: https://context7.com/lucyydotp/tinsel/llms.txt An immutable collection of `FontFamily` objects, always including the default Minecraft font. Used as the font registry for `Tinsel` and `TextWidthMeasurer`. ```java import me.lucyydotp.tinsel.font.FontSet; import me.lucyydotp.tinsel.font.Spacing; import me.lucyydotp.tinsel.font.FontFamily; // Create a font set from varargs FontSet simple = FontSet.of(FontFamily.vanilla(), Spacing.font()); // Create from an iterable of families List families = List.of(FontFamily.vanilla(), Spacing.font()); FontSet fromList = FontSet.of(families); // Access fonts FontFamily defaultFont = simple.defaultFont(); FontFamily maybeNull = simple.fontFamily(Key.key("myplugin:ui")); // null if absent Font specificFont = simple.font(Key.key("tinsel:default_offset_-8")); // null if absent Map all = simple.fontFamilies(); ``` -------------------------------- ### Draw Components with TextDrawContext Source: https://context7.com/lucyydotp/tinsel/llms.txt Use TextDrawContext to manage cursor position and draw components within a specified canvas width. Supports absolute cursor movement, left-aligned, centered, and fixed-width drawing. ```java tinsel.draw(255, Style.empty(), ctx -> { // Read current cursor position int x = ctx.cursorX(); // current horizontal position in pixels int y = ctx.cursorY(); // current vertical offset in pixels int total = ctx.totalWidth(); // total canvas width (255) // Move cursor to absolute coordinates (uses spacing glyphs for X, offset fonts for Y) ctx.moveCursor(50, -16); // move to x=50, y=-16 (16px up from baseline) // Draw a component, left-aligned from cursor ctx.draw(Component.text("Hello")); // Draw centred on the cursor (align=0.5 shifts left by half the component width) ctx.draw(Component.text("World"), 0.5f); // Draw aligned relative to the total canvas width (0=left, 0.5=centre, 1=right) ctx.drawAligned(Component.text("Footer"), 0.5f); // Draw with a pre-known width (skips measurement) int knownWidth = 40; ctx.drawWithWidth(Component.text("Fast"), knownWidth); }); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.