kyoripowered / adventure Goto Github PK
View Code? Open in Web Editor NEWA user-interface library, formerly known as text, for Minecraft: Java Edition
Home Page: https://docs.advntr.dev/
License: MIT License
A user-interface library, formerly known as text, for Minecraft: Java Edition
Home Page: https://docs.advntr.dev/
License: MIT License
String str = "&cLine1\n&cLine2";
TextComponent comp = LegacyComponentSerializer.INSTANCE.deserialize(str, '&');
// comp looks fine - empty component, two children, "Line1\n" and "Line2", both red
// now serialize again:
str = LegacyComponentSerializer.INSTANCE.serialize(comp);
// Not fine: "§cLine1\nLine2" - second red coloring dropped due to linked line thinking that text is still red. however, the client resets color when a newline is encountered, so "Line2" is white
When trying to color a full message wrapped in a TextComponent, if that message happens to be too long and happens to go to the second line in the chat, the color is lost. This does not happen with the legacy serializer, which is the current workaround.
For example, this code will break it:
TextComponent.builder("This message is an example of a bug with KyoriPowered/Text. It is too long, so it goes to a second line, and unfortunately it loses its color :/").color(TextColor.RED).build()
Related: PaperMC/Velocity#91
for example:
https://hasteb.in/pategewe.lua
"<dark_gray>»<gray> To download it from the internet, <click:open_url:<pack_url>><hover:show_text:\"<green>/!\\ install it from Options/ResourcePacks in your game\"><green><bold>CLICK HERE</bold></hover></click>"
BaseComponent[] components = Pack.WELCOME_MESSAGE.toMiniMessage("url", url);
So I didn't replace <pack_url> by < url>
public interface BossBar {
@NonNull Component name();
float percent();
@NonNull Color color();
@NonNull Overlay overlay();
@NonNull Set<Flag> flags();
}
I'm currently working on a library which would allow text to be translated into TextComponents, using this library.
But I'm currently stuck at a way to make this as efficient as possible, which is why I ask now for some assistance if possible.
My library would allow to have some text like Hello. Do you know [Google](hover:{text:["Click me!"]},click:{url:"https://google.com"})?
which would look for any appearance of [text](text)
and translate those into TextComponents with hover and/or click events set, before adding the remaining text and returning a TextComponent containing the whole text with the above-mentioned changes (So the text would mostly stay normal while the word "Google" would have hover and click actions)
My biggest struggle is not how to get the text to add actions to (I have a Pattern made for this that should work) but how to combine the normal text with the changed text to return as a TextComponent.
Any help is greatly appreciated and if needed can I provide additional information.
When you install multiple plugins, which use the Text library and multiple of them doesn't shade/relocate the lib itself, can the following warnings on Spigot appear:
[05:37:18] [Server thread/WARN]: [:plugin] Loaded class net.kyori.text.Component from :plugin which is not a depend, softdepend or loadbefore of this plugin.
I suggest adding a note, or code example to the readme, to inform about this step being recommended, if not even required.
As of the latest snapshot, rgb colors are now supported in the color
field as well.
Link for information: https://www.minecraft.net/en-us/article/minecraft-snapshot-20w17a
In the later Minecraft versions, vanilla adds NBT path, which is much similar to sponge's dataquery except that one NBT path can represent multiple targets at once with its filtering and multi-index selection (in list) ability.
Given text partially depends on NBT path (the nbt components) and that part of the NBT path (in the path filters) model is already interfaced out in kyoripowered nbt library, maybe the NBT path can be considered to have a library.
I shouldn't be required to pass content to builder when it can easily default to an empty string. See below
TextComponent.Builder builder = TextComponent.builder().append("This is a test").color(TextColor.RED).build();
I'm using this with negative fonts translate offset
and it's not working because it doesn't use the correct json for it.
In that gif above, the command I used was
/tellraw @a [{"text":"Ahoy"},{"translate":"offset.-40","with":[{"color":"red","text":"mates!"}]}]
The json provided by MiniMessage was
{"text":"","extra":[{"text":"Ahoy "},{"translate":"offset.-40"},{"text":"mates!","color":"red"}]}
As for new MiniMessageFont().handleOffset("Ahoy <offset:-40><red>mates!")
, it's just a simple method that replaces <offset:
with <lang:offset.
TextComponent.Builder builder = TextComponent.builder();
TextComponent test = builder.build();
if (test == TextComponent.empty()) {
System.out.println("TEST IS EMPTY!");
}
The code above generates empty TextComponentImpl objects
TextComponentImpl{content=, children=[], style=Style{color=null, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}}
I would expect if nothing is appended to the builder, it would just return TextComponent.empty() and trigger the print out in test above.
I should be able to append primitives like a string. See below
int claimBlocks = 50;
Component text = TextComponent.builder("").append(claimBlocks, TextColor.YELLOW).build();
Sorry to ask this through an issue, but I wonder if there is a proper site, wiki or similar to get started with this library as the Readme doesn't cover everything you might wanna know.
Like if you could create a hover text from a List and how that would be done when it is possible.
I want to use this library but the lack of explanation for (most commonly) made methods makes it a bit hard, to begin with. Especially when you just begin with those things like I do right now.
And another question I have is if there is a method to use, that would parse the raw JSON based on what server version the plugin is running on considering that there seem to be two separate types of JSON formats.
Right now it's very inconvenient to merge two Style
s, because you have to call multiple methods, and it doesn't even cover the insertion.
private static Style mergeStyle(Style first, Style second) {
first = first
.mergeColor(second)
.mergeDecorations(second)
.mergeEvents(second);
String insertion = second.insertion();
return insertion != null ? first.insertion(insertion) : first;
}
A single merge
method simplifies this and also reduces object creation.
When more than one color code is specified consecutively, the one which appears first is used, rather than the last.
For example, &a&9foo
is parsed to foo
with color green
as opposed to foo
with color blue
.
Test case:
@Test
public void testFromColor() {
final TextComponent component = TextComponent.builder("")
.append(TextComponent.of("foo").color(TextColor.BLUE))
.build();
assertEquals(component, ComponentSerializers.LEGACY.deserialize("&a&9foo", '&'));
}
java.lang.AssertionError:
Expected :TextComponent{content=, children=[TextComponent{content=foo, children=[], color=blue, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}], color=null, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}
Actual :TextComponent{content=, children=[TextComponent{content=foo, children=[], color=green, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}], color=null, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}
I've tried playing around with LegacyComponentSerializer
to work out a fix. I assume this is happening because the string is being parsed in reverse, meaning the first color code in the string is being read after the color code later in the string - hence overriding the last.
The style simply gets overwritten, but it probably should be merged instead.
https://github.com/KyoriPowered/text/blob/934e5ea2055d87abbc7060ec7df8f466b2921f8e/serializer-legacy/src/main/java/net/kyori/text/serializer/legacy/LinkingLegacyComponentSerializer.java#L74-L77
Currently I am using the following code to render out styling and text replacements based on translation keys: https://gist.github.com/octylFractal/cdd92710b05b50613d96d2fee35427f2
However, my main issue is that I have to manually do deep replacement, and this leaves me open to bugs like forgetting that a translatable component can have args
and children
. It would be nice if adventure allowed me to write a ComponentRenderer
that made the call I make at the top of render
in the above code: component = replaceSubcomponents(component, context);
In this way, it would automatically deeply render all relevant parts, and as replaceSubcomponents
would become part of adventure code, it would be well tested + supported by the library, as well as more likely to include any future sub-component cases.
Hey,
I using this api on my project but i have a translation system. I want implement this system in this api on my project. It's possible to allow heritage on TextComponent and Builder TextComponent?
Best regards,
MissIlys
If a user provides <green>hello</red>
, what would the expected response be? right now the MiniMessage parser appears to ignore the trailing </red>
. Would it make sense to throw a parse error?
Hi, I'm trying to send a message , and i'm using both 'text' repository, and 'text-adapter-bukkit' repository in order to send components to a player.
However when this happens i get a NoSuchMethodError:
java.lang.NoSuchMethodError: 'java.lang.String net.kyori.text.util.NameMap.name(java.lang.Object)'
More info:
Gradle build file:
PasteBin - gradle.build
Creating TextComponent Java code:
protected static TextComponent buildKashikeComponent(List<String> strings, List<String> hoverString) {
if (strings.isEmpty())
return TextComponent.empty();
TextComponent.Builder builder = TextComponent.builder();
TextComponent message = LegacyComponentSerializer.INSTANCE.deserialize(String.join("\n", strings), '&');
if (!hoverString.isEmpty())
message.hoverEvent(HoverEvent.showText(LegacyComponentSerializer.INSTANCE.deserialize(String.join("\n", hoverString), '&')));
builder.append(message);
return builder.build();
}
Sending the components to a Player inside my plugin:
public static void sendIfNotEmptyComponent(TextComponent component, Player player) {
if (!component.isEmpty())
TextAdapter.sendComponent(player, component);
}
If you can help understand why this is happening I'd be very happy )=
When serializing a message from legacy that includes a link and sending it to a player. The link is not clickable.
The same link sent in base MC chat is clickable, but legacy seems to break this function
currently it only allows " which plz stop
The ability to word-wrap a component to a specific width - would most likely require #59.
public interface WordWrapper {
@NonNull List<Component> wordWrap(final @NonNull Component component, final int width);
}
Currently RGB colours only appear to be accepted as parameters to the <color>
tag, not as standalone tags like named colours are.
The ability to find the pixel-width of a single character, or the content of an entire component (and children).
public interface PixelWidthSource {
int width(final @NonNull Component component);
int width(final char character);
}
I just got version 3.0.4 of text to try and use the TextComponent.join() function.
This method either has a bug or is functioning wrong in my eyes as when you only have 1 TextComponent it tries to join it with nothing as can be seen in the image.
The code used for executing the command can be found here: https://gist.github.com/StealWonders/96027959ddc0120c7cfcd3c806a30ccd
The output of line 15 is " 1 ".
If you need any further information, feedback or testing from me feel free to ask.
Can you add a tag to set the font of a part of the text?
The call to parent.append(...)
does not actually modify parent
, as components are immutable! It returns the result.
input: Your link code is &l4000&r. PM the bot on Discord (&l3XP3R1M3N2L B0T&r) containing just this &lcode&r as the &bmessage&r to link your accounts.
with character &
here are the outputs with different versions of the library (api & legacy serializer):
adventure 4.0.0-SNAPSHOT (wrong works properly)
TextComponentImpl{content="Your link code is ", children=[
TextComponentImpl{content="4000", children=[], style=Style{color=null, obfuscated=null, bold=true, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null, font=null}},
TextComponentImpl{content=". PM the bot on Discord (", children=[
TextComponentImpl{content="3XP3R1M3N2L B0T", children=[], style=Style{color=null, obfuscated=null, bold=true, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null, font=null}}
], style=Style{color=null, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null, font=null}},
TextComponentImpl{content=") containing just this ", children=[
TextComponentImpl{content="code", children=[], style=Style{color=null, obfuscated=null, bold=true, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null, font=null}}
], style=Style{color=null, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null, font=null}},
TextComponentImpl{content=" as the ", children=[], style=Style{color=null, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null, font=null}},
TextComponentImpl{content="message", children=[], style=Style{color=aqua, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null, font=null}},
TextComponentImpl{content=" to link your accounts.", children=[], style=Style{color=null, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null, font=null}}
], style=Style{color=null, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null, font=null}}
text 3.0.1-3.0.4 (also wrong)
TextComponentImpl{content=Your link code is , children=[
TextComponentImpl{content=4000, children=[], style=Style{color=null, obfuscated=null, bold=true, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}},
TextComponentImpl{content=. PM the bot on Discord (, children=[], style=Style{color=null, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}},
TextComponentImpl{content=) containing just this , children=[], style=Style{color=null, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}},
TextComponentImpl{content= as the , children=[], style=Style{color=null, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}},
TextComponentImpl{content=message, children=[], style=Style{color=aqua, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}},
TextComponentImpl{content= to link your accounts., children=[], style=Style{color=null, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}},
TextComponentImpl{content=3XP3R1M3N2L B0T, children=[], style=Style{color=null, obfuscated=null, bold=true, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}},
TextComponentImpl{content=code, children=[], style=Style{color=null, obfuscated=null, bold=true, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}}
], style=Style{color=null, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}}
text 3.0.0 (correct)
TextComponentImpl{content=Your link code is , children=[
TextComponentImpl{content=4000, children=[], style=Style{color=null, obfuscated=null, bold=true, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}},
TextComponentImpl{content=. PM the bot on Discord (, children=[
TextComponentImpl{content=3XP3R1M3N2L B0T, children=[], style=Style{color=null, obfuscated=null, bold=true, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}}
], style=Style{color=null, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}},
TextComponentImpl{content=) containing just this , children=[
TextComponentImpl{content=code, children=[], style=Style{color=null, obfuscated=null, bold=true, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}}
], style=Style{color=null, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}},
TextComponentImpl{content= as the , children=[], style=Style{color=null, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}},
TextComponentImpl{content=message, children=[], style=Style{color=aqua, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}},
TextComponentImpl{content= to link your accounts., children=[], style=Style{color=null, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}}
], style=Style{color=null, obfuscated=null, bold=null, strikethrough=null, underlined=null, italic=null, clickEvent=null, hoverEvent=null, insertion=null}}
Currently the only way to replace text in TextComponents is via replace(...)
, however that method replaces all occurrences of the supplied pattern in the TextComponent.
I would like for a way to replace only the first occurrence.
Current use case is for parsing placeholders in user input, however the user can supply the placeholder multiple times, and replace
will replace all of them.
A method to replaceFirst
or replace(int occurrences, Pattern pattern, UnaryOperator<TextComponent.Builder> builder)
would resolve this issue without having to manipulate the input and remove all duplicate placeholders.
I might have missed where it's possible but I was wondering if the
`AbstractLegacyComponentSerializer.formatByLegacyChar(Char char) method could be made public ?
Why? I would like to be able to store a List against a series of regex's to allow dynamic colourization by keyword. Historically we did this with ChatColor
so we would start with a config file
/badmin/b > c
we take the regex create a pattern /badmin/b
and then take c
and get the ChatColor that it corresponds to. we store them in a map and use it to dynamically format chat.
We can use the c to create a TextComponent that contains the textFormat but not ideal as when we later need to apply it to other text its cumbersome.
One of my libraries, SupaCommons, uses text
, but due to the versioning my library breaks with text
API changes since they are pushed to the same version, which is currently 1.12-SNAPSHOT
.
I'm looking for a way to take a config value like %displayname%: %message%
and replace %displayname% and %message% with components (and somehow probably also parse & color codes at the same time (ex. %displayname%&r: %message%
))
Example: (simplified for demonstration purposes, in the real world the replaced components could have click & hover events and wouldn't just be a simple text component with just content)
Component comp = TextComponent.of("%displayname%: %message%")
.replace("%displayname", TextComponent.of("Steve"))
.replace("%message%", TextComponent.of("Hello World!"));
I've got a TextComponent defined as a prefix which is applied to all messages. At the end of the prefix, there is a color code to be applied. Prefix: &7[&bPrefix&7] &a
The messages are then loaded as TextComponent objects.
Once ready to send, I append the message TextComponent to the prefix TextComponent.
The expected behavior is that the entirety of the message, until another code is found, should be green since the prefix has a trailing &a color code; however, the message appears white until another color code is found.
Example: http://prntscr.com/nkpxhj
Here's the component in question:
TextComponent velocityWebsite = TextComponent.builder()
.content("Visit the ")
.append(TextComponent.builder("Velocity website")
.color(TextColor.GREEN)
.clickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://www.velocitypowered.com"))
.build())
.append(TextComponent.of(" or the ").resetStyle())
.append(TextComponent.builder("Velocity GitHub")
.color(TextColor.GREEN)
.clickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://github.com/astei/velocity"))
.build())
.build();
This is how it looks in-game, which is correct:
ComponentSerializers.LEGACY
turns this component into Visit the §aVelocity website§r or the Velocity GitHub
, which is not consistent with the in-game display. It should be more like Visit the §aVelocity website§r or the §aVelocity GitHub
.
Using text 1.12-1.6.2.
It would be nice if there was an additional static method on TextComponent
, like Sponge's Text.joinWith
:
static TextComponent joinWith(TextComponent separator, Iterable<TextComponent> components)
static TextComponent joinWith(TextComponent separator, TextComponent... components)
A limiting factor in recent years with the new JSON chat system is the ability to construct messages with arguments conveniently and safely.
In my own systems, I have implemented an XML parser that takes XML code and converts it to a JSON text object. E.g. <span style="9">foo</span>
translates to {"text": "foo", color: "blue"}
I also added the ability to have parameters in messages to be given in runtime. So <span style="9">foo {0}</span>
, with {0}
being "bar"
, translates to {"text": "foo bar", color: "blue"}
.
Now, I've reached a point where parameters need to be more complicated in the form of text components. So when given <span style="9">foo {0}</span>
, with {0}
being a Component, translates to {"text": "foo", color: "blue", extra: [ {"text": "bar", color: "yellow"} ] }
.
I know this falls outside of the project's scope currently as there is no ability to string format messages. However, since it is a text library I thought it might be fitting for those who wish to implement I18n-like systems or just organised messages.
Gradients right now doesn't allow 3+ colors/hexes but this feature can be pretty neat.
The small bandage for now.
<gradient:#000000:#ffffff>||||||||||||||||||||||||</gradient><gradient:#ffffff:#000000>||||||||||||||||||||||||</gradient>
<gradient:red:blue>||||||||||||||||||||||||</gradient><gradient:blue:green>||||||||||||||||||||||||</gradient><gradient:green:yellow>||||||||||||||||||||||||</gradient><gradient:yellow:red>||||||||||||||||||||||||</gradient>
With the latest Minecraft client, we can send texts in any RGB color, rather than the previous space of only 16.
Full color isn't supported by every viewer of our text -- commonly used console libraries convert to ANSI based on legacy color codes, and we target clients all the way back to MC 1.8.
When unsupported colors are passed to the legacy serializer, it fails locally with an exception.
When unsupported colors are sent to players, the color will be stripped entirely and players will see white text.
Users of the API could only avoid these issues by tracking the capabilities of every individual version they target, or by not using RGB at all.
I've added some API, currently on NamedTextColor, to find the nearest legacy color from any RGB color, but it is not yet used in any of the serializers. I'm also not entirely satisfied with the algorithm used -- it tends to favor the grays, as relatively "average" colors numerically.
How should the different serializers handle it?
A useful feature would be a tag that would allow new lines in text.
It would be used something like this:
<hover:show_text:"<red>test:TEST</red><br><green>TEST</green>">TEST
Using the string §r§r§c§k||§e§lProfile§c§k||
the first §k
isn't picked up properly causing the resulting TextComponent to look like the below image.
String name = "§r§r§c§k||§e§lProfile§c§k||";
TextComponent component = LegacyComponentSerializer.legacy().deserialize(name);
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.