diff --git a/src/dev/w1zzrd/invtweaks/DataStore.java b/src/dev/w1zzrd/invtweaks/DataStore.java index 2077c8f..911cc91 100644 --- a/src/dev/w1zzrd/invtweaks/DataStore.java +++ b/src/dev/w1zzrd/invtweaks/DataStore.java @@ -12,6 +12,9 @@ import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; +/** + * Manager for persistent data storage for a plugin + */ public class DataStore { private static final Logger logger = Bukkit.getLogger(); @@ -19,6 +22,11 @@ public class DataStore { private final File storeFile; private final FileConfiguration config; + /** + * Create a data store with the given name. This will attempt to load a yaml file named after the store + * @param storeName Name of the store to load. File will be named storeName + ".yml" + * @param plugin Plugin to associate the data store with + */ public DataStore(final String storeName, final Plugin plugin) { storeFile = new File(plugin.getDataFolder(), storeName + ".yml"); config = YamlConfiguration.loadConfiguration(storeFile); @@ -27,15 +35,31 @@ public class DataStore { saveData(); } + /** + * Load a value from the data store + * @param path Path in the file to load the data from + * @param defaultValue Getter for a default value, in case the data does not exist in the store + * @param Type of the data to load + * @return Data at the given path, if available, else the default value + */ public T loadData(final String path, final DefaultGetter defaultValue) { final T value = (T) config.get(path); return value == null ? defaultValue.get() : value; } + /** + * Save data at a given path in the store + * @param path Path to store data at + * @param value Data to store + * @param Type of {@link ConfigurationSerializable} data to store + */ public void storeData(final String path, final T value) { config.set(path, value); } + /** + * Save the current data store in memory to persistent memory + */ public void saveData() { try { config.save(storeFile); @@ -44,6 +68,9 @@ public class DataStore { } } + /** + * Reload data store from persistent memory, overwriting any current state + */ public void loadData() { try { config.load(storeFile); @@ -57,6 +84,10 @@ public class DataStore { * @param Type to construct */ public interface DefaultGetter { + /** + * Instantiate default value + * @return Default value that was instantiated + */ T get(); } } diff --git a/src/dev/w1zzrd/invtweaks/InvTweaksPlugin.java b/src/dev/w1zzrd/invtweaks/InvTweaksPlugin.java index 5262ed7..714e677 100644 --- a/src/dev/w1zzrd/invtweaks/InvTweaksPlugin.java +++ b/src/dev/w1zzrd/invtweaks/InvTweaksPlugin.java @@ -63,6 +63,10 @@ public final class InvTweaksPlugin extends JavaPlugin { magnetCommandExecutor.reloadConfig(); } + /** + * Get a reference to the persistent data store object for this plugin + * @return An instance of {@link DataStore} for this plugin + */ public DataStore getPersistentData() { return data; } @@ -108,18 +112,31 @@ public final class InvTweaksPlugin extends JavaPlugin { HandlerList.unregisterAll(this); } + /** + * Register type serializers/deserializers for configurations and YAML files + * + * @see #unregisterSerializers() + */ private void registerSerializers() { ConfigurationSerialization.registerClass(MagnetConfig.class); ConfigurationSerialization.registerClass(MagnetData.class); ConfigurationSerialization.registerClass(UUIDList.class); } + /** + * Unregister type serializers/deserializers for configurations and YAML files + * + * @see #registerSerializers() + */ private void unregisterSerializers() { ConfigurationSerialization.unregisterClass(MagnetConfig.class); ConfigurationSerialization.unregisterClass(MagnetData.class); ConfigurationSerialization.unregisterClass(UUIDList.class); } + /** + * Initialize persistent data storage sources and handlers + */ private void enablePersistentData() { registerSerializers(); @@ -131,6 +148,9 @@ public final class InvTweaksPlugin extends JavaPlugin { data = new DataStore(PERSISTENT_DATA_NAME, this); } + /** + * De-activate and finalize persistent data storage sources and handlers + */ private void disablePersistentData() { data.saveData(); data = null; diff --git a/src/dev/w1zzrd/invtweaks/command/MagnetCommandExecutor.java b/src/dev/w1zzrd/invtweaks/command/MagnetCommandExecutor.java index c7bb9d6..ded4cda 100644 --- a/src/dev/w1zzrd/invtweaks/command/MagnetCommandExecutor.java +++ b/src/dev/w1zzrd/invtweaks/command/MagnetCommandExecutor.java @@ -15,7 +15,6 @@ import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitTask; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.UUID; import java.util.logging.Logger; @@ -241,20 +240,36 @@ public class MagnetCommandExecutor implements CommandExecutor { divIndex = (divIndex + 1) % subdivide; } + /** + * Event handler for when a potential magnet player logs out + * @param magnet Player to check magnet state for + */ public void onMagnetLogout(final UUID magnet) { if (magnetData.removeLogoutOnline(magnet)) updateMagnetismTask(true); } + /** + * Event handler for when a potential magnet player logs in + * @param magnet Player to check magnet state for + */ public void onMagnetLogin(final UUID magnet) { if (magnetData.addLoginOnline(magnet)) updateMagnetismTask(false); } + /** + * Event handler for saving magnet data to persistent data store + */ public void onDisable() { data.storeData("magnets", magnetData); } + /** + * Load magnet configuration data for given plugin + * @param plugin Plugin for which to load configuration for + * @return Configuration from persistent data if available, else default configuration values + */ private static MagnetConfig loadConfig(final Plugin plugin) { return (MagnetConfig) plugin.getConfig().get( CONFIG_PATH, diff --git a/src/dev/w1zzrd/invtweaks/listener/MagnetismListener.java b/src/dev/w1zzrd/invtweaks/listener/MagnetismListener.java index 2c43663..c578698 100644 --- a/src/dev/w1zzrd/invtweaks/listener/MagnetismListener.java +++ b/src/dev/w1zzrd/invtweaks/listener/MagnetismListener.java @@ -8,10 +8,17 @@ import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerKickEvent; import org.bukkit.event.player.PlayerQuitEvent; +/** + * Event listener for enabling/disabling magnet task state + */ public class MagnetismListener implements Listener { private final MagnetCommandExecutor magnetCommandExecutor; + /** + * Create a new listener for the given executor + * @param magnetCommandExecutor Command handler to track events for + */ public MagnetismListener(final MagnetCommandExecutor magnetCommandExecutor) { this.magnetCommandExecutor = magnetCommandExecutor; } @@ -31,11 +38,11 @@ public class MagnetismListener implements Listener { onLeave(event.getPlayer()); } + /** + * Unified handler for when a player disconnects from the server + * @param player Player that has disconnected + */ private void onLeave(final Player player) { magnetCommandExecutor.onMagnetLogout(player.getUniqueId()); } - - private boolean shouldNotifyExecutor(final Player player) { - return magnetCommandExecutor.isMagnet(player); - } } diff --git a/src/dev/w1zzrd/invtweaks/listener/StackReplaceListener.java b/src/dev/w1zzrd/invtweaks/listener/StackReplaceListener.java index 0fef489..6b07e44 100644 --- a/src/dev/w1zzrd/invtweaks/listener/StackReplaceListener.java +++ b/src/dev/w1zzrd/invtweaks/listener/StackReplaceListener.java @@ -19,6 +19,9 @@ import static dev.w1zzrd.invtweaks.InvTweaksPlugin.LOG_PLUGIN_NAME; */ public class StackReplaceListener implements Listener { + /** + * Max index for main player inventory + */ private static final int MAX_MAIN_INV = 35; @@ -48,6 +51,15 @@ public class StackReplaceListener implements Listener { logger.fine(LOG_PLUGIN_NAME + " Moved tool into empty hand for player " + event.getPlayer().getName()); } + /** + * Attempt to find and move a similar stack in the inventory to the one given, using the supplied comparison + * function + * @param usedItemStack Stack to find a replacement for + * @param target Inventory slot to move stack to + * @param inventory Inventory to search for similar items in + * @param compareFunc Function to use when determining similarity between stacks + * @return True if a similar stack was found and moved, else false + */ private boolean findAndMoveSimilarStack( final ItemStack usedItemStack, final EquipmentSlot target, diff --git a/src/dev/w1zzrd/invtweaks/serialization/MagnetConfig.java b/src/dev/w1zzrd/invtweaks/serialization/MagnetConfig.java index 4209173..53186b4 100644 --- a/src/dev/w1zzrd/invtweaks/serialization/MagnetConfig.java +++ b/src/dev/w1zzrd/invtweaks/serialization/MagnetConfig.java @@ -5,39 +5,83 @@ import org.bukkit.plugin.Plugin; import java.util.Map; import java.util.Objects; +/** + * Type representation of persistent configuration for /magnet + */ public class MagnetConfig extends SimpleReflectiveConfigItem { + /** + * Radius from player to check for items + */ private double radius; + + /** + * Interval (in ticks) to check for items around magnet players + */ private int interval; + + /** + * How many subsets to divide the active player list into when running magnetism check (for performance) + */ private int subdivide; public MagnetConfig(final Map mappings) { super(mappings); } + /** + * Get item search radius + * @return Item search radius + */ public double getRadius() { return radius; } + /** + * Get item search interval (in ticks) + * @return Item search interval + */ public int getInterval() { return interval; } + /** + * Get item search list subdivisions + * @return Item search list subdivisions + */ public int getSubdivide() { return subdivide; } + /** + * Set item search radius + * @param radius Radius + */ public void setRadius(double radius) { this.radius = radius; } + /** + * Set item search interval (in ticks) + * @param interval Interval + */ public void setInterval(int interval) { this.interval = interval; } + /** + * Set item search list subdivisions + * @param subdivide Subdivisions + */ public void setSubdivide(int subdivide) { this.subdivide = subdivide; } + /** + * Load default configuration values from the given plugin + * @param plugin Plugin to load defaults for + * @param path Path in default configuration to load values from + * @return Instance containing default configuration values + */ public static MagnetConfig getDefault(final Plugin plugin, final String path) { return (MagnetConfig) Objects.requireNonNull(plugin.getConfig().getDefaults()).get(path); } diff --git a/src/dev/w1zzrd/invtweaks/serialization/MagnetData.java b/src/dev/w1zzrd/invtweaks/serialization/MagnetData.java index 22bc522..52fda24 100644 --- a/src/dev/w1zzrd/invtweaks/serialization/MagnetData.java +++ b/src/dev/w1zzrd/invtweaks/serialization/MagnetData.java @@ -5,6 +5,9 @@ import org.bukkit.entity.Player; import java.util.*; +/** + * Persistent data pertaining to /magnet command + */ public class MagnetData extends SimpleReflectiveConfigItem { /** @@ -18,6 +21,10 @@ public class MagnetData extends SimpleReflectiveConfigItem { private final transient List onlineMagnets = new ArrayList<>(); private final transient List onlineMagnetsView = Collections.unmodifiableList(onlineMagnets); + /** + * Construct persistent magnet data from serialized data + * @param mappings Mappings to deserialize + */ public MagnetData(final Map mappings) { super(mappings); @@ -27,6 +34,11 @@ public class MagnetData extends SimpleReflectiveConfigItem { ensureListIntegrity(); } + /** + * Toggle magnet state for a given player + * @param magnet Player to toggle state for + * @return True if player is a magnet after this method call, else false + */ public boolean toggleMagnet(final UUID magnet) { final int index = Collections.binarySearch(activeMagnets, magnet); @@ -38,42 +50,51 @@ public class MagnetData extends SimpleReflectiveConfigItem { } else { activeMagnets.remove(index); - removeDisabledOnline(magnet); - return false; } } + /** + * Add a player as a magnet + * @param magnet Player to activate magnetism for + * @return True if list of magnets was modified, else false + */ public boolean addMagnet(final UUID magnet) { final int index = Collections.binarySearch(activeMagnets, magnet); // Insert magnet at correct place in list to keep it sorted if (index < 0) { activeMagnets.add(-(index + 1), magnet); - addMagnet(magnet); - return true; } return false; } + /** + * Remove a player from magnet list + * @param magnet Player to disable magnetism for + * @return True if list of magnets was modified, else false + */ public boolean removeMagnet(final UUID magnet) { final int index = Collections.binarySearch(activeMagnets, magnet); if (index >= 0) { activeMagnets.remove(index); - removeDisabledOnline(magnet); - return true; } return false; } + /** + * Remove many players from magnet list + * @param magnets Players to disable magnetism for + * @return True if list of magnets was modified, else false + */ public boolean removeMagnets(final Iterable magnets) { boolean changed = false; for(final UUID uuid : magnets) { @@ -82,7 +103,6 @@ public class MagnetData extends SimpleReflectiveConfigItem { continue; activeMagnets.remove(index); - removeDisabledOnline(uuid); changed = true; @@ -90,35 +110,72 @@ public class MagnetData extends SimpleReflectiveConfigItem { return changed; } + /** + * Check if a player is a magnet + * @param check Player to check + * @return True if player is a magnet, else false + * @see #isOnlineMagnet(UUID) + */ public boolean isMagnet(final UUID check) { return Collections.binarySearch(activeMagnets, check) >= 0; } + /** + * Check if player is a magnet and is online + * @param check Player to check + * @return True if player is online and a magnet + * @see #isMagnet(UUID) + */ public boolean isOnlineMagnet(final UUID check) { return Collections.binarySearch(onlineMagnets, check) >= 0; } + /** + * Get view of players with magnetism enabled + * @return Unmodifiable list of magnets + */ public List getActiveMagnetsView() { return activeMagnetsView; } + /** + * Get view of online players with magnetism enabled + * @return Unmodifiable list of online magnets + */ public List getOnlineMagnetsView() { return onlineMagnetsView; } + /** + * Get amount of magnets + * @return Number of total magnets + */ public int activeMagnets() { return activeMagnets.size(); } + /** + * Get amount of online magnets + * @return Number of online magnets + */ public int onlineMagnets() { return onlineMagnets.size(); } + /** + * Add player to online magnet list if player is online + * @param magnet Player to potentially add + */ private void addEnabledOnline(final UUID magnet) { if (isPlayerOnline(magnet)) addOnline(magnet); } + /** + * Add player to online magnet list if player is a magnet + * @param magnet Player to potentially add + * @return True if player is a magnet, else false + */ public boolean addLoginOnline(final UUID magnet) { if (isMagnet(magnet)) { addOnline(magnet); @@ -128,15 +185,28 @@ public class MagnetData extends SimpleReflectiveConfigItem { return false; } + /** + * Add player to online magnet list + * @param magnet Player to add + */ private void addOnline(final UUID magnet) { onlineMagnets.add(-(Collections.binarySearch(onlineMagnets, magnet) + 1), magnet); } + /** + * Remove player from online magnet list if they are online + * @param magnet Player to remove from list + */ private void removeDisabledOnline(final UUID magnet) { if (isPlayerOnline(magnet)) removeOnline(magnet); } + /** + * Remove player from online magnet list on logout + * @param magnet Player to remove + * @return True if player was an online magnet, else false + */ public boolean removeLogoutOnline(final UUID magnet) { if (isOnlineMagnet(magnet)) { removeOnline(magnet); @@ -146,6 +216,10 @@ public class MagnetData extends SimpleReflectiveConfigItem { return false; } + /** + * Remove a player from the online magnet list + * @param magnet Player to remove + */ private void removeOnline(final UUID magnet) { onlineMagnets.remove(Collections.binarySearch(onlineMagnets, magnet)); } @@ -174,12 +248,20 @@ public class MagnetData extends SimpleReflectiveConfigItem { } + /** + * Check if a given player is online + * @param check Player to check + * @return True if player is online, else false + */ private static boolean isPlayerOnline(final UUID check) { final Player player = Bukkit.getPlayer(check); return player != null && player.isOnline(); } - + /** + * Create an empty {@link MagnetData} configuration object + * @return Blank (valid) object + */ public static MagnetData blank() { return new MagnetData(Collections.singletonMap("activeMagnetsUUIDS", new UUIDList())); } diff --git a/src/dev/w1zzrd/invtweaks/serialization/SimpleReflectiveConfigItem.java b/src/dev/w1zzrd/invtweaks/serialization/SimpleReflectiveConfigItem.java index 3e76801..9cb6e0c 100644 --- a/src/dev/w1zzrd/invtweaks/serialization/SimpleReflectiveConfigItem.java +++ b/src/dev/w1zzrd/invtweaks/serialization/SimpleReflectiveConfigItem.java @@ -8,8 +8,15 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.*; +/** + * Configuration serializable type for automatically serializing/deserializing fields + */ public class SimpleReflectiveConfigItem implements ConfigurationSerializable { + /** + * Required constructor for deserializing data + * @param mappings Data to deserialize + */ public SimpleReflectiveConfigItem(final Map mappings) { deserializeMapped(mappings); } @@ -30,12 +37,17 @@ public class SimpleReflectiveConfigItem implements ConfigurationSerializable { return values; } + /** + * Deserialize mapped data by name + * @param mappings Data to deserialize + */ private void deserializeMapped(final Map mappings) { for (final Field field : getClass().getDeclaredFields()) { if (Modifier.isTransient(field.getModifiers()) || Modifier.isStatic(field.getModifiers())) continue; try { + // Try to find mappings by field name if (mappings.containsKey(field.getName())) parse(mappings.get(field.getName()), field, this); } catch (IllegalAccessException | InvocationTargetException e) { @@ -45,6 +57,14 @@ public class SimpleReflectiveConfigItem implements ConfigurationSerializable { } } + /** + * Attempt to parse a value such that it can be stored in the given field + * @param value Value to parse + * @param field Field to store value in + * @param instance Configuration object for which to parse the vaue + * @throws IllegalAccessException Should never be thrown + * @throws InvocationTargetException Should never be thrown + */ private static void parse(final Object value, final Field field, final Object instance) throws IllegalAccessException, InvocationTargetException { field.setAccessible(true); @@ -67,6 +87,11 @@ public class SimpleReflectiveConfigItem implements ConfigurationSerializable { throw new IllegalArgumentException(String.format("No defined parser for value \"%s\"", value)); } + /** + * Converter for boxed primitives + * @param cls Primitive type + * @return Boxed type for primitive type, else the given type + */ private static Class getBoxedType(final Class cls) { if (cls == int.class) return Integer.class; else if (cls == double.class) return Double.class; @@ -79,6 +104,12 @@ public class SimpleReflectiveConfigItem implements ConfigurationSerializable { else return cls; } + /** + * Attempt to find a parser method for the given type + * @param cls Type to find parser for + * @param prim Primitive type find parser for (if applicable) + * @return Static method which accepts a {@link String} argument and returns the desired type + */ private static Method locateParser(final Class cls, final Class prim) { for (final Method method : cls.getDeclaredMethods()) { final Class[] params = method.getParameterTypes(); diff --git a/src/dev/w1zzrd/invtweaks/serialization/UUIDList.java b/src/dev/w1zzrd/invtweaks/serialization/UUIDList.java index d549ceb..6bac651 100644 --- a/src/dev/w1zzrd/invtweaks/serialization/UUIDList.java +++ b/src/dev/w1zzrd/invtweaks/serialization/UUIDList.java @@ -5,18 +5,35 @@ import org.bukkit.configuration.serialization.ConfigurationSerializable; import java.util.*; import java.util.stream.Collectors; +/** + * Serializable dataclass holding a collection of {@link UUID} objects + */ public class UUIDList implements ConfigurationSerializable { + /** + * This is public to decrease performance overhead + */ public final List uuids; + /** + * Wrap a backing list of {@link UUID} objects to enable configuration serialization + * @param backingList Modifiable, backing list of {@link UUID} objects + */ public UUIDList(final List backingList) { uuids = backingList; } + /** + * Create a blank list of {@link UUID} objects + */ public UUIDList() { this(new ArrayList<>()); } + /** + * Deserialize serialized UUID strings + * @param values Data to deserialize + */ public UUIDList(final Map values) { this(); if (values.containsKey("values")) diff --git a/src/dev/w1zzrd/invtweaks/serialization/package-info.java b/src/dev/w1zzrd/invtweaks/serialization/package-info.java new file mode 100644 index 0000000..a75ac43 --- /dev/null +++ b/src/dev/w1zzrd/invtweaks/serialization/package-info.java @@ -0,0 +1,4 @@ +/** + * Types used for serializing and deserializing persistent data + */ +package dev.w1zzrd.invtweaks.serialization; \ No newline at end of file