private TextComponent componentForPlugin(PluginDescription description) { String pluginInfo = description.getName().orElse(description.getId()) + description.getVersion().map(v -> " " + v).orElse(""); TextComponent.Builder hoverText = TextComponent.builder(pluginInfo); description.getUrl().ifPresent(url -> { hoverText.append(Components.newline()); hoverText.append(TextComponent.of("Website: " + url)); }); if (!description.getAuthors().isEmpty()) { hoverText.append(Components.newline()); if (description.getAuthors().size() == 1) { hoverText.append(TextComponent.of("Author: " + description.getAuthors().get(0))); } else { hoverText.append(TextComponent.of("Authors: " + Joiner.on(", ") .join(description.getAuthors()))); } } description.getDescription().ifPresent(pdesc -> { hoverText.append(Components.newline()); hoverText.append(Components.newline()); hoverText.append(TextComponent.of(pdesc)); }); return TextComponent.of(description.getId(), TextColor.GRAY) .hoverEvent(new HoverEvent(Action.SHOW_TEXT, hoverText.build())); }
.decoration(TextDecoration.BOLD, true) .color(TextColor.DARK_AQUA) .append(TextComponent.of(version.getVersion()).decoration(TextDecoration.BOLD, false)) .build(); TextComponent copyright = TextComponent 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,
private Component render(final TranslatableComponent component, final C context) { final /* @Nullable */ MessageFormat format = this.translation(context.locale(), component.key()); if(format == null) { return component; } final List<Component> args = component.args(); final TextComponent.Builder builder = TextComponent.builder(); this.mergeStyle(component, builder, context); // no arguments makes this render very simple if(args.isEmpty()) { return builder.content(format.format(null, new StringBuffer(), null).toString()).build(); } final Object[] nulls = new Object[args.size()]; final StringBuffer sb = format.format(nulls, new StringBuffer(), null); final AttributedCharacterIterator it = format.formatToCharacterIterator(nulls); while(it.getIndex() < it.getEndIndex()) { final int end = it.getRunLimit(); final Integer index = (Integer) it.getAttribute(MessageFormat.Field.ARGUMENT); if(index != null) { builder.append(this.render(args.get(index), context)); } else { builder.append(TextComponent.of(sb.substring(it.getIndex(), end))); } it.setIndex(end); } return builder.content("").build(); }
@Test void testComplex() { final FriendlyComponentRenderer<ComponentRenderer.Context> renderer = FriendlyComponentRenderer.from((locale, key) -> new MessageFormat(TRANSLATIONS.get(locale, key), locale)); assertEquals( TextComponent.builder("") .color(TextColor.YELLOW) .append(TextComponent.of("kashike")) .append(TextComponent.of(" and ")) .append(TextComponent.of("lucko")) .append(TextComponent.of(" are cats.")) .build(), renderer.render( TranslatableComponent .builder() .key("cats") .args( TextComponent.of("kashike"), TextComponent.of("lucko") ) .color(TextColor.YELLOW) .build(), new ComponentRenderer.Context() { @Override public @NonNull Locale locale() { return Locale.US; } } ) ); }
/** * Handles unexpected disconnects. * @param server the server we disconnected from * @param disconnect the disconnect packet */ public void handleConnectionException(RegisteredServer server, Disconnect disconnect) { Component disconnectReason = ComponentSerializers.JSON.deserialize(disconnect.getReason()); String plainTextReason = PASS_THRU_TRANSLATE.serialize(disconnectReason); if (connectedServer != null && connectedServer.getServerInfo().equals(server.getServerInfo())) { logger.error("{}: kicked from server {}: {}", this, server.getServerInfo().getName(), plainTextReason); handleConnectionException(server, disconnectReason, TextComponent.builder() .content("Kicked from " + server.getServerInfo().getName() + ": ") .color(TextColor.RED) .append(disconnectReason) .build()); } else { logger.error("{}: disconnected while connecting to {}: {}", this, server.getServerInfo().getName(), plainTextReason); handleConnectionException(server, disconnectReason, TextComponent.builder() .content("Can't connect to server " + server.getServerInfo().getName() + ": ") .color(TextColor.RED) .append(disconnectReason) .build()); } }
final TextComponent c1 = TextComponent.builder("hi") .decoration(TextDecoration.BOLD, TextDecoration.State.TRUE) .append( TextComponent.of("foo") .color(TextColor.GREEN) .decoration(TextDecoration.BOLD, TextDecoration.State.FALSE) .append( TextComponent.of("bar") .color(TextColor.BLUE) .append(TextComponent.of("baz")) .build(); assertEquals("hifoobarbaz", PlainComponentSerializer.INSTANCE.serialize(c1)); .append( TextComponent.of("you") .color(TextColor.GREEN) .decoration(TextDecoration.BOLD, TextDecoration.State.FALSE) .append( TextComponent.of("!") .color(TextColor.BLUE)
private Component render(final TranslatableComponent component, final C context) { final /* @Nullable */ MessageFormat format = this.translation(context.locale(), component.key()); if(format == null) { return component; } final List<Component> args = component.args(); final TextComponent.Builder builder = TextComponent.builder(); this.mergeStyle(component, builder, context); // no arguments makes this render very simple if(args.isEmpty()) { return builder.content(format.format(null, new StringBuffer(), null).toString()).build(); } final Object[] nulls = new Object[args.size()]; final StringBuffer sb = format.format(nulls, new StringBuffer(), null); final AttributedCharacterIterator it = format.formatToCharacterIterator(nulls); while(it.getIndex() < it.getEndIndex()) { final int end = it.getRunLimit(); final Integer index = (Integer) it.getAttribute(MessageFormat.Field.ARGUMENT); if(index != null) { builder.append(this.render(args.get(index), context)); } else { builder.append(TextComponent.of(sb.substring(it.getIndex(), end))); } it.setIndex(end); } return builder.content("").build(); }
private Component render(final TranslatableComponent component, final C context) { final /* @Nullable */ MessageFormat format = this.translation(context.locale(), component.key()); if(format == null) { return component; } final List<Component> args = component.args(); final TextComponent.Builder builder = TextComponent.builder(); this.mergeStyle(component, builder, context); // no arguments makes this render very simple if(args.isEmpty()) { return builder.content(format.format(null, new StringBuffer(), null).toString()).build(); } final Object[] nulls = new Object[args.size()]; final StringBuffer sb = format.format(nulls, new StringBuffer(), null); final AttributedCharacterIterator it = format.formatToCharacterIterator(nulls); while(it.getIndex() < it.getEndIndex()) { final int end = it.getRunLimit(); final Integer index = (Integer) it.getAttribute(MessageFormat.Field.ARGUMENT); if(index != null) { builder.append(this.render(args.get(index), context)); } else { builder.append(TextComponent.of(sb.substring(it.getIndex(), end))); } it.setIndex(end); } return builder.content("").build(); }
@Override public void execute(CommandSource source, String @NonNull [] args) { if (args.length != 0) { source.sendMessage(TextComponent.of("/velocity plugins", TextColor.RED)); return; } List<PluginContainer> plugins = ImmutableList.copyOf(server.getPluginManager().getPlugins()); int pluginCount = plugins.size(); if (pluginCount == 0) { source.sendMessage(TextComponent.of("No plugins installed.", TextColor.YELLOW)); return; } TextComponent.Builder output = TextComponent.builder("Plugins: ") .color(TextColor.YELLOW); for (int i = 0; i < pluginCount; i++) { PluginContainer plugin = plugins.get(i); output.append(componentForPlugin(plugin.getDescription())); if (i + 1 < pluginCount) { output.append(TextComponent.of(", ")); } } source.sendMessage(output.build()); }
@Test void testDeserializeText() { assertEquals(TextComponent.of("Hello, world."), GsonComponentSerializer.INSTANCE.deserialize("{\"text\":\"Hello, world.\"}")); assertEquals(TextComponent.builder("c") .color(TextColor.GOLD) .append(TextComponent.of("o", TextColor.DARK_AQUA)) .append(TextComponent.of("l", TextColor.LIGHT_PURPLE)) .append(TextComponent.of("o", TextColor.DARK_PURPLE)) .append(TextComponent.of("u", TextColor.BLUE)) .append(TextComponent.of("r", TextColor.DARK_GREEN)) .append(TextComponent.of("s", TextColor.RED)) .build(), GsonComponentSerializer.INSTANCE.deserialize("[{\"text\":\"c\",\"color\":\"gold\"},{\"text\":\"o\",\"color\":\"dark_aqua\"},{\"text\":\"l\",\"color\":\"light_purple\"},{\"text\":\"o\",\"color\":\"dark_purple\"},{\"text\":\"u\",\"color\":\"blue\"},{\"text\":\"r\",\"color\":\"dark_green\"},{\"text\":\"s\",\"color\":\"red\"}]")); assertEquals(TextComponent.builder("This is a test.") .color(TextColor.DARK_PURPLE) .hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("A test."))) .append(TextComponent.of(" ")) .append(TextComponent.of("A what?", TextColor.DARK_AQUA)) .build(), GsonComponentSerializer.INSTANCE.deserialize("[{\"text\":\"This is a test.\",\"color\":\"dark_purple\",\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"A test.\"}}},{\"text\":\" \"},{\"text\":\"A what?\",\"color\":\"dark_aqua\"}]")); }
@Test void testCompound() { final TextComponent component = TextComponent.builder() .content("hi there ") .append(TextComponent.builder("this bit is green ") .color(TextColor.GREEN) .build()) .append(TextComponent.of("this isn't ").resetStyle()) .append(TextComponent.builder("and woa, this is again") .color(TextColor.GREEN) .build()) .build(); assertEquals("hi there &athis bit is green &rthis isn't &aand woa, this is again", LegacyComponentSerializer.INSTANCE.serialize(component, '&')); }
@Test void testResetOverride() { final TextComponent component = TextComponent.builder("") .append(TextComponent.of("foo").color(TextColor.GREEN).decoration(TextDecoration.BOLD, TextDecoration.State.TRUE)) .append(TextComponent.of("bar").color(TextColor.DARK_GRAY)) .build(); assertEquals(component, LegacyComponentSerializer.INSTANCE.deserialize("&a&lfoo&r&8bar", '&')); }
@Test void testFromColorOverride() { final TextComponent component = TextComponent.builder("") .append(TextComponent.of("foo").color(TextColor.BLUE)) .build(); assertEquals(component, LegacyComponentSerializer.INSTANCE.deserialize("&a&9foo", '&')); }
@Test void testFromColor() { final TextComponent component = TextComponent.builder("") .append(TextComponent.of("foo").color(TextColor.GREEN).decoration(TextDecoration.BOLD, TextDecoration.State.TRUE)) .append(TextComponent.of("bar").color(TextColor.BLUE)) .build(); assertEquals(component, LegacyComponentSerializer.INSTANCE.deserialize("&a&lfoo&9bar", '&')); }
@Test void testCopy() { final TextComponent.Builder component = TextComponent.builder().content("").color(TextColor.GRAY); component.append(TextComponent.builder().content("This is a test").color(TextColor.DARK_PURPLE).build()); component.append(TextComponent.builder().content(" ").build()); component.append(TextComponent.builder().content("A what?").color(TextColor.DARK_AQUA).clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/what")).build()); assertEquals(component.build(), component.build().copy()); }
@Test void testContains() { final Component child = TextComponent.of("kittens"); final Component component = TextComponent.builder() .content("cat") .append(child) .build(); assertTrue(component.contains(child)); }