diff --git a/Chroma-Core/src/main/java/buttondevteam/core/ComponentCommand.java b/Chroma-Core/src/main/java/buttondevteam/core/ComponentCommand.java index 4c601d8..a5014b7 100644 --- a/Chroma-Core/src/main/java/buttondevteam/core/ComponentCommand.java +++ b/Chroma-Core/src/main/java/buttondevteam/core/ComponentCommand.java @@ -83,7 +83,7 @@ public class ComponentCommand extends ICommand2MC { oc.get().shouldBeEnabled().set(enable); sender.sendMessage(oc.get().getClass().getSimpleName() + " " + (enable ? "en" : "dis") + "abled " + (permanent ? "permanently" : "temporarily") + "."); } catch (Exception e) { - TBMCCoreAPI.SendException("Couldn't " + (enable ? "en" : "dis") + "able component " + component + "!", e); + TBMCCoreAPI.SendException("Couldn't " + (enable ? "en" : "dis") + "able component " + component + "!", e, (JavaPlugin) plugin); } return true; } diff --git a/Chroma-Core/src/main/java/buttondevteam/core/ComponentManager.java b/Chroma-Core/src/main/java/buttondevteam/core/ComponentManager.java index bbc3a01..a836076 100644 --- a/Chroma-Core/src/main/java/buttondevteam/core/ComponentManager.java +++ b/Chroma-Core/src/main/java/buttondevteam/core/ComponentManager.java @@ -25,7 +25,7 @@ public final class ComponentManager { try { Component.setComponentEnabled(c, true); } catch (Exception | NoClassDefFoundError e) { - TBMCCoreAPI.SendException("Failed to enable one of the components: " + c.getClass().getSimpleName(), e); + TBMCCoreAPI.SendException("Failed to enable one of the components: " + c.getClass().getSimpleName(), e, c); } }); componentsEnabled = true; diff --git a/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.java b/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.java index 1c008d0..bb4d7cb 100755 --- a/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.java +++ b/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.java @@ -142,7 +142,7 @@ public class MainPlugin extends ButtonPlugin { try { Files.write(new File("plugins", "plugins.txt").toPath(), Arrays.stream(Bukkit.getPluginManager().getPlugins()).map(p -> (CharSequence) p.getDataFolder().getName())::iterator); } catch (IOException e) { - TBMCCoreAPI.SendException("Failed to write plugin list!", e); + TBMCCoreAPI.SendException("Failed to write plugin list!", e, this); } } if (getServer().getPluginManager().isPluginEnabled("Essentials")) diff --git a/Chroma-Core/src/main/java/buttondevteam/core/PlayerListener.java b/Chroma-Core/src/main/java/buttondevteam/core/PlayerListener.java index 85fc737..ea21f17 100755 --- a/Chroma-Core/src/main/java/buttondevteam/core/PlayerListener.java +++ b/Chroma-Core/src/main/java/buttondevteam/core/PlayerListener.java @@ -77,7 +77,7 @@ public class PlayerListener implements Listener { try { event.setCancelled(ButtonPlugin.getCommand2MC().handleCommand(new Command2MCSender(event.getSender(), event.getChannel(), event.getPermCheck()), event.getMessage())); } catch (Exception e) { - TBMCCoreAPI.SendException("Command processing failed for sender '" + event.getSender() + "' and message '" + event.getMessage() + "'", e); + TBMCCoreAPI.SendException("Command processing failed for sender '" + event.getSender() + "' and message '" + event.getMessage() + "'", e, MainPlugin.Instance); } } diff --git a/Chroma-Core/src/main/java/buttondevteam/core/component/restart/RestartComponent.java b/Chroma-Core/src/main/java/buttondevteam/core/component/restart/RestartComponent.java index 1333955..9256910 100644 --- a/Chroma-Core/src/main/java/buttondevteam/core/component/restart/RestartComponent.java +++ b/Chroma-Core/src/main/java/buttondevteam/core/component/restart/RestartComponent.java @@ -4,6 +4,7 @@ import buttondevteam.core.MainPlugin; import buttondevteam.core.component.channel.Channel; import buttondevteam.lib.TBMCSystemChatEvent; import buttondevteam.lib.architecture.Component; +import buttondevteam.lib.architecture.ComponentMetadata; import buttondevteam.lib.architecture.ConfigData; import buttondevteam.lib.chat.IFakePlayer; import buttondevteam.lib.chat.TBMCChatAPI; @@ -14,14 +15,15 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerQuitEvent; -import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; /** - * Provides commands such as /schrestart (restart after a countdown) and /primerestart (restart when nobody is online) + * Provides commands such as /schrestart (restart after a countdown) and /primerestart (restart when nobody is online). + * Also can automatically restart at a given time. */ +@ComponentMetadata(enabledByDefault = false) public class RestartComponent extends Component implements Listener { @Override public void enable() { diff --git a/Chroma-Core/src/main/java/buttondevteam/core/component/spawn/SpawnComponent.java b/Chroma-Core/src/main/java/buttondevteam/core/component/spawn/SpawnComponent.java index b786558..de28b06 100644 --- a/Chroma-Core/src/main/java/buttondevteam/core/component/spawn/SpawnComponent.java +++ b/Chroma-Core/src/main/java/buttondevteam/core/component/spawn/SpawnComponent.java @@ -2,6 +2,7 @@ package buttondevteam.core.component.spawn; import buttondevteam.core.MainPlugin; import buttondevteam.lib.architecture.Component; +import buttondevteam.lib.architecture.ComponentMetadata; import buttondevteam.lib.architecture.ConfigData; import buttondevteam.lib.chat.Command2; import buttondevteam.lib.chat.CommandClass; @@ -23,6 +24,7 @@ import java.math.BigDecimal; /** * Provides a /spawn command that works with BungeeCord. Make sure to set up on each server. */ +@ComponentMetadata(enabledByDefault = false) public class SpawnComponent extends Component implements PluginMessageListener { @Override protected void enable() { diff --git a/Chroma-Core/src/main/java/buttondevteam/core/component/towny/TownyComponent.java b/Chroma-Core/src/main/java/buttondevteam/core/component/towny/TownyComponent.java index fd34aef..d23b197 100644 --- a/Chroma-Core/src/main/java/buttondevteam/core/component/towny/TownyComponent.java +++ b/Chroma-Core/src/main/java/buttondevteam/core/component/towny/TownyComponent.java @@ -8,7 +8,6 @@ import com.palmergames.bukkit.towny.TownyUniverse; import com.palmergames.bukkit.towny.exceptions.AlreadyRegisteredException; import com.palmergames.bukkit.towny.exceptions.NotRegisteredException; import com.palmergames.bukkit.towny.object.Resident; -import org.bukkit.Bukkit; /** * Automatically renames Towny players if they changed their Minecraft name @@ -48,9 +47,9 @@ public class TownyComponent extends Component { component.log("Renaming done."); } } catch (AlreadyRegisteredException e) { - TBMCCoreAPI.SendException("Failed to rename resident, there's already one with this name.", e); + TBMCCoreAPI.SendException("Failed to rename resident, there's already one with this name.", e, component); } catch (NotRegisteredException e) { - TBMCCoreAPI.SendException("Failed to rename resident, the resident isn't registered.", e); + TBMCCoreAPI.SendException("Failed to rename resident, the resident isn't registered.", e, component); } } } diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/EventExceptionCoreHandler.java b/Chroma-Core/src/main/java/buttondevteam/lib/EventExceptionCoreHandler.java index 0cffe71..bd07561 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/EventExceptionCoreHandler.java +++ b/Chroma-Core/src/main/java/buttondevteam/lib/EventExceptionCoreHandler.java @@ -1,13 +1,14 @@ -package buttondevteam.lib; - -import org.bukkit.event.Event; - -class EventExceptionCoreHandler extends EventExceptionHandler { - - @Override - public boolean handle(Throwable ex, Event event) { - TBMCCoreAPI.SendException("An error occured while executing " + event.getEventName() + "!", ex); - return true; - } - -} +package buttondevteam.lib; + +import org.bukkit.Bukkit; +import org.bukkit.event.Event; + +class EventExceptionCoreHandler extends EventExceptionHandler { + + @Override + public boolean handle(Throwable ex, Event event) { + TBMCCoreAPI.SendException("An error occured while executing " + event.getEventName() + "!", ex, false, Bukkit.getLogger()::warning); + return true; + } + +} diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/TBMCCoreAPI.java b/Chroma-Core/src/main/java/buttondevteam/lib/TBMCCoreAPI.java index 244a16b..72129aa 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/TBMCCoreAPI.java +++ b/Chroma-Core/src/main/java/buttondevteam/lib/TBMCCoreAPI.java @@ -1,13 +1,14 @@ package buttondevteam.lib; import buttondevteam.core.MainPlugin; +import buttondevteam.lib.architecture.Component; import buttondevteam.lib.player.ChromaGamerBase; import buttondevteam.lib.potato.DebugPotato; import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.event.Listener; import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.java.JavaPlugin; import java.io.IOException; import java.io.InputStream; @@ -15,6 +16,7 @@ import java.net.URL; import java.net.URLConnection; import java.util.*; import java.util.Map.Entry; +import java.util.function.Consumer; public class TBMCCoreAPI { static final List coders = new ArrayList() { @@ -51,11 +53,21 @@ public class TBMCCoreAPI { * @param sourcemsg A message that is shown at the top of the exception (before the exception's message) * @param e The exception to send */ - public static void SendException(String sourcemsg, Throwable e) { - SendException(sourcemsg, e, false); + public static void SendException(String sourcemsg, Throwable e, Component component) { + SendException(sourcemsg, e, false, component::logWarn); } - public static void SendException(String sourcemsg, Throwable e, boolean debugPotato) { + /** + * Send exception to the {@link TBMCExceptionEvent}. + * + * @param sourcemsg A message that is shown at the top of the exception (before the exception's message) + * @param e The exception to send + */ + public static void SendException(String sourcemsg, Throwable e, JavaPlugin plugin) { + SendException(sourcemsg, e, false, plugin.getLogger()::warning); + } + + public static void SendException(String sourcemsg, Throwable e, boolean debugPotato, Consumer logWarn) { try { SendUnsentExceptions(); TBMCExceptionEvent event = new TBMCExceptionEvent(sourcemsg, e); @@ -64,7 +76,7 @@ public class TBMCCoreAPI { if (!event.isHandled()) exceptionsToSend.put(sourcemsg, e); } - Bukkit.getLogger().warning(sourcemsg); + logWarn.accept(sourcemsg); e.printStackTrace(); if (debugPotato) { List devsOnline = new ArrayList<>(); @@ -105,6 +117,7 @@ public class TBMCCoreAPI { } private static EventExceptionCoreHandler eventExceptionCoreHandler; + /** * Registers Bukkit events, handling the exceptions occurring in those events * diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java index d7c4714..4112591 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java +++ b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java @@ -59,7 +59,7 @@ public abstract class ButtonPlugin extends JavaPlugin { try { pluginEnable(); } catch (Exception e) { - TBMCCoreAPI.SendException("Error while enabling plugin " + getName() + "!", e); + TBMCCoreAPI.SendException("Error while enabling plugin " + getName() + "!", e, this); } if (configGenAllowed(this)) //If it's not disabled (by default it's not) IHaveConfig.pregenConfig(this, null); @@ -85,7 +85,7 @@ public abstract class ButtonPlugin extends JavaPlugin { getLogger().info("Saved configuration changes."); getCommand2MC().unregisterCommands(this); } catch (Exception e) { - TBMCCoreAPI.SendException("Error while disabling plugin " + getName() + "!", e); + TBMCCoreAPI.SendException("Error while disabling plugin " + getName() + "!", e, this); } } @@ -142,7 +142,7 @@ public abstract class ButtonPlugin extends JavaPlugin { if (yaml != null) yaml.save(); } catch (Exception e) { - TBMCCoreAPI.SendException("Failed to save config", e); + TBMCCoreAPI.SendException("Failed to save config", e, this); } } diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/Component.java b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/Component.java index c214064..548404f 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/Component.java +++ b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/Component.java @@ -77,7 +77,7 @@ public abstract class Component { } if (register) { if (components.containsKey(component.getClass())) { - TBMCCoreAPI.SendException("Failed to register component " + component.getClassName(), new IllegalArgumentException("The component is already registered!")); + TBMCCoreAPI.SendException("Failed to register component " + component.getClassName(), new IllegalArgumentException("The component is already registered!"), plugin); return false; } component.plugin = plugin; @@ -92,7 +92,7 @@ public abstract class Component { setComponentEnabled(component, true); return true; } catch (Exception | NoClassDefFoundError e) { - TBMCCoreAPI.SendException("Failed to enable component " + component.getClassName() + "!", e); + TBMCCoreAPI.SendException("Failed to enable component " + component.getClassName() + "!", e, component); return true; } } @@ -103,7 +103,7 @@ public abstract class Component { try { setComponentEnabled(component, false); } catch (Exception | NoClassDefFoundError e) { - TBMCCoreAPI.SendException("Failed to disable component " + component.getClassName() + "!", e); + TBMCCoreAPI.SendException("Failed to disable component " + component.getClassName() + "!", e, component); return false; //If failed to disable, won't unregister either } } @@ -112,7 +112,7 @@ public abstract class Component { } return true; } catch (Exception e) { - TBMCCoreAPI.SendException("Failed to " + (register ? "" : "un") + "register component " + component.getClassName() + "!", e); + TBMCCoreAPI.SendException("Failed to " + (register ? "" : "un") + "register component " + component.getClassName() + "!", e, plugin); return false; } } @@ -153,7 +153,7 @@ public abstract class Component { } } - public static void updateConfig(JavaPlugin plugin, Component component) { + public static void updateConfig(JavaPlugin plugin, Component component) { if (plugin.getConfig() != null) { //Production var compconf = plugin.getConfig().getConfigurationSection("components"); if (compconf == null) compconf = plugin.getConfig().createSection("components"); diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/IHaveConfig.java b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/IHaveConfig.java index ca7e5ac..f034fec 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/IHaveConfig.java +++ b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/IHaveConfig.java @@ -5,7 +5,9 @@ import buttondevteam.lib.TBMCCoreAPI; import lombok.Getter; import lombok.Setter; import lombok.val; +import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.plugin.java.JavaPlugin; import javax.annotation.Nullable; import java.lang.reflect.InvocationTargetException; @@ -211,7 +213,13 @@ public final class IHaveConfig { try { return (ConfigData) m.invoke(obj, kv.getValue()); } catch (IllegalAccessException | InvocationTargetException e) { - TBMCCoreAPI.SendException("Failed to pregenerate " + m.getName() + " for " + obj + " using config " + kv.getKey() + "!", e); + String msg = "Failed to pregenerate " + m.getName() + " for " + obj + " using config " + kv.getKey() + "!"; + if (obj instanceof Component) + TBMCCoreAPI.SendException(msg, e, (Component) obj); + else if (obj instanceof JavaPlugin) + TBMCCoreAPI.SendException(msg, e, (JavaPlugin) obj); + else + TBMCCoreAPI.SendException(msg, e, false, Bukkit.getLogger()::warning); return null; } }).filter(Objects::nonNull).collect(Collectors.toList()); @@ -228,7 +236,13 @@ public final class IHaveConfig { c.get(); //Saves the default value if needed - also checks validity } } catch (Exception e) { - TBMCCoreAPI.SendException("Failed to pregenerate " + m.getName() + " for " + obj + "!", e); + String msg = "Failed to pregenerate " + m.getName() + " for " + obj + "!"; + if (obj instanceof Component) + TBMCCoreAPI.SendException(msg, e, (Component) obj); + else if (obj instanceof JavaPlugin) + TBMCCoreAPI.SendException(msg, e, (JavaPlugin) obj); + else + TBMCCoreAPI.SendException(msg, e, false, Bukkit.getLogger()::warning); } } } diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2.java b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2.java index 0c3c905..66ef830 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2.java +++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2.java @@ -147,7 +147,7 @@ public abstract class Command2, TP extends Command2Send try { handleCommandAsync(sender, commandline, sd, subcommand, sync); } catch (Exception e) { - TBMCCoreAPI.SendException("Command execution failed for sender " + sender.getName() + "(" + sender.getClass().getCanonicalName() + ") and message " + commandline, e); + TBMCCoreAPI.SendException("Command execution failed for sender " + sender.getName() + "(" + sender.getClass().getCanonicalName() + ") and message " + commandline, e, MainPlugin.Instance); } }); return true; //We found a method @@ -271,9 +271,9 @@ public abstract class Command2, TP extends Command2Send } else if (ret != null) throw new Exception("Wrong return type! Must return a boolean or void. Return value: " + ret); } catch (InvocationTargetException e) { - TBMCCoreAPI.SendException("An error occurred in a command handler!", e.getCause()); + TBMCCoreAPI.SendException("An error occurred in a command handler for " + subcommand + "!", e.getCause(), MainPlugin.Instance); } catch (Exception e) { - TBMCCoreAPI.SendException("Command handling failed for sender " + sender + " and subcommand " + subcommand, e); + TBMCCoreAPI.SendException("Command handling failed for sender " + sender + " and subcommand " + subcommand, e, MainPlugin.Instance); } }; if (sync) @@ -306,7 +306,7 @@ public abstract class Command2, TP extends Command2Send if (!commandHelp.contains(mainPath)) commandHelp.add(mainPath); } catch (Exception e) { - TBMCCoreAPI.SendException("Could not register default handler for command /" + path, e); + TBMCCoreAPI.SendException("Could not register default handler for command /" + path, e, MainPlugin.Instance); } var addedSubcommands = new ArrayList>(); for (val method : command.getClass().getMethods()) { @@ -347,7 +347,7 @@ public abstract class Command2, TP extends Command2Send private String[] getParameterHelp(Method method, String[] ht, String subcommand, String[] parameters) { val str = method.getDeclaringClass().getResourceAsStream("/commands.yml"); if (str == null) - TBMCCoreAPI.SendException("Error while getting command data!", new Exception("Resource not found!")); + TBMCCoreAPI.SendException("Error while getting command data!", new Exception("Resource not found!"), MainPlugin.Instance); else { if (ht.length > 0) ht[0] = "§6---- " + ht[0] + " ----"; @@ -368,11 +368,11 @@ public abstract class Command2, TP extends Command2Send for (int j = 0; j < paramArray.length && j < parameters.length; j++) parameters[j] = paramArray[j]; } else - TBMCCoreAPI.SendException("Error while getting command data for " + method + "!", new Exception("Method '" + method.toString() + "' != " + mname + " or params is " + params)); + TBMCCoreAPI.SendException("Error while getting command data for " + method + "!", new Exception("Method '" + method.toString() + "' != " + mname + " or params is " + params), MainPlugin.Instance); } else - TBMCCoreAPI.SendException("Error while getting command data for " + method + "!", new Exception("cs is " + cs)); + TBMCCoreAPI.SendException("Error while getting command data for " + method + "!", new Exception("cs is " + cs), MainPlugin.Instance); } else - TBMCCoreAPI.SendException("Error while getting command data for " + method + "!", new Exception("ccs is " + ccs + " - class: " + method.getDeclaringClass().getCanonicalName())); + TBMCCoreAPI.SendException("Error while getting command data for " + method + "!", new Exception("ccs is " + ccs + " - class: " + method.getDeclaringClass().getCanonicalName()), MainPlugin.Instance); } return ht; } diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MC.java b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MC.java index 102ce0d..87cadd2 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MC.java +++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MC.java @@ -8,7 +8,6 @@ import buttondevteam.lib.player.ChromaGamerBase; import com.mojang.brigadier.arguments.*; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.RequiredArgumentBuilder; -import com.mojang.brigadier.suggestion.SuggestionProvider; import com.mojang.brigadier.tree.CommandNode; import com.mojang.brigadier.tree.LiteralCommandNode; import lombok.val; @@ -233,7 +232,10 @@ public class Command2MC extends Command2 implemen if (CommodoreProvider.isSupported()) TabcompleteHelper.registerTabcomplete(command, subcmds, bukkitCommand); } catch (Exception e) { - TBMCCoreAPI.SendException("Failed to register command in command map!", e); + if (command.getComponent() == null) + TBMCCoreAPI.SendException("Failed to register command in command map!", e, command.getPlugin()); + else + TBMCCoreAPI.SendException("Failed to register command in command map!", e, command.getComponent()); shouldRegisterOfficially = false; } } @@ -241,7 +243,7 @@ public class Command2MC extends Command2 implemen private boolean executeCommand(CommandSender sender, Command command, String label, String[] args) { var user = ChromaGamerBase.getFromSender(sender); if (user == null) { - TBMCCoreAPI.SendException("Failed to run Bukkit command for user!", new Throwable("No Chroma user found")); + TBMCCoreAPI.SendException("Failed to run Bukkit command for user!", new Throwable("No Chroma user found"), MainPlugin.Instance); sender.sendMessage("§cAn internal error occurred."); return true; } @@ -372,7 +374,7 @@ public class Command2MC extends Command2 implemen .filter(t -> param.replaceAll("[\\[\\]<>]", "").equalsIgnoreCase(t.getValue1().param())) .findAny(); var argb = RequiredArgumentBuilder.argument(param, type) - .suggests((SuggestionProvider) (context, builder) -> { + .suggests((context, builder) -> { if (parameter.isVarArgs()) { //Do it before the builder is used int nextTokenStart = context.getInput().lastIndexOf(' ') + 1; builder = builder.createOffset(nextTokenStart); @@ -399,12 +401,9 @@ public class Command2MC extends Command2 implemen args[j] = paramValueString; continue; } - val converter = ButtonPlugin.getCommand2MC().paramConverters.get(params[j].getType()); - if (converter == null) { - TBMCCoreAPI.SendException("Could not find a suitable converter for type " + params[j].getType().getSimpleName(), - new NullPointerException("converter is null")); + val converter = getParamConverter(params[j].getType(), command2MC); + if (converter == null) break; - } val paramValue = converter.converter.apply(paramValueString); if (paramValue == null) //For example, the player provided an invalid plugin name break; @@ -427,16 +426,17 @@ public class Command2MC extends Command2 implemen else throw new ClassCastException("Bad return type! It should return a String[] or an Iterable."); } catch (Exception e) { - TBMCCoreAPI.SendException("Failed to run tabcomplete method " + method.getName() + " for command " + command2MC.getClass().getSimpleName(), e); + String msg = "Failed to run tabcomplete method " + method.getName() + " for command " + command2MC.getClass().getSimpleName(); + if (command2MC.getComponent() == null) + TBMCCoreAPI.SendException(msg, e, command2MC.getPlugin()); + else + TBMCCoreAPI.SendException(msg, e, command2MC.getComponent()); } } } if (!ignoreCustomParamType && customParamType) { - val converter = ButtonPlugin.getCommand2MC().paramConverters.get(ptype); - if (converter == null) - TBMCCoreAPI.SendException("Could not find a suitable converter for type " + ptype.getSimpleName(), - new NullPointerException("converter is null")); - else { + val converter = getParamConverter(ptype, command2MC); + if (converter != null) { var suggestions = converter.allSupplier.get(); for (String suggestion : suggestions) builder.suggest(suggestion); @@ -467,4 +467,18 @@ public class Command2MC extends Command2 implemen } } } + + private static ParamConverter getParamConverter(Class cl, ICommand2MC command2MC) { + val converter = ButtonPlugin.getCommand2MC().paramConverters.get(cl); + if (converter == null) { + String msg = "Could not find a suitable converter for type " + cl.getSimpleName(); + Exception exception = new NullPointerException("converter is null"); + if (command2MC.getComponent() == null) + TBMCCoreAPI.SendException(msg, exception, command2MC.getPlugin()); + else + TBMCCoreAPI.SendException(msg, exception, command2MC.getComponent()); + return null; + } + return converter; + } } diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/player/ChromaGamerBase.java b/Chroma-Core/src/main/java/buttondevteam/lib/player/ChromaGamerBase.java index 6c6ea0b..31a47d7 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/player/ChromaGamerBase.java +++ b/Chroma-Core/src/main/java/buttondevteam/lib/player/ChromaGamerBase.java @@ -1,5 +1,6 @@ package buttondevteam.lib.player; +import buttondevteam.core.MainPlugin; import buttondevteam.core.component.channel.Channel; import buttondevteam.lib.TBMCCoreAPI; import com.google.common.collect.HashBiMap; @@ -30,19 +31,17 @@ public abstract class ChromaGamerBase implements AutoCloseable { playerTypes.put(userclass, userclass.getAnnotation(UserClass.class).foldername()); else if (userclass.isAnnotationPresent(AbstractUserClass.class)) playerTypes.put(userclass.getAnnotation(AbstractUserClass.class).prototype(), - userclass.getAnnotation(AbstractUserClass.class).foldername()); + userclass.getAnnotation(AbstractUserClass.class).foldername()); else // <-- Really important throw new RuntimeException("Class not registered as a user class! Use @UserClass or TBMCPlayerBase"); } /** * Returns the folder name for the given player class. - * - * @param cl - * The class to get the folder from (like {@link TBMCPlayerBase} or one of it's subclasses) + * + * @param cl The class to get the folder from (like {@link TBMCPlayerBase} or one of it's subclasses) * @return The folder name for the given type - * @throws RuntimeException - * If the class doesn't have the {@link UserClass} annotation. + * @throws RuntimeException If the class doesn't have the {@link UserClass} annotation. */ public static String getFolderForType(Class cl) { if (cl.isAnnotationPresent(UserClass.class)) @@ -54,9 +53,8 @@ public abstract class ChromaGamerBase implements AutoCloseable { /** * Returns the player class for the given folder name. - * - * @param foldername - * The folder to get the class from (like "minecraft") + * + * @param foldername The folder to get the class from (like "minecraft") * @return The type for the given folder name or null if not found */ public static Class getTypeForFolder(String foldername) { @@ -72,16 +70,16 @@ public abstract class ChromaGamerBase implements AutoCloseable { } /** - * Use {@link #data(Object)} or {@link #data(String, Object)} where possible; the 'id' must be always set + * Use {@link #data(Object)} or {@link #data(String, Object)} where possible; the 'id' must be always set */ protected YamlConfiguration plugindata; /*** * Loads a user from disk and returns the user object. Make sure to use the subclasses' methods, where possible, like {@link TBMCPlayerBase#getPlayer(java.util.UUID, Class)} * - * @param fname Filename without .yml, usually UUID - * @param cl User class - * @return The user object + * @param fname Filename without .yml, usually UUID + * @param cl User class + * @return The user object */ public static T getUser(String fname, Class cl) { try { @@ -93,7 +91,7 @@ public abstract class ChromaGamerBase implements AutoCloseable { obj.plugindata.set(folder + "_id", fname); return obj; } catch (Exception e) { - TBMCCoreAPI.SendException("An error occured while loading a " + cl.getSimpleName() + "!", e); + TBMCCoreAPI.SendException("An error occured while loading a " + cl.getSimpleName() + "!", e, MainPlugin.Instance); } return null; } @@ -140,15 +138,14 @@ public abstract class ChromaGamerBase implements AutoCloseable { try { close(); } catch (Exception e) { - TBMCCoreAPI.SendException("Error while saving player to " + getFolder() + "/" + getFileName() + ".yml!", e); + TBMCCoreAPI.SendException("Error while saving player to " + getFolder() + "/" + getFileName() + ".yml!", e, MainPlugin.Instance); } } /** * Connect two accounts. Do not use for connecting two Minecraft accounts or similar. Also make sure you have the "id" tag set - * - * @param user - * The account to connect with + * + * @param user The account to connect with */ public void connectWith(T user) { // Set the ID, go through all linked files and connect them as well @@ -157,7 +154,7 @@ public abstract class ChromaGamerBase implements AutoCloseable { final String ownFolder = getFolder(); final String userFolder = user.getFolder(); if (ownFolder.equalsIgnoreCase(userFolder)) - throw new RuntimeException("Do not connect two accounts of the same type! Type: "+ownFolder); + throw new RuntimeException("Do not connect two accounts of the same type! Type: " + ownFolder); user.plugindata.set(ownFolder + "_id", plugindata.getString(ownFolder + "_id")); plugindata.set(userFolder + "_id", user.plugindata.getString(userFolder + "_id")); Consumer sync = sourcedata -> { @@ -176,7 +173,7 @@ public abstract class ChromaGamerBase implements AutoCloseable { cg.plugindata.set(item.getValue() + "_id", sourcedata.getString(item.getValue() + "_id")); // Set all existing IDs } catch (Exception e) { TBMCCoreAPI.SendException("Failed to update " + sourcefolder + " ID in player files for " + id - + " in folder with " + entry.getValue() + " id " + otherid + "!", e); + + " in folder with " + entry.getValue() + " id " + otherid + "!", e, MainPlugin.Instance); } } }; @@ -186,9 +183,8 @@ public abstract class ChromaGamerBase implements AutoCloseable { /** * Retunrs the ID for the T typed player object connected with this one or null if no connection found. - * - * @param cl - * The player class to get the ID from + * + * @param cl The player class to get the ID from * @return The ID or null if not found */ public String getConnectedID(Class cl) { @@ -198,9 +194,8 @@ public abstract class ChromaGamerBase implements AutoCloseable { /** * Returns this player as a plugin player. This will return a new instance unless the player is online.
* Make sure to close both the returned and this object. A try-with-resources block or two can help.
- * - * @param cl - * The target player class + * + * @param cl The target player class * @return The player as a {@link T} object or null if not having an account there */ @SuppressWarnings("unchecked") @@ -224,16 +219,16 @@ public abstract class ChromaGamerBase implements AutoCloseable { private void ThrowIfNoUser() { if (!getClass().isAnnotationPresent(UserClass.class) - && !getClass().isAnnotationPresent(AbstractUserClass.class)) + && !getClass().isAnnotationPresent(AbstractUserClass.class)) throw new RuntimeException("Class not registered as a user class! Use @UserClass"); } @SuppressWarnings("rawtypes") - private final HashMap datamap = new HashMap<>(); + private final HashMap datamap = new HashMap<>(); /** * Use from a data() method, which is in a method with the name of the key. For example, use flair() for the enclosing method of the outer data() to save to and load from "flair" - * + * * @return A data object with methods to get and set */ @SuppressWarnings("unchecked") @@ -247,7 +242,7 @@ public abstract class ChromaGamerBase implements AutoCloseable { /** * Use from a method with the name of the key. For example, use flair() for the enclosing method to save to and load from "flair" - * + * * @return A data object with methods to get and set */ @SuppressWarnings("unchecked") @@ -265,7 +260,7 @@ public abstract class ChromaGamerBase implements AutoCloseable { /** * Use from a data() method, which is in a method with the name of the key. For example, use flair() for the enclosing method of the outer data() to save to and load from "flair" - * + * * @return A data object with methods to get and set */ @SuppressWarnings("unchecked") @@ -306,9 +301,8 @@ public abstract class ChromaGamerBase implements AutoCloseable { /** * Get player information. This method calls the {@link TBMCPlayerGetInfoEvent} to get all the player information across the TBMC plugins. - * - * @param target - * The {@link InfoTarget} to return the info for. + * + * @param target The {@link InfoTarget} to return the info for. * @return The player information. */ public String getInfo(InfoTarget target) { diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.java b/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.java index 88c83b2..8b311e8 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.java +++ b/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.java @@ -16,7 +16,7 @@ import java.util.concurrent.ConcurrentHashMap; public abstract class TBMCPlayerBase extends ChromaGamerBase { protected UUID uuid; - private String pluginname; + private final String pluginname; protected TBMCPlayerBase() { if (getClass().isAnnotationPresent(PlayerClass.class)) @@ -77,8 +77,7 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase { player.uuid = uuid; return player; } catch (Exception e) { - TBMCCoreAPI.SendException( - "Failed to get player with UUID " + uuid + " and class " + cl.getSimpleName() + "!", e); + TBMCCoreAPI.SendException("Failed to get player with UUID " + uuid + " and class " + cl.getSimpleName() + "!", e, MainPlugin.Instance); return null; } } @@ -86,7 +85,7 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase { /** * Key: UUID-Class */ - static final ConcurrentHashMap playermap = new ConcurrentHashMap<>(); + private static final ConcurrentHashMap playermap = new ConcurrentHashMap<>(); /** * Gets the TBMCPlayer object as a specific plugin player, keeping it's data
@@ -147,7 +146,7 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase { p.close(); } catch (Exception e) { TBMCCoreAPI.SendException("Error while saving player " + p.PlayerName().get() + " (" + p.getFolder() - + "/" + p.getFileName() + ")!", e); + + "/" + p.getFileName() + ")!", e, MainPlugin.Instance); } }); }