#adventure-help
1 messages · Page 9 of 1
Oh i understand now
I assume this works fine on Chat messages but for lores is indeed a problem
I would say it is the other way around
But I don’t know your use case, where are you getting these components with new lines from?
I guess it doesn’t matter, in the end as Kezz said, if you do want to carry style over then you’ll have to make an algorithm that satisfies your use case
From pre-existing items, new lines I decided to add, etc..
Yeah I'll prob put my code on my wrapper instead of increasing complexity on MiniMessage side
Indeed having style that break and a potential fix with performance-heavy functions doesn't sound the best
Not so much performance heavy since you’d only do it once to port them over, just kind of annoying as there’s no shoe that fits all in this kind of situation, hence why adventure doesn’t provide an utility for it except maybe LinearComponents utility which people have used to have some semblance of style merging behavior
I'll be taking a look, thanks for the help!
bump
you could take the debug output by setting the MiniMessage.Builder::debug consumer on your MM instance
the debug output containing the ParsingException's message when MiniMessage::deserializeToTree is used
when using the normal deserialize method, it seems to contain a string representation of the tree as well as the exception's message
I really want the indices and parsing strings doesn't seem that effective
you can't really get the parsing exception, the parsing methods discard them
if anything, you could probably make a PR so it gets exposed somehow when in debug mode
So I got it working by using some hacky stuff from internals
ya we never fully explored how to expose that, it was supposed to be exposed as part of the completions project
but like, there hasn't been a ton of core parser work on MM after what was needed to shove it out the door
Hey, I'm looking to make my item looks like this: "§e§lArena §8▪ §7Clic-Droit" but using Component, I've been using different ways but still can't achieve the correct format, either all the text is getting bold or not a single character is, how can I do it ?
Current code:
@Override
public @NotNull ItemStack getIcon(final Player entity) {
return ItemBuilder.from(Material.NETHER_STAR)
.name(
Component.text("Arena", NamedTextColor.YELLOW, TextDecoration.BOLD)
.append(Component.text(" ▪ ", NamedTextColor.DARK_GRAY)
.decoration(TextDecoration.BOLD, false))
.append(Component.text("Clic-Droit", NamedTextColor.GRAY))
.decoration(TextDecoration.BOLD, false))
.build();
}
Current render:
You should try making an empty root component, and then applying your style to individual child
Something along the line of:
Component.text()
.append(Component.text("Arena", ...))
.append(Component.text("..."))
...
.build();
Because right now, your entire text is getting bold because you apply the bold style on the root component of your tree
how to use adventure when im using properties file for translation keys but need diffrent number of lines for item description
because in diffrent languages sentences take diffrent amount of space
easiest way would be to just have different keys for each line
sadly the properties file standard don't have a concept of lists so that's the best you can do with it
Yes but for example sentence one can take 2 lines in another language i said that
that's for the person translating to deal with
just make sure to offer a reload command in your plugin so they can quickly change the translations lol
if your question is how to make them the same length in any language, that'd involve component splitting which isn't something that Adventure supports, at least yet. You'd have to make your own algorithm for that by using the component iterator as well as figuring out when to split based on character width
does the legacy component deserializer produce a linear output?
Why?
it doesn't really matter honestly, made it recursive just in case
I'm trying to sanitize a component, thought there was some neater way to do it
Great because, while I don't know the answer to your question, I wouldn't make any assumption on it. Your code would be more robust that way
I should've asked the actual question first
What do you mean exactly by "sanitize"?
is there a neater way to iterate through a component and all its children already
while mutating them
conditionally remove colors/decorations
Iterating, yes, mutating, no since they're all immutable
However, you can get a builder using toBuilder() to something like this, and then .mapChildrenDeep(...)
(Method names may not be 100% accurate, check the javadoc for the exact ones, I've not used them in a while)
that's more like it, thanks
I'll have to check if it applies to the root component as well
doesn't look like it does, at least according to the javadocs
iirc, the only downside is that mapChildrenDeep method is only on builder (because they need to be mutable) and you can't call toBuilder on a generic Component, you need to cast it to a concrete type (TextComponent, TranslatableComponent...), which is a little bit sad
I have a text component since I deserialize one using the legacy serializer
Just create an empty component and append your root as a child
the annoying part is that it doesn't apply the mapping to the actual component you pass it to, just the children
sounds like a big xy, if you tell us a bit more about what you're actually doing we could point you to a better answer
He explained here
(But it's true it's very little info about the actual goal)
well thats just inconvinient
any other suggestions on how to do this?
I guess you could have a key my.translation.key and loop through .0, .1 and so on?
i just have a system where you do smth like "find every key.N key, loop until there's none left"
yeah basically that
oh yeah that would work fine i was thinking of something like this:
while(true)
getTranslatedComponent(key.i)
if(component == null) break
addcomponent
but
if the key isnt found it doesnt give null right
so its unsafe
you can just canTranslate(key, locale) so even easier
okay so this way
so maybe just iterate like canTranslate(key.i)
and if false then break?
yep
thanks that works
that's how i do it
actually one more thing i would ask you guys but that's more about general code managment i would say
Maybe adding a built-in method to do so would be nice? So it makes like a clear intended way to handle multi-line translated lore, which could reduce the number of times this question is asked? x)
yeah yeah in my example like getComponents for rootKey would work fine
however so im having one abstract class on which another classes are based like for example stick or rod
and then normally im builidng itemstack in abstract class because this logic is practically same
however for the description it needs arguments which differs a lot based on class
however the logic of getting the description componenets is the same
oh yeah that;s also something i didnt think through much
so for example i have description like this:
where 2 hearts ( 4<3) is injected as an argument
however what if in another translation this first and only argumnet is on 3rd line
I guess named arguments would be the way to go?
(But it only works for MM translation store iirc)
yeah im not sure if this would work in my case i didnt use them before
Otherwise, you could always provide the whole list of arguments for every line, and then use numbers to reference them (I think you can)
Which translation store are you using?
public static void loadTranslations(){
MiniMessageTranslationStore store = MiniMessageTranslationStore.create(STORE_KEY, MiniMessage.miniMessage());
for (Locale locale : SUPPORTED_LANGUAGES) {
ResourceBundle bundle = ResourceBundle.getBundle(
BASE_NAME,
locale,
UTF8ResourceBundleControl.get()
);
for (String key : bundle.keySet()) {
String message = bundle.getString(key);
store.register(key, locale, message);
}
}
GlobalTranslator.translator().addSource(store);
}
im using miniMessageTranslationStore actually
Then this
In that example, that would result as passing the "4 ♥️" argument to every line
yeah that would also make it so i can actually get description components from the abstract class then write desc arguments in sepcific class and get them and render them into description right
And only using it on the second line
But since you're using MM, I would suggest you to use named arguments
You can also use the Argument class to create named tags for ease of use. For example, this component
Component.translatable(key, Argument.component("name", Component.text("Kezz"))will produce the string “Hello, Kezz!” when used with eitherHello, <arg:0>!orHello, <name>!.
https://docs.advntr.dev/minimessage/translator.html#using-a-minimessage-translator
yeah but i still have to pass it to all components read from desc.i
right?
i mean its more readable
Hey guys, not sure if anyone can help me on this one but do you have any idea how i can translate placeholders together with MiniMessage? Cause i have the MM Component, but PlaceholderAPI only accepts String and converting to String as we all know will lose information
Hi, thanks, and what do i do with this TagResolver?
How to net.kyori.adventure.text.Component -> net.kyori.adventure.nbt.BinaryTag?
they're two completely different things lol
I mean, like JSON serialization but into tags
for now the best way is to go via MC's serializers
or like, serialize to json and use DFU to convert json to nbt
eventually we want to do up native dfu codecs for adventure types so we aren't reimplementing the same logic 50 times for slightly different formats and libraries
Thanks
Hey guys, is the MiniMessage.miniMessage().serialize 100% reliable? (While using Paper ItemStack)
When i meant reliable, is it gonna really provide me with the correct syntax, without losing anything, so then when i do try to deserialize it again, it will match the original
I mean, that is generally the intent, not doing so would generally be a failure and we have tests to try to ensure that
Do note that long term persistence of such data components is 100% unsupported by mojang however
No, there are a few small, rarely used parts of the component system that MiniMessage does not represent. You should not use MiniMessage for persistent, long-term storage of components either.
I wouldnt say is for long-term. Just to convert from ItemStack displayName()/lore() so I can do the appropriate changes
Everything would stay in-memory, not sure if that is what you mean
I would say this kind of thing is a bit of a code smell. Unless you're interfacing with other plugins which don't provide any means to preemptively obtain what they're going to put in the lore/name, making changes based off what is already in there souds redundant if you already have the data that is there in your plugin
it isn't bad per-se, just not particularly clean way to do things. I do think there's cases where you can't avoid it though
I know is not clean but I don't really have any other option. I'm supporting both Spigot and Paper, MiniMessage / No MiniMessage
you can do MM on Spigot too, if you're willing to use internals
Tried creating a wrapper on both components but everything gets more difficult so working based on non-styled components (String-based), and then only create wrapper for end-results such as Player message, Items (like a encoding) is the one strategy i would say
yikes, painful, no thanks lol
I mean, lets be honest, why would u still use Spigot right? If you really wanna use MM, I'm sure you would be okay going to paper
it sounds bad but internals about these things are pretty solid right now, them being data components and all
well, that's a question up to you to answer. If you have bstats setup then you would know the answer 😛
I don't particularly believe it is as annoying as one would think it is, just definitely not as straightforward of a process as it is on paper given the native support for adventure
There are still people using Spigot, thats the thing but my choice staying with Spigot support is not only regarding how many people use it or not but thats a conversation for another day lol
I already have enough pain, sometimes deciding which one is worth it is wise lol
so, what you're trying to do breakthrough is kinda annoying because there's no good way to have a placeholder that is extended over multiple lines when it comes to the lore
what I would do is just have the members part be a flag instead, so they can turn it off and on
I bet that it breaks formatting lol
no, i just didnt have any formatting in the config files
hi can anyone tell me how to remove all the players from my bossbar? or more precisely how do I completely remove the bossbar from the server?
I just found out that this method exists net.kyori.adventure.text.minimessage.translation.Argument.numeric(String, String)
I think that one should be called "text" or something like that instead, right?
when a player sends a chat message i want the message to be "formatable" using the minimessage formatings, so for example if the player sent "<red>hi" it would return a red hi. problem is that i can't pass a Component, which the chat renderer returns, to the .deserialize method. are there any other ways i could go about this?
Well, you want the plain text contents of the components
yes
(use the plain text serialiser)
something like this?
Yes
im dumb as shit, thanks for the help lmao
nah, nothing wrong with asking
i read the docs like 3 times and i was unsure of the correct solution
i tried using the .serialize method on the miniMessage() but that cancelled the tags by putting a \ in front of it
Well, yea, they're part of the contents to it escapes them to keep them as part of the contents 😄
guys, so who can tell me how to forcibly delete the boss bar from the server? I'm sorry for my English (I don't know it at all :D)
I'd imagine that you're in the wrong channel
hiding platform specific bossbars is platform specific
Well, I use the library bar. And it is not possible to delete it as in the same Bukkit.
paper doesn't expose the native bossbar in adventure
Audience#hideBossBar ?
as far as I know, this will not completely remove the bar from the server, but only hide it from the player?
bossbars created via adventure are not tracked on the server
that's what the name says, yes. But you can't create native bossbars with adventure anyways as far as I'm aware?
as long as you hide it to the player and lose a reference to it, there is nothing tracking it
if you want to remove a player from an adventure boss bar you just remove them as a viewer somewhere
method on BossBar literally calls viewer.hideBossBar lol
Yes, it's already deprecated and replaced
Oh, I must be using an old version or something, then
is it just me or is adventure 4.25.0-SNAPSHOT not released to the maven repo?
looks like it should be but yes that is weird
Hey, is there a library i can use to convert a minimessage string to html, kinda like the minimessage webui, but for javascript / typescript?
Nah, we didn't want to maintain a duplicated parser that might diverge, so they webui uses a server
But it has an API if you want
Understandable. What does the API allow me to do? Is it possible to send a minimessage String and get html in return?
Thanks. I'll see what I can find.
Uff I think we only have mini to json as a rest request, the other was moved to websockets
The code is here https://github.com/KyoriPowered/adventure-webui/blob/main/src/jvmMain/kotlin/net/kyori/adventure/webui/jvm/minimessage/MiniMessage.kt
If that's a way you wanna go down, idk what your project is and if you wanna rely on a 3rd party service like this, we could look into offering a rest endpoint for this again, its just a few min of work
I'm creating a localization system for Minecraft plugins. Now when a now translation is added there should be a preview how it would look in game:
That of course means, I would have to send a request everytime a new character is entered
fairly sure we already do that with the web UI?
Hmm right
Like, you could always self host it yourself if so desired
There just isn't the interest in having to maintain two entirely different parsers with potentially differing behaviors, especially with the feature set of MM
Yeah I understand. I would definitely self-host it so that I don't burden the official instance.
For editing workflows there is an official api
Idk how exactly it works, never used it, but I think it generates a custom link to webui and you edit and save stuff and then your backend can retrieve the saved value
I don't think this would help me there?
I just need the preview, the rest is handled through my backend.
Ah that's also not documented, I think only kezz uses it
If you already have a backend just have a route that uses MiniMessage?
Oh wait you need the html
Yes, or is there a better way to render it on a website? 
Maybe a proper html serializer for adventure components is worth it? It's def not an unusual request
You would still need to have your own backend but then you just throw stuff together in a couple of lines
That would be great
Sounds like a fun project for somebody
It wouldn't be impossible, but there is just some stuff which is kinda hard to implement (like sprite components from 1.21.9, everything that uses server state, and stuff like translatables).
I mean, you could just render the translatable key, but I think that is not clean for stuff like this
I guess just do it like the current MM webui does
I don't think it has support for object components just yet
So that is new territory in general
(I was talking about translatable)
How does it do them?
Player heads wouldn't be that hard (just requires a little code and a few calls to Mojang's API), but sprites yeah without the vanilla resource pack, they wouldn't work. Maybe providing a way to hook a resource pack would solve it
No idea, I guess they renders the key
I think rendering the key is not that great, maybe a Vanilla lang file on there for resolving would be great
Oh no it just disappear

MiniMessage Viewer is a web interface to help generate and edit MiniMessage strings.
So, until the html serializer (maybe propably) becomes reality, what would be the best solution to my probem?
You could make your own simple one. Something around the lines of MM -> Component -> Json -> HTML (with your own, very simple custom serializer, only needs to support colors and styling, and that should not be particularly hard to implement)
no idea if it does what you need but there is an html serializer in squaremap
@uneven silo btw could you open an issue on the adventure repository for this as a feature request just so that somebody more official can approve/deny it officially
I think having some input from the team would be good before anybody spends a sizable amount of time on that just for it to be rejected
I would start simple, as in, the stuff that is easily representable in html without any data or API or whatever
Can always extend later
And this could be a starting point
However idk if the best would be to output a completely standalone HTML element (with all styling embedded), or to use proper markup and CSS classes, and make it work with a predefined stylesheet
Either way, the fact that both HTML and components are trees should greatly help
the former IMO, I think WebUI does it pretty well since it uses HTML's style inheritance
oh wait hover boxes exist, hmm... 🤔
why does
<hover:show_text:\'test\'>test
fail?
Not sure, but you should probably be using <hover:show_text:"'test'">test instead
Please open an issue
are there ways to split a component part way through its contents and insert another?
ie component.text("foobar") -> component.text("foo").append(component.text("biz")).append(component.text("baz"))
that's not xy :p
xy?
why
sorry i think misunderstand
ohh right
sorry was tryign to write another then responded to urs so
pretty much trying to play with the new sprite stuff at least partially,, i know i can split a component by its string contents and replace strings within a component, what i want to do is split a component where i see specific text and append the sprite component where that text previously was
kind of starting to believe this isnt really supported though lol
someone types
hi XYZ, how are you
xyz gets replaced with the sprite component, so i suppose this would only have to handle textcomponents?
(I add another question: how do you get your components in the first place?)
oh yeah sorry from chatevents
It's basically text only then?
yeah
ig it works just as well if its possible to get all the text out of a component and just make another out of the text
sorry ended up being a bit drawn out with explanation.. probably shouldve fronted w that
So, you should extract the plain text content as a string and work with that (do whatever manipulation you want, and then use something like MiniMessage or build a component yourself if you really want to control precisely the output)
PlainTextComponentSerializer
i mean it depends what XYZ is - fixed text? player name? placeholder? etc
any piece of text a player could send really
that doesn't make sense, how would that even work haha
be more specific :p help us help you
The question was: What do you want to replace in the text written by the player?
with another component (not a text component) i.e. sprite component (which i know isn't in the latest stable adventure but still)
i mean its true though 😭 if someone sends a certain string that have preconfigured to look for it should be replaced witht he correpsonding sprite
Here's an example of the kinda info I'm looking for from you:
I would like to replace player names with the player name prefixed with their head as an object component
That's what you want to add instead, but what do you want to remove
yeah thats pretty much there really
well typically the text
okay there we go! so you've got a config with a map of strings -> sprites?
mhm!
sorry
oh you know what
im a complete bloody numpty
there is a content method in a text component..
idk how did not notice that XD i think should be able to do that w that,,, though dont think it would work if we got a player message that didnt contain a plain text message but Maybe that wont happen /shrug 😭 sorry again thank you for trying to walk through my rambling
okay so I figured out why this fails,
since TAG state doesn't really escape anything it goes into STRING state and since you can escape the same char code point it never finds the string's ending quote
is this an issue or expected behaviour?
@cloud vapor I hope you don't mind if I ping you for this
But why does
<hover:show_text:fo"o"b"ar>Hello!
parse 
component = component.replaceText(configurer -> {
configurer.matchLiteral("%previous_page_button%").replacement((matchResult, builder) -> {
if (page > 1) {
builder.append(formatPageString(options.previousButtonFormat, page));
} else {
builder.append(Component.empty());
}
return builder;
});
});
``` this doesn't seeem to actually replace the text, but rather append like after the text
is there a reason you couldn't use Component::replaceText for this?
builder is the match - you're just appending to it rather than changing it or replacing the match
well, you're appending to the builder, you probably want to set the content of the TextComponent builder
how do I do that?
if i was you i'd consider plain text serializing the message and then using MiniMessage to handle placeholders - very easily done unless you have other plugins messing with the message
You can set it via TextComponent.Builder::content
you probably just want to set it to an empty text and then append
it's an issue, it should work fine. your example with quotes on the inside should also be fine? idk, at that point we know what you're intending to do
or I guess you could just forget about the provided builder altogether and return your formatPageString component
i think you might need to make sure you copy over children?
uh, that could be a thing. I know the text replacement renderer does it for you when you use a simple string replacement but I don't remember what happens when you do the function replacement
ya ive come back to this with clearer eyes this is rougly what im doing (except have been replacing them with objectcomponents instead)
because as said the thing im replacing the text with is not text :p
oops sorry ping
You can replace text with not text using the replaceText method
And I don’t mind pings
oh huh, i really need to learn to read closer 😭 (or maybe put my glasses on haha)
that should remove some of the blehh'y parts from my code actually... ty !
hey, i added
implementation 'net.kyori:adventure-api:4.24.0'
to my project and i have access to stuff like Component, but for some reason, the Key class; the entire net.kyori.adventure.key package does not exist for some reason. Why is this?
Key is a separate project
it's still a transitive dependency of adventure-api so something else in your build setup is being funky
ah ok, is there a github?
i dont really have any extra dependencies except adventure and the gson serializer
It's just https://github.com/KyoriPowered/adventure. It's a very big repo with most adventure stuff
Including key
not for me. this is what worked:
implementation 'net.kyori:adventure-api:4.24.0'
implementation 'net.kyori:adventure-text-serializer-gson:4.24.0'
implementation 'net.kyori:adventure-key:4.24.0'
i had to include it separately even though it's apparently transitive?
but if it works it works i guess
a monorepo if you will
also, consider using the bom
implementation(platform("net.kyori:adventure-bom:4.24.0"))
implementation("net.kyori:adventure-api")
implementation("net.kyori:adventure-text-minimessage")
this is getting out of hand:
implementation 'net.kyori:adventure-api:4.24.0'
implementation 'net.kyori:adventure-text-serializer-gson:4.24.0'
implementation 'net.kyori:adventure-key:4.24.0'
implementation 'net.kyori:examination-api:1.3.0'
i will use the BOM, but how come i have to declare each one independantly? is there no all-in-one artifact?
also this?
return GsonComponentSerializer.gson().deserializeFromTree(json);
^
class file for net.kyori.adventure.text.serializer.json.JSONComponentSerializer not found
because they are not all one module, you just take what you use
as for your issue, it is probably because you don't have the text-serializer-json module? Though it should be a transitive dependency of the gson module, make sure your build script isn't messing your classpath
also, is this a project independent of paper?
yes, i am experimenting with my own server software
just to see how some stuff works
i had to add it manually for some reason, but it works now
You really don't, key is a transitive of the api and json is transitive of gson which are both transitive of the api. Your built setup is scuffed if you have to declare each one individually
but also, #build-tooling-help
how does one create a ClickEvent with an Action and a Payload object? The constructor is private and the ClickEvent.clickEvent only takes a string (and the page) as the payload?
ClickEvent.custom
no, that's not what I mean
I want to supply an arbitrary ClickEvent.Action object and it's Payload, similar to how it was in the past with the ClickEvent#clickEvent(Action, String) method but now there are payload types and that method is deprecated
arbitary Action makes 0 sense
it does when you are parsing it from a string
minimessage literally does that too: https://github.com/KyoriPowered/adventure/blob/main/4/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/standard/ClickTag.java#L67 xD
meh, it doesn't like me cheating with reflections ;_;
I just updated the version and not the color codes don't process
gib more info pls
update adventure-platform-bukkit to 4.4.0
was working fine on older version of adventure-platform-bukkit
What was working fine?
code? platform? version? client version? etc?
processing the color codes
cool thanks for answering literally zero of my questions, ill be sure to polish off my crystal ball to get you an answer asap
Sorry I had to eat dinner, now that I'm back lets see if I can figure out what you ask
adventure-platform-bukkit 4.4.0
Paper 1.21
"processing the color codes" unless I'm just out of touch this doesn't actually mean anything
I don't recall whre the code is in the plugin, was over a year I did that
this is what I get in game <LIGHT_PURPLE>Active paths (<GOLD>Creative<LIGHT_PURPLE>): <GOLD>Active
I missed undo some code change from the auto fix, I rebuild and test again
please answer all these questions if i you want help
also you don't need adventure-platform on paper
Hey in the linearcomponentbuilder, how do I make the italic/bold etc sections stop? I dont see a RESET
Is there a way to keep component style that was before in Component.replaceText(...);?
return component.replaceText(TextReplacementConfig.builder()
.match("(/join\\s+\\S+)")
.once()
.replacement((match, builder) -> {
String command = match.group(1) + " " + match.group(2);
if (!someCondition) {
// return default text that was before
// in current it will return without any style
return Component.text(command); // ???
}
return Component.text(command)
.decorate(TextDecoration.UNDERLINED)
.clickEvent(ClickEvent.suggestCommand(command));
})
.build());
I think you'd have to manually copy over the style and decoration?
builder should have that data
or you could just mutate the builder you are given 
Doesn't that have the original text in it though?
you can also just change that
Well I guess it would have to be a single component with that text
TextComponent.Builder#content(String)
text replacement only works on contiguous pieces of text in text components anyway and not across components
Does someone know how to use the Player Head Component with Adventure?
you just do it?
which part are you having trouble with?
I just implemented experimental support for that in Minedown (https://github.com/Phoenix616/MineDown/commit/0bfceec0bcfa501fb63e1796a223dd35353fcea1 ) so I might be able to answer questions xD
Thanks
Searched in the following locations:
- file:/C:/Users/pzvi/Downloads/totemNotifier/.gradle/loom-cache/remapped_mods/net/kyori/adventure-text-minimessage/4.25.0/adventure-text-minimessage-4.25.0.pom
- file:/C:/Users/pzvi/.gradle/caches/fabric-loom/minecraftMaven/net/kyori/adventure-text-minimessage/4.25.0/adventure-text-minimessage-4.25.0.pom
- file:/C:/Users/pzvi/Downloads/totemNotifier/.gradle/loom-cache/minecraftMaven/net/kyori/adventure-text-minimessage/4.25.0/adventure-text-minimessage-4.25.0.pom```
implementation("net.kyori:adventure-text-minimessage:4.25.0")
im confused
why wont this import
can someone help 🙏
i mean, what's your build script? and you probably want #build-tooling-help
also wait, 4.25 isn't even out yet, is it?
the website gave me this import
what website?
afaik you'd need to add the snapshot repo to have access to 4.25
~shrug~
4.25 is probably coming out soon and those docs were just merged in, so probably just a case of them being updated a bit soon?
how can i make the MiniMessage#serialize(Component) method not to escape the < char?
Manually unescape it afterward
😭
why do you have minimessage in a component
🤫
i'm trying to make a minimessage tag that adds a space between every charecter inside it, how would i do that? i want all the tags/placeholders inside it to be parsed first.
aka: <space:2><red>hi</red><level></space>
parses to h i 1 0 0 assuming level is 100
You'd want to look at a modifying tag - shouldn't be too hard
Placeholders are resolved from the inner-most to the outer-most, iirc, so I should "just works"
oh god... modifying tags scare me
oh nice
thryre fun :)
ur fun
prove it
i'm guessing i wanna do it in postVisit?
uh whatever abstractcollrchangingtag does
bless you
it does a lot..... time to dig in ig lmao
They're not that difficult, once you played a little bit with them. However there are a few things that are good to know before (otherwise you just spend more time figuring them out yourself):
- The
applymethod is called with every component of the child tree (recursively), and the root (the first child, i.e. the whole content) is atdepth == 0. - Children gets carried over automatically after the
applymethod, so if you want to not modify the component for whatever reason, you need to clear its children otherwise they'll get duplicated (component.children(List.of())). - If you want to traverse the tree yourself, you should only do it at
depth == 0and always returnComponent.empty()otherwise (so all the children become empty, and are not added)
If you want an example, here's an abstract class I'm using as a base for all my text-related Modifying tags:
public abstract class TextModifying implements Modifying {
public abstract @NotNull String modifyText(@NotNull String text);
@Override
public @NotNull Component apply(@NotNull Component current, int depth) {
if (current instanceof TextComponent text)
return Component.text(this.modifyText(text.content()), text.style());
return current.children(List.of());
}
}
Feel free to take inspiration
hm, that might be a nice thing to have in the api if you fancy a pr :p
Why not, however I would need to make sure about a few corner cases I am wondering (but never really got them myself):
- I don't know about
VirtualComponents, but I saw that when checks are done in other classes, they test for them to exclude them frominstanceof TextComponent - Server-side translatable components could technically get processed as well, but it gets trickier and I never really played with that in practice
whew yeah those are two tricky ones haha
i think you could either ignore or exclude virtual components that's fine
not sure about the second one, probably nothing you can do about that
(but what are they, really?)
they're just an implementation of TextComponent that holds some additional data that you can use to do funky stuff with
Oh, so here the additional data would be lost with that code?
yeah it would
But since the content would be modified, it makes sense to drop that additional data because it could no longer be relevant?
good example is the mm translator (see argument and the translator)
Oh so the renderer of the virtual component is that additional data
yeah
tbh i'd just skip virtual components entirely, too niche to bother for 99% of cases really
you could remake it with modified text ig
no ignore me, virtual components always have empty text
So they're safe to ignore, and their children will get processed normally
yep
Nice
the 4.25.0 release does not seem to be on the maven repository
Could not determine the dependencies of task ':demo:demo-minestom:compileJava'.
Could not resolve all dependencies for configuration ':demo:demo-minestom:compileClasspath'.
Could not resolve net.kyori:adventure-api:4.25.0.
Required by:
project ':demo:demo-minestom' > project :core:core-all > project :core:core-shared > project :api:core-api:core-shared-api
project ':demo:demo-minestom' > project :ootb:ootb-layer:ootb-layer-onboarding > project :api:layer-api:layer-core-api > project :platform:platform-minestom > net.minestom1_21_9-SNAPSHOT:20251006.134713-8
Could not resolve net.kyori:adventure-api:4.25.0.
Could not parse POM https://repo.maven.apache.org/maven2/net/kyori/adventure-api/4.25.0/adventure-api-4.25.0.pom
Could not find net.kyori:adventure-bom:4.25.0.
There are 8 more failures with identical causes.
Odd because it does not seem like my project can fetch the dependancy
not sure what repo that is but it seems to include outdated jars
it's in https://oss.sonatype.org/content/repositories/releases/
ah, apparently central doesn't have it yet for some reason? I assume they do manual checks before publishing
I know that in the past central could have ~10 minutes of delay between upload and it actually being on central, not sure what the situation is now that they migrated over to their new system.
Just be patient, it takes time
It's in central for me, not for others - the rollout is gradual it seems or whatever cdn they use caches 404s or smth
since replaceText doesnt work if message is "gradientized" is there an alternative?
Certainly. Why would you need it? It's highly possible you can do without it
mostly not for myself, but a plugin used for resourcepack, is not able to do replacement when the message is gradientized. But strange thing is that he uses AsyncChatDecorateEvent which is called before my event (AsyncChatEvent)
And why don't you use something like <alien> instead?
(With the correct tag resolver/placeholder)
Players/people are accustomed to emois in format like :rolling_eyes:, with colons
yes
Then do preprocessing of :something: into <emoji:'something'> and let the emoji tag resolver do the job (and fallback to :something: if the given emoji doesn't exist, so it undo the preprocessing done on incorrect texts)
Will tell him thanks
intercepting the message with packets, before it reaches PaperMC, will give problems to signature of the message?
Zero reason to do that even if it does/doesn't
The chat event is basically a packet wrapper
He mostly doesnt want to do that with event, to avoid altering the signature
hey how would I obtain the list of tags from a tagresolver?
Why?
You can check if a tag name exists in this resolver, but idk if that fits your need: https://jd.advntr.dev/text-minimessage/4.25.0/net/kyori/adventure/text/minimessage/tag/resolver/TagResolver.html#has(java.lang.String)
I want to do some autocompletion of tags in a command
I know it once was a goal to provide auto-completion, but the idea wasn’t completed. Idk if there is still a draft somewhere you could inspire from
TagResolver.Single has a method https://jd.advntr.dev/text-minimessage/4.25.0/net/kyori/adventure/text/minimessage/tag/resolver/TagResolver.Single.html#key()
declaration: package: net.kyori.adventure.text.minimessage.tag.resolver, interface: TagResolver, interface: Single
Maybe you can find a way to decompose your resolver that way
I am not sure how I would be able to use that to get all the tags though. But I'll have a look if I can find some info on that attempt at auto-completion
#923037327578771457 message seems like its just one issue that gets mentioned here and there. I guess I am just perpetuating the cycle because I am not sure if I have the abilities to fix this ;p
it's not possible with the current api design bc tag resolvers dynamically match names - we'd need to expose a "completions" method somehow
it's not a big change assuming you only care about tag names, but becomes a bit more complex if you want to think about arguments too
Ah okay. thanks for the info!
so this would require breaking the api a little to add? TagResolver implementations would have to implement some kind of complete method?
it wouldnt' break the api, as you could just default impl the method
Yeah only doing the tag names was quite easy. though finding a nice way to incorporate arguments has me stumped at the moment.
I added these methods to the interface: https://github.com/KyoriPowered/adventure/commit/6185ef508436d4c0a6f3740b07c8cb553c9ec23a#diff-485f6e5af727bcf56f843458cc0eef95903ea879f4fa4f72721a23bf7f1e9852R234-R237
But I think to make a functional autocompletion with this you would somehow need to know how many arguments a given tag needs
-# sorry for the ping, forgot to untick it
So my idea of the design of it is a sealed CompletionContext object (an arg or a tag, the list of args) and then return some CompletionResult interface which can either be a concrete list of strings or some other implementation that holds a name of an argument or some other descriptor
Could someone point me in the direction of finding a list of keys for the Keybind Tag
Minecraft offers controls tailored for different input methods. While Java Edition is playable only with a keyboard and mouse, Bedrock Edition has a wider variety of control schemes in order to accommodate players across all platforms. These controls can be changed in the options menu.
Much appreciated!
Do you mean each Tag has a completioncontext? Or is the CompletionContext something you would create and then use to get CompletionResults?
minimessage would create the context and pass it to a method in tag resolver - it being generic like this would let us e.g. expand to do argument completion later
how do you apply the tint to an atlas?
I am doing something like:
import static net.kyori.adventure.text.object.ObjectContents.sprite;
Component spriteComponent = Component.object(sprite(
Key.key("minecraft", "blocks"),
Key.key(spritePath)
));
but things like leaves are greyscale
Coloring the component does work, I’ve accidentally tinted a sprite when trying that out lol
neat!
do you have any idea how he solved it? kinda running into the same issue
He did not, but it was not my problem, I was just trying to help.
What is your issue?
same gradient thing
is the plugin colorizing the chat yours?
currently not home but my plan was to maybe plain serialize the message and replacing the emojis with the placeholders before deserializing it again
havent tried yet thougj
yes, but it really depends on the plugin colorizing the chat.
All the current plugins on the market, they use AsyncPlayerChatEvent(legacy) and colorize the message there
ill experiment further once i get home
how can i replace text independently of stuff like color and style? imagine i have a text and part of it is a rainbow "0123456", so each char is a different color; i want to add a hover event to the whole "0123456" and keep the color and any other formatting
I imagine you're generating that rainbow gradient with MiniMessage, I would recommend adding the hover in before you parse the MM into a component, otherwise it gets tricky
the rainbow was just an example, but im trying to replace an already made up Component
i want to add a hover to the second WizardlyBump17
Probably easiest to serialize it to MM, do transforms to that text, then deserialize it
you'll have to iterate through the component tree to do that, but again it is kind of tricky if it comes down to a lot of colors
i might do that
ah right, since it emits virtual components then it might be able to reconstruct the gradient tag
Not sure on that front actually, was just thinking regex is easier to understand than a custom tree iterator
but then i would end up with a <green>Wizard</green><red>lyBump17</red>
Sure, just means you need a better regex 😄
And it makes me wonder why you're already generating multicolor text before deciding "ya know what, I should add something else here"
They're trying to edit someone else's message
I imagine it has something to do with chat, yeah
probably adding an entity hover event to a player's display name or something
though if that's exactly the use-case, I think you could get away with something like this:
@EventHandler
public void onChat(AsyncChatEvent event) {
event.renderer(viewerUnaware((source, displayName, message) -> {
var uuid = source.getUniqueId().toString();
return miniMessage()
.deserialize("<hover:show_entity:'%s'><name></hover>: <message>".formatted(uuid),
component("message", message),
component("name", displayName));
}));
}
component being Placeholder::component
what does velocity do when I send an object component to a 1.21.8 player?
I imagine velocity doesn't care. Did you mean to say viaversion?
would velocity pass a 1.21.9 object component to a 1.21.8 connected player?
Can I use components (or minimessage) to display player heads and items, as has been possible since the 1.21.9 update?
Example: /title @a title {player:{name:Jeb_}}
Yes - see object component and head/sprite tags
👍 Thanks.
Do you know if adventure v4.25.0 is used in Paper 1.21.10-R0.1-SNAPSHOT ?
how would i get the name of an enchantment in english/the player's language?
e.g., bukkit Enchantment.SHARPNESS -> "Sharpness"
translationKey is deprecated
(as a Component.translatable)
Enchantment#description
translatable components are handled on the client unless you've setup server-side translations for your plugin (though, it shouldn't affect vanilla translation keys)
Uhm, what's the exception thrown when a deserialization fails due to having legacy colors?
ParsingExceptionImpl
Which string-based encoding would you recommend to transfer a component between 2 programs? (I'm not storing it, it will be used immediately by the other program, and both programs will run with the exact same version of adventure, this is guaranteed)
go for gson I'd guess
(Technically it also work if the encoding is not strictly string-based and encodes as bytes, since I can always use base64, but you got the idea)
Interesting, so this brings another interrogation
I already use Gson to encode my full data object as JSON (the data contains various values, such as an UUID, a timestamp, and a component)
Would it be possible to do a "all-in-one" encoding, like configuring my Gson instance to properly encode/decode Component class?
(If not possible or not worth it, I'll just put a String in my data class and handle the component encoding myself, and it'll work, but was just wondering)
I mean, sure, maybe, potentially
you'd need to grab all the type adaptors from the gson serialiser module and add them into your own thing
Because I could also do it the other way around, since I'm using a plain new Gson() instance with all defaults, I could just grab the Gson from the serializer
Oh I think I understood what it was by looking at the impl
Can the sprite text component be used in a form like Component.sprite(...)?
sprite text component? はComponent.sprite(...)のような形で使用できるようになりますか?
Component.object(ObjectContents.sprite(Key.key("item/emerald")))
thank
will two identical components return the same HashCode?
What do you mean by "identical"?
e.g.,
for(int i = 0; i < 10; i++) {
System.out.println("hashCode: " + Component.text("Test", NamedTextColor.GOLD).hashCode());
}
will this print the same thing 10 times?
Yes
ok ty
But we're talking about structurally identical components here, not visually identical ones
(Obviously, structurally identical components are also visually identical, but the reverse isn't always true)
i see
this is my usecase
obj.getScore("" + line.hashCode()).setScore(score--);
obj.getScore("" + line.hashCode()).customName(line);
why are you using the hashcode for that?
there's no Objective.getScore(Component)
That's wrong usecase for hashCode, it is prone to collision
e.g two different components may have same hashcode
hi I was wondering how to know if this replacement was successful since it only returns a component
for(final String match : REPLACEMENTS.get(key)) {
nextComponent = nextComponent.replaceText(TextReplacementConfig.builder()
.matchLiteral(match)
.replacement(replacement)
.once()
.build());
}
I just need a boolean to know whether something was updated or not
if anyone knows feel free to ping me
you can just check whether the old and new component are equal
wait thats actually so valid
thank you
when using this example:
Look at my <sprite:blocks:block/stone>! This item costs 10 x <sprite:"minecraft:items":item/porkchop>.
from: https://docs.papermc.io/adventure/minimessage/format/#sprite
seems like the item doesnt show properly
The "minecraft:items" atlas doesn't exist iirc
It's all in "minecraft:blocks"
And because this is the default atlas, you could just write <sprite:item/porkchop> / <sprite:block/stone>
thank you!
Maybe we should fix that 
hi
final Component message = attribute.paintComponent(cosmetic.getMessage());
final var replacement = TextReplacementConfig.builder()
.matchLiteral("<name>")
.replacement(KyoriHexUtil.colorify(this.buildName(user)))
.once()
.build();
Bukkit.broadcast(message.replaceText(replacement));
I want to find <name> in my component and just replace it, I can't use TagResolvers or anything because I'm working with legacy code so it'd be too much of a hassle to modify everything, also the component looks like this sometimes
I want to just replace any reference of <name> with the component provided by KyoriHexUtil, is this possible?
Nope, as soon as you made each one a different color you made this much harder
You can't just replaceText, you'd have to walk the tree and figure out if you're seeing <name> manually
Each character is a separate component, replaceText only works within a single component in the tree

do you have any recommendations on how to do this or am I just cooked
You are indeed "cooked". Even going one-by-one, checking the component's values and concating it together does not work because then the format would be completely screwed up. You somehow need a way to replace the <name> before you serialize it to a component
just use minimessage bro
hi,
i literally cannot use minimessage for my use-case
you are already using components, if your codebase is in a state were you cannot add minimessage somewhere in between then perhaps you should do some much needed refactoring
the library you are working with is also called adventure, kyori is the name of the organization behind it
I mean, isn't that exactly what the replacement system is for or am I missing something?
I was referring to the one in adventure directly which they are already using
Can you explain a bit more about your use case? It seems you might already be using MiniMessage somewhere to create the gradients, no? If you go into a bit more detail we might be able to point you towards a good solution.
Kind of.
I use MiniMessage in some scenarios to parse out the colors & you're right I use MiniMessage to do the gradient work.
But I also need to support different kinds of ways to build colors, i.e. "discrete" colors, provided below is the code to make discrete colors work.
public class DiscreteColorPainter implements ColorPainter {
@Override
public Component paintComponent(ColorService.Context ctx) {
if(ctx.contents().isEmpty()) {
return Component.empty();
}
Component component = Component.empty();
int idx = 0;
for(final ColorService.Content content : ctx.contents()) {
if(content.special()) {
component = component.append(Component.text(content.content()));
continue;
}
for(final char c : content.content().toCharArray()) {
final ColorContainer container = ctx.colors().get(idx);
// skip over the letter i guess..
if(container == null) {
continue;
}
component = component.append(Component.text(c)
.shadowColorIfAbsent(ctx.shadowColor())
.color(container.toTextColor())
);
if(++idx == ctx.colors().size()) {
idx = 0;
}
}
}
return component;
}
}
Where I cycle through each TextColor then rebuild my string with each character using a new color.
Unless MiniMessage can support this kind of way of coloring then I don't think I'm able to use it for my use-case.
If I can build a MiniMessage tag to do this kind of coloring then I will be over the moon and implement that ASAP
Unless what I asked above is possible from what I know I don't think it's possible unfortunately.
what kind of overcomplication is ts
it's called a feature somebody asked for
what do you mean by "cycle through each TextColor"? Like a gradient? Or random colors for each character?
Of course I don't know the exact requirements and implications of this implementation, but yes you can indeed make a MiniMessage tag to set a different color for each letter. This is similar to the gradient tag
Be nice
^ it does seem like you could reproduce that as a MiniMessage tag, which means you could do it all in one go
Yeah you'd be wanting to effectively adapt the gradient tag to change the colour for each character and remove lerping
so kinda like a simplified form of that tag
(oh, default branch is main/5 now?)
Gotcha, tysm Kezz & indyteo
yep! we're considering 4.x feature complete now and are moving development to 5.0!
Nice
You can check out https://kezz-feature-adventure-5.papermc-docs.pages.dev/adventure/migration/adventure-4.x/ for a WIP migration guide if you want a tl;dr on the changes
hey @cloud vapor I think ComponentSerializer#deseializeOrNull should also be removed as its been deprecated since 4.8.0 (<t:1623175431:R>)
they just don't want to let me forget my spelling :p
it is sad that adventure 5.0 will move from java 8, i know it is necessary but i planned to use adventure in a platform agnostic module implementation that can support multiple versions, however if the java required version changes that will not be possible anymore
Older versions of the game can use modern Java too, you can just require that
My approach is "you want to run something in 2025? Use modern Java." and my maintained 1.8 plugin requires Java 21. I know you said platform agnostic and I'm only talking Bukkit derivatives, but surely other maintained outdated platforms have upgraded themselves to 21 by now or are outdated in a "wow this server is insecure on the public internet" way.
Not always, for instance trying to run a 1.16.5 sponge server with java 21 won't work, maybe it is because of the mixins, not sure
you can use https://github.com/unimined/JvmDowngrader
I mean why does 1.16.5 sponge matter? it ships with a fixed adventure version already
And at the end of the day, we have better things to do than restrict ourselves to old java versions on a hobby project
if you want to target old game versions, the old adventure versions aren't going anywhere
Yeah old game versions target old Adventure versions, that's just how it works 🤷 You can always make your own adventure-platform-esque impl or just use that when we update it to Adventure 5.0
this is awesome! saw something which stated sealed interfaces were going to be added, would this apply to key? I personally have a use case for implementing key myself (no "safe" character checks for keys), if it is going to be sealed, would an "UnsafeKey" ever be implemented?
No, we have no intention of allowing non-standard key implementations to exist. Could you explain a bit more about your use case and perhaps we can point you towards an alternative, or maybe tweak our API to better fit your needs?
so yes we will be sealing key
mainly the Minecraft client allowing file names with capital letters, and we use a key to store the paths of them "distant_horizons:darkTheme.svg" for example
that breaks when we try to store it
there're probably some other characters the client accepts that adventure keys do not
Are those capitals really supported or only "tolerated" by the client? I mean, what are the docs/specs saying about this?
probably tolerated
And maybe this is a kind of stupid remark, but couldn't you just rename those files to have a more complient file name? dark_theme.svg
we load assets that aren't ours
Ah, I see
as annoying as it is, we kinda have to work around it
luckily we're in a modded environment, worst case is mixin to key to remove the checks
Then maybe the adventure key implementation should enforce only what Minecraft itself enforces, and maybe provide a configuration option to more strictly prohibit those characters
(Or the other way around, an option to be lenient instead of more aggressive)
yeah that'd be a nice solution
And just it doesn't really solve the issue, but iirc Windows filesystem is case insensitive. So maybe distant_horizons:darktheme.svg would work, at least on Windows?
But that's not a good solution indeed
Oh damn Windows is worse that I think:
The Windows file system supports setting case sensitivity with attribute flags per directory. While the standard behavior is to be case-insensitive, you can assign an attribute flag to make a directory case sensitive
Anyway really not a good idea to rely on this
Capital letters are invalid characters in vanilla, I don't think whatever you're doing would be supported by the client either https://minecraft.wiki/w/Resource_location#Java_Edition
We specifically match what the java edition client accepts
org.bukkit.NamespacedKey implements n.k.a.k.Key :d
that's going to be fun
That's gonna suck with most of new Paper API taking in a Key and many users entering NamespacedKeys to them
Or does Keyed extend Key so that it would still work?
I guess it's rather Key extends Keyed
Well Keyed is iirc just an interface with has a method to return a Key. So making Keyed implement Key and it just delegates all method calls over to the underlying Key wouldn't be unplausible
I haven't looked at the key project, so idk how it is handled
I think we might just have to unseal Key, it's not even marked as non-extendable atm
you actually have to ignore me ive already made that decision key isn't even sealed in 5.x lmao
lol
hm, I'll see how it loads then, since that's an actual distant horizons asset iirc, caused issues
perhaps it's just skipping that asset, which we could also do
Isn't there any workaround for the lore newline problem so far?
there is, specifying your lore as a list
Why would there? It’s not intended to use newlines
if you want newlines, you can always implement splitting
I'm using a TagResolver that doesn't really know where it's displayed, but it makes as newlines as necessary, and in my usecase the ItemStack creation for lore is based on a TranslationStore key/val with the args I specify.
For context, even though it may appear x/y problem, here is the layer of abstraction I'm using, which is based in config:
interface ItemStackWithArgs{
ItemStack from(Locale locale, ComponentLike... args);
}
and I normally do itemStackWithArgs.from(player.locale(), Resolvers.myComplexResolverThatMayMakeMultiLines()
Perfect where would I start with doing that, is the ComponentFlattener a good start point for doing it?
Hmm will check, but ain't the ComponentFlattener just traverse all over the component tree and I can have a List<Component> and only append when text isn't containing \n, but if it does just create a new entry in the list?
no
TextReplacementRenderer is way too cooked for me
I guess reworking my abstraction would be easier 😂
like, it's replacing to the point it even takes care of TranslationArgument, each Component type, etc. etc..
aaaand that's why component.split() doesn't exist yet :p
someone should have done it 🙁
I have seen this, but seems like it's still work in progress
"someone"
its a volunteer project lol
ik, I really appreciate the hardwork, tho I'm still surprised no efforts were made in resolving this issue
like each year I come to see if something new happened with this problem and still not yet anything new 😂
back in days when it was about legacy coloring, a String#split would resolve the problem lol, we can do it with LegacyComponentSerializer but that seems too cursed
that would work if you don't care about fonts, rgb colors, style inheritance, sprites, or translatable components
Splitting on \n character isn't particularly hard (I've done it), however it's also relatively limited, because if you are able to place newlines yourself in your component, why not split it in multiple ones from the beginning...
well, in this case it is a placeholder that spans over multiple lines, so it is hard to do that
The reason it hasn't been done is because it's not a good idea. It's considerably easier and more user friendly to start with a list in the first place
how does that work with placeholders that span over multiple lines though
you just don't have those I guess? Lol
Yep
If you want to see how I've done it, I can push a working draft, but I must say I didn't pay much care to the readability of my split function, and surely with a little bit more of thinking we could improve the double-loop that kills readability
I was thinking one could just make the new line tag emit virtual components so it'd be easier to know when to split instead of whenever one finds some \n character inside a text component
then with each splitting, you could just decide whether you want to merge the previous component style or not
Here's my POC (note that it's based on my Component#linear method, which is reason I've done it): https://github.com/indyteo/adventure/tree/component-split
The component-linear branch is "clean" (I could open a PR if you want), but the component-split branch isn't, it's just to show that (awful) working single-char split
Knowing when to split is the easy part
it's the whole "splitting trees" which becomes somewhat cludgy
That’s why I first linearize the tree
Uh so I know I can use Placeholder#parsed() to create static placeholders in MM but how would I do ones where the output is dynamic aka depends on a condition (but can be static still)
Can you give an example?
You want to make a TagResolver
I do some stuff where I pop an arg and then switch
I see
would a Tag#inserting be the correct choice for a tag that just outputs a specific thing?
Imagine Kitty says <meow>! where you compare a Tag#inserting and Tag#selfClosingInserting, and have the meow tag output a red meow. With inserting, the exclamation mark is red, with self closing it doesn't pick up the red.
I see, interesting, thanks!
Uhm actually, if I were to want the output of a tag to contain other tags, is it automatically parsed or would I have to deserialize it twice so to say?
In my case I am turning a component to string and then to component, wouldn't it be better to just do string manipulation at this point?
nested tags should be parsed automatically
probably? What's the actual xy here
well Tag#inserting, etc receive components as a param
tldr; intercepting system chat messages, converting them to string, applying custom placeholders generated by the user (what I am trying to do), then convert it back to a component. Idea is to add minimessage support everywhere with some extra stuff
Not really sure how I'd properly approach this
I was previously only using static placeholders which made this easy but yeah, now I am not sure
I am confused at the goal here, you would add mini message support to third-party messages (as in, not sent by your plugin) even though they wouldn't use them?
well, the whole thing is to give users the option to use them in plugins that do not support MM
for player messages I would understand, but for system messages I don't
if that's the case then I would just serialize component into string and then deserialize into component again like I assume you're doing, I don't see the problem with that. Though I find the whole thing to be kind of a recipe for troubles
well the question is if I do the custom tags/placeholders handling when its a string or after deserializing
I would just do it at deserialization, there shouldn't be anything that dynamic replacements don't support for this kind of thing
so using tag resolvers?
yes
hmm can someone explain this error: Tag name must match pattern [!?#]?[a-z0-9_-]*, was p_isOnline? What exactly is this pattern
lowercase
I am trying to replace arguments in a TranslatableComponent with another TranslatableComponent. The inner translatable components don't get replaced with the text, but the key for the translation.
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
That's a known issue iirc, I've already heard of that one
Which version are you using?
It seems it has been fixed
Oh no that might still be an issue if you're using named arguments, as stated here, since this other issue is still open
Named arguments?
Arguments are in the format {0}, {1}, {2}, ... .
You're using MiniMessageTranslationStore or the other one?
Uhh no clue lol. The translation part is handled by a different plugin. I just specify the keys for each locale and then use them in Component.translatable()
Then check the version of adventure in use (by that other plugin)
The issue you seems to encounter has been solved in 4.22.0
I'm assuming that adventure is provided by paperweight. So I'm not sure
id 'io.papermc.paperweight.userdev' version '2.0.0-beta.18'
Which version of Paper are you on?
1.21.4-RO.1-SNAPSHOT
Hmm, that might be why, let me check the adventure version in use by that version
Yep
Paper 1.21.4 uses Adventure 4.20.0
Your issue has been fixed in Adventure 4.22.0
Ouch
So you either need to update to more recent Paper version (not a bad thing but can require more work), or bundles your own version of Adventure to use it, but you might have other issues by having 2 different adventure versions
I see, I'll let the developer of the translation plugin know. Thanks for the help
Np, good luck for the rest x)
This is not really a bug, but a small problem.
Basically I use PlainTextSerializer to flat a component then I parse the string with Minimessage to remove any know tags <red> <blue> etc.
Some users found a cool way to bypass this:
<<red>blue>How are you? has <red>
It will result in a blue colored message "How are you? has"
Why not just use a MiniMessage instance without the default tags?
you mean deserializing using a Minimessage without default tags? so message will look not colored but <blue> How are you? has
Yes
thats a good idea, how can I build a minimessage instance without tags?
I'm still confused. What are you doing this for.
Like, if you don't want them adding tags why is it going through mm
Because via configuration you can use minimessage tags to customize the formatting and the message
Okay, are we talking something like chat formatting?
Why not parse the message as plaintext with the plaintext serializer and then insert it into the minimessage string with a component placeholder?
unparsed takes string, strok
If it's the component from the event though I'd just push that component, without plaintextserializer, into a placeholder
My point was the edit was unnecessary
hey yes exactly
then yes, what we said
Will read it in a bit xD and properly reply
the problem why I need to find a good trick is this.
If somebody has this format
format: %player_name% -> <red>{message}
By doing that, I can't use configuration inputs
What on earth is this cursed format?
<player_name> -> <red><message> and then player name and message are placeholders.
it is placeholderAPI, to use placeholders
Oh okay, then create a tag resolver to do papi.
<papi:player_name> -> <red><message>
mmm is this documented? I mean has Minimess a way to resolve placeholder api placeholders? (without knowing them)
ah good lemme read it
hanks
I wrote it :3
thanks*
You could use MiniPlaceholders 
the thing is always the same, if it was for me, this wouldnt have been a problem xD. Problem starts to arise when I have to make it extremely customizable without headache for the end user.
Btw that doc is helpful so thank you
Is there a way for the server to know if a player hovered on a text? It looks like you can’t listen to HoverEvent. I want to do this to collect metrics
Sounds cool, but I don't think there's anything sent back for that.
Not the client doesn’t share this info
Your only way would be to set a click event and ask the user to click after hovering
Why are messages not sending to a player?
- Server version:
Spigot 1.21.8 - Spigot-API:
1.21-R0.1-SNAPSHOT - Adventure version:
4.25.0 - Adventure Platform Bukkit:
4.4.1
Code example:
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
Audience adventureSender = plugin.adventure().sender(sender);
System.out.println(adventureSender.get(Identity.NAME)); // returns Optional[teunjojo]
MiniMessage mm = MiniMessage.miniMessage();
Component parsed = mm
.deserialize("Hello <rainbow>world</rainbow>, isn't <underlined>MiniMessage</underlined> fun?");
adventureSender.sendMessage(parsed);
}
when using plugin.adventure().sender(sender) no messages get send to the player but plugin.adventure().console does send it to the console
What am i doing wrong?
have you actually downloaded and compiled spigot yourself or are you using paper
actually spigot
you'll need to enable debug logging for adventure platform and go from there, the flag should be in the docs somewhere
but if you're already targeting 1.21+ you should just drop spigot support and make things easier on yourself
im targetting 1.8-1.12.8
if you really want to hold on to old versions for longer then I would do a break and ship two jars
you will need separate code for paper eventually anyway, we update separately from and before spigot now (see our snapshot branch)
you can see an example of that here https://modrinth.com/plugin/minimotd/versions - the jar for 1.8-1.21.7 uses adventure-platform-bukkit
the 1.21.8+ paper only one does not
alright
long term that will have less maintenance, but if you still want to debug platform-bukkit debug logs are needed
also on 1.8 it does show the messages but when i do
adventureSender.showTitle(Title.title(
Component.text("Main title"),
Component.text("Subtitle")));
the title doesn't show up
idk if that is somehow related
big blue box about it there
i set the flag but i dont get any special output. also when calling showTitle on 1.21.8 i get disconnected and the console throws an error:
[Netty Epoll Server IO #2/ERROR]: Error sending packet clientbound/minecraft:set_subtitle_text
io.netty.handler.codec.EncoderException: Failed to encode packet 'clientbound/minecraft:set_subtitle_text'
There should be a bunch of output into the log. Not sure you set the flag right.
for an encoder exception you might need to enable debug in server.properties, vanilla does a good job of silencing exceptions inside of their networking stuff
Ok so I don't know what I did but all of a sudden all, i got the debug messages, no more crashes and the messages and titles started working
thanks for the help tho
<@&748618676189528155>
How can I replace multiple texts in a component?
If I do this, then only {name} is replaced:
CachedComponents.IMP.player.kick.realname.replaceText(builder -> builder
.matchLiteral("{realname}")
.replacement(user.getRealName())
.matchLiteral("{name}")
.replacement(player.getUsername()))
is there a reason you aren't just replacing those before converting it into a component
minimessage formatting takes about 200ms, so I format messages in advance so as not to do it in runtime
Must be a massive message
oh, sorry, I got the zeros a little wrong.
i converted nanoseconds to milliseconds incorrectly
but the very essence is the same, as for me it is better to create a component in advance than to do it in runtime
Must be a very unusual use case
problem solved, i found a solution
What was the solution?
make two separate replaceText
btw, I checked, it's better to use match(Pattern) instead of matchLiteral(String) because with matchLiteral(String) the Pattern is compiled every time
instead, better to create a static Pattern and use it so that the replacement takes less time
that way it'll be more optimized
Sending this component to a player sends the correct message in chat, but it's missing hover and click events. Any idea why? Both messages from the config are TranslatableComponent's.
final Component acceptComponent = this.config.messages()
.get(PlayerTradeMessageConfig.Messages.INCOMING_TRADE_REQUEST_ACCEPT_MESSAGE)
.hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT, this.config.messages().get(PlayerTradeMessageConfig.Messages.INCOMING_TRADE_REQUEST_ACCEPT_TOOLTIP)))
.clickEvent(ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/trade " + this.sender.getName()));
No it isn't, your solution here will likely be slower than using MiniMessage
How are you sending it to them? What platform? What client version, any client mods or custom clients?
player.sendMessage(Component)
folia
1.21.4
no mods just vanilla
any protocol hacks on your server or proxy?
Protocol hacks?
viaversion, other such plugins that mess with the protocol level, etc
try without those and you'll likely find what's causing it
okay so
to get player Locale i have to do smth like this
redisConnection.getPlayerData(uuid).getPlayerLanguage
so currently when i for example want to send message to all 10 players in game
i have to do it by for each player
getLanguage
translatableComponent = Component.translatable(key, args)
player.sendMessage(GlobalTranslator.translator().translate(translatableComponent, locale);
yes there is no way to override the locale for a player yet but it is on my to-do list post 5.0 release
but you could easily extract that into a util method
okay so thats the only correct way to do this rn right?
yep
yeah im doing it
just displayed the code for understanding
that's great then looking forward to it
I was thinking of something like
TranslatableComponent
Audience.sendMessage(translatableComponent, ( road to player language like: ) redis.getPlayerData(playerInAudience.getUUID).getPlayerLanguage)
but whatever achieves goal of sending message to many players in diffrent languages based on those cached locale im
good with it
depending on how you do your translation, it's possible to override the locale when creating the component (e.g. the built-in minimessage translator system lets you override it)
You're trading maintainability for performance, micro optimizing might make your code some nanoseconds faster, but eventually it will make it hard to maintain and debug
You're also not getting (or very unlikely to get) better performance
right, although idk what's the point of not just using minimessage
after the MiniMessageTranslator was released, and the Argument class, it was my way since then
super flexible and easy to use
why not sending the translated component instead
players.forEach(player -> {
var playerLocale = myOwnLocaleResolver(player);
player.sendMessage(GlobalTranslator.get().translate(playerLocale, messageKey));
});
?
something like that
im glad you like it :D
I already do that with my own translator, I don't really like to depend on the global translator, best to avoid collision with other plugins translations
I really do! honestly best thing was done in kyori ever, combo of MM and translations part of kyori is W
lmk if there's anything you think we could do to improve it!
I mean yeah thats basically what i do but it could be done better if it worked with audiences
right, if that means a lot for you why don't you fork adventure and add a way to set the locale (e.g. modify the locale pointer i guess?)
or just make your own abstraction
though they would def add it later but for now it's what it is lol
i'm having an issue where my apostrophes are getting doubled up when displayed in game
this is my minimessage text (the hover:show_text at the end is where the issue is) :
message.command.map.output=<meadow>:earth_africa: <click:open_url:"https://map.worldmc.org/?zoom=6&x=<x>&y=64&z=<z>"><ash>Click here to view your location.</click> <hover:show_text:"<ash>Can't see yourself? Make sure you aren't under blocks or water!"><aqua>🛈
this is the code sending it:
sender.sendMessage(Component.translatable(
"message.command.map.output",
Argument.tag("x", Tag.preProcessParsed(String.valueOf(location.getBlockX()))),
Argument.tag("z", Tag.preProcessParsed(String.valueOf(location.getBlockZ())))
));
i tried escaping with backslashes and more quotes and stuff but i couldn't figure anything out
what's your code for creating the translator & registering the translations?
In the case of matchLiteral(String) and match(Pattern), the difference is actually significant. I checked, and replacement via matchLiteral(String) takes almost 30 ms because Pattern will be compiled each time, which is a lot for replacing a placeholder
that was the issue, ty
does it? I thought the pattern was stored in the renderer
yes, that compiles the literal and then that TextReplacementConfig is used to create the TextReplacementRenderer, which stores the Pattern in the TextReplacementRenderer.State class
so, there shouldn't be any difference
I think he's not reusing the text replacement config, but recreates it every time, which is kinda funny considering their initial goal was to micro- (should I say nano-) optimize
that would make sense
tbf I can't blame them for not reusing the config when most replaceText examples use the method that takes a consumer of the TRC builder
compiling a literal pattern shouldn't take that long, lol
can't really say anything without a proper profile report however
You might be right but IMO there are many more things to care about rather than this small detail and for sure it aint take 30ms thats crazy lmao, also use MM or translation arguments for placeholders, the replacement config is meant for more complex use cases
For some reason I can no longer get the adventure-text-feature-pagination from maven. I've checked the https://central.sonatype.com/ site but can't find the package anywhere?
iirc it's not longer published because it was never published (officially). Only snapshots were, and they expired. And since the project is discontinuated, you'll need to publish it yourself to your own repo, or build it locally
Sorry if this gets asked a lot but when will dialog support be worked on? The last time I checked a bunch of people wanted to wait until the dialog system becomes stable. According to the minecraft wiki mojang hasn't made any changes to it since it was initially added in 1.21.6, which was over 4 months ago now.
that's why I asked when it will be worked on, not when it will be finished
Mojang simply hasn't tended to the dialog system yet. Seeing as there has only been one game drop (1.21.9) since then, it is still too soon to establish that Mojang will not do any ridiculous changes to it, we'll just have to wait a bit more
For how many more game drops do you want to wait then? Mojang could always make big changes to it, no matter how long you wait. I dont think there is gonna be a better indicator that it's gonna be stable for a while other than mojang not touching it.
You basically answered yourself
I dont think there is gonna be a better indicator that it's gonna be stable for a while other than mojang not touching it.
And a single game drop
consider reading the first part of my message
I am not entirely certain why this is a discussion. The adventure team will introduce a dialog API as soon as they believe it is safe to do, anything apart from that are just speculations
Tbf, the whole dialog thing, while being revolutionary (compared to older alternatives, such as chat or chests), still feels harsh, and unfinished (there are a few "simple" features that could get added or reworked that could make the thing way better). So yeah maybe Mojang is happy with that, and they won't change it, and this waiting is "unnecessary", but considering they worked a lot on technical features and ability to customize things recently, the contrary wouldn't be surprising either. Anyway, I'm not the one who took that decision, and I blame no one for that because even if I don't completely agree (my personal opinion is that even if Mojang improves the dialogs, they won't change the whole system, but that's just my personal opinion), I understand the adventure team's point of view
yeah but my point is that the reason that the adventure team has given for not starting to develop it yet is also just based on speculation
mojang could always make major changes to the whole system and they probably will at some point
Of course, we all take decisions based on how we think the future will be. How else could we do? I don't have a crystal ball x)
but we can't know when, so more waiting is pointless imo.
Mojang has shown by the past that they could add something, and immediately change it in the next update(s)
So this is not far-fetched to think it could happen with dialogs
Dialogs really do seem rather so-so for their promise at the moment
(However, considering they did not change a thing about them in the latest update, yes we can begin to question whether this will be the case this time or not. And maybe the team will reconsider their decision. Or maybe not, idk, they take whatever decision they think it the best for their project)
A single update isn't really too reflective of much, bearing in mind how much components have been churned around since
Adventure wants to be able to offer stable API
I feel like with this mindset, this could go on forever. If they keep it in its current state, you'll say it's clearly unfinished and they will touch it again. And if they do change it again you're also gonna keep waiting because "well clearly they're still working on it".
components were changed in every update tho, they didnt wait for one update until they started changing them
We're not talking about the same kind of "changes"
Additions are fine
Components were added in updates, they went back and modified a chunk of stuff from their first iteration in the 2nd gamedrop or so iirc
but they've also made non-additive changes that lasted a single version, yet adventure has added those changes
A "stable" API could receive new features (otherwise it would be a problem lmao), the things that are harder to handle is when a part of an API needs to change because it can no longer work the same
Which one?
like, perpetual can kicking is always a risk, but there is some level of trepidation over adopting brand new entire systems and writing the API for it, especially when there has been a whole host of feedback against it, I'd imagine it might be easier to start now, but, project done in free time, etc
see for example the whole mayhem that was 1.19/.1/,2 etc around chat signing, first it was sender uuid, then it was signatures, chat types etc etc
adventure adopted every single one of those changes and a large chunk of those methods have been deprecated ever since because mojang just changed how the mechanisms worked the very next version
Yeah, that's true, and imo it could have been better to wait like now 😅
yes, so the question becomes: how long should one wait?
Good thing Adventure 5.0 removes those
how long is long enough
I think that the decision to wait a version probably forgot how game drops worked now
That's a tough question, of course. A question I could share my point of view of the answer, but idk if it would be very useful since I'm not the one taking decision (thankfully xD)
Game drops are also questionable, I mean, yes the community "won" more frequent, smaller updates, but I feel we all lost a lot of clarity about what's going on
-# But that's a topic for #general ig
I think waiting one game drop is enough. It's reasonable to assume that they will make adjustments to a new system in the following game drop. But after that it just becomes blind speculation.
If you want an "official" answer - our current focus is the 5.0 update, then we'll likely revisit dialogs if they're still "stable" after the next drop or two
I don't understand the rush
Paper already has an API for it, Fabric I'm sure you can just use Mojang's own stuff
Adventure's might end up being nicer to use but it's not like you can't do dialogs right now
it does bring the point of abstraction, just write code for it once for all rather than once for each, i think it's fair enough given the surface area of the system
I suppose but my guess is they're hoping for adventure-platform-bukkit to support it and that's the only concern 😛
I suspect they want to use it on velocity.
adventure having an API for it isn't going to magic that up, although I suppose velocity could be waiting for adventure to have an API before adding dialog support
I honestly don't believe there's any point in waiting either but I just assumed that adventure has very little manpower to muscle through a good design for the dialog API and nobody was up for a job that could possibly be thrown out of the window if Mojang decided to change things up, so we are where we are
it didn't come at a good time either given 5.x was in the works when dialogs were introduced, so that took focus instead. Though it would've been nice if 5.0 release would've introduced the dialog API, we're not there yet
That is the case yeah
Heya, iam creating a brigadier cmd that makes it able to edit a sign line.
i get the sign and the sign side then i set its line with the text to Component
however when i use sprites in the chat it shows on the sign as a black block instead of the sprite (blue_wool)
iam using sprite:block/blue_wool
Can client side translations take translation arguments 🤔?
didn't try client-side translations nor any mod development yet to know, but if they do support receiving translation arguments from server side, that would be neat
they can, however I don't think you can use components as arguments when it comes to client-side translations as they use the MessageFormat stuff
ahh that sucks
it doesn't use MessageFormat, it uses its own format that is basically a stripped down version of String.format, arguments can be and are components, what is not a component is the translation format itself, but it can take components for arguments
var player = (Player) commandSourceStack.getSender();
var template = "<click:open_url:'ddd'><#ffe49c>Join our Discord server!</click>";
var message = MiniMessage.miniMessage().deserialize(template);
var component = Component.text().append(message).clickEvent(ClickEvent.openUrl("ddd")).build();
player.sendMessage(component);
```
Does anyone know why the custom color code doesn't work
what's your platform & the platform's version?
are you using the vanilla client? version?
could anyone tell me why my message when im not using <!i> at the start is always italic?
Is it in item's lore or description?
Because that inherits origin style which includes italics
Just expect it to be italics and set it to no italics if you explicitly want that
Hey, I got an issue where the ' character gets duplicated, when I use translatable Components.
For instance my properties (UTF-8) has the following line: command.speed.set.other=Set <yellow><player>'s</yellow> speed to <yellow><speed><yellow>.
which is sent as Set players''s speed to 1.0. to the player/console.
Set escapeSingleQuotes to false in your bundle loading code
Whats the usecase for escaping single quotes? When does it come in handy?
when they're in single quote arguments
otherwise you can't escape them
How can I force adventure to parse the legacy style from the text components and fallbacks of translations?
My current code:
private static String translateInternal(Component component, Locale locale) {
String discorded = DiscordSerializer.INSTANCE.serialize(GlobalTranslator.render(
component, Objects.requireNonNullElse(locale, TranslatorUtils.DEFAULT_LOCALE)
), SERIALIZER_OPTIONS.withMaskedLinks(true));
if (discorded.contains("§")) { // legacy
discorded = DiscordSerializer.INSTANCE.serialize(
LegacyComponentSerializer.legacySection().deserialize(discorded),
SERIALIZER_OPTIONS.withMaskedLinks(false)
);
}
return discorded;
}
What are you trying to do here? Looks like you're trying to turn a component into discord markdown, in which case why is legacy involved here at all?
Just go from component -> discord, running it through the global translator first if you need to
component -> discord but if there is legacy formatting, then component -> discord -> legacy -> discord so that it is applied correctly (but in reality it is not)
why would you have legacy formatting inside a component? sounds like that's where your issue lies
This is a bot for Emotecraft. People can specify both JSON and legacy formatting in the name, and Minecraft will accept it, but Adventure will not
A good example would be something like:
"name": {
"translate": "translatekey",
"fallback": "§4Fallback" // legacy
}
just don't do that, you can specify colour in json fine
best to keep one unified format
I can't make everyone do this!
As long as Minecraft can accept it, people will use it
Then you're just gonna have to plain text serialize and hope you don't lose any other styling information
I need parity with Minecraft
This is why mixing formats is awful, no matter whether you're making a Minecraft plugin or something completely different
Then you're going to have to write an entirely custom component renderer
🙄
Yeah, welcome to the joy of mixing formats haha
how it works in minecraft?
no clue, you'd have to look at the source
Does bungeecord chat support this?
Nope
You'd be having to do the same thing no matter what component library you were using
In fact you'd likely find it harder in bungeechat as they don't provide a framework for custom component renderers
Why is it that using anything by Paper always has to be such a pain? 
- this has nothing to do with paper
- paper didn't make adventure
- you'd be having this issue using any other component library
- you'd be having this issue even if you weren't making a Minecraft plugin and were just mixing json and some other format interchangeably
if you want help im here and happy and willing to help you but if you're just gonna complain and be rude then good luck you're on your own 👍
Thank you for your help, I will continue my research! 
||Developing plugins is a terrible experience, and I don't understand why many people still choose to do it||
Godspeed! It definitely gets easier if you limit what you support based on what is easier that's for sure
Moved to #adventure-platform-mod-help
Thanks, I'll move my post there
Hi, can I remove or replace selected TagResolvers in the list if I have a duplicate but with different functionality? I'm trying to replace the selected TagResolvers in TagResolver.standard() to change the processing code, but if I specify them together, the processing is incorrect. I tried specifying all the standard TagResolvers manually, but I encountered a version difference: new format codes aren't processed, and I can't specify them in the old version of MiniMessage due to the core being tied to a specific version
what tag resolvers are you replacing, specifically?
gradient and transition
No, modifying them is unsupported, you would need to create your own tag resolver set
from a quick look at the javadocs of https://jd.advntr.dev/text-minimessage/4.25.0/net/kyori/adventure/text/minimessage/tag/resolver/TagResolver.html#resolver(net.kyori.adventure.text.minimessage.tag.resolver.TagResolver...), the order determines which tag takes priority
The last specified resolver takes priority.
woops did not intentionally trigger automod... sorry guys
does minimessage just not serialize closing tags if they are at the end of a string?
private @NotNull String parse(String message, DiscordChatMessage discordChatMessage) {
TagResolver.Single discordMessageHover = Placeholder.parsed("discord_notice", """
<hover:show_text:'<gray>This message has been sent in the discord channel.
<blue>Channel: <white>%s</white>
Link: <white>%s</white></blue></gray>'><dark_gray>[<blue>D</blue>]</dark_gray></hover>"""
.formatted(discordChatMessage.discordChannel(), "invite link"));
Component temp = FormatUtils.getNoPrefixMiniMessage().deserialize(message, discordMessageHover);
return FormatUtils.getNoPrefixMiniMessage().serialize(temp);
}
This is what is returned by the instance:
<dark_gray><hover:show_text:'<gray>This message has been sent in the discord channel.
<blue>Channel: <white>allgemein</white>
Link: <white>invite link'>[<blue>D</blue>]
only in strict mode iirc
Hi, I want to translate messages for players. But it's very difficult to support every language (that would take too much time). Therefore I am looking for a way to set the fallback language to english.
Example:
- Player A has set his language to german: german is supported so the player gets a translated message
- Player B has set the language to russian: but russian is not supported; the player gets a message in english (from the english resourcebundle)
How can I do this? I already tried this:
public static boolean sendTranslatableMessage(Player player, String translationKey, Component... arguments) {
Locale playerLocale = player.locale();
Component translatedMessage = (Component) GlobalTranslator.translator().translate(translationKey, playerLocale);
if (translatedMessage != null) {
player.sendMessage(translatedMessage);
return true;
}
Component translatedFallbackMessage = (Component) GlobalTranslator.translator().translate(translationKey, Locale.ENGLISH);
if (translatedFallbackMessage == null) {
return false;
}
player.sendMessage(translatedFallbackMessage);
return true;
}
But the problems is, that I cant involve arguments. I am happy about every idea :)
you can do that simply by setting the default locale of your translation store
Ah okay, what is the method for that?
declaration: package: net.kyori.adventure.translation, interface: TranslationStore
generally, just look at the javadocs
Yeah, sorry. Wait I thought I habe to create a translation store for every "language". Do I only have to create one for a plugin and add multiple resource bundles?
you only have to create 1
when you register a resource bundle you specify the locale it's for
That’s nice to know, ty :)
is there a way to make a tag resolver in minimessage that styles and appends something?
For example: <hp>2.5</hp> would show translate to what looks like <red>2.5</red> <glyph:heart>
Is it strictly required for you to put the <glyph:heart> OUTSIDE of the <red>...</red> tag?
it's not
So it makes this easier- wait no nevermind it changes nothing. You can do it with a Modifying tag
So something like this?
You don't need to test for the type of the component?
True
It's more like:
class StatTag implements Modifying {
TextColor statColor = ...;
Component statIcon = ...;
@Override
public Component apply(Component current, int depth) {
if (depth != 0)
return Component.empty(); // .apply() is called recursively with all children, but you only want to process the root to wrap it and append something
// Here it depends if you want to overwrite possibly present child color and also color icon or not:
return current.color(statColor).append(statIcon); // you might want to deep re-color children if you want to really overwrite the color
// Otherwise, to leave the icon un-colored, and also not overwrite child color:
// return Component.text()
// .append(current.colorIfAbsent(statColor))
// .append(statIcon)
// .build();
}
}
Of course you need to adapt it to your exact context
But it's important to properly process (or not) children, because the Modifying tag has quite an odd default behavior (you can quickly duplicate them if not paying attention)
Does custom font get processed inside of these? I'm placing the tag inside an item's lore, if that changes anything
I don't know how your glyph/font works, but it looks like you're trying to give a minimessage-encoded string (<glyph:heart_icon>) to Component.text(...), which won't deserialize it. It looks like you need to use MiniMessage.miniMessage().deserialize(...) to turn your "<glyph:heart_icon>" to a Component
Except if your font renders the raw text <glyph:heart_icon> as the heart icon (but I doubt that, I think the glyph tag returns a special character that the font turns into the icon)
This is elsewhere in my code. I'm using Nexo to generate my font files/resourcepack, and it does dynamic replacements like here
But does this work correctly?
1_21_9-SNAPSHOT:20251006.134713-8
