From 59a75c455371a56fe4602f4e428a2bb7f9429376 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Mon, 24 Oct 2016 19:08:53 +0200 Subject: [PATCH 01/21] Added files --- .gitignore | 224 ++++++++++++++++++ README.md | 2 + jitpack.yml | 10 + .../lib/EventExceptionHandler.java | 154 ++++++++++++ .../java/buttondevteam/lib/TBMCCoreAPI.java | 94 ++++++++ .../java/buttondevteam/lib/TBMCPlayer.java | 150 ++++++++++++ .../buttondevteam/lib/TBMCPlayerAddEvent.java | 36 +++ .../lib/TBMCPlayerJoinEvent.java | 27 +++ .../lib/TBMCPlayerLoadEvent.java | 34 +++ .../lib/TBMCPlayerQuitEvent.java | 27 +++ .../lib/TBMCPlayerSaveEvent.java | 34 +++ src/main/resources/plugin.yml | 4 + 12 files changed, 796 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 jitpack.yml create mode 100644 src/main/java/buttondevteam/lib/EventExceptionHandler.java create mode 100644 src/main/java/buttondevteam/lib/TBMCCoreAPI.java create mode 100644 src/main/java/buttondevteam/lib/TBMCPlayer.java create mode 100644 src/main/java/buttondevteam/lib/TBMCPlayerAddEvent.java create mode 100644 src/main/java/buttondevteam/lib/TBMCPlayerJoinEvent.java create mode 100644 src/main/java/buttondevteam/lib/TBMCPlayerLoadEvent.java create mode 100644 src/main/java/buttondevteam/lib/TBMCPlayerQuitEvent.java create mode 100644 src/main/java/buttondevteam/lib/TBMCPlayerSaveEvent.java create mode 100644 src/main/resources/plugin.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..10f8ea2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,224 @@ +################# +## Eclipse +################# + +*.pydevproject +.project +.metadata/ +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.classpath +.settings/ +.loadpath +target/ +.project + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# PDT-specific +.buildpath + + +################# +## Visual Studio +################# + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +build/ +[Bb]in/ +[Oo]bj/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml +*.pubxml +*.publishproj + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +#packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + +############# +## Windows detritus +############# + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac crap +.DS_Store + + +############# +## Python +############# + +*.py[cod] + +# Packages +*.egg +*.egg-info +dist/ +build/ +eggs/ +parts/ +var/ +sdist/ +develop-eggs/ +.installed.cfg + +# Installer logs +pip-log.txt + +# Unit test / coverage reports +.coverage +.tox + +#Translations +*.mo + +#Mr Developer +.mr.developer.cfg +.metadata/* +TheButtonAutoFlair/out/artifacts/Autoflair/Autoflair.jar +*.iml +*.name +.idea/compiler.xml +*.xml diff --git a/README.md b/README.md new file mode 100644 index 0000000..fda2dc0 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# ButtonLib +A library that stores everything common to the TBMC plugins diff --git a/jitpack.yml b/jitpack.yml new file mode 100644 index 0000000..219eab8 --- /dev/null +++ b/jitpack.yml @@ -0,0 +1,10 @@ +jdk: + - oraclejdk8 +#before_install: +# - ./prepareEnvironment.sh +install: + - echo "Downloading Towny JAR..." + - 'wget -O "Towny.jar" --header="Accept-Language: en-us,en;q=0.5" http://palmergames.com/file-repo/Towny%20Advanced/Development/0.91.1.5/Towny.jar' + - mvn install:install-file -Dfile=Towny.jar -DgroupId=com.github.TBMCPlugins.ButtonCore -DartifactId=Towny -Dversion=master-SNAPSHOT -Dpackaging=jar + - mvn clean install -DskipTests +# - rm -r ~/.m2/repository/com/palmergames/Towny/ \ No newline at end of file diff --git a/src/main/java/buttondevteam/lib/EventExceptionHandler.java b/src/main/java/buttondevteam/lib/EventExceptionHandler.java new file mode 100644 index 0000000..7c64e4f --- /dev/null +++ b/src/main/java/buttondevteam/lib/EventExceptionHandler.java @@ -0,0 +1,154 @@ +package buttondevteam.lib; + +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang.Validate; +import org.bukkit.event.Event; +import org.bukkit.event.EventException; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.plugin.EventExecutor; +import org.bukkit.plugin.IllegalPluginAccessException; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginManager; +import org.bukkit.plugin.RegisteredListener; + +import com.google.common.collect.Lists; + +public abstract class EventExceptionHandler { // https://gist.github.com/aadnk/5430459 + // For wrapping a registered listener + private static class ExceptionRegisteredListener extends RegisteredListener { + /** + * Represents an event executor that does nothing. This is not really necessary in the current + * implementation of CraftBukkit, but we will take no chances. + */ + private static EventExecutor NULL_EXECUTOR = new EventExecutor() { + @Override + public void execute(Listener listener, Event event) throws EventException { + // Do nothing + } + }; + + private final RegisteredListener delegate; + private final EventExceptionHandler handler; + + public ExceptionRegisteredListener(RegisteredListener delegate, EventExceptionHandler handler) { + super(delegate.getListener(), NULL_EXECUTOR, delegate.getPriority(), + delegate.getPlugin(), delegate.isIgnoringCancelled()); + this.delegate = delegate; + this.handler = handler; + } + + @Override + public void callEvent(Event event) throws EventException { + try { + delegate.callEvent(event); + } catch (EventException e) { + if (!handler.handle(e.getCause(), event)) { + throw e; + } + } catch (Throwable e) { + if (!handler.handle(e, event)) { + doThrow(e); + } + } + } + + // WARNING: HORRIBLE, HORRIBLE HACK to get around checked exceptions + private static void doThrow(Throwable e) { + ExceptionRegisteredListener. doThrowInner(e); + } + + @SuppressWarnings("unchecked") + private static void doThrowInner(Throwable e) throws E { + throw (E) e; + } + } + + /** + * Register Bukkit event handlers with a given exception handler. + * @param listener - a class of event handlers. + * @param plugin - the current plugin. + * @param handler - exception handler. + */ + public static void registerEvents(Listener listener, Plugin plugin, EventExceptionHandler handler) { + Validate.notNull(plugin, "Plugin cannot be NULL."); + + registerEvents(plugin.getServer().getPluginManager(), listener, plugin, handler); + } + + /** + * Register Bukkit event handlers with a given exception handler. + * @param manager - the current plugin manager. + * @param listener - a class of event handlers. + * @param plugin - the current plugin. + * @param handler - exception handler. + */ + public static void registerEvents(PluginManager manager, Listener listener, Plugin plugin, EventExceptionHandler handler) { + Validate.notNull(manager, "Manager cannot be NULL."); + Validate.notNull(listener, "Listener cannot be NULL."); + Validate.notNull(plugin, "Plugin cannot be NULL."); + Validate.notNull(handler, "Handler cannot be NULL."); + + if (!plugin.isEnabled()) { + throw new IllegalPluginAccessException("Plugin attempted to register " + listener + " while not enabled"); + } + + // Create normal listeners + for (Map.Entry, Set> entry : + plugin.getPluginLoader().createRegisteredListeners(listener, plugin).entrySet()) { + + // Wrap these listeners in our exception handler + getHandlerList(entry.getKey()).registerAll(wrapAll(entry.getValue(), handler)); + } + } + + /** + * Wrap every listener in the given collection around an exception handler. + * @param listeners - the listeners to wrap. + * @param handler - the exception handler to add. + * @return The wrapped listeners. + */ + private static Collection wrapAll(Collection listeners, EventExceptionHandler handler) { + List output = Lists.newArrayList(); + + for (RegisteredListener listener : listeners) { + output.add(new ExceptionRegisteredListener(listener, handler)); + } + return output; + } + + /** + * Retrieve the handler list associated with the given class. + * @param clazz - given event class. + * @return Associated handler list. + */ + private static HandlerList getHandlerList(Class clazz) { + // Class must have Event as its superclass + while (clazz.getSuperclass() != null && Event.class.isAssignableFrom(clazz.getSuperclass())) { + try { + Method method = clazz.getDeclaredMethod("getHandlerList"); + method.setAccessible(true); + return (HandlerList) method.invoke(null); + } catch (NoSuchMethodException e) { + // Keep on searching + clazz = clazz.getSuperclass().asSubclass(Event.class); + } catch (Exception e) { + throw new IllegalPluginAccessException(e.getMessage()); + } + } + throw new IllegalPluginAccessException("Unable to find handler list for event " + clazz.getName()); + } + + /** + * Handle a given exception. + * @param ex - the exception to handle. + * @param event - the event that was being handled. + * @return TRUE to indicate that the exception has been handled, FALSE to rethrow it. + */ + public abstract boolean handle(Throwable ex, Event event); +} \ No newline at end of file diff --git a/src/main/java/buttondevteam/lib/TBMCCoreAPI.java b/src/main/java/buttondevteam/lib/TBMCCoreAPI.java new file mode 100644 index 0000000..6e1775d --- /dev/null +++ b/src/main/java/buttondevteam/lib/TBMCCoreAPI.java @@ -0,0 +1,94 @@ +package buttondevteam.lib; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.bukkit.Bukkit; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +public final class TBMCCoreAPI { + /** + * Updates or installs the specified plugin. The plugin must use Maven. + * + * @param name + * The plugin's repository name. + * @return Error message or empty string + */ + public static String UpdatePlugin(String name) { + List plugins = GetPluginNames(); + String correctname = null; + for (String plugin : plugins) { + if (plugin.equalsIgnoreCase(name)) { + correctname = plugin; // Fixes capitalization + break; + } + } + if (correctname == null) { + Bukkit.getLogger().warning("There was an error while updating TBMC plugin: " + name); + return "Can't find plugin: " + name; + } + Bukkit.getLogger().info("Updating TBMC plugin: " + correctname); + String ret = ""; + URL url; + try { + url = new URL("https://jitpack.io/com/github/TBMCPlugins/" + + (correctname.equals("ButtonCore") ? "ButtonCore/ButtonCore" : correctname) + "/master-SNAPSHOT/" + + correctname + "-master-SNAPSHOT.jar"); // ButtonCore exception required since it hosts Towny as well + FileUtils.copyURLToFile(url, new File("plugins/" + correctname + ".jar")); + } catch (FileNotFoundException e) { + ret = "Can't find JAR, the build probably failed. Build log (scroll to bottom):\nhttps://jitpack.io/com/github/TBMCPlugins/" + + correctname + "/master-SNAPSHOT/build.log"; + } catch (IOException e) { + ret = "IO error!\n" + e.getMessage(); + } catch (Exception e) { + Bukkit.getLogger().warning("Error!\n" + e); + ret = e.toString(); + } + return ret; + } + + /** + * Retrieves all the repository names from the GitHub organization. + * + * @return A list of names + */ + public static List GetPluginNames() { + List ret = new ArrayList<>(); + try { + String resp = DownloadString("https://api.github.com/orgs/TBMCPlugins/repos"); + JsonArray arr = new JsonParser().parse(resp).getAsJsonArray(); + for (JsonElement obj : arr) { + JsonObject jobj = obj.getAsJsonObject(); + ret.add(jobj.get("name").getAsString()); + } + } catch (Exception e) { + e.printStackTrace(); + } + return ret; + } + + public static String DownloadString(String urlstr) throws MalformedURLException, 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; + } +} diff --git a/src/main/java/buttondevteam/lib/TBMCPlayer.java b/src/main/java/buttondevteam/lib/TBMCPlayer.java new file mode 100644 index 0000000..8a0840a --- /dev/null +++ b/src/main/java/buttondevteam/lib/TBMCPlayer.java @@ -0,0 +1,150 @@ +package buttondevteam.lib; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.configuration.file.YamlConfiguration; +import com.palmergames.bukkit.towny.Towny; +import com.palmergames.bukkit.towny.object.Resident; +import com.palmergames.bukkit.towny.object.TownyUniverse; + +/** + *

+ * The class for holding data common to all TBMC plugins + *

+ *

+ * Listen to the load and save events from this package to load and save plugin-specific data + *

+ * + * @author Norbi + * + */ +public class TBMCPlayer { + private static final String TBMC_PLAYERS_DIR = "TBMC/players"; + + public String PlayerName; + + public UUID UUID; + + public T AsPluginPlayer(Class cl) { + T obj = null; + try { + obj = cl.newInstance(); + obj.UUID = UUID; + obj.PlayerName = PlayerName; + } catch (Exception e) { + e.printStackTrace(); + } + return obj; + } + + public static HashMap OnlinePlayers = new HashMap<>(); + + /** + * @param name + * The player's name + * @return The {@link TBMCPlayer} object for the player + */ + public static TBMCPlayer GetFromName(String name) { + @SuppressWarnings("deprecation") + OfflinePlayer p = Bukkit.getOfflinePlayer(name); + if (p != null) + return GetPlayer(p); + else + return null; + } + + /** + * @param p + * The Player object + * @return The {@link TBMCPlayer} object for the player + */ + public static TBMCPlayer GetPlayer(OfflinePlayer p) { + if (TBMCPlayer.OnlinePlayers.containsKey(p.getUniqueId())) + return TBMCPlayer.OnlinePlayers.get(p.getUniqueId()); + else + return TBMCPlayer.LoadPlayer(p); + } + + protected static TBMCPlayer LoadPlayer(OfflinePlayer p) { + if (OnlinePlayers.containsKey(p.getUniqueId())) + return OnlinePlayers.get(p.getUniqueId()); + File file = new File(TBMC_PLAYERS_DIR); + file.mkdirs(); + file = new File(TBMC_PLAYERS_DIR, p.getUniqueId().toString() + ".yml"); + if (!file.exists()) + return AddPlayer(p); + else { + final YamlConfiguration yc = new YamlConfiguration(); + try { + yc.load(file); + } catch (Exception e) { + new Exception("Failed to load player data for " + p.getUniqueId(), e).printStackTrace(); + return null; + } + TBMCPlayer player = new TBMCPlayer(); + player.UUID = p.getUniqueId(); + player.PlayerName = yc.getString("playername"); + System.out.println("Player name: " + player.PlayerName); + if (player.PlayerName == null) { + player.PlayerName = p.getName(); + System.out.println("Player name saved: " + player.PlayerName); + } else if (!p.getName().equals(player.PlayerName)) { + System.out.println("Renaming " + player.PlayerName + " to " + p.getName()); + TownyUniverse tu = Towny.getPlugin(Towny.class).getTownyUniverse(); + Resident resident = tu.getResidentMap().get(player.PlayerName); + if (resident == null) + System.out.println("Resident not found - couldn't rename in Towny."); + else if (tu.getResidentMap().contains(p.getName())) + System.out.println("Target resident name is already in use."); // TODO: Handle + else + resident.setName(p.getName()); + player.PlayerName = p.getName(); + System.out.println("Renaming done."); + } + + // Load in other plugins + Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerLoadEvent(yc, player)); + return player; + } + } + + static TBMCPlayer AddPlayer(OfflinePlayer p) { + TBMCPlayer player = new TBMCPlayer(); + player.UUID = p.getUniqueId(); + player.PlayerName = p.getName(); + OnlinePlayers.put(p.getUniqueId(), player); + Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerAddEvent(player)); + SavePlayer(player); + return player; + } + + static void SavePlayer(TBMCPlayer player) { + YamlConfiguration yc = new YamlConfiguration(); + yc.set("playername", player.PlayerName); + Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerSaveEvent(yc, player)); + try { + yc.save(TBMC_PLAYERS_DIR + "/" + player.UUID + ".yml"); + } catch (IOException e) { + new Exception("Failed to save player data for " + player.PlayerName, e).printStackTrace(); + } + } + + static void JoinPlayer(TBMCPlayer player) { + OnlinePlayers.put(player.UUID, player); + Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerJoinEvent(player)); + } + + static void QuitPlayer(TBMCPlayer player) { + OnlinePlayers.remove(player.UUID); + Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerQuitEvent(player)); + } + + T GetAs(Class cl) { // TODO: Serialize player classes + return null; + } +} diff --git a/src/main/java/buttondevteam/lib/TBMCPlayerAddEvent.java b/src/main/java/buttondevteam/lib/TBMCPlayerAddEvent.java new file mode 100644 index 0000000..ae576ec --- /dev/null +++ b/src/main/java/buttondevteam/lib/TBMCPlayerAddEvent.java @@ -0,0 +1,36 @@ +package buttondevteam.lib; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + *

+ * This event gets called when a new player joins. After this event, the + * {@link TBMCPlayerSaveEvent} will be called. + *

+ * + * @author Norbi + * + */ +public class TBMCPlayerAddEvent extends Event { + private static final HandlerList handlers = new HandlerList(); + + private TBMCPlayer player; + + public TBMCPlayerAddEvent(TBMCPlayer player) { + this.player = player; + } + + public TBMCPlayer GetPlayer() { + return player; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} diff --git a/src/main/java/buttondevteam/lib/TBMCPlayerJoinEvent.java b/src/main/java/buttondevteam/lib/TBMCPlayerJoinEvent.java new file mode 100644 index 0000000..fbcc3d0 --- /dev/null +++ b/src/main/java/buttondevteam/lib/TBMCPlayerJoinEvent.java @@ -0,0 +1,27 @@ +package buttondevteam.lib; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class TBMCPlayerJoinEvent extends Event { + private static final HandlerList handlers = new HandlerList(); + + private TBMCPlayer player; + + public TBMCPlayerJoinEvent(TBMCPlayer player) { + this.player = player; + } + + public TBMCPlayer GetPlayer() { + return player; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} diff --git a/src/main/java/buttondevteam/lib/TBMCPlayerLoadEvent.java b/src/main/java/buttondevteam/lib/TBMCPlayerLoadEvent.java new file mode 100644 index 0000000..2d017ce --- /dev/null +++ b/src/main/java/buttondevteam/lib/TBMCPlayerLoadEvent.java @@ -0,0 +1,34 @@ +package buttondevteam.lib; + +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class TBMCPlayerLoadEvent extends Event { + private static final HandlerList handlers = new HandlerList(); + + private YamlConfiguration yaml; + private TBMCPlayer player; + + public TBMCPlayerLoadEvent(YamlConfiguration yaml, TBMCPlayer player) { + this.yaml = yaml; + this.player = player; + } + + public YamlConfiguration GetPlayerConfig() { + return yaml; + } + + public TBMCPlayer GetPlayer() { + return player; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} diff --git a/src/main/java/buttondevteam/lib/TBMCPlayerQuitEvent.java b/src/main/java/buttondevteam/lib/TBMCPlayerQuitEvent.java new file mode 100644 index 0000000..3835605 --- /dev/null +++ b/src/main/java/buttondevteam/lib/TBMCPlayerQuitEvent.java @@ -0,0 +1,27 @@ +package buttondevteam.lib; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class TBMCPlayerQuitEvent extends Event { + private static final HandlerList handlers = new HandlerList(); + + private TBMCPlayer player; + + public TBMCPlayerQuitEvent(TBMCPlayer player) { + this.player = player; + } + + public TBMCPlayer GetPlayer() { + return player; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} diff --git a/src/main/java/buttondevteam/lib/TBMCPlayerSaveEvent.java b/src/main/java/buttondevteam/lib/TBMCPlayerSaveEvent.java new file mode 100644 index 0000000..114aea0 --- /dev/null +++ b/src/main/java/buttondevteam/lib/TBMCPlayerSaveEvent.java @@ -0,0 +1,34 @@ +package buttondevteam.lib; + +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class TBMCPlayerSaveEvent extends Event { + private static final HandlerList handlers = new HandlerList(); + + private YamlConfiguration yaml; + private TBMCPlayer player; + + public TBMCPlayerSaveEvent(YamlConfiguration yaml, TBMCPlayer player) { + this.yaml = yaml; + this.player = player; + } + + public YamlConfiguration GetPlayerConfig() { + return yaml; + } + + public TBMCPlayer GetPlayer() { + return player; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..f64dc39 --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,4 @@ +name: ButtonPluginBucket +main: buttondevteam.bucket.MainPlugin +version: 1.0 +author: TBMCPlugins \ No newline at end of file From 3a793b76db9724003d366ebc938a05a8a0fa45a4 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Mon, 24 Oct 2016 19:22:37 +0200 Subject: [PATCH 02/21] Fixed things --- .gitignore | 1 - jitpack.yml | 10 ----- pom.xml | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+), 11 deletions(-) delete mode 100644 jitpack.yml create mode 100644 pom.xml diff --git a/.gitignore b/.gitignore index 10f8ea2..77e539d 100644 --- a/.gitignore +++ b/.gitignore @@ -221,4 +221,3 @@ TheButtonAutoFlair/out/artifacts/Autoflair/Autoflair.jar *.iml *.name .idea/compiler.xml -*.xml diff --git a/jitpack.yml b/jitpack.yml deleted file mode 100644 index 219eab8..0000000 --- a/jitpack.yml +++ /dev/null @@ -1,10 +0,0 @@ -jdk: - - oraclejdk8 -#before_install: -# - ./prepareEnvironment.sh -install: - - echo "Downloading Towny JAR..." - - 'wget -O "Towny.jar" --header="Accept-Language: en-us,en;q=0.5" http://palmergames.com/file-repo/Towny%20Advanced/Development/0.91.1.5/Towny.jar' - - mvn install:install-file -Dfile=Towny.jar -DgroupId=com.github.TBMCPlugins.ButtonCore -DartifactId=Towny -Dversion=master-SNAPSHOT -Dpackaging=jar - - mvn clean install -DskipTests -# - rm -r ~/.m2/repository/com/palmergames/Towny/ \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..2d27126 --- /dev/null +++ b/pom.xml @@ -0,0 +1,111 @@ + + 4.0.0 + com.github.TBMCPlugins + ButtonLib + master-SNAPSHOT + ButtonLib + ButtonCore + + src/main/java + + + src + + **/*.java + + + + src/main/resources + + *.properties + *.yml + *.csv + *.txt + + true + + + ButtonCore + + + maven-compiler-plugin + 3.3 + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-resources-plugin + 3.0.1 + + + copy + compile + + copy-resources + + + target + + + resources + + + + + + + + + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + jitpack.io + https://jitpack.io/ + + + + + org.spigotmc + spigot-api + 1.9.2-R0.1-SNAPSHOT + + + + org.apache.commons + commons-io + 1.3.2 + + + + TBMCPlugins + https://github.com/TBMCPlugins + + + + internal.repo + Temporary Staging Repository + file://${project.build.directory}/mvn-repo/${project.name} + + + + + github + + + https://github.com/TBMCPlugins/mvn-repo + scm:git:https://github.com/TBMCPlugins/mvn-repo.git + scm:git:https://github.com/TBMCPlugins/mvn-repo.git + + \ No newline at end of file From cbf091d31c7f69a9ea74f41bc3ab5c38742434a0 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Mon, 24 Oct 2016 19:28:39 +0200 Subject: [PATCH 03/21] Moved Towny here --- jitpack.yml | 10 +++ pom.xml | 225 +++++++++++++++++++++++++++------------------------- 2 files changed, 125 insertions(+), 110 deletions(-) create mode 100644 jitpack.yml diff --git a/jitpack.yml b/jitpack.yml new file mode 100644 index 0000000..a94b9fc --- /dev/null +++ b/jitpack.yml @@ -0,0 +1,10 @@ +jdk: + - oraclejdk8 +#before_install: +# - ./prepareEnvironment.sh +install: + - echo "Downloading Towny JAR..." + - 'wget -O "Towny.jar" --header="Accept-Language: en-us,en;q=0.5" http://palmergames.com/file-repo/Towny%20Advanced/Development/0.91.1.5/Towny.jar' + - mvn install:install-file -Dfile=Towny.jar -DgroupId=com.github.TBMCPlugins.ButtonLib -DartifactId=Towny -Dversion=master-SNAPSHOT -Dpackaging=jar + - mvn clean install -DskipTests +# - rm -r ~/.m2/repository/com/palmergames/Towny/ \ No newline at end of file diff --git a/pom.xml b/pom.xml index 2d27126..e3e14bb 100644 --- a/pom.xml +++ b/pom.xml @@ -1,111 +1,116 @@ - - 4.0.0 - com.github.TBMCPlugins - ButtonLib - master-SNAPSHOT - ButtonLib - ButtonCore - - src/main/java - - - src - - **/*.java - - - - src/main/resources - - *.properties - *.yml - *.csv - *.txt - - true - - - ButtonCore - - - maven-compiler-plugin - 3.3 - - 1.8 - 1.8 - - - - - org.apache.maven.plugins - maven-resources-plugin - 3.0.1 - - - copy - compile - - copy-resources - - - target - - - resources - - - - - - - - - - - spigot-repo - https://hub.spigotmc.org/nexus/content/repositories/snapshots/ - - - jitpack.io - https://jitpack.io/ - - - - - org.spigotmc - spigot-api - 1.9.2-R0.1-SNAPSHOT - - - - org.apache.commons - commons-io - 1.3.2 - - - - TBMCPlugins - https://github.com/TBMCPlugins - - - - internal.repo - Temporary Staging Repository - file://${project.build.directory}/mvn-repo/${project.name} - - - - - github - - - https://github.com/TBMCPlugins/mvn-repo - scm:git:https://github.com/TBMCPlugins/mvn-repo.git - scm:git:https://github.com/TBMCPlugins/mvn-repo.git - + + 4.0.0 + com.github.TBMCPlugins + ButtonLib + master-SNAPSHOT + ButtonLib + ButtonCore + + src/main/java + + + src + + **/*.java + + + + src/main/resources + + *.properties + *.yml + *.csv + *.txt + + true + + + ButtonCore + + + maven-compiler-plugin + 3.3 + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-resources-plugin + 3.0.1 + + + copy + compile + + copy-resources + + + target + + + resources + + + + + + + + + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + jitpack.io + https://jitpack.io/ + + + + + org.spigotmc + spigot-api + 1.9.2-R0.1-SNAPSHOT + + + + org.apache.commons + commons-io + 1.3.2 + + + com.github.TBMCPlugins.ButtonLib + Towny + master-SNAPSHOT + + + + TBMCPlugins + https://github.com/TBMCPlugins + + + + internal.repo + Temporary Staging Repository + file://${project.build.directory}/mvn-repo/${project.name} + + + + + github + + + https://github.com/TBMCPlugins/mvn-repo + scm:git:https://github.com/TBMCPlugins/mvn-repo.git + scm:git:https://github.com/TBMCPlugins/mvn-repo.git + \ No newline at end of file From 59bd3ac523163e6fd8067fc1bcd950d640a85886 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Mon, 24 Oct 2016 20:38:35 +0200 Subject: [PATCH 04/21] Fixed visibility levels --- src/main/java/buttondevteam/lib/TBMCPlayer.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/buttondevteam/lib/TBMCPlayer.java b/src/main/java/buttondevteam/lib/TBMCPlayer.java index 8a0840a..fd6e129 100644 --- a/src/main/java/buttondevteam/lib/TBMCPlayer.java +++ b/src/main/java/buttondevteam/lib/TBMCPlayer.java @@ -70,7 +70,7 @@ public class TBMCPlayer { return TBMCPlayer.LoadPlayer(p); } - protected static TBMCPlayer LoadPlayer(OfflinePlayer p) { + public static TBMCPlayer LoadPlayer(OfflinePlayer p) { if (OnlinePlayers.containsKey(p.getUniqueId())) return OnlinePlayers.get(p.getUniqueId()); File file = new File(TBMC_PLAYERS_DIR); @@ -123,7 +123,7 @@ public class TBMCPlayer { return player; } - static void SavePlayer(TBMCPlayer player) { + public static void SavePlayer(TBMCPlayer player) { YamlConfiguration yc = new YamlConfiguration(); yc.set("playername", player.PlayerName); Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerSaveEvent(yc, player)); @@ -134,12 +134,12 @@ public class TBMCPlayer { } } - static void JoinPlayer(TBMCPlayer player) { + public static void JoinPlayer(TBMCPlayer player) { OnlinePlayers.put(player.UUID, player); Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerJoinEvent(player)); } - static void QuitPlayer(TBMCPlayer player) { + public static void QuitPlayer(TBMCPlayer player) { OnlinePlayers.remove(player.UUID); Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerQuitEvent(player)); } From 435ebaac983e6815f358878f7b9277c84903596f Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Mon, 24 Oct 2016 20:51:38 +0200 Subject: [PATCH 05/21] Updated plugin updater --- src/main/java/buttondevteam/lib/TBMCCoreAPI.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/buttondevteam/lib/TBMCCoreAPI.java b/src/main/java/buttondevteam/lib/TBMCCoreAPI.java index 6e1775d..b544c72 100644 --- a/src/main/java/buttondevteam/lib/TBMCCoreAPI.java +++ b/src/main/java/buttondevteam/lib/TBMCCoreAPI.java @@ -45,8 +45,8 @@ public final class TBMCCoreAPI { URL url; try { url = new URL("https://jitpack.io/com/github/TBMCPlugins/" - + (correctname.equals("ButtonCore") ? "ButtonCore/ButtonCore" : correctname) + "/master-SNAPSHOT/" - + correctname + "-master-SNAPSHOT.jar"); // ButtonCore exception required since it hosts Towny as well + + correctname + "/master-SNAPSHOT/" + + correctname + "-master-SNAPSHOT.jar"); // ButtonLib exception not required, not a separate plugin FileUtils.copyURLToFile(url, new File("plugins/" + correctname + ".jar")); } catch (FileNotFoundException e) { ret = "Can't find JAR, the build probably failed. Build log (scroll to bottom):\nhttps://jitpack.io/com/github/TBMCPlugins/" From b0c145af962085bdc6cf0e9bbe5578cd9f69c23a Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Fri, 28 Oct 2016 21:23:39 +0200 Subject: [PATCH 06/21] Moved command stuff to Lib to avoid depedency loops --- pom.xml | 6 ++ .../buttondevteam/lib/chat/TBMCChatAPI.java | 84 +++++++++++++++++++ .../lib/chat/TBMCCommandBase.java | 26 ++++++ 3 files changed, 116 insertions(+) create mode 100644 src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java create mode 100644 src/main/java/buttondevteam/lib/chat/TBMCCommandBase.java diff --git a/pom.xml b/pom.xml index e3e14bb..b2051ac 100644 --- a/pom.xml +++ b/pom.xml @@ -92,6 +92,12 @@ Towny master-SNAPSHOT + + + org.reflections + reflections + 0.9.10 + TBMCPlugins diff --git a/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java b/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java new file mode 100644 index 0000000..e5571df --- /dev/null +++ b/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java @@ -0,0 +1,84 @@ +package buttondevteam.lib.chat; + +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Set; + +import org.bukkit.plugin.java.JavaPlugin; +import org.reflections.Reflections; +import org.reflections.scanners.SubTypesScanner; +import org.reflections.util.ClasspathHelper; +import org.reflections.util.ConfigurationBuilder; + +import buttondevteam.lib.TBMCPlayer; + +public class TBMCChatAPI { + + private static HashMap commands = new HashMap(); + + public static HashMap GetCommands() { + return commands; + } + + /** + *

+ * This method adds a plugin's commands to help and sets their executor. + *

+ *

+ * The command must be registered in the caller plugin's plugin.yml. Otherwise the plugin will output a messsage to console. + *

+ *

+ * Using this method after the server is done loading will have no effect. + *

+ * + * @param plugin + * The caller plugin + * @param acmdclass + * A command's class to get the package name for commands. The provided class's package and subpackages are scanned for commands. + */ + public static void AddCommands(JavaPlugin plugin, Class acmdclass) { + plugin.getLogger().info("Registering commands for " + plugin.getName()); + Reflections rf = new Reflections( + new ConfigurationBuilder().setUrls(ClasspathHelper.forClassLoader(plugin.getClass().getClassLoader())) + .addClassLoader(plugin.getClass().getClassLoader()).addScanners(new SubTypesScanner()) + .filterInputsBy((String pkg) -> pkg.contains(acmdclass.getPackage().getName()))); + Set> cmds = rf.getSubTypesOf(TBMCCommandBase.class); + for (Class cmd : cmds) { + try { + if (Modifier.isAbstract(cmd.getModifiers())) + continue; + TBMCCommandBase c = cmd.newInstance(); + c.plugin = plugin; + commands.put(c.GetCommandPath(), c); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + } + + /** + *

+ * Add player information for {@link PlayerInfoCommand}. Only mods can see the given information. + *

+ * + * @param player + * @param infoline + */ + public void AddPlayerInfoForMods(TBMCPlayer player, String infoline) { + // TODO + } + + /** + *

+ * Add player information for hover text at {@link ChatProcessing}. Every online player can see the given information. + *

+ * + * @param player + * @param infoline + */ + public void AddPlayerInfoForHover(TBMCPlayer player, String infoline) { + // TODO + } +} diff --git a/src/main/java/buttondevteam/lib/chat/TBMCCommandBase.java b/src/main/java/buttondevteam/lib/chat/TBMCCommandBase.java new file mode 100644 index 0000000..d1d4f3d --- /dev/null +++ b/src/main/java/buttondevteam/lib/chat/TBMCCommandBase.java @@ -0,0 +1,26 @@ +package buttondevteam.lib.chat; + +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.Plugin; + +public abstract class TBMCCommandBase { + + public TBMCCommandBase() { + } + + public abstract String[] GetHelpText(String alias); + + public abstract boolean OnCommand(CommandSender sender, String alias, String[] args); + + public abstract String GetCommandPath(); + + public abstract boolean GetPlayerOnly(); + + public abstract boolean GetModOnly(); + + Plugin plugin; // Used By TBMCChatAPI + + public Plugin getPlugin() { // Used by CommandCaller (ButtonChat) + return plugin; + } +} From 4ebb526d8770b61e4d5ffbcdd223b18f011b4f7b Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sat, 29 Oct 2016 12:59:34 +0200 Subject: [PATCH 07/21] Made TBMCPlayer way easier to use and... - Fixed a Maven inconsistency that prevented updating the projects in realtime - Added documentation --- pom.xml | 2 +- .../java/buttondevteam/lib/TBMCPlayer.java | 207 ++++++++++++++---- 2 files changed, 163 insertions(+), 46 deletions(-) diff --git a/pom.xml b/pom.xml index b2051ac..308183b 100644 --- a/pom.xml +++ b/pom.xml @@ -1,7 +1,7 @@ 4.0.0 - com.github.TBMCPlugins + com.github.TBMCPlugins.ButtonLib ButtonLib master-SNAPSHOT ButtonLib diff --git a/src/main/java/buttondevteam/lib/TBMCPlayer.java b/src/main/java/buttondevteam/lib/TBMCPlayer.java index fd6e129..9062790 100644 --- a/src/main/java/buttondevteam/lib/TBMCPlayer.java +++ b/src/main/java/buttondevteam/lib/TBMCPlayer.java @@ -3,6 +3,7 @@ package buttondevteam.lib; import java.io.File; import java.io.IOException; import java.util.HashMap; +import java.util.Map.Entry; import java.util.UUID; import org.bukkit.Bukkit; @@ -17,32 +18,113 @@ import com.palmergames.bukkit.towny.object.TownyUniverse; * The class for holding data common to all TBMC plugins *

*

- * Listen to the load and save events from this package to load and save plugin-specific data + * Use {@link #asPluginPlayer(Class)} to get plugin-specific data *

* * @author Norbi * */ -public class TBMCPlayer { +public class TBMCPlayer implements AutoCloseable { private static final String TBMC_PLAYERS_DIR = "TBMC/players"; - public String PlayerName; + private HashMap data = new HashMap<>(); - public UUID UUID; + /** + *

+ * Gets a player data entry for the caller plugin returning the desired type.
+ * It will automatically determine the key and the return type.
+ * Usage: + *

+ * + *
+	 * {@code
+	 * public String getPlayerName() {
+	 * 	return getData();
+	 * }
+	 * 
+ * + * @return The value or null if not found + */ + @SuppressWarnings("unchecked") + protected T getData() { + StackTraceElement st = new Exception().getStackTrace()[0]; + String mname = st.getMethodName(); + if (!mname.startsWith("get")) + throw new UnsupportedOperationException("Can only use getData from a getXYZ method"); + return (T) LoadedPlayers.get(uuid).data.get(mname.substring("get".length()).toLowerCase()); + } - public T AsPluginPlayer(Class cl) { + /** + * Sets a player data entry based on the caller method
+ * Usage: + *

+ * + *
+	 * {@code
+	 * public String setPlayerName(String value) {
+	 * 	return setData(value);
+	 * }
+	 * 
+ * + * @param value + * The value to set + */ + protected void setData(Object value) { + StackTraceElement st = new Exception().getStackTrace()[0]; + String mname = st.getMethodName(); + if (!mname.startsWith("set")) + throw new UnsupportedOperationException("Can only use setData from a setXYZ method"); + LoadedPlayers.get(uuid).data.put(mname.substring("set".length()).toLowerCase(), value); + } + + /** + * Gets the player's Minecraft name + * + * @return The player's Minecraft name + */ + public String getPlayerName() { + return getData(); + } + + /** + * Sets the player's Minecraft name + * + * @param playerName + * the new name + */ + public void setPlayerName(String playerName) { + setData(playerName); + } + + private UUID uuid; // Do not save it in the file + + /** + * Get the player's UUID + * + * @return The Minecraft UUID of the player + */ + public UUID getUuid() { + return uuid; + } + + /** + * Gets the TBMCPlayer object as a specific plugin player, keeping it's data + * + * @param cl + * @return + */ + public T asPluginPlayer(Class cl) { T obj = null; try { obj = cl.newInstance(); - obj.UUID = UUID; - obj.PlayerName = PlayerName; + ((TBMCPlayer) obj).data.putAll(data); } catch (Exception e) { e.printStackTrace(); } return obj; } - public static HashMap OnlinePlayers = new HashMap<>(); + private static HashMap LoadedPlayers = new HashMap<>(); /** * @param name @@ -53,31 +135,45 @@ public class TBMCPlayer { @SuppressWarnings("deprecation") OfflinePlayer p = Bukkit.getOfflinePlayer(name); if (p != null) - return GetPlayer(p); + return getPlayer(p); else return null; } /** + * This method returns a TBMC player from a Bukkit player. Calling this method may return an offline player, therefore it's highly recommended to use {@link #close()} to unload the player data. + * Using try-with-resources may be the easiest way to achieve this. Example: + * + *
+	 * {@code
+	 * try(TBMCPlayer player = GetPlayer(p))
+	 * {
+	 * 	...
+	 * }
+	 * 
+ * * @param p * The Player object * @return The {@link TBMCPlayer} object for the player */ - public static TBMCPlayer GetPlayer(OfflinePlayer p) { - if (TBMCPlayer.OnlinePlayers.containsKey(p.getUniqueId())) - return TBMCPlayer.OnlinePlayers.get(p.getUniqueId()); + public static TBMCPlayer getPlayer(OfflinePlayer p) { + if (TBMCPlayer.LoadedPlayers.containsKey(p.getUniqueId())) + return TBMCPlayer.LoadedPlayers.get(p.getUniqueId()); else - return TBMCPlayer.LoadPlayer(p); + return TBMCPlayer.loadPlayer(p); } - public static TBMCPlayer LoadPlayer(OfflinePlayer p) { - if (OnlinePlayers.containsKey(p.getUniqueId())) - return OnlinePlayers.get(p.getUniqueId()); + /** + * Only intended to use from ButtonCore + */ + public static TBMCPlayer loadPlayer(OfflinePlayer p) { + if (LoadedPlayers.containsKey(p.getUniqueId())) + return LoadedPlayers.get(p.getUniqueId()); File file = new File(TBMC_PLAYERS_DIR); file.mkdirs(); file = new File(TBMC_PLAYERS_DIR, p.getUniqueId().toString() + ".yml"); if (!file.exists()) - return AddPlayer(p); + return addPlayer(p); else { final YamlConfiguration yc = new YamlConfiguration(); try { @@ -87,25 +183,26 @@ public class TBMCPlayer { return null; } TBMCPlayer player = new TBMCPlayer(); - player.UUID = p.getUniqueId(); - player.PlayerName = yc.getString("playername"); - System.out.println("Player name: " + player.PlayerName); - if (player.PlayerName == null) { - player.PlayerName = p.getName(); - System.out.println("Player name saved: " + player.PlayerName); - } else if (!p.getName().equals(player.PlayerName)) { - System.out.println("Renaming " + player.PlayerName + " to " + p.getName()); + player.uuid = p.getUniqueId(); + player.data.putAll(yc.getValues(true)); + Bukkit.getLogger().info("Loaded player: " + player.getPlayerName()); + if (player.getPlayerName() == null) { + player.setPlayerName(p.getName()); + Bukkit.getLogger().info("Player name saved: " + player.getPlayerName()); + } else if (!p.getName().equals(player.getPlayerName())) { + Bukkit.getLogger().info("Renaming " + player.getPlayerName() + " to " + p.getName()); TownyUniverse tu = Towny.getPlugin(Towny.class).getTownyUniverse(); - Resident resident = tu.getResidentMap().get(player.PlayerName); + Resident resident = tu.getResidentMap().get(player.getPlayerName()); if (resident == null) - System.out.println("Resident not found - couldn't rename in Towny."); + Bukkit.getLogger().warning("Resident not found - couldn't rename in Towny."); else if (tu.getResidentMap().contains(p.getName())) - System.out.println("Target resident name is already in use."); // TODO: Handle + Bukkit.getLogger().warning("Target resident name is already in use."); // TODO: Handle else resident.setName(p.getName()); - player.PlayerName = p.getName(); - System.out.println("Renaming done."); + player.setPlayerName(p.getName()); + Bukkit.getLogger().info("Renaming done."); } + LoadedPlayers.put(p.getUniqueId(), player); // Load in other plugins Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerLoadEvent(yc, player)); @@ -113,38 +210,58 @@ public class TBMCPlayer { } } - static TBMCPlayer AddPlayer(OfflinePlayer p) { + /** + * Only intended to use from ButtonCore + */ + public static TBMCPlayer addPlayer(OfflinePlayer p) { TBMCPlayer player = new TBMCPlayer(); - player.UUID = p.getUniqueId(); - player.PlayerName = p.getName(); - OnlinePlayers.put(p.getUniqueId(), player); + player.uuid = p.getUniqueId(); + player.setPlayerName(p.getName()); + LoadedPlayers.put(p.getUniqueId(), player); Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerAddEvent(player)); - SavePlayer(player); + savePlayer(player); return player; } - public static void SavePlayer(TBMCPlayer player) { + /** + * Only intended to use from ButtonCore + */ + public static void savePlayer(TBMCPlayer player) { YamlConfiguration yc = new YamlConfiguration(); - yc.set("playername", player.PlayerName); + for (Entry item : player.data.entrySet()) + yc.set(item.getKey(), item.getValue()); Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerSaveEvent(yc, player)); try { - yc.save(TBMC_PLAYERS_DIR + "/" + player.UUID + ".yml"); + yc.save(TBMC_PLAYERS_DIR + "/" + player.uuid + ".yml"); } catch (IOException e) { - new Exception("Failed to save player data for " + player.PlayerName, e).printStackTrace(); + new Exception("Failed to save player data for " + player.getPlayerName(), e).printStackTrace(); } } - public static void JoinPlayer(TBMCPlayer player) { - OnlinePlayers.put(player.UUID, player); + /** + * Only intended to use from ButtonCore + */ + public static void joinPlayer(TBMCPlayer player) { + LoadedPlayers.put(player.uuid, player); Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerJoinEvent(player)); } - public static void QuitPlayer(TBMCPlayer player) { - OnlinePlayers.remove(player.UUID); + /** + * Only intended to use from ButtonCore + */ + public static void quitPlayer(TBMCPlayer player) { + LoadedPlayers.remove(player.uuid); Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerQuitEvent(player)); } - T GetAs(Class cl) { // TODO: Serialize player classes - return null; + /** + * By default the player data will only get cleaned from memory when the player quits. Therefore this method must be called when accessing an offline player to clean the player data up. Calling + * this method will have no effect on online players.
+ * Therefore, the recommended use is to call it when using {@link #GetPlayer} or use try-with-resources. + */ + @Override + public void close() throws Exception { + if (!Bukkit.getPlayer(uuid).isOnline()) + LoadedPlayers.remove(uuid); } } From 12a42f8aba753f908b05ea98b8d6d9c6746e9df9 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sat, 29 Oct 2016 14:10:27 +0200 Subject: [PATCH 08/21] Added some comments, documentation --- src/main/java/buttondevteam/lib/TBMCPlayer.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/java/buttondevteam/lib/TBMCPlayer.java b/src/main/java/buttondevteam/lib/TBMCPlayer.java index 9062790..6b52160 100644 --- a/src/main/java/buttondevteam/lib/TBMCPlayer.java +++ b/src/main/java/buttondevteam/lib/TBMCPlayer.java @@ -24,7 +24,7 @@ import com.palmergames.bukkit.towny.object.TownyUniverse; * @author Norbi * */ -public class TBMCPlayer implements AutoCloseable { +public class TBMCPlayer implements AutoCloseable { //TODO: Load player data in Core private static final String TBMC_PLAYERS_DIR = "TBMC/players"; private HashMap data = new HashMap<>(); @@ -127,11 +127,22 @@ public class TBMCPlayer implements AutoCloseable { private static HashMap LoadedPlayers = new HashMap<>(); /** + * This method returns a TBMC player from their name. Calling this method may return an offline player which will load it, therefore it's highly recommended to use {@link #close()} to unload the player data. Using + * try-with-resources may be the easiest way to achieve this. Example: + * + *
+	 * {@code
+	 * try(TBMCPlayer player = getFromName(p))
+	 * {
+	 * 	...
+	 * }
+	 * 
+ * * @param name * The player's name * @return The {@link TBMCPlayer} object for the player */ - public static TBMCPlayer GetFromName(String name) { + public static TBMCPlayer getFromName(String name) { @SuppressWarnings("deprecation") OfflinePlayer p = Bukkit.getOfflinePlayer(name); if (p != null) @@ -146,7 +157,7 @@ public class TBMCPlayer implements AutoCloseable { * *
 	 * {@code
-	 * try(TBMCPlayer player = GetPlayer(p))
+	 * try(TBMCPlayer player = getPlayer(p))
 	 * {
 	 * 	...
 	 * }

From 24d778e69d6933311738c80be0323657728dda09 Mon Sep 17 00:00:00 2001
From: NorbiPeti 
Date: Sat, 29 Oct 2016 19:05:50 +0200
Subject: [PATCH 09/21] Added UUID overload for getPlayer

---
 .../java/buttondevteam/lib/TBMCPlayer.java    | 29 +++++++++++++++++--
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/src/main/java/buttondevteam/lib/TBMCPlayer.java b/src/main/java/buttondevteam/lib/TBMCPlayer.java
index 6b52160..94ee5be 100644
--- a/src/main/java/buttondevteam/lib/TBMCPlayer.java
+++ b/src/main/java/buttondevteam/lib/TBMCPlayer.java
@@ -24,7 +24,7 @@ import com.palmergames.bukkit.towny.object.TownyUniverse;
  * @author Norbi
  *
  */
-public class TBMCPlayer implements AutoCloseable { //TODO: Load player data in Core
+public class TBMCPlayer implements AutoCloseable {
 	private static final String TBMC_PLAYERS_DIR = "TBMC/players";
 
 	private HashMap data = new HashMap<>();
@@ -127,8 +127,8 @@ public class TBMCPlayer implements AutoCloseable { //TODO: Load player data in C
 	private static HashMap LoadedPlayers = new HashMap<>();
 
 	/**
-	 * This method returns a TBMC player from their name. Calling this method may return an offline player which will load it, therefore it's highly recommended to use {@link #close()} to unload the player data. Using
-	 * try-with-resources may be the easiest way to achieve this. Example:
+	 * This method returns a TBMC player from their name. Calling this method may return an offline player which will load it, therefore it's highly recommended to use {@link #close()} to unload the
+	 * player data. Using try-with-resources may be the easiest way to achieve this. Example:
 	 * 
 	 * 
 	 * {@code
@@ -174,6 +174,29 @@ public class TBMCPlayer implements AutoCloseable { //TODO: Load player data in C
 			return TBMCPlayer.loadPlayer(p);
 	}
 
+	/**
+	 * This method returns a TBMC player from a Bukkit player. Calling this method may return an offline player, therefore it's highly recommended to use {@link #close()} to unload the player data.
+	 * Using try-with-resources may be the easiest way to achieve this. Example:
+	 * 
+	 * 
+	 * {@code
+	 * try(TBMCPlayer player = getPlayer(p))
+	 * {
+	 * 	...
+	 * }
+	 * 
+ * + * @param p + * The Player object + * @return The {@link TBMCPlayer} object for the player + */ + public static TBMCPlayer getPlayer(UUID uuid) { + if (TBMCPlayer.LoadedPlayers.containsKey(uuid)) + return TBMCPlayer.LoadedPlayers.get(uuid); + else + return TBMCPlayer.loadPlayer(Bukkit.getOfflinePlayer(uuid)); + } + /** * Only intended to use from ButtonCore */ From ee40f7b5827e48be1725ecf14f3386f6727c57b9 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sat, 29 Oct 2016 19:19:40 +0200 Subject: [PATCH 10/21] Added getPlayerAs --- .../java/buttondevteam/lib/TBMCPlayer.java | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/main/java/buttondevteam/lib/TBMCPlayer.java b/src/main/java/buttondevteam/lib/TBMCPlayer.java index 94ee5be..7181405 100644 --- a/src/main/java/buttondevteam/lib/TBMCPlayer.java +++ b/src/main/java/buttondevteam/lib/TBMCPlayer.java @@ -108,10 +108,12 @@ public class TBMCPlayer implements AutoCloseable { } /** - * Gets the TBMCPlayer object as a specific plugin player, keeping it's data + * Gets the TBMCPlayer object as a specific plugin player, keeping it's data * * + * @param p + * Player to get * @param cl - * @return + * The TBMCPlayer subclass */ public T asPluginPlayer(Class cl) { T obj = null; @@ -175,7 +177,7 @@ public class TBMCPlayer implements AutoCloseable { } /** - * This method returns a TBMC player from a Bukkit player. Calling this method may return an offline player, therefore it's highly recommended to use {@link #close()} to unload the player data. + * This method returns a TBMC player from a player UUID. Calling this method may return an offline player, therefore it's highly recommended to use {@link #close()} to unload the player data. * Using try-with-resources may be the easiest way to achieve this. Example: * *
@@ -197,6 +199,36 @@ public class TBMCPlayer implements AutoCloseable {
 			return TBMCPlayer.loadPlayer(Bukkit.getOfflinePlayer(uuid));
 	}
 
+	/**
+	 * This is a convenience method for {@link #getPlayer(OfflinePlayer)}.{@link #asPluginPlayer(Class)}.
+	 * 
+	 * See those methods for more information.
+	 * 
+	 * @param p
+	 *            Player to get
+	 * @param cl
+	 *            The TBMCPlayer subclass
+	 * @return The player as a subtype of TBMCPlayer
+	 */
+	public static  TBMCPlayer getPlayerAs(OfflinePlayer p, Class cl) {
+		return getPlayer(p).asPluginPlayer(cl);
+	}
+
+	/**
+	 * This is a convenience method for {@link #getPlayer(UUID)}.{@link #asPluginPlayer(Class)}
+	 * 
+	 * See those methods for more information.
+	 * 
+	 * @param uuid
+	 *            The UUID of the player to get
+	 * @param cl
+	 *            The TBMCPlayer subclass
+	 * @return The player as a subtype of TBMCPlayer
+	 */
+	public static  TBMCPlayer getPlayerAs(UUID uuid, Class cl) {
+		return getPlayer(uuid).asPluginPlayer(cl);
+	}
+
 	/**
 	 * Only intended to use from ButtonCore
 	 */

From 981b2e70dbe09ab978d7869095adf6981cc7539e Mon Sep 17 00:00:00 2001
From: NorbiPeti 
Date: Sat, 29 Oct 2016 19:20:42 +0200
Subject: [PATCH 11/21] Fixed return type

---
 src/main/java/buttondevteam/lib/TBMCPlayer.java | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/main/java/buttondevteam/lib/TBMCPlayer.java b/src/main/java/buttondevteam/lib/TBMCPlayer.java
index 7181405..65fe19d 100644
--- a/src/main/java/buttondevteam/lib/TBMCPlayer.java
+++ b/src/main/java/buttondevteam/lib/TBMCPlayer.java
@@ -210,7 +210,7 @@ public class TBMCPlayer implements AutoCloseable {
 	 *            The TBMCPlayer subclass
 	 * @return The player as a subtype of TBMCPlayer
 	 */
-	public static  TBMCPlayer getPlayerAs(OfflinePlayer p, Class cl) {
+	public static  T getPlayerAs(OfflinePlayer p, Class cl) {
 		return getPlayer(p).asPluginPlayer(cl);
 	}
 
@@ -225,7 +225,7 @@ public class TBMCPlayer implements AutoCloseable {
 	 *            The TBMCPlayer subclass
 	 * @return The player as a subtype of TBMCPlayer
 	 */
-	public static  TBMCPlayer getPlayerAs(UUID uuid, Class cl) {
+	public static  T getPlayerAs(UUID uuid, Class cl) {
 		return getPlayer(uuid).asPluginPlayer(cl);
 	}
 

From 2ebadbe5d413573c909eb02ade01d59d4624352e Mon Sep 17 00:00:00 2001
From: NorbiPeti 
Date: Sat, 29 Oct 2016 22:10:00 +0200
Subject: [PATCH 12/21] Moved GetSubCommands

---
 .../java/buttondevteam/lib/chat/TBMCChatAPI.java  | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java b/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java
index e5571df..c1804d9 100644
--- a/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java
+++ b/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java
@@ -1,6 +1,7 @@
 package buttondevteam.lib.chat;
 
 import java.lang.reflect.Modifier;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Set;
 
@@ -20,6 +21,20 @@ public class TBMCChatAPI {
 		return commands;
 	}
 
+	public static String[] GetSubCommands(TBMCCommandBase command) {
+		ArrayList cmds = new ArrayList();
+		cmds.add("ยง6---- Subcommands ----");
+		for (TBMCCommandBase cmd : TBMCChatAPI.GetCommands().values()) {
+			if (cmd.GetCommandPath().startsWith(command.GetCommandPath() + "/")) {
+				int ind = cmd.GetCommandPath().indexOf('/', command.GetCommandPath().length() + 2);
+				if (ind >= 0)
+					continue;
+				cmds.add(cmd.GetCommandPath().replace('/', ' '));
+			}
+		}
+		return cmds.toArray(new String[cmds.size()]);
+	}
+
 	/**
 	 * 

* This method adds a plugin's commands to help and sets their executor. From daa7d29224089eccd8041a3c7333b7d58e4774ee Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sat, 29 Oct 2016 22:39:15 +0200 Subject: [PATCH 13/21] There's a relocated dependency --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 308183b..0c5e083 100644 --- a/pom.xml +++ b/pom.xml @@ -83,7 +83,7 @@ - org.apache.commons + commons-io commons-io 1.3.2 From 0b12aebfe2f6c6b99c6980029fbf8144766f6472 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sun, 30 Oct 2016 00:23:16 +0200 Subject: [PATCH 14/21] Fixed NPE on player data access --- src/main/java/buttondevteam/lib/TBMCPlayer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/buttondevteam/lib/TBMCPlayer.java b/src/main/java/buttondevteam/lib/TBMCPlayer.java index 65fe19d..f2c2c06 100644 --- a/src/main/java/buttondevteam/lib/TBMCPlayer.java +++ b/src/main/java/buttondevteam/lib/TBMCPlayer.java @@ -251,6 +251,7 @@ public class TBMCPlayer implements AutoCloseable { TBMCPlayer player = new TBMCPlayer(); player.uuid = p.getUniqueId(); player.data.putAll(yc.getValues(true)); + LoadedPlayers.put(p.getUniqueId(), player); // Accessing any value requires it to be in the map Bukkit.getLogger().info("Loaded player: " + player.getPlayerName()); if (player.getPlayerName() == null) { player.setPlayerName(p.getName()); @@ -268,7 +269,6 @@ public class TBMCPlayer implements AutoCloseable { player.setPlayerName(p.getName()); Bukkit.getLogger().info("Renaming done."); } - LoadedPlayers.put(p.getUniqueId(), player); // Load in other plugins Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerLoadEvent(yc, player)); @@ -282,8 +282,8 @@ public class TBMCPlayer implements AutoCloseable { public static TBMCPlayer addPlayer(OfflinePlayer p) { TBMCPlayer player = new TBMCPlayer(); player.uuid = p.getUniqueId(); + LoadedPlayers.put(p.getUniqueId(), player); // Accessing any value requires it to be in the map player.setPlayerName(p.getName()); - LoadedPlayers.put(p.getUniqueId(), player); Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerAddEvent(player)); savePlayer(player); return player; From 44109db61f12c3b9f07b165f5e36d1374fedfe7a Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sun, 30 Oct 2016 21:44:56 +0100 Subject: [PATCH 15/21] Added Enum data handling --- .../java/buttondevteam/lib/TBMCPlayer.java | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/src/main/java/buttondevteam/lib/TBMCPlayer.java b/src/main/java/buttondevteam/lib/TBMCPlayer.java index f2c2c06..66d568e 100644 --- a/src/main/java/buttondevteam/lib/TBMCPlayer.java +++ b/src/main/java/buttondevteam/lib/TBMCPlayer.java @@ -47,7 +47,7 @@ public class TBMCPlayer implements AutoCloseable { */ @SuppressWarnings("unchecked") protected T getData() { - StackTraceElement st = new Exception().getStackTrace()[0]; + StackTraceElement st = new Exception().getStackTrace()[1]; String mname = st.getMethodName(); if (!mname.startsWith("get")) throw new UnsupportedOperationException("Can only use getData from a getXYZ method"); @@ -77,6 +77,54 @@ public class TBMCPlayer implements AutoCloseable { LoadedPlayers.get(uuid).data.put(mname.substring("set".length()).toLowerCase(), value); } + /** + *

+ * Gets a player data entry for the caller plugin returning the desired type, which is an enum
+ * It will automatically determine the key and the return type.
+ * Usage: + *

+ * + *
+	 * {@code
+	 * public String getPlayerName() {
+	 * 	return getData();
+	 * }
+	 * 
+ * + * @return The value or null if not found + */ + protected > T getEnumData(Class cl) { + StackTraceElement st = new Exception().getStackTrace()[1]; + String mname = st.getMethodName(); + if (!mname.startsWith("get")) + throw new UnsupportedOperationException("Can only use getData from a getXYZ method"); + return Enum.valueOf(cl, + (String) LoadedPlayers.get(uuid).data.get(mname.substring("get".length()).toLowerCase())); + } + + /** + * Sets a player data entry based on the caller method
+ * Usage: + *

+ * + *
+	 * {@code
+	 * public String setPlayerName(String value) {
+	 * 	return setData(value);
+	 * }
+	 * 
+ * + * @param value + * The value to set + */ + protected void setEnumData(Enum value) { + StackTraceElement st = new Exception().getStackTrace()[0]; + String mname = st.getMethodName(); + if (!mname.startsWith("set")) + throw new UnsupportedOperationException("Can only use setData from a setXYZ method"); + LoadedPlayers.get(uuid).data.put(mname.substring("set".length()).toLowerCase(), value.toString()); + } + /** * Gets the player's Minecraft name * From be8685725cb56b1415b07d0d5194a1f1a372a5c4 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sun, 30 Oct 2016 22:57:59 +0100 Subject: [PATCH 16/21] Fixes IT WORKS! --- .../java/buttondevteam/lib/TBMCPlayer.java | 80 ++++++++++++++++--- 1 file changed, 71 insertions(+), 9 deletions(-) diff --git a/src/main/java/buttondevteam/lib/TBMCPlayer.java b/src/main/java/buttondevteam/lib/TBMCPlayer.java index 66d568e..26d78da 100644 --- a/src/main/java/buttondevteam/lib/TBMCPlayer.java +++ b/src/main/java/buttondevteam/lib/TBMCPlayer.java @@ -51,7 +51,10 @@ public class TBMCPlayer implements AutoCloseable { String mname = st.getMethodName(); if (!mname.startsWith("get")) throw new UnsupportedOperationException("Can only use getData from a getXYZ method"); - return (T) LoadedPlayers.get(uuid).data.get(mname.substring("get".length()).toLowerCase()); + Object ret = LoadedPlayers.get(uuid).data.get(mname.substring("get".length()).toLowerCase()); + if (Integer.class.isAssignableFrom(ret.getClass())) + throw new UnsupportedOperationException("For integers use getIntData()"); + return (T) ret; } /** @@ -86,8 +89,8 @@ public class TBMCPlayer implements AutoCloseable { * *
 	 * {@code
-	 * public String getPlayerName() {
-	 * 	return getData();
+	 * public String getSomeEnum() {
+	 * 	return getEnumData();
 	 * }
 	 * 
* @@ -97,9 +100,12 @@ public class TBMCPlayer implements AutoCloseable { StackTraceElement st = new Exception().getStackTrace()[1]; String mname = st.getMethodName(); if (!mname.startsWith("get")) - throw new UnsupportedOperationException("Can only use getData from a getXYZ method"); - return Enum.valueOf(cl, - (String) LoadedPlayers.get(uuid).data.get(mname.substring("get".length()).toLowerCase())); + throw new UnsupportedOperationException("Can only use getEnumData from a getXYZ method"); + final String retstr = (String) LoadedPlayers.get(uuid).data.get(mname.substring("get".length()).toLowerCase()); + if (retstr != null) + return Enum.valueOf(cl, retstr); + else + return null; } /** @@ -109,8 +115,8 @@ public class TBMCPlayer implements AutoCloseable { * *
 	 * {@code
-	 * public String setPlayerName(String value) {
-	 * 	return setData(value);
+	 * public String setSomeEnum(SomeEnum value) {
+	 * 	return setEnumData(value);
 	 * }
 	 * 
* @@ -121,10 +127,65 @@ public class TBMCPlayer implements AutoCloseable { StackTraceElement st = new Exception().getStackTrace()[0]; String mname = st.getMethodName(); if (!mname.startsWith("set")) - throw new UnsupportedOperationException("Can only use setData from a setXYZ method"); + throw new UnsupportedOperationException("Can only use setEnumData from a setXYZ method"); LoadedPlayers.get(uuid).data.put(mname.substring("set".length()).toLowerCase(), value.toString()); } + /** + *

+ * Gets a player data entry for the caller plugin returning the desired type, which is a number
+ * It will automatically determine the key and the return type.
+ * Usage: + *

+ * + *
+	 * {@code
+	 * public short getNumber() {
+	 * 	return getIntData();
+	 * }
+	 * 
+ * + * @return The value or null if not found + */ + @SuppressWarnings("unchecked") + protected T getIntData(Class cl) { + StackTraceElement st = new Exception().getStackTrace()[1]; + String mname = st.getMethodName(); + if (!mname.startsWith("get")) + throw new UnsupportedOperationException("Can only use getIntData from a getXYZ method"); + Object obj = LoadedPlayers.get(uuid).data.get(mname.substring("get".length()).toLowerCase()); + if (!(obj instanceof Integer)) + throw new UnsupportedOperationException("The retrieved object isn't a number: " + obj); + Integer int_ = (Integer) obj; + if (Short.class.isAssignableFrom(cl)) + return (T) (Object) int_.shortValue(); + else + return (T) (Object) int_; + } + + /** + * Sets a player data entry based on the caller method
+ * Usage: + *

+ * + *
+	 * {@code
+	 * public String setNumber(short value) {
+	 * 	return setIntData(value);
+	 * }
+	 * 
+ * + * @param value + * The value to set + */ + protected void setIntData(Number value) { + StackTraceElement st = new Exception().getStackTrace()[0]; + String mname = st.getMethodName(); + if (!mname.startsWith("set")) + throw new UnsupportedOperationException("Can only use setIntData from a setXYZ method"); + LoadedPlayers.get(uuid).data.put(mname.substring("set".length()).toLowerCase(), value); + } + /** * Gets the player's Minecraft name * @@ -167,6 +228,7 @@ public class TBMCPlayer implements AutoCloseable { T obj = null; try { obj = cl.newInstance(); + ((TBMCPlayer) obj).uuid = uuid; ((TBMCPlayer) obj).data.putAll(data); } catch (Exception e) { e.printStackTrace(); From a6477f5831e5b24e75f196486be13407786a3e04 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Mon, 31 Oct 2016 17:23:18 +0100 Subject: [PATCH 17/21] Added getLoadedPlayers --- .../java/buttondevteam/lib/TBMCPlayer.java | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/main/java/buttondevteam/lib/TBMCPlayer.java b/src/main/java/buttondevteam/lib/TBMCPlayer.java index 26d78da..22c0564 100644 --- a/src/main/java/buttondevteam/lib/TBMCPlayer.java +++ b/src/main/java/buttondevteam/lib/TBMCPlayer.java @@ -51,7 +51,7 @@ public class TBMCPlayer implements AutoCloseable { String mname = st.getMethodName(); if (!mname.startsWith("get")) throw new UnsupportedOperationException("Can only use getData from a getXYZ method"); - Object ret = LoadedPlayers.get(uuid).data.get(mname.substring("get".length()).toLowerCase()); + Object ret = getLoadedPlayers().get(uuid).data.get(mname.substring("get".length()).toLowerCase()); if (Integer.class.isAssignableFrom(ret.getClass())) throw new UnsupportedOperationException("For integers use getIntData()"); return (T) ret; @@ -77,7 +77,7 @@ public class TBMCPlayer implements AutoCloseable { String mname = st.getMethodName(); if (!mname.startsWith("set")) throw new UnsupportedOperationException("Can only use setData from a setXYZ method"); - LoadedPlayers.get(uuid).data.put(mname.substring("set".length()).toLowerCase(), value); + getLoadedPlayers().get(uuid).data.put(mname.substring("set".length()).toLowerCase(), value); } /** @@ -101,7 +101,7 @@ public class TBMCPlayer implements AutoCloseable { String mname = st.getMethodName(); if (!mname.startsWith("get")) throw new UnsupportedOperationException("Can only use getEnumData from a getXYZ method"); - final String retstr = (String) LoadedPlayers.get(uuid).data.get(mname.substring("get".length()).toLowerCase()); + final String retstr = (String) getLoadedPlayers().get(uuid).data.get(mname.substring("get".length()).toLowerCase()); if (retstr != null) return Enum.valueOf(cl, retstr); else @@ -128,7 +128,7 @@ public class TBMCPlayer implements AutoCloseable { String mname = st.getMethodName(); if (!mname.startsWith("set")) throw new UnsupportedOperationException("Can only use setEnumData from a setXYZ method"); - LoadedPlayers.get(uuid).data.put(mname.substring("set".length()).toLowerCase(), value.toString()); + getLoadedPlayers().get(uuid).data.put(mname.substring("set".length()).toLowerCase(), value.toString()); } /** @@ -153,7 +153,7 @@ public class TBMCPlayer implements AutoCloseable { String mname = st.getMethodName(); if (!mname.startsWith("get")) throw new UnsupportedOperationException("Can only use getIntData from a getXYZ method"); - Object obj = LoadedPlayers.get(uuid).data.get(mname.substring("get".length()).toLowerCase()); + Object obj = getLoadedPlayers().get(uuid).data.get(mname.substring("get".length()).toLowerCase()); if (!(obj instanceof Integer)) throw new UnsupportedOperationException("The retrieved object isn't a number: " + obj); Integer int_ = (Integer) obj; @@ -183,7 +183,7 @@ public class TBMCPlayer implements AutoCloseable { String mname = st.getMethodName(); if (!mname.startsWith("set")) throw new UnsupportedOperationException("Can only use setIntData from a setXYZ method"); - LoadedPlayers.get(uuid).data.put(mname.substring("set".length()).toLowerCase(), value); + getLoadedPlayers().get(uuid).data.put(mname.substring("set".length()).toLowerCase(), value); } /** @@ -280,8 +280,8 @@ public class TBMCPlayer implements AutoCloseable { * @return The {@link TBMCPlayer} object for the player */ public static TBMCPlayer getPlayer(OfflinePlayer p) { - if (TBMCPlayer.LoadedPlayers.containsKey(p.getUniqueId())) - return TBMCPlayer.LoadedPlayers.get(p.getUniqueId()); + if (TBMCPlayer.getLoadedPlayers().containsKey(p.getUniqueId())) + return TBMCPlayer.getLoadedPlayers().get(p.getUniqueId()); else return TBMCPlayer.loadPlayer(p); } @@ -303,8 +303,8 @@ public class TBMCPlayer implements AutoCloseable { * @return The {@link TBMCPlayer} object for the player */ public static TBMCPlayer getPlayer(UUID uuid) { - if (TBMCPlayer.LoadedPlayers.containsKey(uuid)) - return TBMCPlayer.LoadedPlayers.get(uuid); + if (TBMCPlayer.getLoadedPlayers().containsKey(uuid)) + return TBMCPlayer.getLoadedPlayers().get(uuid); else return TBMCPlayer.loadPlayer(Bukkit.getOfflinePlayer(uuid)); } @@ -343,8 +343,8 @@ public class TBMCPlayer implements AutoCloseable { * Only intended to use from ButtonCore */ public static TBMCPlayer loadPlayer(OfflinePlayer p) { - if (LoadedPlayers.containsKey(p.getUniqueId())) - return LoadedPlayers.get(p.getUniqueId()); + if (getLoadedPlayers().containsKey(p.getUniqueId())) + return getLoadedPlayers().get(p.getUniqueId()); File file = new File(TBMC_PLAYERS_DIR); file.mkdirs(); file = new File(TBMC_PLAYERS_DIR, p.getUniqueId().toString() + ".yml"); @@ -361,7 +361,7 @@ public class TBMCPlayer implements AutoCloseable { TBMCPlayer player = new TBMCPlayer(); player.uuid = p.getUniqueId(); player.data.putAll(yc.getValues(true)); - LoadedPlayers.put(p.getUniqueId(), player); // Accessing any value requires it to be in the map + getLoadedPlayers().put(p.getUniqueId(), player); // Accessing any value requires it to be in the map Bukkit.getLogger().info("Loaded player: " + player.getPlayerName()); if (player.getPlayerName() == null) { player.setPlayerName(p.getName()); @@ -392,7 +392,7 @@ public class TBMCPlayer implements AutoCloseable { public static TBMCPlayer addPlayer(OfflinePlayer p) { TBMCPlayer player = new TBMCPlayer(); player.uuid = p.getUniqueId(); - LoadedPlayers.put(p.getUniqueId(), player); // Accessing any value requires it to be in the map + getLoadedPlayers().put(p.getUniqueId(), player); // Accessing any value requires it to be in the map player.setPlayerName(p.getName()); Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerAddEvent(player)); savePlayer(player); @@ -418,7 +418,7 @@ public class TBMCPlayer implements AutoCloseable { * Only intended to use from ButtonCore */ public static void joinPlayer(TBMCPlayer player) { - LoadedPlayers.put(player.uuid, player); + getLoadedPlayers().put(player.uuid, player); Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerJoinEvent(player)); } @@ -426,7 +426,7 @@ public class TBMCPlayer implements AutoCloseable { * Only intended to use from ButtonCore */ public static void quitPlayer(TBMCPlayer player) { - LoadedPlayers.remove(player.uuid); + getLoadedPlayers().remove(player.uuid); Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerQuitEvent(player)); } @@ -438,6 +438,10 @@ public class TBMCPlayer implements AutoCloseable { @Override public void close() throws Exception { if (!Bukkit.getPlayer(uuid).isOnline()) - LoadedPlayers.remove(uuid); + getLoadedPlayers().remove(uuid); + } + + public static HashMap getLoadedPlayers() { + return LoadedPlayers; } } From 076ee4ffd0dd3041b8c40d1c35dd22533442fd4e Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Mon, 31 Oct 2016 17:35:19 +0100 Subject: [PATCH 18/21] Fixed a stack trace index --- src/main/java/buttondevteam/lib/TBMCPlayer.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/buttondevteam/lib/TBMCPlayer.java b/src/main/java/buttondevteam/lib/TBMCPlayer.java index 22c0564..5deb51f 100644 --- a/src/main/java/buttondevteam/lib/TBMCPlayer.java +++ b/src/main/java/buttondevteam/lib/TBMCPlayer.java @@ -73,7 +73,7 @@ public class TBMCPlayer implements AutoCloseable { * The value to set */ protected void setData(Object value) { - StackTraceElement st = new Exception().getStackTrace()[0]; + StackTraceElement st = new Exception().getStackTrace()[1]; String mname = st.getMethodName(); if (!mname.startsWith("set")) throw new UnsupportedOperationException("Can only use setData from a setXYZ method"); @@ -124,7 +124,7 @@ public class TBMCPlayer implements AutoCloseable { * The value to set */ protected void setEnumData(Enum value) { - StackTraceElement st = new Exception().getStackTrace()[0]; + StackTraceElement st = new Exception().getStackTrace()[1]; String mname = st.getMethodName(); if (!mname.startsWith("set")) throw new UnsupportedOperationException("Can only use setEnumData from a setXYZ method"); @@ -179,7 +179,7 @@ public class TBMCPlayer implements AutoCloseable { * The value to set */ protected void setIntData(Number value) { - StackTraceElement st = new Exception().getStackTrace()[0]; + StackTraceElement st = new Exception().getStackTrace()[1]; String mname = st.getMethodName(); if (!mname.startsWith("set")) throw new UnsupportedOperationException("Can only use setIntData from a setXYZ method"); From 347c6d40a488a46355070e177cc5bc7d3d70e071 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Tue, 1 Nov 2016 21:13:12 +0100 Subject: [PATCH 19/21] Added getInfo method and an event for it --- .../java/buttondevteam/lib/TBMCPlayer.java | 20 ++++- .../lib/TBMCPlayerGetInfoEvent.java | 73 +++++++++++++++++++ 2 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 src/main/java/buttondevteam/lib/TBMCPlayerGetInfoEvent.java diff --git a/src/main/java/buttondevteam/lib/TBMCPlayer.java b/src/main/java/buttondevteam/lib/TBMCPlayer.java index 5deb51f..a6e6118 100644 --- a/src/main/java/buttondevteam/lib/TBMCPlayer.java +++ b/src/main/java/buttondevteam/lib/TBMCPlayer.java @@ -101,7 +101,8 @@ public class TBMCPlayer implements AutoCloseable { String mname = st.getMethodName(); if (!mname.startsWith("get")) throw new UnsupportedOperationException("Can only use getEnumData from a getXYZ method"); - final String retstr = (String) getLoadedPlayers().get(uuid).data.get(mname.substring("get".length()).toLowerCase()); + final String retstr = (String) getLoadedPlayers().get(uuid).data + .get(mname.substring("get".length()).toLowerCase()); if (retstr != null) return Enum.valueOf(cl, retstr); else @@ -444,4 +445,21 @@ public class TBMCPlayer implements AutoCloseable { public static HashMap getLoadedPlayers() { return LoadedPlayers; } + + /** + * Get player information. This method calls the {@link TBMCPlayerGetInfoEvent} to get all the player information across the TBMC plugins. + * + * @param target + * The {@link InfoTarget} to return the info for. + * @return The player information. + */ + public String getInfo(InfoTarget target) { + TBMCPlayerGetInfoEvent event = new TBMCPlayerGetInfoEvent(this, target); + Bukkit.getServer().getPluginManager().callEvent(event); + return event.getResult(); + } + + public enum InfoTarget { + MCHover, MCCommand, Discord + } } diff --git a/src/main/java/buttondevteam/lib/TBMCPlayerGetInfoEvent.java b/src/main/java/buttondevteam/lib/TBMCPlayerGetInfoEvent.java new file mode 100644 index 0000000..6dac56d --- /dev/null +++ b/src/main/java/buttondevteam/lib/TBMCPlayerGetInfoEvent.java @@ -0,0 +1,73 @@ +package buttondevteam.lib; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import buttondevteam.lib.TBMCPlayer.InfoTarget; + +/** + *

+ * This event gets called when player information is requested. It can be used to give more per-plugin information about a player. + *

+ * + * @author Norbi + * + */ +public class TBMCPlayerGetInfoEvent extends Event { + private static final HandlerList handlers = new HandlerList(); + + private TBMCPlayer player; + private List infolines; + private TBMCPlayer.InfoTarget target; + + TBMCPlayerGetInfoEvent(TBMCPlayer player, TBMCPlayer.InfoTarget target) { + this.player = player; + infolines = new ArrayList<>(); + this.target = target; + } + + /** + * Get the {@link TBMCPlayer} object + * + * @return A player object + */ + public TBMCPlayer getPlayer() { + return player; + } + + /** + * Add a line to the information text. The line should be in the format of key: value . + * + * @param infoline + * The line to add + */ + public void addInfo(String infoline) { + infolines.add(infoline); + } + + /** + * Get the {@link InfoTarget} we want the information for. Use this to format the returned string. + * + * @return The target of the information. + */ + public TBMCPlayer.InfoTarget getTarget() { + return target; + } + + String getResult() { + return infolines.stream().collect(Collectors.joining("\n")); + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} From e6179f447fb7ada0cb2ccfb490cba34c5671f50f Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Tue, 1 Nov 2016 22:22:50 +0100 Subject: [PATCH 20/21] Removed throws declaration --- src/main/java/buttondevteam/lib/TBMCPlayer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/buttondevteam/lib/TBMCPlayer.java b/src/main/java/buttondevteam/lib/TBMCPlayer.java index a6e6118..a15f266 100644 --- a/src/main/java/buttondevteam/lib/TBMCPlayer.java +++ b/src/main/java/buttondevteam/lib/TBMCPlayer.java @@ -437,7 +437,7 @@ public class TBMCPlayer implements AutoCloseable { * Therefore, the recommended use is to call it when using {@link #GetPlayer} or use try-with-resources. */ @Override - public void close() throws Exception { + public void close() { if (!Bukkit.getPlayer(uuid).isOnline()) getLoadedPlayers().remove(uuid); } From 77aca9d5c17322eac7af4fe57b3b8d4bd74874bb Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Tue, 1 Nov 2016 22:47:46 +0100 Subject: [PATCH 21/21] Moved SendException --- .../java/buttondevteam/lib/TBMCCoreAPI.java | 11 +++- .../buttondevteam/lib/TBMCExceptionEvent.java | 57 +++++++++++++++++++ 2 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 src/main/java/buttondevteam/lib/TBMCExceptionEvent.java diff --git a/src/main/java/buttondevteam/lib/TBMCCoreAPI.java b/src/main/java/buttondevteam/lib/TBMCCoreAPI.java index b544c72..44da4df 100644 --- a/src/main/java/buttondevteam/lib/TBMCCoreAPI.java +++ b/src/main/java/buttondevteam/lib/TBMCCoreAPI.java @@ -44,9 +44,8 @@ public final class TBMCCoreAPI { String ret = ""; URL url; try { - url = new URL("https://jitpack.io/com/github/TBMCPlugins/" - + correctname + "/master-SNAPSHOT/" - + correctname + "-master-SNAPSHOT.jar"); // ButtonLib exception not required, not a separate plugin + url = new URL("https://jitpack.io/com/github/TBMCPlugins/" + correctname + "/master-SNAPSHOT/" + correctname + + "-master-SNAPSHOT.jar"); // ButtonLib exception not required, not a separate plugin FileUtils.copyURLToFile(url, new File("plugins/" + correctname + ".jar")); } catch (FileNotFoundException e) { ret = "Can't find JAR, the build probably failed. Build log (scroll to bottom):\nhttps://jitpack.io/com/github/TBMCPlugins/" @@ -91,4 +90,10 @@ public final class TBMCCoreAPI { in.close(); return body; } + + public static void SendException(String sourcemsg, Exception e) { + Bukkit.getPluginManager().callEvent(new TBMCExceptionEvent(sourcemsg, e)); + Bukkit.getLogger().warning(sourcemsg); + e.printStackTrace(); + } } diff --git a/src/main/java/buttondevteam/lib/TBMCExceptionEvent.java b/src/main/java/buttondevteam/lib/TBMCExceptionEvent.java new file mode 100644 index 0000000..ec7f11d --- /dev/null +++ b/src/main/java/buttondevteam/lib/TBMCExceptionEvent.java @@ -0,0 +1,57 @@ +package buttondevteam.lib; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import buttondevteam.lib.TBMCPlayer.InfoTarget; + +/** + *

+ * This event gets called (ideally) each time an exception occurs in a TBMC plugin. To call it, use {@link TBMCCoreAPI#SendException(String, Exception)}. + *

+ * + * @author Norbi + * + */ +public class TBMCExceptionEvent extends Event { + private static final HandlerList handlers = new HandlerList(); + + private String sourcemsg; + private Exception exception; + + TBMCExceptionEvent(String sourcemsg, Exception exception) { + this.sourcemsg = sourcemsg; + this.exception = exception; + } + + /** + * Gets the source message (where did this exception occur, etc.) + * + * @return The message + */ + public String getSourceMessage() { + return sourcemsg; + } + + /** + * Gets the exception + * + * @return The exception + */ + public Exception getException() { + return exception; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +}