#adventure-help
1 messages ยท Page 6 of 1
For example I have a component which is already parsed, how would I translate its papi placeholders now? (Without turning it back into a String)
Why can't you parse the placeholders during the same time you parse your component?
Performance
How would that make any performance difference, huh
Components are immutable
I would imagine parsing 100 components each second take a little server performance
nah
Nah or no? XD
I do that once per tick for my scoreboard, no issues with 100 scoreboards
Parsing is fast
Did you actually encountered any performance issue?
I recommend trying and profiling it for your usecase, and then see if its really an issue. Because that by far is the easiest way of doing the PAPI placeholders
That's a #paper-dev question
oh ok sorry
When trying to read raw playerdata from playerdata folder
File playerDataFile = new File(playerDataFolder, uuid + ".dat");
Packetevents is the failing plugin, not yours
hmm thats strange that packetevents brings kyori nbt
considering that ideally paper should've brought it
didn't notice from the first read, thank you
well paper already has nbt builtin
Are you sure you're running this on paper and not perhaps spigot or aaaancient paper?
paper does not bundle adventure-nbt anyway
I had the same issue. don't shade packetevents. use the snapshot version
the experimental jars
and plus being bad + adventirous shouldn't lead to a crash?????????????????
wat
yeah
being adventurous sometimes isn't safe. yeah be safe out there don't dig straight down
they didn't shade PE lol, and that isn't a crash either
Is there a component serializer for the new 1.21.5+ SNBT format?
I have a tool on 1.21.4 for my staff members allowing them to copy the components from an existing item's tooltip so they can use it when making other items, and I used the JSON component serializer because it was what Minecraft used in commands, but now we're upgrading to 1.21.7 and they need the SNBT encoding instead of JSON so they can still use in Minecraft commands
What platform?
Paper
Do I need something other than io.papermc.paper:paper-api:1.21.7-R0.1-SNAPSHOT ?
it's an internal class
Because I can't find such class (or at least, IntelliJ's autocompletion can't)
Ah
There is no way I can just serialize a Component into a SNBT String from the API? Sad
SNBT is minecraft specific, and we don't expose SNBT inside of the paper API
Hmm, and raw NBT bytes maybe? Serialization to SNBT is not an issue for me
The bytes API is more comfortable because the API doesn't actually promise those bytes are in any particular format
Doing anything with that byte[] other than saving it to provide back to the API unmodified is out of scope, if it breaks you get to keep both pieces
there is some work on adventure for looking to expose a means of dealing with NBT, just, really unstable format
Yes I know this for items, but is it accessible for raw components, or would I need to create a fake item with my component as display name so I can then extract it from NBT bytes after (which is a bit of a hack)
I don't really "care" about the unstable format, because I don't use this for storing. I just want it to be up-to-date format with the current in-game version, so that it can be used back in commands right after
that does become a huge issue when writing a serialiser, however, which is the issue
if you're on paper your easiest option is going to be to use userdev and just poke internals for output
Hmm ok I'll see how it turns out then, thx
You can look at the nbt serializer PR
Haven't had a chance to look at it myself
I'm updating my plugin to the newest adventure libs, and testing on newest Paper for 1.21.7
You are running the latest version
I've noticed messages to the action bar, and hover JSON components messages sent to the player are not functioning (no hover component when hovering over them) in my testing. I'm not seeing any stacktraces in console (maybe I need to enable logging levels? Would appreciate info on that if so.) nor were there any compiler errors or anything prior to testing. Just simply updated Paper for my test server, and updated the dependencies of all the adventure libraries I was using.
Any tips on how I can get to the bottom of what might be happening? When this has happened in the past I usually need to add some new dependency to my shadowed JAR that adventure has incorporated, but I would expect potentially an error or something to help identify that.
Thanks ๐ซก
- Are you using bukkit-platform or paper's API? I assume platform from your comment about shadowing.
- Was your plugin working on 1.21.6? I know platform isn't even updated to that yet.
I am using bukkit-platform
Testing on 1.21.6 also had the same issue, but I didn't mention it since 1.21.6 was around so briefly
PR's here - https://github.com/KyoriPowered/adventure-platform/pull/212
It could really benefit from people testing it out and confirming it works.
-# Also just move to Paper API! :3
I'll test it
@wet kestrel well I wanted to test, but the sonatype repo from md5 wants me to do some user/pass login stuff for some reason
> Could not resolve net.md-5:bungeecord-chat:1.15-SNAPSHOT.
Required by:
project :adventure-platform-bukkit > com.destroystokyo.paper:paper-api:1.15.2-R0.1-SNAPSHOT:20201203.195914-323
> Could not resolve net.md-5:bungeecord-chat:1.15-SNAPSHOT.
> Unable to load Maven meta-data from https://oss.sonatype.org/content/repositories/snapshots/net/md-5/bungeecord-chat/1.15-SNAPSHOT/maven-metadata.xml.
> Could not GET 'https://oss.sonatype.org/content/repositories/snapshots/net/md-5/bungeecord-chat/1.15-SNAPSHOT/maven-metadata.xml'. Received status code 401 from server: Unauthorized
I don't know the process to get an account with auth for that repo
actually that wasn't the only repo to reject me
Oh, sonatype nuked snapshots repo didn't they 
tell that to fuuid
I have two lines of code that exist for Spigot support for now. that's all ๐
if (spigot) {
dont(); }
New snapshots repo if you're up for editing more than you thought you would: #build-tooling-help message
are you telling me fuuid exclusively supports modern versions of paper?!?!
No, and let's stop misusing a help channel :3

Looks like I've run into some unfortunate timing
after the build is updated for the new repos, I don't mind testing that PR
I changed the build locally, but it's not finding the artifacts, I suspect I made a mistake in my changes and it's probably my fault, or perhaps these artifacts are somehow not available yet (maybe unfortunate timing from today being the day it got nuked)
Just want to ask before i spend hours trying to do this to realise its not possible
Is it possible to use adventure nbt to (de)serialize things like block states (or block data, whatever is needed to copy the exact data of the block)
if so, is it platform agnostic (will it work with serializing paper block state and deserializing as a fabric block state)
if the answer to all that is yes,
are there any libraries that do this or am i going to make my own serializers
NBT is just NBT, if you've got NBT, adventure-nbt can handle it
yeah worded this badly sorry, is there built in methods to convert native bukkit objects to nbt
Adventure does not know about any bukkit stuff
paper knows about adventure though and there is converters for text related things
Is there a way to convert an Adventure component to an NMS component?
that's something that would be in adventure-platform, not sure if it's exposed in some form of API though
I kinda doubt it tbh
ok apparently MinecraftComponentSerializer exists and seems accessible
it depends on the platform yes
not all platforms have a MinecraftCS
e.g. -platform-modded has asAdventure/asNative methods in the MinecraftAudiences type, -platform-bukkit has MCS, native platforms will have their own ways too
How do you properly parse unicode glyphs? I use something like this atm: java if (unicode != null && unicode.contains("uE")) { unicode = StringEscapeUtils.unescapeJava("\\" + unicode); but that doesn't work with Adventure. /tellraw works but my usage of some unicode chars becomes empty content and doesn't work.
what do you mean by "parse"
well they come in like this
sounds like your file encoding is borked
nvm i had some unicode strings with a lowercase e so that .contains("uE") wouldn't fire on em
what im saying is you don't have to do any parsing or unescaping logic if you just have your file encoding set correctly
Hey! I've got weird error when I am trying to start my server with custom plugin:https://pastebin.com/KjEU1ji8
this is my pom:
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
I've had the same error on the other project that was built with gradle.kts and relocating adventure solved it. The version is the same - 1.17.1 but the error still stays
You cant relocate adventure and use native paper component methods
java.lang.NoSuchMethodError: 'void org.bukkit.inventory.meta.ItemMeta.displayName(pl.karoldronia.sponges.libs.adventure.text.Component)'
See how it's looking for this method which definitely doesn't exist
tl:dr stop shading and relocating adventure. It's in paper.
okay I don't know if I do it correctly but this is my pom:
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bukkit</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-minimessage</artifactId>
<version>4.18.0</version>
</dependency>
I am not including adventure-api and I am not relocating anything
Error:
public interface MiniMessageHolder {
MiniMessage MINI_MESSAGE = MiniMessage.miniMessage();
}
paper already ships all that so idk why you're including it anyway
and if you're not using paper, then dont use paper
so jsut remove all adventure dependencies?
I suspect that you're building against a much newer adventure than the one bundled in the ANCIENT (outdated, unsupported, exploitable) version of paper you're using.
org.bukkit.plugin.InvalidPluginException: java.lang.NoClassDefFoundError: net/kyori/adventure/platform/AudienceProvider
Paper includes adventure - Player is an audience, you don't need an AudienceProvider
I feel like you haven't removed your adventure deps if you're even able to build with that...
yea now I have removed all adventure dependencies but I got:
java.lang.NoClassDefFoundError: net/kyori/adventure/text/minimessage/MiniMessage do I need to implement MM?
what version you running?
server is on 1.17,1
You're in such ancient territory there. Not sure anybody remembers specifics. You should upgrade off a server full of issues to modern.
Either upgrade to the latest paper version, or either use adventure-platform with relocation. (you will lose ability to use native methods)
Yeah we can't provide support for legacy paper builds
any forecast to support 1.21.7?
There is no ETA
I didn't think there were changes between 1.21.6 and .7 that were adventure-relevant. Are you perhaps using adventure-platform-bukkit?
Okay, then you want #adventure-platform-mod-help where you can see conversation about testing the PR adding that support. Adventure itself has been fine for a whiiile.
HELP, server on 1.21.7
player.sendMessage(
Component.text("test")
.hoverEvent(HoverEvent.showText(Component.text("here")))
.clickEvent(ClickEvent.runCommand("/say test"))
)
clickEvent doesn't work but other events work
What platform?
isn't that just a signed argument thing?
how can I serialize a component as adventure nbt?
Yeah, I figured it out myself now. But I would assume its not in any repo yet and I'm too lazy to setup that myself so I just added this into my codebase lmao
I didn't know Kotlin had async await 
Too lazy to write "Wait for" lmao
I mean technically you can do .await() on a completable future in a coroutine
can I send a translationkey or translatable component as a moonshine @Placeholder or do I need to make a custom resolver for that
iirc moonshine does not integrate directly with adventure at all
so it's kind of up to you to choose how to fit them together
but you can definitely do that
isnt moonshine dead
pretty much
What's the best way of detecting whether an audience can use clickable components or not?
Which is typically just console
Console doesn't work with clicks? I guess I could see the URL part being hard/impossible but run and suggest command should be doable
That's doing to be dependent on the platform implementation though and I don't think there is any way for you to know
Are certain terminals meant to work with clickable components?
They could, I don't know if any of them actually do work though
hmm ok. Thank you
Whether or not console can click on things is going to depend on the kind of click event, the platform, and what terminal you're running the game in
why do you need to detect it?
Heck even URL click events would work if they just called out to xdg-open
Does minimessage support shadow gradients as of now? I saw a github pull request.
Done as a quick tech demo, would need a bit of actual design work and cleanup if we want to actually incorporate this into MM
<gradow:red:blue>hello world
<shainbow>wha...
Like this
If the PR isn't merged, then no
You could technically do it yourself, or up-vote the PR and share your thoughts about it to help the team
And, as we can read in the description:
Done as a quick tech demo, would need a bit of actual design work and cleanup if we want to actually incorporate this into MM
It's not gonna be merged like this, so you should rather leave a comment explaining why you consider such feature to be useful, and worth investing some time to integrate it properly
Can also copy and adapt the tag from the PR into your plugin
Huh, that's way better than gradient on the text itself
Yeah, that looks really pretty
iirc when I tested it, it looked nice on white text with (multi-)colored shadow, but any text color other than white was not that good in terms of results
Hello, how can I reset text decoration like &r in Component.text(...?
.decoration(TextDecoration.ITALIC, false)
so that disables italic? do I understand right?
That's it, if you need to remove other decorations, you can just replace ITALIC by something else
Thanks!
What does MiniMessage.miniMessage().serialize(component); do? please provide an example
ok thank you
lmao
So I do not know if im blind, but im trying to find the docs to do with the click events for adventure?
I checked the adventure docs quite a few times and feel daft for not finding the right page
No actual docs? Just the javadocs? Thats a shame, but cheers ๐
The docs describe there are events. The javadocs show how to use them. They're not super complicated.
If you feel there could be an improvement in the docs, feel free to write an issue or pull request.
Hey, why does the LegacyComponentSerializer not preserve the reset tags(&r and <reset>) upon deserializing a legacy string.
My code:
miniMessage.serialize(legacySerializer.deserialize(msg))
Those two things (reset tag and legacy r) are not identical. It makes more sense to deserialize the legacy to something that makes sense as a tree in components, and then minimessage serializes the tree.
-# Also <reset> is not something you should encourage others to do often :3
Where? Genuinely didn't see them haha
@wet kestrel I was able to compile the build now for blood's PR for platform-bukkit and I was able to confirm it working in Paper 1.21.7 builds, I left a comment on the PR. Sorry I was unable to test it the other day (unfortunate timing with that snapshots repo being sunset... or nuked or whatever)
https://docs.advntr.dev/text.html#events mentioned here
Huzzah! Thanks for helping! ๐
Isn't that exactly what my code is doing? It deserializes the legacy string into a MM object using the Legacy Serializer, and then MM serializes it back into a string
Yes. I am describing what your code is doing. It deserializes the legacy stuff into a tree. The tree lacks the concept of "reset". Then it serializes the tree as minimessage.
Oh wow my bad, cannot believe I didnt see that as I even used the builder example earlier to change my Components due to the immutability.
My apologies once again
Also semi neat / odd thing question... do you use dark mode on the docs by chance mbax?
I do not. Never bothered to hit the button. My OS defaults to light.
Right, got it, that might be my language barrier ๐ Either way, so isn't there any other way to make it deserialize the &r aswell?
I do not think so. And that is a bad design to do so.
Why? I mean, how would one reset for example strikethrough without it?
components have no concept of "resetting"
the &r in legacy text basically just means "wrap the following text with an explicitly set style (white text, no formatting or events)"
this is also notably different than the MM <reset> tag, which closes currently open tags
Strikethrough is a different code from r and should process fine.
Okay, well, thank you for the help
What does component.color(); return if multiple NamedTextColors are used in the component?
a component can only have one colour
however, a component can have children which have different colours
Component#thing() will return you the thing that one component in the tree directly holds
you could analyze all the colors in use using the ComponentFlattener
Im guessing .append() makes those component children? also .thing() doesn't seem to exist at all, looked through javadocs
I feel like this is really dumb, but is it possible to get a List of (or at least separate) components that have .append() in it?
What im trying to do is get the colour of the player's name from displayName() in Paper, with other text being in the display name
.thing() was an example that applies to any one property of a component
children, content, style or style elements like colour or decorations etc
.thing() is not literally an actual property of a component
i'm not entirely sure what is it you're asking, components are a tree, you can traverse them with the various iterator/iterable methods on Component, or with a ComponentFlattener
Would a PR to adventure NBT adding something like
List<MyData> values = ...;
ListBinaryTag.Builder builder = ListBinaryTag.heterogeneousListBinaryTag().initialSize(data.size());
for (MyData data : values) {
builder.add(StringTag.stringTag(data.thing());
}
be fine? basically just, a way to initialize builders with a set size for when you're directly copying another list/map into it.
(Or is that already a thing somewhere and I missed it?)
Do you have a particular reason for wanting this?
Just some potentially hot code that I'd like to optimize all the wayโข, I know it's not the sort of thing that'd make a massive difference, but any easy & non-messy optimization is a good optimization
if you already want to do something like that then I suppose it would be better as heterogeneousListBinaryTag method parameter, so you don't create the backing list object twice
Also unrelated question - is there a reason a lot of defaultValue parameters are @NotNull? compound.getCompound("key") returns an empty compound if the key is missing, so I was gonna do .getCompound("key", null), but ^
Wouldn't be a problem currently as builders only initialize their underlying list/map when something is first added as far as I can see, but if they want to treat that as a subject to change implementation detail thing then yeah probably in the creation method
does the code enforce non-null on the param?
Nope
then yea just an oversight, happy for the param to be nullable with a contract annotation on the return types
I suppose you could do
List<BinaryTag> tags = new ArrayList<>(data.size());
for (MyData data : values) {
tags.add(StringTag.stringTag(data.thing());
}
return ListBinaryTag.listBinaryTag(BinaryTagTypes.LIST_WILDCARD, tags);
For mostly the same effect?
Still has some redundant list copies, but that is probably just micro optimization at that point (and I assume you wouldn't want a fromUntrusted(List) either way)
Just out of curiosity, what is approximately the size of your lists you're talking about?
Any size, which is why I preferred to do it like this - could be very big, could be very small
Alright, thanks!
Sorry, haven't used @Contract much - is @Contract("_, null -> _; _, !null -> !null") + making the method itself nullable correct for that?
If the second param is null it may return null, if the second param isn't null it will never return null
iirc the first part is useless, because it does not specify anything about the return value
Ah, makes sense
Only _, !null -> !null is needed to say that, whatever is the first value, if the second one is not null, then the return value won't be null
Yeah I see, thanks - it already knows it might be null because it's nullable, just need the contract to tell it when it isn't
In this case, yes. But it could also be the other way around, in some other cases: _, null -> null for example, says that the result will always be null if the second param is null. Is says nothing about when it won't be null, meaning it can still be null even if the second param isn't. In this case obviously this is not true, but I was just showing you an example. The method could be "get the property of that user, which might exist or not, but will always return null if the user is null"
you need _, null -> null; _, !null -> !null
Wait, no? The result won't always be null when the default value is: There is the case where the requested value exists and is returned
Unless I'm missing something, I just gave a really far look at the problem
_, null -> null doesn't make any sense
you're saying it will always return null if the second param is null
it's just _, !null -> !null
that's not what contract does, null just indicates the return type is nullable
No, I really don't think so, the nullability of the return type is indicated with the @Nullable on the method
https://javadoc.io/static/org.jetbrains/annotations/26.0.2/org/jetbrains/annotations/Contract.html
that just means "ignoring what the first parameter is, the second parameter being null results in a null return value", not a null return type
when will adventure be ready for 1.21.7? im having a bug with the gson serializer and im not sure how im going to handle it im ngl
here is the error im having
public static final GsonComponentSerializer GSON_SERIALIZER = GsonComponentSerializer.gson();```
literally whats failing rn
Is there any reason you're shading adventure? iirc the GSON serializer is included in Paper
you are not relocating net.kyori.option
lots
oh tysm
PRed these two, but I have another question - is there any way to get a builder from a compound tag (other then making an empty builder and adding the values from the tag)?
The put methods on CompoundBinaryTag copy it and return a new one (which is very useful actually), but then when editing multiple values at once it'd be creating a copy every time, which isn't great.
So something like
CompoundBinaryTag edited = tag.createBuilder().put(x, y).putInt(x, y).remove(x).build();
that'll create a builder directly from the compound's map could be very useful (if it doesn't already exist)
Is there any version of a MiniMessage parser that's able to be ran outside of Minecraft? Like on a non-minecraft app
I mean, MM is tied to adventure itself, it's just a serialiser
it's the component handling which is where platform stuff starts to come into play
I see
I know there's a minimessage web viewer so I thought maybe there was a 'generic' implementation somewhere
Well, yea, that's just MM + Adventure
I have
<click:run_command:/kick <player>> and replace <player> using tag resolver. <player> is parsing, but <click> is not.
btw if I do <click:run_command:'/kick <player>'> <click> is parsing, but <player> is not
how to fix it?
What kind of resolver is player? I make sure to use placeholder.parsed, so I don't mess it up.
it's placeholder.unparsed
hm, it worked with parsed. thanks
Yep! ๐
Is there a way to use the ClickEvent of a component to enact a lambda function / method on click? If so how? If not, is there a reason why that was never added? It seems like a reasonable thing for it to do considering how Paper-entire is based around methods called on event based logic ๐
e.g: imagine having a class defining some custom function, and you can set the click event to call a method within that class if the component is clicked?
ClickEvent.callback or something
See this is why I politely suggested maybe the docs need a tiny bit of elaboration / a few examples of ClickEvent being used in various use-cases.
As I just looked it up and it says the param is a ClickCallback<Audience> which is taking me further down the "undocumented (other than javadocs) abstractions" rabbit hole ๐
I mean, the docs always need more love, be the change you want to see
*I would if I knew what to change.
Hope you see the issue here haha
Pretty sure ClickCallback is just a functional interface
There is a certain level of "Ive figured it out" fatigue.
By the time you brute force it or bash head up wall till it works, you usually dont have the energy to go fix the docs.
Sometimes we just need someone a bit more knowledgeable to come in and add an example for us poor unfortunate sods haha
Yea, can basically just ClickEvent.callback((audience) -> { audience.sendMessage(text("boo"));};
On a slight tangent, the Tauri documentation is rife with "Ive figured it out fatigue".
So much effort goes into getting stuff to work, theres no energy left to fix the docs haha
Cheers Electro
/**
* Represents a collection of messages that can be shown in bulk to an Audience.
*/
public class MessagePage {
/**
* The title of the page.
*/
private final Component title;
/**
* The main content of the page.
*/
private final List<Component> content = new ArrayList<>();
/**
* The footer (the final message at the bottom of the page).
*/
private Component footer = Component.empty();
public MessagePage(Component title, Component footer) {
this.title = title;
}
/**
* Adds a new component to the content of the page (placed directly below the previous line of content).
* @param content The component to add.
*/
public void addContent(Component content) {
this.content.add(content);
}
/**
* Shows the page messages, in the correct order, to the specified Audience.
* @param audience The audience to show the page to.
*/
public void showPage(Audience audience) {
TextComponent.Builder builder = Component
.text()
.append(title)
.appendNewline();
audience
.sendMessage(addContent(builder)
.append(footer)
.build()
);
}
public void setFooter(Component footer) {
this.footer = footer;
}
private TextComponent.Builder addContent(TextComponent.Builder builder) {
if(content.isEmpty()) return builder;
for (Component component : content) {
builder.append(component).appendNewline();
}
return builder;
}
}
public class MessageStack {
private final List<MessagePage> pages = new ArrayList<>();
private int currentPage = 0;
public MessageStack() {}
public boolean addPage(MessagePage page) {
return pages.add(page);
}
public boolean addPage(Component title, List<Component> contentLines) {
MessagePage page = new MessagePage(title);
for (Component content : contentLines) {
page.addContent(content);
}
return pages.add(page);
}
public void showCurrentPage(Audience audience) {
if (pages.isEmpty()) return;
MessagePage page = pages.get(currentPage);
page.setFooter(generateFooter());
page.showPage(audience);
}
public void nextPage(Audience audience) {
if (currentPage < pages.size() - 1) {
currentPage++;
}
showCurrentPage(audience);
}
public void previousPage(Audience audience) {
if (currentPage > 0) {
currentPage--;
}
showCurrentPage(audience);
}
private Component generateFooter() {
TextComponent.Builder builder = Component.text();
Component pageLabel = Component.text("Page " + (currentPage + 1) + " of " + pages.size())
.color(NamedTextColor.GRAY);
builder.append(pageLabel).append(Component.text(" "));
if (currentPage > 0) {
Component prev = Component.text("[Previous]")
.color(NamedTextColor.YELLOW)
.decorate(TextDecoration.UNDERLINED)
.hoverEvent(HoverEvent.showText(Component.text("Go to previous page")))
.clickEvent(ClickEvent.callback(this::previousPage));
builder.append(prev).append(Component.text(" "));
}
if (currentPage < pages.size() - 1) {
Component next = Component.text("[Next]")
.color(NamedTextColor.GREEN)
.decorate(TextDecoration.UNDERLINED)
.hoverEvent(HoverEvent.showText(Component.text("Go to next page")))
.clickEvent(ClickEvent.callback(this::nextPage));
builder.append(next);
}
return builder.build();
}
}
Im pretty happy with that as an MVP (will be changing the formatting of the page buttons obviously, but the concept is pretty neat) ๐
Nice little collection of messages / logs / whatever components you fancy into a "page" of messages you can flick between nice and easy.
Wish there was a slightly more performant way to do page footers than re-do them constantly every time you flick the page.
Maybe builder pattern for the MessageStack, so when the footers are added there is 0 chance of new pages being added?
is that bottom most private method in the 1st one supposed to still be there or
oh and the first one could implement ComponentLike instead of having a method to show to an audience
same with the 2nd one if the page moving is separated out from the showing
But it's right there in the javadocs? Second method in there, too. Javadocs should be your first place for "what can I do with [classnamehere]?"
Why would I want to not show the audience via the class itself?
I appreciate that, but, in my defence, I'm very stupid ๐
Jokes aside it couldn't hurt.
A good example is i have no idea what ComponentLike is, so im gonna pop both to the docs and javadocs haha
It would allow you to instead of msgPage.showPage(audience) you would do audience.sendMessage(msgPage). The main difference being that you could easily replace sendMessage by any other method, and also merge it with other components or anything.
An ComponentLike is just something that can be used as a component (thanks to the method asComponent)
What other commands would be useful to have do to a page other than send Message?
Idk you exact use-case, but I could imagine showing it through a book, a dialog, or doing other kind of component-level operation such as appending a prefix / suffix, or replacing texts, colors, stylesโฆ
Can I get translated item name as String using minimessage?
What do you mean? What are you trying to get? The plain text of the name? The MiniMessage-encoded component? Something else?
Translated Item name as String.java from tranlation component
MM just deals with serialisation
if you wanted to have the localised names in there, you'd need to flatten them
Furthermore, "translated" in which language? English? Korean? iirc on Paper they bundle the English locale file, but in other case you'd need to include and maintain the translation file as well if you want to do server-side translation
So, is there no way to use a Translation Component for item names with Bukkit/Adventure in Spigot either?
that stuff will work as much as spigot allows it to work
adventure mostly covers UX related stuff, it's just a conveinent library that we're able to adopt into the paper API across the board; I don't think that there is a public adapter for non UX stuff;
A translation component contains a translation key with translation arguments (the values for the "placeholders" inside translated content), as well as the style (color, decoration...). You can very much use it, but it won't give you the translated content alone: you need to use a translator, fed with the translation file of the language you want to translate into
But it seems that what you want to achieve is unclear, even maybe for yourself. Please explain a little bit more (with context) about your use-case so we can better understand your goal to actually hepl you achieve it
Yea, I was gonna say, assuming I even understand what you're asking; But, adventure platform doesn't deal with items; idk if they come with a flattener preconfigured to be able to use mojangs built in localisation file for english either
And two more things actually -
- would you be open to adding
CompoundTag#containsKey(String)andCompoundTag#contains(Key, Type)utility methods? - is there any way to get a
BinaryTagTypeby its byte id? I can see an internal method, but as far as I can see it isn't exposed anywhere - would be nice if that could be made public, or at least a way to get a list of allBinaryTagTypes so that I could build my own mapping.
Sorry for all of the NBT questions btw lol - migrating a pretty big project from an old NBT lib to adventure NBT, so I'm just trying to PR some stuff that I'm missing
Hello yall i got a question im tryna learn plugin making with paper on kotlin but i cant quite figure out whats the correct return type after i call ClickEvent.callback(foo()) for foo()
for context this is the foo function im trying to call
Nothing
Wait that looks strange
Please share more of your code, what is that function supposed to do and why do you want it to return a click callback
this is more of a test to see if i can understand how it works so its veeery ugly
but my main goal is to fire handleClick when i click the text
my main problem is it excpects a return value and if i make it nullable it errors out on the callback
ClickCallback is the functional interface type
you're invoking your callback when creating the click event. you should be passing that callback function in instead
So like, blah.clickEvent { handleClick(ctx) }
trying this but it complains abt type mismatch
that's just pseudocode example
look at the method in the interface, that's the signature your lambda has to look like
bruh im so dumb lmao
Sorry would be blah.clickEvent(ClickEvent.callback ({ handleClick()}))
Or does kotlin let you extract the lambda from there? Idk, kotlin weird
im too used to c# lambdas im tryna wrap my head around kotlin syntax
very clean but my small brain cant keep up
It's not super beginner friendly
It was written by senior java devs to speed up writing code I guess
No worries if you're busy right now, but is there a chance you could quickly ๐/๐ my suggestion above, just so that I know whether I'm good to PR it?
ok so i fixed it with this line, as far as i understand clickEvent wants an event to summon when its time to invoke it and the callback then simply acts as a "pointer" to what to run (i may be extremely wrong)
thx for yall help anyways
First sounds good, idk about the second
but if it's not too much hassle just PR it and we'll see
Will do, thanks!
And how about the earlier one (#adventure-help message)?
None of these are a ton of work code wise btw, so if you'd rather I just PR them/any other small things I may have in the future so that everyone can take a look, let me know
yeah that also sounds good to me
Is there a cleaner way to do this?
ListBinaryTag listTag = compoundTag.getList(key, BinaryTagTypes.STRING);
for (BinaryTag tag : listTag) {
materials.add(((StringBinaryTag) tag).value());
}
(As in, without having to cast the tags, since we know the list is of that type)
Is this possible?
<start_date:'<date_format:'dd.MM.yyyy':'EEEE'>'>
first one being resolved by a date resolver and the second being a booleanChoice
Why not just have your statt_date take in the ddMMyyy stuff and not have it run through two resolvers?
can you elaborate? I thought of one way by just using Java's DayOfWeek's display name (PlaceHolder.unparsed usage)
I'm saying to just do <start_date:'dd.MM.yy':'EEEE'>
how would that work?
What do you mean? No differently from any other tag resolver you make.
what...
Can you clarify what you're confused about? ๐
How would I use a custom click event type via Minimessage? I get something like <click:custom:...> but not sure how to format the "..." since the payload is more complex
based on the javadocs, the payload is a key and an NBT tag
honestly i don't understand much more than that, if the point is to run code when the text is clicked then classically run_command is used
trying to figure out where the server receives the custom payload and i dont see anything
ah! here we go
this is the corresponding Paper event
https://jd.papermc.io/paper/1.21.7/io/papermc/paper/event/player/PlayerCustomClickEvent.html
Yeah, appreciate it, though I know about the event and everything. The reason for the custom action is so that you can run custom code without having to register a custom command to do so
Just trying to see how to do it through minimessage, I've tried the things that make sense to me but can't get it working
the click tag seems to be hardcoded to only accept 1 argument after the click type
https://github.com/KyoriPowered/adventure/blob/2f48b6b0cd9332781f7ec724012391f4a70c663b/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/standard/ClickTag.java#L66
so its not like you can pass the key and then the NBT
I believe the NBT is optional for custom events
But then I'd think something like this would work "<click:custom:'minecraft:test'>Hey</click>", but it doesn't seem to
the minimessage tag requires a string value
it doesn't work at all with the custom type because the tag only operates on strings
it using a string payload:
https://github.com/KyoriPowered/adventure/blob/main/4/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/standard/ClickTag.java#L66
it not supporting non-text payloads:
https://github.com/KyoriPowered/adventure/blob/main/4/api/src/main/java/net/kyori/adventure/text/event/ClickEvent.java#L248
you can always write your own tag resolver that works in the way you'd like
it could even prepend a namespace of your choice, to avoid the escaping issue
so <mycustomtag:foo> would create a custom click event with key mynamespace:foo and empty NBT
I guess I'm just surprised because hover:show_item also needs to accept a key, which it accepts as a string, but doesn't work for custom whose only required field is id which is also a namespaced ID
But that makes sense, custom resolver seems like a good approach so I can do that, cheers gang
With BinaryTagIO, is there any way to unwrap lists as you load them?
Kinda like NMS loading logic does:
(And if not, would that get accepted as a PR? otherwise you'd have to have loop over every tag in every tag to make sure they're all unwrapped as far as I can see)
Implemented something like that ^ for now, but would be a lot nicer if the deserialization could do that automatically (probably with some param to toggle it)
Question:
Would there be a way to detect if a specific feature is actually available on the server/proxy Kyori is being used on?
Like in my case would I like to know, if a Server/Proxy runs a version supporting Dialogs to use it.
Also, is there any form of tutorial or example on how to use Dialogs in Adventure?
I want to make a platform-agnostic Dialog system, so that I only have one core code base for it that works on proxy and server (In my case would it run on either Paper, Velocity or BungeeCord (using the platform library), tho I consider droping the last one).
^ I think there's only DialogLike stuff for platforms to extend, but not a full API yet
Rip
And it's not likely to happen soon
It will, at the end, be the case. But when it will be stable
Guess I'll have to make platform-specific code then to create the Dialogs...
For now, you have to use Paper's implementation if you want to use them, and idk about other platforms for now
Dialogs are too potentially in flux. Paper's implementation has the whole package marked experimental.
And this?
Is there a way to know if a Dialog(Like) would work?
I assume I would need to do Class.forName(...) checks for the respective platform?
Are you talking about detecting the presence of an implementation (depending on the platform), or the version of the platform (Paper...) being < 1.21.7 (or whatever version dialogs first came out)?
I simply want to make sure that when I want to use Dialogs, that the platform the server runs on is actually a version that could support it.
Well, since implementations are provided by platforms, if the platform provides one, then it certainly exists, otherwise no. If you're talking about backward compatibility, then you need to check in which version of each platform the dialogs implementation came out, and simply test that version (or, if you don't want to bother checking version, you could technically test for the presence of the specific implementation class, yes)
But you cannot reliably platform-agnostically determine whether dialog implementation exist or not, since dialog implementations are provided by platforms. The best way you can do is assume there's not, and for specific platform you know there's one, then use it
I know I've asked this before, but can I make nested tags in a choice tag or should I just use a custom tag resolver?
For the datetime thing I mentioned before I used a custom tag resolver
yo, after updating adventure click event doesn't work for older versions
idk if thats because of Adventure or Adventure Platform
but what i know is that it works for 1.21.7 but not older versions
If using -platform use #adventure-platform-mod-help ๐
if i have a decoration/style that is set to false rather than unset.. how do i make it unset
declaration: package: net.kyori.adventure.text, interface: Component
set the state to NOT_SET
Is there any form of info/guide for how I could create some own Dialog implementation using Adventure?
Would like to implement some basic system for Velocity to display Dialogs to a player.
You would need the platform to implement it - adventure only provides the framework for platform dialog API until we've added a dialog api of our own
Guess I have to wait until Velocity has something...
The issue I have with velocity is, well, time, but, also; Do I implement something that I will likely then need to deal with again in the future to make it conform to the adventure API
is it possible to make a resource bundle from a file instead of a in jar resource?
https://docs.papermc.io/paper/dev/component-api/i18n/#resourcebundle
Yes, there's methods on the string based translation store to read from a path iirc
Hi everyone!
I'm working on a project that needs to parse sign block-entity data.
My goal is to display them on a website with HTML, so the text, colour and glowing-ness need to be extracted, so I can insert it into the HTML template.
I used to do all the NBT parsing myself, with manual handling of edge cases, like some plugins putting data where it shouldn't normally be, according to the vanilla spec. But I try to handle these things as best as I can anyway.
I also support many Minecraft versions, all the way back to 1.13
So I've been wondering whether using Adventure would be beneficial for me here.
Could it handle (at least a part) of this parsing for me?
yo
my gson serializer is serializing weird for 1.21.4
{"color":"yellow","click_event":{"action":"open_url","url":"https://store.servername.net"},"text":"[โฅ Store]"}```
look at this
click_event instead of clickEvent
url instead of value
yeah you're serializing to a newer version's format than 1.21.4
Well, what are you doing?
probably using a version of adventure not made for 1.21.4
its latest adventure
Okay, but, you are likely using adventure on some form of platform
oh paper
what version of paper?
So, you're not using paper adventure, you're likely using adventure-platform or whatever
it might be
im not sending it to the player yet
Well, adventure isn't magical, it doesn't know what version of MC you're serialising for
how do i make it figure it out then
so it's just going to use some default, given your complaint, the default is likely for the latest version
the serializer serializes based on the current server's capabilities, native adventure integration does not have this problem, platforms kinda need to detect that
okay how do i help it out tho
like how do i provide a version somehow
idk much about server capabilities
but what i do know is that this is incorrect for my use
I'd guess the question is, why are you using the gson serialiser directly?
idk how the version detection stuff works in adventure-platform, so, I'm kinda out
gson-serializer is separate module from adventure-platform
i see adventure-platform tries to set the serializer version so it should be fine if the server is the version you claim it is
actually, yes you are using the serializer directly
that will always be at latest version
if you want the version specific serializer you need to get it from that class
but the fact you are manually serializing a component is kinda sus
oh perfect
I can use BukkitComponentSerializer#gson
Well, you can use adventure-nbt to parse the data if you aren't already - beyond that it depends on what exactly your system is; are you getting the data while the server is running? if so you could probably use NMS to load the NBT with Mojang's logic and avoid needing your own handling.
As for what adventure specifically can do, beyond the NBT bit you could use it to parse the components, but I think that's about it, it's not really meant for handling block entity data or anything like that.
Thanks for the reply!
I didn't know there was an nbt deserializer ๐ Somehow I wasn't able to find it before...
I can't use NMS, because this project will have to work on other server software than just Paper
And it even has to work without a server at all, running completely externally.
i mean, you can totally use adventure-nbt to handle block entity data if you so desire, it's just an nbt parser after all, if it can read it, you can fiddle with it
I see
I do already have an NBT Parsing library I'm very happy with, but it doesn't do more than parsing the NBT, like properly deserializing everything into text components and such
I'd have to deserialize everything myself, manually
Which seems like a rather daunting task
adventure is no different
๐
it just reads the binary and gives you a BinaryTag
I see
I was hoping I could use it to handle the text component stuff for me
Because sign text has been changed many times over the versions
Sometimes even including JSON for extra "fun"
Is there no way to use e.g. the gson serializer detached from a server? don't actually know how it works internally
Or alternatively, just run a server as your backend
I mean, your issue is DFU if your issue is the upgrade stuff
well, maybe; getting the structure is one thing, being able to load it on the server is another, as they just deserialise it into a json element tree and then run it through their codec
I have indeed been suggested this:
But that sounded rather cursed to me, so I was hoping there'd be a better way than this
(BlueNBT is the NBT library I am using)
But I don't want to Fix Up any Data
This needs to be able to run on essentially archived world files from all the way back to 1.13
I mean, when you have the NBT one, transforming to gson and parsing it is doable, mojang already supports that through DFU codec funkery
Or do you mean fixing up the data at runtime, without modifying it on the actual files on disk?
^ that's what the DFU is
I mean, it really depends on what you want to do, part of the reality is that the format is evolving
if you wanted to use the servers built in serialisation stuff, you would need to run the underlying data through DFU somewhere so that it can parse it
Myeah
It's Mojang's system, very rough explanation but basically just - all data is saved with an data version int, and when loaded the data is ran though a list of fixes determined by comparing the data's version to the current version to make it match modern format
flyway but for json?
It's essentially like a CLI tool that runs on the world files themselves directly
Well, Mojang does have some gross codec stuff to convert NBT to Json ๐
But, I mean, once you have it in json iirc adventure is fairly adept at decoding it
Ahh that makes sense
I've done similar stuff in the past: https://github.com/TechnicJelle/BlueMapSignExtractor/blob/ffb576e2e8d4ee9b468d5ab629e96fc1b252350c/src/main/java/com/technicjelle/bluemapsignextractor/common/ChunkClass.java#L29-L55
There is DataConvertor, idk how detatched it is from MC
not entirely, because ofc it needs access to mojang stuff to deal with parsing data, NBT, etc
Then I might try making some classes that mirror the various NBT layouts of the sign data over the versions
And then parse the nbt according to the correct version, like I'm doing here
And then I can convert that to json, and then feed it into adventure-lib...
is it normal that mm crashes with negative rainbow phase? ๐ค
<rainbow:-1>1234567890</rainbow>
at net.kyori.adventure.util.HSVLikeImpl.requireInsideRange(HSVLikeImpl.java:61)
at net.kyori.adventure.util.HSVLikeImpl.<init>(HSVLikeImpl.java:36)
at net.kyori.adventure.util.HSVLike.hsvLike(HSVLike.java:51)
at net.kyori.adventure.text.minimessage.tag.standard.RainbowTag.color(RainbowTag.java:105)
at net.kyori.adventure.text.minimessage.tag.standard.AbstractColorChangingTag.apply(AbstractColorChangingTag.java:126)
at net.kyori.adventure.text.minimessage.MiniMessageParser.handleModifying(MiniMessageParser.java:271)
at net.kyori.adventure.text.minimessage.MiniMessageParser.handleModifying(MiniMessageParser.java:273)
at net.kyori.adventure.text.minimessage.MiniMessageParser.treeToComponent(MiniMessageParser.java:248)```
๐ฏ
As mentioned in #paper-dev you could argue that MM itself should be throwing some kind of parsing exception instead but it should be expected for it to fail when you feed it invalid data
Normally MM just ignores the tag for exceptions iirc
Idk, open an issue I guess and we can see
Hmm, I dunno if it would be better to just strip the rainbow tag in that situation
More robust but more confusing
From a design standpoint, if I'm hotswapping between two boss bars (ie removing one from a player and adding another one in the same tick), is it better to create brand new instances or modify the existing boss bar with new color/text/progress
Don't think it really matters too much, whatever you prefer really
Yes we shouldn't be erroring here - please open an issue!
๐, as far as I can see data is auto wrapped when saving, but isn't unwrapped when loading - but maybe there's a feature for that somewhere that I'm missing?
How does logging components to a console work under the hood in adventure?
how is Windows support and checking terminal capabilities done? How do you convert minimssage into something a console can understand? What does the fallback process look like? (Full color range -> 256 colors -> ANSI colors -> strip colors?)
We have an ANSI serializer that does all of that
fyi, motd preview on the minimessage webui is currently broken
fixed
hey, can i use <click:suggest_command ...> and replace placeholders inside the command thereafter?
So <click:suggest_command:'/snapshots restore <username> <snapshot_unique_id>'>Restore</click>, and replace the <username> etc to the actual variables?
do u have an example or smth?
I'm here for an issue I'm encountering:
you see, i have to modify my shadow color in order for my item description to look clean, so I use <!shadow>. but I want to reactivate the shadow, so I just put a <reset> tag, but the shadow doesn't go away like it's supposed to. am I doing something wrong here, or am I just dum ?
<username> could be done as Placeholder.parsed("username", "mbaxter") for example
You probably don't want to use <reset>. Please provide a full example of MM string with your expected result
<shadow:#FF08FFFE><#FF08FF>Mining Fortune: <lang:space.71><reset><#53F52F>+65<lang:space.7>
Placeholder#unparsed sounds more appropriate, since it is for a command
Oh wait no, I just inverted in my head
worked, thank you!
Tbh, I find those two names (parsed vs unparsed) a bit confusing when looking at them from a distance. Because on one hand, parsed inserts the literal string into the parser, but on the other hand, if you want to get the literal value untouched, you want unparsed. Both have something to do with raw/literal values, but not in the same way
Maybe it is clearer than I think for native English speakers tho, and it is only amplified by the language barrier
You want the string parsed by the parser? Parsed
You want it not parsed by the parser, and untouched? Unparsed
I fixed it, my code was just not adding the tag :/
Yes but look at the above example : We want the player name not to be "parsed", we want it to stay as a string (so the first thing to come in my mind is unparsed). That's why
You do want the player name parsed, as a part of the click event.
I think the misleading part is the fact we don't want to parse tags inside the string (in that case, there should be none, but in a general case)
But I agree about the correctness of the names from the parser point of view
And maybe it's just me who is having trouble every time I need to choose, and I always go inside the code of either one to identify which one I need
(i also find them confusing, as a native speaker)
it's probably an issue from parsed/unparsed being able to be both "should be parsed/unparsed" and "is parsed/unparsed"
The fact that this discussion is currently taking place is indicative in and of itself that the names are confusing
the split between the two types of tags is imo a design flaw anyways
I would like to put some translatable messages into .properties or .json file (like minecraft does in the lang folder) but am confused by the docs and all methods that exist, for example there is this one but I'm unsure how to get a StringBased translation store and also there is no other method that takes a resource bundle
I took this code from docs.advntr.dev Localization:
Is using resource bundles the right way to do this anyway? i did this by right clicking on resources then new then Resource Bundle in Intellij
A component translation store isn't a string based translation store
You want either TranslationStore.messageFormat or MiniMessageTranslationStore
I thought Component.translatable method works only with a component translation store :/
Still, how do I put in a resource bundle? Or any other way of reading keys and appropriate translations from various files
The method is still not showing ๐ฆ
Again, you need a TranslationStore.StringBased - you're just not using that in your type
how do I refer to these keys now though?
I tried everything
did you register your translation store
Should I move this to #adventure-contrib? I just want to know whether I'm good to PR this, and if so, whether there's any specific way you'd want the option implemented (I assume not by default?) - currently if you save a heterogeneous list to file and then load it, you get basically a different list back, and handling unwrapping it manually is not great
I'd say so, and yeah i called this method in onEnable (is this correct?)
in the .properties file Intellij is showing it as "unused property"
omg i finally got it, it just needed some-key and not these namespace keys whatever, saw it here
thanks for the previous help ๐
it's showing me the default one instead of localized :( nvm i just got confused by Locale.FRANCE and Locale.FRENCH (tested by setting french ingame)
Hello, I have my own MessageTranslator class that translate messages into components, everything is OK. All the messages are mapped on a Map<Locale, Map<String, String>> messages; that I load from a json:
{
"messages": {
"en_us": {
"hello.player": "<green>Hello, <player>!"
}
"pt_br": {
"hello.player": "<green>Olรก, <player>!"
}
}
}
But I'm wanting to do something spicy, I want to create a TagResolver "ref" to reference messeges between themselves, example:
{
"messages": {
"en_us": {
"player": "player",
"command.ban.syntax": "/ban \<<ref:player>>"
}
}
}
How can I create a TagResolver like that? should I implement Modifying interface? I wanna make it even more spice, if possible, by adding some arguments, for example: ref:player:to_upper_case or some regex replacements.
Does someone know why the date does not get displayed in the message?
that's kinda wierd, but thank you ๐
it was explained a few messages after mine if you are interested about the why
Is there any particular reason you're not using the global translator?
global translator? it returns a MessageFormat, seems that it isn't good for me, I'll have to make the messages args {0} {1}, unlike MiniMessage
you can use whatever format you want with the global translator, with the translation store stuff
can I use that for lores? Because currently my MessageTranslator class have the method .translate(TranslationRequest) that returns a TranslationResult, then I can do toComponentList() or toSingleComponent() or toLegacy() toPlainText() etc
ItemStacks can't have server-side translations
the automatic translation of the global translator does not operate on items (at least on paper, not sure about other platforms)
but you can still manually invoke the global translator
Well, yeah, I suppose you could manually replace the component with the translated version on the server
as for the list thing, not exactly sure what you mean by that
you pass a component to the global translator, and it renders it using its registered translators
you get a component back, with any translatable components translated if a registered translation is found
you can still have your overall system, but it'd likely be easier to let the global translator handle the key + locale -> translation part
(and the global translator will auto translate messages sent to players, along with some other areas, just not items)
I didn't get It, can you give an example?
wdym
how to use it? it would be something like that?
player.sendMessage(Component.translatable("hello.player"))?
ye, that's all you'd have to do, if your platform supports the global translator
if you have arguments you'd have to pass them as well
currently on my system all the args are on a AgnosticMessageContext, it has a List<TagResolver> field
you can pass tagresolver arguments with the minimessage translator
the javadoc of the 1st link in this message explains some & shows an example of passing arguments
is it possible to get the <namespace> placeholder to be filled in this minimessage string, or should i rework how i am making this message?
<hover:show_text:"<ash>Click to view info."><click:run_command:"/module <namespace> info"><tyrian><module>
return Component.translatable(
"message.module.module_name",
Argument.string("namespace", namespaced()),
Argument.string("module", formatted())
);
<module> works but i assume <namespace> isn't because its nested in a click tag
I don't know what Argument.string is doing but it should be returning a tag resolver that produces a pre process parsed tag if you want <namespace> to get processed, like how Placeholder.parsed works.
i messed around with arguments until i got it to work, so could i ask if this looks fine to you? is this what you meant
return Component.translatable(
"message.module.module_name",
Argument.tag("namespace", Tag.preProcessParsed(namespaced())),
Argument.string("module", formatted())
);
hi, i'm having issues using mimimessage to create messages, font and hover and click tag do not work at all
Context:
Version:
This server is running Paper version 1.21.8-6-main@782ce95 (2025-07-18T20:26:58Z) (Implementing API version 1.21.8-R0.1-SNAPSHOT)
Code:
Component component = MiniMessage.builder().build().deserialize(builder.toString());
if (player != null) {
getAudiences(plugin).player(player).sendMessage(component);```
Text sended:
<font:minecraft:alt> Font</font>
<hover:show_text:'<gray>This is a tooltip!</gray>'> <gold>Hover over me</gold> </hover>
plugin.yml libraries
libraries:
- net.kyori:adventure-platform-bukkit:4.4.0
- net.kyori:adventure-text-minimessage:4.23.0```
pom.xml
<!-- MiniMessage -->
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-minimessage</artifactId>
<version>4.23.0</version>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bukkit</artifactId>
<version>4.4.0</version>
</dependency>```
Am I missing something? Any tips would be really appreciated ๐
Paper does not require adventure-platform. Just use player.sendMessage and you won't have this issue.
Alternatively, if you insist on using the community-maintained -platform, you can find code that seems to work in a PR on the repo. The current release does not support recent changes (1.21....6? 5? I forget... and up)
Yea, I'm supporting spigot too.. maybe I can walkaround and use the Gson serializer and directly send the message as a packet
Or using the Bungee serializer to turn into bungee components
I'll try to find a solution, thanks
Probably easiest to just use the PR'd code, honestly.
But, it's also a great time to start migrating from a server that has a hand-countable percentage of servers. ๐
Yes that looks correct! A pre process parsed tag inserts the contents of the placeholder into the literal string before it goes into fun component land, which means the click event works (bc click event eats normal strings, not components)
if that makes sense
is it possible to add a translation to my holograms plugin so that i can register a minimessage key via plugin, e.g. <t:TEXT>, and then the player will see the translation of TEXT depending on their language? So without packets
are you looking for https://docs.advntr.dev/minimessage/format.html#translatable ?
kinda, but i need to use my own translation system for this, not the default minimessage translator with a file or smth
Translatable components are what you want, specifically coupled with this: https://docs.advntr.dev/localization.html#using-adventure-s-localization
I use CarbonChat which has a feature where you can link items in chat as a hover event. Is there a way I can find these hover events in a message, and edit them to also show the quantity of the item that was linked? Or is that data lost at this point
That feels possible, might be worth talking to Josh directly though and seeing if you can just modify carbon to do that when it's inserting the hover events in the first place
I raised a suggestion for it a while ago but it hasn't been looked at, so I'm thinking about just adding it in my plugin in the meantime
the suggestion was for an ItemLinkEvent which would have info on the item, to be more specific: https://github.com/Hexaoxide/Carbon/issues/658
you may just fork carbon at that point
probably harder than what I want to do here, assuming it's possible
declaration: package: net.kyori.adventure.text.event, class: HoverEvent, class: ShowItem
this is indeed the path i have taken, and it seems to be working very nicely!
currently, i'm just serializing the text with the plain text serializer, and my signs are looking very pretty
except they don't have any colour...
so now i want to properly serialize the net.kyori.adventure.text.Component into an HTML string, instead of using the plain text serializer
does anyone have any hints on how to beging doing that?
for starters, i can't seem to find a getter to access the actual text of Components
Not all components are text components
oh
You would generally want to take a look at the component serialisers and how they work
Well, yea, it's a lot of fun
i thought i'd try being inspired by the ansi encoder
You'd mostly want to be walking over the component and their children
You would basically need to branch depending on the type of component
in the plaintext serializer i see a StringBuilder
Well, yea, as that's mostly just using a flattener
but i can't actually see where it's calling that append
that's the flatteners doing
is that where the sb::append function gets actually called?
I would imagine that flattener.handle calls the component method there
but intellij can't find any implementers of this interface
so i can't track it down any further
I mean, an implementation of that is the sb::append call
whaoh
okay hold on i need to process that
functions, like sb::append, can implement an interface?
Yes
it's a functional interface, i.e. an interface with only one method, which can be implemented using a lambda
๐ตโ๐ซ
has the "basic" flattener
ooh that's where i have to look
I mean, I'm not ultra familiar with this stuff, just cursory glancing
if I was going to start on something that poops out html I would basically start with a span tag, and every time it calls pop/push style, I'd basically de/nest a span tag or something with that info
yeah that's also what i was planning
would probably be horrible but I would hope that would give me enough familiarity of how it works to be dangerous
but didn't know where to start at all
thank you for the information!
i really appreciate it ๐
i guess you can look at how the minimessage web viewer does it
for tonight, i'm going to just use this:
public class HTMLComponentSerializer {
//TODO: Do not use this Plain Text Serializer.
//This needs to properly support nesting.
private final static PlainTextComponentSerializer PLAIN_TEXT_COMPONENT_SERIALIZER = PlainTextComponentSerializer.plainText();
private static final HTMLComponentSerializer INSTANCE = new HTMLComponentSerializer();
public static HTMLComponentSerializer html() {
return INSTANCE;
}
public String serialize(Component component) {
//Get Text
final String text = PLAIN_TEXT_COMPONENT_SERIALIZER.serialize(component);
//Get Colour
TextColor componentColour = component.color();
final String colour;
if (componentColour != null) {
colour = componentColour.asHexString();
} else {
colour = null;
}
//Generate HTML
if (colour != null) {
//The colour for this specific line has been overridden
return "<span style='color:" + colour + ";'>" + text + "</span>";
} else {
//There are no overrides, so glowing here is not necessary. It is handled by the parent sign
return "<span>" + text + "</span>";
}
}
}
i will improve this to actually handle nesting later...
it's already starting to look really good, though!
using adventure was a very good decision
this library is awesome!
i was able to remove a lot of custom parsing code \o/
in exchange for custom encoding code
but i had to do that anyway
even for my previous version which didn't use adventure
i have now expanded it to this: https://github.com/TechnicJelle/BlueMapSignExtractor/blob/4645b538257a81a5ac6d28746868155ea3f69a60/src/main/java/com/technicjelle/BlueMapSignExtractor/HTMLComponentSerializer.java
what do y'all think?
as far as i've seen in my tests, sign text is generally just normal TextComponents, so the instanceof TextComponent that i'm doing isn't the most evil think, i think...
although it may also have Translated Components
i think i have a region file somewhere that has those, so i'll throw that into my testing suite now and see how it deals with it
you probably want to sanitize that output
the serializer in squaremap api uses some google library
Is there adventure to html converter?
Probably not what you want, but the minimessage format is xml
If you're asking about actually replicating minecraft ui formatting on a web browser, uh, hope you can code
I have text with color: and etc
Which I use in website and server
In website I currently stripr all the <>
Maybe it's possible to convert those tags to html elements with colors
Scroll like two messages up lol
and also yes, adventure-webui serializes to HTML via a public API you can use or you can see how it does the serializing yourself
Yea, i'm looking more for a php converter, for websites
PHP just spits out HTML
Basically, we don't wanna reimplement the MiniMessage parser in other languages in fear of stuff not being aligned, so you should just use the API to get the html
I'm really confused regarding NBT in Adventure.
I got the exception that I need to use a Compound Tag for the "additions" in a dialog, but I can't just use CompoundBinaryTag.builder()...build() because it wants me to provide a BinaryTagHolder.
Looking at the Javadocs, it tells me to check net.kyori.adventure.nbt.impl for a platform agnostic implementation, but this isn't linking to anything and also doesn't make it very clear where exactly I should check (I assume one of the GitHub Repositories, but the main adventure one doesn't seem to have such a path anywhere? Is it referring to the archived NBT repo?)
tl;dr: How would I convert a CompoundBinaryTag into a BinaryTagHolder?
it's referring to the adventure-nbt module
That isn't helping me much here
Well....
it's an nbt library
Does it have the source anywhere to check?
source for what?
The stuff it mentions in the docs but doesn't bother to link properly
Feel free to submit a PR to correct the docs
And this btw doesn't have the impl package either
I've linked you to the javadocs for adventure-nbt and you've also been linked the source too
do you have a specific question?
I think that jd comment is just wrong, and the impl subpackage does not exist. However, ...Impl classes are present in the nbt package
Exactly that
The docs imply there is a impl package in the NBT library when there isn't
Yes and you're free to submit a PR that fixes that if you would like, otherwise you're just complaining when we're waiting here to help you with any actual problems you have :p
Since this commit, the impl subpackage was merged into its parent
So.
I apparently need to provide a Compound tag according to the exception I've received.
Tho, in the method where I need to do that does it require me to provide a BinaryTagHolder, which seems to be some form of common interface here?
My current question is, what the best aproach would be to make a Tag that satisfies the BinaryTagHolder requirement while also being a compound tag.
Would I need to make my own implementation (Like the CompoundTagImpl example), or would there be a simpler aproach available in Adventure.
I use adventure through paper, if that is of any significant importance.
BinaryTagHolder is something that just holds a tag, it's not a tag
it looks like there is a method on BinaryTagHolder that lets you create an arbitary holder
You can create an instance using BinaryTagHolder#binaryTagHolder(String) where the parameter is the snbt
And I assume I would call some asString method or similar in the compound tag to convert it into a valid snbt string?
See BinaryTagIO
This is so confusing....
I don't get how BinaryTagIO is helping me here....
Like if I look at Readers I only see methods for getting CompoundBinaryTags, which is something I can get using the Builder already...
And when I check the Writer I can see void methods that need Paths or OutputStreams or similar, which I doubt is what I need here?
I suppose there could be some kind of DirectBinaryTagHolder that would hold BinaryTag instance in adventure-nbt library to make it simplier ๐คท
You can write a created binary tag to whatever output stream way you want to get a string
plenty of different methods to turn output streams to strings and w/e
Seems kinda overcomplicated to me...
Not really, it's kinda Java IO 101
But like this is just a suggestion of what library to use, obvs you can use whatever nbt library you want as long as it can output snbt you can throw into BinaryTagHolder
or make your own one, or use nms, or whatever really
All I seriously want is, to have one single integer added to a BinaryTagHolder, so that I can later extract it for further use
Nothing more
why?
can't you just use click callbacks and just hold the reference to whatever int you want during the dialog?
I'm using Paper's custom click event
I mean, from a 2 second glance, you'd create the compound tag, then use TagStringIO and toss the output into a BinaryTagHolder?
why?
BinaryTagHolder.binaryTagHolder(TagStringIO.tagStringIO().asString(yourCompoundBinaryTag))? doesn't seem that much overcomplicated, though DirectBinaryTagHolder would be nice
just use ClickEvent.callback
Seems like there is only a get() and builder() method, but I get what you mean
where
I think the event is a bit more clean than having the entire handling be done in a callback. Even if I throw everything in a separate method.
TagStringIO
so clean you have to include an entire nbt library haha
you have outdated adventure-nbt
Blame Paper on that
don't reinvent the wheel, ClickEvent.callback is a user-friendly alterantive to doing it yourself
what
Paper doesn't ship adventure-nbt
Paper doesnt include adventure-nbt
K...
and it doesnt have to match adventure api version
Then screw this honestly... I won't shade in/download nbt on runtime just for this...
Wanted to use the Event but guess this stuff is just too annoying to setup properly.
Good idea, you're saving yourself a world of hassle by using the nice clean click callback system we made haha
click callbacks are a wrapper around the custom click event - so it does the nbt, serialization/deserialization, filtering, event handling all for you
if you wanna do that all yourself then go ahead we're not stopping you
even has more logic for custom expiry and uses as well
Just a side question on this topic, I am just wondering, when showing a dialog to a user, with multiple click actions (with callbacks), he only click one of them, and we show him an updated version of the dialog. Aren't we "accumulating" callbacks into memory, that will never be used?
I.e., is setting a really short-lived expiration a good practice to prevent this?
(a few minutes)
(and of course single use, but that only work for the one that is clicked)
hm - i mean i cant see it actually being a problem
but yeah maybe - or we could have a "group" system so that other callbacks with the same group expire when one does or smth
I did not dig into the implementation, but I guess each time we send a callback, Paper needs to remember it somewhere, in a Map or something, no?
So, in a scenario of a user-controlled trigger (like, a dialog showing/updating based only on user input), wouldn't it be possible for a malicious user to "fill" the memory with unused callbacks?
you'd probably want a sensible expiry anyway
(of course not limited to dialogs, it would also apply to chat-based callbacks)
Yes, but the default one being 12 hours, I something stumble across code where I forgot to lower it, and I always had this question of whether it would be a possible attack vector or not
I guess it is probably not the most obvious way an attacker could think of, I admit it
yeah idk, hard to say really
i do remember being not very impressed with paper's implementation of the click callback stuff, but then my ideal solution is just throw it in a nice easy caffiene cache haha
is it safe/recommended to store an object with Key fields in json files? or is it better to have them as strings and create keys from them when needed in runtime? it seems to work fine, but that doesn't always mean it's the best approach
the keys I'm saving are DamageTypes and EntityTypes
I'm using the following Gson serialiser in case that's relevant, because my object also contains Component fields
I don't see any particular reason why not to
as in, why not to do it the way I'm already doing it?
can legacy symbols be converted to minimessage format?
like the string
&cHello world
becomes
<red>Hello world
or will I have to do that manually?
MM doesn't "convert" anything
you would need to deserialise it with the legacy serialiser and then throw it into minimessage
Your earlier question was:
Is it possible to deserialize both legacy and minimessage format in the same string?
This is not going to work out happily. Like, there's no solution that results in predictability or joy.
If you have legacy stuff from an earlier version of the plugin, first do a one-time migration from legacy to minimessage. Then you can start using minimessage going forward. Don't mix and match.
kk
is there a website or something I can use to copy n paste my messages to convert the legacy to minimessage? or do i have to manually find and replace?
(for that one-time migration)
You should read both messages cat wrote instead of just the first one. The legacy serializer can deserialize to component, and then you can serialize to minimessage to save it.
nvm its just like 4 things i have to change. thanks lol
Slightly confused now. For some reason my messaging system doesn't deserialize the minimessage string.
commandSender.sendMessage(MiniMessage.miniMessage().deserialize(message));
instead I just get the raw string.
(e.g. <red>Hellow world)
Did you run the MM string through the legacy serialiser or something?
nope
probably want to print out the raw string before you deserialise it, hard to say with the info provided
Also note that, if just doing default minimessage deserialization, you can do commandSender.sendRichMessage(message) which is waaaaay shorter.
nvm im an idiot. i forgot to rebuild the plugin-
oh thanks
And even sendRichMessage(message, TagResolver) if adding any, actually! Forgot about that one. :3
what do tags do?
So basically, unless you're doing a non-default MM instance (which is rare) you can save a lot of time.
oh you mean the <xyz> tags
Yes
ah ok that makes sense
commandSender.sendRichMessage("Hello <name>!", Placeholder.unparsed("name", "SpyCoderX")); would send you "Hello SpyCoderX!"
oh cool
Check the MM docs/javadocs for info on that.
hi, i tried using MiniMessageImpl#deserialize in every tick for updating scoreboard for each player and it just generate too much memory usage. i need to be able to format text and minimessage does the job
is there any reason it should use so much RAM? any alternavite or suggestion please?
is there a way to translate DamageType? I can't seem to call Component#translatable on them
damage types don't have associated translation keys
what exactly are you trying to do?
Display top 5 causes of death in a hologram. I have a damage type key stored for every death
I guess I can just map my own translations
paste the full spark log
hello guys. I'm right now trying to achieve text with translations. I've got a .yaml file where I get my translations on MiniMOTD format.
game:
round:
started: "<white><gold><b>The game has started!</b></gold></white>"
over:
no_winners: "<white><red><b>Game over!</b></red> No winners this time.</white>"
single_winner: "<white><green><b>Game over!</b></green> <aqua><b>{player}</b></aqua> is the winner!</white>"
multiple_winners: "<white><green><b>Game over!</b></green> Multiple winners survived!</white>"
Doing
player.sendMessage(
Component.translatable("game.scoreboard.title"))
);
works neatly and as intended. but I'm trying to add tags. for example in game.over.single_winner, how could I dinamically change {player} to whatever I want via code?
I've seen I could tweak the deserializer to achieve my result, but I'm unsure how I could go on about it
any help would be greatly appreciated!
by "MiniMOTD format", do you mean minimessage?
minimessage has its own system for dynamic replacements:
https://docs.advntr.dev/minimessage/dynamic-replacements.html
yup! sorry, matter of habit
Interesting, would there be any way to do it from the Component?
are you registering your translations using the minimessage translator stuff?
sorry lol
I'm using a custom translator
yes, but is it using the minimessage translator stuff?
https://docs.advntr.dev/minimessage/translator.html#creating-a-minimessage-translator
like, are you extending MiniMessageTranslator?
oh s- I see now what you mean
or using a MiniMessageTranslationStore?
if either of those 2, what you sent is how you'd specify custom tag resolvers, yes
yeah that's the problem I was only implementing the interface
yeah dude you're 100% right, I feel so stupid right now lol, thanks!
there's some explanation + an example on this javadoc page
https://jd.advntr.dev/text-minimessage/4.23.0/net/kyori/adventure/text/minimessage/translation/MiniMessageTranslator.html
declaration: package: net.kyori.adventure.text.minimessage.translation, class: MiniMessageTranslator
okay that's just what I needed
I can't believe I was stuck on hours for this lmao
thanks man
Does <newline> supposed to work in item lore?
Something seems off
Oh, discord search tells me it isn't supported in lore. Suggestion: make the web editor not imply that it does work.
Yeah it's tricky, there's no nice way of actually making the webui imply it doesn't work unfortunately
I guess a small red text on the top could do fine when the input string contains the tag
Or in the docs, just put it somewhere, I think it is an important note
Feel free to submit a PR!
Or you could create a function which splits a component at every newline, returning a list of components?
Easier said than done, but feel free to submit a PR for that too!
it's much easier to just have a list in your config/whatever
Wdym? Wouldnโt you just serialize each component, split them at any newline
Then just get the color at the end of the previous line to copy to the following one, and reserialize it into a list of components?
serialize to what, json?
no, the process is more complicated than that due to the tree nature of components
yeah you have to maintain the full tree, no real benefit to serializing when all the info exists in the deserialized tree anyways
Well, if you are doing it as a component tree, you just need to split components which have a newline in them into two components with the same position in the tree and same properties (color, style, etc.)
yes, which again is easier said than done
no-one has PRd a fully working solution to adventure and many have tried, otherwise it'd be in the api
Hmm
text("green text", GREEN)
.append(text(" red text in the first line\nred text in the second line", RED))
.append(text(" also green in the second line"))
is enough to give headaches, and it's a single level deep
You can't just cleanly split, you need to iterate over the tree and create new trees with the splits that you need
let alone when a single component in itself is a single newline that could have its own style for whatever reason
it's not an impossible problem, mojang has solved this issue on the client text decomposition :p but it is not a trivial enough problem for the contributors' free time
I see
From what I can tell, youโd only need to iterate over the tree and replace single components with newlines in them into multiple components with the same properties, but only the last one keeps the โextraโ component list.
and all of this is why i always say "just put a list in your config" haha
lol. I love making a more advanced solution to a simple problem XD
not necessarily only the last one would have the children
if you have multiple styles spanning multiple lines and depths
i dont even think it's a nicer solution, i would hate being an end user and having to write everything on one long line bc you made a fancy splitting solution
No because the whole point of newline splitting would be so you can do this:
Component.split(โโโ
This
can
split
โโโ);
and that would allow for writing things like lore in one component .
sure but if you are taking it from a configuration file, unless you allow for both options you are also forcing the user to not have them tidy if they desire ยฏ_(ใ)_/ยฏ
๐คท I see problem, I solve problem. The user can do what they want lol
they can't do what they want if you don't give them the freedon
i mean config file is easy, it's just like:
my_item:
lore: |
<red>first line
<bold>second line
Butโฆ wouldnโt it be a function the user calls in their code?
by user i mean end user of the application using adventure, where the application takes the "lines" from a configuration file the end user configures
Ah
which is why kezz keeps saying "take a list in your configuration file"
I could just see this being slightly surprising for a user who might expect the second line to be red as well, because there's no </red> on the 1st one
which is the simple enough solution
it should be
Huh
read lore as a single component, then split it
Wait, what was the point of your example?
the split should preserve style across lines
Oh ok
Yes yes yes
I thought you were illustrating the way we could ask the user multiple lines of lore, then parse each one individually
But for your example to work, we would need the holy graal Component#split
Imma think on this
and the alternative that doesn't require a WHOLE bunch of code lol
my_item:
lore:
- <red>first line
- <red><bold>second line
When you encounter a newline, wouldnโt you just copy the current list of colors and styles in order, exit out of the current json component, and create a new stack of components with the same styles and order, but with their text set to โโ?
And then youd just have to integrate the remaining unsplit/unprocessed components into the newly created one.
"just" is doing a lot of work there
this is why i keep saying it's easier said than done, lol
the theoretical process is easy to think about at a high level
but actually putting in the time and writing all the gross state-tracking code is the challenge
Couldnโt you copy the current nodeโs parent tree but skip anything before it and then set all of its parents text to โโ?
components don't keep track of their parent
do you know what "easier said than done" actually means btw?
if, instead of spending all this time talking, you went and tried to implement something, you'd understand the issues way better
I would but Iโm at the pool rn
Go enjoy the pool then
XD
I only wanted newlines to work in lore because I need to create some idiot/crowdin format proof config. So every lore would be just one line and splitting on new lines. But yeah this seems kinda complicated to do. Instead I decided to use wrapping which also seems kinda complicated to do, but found a gist which looks like is working perfectly fine or at least I couldn't break it yet
https://gist.github.com/Minikloon/e6a7679d171b90dc4e0731db46d77c84
Will do once I get to it, hopefully for both places
hello everyone! I'm using currently Translation components and I'm trying to use them for Item's names. Here's a minimal working example of my code so far
ItemStack sword = new ItemStack(Material.DIAMOND_SWORD);
ItemMeta meta = sword.getItemMeta();
meta.itemName(
Component.translatable("event.give_special_item_sword")
);
sword.setItemMeta(meta);```
However, in game, they only show the raw string `event.give_special_item_sword`. what do I have to do in this case?
I'm using a custom translator btw, and it seems to be working well so far
Item components canโt be translated as that would require modifying the item and would break a bunch of stuff
hm, I suspected something along the lines of that, thank you!
How can I create a system where I have a color gradient over a message but also if [item] is in the message, that's replaced by a placeholder without allowing any other tags to work in the message
- use <item>
- create a mm instance with the tags you don't want a player to use
- run stripTags with that instance on the input string
- create a new mm instance with the item tag
- prepend your input string with the gradient tag you want
- using the instance in step 4, use that to make your resulting component with the new input string made in step 5
is it not advised to use the keys defined in papers extended Sound interface with adventure's sound api?
the docs use string literals for sound and i was thinking it would be nicer to use the ones provided by this interface as a sort of enum? is there any supported way of doing that or is that discouraged for some reason
the adventure docs do not assume the existence of paper, but ya it implements Sound.Type for a reason
is there a default mm instance that has no tags at all that I have to add to?
you can build your own instance, MiniMessage.builder().tags(TagResolver.resolver(... base tags)).build()
So here's the thing, this works but not really. my tag in the middle is computed as part of the gradient when it shouldn't be so I lose half of the gradient to the tag.
[01:42:42 INFO]: <gradient:#00ffa6:#fc4efc>adsjkfhjkahdsfjkh <2b055d2b-aef0-4ab0-8de4-c73b95328070> nasdfnfjasdnjk
[01:42:56 INFO]: <gradient:#00ffa6:#fc4efc>fajhfjdbjasbnfjhkbakjsldfn
How about a healthy </gradient
same thing
[01:58:09 INFO]: <gradient:#00ffa6:#fc4efc>dasfjfdkjnafdsjk <6da0109f-d659-4cba-adc7-640ba4e2ed53> fasdsafdasdfas</gradient>
You were saying your tag shouldn't be computed, so put the </ before the tag.
I don't understand what you mean here
You did <gradient>words<tag></gradient> and I'm suggesting <gradient>words</gradient><tag> if you don't want <tag> counted.
I understand, of course I could do that but the important part here is that the tag is a placeholder that the user puts in the middle of their text
I just don't want the tag to take from the gradient
You have users manually entering entire UUIDs into chat? Sorry, I didn't see that coming ๐
I'll let someone more skilled in minimessage help further
That's not what I'm saying
a user says [item] in chat (or whatever, it's a regexp pattern), I replace that with <$randomUuid> so that it's picked up by my custom tag handler
in chat the person wrote ...text...[item]...text...
Okay, and then you're slapping a <gradient> on the front of it?
Intense! Thanks for the clarification. Outside of the below thought, I'm out of ideas. Someone else may have a better idea.
I would remove the tag, process to minimessage, walk the tree until I find the place the tag belongs and insert its component. I don't have an answer for how because I've never done that but that seems like a logical strategy for it. May not be the best one though.
Heck, maybe not fully remove but put in some character players can't send, and use that to find it?
the solution is just to fix the bug in Minimessage's gradient parser code to ignore tags
If you PR that, awesome!
If the issue is associated with minimessages, do I need to reproduce it on paper?
The issue is:
A few months back I said that minimessages performance was horrible. At that time I used legacy colors, new colors and a lot of gradients. I was notified that gradients with legacy colors can be the issue.
We now removed all of legacy colors from the server, and on that server reduced the gradients to a minimum. Texts that update each second don't have gradients.
There is a bit over 4000 text displays, by my calculations up to 1500 updates each second.
1 player in a survival server with almost everything vanilla, normal mob spawning, playing as usual, is using up to 1ms of tick
1 player just standing in a boxpvp server with all those text displays, with no other active entities, no random tick time, is using up to 5ms of tick
Will send a spark report a bit later
I don't understand why, but the spark report is messed up
No it isn't, this works fine if you're doing tags correctly - please send some example code and I'll tell you how to fix it
I mean, I can't see any performance issues there beyond "why are you updating 4000 text displays when only one user is online"
I mean, doing stuff takes time
Will need to double check the tops, maybe update each minute
But mine timers needs to be each second
Not really aware of there being any real performance issues when MM is used in a sensible manner, any parser will bog down, especially when dealing with anything more complex than basic string manip
We're also only looking at 38 ticks there over 6 minutes
You're likely just picking up ticks where gc hit in
I'm afraid that with increased player count the issue will be way worse
More text displays
1500 pieces of information updating every second for one player online is still a bit insane
I'd suggest not doing that
but again, this ^
Limiting it via distance in such a small place isn't logical, especially when with more players the distance will be irrelevant as players will be more spread out.
But yea, need to check with more players. Maybe processing all that text will always take 5ms, and player count won't have that much of an impact
Well yea, more players isn't going to make a static amount of work take longer
But again, 38 ticks
I misread part of the report, just under 2/3s of the the report is literally converting it to be stored on the entity
i.e. memory churn and potentially a "you're expecting magic from overly complex components" territory
You can see your mspt avg is 1.4ms so it's not taking 5ms for the majority of the time
That too, yea, you'd basically need to benchmark it using something other than a sampler if you wanted to see how much time it was actually taking to do stuff
how can i make a custom tag resolver that replaces the text inside of it with different text?
Isnt that just Placeholder.unparsed or Placeholder.component?
You're most likely going to need to implement Modifying, but can you tell more about your use case please?
im trying to make a custom tag that takes the contents and turns them into the small caps font
as far as i know that font is not built in
I did a prototype for this few times ago, and yes you have to create a tag implementing Modifying, and paye extra care about the fact that not all components are text (thus, you cannot modify everything)
thank you!
I suggest you first try to do it "simple" like by just using String#toUpperCase() for example, so you can test your text modification logic, and then you can improve it by adding the small caps conversion logic
Because Modifying are powerful, but also quite surprising ๐
(Just to save you some time, but you'll see it yourself, you need to clear the children of the component if you don't modify it, for example, because they'll get re-added by the implementation)
i got you covered
oh im a bit lae
Brotha you ain't late
I think this example code maybe doesn't match with example image. is my though right?
by the way for reference, this is how i did it on my own https://pastes.dev/jxyvcsuZCR
yours is def better, i dont think mine preserves the style
many thanks!
Hey, is there a reason why source removing from the global translator returns false?
final GlobalTranslator globalTranslator = GlobalTranslator.translator();
if (translationStore != null) {
plugin.getSLF4JLogger().warn("Removing existing translation store");
final boolean removed = globalTranslator.removeSource(translationStore);
plugin.getSLF4JLogger().warn("Removed: {}", removed);
}
Console output:
[12:45:13 WARN]: [MyPlugin] Removing existing translation store
[12:45:13 WARN]: [MyPlugin] Removed: false
It is definitely registered, but it's populated with translations after being registered in the GlobalTranslator.
Full method:
// ...
private MiniMessageTranslationStore translationStore;
// ...
private void initializeTranslationStore() {
final GlobalTranslator globalTranslator = GlobalTranslator.translator();
if (translationStore != null) {
plugin.getSLF4JLogger().warn("Removing existing translation store");
final boolean removed = globalTranslator.removeSource(translationStore);
plugin.getSLF4JLogger().warn("Removed: {}", removed);
}
translationStore = MiniMessageTranslationStore.create(TRANSLATIONS_STORE_KEY);
translationStore.defaultLocale(Locale.ENGLISH);
plugin.getSLF4JLogger().warn("Adding new translation store");
final boolean added = globalTranslator.addSource(translationStore);
plugin.getSLF4JLogger().warn("Added: {}", added);
}
// ...
Well, it seems that if the TranslationStore was mutated after registration, it can no longer be unregistered using the same reference. Even though it has a key that uniquely identifies it.
Hey what is the use of ClickEvent.custom() and how can I use it?
Recently (1.21.5 i think?), Mojang added a new "custom" click event, where the client just sends a packet with arbitrary NBT data
So this click event is just the implementation of that new feature, allowing you to use it
so not much useful eh?
its main purpose is dialog form feedbacks
also, the callback system in paper is implemented with it now, not with a command click event wrapper
thought it used to call an event or something
Paper has an event that does fire when the custom payload is received, yes
Hey,
is there a way to convert a com.mojang.brigadier.Message to a Component ?
thanks that's what I was looking for
I use paper
why is EntityType.getTranslationKey() deprecated? What should I use instead?
EntityType#translationKey()
how can I remove MiniMessage default tag resolvers? is it possible?
you can build your own instance, MiniMessage.builder().tags(TagResolver.resolver(... base tags)).build()
thanks I'll try this out
Please do not misuse the help channels.
Is there convenience api for generating reference components to entities/players the same way vanilla death messages and chat messages do? for example:
"<insert:hjk321><click:suggest_command:'/tell hjk321 '><hover:show_entity:player:f90efb8f-6362-43f0-ab7c-6be7f8ec242b:'hjk321'>hjk321"
"<insert:27348008-73cd-4ffd-8791-6d7d5d7d1fa5><hover:show_entity:skeleton:27348008-73cd-4ffd-8791-6d7d5d7d1fa5:'<lang:entity.minecraft.skeleton>'><lang:entity.minecraft.skeleton>"
it's easy enough to construct myself but is rather annoying to do so
what