A bunch of changes and improvements - and Kotlin
- Tried to reduce usage of MainPlugin.Instance, ended up refactoring more Component/ButtonPlugin things - Config fixes, among other things
This commit is contained in:
parent
d6fba6a495
commit
56d1f0c2a2
16 changed files with 684 additions and 697 deletions
|
@ -24,7 +24,7 @@ public class ChromaCommand extends ICommand2MC {
|
||||||
@Command2.Subcommand
|
@Command2.Subcommand
|
||||||
public void reload(CommandSender sender, @Command2.OptionalArg ButtonPlugin plugin) {
|
public void reload(CommandSender sender, @Command2.OptionalArg ButtonPlugin plugin) {
|
||||||
if (plugin == null)
|
if (plugin == null)
|
||||||
plugin = MainPlugin.Instance;
|
plugin = getPlugin();
|
||||||
if (plugin.tryReloadConfig())
|
if (plugin.tryReloadConfig())
|
||||||
sender.sendMessage("§b" + plugin.getName() + " config reloaded.");
|
sender.sendMessage("§b" + plugin.getName() + " config reloaded.");
|
||||||
else
|
else
|
||||||
|
|
|
@ -1,66 +1,81 @@
|
||||||
package buttondevteam.core;
|
package buttondevteam.core
|
||||||
|
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
import buttondevteam.lib.TBMCCoreAPI
|
||||||
import buttondevteam.lib.architecture.ButtonPlugin;
|
import buttondevteam.lib.architecture.ButtonPlugin
|
||||||
import buttondevteam.lib.architecture.Component;
|
import buttondevteam.lib.architecture.Component
|
||||||
import lombok.val;
|
import buttondevteam.lib.architecture.Component.Companion.components
|
||||||
|
import buttondevteam.lib.architecture.Component.Companion.setComponentEnabled
|
||||||
|
import buttondevteam.lib.architecture.Component.Companion.unregisterComponent
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
public final class ComponentManager {
|
object ComponentManager {
|
||||||
private ComponentManager() {}
|
private var componentsEnabled = false
|
||||||
|
|
||||||
private static boolean componentsEnabled = false;
|
/**
|
||||||
|
* This flag is used to enable components registered after the others were enabled.
|
||||||
|
* @return Whether already registered components have been enabled
|
||||||
|
*/
|
||||||
|
fun areComponentsEnabled(): Boolean {
|
||||||
|
return componentsEnabled
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This flag is used to enable components registered after the others were enabled.
|
* Enables components based on a configuration - any component registered afterwards will be also enabled
|
||||||
* @return Whether already registered components have been enabled
|
*/
|
||||||
*/
|
fun enableComponents() {
|
||||||
public static boolean areComponentsEnabled() { return componentsEnabled; }
|
components.values.stream().filter { c: Component<out JavaPlugin> -> c.shouldBeEnabled.get() }
|
||||||
|
.forEach { c ->
|
||||||
|
try {
|
||||||
|
setComponentEnabled(c, true)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
TBMCCoreAPI.SendException("Failed to enable one of the components: " + c.javaClass.simpleName, e, c)
|
||||||
|
} catch (e: NoClassDefFoundError) {
|
||||||
|
TBMCCoreAPI.SendException("Failed to enable one of the components: " + c.javaClass.simpleName, e, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
componentsEnabled = true
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables components based on a configuration - any component registered afterwards will be also enabled
|
* Unregister all components of a plugin that are enabled - called on [ButtonPlugin] disable
|
||||||
*/
|
*/
|
||||||
public static void enableComponents() {
|
@Suppress("UNCHECKED_CAST")
|
||||||
//Component.getComponents().values().stream().filter(c->cs.getConfigurationSection(c.getClass().getSimpleName()).getBoolean("enabled")).forEach(c-> {
|
fun <T : ButtonPlugin> unregComponents(plugin: T) {
|
||||||
Component.getComponents().values().stream().filter(c -> c.shouldBeEnabled.get()).forEach(c -> {
|
while (!plugin.componentStack.empty()) //Unregister in reverse order
|
||||||
try {
|
unregisterComponent(plugin, plugin.componentStack.pop() as Component<T>) //Components are pushed on register
|
||||||
Component.setComponentEnabled(c, true);
|
}
|
||||||
} catch (Exception | NoClassDefFoundError e) {
|
|
||||||
TBMCCoreAPI.SendException("Failed to enable one of the components: " + c.getClass().getSimpleName(), e, c);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
componentsEnabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregister all components of a plugin that are enabled - called on {@link ButtonPlugin} disable
|
* Will also return false if the component is not registered.
|
||||||
*/
|
*
|
||||||
@SuppressWarnings("unchecked")
|
* @param cl The component class
|
||||||
public static <T extends ButtonPlugin> void unregComponents(T plugin) {
|
* @return Whether the component is registered and enabled
|
||||||
while (!plugin.getComponentStack().empty()) //Unregister in reverse order
|
*/
|
||||||
Component.unregisterComponent(plugin, (Component<T>) plugin.getComponentStack().pop()); //Components are pushed on register
|
@JvmStatic
|
||||||
//componentsEnabled = false; - continue enabling new components after a plugin gets disabled
|
fun isEnabled(cl: Class<out Component<*>?>?): Boolean {
|
||||||
}
|
val c = components[cl]
|
||||||
|
return c != null && c.isEnabled
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will also return false if the component is not registered.
|
* Will also return null if the component is not registered.
|
||||||
*
|
*
|
||||||
* @param cl The component class
|
* @param cl The component class
|
||||||
* @return Whether the component is registered and enabled
|
* @return The component if it's registered and enabled
|
||||||
*/
|
*/
|
||||||
public static boolean isEnabled(Class<? extends Component> cl) {
|
@JvmStatic
|
||||||
val c = Component.getComponents().get(cl);
|
@Suppress("UNCHECKED_CAST")
|
||||||
return c != null && c.isEnabled();
|
fun <T : Component<*>> getIfEnabled(cl: Class<T>): T? {
|
||||||
}
|
val c = components[cl]
|
||||||
|
return if (c != null && c.isEnabled) c as T else null
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will also return null if the component is not registered.
|
* It will return null if the component is not registered. Use this method if you don't want to check if the component is enabled.
|
||||||
*
|
*/
|
||||||
* @param cl The component class
|
@JvmStatic
|
||||||
* @return The component if it's registered and enabled
|
@Suppress("UNCHECKED_CAST")
|
||||||
*/
|
fun <T : Component<*>> get(cl: Class<T>): T? {
|
||||||
@SuppressWarnings("unchecked")
|
return components[cl] as T?
|
||||||
public static <T extends Component> T getIfEnabled(Class<T> cl) {
|
}
|
||||||
val c = Component.getComponents().get(cl);
|
|
||||||
return c != null && c.isEnabled() ? (T) c : null;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,173 +1,194 @@
|
||||||
package buttondevteam.core;
|
package buttondevteam.core
|
||||||
|
|
||||||
import buttondevteam.core.component.channel.Channel;
|
import buttondevteam.core.component.channel.Channel
|
||||||
import buttondevteam.core.component.channel.ChannelComponent;
|
import buttondevteam.core.component.channel.ChannelComponent
|
||||||
import buttondevteam.core.component.channel.ChatRoom;
|
import buttondevteam.core.component.channel.ChatRoom
|
||||||
import buttondevteam.core.component.members.MemberComponent;
|
import buttondevteam.core.component.members.MemberComponent
|
||||||
import buttondevteam.core.component.randomtp.RandomTPComponent;
|
import buttondevteam.core.component.randomtp.RandomTPComponent
|
||||||
import buttondevteam.core.component.restart.RestartComponent;
|
import buttondevteam.core.component.restart.RestartComponent
|
||||||
import buttondevteam.core.component.spawn.SpawnComponent;
|
import buttondevteam.core.component.spawn.SpawnComponent
|
||||||
import buttondevteam.core.component.towny.TownyComponent;
|
import buttondevteam.core.component.towny.TownyComponent
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
import buttondevteam.lib.TBMCCoreAPI
|
||||||
import buttondevteam.lib.architecture.ButtonPlugin;
|
import buttondevteam.lib.architecture.ButtonPlugin
|
||||||
import buttondevteam.lib.architecture.Component;
|
import buttondevteam.lib.architecture.Component.Companion.registerComponent
|
||||||
import buttondevteam.lib.architecture.ConfigData;
|
import buttondevteam.lib.chat.Color
|
||||||
import buttondevteam.lib.chat.Color;
|
import buttondevteam.lib.chat.TBMCChatAPI
|
||||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
import buttondevteam.lib.player.ChromaGamerBase
|
||||||
import buttondevteam.lib.player.ChromaGamerBase;
|
import buttondevteam.lib.player.TBMCPlayer
|
||||||
import buttondevteam.lib.player.TBMCPlayer;
|
import buttondevteam.lib.player.TBMCPlayerBase
|
||||||
import buttondevteam.lib.player.TBMCPlayerBase;
|
import com.earth2me.essentials.Essentials
|
||||||
import com.earth2me.essentials.Essentials;
|
import net.milkbowl.vault.economy.Economy
|
||||||
import lombok.Getter;
|
import net.milkbowl.vault.permission.Permission
|
||||||
import lombok.Setter;
|
import org.bukkit.Bukkit
|
||||||
import net.milkbowl.vault.economy.Economy;
|
import org.bukkit.OfflinePlayer
|
||||||
import net.milkbowl.vault.permission.Permission;
|
import org.bukkit.command.BlockCommandSender
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.command.Command
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.command.CommandSender
|
||||||
import org.bukkit.command.BlockCommandSender;
|
import org.bukkit.command.ConsoleCommandSender
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.entity.Player
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.plugin.Plugin
|
||||||
import org.bukkit.command.ConsoleCommandSender;
|
import java.io.File
|
||||||
import org.bukkit.entity.HumanEntity;
|
import java.io.IOException
|
||||||
import org.bukkit.entity.Player;
|
import java.nio.file.Files
|
||||||
import org.bukkit.plugin.PluginDescriptionFile;
|
import java.util.*
|
||||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
import java.util.function.Function
|
||||||
|
import java.util.function.Supplier
|
||||||
|
import java.util.logging.Logger
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
class MainPlugin : ButtonPlugin() {
|
||||||
import java.io.File;
|
private var logger: Logger? = null
|
||||||
import java.io.IOException;
|
private var economy: Economy? = null
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
public class MainPlugin extends ButtonPlugin {
|
/**
|
||||||
public static MainPlugin Instance;
|
* Whether the Core's chat handler should be enabled.
|
||||||
public static Permission permission;
|
* Other chat plugins handling messages from other platforms should set this to false.
|
||||||
@Nullable
|
*/
|
||||||
public static Essentials ess;
|
var isChatHandlerEnabled = true
|
||||||
|
|
||||||
private Logger logger;
|
/**
|
||||||
@Nullable
|
* Sets whether the plugin should write a list of installed plugins in a txt file.
|
||||||
private Economy economy;
|
* It can be useful if some other software needs to know the plugins.
|
||||||
/**
|
*/
|
||||||
* Whether the Core's chat handler should be enabled.
|
private val writePluginList = iConfig.getData("writePluginList", false)
|
||||||
* Other chat plugins handling messages from other platforms should set this to false.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
private boolean chatHandlerEnabled = true;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets whether the plugin should write a list of installed plugins in a txt file.
|
* The chat format to use for messages from other platforms if Chroma-Chat is not installed.
|
||||||
* It can be useful if some other software needs to know the plugins.
|
*/
|
||||||
*/
|
@JvmField
|
||||||
private final ConfigData<Boolean> writePluginList = getIConfig().getData("writePluginList", false);
|
var chatFormat = iConfig.getData("chatFormat", "[{origin}|{channel}] <{name}> {message}")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The chat format to use for messages from other platforms if Chroma-Chat is not installed.
|
* Print some debug information.
|
||||||
*/
|
*/
|
||||||
ConfigData<String> chatFormat = getIConfig().getData("chatFormat", "[{origin}|" +
|
@JvmField
|
||||||
"{channel}] <{name}> {message}");
|
val test = iConfig.getData("test", false)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print some debug information.
|
* 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.
|
||||||
*/
|
*/
|
||||||
public final ConfigData<Boolean> test = getIConfig().getData("test", false);
|
val prioritizeCustomCommands = iConfig.getData("prioritizeCustomCommands", false)
|
||||||
|
public override fun pluginEnable() {
|
||||||
/**
|
Instance = this
|
||||||
* 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 pdf = description
|
||||||
*/
|
logger = getLogger()
|
||||||
public final ConfigData<Boolean> prioritizeCustomCommands = getIConfig().getData("prioritizeCustomCommands", false);
|
if (!setupPermissions()) throw NullPointerException("No permission plugin found!")
|
||||||
|
if (!setupEconomy()) //Though Essentials always provides economy, but we don't require Essentials
|
||||||
@Override
|
getLogger().warning("No economy plugin found! Components using economy will not be registered.")
|
||||||
public void pluginEnable() {
|
saveConfig()
|
||||||
Instance = this;
|
registerComponent(this, RestartComponent())
|
||||||
PluginDescriptionFile pdf = getDescription();
|
registerComponent(this, ChannelComponent())
|
||||||
logger = getLogger();
|
registerComponent(this, RandomTPComponent())
|
||||||
if (!setupPermissions())
|
registerComponent(this, MemberComponent())
|
||||||
throw new NullPointerException("No permission plugin found!");
|
if (Bukkit.getPluginManager().isPluginEnabled("Multiverse-Core"))
|
||||||
if (!setupEconomy()) //Though Essentials always provides economy, but we don't require Essentials
|
registerComponent(this, SpawnComponent())
|
||||||
getLogger().warning("No economy plugin found! Components using economy will not be registered.");
|
if (Bukkit.getPluginManager().isPluginEnabled("Towny")) //It fails to load the component class otherwise
|
||||||
saveConfig();
|
registerComponent(this, TownyComponent())
|
||||||
Component.registerComponent(this, new RestartComponent());
|
/*if (Bukkit.getPluginManager().isPluginEnabled("Votifier") && economy != null)
|
||||||
Component.registerComponent(this, new ChannelComponent());
|
|
||||||
Component.registerComponent(this, new RandomTPComponent());
|
|
||||||
Component.registerComponent(this, new MemberComponent());
|
|
||||||
if (Bukkit.getPluginManager().isPluginEnabled("Multiverse-Core"))
|
|
||||||
Component.registerComponent(this, new SpawnComponent());
|
|
||||||
if (Bukkit.getPluginManager().isPluginEnabled("Towny")) //It fails to load the component class otherwise
|
|
||||||
Component.registerComponent(this, new TownyComponent());
|
|
||||||
/*if (Bukkit.getPluginManager().isPluginEnabled("Votifier") && economy != null)
|
|
||||||
Component.registerComponent(this, new VotifierComponent(economy));*/
|
Component.registerComponent(this, new VotifierComponent(economy));*/
|
||||||
ComponentManager.enableComponents();
|
ComponentManager.enableComponents()
|
||||||
registerCommand(new ComponentCommand());
|
registerCommand(ComponentCommand())
|
||||||
registerCommand(new ChromaCommand());
|
registerCommand(ChromaCommand())
|
||||||
TBMCCoreAPI.RegisterEventsForExceptions(new PlayerListener(), this);
|
TBMCCoreAPI.RegisterEventsForExceptions(PlayerListener(this), this)
|
||||||
TBMCCoreAPI.RegisterEventsForExceptions(Companion.getCommand2MC(), this);
|
TBMCCoreAPI.RegisterEventsForExceptions(command2MC, this)
|
||||||
ChromaGamerBase.addConverter(commandSender -> Optional.ofNullable(commandSender instanceof ConsoleCommandSender || commandSender instanceof BlockCommandSender
|
//Console & cmdblocks
|
||||||
? TBMCPlayer.getPlayer(new UUID(0, 0), TBMCPlayer.class) : null)); //Console & cmdblocks
|
ChromaGamerBase.addConverter { commandSender: CommandSender ->
|
||||||
ChromaGamerBase.addConverter(sender -> Optional.ofNullable(sender instanceof Player
|
Optional.ofNullable(
|
||||||
? TBMCPlayer.getPlayer(((Player) sender).getUniqueId(), TBMCPlayer.class) : null)); //Players, has higher priority
|
if (commandSender is ConsoleCommandSender || commandSender is BlockCommandSender)
|
||||||
TBMCCoreAPI.RegisterUserClass(TBMCPlayerBase.class, TBMCPlayer::new);
|
TBMCPlayer.getPlayer(UUID(0, 0), TBMCPlayer::class.java)
|
||||||
TBMCChatAPI.RegisterChatChannel(Channel.GlobalChat = new Channel("§fg§f", Color.White, "g", null)); //The /ooc ID has moved to the config
|
else null
|
||||||
TBMCChatAPI.RegisterChatChannel(
|
)
|
||||||
Channel.AdminChat = new Channel("§cADMIN§f", Color.Red, "a", Channel.inGroupFilter(null)));
|
}
|
||||||
TBMCChatAPI.RegisterChatChannel(
|
//Players, has higher priority
|
||||||
Channel.ModChat = new Channel("§9MOD§f", Color.Blue, "mod", Channel.inGroupFilter("mod")));
|
ChromaGamerBase.addConverter { sender: CommandSender ->
|
||||||
TBMCChatAPI.RegisterChatChannel(new Channel("§6DEV§f", Color.Gold, "dev", Channel.inGroupFilter("developer")));
|
Optional.ofNullable(
|
||||||
TBMCChatAPI.RegisterChatChannel(new ChatRoom("§cRED§f", Color.DarkRed, "red"));
|
if (sender is Player) TBMCPlayer.getPlayer(sender.uniqueId, TBMCPlayer::class.java) else null
|
||||||
TBMCChatAPI.RegisterChatChannel(new ChatRoom("§6ORANGE§f", Color.Gold, "orange"));
|
)
|
||||||
TBMCChatAPI.RegisterChatChannel(new ChatRoom("§eYELLOW§f", Color.Yellow, "yellow"));
|
}
|
||||||
TBMCChatAPI.RegisterChatChannel(new ChatRoom("§aGREEN§f", Color.Green, "green"));
|
TBMCCoreAPI.RegisterUserClass(TBMCPlayerBase::class.java) { TBMCPlayer() }
|
||||||
TBMCChatAPI.RegisterChatChannel(new ChatRoom("§bBLUE§f", Color.Blue, "blue"));
|
TBMCChatAPI.RegisterChatChannel(Channel("§fg§f", Color.White, "g", null)
|
||||||
TBMCChatAPI.RegisterChatChannel(new ChatRoom("§5PURPLE§f", Color.DarkPurple, "purple"));
|
.also { Channel.GlobalChat = it }) //The /ooc ID has moved to the config
|
||||||
Supplier<Iterable<String>> playerSupplier = () -> Bukkit.getOnlinePlayers().stream().map(HumanEntity::getName)::iterator;
|
TBMCChatAPI.RegisterChatChannel(Channel("§cADMIN§f", Color.Red, "a", Channel.inGroupFilter(null))
|
||||||
Companion.getCommand2MC().addParamConverter(OfflinePlayer.class, Bukkit::getOfflinePlayer, "Player not found!", playerSupplier);
|
.also { Channel.AdminChat = it })
|
||||||
Companion.getCommand2MC().addParamConverter(Player.class, Bukkit::getPlayer, "Online player not found!", playerSupplier);
|
TBMCChatAPI.RegisterChatChannel(Channel("§9MOD§f", Color.Blue, "mod", Channel.inGroupFilter("mod"))
|
||||||
if (writePluginList.get()) {
|
.also { Channel.ModChat = it })
|
||||||
try {
|
TBMCChatAPI.RegisterChatChannel(
|
||||||
Files.write(new File("plugins", "plugins.txt").toPath(), Arrays.stream(Bukkit.getPluginManager().getPlugins()).map(p -> (CharSequence) p.getDataFolder().getName())::iterator);
|
Channel(
|
||||||
} catch (IOException e) {
|
"§6DEV§f",
|
||||||
TBMCCoreAPI.SendException("Failed to write plugin list!", e, this);
|
Color.Gold,
|
||||||
}
|
"dev",
|
||||||
}
|
Channel.inGroupFilter("developer")
|
||||||
if (getServer().getPluginManager().isPluginEnabled("Essentials"))
|
)
|
||||||
ess = Essentials.getPlugin(Essentials.class);
|
) // TODO: Make groups configurable
|
||||||
logger.info(pdf.getName() + " has been Enabled (V." + pdf.getVersion() + ") Test: " + test.get() + ".");
|
TBMCChatAPI.RegisterChatChannel(ChatRoom("§cRED§f", Color.DarkRed, "red"))
|
||||||
}
|
TBMCChatAPI.RegisterChatChannel(ChatRoom("§6ORANGE§f", Color.Gold, "orange"))
|
||||||
|
TBMCChatAPI.RegisterChatChannel(ChatRoom("§eYELLOW§f", Color.Yellow, "yellow"))
|
||||||
|
TBMCChatAPI.RegisterChatChannel(ChatRoom("§aGREEN§f", Color.Green, "green"))
|
||||||
|
TBMCChatAPI.RegisterChatChannel(ChatRoom("§bBLUE§f", Color.Blue, "blue"))
|
||||||
|
TBMCChatAPI.RegisterChatChannel(ChatRoom("§5PURPLE§f", Color.DarkPurple, "purple"))
|
||||||
|
val playerSupplier = Supplier { Bukkit.getOnlinePlayers().map { obj: Player -> obj.name }.asIterable() }
|
||||||
|
command2MC.addParamConverter(OfflinePlayer::class.java, { name: String? ->
|
||||||
|
Bukkit.getOfflinePlayer(
|
||||||
|
name!!
|
||||||
|
)
|
||||||
|
}, "Player not found!", playerSupplier)
|
||||||
|
command2MC.addParamConverter<Player>(
|
||||||
|
Player::class.java, Function { name: String ->
|
||||||
|
Bukkit.getPlayer(name)
|
||||||
|
}, "Online player not found!", playerSupplier
|
||||||
|
)
|
||||||
|
if (writePluginList.get()) {
|
||||||
|
try {
|
||||||
|
Files.write(File("plugins", "plugins.txt").toPath(), Iterable {
|
||||||
|
Arrays.stream(Bukkit.getPluginManager().plugins)
|
||||||
|
.map { p: Plugin -> p.dataFolder.name as CharSequence }
|
||||||
|
.iterator()
|
||||||
|
})
|
||||||
|
} catch (e: IOException) {
|
||||||
|
TBMCCoreAPI.SendException("Failed to write plugin list!", e, this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (server.pluginManager.isPluginEnabled("Essentials")) ess = getPlugin(
|
||||||
|
Essentials::class.java
|
||||||
|
)
|
||||||
|
logger!!.info(pdf.name + " has been Enabled (V." + pdf.version + ") Test: " + test.get() + ".")
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
public override fun pluginDisable() {
|
||||||
public void pluginDisable() {
|
logger!!.info("Saving player data...")
|
||||||
logger.info("Saving player data...");
|
ChromaGamerBase.saveUsers()
|
||||||
ChromaGamerBase.saveUsers();
|
logger!!.info("Player data saved.")
|
||||||
logger.info("Player data saved.");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private boolean setupPermissions() {
|
private fun setupPermissions(): Boolean {
|
||||||
permission = setupProvider(Permission.class);
|
permission = setupProvider(Permission::class.java)
|
||||||
return (permission != null);
|
return permission != null
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean setupEconomy() {
|
private fun setupEconomy(): Boolean {
|
||||||
economy = setupProvider(Economy.class);
|
economy = setupProvider(Economy::class.java)
|
||||||
return (economy != null);
|
return economy != null
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> T setupProvider(Class<T> cl) {
|
private fun <T> setupProvider(cl: Class<T>): T? {
|
||||||
RegisteredServiceProvider<T> provider = getServer().getServicesManager()
|
val provider = server.servicesManager
|
||||||
.getRegistration(cl);
|
.getRegistration(cl)
|
||||||
if (provider != null)
|
return provider?.provider
|
||||||
return provider.getProvider();
|
}
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<String>): Boolean {
|
||||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
if (command.name == "dontrunthiscmd") return true //Used in chat preprocess for console
|
||||||
if (command.getName().equals("dontrunthiscmd")) return true; //Used in chat preprocess for console
|
sender.sendMessage("§cThis command isn't available.") //In theory, unregistered commands use this method
|
||||||
sender.sendMessage("§cThis command isn't available."); //In theory, unregistered commands use this method
|
return true
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
companion object {
|
||||||
|
@JvmField
|
||||||
|
var Instance: MainPlugin = null
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var permission: Permission? = null
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var ess: Essentials? = null
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,116 +1,110 @@
|
||||||
package buttondevteam.core;
|
package buttondevteam.core
|
||||||
|
|
||||||
import buttondevteam.lib.*;
|
import buttondevteam.lib.*
|
||||||
import buttondevteam.lib.architecture.ButtonPlugin;
|
import buttondevteam.lib.architecture.ButtonPlugin
|
||||||
import buttondevteam.lib.chat.ChatMessage;
|
import buttondevteam.lib.chat.ChatMessage
|
||||||
import buttondevteam.lib.chat.Command2MCSender;
|
import buttondevteam.lib.chat.Command2MCSender
|
||||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
import buttondevteam.lib.chat.TBMCChatAPI
|
||||||
import buttondevteam.lib.player.ChromaGamerBase;
|
import buttondevteam.lib.player.ChromaGamerBase
|
||||||
import buttondevteam.lib.player.TBMCPlayer;
|
import buttondevteam.lib.player.TBMCPlayer
|
||||||
import buttondevteam.lib.player.TBMCPlayerBase;
|
import buttondevteam.lib.player.TBMCPlayerBase
|
||||||
import lombok.val;
|
import org.bukkit.Bukkit
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.command.CommandSender
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.entity.Player
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.event.Cancellable
|
||||||
import org.bukkit.event.Cancellable;
|
import org.bukkit.event.EventHandler
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventPriority
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.Listener
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.player.AsyncPlayerChatEvent
|
||||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
import org.bukkit.event.player.PlayerCommandPreprocessEvent
|
||||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
import org.bukkit.event.player.PlayerJoinEvent
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
import org.bukkit.event.player.PlayerQuitEvent
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
import org.bukkit.event.server.ServerCommandEvent
|
||||||
import org.bukkit.event.server.ServerCommandEvent;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
class PlayerListener(val plugin: MainPlugin) : Listener {
|
||||||
|
@EventHandler(priority = EventPriority.NORMAL)
|
||||||
|
fun onPlayerJoin(event: PlayerJoinEvent) {
|
||||||
|
val p = event.player
|
||||||
|
val player = TBMCPlayerBase.getPlayer(p.uniqueId, TBMCPlayer::class.java)
|
||||||
|
val pname = player.PlayerName.get()
|
||||||
|
if (pname.isEmpty()) {
|
||||||
|
player.PlayerName.set(p.name)
|
||||||
|
plugin.logger.info("Player name saved: " + player.PlayerName.get())
|
||||||
|
} else if (p.name != pname) {
|
||||||
|
plugin.logger.info(pname + " renamed to " + p.name)
|
||||||
|
player.PlayerName.set(p.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class PlayerListener implements Listener {
|
@EventHandler(priority = EventPriority.NORMAL)
|
||||||
|
fun onPlayerLeave(event: PlayerQuitEvent) {
|
||||||
|
TBMCPlayerBase.getPlayer(event.player.uniqueId, TBMCPlayer::class.java).uncache()
|
||||||
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.NORMAL)
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
public void OnPlayerJoin(PlayerJoinEvent event) {
|
fun onSystemChat(event: TBMCSystemChatEvent) {
|
||||||
var p = event.getPlayer();
|
if (event.isHandled) return
|
||||||
TBMCPlayer player = TBMCPlayerBase.getPlayer(p.getUniqueId(), TBMCPlayer.class);
|
if (event.exceptions.any { "Minecraft".equals(it, ignoreCase = true) }) return
|
||||||
String pname = player.PlayerName.get();
|
Bukkit.getOnlinePlayers().stream().filter { sender: CommandSender -> event.shouldSendTo(sender) }
|
||||||
if (pname.length() == 0) {
|
.forEach { p: Player -> p.sendMessage(event.channel.displayName.get().substring(0, 2) + event.message) }
|
||||||
player.PlayerName.set(p.getName());
|
}
|
||||||
MainPlugin.Instance.getLogger().info("Player name saved: " + player.PlayerName.get());
|
|
||||||
} else if (!p.getName().equals(pname)) {
|
|
||||||
MainPlugin.Instance.getLogger().info(pname + " renamed to " + p.getName());
|
|
||||||
player.PlayerName.set(p.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.NORMAL)
|
@EventHandler
|
||||||
public void OnPlayerLeave(PlayerQuitEvent event) {
|
fun onPlayerChatPreprocess(event: PlayerCommandPreprocessEvent) {
|
||||||
TBMCPlayerBase.getPlayer(event.getPlayer().getUniqueId(), TBMCPlayer.class).uncache();
|
handlePreprocess(event.player, event.message, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
@EventHandler
|
||||||
public void onSystemChat(TBMCSystemChatEvent event) {
|
fun onSystemChatPreprocess(event: ServerCommandEvent) {
|
||||||
if (event.isHandled())
|
handlePreprocess(event.sender, "/" + event.command, event)
|
||||||
return; // Only handle here if ButtonChat couldn't - ButtonChat doesn't even handle this
|
if (event.isCancelled) event.command = "dontrunthiscmd" //Bugfix
|
||||||
if (Arrays.stream(event.getExceptions()).anyMatch("Minecraft"::equalsIgnoreCase))
|
}
|
||||||
return;
|
|
||||||
Bukkit.getOnlinePlayers().stream().filter(event::shouldSendTo)
|
|
||||||
.forEach(p -> p.sendMessage(event.getChannel().DisplayName.get().substring(0, 2) + event.getMessage()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
private fun handlePreprocess(sender: CommandSender, message: String, event: Cancellable) {
|
||||||
public void onPlayerChatPreprocess(PlayerCommandPreprocessEvent event) {
|
if (event.isCancelled) return
|
||||||
handlePreprocess(event.getPlayer(), event.getMessage(), event);
|
val cg = ChromaGamerBase.getFromSender(sender)
|
||||||
}
|
?: throw RuntimeException("Couldn't get user from sender for " + sender.name + "!")
|
||||||
|
val ev = TBMCCommandPreprocessEvent(sender, cg.channel.get(), message, sender)
|
||||||
|
Bukkit.getPluginManager().callEvent(ev)
|
||||||
|
if (ev.isCancelled) event.isCancelled = true //Cancel the original event
|
||||||
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onSystemChatPreprocess(ServerCommandEvent event) {
|
fun onTBMCPreprocess(event: TBMCCommandPreprocessEvent) {
|
||||||
handlePreprocess(event.getSender(), "/" + event.getCommand(), event);
|
if (event.isCancelled) return
|
||||||
if (event.isCancelled()) event.setCommand("dontrunthiscmd"); //Bugfix
|
try {
|
||||||
}
|
val sender = Command2MCSender(event.sender, event.channel, event.permCheck)
|
||||||
|
event.isCancelled = ButtonPlugin.command2MC.handleCommand(sender, event.message)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
TBMCCoreAPI.SendException(
|
||||||
|
"Command processing failed for sender '${event.sender}' and message '${event.message}'",
|
||||||
|
e,
|
||||||
|
plugin
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void handlePreprocess(CommandSender sender, String message, Cancellable event) {
|
@EventHandler(priority = EventPriority.HIGH) //The one in the chat plugin is set to highest
|
||||||
if (event.isCancelled()) return;
|
fun onPlayerChat(event: AsyncPlayerChatEvent) {
|
||||||
val cg = ChromaGamerBase.getFromSender(sender);
|
if (event.isCancelled) return //The chat plugin should cancel it after this handler
|
||||||
if (cg == null) throw new RuntimeException("Couldn't get user from sender for " + sender.getName() + "!");
|
val cp = TBMCPlayer.getPlayer(event.player.uniqueId, TBMCPlayer::class.java)
|
||||||
val ev = new TBMCCommandPreprocessEvent(sender, cg.channel.get(), message, sender);
|
TBMCChatAPI.SendChatMessage(ChatMessage.builder(event.player, cp, event.message).build())
|
||||||
Bukkit.getPluginManager().callEvent(ev);
|
//Not cancelling the original event here, it's cancelled in the chat plugin
|
||||||
if (ev.isCancelled())
|
//This way other plugins can deal with the MC formatting if the chat plugin isn't present, but other platforms still get the message
|
||||||
event.setCancelled(true); //Cancel the original event
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler(priority = EventPriority.HIGH) //The one in the chat plugin is set to highest
|
||||||
public void onTBMCPreprocess(TBMCCommandPreprocessEvent event) {
|
fun onPlayerChat(event: TBMCChatEvent) {
|
||||||
if (event.isCancelled()) return;
|
if (event.isCancelled) return
|
||||||
try {
|
if (!plugin.isChatHandlerEnabled) return
|
||||||
event.setCancelled(ButtonPlugin.getCommand2MC().handleCommand(new Command2MCSender(event.getSender(), event.getChannel(), event.getPermCheck()), event.getMessage()));
|
if (event.origin == "Minecraft") return //Let other plugins handle MC messages
|
||||||
} catch (Exception e) {
|
val channel = event.channel
|
||||||
TBMCCoreAPI.SendException("Command processing failed for sender '" + event.getSender() + "' and message '" + event.getMessage() + "'", e, MainPlugin.Instance);
|
val msg = plugin.chatFormat.get()
|
||||||
}
|
.replace("{channel}", channel.displayName.get())
|
||||||
}
|
.replace("{origin}", event.origin.substring(0, 1))
|
||||||
|
.replace("{name}", ChromaUtils.getDisplayName(event.sender))
|
||||||
@EventHandler(priority = EventPriority.HIGH) //The one in the chat plugin is set to highest
|
.replace("{message}", String.format("§%x%s", channel.color.get().ordinal, event.message))
|
||||||
public void onPlayerChat(AsyncPlayerChatEvent event) {
|
for (player in Bukkit.getOnlinePlayers()) if (event.shouldSendTo(player)) player.sendMessage(msg)
|
||||||
if (event.isCancelled())
|
Bukkit.getConsoleSender().sendMessage(msg)
|
||||||
return; //The chat plugin should cancel it after this handler
|
}
|
||||||
val cp = TBMCPlayer.getPlayer(event.getPlayer().getUniqueId(), TBMCPlayer.class);
|
|
||||||
TBMCChatAPI.SendChatMessage(ChatMessage.builder(event.getPlayer(), cp, event.getMessage()).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
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGH) //The one in the chat plugin is set to highest
|
|
||||||
public void onPlayerChat(TBMCChatEvent event) {
|
|
||||||
if (event.isCancelled())
|
|
||||||
return;
|
|
||||||
if (!MainPlugin.Instance.isChatHandlerEnabled()) return;
|
|
||||||
if (event.getOrigin().equals("Minecraft")) return; //Let other plugins handle MC messages
|
|
||||||
var channel = event.getChannel();
|
|
||||||
String msg = MainPlugin.Instance.chatFormat.get()
|
|
||||||
.replace("{channel}", channel.DisplayName.get())
|
|
||||||
.replace("{origin}", event.getOrigin().substring(0, 1))
|
|
||||||
.replace("{name}", ChromaUtils.getDisplayName(event.getSender()))
|
|
||||||
.replace("{message}", String.format("§%x%s", channel.Color.get().ordinal(), event.getMessage()));
|
|
||||||
for (Player player : Bukkit.getOnlinePlayers())
|
|
||||||
if (event.shouldSendTo(player))
|
|
||||||
player.sendMessage(msg);
|
|
||||||
Bukkit.getConsoleSender().sendMessage(msg);
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,237 +1,231 @@
|
||||||
package buttondevteam.core.component.channel;
|
package buttondevteam.core.component.channel
|
||||||
|
|
||||||
import buttondevteam.core.ComponentManager;
|
import buttondevteam.core.ComponentManager.get
|
||||||
import buttondevteam.core.MainPlugin;
|
import buttondevteam.core.MainPlugin
|
||||||
import buttondevteam.lib.architecture.Component;
|
import buttondevteam.lib.architecture.ConfigData
|
||||||
import buttondevteam.lib.architecture.ConfigData;
|
import buttondevteam.lib.architecture.IHaveConfig
|
||||||
import buttondevteam.lib.architecture.IHaveConfig;
|
import buttondevteam.lib.architecture.ListConfigData
|
||||||
import buttondevteam.lib.chat.Color;
|
import buttondevteam.lib.chat.Color
|
||||||
import com.google.common.collect.Lists;
|
import org.bukkit.Bukkit
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.command.CommandSender
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.entity.Player
|
||||||
import org.bukkit.entity.Player;
|
import java.util.*
|
||||||
|
import java.util.function.Function
|
||||||
import javax.annotation.Nullable;
|
import java.util.function.Predicate
|
||||||
import java.util.ArrayList;
|
import java.util.stream.Stream
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.BiFunction;
|
|
||||||
import java.util.function.BiPredicate;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a chat channel. May only be instantiated after the channel component is registered.
|
* Represents a chat channel. May only be instantiated after the channel component is registered.
|
||||||
*/
|
*/
|
||||||
public class Channel {
|
open class Channel
|
||||||
/**
|
/**
|
||||||
* Specifies a score that means it's OK to send - but it does not define any groups, only send or not send. See {@link #GROUP_EVERYONE}
|
* Creates a channel.
|
||||||
*/
|
*
|
||||||
public static final int SCORE_SEND_OK = 0;
|
* @param filterAndErrorMSG Checks all senders against the criteria provided here and sends the message if the index matches the sender's - if no score at all, displays the error.<br></br>
|
||||||
/**
|
* May be null to send to everyone.
|
||||||
* Specifies a score that means the user doesn't have permission to see or send the message. Any negative value has the same effect.
|
*/(
|
||||||
*/
|
/**
|
||||||
public static final int SCORE_SEND_NOPE = -1;
|
* The name that should appear at the start of the message. **A chat color is expected at the beginning (§9).**
|
||||||
/**
|
*/
|
||||||
* Send the message to everyone <i>who has access to the channel</i> - this does not necessarily mean all players
|
private val defDisplayName: String,
|
||||||
*/
|
/**
|
||||||
public static final String GROUP_EVERYONE = "everyone";
|
* The default color of the messages sent in the channel
|
||||||
|
*/
|
||||||
|
private val defColor: Color,
|
||||||
|
/**
|
||||||
|
* The channel identifier. It's the same as the command to be used for the channel *without / *. For example "mod".
|
||||||
|
* It's also used for scoreboard objective names.
|
||||||
|
*/
|
||||||
|
val identifier: String,
|
||||||
|
/**
|
||||||
|
* A function that determines who has permission to see the channel.
|
||||||
|
* If the sender doesn't have access, they cannot send the message.
|
||||||
|
* Only those with access can see the messages.
|
||||||
|
* If null, everyone has access.
|
||||||
|
*/
|
||||||
|
private val filterAndErrorMSG: Function<CommandSender, RecipientTestResult>?
|
||||||
|
) {
|
||||||
|
private val config: IHaveConfig? = null // TODO: Use this
|
||||||
|
|
||||||
private static ChannelComponent component;
|
@JvmField
|
||||||
|
val isEnabled = component.config.getData("${this.identifier}.enabled", true)
|
||||||
|
|
||||||
private String defDisplayName;
|
/**
|
||||||
private Color defColor;
|
* Must start with a color code
|
||||||
|
*/
|
||||||
|
@JvmField
|
||||||
|
val displayName: ConfigData<String> =
|
||||||
|
component.config.getData("${this.identifier}.displayName", this.defDisplayName)
|
||||||
|
|
||||||
private IHaveConfig config;
|
@JvmField
|
||||||
|
val color: ConfigData<Color> = component.config.getData("${this.identifier}.color",
|
||||||
|
this.defColor, { c -> Color.valueOf((c as String)) }, Color::toString
|
||||||
|
)
|
||||||
|
|
||||||
public final ConfigData<Boolean> Enabled;
|
@JvmField
|
||||||
|
val extraIdentifiers: ListConfigData<String> = component.config.getListData("${this.identifier}.IDs", listOf())
|
||||||
|
|
||||||
/**
|
val isGlobal: Boolean
|
||||||
* Must start with a color code
|
get() = filterAndErrorMSG == null
|
||||||
*/
|
|
||||||
public final ConfigData<String> DisplayName;
|
|
||||||
|
|
||||||
public final ConfigData<Color> Color;
|
/**
|
||||||
public final String ID;
|
* Note: Errors are sent to the sender automatically
|
||||||
|
*
|
||||||
|
* @param sender The user we're sending to
|
||||||
|
* @param score The (source) score to compare with the user's
|
||||||
|
*/
|
||||||
|
fun shouldSendTo(sender: CommandSender, score: Int): Boolean {
|
||||||
|
return score == getMCScore(sender) //If there's any error, the score won't be equal
|
||||||
|
}
|
||||||
|
|
||||||
public ConfigData<String[]> IDs;
|
/**
|
||||||
|
* Note: Errors are sent to the sender automatically
|
||||||
|
*/
|
||||||
|
fun getMCScore(sender: CommandSender): Int {
|
||||||
|
return getRTR(sender).score //No need to check if there was an error
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters both the sender and the targets
|
* Note: Errors are sent to the sender automatically<br></br>
|
||||||
*/
|
*
|
||||||
private final Function<CommandSender, RecipientTestResult> filteranderrormsg;
|
*
|
||||||
|
* Null means don't send
|
||||||
|
*/
|
||||||
|
fun getGroupID(sender: CommandSender): String? {
|
||||||
|
return getRTR(sender).groupID //No need to check if there was an error
|
||||||
|
}
|
||||||
|
|
||||||
private static final List<Channel> channels = new ArrayList<>();
|
fun getRTR(sender: CommandSender): RecipientTestResult {
|
||||||
|
return filterAndErrorMSG?.apply(sender) ?: RecipientTestResult(SCORE_SEND_OK, GROUP_EVERYONE)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
class RecipientTestResult {
|
||||||
* Creates a channel.
|
@JvmField
|
||||||
*
|
val errormessage: String?
|
||||||
* @param displayname The name that should appear at the start of the message. <b>A chat color is expected at the beginning (§9).</b>
|
|
||||||
* @param color The default color of the messages sent in the channel
|
|
||||||
* @param command The command to be used for the channel <i>without /</i>. For example "mod". It's also used for scoreboard objective names.
|
|
||||||
* @param filteranderrormsg Checks all senders against the criteria provided here and sends the message if the index matches the sender's - if no score at all, displays the error.<br>
|
|
||||||
* May be null to send to everyone.
|
|
||||||
*/
|
|
||||||
public Channel(String displayname, Color color, String command,
|
|
||||||
Function<CommandSender, RecipientTestResult> filteranderrormsg) {
|
|
||||||
defDisplayName = displayname;
|
|
||||||
defColor = color;
|
|
||||||
ID = command;
|
|
||||||
this.filteranderrormsg = filteranderrormsg;
|
|
||||||
init();
|
|
||||||
Enabled = component.getConfig().getData(ID + ".enabled", true);
|
|
||||||
DisplayName = component.getConfig().getData(ID + ".displayName", defDisplayName);
|
|
||||||
Color = component.getConfig().getData(ID + ".color", defColor, c -> buttondevteam.lib.chat.Color.valueOf((String) c), Enum::toString);
|
|
||||||
//noinspection unchecked
|
|
||||||
IDs = component.getConfig().getData(ID + ".IDs", new String[0], l -> ((List<String>) l).toArray(new String[0]), Lists::newArrayList);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
@JvmField
|
||||||
* Must be only called from a subclass - otherwise it'll throw an exception.
|
val score // Anything below 0 is "never send"
|
||||||
*
|
: Int
|
||||||
* @see Channel#Channel(String, Color, String, Function)
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected <T extends Channel> Channel(String displayname, Color color, String command,
|
|
||||||
BiFunction<T, CommandSender, RecipientTestResult> filteranderrormsg) {
|
|
||||||
defDisplayName = displayname;
|
|
||||||
defColor = color;
|
|
||||||
ID = command;
|
|
||||||
this.filteranderrormsg = s -> filteranderrormsg.apply((T) this, s);
|
|
||||||
init();
|
|
||||||
Enabled = component.getConfig().getData(ID + ".enabled", true);
|
|
||||||
DisplayName = component.getConfig().getData(ID + ".displayName", defDisplayName);
|
|
||||||
Color = component.getConfig().getData(ID + ".color", defColor, c -> buttondevteam.lib.chat.Color.valueOf((String) c), Enum::toString);
|
|
||||||
//noinspection unchecked
|
|
||||||
IDs = component.getConfig().getData(ID + ".IDs", new String[0], l -> ((List<String>) l).toArray(new String[0]), Lists::newArrayList);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void init() {
|
@JvmField
|
||||||
if (component == null)
|
val groupID: String?
|
||||||
component = (ChannelComponent) Component.getComponents().get(ChannelComponent.class);
|
|
||||||
if (component == null)
|
|
||||||
throw new RuntimeException("Attempting to create a channel before the component is registered!");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isGlobal() {
|
/**
|
||||||
return filteranderrormsg == null;
|
* Creates a result that indicates an **error**
|
||||||
}
|
*
|
||||||
|
* @param errormessage The error message to show the sender if they don't meet the criteria.
|
||||||
|
*/
|
||||||
|
constructor(errormessage: String?) {
|
||||||
|
this.errormessage = errormessage
|
||||||
|
score = SCORE_SEND_NOPE
|
||||||
|
groupID = null
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note: Errors are sent to the sender automatically
|
* Creates a result that indicates a **success**
|
||||||
*
|
*
|
||||||
* @param sender The user we're sending to
|
* @param score The score that identifies the target group. **Must be non-negative.** For example, the index of the town or nation to send to.
|
||||||
* @param score The (source) score to compare with the user's
|
* @param groupID The ID of the target group.
|
||||||
*/
|
*/
|
||||||
public boolean shouldSendTo(CommandSender sender, int score) {
|
constructor(score: Int, groupID: String?) {
|
||||||
return score == getMCScore(sender); //If there's any error, the score won't be equal
|
require(score >= 0) { "Score must be non-negative!" }
|
||||||
}
|
this.score = score
|
||||||
|
this.groupID = groupID
|
||||||
|
errormessage = null
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
companion object {
|
||||||
* Note: Errors are sent to the sender automatically
|
@JvmField
|
||||||
*/
|
val ALL = RecipientTestResult(SCORE_SEND_OK, GROUP_EVERYONE)
|
||||||
public int getMCScore(CommandSender sender) {
|
}
|
||||||
return getRTR(sender).score; //No need to check if there was an error
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
companion object {
|
||||||
* Note: Errors are sent to the sender automatically<br>
|
/**
|
||||||
* <p>
|
* Specifies a score that means it's OK to send - but it does not define any groups, only send or not send. See [.GROUP_EVERYONE]
|
||||||
* Null means don't send
|
*/
|
||||||
*/
|
const val SCORE_SEND_OK = 0
|
||||||
@Nullable
|
|
||||||
public String getGroupID(CommandSender sender) {
|
|
||||||
return getRTR(sender).groupID; //No need to check if there was an error
|
|
||||||
}
|
|
||||||
|
|
||||||
public RecipientTestResult getRTR(CommandSender sender) {
|
/**
|
||||||
if (filteranderrormsg == null)
|
* Specifies a score that means the user doesn't have permission to see or send the message. Any negative value has the same effect.
|
||||||
return new RecipientTestResult(SCORE_SEND_OK, GROUP_EVERYONE);
|
*/
|
||||||
return filteranderrormsg.apply(sender);
|
const val SCORE_SEND_NOPE = -1
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a stream of the enabled channels
|
* Send the message to everyone *who has access to the channel* - this does not necessarily mean all players
|
||||||
*
|
*/
|
||||||
* @return Only the enabled channels
|
const val GROUP_EVERYONE = "everyone"
|
||||||
*/
|
private val component: ChannelComponent by lazy {
|
||||||
public static Stream<Channel> getChannels() {
|
get(ChannelComponent::class.java)
|
||||||
return channels.stream().filter(ch -> ch.Enabled.get());
|
?: throw RuntimeException("Attempting to create a channel before the component is registered!")
|
||||||
}
|
}
|
||||||
|
private val channels: MutableList<Channel> = ArrayList()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return all channels whether they're enabled or not
|
* Get a stream of the enabled channels
|
||||||
*
|
*
|
||||||
* @return A list of all channels
|
* @return Only the enabled channels
|
||||||
*/
|
*/
|
||||||
public static List<Channel> getChannelList() {
|
@JvmStatic
|
||||||
return Collections.unmodifiableList(channels);
|
fun getChannels(): Stream<Channel> {
|
||||||
}
|
return channels.stream().filter { ch: Channel -> ch.isEnabled.get() }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
@JvmStatic
|
||||||
* Convenience method for the function parameter of {@link #Channel(String, Color, String, Function)}. It checks if the sender is OP or optionally has the specified group. The error message is
|
val channelList: List<Channel>
|
||||||
* generated automatically.
|
/**
|
||||||
*
|
* Return all channels whether they're enabled or not
|
||||||
* @param permgroup The group that can access the channel or <b>null</b> to only allow OPs.
|
*
|
||||||
* @return If has access
|
* @return A list of all channels
|
||||||
*/
|
*/
|
||||||
public static Function<CommandSender, RecipientTestResult> inGroupFilter(String permgroup) {
|
get() = Collections.unmodifiableList(channels)
|
||||||
return noScoreResult(
|
|
||||||
s -> s.isOp() || (permgroup != null && (s instanceof Player && MainPlugin.permission != null && MainPlugin.permission.playerInGroup((Player) s, permgroup))),
|
|
||||||
"You need to be a(n) " + (permgroup != null ? permgroup : "OP") + " to use this channel.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Function<CommandSender, RecipientTestResult> noScoreResult(Predicate<CommandSender> filter,
|
/**
|
||||||
String errormsg) {
|
* Convenience method for the function parameter of [.Channel]. It checks if the sender is OP or optionally has the specified group. The error message is
|
||||||
return s -> filter.test(s) ? new RecipientTestResult(SCORE_SEND_OK, GROUP_EVERYONE) : new RecipientTestResult(errormsg);
|
* generated automatically.
|
||||||
}
|
*
|
||||||
|
* @param permgroup The group that can access the channel or **null** to only allow OPs.
|
||||||
|
* @return If has access
|
||||||
|
*/
|
||||||
|
fun inGroupFilter(permgroup: String?): Function<CommandSender, RecipientTestResult> {
|
||||||
|
return noScoreResult(
|
||||||
|
{ s ->
|
||||||
|
s.isOp || s is Player && permgroup?.let { pg ->
|
||||||
|
MainPlugin.permission?.playerInGroup(
|
||||||
|
s,
|
||||||
|
pg
|
||||||
|
)
|
||||||
|
} ?: false
|
||||||
|
},
|
||||||
|
"You need to be a(n) " + (permgroup ?: "OP") + " to use this channel."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
public static <T extends Channel> BiFunction<T, CommandSender, RecipientTestResult> noScoreResult(
|
fun noScoreResult(
|
||||||
BiPredicate<T, CommandSender> filter, String errormsg) {
|
filter: Predicate<CommandSender>,
|
||||||
return (this_, s) -> filter.test(this_, s) ? new RecipientTestResult(SCORE_SEND_OK, GROUP_EVERYONE) : new RecipientTestResult(errormsg);
|
errormsg: String?
|
||||||
}
|
): Function<CommandSender, RecipientTestResult> {
|
||||||
|
return Function { s ->
|
||||||
|
if (filter.test(s)) RecipientTestResult(SCORE_SEND_OK, GROUP_EVERYONE)
|
||||||
|
else RecipientTestResult(errormsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static Channel GlobalChat;
|
@JvmField
|
||||||
public static Channel AdminChat;
|
var GlobalChat: Channel? = null
|
||||||
public static Channel ModChat;
|
var AdminChat: Channel? = null
|
||||||
|
var ModChat: Channel? = null
|
||||||
|
|
||||||
public static void RegisterChannel(Channel channel) {
|
@JvmStatic
|
||||||
if (!channel.isGlobal() && !ComponentManager.isEnabled(ChannelComponent.class))
|
fun registerChannel(channel: Channel) {
|
||||||
return; //Allow registering the global chat (and I guess other chats like the RP chat)
|
if (!channel.isGlobal && !component.isEnabled) return //Allow registering the global chat (and I guess other chats like the RP chat)
|
||||||
channels.add(channel);
|
channels.add(channel)
|
||||||
component.registerChannelCommand(channel);
|
component.registerChannelCommand(channel)
|
||||||
Bukkit.getScheduler().runTask(MainPlugin.Instance, () -> Bukkit.getPluginManager().callEvent(new ChatChannelRegisterEvent(channel))); // Wait for server start
|
Bukkit.getScheduler().runTask(component.plugin,
|
||||||
}
|
Runnable {
|
||||||
|
Bukkit.getPluginManager().callEvent(ChatChannelRegisterEvent(channel))
|
||||||
|
}) // Wait for server start
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class RecipientTestResult {
|
|
||||||
public final String errormessage;
|
|
||||||
public final int score; // Anything below 0 is "never send"
|
|
||||||
public final String groupID;
|
|
||||||
public static final RecipientTestResult ALL = new RecipientTestResult(SCORE_SEND_OK, GROUP_EVERYONE);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a result that indicates an <b>error</b>
|
|
||||||
*
|
|
||||||
* @param errormessage The error message to show the sender if they don't meet the criteria.
|
|
||||||
*/
|
|
||||||
public RecipientTestResult(String errormessage) {
|
|
||||||
this.errormessage = errormessage;
|
|
||||||
this.score = SCORE_SEND_NOPE;
|
|
||||||
this.groupID = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a result that indicates a <b>success</b>
|
|
||||||
*
|
|
||||||
* @param score The score that identifies the target group. <b>Must be non-negative.</b> For example, the index of the town or nation to send to.
|
|
||||||
* @param groupID The ID of the target group.
|
|
||||||
*/
|
|
||||||
public RecipientTestResult(int score, String groupID) {
|
|
||||||
if (score < 0) throw new IllegalArgumentException("Score must be non-negative!");
|
|
||||||
this.score = score;
|
|
||||||
this.groupID = groupID;
|
|
||||||
this.errormessage = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -47,12 +47,12 @@ public class ChannelComponent extends Component<JavaPlugin> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCommandPath() {
|
public String getCommandPath() {
|
||||||
return channel.ID;
|
return channel.identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getCommandPaths() {
|
public String[] getCommandPaths() {
|
||||||
return channel.IDs.get();
|
return channel.extraIdentifiers.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Command2.Subcommand
|
@Command2.Subcommand
|
||||||
|
@ -74,7 +74,7 @@ public class ChannelComponent extends Component<JavaPlugin> {
|
||||||
if (channel instanceof ChatRoom)
|
if (channel instanceof ChatRoom)
|
||||||
((ChatRoom) channel).joinRoom(sender);
|
((ChatRoom) channel).joinRoom(sender);
|
||||||
}
|
}
|
||||||
sender.sendMessage("§6You are now talking in: §b" + user.channel.get().DisplayName.get());
|
sender.sendMessage("§6You are now talking in: §b" + user.channel.get().displayName.get());
|
||||||
} else
|
} else
|
||||||
TBMCChatAPI.SendChatMessage(ChatMessage.builder(sender, user, message).fromCommand(true)
|
TBMCChatAPI.SendChatMessage(ChatMessage.builder(sender, user, message).fromCommand(true)
|
||||||
.permCheck(senderMC.getPermCheck()).build(), channel);
|
.permCheck(senderMC.getPermCheck()).build(), channel);
|
||||||
|
|
|
@ -1,28 +1,35 @@
|
||||||
package buttondevteam.core.component.channel;
|
package buttondevteam.core.component.channel
|
||||||
|
|
||||||
import buttondevteam.lib.TBMCSystemChatEvent;
|
import buttondevteam.lib.TBMCSystemChatEvent
|
||||||
import buttondevteam.lib.chat.Color;
|
import buttondevteam.lib.chat.Color
|
||||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
import buttondevteam.lib.chat.TBMCChatAPI
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender
|
||||||
|
|
||||||
import java.util.ArrayList;
|
class ChatRoom(displayname: String, color: Color, command: String) : Channel(
|
||||||
import java.util.List;
|
displayname, color, command, null // TODO: Custom filter for rooms using abstract method
|
||||||
|
) {
|
||||||
|
private val usersInRoom: MutableList<CommandSender> = ArrayList()
|
||||||
|
private fun isInRoom(sender: CommandSender): Boolean {
|
||||||
|
return usersInRoom.contains(sender)
|
||||||
|
}
|
||||||
|
|
||||||
public class ChatRoom extends Channel {
|
fun joinRoom(sender: CommandSender) {
|
||||||
private final List<CommandSender> usersInRoom = new ArrayList<>();
|
usersInRoom.add(sender)
|
||||||
|
TBMCChatAPI.SendSystemMessage(
|
||||||
|
this,
|
||||||
|
RecipientTestResult.ALL,
|
||||||
|
sender.name + " joined the room",
|
||||||
|
TBMCSystemChatEvent.BroadcastTarget.ALL
|
||||||
|
) //Always show message in the same kind of channel
|
||||||
|
}
|
||||||
|
|
||||||
public ChatRoom(String displayname, Color color, String command) {
|
fun leaveRoom(sender: CommandSender) {
|
||||||
<ChatRoom>super(displayname, color, command, noScoreResult((this_, s) -> this_.usersInRoom.contains(s),
|
usersInRoom.remove(sender)
|
||||||
"Not implemented yet. Please report it to the devs along with which platform you're trying to talk from."));
|
TBMCChatAPI.SendSystemMessage(
|
||||||
}
|
this,
|
||||||
|
RecipientTestResult.ALL,
|
||||||
public void joinRoom(CommandSender sender) {
|
sender.name + " left the room",
|
||||||
usersInRoom.add(sender);
|
ChannelComponent.roomJoinLeave
|
||||||
TBMCChatAPI.SendSystemMessage(this, RecipientTestResult.ALL, sender.getName() + " joined the room", TBMCSystemChatEvent.BroadcastTarget.ALL); //Always show message in the same kind of channel
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public void leaveRoom(CommandSender sender) {
|
|
||||||
usersInRoom.remove(sender);
|
|
||||||
TBMCChatAPI.SendSystemMessage(this, RecipientTestResult.ALL, sender.getName() + " left the room", ChannelComponent.roomJoinLeave);
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -3,7 +3,6 @@ package buttondevteam.lib.architecture
|
||||||
import buttondevteam.buttonproc.HasConfig
|
import buttondevteam.buttonproc.HasConfig
|
||||||
import buttondevteam.core.ComponentManager
|
import buttondevteam.core.ComponentManager
|
||||||
import buttondevteam.lib.TBMCCoreAPI
|
import buttondevteam.lib.TBMCCoreAPI
|
||||||
import buttondevteam.lib.architecture.Component.Companion.updateConfig
|
|
||||||
import buttondevteam.lib.chat.Command2MC
|
import buttondevteam.lib.chat.Command2MC
|
||||||
import buttondevteam.lib.chat.ICommand2MC
|
import buttondevteam.lib.chat.ICommand2MC
|
||||||
import org.bukkit.configuration.InvalidConfigurationException
|
import org.bukkit.configuration.InvalidConfigurationException
|
||||||
|
@ -17,7 +16,8 @@ import java.util.function.Consumer
|
||||||
|
|
||||||
@HasConfig(global = true)
|
@HasConfig(global = true)
|
||||||
abstract class ButtonPlugin : JavaPlugin() {
|
abstract class ButtonPlugin : JavaPlugin() {
|
||||||
protected val iConfig = IHaveConfig { saveConfig() }
|
protected var iConfig = getIConfigInstance()
|
||||||
|
private set
|
||||||
private var yaml: YamlConfiguration? = null
|
private var yaml: YamlConfiguration? = null
|
||||||
|
|
||||||
protected val data //TODO
|
protected val data //TODO
|
||||||
|
@ -52,12 +52,16 @@ abstract class ButtonPlugin : JavaPlugin() {
|
||||||
IHaveConfig.pregenConfig(this, null)
|
IHaveConfig.pregenConfig(this, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getIConfigInstance(): IHaveConfig {
|
||||||
|
return IHaveConfig(
|
||||||
|
::saveConfig,
|
||||||
|
this.config.getConfigurationSection("global") ?: this.config.createSection("global")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun reloadIConfig(): Boolean {
|
private fun reloadIConfig(): Boolean {
|
||||||
val config = config
|
iConfig = getIConfigInstance()
|
||||||
var section = config.getConfigurationSection("global")
|
return isConfigLoaded // If loading fails, getConfig() returns a temporary instance
|
||||||
if (section == null) section = config.createSection("global")
|
|
||||||
iConfig.reset(section)
|
|
||||||
return configLoaded // If loading fails, getConfig() returns a temporary instance
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDisable() {
|
override fun onDisable() {
|
||||||
|
@ -79,7 +83,7 @@ abstract class ButtonPlugin : JavaPlugin() {
|
||||||
fun tryReloadConfig(): Boolean {
|
fun tryReloadConfig(): Boolean {
|
||||||
if (!justReload()) return false
|
if (!justReload()) return false
|
||||||
reloadIConfig()
|
reloadIConfig()
|
||||||
componentStack.forEach(Consumer { c: Component<*>? -> updateConfig(this, c!!) })
|
componentStack.forEach(Consumer { c -> c.updateComponentData() })
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,10 +126,10 @@ abstract class ButtonPlugin : JavaPlugin() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun saveConfig() {
|
override fun saveConfig() {
|
||||||
if (configLoaded) super.saveConfig()
|
if (isConfigLoaded) super.saveConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
val configLoaded get() = yaml != null
|
val isConfigLoaded get() = yaml != null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers command and sets its plugin.
|
* Registers command and sets its plugin.
|
||||||
|
@ -142,6 +146,7 @@ abstract class ButtonPlugin : JavaPlugin() {
|
||||||
annotation class ConfigOpts(val disableConfigGen: Boolean = false)
|
annotation class ConfigOpts(val disableConfigGen: Boolean = false)
|
||||||
companion object {
|
companion object {
|
||||||
//Needs to be static as we don't know the plugin when a command is handled
|
//Needs to be static as we don't know the plugin when a command is handled
|
||||||
|
@JvmStatic
|
||||||
val command2MC = Command2MC()
|
val command2MC = Command2MC()
|
||||||
fun configGenAllowed(obj: Any): Boolean {
|
fun configGenAllowed(obj: Any): Boolean {
|
||||||
return !Optional.ofNullable(obj.javaClass.getAnnotation(ConfigOpts::class.java))
|
return !Optional.ofNullable(obj.javaClass.getAnnotation(ConfigOpts::class.java))
|
||||||
|
|
|
@ -18,10 +18,10 @@ import java.util.stream.Collectors
|
||||||
@HasConfig(global = false) //Used for obtaining javadoc
|
@HasConfig(global = false) //Used for obtaining javadoc
|
||||||
abstract class Component<TP : JavaPlugin> {
|
abstract class Component<TP : JavaPlugin> {
|
||||||
var isEnabled = false
|
var isEnabled = false
|
||||||
private var wrapper: ButtonComponent<TP>? = null
|
internal var componentData: ComponentData<TP>? = null
|
||||||
|
|
||||||
val config get() = wrapper!!.config
|
val config get() = componentData!!.config
|
||||||
val plugin get() = wrapper!!.plugin
|
val plugin get() = componentData!!.plugin
|
||||||
|
|
||||||
private val data //TODO
|
private val data //TODO
|
||||||
: IHaveConfig? = null
|
: IHaveConfig? = null
|
||||||
|
@ -120,11 +120,34 @@ abstract class Component<TP : JavaPlugin> {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
private val className: String
|
private val className: String get() = javaClass.simpleName
|
||||||
get() = javaClass.simpleName
|
|
||||||
|
internal fun updateComponentData(plugin: TP = this.plugin) {
|
||||||
|
componentData = ComponentData(plugin, { plugin.saveConfig() }, this.getConfigSection(plugin))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getConfigSection(plugin: JavaPlugin): ConfigurationSection {
|
||||||
|
var compconf = plugin.config.getConfigurationSection("components")
|
||||||
|
if (compconf == null) compconf = plugin.config.createSection("components")
|
||||||
|
var configSect = compconf.getConfigurationSection(className)
|
||||||
|
if (configSect == null) configSect = compconf.createSection(className)
|
||||||
|
return configSect
|
||||||
|
// TODO: Support tests (provide Bukkit configuration for tests)
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val components = HashMap<Class<out Component<*>>, Component<out JavaPlugin>>()
|
private val _components = HashMap<Class<out Component<*>>, Component<out JavaPlugin>>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the currently registered components<br></br>
|
||||||
|
*
|
||||||
|
* @return The currently registered components
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
val components: Map<Class<out Component<*>>, Component<out JavaPlugin>>
|
||||||
|
get() {
|
||||||
|
return Collections.unmodifiableMap(_components)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a component checking it's dependencies and calling [.register].<br></br>
|
* Registers a component checking it's dependencies and calling [.register].<br></br>
|
||||||
|
@ -178,10 +201,11 @@ abstract class Component<TP : JavaPlugin> {
|
||||||
)
|
)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
val wrapper = ButtonComponent(plugin, { plugin.saveConfig() }, getConfigSection(plugin, component))
|
|
||||||
component.register(plugin)
|
component.register(plugin)
|
||||||
components[component.javaClass] = component
|
// The plugin is saved with this call, so it must be specified
|
||||||
if (plugin is ButtonPlugin) (plugin as ButtonPlugin).componentStack.push(component)
|
component.updateComponentData(plugin)
|
||||||
|
_components[component.javaClass] = component
|
||||||
|
if (plugin is ButtonPlugin) plugin.componentStack.push(component)
|
||||||
if (ComponentManager.areComponentsEnabled() && component.shouldBeEnabled.get()) {
|
if (ComponentManager.areComponentsEnabled() && component.shouldBeEnabled.get()) {
|
||||||
return try { //Enable components registered after the previous ones getting enabled
|
return try { //Enable components registered after the previous ones getting enabled
|
||||||
setComponentEnabled(component, true)
|
setComponentEnabled(component, true)
|
||||||
|
@ -220,7 +244,7 @@ abstract class Component<TP : JavaPlugin> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
component.unregister(plugin)
|
component.unregister(plugin)
|
||||||
components.remove(component.javaClass)
|
_components.remove(component.javaClass)
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
@ -242,7 +266,7 @@ abstract class Component<TP : JavaPlugin> {
|
||||||
if (component.isEnabled == enabled) return //Don't do anything
|
if (component.isEnabled == enabled) return //Don't do anything
|
||||||
if (enabled.also { component.isEnabled = it }) {
|
if (enabled.also { component.isEnabled = it }) {
|
||||||
try {
|
try {
|
||||||
getConfigSection(component.plugin!!, component)
|
component.getConfigSection(component.plugin)
|
||||||
component.enable()
|
component.enable()
|
||||||
if (ButtonPlugin.configGenAllowed(component)) {
|
if (ButtonPlugin.configGenAllowed(component)) {
|
||||||
IHaveConfig.pregenConfig(component, null)
|
IHaveConfig.pregenConfig(component, null)
|
||||||
|
@ -267,24 +291,5 @@ abstract class Component<TP : JavaPlugin> {
|
||||||
ButtonPlugin.command2MC.unregisterCommands(component)
|
ButtonPlugin.command2MC.unregisterCommands(component)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getConfigSection(plugin: JavaPlugin, component: Component<*>): ConfigurationSection {
|
|
||||||
var compconf = plugin.config.getConfigurationSection("components")
|
|
||||||
if (compconf == null) compconf = plugin.config.createSection("components")
|
|
||||||
var configSect = compconf.getConfigurationSection(component.className)
|
|
||||||
if (configSect == null) configSect = compconf.createSection(component.className)
|
|
||||||
return configSect
|
|
||||||
// TODO: Support tests (provide Bukkit configuration for tests)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the currently registered components<br></br>
|
|
||||||
*
|
|
||||||
* @return The currently registered components
|
|
||||||
*/
|
|
||||||
@JvmStatic
|
|
||||||
fun getComponents(): Map<Class<out Component<*>>, Component<out JavaPlugin>> {
|
|
||||||
return Collections.unmodifiableMap(components)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,10 +6,10 @@ import org.bukkit.plugin.java.JavaPlugin
|
||||||
/**
|
/**
|
||||||
* A wrapper for plugin components. This is used internally.
|
* A wrapper for plugin components. This is used internally.
|
||||||
*/
|
*/
|
||||||
class ButtonComponent<TP : JavaPlugin>(
|
class ComponentData<TP : JavaPlugin>(
|
||||||
val plugin: TP,
|
val plugin: TP,
|
||||||
saveAction: Runnable,
|
saveAction: Runnable,
|
||||||
config: ConfigurationSection
|
config: ConfigurationSection
|
||||||
) {
|
) {
|
||||||
val config = IHaveConfig(saveAction, config)
|
val config = IHaveConfig(saveAction, config) // TODO: Use lateinit instead of this class
|
||||||
}
|
}
|
|
@ -82,33 +82,6 @@ class ConfigData<T> internal constructor(
|
||||||
|
|
||||||
private class SaveTask(val task: BukkitTask, val saveAction: Runnable)
|
private class SaveTask(val task: BukkitTask, val saveAction: Runnable)
|
||||||
|
|
||||||
class ConfigDataBuilder<T> internal constructor(
|
|
||||||
private val config: IHaveConfig,
|
|
||||||
private val path: String,
|
|
||||||
private val primitiveDef: Any?,
|
|
||||||
private val getter: Function<Any?, T>,
|
|
||||||
private val setter: Function<T, Any?>
|
|
||||||
) {
|
|
||||||
/**
|
|
||||||
* Builds a modifiable config representation. Use if you want to change the value *in code*.
|
|
||||||
*
|
|
||||||
* @return A ConfigData instance.
|
|
||||||
*/
|
|
||||||
fun build(readOnly: Boolean = false): ConfigData<T> {
|
|
||||||
val config = ConfigData(config, path, primitiveDef, getter, setter, readOnly)
|
|
||||||
this.config.onConfigBuild(config)
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
||||||
fun buildList(readOnly: Boolean = false): ListConfigData<T> {
|
|
||||||
if (primitiveDef is List<*>) {
|
|
||||||
val config = ListConfigData(config, path, primitiveDef, getter, setter, readOnly)
|
|
||||||
this.config.onConfigBuild(config)
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val saveTasks = HashMap<Configuration, SaveTask>()
|
private val saveTasks = HashMap<Configuration, SaveTask>()
|
||||||
fun signalChange(config: IHaveConfig) {
|
fun signalChange(config: IHaveConfig) {
|
||||||
|
@ -147,9 +120,5 @@ class ConfigData<T> internal constructor(
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> builder(config: IHaveConfig, path: String, primitiveDef: Any?, getter: Function<Any?, T>, setter: Function<T, Any?>): ConfigDataBuilder<T> {
|
|
||||||
return ConfigDataBuilder(config, path, primitiveDef, getter, setter)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,7 +2,6 @@ package buttondevteam.lib.architecture
|
||||||
|
|
||||||
import buttondevteam.core.MainPlugin
|
import buttondevteam.core.MainPlugin
|
||||||
import buttondevteam.lib.TBMCCoreAPI
|
import buttondevteam.lib.TBMCCoreAPI
|
||||||
import buttondevteam.lib.architecture.ConfigData.ConfigDataBuilder
|
|
||||||
import buttondevteam.lib.architecture.config.IConfigData
|
import buttondevteam.lib.architecture.config.IConfigData
|
||||||
import org.bukkit.Bukkit
|
import org.bukkit.Bukkit
|
||||||
import org.bukkit.configuration.ConfigurationSection
|
import org.bukkit.configuration.ConfigurationSection
|
||||||
|
@ -11,7 +10,6 @@ import java.lang.reflect.InvocationTargetException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.function.Function
|
import java.util.function.Function
|
||||||
import java.util.function.Predicate
|
import java.util.function.Predicate
|
||||||
import java.util.function.Supplier
|
|
||||||
import java.util.stream.Collectors
|
import java.util.stream.Collectors
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,33 +28,6 @@ class IHaveConfig(
|
||||||
) {
|
) {
|
||||||
private val datamap = HashMap<String, IConfigData<*>>()
|
private val datamap = HashMap<String, IConfigData<*>>()
|
||||||
|
|
||||||
/**
|
|
||||||
* You may use this method with any data type, but always provide getters and setters that convert to primitive types
|
|
||||||
* if you're not using primitive types directly.
|
|
||||||
* These primitive types are strings, numbers, characters, booleans and lists of these things.
|
|
||||||
*
|
|
||||||
* @param path The path in config to use
|
|
||||||
* @param def The value to use by default
|
|
||||||
* @param getter A function that converts a primitive representation to the correct value
|
|
||||||
* @param setter A function that converts a value to a primitive representation
|
|
||||||
* @param primDef Whether the default value is a primitive value that needs to be converted to the correct type using the getter
|
|
||||||
* @param T The type of this variable (can be any class)
|
|
||||||
* @return The data object that can be used to get or set the value
|
|
||||||
*/
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
fun <T> getConfig( // TODO: Remove
|
|
||||||
path: String,
|
|
||||||
def: T,
|
|
||||||
getter: Function<Any?, T>? = null,
|
|
||||||
setter: Function<T, Any?>? = null
|
|
||||||
): ConfigDataBuilder<T> {
|
|
||||||
return ConfigData.builder(this, path, if (setter != null) setter.apply(def) else def, getter ?: Function { it as T }, setter ?: Function { it })
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onConfigBuild(config: IConfigData<*>) {
|
|
||||||
datamap[config.path] = config
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* You may use this method with any data type, but always provide getters and setters that convert to primitive types
|
* You may use this method with any data type, but always provide getters and setters that convert to primitive types
|
||||||
* if you're not using primitive types directly.
|
* if you're not using primitive types directly.
|
||||||
|
@ -109,30 +80,26 @@ class IHaveConfig(
|
||||||
* This method overload should only be used with primitves or String.
|
* This method overload should only be used with primitves or String.
|
||||||
*
|
*
|
||||||
* @param path The path in config to use
|
* @param path The path in config to use
|
||||||
* @param def The value to use by default
|
|
||||||
* @param <T> The type of this variable (only use primitives or String)
|
* @param <T> The type of this variable (only use primitives or String)
|
||||||
* @return The data object that can be used to get or set the value
|
* @return The data object that can be used to get or set the value
|
||||||
</T> */
|
</T> */
|
||||||
fun <T> getData(path: String, def: Supplier<T>): ConfigData<T> { // TODO: Remove
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
fun <T> getListData(
|
||||||
|
path: String,
|
||||||
|
def: List<T>,
|
||||||
|
elementGetter: Function<Any?, T>? = null,
|
||||||
|
elementSetter: Function<T, Any?>? = null,
|
||||||
|
readOnly: Boolean = false
|
||||||
|
): ListConfigData<T> {
|
||||||
var data = datamap[path]
|
var data = datamap[path]
|
||||||
if (data == null) {
|
if (data == null) datamap[path] = ListConfigData(
|
||||||
val defval = def.get()
|
this,
|
||||||
datamap[path] = ConfigData(this, path, defval, defval, null, null).also { data = it }
|
path,
|
||||||
}
|
def,
|
||||||
@Suppress("UNCHECKED_CAST")
|
elementGetter ?: Function { it as T },
|
||||||
return data as ConfigData<T>
|
elementSetter ?: Function { it },
|
||||||
}
|
readOnly
|
||||||
|
).also { data = it }
|
||||||
/**
|
|
||||||
* This method overload should only be used with primitves or String.
|
|
||||||
*
|
|
||||||
* @param path The path in config to use
|
|
||||||
* @param <T> The type of this variable (only use primitives or String)
|
|
||||||
* @return The data object that can be used to get or set the value
|
|
||||||
</T> */
|
|
||||||
fun <T> getListData(path: String): ListConfigData<T> {
|
|
||||||
var data = datamap[path]
|
|
||||||
if (data == null) datamap[path] = ListConfigData(this, path, ListConfigData.List<T>()).also { data = it }
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
return data as ListConfigData<T>
|
return data as ListConfigData<T>
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,11 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
annotation class OptionalArg
|
annotation class OptionalArg
|
||||||
|
|
||||||
protected class ParamConverter<T>(val converter: Function<String, T>, val errormsg: String, val allSupplier: Supplier<Iterable<String>>)
|
protected class ParamConverter<T>(
|
||||||
|
val converter: Function<String, T?>,
|
||||||
|
val errormsg: String,
|
||||||
|
val allSupplier: Supplier<Iterable<String>>
|
||||||
|
)
|
||||||
|
|
||||||
protected val paramConverters = HashMap<Class<*>, ParamConverter<*>>()
|
protected val paramConverters = HashMap<Class<*>, ParamConverter<*>>()
|
||||||
private val commandHelp = ArrayList<String>() //Mainly needed by Discord
|
private val commandHelp = ArrayList<String>() //Mainly needed by Discord
|
||||||
|
@ -70,15 +74,17 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a param converter that obtains a specific object from a string parameter.
|
* Adds a param converter that obtains a specific object from a string parameter.
|
||||||
* The converter may return null.
|
* The converter may return null to signal an error.
|
||||||
*
|
*
|
||||||
* @param <T> The type of the result
|
* @param <T> The type of the result
|
||||||
* @param cl The class of the result object
|
* @param cl The class of the result object
|
||||||
* @param converter The converter to use
|
* @param converter The converter to use
|
||||||
* @param allSupplier The supplier of all possible values (ideally)
|
* @param allSupplier The supplier of all possible values (ideally)
|
||||||
</T> */
|
</T> */
|
||||||
open fun <T> addParamConverter(cl: Class<T>, converter: Function<String, T>, errormsg: String,
|
open fun <T> addParamConverter(
|
||||||
allSupplier: Supplier<Iterable<String>>) {
|
cl: Class<T>, converter: Function<String, T?>, errormsg: String,
|
||||||
|
allSupplier: Supplier<Iterable<String>>
|
||||||
|
) {
|
||||||
paramConverters[cl] = ParamConverter(converter, errormsg, allSupplier)
|
paramConverters[cl] = ParamConverter(converter, errormsg, allSupplier)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,12 @@ class Command2MC : Command2<ICommand2MC, Command2MCSender>('/', true), Listener
|
||||||
* Automatically colors the message red.
|
* Automatically colors the message red.
|
||||||
* {@see super#addParamConverter}
|
* {@see super#addParamConverter}
|
||||||
*/
|
*/
|
||||||
override fun <T> addParamConverter(cl: Class<T>, converter: Function<String, T>, errormsg: String, allSupplier: Supplier<Iterable<String>>) {
|
override fun <T> addParamConverter(
|
||||||
|
cl: Class<T>,
|
||||||
|
converter: Function<String, T?>,
|
||||||
|
errormsg: String,
|
||||||
|
allSupplier: Supplier<Iterable<String>>
|
||||||
|
) {
|
||||||
super.addParamConverter(cl, converter, "§c$errormsg", allSupplier)
|
super.addParamConverter(cl, converter, "§c$errormsg", allSupplier)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +218,7 @@ class Command2MC : Command2<ICommand2MC, Command2MCSender>('/', true), Listener
|
||||||
|
|
||||||
private class BukkitCommand(name: String?) : Command(name) {
|
private class BukkitCommand(name: String?) : Command(name) {
|
||||||
override fun execute(sender: CommandSender, commandLabel: String, args: Array<String>): Boolean {
|
override fun execute(sender: CommandSender, commandLabel: String, args: Array<String>): Boolean {
|
||||||
return ButtonPlugin.getCommand2MC().executeCommand(sender, this, commandLabel, args)
|
return ButtonPlugin.command2MC.executeCommand(sender, this, commandLabel, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(IllegalArgumentException::class)
|
@Throws(IllegalArgumentException::class)
|
||||||
|
@ -312,10 +317,9 @@ class Command2MC : Command2<ICommand2MC, Command2MCSender>('/', true), Listener
|
||||||
j++
|
j++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
//Break if converter is not found or for example, the player provided an invalid plugin name
|
||||||
val converter = getParamConverter(params[j].type, command2MC) ?: break
|
val converter = getParamConverter(params[j].type, command2MC) ?: break
|
||||||
val paramValue = converter.converter.apply(paramValueString)
|
val paramValue = converter.converter.apply(paramValueString) ?: break
|
||||||
?: //For example, the player provided an invalid plugin name
|
|
||||||
break
|
|
||||||
args[j] = paramValue
|
args[j] = paramValue
|
||||||
k++ //Only increment if not CommandSender
|
k++ //Only increment if not CommandSender
|
||||||
j++
|
j++
|
||||||
|
|
|
@ -35,9 +35,9 @@ public class TBMCChatAPI {
|
||||||
*/
|
*/
|
||||||
public static boolean SendChatMessage(ChatMessage cm, Channel channel) {
|
public static boolean SendChatMessage(ChatMessage cm, Channel channel) {
|
||||||
if (!Channel.getChannelList().contains(channel))
|
if (!Channel.getChannelList().contains(channel))
|
||||||
throw new RuntimeException("Channel " + channel.DisplayName.get() + " not registered!");
|
throw new RuntimeException("Channel " + channel.getDisplayName().get() + " not registered!");
|
||||||
if (!channel.Enabled.get()) {
|
if (!channel.isEnabled.get()) {
|
||||||
cm.getSender().sendMessage("§cThe channel '" + channel.DisplayName.get() + "' is disabled!");
|
cm.getSender().sendMessage("§cThe channel '" + channel.displayName.get() + "' is disabled!");
|
||||||
return true; //Cancel sending if channel is disabled
|
return true; //Cancel sending if channel is disabled
|
||||||
}
|
}
|
||||||
Supplier<Boolean> task = () -> {
|
Supplier<Boolean> task = () -> {
|
||||||
|
@ -70,11 +70,11 @@ public class TBMCChatAPI {
|
||||||
*/
|
*/
|
||||||
public static boolean SendSystemMessage(Channel channel, RecipientTestResult rtr, String message, TBMCSystemChatEvent.BroadcastTarget target, String... exceptions) {
|
public static boolean SendSystemMessage(Channel channel, RecipientTestResult rtr, String message, TBMCSystemChatEvent.BroadcastTarget target, String... exceptions) {
|
||||||
if (!Channel.getChannelList().contains(channel))
|
if (!Channel.getChannelList().contains(channel))
|
||||||
throw new RuntimeException("Channel " + channel.DisplayName.get() + " not registered!");
|
throw new RuntimeException("Channel " + channel.displayName.get() + " not registered!");
|
||||||
if (!channel.Enabled.get())
|
if (!channel.enabled.get())
|
||||||
return true; //Cancel sending
|
return true; //Cancel sending
|
||||||
if (!Arrays.asList(exceptions).contains("Minecraft"))
|
if (!Arrays.asList(exceptions).contains("Minecraft"))
|
||||||
Bukkit.getConsoleSender().sendMessage("[" + channel.DisplayName.get() + "] " + message);
|
Bukkit.getConsoleSender().sendMessage("[" + channel.displayName.get() + "] " + message);
|
||||||
TBMCSystemChatEvent event = new TBMCSystemChatEvent(channel, message, rtr.score, rtr.groupID, exceptions, target);
|
TBMCSystemChatEvent event = new TBMCSystemChatEvent(channel, message, rtr.score, rtr.groupID, exceptions, target);
|
||||||
return ChromaUtils.callEventAsync(event);
|
return ChromaUtils.callEventAsync(event);
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,6 @@ public class TBMCChatAPI {
|
||||||
* @param channel A new {@link Channel} to register
|
* @param channel A new {@link Channel} to register
|
||||||
*/
|
*/
|
||||||
public static void RegisterChatChannel(Channel channel) {
|
public static void RegisterChatChannel(Channel channel) {
|
||||||
Channel.RegisterChannel(channel);
|
Channel.registerChannel(channel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -313,5 +313,5 @@ public abstract class ChromaGamerBase {
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
|
|
||||||
public final ConfigData<Channel> channel = config.getData("channel", Channel.GlobalChat,
|
public final ConfigData<Channel> channel = config.getData("channel", Channel.GlobalChat,
|
||||||
id -> Channel.getChannels().filter(ch -> ch.ID.equalsIgnoreCase((String) id)).findAny().orElse(null), ch -> ch.ID);
|
id -> Channel.getChannels().filter(ch -> ch.identifier.equalsIgnoreCase((String) id)).findAny().orElse(null), ch -> ch.ID);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue