#adventure-help

1 messages · Page 7 of 1

rare sage
#

i mean, you can make your own tag that takes an entity as context target passed to the deserialize method

naive gale
#

is there a way to sanatize or remove all minimessage parts of a string?

#

Im trying to have a configurable chat format, and i want the chat format part to be able to use minimessage, but not let player inject their own

#

or maybe a way to like replace a string in a component with another

fiery oracle
#

if you're using a minimessage placeholder for the user-provided bit of the format, there's a placeholder for text that shouldn't be parsed

wet kestrel
#

Seconding the use of Placeholder.unparsed, because that would more directly call them out when their message shows up with all the mm stuff in it 😆

ripe tulip
#

is there a reason the adventure webui doesn't use the actual font minecraft uses? it has some notable differences and many missing characters as it uses an unofficial recreation

the minecraft website uses fonts by the foundry canada type, they are more accurate to the in-game font as far as i can tell, ideally it would be exactly as displayed in game though with all characters supported

#

in the client jar, assets/minecraft/textures/font has .pngs containing each glyph used in game

cloud vapor
#

The font we use is some free dupe

sage river
#

and the fallback font is just unifont

#

or, atleast the repo is MIT except for the images

sand drift
#

The mojang font is unlikely to be MIT and is covered under their brand guidelines, etc, iirc

cloud vapor
sand drift
#

assets included in a repo and their licensing is often a weird area

#

idk if there is a general expectation that the license of the repo would apply to all assets, especially when brand guidelines exist, etc

cloud vapor
#

it's got a SIL license in the folder

#

although yeah the ofl was added alongside the notosans fonts

sand drift
#

From the Noto Sans PR

cloud vapor
#

so probably not

sand drift
#

That was added 2 years ago, the MC fonts have been there for 7

#

*5 years ago

cloud vapor
#

default license also states

All image assets of this project are copyrighted by Mojang Studios and may not be used outside this project without permission by Mojang Studios.

sweet hornet
#

Just to share my personal opinion:
I don’t think this is worth messing with all those licensing questions when the current font is more than acceptable for the need of the current viewer, which is to preview the formatting of a MM string

sand drift
#

I've bumped them a nod to improve the clarification, but, it's generally fairly clear from all of their documentation and such that those assets are probably not ours to take

fair thunder
#

question: is there any way to handle plurals in translatable components?
for example, let's say i have a string such as You have <count> coins.
the way i18next handles this is it adds suffixes to keys. in English, that'd be _one and _other, for example:

_one => You have {count} coin. // 1 coin
_other => You have {count} coins. // 2 coins

in Polish, there's _one, _few and _many, for example:

_one => Masz {count} monetę. // 1 coin
_few => Masz {count} monety. // 2 coins
_many => Masz {count} monet. // 5 coins

does Adventure support this? right now i'm just assuming the _many case for PL

sand drift
#

No, that would be on the translator to deal with

#

and the default translators don't provide such a feature, at least afaik

cloud vapor
#

MiniMessage has a choice format tag if you're using that

fair thunder
#

idk if im using this correctly 😅

Component.translatable(
    "commands.warnings.some.other",
    Argument.string("player", target.name),
    Argument.numeric("count", warnings.size),
    Argument.tagResolver(Formatter.choice("choice", warnings.size))
)
tawny bolt
#

Might need the single quotes? ' in the example and you have ".
Not sure though, just noticed that

fair thunder
#

oh true

prisma mason
#

yeah I think so, if choice is similar to booleanChoice you could also just pass them as multiple arguments

fair thunder
#

wait i have single quotes in my properties file tho

prisma mason
#

e.g. <choice:'choice1':'choice2':'choice3'>, not sure if this works tho

fair thunder
#

maybe i need to escape them

#

escaping them doesnt help. hmm

regal frigate
#

Hey, just a quick question: this should work correctly, replacing the <placeholder>?

MiniMessage MM = MiniMessage.miniMessage();
Component source = Component.text("<placeholder>");
String serialized = MM.serialize(source);
Component output = MM.deserialize(serialized, Placeholder.unparsed("placeholder", "something"); // -> something

I'm asking because it's some kind of magic and it doesn't work or I'm not aware about some stuff.

thick rapids
#

serialize will escape the <>

regal frigate
sweet hornet
#

But, why?

#

The situation you ended up in is weird, and looks like an XY problem

regal frigate
# sweet hornet But, why?

I have a TranslationStore that I use to fetch a message in the specified language. Messages may contain placeholders that need to be replaced. I’m also using final components in the dialog created with the experimental Dialog API.

I tried using Component.translatable(…) when building the dialog, but they don’t resolve — what ends up on screen are the translation keys, not the actual strings.

So instead of that approach, I’m forced to obtain the component directly via TranslationStore#translate(TranslatableComponent, Locale) that returns Component.

cloud vapor
#

I still don't know why you'd be having that issue - why aren't you using a MiniMessageTranslationStore?

regal frigate
#

Do you mean that they don’t resolve in dialogs? I’m actually using MiniMessageTranslationStore.

cloud vapor
#

Like you can just manually translate a component with your store, or even via the GlobalTranslator if you've registered it there

regal frigate
#

Ah, do you mean that I should call TranslationStore.translate(...) with Component.translatable(...), where I specify the argument resolvers?

translationStore.translate(Component.translatable("message.key", Argument.string("placeholder", "value")), Locale.ENGLISH);
cloud vapor
#

Yep

regal frigate
#

Looks and works well, thank you

harsh pecan
#

does Component.replaceText return a new object or just the mutated copy
in other words, should i do component = component.replaceText or just component.replaceText without the reassignment

sour totem
#

components are immutable, so you'd need to reassign it (the first one)

tough peak
#
sender.sendRichMessage("<yellow><click:run_command:/trade accept <player_name>>")```
can I use tagResolver to replace `<player_name>` with a string?
dense veldt
#

oh wait, this is inside of a run command, I don't think it works then

sour totem
#

it seems to work within webui

#

fwiw

sweet hornet
#

You need to quote the command as an argument of click (i.e. <click:run_command:'/trade accept <player_name>'>), and use the Placeholder#parsed tag resolver

dense veldt
#

I think click only passes along the string value and doesn't do any deserializing like hover

#

but just try and see I guess

sweet hornet
#

Yes, but Placeholder#parsed tag resolvers are resolved first

dense veldt
#

I see, makes sense

rugged leaf
#

If I'm using for example the MiniMessage translator for my plugin messages, are there any limitations to what tag resolvers I can use there + can I use translations inside translations there?

cloud vapor
#

no limitations - nested translations should work fine too

rugged leaf
#

Great! And thanks for the quick response!

cloud vapor
#

🫡

fiery oracle
cloud vapor
#

we love virtual components here

fiery oracle
cloud vapor
#

hm that if statement seems rather silly, why would we need to filter those out?

#

also this is why we have a github issues tracker, if you find issues let us know so we can fix them :p

#

first im ever hearing of custom arguments not working with a minimessage translator specifically in the global renderer

fiery oracle
cloud vapor
#

im kinda struggling to understand why filtering is even done there

fiery oracle
#

that if statement is present because it'd otherwise just collapse the virtual component to an empty component in the renderer

slate current
#

I know you all do this on your free time and all, so no worries if you cant right now, but seeing as there's just been a couple of PR merges & a release - is there a chance you could take a look at my Adventure NBT PRs? would be really helpful if these could get merged/looked at

cloud vapor
#

yeah they're on my list for 4.25

cloud vapor
fiery oracle
#

look at the virtual check - it doesn't return

cloud vapor
#

oh i see, that doesn't chain

#

see now im really trying to work out why we're even doing that

#

like you have to be very specific to leave virtual components lying about, why are we even getting in the way of them here

fiery oracle
#

what exactly do you mean by that?

dry valley
#

Hi, I am not sure if this belongs here or in the velocity chat.
I am sending a component to a player like this

source.sendMessage(LegacyComponentSerializer.builder()
      .extractUrls()
      .character('§')
      .hexColors()
      .build()
      .deserialize("Discord: <https://discord.cloudnetservice.eu/>"));

once the 1.21.8 client receives it the client disconnects

Caused by: io.netty.handler.codec.DecoderException: Failed to decode: Illegal character in path at index 35: https://discord.cloudnetservice.eu/> {extra:[{click_event:{action:"open_url",url:"https://discord.cloudnetservice.eu/>"},text:"https://discord.cloudnetservice.eu/>"}],text:"Discord: <"}

I am using Velocity 3.4.0-SNAPSHOT (git-81deb1ff-b521) (please ping on response)

sweet hornet
#

I saw a similar stack trace on my Paper dev server a few days ago, so this is not Velocity-specific I guess

fiery oracle
#

that error is just from constructing a URI from https://discord.cloudnetservice.eu/>, because of that >
so i assume it's an issue with whatever regex is used for the #extractUrls

#

the regex is (?:(https?)://)?([-\w_.]+\.\w{2,})(/\S*)?

cloud vapor
#

Feel free to open an issue, or even better a PR!

cloud vapor
dry valley
#

Well thats just a minimal reproducer

#

Its never used like that

lucid vine
#

Is there anywhere i can see discussion or a wip pr for dialog support?

sterile rampart
#

anything that exists is in these channels or on github

#

the consensus for now though is I think we're just letting dialogs mature for a version or two

#

let things stabilize before we try and build some sort of api in adventure

glad mulch
cloud vapor
#

Yes

cedar forge
#

I have a Placeholder.unparsed tag resolver that I am using on MiniMessage deserialize. It parses like normal in the chat, but it does not replace in my copy to clipboard. <click:copy_to_clipboard:'{{:<title>}}'>

cloud vapor
#

Copy to clipboard is just text, so you need to use a pre parsed placeholder

cedar forge
#

ahhh

#

that works, thanks!

vernal steppe
#

what fonts are supported by minimessage?

sweet hornet
vernal steppe
#

okay

robust wharf
#

small caps is not a font

sweet hornet
robust wharf
#

its just different unicode characters that kinda look like the latin ones, but its horrible for accessibility and I just closed a PR for minimessage yesterday adding support for that since we dont want to promote bad accessibility

vernal steppe
#

well the thing is, in my scoreboard there are placeholders, and they are using standard font for minecraft, and i want to replace it with small caps

sweet hornet
robust wharf
vernal steppe
#

I think it's quite readable.

#

and pretty much 95% of czechoslovak servers use small caps

cloud vapor
#

Not by screen readers or the narrator. You should instead find a font to use that emulates it

#

Will also be easier to use as you can simply just set the font

vernal steppe
#

ill look on it

cosmic loom
vernal steppe
#

i installed it into resourcepack, how should i put it in scoreboard?

dense veldt
#

you'd want to change the font of the component on the scoreboard to that font

#

if you're using mini message use the font tag, otherwise something like Component#font(Key)

stable hedge
#

hii all! is there anyway to prevent the "parent" translatablecomponent to not pass its style to the args without changing the style of each arg?

sterile rampart
#

no

ocean agate
#

I tried to modify the number while keeping the colors and formats. How can I do that?

private void modifyAttribute(List<Component> lore, Component component, String key, int i) {
            Component newLore = component.replaceText(builder ->
                    builder.match(key + "[::] (\\d+)")
                            .replacement((matchResult, textBuilder) -> {
                                String colon = matchResult.group(0).substring(key.length(), key.length() + 1);
                                int num = Integer.parseInt(matchResult.group(1)) + blueprint.getUpgrades().getAttributeValue(key);
                                return Component.text(key + colon + " " + num);
                            })
            );
            lore.set(i, newLore);
        }

I'm now using the code above, but obviously it can only replace texts when they are together without different colors or formats

cloud vapor
#

Correct, that's just how it works

#

I'd suggest recreating the component from scratch, no reason to be doing replacements like this for such a simple problem

cedar forge
#

I know this is probably asked a ton, but when you have a component that contains legacy section characters inside the text field itself, whats the best way to handle it? My specific issue is that the components are straight from bookMeta.pages().

#

Right now its parsing out to this on our website.

cloud vapor
#

The best way to handle it is don't do that lol

#

Nothing should be giving you that either, so you must have some cursed setup to get books like that

cedar forge
#

does paper default prevent a section character being placed in a book?

cloud vapor
#

No but unless you're creating the books with legacy formatting in a component it should be gracefully handled

cedar forge
#

I'm not familiar with how they are even placing them there.

cloud vapor
#

That'd be the place to start

#

books with legacy inside of components are gonna cause lots of problems

slate current
#

Would a PR adding support for reading a builder's current values be accepted? running into a scenario where I'd have to build the entire component pre-maturely just to read some values (unless I'm blind and there's already a way to do that)

#

There's already some features like that (e.g. text component builders let you both get and set the content), but for most values it doesn't seem to be supported - would be nice if it could just implement StyleGetter there or something like that

cloud vapor
#

What's the xy?

slate current
#

Migrating some stuff from Bungee chat to Adventure (finally :D), and places that just had a Bungee chat component and added children and such along the way now use a builder, which means a lot of the existing logic we have is going to be very annoying to update currently

cloud vapor
#

I mean, what sort of scenarios are you in where you need to do that?

slate current
#

A custom component parser from back when there weren't really any better options - it's got a lot of logic to support edge-case parsing shenanigans, so I'd much rather just update it as-is and work on moving to MiniMessage now that there's better options out there, rather than give it a big rewrite and then work on switching

#

I can link you specific places if you want, but uh, it's big and a little hard to read through

cloud vapor
#

Yeah ig I'm just looking for specific code examples of what behaviour you're missing, bc I can't really see what we actually need to add here

#

snippets/examples are fine

slate current
#

Mostly just StyleGetter stuff,

var builder = Component.text();
builder.decoration(TextDecoration.BOLD, true)
// Someplace else
if (builder.decoration(TextDecoration.BOLD) == TextDecoration.State.TRUE) {
    // Checking the builder's value
}
#

One actual example would be this

    private static void copyDecoration(TextDecoration decoration, StyleGetter origin, StyleSetter<?> destination, boolean minimize) {
        TextDecoration.State state = origin.decoration(decoration);
        if (state == TextDecoration.State.NOT_SET) {
            return;
        }
        if (minimize && state == TextDecoration.State.FALSE) {
            return;
        }
        destination.decoration(decoration, state);
    }

    public static TextComponent.Builder copyFormatToNewText(TextComponent.Builder last, boolean minimize) {
        TextComponent.Builder toRet = Component.text();
        Component lastBuilt = last.build();
        copyDecoration(TextDecoration.OBFUSCATED, lastBuilt, toRet, minimize);
        copyDecoration(TextDecoration.BOLD, lastBuilt, toRet, minimize);
        copyDecoration(TextDecoration.STRIKETHROUGH, lastBuilt, toRet, minimize);
        copyDecoration(TextDecoration.UNDERLINED, lastBuilt, toRet, minimize);
        copyDecoration(TextDecoration.ITALIC, lastBuilt, toRet, minimize);
        toRet.color(lastBuilt.color());
        return toRet;
    }
cloud vapor
#

in that example couldn't you use decorationIfAbsent or one of the style merge strategies?

slate current
#

Am I missing something ;-;? all of these look like they would require building the component first to read the values (either getting the states for decorationIfAbsent, or getting the style for merging)

#

The logic for setting the decorations can maybe be cleaned up with adventure's extra API, but you'd still need to get the styling/decorations off of TextComponent.Builder last somehow as far as I can see

cloud vapor
#

Ah actually I see what you're trying to do, I think you can just ignore all that and compact the component at the end

#

Yes the builders should be able to return the style too, feel free to open an issue but it's unlikely to get done soon as I'm trying to avoid big new features before Adventure 5.0

slate current
slate current
cloud vapor
#

Yeah it's mainly annoying rebases im trying to avoid, but feel free to!

slate current
#

I assume I need to override the JD and specify @since 4.25.0, but should I just copy over the entire JD? Or is

/**
* {@inheritDoc}
* @since 4.25.0
*/

fine?

#

So something like:

sterile star
#

I don't see why that wouldn't be fine shrug_animated

#

That's basically exactly what @inheritDoc is meant for

slate current
#

Just asking because some methods there say like, Sets the color of this component (not sure why it says component and not component builder actually)

sweet hornet
#

Just be careful, sometimes the IntelliJ preview does not show the exact result of the JavaDoc tool. Maybe try to generate the JD once, to ensure it works properly

sterile star
#

Yeah that too. Just give it a quick poke and check manually if it matches what you expect

#

-# I did not mean git push, that was just a metaphorical expression, mb if that sounded incorrect lol

slate current
#

Or the #insertion JD says Gets the string to be inserted when this stylable is shift-clicked. - styleable there is probably fine? but maybe I should override the JD to say component instead?

rare sage
#

well, a component is stylable, no?

slate current
#

StyleGetter#insetion - Gets the string to be inserted when this stylable is shift-clicked.
Component#insertion - Gets the string to be inserted when this component is shift-clicked.

#

Imo I don't think it's that big a deal, but just making sure since it's already being done ^

sweet hornet
#

Just an external point of view, it is perfectly fine for me to leave styleable, it's like when you have Entity#getId and Cat#getId, you won't override the JD just to say Gets the ID of this cat, it is fine to say Gets the ID of this entity because a cat is an entity

hardy estuary
#

I need to do validation for sounds provided from users in config, I am using kyori adventure sound. What happens if a provided sound Key (minecraft:....) doesn't exists? Will an exception be thrown?

rare sage
#

no, the packet will be sent anyway, sounds can exist solely in the client without the server knowing

sweet hornet
#

<@&748618676189528155>

vagrant burrow
#

Handled @sweet hornet paperOhhh

rare sage
#

no

#

oh, hm, it might disconnect it

#

anyway, adventure itself does not provide an interface to validate a sound existing on the server (and a server can't know what sounds the client has), you'd need to fetch it from the registry in whatever platform you're using or just hope for the best

hardy estuary
sweet hornet
#

I mean, if the client crashes every time it receive a sound it doesn't know about, it seems to me like a strange design choice

rare sage
#

nvm i was reading the wrong thing, i don't think it disconnects

#

it should just no-op

fiery oracle
#

it no ops (on the client)

rare sage
#

i mean on the client

hardy estuary
#

thanks for helping guys

normal hemlock
#

How would you do <!i> in Legacy?

sweet hornet
#

Why?

normal hemlock
#

Why? As far as I remember lores and names will otherwise be italic'ed?

sweet hornet
#

Why legacy?

normal hemlock
#

Because my clients don't want MiniMessage

#

and I'm not being paid enough to argue and educate them

#

i enjoy minimessage it's easy to work with

normal hemlock
sweet hornet
#

There's no real way to replicate the <!i> in legacy. The "best" (least worse) you can do is §r, but it's violent. If you're dealing with it in the code side, you can just component.decorationIfAbsent(ITALIC, false), but mixing legacy and components is really really really discouraged as it will lead to unexpected behaviours

normal hemlock
#

Applying #decorationIfAbsent(...) to the root component won't change the underlying component's style will it?

sweet hornet
#

If you're parsing the legacy codes with the legacy component deserializer, at least you should have a valid component tree at the end, and applying decorationIfAbsent should work

normal hemlock
#

&aHello &iWorld (i forgot what's the italic thing)

sweet hornet
#

But if your bundling the legacy codes inside a text component, then you're screwed (and I can't help you any further)

normal hemlock
#

Oh defo not

#

I tried to combine MiniMessages and Legacy

sweet hornet
#

Bad idea

normal hemlock
#

and I failed horribly

#

and then I gave up

#

lol

sweet hornet
#

The two syntaxes differ in paradigms

#

Legacy codes are "linear", while MM is a tree-structure

#

And, since components are a tree structure, no need to tell you which one is the easiest to work with...

normal hemlock
#

Yep

#

One more question! How would you close <#RRGGBB> tag?

#

</>?

#

</color>?

#

or do i have to do </#RRGGBB>?

sweet hornet
#

It depends on how you opened it

#

<#rrggbb> must be closed by </#rrggbb>; <c:#rrggbb> by </c>; and so on

#

You can have <#rrggbb>, <c:#rrggbb>, <color:#rrggbb> or <colour:#rrggbb> all leading to the same result, but each one needs to be closed accordingly

#

And I think by far <c:#rrggbb> is the best for RGB colors, since it can be closed with </c> without repeating the color

normal hemlock
#

For sure!

wet kestrel
#

I prefer defining <coolcolor> as a hex color so I can </coolcolor>

sweet hornet
#

That's also a nice option for a predefined color palette, sure

wet kestrel
#

I let users define

copper marsh
#

How can I make a minimessage tag resolver that converts a component into another?

#

For example an align:center that calls my Component centerAlign(Component) method

sweet hornet
#

You should take a look at the Modifying tag interface

copper marsh
#

So something like this

sweet hornet
#

Huh, I don't think casting is enough... Oh well maybe, since it's a functional interface... I guess you can try it out. However, there is a particular handling of this tag that will cause its children to get duplicated if you do it like this. I think in your case, you are already handling the children inside your .centerAlign method, so you should only call it at depth == 0, and return an empty component otherwise (to discard the children that would get processed as well)

copper marsh
#

The casting thing is an IDE autosuggestion

fiery oracle
#

"casting" like that is a hint to the compiler for lambdas

rare sage
#

& Serializable TrollDespair

deep steppe
#

why cant tags have spaces

sterile star
#

Because that's how the syntax is defined shrug_animated

#

Makes it easier to parse them

#

And also, it would be kinda annoying if this would get parsed as one large tag: ```xml
As we all know, 25 < 16. This is not true for 25 > 45.

For this reason, MM defines that a tag name cannot have spaces, and if it has a space, it will be treated as a string literal instead so that my example parses correctly.
deep steppe
#

makes sense

#

we were moving skript's components to adventure while keeping support for legacy tags but <dark red> became an issue

dapper bay
dense veldt
#

I'm guessing here, but probably reading it from some config and then adding Placeholder.styling tag resolvers to a mini message instance

wet kestrel
#

Yep!

forest relic
#

im trying to use tag resolver but i get this

upper tinselBOT
forest relic
sterile rampart
#

something in your build process is fucked up

#

the fqcn is missing all its dots/slashes

forest relic
sterile rampart
#

ah maybe something weird with the log site

#

iirc 1.16 didn't ship with MM

forest relic
#

ive been using MM on 1.16

upper tinselBOT
sweet meadow
#

this seems like something stupidly trivial that im missing but,
header should have hover+click while message should continue with its own hover+click
but still retaining the color/decroation from the previous component

#

i have no clue how to go about this

sweet hornet
#

What's your current output vs expected?

rare sage
#

all style is inherited unless explicitly overridden

#

hover and click are part of style

sweet meadow
#

hmm thats interesting because i do infact override it in a certain situation and it does not act as such

rare sage
#

there is nothing more to comment without seeing the rest of the tree

sweet meadow
#

give me a second sorry im getting that now lol

rare sage
sweet meadow
#

yeah this is why im confused

#

chucks the item in just fine

#

but the hover is retained

cloud vapor
#

can you show some more code

#

all the little snippets make it hard to see what's fully going on

#

and if you can't share more, a little MRE is fine too

sweet meadow
#

yeah i can give this

#

the component serializer in question

#

String.formatted and Component.asString are extension funcs to use the normal minimessage de(serializer)

cloud vapor
#

you might wanna try and make an MRE, lots of moving parts there

#

what does debugging tell you? where is the hover getting lost?

sweet meadow
#

didnt really do debugging, assumed it was just me being stupid and missing something give me a sec

#

hmm it is possible it has something to do with MiniMessage#deserialize(String) not reading item hover events?

#

because thats the only thing i could see as an issue thus far

cloud vapor
#

idk, is it? what does your debugging tell you

sweet meadow
#

it tells me theres no issue if i take the components at face value and its in the serialization

rare sage
#

does the issue persist if you use the json serializer instead?

sweet meadow
#

(which is purely using minimessage deserialize and serialize)

cloud vapor
#

so debugging is telling you that you are sending the correct component to the client?

#

if so, then make sure you're on a vanilla client, check mods, etc

sweet meadow
cloud vapor
#

that should work fine, but i would never use minimessage for over-the-wire serialization

sweet meadow
#

yeah im a bit dumbfounded as to why our serializer uses minimessage when we use json serializer elsewhere but i digress

#

conclusion:
minimessage serializer appears to be a bit borked in terms of item hover events

#

but my original question was actually more, how do i stop the hover/click events from applying to the appended component without clearing the events from the component itself

cloud vapor
sweet meadow
#

will do

cloud vapor
sweet meadow
#

but then comes the predicament of i want to keep the color and decoration! 😭

sweet hornet
#

You unfortunately can't have both the butter and the money of the butter (idk if that saying translates well in english 😅)

sweet meadow
#

is there not a way i can copy specific styling and prepend it to a component

sweet hornet
#

Of course you can, but it's similar to unsetting the hover/click events imo

#

It's up to you about what approach you prefer

#

ig

cloud vapor
#

sounds like what you want to have is

parent component (color)
 -> child header (click/hover)
 -> child message (click/hover)
sweet meadow
#

yes indeed, but the color comes from the header sadly

sweet hornet
#

They'd need to extract the color/decoration part of the style anyway

sweet meadow
#

using Component#color would return the last color right?

sweet hornet
#

iirc it just returns the color of the style of that component

#

No hierarchical operation performed

cloud vapor
#

yep

sweet meadow
#

right...

#

hm

hollow stag
#

Hello, is there any way to turn a component back into minimessage format?

#

Hopefully this is the right place to ask

hollow stag
#

says this?

prisma mason
#

I could be wrong tbh

hollow stag
#

Lemme see if there's anything obvious

prisma mason
#

actually there is a method to serialize

#

MiniMessage#serialize

#

I've never used it, worth giving a shot

hollow stag
#

alr cool yeah I was just about to check if that method exists

#

Will try that ty

wet kestrel
prisma mason
wet kestrel
#

Very bad. It's always been both ways.

near valley
#

Why does using <reset> not work on item lore or display names? (they stay italic unless I explicitly use italic:false)

sand drift
#

because reset is a broken concept

upper tinselBOT
near valley
#

why does it even exist then?

#

I don't think anyone uses it for anything else

robust wharf
#

it does work

#

its just that a tree child cant unset style a parent sets, only override it

#

and since for lores vanilla sets italic as parent, reset doesnt know that it needs to unset it

#

but if you control the full component it works

#

use can use <!i> as a shortcut btw

near valley
near valley
robust wharf
#

I dont disagree, we only added it because people kept demanding it

#

and for chat it works exactly as those legacy users expect

near valley
#

ok fair

short kelp
#

what is the most direct way to set a list of children in a component?

sand drift
#

Pretty sure that there is a Component method to do that?

short kelp
#

I need a direct way. This children method somehow takes 20% of the execution time of the entire huge program

sand drift
#

There isn't a direct way because of ComponentLike, but it should be fairly fast unless you're doing something crazy

#

can't really comment on perf reports I can't see

near valley
#

how do I use the new custom click type added in 1.21.6?

#

I tried specifying both arguments with or without quotes respectively and it doesn't work no matter what

dense veldt
#

this requires some more context, is this about minimessage (sice you're talking about quotes)?

#

I don't think you can send a custom click event with mm

near valley
#

yes

#

really?

#

oh, should have probably read that conversation till the end

dense veldt
#

yeah it only implements actions that require a simple string/integer

near valley
#

well custom requires 2 strings according to the mc wiki

#

so it shouldn't be that hard to implement

dense veldt
#

feel free to open a pr

#

or just implement your own tag for your use case

near valley
#

wait does ClickEvent.callback use the custom click type?

dense veldt
#

depends on your platform

#

paper does iirc, velocity still uses a command

near valley
#

well I'm on paper soooo

#

what's the best way to get the player object from an audience?

dense veldt
#

check instanceof and cast

cloud vapor
short kelp
cloud vapor
#

Please share your profiling data so we can actually make improvements to the software you're using and complaining about

short kelp
#

Unfortunately I can't

cloud vapor
#

Awesome

sweet hornet
#

Is there a way to instruct MM to prefer a tag name alias over the regular name on serialization?

#

(I.e. use <!i> instead of <!italic>)

cloud vapor
#

I don't think so no

sweet hornet
#

Hmm, and what do you think of this?

#

Is it something that would make sense for you?

#

I can explain a little bit more what led me to this, if you want

#

Alternatively, do you think a simple find-and-replace technique on the serialized string would work?

sand drift
#

I mean, we don't really support "find and replace" type manipulation, though, it can be effective

sweet hornet
#

I know, that's why I originally not choose that, but if that's the only possible way to do it, I may try

sterile rampart
#

one day™ we can expose the serialization api

#

then you just do a custom serializable resolver

cloud vapor
#

What's the xy tho?

cloud vapor
sweet hornet
# cloud vapor What's the xy tho?

I’m working on an in-game item editor, without mods (with dialogs). And as you can guess, all the components use the MM format, so they are easily editable for the end-user. For item name and lore, obviously most of the time the italic is unwanted, so I have an option to auto-apply .decorationIfAbsent(ITALIC, FALSE). But when the user edits the same item, it then show the <!italic> in front of every line (and this is completely normal, of course), so just to make that a little less cluttered, I wanted to use the shorter version <!i> instead

#

While writing this, I realised maybe the most logic way to handle this situation in my case would be to detect if all the lore lines have the italic set to false, then completely unset it before serialisation and enable by default my toggle for auto-italic, so it will be added back after deserialisation

sterile star
sweet hornet
# sterile star Yeah what you said right here would make the most sense. Just unset the style ov...

The problem is then for detecting italic when sometimes, for existing items, the component looks like this:

{ "extra": [ { "text": "...", "italic": false }, { "text": "...", "italic": false } ] }

Technically, the root component does not disable italic, BUT italic is effectively disabled at each child level. Of course, then the component is not really optimized, but unfortunately, some item creation websites are pretty bad at this... (I actually have many examples in our "itembase" like this)

#

I don't think Component#compact handle this

#

It would require "factorizing" the style to optimize the component (by pulling up common style from all children), which sounds possible, but would require more work

small cloud
#

ah wait that'd break if it was escaped

sweet hornet
#

Component#compact optimizes the style of the component as if it was the root component (parent style is set to null). But in some context, it is not the case, and it could optimize further if it knew the parent style (mainly, in item's lore, the parent style being italic & dark purple). But there's no way to specify it, even when it is supported in the code (nor we can call directly ComponentCompaction.compact since it's a package-private class)

cloud vapor
#

sounds like a good PR opportunity

hardy estuary
#

https://jd.advntr.dev/api/4.24.0/net/kyori/adventure/audience/Audience.html#deleteMessage(net.kyori.adventure.chat.SignedMessage)

Does this method works if server is offline-mode or the server has plugins like AntiPopup/Freedomchat or similars which messes with chat?

Im asking to understand if it safe to include in a public plugin. Would use it as a feature to cancel messages after they are sent in chat, (for example it they contains swears etc)

fiery oracle
#

deleting messages only exist for signed messages

hardy estuary
#

I would store them from the AsyncChatEvent

fiery oracle
#

plugins that cancel chat and send system messages instead will break it :P

hardy estuary
#

last option, which I wanted to avoid, was storing in a cache the last 100 messages, when one is cancelled, sending again them in order

calm trench
#

Heya! Is there a recommended maximum setting for the nesting limit in the component flattener?
Currently seeing an issue where excessively nested components are able to cause havoc, stumbled across that option, and am now curious what you'd recommend :)

cloud vapor
#

you could probably go lower, you can also override the default if you want to affect all flatteners created

last horizon
hardy estuary
tawny bolt
#

note that delete message does not actually delete the message on the client

#

you get a "<Message deleted>" text instead, its sadly is not completely gone

#

So if you want to replay chat or similar, the only way of truly clearing it is still spamming the client with empty messages

hardy estuary
rapid laurel
#

is there a better way to unescape tags in minimessage then .replace("/<", "<")?

cloud vapor
#

even that won't work if someone is escaping the escape char

#

sounds like an xy problem

upper tinselBOT
rapid laurel
#
String formatStr = StringUtils.parseArgs(PlaceholderManager.parseString(player, format), name);
Component chatFormat = miniMessage.deserialize(formatStr);

formatStr is containing both legacy color and minimessage
I just though of a better approach that might work but this still could be useful for future

cloud vapor
calm trench
sweet hornet
#

What's the purpose of Style.Merge.Strategy.NEVER?

#

I mean, if we never merge, why calling merge in the first place? 😅

#

Why is there TextDecoration.State & TriState? Didn't they fill the same purpose? TriState has some really useful methods, but unfortunately I can't use them because I have TextDecoration.States

graceful kestrel
#

tristate was added later

runic onyx
earnest wyvern
#

im unsure how to go about recoloring all children (deep) from a given Component, ayone got any idea? im aware ComponentBuilder#mapChildrenDeep is a thing but unsure how to get to that or use it at all

sand drift
#

You would need to turn the component into a builder to use that using the asBuilder method

#

then you call that method and it passes in all of the subcomponents and their subcomponents... into that function, you return the new component

dense veldt
#

If you just have a generic Component you first have to instanceof and cast to BuildableComponent<?, ?> (all components extend this so checking is kind of optional, but good practices and all), then you can call BuildableComponent#toBuilder

#

If you already have some sort of Component implementation (like TextComponent) you should already be able to call #toBuilder on that

earnest wyvern
#

okay so, my component is a TranslatableComponent apparently, and the hover event text i want to change color is an argument, is there any method like the mapChildrenDeep one to recolor arguments?

sand drift
#

mapChildrenDeep iterates the component tree, arguments aren't really considered to be part of that

#

you would need to manually deal with the transltable component yourself

small cloud
#

not really an adventure question but is there some way to allow color definition in resourcepack translatable?

fiery oracle
#

you can color the translatable component itself and the arguments you pass to it but you can't do coloring for the entries in the resource pack
i guess you could try shoving legacy codes there to abuse the client's tendency to render them in most places

tough peak
#

is there a way to "substring" a component?

tough peak
wet kestrel
#

what's the XY here

tough peak
# wet kestrel what's the XY here

I want to display colors in the action bar for a plugin I am working on.
The text is shown per-letter so currently I do a scheduler that for every time it subString the text.

#

I thought about using component.children() because I guess it would give me individual components that have the same style for each one

tough peak
#

so for example:

"<red>Hello <yellow>World"
"<red>Hello " - this it an object with the color red
"<yellow>World" - this it an object with the color yellow

cloud vapor
#

idk why you'd start with a completed component there, big design issue on your part

tough peak
#

but the thing is I need a splitted component and a plain string version of the splitted component

#

so I can apply style in a way

cloud vapor
tough peak
#

how I get to that point tho

#

How can I cut the component to multiple ones

cloud vapor
#

why cut it

#

start with it

tough peak
#

like, wdym start with it

cloud vapor
#

start with a list of strings and their associated style

tough peak
#

thats is what I was asking - how can I split it from here

cloud vapor
#

don't, start with a list of strings and style for each part

tough peak
cloud vapor
#

sure you could iterate the component tree

#

but that's long and a lot of effort

tough peak
#

I tried the iterable thing but I couldnt get out of it something

cloud vapor
#

have you tried putting the arguments in

tough peak
cloud vapor
#

... then you have the iterator so you can iterate though it

tough peak
#
        Iterator<Component> iterator = comp.iterator(ComponentIteratorType.BREADTH_FIRST, new HashSet<>());
        List<Component> components = new ArrayList<>();
        iterator.forEachRemaining(components::add);

        for (Component component1 : components) {
            System.out.println(MiniMessage.miniMessage().serialize(component1));
        }

well I don't usually use the Iterator directly...
but the logging seems weird?

The input : "<red>Hello</red><green>Hello"

[12:37:03 INFO]: [TalkShow] [STDOUT] <red>Hello</red><green>Hello // -> why is it logging the full msg?
[12:37:03 INFO]: [TalkShow] [STDOUT] <red>Hello
[12:37:03 INFO]: [TalkShow] [STDOUT] <green>Hello
sand drift
#

it iterates all components

#

including the root component

gusty pond
#

"<b><gradient:#8E2DE2:#4A00E0>test </b>test" i cant stop bold text after setting a gradient? why?

last horizon
#

you would have to close your gradient first

#

OR "<gradient:#8E2DE2:#4A00E0><b>test </b>test"

gusty pond
last horizon
#

show your entire string

gusty pond
#

"<gradient:#8E2DE2:#4A00E0><b>test</b>test"

quaint monolith
#

Works on the web viewer at least

gusty pond
#

even if i close the gradient it still wont let me

last horizon
#

maybe in code the styling is set to always bold
do you have access to the code?

quaint monolith
#

Ah yeah if the parent is setting bold it'll just all be bold

tawny bolt
#

<!b> should work in that case

last horizon
#

use !b

gusty pond
#

it does thank you

hard gate
#

Hi, does MiniMessage.miniMessage create a new instance every time? Or does it just return an already initialized instance?

tawny bolt
#

it returns an existing one

hard gate
tawny bolt
#

even if it created a new one it likely wouldn't, but yeah

weak hull
#
    public static List<Component> buildHoverText(ItemStack item) {
        List<Component> hoverText = new ArrayList<>();
        ItemMeta meta = item.getItemMeta();

        hoverText.add(item.displayName());

are these square brackets a side-effect of not serializing?

#

How should I be better handling this?

wet kestrel
#

Try meta.displayName instead.

weak hull
#

fuck right

wet kestrel
#

(also this sounds like a paper question not an adventure one)

weak hull
#

oh right lol

#

sorry!

tough peak
#

I still can't figure a way to do this.
Lets say I have a string (that can me deserialized) - "<red>Hello guys! <yellow>Get out."
I want to send the player this msg (in their action bar) like it is being written. to do so I use the scheduler.
What I need is a way to cut the component each time so I could achieve this effect ("H", "He" , ...., "Hello gu", .... "Hello guys! Get out").

My test version didn't support styling and just used the plain text and the substring method.
But now I want to have colors in it. Any ideas? 😔

sand drift
#

There is no clean way to do that which isn't basically manually iterating over the component to rebuild a small subsect of it

tough peak
#

I guess its kinda my problem but I want a way around this

sand drift
#

you would need to rebuild a new component from the old one

#

the fact that it iterates the root component is literally what you'd want here

tough peak
tough peak
#

umm

#

what if I just iterate these ones

sand drift
#

This is really not that hard of a concept to understand

#

if you serialise the root component you'll get all of the children in there too

#

you would need to actually introspect the components you're dealing with

#

and build a new component from that, respecting the tree

#

This is generally a headache and why there is no magical util to do this; it's not massively complex but it is a pain

tough peak
#
        component.iterator(ComponentIteratorType.BREADTH_FIRST, new HashSet<>()).forEachRemaining(c -> {
            if (c instanceof TextComponent textComp && !textComp.content().isEmpty()) {
                Component a = Component.text(textComp.content(), textComp.color());
                source.getSender().sendMessage(a);
            }
        });

well this works

#

for some reason

fiery oracle
#

that looks like it'd break for any component that inherited styling from its parent

#

also it only preserves colors and not text decorations

tough peak
#

🤷‍♂️

tough peak
fiery oracle
#

<red>Hello <bold>guys!

tough peak
#

~~```java
component.iterator(ComponentIteratorType.BREADTH_FIRST, new HashSet<>()).forEachRemaining(c -> {
if (c instanceof TextComponent textComp && !textComp.content().isEmpty()) {
Component a = Component.text(textComp.content()).style(c.style());
source.getSender().sendMessage(a);
}
});

this one seems to save the style~~
#

its really a headache for me that problem

tough peak
#
        LinkedList<Component> componentList = new LinkedList<>();
        component.iterator(ComponentIteratorType.BREADTH_FIRST, new HashSet<>()).forEachRemaining(componentList::add);

        Style currentStyle = Style.empty();

        TextComponent.Builder builder = Component.text();

        for (Component c : componentList) {
            if (c instanceof TextComponent textComponent) {
                currentStyle = currentStyle.merge(c.style());

                builder.append(Component.text(textComponent.content()).style(currentStyle));
                source.getSender().sendMessage(builder.build());
            }
        }

I guess this works

fiery oracle
#

why a linked list?

#

the style merge logic you have there doesn't work properly

#

it assumes that a component has at most 1 child

#

you need to do something similar to what a ComponentFlattener does

#

i do have a gist lying around of where i had to do something similarish for some stupid idea i had
but a lot of that gist is filled with stuff to avoid adventure's style merging (because it used to be weirdly slow)

tough peak
fiery oracle
#

what?

tough peak
#

Ahh I can't do this anymore

boreal orchid
tough peak
#

At the end I need a colored substring

cloud vapor
#

By splitting it into a list of singularly styled strings like I said right at the beginning

#

Of course this is difficult, you're solving a design problem with a code solution

tough peak
#

    private List<Component> loadTextFrames(Component component) {
        List<Component> frames = new ArrayList<>();
        List<Component> componentList = new ArrayList<>();
        component.iterator(ComponentIteratorType.BREADTH_FIRST, new HashSet<>())
                .forEachRemaining(componentList::add);

        TextComponent.Builder cumulativeBuilder = Component.text();

        for (Component section : componentList) {
            TextComponent textComponent = (TextComponent) section;
            String s = textComponent.content();
            Style style = textComponent.style();

            for (int index = 0; index < s.length(); index++) {
                char c = s.charAt(index);

                cumulativeBuilder.append(Component.text(c).style(style));

                if (c != ' ') {
                    frames.add(cumulativeBuilder.build());
                }
            }
        }

        return frames;
    }

yesterday I coded this, looks like it works

cloud vapor
#

you'll lose the red

tough peak
#

oh shoot

#

I can't understand your answer as well
how can I split it up then?
Find a Regex in the mm string?!

cloud vapor
#

make your input a list

#

start with what you are doing all this code to end up with

boreal orchid
#

I wonder, you could probably use the deserializeToTree method to properly split the nodes

tight pike
#

Hello, I have a problem. So I'm currently making a rank system in minecraft with a special symbol for every rank. So I make a Component with the Player's name and then append whatever rank they have to it. These Components are for example used to make item names. Now I'm trying to make a function where something happens to the player when I click on the item. This happens by getting the displayname, casting it to TextComponent, getting the content and removing the symbol and the space before it. However the .content() method seems to only return the symbol and not the name. Does anyone know what could be causing this?

obsidian nimbus
tight pike
#

what does tree structured mean?

quaint monolith
#

It's like the DOM in browsers, just because it looks like a single line in your UI doesn't mean it's a single component, it's a nested pile of components, usually one per style change although you can get even more via append

tight pike
#

ah, ok

#

pdc then

quaint monolith
#

You'd have to serialize the component to plain text to get a single line like you appear to be expecting but this is not a good strategy for storing information

#

Paper's PDC is a good alternative for storing stuff but really anything else that makes sense for your environment and the data you're storing

#

Could be as simple as a HashMap<UUID, MyData>

hearty nimbus
#

why does translatable("test.entry", Argument.tagResolver(Placeholder.parsed("value", String.valueOf(value))) works correctly, but translatable("test.entry", Argument.numeric("value", value)) does not? hover is parsed correctly, the value is substituted, but nothing is substituted into the click event. Message: <hover:show_text:'Click to delete <value>'> <click:run_command:'/test remove <value>'><value>.

rare sage
#

that screen shows up because the command is not visible to the client

#

whether it is because you don't have permission or are otherwise excluding it, for that screen to not show the command needs to be visible to the client

hearty nimbus
#

the problem is that the command is not substituted as a <value> tag if you use Argument.numeric("value", value)

#

but hover works correctly)

sand drift
#

I'd guess it's the matter of it being parsed?

#

i forget what is what, but, you have to use a specific type if you want to be able to inject into stuff before some stuff is processed

hearty nimbus
sand drift
#

It is, parsed means to slip it into the MM string, rather than it being processed as the contents of something later on

next ferry
#

Hello
"UnsupportedOperationException: null"
Is it adventure, triumphteam or my error?
https://pastebin.com/7wULZq5H

Using server leaf-mc 1.21.8-79-ver/1.21.8@e396d8c
Using for build plugin java 21, paper-api 1.21.8-R0.1-SNAPSHOT

My code at BusinessesContainer at line 149:

private MiniMessage miniMessage;

public BusinessesContainer() {
  this.miniMessage = MiniMessage.builder()
      .tags(TagResolver.builder()
          .resolver(StandardTags.color())
          .resolver(StandardTags.newline())
          .resolver(StandardTags.transition())
          .resolver(StandardTags.translatable())
          .resolver(StandardTags.keybind())
          .resolver(StandardTags.decorations())
          .resolver(StandardTags.font())
          .resolver(StandardTags.gradient())
          .resolver(StandardTags.rainbow())
          .resolver(StandardTags.clickEvent())
          .resolver(StandardTags.hoverEvent())
          .resolver(StandardTags.pride())
          .resolver(StandardTags.shadowColor())
      ).build();
}

...
            ItemBuilder
149 line -> .name(parseMM("Information about <business_name>", Placeholder.parsed("business_name", configItem.name()))) //.name() returns String
...

private Component parseMM(String message, TagResolver... tags) {
  this.miniMessage.deserialize(message, tags);
}
hardy crest
#

I dont know why the cause would be adventure, thats basic deserializing and Placeholders, I see no issue there

wet kestrel
#

Did some digging, you apear to be running an outdated platform too.

next ferry
#

I think the error is on the side of triumphteam-gui lib, I'll try to write to them
I'm using the paper api, not adventure
Thank you

next ferry
#

Ye I found solution:
I need to use PaperItemBuilder instead of ItemBuilder

boreal orchid
#

I hate it, but it works

#

could probably clean it up a little by making it more of an utility, I just didn't bother because I was testing with jshell

#

in the end, it'd probably have been better to just deal with the components instead of MM for this, so I was wrong about using the MM string being simpler

tough peak
boreal orchid
tough peak
boreal orchid
#

well, kind of not API. It is supposed to be exposed to the API eventually but it seems like the whole tree-traversal part of MM is yet to be done (if it is ever going to be done, I doubt many people actually want to use it)

tough peak
#

I hope they add a way to easily just cut a component someday

#

the idea is to just close all tags at the end

boreal orchid
#

I'll give the component only way a go later and if I get something working I'll post it here as well

tough peak
sweet hornet
#

If you REALLY want to do it automatically, after all this time, you can linearize (or flatten or call that what you want) the component tree, then your existing code will probably work

sweet hornet
#

I think the tree linearization is the only part you’re missing (but I did not nor plan to look your code in depth, it’s up to you to test it)

tough peak
tough peak
#

I think someone also suggested to flat the component I just didn't really knew what it meant

sweet hornet
tough peak
#

I can look at like like a pyramid of overriding

sweet hornet
tough peak
#

layers*

sweet hornet
#

Idk what your drawing is supposed to represent, but the styles are just inherited from parents to children, rather simple concept (considering you can access individual components’ style & children, and also merge styles)

boreal orchid
nocturne marsh
#

Hi,
I think I'm missing something here:

Registry<org.bukkit.Sound> soundRegistry = RegistryAccess.registryAccess().getRegistry(RegistryKey.SOUND_EVENT);

NamespacedKey soundKey = soundRegistry.getKey(org.bukkit.Sound.MUSIC_DISC_11);
audience.playSound(Sound.sound(soundKey, Sound.Source.UI, 1.0f, 1.0f));

Is there a better less verbose way to do something like this without hardcoding the key string?
I like the org.bukkit.sound enum, but I can't use it inside Audience#playSound
because it uses net.kyori.adventure.sound.Sound

rare sage
#

bukkit Sound implements adventure Sound.Type, which you can use to build an adventure Sound

nocturne marsh
#

Yes, but it seems that this method has since become deprecated, so I would like to avoid using it.

rare sage
#

i'm not saying to use that method tho?

#

n.k.a.s.Sound.sound(o.b.Sound.WHATEVER, n.k.a.s.Sound.Source.WHEREVER, volume, pitch)

nocturne marsh
#

Hmm, I definitely haven't seen that method, Thanks !
I thought you were talking about the implementation of the Sound.Type interface in Bukkit Sound (key() )

cyan depot
#

Hey, i got a question about how to use minimessage properly. So i own a minecraft server with a custom codebase and pretty much use minimessage for every gui (itemnames & lores) and chat messages.
Everytime a message or lore is built i use the deserialize function. This oviously causes a huge dent in performance pushing the mspt to around 90 with just 100 players online.

can someone with a bit more experience teach me how to "pre-deserialize" the messages and reuse these components and replace the dynamic content (custom placeholders)?
Maybe there is a different way of doing it properly, thanks for any help in advance.

sweet hornet
#

I guess you’d need to share the full spark report, but it seems you are at 20 TPS so… What is your real issue?

upper tinselBOT
cloud vapor
pure elbow
#

is it possible to somehow serialize kyori component to lang files so i can specify colors/etc... directly in resource pack's lang file? would be way easier than having to separate each arg/string that has different color/click event/...

sweet hornet
#

What format do resource packs lang files use? JSON encoding?

#

If so, yeah sure you can use the GsonComponentSerializer

#

But I'm not sure they are components at all

sterile rampart
#

resource pack translations doing support styling in values

sweet hornet
#

iirc they just are plain strings

sterile rampart
#

ya

grave kindle
#

Hello, is there a reference parser for MiniMessage-formatted text?

sweet hornet
#

MiniMessage.miniMessage()?

quaint monolith
#

If you mean is there a spec with the grammar defined or is there a simple implementation outside of any ecosystem no, afaik

dense umbra
#

is it possible to add my own component after each color in a component? I wanna try to implement vanilla-like shadows for scoreboard

dense umbra
sand drift
#

I mean, sure,y ou can do basically anything, question is how easy is it

dense umbra
#

yes

sand drift
#

if you wanted to modify the tree you'd basically need to walk over it

dense umbra
#

oh yea there is children() method

sand drift
#

adventure contains all of the tools you'd need to do that at the very least

dense umbra
#

yeah its so hard

#

i just tried

#

i dont understand is shadow a text decoration or what

sweet hornet
#

ShadowColor is part of the style of the component

dense umbra
#

ah wait

#

i got an idea

#

just gonna serialize minimessage back to text and insert <shadow> there

#

xd

sweet hornet
#

And remember that components (including all of its composing parts: style, children...) and immutable, so if you want to add shadow color to each component that have a color defined, you'll have to create new components for the whole tree

dense umbra
#

yeah this is annoying

#

ill try my idea with mm

sand drift
#

I mean, if that would work you could literally just set that on the root component

#

(no idea how the shadow stuff works)

sweet hornet
#

According to my understanding of your goal, imo it's far easier to work with components rather than the MM-encoded string of said components

dense umbra
sweet hornet
#

It's pretty simple:

dense umbra
#

well write it for me if its that simple!

sweet hornet
#

It works exactly the same way as color, but it also supports alpha channel

dense umbra
#

Yup just did it with mm

#

Works

#

hehe

sweet hornet
dense umbra
#

I know

dense umbra
#

but i dont care

#

nevermind

ocean agate
#

the callback did nothing

#

command run from console can work

rare sage
#

hm, client/server version? and what platform

ocean agate
#

Client:1.21.7 Server:Paper 1.21.8-31

#

Maybe mod issue, I'll check tomorrow

#

I saw the ChatPatches mod add some custom click actions into the component

ocean agate
#
executor.sendMessage(Component.text("[确认]").color(NamedTextColor.GREEN).hoverEvent(HoverEvent.showText(Component.text("点击确认"))).clickEvent(ClickEvent.callback(audience -> {
    audience.sendMessage(Component.text("已为" + player.getName() + "解锁所有词条").color(NamedTextColor.GREEN));
})));
#

tried with paper 1.21.8-40 and vanilla client 1.21.8, this doesn't work

#

the code is in brig command

#

full code here

ocean agate
#

seems like plugin conflict

#

some plugin removed the payload in the message

ocean agate
#

it's typewriter

#

🤦‍♂️

ocean agate
wet kestrel
#

You can reproduce it by only having packetevents?

ocean agate
#

yes

#

seems that pe only recognizes string payload

#

Payload is not a string payload, is CustomImpl{key=KeyImpl{namespace="paper", value="click_callback"}, nbt=BinaryTagHolderImpl{}}

wet kestrel
#

So instead of ignoring the packet it destroys it?

ocean agate
#

probably

fleet crown
#

Why serializator can handle colors/styles without other symbols from text in MiniMessage (<red>, <red><bold>), but not in Legacy (&c, &c&l)?

I try to deserialize input text and then serialize it to string to save in config. I type text, that contains only colors or style (without any other text). MiniMessage serializes fine, but LegacyComponentSerializer returns '' (empty string) instead of &c, so I have to type some other symbol &c... and it saves as '&c...'

sand drift
#

MM aims to preserve the tree

#

the legacy component serialiser from what I recall generally reasonbly behaves like the spigot one

#

(i.e. there is 0 consideration towards the formation of the tree, anything that isn't set is as part of the formatting stuff just generally overrides the stack, etc)

wet kestrel
#

The neat thing about the legacy serializer is you don't have to worry about how it writes because it's such a lossy serializer it's not worth using as anything but a way to migrate pre-2014 text to something modern like minimessage

fleet crown
sand drift
#

I tested because I wanted to double confirm that;

15:07:47 INFO]: [STDOUT] [net.minecraft.server.dedicated.DedicatedServer] [empty[siblings=[literal{Test}[style={color=aqua,!italic}]]]]
System.out.println(java.util.Arrays.toString(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(org.bukkit.ChatColor.translateAlternateColorCodes('&', "&a&bTest"))));
sweet hornet
wet kestrel
#

Should just use paper's when paper is present

#

It's so much easier to build a plugin that way imo

boreal orchid
#

if you're already shading and relocating your own version, it'd be more sensible to use your own, for the sake of behavior being deterministic

#

of course, you run into issues like this where new features aren't adapted as fast, but that's a price you should be willing to pay if you patch/fork anything

sweet hornet
#

So, when they updated adventure, they forgot to update this weird "forked"/"overridden" version of the Gson serializer, which mean it is outdated

boreal orchid
#

it looks like it was so they could support different versions of the game with just one serializer, looking at BackwardCompatUtil, I had assumed the adventure one would handle that kind of thing by itself tbh

sweet hornet
#

There are options to control how the serializers behave iirc. But they would need one correctly-configured serializer per version, I guess

#

tho they could make a single serializer delegating to the correct one if they really need to, but I don't really know what/why they are doing anyway. I was just intrigued by how that issue could've happened

wet kestrel
#

And packetevents is something that needs updates for each version that adventure would update (and plenty adventure wouldn't update for)

boreal orchid
#

either you permit delegation in your serializer so that new features are properly handled and maybe open a door to unforeseen issues, or you just use your own versions like they do and just fail completely at handling new features

boreal orchid
#

the former choice would eventually be the sensible one given how fast the ecosystem moves

oak forge
#

When using MiniMessage, it seems that I can't put an argument as the key in a lang tag, so <lang:<key_arg>> doesn't work. Does this work as intended?

rare sage
#

you'd need to use a Placeholder.parsed for that kinda stuff

oak forge
#

Okay, another question:
I created a method that can deep clean styling from a component and I want to turn that into a minimessage tag, but I don't know which one to use. I tried Modifying but that duplicates my component because of how it works internally, doesn't seem to be made for what I'm trying to do.

sweet hornet
cloud vapor
#

like quite intensely stupid both in a) the fact it exists and b) the way it was implemented

#

the fact that they could achieve the exact same things they are forking for with api is just sad

prisma mason
#

What chars are allowed for a tag name? The pygments suggests any char goes (except ofcourse [>:'"])

fiery oracle
prisma mason
#

alr thanks ❤️

molten jasper
#

how do i send message to all players on server using Audiences?

wet kestrel
#

Depends on the server software. What's yours?

#

Paper, for instance, has methods on Server.

molten jasper
#

yeah paper

#

im using audiences first time i already have some class that im using for general context player messages however now i want to send message to all players on arena that the match is cancelled

quick urchin
#

if you have one arena per server of world then it's easy, since those both implement audience

molten jasper
#

so i coudl do this by doing for player : players player.sendMessage(ServerMessage.error(playerData.getPlayerLanguage, "info.match.players.failedtoconnect"))) smth like this

molten jasper
molten jasper
#

so i'd love to do this using audiences as i believe this is the right way?

#

well now i realised its actually not the case in my case because im getting playerLanguage for each player and by audiences i would send the same message to everyone

quiet sluice
molten jasper
#

yeah yeah just realised

#

well then

#

some time lost on this

sweet hornet
#

It seems you’re using some kind of i18n, but not adventure’s one. Any reason for this? Because with built-in localisation system, you could get the best of both worlds: using the server as audience and player-specific localised messages

#

With something alongs the lines of:

Bukkit.getServer().sendMessage(Component.translatable("my.message.key"));
molten jasper
#

and they might prefer play minecraft in english and mini game in their own language because some of the information is complex

sweet hornet
#

So, the locale is fixed on the server?

molten jasper
#

the locale that i use for server messages is server based yeah

#

its stored in player's settings

#

so they can play minecraft in chinese and server in french or whatever

sweet hornet
#

So you could just configure the adventure translation system to do server-side translation based on the configured language, I guess

molten jasper
#

That's something im doing to some extent im just dynamically injecting player's language into adventure translation system

#
    public static Component translated(Locale locale, String key, Component... args) {
        return GlobalTranslator.translator().translate(Component.translatable(key, args), locale);
    }
#
return Component messageComponent = translated(locale, messageKey, args);
}```
#

and im injecting the player's locale on the run

sweet hornet
#

Ok, but if you wire things correctly, I think you shouldn't need to send different components to individual players

#

Because if you correctly configure server-side translation on Paper, it is done when the actual component is being sent to the player

#

So you just have to send the same translatable component to everyone (which can be achieved easily through the fact that Server implements Audience to forward messages to all online players)

molten jasper
#

Ahhh yeah i get it now

#

yeah i was using it wrong i believe

#

right right and then i should be able to for example send GlobalTranslator.translator().translate(Component.translatable(key, args), playerdata.locale);

#

right?

#

my bad but i didnt understand it quite well when i started doing this

#

well that changes a lot

#

Yeah that was really helpfull that will actually work but it needs much changes in code at this point but ig that's the way to go

sweet hornet
#

I actually don't have much experience myself with that localisation system, but this documentation page should provide you with most of the info: https://docs.advntr.dev/localization.html

molten jasper
#

Yeah i mean i understand it to the part where audiences don't make their appearence

boreal orchid
#

as far I understand it, shouldn't you be able to just send the translatable component, and Paper should render it under the hood?

molten jasper
#

yeah that's kind of to what conclusion we came there the way i was using it before is i rendered it before using it later in my code

#

i was using this function

    public static Component translated(Locale locale, String key, Component... args) {
        return GlobalTranslator.translator().translate(Component.translatable(key, args), locale);
    }
``` which already translated it
molten jasper
#

audience.sendMessage(Translatable , locale)

#

however players from audience have diffrent locales right

sweet hornet
# molten jasper Yeah i mean i understand it to the part where audiences don't make their appeare...

Audiences really aren't a complex concept at all. An audience is just "something that may be able to handle messages/titles/actionbar/...". The most simple audience being a player. And then, there's the useful concept of "forwarding audiences", which are audiences that simply forward everything they receive to some others. A team is a good example, it forwards to every players part of that team. A world forwards to all players in that world. The server to all online players... You can define your own audiences to simplify the handling of "a list of targets" for instance.
And another nice concept of audiences is that they silently ignore any request they couldn't handle. For example, the console is an audience, it can receive messages, but not titles. If it do receive one, it will just ignore it, so that a forwarding audience forwarding both to a player, and the console, if you send it a message, both will receive it, and if you send a title, the player will receive it and the console ignore it

#

There is no special relation between audiences and translatable components, the audience just provides a standard interface with methods you can call with components (which can be translatable ones) if you want

molten jasper
#

yeah yeah so that's where this complexity comes in because if you want translated message to come out for players you just send translatable component and players locale but if there is a group of players with diffrent locales?

sweet hornet
#

Translatable components doesn't comes with locale

molten jasper
#

but translating it needs a locale?

sweet hornet
#

A translatable component is locale-independent, it only contains a translation key and arguments (and possibly a fallback string in case the key is unknown, but in a correctly configured environment, this isn't needed)

#

Technically speaking, you could just send the component to the player as-is. Minecraft will process it, however it will likely don't know how to translate it, causing the raw translation key to appear

#

(Unless the translation key is one of the existing Minecraft message, or the client has a resource pack with a language file containing a message for this key)

#

This would be client-side translation

#

But in your case, you want server-side translation

#

And Paper & Adventure allow this to be done fairly easily, with the GlobalTranslator

#

On one hand, you configure the translator so it knows how to resolve translatable components (= turn them into text components, using the player's locale (and you may be able to override the way the locale is selected, but I'm unsure about that), and the messages associated to their translation key, for each locale)

molten jasper
#

yeah so im doing it at this point for singular components right

sweet hornet
#

And on the other hand, you just send raw translatable components to audiences, and Paper will automatically call the translator on them for each player that will receive that component

molten jasper
#

yeah but translator won't know what to translate it for each player because it doesnt have this knowledge

#

he has knowledge on how to translate the translatables but he needs to know what to translate it to or else he will just change it to default

sweet hornet
#

Hence why you need to provide him that knowledge by configuring it as explained in the doc I linked you above

molten jasper
#

hmm yeah ill work on it

rare sage
serene hare
#

redirecting this question here.

instead of Locale.ROOT should i use Locale.US for fallbacks?

cloud vapor
#

use whatever locale you want for the default

hexed field
#

looking at SoundStop, is there a way to stop all sounds except a specific sound?

sand drift
#

No

obsidian nimbus
#

couldnt you just iterate thru all sound

hexed field
#

yeah i was hoping to not have to do that but i'll give that a try

serene hare
# cloud vapor use whatever locale you want for the default

wdym?
maybe i was not clear: i have a locale file (written in english) that i want to use as a fallback if the client's current language isn't supported by my plugin.

e.g.

  1. show fallback text (english) if the user locale is german and i do not have a german specific language file

  2. show fallback text only for the keys that are not in the matched locale file (the plugin has a german locale file but it's missing a key that exists in the fallback file)

honest ermine
#

is there a way to Clear/stop a title and/or action bar?

fiery oracle
#

couldn't you send an empty one?

boreal orchid
cloud vapor
serene hare
cloud vapor
#

yes fallbacks can only be strings

serene hare
#

i lose all the fancy formatting then

cloud vapor
#

what you could do in your case is:

  1. override contains to always return true
  2. override translate to call super and if null return a custom message
#

bear in mind that will break every single other plugin and translatable component if you register that store to the global translator

#

but idk why you'd want to do that in the first place, standard practice for translatable messages is to just return the key if anything is missing

serene hare
serene hare
sweet hornet
#

Not a fallback message for every unknown key

cloud vapor
#

that's not what they asked in their follow up message

sweet hornet
#

I think it's just a language barrier, it was weirdly worded 😅

serene hare
cloud vapor
#

in that case just set the default locale for the store

serene hare
cloud vapor
#

yes

serene hare
# cloud vapor yes

well that's easy, should I do it before adding the store to the globaltranslator?

cloud vapor
#

doesn't matter when really

serene hare
#

surely before showing text to players i'd imagine

cloud vapor
#

yes

bright remnantBOT
prisma mason
#

what are the allowed chars for non string arguments? anything?

sweet hornet
#

"non-string arguments"?

#

Wdym

prisma mason
#

for example hover's show_text and such

rare sage
#

either i am sleep deprived or your question does not make any sense

#

allowed chars where for what kind of non-string arguments?

prisma mason
#
<hover:show_text:'<red>test'>TEST

Here '<red>test' is a string arg, while show_text is a "non-string" arg

sweet hornet
#

This is a string as well

#

You mean "quoted" vs "unquoted" maybe?

prisma mason
#

I'm having trouble understanding the source code, but from what I understood anything goes untill it reaches : if it's not in a URL

prisma mason
sweet hornet
#

You need to quote arguments if they contains <, :, > or (space). Maybe others, but those ones are the most obvious ones

rare sage
#

spaces i believe are allowed

sweet hornet
#

Ah?

cloud vapor
#

yeah they are

sweet hornet
#

Ok mb, it's only in the tag name where they aren't then ig

prisma mason
#

alright thanks

restive aspen
#
        TextReplacementConfig replacement = TextReplacementConfig.builder()
                .matchLiteral("%frequency%").replacement(String.valueOf(settings.getFrequency()))
                .matchLiteral("%radius%").replacement(String.valueOf(settings.getRadius()))
                .build();

I assume this isn't ok because I added the second literal match and now nothing is replaced. What should I do instead of this?

cloud vapor
#

You should use a framework/library that has built in placeholder support e.g. MiniMessage

#

TextReplacementConfig only replaces one thing at a time, you're replacing the frequency literal with the radius literal matching there

restive aspen
#

I'm actually using minimessage already

cloud vapor
#

Then why aren't you using its placeholder system?

restive aspen
cloud vapor
#

Yeah

restive aspen
#

i had no idea it existed withinin mm until now

cloud vapor
#

well there ya go :p

restive aspen
#

Do placeholders have to be <some> with < >

sweet hornet
#

Yeah, all tags are formatted like this

restive aspen
#

So how should I go about replacing placeholders in an ItemStack displayName()

cloud vapor
#

Why are you doing it on the component? Aren't you starting with a MiniMessage string?

restive aspen
#

I'm not actually I was wrong I have an ItemStack and I need to replace placeholders in its name component

cloud vapor
#

why are there placeholders in the component name of the item stack?

#

who/what put them there?

restive aspen
#

I have an ItemStack in my configuration file for users to edit

#

and you can have placeholders in the display name which will contain dynamic information about the item so it needs replacing

sweet hornet
#

But why don't you parse the components when reading the item stack from the config?

restive aspen
#

i use a config library which just gives me an itemstack

#

thats out of my control

#

im not going to switch library at the moment as it's too much work

restive aspen
cloud vapor
#

string != component

sand drift
#

Well, yea, because your input would be the raw string from the config in that case, rather than having to run around a roundabout and have to potentially deal with messing to parse out something or losing data in the process

cloud vapor
#

you should either a) make your config library let you use minimessage or b) plain text serialize the item name and recreate it as a component using MiniMessage

restive aspen
sand drift
#

all of the plain text formats bar MM will discard any rich formatting, and MM will escape any tag inside of the content of a tag

restive aspen
#

ok so serialize the name and use mm to recreate a component and replace its placeholders

restive aspen
# cloud vapor you should either a) make your config library let you use minimessage or b) plai...

a) make your config library let you use minimessage
just out of curiosity, how would a change to the config library work? if i save an ItemStack in the config then will the library still not return me an ItemStack? Where about does MM come into play here and where does everything get replaced? The replacements happen when a user runs a command e.g /specialcommand <frequency> <radius> so it needs to replace it here not when reading from the config initially right?

sand drift
#

not having a raw itemstack pulled from the config would give you many dozen potential code options depending on the route you wanted to go down

restive aspen
#

ok so dont store item stacks and store mm strings instead

cloud vapor
#

yep, you'll find that much easier to deal with

upper tinselBOT
sterile rampart
#

"too much" is meaningless

serene hare
#

how can i reload/register again the translations in a TranslationStore?

cloud vapor
#

If you're using the global translator, you can unregister the store from its key and then register a new one

serene hare
forest meteor
#

how did we get closest namedtextcolor again?

#

from textcolor

dense veldt
#

NamedTextColor#nearestTo(TextColor)

serene hare
cloud vapor
#

You can just swap the store you're using

#

or call unregister

#

or just register everything again (im p sure they replace)

serene hare
cloud vapor
#

yeah like just make a new one

serene hare
#

and register the translations again

serene hare
rare sage
#

it doesn't replace

#

frankly i'd just recreate it, it's the easiest

serene hare
#

also, what's the need of the key when creating a TrnaslationStore?
TranslationStore.messageFormat(Key.key("namespace:value"));

rare sage
#

well if you are adding it to the global translator it needs to be identified

serene hare
#

and if I'm not?

serene hare
rare sage
#

idk debugging?

#

even if you're not you still have to pass one in

#

and it doesn't hurt anyone, so like

serene hare
#

yeah yeah, just for my knowledge

forest relic
#

does adventure support on legacy ? (1.8 - 1.21)

rare sage
#

the adventure api is version agnostic for the most part, then each implementing platform chooses what versions it supports

serene hare
#

does the console have a locale?

serene hare
#

and how i can get the locale() from an audience object?

sweet hornet
#

Using pointer iirc

serene hare
#

ok i figured it out what pointers are, but if I have this.audience.get(Identity.LOCALE), what happens if multiple players are included in the audience?

fiery oracle
#

where are you getting this audience from?

serene hare
#

command sender, and occasionally casting player to Audience to have a standard thing where I don't have directly access to an audience object

fiery oracle
#

forwarding audiences (generally) don't expose any pointers

serene hare
fiery oracle
#

i mean, what exactly are you doing?

serene hare
#

creating an helper for sending messages

#

but i need the locale to translate to

wicked torrent
#

then you want to unwrap any forwarding audiences and iterate them yourself

#

or use the translation api

serene hare
wicked torrent
serene hare
fiery oracle
#

?
if you're using the global translator, you don't need to render the components yourself

serene hare
#

i'm not using the global translator, i use an unregistered translationstore

static flare
#

Is there a way to nest a <selector> inside a show_text hover?

I have this:

"<hover:show_text:'<selector:@a[team=Hider]>'>" + " <aqua>" + hiderTeam.getSize() + " <gray>players remaining." + "</hover>"

but in game it just puts the selector value as the hover text

#

I would bet that it is just a syntax error that im missing but cant seem to get it to work with trial and error

wicked torrent
#

selectors must be resolved manually unless you use it in a spot where that happens automatically

#

which I forget what they are if any exist

#

each platform may provide API for it

#

PaperComponents in Paper

static flare
#

got it working, thanks

serene hare
#

Which is a class common to both CommandSender and Player?

I would like to make a method that sends a custom message and didn't wanted to make a different for each type

rare sage
#

.. Audience?

serene hare
#

But Audience can be also multiple targets?

#

Like 2 players in a single Audience object? Or that's the ForwardingAudience

rare sage
#

that would fall under forwarding audience, yes

serene hare
#

So Audience refers to a single target

rare sage
#

i mean, ForwardingAudience extends Audience to make it easier to, well, forward all the method calls to the forwarded audiences

serene hare
#

And I could get the locale of that target with audience.get(Identity.LOCALE)?

rare sage
#

and which of the forwarded audiences would it get the pointer for?

serene hare
#

I don't want to use forwardingaudience

rare sage
#

then don't use it

serene hare
#

I'm using a translation store without registering it to the global translator

#

So I'm handling all of the translations manually, and creating an helper class to do so

rare sage
#

you'd need to explode forwarding audiences to their individual audiences

serene hare
#

The problem is that I want to make a method like "MyHelper#sendMessage" that can take both a CommandSender and a Player

#

And then get the locale of the player/commandsender (or use default locale if sender is console as it doesn't have a locale)

rare sage
#

take an audience, and explode forwarding audiences recursively to send the message to the individual audiences

serene hare
#

But only the Player object has locale() method

rare sage
#

okay

serene hare
rare sage
#

no need to check for player, just check that the pointer value is not empty

#

getOrDefault(Identity.LOCALE, defaultLocale)

#

but you need to explode forwarding audiences and recursively call the method

sweet hornet
#

(to answer strictly to your question)

serene hare
sweet hornet
#

That's a solution, but just to be sure: If you simply want to send messages to either CommandSender or Player, you just need to write your function for CommandSender, since Player extends it

cloud vapor
#

feels like you just wanna look at forEachAudience

#

that will give you a consumer for each individual audience member in any forwarding audience

#

or just one call for any single audiences

serene hare
rare sage
#

you can just use the pointer, man

#

it's not rocket science 😭

serene hare
#

Yeah yeah, I was just replying

serene hare
#

And use the pointer to get the locale, if any

#

And then use my translator and send the message

sweet hornet
#

That's it

serene hare
#

Seems right?

#

I'll try when I'll be back home from work

gloomy thicket
#

how do i turn off formatting in specific selection of text?

#

i have chat message formatting like this

#

Text: '<hover:show_text:''<i><lgray>Message was sent at: <white>%localtime_time_hh:MM:ss%</white></lgray></i>''>%ezcolors_color%%message%</hover>'

#

but if players include < in their chat message

#

it gets ruined

gloomy thicket
sweet hornet
#

And why not use MM tag system for placeholders?

robust wharf
#

Use proper MiniMessage placeholders and not whatever % system you have there

#

Those can be parsed and unparsed (what you want)

gloomy thicket
#

which placeholders?

#

i just use what plugin provided (sunlight)

robust wharf
#

That is a really glaring bug/exploit in that plugin then and should be reported

gloomy thicket
#

what other things can players do with it?

robust wharf
#

Send click events for example

gloomy thicket
#

oh

#

shit

robust wharf
#

With open url stuff

cloud vapor
#

Anyone could just type <click:run_command:/op kezz101>here's my normal chat message heheeh

robust wharf
#

Or suggesting commands

gloomy thicket
#

what minimessage placeholder should i try???

cloud vapor
#

there's no placeholder that'll fix this, you need to get the plugin to use placeholders properly

#

if, e.g. %message% was instead a component placeholder no minimessage tags would get parsed in it at all

robust wharf
#

Basically the code needs to be fixed that you can define the message via <message> and not %message%

gloomy thicket
#

alr

#

ill contact the author

cloud vapor
#

if you direct them here we'll be happy to help them switch over

gloomy thicket
#

@daring root

#

i think this is the guy

gloomy thicket
daring root
supple whale
#

Hello, I'm using ClickEvent to run a command, how can I disable the confirmation to run the command?

sweet hornet
#

You can't, basically

#

It's client-side on modern Minecraft

#

However, iirc it only shows that confirmation for commands that are either unrecognized (by the client), or privileged (requiring OP in vanilla)

supple whale
#

i'm doing [inv] in chat, and when I click to [inv] I run a command, other server has this function and they don't ask to confirm the run

sweet hornet
#

So maybe you can make a command that is not perceived by the client as priviliged, while still maintaining the server-side checks to ensure only authorized users can run it

#

But I don't know the details about how to do that, neither if it would work

supple whale
#

my command has no permission

sweet hornet
#

Can you show the confirmation screen plz?

sweet hornet
#

Can you translate the text in english? 😅

#

Mostly the second line

#

Is it refering to a privileged command, or an unknown one?

#

"non riconosciuto o invalido" seems to means "unrecognized or invalid", right?

#

If that is the case, then your problem is that the client doesn't know about this command (i.e., if you type it in chat, it'll be shown as unknown, in red)

supple whale
serene hare
#
ctx.source.sender.sendMessage("&8&m+----------+&r $prefix &8&m+----------+")
ctx.source.sender.sendMessage("")
ctx.source.sender.sendMessage("   &7Author: &b" + Plugin.pluginMeta.authors[0])
ctx.source.sender.sendMessage("")
ctx.source.sender.sendMessage("   &7Version: &bv" + Plugin.pluginMeta.version)
ctx.source.sender.sendMessage("")
ctx.source.sender.sendMessage("&8&m+----------+&r $prefix &8&m+----------+")

What would be the best way to replicate that using MiniMessage?

boreal orchid
# serene hare ```kotlin ctx.source.sender.sendMessage("&8&m+----------+&r $prefix &8&m+-------...
ctx.source.sender.sendRichMessage("<dark_gray><st>+----------+</st></dark_gray> $prefix <dark_gray><st>+----------+");
ctx.source.sender.sendRichMessage("");
ctx.source.sender.sendRichMessage("   <gray>Author: <aqua>" + Plugin.pluginMeta.authors().get(0));
ctx.source.sender.sendRichMessage("");
ctx.source.sender.sendRichMessage("   <gray>Version: <aqua>v" + Plugin.pluginMeta.version());
ctx.source.sender.sendRichMessage("");
ctx.source.sender.sendRichMessage("<dark_gray><st>+----------+</st></dark_gray> $prefix <dark_gray><st>+----------+");
serene hare