Merge pull request #61 from TBMCPlugins/dev
New command system, fixes, improvements
This commit is contained in:
commit
98b73aaac3
48 changed files with 1092 additions and 590 deletions
|
@ -1,13 +0,0 @@
|
|||
<component name="libraryTable">
|
||||
<library name="Maven: com.github.TBMCPlugins.ButtonCore:Towny:master-248b0d8d0a-1">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/com/github/TBMCPlugins/ButtonCore/Towny/master-248b0d8d0a-1/Towny-master-248b0d8d0a-1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/com/github/TBMCPlugins/ButtonCore/Towny/master-248b0d8d0a-1/Towny-master-248b0d8d0a-1-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/com/github/TBMCPlugins/ButtonCore/Towny/master-248b0d8d0a-1/Towny-master-248b0d8d0a-1-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
|
@ -1,13 +0,0 @@
|
|||
<component name="libraryTable">
|
||||
<library name="Maven: com.github.milkbowl:VaultAPI:master-431c5273c2-1">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/com/github/milkbowl/VaultAPI/master-431c5273c2-1/VaultAPI-master-431c5273c2-1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/com/github/milkbowl/VaultAPI/master-431c5273c2-1/VaultAPI-master-431c5273c2-1-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/com/github/milkbowl/VaultAPI/master-431c5273c2-1/VaultAPI-master-431c5273c2-1-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
|
@ -12,6 +12,7 @@
|
|||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="ButtonCore (1) (com.github.TBMCPlugins.ButtonCore)" />
|
||||
<orderEntry type="module" module-name="ButtonCore (1) (com.github.TBMCPlugins.ButtonCore)" />
|
||||
<orderEntry type="library" name="Maven: org.reflections:reflections:0.9.10" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.google.code.findbugs:annotations:2.0.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.javassist:javassist:3.20.0-GA" level="project" />
|
||||
|
@ -19,6 +20,7 @@
|
|||
<orderEntry type="library" scope="RUNTIME" name="Maven: net.bytebuddy:byte-buddy:1.6.11" level="project" />
|
||||
<orderEntry type="library" scope="RUNTIME" name="Maven: net.bytebuddy:byte-buddy-agent:1.6.11" level="project" />
|
||||
<orderEntry type="library" scope="RUNTIME" name="Maven: org.objenesis:objenesis:2.5" level="project" />
|
||||
<orderEntry type="module" module-name="ButtonProcessor" />
|
||||
<orderEntry type="library" name="Maven: org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT" level="project" />
|
||||
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.6" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.googlecode.json-simple:json-simple:1.1.1" level="project" />
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import buttondevteam.component.updater.PluginUpdater;
|
||||
import buttondevteam.core.component.updater.PluginUpdater;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
|
|
@ -167,7 +167,7 @@
|
|||
<groupId>com.github.TBMCPlugins.ButtonCore</groupId>
|
||||
<artifactId>ButtonProcessor</artifactId>
|
||||
<version>master-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.ess3</groupId>
|
||||
|
|
|
@ -2,62 +2,65 @@ package buttondevteam.core;
|
|||
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.architecture.Component;
|
||||
import buttondevteam.lib.chat.Command2MC;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
||||
import lombok.val;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@CommandClass(modOnly = true)
|
||||
public class ComponentCommand extends TBMCCommandBase {
|
||||
@Override
|
||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
||||
if (args.length < 1)
|
||||
return false;
|
||||
boolean enable = true;
|
||||
try {
|
||||
switch (args[0]) {
|
||||
case "enable":
|
||||
enable = true;
|
||||
break;
|
||||
case "disable":
|
||||
enable = false;
|
||||
break;
|
||||
case "list":
|
||||
sender.sendMessage("§6List of components:");
|
||||
Component.getComponents().values().stream().map(c -> c.getPlugin().getName() + " - " + c.getClass().getSimpleName() + " - " + (c.isEnabled() ? "en" : "dis") + "abled").forEach(sender::sendMessage);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@CommandClass(modOnly = true, helpText = {
|
||||
"§6---- Component command ----",
|
||||
"Can be used to enable/disable/list components"
|
||||
})
|
||||
public class ComponentCommand extends Command2MC {
|
||||
public ComponentCommand() {
|
||||
addParamConverter(Plugin.class, arg -> Bukkit.getPluginManager().getPlugin(arg));
|
||||
|
||||
}
|
||||
if (args.length < 2)
|
||||
return false;
|
||||
val oc = getComponentOrError(args[1], sender);
|
||||
|
||||
@Subcommand
|
||||
public boolean enable(CommandSender sender, Plugin plugin, String component) {
|
||||
if (plugin == null) return respond(sender, "§cPlugin not found!");
|
||||
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
|
||||
public boolean disable(CommandSender sender, Plugin plugin, String component) {
|
||||
if (plugin == null) return respond(sender, "§cPlugin not found!");
|
||||
return enable_disable(sender, plugin, component, false);
|
||||
}
|
||||
|
||||
@Subcommand
|
||||
public boolean list(CommandSender sender, 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
|
||||
.map(c -> c.getPlugin().getName() + " - " + c.getClass().getSimpleName() + " - " + (c.isEnabled() ? "en" : "dis") + "abled").forEach(sender::sendMessage);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean enable_disable(CommandSender sender, Plugin plugin, String component, boolean enable) {
|
||||
try {
|
||||
val oc = getComponentOrError(plugin, component, sender);
|
||||
if (!oc.isPresent())
|
||||
return true;
|
||||
if (enable) //Reload config so the new config values are read
|
||||
getPlugin().reloadConfig(); //All changes are saved to disk on disable
|
||||
Component.setComponentEnabled(oc.get(), enable);
|
||||
sender.sendMessage(oc.get().getClass().getSimpleName() + " " + (enable ? "en" : "dis") + "abled.");
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("Couldn't " + (enable ? "en" : "dis") + "able component " + args[0] + "!", e);
|
||||
TBMCCoreAPI.SendException("Couldn't " + (enable ? "en" : "dis") + "able component " + component + "!", e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private Optional<Component> getComponentOrError(String arg, CommandSender sender) {
|
||||
val oc = Component.getComponents().values().stream().filter(c -> c.getClass().getSimpleName().equalsIgnoreCase(arg)).findAny();
|
||||
private Optional<Component> getComponentOrError(Plugin plugin, String arg, CommandSender sender) {
|
||||
val oc = Component.getComponents().values().stream()
|
||||
.filter(c -> plugin.getName().equals(c.getPlugin().getName()))
|
||||
.filter(c -> c.getClass().getSimpleName().equalsIgnoreCase(arg)).findAny();
|
||||
if (!oc.isPresent())
|
||||
sender.sendMessage("§cComponent not found!");
|
||||
sender.sendMessage("§cComponent not found!"); //^ Much simpler to solve in the new command system
|
||||
return oc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] GetHelpText(String alias) {
|
||||
return new String[]{
|
||||
"§6---- Component command ----",
|
||||
"Enable or disable or list components"
|
||||
};
|
||||
}
|
||||
} //TODO: Tabcompletion for the new command system
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package buttondevteam.core;
|
||||
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.architecture.ButtonPlugin;
|
||||
import buttondevteam.lib.architecture.Component;
|
||||
import lombok.val;
|
||||
|
||||
|
@ -31,16 +32,11 @@ public final class ComponentManager {
|
|||
}
|
||||
|
||||
/**
|
||||
* Disables all components that are enabled
|
||||
* Unregister all components of a plugin that are enabled - called on {@link ButtonPlugin} disable
|
||||
*/
|
||||
public static void disableComponents() {
|
||||
Component.getComponents().values().stream().filter(Component::isEnabled).forEach(c -> {
|
||||
try {
|
||||
Component.setComponentEnabled(c, false);
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("Failed to disable one of the components: " + c.getClass().getSimpleName(), e);
|
||||
}
|
||||
});
|
||||
public static void unregComponents(ButtonPlugin plugin) {
|
||||
while (!plugin.getComponentStack().empty()) //Unregister in reverse order
|
||||
Component.unregisterComponent(plugin, plugin.getComponentStack().pop()); //Components are pushed on register
|
||||
componentsEnabled = false;
|
||||
}
|
||||
|
||||
|
@ -54,4 +50,16 @@ public final class ComponentManager {
|
|||
val c = Component.getComponents().get(cl);
|
||||
return c != null && c.isEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Will also return null if the component is not registered.
|
||||
*
|
||||
* @param cl The component class
|
||||
* @return The component if it's registered and enabled
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends Component> T getIfEnabled(Class<T> cl) {
|
||||
val c = Component.getComponents().get(cl);
|
||||
return c != null && c.isEnabled() ? (T) c : null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
package buttondevteam.core;
|
||||
|
||||
import buttondevteam.component.channel.Channel;
|
||||
import buttondevteam.component.channel.ChannelComponent;
|
||||
import buttondevteam.component.channel.ChatRoom;
|
||||
import buttondevteam.component.members.MemberComponent;
|
||||
import buttondevteam.component.randomtp.RandomTPComponent;
|
||||
import buttondevteam.component.restart.RestartComponent;
|
||||
import buttondevteam.component.towny.TownyComponent;
|
||||
import buttondevteam.component.updater.PluginUpdater;
|
||||
import buttondevteam.component.updater.PluginUpdaterComponent;
|
||||
import buttondevteam.core.component.channel.Channel;
|
||||
import buttondevteam.core.component.channel.ChannelComponent;
|
||||
import buttondevteam.core.component.channel.ChatRoom;
|
||||
import buttondevteam.core.component.members.MemberComponent;
|
||||
import buttondevteam.core.component.randomtp.RandomTPComponent;
|
||||
import buttondevteam.core.component.restart.RestartComponent;
|
||||
import buttondevteam.core.component.towny.TownyComponent;
|
||||
import buttondevteam.core.component.updater.PluginUpdater;
|
||||
import buttondevteam.core.component.updater.PluginUpdaterComponent;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.architecture.ButtonPlugin;
|
||||
import buttondevteam.lib.architecture.Component;
|
||||
import buttondevteam.lib.architecture.ConfigData;
|
||||
import buttondevteam.lib.chat.Color;
|
||||
import buttondevteam.lib.chat.Command2MC;
|
||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||
import buttondevteam.lib.player.ChromaGamerBase;
|
||||
import buttondevteam.lib.player.TBMCPlayer;
|
||||
|
@ -68,7 +69,7 @@ public class MainPlugin extends ButtonPlugin {
|
|||
Component.registerComponent(this, new MemberComponent());
|
||||
Component.registerComponent(this, new TownyComponent());
|
||||
ComponentManager.enableComponents();
|
||||
TBMCChatAPI.AddCommand(this, ComponentCommand.class);
|
||||
Command2MC.registerCommand(new ComponentCommand());
|
||||
TBMCCoreAPI.RegisterEventsForExceptions(new PlayerListener(), this);
|
||||
ChromaGamerBase.addConverter(commandSender -> Optional.ofNullable(commandSender instanceof ConsoleCommandSender || commandSender instanceof BlockCommandSender
|
||||
? TBMCPlayer.getPlayer(new UUID(0, 0), TBMCPlayer.class) : null)); //Console & cmdblocks
|
||||
|
@ -100,7 +101,6 @@ public class MainPlugin extends ButtonPlugin {
|
|||
|
||||
@Override
|
||||
public void pluginDisable() {
|
||||
ComponentManager.disableComponents();
|
||||
logger.info("Saving player data...");
|
||||
TBMCPlayerBase.savePlayers();
|
||||
logger.info("Player data saved.");
|
||||
|
@ -132,6 +132,7 @@ public class MainPlugin extends ButtonPlugin {
|
|||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (command.getName().equals("dontrunthiscmd")) return true; //Used in chat preprocess for console
|
||||
sender.sendMessage("§cThis command isn't available."); //In theory, unregistered commands use this method
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,21 @@
|
|||
package buttondevteam.core;
|
||||
|
||||
import buttondevteam.lib.TBMCCommandPreprocessEvent;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.TBMCSystemChatEvent;
|
||||
import buttondevteam.lib.chat.Command2MC;
|
||||
import buttondevteam.lib.player.TBMCPlayerBase;
|
||||
import lombok.val;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.server.ServerCommandEvent;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
|
@ -32,4 +40,33 @@ public class PlayerListener implements Listener {
|
|||
Bukkit.getOnlinePlayers().stream().filter(event::shouldSendTo)
|
||||
.forEach(p -> p.sendMessage(event.getChannel().DisplayName().get().substring(0, 2) + event.getMessage()));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerChatPreprocess(PlayerCommandPreprocessEvent event) {
|
||||
handlePreprocess(event.getPlayer(), event.getMessage(), event);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onSystemChatPreprocess(ServerCommandEvent event) {
|
||||
handlePreprocess(event.getSender(), "/" + event.getCommand(), event);
|
||||
if (event.isCancelled()) event.setCommand("dontrunthiscmd"); //Bugfix
|
||||
}
|
||||
|
||||
private void handlePreprocess(CommandSender sender, String message, Cancellable event) {
|
||||
if (event.isCancelled()) return;
|
||||
val ev = new TBMCCommandPreprocessEvent(sender, message);
|
||||
Bukkit.getPluginManager().callEvent(ev);
|
||||
if (ev.isCancelled())
|
||||
event.setCancelled(true); //Cancel the original event
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onTBMCPreprocess(TBMCCommandPreprocessEvent event) {
|
||||
if (event.isCancelled()) return;
|
||||
try {
|
||||
event.setCancelled(Command2MC.handleCommand(event.getSender(), event.getMessage()));
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("Command processing failed for sender '" + event.getSender() + "' and message '" + event.getMessage() + "'", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,13 +1,14 @@
|
|||
package buttondevteam.core;
|
||||
|
||||
import buttondevteam.component.channel.Channel;
|
||||
import buttondevteam.component.channel.ChannelComponent;
|
||||
import buttondevteam.core.component.channel.Channel;
|
||||
import buttondevteam.core.component.channel.ChannelComponent;
|
||||
import buttondevteam.lib.architecture.Component;
|
||||
import buttondevteam.lib.chat.Color;
|
||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
|
@ -40,7 +41,7 @@ public class TestPrepare {
|
|||
return cl.isAssignableFrom(invocation.getMethod().getReturnType());
|
||||
}
|
||||
}));
|
||||
Component.registerComponent(Mockito.mock(MainPlugin.class), new ChannelComponent());
|
||||
Component.registerComponent(Mockito.mock(JavaPlugin.class), new ChannelComponent());
|
||||
TBMCChatAPI.RegisterChatChannel(Channel.GlobalChat = new Channel("§fg§f", Color.White, "g", null));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package buttondevteam.component.channel;
|
||||
package buttondevteam.core.component.channel;
|
||||
|
||||
import buttondevteam.core.ComponentManager;
|
||||
import buttondevteam.core.MainPlugin;
|
|
@ -1,4 +1,4 @@
|
|||
package buttondevteam.component.channel;
|
||||
package buttondevteam.core.component.channel;
|
||||
|
||||
import buttondevteam.lib.architecture.Component;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
|
@ -1,4 +1,4 @@
|
|||
package buttondevteam.component.channel;
|
||||
package buttondevteam.core.component.channel;
|
||||
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
|
@ -1,4 +1,4 @@
|
|||
package buttondevteam.component.channel;
|
||||
package buttondevteam.core.component.channel;
|
||||
|
||||
import buttondevteam.lib.chat.Color;
|
||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
|
@ -1,4 +1,4 @@
|
|||
package buttondevteam.component.members;
|
||||
package buttondevteam.core.component.members;
|
||||
|
||||
import buttondevteam.core.MainPlugin;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
|
@ -1,4 +1,4 @@
|
|||
package buttondevteam.component.members;
|
||||
package buttondevteam.core.component.members;
|
||||
|
||||
import buttondevteam.core.MainPlugin;
|
||||
import buttondevteam.lib.architecture.Component;
|
|
@ -1,4 +1,4 @@
|
|||
package buttondevteam.component.randomtp;
|
||||
package buttondevteam.core.component.randomtp;
|
||||
|
||||
import buttondevteam.lib.architecture.Component;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
|
@ -1,4 +1,4 @@
|
|||
package buttondevteam.component.randomtp;
|
||||
package buttondevteam.core.component.randomtp;
|
||||
|
||||
import buttondevteam.lib.architecture.Component;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package buttondevteam.component.restart;
|
||||
package buttondevteam.core.component.restart;
|
||||
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
|
@ -1,4 +1,4 @@
|
|||
package buttondevteam.component.restart;
|
||||
package buttondevteam.core.component.restart;
|
||||
|
||||
import buttondevteam.lib.architecture.Component;
|
||||
import buttondevteam.lib.chat.IFakePlayer;
|
|
@ -1,9 +1,11 @@
|
|||
package buttondevteam.component.restart;
|
||||
package buttondevteam.core.component.restart;
|
||||
|
||||
import buttondevteam.core.MainPlugin;
|
||||
import buttondevteam.lib.ScheduledServerRestartEvent;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.boss.BarColor;
|
||||
import org.bukkit.boss.BarFlag;
|
||||
|
@ -14,43 +16,45 @@ import org.bukkit.scheduler.BukkitTask;
|
|||
|
||||
@CommandClass(modOnly = true, path = "schrestart")
|
||||
public class ScheduledRestartCommand extends TBMCCommandBase {
|
||||
private static volatile int restartcounter;
|
||||
private static volatile BukkitTask restarttask;
|
||||
private static volatile BossBar restartbar;
|
||||
@Getter
|
||||
@Setter
|
||||
private int restartCounter;
|
||||
private BukkitTask restarttask;
|
||||
private volatile BossBar restartbar;
|
||||
|
||||
@Override
|
||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
||||
int ticks = 20 * 60;
|
||||
int secs = 60;
|
||||
try {
|
||||
if (args.length > 0)
|
||||
ticks = Integer.parseInt(args[0]);
|
||||
secs = Integer.parseInt(args[0]);
|
||||
} catch (NumberFormatException e) {
|
||||
sender.sendMessage("§cError: Ticks must be a number.");
|
||||
sender.sendMessage("§cError: Seconds must be a number.");
|
||||
return false;
|
||||
}
|
||||
if (ticks < 20) {
|
||||
sender.sendMessage("§cError: Ticks must be more than 20.");
|
||||
if (secs < 10) {
|
||||
sender.sendMessage("§cError: Seconds must be at least 10.");
|
||||
return false;
|
||||
}
|
||||
final int restarttime = restartcounter = ticks;
|
||||
restartbar = Bukkit.createBossBar("Server restart in " + ticks / 20f + "s", BarColor.RED, BarStyle.SOLID,
|
||||
final int restarttime = restartCounter = secs * 20;
|
||||
restartbar = Bukkit.createBossBar("Server restart in " + secs + "s", BarColor.RED, BarStyle.SOLID,
|
||||
BarFlag.DARKEN_SKY);
|
||||
restartbar.setProgress(1);
|
||||
Bukkit.getOnlinePlayers().forEach(p -> restartbar.addPlayer(p));
|
||||
sender.sendMessage("Scheduled restart in " + ticks / 20f);
|
||||
ScheduledServerRestartEvent e = new ScheduledServerRestartEvent(ticks);
|
||||
sender.sendMessage("Scheduled restart in " + secs);
|
||||
ScheduledServerRestartEvent e = new ScheduledServerRestartEvent(restarttime, this);
|
||||
Bukkit.getPluginManager().callEvent(e);
|
||||
restarttask = Bukkit.getScheduler().runTaskTimer(MainPlugin.Instance, () -> {
|
||||
if (restartcounter < 0) {
|
||||
if (restartCounter < 0) {
|
||||
restarttask.cancel();
|
||||
restartbar.getPlayers().forEach(p -> restartbar.removePlayer(p));
|
||||
Bukkit.spigot().restart();
|
||||
}
|
||||
if (restartcounter % 200 == 0)
|
||||
Bukkit.broadcastMessage("§c-- The server is restarting in " + restartcounter / 20 + " seconds!");
|
||||
restartbar.setProgress(restartcounter / (double) restarttime);
|
||||
restartbar.setTitle(String.format("Server restart in %.2f", restartcounter / 20f));
|
||||
restartcounter--;
|
||||
if (restartCounter % 200 == 0)
|
||||
Bukkit.broadcastMessage("§c-- The server is restarting in " + restartCounter / 20 + " seconds! (/press)");
|
||||
restartbar.setProgress(restartCounter / (double) restarttime);
|
||||
restartbar.setTitle(String.format("Server restart in %.2f", restartCounter / 20f));
|
||||
restartCounter--;
|
||||
}, 1, 1);
|
||||
return true;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package buttondevteam.component.towny;
|
||||
package buttondevteam.core.component.towny;
|
||||
|
||||
import buttondevteam.core.ComponentManager;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
|
@ -1,4 +1,4 @@
|
|||
package buttondevteam.component.updater;
|
||||
package buttondevteam.core.component.updater;
|
||||
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import com.google.gson.JsonArray;
|
|
@ -1,4 +1,4 @@
|
|||
package buttondevteam.component.updater;
|
||||
package buttondevteam.core.component.updater;
|
||||
|
||||
import buttondevteam.lib.architecture.Component;
|
||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
|
@ -1,4 +1,4 @@
|
|||
package buttondevteam.component.updater;
|
||||
package buttondevteam.core.component.updater;
|
||||
|
||||
import buttondevteam.core.MainPlugin;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
|
@ -1,20 +1,18 @@
|
|||
package buttondevteam.lib;
|
||||
|
||||
import buttondevteam.core.component.restart.ScheduledRestartCommand;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public class ScheduledServerRestartEvent extends Event {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private final int restartticks;
|
||||
|
||||
public ScheduledServerRestartEvent(int restartticks) {
|
||||
this.restartticks = restartticks;
|
||||
}
|
||||
|
||||
public int getRestartTicks() {
|
||||
return restartticks;
|
||||
}
|
||||
private final int restartTicks;
|
||||
private final ScheduledRestartCommand command;
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package buttondevteam.lib;
|
||||
|
||||
import buttondevteam.component.channel.Channel;
|
||||
import buttondevteam.core.component.channel.Channel;
|
||||
import buttondevteam.lib.chat.ChatMessage;
|
||||
import lombok.Getter;
|
||||
import lombok.experimental.Delegate;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package buttondevteam.lib;
|
||||
|
||||
import buttondevteam.component.channel.Channel;
|
||||
import buttondevteam.core.component.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package buttondevteam.lib;
|
||||
|
||||
import buttondevteam.component.channel.Channel;
|
||||
import buttondevteam.core.component.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
|
39
ButtonCore/src/main/java/buttondevteam/lib/TBMCCommandPreprocessEvent.java
Executable file
39
ButtonCore/src/main/java/buttondevteam/lib/TBMCCommandPreprocessEvent.java
Executable file
|
@ -0,0 +1,39 @@
|
|||
package buttondevteam.lib;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
/**
|
||||
* Can be used to change or handle commands before they're sent.
|
||||
* <b>Called on using player, console and Discord commands.</b>
|
||||
*
|
||||
* @author NorbiPeti
|
||||
*/
|
||||
@Getter
|
||||
public class TBMCCommandPreprocessEvent extends Event implements Cancellable {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private final CommandSender sender;
|
||||
@Setter
|
||||
private String message;
|
||||
@Setter
|
||||
private boolean cancelled;
|
||||
|
||||
public TBMCCommandPreprocessEvent(CommandSender sender, String message) {
|
||||
this.sender = sender;
|
||||
this.message = message; //TODO: Actually call from Discord as well
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package buttondevteam.lib;
|
||||
|
||||
import buttondevteam.component.updater.PluginUpdater;
|
||||
import buttondevteam.core.MainPlugin;
|
||||
import buttondevteam.core.component.updater.PluginUpdater;
|
||||
import buttondevteam.lib.player.ChromaGamerBase;
|
||||
import buttondevteam.lib.potato.DebugPotato;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package buttondevteam.lib;
|
||||
|
||||
import buttondevteam.component.channel.Channel;
|
||||
import buttondevteam.core.component.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
|
38
ButtonCore/src/main/java/buttondevteam/lib/ThorpeUtils.java
Normal file
38
ButtonCore/src/main/java/buttondevteam/lib/ThorpeUtils.java
Normal file
|
@ -0,0 +1,38 @@
|
|||
package buttondevteam.lib;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public final class ThorpeUtils {
|
||||
private ThorpeUtils() {}
|
||||
|
||||
public static String getDisplayName(CommandSender sender) {
|
||||
if (sender instanceof IHaveFancyName)
|
||||
return ((IHaveFancyName) sender).getFancyName();
|
||||
if (sender instanceof Player)
|
||||
return ((Player) sender).getDisplayName();
|
||||
return sender.getName();
|
||||
}
|
||||
|
||||
public static String getFullDisplayName(CommandSender sender) {
|
||||
if (sender instanceof IHaveFancyName)
|
||||
return ((IHaveFancyName) sender).getFancyFullName();
|
||||
return getDisplayName(sender);
|
||||
}
|
||||
|
||||
public interface IHaveFancyName {
|
||||
/**
|
||||
* May not be null.
|
||||
*
|
||||
* @return The name to be displayed in most places.
|
||||
*/
|
||||
String getFancyName();
|
||||
|
||||
/**
|
||||
* May return null.
|
||||
*
|
||||
* @return The full name that can be used to uniquely indentify the user.
|
||||
*/
|
||||
String getFancyFullName();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package buttondevteam.lib.architecture;
|
||||
|
||||
import buttondevteam.core.ComponentManager;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||
import lombok.AccessLevel;
|
||||
|
@ -7,14 +8,30 @@ import lombok.Getter;
|
|||
import lombok.experimental.var;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
public abstract class ButtonPlugin extends JavaPlugin {
|
||||
@Getter(AccessLevel.PROTECTED)
|
||||
private IHaveConfig iConfig;
|
||||
/**
|
||||
* Used to unregister components in the right order
|
||||
*/
|
||||
@Getter
|
||||
private Stack<Component> componentStack = new Stack<>();
|
||||
|
||||
protected abstract void pluginEnable();
|
||||
|
||||
/**
|
||||
* Called after the components are unregistered
|
||||
*/
|
||||
protected abstract void pluginDisable();
|
||||
|
||||
/**
|
||||
* Called before the components are unregistered
|
||||
*/
|
||||
protected void pluginPreDisable() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onEnable() {
|
||||
var section = super.getConfig().getConfigurationSection("global");
|
||||
|
@ -30,6 +47,8 @@ public abstract class ButtonPlugin extends JavaPlugin {
|
|||
@Override
|
||||
public final void onDisable() {
|
||||
try {
|
||||
pluginPreDisable();
|
||||
ComponentManager.unregComponents(this);
|
||||
pluginDisable();
|
||||
saveConfig();
|
||||
iConfig = null; //Clearing the hashmap is not enough, we need to update the section as well
|
||||
|
|
|
@ -3,6 +3,7 @@ package buttondevteam.lib.architecture;
|
|||
import buttondevteam.core.ComponentManager;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.architecture.exceptions.UnregisteredComponentException;
|
||||
import buttondevteam.lib.chat.Command2MC;
|
||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
||||
import lombok.Getter;
|
||||
|
@ -38,7 +39,8 @@ public abstract class Component {
|
|||
/**
|
||||
* Registers a component checking it's dependencies and calling {@link #register(JavaPlugin)}.<br>
|
||||
* Make sure to register the dependencies first.<br>
|
||||
* The component will be enabled automatically, regardless of when it was registered.
|
||||
* The component will be enabled automatically, regardless of when it was registered.<br>
|
||||
* <b>If not using {@link ButtonPlugin}, call {@link ComponentManager#unregComponents(ButtonPlugin)} on plugin disable.</b>
|
||||
*
|
||||
* @param component The component to register
|
||||
* @return Whether the component is registered successfully (it may have failed to enable)
|
||||
|
@ -49,15 +51,13 @@ public abstract class Component {
|
|||
|
||||
/**
|
||||
* Unregisters a component by calling {@link #unregister(JavaPlugin)}.<br>
|
||||
* Make sure to unregister the dependencies last.
|
||||
* Make sure to unregister the dependencies last.<br>
|
||||
* <b>Components will be unregistered in opposite order of registering by default by {@link ButtonPlugin} or {@link ComponentManager#unregComponents(ButtonPlugin)}.</b>
|
||||
*
|
||||
* @param componentClass The component class to unregister
|
||||
* @param component The component to unregister
|
||||
* @return Whether the component is unregistered successfully (it also got disabled)
|
||||
*/
|
||||
public static boolean unregisterComponent(JavaPlugin plugin, Class<? extends Component> componentClass) {
|
||||
val component = components.get(componentClass);
|
||||
if (component == null)
|
||||
return false; //Failed to load
|
||||
public static boolean unregisterComponent(JavaPlugin plugin, Component component) {
|
||||
return registerUnregisterComponent(plugin, component, false);
|
||||
}
|
||||
|
||||
|
@ -74,10 +74,16 @@ public abstract class Component {
|
|||
}
|
||||
}
|
||||
if (register) {
|
||||
if (components.containsKey(component.getClass())) {
|
||||
TBMCCoreAPI.SendException("Failed to register component " + component.getClassName(), new IllegalArgumentException("The component is already registered!"));
|
||||
return false;
|
||||
}
|
||||
component.plugin = plugin;
|
||||
updateConfig(plugin, component);
|
||||
component.register(plugin);
|
||||
components.put(component.getClass(), component);
|
||||
if (plugin instanceof ButtonPlugin)
|
||||
((ButtonPlugin) plugin).getComponentStack().push(component);
|
||||
if (ComponentManager.areComponentsEnabled() && component.shouldBeEnabled().get()) {
|
||||
try { //Enable components registered after the previous ones getting enabled
|
||||
setComponentEnabled(component, true);
|
||||
|
@ -89,6 +95,8 @@ public abstract class Component {
|
|||
}
|
||||
return true; //Component shouldn't be enabled
|
||||
} else {
|
||||
if (!components.containsKey(component.getClass()))
|
||||
return true; //Already unregistered
|
||||
if (component.enabled) {
|
||||
try {
|
||||
setComponentEnabled(component, false);
|
||||
|
@ -183,6 +191,16 @@ public abstract class Component {
|
|||
*/
|
||||
protected abstract void disable();
|
||||
|
||||
/**
|
||||
* Registers a TBMCCommand to the component. Make sure to use {@link buttondevteam.lib.chat.CommandClass} and {@link buttondevteam.lib.chat.Command2.Subcommand}.
|
||||
* You don't need to register the command in plugin.yml.
|
||||
*
|
||||
* @param commandBase Custom coded command class
|
||||
*/
|
||||
protected final void registerCommand(Command2MC commandBase) {
|
||||
Command2MC.registerCommand(commandBase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a TBMCCommand to the component. Make sure to add it to plugin.yml and use {@link buttondevteam.lib.chat.CommandClass}.
|
||||
*
|
||||
|
|
|
@ -62,6 +62,18 @@ public class ConfigData<T> { //TODO: Save after a while
|
|||
if (hmm == null) hmm = def; //Set if the getter returned null
|
||||
return hmm;
|
||||
}
|
||||
if (val instanceof Number) {
|
||||
if (def instanceof Long)
|
||||
val = ((Number) val).longValue();
|
||||
else if (def instanceof Short)
|
||||
val = ((Number) val).shortValue();
|
||||
else if (def instanceof Byte)
|
||||
val = ((Number) val).byteValue();
|
||||
else if (def instanceof Float)
|
||||
val = ((Number) val).floatValue();
|
||||
else if (def instanceof Double)
|
||||
val = ((Number) val).doubleValue();
|
||||
}
|
||||
return (T) val;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
package buttondevteam.lib.architecture;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.val;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Members of this interface should be protected (access level)
|
||||
* A config system
|
||||
*/
|
||||
public final class IHaveConfig {
|
||||
private final HashMap<String, ConfigData<?>> datamap = new HashMap<>();
|
||||
|
@ -15,7 +17,7 @@ public final class IHaveConfig {
|
|||
private ConfigurationSection config;
|
||||
|
||||
/**
|
||||
* May be used in testing
|
||||
* May be used in testing.
|
||||
*
|
||||
* @param section May be null for testing
|
||||
*/
|
||||
|
@ -73,4 +75,42 @@ public final class IHaveConfig {
|
|||
datamap.put(path, data = new ConfigData<>(config, path, getter.apply(primitiveDef), primitiveDef, getter, setter));
|
||||
return (ConfigData<T>) data;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method overload should only be used with primitves or String.
|
||||
*
|
||||
* @param path The path in config to use
|
||||
* @param def The value to use by default
|
||||
* @param <T> The type of this variable (only use primitives or String)
|
||||
* @return The data object that can be used to get or set the value
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> ConfigData<T> getData(String path, Supplier<T> def) {
|
||||
ConfigData<?> data = datamap.get(path);
|
||||
if (data == null) {
|
||||
val defval = def.get();
|
||||
datamap.put(path, data = new ConfigData<>(config, path, defval, defval));
|
||||
}
|
||||
return (ConfigData<T>) data;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method overload may be used with any class.
|
||||
*
|
||||
* @param path The path in config to use
|
||||
* @param def The value to use by default
|
||||
* @param getter A function that converts a primitive representation to the correct value
|
||||
* @param setter A function that converts a value to a primitive representation
|
||||
* @param <T> The type of this variable (can be any class)
|
||||
* @return The data object that can be used to get or set the value
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> ConfigData<T> getData(String path, Supplier<T> def, Function<Object, T> getter, Function<T, Object> setter) {
|
||||
ConfigData<?> data = datamap.get(path);
|
||||
if (data == null) {
|
||||
val defval = def.get();
|
||||
datamap.put(path, data = new ConfigData<>(config, path, defval, setter.apply(defval), getter, setter));
|
||||
}
|
||||
return (ConfigData<T>) data;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +1,53 @@
|
|||
package buttondevteam.lib.chat;
|
||||
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.player.ChromaGamerBase;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.experimental.var;
|
||||
import lombok.val;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* The method name is the subcommand, use underlines (_) to add further subcommands.
|
||||
* The args may be null if the conversion failed.
|
||||
*/
|
||||
public abstract class Command2 {
|
||||
/**
|
||||
* Default handler for commands, can be used to copy the args too.
|
||||
*
|
||||
* @param sender The sender which ran the command
|
||||
* @param command The (sub)command ran by the user
|
||||
* @param args All of the arguments passed as is
|
||||
* @return
|
||||
* @return The success of the command
|
||||
*/
|
||||
public boolean def(CommandSender sender, String command, @TextArg String args) {
|
||||
public boolean def(CommandSender sender, @TextArg String args) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method. Return with this.
|
||||
*
|
||||
* @param sender The sender of the command
|
||||
* @param message The message to send to the sender
|
||||
* @return Always true so that the usage isn't shown
|
||||
*/
|
||||
protected boolean respond(CommandSender sender, String message) {
|
||||
sender.sendMessage(message);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: @CommandClass(helpText=...)
|
||||
* Parameters annotated with this receive all of the remaining arguments
|
||||
|
@ -28,4 +56,172 @@ public abstract class Command2 {
|
|||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface TextArg {
|
||||
}
|
||||
|
||||
/**
|
||||
* Methods annotated with this will be recognised as subcommands
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Subcommand {
|
||||
/**
|
||||
* Help text to show players. A usage message will be also shown below it.
|
||||
*/
|
||||
String[] helpText() default {};
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
protected static class SubcommandData<T extends Command2> {
|
||||
public final Method method;
|
||||
public final T command;
|
||||
public final String[] helpText;
|
||||
}
|
||||
|
||||
public Command2() {
|
||||
path = getcmdpath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a param converter that obtains a specific object from a string parameter.
|
||||
* The converter may return null.
|
||||
*
|
||||
* @param cl The class of the result object
|
||||
* @param converter The converter to use
|
||||
* @param <T> The type of the result
|
||||
*/
|
||||
protected static <T> void addParamConverter(Class<T> cl, Function<String, T> converter, HashMap<Class<?>, Function<String, ?>> map) {
|
||||
map.put(cl, converter);
|
||||
}
|
||||
|
||||
protected static <T extends Command2> boolean handleCommand(CommandSender sender, String commandline,
|
||||
HashMap<String, SubcommandData<T>> subcommands, HashMap<Class<?>, Function<String, ?>> paramConverters) throws Exception {
|
||||
for (int i = commandline.length(); i != -1; i = commandline.lastIndexOf(' ', i - 1)) {
|
||||
String subcommand = commandline.substring(0, i).toLowerCase();
|
||||
SubcommandData sd = subcommands.get(subcommand); //O(1)
|
||||
if (sd == null) continue; //TODO: This will run each time someone runs any command
|
||||
val params = new ArrayList<Object>(sd.method.getParameterCount());
|
||||
int j = subcommand.length(), pj;
|
||||
Class<?>[] parameterTypes = sd.method.getParameterTypes();
|
||||
if (parameterTypes.length == 0)
|
||||
throw new Exception("No sender parameter for method '" + sd.method + "'");
|
||||
val sendertype = parameterTypes[0];
|
||||
final ChromaGamerBase cg;
|
||||
if (sendertype.isAssignableFrom(sender.getClass()))
|
||||
params.add(sender); //The command either expects a CommandSender or it is a Player, or some other expected type
|
||||
else if (ChromaGamerBase.class.isAssignableFrom(sendertype)
|
||||
&& (cg = ChromaGamerBase.getFromSender(sender)) != null
|
||||
&& cg.getClass() == sendertype) //The command expects a user of our system
|
||||
params.add(cg);
|
||||
else {
|
||||
sender.sendMessage("§cYou need to be a " + sendertype.getSimpleName() + " to use this command.");
|
||||
return true;
|
||||
}
|
||||
for (int i1 = 1; i1 < parameterTypes.length; i1++) {
|
||||
Class<?> cl = parameterTypes[i1];
|
||||
pj = j + 1; //Start index
|
||||
if (pj == commandline.length() + 1) { //No param given
|
||||
params.add(null);
|
||||
continue; //Fill the remaining params with nulls
|
||||
}
|
||||
j = commandline.indexOf(' ', j + 1); //End index
|
||||
if (j == -1) //Last parameter
|
||||
j = commandline.length();
|
||||
String param = commandline.substring(pj, j);
|
||||
if (cl == String.class) {
|
||||
params.add(param);
|
||||
continue;
|
||||
}
|
||||
val conv = paramConverters.get(cl);
|
||||
if (conv == null)
|
||||
throw new Exception("No suitable converter found for parameter type '" + cl.getCanonicalName() + "' for command '" + sd.method.toString() + "'");
|
||||
params.add(conv.apply(param));
|
||||
}
|
||||
//System.out.println("Our params: "+params);
|
||||
val ret = sd.method.invoke(sd.command, params.toArray()); //I FORGOT TO TURN IT INTO AN ARRAY (for a long time)
|
||||
if (ret instanceof Boolean) {
|
||||
if (!(boolean) ret) //Show usage
|
||||
sender.sendMessage(sd.helpText);
|
||||
} else if (ret != null)
|
||||
throw new Exception("Wrong return type! Must return a boolean or void. Return value: "+ret);
|
||||
return true; //We found a method
|
||||
}
|
||||
return false; //Didn't handle
|
||||
} //TODO: Add to the help
|
||||
|
||||
protected static <T extends Command2> void registerCommand(T command, HashMap<String, SubcommandData<T>> subcommands, char commandChar) {
|
||||
val path = command.getCommandPath();
|
||||
try { //Register the default handler first so it can be reliably overwritten
|
||||
val method = command.getClass().getMethod("def", CommandSender.class, String.class);
|
||||
val cc = command.getClass().getAnnotation(CommandClass.class);
|
||||
var ht = cc == null ? new String[0] : cc.helpText();
|
||||
String[] both = Arrays.copyOf(ht, ht.length + 1);
|
||||
both[ht.length] = "Usage: " + commandChar + path; //TODO: Print subcommands
|
||||
ht = both;
|
||||
subcommands.put(commandChar + path, new SubcommandData<>(method, command, ht)); //TODO: Disable components when the plugin is disabled
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("Could not register default handler for command /" + path, e);
|
||||
} //Continue on
|
||||
for (val method : command.getClass().getMethods()) {
|
||||
val ann = method.getAnnotation(Subcommand.class);
|
||||
if (ann != null) {
|
||||
val cc = command.getClass().getAnnotation(CommandClass.class);
|
||||
var ht = ann.helpText().length != 0 || cc == null ? ann.helpText() : cc.helpText(); //If cc is null then it's empty array
|
||||
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);
|
||||
subcommands.put(subcommand, new SubcommandData<>(method, command, ht)); //Result of the above (def) is that it will show the help text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String[] getHelpText(Method method, String[] ht, String subcommand) { //TODO: helpText[0]="§6---- "+helpText[0]+" ----";
|
||||
val str = method.getDeclaringClass().getResourceAsStream("/commands.yml");
|
||||
if (str == null)
|
||||
TBMCCoreAPI.SendException("Error while getting command data!", new Exception("Resource not found!"));
|
||||
else {
|
||||
YamlConfiguration yc = YamlConfiguration.loadConfiguration(new InputStreamReader(str)); //Generated by ButtonProcessor
|
||||
val ccs = yc.getConfigurationSection(method.getDeclaringClass().getCanonicalName());
|
||||
if (ccs != null) {
|
||||
val cs = ccs.getConfigurationSection(method.getName());
|
||||
if (cs != null) {
|
||||
val mname = cs.getString("method");
|
||||
val params = cs.getString("params");
|
||||
val goodname = method.getName() + "(" + Arrays.stream(method.getParameterTypes()).map(cl -> cl.getCanonicalName()).collect(Collectors.joining(",")) + ")";
|
||||
if (goodname.equals(mname) && params != null) {
|
||||
String[] both = Arrays.copyOf(ht, ht.length + 1);
|
||||
both[ht.length] = "Usage: " + subcommand + " " + params;
|
||||
ht = both;
|
||||
} else
|
||||
TBMCCoreAPI.SendException("Error while getting command data for " + method + "!", new Exception("Method '" + method.toString() + "' != " + mname + " or params is " + params));
|
||||
} else
|
||||
TBMCCoreAPI.SendException("Error while getting command data for " + method + "!", new Exception("cs is " + cs));
|
||||
} else
|
||||
TBMCCoreAPI.SendException("Error while getting command data for " + method + "!", new Exception("ccs is " + ccs + " - class: " + method.getDeclaringClass().getCanonicalName()));
|
||||
}
|
||||
return ht;
|
||||
}
|
||||
|
||||
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>
|
||||
*
|
||||
* @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();
|
||||
path = path.length() == 0 ? getFromClass.apply(getClass()) : path;
|
||||
return path;
|
||||
}
|
||||
} //TODO: Test support of Player instead of CommandSender
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package buttondevteam.lib.chat;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class Command2MC extends Command2 {
|
||||
|
||||
private static HashMap<String, SubcommandData<Command2MC>> subcommands = new HashMap<>();
|
||||
private static HashMap<Class<?>, Function<String, ?>> paramConverters = new HashMap<>();
|
||||
|
||||
public static boolean handleCommand(CommandSender sender, String commandLine) throws Exception {
|
||||
return handleCommand(sender, commandLine, subcommands, paramConverters);
|
||||
}
|
||||
|
||||
public static void registerCommand(Command2MC command) {
|
||||
registerCommand(command, subcommands, '/');
|
||||
}
|
||||
|
||||
public static <T> void addParamConverter(Class<T> cl, Function<String, T> converter) {
|
||||
addParamConverter(cl, converter, paramConverters);
|
||||
}
|
||||
}
|
|
@ -38,7 +38,7 @@ public @interface CommandClass {
|
|||
boolean excludeFromPath() default false;
|
||||
|
||||
/**
|
||||
* The help text to show for the players.
|
||||
* The help text to show for the players. A usage message will be also shown below it.
|
||||
*
|
||||
* @return The help text
|
||||
*/
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package buttondevteam.lib.chat;
|
||||
|
||||
import buttondevteam.component.channel.Channel;
|
||||
import buttondevteam.component.channel.Channel.RecipientTestResult;
|
||||
import buttondevteam.core.CommandCaller;
|
||||
import buttondevteam.core.MainPlugin;
|
||||
import buttondevteam.core.component.channel.Channel;
|
||||
import buttondevteam.core.component.channel.Channel.RecipientTestResult;
|
||||
import buttondevteam.lib.TBMCChatEvent;
|
||||
import buttondevteam.lib.TBMCChatPreprocessEvent;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
|
@ -160,7 +160,7 @@ public class TBMCChatAPI {
|
|||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("An error occured while registering command " + thecmdclass.getSimpleName(), e);
|
||||
}
|
||||
} //TODO: onCommand(CommandSender sender, String alias, int arg1, String arg2) (planned for a while)
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package buttondevteam.lib.player;
|
||||
|
||||
import buttondevteam.component.channel.Channel;
|
||||
import buttondevteam.core.component.channel.Channel;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
public class ChannelPlayerData { //I just want this to work
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package buttondevteam.lib.player;
|
||||
|
||||
import buttondevteam.component.channel.Channel;
|
||||
import buttondevteam.core.component.channel.Channel;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import lombok.val;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package buttondevteam.lib.player;
|
||||
|
||||
import buttondevteam.component.towny.TownyComponent;
|
||||
import buttondevteam.core.component.towny.TownyComponent;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
name: ButtonCore
|
||||
name: ThorpeCore
|
||||
main: buttondevteam.core.MainPlugin
|
||||
version: 1.0
|
||||
author: TBMCPlugins
|
||||
|
@ -15,3 +15,4 @@ commands:
|
|||
description: Add or remove a member
|
||||
component:
|
||||
description: Enable or disable or list components
|
||||
dontrunthiscmd:
|
|
@ -12,6 +12,13 @@
|
|||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.21" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT" level="project" />
|
||||
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.6" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.googlecode.json-simple:json-simple:1.1.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.google.guava:guava:21.0" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.0" level="project" />
|
||||
<orderEntry type="library" name="Maven: net.md-5:bungeecord-chat:1.12-SNAPSHOT" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:3.8.1" level="project" />
|
||||
</component>
|
||||
</module>
|
|
@ -1,6 +1,26 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spigot-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>1.21</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.12.2-R0.1-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<parent>
|
||||
<groupId>com.github.TBMCPlugins</groupId>
|
||||
<artifactId>ButtonCore</artifactId>
|
||||
|
|
|
@ -1,17 +1,25 @@
|
|||
package buttondevteam.buttonproc;
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import javax.annotation.processing.AbstractProcessor;
|
||||
import javax.annotation.processing.RoundEnvironment;
|
||||
import javax.annotation.processing.SupportedAnnotationTypes;
|
||||
import javax.lang.model.SourceVersion;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.element.*;
|
||||
import javax.tools.Diagnostic;
|
||||
import javax.tools.Diagnostic.Kind;
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.StandardLocation;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@SupportedAnnotationTypes("buttondevteam.*")
|
||||
public class ButtonProcessor extends AbstractProcessor {
|
||||
|
@ -23,7 +31,7 @@ public class ButtonProcessor extends AbstractProcessor {
|
|||
System.out.println("Processing " + targetcl);
|
||||
List<? extends AnnotationMirror> annotationMirrors = processingEnv.getElementUtils()
|
||||
.getAllAnnotationMirrors(targetcl);
|
||||
System.out.println("Annotations: " + annotationMirrors);
|
||||
//System.out.println("Annotations: " + annotationMirrors);
|
||||
Function<String, Boolean> hasAnnotation = ann -> annotationMirrors.stream()
|
||||
.anyMatch(am -> am.getAnnotationType().toString().contains(ann));
|
||||
if (hasAnnotation.apply("ChromaGamerEnforcer") && !hasAnnotation.apply("UserClass")
|
||||
|
@ -36,15 +44,67 @@ public class ButtonProcessor extends AbstractProcessor {
|
|||
"No PlayerClass annotation found for " + targetcl.getSimpleName(), targetcl);
|
||||
for (AnnotationMirror annotation : annotationMirrors) {
|
||||
String type = annotation.getAnnotationType().toString();
|
||||
System.out.println("Type: " + type);
|
||||
//System.out.println("Type: " + type);
|
||||
}
|
||||
processSubcommands(targetcl, annotationMirrors);
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (found) {
|
||||
FileObject fo = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", "commands.yml");
|
||||
yc.save(new File(fo.toUri()));
|
||||
found = false;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return true; // claim the annotations
|
||||
}
|
||||
|
||||
private YamlConfiguration yc = new YamlConfiguration();
|
||||
private boolean found = false;
|
||||
|
||||
private void processSubcommands(Element targetcl, List<? extends AnnotationMirror> annotationMirrors) {
|
||||
if (!(targetcl instanceof ExecutableElement))
|
||||
return;
|
||||
//System.out.println("Annotations: "+annotationMirrors);
|
||||
if (annotationMirrors.stream().noneMatch(an -> an.getAnnotationType().toString().endsWith("Subcommand")))
|
||||
return;
|
||||
//System.out.print("Processing method: " + targetcl.getEnclosingElement()+" "+targetcl);
|
||||
ConfigurationSection cs = yc.createSection(targetcl.getEnclosingElement().toString()
|
||||
+ "." + targetcl.getSimpleName().toString()); //Need to do the 2 config sections at once so it doesn't overwrite the class section
|
||||
System.out.println(targetcl);
|
||||
cs.set("method", targetcl.toString());
|
||||
cs.set("params", ((ExecutableElement) targetcl).getParameters().stream().skip(1).map(p -> {
|
||||
//String tn=p.asType().toString();
|
||||
//return tn.substring(tn.lastIndexOf('.')+1)+" "+p.getSimpleName();
|
||||
boolean optional = p.getAnnotationMirrors().stream().anyMatch(am -> am.getAnnotationType().toString().endsWith("Optional"));
|
||||
if (optional)
|
||||
return "[" + p.getSimpleName() + "]";
|
||||
return "<" + p.getSimpleName() + ">";
|
||||
}).collect(Collectors.joining(" ")));
|
||||
//System.out.println();
|
||||
found = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceVersion getSupportedSourceVersion() {
|
||||
return SourceVersion.latestSupported();
|
||||
}
|
||||
|
||||
private String fetchSourcePath() {
|
||||
try {
|
||||
JavaFileObject generationForPath = processingEnv.getFiler().createSourceFile("PathFor" + getClass().getSimpleName());
|
||||
Writer writer = generationForPath.openWriter();
|
||||
String sourcePath = generationForPath.toUri().getPath();
|
||||
writer.close();
|
||||
generationForPath.delete();
|
||||
|
||||
return sourcePath;
|
||||
} catch (IOException e) {
|
||||
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, "Unable to determine source file path!");
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue