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