#adventure-help

1 messages · Page 4 of 1

sweet hornet
#

Finally, TranslatableComponents, if you only use them for client-side translation, then you can't do anything about them, but if you do rely on server-side translations, you may want to resolve them, and lower their final form

#

(Which may gets trickier depending on the situation)

vivid bobcat
#

I want it mainly to lower other tags, like <lower><player_name><lower>
would <player_name> be a TextComponent?

sweet hornet
#

Tags are resolved from the most nested to the least nested, so your <lower> tag would receive whatever the <player_name> resolves to

vivid bobcat
#

how to apply my LowerTag here

sweet hornet
#

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();
vivid bobcat
sweet hornet
#

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

vivid bobcat
#

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

cloud vapor
#

heck yea

sweet hornet
#

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

vivid bobcat
sweet hornet
#

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());
vivid bobcat
#

does this make sense?

#

I missed the to lower case btw

sweet hornet
sweet hornet
vivid bobcat
#

I'll do one more test to understand it better, lets see

#

yes I think its working nice

cloud vapor
#

ive been wanting a simpler version modifying that just allows direct text modification, like a wrapper to make this easier

sweet hornet
#

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

vivid bobcat
#

I can't understand why, each char in the <rainbow> becomes a separated TextComponent?

rare sage
#

yes, so each can have its own Style with the corresponding color component

cloud vapor
#

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 ^

sweet hornet
#

No

sweet hornet
#

I had the same reaction

cloud vapor
#

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))

sweet hornet
#

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 Modifying instance 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:

oak forge
#

Does minimessage have support for translateable components with fallbacks?

sweet hornet
#

<lang_or>

#

Yes

oak forge
#

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)

sweet hornet
#

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!

robust wharf
#

It's newish

oak forge
cloud vapor
#

will get that merged 🫡

stark kiln
#

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

sweet hornet
#

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

stark kiln
#

I'm trying to do that on velocity

sweet hornet
#

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

stark kiln
#

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

marsh oar
cloud vapor
#

it's unmaintained and should probably be archived tbh

vivid bobcat
#

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

sweet hornet
#

You need to clear the children

cloud vapor
#

we really need to document that tbh

sage river
#

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

sterile star
#

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)));
sage river
sterile star
#

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

sage river
#

okay thanks

vivid bobcat
#

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?

short sparrow
#

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?

sweet hornet
hearty wren
sweet hornet
vivid bobcat
sweet hornet
#

Can you share some examples of that so I can test if I understood correctly?

vivid bobcat
#

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

sweet hornet
#

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

sweet hornet
#

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)

cloud vapor
#

did you trim the spaces from that code too? :p

sweet hornet
#

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

vivid bobcat
sweet hornet
#

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

obtuse ruin
#

is the recursive translation of an translatablecomponent still not merged?

obtuse ruin
#

because both the minimessagestore and a impl of the minimessagetranslator are giving me the key of the tcomponent instead of the translated one

cloud vapor
#

Not merged? I mean there's no PR that can be merged anyway 😅

#

It's a very complicated problem

obtuse ruin
#

what does the MiniMessageTranslationStore do wthat the old TranslationRegistry does not? Just replacing them in my impl for recursive translation breaks them somehow

cloud vapor
#

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

marsh oar
cerulean delta
#

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)?

sweet hornet
#

Do you consider {"text":"Hello","color":"red"} and {"text":"","color":"green","extra":[{"text":"Hello","color":"red"}]} to be equals?

cerulean delta
sweet hornet
#

Then, no

cerulean delta
#

Very well, is there a way to recursively remove styling from a component and its child components?

sweet hornet
#

I don't think it is recursive but you can do it yourself, with either Style#unmerge(Style) or basic removal operations

cloud vapor
#

but really you should be using PDC

#

no excuse for comparing lore/display names

cerulean delta
#

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"

sweet hornet
#

But that's not how Minecraft handles items, unfortunately

cerulean delta
#

Yup

#

Hmm, could this be resolved somehow with data packs?

#

In a roundabout way?

sweet hornet
#

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

unkempt zodiac
#

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
prisma mason
#

e.g. <font:ult_effects:%s>.formatted("myfont")

unkempt zodiac
#

ive never seen that

prisma mason
#

Java string formatting

unkempt zodiac
unkempt zodiac
#

do u know what i would need to import for that

last horizon
#

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

last horizon
#

.formatted is most likely not going to solve your problem

unkempt zodiac
#
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"```
last horizon
#

you are better of asking the addon author or in a skript forum

unkempt zodiac
#

and the addon author prob wont respond but ill try

#

its skbee that im using.. idk if u know it

last horizon
#

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

unkempt zodiac
#

am i cooked lol

last horizon
#

on one of his official support channels if there are any
^

unkempt zodiac
unkempt zodiac
hardy crest
#

One solution: Learn java/kotlin

unkempt zodiac
tawny bolt
#

yeah if you are at the point of using skript-reflect/mirror, just using Java is actually going to be easier lol

unkempt zodiac
#

But so far no one has

tawny bolt
#

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"));

icy basin
#

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.

fiery oracle
#

that's adding a custom tag, not a "color"

#

so the gradient tag will still just reference the named text color

unkempt zodiac
icy basin
#

just trying to find out if there's a proper way of doing this

tawny bolt
icy basin
#

I guess I could change the values of NamedTextColor with reflection, but that kinda sucks

unkempt zodiac
sweet hornet
vagrant vine
unkempt zodiac
grim bear
#

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

sand drift
#

I mean, components are not a suitable mechanism for doing that because names can be changed on entities, etc

grim bear
#

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

cloud vapor
#

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

grim bear
#

I see. I guess storing EntityTypes associated with deaths would be better than relying on death messages then

cloud vapor
#

store the key yeah, although even those change sometimes

grim bear
#

I was just thinking of storing the enum as a string. Key would be better?

cloud vapor
#

yep

oak hamlet
mental vineBOT
sour totem
#

try updating your paper dependency

#

it seems to rely on a snapshot version of adventure that's not available anymore

oak hamlet
#

you mean that adventure is not implemented on 1.20.1 right?

sweet hornet
#

It's 1.21.4 now (and soon 1.21.5), 1.20.1 is quite old

sand drift
#

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

cloud vapor
#

just update your paper dependency

small cloud
#

uuh whats the snbt for enchantments, morespecific how do I add an enchantments to the minimsg hover:show_item tag?

sour totem
#

you can look at the output of /paper dumpitem while holding any enchanted item to see the snbt of it

cloud vapor
#

i would never rec hand writing a show item tag if you value your sanity

small cloud
cloud vapor
#

ngl i have no clue

#

maybe uh, make a component then serialise it to a minimessage string and have a look haha

primal dome
#

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?

cloud vapor
#

nope

trail iris
#

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

midnight spire
#

adventure 4.21.0 which should be included in Velocity since last weak should support it

#

which Velocity build are you on?

trail iris
#

498

restive spruce
#

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)?

cloud vapor
#

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

shadow wyvern
#

for nbt, how to get nbt from string? and how to set things in CompoundBinaryTag or something similar?

#

nvm found out

gritty tundra
#

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.

umbral wharf
#

because thats not how placeholders work

gritty tundra
#

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));

umbral wharf
#

read the bottom part that i linked

gritty tundra
#

I am. I think my confusion is that that example is specifically for hard-coded demo above, that's why it would workd

umbral wharf
#

This tag will be <arg:index> or <argument:index>

gritty tundra
#

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

umbral wharf
#

ohhhhh

#

that part is message format so uses string replacement formatting

gritty tundra
#

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

umbral wharf
#

show how ur creating the component

gritty tundra
#

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

umbral wharf
#

afaik for mm replacements like arg:0 you'll need to use a MiniMessageTranslationStore

gritty tundra
#

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

dense veldt
#

If you're using a "normal" translation store, it would just be {0} and so on

gritty tundra
#

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

umbral wharf
#

if it would get parsed by mm normally it'll get parsed here

gritty tundra
#

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"

cloud vapor
#

hover events might not be translated tbh

#

open an issue on whatever platform you're using

gritty tundra
#

ok will do

gritty tundra
#

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"))
fiery oracle
gloomy owl
#

can I make my own audience? it wont let me import methods

wet kestrel
#

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.

gloomy owl
wet kestrel
#

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

gloomy owl
#

implement mb

pale cipher
#

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");
cloud vapor
#

<!italic>

hardy crest
#

or short <!i>

pale cipher
cloud vapor
#

yes it does, show some code pls

pale cipher
#

i am using triumph gui dependecy if it matters

cloud vapor
#

should be fine

pale cipher
# cloud vapor yes it does, show some code pls

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);

                            })
                    );

                })
last horizon
#

<reset>

cloud vapor
#

well yeah you're just resetting directly after

pale cipher
#

❤️

graceful kestrel
#

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);

https://i.imgur.com/yBOZC3C.png

dense veldt
#

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

graceful kestrel
#

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

cloud vapor
#

tbh that probs should be throwing an error

mental pollen
sterile rampart
#

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

tawny bolt
#

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

sterile rampart
#

that's already in the release notes though

cloud vapor
stable swallow
#

Does anyone have a quick an easy method to darken an entire component?

prisma mason
stable swallow
prisma mason
#

You're going to have to ask them, as I dont know where the feature they are working on's codebase is

stable swallow
#

Alright no worries Thankyou. You've already pinged them so I'm guessing they will see this message eventually

cloud vapor
#

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

stable swallow
cloud vapor
#

component or maybe component builder

#

renderer probs the easiest method tho imo

stable swallow
#

oh wow I wish i knew that existed lmao.

#

I'll check out making my own renderer. Thanks

raven parcel
raven parcel
#

After near a year of working just fine

#

I'm assuming some kyori update changes, can someone tell me exactly what happened?

cloud vapor
#

What's the input? And what update did you do?

sweet hornet
sweet hornet
wary bough
#

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.

rare sage
#

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

wary bough
#

Ahh, I see thanks for the clarification on it

gritty tundra
#

is there any way for the pagination lib to work with moonshine?

cloud vapor
#

Both libraries are effectively unsupported archived software atp

shadow wyvern
#

Why is TranslatableComponent not convertable to Component

sand drift
#

what do you mean, not convertable?

midnight spire
#

define "convertable"

shadow wyvern
#

Oh yeah should've phrased it a little bit better what was I even saying

sand drift
#

You're not trying to mix and match some 3rd party component library or something?

shadow wyvern
#

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

sand drift
#

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

shadow wyvern
#

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)

midnight spire
#

well... that's a List, not a Component or TranslatableComponent which you are passing

sand drift
#

generics, woo

shadow wyvern
sand drift
#

I forget the exect answer for that, it's generally about making the bounds more applicable to what you're passing in

midnight spire
#

and doing so you left out crucial information ¯_(ツ)_/¯

shadow wyvern
cloud vapor
#

make a List<Component> if you want a List<Component>

#

the toList collector accepts type arguments

shadow wyvern
#

thanks, will try to do that

sweet hornet
#

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 🙂

tough peak
#

Hey how can I check for certain texts (I have a list of strings) in a component?

cloud vapor
#

What's the xy?

#

there's a few solutions, what one is the best depends on why you want to do this

tough peak
cloud vapor
#

You can use Component#replaceText

tough peak
#

or yeah I could replace it with ***

cloud vapor
#

Then assumimg this is simple user input, you can plain text it and use normal string searching

fathom mulch
#

how can i clone a component?

cloud vapor
#

You don't need to, they're immutable

fathom mulch
#

oh, so i can just pass them as i wish without having to worry about the original one being modified?

sweet hornet
#

That's the advantage of immutability, yes

fathom mulch
#

beautiful

#

thank you guys

unkempt zodiac
#

[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

fathom mulch
#

mhh

unkempt zodiac
fathom mulch
# unkempt zodiac ```TextComponentImpl{content="yay", style=StyleImpl{obfuscated=not_set, bold=not...

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 😄
unkempt zodiac
#

idk if the text is the component itself

#

but ill try

fathom mulch
unkempt zodiac
#

its not letting me.. since i kinda need to use it like i have above

fathom mulch
#

i think we should move channels

#

or server entirely

gloomy owl
gloomy owl
graceful kestrel
#

can you explain more what you want

quaint monolith
#

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

cloud vapor
#

yeah, it's just Audience

prisma mason
#

ForwardingAudience might be even better

whole lark
#

@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.

static ridge
whole lark
cloud vapor
#

i have to say it's wild that webstire stole the screenshot i took for minimessage viewer omegaLUL

#

so funny

gloomy owl
#

across my modules

sweet hornet
#

As they already said, it's Audience

gloomy owl
gloomy owl
rare sage
#

what

#

Audience already is this abstract form of player/command sender you're looking for

gloomy owl
#

you don't get it

#

I want to have a player object I can use in all of my modules

rare sage
#

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

gloomy owl
#

so I make it just a forwarding audience instead of an audience?

rare sage
#

yes, so you don't have to implement all the Audience methods, simply provide an Audience instance the methods will be proxied to

gloomy owl
rare sage
#

you don't need to implement any of the methods in Audience

#

there is a single abstract method from ForwardingAudience you have to implement

gloomy owl
#

explain

rare sage
#

ForwardingAudience has a single method you have to implement

gloomy owl
#

which is?

#

any of them?

rare sage
#

audience or audiences, something like that

gloomy owl
gloomy owl
sand drift
#

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

gloomy owl
#

yeah that was what I was going to do

gloomy owl
sand drift
#

You can make your shared class a ForwardingAudience if that suits your needs

gloomy owl
#

alright

sand drift
#

This is generally a design question which is more on the needs of your app, using a ForwardingAudience comes with some pros and cons

upper tinselBOT
gloomy owl
sand drift
#

you don't implement all of the methods on there

dense veldt
#

As pointed out earlier, you only need to implement the audiences() mnethod

gloomy owl
#

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?
sweet hornet
#

There's no point in having the signature of the abstract method when it's the exact same that the original one

sand drift
#

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

sweet hornet
gloomy owl
#

is that all I do then?

wicked torrent
#

you would be served well by brushing up on java inheritance

sweet hornet
#

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

gloomy owl
#

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

sand drift
#

I mean, you're talking about a non trivial design pattern and yet seem to be struggling with some relatively basic concept

gloomy owl
#

because I don't make stuff in modules alot and use audiences

sand drift
#

your platform specific things need to deal with creating Audiences, and then your common module just deals with passing that around

sweet hornet
#

Audiences have nothing to do with designing a software

sand drift
#

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

sweet hornet
#

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"

gloomy owl
#

cause I don't use them ever

sweet hornet
#

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)

sand drift
#

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

sweet hornet
#

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

safe girder
#

Whenever I use .appendNewline(), I get this icon. How can I fix this?

sand drift
#

you can't have a newline there

dense veldt
#

newlines dont work in lores

safe girder
#

😔

prisma mason
#

Is it a bad idea to implement Title?

cloud vapor
#

Yes

#

why would you do that

sterile rampart
#

hello disappearing messages

prisma mason
# cloud vapor why would you do that

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

cloud vapor
#

Yeah just make the enum have a title property

forest meteor
#

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

umbral wharf
#

are you using the plain text serializer? iirc that shouldnt be escaping them

forest meteor
#

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 :/

cloud vapor
#

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

quaint monolith
#

inb4 mixing legacy and MM

obsidian nimbus
#

(replacing \< with < works)

wet kestrel
upper galleon
#

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?

cloud vapor
alpine marlin
#

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.

prisma mason
#

pretty sure you can't, because components can be created with different ways not just MM

alpine marlin
#

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)

dense veldt
#

MiniMessage#serialize(Component)

alpine marlin
wet kestrel
#

@fathom mulch please do not misuse the help channels for jokes about spelling errors

fathom mulch
#

Noted, my apologies

knotty laurel
#
    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?

plain glade
hot mountain
#

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.

cloud vapor
cloud vapor
hot mountain
hot mountain
hot mountain
cloud vapor
hot mountain
cloud vapor
#

🫡

sly hull
#

Does adventure have a Parser which can parse a Component into a BaseComponen from md_5.bungee?

cloud vapor
#

Somewhere in adventure-platform yes

#

Although we obviously don't recommend using bungeechat

prisma mason
#

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.

sly hull
#

Yeah of course, I am no fan of it either, but the plugin I am working on still has legacy support..

knotty laurel
cloud vapor
#

Yeah it should be smooth :/

sly hull
#

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

prisma mason
#

if so then what you are doing is correct

sly hull
#

No, I need the colored string

#

I guess I need to add the BungeeSerializer or something like that

#

j

prisma mason
#

do you need the legacy tags?

sly hull
#

Yes

prisma mason
#

like &b

#

LegacyComponentSerializer then

sly hull
#

Oh, thanks. I'll try that! <3

hot mountain
cloud vapor
#

Well you need something to choose on

#

So no

hot mountain
cloud vapor
#

I mean, how would you choose on something that doesn't exist :')

obsidian nimbus
#

why do you have to strip children in modifying tag? whats the benefit?

#

of this design particulary

cloud vapor
#

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

obsidian nimbus
cloud vapor
#

can't think of any off the top of my head

obsidian nimbus
#

so that's not even used in minimessage standard tags?

#

okay

cloud vapor
#

no standard tag modifies the parameter component

#

they all make new ones iirc

sweet hornet
#

Components are immutable

cloud vapor
#

as in parameter.color(RED) for example

#

getting a new version of the original parameter component

sweet hornet
cloud vapor
#

ye

plush ginkgo
#

how can i get the Audience viewer that contains all online player in the server

tawny bolt
#

that would just be the Server

rare sage
#

depends on the platform, but you can get all the individual audiences into a list or something and pass them into Audience.audience

tawny bolt
#

e.g. Bukkit#getServer

plush ginkgo
#

im on papermc

#

im trying to remove the bossbar for all online players

rare sage
#

that should work

plush ginkgo
#

is BossBar thread-safe?

#

i want to offload those code into async because it is getting data from the db

rare sage
#

no, unless explicitly noted one should assume nothing is

plush ginkgo
#

hm, ok thanks

#

probably just do main thread task after got the data then

mild oracle
#

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?

sterile rampart
#

read the release notes

ebon talon
#

I'm using MiniMessageTranslationStore with ResourceBundles, everything works fine except BossBar's translatable component arguments do not update

cloud vapor
#

What do you mean by "update"? And what platform are you using?

ebon talon
#

progress updates, the name doesn't though

#

when I use GlobalTranslator.translator().translate() on that translatable component it works properly

cloud vapor
#

And are you regularly calling this update boss bar method?

#

Also, what platform?

ebon talon
#

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.

cloud vapor
#

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

ebon talon
#

is this checked only for boss bars?

#

chat messages work fine

#

with the same usage of arguments

cloud vapor
#

there is no "old version of a chat message"

ebon talon
#

makes sense

#

it sucks though

cloud vapor
#

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

ebon talon
#

agreed

#

also, not sure why a string literal argument is called numeric

cloud vapor
#

typo, was fixed in later release

ebon talon
#

alright

cloud vapor
#

For now, just send some random argument or something to make it "think" it's a new component

swift jetty
#

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

cloud vapor
#

We do not support that format

swift jetty
#

Figured, thanks :p

untold quarry
#

Are nested translations supported through minimessagetranslator?

#

Something like

Component.translatable("test.test", Argument.translatable("another.translatable"));

And so on..

cloud vapor
#

I don't think they are, I think there's an issue open if you want to submit a PR

obtuse ruin
#

currently its not supported. you would need to implement that yourself

untold quarry
#

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

cloud vapor
#

what do you mean by "scale"

#

what are you trying to do that you can't actually do now

untold quarry
#

I already answered the question
"extend functionality by adding support for TranslatableComponent"

cloud vapor
#

what functionality

untold quarry
#

Making TranslatableComponent arguments translated when the main component is translated and mm parsed

cloud vapor
#

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

#

feel free to give it a test and see if it works for you - dropping a comment letting us know it works is helpful!

untold quarry
cloud vapor
#

🫡

untold quarry
#

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?

cloud vapor
#

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

untold quarry
#

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

untold quarry
cloud vapor
#

yeah it's def high on my todo list, i wanna try and get out a bugfix patch this week

untold quarry
#

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 😢

cloud vapor
#

Why do you need it?

#

There's likely a better solution

untold quarry
#

It ties the Argument class to a final class MiniMessageTranslationArgument

rare sage
#

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?

untold quarry
cloud vapor
#

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

rare sage
#

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

untold quarry
# cloud vapor If you give an example of what you need that for I can help you out further

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?

untold quarry
cloud vapor
#

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

untold quarry
untold quarry
#

unless using Reflection to access the value field of MMTA

sand drift
#

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"

untold quarry
#

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?

sand drift
#

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

rare sage
#

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

untold quarry
#

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

untold quarry
cloud vapor
#

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

untold quarry
#

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

untold quarry
#

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

obtuse ruin
#

Thats more or less exactly what i did a few month ago hAA

cloud vapor
#

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

obtuse ruin
#

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

forest flame
#

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

dense veldt
#

Take a look at Component#replaceText(TextReplacementConfig)

forest flame
#

thank fuck

#

i love u

ebon talon
#
    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

tawny bolt
#

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

ebon talon
#

I send component on paper server behind velocity proxy

#

checklocale command I used just prints Player#locale so I guess it's set?

cloud vapor
forest meteor
#

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

cloud vapor
#

Why do you have a component to begin with?

forest meteor
#

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)

cloud vapor
#

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

forest meteor
#

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

cloud vapor
#

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

forest meteor
#

its not a player message, its a plugin message

#

like an essentialsx message to a player

#

so its usually a component

cloud vapor
#

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?

forest meteor
#

because the value returned from the packet using PacketEvents and ProtocolLib is already a component

cloud vapor
#

you can turn a component into plain text using the PlainTextComponentSerializer

forest meteor
#

then you lose all colors, decorations and shadows

hardy crest
#

Cant you just do prefix.append(yourIntercepterComponent) ?

forest meteor
#

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

cloud vapor
#

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

forest meteor
#

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

cloud vapor
#

yeesh i mean this is a pretty weird situation you've got tbh

forest meteor
#

yep

cloud vapor
#

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?

forest meteor
#

i doubt the possibility of this

#

plus it needs to be minimessage to respond to Tag class anyways

forest meteor
cloud vapor
#

why wouldn't that be possible?

#

tbh atp i think your design is so bad that you're on your own unfortunately

forest meteor
cloud vapor
#

im not sure, it's been a while since ive poked about in the parser internals

fathom mulch
#

why do line breaks <br> show up like this

dense veldt
#

You can't have line breaks in lore

fathom mulch
#

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

sand drift
#

No, there is no magical built in util for tree splitting

fathom mulch
#

alright, thank you

cloud vapor
#

can you show the full code? are you sure that translation string is in your translation store?

small cloud
#

is there some way to have MiniMessage.miniMessage().serialize also serialize new lines?

cloud vapor
#

what do you mean? MiniMessage doesn't care about newlines they're just a character

small cloud
#

I mean there is the <newline> tag, and I'd like \n be serialized to <newline>

cloud vapor
#

i mean you could just replace it after the fact

sand drift
#

Probably not because \n is text and not a tag

cloud vapor
#

doesnt matter we can rountrip with virtual components

#

i just dont know why we would bother here

small cloud
#

just wanted to know if there was an built in way, I guess I'll just replace it by hand

rare sage
#

apparently it will serialize <br> if the component it's visiting is equal to Component.newline()

small cloud
#

I guess I'll just manually do .replace("\n","<newline>")

sand drift
#

if you mean you have a \n in the middle of a random component a lot of advice is to don't

small cloud
#

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()))

cloud vapor
#

it's fine

small cloud
#

wait.. I can just get the signedMessage.message() which returns a string?

small cloud
obsidian nimbus
#

what is the usecase for Nbt Storage components?

nova agate
#

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?

cloud vapor
#

can you show some code?

#

what is the format of the join message?

midnight spire
#

you can theoretically just adjust the color of all parts of the component

nova agate
nova agate
#

I could perhaps loop through child components and append a recolored version to a new component builder?

cloud vapor
#

see mapChildrenDeep

obsidian nimbus
cloud vapor
#

feel free to open an issue or pr instead of just mindlessly complaining

obsidian nimbus
#

okaay

nova agate
#

that is exactly what I needed

forest meteor
#

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

cloud vapor
#

they aren't useless, the default state for styles is unset, which is mechanically different from false

forest meteor
#

yes. but it sets it even tho it was unset

#

at least for me

cloud vapor
#

it doesn't add those values without you setting them, can you show some code?

forest meteor
#

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

lost steppe
#

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

next hedge
#

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.

serene hare
#

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(""))

cloud vapor
next hedge
cloud vapor
#

You can't do it with adventure

nova agate
#

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.

sweet hornet
#

comp.append(Component.newline())

nova agate
#

thank you :))

serene hare
serene hare
cloud vapor
#

you use it to remove the source at a later date if needed

cloud vapor
alpine marlin
#

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)

rare sage
#

#,##0.##

#

you need to specify it

alpine marlin
next hedge
#

Can I get the original volume and pitch of a minecraft sound with paper or adventure api?

cloud vapor
#

Not with adventure

odd fiber
#

how to add support legacy mini message format??

hallow tangle
#

Legacy or MiniMessage?

odd fiber
#

legacy support format in mini message

sterile rampart
#

you don't

odd fiber
#

uhhhhh

hallow tangle
#

Maybe he meant in Adventure

odd fiber
#

yes thats what i mean

sterile rampart
#

LegacyComponentSerializer

odd fiber
#

where to add it?

sterile rampart
#

not sure why you'd say MiniMessage when you mean adventure

sterile rampart
odd fiber
#

howbuffering

sterile rampart
#

what do you mean how? what do you currently have written?

odd fiber
#

i dont know actually where to add, can you give me tutorial?

sterile rampart
#

no

#

we aren't going to spoonfeed you here, we will assist you in solving your own problems though

odd fiber
#

damn

grim bear
#

are Components immutable? I'm trying to create an immutable snapshot version of a class which contains Components as fields

tiny bone
#

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.

cloud vapor
#

do books support the suggest_command click action?

tiny bone
sweet hornet
#

"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

tiny bone
hoary plume
#

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.

sweet hornet
#

Different components can have the same render, so it depends on how you define "same"

quaint monolith
#

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?

hoary plume
#

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,

dense veldt
#

I mean mini message has its own unit tests, so I would assume that testing simple stuff like that should be somewhat okay™️?

sweet hornet
#

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)

sand drift
#

There is no real long term garauntee on the stability of components

serene hare
cloud vapor
#

like, plain text? message format? json? minimessage? etc

serene hare
#

and maybe use the minimessage translator (even if i still don't understand how to implement it)

cloud vapor
#

Give these a read over and let us know if youve got any questions!!

serene hare
cloud vapor
#

There is a translation store for minimessage

serene hare
#

oh right, didn't see it

small cloud
#

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

cloud vapor
#

Nope - where are you getting the component from? there is likely a better solution

small cloud
#

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

cloud vapor
#

Yeah we don't support that unfortunately

#

It's best to stick with one format consistently rather that mix multiple

restive spruce
#

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"]

cloud vapor
#

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

grim bear
#

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"

dense veldt
#

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

grim bear
#

a nice, thank you

#

how do I choose what locale is used?

dense veldt
#

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

serene hare
#

what's the best approach to store translations?

dense veldt
#

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.

cloud vapor
#

yep

serene hare
#

that would be the best practice right?

cloud vapor
#

you're gonna get the same answer i gave you yesterday tho, go read the docs i linked :p

#

yep

serene hare
#

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?

cloud vapor
#

sure that's one way

serene hare
#

i discovered that you cannot load all the files in a resource bundle

#

you must load them per locale

grim bear
#

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?

cloud vapor
cloud vapor
serene hare
cloud vapor
#

sure

serene hare
#

the "big" issue is that i can't iterate over files in the classpath resources

hazy oak
#

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?

quaint monolith
#

Books can run a command (but not suggest one) so you can have a command handler to do that

hazy oak
#

I see.

quaint monolith
#

Or use the callback system to avoid needing your own command, I know that should at least work for Paper

hazy oak
#

So, I could theoretically, have like 10 commands per page in a book?

quaint monolith
#

Sure

hazy oak
#

the user would just click on each line or whatever

#

Awesome

#

Honeslty coming back to plugin dev after 10 years

#

this is amazing

wet kestrel
hazy oak
#

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

tough peak
#

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

sweet hornet
#

What is calling it alot?

#

You could maybe cache values there

sour totem
#

would you mind sharing the spark report that you're looking at?

sweet hornet
#

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

sweet hornet
tough peak
tough peak
sweet hornet
#

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)

tough peak
obsidian nimbus
#

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

small cloud
#

is there some way to check if a component contains a specific string?

sweet hornet
#

What is your final goal?

small cloud
#

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

quaint monolith
#

Make %shops% be <shops> and use a tag resolver

small cloud
#

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())
quaint monolith
#

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

small cloud
#

hmm

sweet hornet
#

<shops:1>, <shops:2>

quaint monolith
#

No need for that even

small cloud
quaint monolith
#

Or one of the simpler placeholders mentioned at the top, I'm not sure

small cloud
#

I see, I see, thank you

prisma mason
#

Still, Amaranth's answer is the better solution

sweet hornet
hardy estuary
#

Hello, is there in adventure something to strip hex colors from a component or a string? (Hex colors represented like &#ffffff)

sweet hornet
#

This is legacy format, you could use the legacy component deserializer and plain text serializer

hardy estuary
#

it also remove legacy colors codes?

sweet hornet
#

Indeed

#

It will remove all legacy formatting

hardy estuary
#

unluckily I double check, I already use both but it doesn't strip it

sweet hornet
#

Can you share some code plz?

small cloud
#

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?

cloud vapor
#

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

small cloud
#

hmm, I'll just do a complex one then seems less hacky

cloud vapor
#

yeah, better to use arguments when needed

small cloud
#

what exactly is a Pointered target? what can it be? just anything?

sweet hornet
dense veldt
small cloud
#

when does one use it with deserialize? what tags need it? how would I use it in a custom tag?

dense veldt
small cloud
#

and then? how do I use the pointers it provides? or should I just cast it to my own type?

dense veldt
#

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

small cloud
#

mkay, there can not be multiple targets for a deserialization, right?

#

i.e. there isn't something like a PointeredCollection or something

dense veldt
#

Yeah only one target

cloud vapor
#

You can implement Pointered and do whatever you want tbh

#

cast or whatever

shadow wyvern
#

What's happening with adventure 4.22.0, I would be very interested in it

rare sage
#

patch releases ⚰️

cloud vapor
#

i am on holiday, the patch release shall happen at some point soon

silent thorn
#

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

cloud vapor
#

Yes that is intended - see the config for the builder for the callback

#

sorry, ClickCallback.Optiona

silent thorn
#

got it, thank you

sweet hornet
#

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

sand drift
#

That would come from mojang parsing the thing you passed into the command

sweet hornet
#

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)

sand drift
#

idk, mojang messed with the formats recently

sweet hornet
#

Yeah I saw that, but it's for 1.21.5 iirc

knotty laurel
#
            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

cloud vapor
#

yeah, doesn't look like there's a null check there

#

is the get index line failing?

knotty laurel
#

yep

#

I feel like that should be covered by default value

sweet hornet
warm hazel
#

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 ?

sour totem
#

your show_text contains a ', so you should put a "" around it instead

warm hazel
#

Oh yeah, completely missed that, thanks for your help ! 🙂

inner sapphire
#

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 😅

cloud vapor
#

Feel free to submit a PR

vestal sedge
#

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?

wet kestrel
#

** and provide the code that doesn't work**

fiery oracle
#

(using a paste site, if it's long)

vestal sedge
#

and further away from him there is SendMessage, which immediately transfers the message to the minimessage.

wet kestrel
#

Doesn't that code show you building a custom MM instance, that doens't have the shadow tags added?

vestal sedge
vestal sedge
#

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(

fiery oracle
#

what does it look like?

vestal sedge
#

For standard shadows from minecraft

#

And it should look like this

fiery oracle
#

are you using a vanilla 1.21.4 client?

vestal sedge
#

1.21.3

#

Is it necessary to use a client above 1.21.4?

#

Dudeeeeeeeee

#

thanks

fiery oracle
#

considering shadow colors were added in 1.21.4, yes, you need at least a 1.21.4 client

vestal sedge
#

thanks

warm spoke
#

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 🙏

sterile rampart
#

what do you mean "legacy" classes?

#

like, are you sure the mods you are using are even compatible with that game version?

warm spoke
# sterile rampart like, are you sure the mods you are using are even compatible with that game ver...

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

sterile rampart
#

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?

warm spoke
sterile rampart
#

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

warm spoke
#

all the mods that give me this error are either for 1.21.1 directly or an older version like 1.20.1

sterile rampart
#

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)

warm spoke
#

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

sterile rampart
#

(also generally mods need to be a pretty exact match with the minecraft version, newer or older usually don't work)

warm spoke
sterile rampart
#

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

warm spoke
#

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?

sterile rampart
#

probably

#

see the binary search section here

warm spoke
#

what should I do with this site?

#

just go as follows and eliminate mods until i magically stop getting the class error?

full onyx
#

Mods on paper?

warm spoke
#

my server is fabric

warm spoke
#

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 ^-^

upper galleon
#

Can you tell me which version of adventure-api and adventure-text-minimessage support 1.16.5.

wet kestrel
#

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.

jolly oyster
#

Hi, does the hashCode get saved when creating a text component or it gets calculated every time hashCode is used?

sterile rampart
sterile rampart
jolly oyster
#

nope I asked here first

obsidian nimbus
#

it is calculated every time

#

whats the deal?