New command system, fixes, improvements #61

Merged
NorbiPeti merged 6 commits from dev into master 2019-02-01 16:07:50 +00:00
38 changed files with 487 additions and 341 deletions
Showing only changes of commit 7331568886 - Show all commits

View file

@ -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>

View file

@ -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>

View file

@ -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" />

View file

@ -1,4 +1,4 @@
import buttondevteam.component.updater.PluginUpdater;
import buttondevteam.core.component.updater.PluginUpdater;
import java.util.List;
import java.util.stream.Collectors;

View file

@ -11,7 +11,10 @@ import org.bukkit.plugin.Plugin;
import java.util.Optional;
@CommandClass(modOnly = true)
@CommandClass(modOnly = true, helpText = {
"§6---- Component command ----",
"Can be used to enable/disable/list components"
})
public class ComponentCommand extends Command2 {
public ComponentCommand() {
addParamConverter(Plugin.class, arg -> Bukkit.getPluginManager().getPlugin(arg));
@ -58,13 +61,6 @@ public class ComponentCommand extends Command2 {
.filter(c -> c.getClass().getSimpleName().equalsIgnoreCase(arg)).findAny();
if (!oc.isPresent())
sender.sendMessage("§cComponent not found!"); //^ Much simpler to solve in the new command system
return oc; //TODO: Offer overload options with clickable link (with all the plugins it found)
return oc;
} //TODO: Tabcompletion for the new command system
public String[] GetHelpText(String alias) { //TODO
return new String[]{
"§6---- Component command ----",
"Enable or disable or list components"
};
}
}

View file

@ -1,14 +1,14 @@
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;

View file

@ -1,7 +1,7 @@
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;

View file

@ -1,4 +1,4 @@
package buttondevteam.component.channel;
package buttondevteam.core.component.channel;
import buttondevteam.core.ComponentManager;
import buttondevteam.core.MainPlugin;

View file

@ -1,4 +1,4 @@
package buttondevteam.component.channel;
package buttondevteam.core.component.channel;
import buttondevteam.lib.architecture.Component;
import org.bukkit.plugin.java.JavaPlugin;

View file

@ -1,4 +1,4 @@
package buttondevteam.component.channel;
package buttondevteam.core.component.channel;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;

View file

@ -1,4 +1,4 @@
package buttondevteam.component.channel;
package buttondevteam.core.component.channel;
import buttondevteam.lib.chat.Color;
import buttondevteam.lib.chat.TBMCChatAPI;

View file

@ -1,4 +1,4 @@
package buttondevteam.component.members;
package buttondevteam.core.component.members;
import buttondevteam.core.MainPlugin;
import buttondevteam.lib.chat.CommandClass;

View file

@ -1,4 +1,4 @@
package buttondevteam.component.members;
package buttondevteam.core.component.members;
import buttondevteam.core.MainPlugin;
import buttondevteam.lib.architecture.Component;

View file

@ -1,4 +1,4 @@
package buttondevteam.component.randomtp;
package buttondevteam.core.component.randomtp;
import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.chat.CommandClass;

View file

@ -1,4 +1,4 @@
package buttondevteam.component.randomtp;
package buttondevteam.core.component.randomtp;
import buttondevteam.lib.architecture.Component;

View file

@ -1,4 +1,4 @@
package buttondevteam.component.restart;
package buttondevteam.core.component.restart;
import buttondevteam.lib.chat.CommandClass;
import buttondevteam.lib.chat.TBMCCommandBase;

View file

@ -1,4 +1,4 @@
package buttondevteam.component.restart;
package buttondevteam.core.component.restart;
import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.chat.IFakePlayer;

View file

@ -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;
}

View file

@ -1,4 +1,4 @@
package buttondevteam.component.towny;
package buttondevteam.core.component.towny;
import buttondevteam.core.ComponentManager;
import buttondevteam.lib.TBMCCoreAPI;

View file

@ -1,4 +1,4 @@
package buttondevteam.component.updater;
package buttondevteam.core.component.updater;
import buttondevteam.lib.TBMCCoreAPI;
import com.google.gson.JsonArray;

View file

@ -1,4 +1,4 @@
package buttondevteam.component.updater;
package buttondevteam.core.component.updater;
import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.chat.TBMCChatAPI;

View file

@ -1,4 +1,4 @@
package buttondevteam.component.updater;
package buttondevteam.core.component.updater;
import buttondevteam.core.MainPlugin;
import buttondevteam.lib.TBMCCoreAPI;

View file

@ -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() {

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -1,188 +1,188 @@
package buttondevteam.lib;
import buttondevteam.component.updater.PluginUpdater;
import buttondevteam.core.MainPlugin;
import buttondevteam.lib.player.ChromaGamerBase;
import buttondevteam.lib.potato.DebugPotato;
import org.apache.commons.io.IOUtils;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.plugin.Plugin;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
public class TBMCCoreAPI {
static final List<String> coders = new ArrayList<String>() {
private static final long serialVersionUID = -4462159250738367334L;
{
add("Alisolarflare");
add("NorbiPeti");
add("iie");
add("thewindmillman");
add("mayskam1995");
}
};
/**
* Updates or installs the specified plugin. The plugin must use Maven.
*
* @param name
* The plugin's repository name.
* @param sender
* The command sender (if not console, messages will be printed to console as well).
*/
public static void UpdatePlugin(String name, CommandSender sender) {
UpdatePlugin(name, sender, "master");
}
/**
* Updates or installs the specified plugin from the specified branch. The plugin must use Maven.
*
* @param name
* The plugin's repository name.
* @param sender
* The command sender (if not console, messages will be printed to console as well).
* @param branch
* The branch to download the plugin from.
* @return Success or not
*/
public static boolean UpdatePlugin(String name, CommandSender sender, String branch) {
return PluginUpdater.UpdatePlugin(name, sender, branch);
}
public static String DownloadString(String urlstr) throws IOException {
URL url = new URL(urlstr);
URLConnection con = url.openConnection();
con.setRequestProperty("User-Agent", "TBMCPlugins");
InputStream in = con.getInputStream();
String encoding = con.getContentEncoding();
encoding = encoding == null ? "UTF-8" : encoding;
String body = IOUtils.toString(in, encoding);
in.close();
return body;
}
private static final HashMap<String, Throwable> exceptionsToSend = new HashMap<>();
private static final List<String> debugMessagesToSend = new ArrayList<>();
/**
* Send exception to the {@link TBMCExceptionEvent}.
*
* @param sourcemsg
* A message that is shown at the top of the exception (before the exception's message)
* @param e
* The exception to send
*/
public static void SendException(String sourcemsg, Throwable e) {
SendException(sourcemsg, e, false);
}
public static void SendException(String sourcemsg, Throwable e, boolean debugPotato) {
SendUnsentExceptions();
TBMCExceptionEvent event = new TBMCExceptionEvent(sourcemsg, e);
Bukkit.getPluginManager().callEvent(event);
synchronized (exceptionsToSend) {
if (!event.isHandled())
exceptionsToSend.put(sourcemsg, e);
}
Bukkit.getLogger().warning(sourcemsg);
e.printStackTrace();
if (debugPotato) {
List<Player> devsOnline = new ArrayList<Player>();
for (Player player : Bukkit.getOnlinePlayers()) {
if (coders.contains(player.getName())) {
devsOnline.add(player);
}
}
if (!devsOnline.isEmpty()) {
DebugPotato potato = new DebugPotato()
.setMessage(new String[] { //
"§b§o" + e.getClass().getSimpleName(), //
"§c§o" + sourcemsg, //
"§a§oFind a dev to fix this issue" })
.setType(e instanceof IOException ? "Throwable Potato"
: e instanceof ClassCastException ? "Squished Potato"
: e instanceof NullPointerException ? "Plain Potato"
: e instanceof StackOverflowError ? "Chips" : "Error Potato");
for (Player dev : devsOnline) {
potato.Send(dev);
}
}
}
}
public static void sendDebugMessage(String debugMessage) {
SendUnsentDebugMessages();
TBMCDebugMessageEvent event = new TBMCDebugMessageEvent(debugMessage);
Bukkit.getPluginManager().callEvent(event);
synchronized (debugMessagesToSend) {
if (!event.isSent())
debugMessagesToSend.add(debugMessage);
}
}
/**
* Registers Bukkit events, handling the exceptions occurring in those events
*
* @param listener
* The class that handles the events
* @param plugin
* The plugin which the listener belongs to
*/
public static void RegisterEventsForExceptions(Listener listener, Plugin plugin) {
EventExceptionHandler.registerEvents(listener, plugin, new EventExceptionCoreHandler());
}
public static <T extends ChromaGamerBase> void RegisterUserClass(Class<T> userclass) {
ChromaGamerBase.RegisterPluginUserClass(userclass);
}
/**
* Send exceptions that haven't been sent (their events didn't get handled). This method is used by the DiscordPlugin's ready event
*/
public static void SendUnsentExceptions() {
synchronized (exceptionsToSend) {
if (exceptionsToSend.size() > 20) {
exceptionsToSend.clear(); // Don't call more and more events if all the handler plugins are unloaded
Bukkit.getLogger().warning("Unhandled exception list is over 20! Clearing!");
}
for (Iterator<Entry<String, Throwable>> iterator = exceptionsToSend.entrySet().iterator(); iterator.hasNext(); ) {
Entry<String, Throwable> entry = iterator.next();
TBMCExceptionEvent event = new TBMCExceptionEvent(entry.getKey(), entry.getValue());
Bukkit.getPluginManager().callEvent(event);
if (event.isHandled())
iterator.remove();
}
}
}
public static void SendUnsentDebugMessages() {
synchronized (debugMessagesToSend) {
if (debugMessagesToSend.size() > 20) {
debugMessagesToSend.clear(); // Don't call more and more DebugMessages if all the handler plugins are unloaded
Bukkit.getLogger().warning("Unhandled Debug Message list is over 20! Clearing!");
}
for (Iterator<String> iterator = debugMessagesToSend.iterator(); iterator.hasNext(); ) {
String message = iterator.next();
TBMCDebugMessageEvent event = new TBMCDebugMessageEvent(message);
Bukkit.getPluginManager().callEvent(event);
if (event.isSent())
iterator.remove();
}
}
}
public static boolean IsTestServer() {
return MainPlugin.Test;
}
package buttondevteam.lib;
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;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.plugin.Plugin;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
public class TBMCCoreAPI {
static final List<String> coders = new ArrayList<String>() {
private static final long serialVersionUID = -4462159250738367334L;
{
add("Alisolarflare");
add("NorbiPeti");
add("iie");
add("thewindmillman");
add("mayskam1995");
}
};
/**
* Updates or installs the specified plugin. The plugin must use Maven.
*
* @param name
* The plugin's repository name.
* @param sender
* The command sender (if not console, messages will be printed to console as well).
*/
public static void UpdatePlugin(String name, CommandSender sender) {
UpdatePlugin(name, sender, "master");
}
/**
* Updates or installs the specified plugin from the specified branch. The plugin must use Maven.
*
* @param name
* The plugin's repository name.
* @param sender
* The command sender (if not console, messages will be printed to console as well).
* @param branch
* The branch to download the plugin from.
* @return Success or not
*/
public static boolean UpdatePlugin(String name, CommandSender sender, String branch) {
return PluginUpdater.UpdatePlugin(name, sender, branch);
}
public static String DownloadString(String urlstr) throws IOException {
URL url = new URL(urlstr);
URLConnection con = url.openConnection();
con.setRequestProperty("User-Agent", "TBMCPlugins");
InputStream in = con.getInputStream();
String encoding = con.getContentEncoding();
encoding = encoding == null ? "UTF-8" : encoding;
String body = IOUtils.toString(in, encoding);
in.close();
return body;
}
private static final HashMap<String, Throwable> exceptionsToSend = new HashMap<>();
private static final List<String> debugMessagesToSend = new ArrayList<>();
/**
* Send exception to the {@link TBMCExceptionEvent}.
*
* @param sourcemsg
* A message that is shown at the top of the exception (before the exception's message)
* @param e
* The exception to send
*/
public static void SendException(String sourcemsg, Throwable e) {
SendException(sourcemsg, e, false);
}
public static void SendException(String sourcemsg, Throwable e, boolean debugPotato) {
SendUnsentExceptions();
TBMCExceptionEvent event = new TBMCExceptionEvent(sourcemsg, e);
Bukkit.getPluginManager().callEvent(event);
synchronized (exceptionsToSend) {
if (!event.isHandled())
exceptionsToSend.put(sourcemsg, e);
}
Bukkit.getLogger().warning(sourcemsg);
e.printStackTrace();
if (debugPotato) {
List<Player> devsOnline = new ArrayList<Player>();
for (Player player : Bukkit.getOnlinePlayers()) {
if (coders.contains(player.getName())) {
devsOnline.add(player);
}
}
if (!devsOnline.isEmpty()) {
DebugPotato potato = new DebugPotato()
.setMessage(new String[] { //
"§b§o" + e.getClass().getSimpleName(), //
"§c§o" + sourcemsg, //
"§a§oFind a dev to fix this issue" })
.setType(e instanceof IOException ? "Throwable Potato"
: e instanceof ClassCastException ? "Squished Potato"
: e instanceof NullPointerException ? "Plain Potato"
: e instanceof StackOverflowError ? "Chips" : "Error Potato");
for (Player dev : devsOnline) {
potato.Send(dev);
}
}
}
}
public static void sendDebugMessage(String debugMessage) {
SendUnsentDebugMessages();
TBMCDebugMessageEvent event = new TBMCDebugMessageEvent(debugMessage);
Bukkit.getPluginManager().callEvent(event);
synchronized (debugMessagesToSend) {
if (!event.isSent())
debugMessagesToSend.add(debugMessage);
}
}
/**
* Registers Bukkit events, handling the exceptions occurring in those events
*
* @param listener
* The class that handles the events
* @param plugin
* The plugin which the listener belongs to
*/
public static void RegisterEventsForExceptions(Listener listener, Plugin plugin) {
EventExceptionHandler.registerEvents(listener, plugin, new EventExceptionCoreHandler());
}
public static <T extends ChromaGamerBase> void RegisterUserClass(Class<T> userclass) {
ChromaGamerBase.RegisterPluginUserClass(userclass);
}
/**
* Send exceptions that haven't been sent (their events didn't get handled). This method is used by the DiscordPlugin's ready event
*/
public static void SendUnsentExceptions() {
synchronized (exceptionsToSend) {
if (exceptionsToSend.size() > 20) {
exceptionsToSend.clear(); // Don't call more and more events if all the handler plugins are unloaded
Bukkit.getLogger().warning("Unhandled exception list is over 20! Clearing!");
}
for (Iterator<Entry<String, Throwable>> iterator = exceptionsToSend.entrySet().iterator(); iterator.hasNext(); ) {
Entry<String, Throwable> entry = iterator.next();
TBMCExceptionEvent event = new TBMCExceptionEvent(entry.getKey(), entry.getValue());
Bukkit.getPluginManager().callEvent(event);
if (event.isHandled())
iterator.remove();
}
}
}
public static void SendUnsentDebugMessages() {
synchronized (debugMessagesToSend) {
if (debugMessagesToSend.size() > 20) {
debugMessagesToSend.clear(); // Don't call more and more DebugMessages if all the handler plugins are unloaded
Bukkit.getLogger().warning("Unhandled Debug Message list is over 20! Clearing!");
}
for (Iterator<String> iterator = debugMessagesToSend.iterator(); iterator.hasNext(); ) {
String message = iterator.next();
TBMCDebugMessageEvent event = new TBMCDebugMessageEvent(message);
Bukkit.getPluginManager().callEvent(event);
if (event.isSent())
iterator.remove();
}
}
}
public static boolean IsTestServer() {
return MainPlugin.Test;
}
}

View file

@ -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;

View 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();
}
}

View file

@ -1,18 +1,24 @@
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.
@ -26,7 +32,6 @@ public abstract class Command2 {
* @param args All of the arguments passed as is
* @return The success of the command
*/
@Subcommand
public boolean def(CommandSender sender, @TextArg String args) {
return false;
}
@ -58,12 +63,17 @@ public abstract class Command2 {
@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
private static class SubcommandData {
public final Method method;
public final Command2 command;
public final String[] helpText;
}
private static HashMap<String, SubcommandData> subcommands = new HashMap<>();
@ -133,8 +143,8 @@ public abstract class Command2 {
//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)
sender.sendMessage("Wrong usage."); //TODO: Show help text
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
@ -143,11 +153,55 @@ public abstract class Command2 {
} //TODO: Add to the help
public static void registerCommand(Command2 command) {
for (val method : command.getClass().getMethods())
if (method.isAnnotationPresent(Subcommand.class))
subcommands.put("/" + command.path + //Add command path (class name by default)
(method.getName().equals("def") ? "" : " " + method.getName().replace('_', ' ').toLowerCase()), //Add method name, unless it's 'def'
new SubcommandData(method, command)); //Result of the above (def) is that it will show the help text
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: /" + command.path; //TODO: Print subcommands
ht = both;
subcommands.put("/" + command.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 /" + 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 = "/" + command.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 = Command2.class.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().getName());
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!", new Exception("Method '" + method.toString() + "' != " + mname + " or params is " + params));
} else
TBMCCoreAPI.SendException("Error while getting command data!", new Exception("cs is " + cs));
} else
TBMCCoreAPI.SendException("Error while getting command data!", new Exception("ccs is " + ccs));
}
return ht;
}
private final String path;

View file

@ -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
*/

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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>

View file

@ -1,40 +1,54 @@
<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>
<parent>
<groupId>com.github.TBMCPlugins</groupId>
<artifactId>ButtonCore</artifactId>
<version>master-SNAPSHOT</version>
</parent>
<groupId>com.github.TBMCPlugins.ButtonCore</groupId>
<artifactId>ButtonProcessor</artifactId>
<packaging>jar</packaging>
<name>ButtonProcessor</name>
<url>http://maven.apache.org</url>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgument>-proc:none</compilerArgument>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<useSystemClassLoader>false
</useSystemClassLoader> <!-- https://stackoverflow.com/a/53012553/2703239 -->
</configuration>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
<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>
<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>
<version>master-SNAPSHOT</version>
</parent>
<groupId>com.github.TBMCPlugins.ButtonCore</groupId>
<artifactId>ButtonProcessor</artifactId>
<packaging>jar</packaging>
<name>ButtonProcessor</name>
<url>http://maven.apache.org</url>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgument>-proc:none</compilerArgument>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<useSystemClassLoader>false
</useSystemClassLoader> <!-- https://stackoverflow.com/a/53012553/2703239 -->
</configuration>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

View file

@ -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
}
@Override
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 "";
}
}