Patchouli Documentation

repository·26.1·Indexed 18 days ago

https://github.com/vazkiimods/patchouli

A data-driven, dependency-free documentation framework for Minecraft modders and pack makers to create in-game guides. Includes guides on adding Patchouli as a dependency for Fabric and NeoForge, using Component Processors to derive template variables, and detailed specifications for template components such as text, items, images, entities, and tooltips.

Tokens
16.9K
Snippets
49
Records
90
Agent score
63%

What's inside Patchouli

  1. How Config Flags work for gating content

    26.1

    Config Flags allow you to dynamically enable or disable content within a Patchouli book (including categories, entries, pages, or template components) based on the game environment or configuration settings.

    In your book's JSON structures, you can assign a "flag" tag to an element. If the expression assigned to that flag evaluates to false, the content is disabled and will not appear in the book. If a flag name is used that has not been defined, it defaults to false.

  2. Understand multiblock pattern indexing and directions

    26.1

    When defining a pattern, the axes follow programming conventions rather than standard cardinal directions. This is critical when placing blocks with specific properties like facing.

    • Y-axis: The outer array. Index 0 is the top layer, increasing downwards.
    • X-axis: The middle array. Later entries in the array move East.
    • Z-axis: The characters within the strings. Later characters in the string move South.

    Example for placing stairs facing different directions:

    "pattern": [
      [
        " W ",
        "N S",
        " E "
      ]
    ],
    "mapping": {
      "W": "minecraft:oak_stairs[facing=west]",
      "N": "minecraft:oak_stairs[facing=north]",
      "S": "minecraft:oak_stairs[facing=south]",
      "E": "minecraft:oak_stairs[facing=east]"
    }
  3. Bind variables in included templates

    26.1

    Variables inside an included template can be resolved using the alias defined in the as key.

    Default Resolution

    If you include a template as incl, and that template uses a variable #text, you access it in the parent template (or entry) using the path incl.text.

    Using the using object for custom binding

    You can use the using object to remap variables or provide static values. This allows you to change the variable name or bind it to a parent variable.

    1. Static Values: Set a variable to a specific string.
    2. Variable Rebinding: Map an included variable to a parent variable (e.g., mapping #text in the child to #text in the parent). This allows you to use the variable directly (e.g., text) instead of using the alias prefix (e.g., incl.text).
    "include": [
        {
            "template": "sometemplate",
            "as": "incl",
            "using": {
                 "text": "I'm an included template"
            }
        }
    ]
  4. Common attributes for all Patchouli page types

    26.1

    Every page object within a pages array in a Patchouli Entry can use the following common attributes to control visibility, locking, and internal referencing:

    • type (String, mandatory): The namespaced ID determining the page type (e.g., patchouli:text). In 1.17+, use fully-qualified namespaced IDs. In 1.16 or earlier, use the short name (e.g., text).
    • advancement (String): A resource location pointing to a Minecraft advancement. The page will only appear once this advancement is completed. Leaving it empty or omitting it keeps the page unlocked.
    • flag (String): A config flag expression that determines if the page should exist based on user configuration.
    • anchor (String): A unique identifier used to refer to this specific page via internal links.
  5. Use variables in Patchouli templates

    26.1

    You can pass dynamic data from a book entry into a template using variables.

    1. In the Template: Define a variable by prefixing a key with a hash symbol (e.g., "#text").
    2. In the Entry: Provide a value for that key at the same level as the type declaration.

    Example Template (test_template.json):

    {
    	"components": [
    		{
    			"type": "patchouli:text",
    			"text": "#text",
    			"x": 20,
    			"y": 30
    		}
    	]
    }

    Example Entry:

    {
        "type": "yourbooknamespace:test_template",
        "text": "We just passed in the text from a variable!"
    }

    Constraints:

    • You can define multiple unique variables (e.g., #upper_text, #lower_text).
    • Warning: You cannot use variable names that conflict with existing common keys used by Default Page Types.
    {
    	"components": [
    		{
    			"type": "patchouli:text",
    			"text": "#text",
    			"x": 20,
    			"y": 30
    		}
    	]
    }
  6. Derive data from variables using functions

    26.1

    Patchouli allows you to transform variable values by applying functions. To apply a function, append ->func to the variable name inside the # delimiters.

    Key capabilities:

    • Chaining: You can chain multiple functions together (e.g., #item->iname->capital).
    • Inline Derivation: You can use derived variables directly within a string (e.g., This recipe produces #item->iname#.).
    • Logic Guards: Functions that return true or false can be used with the guard attribute in template components to conditionally show/hide elements.
    // Example of chaining: getting an item name and capitalizing it
    "text": "You need #item->iname->capital#"
  7. Create Quest Pages (`patchouli:quest`)

    26.1

    Quest pages allow you to create interactive objectives within a Patchouli entry. When a quest is completed, the entry in the book will display a checkmark and move to the end of the list to keep the interface clean.

    Important Constraints:

    • Do not place multiple quest pages within a single entry, as this will prevent the completion status from being marked correctly.
    • It is recommended to use the [turnin](/docs/reference/entry-json) feature in the entry when using quest pages.

    Fields:

    • trigger (String): The advancement ID that must be completed to clear the quest. Leave this empty if you want the quest to be completed manually.
    • title (String): The title displayed above the links. If omitted or empty, it defaults to "Objective".
    • text (String): The body text displayed under the links. Supports text formatting.
    {
      "type": "patchouli:quest",
      "trigger": "minecraft:story/my_advancement",
      "title": "Gathering Materials",
      "text": "Collect 5 iron ingots to proceed."
    }
  8. Licensing and Jar-in-Jar bundling considerations

    26.1

    Patchouli's original code and assets are licensed under CC-BY-NC-SA 3.0 Unported.

    Licensing implications for modders:

    • Normal Dependency: If you simply depend on Patchouli via your build system, there are no licensing concerns because the mod is remapped to Intermediary (or SRG for Forge) upon compilation.
    • Jar-in-Jar Bundling: If you bundle Patchouli inside your mod using Jar-in-Jar, your mod will include a refmap containing raw Mojang mappings in a JSON file. If this presents a licensing conflict for your project, do not bundle Patchouli; instead, depend on it externally.

    It is generally recommended to use normal dependencies rather than Jar-in-Jar to keep archive sizes smaller.

  9. Extend an Existing Book (Pre-1.20 Only)

    26.1

    In versions before 1.20, you can create an "extension book" that adds content to an existing book without creating a new item.

    • extend (String): The ID of the target book to extend (format: modid:path). For example, patchouli:coolbook extends a book located at /data/patchouli/patchouli_books/coolbook/book.json.
    • allow_extensions (boolean): If false, prevents other books from extending this book (defaults to true).

    Note: When extend is set, all other keys in the JSON file are ignored. The extension book inherits all entries, categories, templates, and macros from the target book.

    {
      "extend": "patchouli:coolbook"
    }