From 42fd0dfeacae8bc03815d385ef9813689544183c Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Mon, 17 Apr 2023 03:11:36 +0200 Subject: [PATCH] Player, config and player data improvements --- .../java/buttondevteam/core/MainPlugin.kt | 12 +- .../java/buttondevteam/core/PlayerListener.kt | 2 +- .../component/restart/RestartComponent.kt | 159 ++++++++------- .../java/buttondevteam/lib/TBMCChatEvent.java | 22 +-- .../buttondevteam/lib/TBMCSystemChatEvent.kt | 109 +++++----- .../lib/architecture/ConfigData.kt | 8 +- .../lib/architecture/IHaveConfig.kt | 94 +-------- .../lib/architecture/ListConfigData.kt | 4 - .../lib/architecture/config/IConfigData.kt | 1 - .../buttondevteam/lib/chat/ChatMessage.kt | 123 +++++++----- .../lib/chat/Command2MCSender.kt | 37 ++-- .../buttondevteam/lib/chat/TBMCChatAPI.kt | 186 +++++++++--------- .../commands/CommandArgumentHelpManager.kt | 30 +-- .../lib/player/ChromaGamerBase.kt | 51 +++-- .../lib/player/TBMCPlayerBase.kt | 8 +- 15 files changed, 383 insertions(+), 463 deletions(-) diff --git a/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.kt b/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.kt index 3acb223..4cd26b3 100755 --- a/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.kt +++ b/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.kt @@ -80,14 +80,14 @@ class MainPlugin : ButtonPlugin() { ChromaGamerBase.addConverter { commandSender: CommandSender -> Optional.ofNullable( if (commandSender is ConsoleCommandSender || commandSender is BlockCommandSender) - TBMCPlayer.getPlayer(UUID(0, 0), TBMCPlayer::class.java) + TBMCPlayerBase.getPlayer(UUID(0, 0), TBMCPlayer::class.java) else null ) } //Players, has higher priority ChromaGamerBase.addConverter { sender: CommandSender -> Optional.ofNullable( - if (sender is Player) TBMCPlayer.getPlayer(sender.uniqueId, TBMCPlayer::class.java) else null + if (sender is Player) TBMCPlayerBase.getPlayer(sender.uniqueId, TBMCPlayer::class.java) else null ) } TBMCCoreAPI.RegisterUserClass(TBMCPlayerBase::class.java) { TBMCPlayer() } @@ -114,7 +114,7 @@ class MainPlugin : ButtonPlugin() { val playerSupplier = Supplier { Bukkit.getOnlinePlayers().map { obj -> obj.name }.asIterable() } command2MC.addParamConverter( OfflinePlayer::class.java, - { name -> Bukkit.getOfflinePlayer(name) }, + { name -> @Suppress("DEPRECATION") Bukkit.getOfflinePlayer(name) }, "Player not found!", playerSupplier ) @@ -125,13 +125,13 @@ class MainPlugin : ButtonPlugin() { playerSupplier ) if (server.pluginManager.isPluginEnabled("Essentials")) ess = getPlugin(Essentials::class.java) - logger!!.info(pdf.name + " has been Enabled (V." + pdf.version + ") Test: " + test.get() + ".") + logger.info(pdf.name + " has been Enabled (V." + pdf.version + ") Test: " + test.get() + ".") } public override fun pluginDisable() { - logger!!.info("Saving player data...") + logger.info("Saving player data...") ChromaGamerBase.saveUsers() - logger!!.info("Player data saved.") + logger.info("Player data saved.") } private fun setupPermissions(): Boolean { diff --git a/Chroma-Core/src/main/java/buttondevteam/core/PlayerListener.kt b/Chroma-Core/src/main/java/buttondevteam/core/PlayerListener.kt index b27ca5b..9717ebe 100755 --- a/Chroma-Core/src/main/java/buttondevteam/core/PlayerListener.kt +++ b/Chroma-Core/src/main/java/buttondevteam/core/PlayerListener.kt @@ -87,7 +87,7 @@ class PlayerListener(val plugin: MainPlugin) : Listener { @EventHandler(priority = EventPriority.HIGH) //The one in the chat plugin is set to highest fun onPlayerChat(event: AsyncPlayerChatEvent) { if (event.isCancelled) return //The chat plugin should cancel it after this handler - val cp = TBMCPlayer.getPlayer(event.player.uniqueId, TBMCPlayer::class.java) + val cp = TBMCPlayerBase.getPlayer(event.player.uniqueId, TBMCPlayer::class.java) TBMCChatAPI.SendChatMessage(ChatMessage.builder(event.player, cp, event.message).build()) //Not cancelling the original event here, it's cancelled in the chat plugin //This way other plugins can deal with the MC formatting if the chat plugin isn't present, but other platforms still get the message diff --git a/Chroma-Core/src/main/java/buttondevteam/core/component/restart/RestartComponent.kt b/Chroma-Core/src/main/java/buttondevteam/core/component/restart/RestartComponent.kt index 817c4c1..2235c0b 100644 --- a/Chroma-Core/src/main/java/buttondevteam/core/component/restart/RestartComponent.kt +++ b/Chroma-Core/src/main/java/buttondevteam/core/component/restart/RestartComponent.kt @@ -1,86 +1,95 @@ -package buttondevteam.core.component.restart; +package buttondevteam.core.component.restart -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; -import lombok.Getter; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerQuitEvent; - -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; +import buttondevteam.core.MainPlugin +import buttondevteam.core.component.channel.Channel +import buttondevteam.lib.TBMCSystemChatEvent.BroadcastTarget +import buttondevteam.lib.TBMCSystemChatEvent.BroadcastTarget.Companion.add +import buttondevteam.lib.TBMCSystemChatEvent.BroadcastTarget.Companion.remove +import buttondevteam.lib.architecture.Component +import buttondevteam.lib.architecture.ComponentMetadata +import buttondevteam.lib.chat.IFakePlayer +import buttondevteam.lib.chat.TBMCChatAPI +import lombok.Getter +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.player.PlayerQuitEvent +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). * Also can automatically restart at a given time. */ @ComponentMetadata(enabledByDefault = false) -public class RestartComponent extends Component implements Listener { - @Override - public void enable() { - var scheduledRestartCommand = new ScheduledRestartCommand(this); - registerCommand(scheduledRestartCommand); - registerCommand(new PrimeRestartCommand(this)); - registerListener(this); - restartBroadcast = TBMCSystemChatEvent.BroadcastTarget.add("restartCountdown"); +class RestartComponent : Component(), Listener { + public override fun enable() { + val scheduledRestartCommand = ScheduledRestartCommand(this) + registerCommand(scheduledRestartCommand) + registerCommand(PrimeRestartCommand(this)) + registerListener(this) + restartBroadcast = add("restartCountdown") + val restartAt = restartAt.get() + if (restartAt < 0) return + val restart = syncStart(restartAt) + log("Scheduled restart " + restart / 3600.0 / 20.0 + " hours from now") + Bukkit.getScheduler().runTaskLater( + plugin, + Runnable { scheduledRestartCommand.def(Bukkit.getConsoleSender(), 0) }, + restart.toLong() + ) + } - int restartAt = this.restartAt.get(); - if (restartAt < 0) return; - int restart = syncStart(restartAt); - log("Scheduled restart " + (restart / 3600. / 20.) + " hours from now"); - Bukkit.getScheduler().runTaskLater(getPlugin(), () -> scheduledRestartCommand.def(Bukkit.getConsoleSender(), 0), restart); - } + public override fun disable() { + remove(restartBroadcast) + } - @Override - public void disable() { - TBMCSystemChatEvent.BroadcastTarget.remove(restartBroadcast); - } + /** + * Specifies the hour of day when the server should be restarted. Set to -1 to disable. + */ + private val restartAt = config.getData("restartAt", 12) + private var lasttime: Long = 0 - /** - * Specifies the hour of day when the server should be restarted. Set to -1 to disable. - */ - private final ConfigData restartAt = getConfig().getData("restartAt", 12); + @Getter + private var restartBroadcast: BroadcastTarget? = null + private fun syncStart(hour: Int): Int { + val now = ZonedDateTime.now(ZoneId.ofOffset("", ZoneOffset.UTC)) + val secs = now.hour * 3600 + now.minute * 60 + now.second + var diff = secs - hour * 3600 + if (diff < 0) { + diff += 24 * 3600 + } + val count = diff / (24 * 3600) + val intervalPart = diff - count * 24 * 3600 + val remaining = 24 * 3600 - intervalPart + return remaining * 20 + } - private long lasttime = 0; - @Getter - private TBMCSystemChatEvent.BroadcastTarget restartBroadcast; - - private int syncStart(int hour) { - var now = ZonedDateTime.now(ZoneId.ofOffset("", ZoneOffset.UTC)); - int secs = now.getHour() * 3600 + now.getMinute() * 60 + now.getSecond(); - int diff = secs - hour * 3600; - if (diff < 0) { - diff += 24 * 3600; - } - int count = diff / (24 * 3600); - int intervalPart = diff - count * 24 * 3600; - int remaining = 24 * 3600 - intervalPart; - return remaining * 20; - } - - @EventHandler - public void onPlayerLeave(PlayerQuitEvent event) { - if (PrimeRestartCommand.isPlsrestart() - && !event.getQuitMessage().equalsIgnoreCase("Server closed") - && !event.getQuitMessage().equalsIgnoreCase("Server is restarting")) { - if (Bukkit.getOnlinePlayers().size() <= 1) { - if (PrimeRestartCommand.isLoud()) - TBMCChatAPI.SendSystemMessage(Channel.globalChat, Channel.RecipientTestResult.ALL, "§cNobody is online anymore. Restarting.", restartBroadcast); - Bukkit.spigot().restart(); - } else if (!(event.getPlayer() instanceof IFakePlayer) && System.nanoTime() - 10 * 60 * 1000000000L - lasttime > 0) { //10 minutes passed since last reminder - lasttime = System.nanoTime(); - if (PrimeRestartCommand.isLoud()) - TBMCChatAPI.SendSystemMessage(Channel.globalChat, Channel.RecipientTestResult.ALL, ChatColor.DARK_RED + "The server will restart as soon as nobody is online.", restartBroadcast); - } - } - } -} + @EventHandler + fun onPlayerLeave(event: PlayerQuitEvent) { + if (PrimeRestartCommand.isPlsrestart() + && !event.quitMessage.equals("Server closed", ignoreCase = true) + && !event.quitMessage.equals("Server is restarting", ignoreCase = true) + ) { + if (Bukkit.getOnlinePlayers().size <= 1) { + if (PrimeRestartCommand.isLoud()) TBMCChatAPI.SendSystemMessage( + Channel.globalChat, + Channel.RecipientTestResult.ALL, + "§cNobody is online anymore. Restarting.", + restartBroadcast + ) + Bukkit.spigot().restart() + } else if (event.player !is IFakePlayer && System.nanoTime() - 10 * 60 * 1000000000L - lasttime > 0) { //10 minutes passed since last reminder + lasttime = System.nanoTime() + if (PrimeRestartCommand.isLoud()) TBMCChatAPI.SendSystemMessage( + Channel.globalChat, + Channel.RecipientTestResult.ALL, + ChatColor.DARK_RED.toString() + "The server will restart as soon as nobody is online.", + restartBroadcast + ) + } + } + } +} \ No newline at end of file diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/TBMCChatEvent.java b/Chroma-Core/src/main/java/buttondevteam/lib/TBMCChatEvent.java index 4476442..ab27275 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/TBMCChatEvent.java +++ b/Chroma-Core/src/main/java/buttondevteam/lib/TBMCChatEvent.java @@ -18,7 +18,7 @@ import javax.annotation.Nullable; @Getter public class TBMCChatEvent extends TBMCChatEventBase { public TBMCChatEvent(Channel channel, ChatMessage cm, Channel.RecipientTestResult rtr) { - super(channel, cm.getMessage(), rtr.score, rtr.groupID); + super(channel, cm.message, rtr.score, rtr.groupID); this.cm = cm; } @@ -28,7 +28,7 @@ public class TBMCChatEvent extends TBMCChatEventBase { private ChatMessage cm; private boolean isIgnoreSenderPermissions() { - return cm.getPermCheck() != cm.getSender(); + return cm.getPermCheck() != cm.sender; } /** @@ -36,9 +36,9 @@ public class TBMCChatEvent extends TBMCChatEventBase { */ @Override public boolean shouldSendTo(CommandSender sender) { - if (isIgnoreSenderPermissions() && sender.equals(this.cm.getSender())) - return true; //Allow sending the message no matter what - return super.shouldSendTo(sender); + if (isIgnoreSenderPermissions() && sender.equals(this.cm.sender)) + return true; //Allow sending the message no matter what + return super.shouldSendTo(sender); } /** @@ -46,9 +46,9 @@ public class TBMCChatEvent extends TBMCChatEventBase { */ @Override public int getMCScore(CommandSender sender) { - if (isIgnoreSenderPermissions() && sender.equals(this.cm.getSender())) - return getScore(); //Send in the correct group no matter what - return super.getMCScore(sender); + if (isIgnoreSenderPermissions() && sender.equals(this.cm.sender)) + return getScore(); //Send in the correct group no matter what + return super.getMCScore(sender); } /** @@ -57,9 +57,9 @@ public class TBMCChatEvent extends TBMCChatEventBase { @Nullable @Override public String getGroupID(CommandSender sender) { - if (isIgnoreSenderPermissions() && sender.equals(this.cm.getSender())) - return getGroupID(); //Send in the correct group no matter what - return super.getGroupID(sender); + if (isIgnoreSenderPermissions() && sender.equals(this.cm.sender)) + return getGroupID(); //Send in the correct group no matter what + return super.getGroupID(sender); } @Override diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/TBMCSystemChatEvent.kt b/Chroma-Core/src/main/java/buttondevteam/lib/TBMCSystemChatEvent.kt index f5d5a0f..13afa8a 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/TBMCSystemChatEvent.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/TBMCSystemChatEvent.kt @@ -1,74 +1,59 @@ -package buttondevteam.lib; +package buttondevteam.lib -import buttondevteam.core.component.channel.Channel; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import lombok.val; -import org.bukkit.command.CommandSender; -import org.bukkit.event.HandlerList; - -import javax.annotation.Nullable; -import java.util.HashSet; -import java.util.Objects; -import java.util.stream.Stream; +import buttondevteam.core.component.channel.Channel +import org.bukkit.event.HandlerList +import java.util.* +import java.util.stream.Stream /** - * Make sure to only send the message to users who {@link #shouldSendTo(CommandSender)} returns true. - * - * @author NorbiPeti + * Make sure to only send the message to users who [.shouldSendTo] returns true. * - */ -@Getter -public class TBMCSystemChatEvent extends TBMCChatEventBase { - private final String[] exceptions; - private final BroadcastTarget target; - private boolean handled; + * @author NorbiPeti + */ // TODO: Rich message +class TBMCSystemChatEvent( + channel: Channel, + message: String, + score: Int, + groupid: String, + val exceptions: Array, + val target: BroadcastTarget +) : TBMCChatEventBase(channel, message, score, groupid) { + var isHandled = false - public void setHandled() { - handled = true; - } + override fun getHandlers(): HandlerList { + return handlerList + } - public TBMCSystemChatEvent(Channel channel, String message, int score, String groupid, String[] exceptions, BroadcastTarget target) { // TODO: Rich message - super(channel, message, score, groupid); - this.exceptions = exceptions; - this.target = target; - } + class BroadcastTarget private constructor(val name: String) { - private static final HandlerList handlers = new HandlerList(); + companion object { + private val targets = HashSet() + val ALL = BroadcastTarget("ALL") - @Override - public HandlerList getHandlers() { - return handlers; - } + @JvmStatic + fun add(name: String): BroadcastTarget { + val bt = BroadcastTarget(Objects.requireNonNull(name)) + targets.add(bt) + return bt + } - public static HandlerList getHandlerList() { - return handlers; - } + @JvmStatic + fun remove(target: BroadcastTarget?) { + targets.remove(target) + } - @RequiredArgsConstructor(access = AccessLevel.PRIVATE) - public static class BroadcastTarget { - private final @Getter String name; - private static final HashSet targets = new HashSet<>(); - public static final BroadcastTarget ALL = new BroadcastTarget("ALL"); + operator fun get(name: String?): BroadcastTarget? { + return targets.stream().filter { bt: BroadcastTarget? -> bt!!.name.equals(name, ignoreCase = true) } + .findAny().orElse(null) + } - public static BroadcastTarget add(String name) { - val bt = new BroadcastTarget(Objects.requireNonNull(name)); - targets.add(bt); - return bt; - } + fun stream(): Stream { + return targets.stream() + } + } + } - public static void remove(BroadcastTarget target) { - targets.remove(target); - } - - @Nullable - public static BroadcastTarget get(String name) { - return targets.stream().filter(bt -> bt.name.equalsIgnoreCase(name)).findAny().orElse(null); - } - - public static Stream stream() { - return targets.stream(); - } - } -} + companion object { + val handlerList = HandlerList() + } +} \ 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 d9d871f..95c428b 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ConfigData.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ConfigData.kt @@ -10,7 +10,7 @@ import java.util.function.Function /** * Use the getter/setter constructor if [T] isn't a primitive type or String.

- * Use [Component.getConfig] or [ButtonPlugin.getIConfig] then [IHaveConfig.getData] to get an instance. + * Use [Component.config] or [ButtonPlugin.iConfig] then [IHaveConfig.getData] to get an instance. * @param config May be null for testing * @param getter The parameter is of a primitive type as returned by [Configuration.get] * @param setter The result should be a primitive type or string that can be retrieved correctly later @@ -40,10 +40,6 @@ class ConfigData internal constructor( return "ConfigData{path='$path', value=$value}" } - override fun reset() { - value = null - } - override fun get(): T { val cachedValue = value if (cachedValue != null) return cachedValue //Speed things up @@ -96,7 +92,7 @@ class ConfigData internal constructor( synchronized(saveTasks) { saveTasks.put( root, - SaveTask(Bukkit.getScheduler().runTaskLaterAsynchronously(MainPlugin.instance, { + SaveTask(Bukkit.getScheduler().runTaskLaterAsynchronously(MainPlugin.instance, Runnable { synchronized(saveTasks) { saveTasks.remove(root) sa.run() diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/IHaveConfig.kt b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/IHaveConfig.kt index eaa767d..1be751e 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/IHaveConfig.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/IHaveConfig.kt @@ -1,16 +1,9 @@ package buttondevteam.lib.architecture -import buttondevteam.core.MainPlugin -import buttondevteam.lib.TBMCCoreAPI import buttondevteam.lib.architecture.config.IConfigData -import org.bukkit.Bukkit import org.bukkit.configuration.ConfigurationSection -import org.bukkit.plugin.java.JavaPlugin -import java.lang.reflect.InvocationTargetException import java.util.* import java.util.function.Function -import java.util.function.Predicate -import java.util.stream.Collectors /** * A config system @@ -111,14 +104,6 @@ class IHaveConfig( ConfigData.signalChange(this) } - /** - * Clears all caches and loads everything from yaml. - */ - fun reset(config: ConfigurationSection?) { // TODO: Simply replace the object - this.config = config - datamap.forEach { (_, data) -> data.reset() } - } - companion object { /** * Generates the config YAML. @@ -127,84 +112,7 @@ class IHaveConfig( * @param configMap The result from [Component.getConfigMap]. May be null. */ fun pregenConfig(obj: Any, configMap: Map?) { - val ms = obj.javaClass.declaredMethods - for (m in ms) { - if (m.returnType.name != ConfigData::class.java.name) continue - val mName: String - run { - val name = m.name - val ind = name.lastIndexOf('$') - mName = if (ind == -1) name else name.substring(ind + 1) - } - try { - m.isAccessible = true - var configList: List> - configList = if (m.parameterCount == 0) { - listOf(m.invoke(obj) as ConfigData<*>) - } else if (m.parameterCount == 1 && m.parameterTypes[0] == IHaveConfig::class.java) { - if (configMap == null) continue //Hope it will get called with the param later - configMap.entries.stream().map { (key, value): Map.Entry -> - try { - return@map m.invoke(obj, value) as ConfigData<*> - } catch (e: IllegalAccessException) { - val msg = "Failed to pregenerate $mName for $obj using config $key!" - if (obj is Component<*>) TBMCCoreAPI.SendException( - msg, - e, - obj - ) else if (obj is JavaPlugin) TBMCCoreAPI.SendException( - msg, - e, - obj - ) else TBMCCoreAPI.SendException(msg, e, false) { msg: String? -> - Bukkit.getLogger().warning(msg) - } - return@map null - } catch (e: InvocationTargetException) { - val msg = "Failed to pregenerate $mName for $obj using config $key!" - if (obj is Component<*>) TBMCCoreAPI.SendException( - msg, - e, - obj - ) else if (obj is JavaPlugin) TBMCCoreAPI.SendException( - msg, - e, - obj - ) else TBMCCoreAPI.SendException(msg, e, false) { msg: String? -> - Bukkit.getLogger().warning(msg) - } - return@map null - } - } - .filter(Predicate> { obj: ConfigData? -> Objects.nonNull(obj) }) - .collect(Collectors.toList()) - } else { - if (TBMCCoreAPI.IsTestServer()) MainPlugin.instance.logger.warning( - "Method " + mName + " returns a config but its parameters are unknown: " + Arrays.toString( - m.parameterTypes - ) - ) - continue - } - for (c in configList) { - if (c.path.length == 0) c.setPath(mName) else if (c.path != mName) MainPlugin.instance.logger.warning( - "Config name does not match: " + c.path + " instead of " + mName - ) - c.get() //Saves the default value if needed - also checks validity - } - } catch (e: Exception) { - val msg = "Failed to pregenerate $mName for $obj!" - if (obj is Component<*>) TBMCCoreAPI.SendException( - msg, - e, - obj - ) else if (obj is JavaPlugin) TBMCCoreAPI.SendException(msg, e, obj) else TBMCCoreAPI.SendException( - msg, - e, - false - ) { msg: String? -> Bukkit.getLogger().warning(msg) } - } - } + // TODO: The configs are generated by ConfigData on creation } } } \ No newline at end of file diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ListConfigData.kt b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ListConfigData.kt index e17e009..785eee4 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ListConfigData.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ListConfigData.kt @@ -19,10 +19,6 @@ class ListConfigData internal constructor( override val path: String get() = listConfig.path - override fun reset() { - listConfig.reset() - } - override fun get(): List { return listConfig.get() } diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/config/IConfigData.kt b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/config/IConfigData.kt index 0f48e48..9b2ba6b 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/config/IConfigData.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/config/IConfigData.kt @@ -1,7 +1,6 @@ package buttondevteam.lib.architecture.config interface IConfigData { - fun reset() fun get(): T? fun set(value: T?) diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/ChatMessage.kt b/Chroma-Core/src/main/java/buttondevteam/lib/chat/ChatMessage.kt index 8496cbc..22b9159 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/ChatMessage.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/ChatMessage.kt @@ -1,57 +1,76 @@ -package buttondevteam.lib.chat; +package buttondevteam.lib.chat -import buttondevteam.lib.player.ChromaGamerBase; -import lombok.Builder; -import lombok.Getter; -import lombok.NonNull; -import lombok.Setter; -import org.bukkit.command.CommandSender; +import buttondevteam.lib.player.ChromaGamerBase +import org.bukkit.command.CommandSender +import java.util.* -@Builder -@Getter -public class ChatMessage { - /** - * The sender which sends the message. - */ - private final CommandSender sender; - /** - * The Chroma user which sends the message. - */ - private final ChromaGamerBase user; - /** - * The message to send as the user. - */ - @Setter - private String message; - /** - * Indicates whether the message comes from running a command (like /tableflip). Implemented to be used from Discord. - */ - private boolean fromCommand; - /** - * The sender which we should check for permissions. Same as {@link #sender} by default. - */ - private CommandSender permCheck; - /** - * The origin of the message, "Minecraft" or "Discord" for example. May be displayed to the user.
- * This is the user class capitalized folder name. - */ - private final String origin; +class ChatMessage internal constructor( + /** + * The sender which sends the message. + */ + val sender: CommandSender, + /** + * The Chroma user which sends the message. + */ + val user: ChromaGamerBase, + /** + * The message to send as the user. + */ + var message: String, + /** + * Indicates whether the message comes from running a command (like /tableflip). Implemented to be used from Discord. + */ + val isFromCommand: Boolean, + /** + * The sender which we should check for permissions. Same as [.sender] by default. + */ + val permCheck: CommandSender, + /** + * The origin of the message, "Minecraft" or "Discord" for example. May be displayed to the user.

+ * **This is the user class capitalized folder name by default.** + */ + val origin: String +) { - /** - * The sender which we should check for permissions. Same as {@link #sender} by default. - * - * @return The perm check or the sender - */ - public CommandSender getPermCheck() { - return permCheck == null ? sender : permCheck; - } + class ChatMessageBuilder internal constructor( + private var sender: CommandSender, + private var user: ChromaGamerBase, + private var message: String, + private var origin: String + ) { + private var fromCommand = false + private var permCheck: CommandSender? = null - private static ChatMessageBuilder builder() { - return new ChatMessageBuilder(); - } + fun fromCommand(fromCommand: Boolean): ChatMessageBuilder { + this.fromCommand = fromCommand + return this + } - @NonNull - public static ChatMessageBuilder builder(CommandSender sender, ChromaGamerBase user, String message) { - return builder().sender(sender).user(user).message(message).origin(user.getFolder().substring(0, 1).toUpperCase() + user.getFolder().substring(1)); - } -} + fun permCheck(permCheck: CommandSender): ChatMessageBuilder { + this.permCheck = permCheck + return this + } + + fun origin(origin: String): ChatMessageBuilder { + this.origin = origin + return this + } + + fun build(): ChatMessage { + return ChatMessage(sender, user, message, fromCommand, permCheck ?: sender, origin) + } + + override fun toString(): String { + return "ChatMessage.ChatMessageBuilder(sender=$sender, user=$user, message=$message, fromCommand=$fromCommand, permCheck=$permCheck, origin=$origin)" + } + } + + companion object { + fun builder(sender: CommandSender, user: ChromaGamerBase, message: String): ChatMessageBuilder { + return ChatMessageBuilder( + sender, user, message, + user.folder.substring(0, 1).uppercase(Locale.getDefault()) + user.folder.substring(1) + ) + } + } +} \ No newline at end of file diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MCSender.kt b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MCSender.kt index 647dd38..b77614a 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MCSender.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MCSender.kt @@ -1,28 +1,19 @@ -package buttondevteam.lib.chat; +package buttondevteam.lib.chat -import buttondevteam.core.component.channel.Channel; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.bukkit.command.CommandSender; +import buttondevteam.core.component.channel.Channel +import org.bukkit.command.CommandSender -@RequiredArgsConstructor -public class Command2MCSender implements Command2Sender { - private @Getter final CommandSender sender; - private @Getter final Channel channel; - private @Getter final CommandSender permCheck; +class Command2MCSender(val sender: CommandSender, val channel: Channel, val permCheck: CommandSender) : Command2Sender { - @Override - public void sendMessage(String message) { - sender.sendMessage(message); - } + override fun sendMessage(message: String) { + sender.sendMessage(message) + } - @Override - public void sendMessage(String[] message) { - sender.sendMessage(message); - } + override fun sendMessage(message: Array) { + sender.sendMessage(*message) + } - @Override - public String getName() { - return sender.getName(); - } -} + override fun getName(): String { + return sender.name + } +} \ No newline at end of file diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.kt b/Chroma-Core/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.kt index 8461ef5..d3f8628 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.kt @@ -1,97 +1,99 @@ -package buttondevteam.lib.chat; +package buttondevteam.lib.chat -import buttondevteam.core.component.channel.Channel; -import buttondevteam.core.component.channel.Channel.RecipientTestResult; -import buttondevteam.lib.ChromaUtils; -import buttondevteam.lib.TBMCChatEvent; -import buttondevteam.lib.TBMCChatPreprocessEvent; -import buttondevteam.lib.TBMCSystemChatEvent; -import lombok.val; -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; +import buttondevteam.core.component.channel.Channel +import buttondevteam.core.component.channel.Channel.Companion.channelList +import buttondevteam.core.component.channel.Channel.Companion.registerChannel +import buttondevteam.core.component.channel.Channel.RecipientTestResult +import buttondevteam.lib.ChromaUtils.callEventAsync +import buttondevteam.lib.ChromaUtils.doItAsync +import buttondevteam.lib.TBMCChatEvent +import buttondevteam.lib.TBMCChatPreprocessEvent +import buttondevteam.lib.TBMCSystemChatEvent +import buttondevteam.lib.TBMCSystemChatEvent.BroadcastTarget +import org.bukkit.Bukkit +import org.bukkit.command.CommandSender +import java.util.* +import java.util.function.Supplier -import java.util.Arrays; -import java.util.function.Supplier; +object TBMCChatAPI { + /** + * Sends a chat message to Minecraft. Make sure that the channel is registered with [.RegisterChatChannel].

+ * This will also send the error message to the sender, if they can't send the message. + * + * @param cm The message to send + * @param channel The MC channel to send in + * @return The event cancelled state + */ + /** + * Sends a chat message to Minecraft. Make sure that the channel is registered with [.RegisterChatChannel].

+ * This will also send the error message to the sender, if they can't send the message. + * + * @param cm The message to send + * @return The event cancelled state + */ + @JvmOverloads + fun SendChatMessage(cm: ChatMessage, channel: Channel = cm.user.channel.get()): Boolean { + if (!channelList.contains(channel)) throw RuntimeException( + "Channel " + channel.displayName.get() + " not registered!" + ) + if (!channel.isEnabled.get()) { + cm.sender.sendMessage("§cThe channel '" + channel.displayName.get() + "' is disabled!") + return true //Cancel sending if channel is disabled + } + val task = Supplier { + val permcheck = cm.getPermCheck() + val rtr = getScoreOrSendError(channel, permcheck) + val score = rtr.score + if (score == Channel.SCORE_SEND_NOPE || rtr.groupID == null) return@Supplier true + val eventPre = TBMCChatPreprocessEvent(cm.sender, channel, cm.message) + Bukkit.getPluginManager().callEvent(eventPre) + if (eventPre.isCancelled) return@Supplier true + cm.message = eventPre.message + val event = TBMCChatEvent(channel, cm, rtr) + Bukkit.getPluginManager().callEvent(event) + event.isCancelled + } + return doItAsync(task, false) //Not cancelled if async + } -public class TBMCChatAPI { - /** - * Sends a chat message to Minecraft. Make sure that the channel is registered with {@link #RegisterChatChannel(Channel)}.
- * This will also send the error message to the sender, if they can't send the message. - * - * @param cm The message to send - * @return The event cancelled state - */ - public static boolean SendChatMessage(ChatMessage cm) { - return SendChatMessage(cm, cm.getUser().channel.get()); - } + /** + * Sends a regular message to Minecraft. Make sure that the channel is registered with [.RegisterChatChannel]. + * + * @param channel The channel to send to + * @param rtr The score&group to use to find the group - use [RecipientTestResult.ALL] if the channel doesn't have scores + * @param message The message to send + * @param exceptions Platforms where this message shouldn't be sent (same as [ChatMessage.getOrigin] + * @return The event cancelled state + */ + @JvmStatic + fun SendSystemMessage( + channel: Channel, + rtr: RecipientTestResult, + message: String, + target: BroadcastTarget?, + vararg exceptions: String + ): Boolean { + if (!channelList.contains(channel)) throw RuntimeException("Channel " + channel.displayName.get() + " not registered!") + if (!channel.isEnabled.get()) return true //Cancel sending + if (!exceptions.contains("Minecraft")) Bukkit.getConsoleSender() + .sendMessage("[" + channel.displayName.get() + "] " + message) + val event = TBMCSystemChatEvent(channel, message, rtr.score, rtr.groupID!!, exceptions, target!!) + return callEventAsync(event) + } - /** - * Sends a chat message to Minecraft. Make sure that the channel is registered with {@link #RegisterChatChannel(Channel)}.
- * This will also send the error message to the sender, if they can't send the message. - * - * @param cm The message to send - * @param channel The MC channel to send in - * @return The event cancelled state - */ - public static boolean SendChatMessage(ChatMessage cm, Channel channel) { - if (!Channel.getChannelList().contains(channel)) - throw new RuntimeException("Channel " + channel.getDisplayName().get() + " not registered!"); - if (!channel.isEnabled.get()) { - cm.getSender().sendMessage("§cThe channel '" + channel.displayName.get() + "' is disabled!"); - return true; //Cancel sending if channel is disabled - } - Supplier task = () -> { - val permcheck = cm.getPermCheck(); - RecipientTestResult rtr = getScoreOrSendError(channel, permcheck); - int score = rtr.score; - if (score == Channel.SCORE_SEND_NOPE || rtr.groupID == null) - return true; - TBMCChatPreprocessEvent eventPre = new TBMCChatPreprocessEvent(cm.getSender(), channel, cm.getMessage()); - Bukkit.getPluginManager().callEvent(eventPre); - if (eventPre.isCancelled()) - return true; - cm.setMessage(eventPre.getMessage()); - TBMCChatEvent event; - event = new TBMCChatEvent(channel, cm, rtr); - Bukkit.getPluginManager().callEvent(event); - return event.isCancelled(); - }; - return ChromaUtils.doItAsync(task, false); //Not cancelled if async - } + private fun getScoreOrSendError(channel: Channel, sender: CommandSender): RecipientTestResult { + val result = channel.getRTR(sender) + if (result.errormessage != null) sender.sendMessage("§c" + result.errormessage) + return result + } - /** - * Sends a regular message to Minecraft. Make sure that the channel is registered with {@link #RegisterChatChannel(Channel)}. - * - * @param channel The channel to send to - * @param rtr The score&group to use to find the group - use {@link RecipientTestResult#ALL} if the channel doesn't have scores - * @param message The message to send - * @param exceptions Platforms where this message shouldn't be sent (same as {@link ChatMessage#getOrigin()} - * @return The event cancelled state - */ - public static boolean SendSystemMessage(Channel channel, RecipientTestResult rtr, String message, TBMCSystemChatEvent.BroadcastTarget target, String... exceptions) { - if (!Channel.getChannelList().contains(channel)) - throw new RuntimeException("Channel " + channel.displayName.get() + " not registered!"); - if (!channel.enabled.get()) - return true; //Cancel sending - if (!Arrays.asList(exceptions).contains("Minecraft")) - Bukkit.getConsoleSender().sendMessage("[" + channel.displayName.get() + "] " + message); - TBMCSystemChatEvent event = new TBMCSystemChatEvent(channel, message, rtr.score, rtr.groupID, exceptions, target); - return ChromaUtils.callEventAsync(event); - } - - private static RecipientTestResult getScoreOrSendError(Channel channel, CommandSender sender) { - RecipientTestResult result = channel.getRTR(sender); - if (result.errormessage != null) - sender.sendMessage("§c" + result.errormessage); - return result; - } - - /** - * Register a chat channel. See {@link Channel#Channel(String, Color, String, java.util.function.Function)} for details. - * - * @param channel A new {@link Channel} to register - */ - public static void RegisterChatChannel(Channel channel) { - Channel.registerChannel(channel); - } -} + /** + * Register a chat channel. See [Channel.Channel] for details. + * + * @param channel A new [Channel] to register + */ + @JvmStatic + fun RegisterChatChannel(channel: Channel) { + registerChannel(channel) + } +} \ No newline at end of file diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/commands/CommandArgumentHelpManager.kt b/Chroma-Core/src/main/java/buttondevteam/lib/chat/commands/CommandArgumentHelpManager.kt index 74381d2..cb1621f 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/commands/CommandArgumentHelpManager.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/commands/CommandArgumentHelpManager.kt @@ -13,14 +13,14 @@ import java.lang.reflect.Method /** * Deals with reading the commands.yml file from the plugin. The file is generated by ButtonProcessor at compile-time. * Only used when registering commands. + * + * @param command The command object to use */ class CommandArgumentHelpManager, TP : Command2Sender>(command: TC) { private var commandConfig: ConfigurationSection? = null /** * Read the yaml file for the given command class. - * - * @param command The command object to use */ init { val commandClass = command.javaClass @@ -59,17 +59,23 @@ class CommandArgumentHelpManager, TP : Command2Sender>(comman MainPlugin.instance.logger.warning("Failed to get command data for $method! Make sure to use 'clean install' when building the project.") return null } - val mname = cs.getString("method") - val params = cs.getString("params") - val i = - mname.indexOf('(') //Check only the name - the whole method is still stored for backwards compatibility and in case it may be useful - if (i != -1 && method.name == mname.substring(0, i) && params != null) { + + fun fail(message: String): String? { + TBMCCoreAPI.SendException( + "Error while getting command data for $method!", + Exception(message), + MainPlugin.instance + ) + return null + } + + val mname = cs.getString("method") ?: return fail("Method is null") + val params = cs.getString("params") ?: return fail("Params is null") + //Check only the name - the whole method is still stored for backwards compatibility and in case it may be useful + val i = mname.indexOf('(') + if (i != -1 && method.name == mname.substring(0, i)) { return params - } else TBMCCoreAPI.SendException( - "Error while getting command data for $method!", - Exception("Method '$method' != $mname or params is $params"), - MainPlugin.instance - ) + } else fail("Method '$method' != $mname") return null } } \ No newline at end of file diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/player/ChromaGamerBase.kt b/Chroma-Core/src/main/java/buttondevteam/lib/player/ChromaGamerBase.kt index 31e99ae..30ad8ee 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/player/ChromaGamerBase.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/player/ChromaGamerBase.kt @@ -18,9 +18,11 @@ import java.util.function.Supplier @ChromaGamerEnforcer abstract class ChromaGamerBase { lateinit var config: IHaveConfig + protected set protected lateinit var commonUserData: CommonUserData protected open fun init() { + config = IHaveConfig({ save() }, commonUserData.playerData) } protected fun updateUserConfig() {} // TODO: Use this instead of reset() @@ -96,9 +98,19 @@ abstract class ChromaGamerBase { * @param cl The player class to get the ID from * @return The ID or null if not found */ - fun getConnectedID(cl: Class): String? { - val data = staticDataMap[cl] ?: throw RuntimeException("Class $cl is not registered!") - return commonUserData.playerData.getString(data.folder + "_id") + fun getConnectedID(cl: Class): String? { + return getConnectedID(getStaticData(cl).folder) + + } + + /** + * Returns 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 + * @return The ID or null if not found + */ + fun getConnectedID(folder: String): String? { + return commonUserData.playerData.getString(folder + "_id") } /** @@ -111,26 +123,24 @@ abstract class ChromaGamerBase { fun getAs(cl: Class): T? { @Suppress("UNCHECKED_CAST") if (cl.simpleName == javaClass.simpleName) return this as T - val newfolder = getFolderForType(cl) - if (newfolder == folder) // If in the same folder, the same filename is used + val data = getStaticData(cl) + if (data.folder == folder) // If in the same folder, the same filename is used return getUser(fileName, cl) - val playerData = commonUserData.playerData - return if (playerData.contains(newfolder + "_id")) - getUser(playerData.getString(newfolder + "_id")!!, cl) - else null + return getConnectedID(data.folder)?.let { getUser(it, cl) } } - val fileName: String - /** - * This method returns the filename for this player data. For example, for Minecraft-related data, MC UUIDs, for Discord data, Discord IDs, etc.

- * **Does not include .yml** - */ - get() = commonUserData.playerData.getString(folder + "_id")!! - val folder: String - /** - * This method returns the folder that this player data is stored in. For example: "minecraft". - */ - get() = getFolderForType(javaClass) + /** + * Returns the filename for this player data. For example, for Minecraft-related data, MC UUIDs, for Discord data, Discord IDs, etc.

+ * **Does not include .yml** + */ + val fileName: String by lazy { + commonUserData.playerData.getString(folder + "_id") ?: throw RuntimeException("ID not set!") + } + + /** + * Returns the folder that this player data is stored in. For example: "minecraft". + */ + val folder: String by lazy { getStaticData(javaClass).folder } /** * Get player information. This method calls the [TBMCPlayerGetInfoEvent] to get all the player information across the TBMC plugins. @@ -282,7 +292,6 @@ abstract class ChromaGamerBase { } } obj.commonUserData = commonUserData - obj.config = IHaveConfig({ obj.save() }, commonUserData.playerData) obj.init() obj.scheduleUncache() return obj diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.kt b/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.kt index ad3cd3f..4947253 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.kt @@ -1,12 +1,13 @@ package buttondevteam.lib.player +import buttondevteam.lib.architecture.IHaveConfig import org.bukkit.Bukkit import java.util.* @AbstractUserClass(foldername = "minecraft", prototype = TBMCPlayer::class) @TBMCPlayerEnforcer abstract class TBMCPlayerBase : ChromaGamerBase() { - val uniqueId: UUID get() = UUID.fromString(fileName) + val uniqueId: UUID by lazy { UUID.fromString(fileName) } @JvmField val playerName = super.config.getData("PlayerName", "") @@ -17,9 +18,8 @@ abstract class TBMCPlayerBase : ChromaGamerBase() { else throw RuntimeException("Class not defined as player class! Use @PlayerClass") val playerData = commonUserData.playerData - var section = playerData.getConfigurationSection(pluginName) - if (section == null) section = playerData.createSection(pluginName) - config.reset(section) + val section = playerData.getConfigurationSection(pluginName) ?: playerData.createSection(pluginName) + config = IHaveConfig({ save() }, section) } /**