[SPIGOT-3718] "java.lang.IllegalArgumentException: Component loop" when sending message which extends TextComponent Created: 25/Dec/17 Updated: 30/Mar/18 Resolved: 26/Dec/17 |
|
| Status: | Resolved |
| Project: | Spigot |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | Bug | Priority: | Minor |
| Reporter: | Matt D. | Assignee: | Unassigned |
| Resolution: | Invalid | Votes: | 0 |
| Labels: | TextComponent | ||
| Environment: |
Linux/CentOS 7 |
||
| Plugin: | Custom |
| Description |
|
I want to extend TextComponent to add my own features but for some reason this is causing an exception to be thrown.
See the following plugin. When a player issues "/test", the plugin will attempt to send a message to the first player returned by Bukkit.getOnlinePlayers() using ChatComponent which extends TextComponent. This will kick the player and report the following error to the console: "java.lang.IllegalArgumentException: Component loop".
Plugin source:
package com.codespunk.testplugin; import java.util.LinkedList; import java.util.List; import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import org.eclipse.jdt.annotation.NonNullByDefault; import net.md_5.bungee.api.chat.TextComponent; public class BukkitPlugin extends JavaPlugin implements CommandExecutor { public static class ChatComponent extends TextComponent { public ChatComponent( String text) { super(text); } } @Override public void onEnable() { getCommand("test").setExecutor(this); } @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { List<Player> players = new LinkedList<>(Bukkit.getOnlinePlayers()); if (!players.isEmpty()) players.iterator().next().spigot() .sendMessage(new ChatComponent("Hello!")); return true; } } |
| Comments |
| Comment by md_5 [ 30/Mar/18 ] |
|
Sorry that still doesn’t make sense as a legitimate reason. |
| Comment by Hugo Manrique [ 30/Mar/18 ] |
|
I'm currently creating a public API that would benefit greatly from having a class that would wrap a TextComponent (all the overrideable methods would call the wrapped TextComponent) but still extend the BaseComponent class for allowing users to call `Player.Spigot#sendMessage(BaseComponent)` with this component (which changes the text content based on the viewer). I've tried to override and imitate all the overridable methods but I'm still getting this warning. I even went so far to add a `TypeAdapterFactory` to the Gson instance used for serialization to implement the same logic the `TextComponentSerializer` is performing via reflection but it didn't work. I know I could just create a TextComponent from outside, but I really like this pattern. Perhaps you could think about adding a "ComponentRenderer" API which would allow outsiders to modify the content of any BaseComponent before getting sent. |
| Comment by md_5 [ 26/Dec/17 ] |
|
Because the chat API and Minecraft cannot handle custom component serialisation or deserialisation, and the API makes no suggestion that extending a component will lead to anything fruitful (nor should it). These classes are now (correctly) final - https://github.com/SpigotMC/BungeeCord/commit/dda06388692fa199c149a4fdab238fb5d04a7ebf - if you have a compelling reason to extend them then you should raise an issue about how/why.
As for why your original attempt didn't work, it's because you forgot to override key methods. |
| Comment by Matt D. [ 26/Dec/17 ] |
|
This is the most basic form of polymorphism. How is this abuse? |
| Comment by md_5 [ 26/Dec/17 ] |
|
This is abuse of the API pure and simple, and not supported. If you want to make it work, you are on your own.
|