#adventure-help

1 messages Β· Page 1 of 1 (latest)

hazy thicket
#
I was here!
sterile rampart
tender egret
#

hiiiii

sour oak
#

whats this?

misty marten
#

wow

orchid star
#

Fifth

keen nacelle
#

Wow

icy locust
#

hi

wispy elm
#

same, havent heared of adventure yet. checking it out rn

young meteor
snow spade
#

hiya all

wispy elm
#

hi:)

sour oak
#

ahhh okk, dev stuff

young meteor
fathom mulch
#

Dibs

cosmic loom
#

hell yeah

proud vapor
#

yo

deep scarab
#

yoooo, welcome new official papermc devs :D

delicate zephyr
#

Hello!

gloomy thicket
#

Xd

long pasture
#

πŸ‘‹

brazen vessel
#

party time?

ocean agate
#

hello

obsidian zodiac
#

Isn't Kezz a Mcc dev?

full tartan
#

Yooow

#

what is this "adevnture" thing

hazy thicket
#

20+ messages here and all off-topic kekw

misty marten
#

this merger is really cool, Adventure is a great thing

half matrix
#

Is this the adventure with the components and shit? Or am I brain dead

misty marten
half matrix
#

Oh hell yeah

half matrix
#

But things like the ansi serializer and compatibility with other platforms will keep existing right?

cosmic loom
odd jungle
#

What adventure is for?

#

Is that for server admins or for plugin creators?

foggy wharf
#

hey!

barren basalt
misty marten
misty marten
keen bluff
obsidian zodiac
#

yo, this is sick

odd jungle
#

Oh damn no thx skript my beloved

misty marten
#

lol really not many people know what that is?

ruby locust
#

Looks like it πŸ‘€

foggy wharf
naive sun
#

hi chat whats adventure

#

what it do

quaint monolith
#

It's a developer thing, there is nothing to screenshot

sour quarry
sterile rampart
naive sun
foggy wharf
sour quarry
#

(Though I expect help with Minimessage as an admin will be directed here now)

sterile rampart
#

like, server admin side MiniMessage is the most visible thing yeah

quaint monolith
#

It's how developers do formatted chat and items and such

fleet crown
#

But it already was in Paper, wasn't it?

quaint monolith
#

Like putting colors and clickable links and such

keen bluff
#

Adventure is mainly a text component library. Makes it easier to create cool text components for chat, and other places.

quaint monolith
#

Yes Paper has used it since 1.17

naive sun
#

boring vexedtomato

#

folia stable release eta wen /j

sterile rampart
#

yeah, it's mostly an administrative change lol

sour quarry
naive sun
hexed haven
#

what does "user-interface project" even mean

naive sun
#

announcements were looking dry anyway

keen bluff
quaint monolith
#

The ways you interact with users are inventory and text, adventure is the text parts πŸ˜›

misty marten
#

Guys, Adventure is (in my experience of using it) a library that allows developers to make text components, work with sound events, bossbars and everything else more conveniently, there's nothing to screenshot and show, you have to try it.

drowsy shuttle
#

this channel opened 10 mins ago damn?

quaint monolith
#

Oh yeah, and bossbars and sounds and such

sour oak
hexed haven
#

so i guess its not like a full merger?

tender egret
#

can we get a minimessage channel

quaint monolith
#

adventure still exists as a project and supports non-Paper things so not a full merger

analog mist
#

whoop goodjob

sour oak
urban garnet
#

t

mighty cove
#

What is user interface?

#

Any exemplars?

#

Docs?

upper tinselBOT
misty marten
#

guys, do you think using components like this is more convenient than the standard library?

wispy lichen
wispy wagon
sour quarry
#

Use Minimessage placeholders, don't replace it after the fact (that's breaking because each letter is split up into a differently-colored compoinents)

wispy lichen
#

Well but then it shouldn't work for static colored components aswell or?

#

oh...

wispy wagon
wispy lichen
#

i got it..

#

bru

#

thanks I guess

quaint monolith
#

Use placeholders or do the replacement before you deserialize it

dark flume
#

I dont get what adventure is for and what it is used for

misty marten
#
dark flume
#

Dope

misty marten
#

Adventure is a library for server-controllable user interface elements in Minecraft: Java Edition.

#

kinda

quaint monolith
#

It's been in paper since 1.17 so there is nothing new if you're making plugins

#

It's just some organizational changes

#

1.16? Somewhere around there

dark flume
#

Mostly never made plug-ins except some security plug-ins to link with my backend

hot trellis
#

ClickCallback is updating itemstack to air ? In the image I had clicked on the message which displayed that I was wearing the helmet, then i took the helmet off, but the callback shouldnt update ?

robust wharf
#

Can you share your code?

#

The callback code will always be called when you click, it doesn't store any state

hot trellis
#

contentToUpdate is outside the callback area, so it shouldnt be touched besides running through the loop

robust wharf
#

Mmh, those arrays might be a live view and you need to clone them, can't check implementation of those two get methods rn, am on mobile

hot trellis
#

its ItemStack[]

#

which is primitive I think?

#

maybe

#

shit idk

robust wharf
#

Well, you can try cloning it

#

But that's the only way I can explain the behavior you are seeing rn

pseudo ravine
#

When will adventure fully gets implemented in velocity? Atleast the sound part

robust wharf
#

Is there an issue explaining what is missing?.

#

If so, people can start working on it πŸ™‚

sand drift
#

Sound can be done in newer versions, but, for older versions that will never happen

#

This is generally just the joys of a 10 mile todo list

gritty geyser
#

so uh wahts adventure

robust wharf
#

It's the way plugin devs send messages or set the lore of items and stuff

faint zealot
#

Let's go

shrewd carbon
#

what's this

cloud vapor
#

Adventure is a library that provides cross platform API for text, sound, boss bars, action bars, etc, etc

#

If you've used Component or MiniMessage anywhere, that's adventure!

brisk meadow
#

Is there a plugin using Adventure yet?

bold fox
#

Component.text() is from adventure

cloud vapor
#

Plenty of plugins yeah

brisk meadow
#

Ohhhh, that's cool!

bold fox
#

so, all plugins that do not use legacy chat KEKW

brisk meadow
#

yep cool_doge

prisma mason
#

One question about this merge, does this mean the JavaDocs will also get merged or will they stay separated?

cloud vapor
#

Adventure is still independent of Paper the server software so yes the javadocs will remain separated

#

I'm not sure what our plans are in terms of moving over to the paper docs, but nothing for a while as it's low prio regardless

rare sage
#

i think they mean whether the javadocs will be hosted on jd.papermc.io

#

/adventure or something

#

they will certainly not be merged with the paper api jd

pseudo ravine
rare sage
#

yes

#

and that remains true on the proxy

prisma mason
#

now that I think of it, I realise why its stupid

cerulean delta
#

Hey, forgive me if this is obvious, but does Kyori have any way to test effective equality, rather than data-structure equality? The easiest example being an item's display name set via meta.setDisplayName("Hello") vs meta.displayName(Component.text("Hello")), though my question isn't just limited to that.

Like, let's say for whatever reason that someone did:

final Component lhs = Component.text("").append(
    Component.text("").append(
        Component.text("Hello")
    )
);

final Component rhs = LegacyComponentSerializer.legacySection().deserialize("Β§rHello");

Is there a strategy somewhere of how to test whether these 'compile' to an identical chat message?

swift holly
#

Hello does anyone know if the Adventure is the same as the Minimessage format?

cosmic loom
#

minimessage is by adventure

#

not sure what you mean

swift holly
#

How do I get it on my server?

wet kestrel
#

It's built into Paper already, has been for years

cosmic loom
#

it's included since like 1.16.3

wet kestrel
#

Plugins support it (or don't, if they're outdated or making... interesting... choices)

swift holly
#

Cuz I watched a video by 'KassaiSora' on yt ABT using the Minimessage format, and he also said about installing Carbonchat, but when I use the <colour> tag in my paper 1.20.1 server, it comes out as plain text 😦

wet kestrel
#

Yeah, CarbonChat supports minimessage. Talk to them for further help on that.

#

Also, you really need to upgrade your server. It's full of exploits

upper tinselBOT
swift holly
#

I don't even know what Carbonchat does, I just installed it

wet kestrel
#

It's a chat plugin. Read its docs.

swift holly
#

Does essentialsXChat support it

swift holly
wet kestrel
#

Those plugins are surely dead at this point, if they're not updated past autumn 2023.

#

It's time to move on. It was time to move on a year ago. A full year ago, you would have already been past the point where you should have been on 1.20.4, abandoning dead plugins.

swift holly
#

B-But they're no alternatives

#

I just think mojang updates are just too frequent but don't add/remove/change alot

wet kestrel
#

The updates have been pretty spread out. Dead plugins are just dead. If you want to continue this chat, let's take it to #general , as this channel isn't meant for explaining to people why they shouldn't run exploitable software.

swift holly
#

Ohok I'll try updating tysm

#

Which do U think I should update to?

wet kestrel
#

1.21.4

swift holly
#

??? 😭

wet kestrel
swift holly
#

Okk

rare sage
#

the very latest, previous versions have known, widespread dupe and crash exploits

swift holly
#

Ok can someone still explain to me why MN format isn't working

#

Please

#

Does it support EssentialsXChat?

wet kestrel
#

MiniMessage format works fine. Your issue is with a plugin. I already told you to look to that plugin for help.

#

Carbon 100% supports adventure. I don't know about EssX, but you could ask them.

swift holly
#

What do you think is the best message formatting plugin

wet kestrel
#

I like Carbon

swift holly
#

Idk how to configure it, the data folder is empty

wet kestrel
#

Okay.

#

If you ignore the suggestion of reading their documentation and looking to their support system, I don't know what else to tell you.

swift holly
#

Sorry

#

Too excited

#

Also..

#

Does the MM support GeyserMC?

#

Do the hex codes work or they get replaced with default colours?

sand drift
#

MM is just a component serialiser

#

Past that, it's up to how your platform deals with the component

robust wharf
cerulean delta
swift holly
#

U mean if they support hex codes at all?

robust wharf
#

Adventure doesn't provide a way to do what you want since normally there isn't a need to and it's actually quite complex

#

You will have to use some form of serializer or just do stuff properly

sand drift
#

given that afaik, bedrock doesn't support RGB, they'll likely just downscale it

wet kestrel
#

Just like your other questions about plugins Paper doesn't make, Turbo, this is a question for Geyser.

wet kestrel
#

That's up to Mojang, buddy.

swift holly
#

So I cant get any other colour from the ones in the colour kit in essentials?

wet kestrel
#

Nobody said that.

#

If EssX supports hex, you can do hex in Java. Which Paper is.

#

Further EssX support belongs with EssX. Which is something I've told you before.

#

I'm worried by how much you keep ignoring what I say. 😦

swift holly
#

O-ok?...

#

What about GeyserMC

#

That's what I don't get

sand drift
#

They're a protocol translation layer, they'll only support what the protocol supports

wet kestrel
#

You need to read all replies you get to your questions.

rare sage
#

no, bedrock does not support hex, bedrock players will not see the full rgb spectrum, java players will

sand drift
#

You can use hex inside of a component, but, bedrock will not support showing the RGB, they'll likely downscale it to the closest color it can

rare sage
#

mojang choices

sand drift
#

Because Mojang didn't implement RGB support there

rare sage
#

it's a limitation on the bedrock side of things

swift holly
#

I hate mojangggggggg

#

Ugh

swift holly
rare sage
#

bedrock is

wet kestrel
#

It's only limited for bedrock players. You can still use hex for java players.

swift holly
#

So I'm only limited to this on bedrock?:

wet kestrel
#

Which has been stated already, repeatedly.

swift holly
#

Ok

wet kestrel
#

We're not bedrock support

#

We're not Geyser support

swift holly
#

It hurts

wet kestrel
#

We support Paper, which is for Java edition.

swift holly
#

And I can't use MM!

bright remnantBOT
#

(67b897ab6ed5010734cf1b87) // @sour silo (@drjoehn / 656146295555358736) has been warned by @wet kestrel (71627708521512960)
Reason: Be polite. There is no reason to attack other users.

swift holly
#

Bro πŸ’€

wet kestrel
#

If you continue to ignore our replies and keep repeating yourself, you will be timed out because this is getting too cyclical.

swift holly
#

Oh one more thing

#

I've been looking to modify death messages, is there a plugin that allows you to modify the death messages for each damage/type?. So basically let's say I wanna modify the death messages caused by PvP, in the config or smthg, I can give lists of messages(with the victim+killer placeholders included obv) and the plugin with choose anyone from that category at random to display in game, and so on and so forth for other damage/death type

#

Pleasee

wet kestrel
#

that's not an adventure question. Repost that in #general

swift holly
#

Yes yes can't wait!

#

Oh sorry

cerulean delta
# robust wharf So I guessed weird and this is the wrong approach, pdc should be used instead

Yeeaaaah, I agree. Honestly, and this is well outside the scope of Adventure, but it would be awesome if we could register custom materials, but also be able to add item visuals at network-time. Setting a custom-item flag on a PDC is great, but then what if you want some explanatory lore? But then what if later you realise the lore has a typo? If the lore was added at only at network-time, it's never actually on the item, then you can just change the network-time lore without needing to do any kind of DataFixer or similar.

robust wharf
#

You wouldnt set a flag, you would set a custom item type string as pdc

cerulean delta
#

Oh yeah, that's what I meant

wet kestrel
#

You can also typo-fix the lore on the item by detecting it with the PDC

sick vortex
#

Just wanted to drop in and say, it's cool Adventure finally merged into Paper!

celest lion
#

adventure has been in paper for years

cloud vapor
#

Merged into PaperMC the organisation :p

graceful kestrel
#

o_O

prime sigil
#

πŸ‘€

misty marten
#

Where is Sound.Source.RECORD used? Is this used for a music disc? Or is Source.MUSIC used for a music disc?

graceful kestrel
#
Minecraft Wiki

Sounds are auditory outputs of the game intended to communicate the happening of certain events, as well as create atmosphere. Different objects such as mobs, weapons or blocks have sounds.

celest lion
hoary plume
robust wharf
#

The lack of support for named arguments strikes again

#

No clue how such a tag would look like

hoary plume
#

Maybe use the lack of named args as an advantage?
Like f.e. <lang:commands.drop.success.single:'1':'Stone':fallback='You droped something...'>
Tho, maybe a dedicated tag with the first arg being the fallback would be a bit better to not break existing setups

#

Or alternatively have an arg prefixed with a specific character to identify as fallback.

#

And another question.... Can I access translatables from non-mc namespaces (i.e. from resource packs)?

bold fox
#

in MM? yea, they are not rendered out

hoary plume
#

Your reply is a bit confusing... Is it supported or not?

bold fox
#

Well "access" is a weird word

#

you are just specifying the key of a translatable component

#

you can put whatever you want there

#

it is only actually "converted" on the client

hoary plume
#

I wasn't sure, given the file would be in a namespace that isn't Minecraft and I don't know how it would be identified

cloud vapor
#

I don't want to add named args

bold fox
#

I am semi certain the lang stuff isn't namespaced

cloud vapor
#

I'd much rather <translatable_with_fallback:fallback:args>

#

Yeah languages aren't namespaced, they're just keys

hoary plume
#

I think translatable would be enough.
Just the diff towards lang would need to be made clear.

cloud vapor
#

We already have translatable as an alias for lang

hoary plume
#

oh, rip

cloud vapor
#

Oh, we don't - but either way that's confusing

#

Fallback is a pretty niche part of an already niche minimessage tag, I don't want to introduce more confusion. If you need such a tag, PRs would be welcome - but let's keep it clear

robust wharf
#

(and if you don't wanna PR, an issue would be appreciated too)

cerulean delta
# wet kestrel You can also typo-fix the lore on the item by detecting it with the PDC

Weeeell, yes, but these are legacy items: putting the custom-item-type string on the PDC would have to come after detecting an item with the lore, or otherwise it's effectively voiding any and all existing custom items of that type. It also doesn't play nicely with item.isSimilar, which is how these custom items are handled in code. As I said before, I have little to no control over this.

cloud vapor
#

Unfortunately beyond incredibly lossy serializers (e.g. plain text) or insanely complicated methods (e.g. idk, pixel comparison of rendering or smth) there are no good solutions for "effective" comparison because it doesn't make much sense

cerulean delta
#

Fair

cloud vapor
#

There are some bad solutions, you could try compacting both components and just hoping they end up the same

#

But yes, identifiers in PDC are what you (or whoever's code you're inheriting) should've done from the get go

cerulean delta
#

Another question though: does Kyori have, for want of a better word, component regexes? The XY of this is waypoints in chat messages (eg: [name:Some waypoint, x:5, y:0, z:125]), where a mod can find and replace that specific segment of the chat message with a clickable.

cerulean delta
#

This code goes back to serialising custom data as section codes in the 0th line of lore xD

cloud vapor
#

Well, yes, regexes exist :') See Component#replaxeText

cerulean delta
#

Agreed

bold fox
#

can recommend a full on DFU abuse during the next version upgrade of your server

cerulean delta
#

but tbf to them, it was the only solution at the time... trying to access item nbt was such a pita

cloud vapor
#

Yeah literally, don't keep shooting yourself in the foot - take your network offline for a few hours and migrate your data

#

Hacks upon hacks upon hacks upon hacks is not a good foundation

cerulean delta
#

We literally have a plugin called SimpleAdminHacks that's basically like 40 minuature plugins

cerulean delta
bold fox
#

Or that, tho that is a bit uff given it is a continuous thing sitting around

cloud vapor
#

You don't have to use DFU, but the concept of migrations is universally better than layers of hacks in your codebase

cerulean delta
#

Is there a way to use DFU, which uses a separate versioning system?

bold fox
#

Yea, back in the day when I did it, I just had a plugin iterate chunks on the server and load themomegaroll

#

no

#

Given we don't control those IDs, we/you basically have to hijack

cloud vapor
#

Migrations also aren't "check a thing every time a player joins" - idk if it would be a good thing for paper to support hacks like that

bold fox
#

Exposing DFU is just, not really a vibe KEKW

#

I'd rather not have plugins fuck up stuff, traceability is ass

cerulean delta
#

We currently have a custom item type, well, kind of, where every(?) single item has a "compacted" counterpart. And this is denoted by whether the item has "Compacted Item" in its last line of lore. Attempting to update this would be such a monumental pita and require so much testing. And then migrating all existing items into the new data structure...

cloud vapor
#

a PITA sure, but what's your alternative?

cerulean delta
#

Continue trucking along with everything still mostly working? :P

cloud vapor
#

Then you no longer need us haha

winter socket
#

Hello! What is the way to parse this sign into components (I assume 4 per side)
{back_text:{color:"black",has_glowing_text:0b,messages:['""','""','""','""']},front_text:{color:"black",has_glowing_text:0b,messages:['{"extra":["Test Sign"],"text":""}','{"extra":["Hello!"],"text":""}','""','""']},is_waxed:0b}

cloud vapor
cosmic loom
#

doubt is_waxed:0b is json

robust wharf
#

It's snbt

winter socket
#

oh yeah it is SNBT, the json serializer wouldn't work right?

winter socket
#

is there no way to parse these to components

glad sinew
#

is there anyway to like substring components?

plain glade
#

maybe there would be a better way to get the info

misty marten
wet kestrel
#

That's just going to work for the singular content of a text component.

wet kestrel
winter socket
#

I don't have access to the actual block

cloud vapor
#

The JSON serialised would work for the messages - not the rest of the nbt

glad sinew
#

Actually I resolved the issue using a custom method by serializing the component as minimessage, escaping minimessage tags and then with some math to substring the content with the colours

plain glade
plain glade
#

nvm, yeah, for a moment thought for some reason that escaping means removing

misty marten
cloud vapor
#

Why? What would you even need a substring for?.

#

If you share why you need it, we can point you to a better solution

wet kestrel
#

@misty marten ^

glad sinew
glad sinew
cosmic loom
#

i feel like you just want a substr of the actual content, not of the components

cloud vapor
#

The best solution for this would be to use a custom flattener that can create a list of components, adding to the list after every new character

#

Flatteners accept style and content independently, which would allow you to slowly reconstruct the component tree char by char

vivid bobcat
#

how to capitalize or toUpperCase toLowerCase a placeholder?
ex: Hello <player>
how to uppercase <player> result

graceful kestrel
#

Placeholder.parsed(β€œplayer”, player.getName().toUppercase()?

#

or whatever kind of placeholder you use

vivid bobcat
#

not possible to capitalize in the tag instead of hardcode

#

?

graceful kestrel
#

what?

vivid bobcat
#

nevermind

hoary plume
#

There are a few questions I feel like can/should be answered in a future faq about the move:

  • Will this have an impact on the domain used for documentation, javadocs, etc? Like will it eventually be moved under the papermc.io domain or remain separate?
  • Will this have an effect on the dependencies, like group id, repository URL, or similar?
graceful kestrel
#

repository url as in github or maven

wet kestrel
#

Any changes made, I imagine, would be made with the same sort of warning we have given for other things. Velocity's old domain still works, and redirects to the new paper site for example, and the groupId remains the same. Not an official statement, just noting previous project absorptions.

graceful kestrel
#

github repo's will be moved over, maven stuff will likely stay on central/sona

copper oriole
#

Is this where I ask why it's light_purple and not pink Ded

fiery oracle
#

i mean, that's just what it's called

#

ask mojang why they gave it that name if you disagree

torpid robin
sterile rampart
#

blame miku

sweet hornet
#

Hello, quick question, I think I already know the answer but I just want to know if someone already tried something, or had thought to share about an eventual implementation I could try.

Is there any way to compute a word-wrap operation on a component?
Having https://github.com/KyoriPowered/adventure/issues/499 would make it possible, but sounds pretty difficult to implement. Especially because we do not know the exact value and are thus unable to split some components (translatable being the obvious example).

The obvious use-case is to take a somewhat long component and split it into a list of smaller components, so it can be put in an item's lore without having an overflowing tooltip.
Ultimately, I agree Minecraft itself is able to do it client-side (cough Text Displays cough cough Chat cough) and should provide a way to do so for item's lore as well but... In the meantime it would be cool to find a way to do it! πŸ™‚

cloud vapor
#

There is no API for it - you should be allowing your users to configure lists of components so they can wrap themselves

#

It's something that would be nice to have, but it would require a lot of work, won't be fully accurate due to clientside font changes, and also has better alternatives (e.g. allowing users to define lists instead of doing the wrapping yourself)

sweet hornet
#

I'd like to, but unfortunately, this is kind of not really an appealing option for me... Just to give a little more insights about my use-case:
First, I am my own and only user, as this is a "simple" plugin for my server. The plugin deals with quest scrolls (you have an item generated by the plugin which gives you a quest to do).
Quests have objectives, like "Break 15 Diamond Ore in the mine", "Kill 50 Zombie, Skeleton, Spider or Creeper in the arena"...
Those objectives are defined through the config file of the plugin, by specifying the type (break blocks, kill entities...), the amount, and which blocks/entities/... count. Currently, the description of the quest (in the item's lore) is automatically generated by the plugin (using translatable components for blocks/entities), which is perfectly fine, except it overflows when given a long list of options. Having to manually write the description for each single quest would be very very time consuming (and a bit counter-productive because if we modify a quest, and forget to edit the description, it would break). And I also cannot really generate the description with line breaks, because with smaller list it would not be really good:

Break 15
Diamond Ore
in the mine
I could make some predefined templates depending on the number of options, but it would also not be ideal. And considering we have a lot of handy methods like Component#join for example, I thought this would also fit the API well

cloud vapor
#

It wouldn't fit in the API directly as it requires vanilla generated data (the width of every character) but I could see us adding support for automated wrapping of some sort if the user would supply that data

#

Unfortunately there is no such plans for this as it's quite considerably difficult as I mentioned above

sweet hornet
#

And I don't care about the exact accuracy of the wrap, I just need it to wrap somewhere near the nth character, even if it's approximately

cloud vapor
#

Wrapping with newlines is less complicated (you can mapChildrenDeep and character count, inserting a newline when needed) but in your case you need full splitting which is a lot more complicated

sweet hornet
cloud vapor
#

Flatten how?

#

You'd want to look into ComponentFlattener

sweet hornet
#

Oh

sweet hornet
# cloud vapor Flatten how?

For example (using JSON representation because it's easier to write here), turn:

{
  "text": "A",
  "color": "red",
  "extra": [
    {
      "text": "B",
      "italic": true,
      "extra": [ { "text": "C", "color": "green" } ]
    },
    { "text": "D", "color": "blue" }
  ]
}

Into:

{
  "text": "",
  "extra": [
    { "text": "A", "color": "red" },
    { "text": "B", "color": "red", "italic": true },
    { "text": "C", "color": "green", "italic": true },
    { "text": "D", "color": "blue" }
  ]
}
#

(Or basically just the list of components in extra, because the idea is to have a flat result, so no root content/style)

cloud vapor
#

I don't believe we have any API to produce components like that, although I'm not against such a thing being added as I can see the use cases

#

Your best bet would be a custom flattener impl yes

sweet hornet
#

Ok I'd have a look at it thanks

fathom mulch
#

How does one use gradients without minimessage?

cloud vapor
#

There is no API for it in adventure so you'd have to code it yourself

#

However, just use MiniMessage and save yourself the hassle :p

fathom mulch
#

I see

#

What if I added it to the API myself

#

How hard would it be?

cloud vapor
#

There is a WIP PR that was never finished (https://github.com/KyoriPowered/adventure/pull/1063), but the basic idea of it is quite nice (a generic gradient api with a list of positioned stops). I wouldn't want it to be overly complicated (I don't want us to introduce a full set of interfaces for alternative colour spaces as the original PR suggested was the end goal) but I'm happy for it to remain relatively generic to allow consumers to edit it as needed

fathom mulch
#

i see

#

very nice

raven tusk
#

how to make minimessage with "\"(new line) to List<Componenet>?

cloud vapor
#

You should just allow your users to supply a list

#

it's much more user friendly and you won't have to mess around with splitting text up

raven tusk
#

...?

#

No, no, I want to know the technical conversion method in a Java environment.

wet kestrel
#

Instead of starting with newline chars, start with a list.

#

kezz is pointing out that this is coming from a design error.

raven tusk
#

From what I remember there is something that automatically converts minimessages using \n.

cloud vapor
#

There is not

#

If you want a list of components, you should start with a list of minimessage strings

raven tusk
#

hmm... okay

sweet hornet
#

Is there a reason ComponentLike isn't ComponentBuilderApplicable? I mean, it sounds completely possible to add this to ComponentLike to make it extends ComponentBuilderApplicable:

default void componentBuilderApply(final @NotNull ComponentBuilder<?, ?> component) {
    component.append(this.asComponent());
}

Am I missing something? It would be handy to use ComponentLikes inside LinearComponents#linear

#

Especially given that LinearComponents#linear checks instanceof ComponentLike itself, despite not accepting this type

cloud vapor
#

Sounds like a fine addition yea

sweet hornet
#

Do you want me to make a PR or is it something to be handled by your team?

cloud vapor
#

Go for it!

#

PRs always welcome

raven tusk
cloud vapor
#

All you need is a for loop or streams, we don't have API for that in particular no

raven tusk
#

oh okay

empty briar
#

not so well tested lol but wanted to drop it in case it helps

sweet hornet
#

I’ll definitely have a look at it, thanks!

cerulean delta
# cerulean delta Another question though: does Kyori have, for want of a better word, component r...

Hey, so I've been playing with the solution to this question ⬆️ and I've hit a snag and I'm unsure how to go ahead without going full lexer.

It seems like the replaceText code is only testing the regex against individual components, meaning that a component like "[", "name: Some waypoint", ",", "x:5", ",", "y:0", ",", "z:125", "]" would fail because none of the individual parts would match the regex, even though, if they were combined, they would. Then I found .compact(), which fixes the problem if used prior to the regex text.

However, the snag is that, if any of the parts are styled, such as the x, y, z values being coloured red, green, and blue respectively, then .compact() doesn't include it (as expected), and thus the regex doesn't match. I'm not entirely sure where to go from here that isn't backtracking entirely and implementing what would amount to a pet-language lexer for waypoints xD

cloud vapor
#

What is the context of these replacements? Why can they have different styling to begin with?

cerulean delta
# cloud vapor What is the context of these replacements? Why can they have different styling t...

This is in context to a client, but I figured the context is vague enough and isn't really specific enough to a particular platform implementation. The idea is to replace any embedded waypoint (eg: [name:Some waypoint, x:5, y:0, z:125]) with an identical version of itself that, when clicked, executes a local command for my map mod. However, there are occasions where the server sends styled embedded waypoints, such as the axis values coloured to their axis colours. I could PR to change this for the particular server I play on, but I'd rather have the mod be resilient to what servers provide it than attempt to simplify server outputs to satisfy the mod.

#

Hmmm, idea

#

Since I'm replacing the embedded waypoint with an exact content-copy of itself, I could run the regex on a plain-text serialised component, and then add the click event to the components at the specific index. Though I'd need to split the component beforehand and join it afterwards.

#

Is there a component-equivalent to a String's .split("")?

sweet hornet
cloud vapor
cerulean delta
#

Okay, I've got something largely working but I've hit another snag: components that, in their literal content, contain legacy formatting codes. This does not work well with character splitting because it splits it into, for example, ["Β§", "a"], so then the chat message just has a random "a", rather than green text. Does Kyori have a "recursively serialise" function somewhere?

sterile rampart
#

those are invalid components

rare sage
#

those components are flawed and incorrectly constructed to begin with

cerulean delta
#

I agree, but it seems that some servers still send them :P

#

But if them being invalid means there's no function, fair enough

rare sage
#

that is a bug in their software

cerulean delta
#

It's odd that it's invalid though, since the Minecraft chat still works with it

sand drift
#

Mojang deprecated the legacy format 10 years ago

#

using legacy colors inside of components is an artifact of them not stripping that stuff

#

it would make 0 sense for adventure to add specialcasing for an archiac and deprecated format of which there is no means of defining a sane and consistent behavior for

rare sage
#

mojang will remove the rendering of section symbols as style

cerulean delta
#

Oke, since I've somehow summoned three separate maintainers :P is there a NMS function for this, so I can then pass the fully-resolved component to Kyori? Since this code is meddling with the user's chat, I'd rather not remove styling that would be there, even if that styling is deprecated.

sand drift
#

what?

#

if you mean the legacy color code stuff, no

#

that literally means nothing to anything but the legacy block of rendering code in the client

sweet hornet
#

Maybe you can try recomputing the component if you find an Β§ inside using the LegacyComponentSerializer

cloud vapor
#

There is no method, either supported, unsupported, or in NMS for turning a component containing legacy text into a proper component

cloud vapor
#

The best you can do is run it through the legacy serializer and hope you don't mind it being lossy

amber quail
#
      name: "<reset><gray>Close</gray>"

For some reason it always addes the italic event even

        ConfigurationSection itemsSection = plugin.getGuiManager().getGuiConfig().getConfigurationSection("gui.items");
        if (itemsSection != null) {
            for (String key : itemsSection.getKeys(false)) {
                ConfigurationSection itemSection = itemsSection.getConfigurationSection(key);
                if (itemSection != null) {
                    Material material = Material.valueOf(itemSection.getString("material", "STONE"));
                    String name = itemSection.getString("name", "");
                    List<String> lore = itemSection.getStringList("lore").stream()
                            .map(line -> "<reset>" + line)
                            .collect(Collectors.toList());
                    String type = itemSection.getString("type", "dummy");
                    List<Integer> slots = Arrays.stream(itemSection.getString("slot").split(","))
                            .map(Integer::parseInt)
                            .collect(Collectors.toList());

                    GuiItem guiItem = ItemBuilder.from(material)
                            .name(miniMessage.deserialize("<reset>" + name))
                            .lore(lore.stream().map(miniMessage::deserialize).toList())
                            .asGuiItem(event -> handleItemClick(event, type));

                    for (int slot : slots) {
                        gui.setItem(slot, guiItem);
                    }
                }
            }
        }

        gui.open(player);
    }
#

I even tried adding the <reset> in the code hardcoded

rare sage
#

<reset> simply closes all open tags in the MiniMessage string

plain glade
rare sage
#

<!i> is probably what you're looking for, or better, Component#decorateIfAbsent

amber quail
#

Ah cool thanks alot!

runic breach
#

Hey, anyone know if it's possible to use a transition with a numeric PAPI placeholder? (in-game w/ existing mini-message supported plugins)

cloud vapor
#

Probably? Depends how the plugin handles papi placeholders in minimeseage

prime sigil
grim bear
#

I wanna send a message to all players with a certain permission, and I feel like using audiences is the proper way. How can I get an audience of all online players who have said certain permission?

fiery oracle
grim bear
#

yeah I'll probably just do that

#

I thought that might be considered clunky but I guess that's inevitably what's gonna need to happen in the background anyway

celest lion
#

cant you make your own Audience?

cloud vapor
#

I'd quite like the API to have a dynamically filtering audience tbh

fiery oracle
#

well pencil kicked me for posting javadoc links so find 'em if you want, but either implement your own forwarding audience like leah mentioned, or use guava's filtering iterable (Iterables#filter) thing w/ Audience#audience

sweet hornet
jolly sage
#

This is somewhat regarding the discussion above

In AsyncChatEvent event, event.viewers() returns Set<Audience> and I noticed there is the console and every online CraftPlayer in the set java event.viewers().forEach(a -> plugin.getLogger().info("Audience: " + a));
However i'm not sure how to hide chat messages from specific players?

  • event.viewers().remove((CraftPlayer) player2) ?
    this does not feel right to me, is there a proper way?
sour quarry
#

You can just remove the normal bukkit player, no need to cast. Remember that CraftPlayer is just the implementation of the Player

jolly sage
#

Fair enough, thank you

#

Is Audience useful in the scenario for making "chat rooms"? (players are divided into groups/rooms and can only see each other's message if they are in the same group)
I can't imagine not making spaghetti code inside the chat event otherwise

#

(or I fully misunderstood what Audience is used for 😦)

sweet hornet
#

An audience is "something you can send things to". You can have a single audience per room, with the appropriate players inside, and when a player sends a chat message, you set the viewers to the room he's in

#

What makes audiences useful is that a single audience can be forwarding to multiple players/console/admins...

#

So you just have a single receiver in your code, yet it represents everyone that should receive the messages

#

And the audience adapts to the receiver's abilities: You can show a title to an audience forwarding to players and console, and only the players will see it, because there's no way to show a title in the console

fiery oracle
sweet hornet
#

But the console's implementation of audience will handle this filtering for you, no need to worry about that yourself

sour quarry
#

(that's part of the contract of Audience - if an audience doesn't support a method, it will silently do nothing)

jolly sage
#

I wrote this code first time when implementing chat rooms πŸ˜† ```java
@EventHandler
public void onPlayerChat(AsyncChatEvent event) {
Set<Audience> viewers0 = event.viewers();
Set<Audience> viewers = new HashSet<>();

ChatRoom channel = plugin.getChannel(event.getPlayer());
viewers0.forEach(audience -> {
    if (audience instanceof Player receiver) {
        // both can be null and it is ok
        if (channel == plugin.getChannel(receiver))
            viewers.add(audience);
    } else {  
        viewers.add(audience);
    }
});
viewers0.clear();
viewers0.addAll(viewers);

}If i'm not mistaken, there could be a single `Audience` object representing my chat room (something else will handle adding and removing players from it), and the above method would just become something likejava
event.viewers().clear(); // actually, clear only players, not the console and etc
event.viewers().addAll(plugin.getChannel().getAudience());``` Is this right?

sweet hornet
sour quarry
sweet hornet
sour quarry
sweet hornet
#

Oh yes, I forgot about this!

jolly sage
#

I see a static factory function Audience.audience which i can just call with a list of players
I'm assuming this is bad (that's why i crossed it out) java public class ChatRoom { private final List<Player> members; public ForwardingAudience getAudience() { return Audiences.audience(members) } } because it creates a new audience every time this is called, but if I keep a single ForwardingAudience is it possible to add and remove audiences from it on the run? Or does it take it directly from this List every time it requires?

sour quarry
#

(The entire point of that interface is specifically to make stuff like this easy to implement)

jolly sage
sour quarry
#

Use IJ's "implement" keybind (Ctrl+i) instead of override (Ctrl+o), it should prompt only the unimplemented abstract method

#

(Quick check, the one you're looking for is Iterable<? extends Audience> audiences())

sour quarry
jolly sage
#

oh wait it makes more sense now
I thought i'd have to override sendMessage and put all the broadcasting logic in there and it worried me that I'd have to do the same for the rest, sendTitles for example

jolly sage
sour quarry
#

Wierd.

jolly sage
#

It's okay, thank you for taking your time writing all these things out ✨

sweet hornet
jolly sage
#

it's just a slightly different icon here too xD

sweet hornet
#

Yeah, but I feel this is more contrasted with the vertical bars than the "dashed" style of the new UI

#

Or I'm just more used to it, maybe x)

#

Anyway, it's not obvious, but now you know

quaint monolith
#

Doesn't the UI also just autoselect all the methods you don't already have that you have to implement?

sweet hornet
#

Weirdly, no, I just tried and using the "Implement methods" quick fix just showed me this dialog

#

But I thought the same before, hence why I checked

tawdry escarp
#

hello
Does anyone know how I can add custom tags so that they can be used on the server?
Or if there is a base project that shows this. If you basically took the .jar and put it in the plugins folder, you would already have the tags as an addition
Looking at this section, I have no idea how to register the tag so that it can be recognized globally

fiery oracle
#

why do you need your tags to be "global"?

tawdry escarp
#

In my maven project I have the paper dependency, adventure is already implemented together as mentioned in the paper documentation, I wanted to know how to create my own Parser Directives

#

The "global" would be the possibility for you to use the tags you created in any other plugin that supports minimessage

#

You can create a package full of parsers, in addition to those standard ones in the Adventure documentation

#

I just don't know how to implement this, because I'm still a noob at creating plugins XD. But I have the ability to understand complex code

sterile rampart
prime sigil
tawdry escarp
#

@prime sigil The problem with using miniplaceholders is that it only works for String interpolation, creating a parser directly through TagResolver, allows the modification of strings between closing or opening tags

#

An example in the Minimessage documentation is the use of <clear>, a custom tag just for example

#

It would even be possible to create a swearword filter system, where such words would be replaced in red. Anyway, lots of ideas.

tawdry escarp
#

Something along those lines

sterile rampart
#

there's no such things, and there will not be

#

see the issue i linkeud

tawdry escarp
#

@sterile rampart thx for info, From what I understand, it would be a contribution to the project itself. But what most people would like is for it to be possible on their own servers to have their own tags.

#

I don't know if I misunderstood, but I saw an issue where a guy tried to create a custom tag <list to format spacing in lists

#

I don't have the issue link to send you at the moment, as I was trying to understand what was being discussed there.

ruby pumice
#

how can i remove the shadow from a component?

sterile rampart
ruby pumice
#

perfect thx

prime sigil
tawdry escarp
#

@prime sigil That's exactly what I wanted to get to, thank you for your help. However, my intention is not to do a filter project, something else

#

Now that I saw that the creator of the expansions was you HAHA

prime sigil
#

πŸ˜…

silent solar
#
fun resolveTags(string: String, tags: TagResolver): String { // Resolve tags and then un-resolve LOL
        return miniMessage.serialize(miniMessage.deserialize(string, tags))
    }```
#

This can't possible be the best way to do this D:

#

Essentially, the API I'm using wants a list of strings because it has it's own MiniMessage thing going on. Now, I have a list of tags which are bundled in that TagResolver which I want to resolve before passing on the string list. However I can only see this as a valid method of doing it?

#

Unless I missed something on the JDocs

graceful kestrel
#

should ask that api to add a way to pass your own tagreaolvers to it

silent solar
#

That would be ideal, but is there a method in Adventure ( I can't find one ) which would tags.replace(string) or something

#

without parsing to a component D:

tawdry escarp
#

As seen in its documentation, there must be plugins compatible with the miniplaceholder plugin, it would be interesting if the miniplaceholder.jar did something like that, injecting/modifying the main minimessage class. This would allow plugins to not need the miniplaceholder hook

#

For example, I use a plugin called Socialismus, it supports Minimessage, but I wanted to use my expansions on it too. For this I depend on the author adding support for the miniplaceholder hook...

#

The way your plugin is built is perfect, but I believe that what I said would be the final touch to complete the implementation.

prime sigil
# tawdry escarp The way your plugin is built is perfect, but I believe that what I said would be...

The problem with that is that it would create unwanted situations and possible exploits.
For example, you would not want a player to access all the data contained in your server without restriction, so you would not parse the player's input with the MiniPlaceholders placeholders. But by adding the MiniPlaceholders TagResolvers globally, you would be making every plugin that uses MiniMessage.miniMessage() able to access that data, including chat plugins.
A very common example of this is using PlaceholderAPI, you will never see a chat plugin that allows player input to be modified by PlaceholderAPI as it can display sensitive information such as IPs

silent solar
quaint monolith
#

Heck even just the default tag resolvers you wouldn't want to let user input have access to

#

Anything handling user input would have a custom MiniMessage instance so even if you could inject into the default one that wouldn't help

prime sigil
quaint monolith
#

But selectors and NBT...

#

I'd consider any plugin passing user input to the default instance to have an exploit

#

Well, unless it limits user input to admins or whatever via permissions

sterile rampart
#

i mean tbh those kinds of plugins don't do resolution on the components so it ends up not mattering lol

cloud vapor
#

fwiw it is a long term goal to have a global mutable tag registry, but there's just a lot of hurdles in the way of that first

#

one thing I was thinking about was making context able to check permissions and giving all tags some sort of permission that can be set

dawn pewter
void sapphire
#

Hi all, this might be a long-shot, but given a Component that is comprised of many bits of formatting / colors / etc., is there a way I could split this component into multiple Components whilst retaining the formatting across lines? Context here is having a long MiniMessage formatted string that needs to be applied as lore on an ItemStack, but without splitting it the ItemStack's lore would get super long. I'm also fine with any other way to represent a MiniMessage format / Component that indicates line breaks of some sort.

One naive approach I could think off is to convert the Component to a plain text string and stripping out any MiniMessage tags, then wrap the string, then somehow trying to piece back together the MiniMessage tags, but this feels like an absolute nightmare.

sterile rampart
#

PRs welcome, that's a open issue

#

it's a bit of a walk-the-tree project

void sapphire
#

Hm, I see indeed an issue open for something like this (#499). I might give it a think and a look in the source code of Components (as I am not at all familiar with this), but can't promise anything.

#

Thanks for the response nonetheless!

sweet hornet
#

Hello!

What's the best way to define dynamic tags* in a MiniMessage instance?

*By "dynamic tags" I mean to have the ability to add / remove some later, at runtime. Note that unlike most other, I do not want to modify tags globally, simply have my local MiniMessage instance to which I can decide to add or remove tag resolvers based on whatever rule I want.

I am currently considering 2 options:

private @NotNull MiniMessage miniMessage = MiniMessage.miniMessage();

public void addTag(@TagPattern @NotNull String tagName, @NotNull BiFunction<ArgumentQueue, Context, Tag> tagHandler) {
    this.miniMessage = MiniMessage.builder().tags(this.miniMessage.tags()).editTags(tags -> tags.tag(tagName, tagHandler)).build();
}

Or having some kind of "default tag handler" if it is possible, that will call a handler whenever it encounter a tag it doesn't know about, and I can resolve it myself from, say, a Map<String, BiFunction<ArgumentQueue, Context, Tag>> that I could dynamically populate in my addTag(...) method.

I don't really know what's the best option here, because since the MiniMessage instance is unmodifiable, I feel like solution #1 is "cheating" and solution #2 would be better, but in the same time I don't even know if solution #2 is possible (is it possible to handle all unknown tags with a single handler?)

sage river
#

you can provide tag resolvers in deserialize method

sweet hornet
#

Oh yes I know about that, that's true it is a third solution I didn't mentioned, but isn't it better to have them registered in the instance so that it simplify using it?

sage river
#

you can't dynamically register tag resolvers, so that's the best solution actually

sweet hornet
#

And also what's the performance difference between registered tag resolvers and dynamically added one, if any?

sage river
#

I don't think there would be any difference, registered or not tag resolvers work exactly the same

sweet hornet
#

Interesting, I wonder then why they made the MiniMessage instance immutable

sage river
#

most likely design choice, not sure tho

#

personally I think it's better to provide a serializer with static options, than with dynamic

sweet hornet
#

Oh I just found how to do my solution #2: I just need to write a custom TagResolver implementation

upper tinselBOT
tough peak
#

Component to String?

wet kestrel
tough peak
wet kestrel
#

Stripping out all formatting, colors, hovers, etc?

tough peak
#

yeah

#

just need the text

wet kestrel
#

There's a plain text serializer for that purpose. For curiosity, what do you need it for?

tough peak
#

trust me

wet kestrel
#

Just trying to watch out for the 'wrong' uses of it, like when we see people use it to compare item names to then do things with that.

tough peak
#

ye ok let me think

#

I have a string with placeholders in the config (ymal).
I currently use String.contains() to check for the pattern and as I am writing this down I remembered the time I used the component placeholder methods and that I could use that instead☹️
...

wet kestrel
#

Are you trying to replace placeholders into a component? Just use minimessage.

tough peak
wet kestrel
tough peak
winter socket
#

how do I strip all styling, hover events, etc. from a component?

wet kestrel
#

The plain serializer does it, but can you clarify why you want it? Lots of folks do it for bad-coding-design reasons that bite them later.

winter socket
#

it's just a niche thing I'm using to parse commands from signs, which means I already put it through a json serializer

sterile rampart
#

(like, if you want to clear styling while preserving translatables and such you'll want to convert the component to a builder and mapChildrenDeep to set the style to an empty style on each element)

winter socket
#

putting it through another serializer is probably bad but idk, maybe adventure is that performant

#

I don't care about preserving translatables

sterile rampart
#

parsing commands from signs seems not super practical tbh cuz of length limits, but plain serializer is probably what you want

#

if its not displayed you could use PDC/storing custom nbt

#

funky, there are custom payloads though

wet kestrel
#

you mean like the custom payload packet built into the server, that plugins can interact with?

cloud vapor
#

it's restricted to a byte array up to your control so i think you could manage to put something nice there :p

flat marsh
#

Hey. Im trying to seperate a part of a component.
When you kill someone you are given a Component deathMessage

And sometimes it contains the info about the weapon that was used (look image)
for this part of the message its possible to hover and see more information

How do i seperate this part from the whole message? and is it possible?

sand drift
#

seperate it, why?

#

Like, you could always walk the tree and look for the translatable component and grab the args from it, pretty sure that would work

flat marsh
#

if i want to reconstruct the message with the used item elsewhere or formatted seperately from the rest of the message

sand drift
#

are you on paper?

#

Like, paper just exposes that as the ItemStack#displayName() or something

#

otherwise, there should be an nms method for that

flat marsh
#

i am on paper

sand drift
#

otherwise, yea, components are 'just' a tree structure

flat marsh
#

How do i get rid of the color of the weapon?

deathMessage = deathMessage.color(NamedTextColor.GRAY);
for (Player player : Bukkit.getOnlinePlayers()) {
    player.sendMessage(deathMessage);
}

result

sand drift
#

I'd suggest looking into the component manipulation APIs provided by adventure

#

It's pretty hard to explain what to do loosely if you're not really familiar with how components work

flat marsh
#

alrigh thanks

hardy crest
#
        MiniMessage
            .builder()
            .editTags { builder ->
                builder.tag("party_prefix") { args, ctx ->
                    Tag.preProcessParsed("<pink>PARTY <dark_gray>β€Ίβ€Ί <#49b6ff>")
                }
            }
            .build()

Will the party_prefix be able to be closed?

#

So like this <party_prefix>Test</party_prefix>

sand drift
#

I believe so? Just, ofc, it's not going to magically know what to do with any contents

hardy crest
#

I just want to make aliases for colors for example, so i can change it globally so for example <text_color> will redirect to <gray> and it would be nice if they are able to be closed, i think ill just try and see

cloud vapor
#

You'd want to use an inserting tag, e.g. Placeholder.component

sand drift
#

Oh, yea, I derped on that front, ^

hardy crest
#
                builder.tag("text_color") { args, ctx ->
                    Tag.styling(
                        NamedTextColor.GRAY
                    )
                }

But this would work?

cloud vapor
#

Yes that would be closeable

hardy crest
#

And Tag.inserting is also closable?

cloud vapor
#

Yes, the javadocs are your friend :p

#

The opposite is selfClosingInserting

hardy crest
#

ty

mint path
#

So I started the adventure-web-ui on a server as a daemon, now I literally cannot kill/stop/anything it. Force killing the pid just respawns it instantly, there is no GradleDaemon running in ps, and I have restarted the box. What in the holy hell is keeping it going?

foggy briar
#

What is adventure favor against legacy system?

#

because idk it just seems complicated and I dont see why I should switch

#

@shrewd nest Could you explain why its outdated? and what adventure does better since your reactions aren't really helpful

last horizon
#

legacy is nothing more than a collection of hacks and it hasnt been relevant for as long as some people in this discord have been alive

foggy briar
#

why "hacks"? I want to know what adventure does

last horizon
#

with adventure you can easily use hex colors hover and click messages and much more

sour totem
#

Adventure supports all the features of minecraft's component system while legacy does not, think of stuff like hover text, smooth gradients, clickable stuff

last horizon
# foggy briar why "hacks"? I want to know what adventure does

legacy Β§xΒ§FΒ§FΒ§0Β§0Β§0Β§0HΒ§xΒ§FΒ§FΒ§5Β§FΒ§0Β§0eΒ§xΒ§FΒ§FΒ§BΒ§FΒ§0Β§0lΒ§xΒ§DΒ§FΒ§FΒ§FΒ§0Β§0lΒ§xΒ§7Β§FΒ§FΒ§FΒ§0Β§0o Β§xΒ§0Β§0Β§FΒ§FΒ§3Β§FmΒ§xΒ§0Β§0Β§FΒ§FΒ§9Β§Fy Β§xΒ§0Β§0Β§9Β§FΒ§FΒ§FfΒ§xΒ§0Β§0Β§3Β§FΒ§FΒ§FrΒ§xΒ§1Β§FΒ§0Β§0Β§FΒ§FiΒ§xΒ§7Β§FΒ§0Β§0Β§FΒ§FeΒ§xΒ§DΒ§FΒ§0Β§0Β§FΒ§FnΒ§xΒ§FΒ§FΒ§0Β§0Β§BΒ§FdΒ§xΒ§FΒ§FΒ§0Β§0Β§5Β§Fs
minimessage <rainbow>Hello my friends

that took me WAY too long
no idea why i did that manually

#

damn i forgot the spaces and everything was uppercase

foggy briar
#

ah okay

quaint monolith
#

The legacy way also just isn't how text has worked in Minecraft for over a decade

foggy briar
#

wdym?

quaint monolith
#

Behind the scenes Spigot/Paper has been converting that to components for you

foggy briar
#

oo so they have been working as components?

quaint monolith
#

This project didn't make up components, that's all Mojang, since 1.7.1

foggy briar
#

ah okay

#

never knew that thanks

quaint monolith
#

This project just lets you actually use them instead of just converting the limited functionality the legacy system had to keep it working with components

foggy briar
#

is the legacy planned to be removed any time soon? since its deperecated

cosmic loom
#

the client can still render some of it in some parts, and probably not any time soon

#

since that would break a huge amount of plugins

foggy briar
#

wdym can still render some of it

quaint monolith
#

Some Day ℒ️

last horizon
#

hypixel for example actually sends the motd as legacy

foggy briar
#

also I am unsure if its my issue but when seeing hex colors it varies on diffrent clients like I see #FFFF00 as yellow but on vanilla mc its black

quaint monolith
#

Did you intentionally put an invalid hex code there?

foggy briar
#

its yellow but I miss typed it

last horizon
last horizon
#

i know that liquid bounce messes with the rendering of components and colors but i doubt that it shows yellow as black
probably something like viafabric or viaversion (on the server)

foggy briar
#

both clients are same version one is lunar client and one is vanilla mc

#

and there is no via

last horizon
#

because #FFFF00 is translated to Β§x...Β§0 which in turn means black

foggy briar
#

FFFF00 is yellow

last horizon
#

i know but neither bukkit nor the client know that

foggy briar
#

yeah but I dont understand how 2 clients have 2 diffrence colors

quaint monolith
#

Hold on

last horizon
#

i daubt thats client related in this case

quaint monolith
#

Do you mean <c:#ffff00>Hi, component API, or legacy jank?

foggy briar
#

component

#

thats the issue I haddd

last horizon
#

and which client version

foggy briar
#

1.20.4

#

same server version

#

i was using mini message

shadow wyvern
#

What would be the best way to leftstrip from a component?

cloud vapor
#

the best way is to trim it before it's a component! failing that, see replaceText - match characters, replace whitespace with blank strings and end as soon as you hit a non whitespace char

kind jungle
#

I recently ported Grim's command system from ACF to Paper and made the entire project cross platform and was looking to improve command/text translations.

#

I was gonna do my own thing for translating text until I saw adventure had support for server-side translation, but I don't really get how it works and I'd like to make sure it can replace my original plan:

My idea was to do the following:

  1. Intercept Client Options packet
  2. Decode to find client language and set a grimPlayer.language field for each player (which defaults to server language)

Create a method grimPlayer.translate(key, "fallback-text")

The idea would be

  1. we would read from a file defining translations for the key in the player's native language
  2. if that key doesn't exist we would fall back to that key in the server's default language
  3. and if neither exist we fallback to the hardcoded text.
#

I would like to however minimize custom code and would prefer to use common library code to achieve these goals.

How do I achieve equivalent behavior in adventure? With the proper fallback order and hardcoded default text? Is getting the player's language supported on all platforms and not just Bukkit? My packet based approach would work on any platform but how does adventure get a player's language on Fabric and Velocity?

(And yes all my text uses components already)

fiery oracle
#

basically you register your translations to the GlobalTranslator
https://jd.advntr.dev/api/latest/net/kyori/adventure/translation/GlobalTranslator.html
as the javadoc states, you either use

  • TranslationRegistry, which you create using TranslationRegistry#create and uses MessageFormat for the translation strings
    or
  • implement Translator and decide your own translation logic (where to source translation from, how those translations are converted into a component, etc.)
    TranslationRegistry lets you set a default locale, and with Translator your implementation could decide to fallback to another locale if you want
#

and adventure gets the locale the same way you do - the client sends their locale setting to the server, and the adventure implementation sources the locale from the platform

#

if you implement Translator, then the locale is provided when the global translator calls Translator#translate

#

what you want to do is very much possible with adventure

sweet hornet
#

What’s the simple way to get a safe MiniMessage instance? By safe I mean only tags that present no risk being used by players, such as colors, decorations, and gradients for instance, but not NBT, click events…

#

I just know about MiniMessage.standard() (all default tags) and MiniMessage.empty() no tag at all…

robust wharf
#

You can individually enable or disable tags just as you want

sweet hornet
#

Ok I was missing the StandardTags class, it makes more sense now

#

Thx

mint path
#

Is there some sort of cache with adventure-webui? I swear to god i can make local changes that reflect in my forked version, but when I push them to our real web server, the changes (seemingly in the .kt files) for real just don't take. Also, running it in -PisDevelopment=true doesn't seem to matter.

I can confirm the .kt files on the prod server are correct

#

-# unrelated but not having a #webui at all anymore is understandable? but also sad 😦

cloud vapor
#

Well, your browser will be caching the html and js yeah

#

Make sure you're hard reloading

mint path
#

nah it's not browser-level stuff pretty sure

#

tried the various ctrl-f5's of the world etc

cloud vapor
#

it's just effectively a static file server, it can't cache files across builds

#

id assume you might have some cloudflare cache in front or other similar things?

kind jungle
# fiery oracle basically you register your translations to the `GlobalTranslator` <https://jd.a...

Will converting components to native text convert the translated text? On Fabric I am not using adventure-platform-fabric because its version-specific (my mod supports multiple fabric versions in one jar). I have a PlatformPlayer interface, the implementation on Fabric looks like the following.

    @Override
    public void sendMessage(Component message) {
        fabricPlayer.sendMessage(FabricConversionUtil.toNativeText(message));
    }
    private static Function<Component, Text> nativeTextMapperFunction = (component) -> Text.Serialization.fromJsonTree(GsonComponentSerializer.gson().serializeToTree(component), DynamicRegistryManager.EMPTY);

    public static Text toNativeText(Component component) {
        return nativeTextMapperFunction.apply(component);
    }

Does the TranslationRegistry depend on platform specific behaviour?

sterile rampart
#

no also your logic is wrong

#

you need registry context

kind jungle
sterile rampart
#

anything that needs registries will have lookups fail

#

look at data components

kind jungle
#

I'm sending text what would I ever need to lookup in a registry besides translations?

sterile rampart
#

hover event show item

kind jungle
#

no hovering text works on Fabric

#

do you mean something else?

sterile rampart
#

your testing working does not mean every case is correct

kind jungle
#

fair enough I guess I'd like to know what breaks if you do

sterile rampart
#

look at issues on platform-mod

kind jungle
#

I don't see anything related to hovering

sterile rampart
#

we live in a world where some issues are closed

#

fun fact

kind jungle
#

I know I searched through closed issues

#

for "translate" and "hover"

#

and I got two results

#

and cover just led me to a completely unrelated issue

sterile rampart
kind jungle
#

Ok so I just need to pass in an instance of BuiltInRegistries.Registry or whatever it is

#

that's fine

#

interesting didn't know that though

sterile rampart
#

still not true

kind jungle
#

not sure if that would've ever come up but its good to have the case covered

sterile rampart
#

datapack registries are a thing

kind jungle
#

I don't really care I'm not going to lie...

#

I mean I guess I could look through each one with a wrapper function

#

but I don't think that's all that important

sterile rampart
#

you're putting in a lot of work into a worse implementation lol

kind jungle
#

unless you have a simple and easy way to add this, support for grabbing entires fro data pack registries is really not on my priorities list

sterile rampart
#

I do, it's called adventure-platform-mod

kind jungle
#

Yeah and it has all the issues I feared it would

#

lots of minor ones but most importantly there's no multi version support

kind jungle
#

but I'm really hoping I won't have to do something like this

#

I'd rather stick to adventure APIs for accessability to future devs

kind jungle
kind jungle
sterile rampart
#

what docs?

kind jungle
#

uh I googled first and went to the paper page and right now I'm downloading the javadocs

sterile rampart
#

what javadocs? vanilla minecraft doesn't publish those

kind jungle
kind jungle
sterile rampart
#

like you're making stupid choices with systems you don't understand, so you're going to keep having stupid problems

sterile rampart
kind jungle
#

supporting multiple platforms on multiple versions...?

sterile rampart
#

reinventing the wheel, and supporting multiple game versions in one jar in the modded world

#

when you clearly know very little about the mojang codebase

kind jungle
#

Maybe I presented this unclearly but I have good reasons to make the decisions I have, give me a second to explain

#

I'm working on making GrimAC multiplatform. We support Bukkit, Fabric (1.20.1, 1.21.1, and 1.21.4 as of time of writingβ€”yes this will work for most mods so long as they don't add new packets to the game for movement and purely client side movement) and have intentions of supporting Velocity, Bungeecoord, NeoForge, Sponge, etc... servers if possible.

We also support 1.7 to 1.21.X clients on each of these server versions.

#

Our code is largely packet based, and we handle multi-version support at the packet level (usually behind via but we take care of some packets before viaversion). Because the codebase is largely packet based the platform-specific integrations are rather small. 99% of the code is just screwing around with packets and so the actual maintenance cost of supporting many versions even in the modded space is very low

#

We have a set of platform-specific interfaces to implement on each platform and that's that. As for Fabric you can take a look at how its organized if you're curious but we have subprojects for each version we directly support. The amount of actual duplicated code is very small (~10kb per version most of which is config files where as the project as a whole is 8 MB)

#

Our use case for adventure is simply to have a nice cross-platform and modern way of working with text in the game, previously we simply used strings and bukkit color codes. The completely feature of adventure is amazing but it is not required.

#

I originally used adventure-platform-fabric but after implementing support for Fabric in Grim I realized we hadn't used a single line of code from adventure-paltform-fabric and so I removed it.

#

I understand Mojang's internal code changes widely between versions. Fun fact Mojang slightly changed the code for determning whether or not you were touching a block in 1.21.2 which caused falses in our player movement simulation model that took ages to fix and reimplemeint.

#

But the platform and version-specific hooks we need are not complicated. If you consider it reinventing the wheel to add cross-platform abstractions than I suppose from a certain perspective it is but it makes it possibly for us to continually update a codebase while supporting many platforms.

#

I hope now that you can see a little more of my situation, you can understand I didn't just decide to make stupid uninformed decisions. My choices were made given carefully consideration to the codebase I was working with and the nature of my project.

#

With that said, is there a way within adventure or platform-specific native code that can be abstracted into working with components to have translatable text, given the confines I"ve described?

kind jungle
kind jungle
# sterile rampart no also your logic is wrong

But I would still greatly appreciate it if you could share your knowledge to point me in the right direction and help me understand the edge cases. With luck they won't be important to my use case but I'd rather with your help be able to make a fully informed decision.

summer comet
#

Hi, does anyone know how I can convert a Component to BaseComponent so i can use the traditional .spigot().sendMessage() for cross-compability?

robust wharf
#

Pls don't

#

You will lose features as bungees legacy chat components don't support all modern Minecraft features

#

You want to use adventure-platform-bukkit if you still care about spigot (you shouldn't)

summer comet
#

Yeah i checked adventure-platform-bukkit, my idea is that MiniMessage will be only available for users that use paper

robust wharf
#

10% less revenue for how much increased work πŸ˜‰

summer comet
#

But i still have to work based on the spigot api, so using adventure-platform-bukkit would allow me to still support modern components?

summer comet
robust wharf
#

It's basically an abstraction that you will use to send messages instead of on the player object and it will either use the paper API internally if available or do hacks to make it work on legacy platforms

summer comet
robust wharf
#

I don't really understand that requirement

#

Either you want to use adventure components on spigot or you don't

summer comet
#

I want to allow Paper users to have the ability to use MiniMessage

#

I know this is a feature that I can even have on Spigot however I don't see why I would shade the whole minimessage library on the plugin, for that is just better for the user to go to Paper

robust wharf
#

Why would you withold that from spigot users?

#

Why are people so obsessed with file size? Lol

#

MiniMessage us like 20 classes

summer comet
#

MiniMessage is already on Paper, i'm just saying if i have to still shade " adventure-platform-bukkit" or not

summer comet
#

Is not about file size, if paper already contains minimessage, there is no reason to have it on the plugin, on top of that if people really want minimessage they should be already on paper

robust wharf
#

Well, if you want one code path for both platforms, you need to shade it on paper too

summer comet
#

Yeah I'll have a dynamic system that if is paper, it will support MiniMessage

#

So in this case what do I have to shade that is not included on paper?

#

Is "adventure-platform-bukkit" already included on paper, or do I have to shade only that?

robust wharf
#

No

summer comet
#

Alright awesome

robust wharf
#

Spigot users need adventure API, adventure platform and MiniMessage, on paper API and MiniMessage is available

#

But the adventure version paper ships might not be compatible with the platform version you ship

summer comet
#

Oh i see

#

Are there any incompabilities from Paper 1.16.5 minimessage platform to now?

robust wharf
#

No api breaks but new stuff will not be available on auch ancient versions obviously

summer comet
#

Yeah it makes sense, but as I'm just working on the API, the text that the user uses is not my business, i should be fine then

robust wharf
#

If I would enter the painful valley of multi platform multi version support you would just shade and relocate everything and don't depend on what the platform provides

summer comet
robust wharf
#

You just got used to the pain, lol

summer comet
#

You might be right

#

1.8.8-1.21.4 support + cross-compability

fossil timber
#

What is the VirtualComponent? Is there any documentation for it?

cloud vapor
#

Beyond the javadocs no

#

It's basically a text component that can hold addition data

foggy plume
#

If I register a custom tag to paper's instance of MiniMessage will that tag then be available in all plugins that also use the same instance?
Unsure if I should be asking this here or #paper-dev

cloud vapor
#

e.g. it's used in MiniMessage to store a bit of data saying "btw this mess of colours in my children is a gradient from red to blue" so that if you turn that component back into MiniMessage it will know to use <gradient:red:blue> instead

cloud vapor
fossil timber
#

Can I do something like a <plugin-prefix> tag with it?

#

And have a second component that replaces it?

#

πŸ€”

cloud vapor
#

Well the easiest way to do that is just to use a custom tag resolver with MiniMessage e.g. Placeholder.component

fossil timber
foggy plume
fossil timber
cloud vapor
#

Yes, that is a long term goal of ours! Just a few hurdles in the way

cloud vapor
foggy plume
cloud vapor
#

I'll make one

foggy plume
#

Thank you so much!

cloud vapor
foggy plume
#

Thank you!

lean rivet
#

How does Tag.styling() works exactly? There is an example provided in Adventure's docs:

TagResolver.resolver("click-by-version", (args, context) -> {
  final String version = args.popOr("version expected").value();
  return Tag.styling(ClickEvent.openUrl("https://jd.advntr.dev/api/ " + version + "/"));
});``` however I'm wondering how would I append text somewhere near, can I do `<click-by-version>Some text here</click-by-version>` in that case?
lean rivet
#

Yeah that was it, just escape tags lol

dense veldt
#

Hey, when implementing a custom placeholder tag for MiniMessage I noticed that the Context doesn't pass down its Pointered target when using Context#deserialize. My placeholder tag uses the target to determine what to replace and when using it as with in a <translatable> tag this breaks. An example string that doesn't work would be <translatable:example.key:'<placeholder:lolxd/>'/>. When deserializing this string with a target it doesnt get passed down when the arguments are deserialized.
As a workaround I implemented my own translatable tag that passes the target to its arguments correctly, but I feel like this should be the default behaviour. Before making an issue on github about this I wanted to ask if this was intended.

cloud vapor
naive sphinx
barren basalt
naive sphinx
#

A person just pointed me here

cloud vapor
#

Thanks for sharing! I'm not sure if I can see where your performance issues are though? Your max MSPT is only 37?

cloud vapor
#

Yeah done a big look through that spark and there are no performance issues there so I'm not even sure what issues you are talking about

#

There's not even really anything we could feasibly do to improve that spark. I mean, the only thing I can think of is writing a non-throwing parseDouble/parseInt but like,,, let's not be silly haha

kind jungle
kind jungle
#

If you need some help with project setup for multi-platofrm multi-version take a look at ^

robust wharf
fossil timber
#

Not true, there is a small, almost unnoticeable at first, overhead right there, after analysing the code of parsing ints and doubles, which can be backed by the spark profiler he sent, but its effects are observed when the method is called too many times, in a short period of time.

cloud vapor
#

What overhead?

fossil timber
#

Parsing doubles using Double.parseDouble(String) is the cause.

cloud vapor
fossil timber
naive sphinx
cloud vapor
#

The "expensive" part isn't the parsing it's the exception construction

fossil timber
#

But it also goes back to the Double being cached

naive sphinx
#

With one player and a few holograms mspt is 0.5

#

That's a lot

cloud vapor
#

That's not a lot, servers have a base level of overhead

#

Stuff doesn't scale directly

naive sphinx
#

Yea, as mentioned, it was exponentially

#

Will need to place a bunch of holograms

fossil timber
cloud vapor
#

parseDouble throws NumberFormatException

ashen breach
#

Is there an option to serialize/deserialize a component to bytes rather than serializing it to Gson and writing that as a string?

fossil timber
#

But it throws NPE if the string is null

cloud vapor
#

Yes it does

#
Throws:
NumberFormatException - if the string does not contain a parsable number
fossil timber
cloud vapor
fossil timber
#

Jesus, why doesn't the java documentation just mark it correctly in the mobile version

cold condor
# fossil timber valueOf doesn't

it seems like you completely misunderstand what's going on. Double.valueOf returns a Double object while parseDouble returns a double primitive, so changing that part doesn't make any sense

ashen breach
cloud vapor
#

Not as effective how?

fossil timber
#

By the JVM

cold condor
#

the current implementation is literally new Double(parseDouble(s))

fossil timber
ashen breach
fossil timber
cold condor
cloud vapor
#

Uh, I mean, sure you could write your own serializer that converts to a more packed format but we're talking about bytes here

ashen breach
cold condor
# fossil timber

That answer is flawed. The docs only say that the method should be preferred over using new Double(), but there is no guarantee about any caching involved (otherwise, the current implementation would be broken)

cloud vapor
#

Yeah it's been done before, Moulberry has adventure-binary-serializer but it's not updated. Generally nobody has bothered before because it's not necessary

fossil timber
fossil timber
fossil timber
#

😢

cold condor
#

yes, that's parseDouble, the method adventure already uses

cloud vapor
#

Alright ywell lets take the flaming over to #general now

fossil timber
#

😢

fossil timber
#

Returns null if the string can't be parsed. No exceptions thrown. More efficient than Double.parseDouble(String).

summer comet
summer comet
#

What costs more time is literally supporting a new version and in this news versions I just need to clone the module and change some dependencies/imports and that is what costs me more time

#

Making multi module when you intend to just do one plugin I would say is not worth it, if you want to make a lot of plugins that are wide-known, you have your perks, on top of that paper by itself doesnt support hybrid versions (modded), we have plenty of people that use modded servers

#

Just imagine somehow Paper contacted all of this modded hybrid softwares such as Arclight, etc... And talked to them to switch to Paper πŸ‘€

cloud vapor
fossil timber
cloud vapor
#

yeah but not in adventure

summer comet
fossil timber
#

I just looked at the source code

#

It's again using Double.parseDouble

#

πŸ’€

cloud vapor
#

I mean, I'm not against using a regex check before parsing if it's faster - I just kinda doubt it would be

cloud vapor
fossil timber
#

And that will be faster..

#

But this will be too much for 0.05 ms of performance..

fossil timber
cloud vapor
#

If guava says it's more efficient I'm inclined to believe them, maybe I'll throw some benchmarks up

#

Nothing like a bit of Friday premature micro optimization

fossil timber
robust wharf
#

Which means they intend to look at stuff tomorrow?

cloud vapor
#

no nico is right i have no idea what day it is lmao

robust wharf
#

Lol I thought you already had a plan since yesterday you said Friday too about that other thing

cloud vapor
#

well i did some jmh-ing and the answer is "yes it's technically faster to check against a nasty regex" but i've instead opted to rework the gradient/transition tags slightly to avoid checking against the double unless it knows it needs a double or needs to fail

#

so an identical perf improvement without the hassle of having a nasty regex in our codebase

fossil timber
cloud vapor
#

we also don't depend on apache lang either

rare sage
#

do we care about supporting anything other than decimal fp strings? e.g. hex fp strings or exponential notation. if not the check can simply be reduced to a simple (?:\d+(?:\.\d*)?)|(?:\d*\.\d+) (or regex-less equivalent to only iterate the string once instead of twice)

cloud vapor
#

i definitely do not care about non decimal fp strings no, but we also don't even need a regex check anyway

rare sage
#

maaaybe Infinity and maaybe NaN, there's probably some freak out there using those in their custom tags

cloud vapor
#

at least in gradient/transition tags those would be errors anyway iirc

rare sage
#

yeah

cloud vapor
#

but im also not even sure i care much for saving performance on error cases anyway

rare sage
#

i mean, it's not exactly unknown that filling stack traces is not cheap, and it can easily be avoided if you know what you're dealing with

#

it's less of an error case and more of a "this is not the phase argument" case

cloud vapor
#

yeah i've already fixed that by checking the colors first

rare sage
#

well yeah but if you do <gradient:#123456:#abcdef> it will still need to check if the last argument is the phase argument by checking if it can parse to a double

cloud vapor
#

yeah but if we check color first then we skip having to always fill the stack trace, instead only filling the stack trace in the case where it's an invalid phase argument

rare sage
#

move the resolveColor tag inside the last arg check too?

#

that's more likely gonna be the more common case, still gonna throw an exception if it's the phase but that's probably less common

#

✨ trade offs

cloud vapor
#

i moved the resolveColor check before the check for the last arg entirely

#

so it'll now go

  1. is it a color, if so just use that
  2. are we the last arg, if so try and parse the double
  3. throw an exception
rare sage
#

yes, that's what i'm talking about

rare sage
#

that is not an error case, it's a "not phase" case, if the exception can be avoided, cool

#

whether by trying to parse the last argument as color first or by checking if it can be a double before actually trying to parse it and ending up with an exception

cloud vapor
#

yeah the error case is if the last argument is a non-color and non-double in which case idm the overhead of parseDouble there really

rare sage
#

but it is a color tho

#

that's not an error case

#

it tries to parse it as a double and the exception is created either way

cloud vapor
rare sage
#

πŸ™ƒ

#

yeah that looks good

#

let me officially mark it as good looking

cloud vapor
#

heck yeah

fossil timber
fossil timber
#

I will share with you guys, my very own method to work with MiniMessage because, sadly, it lacks features and deserialization is the only way to use some custom tags, like PlaceholdersAPI tags... here we go:

public class NamedColor {
    private final String name;

    private NamedColor(String name) {
        this.name = name;
    }

    public String encase(String text) {
        return "<" + this.name + ">" + text + "</" + this.name + ">";
    }

    public static NamedColor BLACK = new NamedColor("black");
    public static NamedColor DARK_BLUE = new NamedColor("dark_blue");
    public static NamedColor DARK_GREEN = new NamedColor("dark_green");
    public static NamedColor DARK_AQUA = new NamedColor("dark_aqua");
    public static NamedColor DARK_RED = new NamedColor("dark_red");
    public static NamedColor DARK_PURPLE = new NamedColor("dark_purple");
    public static NamedColor GOLD = new NamedColor("gold");
    public static NamedColor GRAY = new NamedColor("gray");
    public static NamedColor DARK_GRAY = new NamedColor("dark_gray");
    public static NamedColor BLUE = new NamedColor("blue");
    public static NamedColor GREEN = new NamedColor("green");
    public static NamedColor AQUA = new NamedColor("aqua");
    public static NamedColor RED = new NamedColor("red");
    public static NamedColor LIGHT_PURPLE = new NamedColor("light_purple");
    public static NamedColor YELLOW = new NamedColor("yellow");
    public static NamedColor WHITE = new NamedColor("white");
}```
```java
public class RGBColor {
    public static String encase(int color, String text) {
        return "<color:#" + Integer.toHexString(color) + ">" + text + "</color>";
    }
}```
#
public class Style {
    public static class Bold {
        public static String encase(String text) {
            return "<b>" + text + "</b>";
        }
    }

    public static class Italic {
        public static String encase(String text) {
            return "<i>" + text + "</i>";
        }
    }

    public static class Underline {
        public static String encase(String text) {
            return "<u>" + text + "</u>";
        }
    }

    public static class Strikethrough {
        public static String encase(String text) {
            return "<st>" + text + "</st>";
        }
    }

    public static class Obfuscated {
        public static String encase(String text) {
            return "<obf>" + text + "</obf>";
        }
    }
}```
```java
public class ClickAction {
    public static class ChangePage {
        public static String encase(int page, String text) {
            return "<click:change_page:" + page + ">" + text + "</click>";
        }
    }

    public static class CopyToClipboard {
        public static String encase(String value, String text) {
            return "<click:copy_to_clipboard:" + value + ">" + text + "</click>";
        }
    }

    public static class OpenFile {
        public static String encase(String file, String text) {
            return "<click:open_file:" + file + ">" + text + "</click>";
        }
    }

    public static class OpenUrl {
        public static String encase(String url, String text) {
            return "<click:open_url:" + url + ">" + text + "</click>";
        }
    }

    public static class RunCommand {
        public static String encase(String command, String text) {
            return "<click:run_command:" + command + ">" + text + "</click>";
        }
    }

    public static class SuggestCommand {
        public static String encase(String command, String text) {
            return "<click:suggest_command:" + command + ">" + text + "</click>";
        }
    }
}```
#

Only to be used with something like:

player.sendMessage(MiniMessage.miniMessage().deserialize(NamedColor.RED.encase(Style.Bold.encase("Hello world!"))));
#

I wish I could have used Components directly, but there's still no way to have a <custom-tag> as a component 😦

#

and be serialisable at the same time

rare sage
#

🀨 what does this "fix" exactly? what kind of features does minimessage lack that this adds? all i can see is you're just building a minimessage string with methods instead

rare sage
#

huh

fossil timber
rare sage
#

just pass the resolved component..?

#

you only need to use minimessage if you are interfacing with user input via a config or something, in that case i don't see why you'd be using hardcoded strings (or why you'd be building them like that?), and yes you do need custom tags for custom tags; but if not, just pass the resolved component?

fossil timber
#

if I pass directly a Component instead of a string, there is 1) no way to have dynamic placeholders.

#
  1. there is no Component, like Component.tag("custom-tag")
fossil timber
cloud vapor
#

uh, you can have dynamic placeholders by using a tag resolver

#

and also, Placeholder.component

fossil timber
#

here's the component class, which also pre-loads components

#

this works.

fossil timber
#

no.

cloud vapor
#

i think you kinda have a fundemental misunderstanding of minimessage

#

You should be using MiniMessage everywhere - e.g. your MESSAGE_HEADER should be a MiniMessage string - then you can use MiniMessage placeholders in them

#

don't keep components lying around, they aren't useful

fossil timber
#

I can use Gson or anything else

#

I still can't use the components as I please.

rare sage
#

i mean you can totally have components that when serializing with minimessage they serialize to your custom tag; that's kind of what virtual components are for

fossil timber
sterile rampart
#

(except the serialization api for custom tags isn't public yet)

rare sage
#

internal package is a myth

fossil timber
fossil timber
cloud vapor
#

Your goal here is wrong - if you want to use MiniMessage and take advantage of tags, placeholders, dynamic tag resolvers, etc - you should be keeping stuff as MiniMessage strings where needed

sterile rampart
#

coming to you in some number of years

rare sage
#

"everyone" is certainly a statement

#

kezz is making a point, you want to make use of MiniMessage features outside of MiniMessage, your quest doesn't make any sense

fossil timber
#

lmao

#

why needed?

cloud vapor
#

What do you mean strip components?

fossil timber
cloud vapor
#

Because components are what Minecraft uses and unfortunately MiniMessage isn't in the vanilla client lol

fossil timber
#

basically all MiniMessages do is deserialisation

cloud vapor
#

To give you an example, in our codebase we have around 100k lines of MiniMessage strings sitting in properties files, when we want to send one of these strings to a player we literally take that MiniMessage string and translate it right before sending it to the player - this lets us add dynamic or custom placeholders for the deserialization right when it's needed

fossil timber
#

if Minecraft has them, why does adventure needs new ones?

rare sage
#

because adventure is a public open-source free api, not proprietary mojang code

rare sage
#

yeah