From 5e4128afe73699406547e84777c8680d6a3ad892 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Mon, 23 Jan 2017 20:54:43 +0100 Subject: [PATCH] Moved the last bits over and deleted old class --- .../java/buttondevteam/core/MainPlugin.java | 8 +- .../buttondevteam/lib/player/TBMCPlayer.java | 510 ------------------ .../lib/player/TBMCPlayerBase.java | 66 ++- .../lib/player/TBMCPlayerGetInfoEvent.java | 12 +- .../lib/player/TBMCPlayerSaveEvent.java | 1 - 5 files changed, 70 insertions(+), 527 deletions(-) delete mode 100644 src/main/java/buttondevteam/lib/player/TBMCPlayer.java diff --git a/src/main/java/buttondevteam/core/MainPlugin.java b/src/main/java/buttondevteam/core/MainPlugin.java index c084692..c09b698 100644 --- a/src/main/java/buttondevteam/core/MainPlugin.java +++ b/src/main/java/buttondevteam/core/MainPlugin.java @@ -1,7 +1,5 @@ package buttondevteam.core; -import java.util.Map.Entry; -import java.util.UUID; import java.util.logging.Logger; import org.bukkit.plugin.PluginDescriptionFile; @@ -10,7 +8,7 @@ import org.bukkit.plugin.java.JavaPlugin; import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.chat.TBMCChatAPI; -import buttondevteam.lib.player.TBMCPlayer; +import buttondevteam.lib.player.TBMCPlayerBase; import net.milkbowl.vault.permission.Permission; public class MainPlugin extends JavaPlugin { @@ -39,9 +37,7 @@ public class MainPlugin extends JavaPlugin { @Override public void onDisable() { logger.info("Saving player data..."); - for (Entry entry : TBMCPlayer.getLoadedPlayers().entrySet()) { - TBMCPlayer.savePlayer(entry.getValue()); - } + TBMCPlayerBase.savePlayers(); logger.info("Player data saved."); } diff --git a/src/main/java/buttondevteam/lib/player/TBMCPlayer.java b/src/main/java/buttondevteam/lib/player/TBMCPlayer.java deleted file mode 100644 index 954027b..0000000 --- a/src/main/java/buttondevteam/lib/player/TBMCPlayer.java +++ /dev/null @@ -1,510 +0,0 @@ -package buttondevteam.lib.player; - -import java.io.File; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map.Entry; -import java.util.Optional; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; - -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 - *

- *

- * Use {@link #asPluginPlayer(Class)} to get plugin-specific data - *

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

- * 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()[1]; - String mname = st.getMethodName(); - if (!mname.startsWith("get")) - throw new UnsupportedOperationException("Can only use getData from a getXYZ method"); - Object ret = getLoadedPlayers().get(uuid).data.get(mname.substring("get".length()).toLowerCase()); - if (ret != null && Integer.class.isAssignableFrom(ret.getClass())) - throw new UnsupportedOperationException("For integers use getIntData()"); - if (ret != null && Boolean.class.isAssignableFrom(ret.getClass())) - throw new UnsupportedOperationException("For booleans use getBoolData()"); - return (T) ret; - } - - /** - * 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()[1]; - String mname = st.getMethodName(); - if (!mname.startsWith("set")) - throw new UnsupportedOperationException("Can only use setData from a setXYZ method"); - getLoadedPlayers().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 getSomeEnum() {
-	 * 	return getEnumData();
-	 * }
-	 * 
- * - * @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 getEnumData from a getXYZ method"); - final String retstr = (String) getLoadedPlayers().get(uuid).data - .get(mname.substring("get".length()).toLowerCase()); - if (retstr != null) - return Enum.valueOf(cl, retstr); - else - return null; - } - - /** - * Sets a player data entry based on the caller method
- * Usage: - *

- * - *
-	 * {@code
-	 * public String setSomeEnum(SomeEnum value) {
-	 * 	return setEnumData(value);
-	 * }
-	 * 
- * - * @param value - * The value to set - */ - protected void setEnumData(Enum value) { - 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"); - getLoadedPlayers().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 Optional 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 = getLoadedPlayers().get(uuid).data.get(mname.substring("get".length()).toLowerCase()); - if (obj == null) - return Optional.empty(); - if (obj instanceof Short) - return Optional.of((T) obj); - if (!(Integer.class.isAssignableFrom(obj.getClass()))) - throw new UnsupportedOperationException("The retrieved object isn't an integer: " + obj); - Integer int_ = (Integer) obj; - if (Short.class.isAssignableFrom(cl)) - return Optional.of((T) (Object) int_.shortValue()); - else - return Optional.of((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()[1]; - String mname = st.getMethodName(); - if (!mname.startsWith("set")) - throw new UnsupportedOperationException("Can only use setIntData from a setXYZ method"); - getLoadedPlayers().get(uuid).data.put(mname.substring("set".length()).toLowerCase(), value); - } - - /** - *

- * Gets a player data entry for the caller plugin returning a boolean.
- * Usage: - *

- * - *
-	 * {@code
-	 * public String getFlairCheater() {
-	 * 	return getBoolData();
-	 * }
-	 * 
- * - * @return The value or false if not found - */ - protected boolean getBoolData() { - 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"); - Object ret = getLoadedPlayers().get(uuid).data.get(mname.substring("get".length()).toLowerCase()); - if (ret != null && !Boolean.class.isAssignableFrom(ret.getClass())) - throw new UnsupportedOperationException("Not a boolean!"); - if (ret == null) - return false; - return (boolean) ret; - } - - /** - * 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; - } - - private ConcurrentHashMap, TBMCPlayer> playermap = new ConcurrentHashMap<>(); // TODO - - /** - * Gets the TBMCPlayer object as a specific plugin player, keeping it's data * - * - * @param p - * Player to get - * @param cl - * The TBMCPlayer subclass - */ - @SuppressWarnings("unchecked") - public T asPluginPlayer(Class cl) { - T obj = null; - if (playermap.containsKey(cl)) - return (T) playermap.get(cl); - try { - obj = cl.newInstance(); - ((TBMCPlayer) obj).uuid = uuid; - // ((TBMCPlayer) obj).data.putAll(data); - playermap.put(cl, obj); - } catch (Exception e) { - e.printStackTrace(); - } - return obj; - } - - 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) { - @SuppressWarnings("deprecation") - OfflinePlayer p = Bukkit.getOfflinePlayer(name); - if (p != null) - 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.getLoadedPlayers().containsKey(p.getUniqueId())) - return TBMCPlayer.getLoadedPlayers().get(p.getUniqueId()); - else - return TBMCPlayer.loadPlayer(p); - } - - /** - * 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: - * - *
-	 * {@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.getLoadedPlayers().containsKey(uuid)) - return TBMCPlayer.getLoadedPlayers().get(uuid); - else - 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 T 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 T getPlayerAs(UUID uuid, Class cl) { - return getPlayer(uuid).asPluginPlayer(cl); - } - - /** - * Only intended to use from ButtonCore - */ - public static TBMCPlayer loadPlayer(OfflinePlayer p) { - 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"); - 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.data.putAll(yc.getValues(true)); - 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()); - 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.getPlayerName()); - if (resident == null) - Bukkit.getLogger().warning("Resident not found - couldn't rename in Towny."); - else if (tu.getResidentMap().contains(p.getName())) - Bukkit.getLogger().warning("Target resident name is already in use."); // TODO: Handle - else - resident.setName(p.getName()); - player.setPlayerName(p.getName()); - Bukkit.getLogger().info("Renaming done."); - } - - // Load in other plugins - Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerLoadEvent(yc, player)); - return player; - } - } - - /** - * Only intended to use from ButtonCore - */ - public static TBMCPlayer addPlayer(OfflinePlayer p) { - TBMCPlayer player = new TBMCPlayer(); - player.uuid = p.getUniqueId(); - 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); - return player; - } - - /** - * Only intended to use from ButtonCore - */ - public static void savePlayer(TBMCPlayer player) { - YamlConfiguration yc = new YamlConfiguration(); - 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"); - } catch (IOException e) { - new Exception("Failed to save player data for " + player.getPlayerName(), e).printStackTrace(); - } - } - - /** - * Only intended to use from ButtonCore - */ - public static void joinPlayer(TBMCPlayer player) { - getLoadedPlayers().put(player.uuid, player); - Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerJoinEvent(player)); - } - - /** - * Only intended to use from ButtonCore - */ - public static void quitPlayer(TBMCPlayer player) { - Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerQuitEvent(player)); - getLoadedPlayers().remove(player.uuid); - } - - /** - * 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() { - final Player player = Bukkit.getPlayer(uuid); - if (player == null || !player.isOnline()) - getLoadedPlayers().remove(uuid); - } - - 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/player/TBMCPlayerBase.java b/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.java index bfc56ab..d66efc2 100644 --- a/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.java +++ b/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.java @@ -71,10 +71,9 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase { static final ConcurrentHashMap playermap = new ConcurrentHashMap<>(); /** - * 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
+ * Make sure to use try-with-resources with this to save the data, as it may need to load the file * - * @param p - * Player to get * @param cl * The TBMCPlayer subclass */ @@ -85,7 +84,7 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase { /** * Only intended to use from ButtonCore */ - public static T loadPlayer(OfflinePlayer p, Class cl) { + public static T loadPlayer(OfflinePlayer p, Class cl) { // TODO: Load player files and get player classes backed by the YAML T player = getPlayer(p.getUniqueId(), cl); Bukkit.getLogger().info("Loaded player: " + player.getPlayerName()); if (player.getPlayerName() == null) { @@ -142,5 +141,64 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase { public static void quitPlayer(TBMCPlayerBase player) { Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerQuitEvent(player)); playermap.remove(player.uuid + "-" + player.getFolder()); + try { + player.close(); + } catch (Exception e) { + TBMCCoreAPI.SendException("Error while saving quitting player " + player.getPlayerName() + " (" + + player.getFolder() + "/" + player.getFileName() + ")!", e); + } + } + + public static void savePlayers() { + playermap.values().stream().forEach(p -> { + try { + p.close(); + } catch (Exception e) { + TBMCCoreAPI.SendException("Error while saving player " + p.getPlayerName() + " (" + p.getFolder() + "/" + + p.getFileName() + ")!", e); + } + }); + } + + /** + * 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 T getFromName(String name, Class cl) { + @SuppressWarnings("deprecation") + OfflinePlayer p = Bukkit.getOfflinePlayer(name); + if (p != null) + return getPlayer(p.getUniqueId(), cl); + else + return null; + } + + /** + * 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/player/TBMCPlayerGetInfoEvent.java b/src/main/java/buttondevteam/lib/player/TBMCPlayerGetInfoEvent.java index b8e5b5e..ba2bc74 100644 --- a/src/main/java/buttondevteam/lib/player/TBMCPlayerGetInfoEvent.java +++ b/src/main/java/buttondevteam/lib/player/TBMCPlayerGetInfoEvent.java @@ -7,7 +7,7 @@ import java.util.stream.Collectors; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; -import buttondevteam.lib.player.TBMCPlayer.InfoTarget; +import buttondevteam.lib.player.TBMCPlayerBase.InfoTarget; /** *

@@ -20,11 +20,11 @@ import buttondevteam.lib.player.TBMCPlayer.InfoTarget; public class TBMCPlayerGetInfoEvent extends Event { private static final HandlerList handlers = new HandlerList(); - private TBMCPlayer player; + private TBMCPlayerBase player; private List infolines; - private TBMCPlayer.InfoTarget target; + private InfoTarget target; - TBMCPlayerGetInfoEvent(TBMCPlayer player, TBMCPlayer.InfoTarget target) { + TBMCPlayerGetInfoEvent(TBMCPlayerBase player, InfoTarget target) { this.player = player; infolines = new ArrayList<>(); this.target = target; @@ -35,7 +35,7 @@ public class TBMCPlayerGetInfoEvent extends Event { * * @return A player object */ - public TBMCPlayer getPlayer() { + public TBMCPlayerBase getPlayer() { return player; } @@ -54,7 +54,7 @@ public class TBMCPlayerGetInfoEvent extends Event { * * @return The target of the information. */ - public TBMCPlayer.InfoTarget getTarget() { + public InfoTarget getTarget() { return target; } diff --git a/src/main/java/buttondevteam/lib/player/TBMCPlayerSaveEvent.java b/src/main/java/buttondevteam/lib/player/TBMCPlayerSaveEvent.java index 67b74a8..2f4ea4c 100644 --- a/src/main/java/buttondevteam/lib/player/TBMCPlayerSaveEvent.java +++ b/src/main/java/buttondevteam/lib/player/TBMCPlayerSaveEvent.java @@ -1,6 +1,5 @@ package buttondevteam.lib.player; -import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.event.Event; import org.bukkit.event.HandlerList;