PlaceholderAPI - A hub for your placeholders


Would it not make sense for this to be for a CommandSource? For example, I might want to display the name of the person observing the message, but I can’t do it through the console. I can imaging that there may be instances where you want to use a placeholder with respect to the console or other source, rather than just a Player.


I suppose so, but the issue is that there is much more limited information about CommandSource than there is about Player, so I am unsure about that. I might try to switch to an annotation system similar to how Sponge handles listeners, something like this:

public Object placeholder(@Source Player player, @Token Optional<String> token) {
    // Placeholder annotation requires id to be specified and to be attached to a method
    // Method can return anything but I am using Object to support a variety of different outputs for one method
    // Source can specify what requirements the placeholder has, for instance CommandSource, Player, Locatable, etc

public void sound(@Source Player player) {
    // The only parameter annotation required is @Source, order should be irrelevant

@Placeholder(id = "player", author = "Wundero", version = "1.0", desc = "Relational player placeholders.")
public Object relate(@Source CommandSource source, @Observer CommandSource observer, @Token String token) {
    // Relational placeholders register separately from normal ones
    // Token can be String or Optional<String> but if it is String it is nullable

This way might be the best way of handling placeholders as it is more dynamic, but it will definitely take a while to implement. If I am to do the CommandSource change, I am going to do all of this at once.

@dualspiral Any thoughts on this or is this a good way to move forwards?


Update on annotation system + version 4.0:

For version 4.0, I have decided to ditch the previous breaking changes in favour of these ones. This update will break every plugin using it, so I do not expect people to update to it readily. I will release a version 3.12 alongside it with some bugfixes but nothing API breaking, but 3.12 will be the last 3.X version I release. Going forwards, this annotation system will be easier to use and more powerful, so I look forward to seeing the transition.

As for progress, I am mostly done the core system, just need to make some minor improvements and then finish testing. I am going to mention that the Source annotation is no longer necessary, method return type can be anything except void, and the supported types for Source and Observer are Locatable, User, CommandSource and any derivatives. This update breaks everything the previous versions had so I don’t expect people to start using this quickly. Placeholders themselves should be more powerful now, but I am still trying to figure out how to properly gather the non-essential or dynamic information about placeholders (for instance, JavaScript supported tokens are loaded scripts, which is a variable I am unable to pass into an annotation). Once I figure that out I will be able to finalize this update. Looks to me like it works and performs well (I decided to take the route of Sponge’s event system rather than using reflection because it saves on a decent chunk of performance, and I am using LoadingCaches to reduce memory consumption by unused placeholders. The cache has no expiry yet because I figured writing a new class every x minutes might not be the best idea, but it seems to be fast so I might change that), so I will not be changing the core much more.

I still haven’t finalized the system so any input will be appreciated. I will be pushing the source code to the GitHub repo soon, under a separate branch so as to retain documentation of the old version, if you want to see it. Any help finishing this would be much appreciated :).


@dualspiral I will create a PR for Gluon once I finish up this update so that you can focus on your main projects. Hopefully this update covers your CommandSource use cases :wink:


Thanks, I appreciate it!


Ok so I have another update message for 4.0 I guess.

I was running into an issue where I could not have changing information about the placeholder (such as configurable descriptions) due to the fact that it was in an annotation. So I ended up redoing much of the system again, and came to a better, two part but single faced solution.

From now on, all placeholders will be registered with an ExpansionBuilder. This builder allows you to fluently build and register placeholders, and supports BOTH the @Placeholder annotation system AND a functional parsing method system. This way, you can create methods with the @Placeholder annotation that can have dynamic information, or you can create a parse method implementation (with support for numerous functional arguments, such as BiConsumer<Source, Token> (proper types will be displayed when you use it in the builder)). I haven’t yet made a way to directly add @Placeholder annotated classes to the registry rather than using the builder, and I am unsure if I am going to, but that will be in the changelog if it is.

The default placeholders will no longer appear in the config file to enable or disable; instead, I will be adding a command to enable or disable them on the fly. While not exactly beneficial on RAM (and I have some tests I am going to do to figure out if and how I can lower the profile of the plugin further), it saves time from going into the config file and changing it, then having to reload the plugin.

I should mention that, in my last post, I said that I am not using reflection because it saves on performance: to clarify, I decided to do automatic class generation instead because I expect plugins to, in the future, be making rapid and numerous calls within short periods of time, for instance for scoreboard plugins updating every tick. The fact that this saves on roughly 4 times the performance (despite being unnoticable in normal use cases) will help many servers who use such plugins, I think.

The annotations I added last time will still work, except now the void return type IS supported, and will just return an empty value when replaced in text.

I ditched some of the LoadingCaches because they were more confusing to use than maps and, while they worked well, they don’t exactly fit the use case. I might return to them or something similar in the future to save memory, but the issue is that, if I try to use a weak referencing system or something else to save memory, I will run into missing placeholders and that is worse than a bit more RAM usage. I still have to test the RAM usage so this may not even be an issue, but I think it’s worth at least talking about as it may change how developers use the plugin.

As with last time, the source code is all on GitHub so any suggestions (particularly relating to this issue) would be lovely. :smiley:


A new version has been released for PlaceholderAPI, it is available for download here.

What’s new in version 3.12:

  • PlaceholderService now supports Text objects containing placeholders as parsing sources, rather than just Strings and TextTemplates.
  • Fixed some internal text parsing to make things work better.
  • Licensed the plugin under the MIT licence.
  • Updated the statistic placeholder to support missing “_” and/or “.” in the id of the stat. This does not change the modifier of the stat though, so you still need “.minecraft.log” if you want to specify logs.
  • Added relational placeholders. I would say more but 4.0 is coming soon and this is more of a legacy support update than anything else. I recommend using 4.0 ASAP since it will both function better AND support all of these changes.
  • Unbroke the API breaking changes I was going to make. Text onPlaceholderRequest(...) is still the implementation-requiring method.
  • Other minor fixes.

Important: THIS IS THE LAST UPDATE BEFORE 4.0 AND THE API REWRITE. If you update to this version, expect your old placeholder plugin hooks to work. If you switch to 4.0, expect your current placeholders (save the ones in the actual plugin) to break until you update the plugins attaching to this one. Gluon will likely update alongside or at least close to the release of 4.0, so there are not too many placeholders that will break, I expect.

Check out the plugin wiki!

View the plugin on GitHub!

See the plugin’s statistics!


Just an afterthought that I think might be useful to some: PlaceholderAPI is built off of SpongeAPI 5.1, but tested on SpongeAPI 7.0. There are no changes to the parts of SpongeAPI that PlaceholderAPI uses, so any version above and including 5.1 is supported.


A new version has been released for PlaceholderAPI, it is available for download here.

Version 4.0: The dynamic update.

This update is a major update to the plugin, and provides a whole host of new features to the plugin.

What’s new in version 4.0:

  • Refactored PlaceholderService class to support new internals. Relational placeholders are now supported and enforced by default, and the documentation covers use cases quite well. New methods are provided to use this updated service more effectively.
  • Removed all old semblance of Expansions in favour of a new Expansion system.
    • This expansion system uses generically typed classes to allow more types for sources, observers and return types.
    • This new system is easier to use, because of the newly added ExpansionBuilder. This builder can be created from the service and provides simple and fluent methods to create expansions.
    • Annotation-based methods: This is the really interesting part of the update. You can now create methods in any object, annotate them with @Placeholder, and, provided that there are no parameters that aren’t annotated properly, it will be used as a placeholder parsing method (via expansion builders). Similar to how Sponge handles events, this system allows you to create fully dynamic parsers from methods. The expansion builder has lots of details, and you can even create a builder straight from the service with this as well.
  • Numerous smaller fixes and updates have been added. Check the wiki in the coming days (I am running out of time right now) for any and all information you need to use this plugin, or check the commit change log on GitHub to see what was changed.
  • All default placeholders provided in the plugin are still present and work exactly the same; Unfortunately, there is currently no way to disable or enable any one placeholder, but in the next update there will be.


This update is VERY MUCH a breaking update. This means that any plugins using PlaceholderAPI WILL break. (Nucleus Gluon should receive an update very soon fixing it, but that is all I can confirm.) While this may discourage people from updating, plugins merely using the service to parse placeholders should quickly be able to update (they need to rearrange a few parameters and then they are finished). Plugins adding new placeholders might take some more time, but the new system allows for much easier placeholder registration so that shouldn’t take too long.

Look forward to 4.1 with some further changes (non-breaking) and fixes, but until then, here is 4.0.

Check out the plugin wiki!

View the plugin on GitHub!

See the plugin’s statistics!


A new version has been released for PlaceholderAPI, it is available for download here.

What’s new in version 4.1:

  • Fixed always registering objects as listeners despite not being annotated with the @Listening annotation on the class.
  • Added listen(Object listener) builder method to allow custom objects for listener registration. This is mostly useful to sync with placeholder reloads.
  • Added enable and disable commands - type /papi enable <id> [relational] or /papi disable <id> [relational] to execute. The commands do not care about the previous state; that is, if it was enabled and you enable it, this won’t change anything but will tell you the placeholder is now enabled. If you want to see which placeholders are enabled, type /papi l.

Check out the plugin wiki!

View the plugin on GitHub!

See the plugin’s statistics!


I’ve tried %statistic_deaths% as you suggested but that does not seem to work.

Can you list these down on the wiki? Like, death count, kill count, etc?


What version of PlaceholderAPI are you using?


I’m using the latest 4.1, but statistics should be in the plugin since version 3 something


What version of Sponge are you using?
It’s working for me on 1.12.1-7.0.0-BETA-321 with PAPI 4.1


I’m on sponge 2424. Scared to update to the latest versions >.< but if that’s what it takes to fix it, I guess I should.


PlaceholderAPI works on SpongeAPI versions 5.1 and newer, which means Minecraft versions 1.10.2 and newer. If your Sponge is older than that then this is not guaranteed to work and probably will not function. When Sponge rolls out the event changes and command changes, PlaceholderAPI will only support the latest versions of SpongeAPI.


Yeah my version is still api 5.1 for mc 1.10.2, just not the latest but its not a far-behind version either. I mean, other placeholders work, it’s just the statistics for death count and kill count not registering for some reason.


Have you tried running with only PlaceholdetAPI?


Ok interesting, I will try running my test build off of 5.1 instead of 7.0 to see if it works or not, but since I build against 5.1 I don’t expect there to be issues. There might be flaws in the logic of the placeholder though so I will try to diagnose them.

I would assume the answer to this question is yes, but are you running in Java 8?


I should also mention that 4.2 will be a fairly big update that will fix some internal issues I didn’t realize were problems, specifically with using primitive return types in the placeholder generator. Some additional features will be coming too, such as token parsing for basic object types, with possibility for more advanced types in the future (I haven’t worked out quite how I want this to work yet so I will update when I figure it out.)