diff --git a/Chroma-Core/pom.xml b/Chroma-Core/pom.xml index 88a6311..91eaea5 100755 --- a/Chroma-Core/pom.xml +++ b/Chroma-Core/pom.xml @@ -73,6 +73,9 @@ me.lucko:commodore + org.jetbrains.kotlin:kotlin-stdlib + com.github.shynixn.mccoroutine:mccoroutine-bukkit-api + com.github.shynixn.mccoroutine:mccoroutine-bukkit-core @@ -231,6 +234,21 @@ kotlin-stdlib ${kotlin.version} + + org.jetbrains.kotlinx + kotlinx-coroutines-core + 1.6.4 + + + com.github.shynixn.mccoroutine + mccoroutine-bukkit-api + 2.11.0 + + + com.github.shynixn.mccoroutine + mccoroutine-bukkit-core + 2.11.0 + TBMCPlugins diff --git a/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.kt b/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.kt index df93219..6c0b069 100755 --- a/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.kt +++ b/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.kt @@ -11,6 +11,7 @@ import buttondevteam.core.component.towny.TownyComponent import buttondevteam.lib.TBMCCoreAPI import buttondevteam.lib.architecture.ButtonPlugin import buttondevteam.lib.architecture.Component.Companion.registerComponent +import buttondevteam.lib.architecture.ConfigData import buttondevteam.lib.chat.Color import buttondevteam.lib.chat.TBMCChatAPI import buttondevteam.lib.player.ChromaGamerBase @@ -55,13 +56,14 @@ class MainPlugin : ButtonPlugin() { * If a Chroma command clashes with another plugin's command, this setting determines whether the Chroma command should be executed or the other plugin's. */ val prioritizeCustomCommands = iConfig.getData("prioritizeCustomCommands", false) + public override fun pluginEnable() { instance = this val pdf = description setupPermissions() if (!setupEconomy()) //Though Essentials always provides economy, but we don't require Essentials logger.warning("No economy plugin found! Components using economy will not be registered.") - saveConfig() + ConfigData.saveNow(config) // Run pending save tasks registerComponent(this, RestartComponent()) registerComponent(this, ChannelComponent()) registerComponent(this, RandomTPComponent()) @@ -102,7 +104,7 @@ class MainPlugin : ButtonPlugin() { ) .also { Channel.adminChat = it }) TBMCChatAPI.registerChatChannel(Channel( - "§9MOD${ChatColor.WHITE}", + "${ChatColor.BLUE}MOD${ChatColor.WHITE}", Color.Blue, "mod", Channel.inGroupFilter("mod") @@ -118,10 +120,10 @@ class MainPlugin : ButtonPlugin() { ) // TODO: Make groups configurable TBMCChatAPI.registerChatChannel(ChatRoom("${ChatColor.RED}RED${ChatColor.WHITE}", Color.DarkRed, "red")) TBMCChatAPI.registerChatChannel(ChatRoom("${ChatColor.GOLD}ORANGE${ChatColor.WHITE}", Color.Gold, "orange")) - TBMCChatAPI.registerChatChannel(ChatRoom("§eYELLOW${ChatColor.WHITE}", Color.Yellow, "yellow")) - TBMCChatAPI.registerChatChannel(ChatRoom("§aGREEN${ChatColor.WHITE}", Color.Green, "green")) + TBMCChatAPI.registerChatChannel(ChatRoom("${ChatColor.YELLOW}YELLOW${ChatColor.WHITE}", Color.Yellow, "yellow")) + TBMCChatAPI.registerChatChannel(ChatRoom("${ChatColor.GREEN}GREEN${ChatColor.WHITE}", Color.Green, "green")) TBMCChatAPI.registerChatChannel(ChatRoom("${ChatColor.AQUA}BLUE${ChatColor.WHITE}", Color.Blue, "blue")) - TBMCChatAPI.registerChatChannel(ChatRoom("§5PURPLE${ChatColor.WHITE}", Color.DarkPurple, "purple")) + TBMCChatAPI.registerChatChannel(ChatRoom("${ChatColor.LIGHT_PURPLE}PURPLE${ChatColor.WHITE}", Color.DarkPurple, "purple")) val playerSupplier = Supplier { Bukkit.getOnlinePlayers().map { obj -> obj.name }.asIterable() } command2MC.addParamConverter( OfflinePlayer::class.java, @@ -173,5 +175,7 @@ class MainPlugin : ButtonPlugin() { @JvmField var ess: Essentials? = null + + val isInitialized get() = ::instance.isInitialized } } \ No newline at end of file diff --git a/Chroma-Core/src/main/java/buttondevteam/core/component/randomtp/RandomTP.java b/Chroma-Core/src/main/java/buttondevteam/core/component/randomtp/RandomTP.java index edcd273..eae1d60 100644 --- a/Chroma-Core/src/main/java/buttondevteam/core/component/randomtp/RandomTP.java +++ b/Chroma-Core/src/main/java/buttondevteam/core/component/randomtp/RandomTP.java @@ -92,8 +92,8 @@ public class RandomTP extends ICommand2MC && !newLocation()) { //if unable to find new location, message player and return false - player.sendMessage("${ChatColor.RED} could not find a location in 10,000 attempts"); - player.sendMessage("${ChatColor.RED} (sorry bud... I did try!)"); + player.sendMessage("§ccould not find a location in 10,000 attempts"); + player.sendMessage("§c (sorry bud... I did try!)"); return false; } diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/TBMCCoreAPI.kt b/Chroma-Core/src/main/java/buttondevteam/lib/TBMCCoreAPI.kt index b9a3930..b45d5ff 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/TBMCCoreAPI.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/TBMCCoreAPI.kt @@ -1,176 +1,176 @@ -package buttondevteam.lib; +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.entity.Player; -import org.bukkit.event.Listener; -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.java.JavaPlugin; +import buttondevteam.core.MainPlugin +import buttondevteam.lib.architecture.Component +import buttondevteam.lib.player.ChromaGamerBase +import buttondevteam.lib.player.ChromaGamerBase.Companion.registerPluginUserClass +import buttondevteam.lib.potato.DebugPotato +import org.bukkit.Bukkit +import org.bukkit.ChatColor +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.net.URL +import java.util.* +import java.util.function.Consumer +import java.util.function.Supplier -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.net.URLConnection; -import java.util.*; -import java.util.Map.Entry; -import java.util.function.Consumer; -import java.util.function.Supplier; +object TBMCCoreAPI { + val coders: List = listOf("Alisolarflare", "NorbiPeti", "iie", "thewindmillman", "mayskam1995") -public class TBMCCoreAPI { - static final List coders = new ArrayList() { - private static final long serialVersionUID = -4462159250738367334L; + @JvmStatic + @Throws(IOException::class) + fun DownloadString(urlstr: String?): String { + val url = URL(urlstr) + val con = url.openConnection() + con.setRequestProperty("User-Agent", "TBMCPlugins") + val `in` = con.getInputStream() + var encoding = con.contentEncoding + encoding = encoding ?: "UTF-8" + val s = Scanner(`in`).useDelimiter("\\A") + val body = if (s.hasNext()) s.next() else "" + `in`.close() + return body + } - { - add("Alisolarflare"); - add("NorbiPeti"); - add("iie"); - add("thewindmillman"); - add("mayskam1995"); - } - }; + private val exceptionsToSend = HashMap() + private val debugMessagesToSend: MutableList = ArrayList() - public static String DownloadString(String urlstr) throws IOException { - URL url = new URL(urlstr); - URLConnection con = url.openConnection(); - con.setRequestProperty("User-Agent", "TBMCPlugins"); - InputStream in = con.getInputStream(); - String encoding = con.getContentEncoding(); - encoding = encoding == null ? "UTF-8" : encoding; - Scanner s = new Scanner(in).useDelimiter("\\A"); - String body = s.hasNext() ? s.next() : ""; - in.close(); - return body; - } + /** + * Send exception to the [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 + */ + @JvmStatic + fun SendException(sourcemsg: String, e: Throwable, component: Component<*>) { + SendException(sourcemsg, e, false) { message: String? -> component.logWarn(message!!) } + } - private static final HashMap exceptionsToSend = new HashMap<>(); - private static final List debugMessagesToSend = new ArrayList<>(); + /** + * Send exception to the [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 + */ + @JvmStatic + fun SendException(sourcemsg: String, e: Throwable, plugin: JavaPlugin) { + SendException(sourcemsg, e, false) { msg: String? -> plugin.logger.warning(msg) } + } - /** - * 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, Component component) { - SendException(sourcemsg, e, false, component::logWarn); - } + @JvmStatic + fun SendException(sourcemsg: String, e: Throwable, debugPotato: Boolean, logWarn: Consumer) { + try { + SendUnsentExceptions() + val event = TBMCExceptionEvent(sourcemsg, e) + Bukkit.getPluginManager().callEvent(event) + synchronized(exceptionsToSend) { if (!event.isHandled) exceptionsToSend[sourcemsg] = e } + logWarn.accept(sourcemsg) + e.printStackTrace() + if (debugPotato) { + val devsOnline: MutableList = ArrayList() + for (player in Bukkit.getOnlinePlayers()) { + if (coders.contains(player.name)) { + devsOnline.add(player) + } + } + if (devsOnline.isNotEmpty()) { + val potato = DebugPotato() + .setMessage( + arrayOf( // + "${ChatColor.AQUA}${ChatColor.ITALIC}" + e.javaClass.simpleName, // + "${ChatColor.RED}${ChatColor.ITALIC}$sourcemsg", // + "${ChatColor.GREEN}${ChatColor.ITALIC}Find a dev to fix this issue" + ) + ) + .setType( + when (e) { + is IOException -> "Throwable Potato" + is ClassCastException -> "Squished Potato" + is NullPointerException -> "Plain Potato" + is StackOverflowError -> "Chips" + else -> "Error Potato" + } + ) + for (dev in devsOnline) { + potato.Send(dev) + } + } + } + } catch (ee: Exception) { + System.err.println("Failed to send exception!") + ee.printStackTrace() + } + } - /** - * 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); - } + @JvmStatic + fun sendDebugMessage(debugMessage: String) { + SendUnsentDebugMessages() + val event = TBMCDebugMessageEvent(debugMessage) + Bukkit.getPluginManager().callEvent(event) + synchronized(debugMessagesToSend) { if (!event.isSent) debugMessagesToSend.add(debugMessage) } + } - public static void SendException(String sourcemsg, Throwable e, boolean debugPotato, Consumer logWarn) { - try { - SendUnsentExceptions(); - TBMCExceptionEvent event = new TBMCExceptionEvent(sourcemsg, e); - Bukkit.getPluginManager().callEvent(event); - synchronized (exceptionsToSend) { - if (!event.isHandled()) - exceptionsToSend.put(sourcemsg, e); - } - logWarn.accept(sourcemsg); - e.printStackTrace(); - if (debugPotato) { - List devsOnline = new ArrayList<>(); - for (Player player : Bukkit.getOnlinePlayers()) { - if (coders.contains(player.getName())) { - devsOnline.add(player); - } - } - if (!devsOnline.isEmpty()) { - DebugPotato potato = new DebugPotato() - .setMessage(new String[]{ // - "${ChatColor.AQUA}§o" + e.getClass().getSimpleName(), // - "${ChatColor.RED}§o" + sourcemsg, // - "§a§oFind a dev to fix this issue"}) - .setType(e instanceof IOException ? "Throwable Potato" - : e instanceof ClassCastException ? "Squished Potato" - : e instanceof NullPointerException ? "Plain Potato" - : e instanceof StackOverflowError ? "Chips" : "Error Potato"); - for (Player dev : devsOnline) { - potato.Send(dev); - } - } - } - } catch (Exception ee) { - System.err.println("Failed to send exception!"); - ee.printStackTrace(); - } - } + private var eventExceptionCoreHandler: EventExceptionCoreHandler? = null - public static void sendDebugMessage(String debugMessage) { - SendUnsentDebugMessages(); - TBMCDebugMessageEvent event = new TBMCDebugMessageEvent(debugMessage); - Bukkit.getPluginManager().callEvent(event); - synchronized (debugMessagesToSend) { - if (!event.isSent()) - debugMessagesToSend.add(debugMessage); - } - } + /** + * Registers Bukkit events, handling the exceptions occurring in those events + * + * @param listener The class that handles the events + * @param plugin The plugin which the listener belongs to + */ + @JvmStatic + fun RegisterEventsForExceptions(listener: Listener, plugin: Plugin) { + if (eventExceptionCoreHandler == null) eventExceptionCoreHandler = EventExceptionCoreHandler() + EventExceptionHandler.registerEvents(listener, plugin, eventExceptionCoreHandler) + } - private static EventExceptionCoreHandler eventExceptionCoreHandler; + @JvmStatic + fun RegisterUserClass(userclass: Class, constructor: Supplier) { + registerPluginUserClass(userclass, constructor) + } - /** - * Registers Bukkit events, handling the exceptions occurring in those events - * - * @param listener The class that handles the events - * @param plugin The plugin which the listener belongs to - */ - public static void RegisterEventsForExceptions(Listener listener, Plugin plugin) { - if (eventExceptionCoreHandler == null) eventExceptionCoreHandler = new EventExceptionCoreHandler(); - EventExceptionHandler.registerEvents(listener, plugin, eventExceptionCoreHandler); - } + /** + * Send exceptions that haven't been sent (their events didn't get handled). This method is used by the DiscordPlugin's ready event + */ + @JvmStatic + fun SendUnsentExceptions() { + synchronized(exceptionsToSend) { + if (exceptionsToSend.size > 20) { + exceptionsToSend.clear() // Don't call more and more events if all the handler plugins are unloaded + Bukkit.getLogger().warning("Unhandled exception list is over 20! Clearing!") + } + val iterator: MutableIterator> = exceptionsToSend.entries.iterator() + while (iterator.hasNext()) { + val (key, value) = iterator.next() + val event = TBMCExceptionEvent(key, value) + Bukkit.getPluginManager().callEvent(event) + if (event.isHandled) iterator.remove() + } + } + } - public static void RegisterUserClass(Class userclass, Supplier constructor) { - ChromaGamerBase.registerPluginUserClass(userclass, constructor); - } + @JvmStatic + fun SendUnsentDebugMessages() { + synchronized(debugMessagesToSend) { + if (debugMessagesToSend.size > 20) { + debugMessagesToSend.clear() // Don't call more and more DebugMessages if all the handler plugins are unloaded + Bukkit.getLogger().warning("Unhandled Debug Message list is over 20! Clearing!") + } + val iterator = debugMessagesToSend.iterator() + while (iterator.hasNext()) { + val message = iterator.next() + val event = TBMCDebugMessageEvent(message) + Bukkit.getPluginManager().callEvent(event) + if (event.isSent) iterator.remove() + } + } + } - /** - * Send exceptions that haven't been sent (their events didn't get handled). This method is used by the DiscordPlugin's ready event - */ - public static void SendUnsentExceptions() { - synchronized (exceptionsToSend) { - if (exceptionsToSend.size() > 20) { - exceptionsToSend.clear(); // Don't call more and more events if all the handler plugins are unloaded - Bukkit.getLogger().warning("Unhandled exception list is over 20! Clearing!"); - } - for (Iterator> iterator = exceptionsToSend.entrySet().iterator(); iterator.hasNext(); ) { - Entry entry = iterator.next(); - TBMCExceptionEvent event = new TBMCExceptionEvent(entry.getKey(), entry.getValue()); - Bukkit.getPluginManager().callEvent(event); - if (event.isHandled()) - iterator.remove(); - } - } - } - - public static void SendUnsentDebugMessages() { - synchronized (debugMessagesToSend) { - if (debugMessagesToSend.size() > 20) { - debugMessagesToSend.clear(); // Don't call more and more DebugMessages if all the handler plugins are unloaded - Bukkit.getLogger().warning("Unhandled Debug Message list is over 20! Clearing!"); - } - for (Iterator iterator = debugMessagesToSend.iterator(); iterator.hasNext(); ) { - String message = iterator.next(); - TBMCDebugMessageEvent event = new TBMCDebugMessageEvent(message); - Bukkit.getPluginManager().callEvent(event); - if (event.isSent()) - iterator.remove(); - } - } - } - - public static boolean IsTestServer() { - if (MainPlugin.instance == null) return true; - return MainPlugin.instance.test.get(); - } + @JvmStatic + fun IsTestServer(): Boolean { + return MainPlugin.instance.test.get() + } } \ No newline at end of file diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ConfigData.kt b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ConfigData.kt index 95c428b..6024f15 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ConfigData.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ConfigData.kt @@ -76,7 +76,10 @@ class ConfigData internal constructor( signalChange(config) } - private class SaveTask(val task: BukkitTask, val saveAction: Runnable) + /** + * @param task The running task, if it was scheduled + */ + private class SaveTask(val task: BukkitTask?, val saveAction: Runnable) companion object { private val saveTasks = HashMap() @@ -85,10 +88,19 @@ class ConfigData internal constructor( val sa = config.saveAction val root = cc.root if (root == null) { - MainPlugin.instance.logger.warning("Attempted to save config with no root! Name: ${config.config.name}") + if (MainPlugin.isInitialized) { + MainPlugin.instance.logger.warning("Attempted to save config with no root! Name: ${config.config.name}") + } else { + println("Attempted to save config with no root! Name: ${config.config.name}") + } return } - if (!saveTasks.containsKey(cc.root)) { + if (!MainPlugin.isInitialized) { + // If the plugin isn't initilized, we can't schedule a task - do it when the plugin is enabled + synchronized(saveTasks) { + saveTasks.put(root, SaveTask(null, sa)) + } + } else if (!saveTasks.containsKey(cc.root)) { synchronized(saveTasks) { saveTasks.put( root, @@ -108,7 +120,7 @@ class ConfigData internal constructor( synchronized(saveTasks) { val st = saveTasks[config] if (st != null) { - st.task.cancel() + st.task?.cancel() saveTasks.remove(config) st.saveAction.run() return true diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MC.kt b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MC.kt index 499d96a..76d5f03 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MC.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MC.kt @@ -176,10 +176,11 @@ class Command2MC : Command2('/', true), Listener TabcompleteHelper.registerTabcomplete(command, node, bukkitCommand) bukkitCommand } catch (e: Exception) { - if (command.component == null) + val component = command.component + if (component == null) TBMCCoreAPI.SendException("Failed to register command in command map!", e, command.plugin) else - TBMCCoreAPI.SendException("Failed to register command in command map!", e, command.component) + TBMCCoreAPI.SendException("Failed to register command in command map!", e, component) shouldRegisterOfficially = false null } @@ -302,7 +303,9 @@ class Command2MC : Command2('/', true), Listener if (converter == null) { val msg = "Could not find a suitable converter for type " + cl.simpleName val exception: Exception = NullPointerException("converter is null") - if (command2MC.component == null) TBMCCoreAPI.SendException(msg, exception, command2MC.plugin) else TBMCCoreAPI.SendException(msg, exception, command2MC.component) + val component = command2MC.component + if (component == null) TBMCCoreAPI.SendException(msg, exception, command2MC.plugin) + else TBMCCoreAPI.SendException(msg, exception, component) return null } return converter