Merge pull request #90 from TBMCPlugins/dev
Configuration comments, fixes, command and other fixes
This commit is contained in:
commit
d48a2d17d3
38 changed files with 736 additions and 778 deletions
|
@ -46,17 +46,17 @@
|
||||||
<bytecodeTargetLevel>
|
<bytecodeTargetLevel>
|
||||||
<module name="BuildConfigUpdater" target="8" />
|
<module name="BuildConfigUpdater" target="8" />
|
||||||
<module name="ButtonCore" target="1.5" />
|
<module name="ButtonCore" target="1.5" />
|
||||||
<module name="ButtonCore (1) (com.github.TBMCPlugins.ButtonCore)" target="13" />
|
<module name="ButtonCore (1) (com.github.TBMCPlugins.ButtonCore)" target="11" />
|
||||||
<module name="ButtonProcessor" target="8" />
|
<module name="ButtonProcessor" target="8" />
|
||||||
<module name="ChunkArchive" target="1.8" />
|
<module name="ChunkArchive" target="1.8" />
|
||||||
<module name="CorePOM" target="13" />
|
<module name="CorePOM" target="11" />
|
||||||
<module name="RandomTeleport" target="1.8" />
|
<module name="RandomTeleport" target="1.8" />
|
||||||
</bytecodeTargetLevel>
|
</bytecodeTargetLevel>
|
||||||
</component>
|
</component>
|
||||||
<component name="JavacSettings">
|
<component name="JavacSettings">
|
||||||
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
|
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
|
||||||
<module name="BuildConfigUpdater" options="" />
|
<module name="BuildConfigUpdater" options="" />
|
||||||
<module name="ButtonCore (1) (com.github.TBMCPlugins.ButtonCore)" options="--enable-preview" />
|
<module name="ButtonCore (1) (com.github.TBMCPlugins.ButtonCore)" options="" />
|
||||||
<module name="ButtonProcessor" options="-proc:none" />
|
<module name="ButtonProcessor" options="-proc:none" />
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
|
|
|
@ -1,107 +0,0 @@
|
||||||
package buttondevteam.core;
|
|
||||||
|
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
|
||||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
|
||||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
|
||||||
import org.bukkit.command.Command;
|
|
||||||
import org.bukkit.command.CommandExecutor;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.command.PluginCommand;
|
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public class CommandCaller implements CommandExecutor {
|
|
||||||
|
|
||||||
private CommandCaller() {
|
|
||||||
}
|
|
||||||
|
|
||||||
private static CommandCaller instance;
|
|
||||||
|
|
||||||
public static void RegisterCommand(TBMCCommandBase cmd) throws Exception {
|
|
||||||
if (instance == null)
|
|
||||||
instance = new CommandCaller();
|
|
||||||
String[] topcmd = new String[1]; //Holds out param
|
|
||||||
PluginCommand pc = getPluginCommand(cmd, topcmd);
|
|
||||||
pc.setExecutor(instance);
|
|
||||||
String[] helptext = cmd.GetHelpText(topcmd[0]);
|
|
||||||
if (helptext == null || helptext.length == 0)
|
|
||||||
throw new Exception("Command " + cmd.GetCommandPath() + " has no help text!");
|
|
||||||
pc.setUsage(helptext.length > 1 ? helptext[1] : helptext[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCommand(CommandSender sender, Command command, String alias, String[] args) {
|
|
||||||
StringBuilder path = new StringBuilder(command.getName().toLowerCase());
|
|
||||||
for (String arg : args)
|
|
||||||
path.append(" ").append(arg);
|
|
||||||
TBMCCommandBase cmd = TBMCChatAPI.GetCommands().get(path.toString());
|
|
||||||
int argc = 0;
|
|
||||||
String[] subcmds = null;
|
|
||||||
while (cmd == null && (subcmds = TBMCChatAPI.GetSubCommands(path.toString(), sender)).length == 0 && path.toString().contains(" ")) {
|
|
||||||
path = new StringBuilder(path.substring(0, path.toString().lastIndexOf(' ')));
|
|
||||||
argc++;
|
|
||||||
cmd = TBMCChatAPI.GetCommands().get(path.toString());
|
|
||||||
}
|
|
||||||
if (cmd == null) {
|
|
||||||
if (subcmds.length > 0) //Subcmds will always have value here (see assignment above)
|
|
||||||
sender.sendMessage(subcmds);
|
|
||||||
else {
|
|
||||||
final String errormsg = "§cYou don't have access to any of this command's subcommands or it doesn't have any.";
|
|
||||||
sender.sendMessage(errormsg);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (cmd.isModOnly() && (MainPlugin.permission != null ? !MainPlugin.permission.has(sender, "tbmc.admin") : !sender.isOp())) {
|
|
||||||
sender.sendMessage("§cYou need to be a mod to use this command.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
final String[] cmdargs = args.length > 0 ? Arrays.copyOfRange(args, args.length - argc, args.length) : args;
|
|
||||||
try {
|
|
||||||
if (!cmd.OnCommand(sender, alias, cmdargs)) {
|
|
||||||
if (cmd.GetHelpText(alias) == null) {
|
|
||||||
sender.sendMessage("Wrong usage, but there's no help text! Error is being reported to devs.");
|
|
||||||
throw new NullPointerException("GetHelpText is null for comand /" + cmd.GetCommandPath());
|
|
||||||
} else
|
|
||||||
sender.sendMessage(cmd.GetHelpText(alias));
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
TBMCCoreAPI.SendException("Failed to execute command /" + cmd.GetCommandPath() + " with arguments "
|
|
||||||
+ Arrays.toString(cmdargs), e);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void UnregisterCommand(TBMCCommandBase cmd) throws Exception {
|
|
||||||
PluginCommand pc = getPluginCommand(cmd, null);
|
|
||||||
pc.setExecutor(null); //Sets the executor to this plugin
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the plugin command from the TBMC command.
|
|
||||||
*
|
|
||||||
* @param cmd The TBMC command
|
|
||||||
* @param out_topcmd An array with at least 1 elements or null
|
|
||||||
* @return The Bukkit plugin command - an exception is generated if null
|
|
||||||
* @throws Exception If the command isn't set up properly (or a different error)
|
|
||||||
*/
|
|
||||||
public static PluginCommand getPluginCommand(TBMCCommandBase cmd, String[] out_topcmd) throws Exception {
|
|
||||||
String topcmd = cmd.GetCommandPath();
|
|
||||||
if (topcmd == null)
|
|
||||||
throw new Exception("Command " + cmd.getClass().getSimpleName() + " has no command path!");
|
|
||||||
if (cmd.getPlugin() == null)
|
|
||||||
throw new Exception("Command " + cmd.GetCommandPath() + " has no plugin!");
|
|
||||||
int i;
|
|
||||||
if ((i = topcmd.indexOf(' ')) != -1) // Get top-level command
|
|
||||||
topcmd = topcmd.substring(0, i);
|
|
||||||
if (out_topcmd != null && out_topcmd.length > 0)
|
|
||||||
out_topcmd[0] = topcmd;
|
|
||||||
{
|
|
||||||
PluginCommand pc = ((JavaPlugin) cmd.getPlugin()).getCommand(topcmd);
|
|
||||||
if (pc == null)
|
|
||||||
throw new Exception("Top level command " + topcmd + " not registered in plugin.yml for plugin: "
|
|
||||||
+ cmd.getPlugin().getName());
|
|
||||||
return pc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -23,21 +23,33 @@ public class ComponentCommand extends ICommand2MC {
|
||||||
getManager().addParamConverter(Plugin.class, arg -> Bukkit.getPluginManager().getPlugin(arg), "Plugin not found!");
|
getManager().addParamConverter(Plugin.class, arg -> Bukkit.getPluginManager().getPlugin(arg), "Plugin not found!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subcommand
|
@Subcommand(helpText = {
|
||||||
|
"Enable component",
|
||||||
|
"Temporarily enables a component. If you want to permanently enable a component, change it's 'enabled' config option.\""
|
||||||
|
})
|
||||||
public boolean enable(CommandSender sender, Plugin plugin, String component) {
|
public boolean enable(CommandSender sender, Plugin plugin, String component) {
|
||||||
if (plugin instanceof ButtonPlugin)
|
if (plugin instanceof ButtonPlugin) {
|
||||||
((ButtonPlugin) plugin).justReload();
|
if (!((ButtonPlugin) plugin).justReload()) {
|
||||||
else
|
sender.sendMessage("§cCouldn't reload config, check console.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else
|
||||||
plugin.reloadConfig(); //Reload config so the new config values are read - All changes are saved to disk on disable
|
plugin.reloadConfig(); //Reload config so the new config values are read - All changes are saved to disk on disable
|
||||||
return enable_disable(sender, plugin, component, true);
|
return enable_disable(sender, plugin, component, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subcommand
|
@Subcommand(helpText = {
|
||||||
|
"Disable component",
|
||||||
|
"Temporarily disables a component. If you want to permanently disable a component, change it's 'enabled' config option."
|
||||||
|
})
|
||||||
public boolean disable(CommandSender sender, Plugin plugin, String component) {
|
public boolean disable(CommandSender sender, Plugin plugin, String component) {
|
||||||
return enable_disable(sender, plugin, component, false);
|
return enable_disable(sender, plugin, component, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subcommand
|
@Subcommand(helpText = {
|
||||||
|
"List components",
|
||||||
|
"Lists all of the registered Chroma components"
|
||||||
|
})
|
||||||
public boolean list(CommandSender sender, @Command2.OptionalArg String plugin) {
|
public boolean list(CommandSender sender, @Command2.OptionalArg String plugin) {
|
||||||
sender.sendMessage("§6List of components:");
|
sender.sendMessage("§6List of components:");
|
||||||
Component.getComponents().values().stream().filter(c -> plugin == null || c.getPlugin().getName().equalsIgnoreCase(plugin)) //If plugin is null, don't check
|
Component.getComponents().values().stream().filter(c -> plugin == null || c.getPlugin().getName().equalsIgnoreCase(plugin)) //If plugin is null, don't check
|
||||||
|
|
|
@ -47,6 +47,7 @@ import java.util.logging.Logger;
|
||||||
public class MainPlugin extends ButtonPlugin {
|
public class MainPlugin extends ButtonPlugin {
|
||||||
public static MainPlugin Instance;
|
public static MainPlugin Instance;
|
||||||
public static Permission permission;
|
public static Permission permission;
|
||||||
|
@Nullable
|
||||||
public static Essentials ess;
|
public static Essentials ess;
|
||||||
|
|
||||||
private Logger logger;
|
private Logger logger;
|
||||||
|
@ -60,19 +61,38 @@ public class MainPlugin extends ButtonPlugin {
|
||||||
@Setter
|
@Setter
|
||||||
private boolean chatHandlerEnabled = true;
|
private boolean chatHandlerEnabled = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the plugin should write a list of installed plugins in a txt file.
|
||||||
|
* It can be useful if some other software needs to know the plugins.
|
||||||
|
*/
|
||||||
private ConfigData<Boolean> writePluginList() {
|
private ConfigData<Boolean> writePluginList() {
|
||||||
return getIConfig().getData("writePluginList", false);
|
return getIConfig().getData("writePluginList", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The chat format to use for messages from other platforms if Chroma-Chat is not installed.
|
||||||
|
*/
|
||||||
ConfigData<String> chatFormat() {
|
ConfigData<String> chatFormat() {
|
||||||
return getIConfig().getData("chatFormat", "[{origin}|" +
|
return getIConfig().getData("chatFormat", "[{origin}|" +
|
||||||
"{channel}] <{name}> {message}");
|
"{channel}] <{name}> {message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print some debug information.
|
||||||
|
*/
|
||||||
public ConfigData<Boolean> test() {
|
public ConfigData<Boolean> test() {
|
||||||
return getIConfig().getData("test", true);
|
return getIConfig().getData("test", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* By default, the plugin uses Vault for all command permission checks, but this can have issues (with PEX for example) where default permissions aren't granted.
|
||||||
|
* When this setting is off, the plugin uses Bukkit's built-in way of handling permissions, which usually works fine for players.
|
||||||
|
* You can also grant chroma.command.* to each player (mod-only commands need another permission, chroma.mod).
|
||||||
|
*/
|
||||||
|
/*public ConfigData<Boolean> useVaultForCommands() {
|
||||||
|
return getIConfig().getData("useVaultForCommands", true);
|
||||||
|
}*/
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pluginEnable() {
|
public void pluginEnable() {
|
||||||
// Logs "Plugin Enabled", registers commands
|
// Logs "Plugin Enabled", registers commands
|
||||||
|
@ -90,6 +110,7 @@ public class MainPlugin extends ButtonPlugin {
|
||||||
Component.registerComponent(this, new ChannelComponent());
|
Component.registerComponent(this, new ChannelComponent());
|
||||||
Component.registerComponent(this, new RandomTPComponent());
|
Component.registerComponent(this, new RandomTPComponent());
|
||||||
Component.registerComponent(this, new MemberComponent());
|
Component.registerComponent(this, new MemberComponent());
|
||||||
|
if (Bukkit.getPluginManager().isPluginEnabled("Multiverse-Core"))
|
||||||
Component.registerComponent(this, new SpawnComponent());
|
Component.registerComponent(this, new SpawnComponent());
|
||||||
if (Bukkit.getPluginManager().isPluginEnabled("Towny")) //It fails to load the component class otherwise
|
if (Bukkit.getPluginManager().isPluginEnabled("Towny")) //It fails to load the component class otherwise
|
||||||
Component.registerComponent(this, new TownyComponent());
|
Component.registerComponent(this, new TownyComponent());
|
||||||
|
@ -124,6 +145,7 @@ public class MainPlugin extends ButtonPlugin {
|
||||||
TBMCCoreAPI.SendException("Failed to write plugin list!", e);
|
TBMCCoreAPI.SendException("Failed to write plugin list!", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (getServer().getPluginManager().isPluginEnabled("Essentials"))
|
||||||
ess = Essentials.getPlugin(Essentials.class);
|
ess = Essentials.getPlugin(Essentials.class);
|
||||||
logger.info(pdf.getName() + " has been Enabled (V." + pdf.getVersion() + ") Test: " + test().get() + ".");
|
logger.info(pdf.getName() + " has been Enabled (V." + pdf.getVersion() + ") Test: " + test().get() + ".");
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package buttondevteam.core.component.members;
|
||||||
|
|
||||||
import buttondevteam.core.MainPlugin;
|
import buttondevteam.core.MainPlugin;
|
||||||
import buttondevteam.lib.architecture.Component;
|
import buttondevteam.lib.architecture.Component;
|
||||||
|
import buttondevteam.lib.architecture.ComponentMetadata;
|
||||||
import buttondevteam.lib.architecture.ConfigData;
|
import buttondevteam.lib.architecture.ConfigData;
|
||||||
import org.bukkit.Statistic;
|
import org.bukkit.Statistic;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
|
@ -18,6 +19,7 @@ import static buttondevteam.core.MainPlugin.permission;
|
||||||
/**
|
/**
|
||||||
* Allows giving a 'member' group over some time elapsed OR played.
|
* Allows giving a 'member' group over some time elapsed OR played.
|
||||||
*/
|
*/
|
||||||
|
@ComponentMetadata(enabledByDefault = false)
|
||||||
public class MemberComponent extends Component<MainPlugin> implements Listener {
|
public class MemberComponent extends Component<MainPlugin> implements Listener {
|
||||||
/**
|
/**
|
||||||
* The permission group to give to the player
|
* The permission group to give to the player
|
||||||
|
@ -62,12 +64,16 @@ public class MemberComponent extends Component<MainPlugin> implements Listener {
|
||||||
if (permission != null && !permission.playerInGroup(event.getPlayer(), memberGroup().get())
|
if (permission != null && !permission.playerInGroup(event.getPlayer(), memberGroup().get())
|
||||||
&& (new Date(event.getPlayer().getFirstPlayed()).toInstant().plus(registeredForDays().get(), ChronoUnit.DAYS).isBefore(Instant.now())
|
&& (new Date(event.getPlayer().getFirstPlayed()).toInstant().plus(registeredForDays().get(), ChronoUnit.DAYS).isBefore(Instant.now())
|
||||||
|| event.getPlayer().getStatistic(playtime.getKey()) > playtime.getValue() * playedHours().get())) {
|
|| event.getPlayer().getStatistic(playtime.getKey()) > playtime.getValue() * playedHours().get())) {
|
||||||
|
try {
|
||||||
if (permission.playerAddGroup(null, event.getPlayer(), memberGroup().get())) {
|
if (permission.playerAddGroup(null, event.getPlayer(), memberGroup().get())) {
|
||||||
event.getPlayer().sendMessage("§bYou are a member now. YEEHAW");
|
event.getPlayer().sendMessage("§bYou are a member now. YEEHAW");
|
||||||
MainPlugin.Instance.getLogger().info("Added " + event.getPlayer().getName() + " as a member.");
|
MainPlugin.Instance.getLogger().info("Added " + event.getPlayer().getName() + " as a member.");
|
||||||
} else {
|
} else {
|
||||||
MainPlugin.Instance.getLogger().warning("Failed to assign the member role! Please make sure the member group exists or disable the component if it's unused.");
|
MainPlugin.Instance.getLogger().warning("Failed to assign the member role! Please make sure the member group exists or disable the component if it's unused.");
|
||||||
}
|
}
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
MainPlugin.Instance.getLogger().warning("Failed to assign the member role! Groups are not supported by the permissions implementation.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,20 @@
|
||||||
package buttondevteam.core.component.randomtp;
|
package buttondevteam.core.component.randomtp;
|
||||||
|
|
||||||
import buttondevteam.lib.architecture.Component;
|
import buttondevteam.lib.chat.Command2;
|
||||||
import buttondevteam.lib.chat.CommandClass;
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
import buttondevteam.lib.chat.ICommand2MC;
|
||||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
|
||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
@SuppressWarnings("FieldCanBeLocal")@CommandClass
|
@SuppressWarnings("FieldCanBeLocal")@CommandClass(helpText = {
|
||||||
public class RandomTP extends TBMCCommandBase
|
"§6---- Random Teleport ----",
|
||||||
|
"Teleport player to random location within world border. Every five players teleport to the same general area, and then a new general area is randomly selected for the next five players."
|
||||||
|
})
|
||||||
|
public class RandomTP extends ICommand2MC
|
||||||
{
|
{
|
||||||
private final int radius = 70; //set how far apart the five teleport positions are
|
private final int radius = 70; //set how far apart the five teleport positions are
|
||||||
|
|
||||||
|
@ -51,37 +55,23 @@ public class RandomTP extends TBMCCommandBase
|
||||||
|
|
||||||
/*================================================================================================*/
|
/*================================================================================================*/
|
||||||
|
|
||||||
public void onEnable(Component component)
|
public void onEnable(RandomTPComponent component)
|
||||||
{
|
{
|
||||||
System.out.println("Adding command");
|
|
||||||
TBMCChatAPI.AddCommand(component, this);
|
|
||||||
|
|
||||||
System.out.println("Getting world");
|
|
||||||
world = Bukkit.getWorld("World");
|
world = Bukkit.getWorld("World");
|
||||||
System.out.println("Getting border");
|
|
||||||
border = world.getWorldBorder();
|
border = world.getWorldBorder();
|
||||||
System.out.println("Getting new location");
|
Logger logger = component.getPlugin().getLogger();
|
||||||
System.out.println("Success: "+newLocation()); //TODO: It takes 10-30 seconds to find a location (newLocation() was there)
|
logger.info("Getting new location");
|
||||||
|
if(border.getSize() > 100000)
|
||||||
|
logger.warning("World border is wide, it may take a minute...");
|
||||||
|
logger.info("Success: "+newLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*================================================================================================*/
|
/*================================================================================================*/
|
||||||
|
|
||||||
public String[] GetHelpText(String alias)
|
@Command2.Subcommand
|
||||||
|
public boolean def(CommandSender sender, Player player)
|
||||||
{
|
{
|
||||||
return new String[]
|
if (sender.isOp()) return rtp(player);
|
||||||
{
|
|
||||||
"§6---- Random Teleport ----",
|
|
||||||
"Teleport player to random location within world border. Every five players teleport to the same general area, and then a new general area is randomly selected for the next five players."
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*================================================================================================*/
|
|
||||||
|
|
||||||
public boolean OnCommand(CommandSender sender, String command, String[] args)
|
|
||||||
{
|
|
||||||
if (args.length == 0) return false;
|
|
||||||
|
|
||||||
if (sender.isOp()) return rtp(Bukkit.getPlayer(args[0]));
|
|
||||||
|
|
||||||
else sender.sendMessage("§7 hmm, " + sender.getName() + "... " + sender.getName() + "... nope, no operator permissions.");
|
else sender.sendMessage("§7 hmm, " + sender.getName() + "... " + sender.getName() + "... nope, no operator permissions.");
|
||||||
|
|
||||||
|
|
|
@ -2,15 +2,20 @@ package buttondevteam.core.component.randomtp;
|
||||||
|
|
||||||
import buttondevteam.core.MainPlugin;
|
import buttondevteam.core.MainPlugin;
|
||||||
import buttondevteam.lib.architecture.Component;
|
import buttondevteam.lib.architecture.Component;
|
||||||
|
import buttondevteam.lib.architecture.ComponentMetadata;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Teleport player to random location within world border.
|
* Teleport player to random location within world border.
|
||||||
* Every five players teleport to the same general area, and then a new general area is randomly selected for the next five players.
|
* Every five players teleport to the same general area, and then a new general area is randomly selected for the next five players.
|
||||||
|
* Author: github.com/iiegit
|
||||||
*/
|
*/
|
||||||
|
@ComponentMetadata(enabledByDefault = false)
|
||||||
public class RandomTPComponent extends Component<MainPlugin> {
|
public class RandomTPComponent extends Component<MainPlugin> {
|
||||||
@Override
|
@Override
|
||||||
protected void enable() {
|
protected void enable() {
|
||||||
new RandomTP().onEnable(this); //It registers it's command
|
var rtp = new RandomTP();
|
||||||
|
registerCommand(rtp);
|
||||||
|
rtp.onEnable(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,22 +1,28 @@
|
||||||
package buttondevteam.core.component.restart;
|
package buttondevteam.core.component.restart;
|
||||||
|
|
||||||
import buttondevteam.core.component.channel.Channel;
|
import buttondevteam.core.component.channel.Channel;
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
import buttondevteam.lib.chat.CommandClass;
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import buttondevteam.lib.chat.ICommand2MC;
|
||||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
@CommandClass(path = "primerestart", modOnly = true)
|
@CommandClass(path = "primerestart", modOnly = true, helpText = {
|
||||||
|
"§6---- Prime restart ----", //
|
||||||
|
"Restarts the server as soon as nobody is online.", //
|
||||||
|
"To be loud, type something after, like /primerestart lol (it doesn't matter what you write)", //
|
||||||
|
"To be silent, don't type anything" //
|
||||||
|
})
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class PrimeRestartCommand extends TBMCCommandBase {
|
public class PrimeRestartCommand extends ICommand2MC {
|
||||||
private final RestartComponent component;
|
private final RestartComponent component;
|
||||||
@Override
|
|
||||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
public void def(CommandSender sender, @Command2.TextArg @Command2.OptionalArg String somethingrandom) {
|
||||||
loud = args.length > 0;
|
loud = somethingrandom != null;
|
||||||
if (Bukkit.getOnlinePlayers().size() > 0) {
|
if (Bukkit.getOnlinePlayers().size() > 0) {
|
||||||
sender.sendMessage("§bPlayers online, restart delayed.");
|
sender.sendMessage("§bPlayers online, restart delayed.");
|
||||||
if (loud)
|
if (loud)
|
||||||
|
@ -28,21 +34,10 @@ public class PrimeRestartCommand extends TBMCCommandBase {
|
||||||
TBMCChatAPI.SendSystemMessage(Channel.GlobalChat, Channel.RecipientTestResult.ALL, "§cNobody is online. Restarting server.", component.getRestartBroadcast());
|
TBMCChatAPI.SendSystemMessage(Channel.GlobalChat, Channel.RecipientTestResult.ALL, "§cNobody is online. Restarting server.", component.getRestartBroadcast());
|
||||||
Bukkit.spigot().restart();
|
Bukkit.spigot().restart();
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private static boolean plsrestart = false;
|
private static boolean plsrestart = false;
|
||||||
@Getter
|
@Getter
|
||||||
private static boolean loud = false;
|
private static boolean loud = false;
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[]{ //
|
|
||||||
"§6---- Prime restart ----", //
|
|
||||||
"Restarts the server as soon as nobody is online.", //
|
|
||||||
"To be loud, type something after, like /primerestart lol (it doesn't matter what you write)", //
|
|
||||||
"To be silent, don't type anything" //
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ public class RestartComponent extends Component<MainPlugin> implements Listener
|
||||||
@Override
|
@Override
|
||||||
public void enable() {
|
public void enable() {
|
||||||
registerCommand(new ScheduledRestartCommand(this));
|
registerCommand(new ScheduledRestartCommand(this));
|
||||||
TBMCChatAPI.AddCommand(this, new PrimeRestartCommand(this));
|
registerCommand(new PrimeRestartCommand(this));
|
||||||
registerListener(this);
|
registerListener(this);
|
||||||
restartBroadcast = TBMCSystemChatEvent.BroadcastTarget.add("restartCountdown");
|
restartBroadcast = TBMCSystemChatEvent.BroadcastTarget.add("restartCountdown");
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import buttondevteam.lib.architecture.ConfigData;
|
||||||
import buttondevteam.lib.chat.Command2;
|
import buttondevteam.lib.chat.Command2;
|
||||||
import buttondevteam.lib.chat.CommandClass;
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
import buttondevteam.lib.chat.ICommand2MC;
|
import buttondevteam.lib.chat.ICommand2MC;
|
||||||
|
import com.earth2me.essentials.Trade;
|
||||||
import com.google.common.io.ByteArrayDataInput;
|
import com.google.common.io.ByteArrayDataInput;
|
||||||
import com.google.common.io.ByteArrayDataOutput;
|
import com.google.common.io.ByteArrayDataOutput;
|
||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
|
@ -13,10 +14,15 @@ import com.onarandombox.MultiverseCore.MultiverseCore;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||||
import org.bukkit.plugin.messaging.PluginMessageListener;
|
import org.bukkit.plugin.messaging.PluginMessageListener;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a /spawn command that works with BungeeCord. Make sure to set up on each server.
|
||||||
|
*/
|
||||||
public class SpawnComponent extends Component<MainPlugin> implements PluginMessageListener {
|
public class SpawnComponent extends Component<MainPlugin> implements PluginMessageListener {
|
||||||
@Override
|
@Override
|
||||||
protected void enable() {
|
protected void enable() {
|
||||||
|
@ -69,7 +75,7 @@ public class SpawnComponent extends Component<MainPlugin> implements PluginMessa
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set to empty if this server is the target.
|
* The BungeeCord server that has the spawn. Set to empty if this server is the target.
|
||||||
*/
|
*/
|
||||||
private ConfigData<String> targetServer() {
|
private ConfigData<String> targetServer() {
|
||||||
return getConfig().getData("targetServer", "");
|
return getConfig().getData("targetServer", "");
|
||||||
|
@ -86,8 +92,16 @@ public class SpawnComponent extends Component<MainPlugin> implements PluginMessa
|
||||||
@Command2.Subcommand
|
@Command2.Subcommand
|
||||||
public void def(Player player) {
|
public void def(Player player) {
|
||||||
if (targetServer().get().length() == 0) {
|
if (targetServer().get().length() == 0) {
|
||||||
player.sendMessage("§bTeleporting to spawn.");
|
player.sendMessage("§bTeleporting to spawn...");
|
||||||
|
try {
|
||||||
|
if (MainPlugin.ess != null)
|
||||||
|
MainPlugin.ess.getUser(player).getTeleport()
|
||||||
|
.teleport(spawnloc, new Trade(BigDecimal.ZERO, MainPlugin.ess), PlayerTeleportEvent.TeleportCause.COMMAND);
|
||||||
|
else
|
||||||
player.teleport(spawnloc);
|
player.teleport(spawnloc);
|
||||||
|
} catch (Exception e) {
|
||||||
|
player.sendMessage("§cFailed to teleport: " + e);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ByteArrayDataOutput out = ByteStreams.newDataOutput();
|
ByteArrayDataOutput out = ByteStreams.newDataOutput();
|
||||||
|
|
|
@ -31,7 +31,9 @@ public class TownyComponent extends Component<MainPlugin> {
|
||||||
*/
|
*/
|
||||||
public static void renameInTowny(String oldName, String newName) {
|
public static void renameInTowny(String oldName, String newName) {
|
||||||
if (!ComponentManager.isEnabled(TownyComponent.class))
|
if (!ComponentManager.isEnabled(TownyComponent.class))
|
||||||
return; TownyUniverse tu = Towny.getPlugin(Towny.class).getTownyUniverse();
|
return;
|
||||||
|
Bukkit.getLogger().info("Renaming" + oldName + " in Towny to " + newName);
|
||||||
|
TownyUniverse tu = Towny.getPlugin(Towny.class).getTownyUniverse();
|
||||||
Resident resident = tu.getResidentMap().get(oldName.toLowerCase()); //The map keys are lowercase
|
Resident resident = tu.getResidentMap().get(oldName.toLowerCase()); //The map keys are lowercase
|
||||||
if (resident == null) {
|
if (resident == null) {
|
||||||
Bukkit.getLogger().warning("Resident not found - couldn't rename in Towny.");
|
Bukkit.getLogger().warning("Resident not found - couldn't rename in Towny.");
|
||||||
|
@ -42,6 +44,7 @@ public class TownyComponent extends Component<MainPlugin> {
|
||||||
} else
|
} else
|
||||||
try {
|
try {
|
||||||
tu.getDataSource().renamePlayer(resident, newName); //Fixed in Towny 0.91.1.2
|
tu.getDataSource().renamePlayer(resident, newName); //Fixed in Towny 0.91.1.2
|
||||||
|
Bukkit.getLogger().info("Renaming done.");
|
||||||
} catch (AlreadyRegisteredException e) {
|
} catch (AlreadyRegisteredException e) {
|
||||||
TBMCCoreAPI.SendException("Failed to rename resident, there's already one with this name.", e);
|
TBMCCoreAPI.SendException("Failed to rename resident, there's already one with this name.", e);
|
||||||
} catch (NotRegisteredException e) {
|
} catch (NotRegisteredException e) {
|
||||||
|
|
|
@ -2,15 +2,16 @@ package buttondevteam.core.component.updater;
|
||||||
|
|
||||||
import buttondevteam.core.MainPlugin;
|
import buttondevteam.core.MainPlugin;
|
||||||
import buttondevteam.lib.architecture.Component;
|
import buttondevteam.lib.architecture.Component;
|
||||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
import buttondevteam.lib.architecture.ComponentMetadata;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Downloads plugin updates built from their source using JitPack - older code
|
* Downloads plugin updates built from their source using JitPack - doesn't work anymore
|
||||||
*/
|
*/
|
||||||
|
@ComponentMetadata(enabledByDefault = false)
|
||||||
public class PluginUpdaterComponent extends Component<MainPlugin> { //TODO: Config
|
public class PluginUpdaterComponent extends Component<MainPlugin> { //TODO: Config
|
||||||
@Override
|
@Override
|
||||||
public void enable() {
|
public void enable() {
|
||||||
TBMCChatAPI.AddCommand(this, new UpdatePluginCommand());
|
registerCommand(new UpdatePluginCommand());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -2,40 +2,41 @@ package buttondevteam.core.component.updater;
|
||||||
|
|
||||||
import buttondevteam.core.MainPlugin;
|
import buttondevteam.core.MainPlugin;
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
import buttondevteam.lib.chat.CommandClass;
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
import buttondevteam.lib.chat.ICommand2MC;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
@CommandClass(modOnly = true)
|
@CommandClass(modOnly = true)
|
||||||
public class UpdatePluginCommand extends TBMCCommandBase {
|
public class UpdatePluginCommand extends ICommand2MC {
|
||||||
@Override
|
public void def(CommandSender sender, @Command2.OptionalArg String plugin, @Command2.OptionalArg String branch) {
|
||||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(MainPlugin.Instance, () -> {
|
Bukkit.getScheduler().runTaskAsynchronously(MainPlugin.Instance, () -> {
|
||||||
if (args.length == 0) {
|
if (plugin == null) {
|
||||||
sender.sendMessage("Downloading plugin names...");
|
sender.sendMessage("Downloading plugin names...");
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for (String plugin : PluginUpdater.GetPluginNames()) {
|
for (String plugin2 : PluginUpdater.GetPluginNames()) {
|
||||||
if (first) {
|
if (first) {
|
||||||
sender.sendMessage("§6---- Plugin names ----");
|
sender.sendMessage("§6---- Plugin names ----");
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
sender.sendMessage("- " + plugin);
|
sender.sendMessage("- " + plugin2);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TBMCCoreAPI.UpdatePlugin(args[0], sender, args.length == 1 ? "master" : args[1]);
|
TBMCCoreAPI.UpdatePlugin(plugin, sender, branch == null ? "master" : branch);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] GetHelpText(String alias) {
|
public String[] getHelpText(Method method, Command2.Subcommand ann) {
|
||||||
return new String[] { //
|
return new String[]{ //
|
||||||
"§6---- Update plugin ----", //
|
"§6---- Update plugin ----", //
|
||||||
"This command downloads the latest version of a TBMC plugin from GitHub", //
|
"This command downloads the latest version of a custom plugin from GitHub", //
|
||||||
"To update a plugin: /" + alias + " <plugin>", //
|
"To update a plugin: add its name", //
|
||||||
"To list the plugin names: /" + alias //
|
"To list the plugin names: don't type a name" //
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package buttondevteam.core.component.votifier;
|
||||||
|
|
||||||
import buttondevteam.core.MainPlugin;
|
import buttondevteam.core.MainPlugin;
|
||||||
import buttondevteam.lib.architecture.Component;
|
import buttondevteam.lib.architecture.Component;
|
||||||
|
import buttondevteam.lib.architecture.ComponentMetadata;
|
||||||
import buttondevteam.lib.architecture.ConfigData;
|
import buttondevteam.lib.architecture.ConfigData;
|
||||||
import com.vexsoftware.votifier.model.Vote;
|
import com.vexsoftware.votifier.model.Vote;
|
||||||
import com.vexsoftware.votifier.model.VotifierEvent;
|
import com.vexsoftware.votifier.model.VotifierEvent;
|
||||||
|
@ -15,6 +16,7 @@ import org.bukkit.event.EventHandler;
|
||||||
* Do not use (EULA)
|
* Do not use (EULA)
|
||||||
*/
|
*/
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
|
@ComponentMetadata(enabledByDefault = false)
|
||||||
public class VotifierComponent extends Component<MainPlugin> {
|
public class VotifierComponent extends Component<MainPlugin> {
|
||||||
private final Economy economy;
|
private final Economy economy;
|
||||||
|
|
||||||
|
@ -39,11 +41,11 @@ public class VotifierComponent extends Component<MainPlugin> {
|
||||||
getPlugin().getLogger().info("Vote: " + vote);
|
getPlugin().getLogger().info("Vote: " + vote);
|
||||||
org.bukkit.OfflinePlayer op = Bukkit.getOfflinePlayer(vote.getUsername());
|
org.bukkit.OfflinePlayer op = Bukkit.getOfflinePlayer(vote.getUsername());
|
||||||
Player p = Bukkit.getPlayer(vote.getUsername());
|
Player p = Bukkit.getPlayer(vote.getUsername());
|
||||||
if (op != null) {
|
/*if (op != null) {
|
||||||
economy.depositPlayer(op, rewardAmount().get());
|
economy.depositPlayer(op, rewardAmount().get());
|
||||||
}
|
}
|
||||||
if (p != null) {
|
if (p != null) {
|
||||||
p.sendMessage("§bThanks for voting! $50 was added to your account.");
|
p.sendMessage("§bThanks for voting! $50 was added to your account.");
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,41 @@
|
||||||
package buttondevteam.lib.architecture;
|
package buttondevteam.lib.architecture;
|
||||||
|
|
||||||
|
import buttondevteam.buttonproc.HasConfig;
|
||||||
import buttondevteam.core.ComponentManager;
|
import buttondevteam.core.ComponentManager;
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
import buttondevteam.lib.chat.Command2MC;
|
import buttondevteam.lib.chat.Command2MC;
|
||||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
@HasConfig
|
@HasConfig(global = true)
|
||||||
public abstract class ButtonPlugin extends JavaPlugin {
|
public abstract class ButtonPlugin extends JavaPlugin {
|
||||||
@Getter
|
@Getter
|
||||||
private static Command2MC command2MC = new Command2MC();
|
private static Command2MC command2MC = new Command2MC();
|
||||||
@Getter(AccessLevel.PROTECTED)
|
@Getter(AccessLevel.PROTECTED)
|
||||||
private IHaveConfig iConfig;
|
private IHaveConfig iConfig;
|
||||||
|
private CommentedConfiguration yaml;
|
||||||
@Getter(AccessLevel.PROTECTED)
|
@Getter(AccessLevel.PROTECTED)
|
||||||
private IHaveConfig data; //TODO
|
private IHaveConfig data; //TODO
|
||||||
private boolean loaded = false;
|
|
||||||
/**
|
/**
|
||||||
* Used to unregister components in the right order - and to reload configs
|
* Used to unregister components in the right order - and to reload configs
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
private Stack<Component<?>> componentStack = new Stack<>();
|
private Stack<Component<?>> componentStack = new Stack<>();
|
||||||
|
;
|
||||||
|
|
||||||
protected abstract void pluginEnable();
|
protected abstract void pluginEnable();
|
||||||
|
|
||||||
|
@ -45,7 +52,10 @@ public abstract class ButtonPlugin extends JavaPlugin {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void onEnable() {
|
public final void onEnable() {
|
||||||
loadConfig();
|
if (!loadConfig()) {
|
||||||
|
getLogger().warning("Please fix the issues and restart the server to load the plugin.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
pluginEnable();
|
pluginEnable();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -55,10 +65,14 @@ public abstract class ButtonPlugin extends JavaPlugin {
|
||||||
IHaveConfig.pregenConfig(this, null);
|
IHaveConfig.pregenConfig(this, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadConfig() {
|
private boolean loadConfig() {
|
||||||
var section = super.getConfig().getConfigurationSection("global");
|
var config = getConfig();
|
||||||
if (section == null) section = super.getConfig().createSection("global");
|
if (config == null)
|
||||||
|
return false;
|
||||||
|
var section = config.getConfigurationSection("global");
|
||||||
|
if (section == null) section = config.createSection("global");
|
||||||
iConfig = new IHaveConfig(section, this::saveConfig);
|
iConfig = new IHaveConfig(section, this::saveConfig);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -67,9 +81,10 @@ public abstract class ButtonPlugin extends JavaPlugin {
|
||||||
pluginPreDisable();
|
pluginPreDisable();
|
||||||
ComponentManager.unregComponents(this);
|
ComponentManager.unregComponents(this);
|
||||||
pluginDisable();
|
pluginDisable();
|
||||||
saveConfig();
|
if (ConfigData.saveNow(getConfig()))
|
||||||
|
getLogger().info("Saved configuration changes.");
|
||||||
iConfig = null; //Clearing the hashmap is not enough, we need to update the section as well
|
iConfig = null; //Clearing the hashmap is not enough, we need to update the section as well
|
||||||
TBMCChatAPI.RemoveCommands(this);
|
//TBMCChatAPI.RemoveCommands(this); - TODO
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
TBMCCoreAPI.SendException("Error while disabling plugin " + getName() + "!", e);
|
TBMCCoreAPI.SendException("Error while disabling plugin " + getName() + "!", e);
|
||||||
}
|
}
|
||||||
|
@ -88,13 +103,48 @@ public abstract class ButtonPlugin extends JavaPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean justReload() {
|
public boolean justReload() {
|
||||||
if (loaded && ConfigData.saveNow(getConfig())) {
|
if (yaml != null && ConfigData.saveNow(getConfig())) {
|
||||||
getLogger().warning("Saved pending configuration changes to the file, didn't reload (try again).");
|
getLogger().warning("Saved pending configuration changes to the file, didn't reload. Apply your changes again.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
super.reloadConfig();
|
var file = new File(getDataFolder(), "config.yml");
|
||||||
loaded = true; //Needed because for the first time it uses reloadConfig() to load it
|
var yaml = new CommentedConfiguration(file);
|
||||||
|
if (file.exists()) {
|
||||||
|
try {
|
||||||
|
yaml.load(file);
|
||||||
|
} catch (IOException | InvalidConfigurationException e) {
|
||||||
|
getLogger().warning("Failed to load config! Check for syntax errors.");
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.yaml = yaml;
|
||||||
|
var res = getTextResource("configHelp.yml");
|
||||||
|
if (res == null)
|
||||||
return true;
|
return true;
|
||||||
|
var yc = YamlConfiguration.loadConfiguration(res);
|
||||||
|
for (var kv : yc.getValues(true).entrySet())
|
||||||
|
if (kv.getValue() instanceof String)
|
||||||
|
yaml.addComment(kv.getKey(), Arrays.stream(((String) kv.getValue()).split("\n"))
|
||||||
|
.map(str -> "# " + str.trim()).toArray(String[]::new));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileConfiguration getConfig() {
|
||||||
|
if (yaml == null)
|
||||||
|
justReload(); //TODO: If it fails to load, it'll probably throw an NPE
|
||||||
|
return yaml;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveConfig() {
|
||||||
|
try {
|
||||||
|
if (yaml != null)
|
||||||
|
yaml.save();
|
||||||
|
} catch (Exception e) {
|
||||||
|
TBMCCoreAPI.SendException("Failed to save config", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
|
|
@ -0,0 +1,228 @@
|
||||||
|
package buttondevteam.lib.architecture;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.bukkit.configuration.file.YamlConstructor;
|
||||||
|
import org.bukkit.configuration.file.YamlRepresenter;
|
||||||
|
import org.yaml.snakeyaml.DumperOptions;
|
||||||
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
import org.yaml.snakeyaml.representer.Representer;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A copy of Towny's CommentedConfiguration: https://github.com/TownyAdvanced/Towny/blob/master/src/com/palmergames/bukkit/config/CommentedConfiguration.java
|
||||||
|
* Modified to remove dependency on the FileMgmt class
|
||||||
|
*
|
||||||
|
* @author dumptruckman & Articdive
|
||||||
|
*/
|
||||||
|
public class CommentedConfiguration extends YamlConfiguration { //TODO: Remove FileMgmt dependency
|
||||||
|
private HashMap<String, String> comments;
|
||||||
|
private File file;
|
||||||
|
|
||||||
|
private final DumperOptions yamlOptions = new DumperOptions();
|
||||||
|
private final Representer yamlRepresenter = new YamlRepresenter();
|
||||||
|
private final Yaml yaml = new Yaml(new YamlConstructor(), yamlRepresenter, yamlOptions);
|
||||||
|
|
||||||
|
public CommentedConfiguration(File file) {
|
||||||
|
|
||||||
|
super();
|
||||||
|
comments = new HashMap<>();
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean load() {
|
||||||
|
|
||||||
|
boolean loaded = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.load(file);
|
||||||
|
} catch (InvalidConfigurationException | IOException e) {
|
||||||
|
loaded = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save() throws IOException {
|
||||||
|
|
||||||
|
boolean saved = true;
|
||||||
|
|
||||||
|
// Save the config just like normal
|
||||||
|
try {
|
||||||
|
this.save(file);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
saved = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there's comments to add and it saved fine, we need to add comments
|
||||||
|
if (!comments.isEmpty() && saved) {
|
||||||
|
// String array of each line in the config file
|
||||||
|
String[] yamlContents = Files.readAllLines(file.toPath()).toArray(new String[0]);
|
||||||
|
|
||||||
|
// This will hold the newly formatted line
|
||||||
|
StringBuilder newContents = new StringBuilder();
|
||||||
|
// This holds the current path the lines are at in the config
|
||||||
|
String currentPath = "";
|
||||||
|
// This flags if the line is a node or unknown text.
|
||||||
|
boolean node;
|
||||||
|
// The depth of the path. (number of words separated by periods - 1)
|
||||||
|
int depth = 0;
|
||||||
|
|
||||||
|
// Loop through the config lines
|
||||||
|
for (String line : yamlContents) {
|
||||||
|
// If the line is a node (and not something like a list value)
|
||||||
|
if (line.contains(": ") || (line.length() > 1 && line.charAt(line.length() - 1) == ':')) {
|
||||||
|
|
||||||
|
// This is a node so flag it as one
|
||||||
|
node = true;
|
||||||
|
|
||||||
|
// Grab the index of the end of the node name
|
||||||
|
int index;
|
||||||
|
index = line.indexOf(": ");
|
||||||
|
if (index < 0) {
|
||||||
|
index = line.length() - 1;
|
||||||
|
}
|
||||||
|
// If currentPath is empty, store the node name as the currentPath. (this is only on the first iteration, i think)
|
||||||
|
if (currentPath.isEmpty()) {
|
||||||
|
currentPath = line.substring(0, index);
|
||||||
|
} else {
|
||||||
|
// Calculate the whitespace preceding the node name
|
||||||
|
int whiteSpace = 0;
|
||||||
|
for (int n = 0; n < line.length(); n++) {
|
||||||
|
if (line.charAt(n) == ' ') {
|
||||||
|
whiteSpace++;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Find out if the current depth (whitespace * 2) is greater/lesser/equal to the previous depth
|
||||||
|
if (whiteSpace / 2 > depth) {
|
||||||
|
// Path is deeper. Add a . and the node name
|
||||||
|
currentPath += "." + line.substring(whiteSpace, index);
|
||||||
|
depth++;
|
||||||
|
} else if (whiteSpace / 2 < depth) {
|
||||||
|
// Path is shallower, calculate current depth from whitespace (whitespace / 2) and subtract that many levels from the currentPath
|
||||||
|
int newDepth = whiteSpace / 2;
|
||||||
|
for (int i = 0; i < depth - newDepth; i++) {
|
||||||
|
currentPath = currentPath.replace(currentPath.substring(currentPath.lastIndexOf(".")), "");
|
||||||
|
}
|
||||||
|
// Grab the index of the final period
|
||||||
|
int lastIndex = currentPath.lastIndexOf(".");
|
||||||
|
if (lastIndex < 0) {
|
||||||
|
// if there isn't a final period, set the current path to nothing because we're at root
|
||||||
|
currentPath = "";
|
||||||
|
} else {
|
||||||
|
// If there is a final period, replace everything after it with nothing
|
||||||
|
currentPath = currentPath.replace(currentPath.substring(currentPath.lastIndexOf(".")), "");
|
||||||
|
currentPath += ".";
|
||||||
|
}
|
||||||
|
// Add the new node name to the path
|
||||||
|
currentPath += line.substring(whiteSpace, index);
|
||||||
|
// Reset the depth
|
||||||
|
depth = newDepth;
|
||||||
|
} else {
|
||||||
|
// Path is same depth, replace the last path node name to the current node name
|
||||||
|
int lastIndex = currentPath.lastIndexOf(".");
|
||||||
|
if (lastIndex < 0) {
|
||||||
|
// if there isn't a final period, set the current path to nothing because we're at root
|
||||||
|
currentPath = "";
|
||||||
|
} else {
|
||||||
|
// If there is a final period, replace everything after it with nothing
|
||||||
|
currentPath = currentPath.replace(currentPath.substring(currentPath.lastIndexOf(".")), "");
|
||||||
|
currentPath += ".";
|
||||||
|
}
|
||||||
|
//currentPath = currentPath.replace(currentPath.substring(currentPath.lastIndexOf(".")), "");
|
||||||
|
currentPath += line.substring(whiteSpace, index);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
node = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node) {
|
||||||
|
// If there's a comment for the current path, retrieve it and flag that path as already commented
|
||||||
|
String comment = comments.get(currentPath);
|
||||||
|
|
||||||
|
if (comment != null) {
|
||||||
|
// Add the comment to the beginning of the current line
|
||||||
|
line = comment + System.getProperty("line.separator") + line + System.getProperty("line.separator");
|
||||||
|
} else {
|
||||||
|
// Add a new line as it is a node, but has no comment
|
||||||
|
line += System.getProperty("line.separator");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Add the (modified) line to the total config String
|
||||||
|
if (!node) {
|
||||||
|
newContents.append(line).append(System.getProperty("line.separator"));
|
||||||
|
} else {
|
||||||
|
newContents.append(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Due to a Bukkit Bug with the Configuration
|
||||||
|
* we just need to remove any extra comments at the start of a file.
|
||||||
|
*/
|
||||||
|
while (newContents.toString().startsWith(" " + System.getProperty("line.separator"))) {
|
||||||
|
newContents = new StringBuilder(newContents.toString().replaceFirst(" " + System.getProperty("line.separator"), ""));
|
||||||
|
}
|
||||||
|
Files.write(file.toPath(), newContents.toString().getBytes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a comment just before the specified path. The comment can be
|
||||||
|
* multiple lines. An empty string will indicate a blank line.
|
||||||
|
*
|
||||||
|
* @param path Configuration path to add comment.
|
||||||
|
* @param commentLines Comments to add. One String per line.
|
||||||
|
*/
|
||||||
|
public void addComment(String path, String... commentLines) {
|
||||||
|
|
||||||
|
StringBuilder commentstring = new StringBuilder();
|
||||||
|
StringBuilder leadingSpaces = new StringBuilder();
|
||||||
|
for (int n = 0; n < path.length(); n++) {
|
||||||
|
if (path.charAt(n) == '.') {
|
||||||
|
leadingSpaces.append(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (String line : commentLines) {
|
||||||
|
if (!line.isEmpty()) {
|
||||||
|
line = leadingSpaces + line;
|
||||||
|
} else {
|
||||||
|
line = " ";
|
||||||
|
}
|
||||||
|
if (commentstring.length() > 0) {
|
||||||
|
commentstring.append(System.getProperty("line.separator"));
|
||||||
|
}
|
||||||
|
commentstring.append(line);
|
||||||
|
}
|
||||||
|
comments.put(path, commentstring.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String saveToString() {
|
||||||
|
yamlOptions.setIndent(options().indent());
|
||||||
|
yamlOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||||
|
yamlOptions.setWidth(10000);
|
||||||
|
yamlRepresenter.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||||
|
|
||||||
|
|
||||||
|
String dump = yaml.dump(getValues(false));
|
||||||
|
|
||||||
|
|
||||||
|
if (dump.equals(BLANK_CONFIG)) {
|
||||||
|
dump = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return dump;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,10 @@
|
||||||
package buttondevteam.lib.architecture;
|
package buttondevteam.lib.architecture;
|
||||||
|
|
||||||
|
import buttondevteam.buttonproc.HasConfig;
|
||||||
import buttondevteam.core.ComponentManager;
|
import buttondevteam.core.ComponentManager;
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
import buttondevteam.lib.architecture.exceptions.UnregisteredComponentException;
|
import buttondevteam.lib.architecture.exceptions.UnregisteredComponentException;
|
||||||
import buttondevteam.lib.chat.ICommand2MC;
|
import buttondevteam.lib.chat.ICommand2MC;
|
||||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
|
||||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
|
@ -16,13 +15,14 @@ import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration is based on class name
|
* Configuration is based on class name
|
||||||
*/
|
*/
|
||||||
@HasConfig //Used for obtaining javadoc
|
@HasConfig(global = false) //Used for obtaining javadoc
|
||||||
public abstract class Component<TP extends JavaPlugin> {
|
public abstract class Component<TP extends JavaPlugin> {
|
||||||
private static HashMap<Class<? extends Component>, Component<? extends JavaPlugin>> components = new HashMap<>();
|
private static HashMap<Class<? extends Component>, Component<? extends JavaPlugin>> components = new HashMap<>();
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ public abstract class Component<TP extends JavaPlugin> {
|
||||||
private @Getter IHaveConfig data; //TODO
|
private @Getter IHaveConfig data; //TODO
|
||||||
|
|
||||||
public final ConfigData<Boolean> shouldBeEnabled() {
|
public final ConfigData<Boolean> shouldBeEnabled() {
|
||||||
return config.getData("enabled", true);
|
return config.getData("enabled", Optional.ofNullable(getClass().getAnnotation(ComponentMetadata.class)).map(ComponentMetadata::enabledByDefault).orElse(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -141,8 +141,7 @@ public abstract class Component<TP extends JavaPlugin> {
|
||||||
//System.out.println("Done enabling "+component.getClassName());
|
//System.out.println("Done enabling "+component.getClassName());
|
||||||
} else {
|
} else {
|
||||||
component.disable();
|
component.disable();
|
||||||
component.plugin.saveConfig();
|
//TBMCChatAPI.RemoveCommands(component); - TODO
|
||||||
TBMCChatAPI.RemoveCommands(component);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,15 +211,6 @@ public abstract class Component<TP extends JavaPlugin> {
|
||||||
ButtonPlugin.getCommand2MC().registerCommand(commandBase);
|
ButtonPlugin.getCommand2MC().registerCommand(commandBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers a TBMCCommand to the component. Make sure to add it to plugin.yml and use {@link buttondevteam.lib.chat.CommandClass}.
|
|
||||||
*
|
|
||||||
* @param commandBase Custom coded command class
|
|
||||||
*/
|
|
||||||
protected final void registerCommand(TBMCCommandBase commandBase) {
|
|
||||||
TBMCChatAPI.AddCommand(this, commandBase);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a Listener to this component
|
* Registers a Listener to this component
|
||||||
*
|
*
|
||||||
|
|
|
@ -9,4 +9,6 @@ import java.lang.annotation.Target;
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface ComponentMetadata {
|
public @interface ComponentMetadata {
|
||||||
Class<? extends Component>[] depends() default {};
|
Class<? extends Component>[] depends() default {};
|
||||||
|
|
||||||
|
boolean enabledByDefault() default true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ import org.bukkit.scheduler.BukkitTask;
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,7 +32,7 @@ public class ConfigData<T> {
|
||||||
@Getter
|
@Getter
|
||||||
@Setter(AccessLevel.PACKAGE)
|
@Setter(AccessLevel.PACKAGE)
|
||||||
private String path;
|
private String path;
|
||||||
private final T def;
|
protected final T def;
|
||||||
private final Object primitiveDef;
|
private final Object primitiveDef;
|
||||||
private final Runnable saveAction;
|
private final Runnable saveAction;
|
||||||
/**
|
/**
|
||||||
|
@ -48,10 +48,6 @@ public class ConfigData<T> {
|
||||||
* The config value should not change outside this instance
|
* The config value should not change outside this instance
|
||||||
*/
|
*/
|
||||||
private T value;
|
private T value;
|
||||||
/**
|
|
||||||
* Whether the default value is saved in the yaml
|
|
||||||
*/
|
|
||||||
private boolean saved = false;
|
|
||||||
|
|
||||||
//This constructor is needed because it sets the getter and setter
|
//This constructor is needed because it sets the getter and setter
|
||||||
ConfigData(ConfigurationSection config, String path, T def, Object primitiveDef, Function<Object, T> getter, Function<T, Object> setter, Runnable saveAction) {
|
ConfigData(ConfigurationSection config, String path, T def, Object primitiveDef, Function<Object, T> getter, Function<T, Object> setter, Runnable saveAction) {
|
||||||
|
@ -84,27 +80,35 @@ public class ConfigData<T> {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public T get() {
|
public T get() {
|
||||||
if (value != null) return value; //Speed things up
|
if (value != null) return value; //Speed things up
|
||||||
Object val = config == null ? null : config.get(path); //config==null: testing
|
Object val;
|
||||||
if (val == null) {
|
if (config == null || !config.isSet(path)) { //Call set() if config == null
|
||||||
val = primitiveDef;
|
val = primitiveDef;
|
||||||
}
|
|
||||||
if (!saved && Objects.equals(val, primitiveDef)) { //String needs .equals()
|
|
||||||
if ((def == null || this instanceof ReadOnlyConfigData) && config != null) //In Discord's case def may be null
|
if ((def == null || this instanceof ReadOnlyConfigData) && config != null) //In Discord's case def may be null
|
||||||
config.set(path, primitiveDef);
|
setInternal(primitiveDef); //If read-only then we still need to save the default value so it can be set
|
||||||
else
|
else
|
||||||
set(def); //Save default value - def is always set
|
set(def); //Save default value - def is always set
|
||||||
saved = true;
|
} else
|
||||||
}
|
val = config.get(path); //config==null: testing
|
||||||
|
if (val == null) //If it's set to null explicitly
|
||||||
|
val = primitiveDef;
|
||||||
|
BiFunction<Object, Object, Object> convert = (_val, _def) -> {
|
||||||
|
if (_def instanceof Number) //If we expect a number
|
||||||
|
if (_val instanceof Number)
|
||||||
|
_val = ChromaUtils.convertNumber((Number) _val,
|
||||||
|
(Class<? extends Number>) _def.getClass());
|
||||||
|
else
|
||||||
|
_val = _def; //If we didn't get a number, return default (which is a number)
|
||||||
|
else if (_val instanceof List && _def != null && _def.getClass().isArray())
|
||||||
|
_val = ((List<T>) _val).toArray((T[]) Array.newInstance(_def.getClass().getComponentType(), 0));
|
||||||
|
return _val;
|
||||||
|
};
|
||||||
if (getter != null) {
|
if (getter != null) {
|
||||||
|
val = convert.apply(val, primitiveDef);
|
||||||
T hmm = getter.apply(val);
|
T hmm = getter.apply(val);
|
||||||
if (hmm == null) hmm = def; //Set if the getter returned null
|
if (hmm == null) hmm = def; //Set if the getter returned null
|
||||||
return hmm;
|
return hmm;
|
||||||
}
|
}
|
||||||
if (val instanceof Number && def != null)
|
val = convert.apply(val, def);
|
||||||
val = ChromaUtils.convertNumber((Number) val,
|
|
||||||
(Class<? extends Number>) def.getClass());
|
|
||||||
if (val instanceof List && def != null && def.getClass().isArray())
|
|
||||||
val = ((List<T>) val).toArray((T[]) Array.newInstance(def.getClass().getComponentType(), 0));
|
|
||||||
return value = (T) val; //Always cache, if not cached yet
|
return value = (T) val; //Always cache, if not cached yet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +119,12 @@ public class ConfigData<T> {
|
||||||
if (setter != null && value != null)
|
if (setter != null && value != null)
|
||||||
val = setter.apply(value);
|
val = setter.apply(value);
|
||||||
else val = value;
|
else val = value;
|
||||||
if (config != null) {
|
if (config != null)
|
||||||
|
setInternal(val);
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setInternal(Object val) {
|
||||||
config.set(path, val);
|
config.set(path, val);
|
||||||
if (!saveTasks.containsKey(config.getRoot())) {
|
if (!saveTasks.containsKey(config.getRoot())) {
|
||||||
synchronized (saveTasks) {
|
synchronized (saveTasks) {
|
||||||
|
@ -128,8 +137,6 @@ public class ConfigData<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
private static class SaveTask {
|
private static class SaveTask {
|
||||||
|
@ -138,6 +145,7 @@ public class ConfigData<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean saveNow(Configuration config) {
|
public static boolean saveNow(Configuration config) {
|
||||||
|
synchronized (saveTasks) {
|
||||||
SaveTask st = saveTasks.get(config);
|
SaveTask st = saveTasks.get(config);
|
||||||
if (st != null) {
|
if (st != null) {
|
||||||
st.task.cancel();
|
st.task.cancel();
|
||||||
|
@ -145,6 +153,7 @@ public class ConfigData<T> {
|
||||||
st.saveAction.run();
|
st.saveAction.run();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,6 +139,21 @@ public final class IHaveConfig {
|
||||||
return (ConfigData<T>) data;
|
return (ConfigData<T>) data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> ListConfigData<T> getListData(String path) {
|
||||||
|
ConfigData<?> data = datamap.get(path);
|
||||||
|
if (data == null)
|
||||||
|
datamap.put(path, data = new ListConfigData<>(config, path, new ListConfigData.List<T>(), saveAction));
|
||||||
|
return (ListConfigData<T>) data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the config YAML.
|
* Generates the config YAML.
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
package buttondevteam.lib.architecture;
|
||||||
|
|
||||||
|
import lombok.val;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
|
||||||
|
public class ListConfigData<T> extends ConfigData<ListConfigData.List<T>> {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
ListConfigData(ConfigurationSection config, String path, List<T> def, Runnable saveAction) {
|
||||||
|
super(config, path, def, new ArrayList<>(def), list -> {
|
||||||
|
var l = new List<>((ArrayList<T>) list);
|
||||||
|
l.listConfig = def.listConfig;
|
||||||
|
return l;
|
||||||
|
}, ArrayList::new, saveAction);
|
||||||
|
def.listConfig = this; //Can't make the List class non-static or pass this in the super() constructor
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class List<T> extends ArrayList<T> {
|
||||||
|
private ListConfigData<T> listConfig;
|
||||||
|
|
||||||
|
public List(@NotNull Collection<? extends T> c) {
|
||||||
|
super(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private void update() {
|
||||||
|
listConfig.set(this); //Update the config model and start save task if needed
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T set(int index, T element) {
|
||||||
|
T ret = super.set(index, element);
|
||||||
|
update();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean add(T t) {
|
||||||
|
val ret = super.add(t);
|
||||||
|
update();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(int index, T element) {
|
||||||
|
super.add(index, element);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T remove(int index) {
|
||||||
|
T ret = super.remove(index);
|
||||||
|
update();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(Object o) {
|
||||||
|
val ret = super.remove(o);
|
||||||
|
update();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addAll(Collection<? extends T> c) {
|
||||||
|
val ret = super.addAll(c);
|
||||||
|
update();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addAll(int index, Collection<? extends T> c) {
|
||||||
|
val ret = super.addAll(index, c);
|
||||||
|
update();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void removeRange(int fromIndex, int toIndex) {
|
||||||
|
super.removeRange(fromIndex, toIndex);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeAll(Collection<?> c) {
|
||||||
|
val ret = super.removeAll(c);
|
||||||
|
update();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean retainAll(Collection<?> c) {
|
||||||
|
val ret = super.retainAll(c);
|
||||||
|
update();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeIf(Predicate<? super T> filter) {
|
||||||
|
val ret = super.removeIf(filter);
|
||||||
|
update();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void replaceAll(UnaryOperator<T> operator) {
|
||||||
|
super.replaceAll(operator);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sort(Comparator<? super T> c) {
|
||||||
|
super.sort(c);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -135,7 +135,7 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
||||||
try {
|
try {
|
||||||
handleCommandAsync(sender, commandline, sd, subcommand, sync);
|
handleCommandAsync(sender, commandline, sd, subcommand, sync);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
TBMCCoreAPI.SendException("Command execution failed for sender " + sender + " and message " + commandline, e);
|
TBMCCoreAPI.SendException("Command execution failed for sender " + sender.getName() + "(" + sender.getClass().getCanonicalName() + ") and message " + commandline, e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return true; //We found a method
|
return true; //We found a method
|
||||||
|
@ -144,6 +144,17 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
||||||
}
|
}
|
||||||
|
|
||||||
//Needed because permission checking may load the (perhaps offline) sender's file which is disallowed on the main thread
|
//Needed because permission checking may load the (perhaps offline) sender's file which is disallowed on the main thread
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles a command asynchronously
|
||||||
|
*
|
||||||
|
* @param sender The command sender
|
||||||
|
* @param commandline The command line the sender sent
|
||||||
|
* @param sd The subcommand data
|
||||||
|
* @param subcommand The subcommand text
|
||||||
|
* @param sync Whether the command was originally sync
|
||||||
|
* @throws Exception If something's not right
|
||||||
|
*/
|
||||||
public void handleCommandAsync(TP sender, String commandline, SubcommandData<TC> sd, String subcommand, boolean sync) throws Exception {
|
public void handleCommandAsync(TP sender, String commandline, SubcommandData<TC> sd, String subcommand, boolean sync) throws Exception {
|
||||||
if (sd.method == null || sd.command == null) { //Main command not registered, but we have subcommands
|
if (sd.method == null || sd.command == null) { //Main command not registered, but we have subcommands
|
||||||
sender.sendMessage(sd.helpText);
|
sender.sendMessage(sd.helpText);
|
||||||
|
@ -247,7 +258,7 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
||||||
|
|
||||||
public abstract void registerCommand(TC command);
|
public abstract void registerCommand(TC command);
|
||||||
|
|
||||||
protected void registerCommand(TC command, char commandChar) {
|
protected void registerCommand(TC command, @SuppressWarnings("SameParameterValue") char commandChar) {
|
||||||
val path = command.getCommandPath();
|
val path = command.getCommandPath();
|
||||||
int x = path.indexOf(' ');
|
int x = path.indexOf(' ');
|
||||||
val mainPath = commandChar + path.substring(0, x == -1 ? path.length() : x);
|
val mainPath = commandChar + path.substring(0, x == -1 ? path.length() : x);
|
||||||
|
@ -277,7 +288,7 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
||||||
if (ht != null) {
|
if (ht != null) {
|
||||||
val subcommand = commandChar + path + //Add command path (class name by default)
|
val subcommand = commandChar + path + //Add command path (class name by default)
|
||||||
(method.getName().equals("def") ? "" : " " + method.getName().replace('_', ' ').toLowerCase()); //Add method name, unless it's 'def'
|
(method.getName().equals("def") ? "" : " " + method.getName().replace('_', ' ').toLowerCase()); //Add method name, unless it's 'def'
|
||||||
ht = getHelpText(method, ht, subcommand);
|
ht = getParameterHelp(method, ht, subcommand);
|
||||||
subcommands.put(subcommand, new SubcommandData<>(method, command, ht)); //Result of the above (def) is that it will show the help text
|
subcommands.put(subcommand, new SubcommandData<>(method, command, ht)); //Result of the above (def) is that it will show the help text
|
||||||
scmdHelpList.add(subcommand);
|
scmdHelpList.add(subcommand);
|
||||||
nosubs = false;
|
nosubs = false;
|
||||||
|
@ -299,7 +310,7 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String[] getHelpText(Method method, String[] ht, String subcommand) {
|
private String[] getParameterHelp(Method method, String[] ht, String subcommand) {
|
||||||
val str = method.getDeclaringClass().getResourceAsStream("/commands.yml");
|
val str = method.getDeclaringClass().getResourceAsStream("/commands.yml");
|
||||||
if (str == null)
|
if (str == null)
|
||||||
TBMCCoreAPI.SendException("Error while getting command data!", new Exception("Resource not found!"));
|
TBMCCoreAPI.SendException("Error while getting command data!", new Exception("Resource not found!"));
|
||||||
|
|
|
@ -6,6 +6,7 @@ import org.bukkit.Bukkit;
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.command.ConsoleCommandSender;
|
import org.bukkit.command.ConsoleCommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.server.TabCompleteEvent;
|
import org.bukkit.event.server.TabCompleteEvent;
|
||||||
|
@ -16,7 +17,6 @@ import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implements Listener {
|
public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implements Listener {
|
||||||
|
@ -26,7 +26,7 @@ public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implemen
|
||||||
var perm = "chroma.command." + command.getCommandPath().replace(' ', '.');
|
var perm = "chroma.command." + command.getCommandPath().replace(' ', '.');
|
||||||
if (Bukkit.getPluginManager().getPermission(perm) == null) //Check needed for plugin reset
|
if (Bukkit.getPluginManager().getPermission(perm) == null) //Check needed for plugin reset
|
||||||
Bukkit.getPluginManager().addPermission(new Permission(perm,
|
Bukkit.getPluginManager().addPermission(new Permission(perm,
|
||||||
modOnly(command) ? PermissionDefault.OP : PermissionDefault.TRUE)); //Allow commands by default, unless it's mod only - TODO: Test
|
PermissionDefault.TRUE)); //Allow commands by default, it will check mod-only
|
||||||
for (val method : command.getClass().getMethods()) {
|
for (val method : command.getClass().getMethods()) {
|
||||||
if (!method.isAnnotationPresent(Subcommand.class)) continue;
|
if (!method.isAnnotationPresent(Subcommand.class)) continue;
|
||||||
String pg = permGroup(command, method);
|
String pg = permGroup(command, method);
|
||||||
|
@ -34,7 +34,6 @@ public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implemen
|
||||||
perm = "chroma." + pg;
|
perm = "chroma." + pg;
|
||||||
if (Bukkit.getPluginManager().getPermission(perm) == null) //It may occur multiple times
|
if (Bukkit.getPluginManager().getPermission(perm) == null) //It may occur multiple times
|
||||||
Bukkit.getPluginManager().addPermission(new Permission(perm,
|
Bukkit.getPluginManager().addPermission(new Permission(perm,
|
||||||
//pg.equals(Subcommand.MOD_GROUP) ? PermissionDefault.OP : PermissionDefault.TRUE)); //Allow commands by default, unless it's mod only
|
|
||||||
PermissionDefault.OP)); //Do not allow any commands that belong to a group
|
PermissionDefault.OP)); //Do not allow any commands that belong to a group
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,16 +49,18 @@ public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implemen
|
||||||
boolean p = true;
|
boolean p = true;
|
||||||
String[] perms = {
|
String[] perms = {
|
||||||
"chroma.command." + command.getCommandPath().replace(' ', '.'),
|
"chroma.command." + command.getCommandPath().replace(' ', '.'),
|
||||||
(pg = permGroup(command, method)).length() > 0 ? "chroma." + pg : null,
|
(pg = permGroup(command, method)).length() > 0 ? "chroma." + pg : null
|
||||||
modOnly(command) ? "tbmc.admin" : null
|
|
||||||
};
|
};
|
||||||
for (String perm : perms) {
|
for (String perm : perms) {
|
||||||
if (perm != null) {
|
if (perm != null) {
|
||||||
if (p) { //Use OfflinePlayer to avoid fetching player data
|
if (p) { //Use OfflinePlayer to avoid fetching player data
|
||||||
if (sender instanceof OfflinePlayer)
|
if (sender instanceof OfflinePlayer)
|
||||||
p = MainPlugin.permission.playerHas(null, (OfflinePlayer) sender, perm);
|
p = MainPlugin.permission.playerHas(sender instanceof Player ? ((Player) sender).getLocation().getWorld().getName() : null, (OfflinePlayer) sender, perm);
|
||||||
else
|
else
|
||||||
p = MainPlugin.permission.playerHas(null, Bukkit.getOfflinePlayer(new UUID(0, 0)), perm);
|
p = false; //Use sender's method
|
||||||
|
//System.out.println("playerHas " + perm + ": " + p);
|
||||||
|
//System.out.println("hasPermission: " + sender.hasPermission(perm));
|
||||||
|
if (!p) p = sender.hasPermission(perm);
|
||||||
} else break; //If any of the permissions aren't granted then don't allow
|
} else break; //If any of the permissions aren't granted then don't allow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,17 +68,7 @@ public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implemen
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this class or <u>any</u> of the superclasses are mod only.
|
* Returns the first group found in the hierarchy starting from the command method <b>or</b> the mod group if <i>any</i></i> of the superclasses are mod only.
|
||||||
*
|
|
||||||
* @param command The command to check
|
|
||||||
* @return Whether the command is mod only
|
|
||||||
*/
|
|
||||||
private boolean modOnly(ICommand2MC command) {
|
|
||||||
return getAnnForValue(command.getClass(), CommandClass.class, CommandClass::modOnly, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if this class or <u>any</u> of the superclasses are mod only.
|
|
||||||
*
|
*
|
||||||
* @param method The subcommand to check
|
* @param method The subcommand to check
|
||||||
* @return The permission group for the subcommand or empty string
|
* @return The permission group for the subcommand or empty string
|
||||||
|
@ -87,6 +78,8 @@ public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implemen
|
||||||
if (sc != null && sc.permGroup().length() > 0) {
|
if (sc != null && sc.permGroup().length() > 0) {
|
||||||
return sc.permGroup();
|
return sc.permGroup();
|
||||||
}
|
}
|
||||||
|
if (getAnnForValue(command.getClass(), CommandClass.class, CommandClass::modOnly, false))
|
||||||
|
return Subcommand.MOD_GROUP;
|
||||||
return getAnnForValue(command.getClass(), CommandClass.class, CommandClass::permGroup, "");
|
return getAnnForValue(command.getClass(), CommandClass.class, CommandClass::permGroup, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,4 +17,9 @@ public class Command2MCSender implements Command2Sender {
|
||||||
public void sendMessage(String[] message) {
|
public void sendMessage(String[] message) {
|
||||||
sender.sendMessage(message);
|
sender.sendMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return sender.getName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,4 +4,6 @@ public interface Command2Sender { //We don't need the 'extras' of CommandSender
|
||||||
void sendMessage(String message);
|
void sendMessage(String message);
|
||||||
|
|
||||||
void sendMessage(String[] message);
|
void sendMessage(String[] message);
|
||||||
|
|
||||||
|
String getName();
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ public abstract class ICommand2<TP extends Command2Sender> {
|
||||||
String path = getClass().getAnnotation(CommandClass.class).path(),
|
String path = getClass().getAnnotation(CommandClass.class).path(),
|
||||||
prevpath = path = path.length() == 0 ? getFromClass.apply(getClass()) : path;
|
prevpath = path = path.length() == 0 ? getFromClass.apply(getClass()) : path;
|
||||||
for (Class<?> cl = getClass().getSuperclass(); cl != null
|
for (Class<?> cl = getClass().getSuperclass(); cl != null
|
||||||
&& !cl.getPackage().getName().equals(TBMCCommandBase.class.getPackage().getName()); cl = cl
|
&& !cl.getPackage().getName().equals(ICommand2MC.class.getPackage().getName()); cl = cl
|
||||||
.getSuperclass()) { //
|
.getSuperclass()) { //
|
||||||
String newpath;
|
String newpath;
|
||||||
if (!cl.isAnnotationPresent(CommandClass.class)
|
if (!cl.isAnnotationPresent(CommandClass.class)
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
package buttondevteam.lib.chat;
|
|
||||||
|
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
public abstract class OptionallyPlayerCommandBase extends TBMCCommandBase {
|
|
||||||
public boolean OnCommand(Player player, String alias, String[] args) {
|
|
||||||
if (getClass().isAnnotationPresent(OptionallyPlayerCommandClass.class)
|
|
||||||
&& getClass().getAnnotation(OptionallyPlayerCommandClass.class).playerOnly())
|
|
||||||
TBMCCoreAPI.SendException("Error while executing command " + getClass().getSimpleName() + "!",
|
|
||||||
new Exception(
|
|
||||||
"The PlayerCommand annotation is present and set to playerOnly but the Player overload isn't overriden!"));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
|
||||||
if (sender instanceof Player)
|
|
||||||
return OnCommand((Player) sender, alias, args);
|
|
||||||
if (!getClass().isAnnotationPresent(OptionallyPlayerCommandClass.class)
|
|
||||||
|| !getClass().getAnnotation(OptionallyPlayerCommandClass.class).playerOnly())
|
|
||||||
TBMCCoreAPI.SendException("Error while executing command " + getClass().getSimpleName() + "!",
|
|
||||||
new Exception(
|
|
||||||
"Command class doesn't override the CommandSender overload and no PlayerCommandClass annotation is present or playerOnly is false!"));
|
|
||||||
sender.sendMessage("§cYou need to be a player to use this command.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
package buttondevteam.lib.chat;
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Only needed to use with {@link OptionallyPlayerCommandBase} command classes
|
|
||||||
*
|
|
||||||
* @author NorbiPeti
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.TYPE)
|
|
||||||
@Inherited
|
|
||||||
public @interface OptionallyPlayerCommandClass {
|
|
||||||
boolean playerOnly();
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
package buttondevteam.lib.chat;
|
|
||||||
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
public abstract class PlayerCommandBase extends TBMCCommandBase {
|
|
||||||
public abstract boolean OnCommand(Player player, String alias, String[] args);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
|
||||||
if (sender instanceof Player)
|
|
||||||
return OnCommand((Player) sender, alias, args);
|
|
||||||
sender.sendMessage("§cYou need to be a player to use this command.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,250 +1,19 @@
|
||||||
package buttondevteam.lib.chat;
|
package buttondevteam.lib.chat;
|
||||||
|
|
||||||
import buttondevteam.core.CommandCaller;
|
|
||||||
import buttondevteam.core.MainPlugin;
|
|
||||||
import buttondevteam.core.component.channel.Channel;
|
import buttondevteam.core.component.channel.Channel;
|
||||||
import buttondevteam.core.component.channel.Channel.RecipientTestResult;
|
import buttondevteam.core.component.channel.Channel.RecipientTestResult;
|
||||||
import buttondevteam.lib.*;
|
import buttondevteam.lib.ChromaUtils;
|
||||||
import buttondevteam.lib.architecture.Component;
|
import buttondevteam.lib.TBMCChatEvent;
|
||||||
|
import buttondevteam.lib.TBMCChatPreprocessEvent;
|
||||||
|
import buttondevteam.lib.TBMCSystemChatEvent;
|
||||||
import lombok.val;
|
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.plugin.java.JavaPlugin;
|
|
||||||
import org.reflections.Reflections;
|
|
||||||
import org.reflections.scanners.SubTypesScanner;
|
|
||||||
import org.reflections.util.ClasspathHelper;
|
|
||||||
import org.reflections.util.ConfigurationBuilder;
|
|
||||||
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class TBMCChatAPI {
|
public class TBMCChatAPI {
|
||||||
|
|
||||||
private static final HashMap<String, TBMCCommandBase> commands = new HashMap<>();
|
|
||||||
|
|
||||||
public static HashMap<String, TBMCCommandBase> GetCommands() {
|
|
||||||
return commands;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns messages formatted for Minecraft chat listing the subcommands of the command.
|
|
||||||
*
|
|
||||||
* @param command The command which we want the subcommands of
|
|
||||||
* @param sender The sender for permissions
|
|
||||||
* @return The subcommands
|
|
||||||
*/
|
|
||||||
public static String[] GetSubCommands(TBMCCommandBase command, CommandSender sender) {
|
|
||||||
return GetSubCommands(command.GetCommandPath(), sender);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns messages formatted for Minecraft chat listing the subcommands of the command.<br>
|
|
||||||
* Returns a header if subcommands were found, otherwise returns an empty array.
|
|
||||||
*
|
|
||||||
* @param command The command which we want the subcommands of
|
|
||||||
* @param sender The sender for permissions
|
|
||||||
* @return The subcommands
|
|
||||||
*/
|
|
||||||
public static String[] GetSubCommands(String command, CommandSender sender) {
|
|
||||||
ArrayList<String> cmds = new ArrayList<String>();
|
|
||||||
Consumer<String> addToCmds = cmd -> {
|
|
||||||
if (cmds.size() == 0)
|
|
||||||
cmds.add("§6---- Subcommands ----");
|
|
||||||
cmds.add(cmd);
|
|
||||||
};
|
|
||||||
for (Entry<String, TBMCCommandBase> cmd : TBMCChatAPI.GetCommands().entrySet()) {
|
|
||||||
if (cmd.getKey().startsWith(command + " ")) {
|
|
||||||
if (cmd.getValue().isPlayerOnly() && !(sender instanceof Player))
|
|
||||||
continue;
|
|
||||||
if (cmd.getValue().isModOnly() && (MainPlugin.permission != null ? !MainPlugin.permission.has(sender, "tbmc.admin") : !sender.isOp()))
|
|
||||||
continue;
|
|
||||||
int ind = cmd.getKey().indexOf(' ', command.length() + 2);
|
|
||||||
if (ind >= 0) {
|
|
||||||
String newcmd = cmd.getKey().substring(0, ind);
|
|
||||||
if (!cmds.contains("/" + newcmd))
|
|
||||||
addToCmds.accept("/" + newcmd);
|
|
||||||
} else
|
|
||||||
addToCmds.accept("/" + cmd.getKey());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cmds.toArray(new String[0]); //Apparently it's faster to use an empty array in modern Java
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* This method adds a plugin's commands to help and sets their executor.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* </p>
|
|
||||||
* <b>The command classes have to have a constructor each with no parameters</b>
|
|
||||||
* <p>
|
|
||||||
* The <u>command must be registered</u> in the caller plugin's plugin.yml. Otherwise the plugin will output a messsage to console.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* <i>Using this method after the server is done loading will have no effect.</i>
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param plugin The caller plugin
|
|
||||||
* @param acmdclass A command's class to get the package name for commands. The provided class's package and subpackages are scanned for commands.
|
|
||||||
*/
|
|
||||||
public static synchronized void AddCommands(JavaPlugin plugin, Class<? extends TBMCCommandBase> acmdclass) {
|
|
||||||
plugin.getLogger().info("Registering commands from " + acmdclass.getPackage().getName());
|
|
||||||
Reflections rf = new Reflections(new ConfigurationBuilder()
|
|
||||||
.setUrls(ClasspathHelper.forPackage(acmdclass.getPackage().getName(),
|
|
||||||
plugin.getClass().getClassLoader()))
|
|
||||||
.addUrls(
|
|
||||||
ClasspathHelper.forClass(OptionallyPlayerCommandBase.class,
|
|
||||||
OptionallyPlayerCommandBase.class.getClassLoader()),
|
|
||||||
ClasspathHelper.forClass(PlayerCommandBase.class, PlayerCommandBase.class.getClassLoader())) // http://stackoverflow.com/questions/12917417/using-reflections-for-finding-the-transitive-subtypes-of-a-class-when-not-all
|
|
||||||
.addClassLoader(plugin.getClass().getClassLoader()).addScanners(new SubTypesScanner()));
|
|
||||||
Set<Class<? extends TBMCCommandBase>> cmds = rf.getSubTypesOf(TBMCCommandBase.class);
|
|
||||||
for (Class<? extends TBMCCommandBase> cmd : cmds) {
|
|
||||||
try {
|
|
||||||
if (!cmd.getPackage().getName().startsWith(acmdclass.getPackage().getName()))
|
|
||||||
continue; // It keeps including the commands from here
|
|
||||||
if (Modifier.isAbstract(cmd.getModifiers()))
|
|
||||||
continue;
|
|
||||||
TBMCCommandBase c = cmd.newInstance();
|
|
||||||
c.plugin = plugin;
|
|
||||||
CommandCaller.RegisterCommand(c); //Will check for nulls
|
|
||||||
commands.put(c.GetCommandPath(), c);
|
|
||||||
} catch (Exception e) {
|
|
||||||
TBMCCoreAPI.SendException("An error occured while registering command " + cmd.getName(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* This method adds a plugin's command to help and sets it's executor. They will be automatically unregistered on plugin disable.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* The <u>command must be registered</u> in the caller plugin's plugin.yml. Otherwise the plugin will output a messsage to console.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* <i>Using this method after the server is done loading will have no effect.</i>
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param plugin The caller plugin
|
|
||||||
* @param thecmdclass The command's class to create it (because why let you create the command class)
|
|
||||||
*/
|
|
||||||
public static void AddCommand(JavaPlugin plugin, Class<? extends TBMCCommandBase> thecmdclass, Object... params) {
|
|
||||||
// plugin.getLogger().info("Registering command " + thecmdclass.getSimpleName() + " for " + plugin.getName());
|
|
||||||
try {
|
|
||||||
TBMCCommandBase c;
|
|
||||||
if (params.length > 0)
|
|
||||||
c = thecmdclass.getConstructor(Arrays.stream(params).map(Object::getClass).toArray(Class[]::new))
|
|
||||||
.newInstance(params);
|
|
||||||
else
|
|
||||||
c = thecmdclass.newInstance();
|
|
||||||
c.plugin = plugin;
|
|
||||||
CommandCaller.RegisterCommand(c); //Will check for nulls
|
|
||||||
commands.put(c.GetCommandPath(), c);
|
|
||||||
} catch (Exception e) {
|
|
||||||
TBMCCoreAPI.SendException("An error occured while registering command " + thecmdclass.getSimpleName(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* This method adds a plugin's command to help and sets its executor. They will be automatically unregistered on plugin disable.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* The <u>command must be registered</u> in the caller plugin's plugin.yml. Otherwise the plugin will output a message to console.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* <i>Using this method after the server is done loading will have no effect.</i>
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param plugin The caller plugin
|
|
||||||
* @param cmd The command to add
|
|
||||||
*/
|
|
||||||
public static void AddCommand(JavaPlugin plugin, TBMCCommandBase cmd) {
|
|
||||||
try {
|
|
||||||
if (plugin == null) throw new IllegalArgumentException("The plugin is null!");
|
|
||||||
if (cmd == null) throw new IllegalArgumentException("The command is null!");
|
|
||||||
cmd.plugin = plugin;
|
|
||||||
CommandCaller.RegisterCommand(cmd); //Checks for other nulls
|
|
||||||
commands.put(cmd.GetCommandPath(), cmd);
|
|
||||||
} catch (Exception e) {
|
|
||||||
TBMCCoreAPI.SendException("An error occured while registering command " + (cmd == null ? "n u l l" : cmd.GetCommandPath()), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* This method adds a plugin's command to help and sets its executor. They will be automatically unregistered on component disable.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* The <u>command must be registered</u> in the caller plugin's plugin.yml. Otherwise the plugin will output a message to console.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* <i>Using this method after the server is done loading will have no effect.</i>
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param component The caller component
|
|
||||||
* @param cmd The command to add
|
|
||||||
*/
|
|
||||||
public static void AddCommand(Component component, TBMCCommandBase cmd) {
|
|
||||||
try {
|
|
||||||
if (component == null) throw new IllegalArgumentException("The component is null!");
|
|
||||||
if (cmd == null) throw new IllegalArgumentException("The command is null!");
|
|
||||||
cmd.plugin = component.getPlugin();
|
|
||||||
cmd.component = component;
|
|
||||||
CommandCaller.RegisterCommand(cmd); //Checks for other nulls
|
|
||||||
commands.put(cmd.GetCommandPath(), cmd);
|
|
||||||
} catch (Exception e) {
|
|
||||||
TBMCCoreAPI.SendException("An error occured while registering command " + (cmd == null ? "n u l l" : cmd.GetCommandPath()), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes all commands from the plugin
|
|
||||||
*
|
|
||||||
* @param plugin The plugin to remove commands from
|
|
||||||
*/
|
|
||||||
public static void RemoveCommands(JavaPlugin plugin) {
|
|
||||||
commands.values().removeIf(c -> {
|
|
||||||
try {
|
|
||||||
if (c.plugin == plugin) {
|
|
||||||
CommandCaller.UnregisterCommand(c);
|
|
||||||
return true; //Remove
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
} catch (Exception e) {
|
|
||||||
TBMCCoreAPI.SendException("An error occured while unregistering commands for " + plugin.getName(), e);
|
|
||||||
return true; //Remove if it couldn't get the plugin command
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes all commands from the component
|
|
||||||
*
|
|
||||||
* @param component The component to remove commands from
|
|
||||||
*/
|
|
||||||
public static void RemoveCommands(Component component) {
|
|
||||||
commands.values().removeIf(c -> {
|
|
||||||
try {
|
|
||||||
if (c.component == component) {
|
|
||||||
CommandCaller.UnregisterCommand(c);
|
|
||||||
return true; //Remove
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
} catch (Exception e) {
|
|
||||||
TBMCCoreAPI.SendException("An error occured while unregistering commands for " + component.getClass().getSimpleName(), e);
|
|
||||||
return true; //Remove if it couldn't get the plugin command
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a chat message to Minecraft. Make sure that the channel is registered with {@link #RegisterChatChannel(Channel)}.<br>
|
* Sends a chat message to Minecraft. Make sure that the channel is registered with {@link #RegisterChatChannel(Channel)}.<br>
|
||||||
* This will also send the error message to the sender, if they can't send the message.
|
* This will also send the error message to the sender, if they can't send the message.
|
||||||
|
|
|
@ -1,111 +0,0 @@
|
||||||
package buttondevteam.lib.chat;
|
|
||||||
|
|
||||||
import buttondevteam.lib.architecture.Component;
|
|
||||||
import javassist.Modifier;
|
|
||||||
import lombok.Getter;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extend this class to create new TBMCCommand and use {@link TBMCChatAPI#AddCommand(org.bukkit.plugin.java.JavaPlugin, TBMCCommandBase)} to add it. <u><b>Note:</b></u> The command path (command name
|
|
||||||
* and subcommand arguments) will be the class name by default, removing any "command" from it. To change it (especially for subcommands), use the path field in the {@link CommandClass} annotation.
|
|
||||||
*
|
|
||||||
* @author Norbi
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@TBMCCommandEnforcer
|
|
||||||
public abstract class TBMCCommandBase {
|
|
||||||
|
|
||||||
public TBMCCommandBase() {
|
|
||||||
path = getcmdpath();
|
|
||||||
modonly = ismodonly();
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract boolean OnCommand(CommandSender sender, String alias, String[] args);
|
|
||||||
|
|
||||||
public abstract String[] GetHelpText(String alias);
|
|
||||||
|
|
||||||
private final String path;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The command's path, or name if top-level command.<br>
|
|
||||||
* For example:<br>
|
|
||||||
* "u admin updateplugin" or "u" for the top level one<br>
|
|
||||||
* <u>The path must be lowercase!</u><br>
|
|
||||||
* <b>Abstract classes with no {@link CommandClass} annotations will be ignored.</b>
|
|
||||||
*
|
|
||||||
* @return The command path, <i>which is the command class name by default</i> (removing any "command" from it) - Change via the {@link CommandClass} annotation
|
|
||||||
*/
|
|
||||||
public final String GetCommandPath() {
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getcmdpath() {
|
|
||||||
if (!getClass().isAnnotationPresent(CommandClass.class))
|
|
||||||
throw new RuntimeException(
|
|
||||||
"No @CommandClass annotation on command class " + getClass().getSimpleName() + "!");
|
|
||||||
Function<Class<?>, String> getFromClass = cl -> cl.getSimpleName().toLowerCase().replace("commandbase", "") // <-- ...
|
|
||||||
.replace("command", "");
|
|
||||||
String path = getClass().getAnnotation(CommandClass.class).path(),
|
|
||||||
prevpath = path = path.length() == 0 ? getFromClass.apply(getClass()) : path;
|
|
||||||
for (Class<?> cl = getClass().getSuperclass(); cl != null
|
|
||||||
&& !cl.getPackage().getName().equals(TBMCCommandBase.class.getPackage().getName()); cl = cl
|
|
||||||
.getSuperclass()) { //
|
|
||||||
String newpath;
|
|
||||||
if (!cl.isAnnotationPresent(CommandClass.class)
|
|
||||||
|| (newpath = cl.getAnnotation(CommandClass.class).path()).length() == 0
|
|
||||||
|| newpath.equals(prevpath)) {
|
|
||||||
if ((Modifier.isAbstract(cl.getModifiers()) && !cl.isAnnotationPresent(CommandClass.class))
|
|
||||||
|| cl.getAnnotation(CommandClass.class).excludeFromPath()) // <--
|
|
||||||
continue;
|
|
||||||
newpath = getFromClass.apply(cl);
|
|
||||||
}
|
|
||||||
path = (prevpath = newpath) + " " + path;
|
|
||||||
}
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
Plugin plugin; // Used By TBMCChatAPI
|
|
||||||
|
|
||||||
public final Plugin getPlugin() { // Used by CommandCaller (ButtonChat)
|
|
||||||
return plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final boolean isPlayerOnly() {
|
|
||||||
return this instanceof PlayerCommandBase ||
|
|
||||||
(this instanceof OptionallyPlayerCommandBase &&
|
|
||||||
(!getClass().isAnnotationPresent(OptionallyPlayerCommandClass.class)
|
|
||||||
|| getClass().getAnnotation(OptionallyPlayerCommandClass.class).playerOnly()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private final boolean modonly;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if this class' or any superclass' modOnly property is set to true.
|
|
||||||
*/
|
|
||||||
public final boolean isModOnly() {
|
|
||||||
return modonly;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean ismodonly() {
|
|
||||||
if (!getClass().isAnnotationPresent(CommandClass.class))
|
|
||||||
throw new RuntimeException(
|
|
||||||
"No @CommandClass annotation on command class " + getClass().getSimpleName() + "!");
|
|
||||||
boolean modOnly = getClass().getAnnotation(CommandClass.class).modOnly();
|
|
||||||
for (Class<?> cl = getClass().getSuperclass(); cl != null
|
|
||||||
&& !cl.getPackage().getName().equals(TBMCCommandBase.class.getPackage().getName()); cl = cl
|
|
||||||
.getSuperclass()) { //
|
|
||||||
if (cl.isAnnotationPresent(CommandClass.class) && !modOnly
|
|
||||||
&& cl.getAnnotation(CommandClass.class).modOnly()) {
|
|
||||||
modOnly = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return modOnly;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
Component component; //May be null
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
package buttondevteam.lib.chat;
|
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Inherited;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.CLASS)
|
|
||||||
@Target(ElementType.TYPE)
|
|
||||||
@Inherited
|
|
||||||
public @interface TBMCCommandEnforcer {
|
|
||||||
|
|
||||||
}
|
|
|
@ -57,10 +57,8 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase {
|
||||||
/**
|
/**
|
||||||
* Get player as a plugin player
|
* Get player as a plugin player
|
||||||
*
|
*
|
||||||
* @param uuid
|
* @param uuid The UUID of the player to get
|
||||||
* The UUID of the player to get
|
* @param cl The type of the player
|
||||||
* @param cl
|
|
||||||
* The type of the player
|
|
||||||
* @return The requested player object
|
* @return The requested player object
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -93,8 +91,7 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase {
|
||||||
* Gets the TBMCPlayer object as a specific plugin player, keeping it's data<br>
|
* Gets the TBMCPlayer object as a specific plugin player, keeping it's data<br>
|
||||||
* Make sure to use try-with-resources with this to save the data, as it may need to load the file
|
* Make sure to use try-with-resources with this to save the data, as it may need to load the file
|
||||||
*
|
*
|
||||||
* @param cl
|
* @param cl The TBMCPlayer subclass
|
||||||
* The TBMCPlayer subclass
|
|
||||||
*/
|
*/
|
||||||
public <T extends TBMCPlayerBase> T asPluginPlayer(Class<T> cl) {
|
public <T extends TBMCPlayerBase> T asPluginPlayer(Class<T> cl) {
|
||||||
return getPlayer(uuid, cl);
|
return getPlayer(uuid, cl);
|
||||||
|
@ -122,10 +119,9 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase {
|
||||||
player.PlayerName().set(p.getName());
|
player.PlayerName().set(p.getName());
|
||||||
Bukkit.getLogger().info("Player name saved: " + player.PlayerName().get());
|
Bukkit.getLogger().info("Player name saved: " + player.PlayerName().get());
|
||||||
} else if (!p.getName().equals(player.PlayerName().get())) {
|
} else if (!p.getName().equals(player.PlayerName().get())) {
|
||||||
Bukkit.getLogger().info("Renaming " + player.PlayerName().get() + " to " + p.getName());
|
|
||||||
TownyComponent.renameInTowny(player.PlayerName().get(), p.getName());
|
TownyComponent.renameInTowny(player.PlayerName().get(), p.getName());
|
||||||
player.PlayerName().set(p.getName());
|
player.PlayerName().set(p.getName());
|
||||||
Bukkit.getLogger().info("Renaming done.");
|
Bukkit.getLogger().info("Renamed to " + p.getName());
|
||||||
}
|
}
|
||||||
playermap.put(p.getUniqueId() + "-" + TBMCPlayer.class.getSimpleName(), player);
|
playermap.put(p.getUniqueId() + "-" + TBMCPlayer.class.getSimpleName(), player);
|
||||||
|
|
||||||
|
@ -168,8 +164,7 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase {
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param name
|
* @param name The player's name
|
||||||
* The player's name
|
|
||||||
* @return The {@link TBMCPlayer} object for the player
|
* @return The {@link TBMCPlayer} object for the player
|
||||||
*/
|
*/
|
||||||
public static <T extends TBMCPlayerBase> T getFromName(String name, Class<T> cl) {
|
public static <T extends TBMCPlayerBase> T getFromName(String name, Class<T> cl) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
name: ChromaCore
|
name: ChromaCore
|
||||||
main: buttondevteam.core.MainPlugin
|
main: buttondevteam.core.MainPlugin
|
||||||
version: 1.0
|
version: 1.0
|
||||||
author: TBMCPlugins
|
author: NorbiPeti
|
||||||
commands:
|
commands:
|
||||||
updateplugin:
|
updateplugin:
|
||||||
description: Update a TBMC plugin
|
description: Update a TBMC plugin
|
||||||
|
@ -22,3 +22,4 @@ softdepend:
|
||||||
- Towny
|
- Towny
|
||||||
- Votifier
|
- Votifier
|
||||||
- Multiverse-Core
|
- Multiverse-Core
|
||||||
|
- Essentials
|
|
@ -1,5 +1,8 @@
|
||||||
package buttondevteam.buttonproc;
|
package buttondevteam.buttonproc;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
import javax.annotation.processing.ProcessingEnvironment;
|
import javax.annotation.processing.ProcessingEnvironment;
|
||||||
import javax.lang.model.element.Element;
|
import javax.lang.model.element.Element;
|
||||||
import javax.lang.model.element.ExecutableElement;
|
import javax.lang.model.element.ExecutableElement;
|
||||||
|
@ -10,29 +13,40 @@ import javax.lang.model.type.TypeMirror;
|
||||||
import javax.tools.FileObject;
|
import javax.tools.FileObject;
|
||||||
import javax.tools.StandardLocation;
|
import javax.tools.StandardLocation;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class ConfigProcessor {
|
public class ConfigProcessor {
|
||||||
private final ProcessingEnvironment procEnv;
|
private final ProcessingEnvironment procEnv;
|
||||||
private final FileWriter sw;
|
private final YamlConfiguration yc = new YamlConfiguration();
|
||||||
|
private final FileObject fo;
|
||||||
|
|
||||||
public ConfigProcessor(ProcessingEnvironment procEnv) {
|
public ConfigProcessor(ProcessingEnvironment procEnv) {
|
||||||
|
FileObject fo1;
|
||||||
this.procEnv = procEnv;
|
this.procEnv = procEnv;
|
||||||
FileWriter sw = null;
|
|
||||||
try {
|
try {
|
||||||
FileObject file = procEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", "configHelp.md");
|
fo1 = procEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", "configHelp.yml");
|
||||||
sw = new FileWriter(new File(file.toUri()));
|
|
||||||
System.out.println(file.toUri());
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
fo1 = null;
|
||||||
}
|
}
|
||||||
this.sw = sw;
|
this.fo = fo1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process(Element targetcl) {
|
public void process(Element targetcl) {
|
||||||
if (targetcl.getModifiers().contains(Modifier.ABSTRACT)) return;
|
if (targetcl.getModifiers().contains(Modifier.ABSTRACT)) return;
|
||||||
final String path = "components." + targetcl.getSimpleName();
|
HasConfig hasConfig = targetcl.getAnnotation(HasConfig.class);
|
||||||
|
if (hasConfig == null) {
|
||||||
|
System.out.println("That's not our HasConfig annotation...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final String path = hasConfig.global() ? "global" : "components." + targetcl.getSimpleName();
|
||||||
|
File file = new File(fo.toUri());
|
||||||
|
try {
|
||||||
|
if (file.exists())
|
||||||
|
yc.load(file);
|
||||||
|
} catch (IOException | InvalidConfigurationException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
for (Element e : targetcl.getEnclosedElements()) {
|
for (Element e : targetcl.getEnclosedElements()) {
|
||||||
/*System.out.println("Element: "+e);
|
/*System.out.println("Element: "+e);
|
||||||
System.out.println("Type: "+e.getClass()+" - "+e.getKind());
|
System.out.println("Type: "+e.getClass()+" - "+e.getKind());
|
||||||
|
@ -49,30 +63,18 @@ public class ConfigProcessor {
|
||||||
String doc = procEnv.getElementUtils().getDocComment(e);
|
String doc = procEnv.getElementUtils().getDocComment(e);
|
||||||
if (doc == null) continue;
|
if (doc == null) continue;
|
||||||
System.out.println("DOC: " + doc);
|
System.out.println("DOC: " + doc);
|
||||||
try {
|
yc.set(path + "." + e.getSimpleName(), doc.trim());
|
||||||
sw.append(path).append(".").append(String.valueOf(e.getSimpleName())).append(System.lineSeparator()).append(System.lineSeparator());
|
|
||||||
sw.append(doc.trim()).append(System.lineSeparator()).append(System.lineSeparator());
|
|
||||||
} catch (IOException e1) {
|
|
||||||
e1.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
String javadoc = procEnv.getElementUtils().getDocComment(targetcl);
|
String javadoc = procEnv.getElementUtils().getDocComment(targetcl);
|
||||||
try {
|
|
||||||
if (javadoc != null) {
|
if (javadoc != null) {
|
||||||
System.out.println("JAVADOC");
|
System.out.println("JAVADOC");
|
||||||
System.out.println(javadoc.trim());
|
System.out.println(javadoc.trim());
|
||||||
sw.append(path).append(System.lineSeparator()).append(System.lineSeparator());
|
yc.set(path, javadoc.trim());
|
||||||
sw.append(javadoc).append(System.lineSeparator()).append(System.lineSeparator());
|
|
||||||
}
|
}
|
||||||
sw.flush();
|
try {
|
||||||
|
yc.save(file);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
sw.close();
|
|
||||||
super.finalize();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package buttondevteam.lib.architecture;
|
package buttondevteam.buttonproc;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Inherited;
|
import java.lang.annotation.Inherited;
|
||||||
|
@ -10,4 +10,5 @@ import java.lang.annotation.Target;
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
@Inherited
|
@Inherited
|
||||||
public @interface HasConfig {
|
public @interface HasConfig {
|
||||||
|
boolean global();
|
||||||
}
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
<module name="ButtonProcessor" />
|
<module name="ButtonProcessor" />
|
||||||
</modules>
|
</modules>
|
||||||
</component>
|
</component>
|
||||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_13_PREVIEW">
|
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_11">
|
||||||
<output url="file://$MODULE_DIR$/target/classes" />
|
<output url="file://$MODULE_DIR$/target/classes" />
|
||||||
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
|
|
|
@ -95,10 +95,12 @@
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
<release>13</release>
|
<release>11</release>
|
||||||
|
<!--
|
||||||
<compilerArgs>
|
<compilerArgs>
|
||||||
<arg>--enable-preview</arg>
|
<arg>HYPHENHYPHENenable-preview</arg>
|
||||||
</compilerArgs>
|
</compilerArgs>
|
||||||
|
-->
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
|
|
Loading…
Reference in a new issue