[{"data":1,"prerenderedAt":276},["ShallowReactive",2],{"docs-\u002Fmodules\u002Fplaceholders-advanced":3},{"id":4,"title":5,"body":6,"description":266,"extension":267,"meta":268,"navTitle":269,"navigation":270,"path":271,"rawbody":272,"seo":273,"stem":274,"__hash__":275},"docs\u002Fmodules\u002Fplaceholders-advanced.md","Placeholders Advanced",{"type":7,"value":8,"toc":253},"minimark",[9,13,17,22,25,36,39,43,46,50,57,60,74,85,102,105,111,115,129,135,139,142,148,151,157,160,164,167,173,177,190,196,203,207,213,217],[10,11,5],"h1",{"id":12},"placeholders-advanced",[14,15,16],"p",{},"This page covers namespace metadata, listeners, local scopes, and platform\nintegration details.",[18,19,21],"h2",{"id":20},"namespace-metadata","Namespace Metadata",[14,23,24],{},"Register namespace metadata to expose author and version information:",[26,27,33],"pre",{"className":28,"code":30,"language":31,"meta":32},[29],"language-java","MagicPlaceholders.registerNamespace(\"donatemenu\", \"THEROER\", \"1.10.0\");\n","java","",[34,35,30],"code",{"__ignoreMap":32},[14,37,38],{},"Metadata is consumed by PlaceholderAPI expansions and Fabric namespace\nregistration layers.",[18,40,42],{"id":41},"key-normalization","Key Normalization",[14,44,45],{},"Namespaces and keys are normalized to lowercase. Use lowercase names to avoid\naccidental duplicates.",[18,47,49],{"id":48},"arguments","Arguments",[14,51,52,53,56],{},"Resolvers receive an optional ",[34,54,55],{},"argument"," string.",[14,58,59],{},"PlaceholderAPI-style examples:",[61,62,63,69],"ul",{},[64,65,66],"li",{},[34,67,68],{},"%donatemenu_balance%",[64,70,71],{},[34,72,73],{},"%donatemenu_balance:bank%",[14,75,76,77,80,81,84],{},"Inside ",[34,78,79],{},"MagicPlaceholders.render(...)",", the default argument separator is ",[34,82,83],{},"|",":",[61,86,87,92,97],{},[64,88,89],{},[34,90,91],{},"{balance|bank}",[64,93,94],{},[34,95,96],{},"{donatemenu:balance}",[64,98,99],{},[34,100,101],{},"{donatemenu:balance:bank}",[14,103,104],{},"Override the local separator per context when needed:",[26,106,109],{"className":107,"code":108,"language":31,"meta":32},[29],"PlaceholderContext context = PlaceholderContext.builder()\n    .argumentSeparator(\"::\")\n    .build();\n",[34,110,108],{"__ignoreMap":32},[18,112,114],{"id":113},"audience-handling","Audience Handling",[14,116,117,120,121,124,125,128],{},[34,118,119],{},"Audience"," can be ",[34,122,123],{},"null"," for console or offline contexts. Use\n",[34,126,127],{},"MagicPlaceholders.audienceFromUuid(UUID)"," when you only have a player ID:",[26,130,133],{"className":131,"code":132,"language":31,"meta":32},[29],"MagicPlaceholders.register(\"donatemenu\", \"balance\", (audience, arg) -> {\n    if (audience == null) {\n        return \"0\";\n    }\n    return \"42\";\n});\n",[34,134,132],{"__ignoreMap":32},[18,136,138],{"id":137},"local-and-global-placeholders","Local And Global Placeholders",[14,140,141],{},"Global placeholders are namespace-free:",[26,143,146],{"className":144,"code":145,"language":31,"meta":32},[29],"MagicPlaceholders.registerGlobal(\"server\", (audience, arg) -> \"Example\");\n",[34,147,145],{"__ignoreMap":32},[14,149,150],{},"Local placeholders are tied to an owner key such as a plugin instance, a\nlogger, or another stable runtime object:",[26,152,155],{"className":153,"code":154,"language":31,"meta":32},[29],"MagicPlaceholders.registerLocal(this, \"balance\", (audience, arg) -> \"42\");\n",[34,156,154],{"__ignoreMap":32},[14,158,159],{},"This is useful when you want one placeholder key to mean different things in\ndifferent runtime scopes.",[18,161,163],{"id":162},"registry-listeners","Registry Listeners",[14,165,166],{},"Listen to registry changes:",[26,168,171],{"className":169,"code":170,"language":31,"meta":32},[29],"MagicPlaceholders.addListener(new MagicPlaceholders.PlaceholderListener() {\n    public void onPlaceholderRegistered(MagicPlaceholders.PlaceholderKey key) {\n        \u002F\u002F refresh cache, update UI, etc.\n    }\n\n    public void onPlaceholderUnregistered(MagicPlaceholders.PlaceholderKey key) {\n    }\n\n    public void onNamespaceUpdated(String namespace) {\n    }\n});\n",[34,172,170],{"__ignoreMap":32},[18,174,176],{"id":175},"debug-listeners","Debug Listeners",[14,178,179,180,183,184,186,187,189],{},"Subscribe to resolution events. The listener's ",[34,181,182],{},"onResolve"," receives the resolved\nkey, owner context, audience, argument, the resolved value (",[34,185,123],{}," on error), and\nthe error (",[34,188,123],{}," on success):",[26,191,194],{"className":192,"code":193,"language":31,"meta":32},[29],"MagicPlaceholders.addDebugListener(new MagicPlaceholders.PlaceholderDebugListener() {\n    @Override\n    public void onResolve(MagicPlaceholders.PlaceholderKey key,\n                          Object ownerKey,\n                          Audience audience,\n                          String argument,\n                          String value,\n                          Throwable error) {\n        if (error != null) {\n            \u002F\u002F resolution failed for `key`\n        } else {\n            \u002F\u002F `key` resolved to `value`\n        }\n    }\n});\n",[34,195,193],{"__ignoreMap":32},[14,197,198,199,202],{},"This is especially useful when debugging placeholder chains inside logger\noutput. ",[34,200,201],{},"LoggerCore"," registers such a listener itself when debug logging is on.",[18,204,206],{"id":205},"safe-resolution","Safe Resolution",[14,208,209,212],{},[34,210,211],{},"MagicPlaceholders.resolve(...)"," returns an empty string when the placeholder is\nmissing or when a resolver throws. Keep resolvers fast and side-effect free.",[18,214,216],{"id":215},"integration-summary","Integration Summary",[61,218,219,230,239],{},[64,220,221,222,229],{},"Bukkit: auto-bridges to ",[223,224,228],"a",{"href":225,"rel":226},"https:\u002F\u002Fmodrinth.com\u002Fplugin\u002Fplaceholderapi",[227],"nofollow","PlaceholderAPI","\nwhen the Bukkit logger integration is active.",[64,231,232,233,238],{},"Fabric: registers with ",[223,234,237],{"href":235,"rel":236},"https:\u002F\u002Fplaceholders.pb4.eu\u002F",[227],"PB4 Placeholder API","\nwhen present.",[64,240,232,241,246,247,252],{},[223,242,245],{"href":243,"rel":244},"https:\u002F\u002Fmodrinth.com\u002Fmod\u002Fplaceholder-api",[227],"Text Placeholder API","\nand ",[223,248,251],{"href":249,"rel":250},"https:\u002F\u002Fmodrinth.com\u002Fmod\u002Fminiplaceholders",[227],"MiniPlaceholders"," when present.",{"title":32,"searchDepth":254,"depth":254,"links":255},3,[256,258,259,260,261,262,263,264,265],{"id":20,"depth":257,"text":21},2,{"id":41,"depth":257,"text":42},{"id":48,"depth":257,"text":49},{"id":113,"depth":257,"text":114},{"id":137,"depth":257,"text":138},{"id":162,"depth":257,"text":163},{"id":175,"depth":257,"text":176},{"id":205,"depth":257,"text":206},{"id":215,"depth":257,"text":216},"Advanced MagicUtils placeholders: dynamic resolvers, arguments, caching, and bridging into PlaceholderAPI on Bukkit\u002FPaper.","md",{},null,true,"\u002Fmodules\u002Fplaceholders-advanced","---\ntitle: Placeholders Advanced\ndescription: 'Advanced MagicUtils placeholders: dynamic resolvers, arguments, caching, and bridging into PlaceholderAPI on Bukkit\u002FPaper.'\n---\n\n# Placeholders Advanced\n\nThis page covers namespace metadata, listeners, local scopes, and platform\nintegration details.\n\n## Namespace Metadata\n\nRegister namespace metadata to expose author and version information:\n\n```java\nMagicPlaceholders.registerNamespace(\"donatemenu\", \"THEROER\", \"1.10.0\");\n```\n\nMetadata is consumed by PlaceholderAPI expansions and Fabric namespace\nregistration layers.\n\n## Key Normalization\n\nNamespaces and keys are normalized to lowercase. Use lowercase names to avoid\naccidental duplicates.\n\n## Arguments\n\nResolvers receive an optional `argument` string.\n\nPlaceholderAPI-style examples:\n\n- `%donatemenu_balance%`\n- `%donatemenu_balance:bank%`\n\nInside `MagicPlaceholders.render(...)`, the default argument separator is `|`:\n\n- `{balance|bank}`\n- `{donatemenu:balance}`\n- `{donatemenu:balance:bank}`\n\nOverride the local separator per context when needed:\n\n```java\nPlaceholderContext context = PlaceholderContext.builder()\n    .argumentSeparator(\"::\")\n    .build();\n```\n\n## Audience Handling\n\n`Audience` can be `null` for console or offline contexts. Use\n`MagicPlaceholders.audienceFromUuid(UUID)` when you only have a player ID:\n\n```java\nMagicPlaceholders.register(\"donatemenu\", \"balance\", (audience, arg) -> {\n    if (audience == null) {\n        return \"0\";\n    }\n    return \"42\";\n});\n```\n\n## Local And Global Placeholders\n\nGlobal placeholders are namespace-free:\n\n```java\nMagicPlaceholders.registerGlobal(\"server\", (audience, arg) -> \"Example\");\n```\n\nLocal placeholders are tied to an owner key such as a plugin instance, a\nlogger, or another stable runtime object:\n\n```java\nMagicPlaceholders.registerLocal(this, \"balance\", (audience, arg) -> \"42\");\n```\n\nThis is useful when you want one placeholder key to mean different things in\ndifferent runtime scopes.\n\n## Registry Listeners\n\nListen to registry changes:\n\n```java\nMagicPlaceholders.addListener(new MagicPlaceholders.PlaceholderListener() {\n    public void onPlaceholderRegistered(MagicPlaceholders.PlaceholderKey key) {\n        \u002F\u002F refresh cache, update UI, etc.\n    }\n\n    public void onPlaceholderUnregistered(MagicPlaceholders.PlaceholderKey key) {\n    }\n\n    public void onNamespaceUpdated(String namespace) {\n    }\n});\n```\n\n## Debug Listeners\n\nSubscribe to resolution events. The listener's `onResolve` receives the resolved\nkey, owner context, audience, argument, the resolved value (`null` on error), and\nthe error (`null` on success):\n\n```java\nMagicPlaceholders.addDebugListener(new MagicPlaceholders.PlaceholderDebugListener() {\n    @Override\n    public void onResolve(MagicPlaceholders.PlaceholderKey key,\n                          Object ownerKey,\n                          Audience audience,\n                          String argument,\n                          String value,\n                          Throwable error) {\n        if (error != null) {\n            \u002F\u002F resolution failed for `key`\n        } else {\n            \u002F\u002F `key` resolved to `value`\n        }\n    }\n});\n```\n\nThis is especially useful when debugging placeholder chains inside logger\noutput. `LoggerCore` registers such a listener itself when debug logging is on.\n\n## Safe Resolution\n\n`MagicPlaceholders.resolve(...)` returns an empty string when the placeholder is\nmissing or when a resolver throws. Keep resolvers fast and side-effect free.\n\n## Integration Summary\n\n- Bukkit: auto-bridges to [PlaceholderAPI](https:\u002F\u002Fmodrinth.com\u002Fplugin\u002Fplaceholderapi)\n  when the Bukkit logger integration is active.\n- Fabric: registers with [PB4 Placeholder API](https:\u002F\u002Fplaceholders.pb4.eu\u002F)\n  when present.\n- Fabric: registers with [Text Placeholder API](https:\u002F\u002Fmodrinth.com\u002Fmod\u002Fplaceholder-api)\n  and [MiniPlaceholders](https:\u002F\u002Fmodrinth.com\u002Fmod\u002Fminiplaceholders) when present.\n",{"title":5,"description":266},"modules\u002Fplaceholders-advanced","xb6MPHfZkQR-ZESZUJY2hs_d54jkU-NlVfNDBZO7y2k",1783944486736]