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>
|
||||
<module name="BuildConfigUpdater" target="8" />
|
||||
<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="ChunkArchive" target="1.8" />
|
||||
<module name="CorePOM" target="13" />
|
||||
<module name="CorePOM" target="11" />
|
||||
<module name="RandomTeleport" target="1.8" />
|
||||
</bytecodeTargetLevel>
|
||||
</component>
|
||||
<component name="JavacSettings">
|
||||
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
|
||||
<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" />
|
||||
</option>
|
||||
</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!");
|
||||
}
|
||||
|
||||
@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) {
|
||||
if (plugin instanceof ButtonPlugin)
|
||||
((ButtonPlugin) plugin).justReload();
|
||||
else
|
||||
if (plugin instanceof ButtonPlugin) {
|
||||
if (!((ButtonPlugin) plugin).justReload()) {
|
||||
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
|
||||
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) {
|
||||
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) {
|
||||
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
|
||||
|
|
|
@ -47,6 +47,7 @@ import java.util.logging.Logger;
|
|||
public class MainPlugin extends ButtonPlugin {
|
||||
public static MainPlugin Instance;
|
||||
public static Permission permission;
|
||||
@Nullable
|
||||
public static Essentials ess;
|
||||
|
||||
private Logger logger;
|
||||
|
@ -60,19 +61,38 @@ public class MainPlugin extends ButtonPlugin {
|
|||
@Setter
|
||||
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() {
|
||||
return getIConfig().getData("writePluginList", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The chat format to use for messages from other platforms if Chroma-Chat is not installed.
|
||||
*/
|
||||
ConfigData<String> chatFormat() {
|
||||
return getIConfig().getData("chatFormat", "[{origin}|" +
|
||||
"{channel}] <{name}> {message}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Print some debug information.
|
||||
*/
|
||||
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
|
||||
public void pluginEnable() {
|
||||
// Logs "Plugin Enabled", registers commands
|
||||
|
@ -90,7 +110,8 @@ public class MainPlugin extends ButtonPlugin {
|
|||
Component.registerComponent(this, new ChannelComponent());
|
||||
Component.registerComponent(this, new RandomTPComponent());
|
||||
Component.registerComponent(this, new MemberComponent());
|
||||
Component.registerComponent(this, new SpawnComponent());
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("Multiverse-Core"))
|
||||
Component.registerComponent(this, new SpawnComponent());
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("Towny")) //It fails to load the component class otherwise
|
||||
Component.registerComponent(this, new TownyComponent());
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("Votifier") && economy != null)
|
||||
|
@ -124,7 +145,8 @@ public class MainPlugin extends ButtonPlugin {
|
|||
TBMCCoreAPI.SendException("Failed to write plugin list!", e);
|
||||
}
|
||||
}
|
||||
ess = Essentials.getPlugin(Essentials.class);
|
||||
if (getServer().getPluginManager().isPluginEnabled("Essentials"))
|
||||
ess = Essentials.getPlugin(Essentials.class);
|
||||
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.lib.architecture.Component;
|
||||
import buttondevteam.lib.architecture.ComponentMetadata;
|
||||
import buttondevteam.lib.architecture.ConfigData;
|
||||
import org.bukkit.Statistic;
|
||||
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.
|
||||
*/
|
||||
@ComponentMetadata(enabledByDefault = false)
|
||||
public class MemberComponent extends Component<MainPlugin> implements Listener {
|
||||
/**
|
||||
* The permission group to give to the player
|
||||
|
@ -62,11 +64,15 @@ public class MemberComponent extends Component<MainPlugin> implements Listener {
|
|||
if (permission != null && !permission.playerInGroup(event.getPlayer(), memberGroup().get())
|
||||
&& (new Date(event.getPlayer().getFirstPlayed()).toInstant().plus(registeredForDays().get(), ChronoUnit.DAYS).isBefore(Instant.now())
|
||||
|| event.getPlayer().getStatistic(playtime.getKey()) > playtime.getValue() * playedHours().get())) {
|
||||
if (permission.playerAddGroup(null, event.getPlayer(), memberGroup().get())) {
|
||||
event.getPlayer().sendMessage("§bYou are a member now. YEEHAW");
|
||||
MainPlugin.Instance.getLogger().info("Added " + event.getPlayer().getName() + " as a member.");
|
||||
} 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.");
|
||||
try {
|
||||
if (permission.playerAddGroup(null, event.getPlayer(), memberGroup().get())) {
|
||||
event.getPlayer().sendMessage("§bYou are a member now. YEEHAW");
|
||||
MainPlugin.Instance.getLogger().info("Added " + event.getPlayer().getName() + " as a member.");
|
||||
} 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.");
|
||||
}
|
||||
} 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;
|
||||
|
||||
import buttondevteam.lib.architecture.Component;
|
||||
import buttondevteam.lib.chat.Command2;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
||||
import buttondevteam.lib.chat.ICommand2MC;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
// @formatter:off
|
||||
@SuppressWarnings("FieldCanBeLocal")@CommandClass
|
||||
public class RandomTP extends TBMCCommandBase
|
||||
@SuppressWarnings("FieldCanBeLocal")@CommandClass(helpText = {
|
||||
"§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
|
||||
|
||||
|
@ -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");
|
||||
System.out.println("Getting border");
|
||||
border = world.getWorldBorder();
|
||||
System.out.println("Getting new location");
|
||||
System.out.println("Success: "+newLocation()); //TODO: It takes 10-30 seconds to find a location (newLocation() was there)
|
||||
}
|
||||
|
||||
/*================================================================================================*/
|
||||
|
||||
public String[] GetHelpText(String alias)
|
||||
{
|
||||
return new String[]
|
||||
{
|
||||
"§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."
|
||||
};
|
||||
Logger logger = component.getPlugin().getLogger();
|
||||
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 boolean OnCommand(CommandSender sender, String command, String[] args)
|
||||
|
||||
@Command2.Subcommand
|
||||
public boolean def(CommandSender sender, Player player)
|
||||
{
|
||||
if (args.length == 0) return false;
|
||||
|
||||
if (sender.isOp()) return rtp(Bukkit.getPlayer(args[0]));
|
||||
if (sender.isOp()) return rtp(player);
|
||||
|
||||
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.lib.architecture.Component;
|
||||
import buttondevteam.lib.architecture.ComponentMetadata;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Author: github.com/iiegit
|
||||
*/
|
||||
@ComponentMetadata(enabledByDefault = false)
|
||||
public class RandomTPComponent extends Component<MainPlugin> {
|
||||
@Override
|
||||
protected void enable() {
|
||||
new RandomTP().onEnable(this); //It registers it's command
|
||||
var rtp = new RandomTP();
|
||||
registerCommand(rtp);
|
||||
rtp.onEnable(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,48 +1,43 @@
|
|||
package buttondevteam.core.component.restart;
|
||||
|
||||
import buttondevteam.core.component.channel.Channel;
|
||||
import buttondevteam.lib.chat.Command2;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import buttondevteam.lib.chat.ICommand2MC;
|
||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
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
|
||||
public class PrimeRestartCommand extends TBMCCommandBase {
|
||||
public class PrimeRestartCommand extends ICommand2MC {
|
||||
private final RestartComponent component;
|
||||
@Override
|
||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
||||
loud = args.length > 0;
|
||||
if (Bukkit.getOnlinePlayers().size() > 0) {
|
||||
sender.sendMessage("§bPlayers online, restart delayed.");
|
||||
if (loud)
|
||||
|
||||
public void def(CommandSender sender, @Command2.TextArg @Command2.OptionalArg String somethingrandom) {
|
||||
loud = somethingrandom != null;
|
||||
if (Bukkit.getOnlinePlayers().size() > 0) {
|
||||
sender.sendMessage("§bPlayers online, restart delayed.");
|
||||
if (loud)
|
||||
TBMCChatAPI.SendSystemMessage(Channel.GlobalChat, Channel.RecipientTestResult.ALL, ChatColor.DARK_RED + "The server will restart as soon as nobody is online.", component.getRestartBroadcast());
|
||||
plsrestart = true;
|
||||
} else {
|
||||
sender.sendMessage("§bNobody is online. Restarting now.");
|
||||
if (loud)
|
||||
plsrestart = true;
|
||||
} else {
|
||||
sender.sendMessage("§bNobody is online. Restarting now.");
|
||||
if (loud)
|
||||
TBMCChatAPI.SendSystemMessage(Channel.GlobalChat, Channel.RecipientTestResult.ALL, "§cNobody is online. Restarting server.", component.getRestartBroadcast());
|
||||
Bukkit.spigot().restart();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Bukkit.spigot().restart();
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
private static boolean plsrestart = false;
|
||||
@Getter
|
||||
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
|
||||
public void enable() {
|
||||
registerCommand(new ScheduledRestartCommand(this));
|
||||
TBMCChatAPI.AddCommand(this, new PrimeRestartCommand(this));
|
||||
registerCommand(new PrimeRestartCommand(this));
|
||||
registerListener(this);
|
||||
restartBroadcast = TBMCSystemChatEvent.BroadcastTarget.add("restartCountdown");
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import buttondevteam.lib.architecture.ConfigData;
|
|||
import buttondevteam.lib.chat.Command2;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import buttondevteam.lib.chat.ICommand2MC;
|
||||
import com.earth2me.essentials.Trade;
|
||||
import com.google.common.io.ByteArrayDataInput;
|
||||
import com.google.common.io.ByteArrayDataOutput;
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
@ -13,10 +14,15 @@ import com.onarandombox.MultiverseCore.MultiverseCore;
|
|||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.bukkit.plugin.messaging.PluginMessageListener;
|
||||
|
||||
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 {
|
||||
@Override
|
||||
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() {
|
||||
return getConfig().getData("targetServer", "");
|
||||
|
@ -86,8 +92,16 @@ public class SpawnComponent extends Component<MainPlugin> implements PluginMessa
|
|||
@Command2.Subcommand
|
||||
public void def(Player player) {
|
||||
if (targetServer().get().length() == 0) {
|
||||
player.sendMessage("§bTeleporting to spawn.");
|
||||
player.teleport(spawnloc);
|
||||
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);
|
||||
} catch (Exception e) {
|
||||
player.sendMessage("§cFailed to teleport: " + e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
ByteArrayDataOutput out = ByteStreams.newDataOutput();
|
||||
|
|
|
@ -31,7 +31,9 @@ public class TownyComponent extends Component<MainPlugin> {
|
|||
*/
|
||||
public static void renameInTowny(String oldName, String newName) {
|
||||
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
|
||||
if (resident == null) {
|
||||
Bukkit.getLogger().warning("Resident not found - couldn't rename in Towny.");
|
||||
|
@ -42,6 +44,7 @@ public class TownyComponent extends Component<MainPlugin> {
|
|||
} else
|
||||
try {
|
||||
tu.getDataSource().renamePlayer(resident, newName); //Fixed in Towny 0.91.1.2
|
||||
Bukkit.getLogger().info("Renaming done.");
|
||||
} catch (AlreadyRegisteredException e) {
|
||||
TBMCCoreAPI.SendException("Failed to rename resident, there's already one with this name.", e);
|
||||
} catch (NotRegisteredException e) {
|
||||
|
|
|
@ -2,15 +2,16 @@ package buttondevteam.core.component.updater;
|
|||
|
||||
import buttondevteam.core.MainPlugin;
|
||||
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
|
||||
@Override
|
||||
public void enable() {
|
||||
TBMCChatAPI.AddCommand(this, new UpdatePluginCommand());
|
||||
registerCommand(new UpdatePluginCommand());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -2,40 +2,41 @@ package buttondevteam.core.component.updater;
|
|||
|
||||
import buttondevteam.core.MainPlugin;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.chat.Command2;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
||||
import buttondevteam.lib.chat.ICommand2MC;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@CommandClass(modOnly = true)
|
||||
public class UpdatePluginCommand extends TBMCCommandBase {
|
||||
@Override
|
||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(MainPlugin.Instance, () -> {
|
||||
if (args.length == 0) {
|
||||
sender.sendMessage("Downloading plugin names...");
|
||||
boolean first = true;
|
||||
for (String plugin : PluginUpdater.GetPluginNames()) {
|
||||
if (first) {
|
||||
sender.sendMessage("§6---- Plugin names ----");
|
||||
first = false;
|
||||
}
|
||||
sender.sendMessage("- " + plugin);
|
||||
}
|
||||
} else {
|
||||
TBMCCoreAPI.UpdatePlugin(args[0], sender, args.length == 1 ? "master" : args[1]);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
public class UpdatePluginCommand extends ICommand2MC {
|
||||
public void def(CommandSender sender, @Command2.OptionalArg String plugin, @Command2.OptionalArg String branch) {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(MainPlugin.Instance, () -> {
|
||||
if (plugin == null) {
|
||||
sender.sendMessage("Downloading plugin names...");
|
||||
boolean first = true;
|
||||
for (String plugin2 : PluginUpdater.GetPluginNames()) {
|
||||
if (first) {
|
||||
sender.sendMessage("§6---- Plugin names ----");
|
||||
first = false;
|
||||
}
|
||||
sender.sendMessage("- " + plugin2);
|
||||
}
|
||||
} else {
|
||||
TBMCCoreAPI.UpdatePlugin(plugin, sender, branch == null ? "master" : branch);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] GetHelpText(String alias) {
|
||||
return new String[] { //
|
||||
"§6---- Update plugin ----", //
|
||||
"This command downloads the latest version of a TBMC plugin from GitHub", //
|
||||
"To update a plugin: /" + alias + " <plugin>", //
|
||||
"To list the plugin names: /" + alias //
|
||||
public String[] getHelpText(Method method, Command2.Subcommand ann) {
|
||||
return new String[]{ //
|
||||
"§6---- Update plugin ----", //
|
||||
"This command downloads the latest version of a custom plugin from GitHub", //
|
||||
"To update a plugin: add its name", //
|
||||
"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.lib.architecture.Component;
|
||||
import buttondevteam.lib.architecture.ComponentMetadata;
|
||||
import buttondevteam.lib.architecture.ConfigData;
|
||||
import com.vexsoftware.votifier.model.Vote;
|
||||
import com.vexsoftware.votifier.model.VotifierEvent;
|
||||
|
@ -15,6 +16,7 @@ import org.bukkit.event.EventHandler;
|
|||
* Do not use (EULA)
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@ComponentMetadata(enabledByDefault = false)
|
||||
public class VotifierComponent extends Component<MainPlugin> {
|
||||
private final Economy economy;
|
||||
|
||||
|
@ -39,11 +41,11 @@ public class VotifierComponent extends Component<MainPlugin> {
|
|||
getPlugin().getLogger().info("Vote: " + vote);
|
||||
org.bukkit.OfflinePlayer op = Bukkit.getOfflinePlayer(vote.getUsername());
|
||||
Player p = Bukkit.getPlayer(vote.getUsername());
|
||||
if (op != null) {
|
||||
/*if (op != null) {
|
||||
economy.depositPlayer(op, rewardAmount().get());
|
||||
}
|
||||
if (p != null) {
|
||||
p.sendMessage("§bThanks for voting! $50 was added to your account.");
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,34 +1,41 @@
|
|||
package buttondevteam.lib.architecture;
|
||||
|
||||
import buttondevteam.buttonproc.HasConfig;
|
||||
import buttondevteam.core.ComponentManager;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.chat.Command2MC;
|
||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||
import lombok.AccessLevel;
|
||||
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 java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.Stack;
|
||||
|
||||
@HasConfig
|
||||
@HasConfig(global = true)
|
||||
public abstract class ButtonPlugin extends JavaPlugin {
|
||||
@Getter
|
||||
private static Command2MC command2MC = new Command2MC();
|
||||
@Getter(AccessLevel.PROTECTED)
|
||||
private IHaveConfig iConfig;
|
||||
private CommentedConfiguration yaml;
|
||||
@Getter(AccessLevel.PROTECTED)
|
||||
private IHaveConfig data; //TODO
|
||||
private boolean loaded = false;
|
||||
/**
|
||||
* Used to unregister components in the right order - and to reload configs
|
||||
*/
|
||||
@Getter
|
||||
private Stack<Component<?>> componentStack = new Stack<>();
|
||||
;
|
||||
|
||||
protected abstract void pluginEnable();
|
||||
|
||||
|
@ -45,7 +52,10 @@ public abstract class ButtonPlugin extends JavaPlugin {
|
|||
|
||||
@Override
|
||||
public final void onEnable() {
|
||||
loadConfig();
|
||||
if (!loadConfig()) {
|
||||
getLogger().warning("Please fix the issues and restart the server to load the plugin.");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
pluginEnable();
|
||||
} catch (Exception e) {
|
||||
|
@ -55,10 +65,14 @@ public abstract class ButtonPlugin extends JavaPlugin {
|
|||
IHaveConfig.pregenConfig(this, null);
|
||||
}
|
||||
|
||||
private void loadConfig() {
|
||||
var section = super.getConfig().getConfigurationSection("global");
|
||||
if (section == null) section = super.getConfig().createSection("global");
|
||||
private boolean loadConfig() {
|
||||
var config = getConfig();
|
||||
if (config == null)
|
||||
return false;
|
||||
var section = config.getConfigurationSection("global");
|
||||
if (section == null) section = config.createSection("global");
|
||||
iConfig = new IHaveConfig(section, this::saveConfig);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -67,9 +81,10 @@ public abstract class ButtonPlugin extends JavaPlugin {
|
|||
pluginPreDisable();
|
||||
ComponentManager.unregComponents(this);
|
||||
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
|
||||
TBMCChatAPI.RemoveCommands(this);
|
||||
//TBMCChatAPI.RemoveCommands(this); - TODO
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("Error while disabling plugin " + getName() + "!", e);
|
||||
}
|
||||
|
@ -88,15 +103,50 @@ public abstract class ButtonPlugin extends JavaPlugin {
|
|||
}
|
||||
|
||||
public boolean justReload() {
|
||||
if (loaded && ConfigData.saveNow(getConfig())) {
|
||||
getLogger().warning("Saved pending configuration changes to the file, didn't reload (try again).");
|
||||
if (yaml != null && ConfigData.saveNow(getConfig())) {
|
||||
getLogger().warning("Saved pending configuration changes to the file, didn't reload. Apply your changes again.");
|
||||
return false;
|
||||
}
|
||||
super.reloadConfig();
|
||||
loaded = true; //Needed because for the first time it uses reloadConfig() to load it
|
||||
var file = new File(getDataFolder(), "config.yml");
|
||||
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;
|
||||
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)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface ConfigOpts {
|
||||
|
|
|
@ -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;
|
||||
|
||||
import buttondevteam.buttonproc.HasConfig;
|
||||
import buttondevteam.core.ComponentManager;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.architecture.exceptions.UnregisteredComponentException;
|
||||
import buttondevteam.lib.chat.ICommand2MC;
|
||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.val;
|
||||
|
@ -16,13 +15,14 @@ import org.bukkit.plugin.java.JavaPlugin;
|
|||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 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> {
|
||||
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
|
||||
|
||||
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());
|
||||
} else {
|
||||
component.disable();
|
||||
component.plugin.saveConfig();
|
||||
TBMCChatAPI.RemoveCommands(component);
|
||||
//TBMCChatAPI.RemoveCommands(component); - TODO
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,15 +211,6 @@ public abstract class Component<TP extends JavaPlugin> {
|
|||
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
|
||||
*
|
||||
|
|
|
@ -9,4 +9,6 @@ import java.lang.annotation.Target;
|
|||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ComponentMetadata {
|
||||
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.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
|
@ -32,7 +32,7 @@ public class ConfigData<T> {
|
|||
@Getter
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
private String path;
|
||||
private final T def;
|
||||
protected final T def;
|
||||
private final Object primitiveDef;
|
||||
private final Runnable saveAction;
|
||||
/**
|
||||
|
@ -48,10 +48,6 @@ public class ConfigData<T> {
|
|||
* The config value should not change outside this instance
|
||||
*/
|
||||
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
|
||||
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")
|
||||
public T get() {
|
||||
if (value != null) return value; //Speed things up
|
||||
Object val = config == null ? null : config.get(path); //config==null: testing
|
||||
if (val == null) {
|
||||
Object val;
|
||||
if (config == null || !config.isSet(path)) { //Call set() if config == null
|
||||
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
|
||||
config.set(path, primitiveDef);
|
||||
setInternal(primitiveDef); //If read-only then we still need to save the default value so it can be set
|
||||
else
|
||||
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) {
|
||||
val = convert.apply(val, primitiveDef);
|
||||
T hmm = getter.apply(val);
|
||||
if (hmm == null) hmm = def; //Set if the getter returned null
|
||||
return hmm;
|
||||
}
|
||||
if (val instanceof Number && def != null)
|
||||
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));
|
||||
val = convert.apply(val, def);
|
||||
return value = (T) val; //Always cache, if not cached yet
|
||||
}
|
||||
|
||||
|
@ -115,20 +119,23 @@ public class ConfigData<T> {
|
|||
if (setter != null && value != null)
|
||||
val = setter.apply(value);
|
||||
else val = value;
|
||||
if (config != null) {
|
||||
config.set(path, val);
|
||||
if (!saveTasks.containsKey(config.getRoot())) {
|
||||
synchronized (saveTasks) {
|
||||
saveTasks.put(config.getRoot(), new SaveTask(Bukkit.getScheduler().runTaskLaterAsynchronously(MainPlugin.Instance, () -> {
|
||||
synchronized (saveTasks) {
|
||||
saveTasks.remove(config.getRoot());
|
||||
saveAction.run();
|
||||
}
|
||||
}, 100), saveAction));
|
||||
}
|
||||
if (config != null)
|
||||
setInternal(val);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
private void setInternal(Object val) {
|
||||
config.set(path, val);
|
||||
if (!saveTasks.containsKey(config.getRoot())) {
|
||||
synchronized (saveTasks) {
|
||||
saveTasks.put(config.getRoot(), new SaveTask(Bukkit.getScheduler().runTaskLaterAsynchronously(MainPlugin.Instance, () -> {
|
||||
synchronized (saveTasks) {
|
||||
saveTasks.remove(config.getRoot());
|
||||
saveAction.run();
|
||||
}
|
||||
}, 100), saveAction));
|
||||
}
|
||||
}
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
|
@ -138,12 +145,14 @@ public class ConfigData<T> {
|
|||
}
|
||||
|
||||
public static boolean saveNow(Configuration config) {
|
||||
SaveTask st = saveTasks.get(config);
|
||||
if (st != null) {
|
||||
st.task.cancel();
|
||||
saveTasks.remove(config);
|
||||
st.saveAction.run();
|
||||
return true;
|
||||
synchronized (saveTasks) {
|
||||
SaveTask st = saveTasks.get(config);
|
||||
if (st != null) {
|
||||
st.task.cancel();
|
||||
saveTasks.remove(config);
|
||||
st.saveAction.run();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -139,6 +139,21 @@ public final class IHaveConfig {
|
|||
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.
|
||||
*
|
||||
|
|
|
@ -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 {
|
||||
handleCommandAsync(sender, commandline, sd, subcommand, sync);
|
||||
} 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
|
||||
|
@ -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
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
if (sd.method == null || sd.command == null) { //Main command not registered, but we have subcommands
|
||||
sender.sendMessage(sd.helpText);
|
||||
|
@ -247,7 +258,7 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
|||
|
||||
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();
|
||||
int x = path.indexOf(' ');
|
||||
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) {
|
||||
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'
|
||||
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
|
||||
scmdHelpList.add(subcommand);
|
||||
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");
|
||||
if (str == null)
|
||||
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.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.server.TabCompleteEvent;
|
||||
|
@ -16,7 +17,6 @@ import java.lang.annotation.Annotation;
|
|||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
|
||||
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(' ', '.');
|
||||
if (Bukkit.getPluginManager().getPermission(perm) == null) //Check needed for plugin reset
|
||||
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()) {
|
||||
if (!method.isAnnotationPresent(Subcommand.class)) continue;
|
||||
String pg = permGroup(command, method);
|
||||
|
@ -34,7 +34,6 @@ public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implemen
|
|||
perm = "chroma." + pg;
|
||||
if (Bukkit.getPluginManager().getPermission(perm) == null) //It may occur multiple times
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -50,16 +49,18 @@ public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implemen
|
|||
boolean p = true;
|
||||
String[] perms = {
|
||||
"chroma.command." + command.getCommandPath().replace(' ', '.'),
|
||||
(pg = permGroup(command, method)).length() > 0 ? "chroma." + pg : null,
|
||||
modOnly(command) ? "tbmc.admin" : null
|
||||
(pg = permGroup(command, method)).length() > 0 ? "chroma." + pg : null
|
||||
};
|
||||
for (String perm : perms) {
|
||||
if (perm != null) {
|
||||
if (p) { //Use OfflinePlayer to avoid fetching player data
|
||||
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
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
*
|
||||
* @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.
|
||||
* 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 method The subcommand to check
|
||||
* @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) {
|
||||
return sc.permGroup();
|
||||
}
|
||||
if (getAnnForValue(command.getClass(), CommandClass.class, CommandClass::modOnly, false))
|
||||
return Subcommand.MOD_GROUP;
|
||||
return getAnnForValue(command.getClass(), CommandClass.class, CommandClass::permGroup, "");
|
||||
}
|
||||
|
||||
|
|
|
@ -17,4 +17,9 @@ public class Command2MCSender implements Command2Sender {
|
|||
public void sendMessage(String[] 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);
|
||||
|
||||
String getName();
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ public abstract class ICommand2<TP extends Command2Sender> {
|
|||
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
|
||||
&& !cl.getPackage().getName().equals(ICommand2MC.class.getPackage().getName()); cl = cl
|
||||
.getSuperclass()) { //
|
||||
String newpath;
|
||||
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;
|
||||
|
||||
import buttondevteam.core.CommandCaller;
|
||||
import buttondevteam.core.MainPlugin;
|
||||
import buttondevteam.core.component.channel.Channel;
|
||||
import buttondevteam.core.component.channel.Channel.RecipientTestResult;
|
||||
import buttondevteam.lib.*;
|
||||
import buttondevteam.lib.architecture.Component;
|
||||
import buttondevteam.lib.ChromaUtils;
|
||||
import buttondevteam.lib.TBMCChatEvent;
|
||||
import buttondevteam.lib.TBMCChatPreprocessEvent;
|
||||
import buttondevteam.lib.TBMCSystemChatEvent;
|
||||
import lombok.val;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import 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.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
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>
|
||||
* 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 {
|
||||
|
||||
}
|
|
@ -36,7 +36,7 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase {
|
|||
|
||||
/**
|
||||
* Use from a method with the name of the key. For example, use flair() for the enclosing method to save to and load from "flair"
|
||||
*
|
||||
*
|
||||
* @return A data object with methods to get and set
|
||||
*/
|
||||
@Override
|
||||
|
@ -46,7 +46,7 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase {
|
|||
|
||||
/**
|
||||
* Use from a method with the name of the key. For example, use flair() for the enclosing method to save to and load from "flair"
|
||||
*
|
||||
*
|
||||
* @return A data object with methods to get and set
|
||||
*/
|
||||
@Override
|
||||
|
@ -56,11 +56,9 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase {
|
|||
|
||||
/**
|
||||
* Get player as a plugin player
|
||||
*
|
||||
* @param uuid
|
||||
* The UUID of the player to get
|
||||
* @param cl
|
||||
* The type of the player
|
||||
*
|
||||
* @param uuid The UUID of the player to get
|
||||
* @param cl The type of the player
|
||||
* @return The requested player object
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -79,7 +77,7 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase {
|
|||
return player;
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException(
|
||||
"Failed to get player with UUID " + uuid + " and class " + cl.getSimpleName() + "!", e);
|
||||
"Failed to get player with UUID " + uuid + " and class " + cl.getSimpleName() + "!", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -92,9 +90,8 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase {
|
|||
/**
|
||||
* 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
|
||||
*
|
||||
* @param cl
|
||||
* The TBMCPlayer subclass
|
||||
*
|
||||
* @param cl The TBMCPlayer subclass
|
||||
*/
|
||||
public <T extends TBMCPlayerBase> T asPluginPlayer(Class<T> cl) {
|
||||
return getPlayer(uuid, cl);
|
||||
|
@ -122,10 +119,9 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase {
|
|||
player.PlayerName().set(p.getName());
|
||||
Bukkit.getLogger().info("Player name saved: " + 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());
|
||||
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);
|
||||
|
||||
|
@ -142,16 +138,16 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase {
|
|||
final TBMCPlayerBase player = playermap.get(p.getUniqueId() + "-" + TBMCPlayer.class.getSimpleName());
|
||||
player.save();
|
||||
Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerQuitEvent(player, p));
|
||||
playermap.entrySet().removeIf(entry -> entry.getKey().startsWith(p.getUniqueId().toString()));
|
||||
playermap.entrySet().removeIf(entry -> entry.getKey().startsWith(p.getUniqueId().toString()));
|
||||
}
|
||||
|
||||
public static void savePlayers() {
|
||||
playermap.values().forEach(p -> {
|
||||
playermap.values().forEach(p -> {
|
||||
try {
|
||||
p.close();
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("Error while saving player " + p.PlayerName().get() + " (" + p.getFolder()
|
||||
+ "/" + p.getFileName() + ")!", e);
|
||||
+ "/" + p.getFileName() + ")!", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -159,7 +155,7 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase {
|
|||
/**
|
||||
* This method returns a TBMC player from their name. Calling this method may return an offline player which will load it, therefore it's highly recommended to use {@link #close()} to unload the
|
||||
* player data. Using try-with-resources may be the easiest way to achieve this. Example:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* try(TBMCPlayer player = getFromName(p))
|
||||
|
@ -167,9 +163,8 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase {
|
|||
* ...
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param name
|
||||
* The player's name
|
||||
*
|
||||
* @param name The player's name
|
||||
* @return The {@link TBMCPlayer} object for the player
|
||||
*/
|
||||
public static <T extends TBMCPlayerBase> T getFromName(String name, Class<T> cl) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
name: ChromaCore
|
||||
main: buttondevteam.core.MainPlugin
|
||||
version: 1.0
|
||||
author: TBMCPlugins
|
||||
author: NorbiPeti
|
||||
commands:
|
||||
updateplugin:
|
||||
description: Update a TBMC plugin
|
||||
|
@ -21,4 +21,5 @@ depend:
|
|||
softdepend:
|
||||
- Towny
|
||||
- Votifier
|
||||
- Multiverse-Core
|
||||
- Multiverse-Core
|
||||
- Essentials
|
|
@ -1,5 +1,8 @@
|
|||
package buttondevteam.buttonproc;
|
||||
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
|
@ -10,29 +13,40 @@ import javax.lang.model.type.TypeMirror;
|
|||
import javax.tools.FileObject;
|
||||
import javax.tools.StandardLocation;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ConfigProcessor {
|
||||
private final ProcessingEnvironment procEnv;
|
||||
private final FileWriter sw;
|
||||
private final YamlConfiguration yc = new YamlConfiguration();
|
||||
private final FileObject fo;
|
||||
|
||||
public ConfigProcessor(ProcessingEnvironment procEnv) {
|
||||
FileObject fo1;
|
||||
this.procEnv = procEnv;
|
||||
FileWriter sw = null;
|
||||
try {
|
||||
FileObject file = procEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", "configHelp.md");
|
||||
sw = new FileWriter(new File(file.toUri()));
|
||||
System.out.println(file.toUri());
|
||||
fo1 = procEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", "configHelp.yml");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
fo1 = null;
|
||||
}
|
||||
this.sw = sw;
|
||||
this.fo = fo1;
|
||||
}
|
||||
|
||||
public void process(Element targetcl) {
|
||||
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()) {
|
||||
/*System.out.println("Element: "+e);
|
||||
System.out.println("Type: "+e.getClass()+" - "+e.getKind());
|
||||
|
@ -49,30 +63,18 @@ public class ConfigProcessor {
|
|||
String doc = procEnv.getElementUtils().getDocComment(e);
|
||||
if (doc == null) continue;
|
||||
System.out.println("DOC: " + doc);
|
||||
try {
|
||||
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();
|
||||
}
|
||||
yc.set(path + "." + e.getSimpleName(), doc.trim());
|
||||
}
|
||||
String javadoc = procEnv.getElementUtils().getDocComment(targetcl);
|
||||
if (javadoc != null) {
|
||||
System.out.println("JAVADOC");
|
||||
System.out.println(javadoc.trim());
|
||||
yc.set(path, javadoc.trim());
|
||||
}
|
||||
try {
|
||||
if (javadoc != null) {
|
||||
System.out.println("JAVADOC");
|
||||
System.out.println(javadoc.trim());
|
||||
sw.append(path).append(System.lineSeparator()).append(System.lineSeparator());
|
||||
sw.append(javadoc).append(System.lineSeparator()).append(System.lineSeparator());
|
||||
}
|
||||
sw.flush();
|
||||
yc.save(file);
|
||||
} catch (IOException e) {
|
||||
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.Inherited;
|
||||
|
@ -10,4 +10,5 @@ import java.lang.annotation.Target;
|
|||
@Target(ElementType.TYPE)
|
||||
@Inherited
|
||||
public @interface HasConfig {
|
||||
boolean global();
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
<module name="ButtonProcessor" />
|
||||
</modules>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_13_PREVIEW">
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_11">
|
||||
<output url="file://$MODULE_DIR$/target/classes" />
|
||||
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
|
|
|
@ -95,10 +95,12 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<release>13</release>
|
||||
<release>11</release>
|
||||
<!--
|
||||
<compilerArgs>
|
||||
<arg>--enable-preview</arg>
|
||||
<arg>HYPHENHYPHENenable-preview</arg>
|
||||
</compilerArgs>
|
||||
-->
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
|
Loading…
Reference in a new issue