#adventure-help
1 messages · Page 4 of 1
I want it mainly to lower other tags, like <lower><player_name><lower>
would <player_name> be a TextComponent?
Tags are resolved from the most nested to the least nested, so your <lower> tag would receive whatever the <player_name> resolves to
how to apply my LowerTag here
Once you created your implementation of that tag, you need to add it to the list of resolvers
If you just want to add it inline in the single deserialize call, you can use TagResolver.resolver("lower", new LowerTag())
But I'd recommand you registering it to your MiniMessage instance, with something like:
MiniMessage mm = MiniMessage.builder().editTags(tags -> tags.tag("lower", new LowerTag())).build();
this one time onEnable is enough?
It builds a new instance of MiniMessage with your new tag inside, but you need to use keep a reference to that instance in order to use it later
MiniMessage.miniMessage() returns the global shared instance, which is immutable and you can't add your resolver there
got it
it worked, thank you
@Override
public Component apply(@NotNull Component current, int depth)
{
if(current instanceof TextComponent textComponent)
{
return Component.text(textComponent.content().toLowerCase(Locale.ROOT));
}
return current;
}
the logic
heck yea
Be careful as you're loosing all style and children this way
Since you only need to modify the text content, I recommand you to do return textComponent.content(textComponent.content().toLowerCase(Locale.ROOT)); instead
Which will simply do the same thing, but keeping your style and children
I tried this by first but it got duplicated
Oh, then maybe you don't want to carry over the children, but only the style, in which case you can do:
return Component.text(textComponent.content().toLowerCase(Locale.ROOT), textComponent.style());
It will do the same thing as this, which will duplicate children then no
I tested this, it seams to work fine
I'll do one more test to understand it better, lets see
yes I think its working nice
ive been wanting a simpler version modifying that just allows direct text modification, like a wrapper to make this easier
That would be interesting, I think
This code will work the same for lower / upper operations, however do note that you'll need a different approach for capitalize or trim
Since you don't want to capitalize every components individually, but probably rather lower everything and then upper only the first character, which may be in root component or it's first child / grandchild / etc
Same for trimming, you only need to trim the spaces from the beginning and the end, not in the middle, thus this is far more challenging
yeah, <capitalize> has broken with the rainbow component, turning it upper cased
I can't understand why, each char in the <rainbow> becomes a separated TextComponent?
yes, so each can have its own Style with the corresponding color component
ah, your issue is you aren't copying the children over i think
you'll want return Component.text(textComponent.content().toLowerCase(Locale.ROOT)).children(textComponent.children);
i think
@vivid bobcat ^
No
See here
I had the same reaction
ohhhh yes
im getting confused with rendering where you do need to copy over the children
tbh it is probably best to just textComponent.content(textComponent.content().toLowerCase(Locale.ROOT))
In this case, the problem is to identify the first character, which could be the first character of the text at depth 0 or 1 depending on the start of the numbering, but if it's empty, then its first child needs to be observed
However, since the Modifying tag traverses the children with DFS, I just realized it can be achieved pretty easily
Yeah I did it pretty easily:
public class TagCapitalize implements Modifying {
private boolean capitalized;
@Override
public Component apply(@NotNull Component current, int depth) {
if (current instanceof TextComponent text) {
String content = text.content().toLowerCase(Locale.ROOT);
if (!this.capitalized && !content.isEmpty()) {
content = content.substring(0, 1).toUpperCase(Locale.ROOT) + content.substring(1);
this.capitalized = true;
}
return Component.text(content, text.style());
}
return current;
}
}
And since this is a Modifying tag which keeps data, according to the docs:
Modifying tags are first given an opportunity to visit every node of the tree in a depth-first traversal. If a
Modifyinginstance stores any state during this traversal, its resolver should return a new instance every time to prevent state corruption.
You should register it like that:
private static final MiniMessage mm = MiniMessage.builder().editTags(tags -> tags.tag("capitalize", (args, ctx) -> new TagCapitalize())).build();
Or inline:
MiniMessage.miniMessage().deserialize("<capitalize><rainbow>teTETStesgER", TagResolver.resolver("capitalize", (args, ctx) -> new TagCapitalize()));
Result:
Does minimessage have support for translateable components with fallbacks?
Thanks, I found it in the source code but it isn't documented on the docs page. Someone should add it (I know I should)
That true, I went in the docs to give you the link but noticed it wasn't there
Feel free to open a PR if you want!
It's newish
I got lucky, there already is an open PR for it.
will get that merged 🫡
Hey! What's the correct way to hide a bossbar from all current viewers?
I tried java bossBar.viewers().forEach(player -> bossBar.removeViewer(player));
but there the player is ? extends net.kyori.adventure.bossbar.BossBarViewer player and removeViewer method requires Audience
Yeah it's a bit strange to have those two interfaces, I remember a discussion about that already
On Paper, Player is both Audience and BossBarViewer, in case you wonder
I'm trying to do that on velocity
But I don't really know what's the platform-independent way to do so, except something like:
for (BossBarViewer viewer : new ArrayList(bossBar.viewers()))
if (viewer instanceof Audience audience)
bossBar.removeViewer(audience);
Idk if the copy of the viewers iterable is needed but it stays it is an immutable view, then it may produce ConcurrentModificationException otherwise
Yeah, I also wondered if I could just remove a viewer while iterating, if it's immutable list - then propably yes
Fow now I could propably just remove all online players, even if the bossbar is not displayed to them, although it isn't my favourite approach for that
https://github.com/KyoriPowered/adventure-text-feature-pagination
I think this repo needs a small update also for the discord. But anyways, is this still working and maintained ?
it's unmaintained and should probably be archived tbh
I'm trying to understand the Modifying tag, I put some logs and I'm returning the self current component on apply, but it's getting duplicated.
ex: <my_tag>abc</my_tag> -> abcabc
@Override
public Component apply(@NotNull Component current, int depth)
{
return current;
}
its duplicating
we really need to document that tbh
is it possible to make it automatically resolve the target?
getServer().getConsoleSender().sendMessage(Component.translatable(
"showcase",
Argument.target(getServer().getConsoleSender())
));
it's pretty ugly to use the target twice
I don't think I understand what you mean?
What here is using double the target?
If you are refering to the getServer().getConsoleSender(), then just put it into a local variable beforehand
final CommandSender sender = getServer().getConsoleSender();
sender.sendMessage(Component.translatable("showcase", Argument.target(sender)));
I meant getServer().getConsoleSender(), wasn't sure how to describe my problem, but I think it would be handy to automatically get the target audience when sending a translatable component
I don't think that is neither useful nor cleanly possible
A translatable component just contains a key. That key can be basically anything. The translatable component has nothing to do with who you are sending the component to
okay thanks
I got the <capitalize_fully> tag working, now I want to create the <trim> tag, but I have no clue how to do that. I also didn't understand the purpose of visit method on Modifying interface, is it possible to modify the TextNode on it?
In MiniMessage there isn't by chance a tag like </> that closes the last opened tag? So i could write <yellow>Hello <green>World</>! instead of <yellow>Hello <green>World</green>! and would only have to replace one mention of green instead of two when changeing the color?
And if not is there a specific reason for that?
I've been using a similar to MM format recently, and it had syntax like this <first>First <second>first+second</> still first</> plain, which was actually pretty handy t...
I've created an issue about that awhile ago, but it's rather inactive - it just isn't much interesting for contributors
(look at the issue above)
I got something working but the code is not very clean. What is your use case?
what do you mean? I just want the <trim> tag working. I'll use it for trim my placeholders when necessary
Can you share some examples of that so I can test if I understood correctly?
for example I have a <duration> it's returning 1d 1h (its configurable on another section by minimessages choice tags, I didn't find a way to remove the extra spaces), so I need it like <trim><duration></trim>, Idk if that does make sense
Ok I see, let me cleanup a little bit the code and I'll share it with you so you can test it. However please do note that it's probably not the best in term of performances but I think at least it works
Ok, even after trying to simplify and comment it, that code is super ugly, but hey, it works (I think so).
For example:
<red> <b> </b> A<i> test <u> </u> </i></red> EOF
<trim><red> <b> </b> A<i> test <u> </u> </i></red> </trim>EOF
Renders:
My screenshot is cut at the left edge of my chat, and I put EOF at the end to visualize the end of the line
As you can see, there's a lot of spaces in nested children, and it strips them all
(From the beginning and the end of the <trim> tag only, not inner spaces)
As shown in this example:
<trim> Inner <red> spaces! </red> </trim>EOF
And here is the code I used (as a bonus there's also my experimentations of lower / upper / capitalize)
(You probably want a TextModifying abstract class to factorize some code between all that other tags, tho)
did you trim the spaces from that code too? :p
Idk why Discord doesn't render tabs in inline file previews, but it shows them if you open the file...
But yeah, I guess it makes sense for that code to have line trimmed as well lol
Whoa nice, your trim tag appears to be working properly. I think I understood your code, It was a good solution the right/left and children recursion by ourselves, so I'll use it with no changes. Those text tags will help me a lot, Thanks for your attention
Np, glad to help! 🙂
It was fun as it got me to think deeper about that Modifying tag, and I think I encountered an interesting case I'll talk a bit more about tomorrow, as it may interest Kezz probably
is the recursive translation of an translatablecomponent still not merged?
because both the minimessagestore and a impl of the minimessagetranslator are giving me the key of the tcomponent instead of the translated one
Not merged? I mean there's no PR that can be merged anyway 😅
It's a very complicated problem
what does the MiniMessageTranslationStore do wthat the old TranslationRegistry does not? Just replacing them in my impl for recursive translation breaks them somehow
Well, the MiniMessageTranslationStore and the TranslationRegistry are very different
one holds MiniMessage strings and turns them into components, the other holds message format strings and turns them into MessageFormat instances
Good to known I use this lib in some projects means I need to maintaine by my self :(
Hey, does adventure have a convenience method somewhere that checks whether two components are equal in terms of content and text formatting (not considering any links or hover events)?
Do you consider {"text":"Hello","color":"red"} and {"text":"","color":"green","extra":[{"text":"Hello","color":"red"}]} to be equals?
Yes, actually. That's part of why I'm asking. We're having issues with item equality between items from prior versions of Minecraft that have different structures in their display names and lore, so we're writing custom equality functions. We want meta.setDisplayName("Hello, World!") and meta.displayName(Component.text("Hello, World!")) to match, but they don't.
Then, no
Very well, is there a way to recursively remove styling from a component and its child components?
I don't think it is recursive but you can do it yourself, with either Style#unmerge(Style) or basic removal operations
plaintext and hope for the best?
but really you should be using PDC
no excuse for comparing lore/display names
Honestly, so much trouble has come from needing to store purely visual information (basically tooltip text) on the item itself. It would be amazing if this could be obviated in favour of some network-time addition of this data so that "if item has this PDC entry, add these lines to its tooltip"
But that's not how Minecraft handles items, unfortunately
No, it would be a complete mess because item equality is checked client-side and server-side, and I'm pretty sure modifying that behavior server-side without changing anything client-side would cause desyncs leading to ghost items
is there a way to use a font but like change the type of font in it
<font:ult_effects:myfont>```
i want to use a variable in place of myfont but if i do that then it doesnt run use the font correctly.. is there a way to do this
I am using skript but java solutions are fine
you could also use String formatting
e.g. <font:ult_effects:%s>.formatted("myfont")
what does the %s> do
ive never seen that
Java string formatting
hmm
ok imma try it.. ty
do u know what i would need to import for that
thats java
unless you have mirror or reflect that aint gonna work
you are looking for a placeholder
<font:ult_effects:%{_myFontVar}%>
also if it isnt parsed properly you should escape the string
i have reflect
.formatted is most likely not going to solve your problem
set {_m} to mini message from "<font:ult_effects:%{_font}%>%arg-1%</font><negativespace>" with {_r}
this does not work.. already tried it
set {_font} to "font_x-0.3_y0.5"```
you are better of asking the addon author or in a skript forum
i asked in skunity (skript discord) but i havent gotten a response.. most ppl never do something like this
and the addon author prob wont respond but ill try
its skbee that im using.. idk if u know it
i do
shane is actually on this discord
i bet he is going to respond if you ask nicely
on one of his official support channels if there are any
his thing says no ping 😭
am i cooked lol
on one of his official support channels if there are any
^
doesn't seem to be any
he sent a message yesterday in #paper-help tho
@vagrant vine ik I’m not supposed to ping u but I really need help with this and your the most qualified. 🙏🙏
.
One solution: Learn java/kotlin
My issue is not using Java. My issue is not knowing the correct thing to do in this case. I can use Java if needed
yeah if you are at the point of using skript-reflect/mirror, just using Java is actually going to be easier lol
Ok but if someone tells me how to do it using Java then I’ll convert it
But so far no one has
either by using components (player.sendMessage(Component.text("Hello").font(Key.key("namespace:key")));
or by using Minimessage: player.sendRichMessage(String.format("<font:%s>Hello</font>", "namespace:key"));
could also use a TagResolver for MM: https://docs.advntr.dev/minimessage/dynamic-replacements.html
How are you supposed to override MM color tags? I'm doing .editTags when creating my MM instance and using Tag.styling:
builder.tag("black", Tag.styling(ColorPalette.BLACK));
However if I add a custom color it seems that gradient does not seem to work with it, so e.g. <gradient:green:light_green> does not work.
that's adding a custom tag, not a "color"
so the gradient tag will still just reference the named text color
Where is the place where I would plug in the font placeholder
yeah, it does override the existing color which seems to mostly work (except for gradients I guess)
just trying to find out if there's a proper way of doing this
namespace:key is the namespace and key of the font. your namespace seems to always be ult_effects, so you could also just always include that
I guess I could change the values of NamedTextColor with reflection, but that kinda sucks
tag resolver didnt work unless i did it wrong
based on what youve provided, i honestly dont know how to help.
I recommend asking in a skript based discord (we're both in skript-hub)
and provided more details
i got it working actually like just now... im just parsing in the numbers in the thing directly and its working now.. idk why it wasn't working before.. Sorry abt the ping again 🙂
I store players' death messages in MiniMessage format, as shown in the attached screenshot. I want to go through all deaths and gather some statistics on them, such as what mob caused the death (if one did). One solution would be to just search the string for something like <lang:entity.minecraft.skeleton> for example, but I was wondering if there was a more robust, neater way of doing it with components?
at the time of running my code, the death messages will all be deserialised into components
I mean, components are not a suitable mechanism for doing that because names can be changed on entities, etc
I just tested dying to a renamed skeleton, and yeah it doesn't contain <lang:entity.minecraft.skeleton> anymore, but it still has <hover:show_entity:skeleton:<uuid>, which still tells us that a skeleton was the mob the did the killing
There is no "neater" way because there is no formal specification for the name of a translatable component
could be anything, could be unrelated to the entity name
I see. I guess storing EntityTypes associated with deaths would be better than relying on death messages then
store the key yeah, although even those change sometimes
I was just thinking of storing the enum as a string. Key would be better?
message.txt by @oak hamlet: https://pastes.dev/WS5uDRekKS
try updating your paper dependency
it seems to rely on a snapshot version of adventure that's not available anymore
you mean that adventure is not implemented on 1.20.1 right?
It's 1.21.4 now (and soon 1.21.5), 1.20.1 is quite old
No, it's just depending on a snapshot version of adventure which is not in the repo anymore
you would basically need to substitute your own or something
just update your paper dependency
uuh whats the snbt for enchantments, morespecific how do I add an enchantments to the minimsg hover:show_item tag?
you can look at the output of /paper dumpitem while holding any enchanted item to see the snbt of it
i would never rec hand writing a show item tag if you value your sanity
wait so is this even the correct syntax?
hover:show_item:'minecraft:diamond_hoe':1:'{enchantments={levels:{"minecraft:fortune":3}}}'[Diamond Hoe]</hover>
ngl i have no clue
maybe uh, make a component then serialise it to a minimessage string and have a look haha
Is there a way to center a text without having to count spaces and hope the player doesnt play on an either stretched af screen or in window mode?
nope
Is the 1.21.5 for hover and click events in text already supported? I'm using Velocity 3.4.0-snapshot and it only works on clients earlier than 1.21.5
adventure 4.21.0 which should be included in Velocity since last weak should support it
which Velocity build are you on?
498
Is there a way in adventure/Minimessage to add unicode chars as escape seuqences (in my file i have \u25cb but in chat i see the unicode symbol)?
Got nothing to do with minimessage or adventure, just the same way you'd escape Unicode chars in whatever language/file format/etc you're using
for nbt, how to get nbt from string? and how to set things in CompoundBinaryTag or something similar?
nvm found out
I've registered some translation keys through the TranslationStore per the docs and it works, except I can't get the component I pass as arg to replace:
// text.test = "%s foo"
complete.append(Component.translatable("text.test", Component.text("test")))
This just shows "%s foo" in chat when I send the component.
because thats not how placeholders work
ah, the head example made me think it would
where would this become used though? myStore.register("mytranslation.key", Locale.US, new MessageFormat("Hello %s!", Locale.US));
read the bottom part that i linked
I am. I think my confusion is that that example is specifically for hard-coded demo above, that's why it would workd
This tag will be <arg:index> or <argument:index>
I get it, I'm saying it was confusing that the custom translate code was needed for %s to work. I misunderstood. https://docs.advntr.dev/localization.html
I see now they manually have a resolution for that, but now I'm changing to what you linked
right I was adding keys to the store like the demo myStore.register("mytranslation.key", Locale.US, new MessageFormat("Hello %s!", Locale.US));, but I was not writing a custom translate method to handling the replacement. I just assumed that was automatic
I assume that to use the minimessage arg system you linked I need to register my keys in a TranslationStore.component instead of the message format store. that seems to work but I still only see <arg:0> foo in the message so I'm trying to narrow down what I've missed
show how ur creating the component
essentially this while testing:
final var store = TranslationStore.component(Key.key("mytestnamespace:mytestplugin"));
store.register("text.test", Locale.US, Component.text("<arg:0> foo"));
GlobalTranslator.translator().addSource(store);
player.sendMessage(Component.translatable("text.test", Component.text("test")))
it sends me <arg:0> foo
afaik for mm replacements like arg:0 you'll need to use a MiniMessageTranslationStore
oh you're right, I was misunderstanding that it wanted the component version because it links to those docs but it does name MiniMessageTranslationStore specifically
If you're using a "normal" translation store, it would just be {0} and so on
sweet it works, thanks! I just needed to switch to MiniMessageTranslationStore.create(key)
will the minimessage store automatically parse the format tags too or does that need to be a separate step, for example <grey>foo
if it would get parsed by mm normally it'll get parsed here
this doesn't seem to work in a hoverEvent. do I need to do something differently?
// text.foo=foo
Component.translatable("text.foo")
.hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT,
Component.translatable("text.foo")))
this shows "foo" but when I hover it shows "text.foo"
hover events might not be translated tbh
open an issue on whatever platform you're using
ok will do
well I've also learned not to append stuff directly but use the builder lol
// doesn't work, prints "footext.foo"
Component.translatable("text.foo").append(Component.translatable("text.foo"));
// works, prints "foofoo"
Component.text().append(Component.translatable("text.foo")).append(Component.translatable("text.foo"))
probably just another problem with non-message format translation stores, since the message format stuff ends up rendering the hover event
can I make my own audience? it wont let me import methods
Yes you can. It's also common to make your own ForwardingAudience instead. "It won't let me import methods" does not make sense to me, and could perhaps be clarified.
Do you mean it's not saying you must implement (not import) some methods? I think they all have default implementations.
What is your actual goal? This sounds potentially like an xy problem
implement mb
hi how can i make text in lore non-italic?
Component panelMessageLore1 = mm.deserialize("<reset>[#006400](/guild/289587909051416579/channel/006400/)<bold>|| <#FFFFFF>W tym miejscu możesz zarządzać");
Component panelMessageLore2 = mm.deserialize("<reset>[#006400](/guild/289587909051416579/channel/006400/)<bold>|| <#FFFFFF>swoim klanem, usuwać członków lub");
Component panelMessageLore3 = mm.deserialize("<reset>[#006400](/guild/289587909051416579/channel/006400/)<bold>|| <#FFFFFF>nadawać im role w klanie i wiele więcej");
<!italic>
or short <!i>
doesnt works
yes it does, show some code pls
i am using triumph gui dependecy if it matters
should be fine
Component panelName = mm.deserialize("<#39FF14><bold>GUI Klanu</bold></#39FF14>");
Component panelItemName = mm.deserialize("<#39FF14><bold>Panel klanu</bold></#39FF14>");
Component panelMessageLore1 = mm.deserialize("<!italic><reset>[#006400](/guild/289587909051416579/channel/006400/)<bold>|| <#FFFFFF>W tym miejscu możesz zarządzać");
Component panelMessageLore2 = mm.deserialize("<!italic><reset>[#006400](/guild/289587909051416579/channel/006400/)<bold>|| <#FFFFFF>swoim klanem, usuwać członków lub");
Component panelMessageLore3 = mm.deserialize("<!italic><reset>[#006400](/guild/289587909051416579/channel/006400/)<bold>|| <#FFFFFF>nadawać im role w klanie i wiele więcej");
final var gui = Gui.of(3)
.title(panelName)
.statelessComponent(container -> {
container.setItem(2, 3, ItemBuilder.from(Material.DIAMOND_SWORD)
.name(panelItemName)
.lore(List.of(
Component.text("").asComponent(),
panelMessageLore1,
panelMessageLore2,
panelMessageLore3
)).asGuiItem((player, context) -> {
player.closeInventory();
Player clicker = (Player) sender;
managmentGui().open(clicker);
})
);
})
<reset>
well yeah you're just resetting directly after
Am I doing something wrong..?
final Component compy = GlobalTranslator.render(
Component.translatable("profile.kick.marked-as-deleted",
Argument.tagResolver(Formatter.date("date", LocalDateTime.ofInstant(profile.deletedAt(), ZoneId.systemDefault()).plusWeeks(2)))),
Locale.US);
Bukkit.getConsoleSender().sendMessage(compy);
event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER,compy);
if I understand it correctly, Formatter#date needs a format as argument in the tag, so in your translation store <date:'yyyy-MM-dd'/> for example
oh.. thanks, originally I was going to make my own tag but I remembered the formatter thing existing but didn't read docs for it
tbh that probs should be throwing an error
sometimes I wish the adventure announcements in #dev-announcements would be a little bit more than just a rss bot scraping https://github.com/KyoriPowered/adventure-platform-mod/releases.atom
what else is there to say?
if it's relevant to the release, it's in the release notes
discord is not a place for information storage, so any info would be in the release notes or docs
A short summary of the changes would be nice, so that there is some actual content in the announcement channel and not just "here, link"
like Kezz did a few versions earlier
that's already in the release notes though
i think you're confusing me asking for adventure 5 feedback with a release
Does anyone have a quick an easy method to darken an entire component?
A tag is in the works by @sweet hornet, as for currently: The best way is to make a similiar algorithm that they made. Check out their PR
I can only see one PR by indyteo for something else. Mind pointing me in the right direction? Thanks
You're going to have to ask them, as I dont know where the feature they are working on's codebase is
Alright no worries Thankyou. You've already pinged them so I'm guessing they will see this message eventually
https://pastebin.com/XMtNJHcy Managed to throw this together in a few minutes. Seems to work for what I need it to
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.
probably slightly overcomplicating it there, check out mapChildrenDeep
orr you could make your own component renderer
basically adventure can already do the iteration logic for you to save yourself the hassle
what is this a method of?
oh wow I wish i knew that existed lmao.
I'll check out making my own renderer. Thanks
https://paste.md-5.net/lufivaloko.sql
I've been using kyori to load my snbt file for a good amount of time now
It suddenly started erroring this
After near a year of working just fine
I'm assuming some kyori update changes, can someone tell me exactly what happened?
What's the input? And what update did you do?
The PR is not yet open since I wanted to discuss the issue about accessing parent’s style first. But I can at least push what I have now so you can see! Will do in a few hours 🙂
you can make a draft PR
I pushed to my fork, but won't make the PR for now because the "parent's style" part is only a proof of concept I don't intend to include in the PR https://github.com/indyteo/adventure/tree/color-modifying-tags
Is there anything to explain the usage of Pointered in the MiniMessage#deserialize method? I'm mainly just looking to understand what it really does. I doubt I have a use for it but I would at least like to understand the point/usage.
you can retrieve it from the deserialization Context, so for example if you have something like a <display-name> tag or whatever, you can retrieve it from the Pointered instance via the Identity.DISPLAY_NAME pointer
or you can construct your own instance with your own pointers, or you can pass a player and cast it, etc etc, it's just more information that can be retrieved by the tag resolvers from the Context
Ahh, I see thanks for the clarification on it
is there any way for the pagination lib to work with moonshine?
Both libraries are effectively unsupported archived software atp
Why is TranslatableComponent not convertable to Component
what do you mean, not convertable?
define "convertable"
Oh yeah should've phrased it a little bit better what was I even saying
You're not trying to mix and match some 3rd party component library or something?
nope but wait until i get my message written
I mean my method takes in a Component, and if I pass it a TranslatableComponent from Component#translatable(String, ComponentLike...), it seems to not work
did you mean the version which doesn't take params? that returns a builder
otherwise, check the actual error, it will generally tell you what it thinks is wrong
I don't mean that, and the error is literally just incompatible types: java.util.List<net.kyori.adventure.text.TranslatableComponent> cannot be converted to java.util.List<net.kyori.adventure.text.Component>
I just used Component.translatable(key, params)
well... that's a List, not a Component or TranslatableComponent which you are passing
generics, woo
Well I was trying to simplify it so I don't have to explain everything
I forget the exect answer for that, it's generally about making the bounds more applicable to what you're passing in
and doing so you left out crucial information ¯_(ツ)_/¯
Didn't think it had anything to do with it because it's just like this
make a List<Component> if you want a List<Component>
the toList collector accepts type arguments
thanks, will try to do that
TL;DR: Kezz's answer is valid, and I just show you another approach so you can better understand your problem.
If all you need is a "list of something that are components" (not a "list of components", read carefully), you may want to use a List<? extends Component>
The main difference is that you cannot add a Component to a List<? extends Component> (because the list might not accept it, if it's a list of translatable components, it cannot handle text components), but you'll be able to read Components from the list. Depending on your use case, it may suit well or not.
And looking at your code, .toList() will definitely return a list of whatever values are in the stream, not a list of a parent type. Furthermore, the returned list is immutable, so the concerns about not being able to add components does not seem to apply. Thus, changing the type of your paginatedList field to List<? extends Component> would be a viable answer, but guessing your broader context, it seems equally correct to refine the type of the list returned by the .toList() method as Kezz suggested 🙂
Hey how can I check for certain texts (I have a list of strings) in a component?
What's the xy?
there's a few solutions, what one is the best depends on why you want to do this
I want to block certain words in a chat msg
You can use Component#replaceText
I want it to block the msg - cancel the sending
or yeah I could replace it with ***
Then assumimg this is simple user input, you can plain text it and use normal string searching
how can i clone a component?
You don't need to, they're immutable
oh, so i can just pass them as i wish without having to worry about the original one being modified?
That's the advantage of immutability, yes
[14:50:55 INFO]: TextComponentImpl{content="", style=StyleImpl{obfuscated=not_set, bold=not_set, strikethrough=not_set, underlined=not_set, italic=not_set, color=null, shadowColor=null, clickEvent=null, hoverEvent=null, insertion=null, font=null}, children=[TextComponentImpl{content="yay", style=StyleImpl{obfuscated=not_set, bold=not_set, strikethrough=not_set, underlined=not_set, italic=not_set, color=null, shadowColor=null, clickEvent=null, hoverEvent=null, insertion=null, font=KeyImpl{namespace="ult_effects", value="font_x0.5_y0.4"}}, children=[]}, TranslatableComponentImpl{key="space.17", arguments=[], fallback=null, style=StyleImpl{obfuscated=not_set, bold=not_set, strikethrough=not_set, underlined=not_set, italic=not_set, color=null, shadowColor=null, clickEvent=null, hoverEvent=null, insertion=null, font=null}, children=[]}]}```
I'm using packetevents to register a listener for when action bars are sent and get their contents. How would I then send this as an actionbar again.. I know how to get this but I am unable to convert it into a text component (i use skript which is why the type is probably not the same). So it is possible if someone could send the java way to do this and Ill set it up using sk-reflect (java in skript). I just need to convert the stuff it gives me into a text component that I can use
@fathom mulch do u know abt this btw
mhh
i do love "mhh" lol
To fix this you need to convert it to skbee's component wrapper class, that'll fix the issue
import:
com.shanebeestudios.skbee.api.wrapper.ComponentWrapper
function asSkBeeComponent(component: object) :: textcomponent:
return ComponentWrapper.fromComponent({_component})
# some trigger
send action bar component asSkBeeComponent({_yourRetrievedComponent) to player```
I know this isnt exactly on topic but I wanted to clear it up for him 😄
from the looks of it you do have the component
its not letting me.. since i kinda need to use it like i have above
does anyone know how to make an audience that I can put in all of my modules?
https://i.e-z.host/cttswgol.png
showed right here
can you explain more what you want
I think they're trying to make their own adapter? But that would be a per-module thing and at that point you may as well just not do it
You could make an interface they could each implement but then, that's just Audience
yeah, it's just Audience
ForwardingAudience might be even better
@static ridge, this should be a more suiting channel.
You can use the LegacyComponentSerializer to convert you legacy string into a component and then MiniMessage#miniMessage#serialize to convert the component into minimessage format.
I need to specify this value in Velocity motd
ah, only old configs (versions below 2.6) will be converted but looks like this website can do it as well:
https://miniconverter.loopbreak.me/
thank
&m - <st>text</st>
i have to say it's wild that webstire stole the screenshot i took for minimessage viewer 
so funny
a global player/commandsender object
across my modules
As they already said, it's Audience
ok.
do I make it an abstract class?
what
Audience already is this abstract form of player/command sender you're looking for
you don't get it
I want to have a player object I can use in all of my modules
i don't see how that bit is related to adventure, but for the adventure side of things, just depend on adventure-api in your common module, and from your platform code pass the respective Audience object; you can write your own common Player interface you implement in each platform too, sure, which you can also implement ForwardingAudience to make them an audience
so I make it just a forwarding audience instead of an audience?
yes, so you don't have to implement all the Audience methods, simply provide an Audience instance the methods will be proxied to
https://i.e-z.host/u7z9c1w7.png would I keep all of the super methods?
you don't need to implement any of the methods in Audience
there is a single abstract method from ForwardingAudience you have to implement
explain
ForwardingAudience has a single method you have to implement
audience or audiences, something like that
https://i.e-z.host/asm0mree.png yep there
and I do what with this?
I mean, you're going to have to implement a small layer of abstraction to deal with platform specifics
but, nothing prevents you slapping an abstract impl of your common class or whatever inside of your common module and initialising it with the per platform types in some manner
yeah that was what I was going to do
would I make that a forwarding audience too?
You can make your shared class a ForwardingAudience if that suits your needs
alright
This is generally a design question which is more on the needs of your app, using a ForwardingAudience comes with some pros and cons
Please send logs to mclo.gs and other large files to pastes.dev.
@sand drift https://pastes.dev/jzuk2Zn5GJ
you don't implement all of the methods on there
As pointed out earlier, you only need to implement the audiences() mnethod
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.audience.ForwardingAudience;
import org.jetbrains.annotations.NotNull;
public abstract class AscAudience implements ForwardingAudience {
@Override public abstract @NotNull Iterable<? extends Audience> audiences();
}
```good?
There's no point in having the signature of the abstract method when it's the exact same that the original one
.
wanna do it like this
there is no point in defining that method, it literally already exists, you'd want to declare it inside of your actual platform specific implementation of that class
That code is strictly equivalent to:
package net.hyperiongames.ascCommon;
public abstract class AscAudience implements ForwardingAudience {}
is that all I do then?
you would be served well by brushing up on java inheritance
The existence of that class can be justified if you need to put other methods inside, as it may sounded in your original messages
But if you do not plan to add any additional method, then the class is useless and you can completely replace its usages by Audience, like we all initially suggested
I'm trying to make a staff chat plugin with a good shared system so I can create modules on platforms easily
like how lp has everything in its common module
I mean, you're talking about a non trivial design pattern and yet seem to be struggling with some relatively basic concept
because I don't make stuff in modules alot and use audiences
your platform specific things need to deal with creating Audiences, and then your common module just deals with passing that around
Audiences have nothing to do with designing a software
in your per platform impls you basically just do something like new CommonPlatformMagicImpl(this) where this is the thing that deals with the native platform hooks, i.e. hooking into event stuff and actually getting your Audiences from the platform
It can be an extra difficulty when you don't know them, and we're here to help you with that, but in your case the problem is deeper, far beyond that "I don't know how to use Audiences"
cause I don't use them ever
There's nothing special about them, there is a basic Java interface Audience, which define methods to send/show stuff. And, for the sake of simplicity, another interface ForwardingAudience, designed to ease the implementation of the former interface. It provides a valid implementation for all methods, all relying on a single one, that you'd have to implement in your final class (to provide the target Audiences to whom forward things)
But as you can see, my answer does not provide you a solution to your problem, because that issue you are facing is far more complicated than "using audiences" (what I explained)
I mean, the biggest complexity isn't Audience in and of itself, your biggest issue is going to be designing something that allows you to generally not care what Audience is implemented by; Your biggest issue is going to be the wider picture, of dealing with the per platform abstractions that you're going to need; You would generally just get your Audience from the platform impl
And, as electroniccat pointed out (and I have the same feeling), it looks like you are struggling with basic concepts of Java programming, and software design. I can only suggest you training more on "toy" projects to learn before working on a proper project
Whenever I use .appendNewline(), I get this icon. How can I fix this?
you can't have a newline there
newlines dont work in lores
😔
Is it a bad idea to implement Title?
hello disappearing messages
I have an enum that for one if its fields has a title. Sometimes I need the description or component name of that enum value and it'd be kinda easier to just access via title methods
Anyways I just access from the static title initialized for each enum value so its not a problem anymorw
Yeah just make the enum have a title property
When serializing a Component to MiniMessage is it possible to disable/skip its escaping Tags and Backslashes of the component's content/text somehow? Maybe overriding a method or something
are you using the plain text serializer? iirc that shouldnt be escaping them
well yes.. but then i don't get the minimessage tags
for colors and shadows and etc..
i have been using my own parser for a while now
from json to minimessage
and from Component to MiniMessage
but i cant keep maintaining it forever to keep up with all the new features ig
even though its really simple-made :/
No, this isn't possible - the serialiser produces the same output after a round-trip
I'd suggest that you have a design issue, maybe you could explain a bit more about why you need to do this and then we can give you a better solution
inb4 mixing legacy and MM
(replacing \< with < works)
Except for then ruining any text that happens to have that combo. It's a silly idea to start with.
Hello, could you please tell me if you know how to make the Italy format not applied by default to text, but still work when tags are used?
Is it possible to convert an Component to a String while keeping all the tags that are provided for the component?
The PlainTextComponentSerializer seems to remove all tags in the outputted string.
pretty sure you can't, because components can be created with different ways not just MM
Doesn't all ways return a Component at the end? deserialize from MM returns a Component, and Component.text(...) also returns a Component.
And there is no way to get the thing you've inputted from the component? (I don't need the exact thing inputted, but a string that you could in theory input into a MM deserialize again with the same result)
MiniMessage#serialize(Component)
Oh, thank you. Didn't thought it was that simple. 😄
@fathom mulch please do not misuse the help channels for jokes about spelling errors
Noted, my apologies
private static Component[] generateFeaturedCache() {
List<Component> gradients = new ArrayList<>();
BigDecimal transition = new BigDecimal("1");
BigDecimal add = new BigDecimal("0.025");
while (transition.doubleValue() >= -1) {
gradients.add(MINI_MESSAGE.deserialize("<gradient:#C85D5D:#D2855B:#D7BF66:#70B88A:#639AC2:#6C6BB2:" +
"#9C6DBB:" + transition.toPlainString() + "><b>\uD83C\uDF1F FEATURED \uD83C\uDF1F"));
transition = transition.subtract(add);
}
return gradients.toArray(new Component[0]);
}
Why does this jolt once it hits the end? I run it by going from the 1st element of this array to the end then immediately back to the 1st. shouldn't the gradients from value -1 to 1 and then -1 to 1 again be consistent?
Can you make a second video where you also include current transition in the text?
sure
sorry about the background noise
Would it be possible to make these classes public? I'd like to change getMiniMessageString method in MiniMessageTranslator. I need my own MiniMessageTranslator class because I want to integrate Fluent and I need args in getMiniMessageString for messages.
No, they are an implementation detail. Why do you need them public? I don't understand why integrating fluent would require you to have those classes public, can you explain a bit more about your use case?
Hm, it should be smooth yeah :/ It's possible it's just a bug in our code, everything you've got looks fine. Could you open an issue, or even better a PR to fix?
String format(@NotNull String messageID, @NotNull Map<String, ?> args)
I need args to format message in FluentBundle. getMiniMessageString accepts only key and locale.
Message varies depending on arguments
I need to change translate method to get messages by key and args.
It sounds like you're trying to mix two different text formats which is obviously going to be a problem. You do know we already have a ChoiceFormat tag right? https://docs.advntr.dev/minimessage/dynamic-replacements.html#insert-a-choice
You're right. ChoiceFormat is good enough for me. Thanks.
🫡
Does adventure have a Parser which can parse a Component into a BaseComponen from md_5.bungee?
Somewhere in adventure-platform yes
Although we obviously don't recommend using bungeechat
Backwards compatibility
The BungeeCordComponentSerializer allows you to convert between Adventure Components and the native BungeeCord chat component API and back. This can be used when native platform support is unavailable. The serializer is available in the adventure-platform-text-serializer-bungeecord artifact.
Yeah of course, I am no fan of it either, but the plugin I am working on still has legacy support..
hmmm.... so I did some testing and when it goes past 0 it flip flops to the other side. I verified this by testing (changing from 0 as my lower bound to -0.05.
this video is with it at -0.05
Yeah it should be smooth :/
Terribly sorry for such basic questions, but what is the proper way of returning the components String / actual message?
Do I need to use a serializer for that or does Component feature a way of doing this
Something like this maybe, not sure what PlainTextComponentSerializer does
so you need just plain text?
if so then what you are doing is correct
No, I need the colored string
I guess I need to add the BungeeSerializer or something like that
j
do you need the legacy tags?
Yes
Oh, thanks. I'll try that! <3
Can I put argument for choice in a message without code?
It's sad
I mean, how would you choose on something that doesn't exist :')
why do you have to strip children in modifying tag? whats the benefit?
of this design particulary
you would either have to strip them or we'd strip them for you
the former is probably a bit more sensible, esp considering a lot of modifying tags completely recreate a brand new component
are there any usecases where stripping children is not necessary? jut curious
can't think of any off the top of my head
How would they?
Components are immutable
as in parameter.color(RED) for example
getting a new version of the original parameter component
Oh yes you mean "create a new component FROM the original one" vs "create a new component from scratch"
ye
how can i get the Audience viewer that contains all online player in the server
that would just be the Server
depends on the platform, but you can get all the individual audiences into a list or something and pass them into Audience.audience
e.g. Bukkit#getServer
that should work
is BossBar thread-safe?
i want to offload those code into async because it is getting data from the db
no, unless explicitly noted one should assume nothing is
I am trying to get a 1.21.1 mod to work with the adventure platform, the mod uses arch to support both fabric and neoforge
common -> modCompileOnly("net.kyori:adventure-platform-mod-shared-fabric-repack:6.0.0")
fabric -> modCompileOnly("net.kyori:adventure-platform-fabric:6.0.0")
neoforge -> modCompileOnlyApi("net.kyori:adventure-platform-neoforge:6.0.0")
but the adventure-platform-fabric:6.0.0 is missing?
read the release notes
I'm using MiniMessageTranslationStore with ResourceBundles, everything works fine except BossBar's translatable component arguments do not update
What do you mean by "update"? And what platform are you using?
progress updates, the name doesn't though
when I use GlobalTranslator.translator().translate() on that translatable component it works properly
I'm using latest paper 1.21.4
yes, I'm calling it every second to update progress and name. Progress updates properly, the name doesn't.
I see, there's a check on paper to see if the name component equals the old one before it updates the client
This check is done before translation, meaning technically you have the same component
is this checked only for boss bars?
chat messages work fine
with the same usage of arguments
there is no "old version of a chat message"
I don't think it does, I'm half tempted to just remove the check
The alternative of "checking against the translator to see if the component has changed for any listener" is a bit boring
and i don't think we should really care too much about it in this case
typo, was fixed in later release
alright
For now, just send some random argument or something to make it "think" it's a new component
Eventually I'll get this merged https://github.com/KyoriPowered/adventure/pull/1230
Does the (ampersand) LegacyComponentSerializer support unprefixed hex colors? I'm making a placeholder expansion where I need to parse stupid legacy that has the ampersand format &c in addition to a RGB format of #rrggbb. Or do I just String#replace("#", "&#")?
I tried doing
LegacyComponentSerializer.builder()
.character('&')
.hexColors()
.hexCharacter('#')
.build();
but the .character('&') seems to apply to both legacy and hex codes
We do not support that format
Figured, thanks :p
Are nested translations supported through minimessagetranslator?
Something like
Component.translatable("test.test", Argument.translatable("another.translatable"));
And so on..
I don't think they are, I think there's an issue open if you want to submit a PR
currently its not supported. you would need to implement that yourself
Well the new support for MM in translations sounds promising, but the implementation is a bit not scalable at all (Needs full rewrite of MM translation related classes in order to scale, and even that, it would not be enough).
I spent half an hour trying to scale the functionality of MiniMessageTranslator by making a new one that extends it, but everything is tied to MiniMessageTranslationArgument<?>, which is a protected class, tho the implementation of MiniMessageTranslator relies completely on it and its #data() method.
I think I have to fork adventure in order to extend it, even tho the problem is a class being protected, though MiniMessageTranslationArgument should have been interface-d with something like ComponentHolder or something, or am I missing something to access the component that it holds?
this is the part of MiniMessageTranslator I wanted to extend functionality by adding support for TranslatableComponent
what do you mean by "scale"
what are you trying to do that you can't actually do now
I already answered the question
"extend functionality by adding support for TranslatableComponent"
what functionality
Making TranslatableComponent arguments translated when the main component is translated and mm parsed
if you give me a good idea about what functionality you're missing, i can either point you in the right direction or go and write some code for adventure to make it possible for you
that's just a bug, we're already looking to get a bug fix release out with this pr that fixes it https://github.com/KyoriPowered/adventure/pull/1226
feel free to give it a test and see if it works for you - dropping a comment letting us know it works is helpful!
Sounds promising! And actually thanks for helping out
🫡
I don't think the functionality added by this user is anything near of what the meaning of translatable component is
Look here (his code)
Component.translatable(
"<name> is <thing>!",
Argument.component("name", Component.translatable("<arg:0>", Component.text("Kezz"))),
Argument.component("thing", Component.translatable("<arg:0>", Component.text("cool")))
)
Since when we put plain text in key part?
That PR makes translatable component arguments translated when the main component is translated which is what you specifically asked for
That test is just an example, we have different unit tests to ensure the translation key -> mm strings work, so we don't need to test that as well here
I see!
I saw their first test unit and thought they broke the principle of translatable components, however the other test unit is pretty perfect and that's the intended behavior
But if you deep look in the test units, they put plain mm text in key argument of the translatable component
However, as you said you would try to fix it if you can, I would be glad if you did!
adventure is perfect but it misses this small detail, if you can fix it, then it would be much appreciated
Didn't see this message, IG I will try out
yeah it's def high on my todo list, i wanna try and get out a bugfix patch this week
Thanks, and if you can, please remove/(make public)/(interface for #data()) the MiniMessageTranslationArgument wrapper class since it makes it impossible to access the actual data passed in the argument when trying to wrap the MiniMessageTranslator or in general extending MiniMessageTranslator
I thought on using Reflection to access passed data in the argument 😢
It ties the Argument class to a final class MiniMessageTranslationArgument
if you are only extending MiniMessageTranslator, you only ever see a String and a Locale, at no point in time is MMTA exposed?
what are you doing?
No, I'm overriding the translate function, which needs to access the argument data, in which the MiniMessageTranslationArgument makes it impossible to do so since it's a protected final class not accessible at all outside adventure
I don't know why you're doing that though
If you give an example of what you need that for I can help you out further
atm we're in xy problem territory a bit
I am very confused here, you say you are making a class that extends MiniMessageTranslator, yes? the translate methods are final, you can't override them, there is one abstract method that just gives you a String,Locale and returns a String
I stated above I wanted to extend the translation to support translatable components, for now that's my proble which I trust you would fix in the next patch, but for future, if I wanted to extend the MMT (by making a new translator class) to add support for let's say custom component or anything else, it's not possible at all, my translator would break down the functionality of native Argument class since I can't add support for it because all data is wrapped under MMTA which is a final class, right? or am I missing anything?
I completely understand and sorry if it appears so
You need to take a step back a bit and explain why you want this functionality
What specific feature or function is not possible with the current system that you would like to achieve?
not how you want to achieve it, but what it is you want to achieve
By making a new translator and copying the content of MMT, sorry I missed the final part
For now, trying to add TranslatableComponent support is impossible for me if trynig to make a new Translator that supports the Argument class and TranslatableComponent
unless using Reflection to access the value field of MMTA
The implementation aspects of MMT are not considered API; They want to know the why of what you're doing so they can actually work on a maintainable solution or offer advice which isn't just "start exposing stuff publically"
Okay thanks for pointing that out, I just want to make my new MMT with translatable components support and Argument class support, point me out on how to do that in the current version of adventure?
You would likely need to fork the serialiser and maintain your own tweaks in there and shade it into your plugin, or wait for the next release where native support is added
the big question here is why do you need to do that and can't use a real MMT?
if it's that bug you mentioned, it's gonna get fixed soon, so there wouldn't be a reason to expose that stuff anyway
I thought about that solution, but first I thought I can do that by just adding a class in my plugin and use it as a translator. So everytime I have a feature to add or manipulate the translation, I need to fork it right? In conclusion, the API has nothing to offer when it comes to accessing arguments data?
A bit strange actually since every aspect of adventure is scalable (Honestly a big W) but when it comes to this small part it's not, as you mentioned, it's not considered to be API.
However, thanks for help! I really appreciated that 😅, and sorry if it appeared to be xy problem or being annoying
Perfect! I wish it gets fixed soon, that would be a new experience of i18n and l10n for me 😄
What feature do you want to add? The whole API for this area was designed so you can do basically everything you could if you were using a MiniMessage instance raw
Nevermind, if the TranslatableComponent translation support would be added in the next patch, then I wouldn't need anything, I just overwhelmed a bit when I wasn't being able to do it, but if you or the team are planning to do it, then I don't need any extra features!
I guess for now I will go with a delegate pattern approach (Didn't try yet) to get it working, and when the next patch get released I will remove my solution and stick with the standard release
Got it working by delegating the MMT 💀
Tried with named arguments, passed arguments, and translatable tag, all worked fine!
I guess I will stick with this until the new release
Thats more or less exactly what i did a few month ago 
if you'd have just made that into a pr a few months ago we couldve merged it by now lol
anyway, should have an adventure release out this week with a fix
well back there i remember an discussion if this the best way to translate recursively
and i used your newly named arguments that were still in development
fr
Is there any way to replace a word or phrase with a component, or is the best way to just searialize and desearalize it from minimessage
Take a look at Component#replaceText(TextReplacementConfig)
fun loadTranslations(name: String) {
val resource = plugin.getResource("messages_$name.properties")
val bundle = PropertyResourceBundle(resource)
val translationRegistry = MiniMessageTranslationStore.create(Key.key(name)).apply {
registerAll(Locale.US, bundle, true)
}
GlobalTranslator.translator().addSource(translationRegistry)
}```
GlobalTranslator.translator().translate(translatable(key, *args), Locale.US) force translated components are working fine
is that on Paper, Velocity or something else?
looks like its missing the client language. That gets sent with the client options, and the client might simply not have sent it yet
I send component on paper server behind velocity proxy
checklocale command I used just prints Player#locale so I guess it's set?
Update your paper server
actually the thing is I have access to a Component, and im trying to override it after parsing it with my placeholders and tags
and i cant really access it any other way before turning it into a component
So yes it's technically a design issue
but again, hands are tied
thats why my only option is to edit the serializer itself
maybe when this is planned it could be added as an option
https://github.com/KyoriPowered/adventure/blob/main/4/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/MiniMessageSerializer.java#L47
Why do you have a component to begin with?
you will probably not like this, but it's because its PacketEvents API (yes packet interception.. i know not ideal but it is what it is)
That's how you have a component, but I'm interested in why - what specific packet are you intercepting and why? If you start with the design it's easier to go from there
have you ever heard of the plugin ItsMyConfig? it's been around for a while now
we intercept chat messages sent to the player by plugins and check if it starts with a specific prefix and then we modify it based on that
Okay, so why do you need to start with a component?
Player's cant chat components, so just listen to the chat event/packet very early and turn it into a plain text string, then MiniMessage it and turn it back into a component again
its not a player message, its a plugin message
like an essentialsx message to a player
so its usually a component
ah right
well the same concept applies - surely you're not mixing and matching multiple forms of colouring so why can't you just plaintext and go from there?
because the value returned from the packet using PacketEvents and ProtocolLib is already a component
you can turn a component into plain text using the PlainTextComponentSerializer
then you lose all colors, decorations and shadows
Cant you just do prefix.append(yourIntercepterComponent) ?
no? i don't add a prefix, i actually remove the prefix and edit the message accordingly
$<red>Hello <custom-placeholder> -> <red>Hello Return of Custom Placeholder
I'm confused, where is the other colour happening here? You're saying that when this prefix exists you are parsing the string as MiniMessage, why do you care about the existing styling? Surely you can see there's a bit of a design conflict here
because thats what people want lol
they don't want to lose existing colors and add support to their multifunctional placeholders
these placeholders could return texts, could create a bossbar for seconds, title, subtitle, (the thing above the level barbi forgot it's name), and of course the normal plain returned text
so yeah its technically essential to keep previous colors
i wonder if i copying the class MiniMessage serializer and modifying it for now would work
yeesh i mean this is a pretty weird situation you've got tbh
yep
okay so what if you substring-d after the prefix and then just treated that as plain text
"split" the component at the prefix, leave everything before as is and then handle the latter parts?
i doubt the possibility of this
plus it needs to be minimessage to respond to Tag class anyways
yep its not really possible
why wouldn't that be possible?
tbh atp i think your design is so bad that you're on your own unfortunately
wouldnt copying this class and removing this specific line just work
im not sure, it's been a while since ive poked about in the parser internals
why do line breaks <br> show up like this
You can't have line breaks in lore
right
thank you
then is there a built in way to copy the remaining open tags of a minimessage over to another?
so if i have
<red>a <blue>b</blue>
and
hello
hello would show up red
No, there is no magical built in util for tree splitting
alright, thank you
can you show the full code? are you sure that translation string is in your translation store?
is there some way to have MiniMessage.miniMessage().serialize also serialize new lines?
what do you mean? MiniMessage doesn't care about newlines they're just a character
I mean there is the <newline> tag, and I'd like \n be serialized to <newline>
i mean you could just replace it after the fact
Probably not because \n is text and not a tag
doesnt matter we can rountrip with virtual components
i just dont know why we would bother here
just wanted to know if there was an built in way, I guess I'll just replace it by hand
apparently it will serialize <br> if the component it's visiting is equal to Component.newline()
I guess I'll just manually do .replace("\n","<newline>")
if you mean you have a \n in the middle of a random component a lot of advice is to don't
well I deserialize text<newline>text that is deserialized to text\ntext..
to be more specific <shadow:#4040403F>[#545454](/guild/289587909051416579/channel/545454/)Goddess Of<newline>The Hearth get deserlialized to that
(just to add context, this is text on a text display)
tho I am using this weird thing to get the players chat message from the async chat event...
MiniMessage.miniMessage().deserialize(PlainTextComponentSerializer.plainText().serialize(event.message()))
it's fine
wait.. I can just get the signedMessage.message() which returns a string?
well anyways, so thats why there is a newline in my component
what is the usecase for Nbt Storage components?
Hey, I'm trying to recolor a join message when players are in a team. With the old system I'd manually scan the string to remove formatting codes, with components not so sure what to do, just calling color() doesn't work. I could use a plain text seralisier and create a new component but that seems inelegant, any advice?
you can theoretically just adjust the color of all parts of the component
after adding a player to a team with a color...
e.joinMessage(e.joinMessage().color(NamedTextColor.COLOR)
no longer works
I feel like I should be able to do that yeah, but I can't figure out how
I could perhaps loop through child components and append a recolored version to a new component builder?
see mapChildrenDeep
you should refactor it 😭 why does it require a BuildableComponent yet Component itself is not BuildableComponent
feel free to open an issue or pr instead of just mindlessly complaining
okaay
When using the Gson serializer... is it possible for it not to add useless values?
like there was never an italic option for example in a component, but it automatically adds italic: false
same for bold, etc..
or at least ignore it when deserializing.. so it doesn't explicitly set these to false in the component itself
they aren't useless, the default state for styles is unset, which is mechanically different from false
it doesn't add those values without you setting them, can you show some code?
i need to run a debug to show it @-@
its 2am imma give it tmrw
but i figured it does that since MM that's gotten from gson serializer components starts doing stuff like:
<!italic><!underlined><!strikethrough><!bold><!obfuscated><dark_gray>-------</dark_gray>
even though it's just started with <dark_gray>-------</dark_gray>
i was messing with code :p
In the dynamic replacements section of the wiki it says something abb ChoiceFormat patterns but i cant find anything on how that pattern works on the wiki
Hey, hi! Can i get a list of all sub-sounds under a sound with AdventureAPI? i just need the original sound list for minecraft.
what's the difference between the messageformat translationstore and component one?
also, what I would need to put as the key, mypluginname:translations?
TranslationStore.messageFormat(Key.key(""))
one stores MessageFormat objects, the other stores Component objects
sure that would work
See the Minecraft wiki
No I'm asking if I can do this with the Adventure API or maybe NMS methods.
You can't do it with adventure
I am sure this must be obvious somewhere and I just cant find it, but does anybody know how to add an empty line in a component.
comp.append(Component.newline())
thank you :))
and in which case i should use one or another?
so it just needs to be "something". will it be something i need to use again? maybe referencing elsewhere idk
you use it to remove the source at a later date if needed
depends what you want, what format are your translation strings in?
Hey, I use the following placeholder for a variable in a MiniMessage.
Formatter.number("example-double", my-double)
I noticed that for integers if I display them with <example-integer:'en-US'>, they get a separator for each thousand based on the language. (so 1000 -> 1,000)
When I do the same thing with doubles, but with the following line, i only get the double with the decimal separator and no thousand separator.
<example-double:'en-US':'0.##'>
How can I make it so I've both separators for the double as well? (so e.g. 1500.514 -> 1,500.51)
Ah, alright. Thank you.
Can I get the original volume and pitch of a minecraft sound with paper or adventure api?
Not with adventure
how to add support legacy mini message format??
Legacy or MiniMessage?
legacy support format in mini message
you don't
uhhhhh
Maybe he meant in Adventure
yes thats what i mean
LegacyComponentSerializer
where to add it?
not sure why you'd say MiniMessage when you mean adventure
wherever you want to serialize or deserialize a Component from a String
how
what do you mean how? what do you currently have written?
i dont know actually where to add, can you give me tutorial?
no
we aren't going to spoonfeed you here, we will assist you in solving your own problems though
damn
are Components immutable? I'm trying to create an immutable snapshot version of a class which contains Components as fields
Yes they are
Question:
when using the click:run_command:samplesample</click> in a book -> successfully closes the book and executes the command.
when using the click:suggest_command:samplesample</click> in a book -> unsuccessfully closes the book and doesn't suggest the command in the command line.
So I deduced that either I'm doing something wrong, or there is a bug, or it isn't a feature.
do books support the suggest_command click action?
good question, imma check, brb
"suggest_command": Opens chat and fills in the specified text or command. If a chat message was already being composed, it is overwritten. This does not work in books.[1]
From the MC Wiki
o damn
Is it safe to compare two components to ensure they are the same?
I want to add a test to my plugin to ensure that the Component parser util I have properly converts provided MiniMessage Strings to the right components.
Different components can have the same render, so it depends on how you define "same"
I would suspect JSON->Component is always the same but I don't think there is any promise MM->Component is the same from version to version
And heck, Component->JSON could potentially change version to version, perhaps by adding in some kind of optimization pass
So long as it renders the same way
I'm not sure if there is anything in there that would get you different run to run results for MM->Component on a given adventure version so as long as you're willing to debug and update your tests if something changes with a new version you might be okay?
Okay....
Well, I would want to do simple ComponentParser.parse("<yellow>Hello <green>World!") equals Component.text(...) checks here.
The MiniMessage instance I use in the ComponentParser is just the norma minimessage() one you can get,
I mean mini message has its own unit tests, so I would assume that testing simple stuff like that should be somewhat okay™️?
Why do you want to test MiniMessage? Especially since you just said you were using the default instance, so I guess you're not using any custom tag resolver that you would be wanting to test
(I might even argue about why using an helper method for such a basic MiniMessage#deserialize(String) call, but that's another debate)
There is no real long term garauntee on the stability of components
sorry for the late response bruh, what you mean as format?
like, plain text? message format? json? minimessage? etc
i'm trying to implement resource bundles with properties files
and maybe use the minimessage translator (even if i still don't understand how to implement it)
Give these a read over and let us know if youve got any questions!!
to use the minimessage translator, i must implement it myself, there's not translation store right?
There is a translation store for minimessage
oh right, didn't see it
is there some way to serialize to minimsg string without adding \ before every non previously serialized tag?
as a simple example:
have a Component.text("<gold>text")
-> serlialize as minimsg string -> deserialize -> get a golden colored text
Nope - where are you getting the component from? there is likely a better solution
well I want to support both legacyampersand and minimessage, therefore wanted to just parse as legacy and then deserialize to minimsg and then parse again but that adds \ before all previous minimessage tags
Yeah we don't support that unfortunately
It's best to stick with one format consistently rather that mix multiple
Has anyone experience with the following error using mockbukkit, or should i just dig through my build.gradle files?
Expected to find one service interface net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer$Provider, found multiple [in thread "Test worker"]
You'd have to ask mockbukkit unfortunately - that error just displays if you've got multiple classes trying to be a provider for a serializer
which doesn't happen in "normal" paper
I have never done anything like this before - if I have a Key that represents a BlockType, ItemType or EntityType, can I translate that to a locale? or do I need more than just the key
basically instead of showing a player "diamond_block", I would show them "Diamond Block"
BlockType, ItemType and EntityType implement Translatable, so if possible you can just pass them into Component.translatable(). You could also look at the implementation of the Translatable#translationKey method to get an idea how the translation keys are created, but that would require you knowing which of the 3 your key belongs to
That is usually decided by the platform, for example when you send a translatable component to a player using Player#sendMessage the component gets passed through the global translator using the players locale
Oh but for translations like BlockType, ItemType and EntityType it gets rendered on the client using the client locale, I think
what's the best approach to store translations?
If you're talking about server side translations the most common approach is probably using ResourceBundle. There is an exampe in the paper docs on how to use it.
But I also recommend reading the adventure docs on server side translations
so .properties files?
yep
that would be the best practice right?
you're gonna get the same answer i gave you yesterday tho, go read the docs i linked :p
yep
now i have a different question lol
how I can make a resource bundle editable by the user? creating it first in the plugin resources and then copy the files in the plugin folder?
sure that's one way
and what could be some other ways?
i discovered that you cannot load all the files in a resource bundle
you must load them per locale
not sure if this is the appropriate channel, but, is there a way to reliably get a translatable from a Statistic? doing Component.translatable("stat." + statisticKey.namespace() + "." + statisticKey.value()) seems to work for some of them, but not all. looking at the lang file, the translation keys don't all match up with the statistic key's value, so I think that's the problem. not really sure what to do
do I need to make my own map of statistics and their translation keys?
probably best to ask in #paper-dev
could have, idk, an override file or something?
like, the user creates a file and writes in it only the strings that he want to edit?
sure
you know some workaround for this?
the "big" issue is that i can't iterate over files in the classpath resources
Using adventure API components, can we make text within a book clickable/hoverable?
So, when a user clicks on a text component, we can run code server side?
Books can run a command (but not suggest one) so you can have a command handler to do that
I see.
Or use the callback system to avoid needing your own command, I know that should at least work for Paper
So, I could theoretically, have like 10 commands per page in a book?
Sure
the user would just click on each line or whatever
Awesome
Honeslty coming back to plugin dev after 10 years
this is amazing
Depending on your timeline and what you're making, also take a look at the new (coming soon to 1.21.6) dialog stuff. https://minecraft.wiki/w/Dialog
ahhh yes
i abandoned my idea with the client side commands
didnt really fit my server
but that is very cool addition, thanks for letting me know, that would work for me
How can I minimize the calling for MiniMessage.miniMessage().deserialize()? -> I mean, I call a lot of times for deserialize(), and it shows up at the spark report.
Just asking if there is a way to minimize the memory usage for that, how to use it efficiently
would you mind sharing the spark report that you're looking at?
But it can only be done on a per-usage basis, because if you have some tags those values depend on context or time, it wouldn't work, or at least cause undersired side effects
And are you sure you want to reduce memory usage and not execution time?
yes
execution is when players send nessages
Yeah good idea
Maybe if you could share the spark yes, and eventually some code as well, because it is a little bit surprising that you're facing performance issue on MM deserialization of player messages. Unless you nave hundreds of messages to handle every second, which I doubt (no offense)
no no its not a " performance issue " - it just shows up on the plugins tab at the spark report
not much you can do, is minimessage really bottleneck of your plugin?
ofc you can just deserialize components once if they dont got no placeholders
but not always the case, and replacingText in components may be even more expensive / just not working
is there some way to check if a component contains a specific string?
What is your final goal?
I wanna insert components into a lore where a spcific string is
so basically:
I have this lore in my config:
being-sold-lore:
- "<dark_green>Being sold at:"
- "<italic>%shops%"
- "<gray><Click for more Information>"
and I wanna replace %shops% with each %shops% component
but for that I would need to know in what lore line shops is
Make %shops% be <shops> and use a tag resolver
but i need to put multiple shops there
so pseudo code style
var loreLine = getShopIndex(lore)
var shopComponent = lore.removeAt(loreLine)
for shop in shops
lore.add(loreLine, shop.component())
You either have to do it before you deserialize to Component (so work on the raw String) or use a tag resolver to do it as a part of deserialization
hmm
<shops:1>, <shops:2>…
No need for that even
could you elaborate? I never used Tag resolvers before?
I see, I see, thank you
Could also use Component#replaceText
Still, Amaranth's answer is the better solution
Imagine using replaceText to make a placeholder system when a whole TagResolver system exists
Hello, is there in adventure something to strip hex colors from a component or a string? (Hex colors represented like &#ffffff)
This is legacy format, you could use the legacy component deserializer and plain text serializer
it also remove legacy colors codes?
unluckily I double check, I already use both but it doesn't strip it
Can you share some code plz?
is it possible to make a tag resolver that matches any tag but only changes some of them? i.e. it gets given all tags but decides in code if its this resolvers tag?
not all tags no
well, technically yeah - you can implement hasName or whatever it is
return true for all and then return null in the actual resolve method if needed
hmm, I'll just do a complex one then seems less hacky
yeah, better to use arguments when needed
what exactly is a Pointered target? what can it be? just anything?
Just tested it, and it works perfectly fine for me:
String messageWithLegacyFormatting = String.join(" ", args);
Component legacyDeserialized = LegacyComponentSerializer.legacyAmpersand().deserialize(messageWithLegacyFormatting);
String strippedLegacyFormatting = PlainTextComponentSerializer.plainText().serialize(legacyDeserialized);
Well, its something with pointers (lol), Audience extends it so in paper for example that extends down to CommandSender, Player etc
when does one use it with deserialize? what tags need it? how would I use it in a custom tag?
I don't think any of the standard tags use it. You can access it in a custom tag using Context#target
and then? how do I use the pointers it provides? or should I just cast it to my own type?
You can do both. There are some "default" ones in Identity, but its up to the platform you're using if they're actually provided in the pointered (But paper and velocity supply them, so you should probably be good).
You can also implement your own Pointered, define your own Pointer and use that. Or just instance of and cast to your own type, or a type you know implements pointered
mkay, there can not be multiple targets for a deserialization, right?
i.e. there isn't something like a PointeredCollection or something
Yeah only one target
What's happening with adventure 4.22.0, I would be very interested in it
patch releases ⚰️
i am on holiday, the patch release shall happen at some point soon
I added a TextComponent with ClickEvent.callback to a static book instance that is opened via command. Unfortunately code inside the callback is executed only once, for the first player to click it after the server starts. Is that intended? I figured I wouldn't have to create separate instance of a static book for each player
Yes that is intended - see the config for the builder for the callback
sorry, ClickCallback.Optiona
got it, thank you
I am experimenting with MM translation store and text displays, and I see this in the console (not sure if it comes from adventure or paper)
[20:23:08 INFO]: indyteo issued server command: /summon minecraft:text_display ~ ~ ~ {text:'{"translate":"test"}'}
[20:23:08 ERROR]: Display entityNot a string
[20:23:08 INFO]: [indyteo: Summoned new Text Display]
The MM translator, just in case it matters:
GlobalTranslator.translator().addSource(new MiniMessageTranslator() {
@Override
public @NotNull Key name() {
return Key.key("test");
}
@Override
protected @Nullable String getMiniMessageString(@NotNull String key, @NotNull Locale locale) {
return key.equals("test") ? "<red>Test" : null;
}
});
Aside from that, the text is correctly rendered red, so it works. Just a strange log message
That would come from mojang parsing the thing you passed into the command
And do you see anything that looks wrong in my command?
I'm on 1.21.4 (latest stable Paper release)
This server is running Paper version 1.21.4-231-ver/1.21.4@09e9afd (2025-05-19T17:59:36Z) (Implementing API version 1.21.4-R0.1-SNAPSHOT)
You are running the latest version
Previous version: 1.21.4-227-7675321 (MC: 1.21.4)
idk, mojang messed with the formats recently
Yeah I saw that, but it's for 1.21.5 iirc
double x = listBinaryTag.getFloat(0);
double y = listBinaryTag.getFloat(1);
double z = listBinaryTag.getFloat(2);
float yaw = listBinaryTag.getFloat(3, 0);
float pitch = listBinaryTag.getFloat(4, 0);
last line is erroring with an index out of bounds even though there's a default value for getFloat?
using adventure nbt
It would require a refactoring of the code since the method without a default value seems to rely on a default default value of 0. But whether it is done or not, it should be better documented, I agree
Hello, I'm trying to use the following MiniMessage :
<click:run_command:'/mycommand'><hover:show_text:'<green>Clique pour t'y téléporter'><yellow>0)</yellow>
<gray> Monde: ddd
x: 1
y: 1
z: 1</gray></hover></click>
And it displays well in game and on https://webui.advntr.dev/
However, if I put it twice instead of once, it completely breaks :
What did i do wrong ?
your show_text contains a ', so you should put a "" around it instead
Oh yeah, completely missed that, thanks for your help ! 🙂
Hey! I was wondering if there is the 1.21.5 nbt hashing implemented in adventure-nbt? I'm using it for my own mc server implementation and it would be really nice if I didn't have to write my own nbt implementation because of it 😅
Feel free to submit a PR
Hello, my server version is 1.21.4 and I use minimessage to format text. Everything works fine except for shadows. Can you help? maybe you need to add some kind of dependency to make them work, or are they included in the regular minimessage?
(using a paste site, if it's long)
sender#1342377662638850140 <- its a kotlin extension
and further away from him there is SendMessage, which immediately transfers the message to the minimessage.
Doesn't that code show you building a custom MM instance, that doens't have the shadow tags added?
I don't quite understand you.
ohhh
I think I've started to understand what you're talking about.
I added shadows, their tags are working now and renames them, but I don't see the shadows themselves in the text(
what does it look like?
are you using a vanilla 1.21.4 client?
considering shadow colors were added in 1.21.4, yes, you need at least a 1.21.4 client
thanks
Hi! I’m running a Minecraft 1.21.1 Fabric server and I’m trying to use some mods that still reference legacy Kyori Adventure classes like net.kyori.adventure.text.VirtualComponentRenderer and VirtualComponent.
I’ve tried adding the 4.9.3 versions of adventure-api, adventure-text, and adventure-text-serializer-legacy into my mods folder, along with OpenLoader and Prickle to make sure they load first — but I’m still getting ClassNotFoundExceptions for those classes when using certain commands or features from other mods.
At this point, I think something is overriding the classloader or another mod is conflicting. Would someone be willing to help me track this down or maybe build a proper jar that resolves the issue?
Thanks so much in advance 🙏
what do you mean "legacy" classes?
like, are you sure the mods you are using are even compatible with that game version?
yeah they are, up till now i’ve been using chat gpt to try and get it working. But in game using some commands gives me an error and in console it says this
[05:07:48] [Server thread/WARN]: Error loading class: net/kyori/adventure/text/VirtualComponentRenderer (java.lang.ClassNotFoundException: net/kyori/adventure/text/VirtualComponentRenderer)
[05:07:48] [Server thread/WARN]: Error loading class: net/kyori/adventure/text/VirtualComponent (java.lang.ClassNotFoundException: net/kyori/adventure/text/VirtualComponent)
so i’ve gone through download all the kyori adventure stuff trying to get it fixed
I'd recommend starting out by ignoring everything chatgpt says
virtual components were added pretty recently, I don't think they were present in 1.21.1 era adventure distributions
I'm also not sure what OpenLoader and Prickle have to do with this, just googling the mods they don't seem to interact with mod loading at all?
chat gpt suggested them to get library jars read as librarys as when I put the adventure jars into my mods folder console was showing them as non fabric mods
please think for yourself, mod descriptions are written to be read
i'm like 98% sure you have a mod designed for a newer version of minecraft installed
all the mods that give me this error are either for 1.21.1 directly or an older version like 1.20.1
Which mods are triggering the issue? It can help isolating things by taking the mod you experience issues with and running it alone on the server (well, with it + any mods it needs to run)
so its a cobblemon modpack, I have GTS downloaded and that doesnt seem to work. Impactor Economy also gives the error. Ultimate warps, I have cobblemon /hunts as well but I am unsure whether that issue is because impactor doesnt work or kyori directly. Lastly, I have pokeplushies which gives me the kyori error
(also generally mods need to be a pretty exact match with the minecraft version, newer or older usually don't work)
the only mod that it isnt exact version is pokeplushie. Which was made for 1.20.1 but I edited it tobe 1.21.1 as I have seen other servers on 1.21 with this mod working. Other than that all my mods are set for 1.21.1
I think your best route at this point is to take any mods you installed on top of the cobblemon mod pack (since presumably the base mod pack works on its own), and try and run them individually to figure out which is the mod causing the issue, and then talk to them directly
the only other thing it could be is if some mod incorrectly shades adventure without relocating
I made the modpack and I am not sure which mod would be causing the error. But as i go on some new mods continue to have the same error
do you think one mod is causing that one class to not be read correctly and thus is causing the error for all the other mods attempting to use that class?
probably
see the binary search section here
what should I do with this site?
just go as follows and eliminate mods until i magically stop getting the class error?
Mods on paper?
my server is fabric
I figured out which mod it was, it was fabric essentials so I will have to find a different mod to use, thanks for the help everyone ^-^
Can you tell me which version of adventure-api and adventure-text-minimessage support 1.16.5.
I suspect you can find it in the release notes. Failing that, check paper's archive repo for the version used in its API, that probably is it.
Hi, does the hashCode get saved when creating a text component or it gets calculated every time hashCode is used?
strictly speaking, all versions should work with 1.16, all that matters is what the platform provides
have you tried looking at the method impl?
nope I asked here first