Maven cleanliness and API progress

The project was very messy and due to older Bukkit packaging conventions, 1_4_5 and 1_4_6 were sorted away from the rest of the versioned code. All of the versioned internals are now submodules of the internal module.
Rather than use the hackish existing method of abusing the shade plugin to combine "dependencies" for a dummy assembly project, we're actually using the assembly plugin.
Profiles are still split up between the parent pom and the internal module pom, but they're much more clean.

The API is now its own module and can be compiled and released as a separate file for developers. Soon, Bukkit ticket 20, you'll be closed.
This commit is contained in:
Jikoo
2016-11-30 21:26:56 -05:00
parent db2cade4e2
commit 7942466863
166 changed files with 563 additions and 391 deletions

View File

@@ -0,0 +1,42 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.lishid</groupId>
<artifactId>openinvplugin</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>openinvplugincore</artifactId>
<name>OpenInvPluginCore</name>
<dependencies>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.4.5-R1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.lishid</groupId>
<artifactId>openinvcommon</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.lishid</groupId>
<artifactId>openinvpluginv1_10_r1</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>

View File

@@ -35,9 +35,14 @@ import com.lishid.openinv.internal.IInventoryAccess;
import com.lishid.openinv.internal.IPlayerDataManager;
import com.lishid.openinv.internal.ISpecialEnderChest;
import com.lishid.openinv.internal.ISpecialPlayerInventory;
import com.lishid.openinv.internal.InternalAccessor;
import com.lishid.openinv.listeners.InventoryClickListener;
import com.lishid.openinv.listeners.InventoryDragListener;
import com.lishid.openinv.listeners.PlayerListener;
import com.lishid.openinv.util.Cache;
import com.lishid.openinv.util.ConfigUpdater;
import com.lishid.openinv.util.Function;
import com.lishid.openinv.util.InternalAccessor;
import com.lishid.openinv.util.Permissions;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
@@ -54,7 +59,7 @@ import org.bukkit.scheduler.BukkitRunnable;
*
* @author lishid
*/
public class OpenInv extends JavaPlugin {
public class OpenInv extends JavaPlugin implements IOpenInv {
private final Map<String, ISpecialPlayerInventory> inventories = new HashMap<String, ISpecialPlayerInventory>();
private final Map<String, ISpecialEnderChest> enderChests = new HashMap<String, ISpecialEnderChest>();
@@ -120,9 +125,13 @@ public class OpenInv extends JavaPlugin {
new ConfigUpdater(this).checkForUpdates();
pm.registerEvents(new OpenInvPlayerListener(this), this);
pm.registerEvents(new OpenInvInventoryListener(this), this);
// Register listeners
pm.registerEvents(new PlayerListener(this), this);
pm.registerEvents(new InventoryClickListener(this), this);
// Bukkit will handle missing events for us, attempt to register InventoryDragEvent without a version check
pm.registerEvents(new InventoryDragListener(this), this);
// Register commands to their executors
getCommand("openinv").setExecutor(new OpenInvPluginCommand(this));
getCommand("openender").setExecutor(new OpenEnderPluginCommand(this));
SearchInvPluginCommand searchInv = new SearchInvPluginCommand();
@@ -149,8 +158,9 @@ public class OpenInv extends JavaPlugin {
*
* @return true if the server version is supported
*/
@Override
public boolean isSupportedVersion() {
return this.accessor.isSupported();
return this.accessor != null && this.accessor.isSupported();
}
/**
@@ -159,6 +169,7 @@ public class OpenInv extends JavaPlugin {
*
* @return the IInventoryAccess
*/
@Override
public IInventoryAccess getInventoryAccess() {
return this.inventoryAccess;
}
@@ -169,6 +180,7 @@ public class OpenInv extends JavaPlugin {
*
* @return the ISilentContainer
*/
@Override
public IAnySilentContainer getAnySilentContainer() {
return this.anySilentContainer;
}
@@ -180,6 +192,7 @@ public class OpenInv extends JavaPlugin {
* @param online true if the Player is currently online
* @return the ISpecialPlayerInventory
*/
@Override
public ISpecialPlayerInventory getInventory(Player player, boolean online) {
String id = playerLoader.getPlayerDataID(player);
if (inventories.containsKey(id)) {
@@ -198,6 +211,7 @@ public class OpenInv extends JavaPlugin {
* @param online true if the Player is currently online
* @return the ISpecialEnderChest
*/
@Override
public ISpecialEnderChest getEnderChest(Player player, boolean online) {
String id = playerLoader.getPlayerDataID(player);
if (enderChests.containsKey(id)) {
@@ -214,6 +228,7 @@ public class OpenInv extends JavaPlugin {
*
* @param player the OfflinePlayer to unload
*/
@Override
public void unload(OfflinePlayer player) {
this.playerCache.invalidate(this.playerLoader.getPlayerDataID(player));
}
@@ -226,6 +241,7 @@ public class OpenInv extends JavaPlugin {
*
* @return false unless configured otherwise
*/
@Override
public boolean disableSaving() {
return getConfig().getBoolean("settings.disable-saving", false);
}
@@ -236,6 +252,7 @@ public class OpenInv extends JavaPlugin {
*
* @return true unless configured otherwise
*/
@Override
public boolean notifySilentChest() {
return getConfig().getBoolean("notify.silent-chest", true);
}
@@ -246,6 +263,7 @@ public class OpenInv extends JavaPlugin {
*
* @return true unless configured otherwise
*/
@Override
public boolean notifyAnyChest() {
return getConfig().getBoolean("notify.any-chest", true);
}
@@ -256,6 +274,7 @@ public class OpenInv extends JavaPlugin {
* @param player the OfflinePlayer
* @return true if SilentChest is enabled
*/
@Override
public boolean getPlayerSilentChestStatus(OfflinePlayer player) {
return getConfig().getBoolean("toggles.silent-chest." + playerLoader.getPlayerDataID(player), false);
}
@@ -266,6 +285,7 @@ public class OpenInv extends JavaPlugin {
* @param player the OfflinePlayer
* @param status the status
*/
@Override
public void setPlayerSilentChestStatus(OfflinePlayer player, boolean status) {
getConfig().set("toggles.silent-chest." + playerLoader.getPlayerDataID(player), status);
saveConfig();
@@ -277,6 +297,7 @@ public class OpenInv extends JavaPlugin {
* @param player the OfflinePlayer
* @return true if AnyChest is enabled
*/
@Override
public boolean getPlayerAnyChestStatus(OfflinePlayer player) {
return getConfig().getBoolean("toggles.any-chest." + playerLoader.getPlayerDataID(player), false);
}
@@ -287,6 +308,7 @@ public class OpenInv extends JavaPlugin {
* @param player the OfflinePlayer
* @param status the status
*/
@Override
public void setPlayerAnyChestStatus(OfflinePlayer player, boolean status) {
getConfig().set("toggles.any-chest." + playerLoader.getPlayerDataID(player), status);
saveConfig();
@@ -299,6 +321,7 @@ public class OpenInv extends JavaPlugin {
* @param offline the OfflinePlayer
* @return the identifier
*/
@Override
public String getPlayerID(OfflinePlayer offline) {
return this.playerLoader.getPlayerDataID(offline);
}
@@ -313,6 +336,7 @@ public class OpenInv extends JavaPlugin {
* @param name the name of the Player
* @return the OfflinePlayer with the closest matching name or null if no players have ever logged in
*/
@Override
public OfflinePlayer matchPlayer(String name) {
// Warn if called on the main thread - if we resort to searching offline players, this may take several seconds.
@@ -391,6 +415,7 @@ public class OpenInv extends JavaPlugin {
* @param offline the OfflinePlayer to load a Player for
* @return the Player
*/
@Override
public Player loadPlayer(final OfflinePlayer offline) {
if (offline == null) {
@@ -473,6 +498,7 @@ public class OpenInv extends JavaPlugin {
if (this.inventories.containsKey(key)) {
this.inventories.get(key).setPlayerOnline(player);
new BukkitRunnable() {
@SuppressWarnings("deprecation") // Unlikely to ever be a viable alternative, Spigot un-deprecated.
@Override
public void run() {
if (player.isOnline()) {

View File

@@ -19,8 +19,8 @@ package com.lishid.openinv.commands;
import java.util.HashMap;
import com.lishid.openinv.OpenInv;
import com.lishid.openinv.Permissions;
import com.lishid.openinv.internal.ISpecialEnderChest;
import com.lishid.openinv.util.Permissions;
import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;

View File

@@ -19,8 +19,8 @@ package com.lishid.openinv.commands;
import java.util.HashMap;
import com.lishid.openinv.OpenInv;
import com.lishid.openinv.Permissions;
import com.lishid.openinv.internal.ISpecialPlayerInventory;
import com.lishid.openinv.util.Permissions;
import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;

View File

@@ -14,49 +14,36 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.lishid.openinv;
package com.lishid.openinv.listeners;
import com.lishid.openinv.IOpenInv;
import com.lishid.openinv.util.Permissions;
import org.bukkit.entity.HumanEntity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.inventory.Inventory;
public class OpenInvInventoryListener implements Listener {
public class InventoryClickListener implements Listener {
private final OpenInv plugin;
private final IOpenInv plugin;
public OpenInvInventoryListener(OpenInv plugin) {
public InventoryClickListener(IOpenInv plugin) {
this.plugin = plugin;
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onInventoryClick(InventoryClickEvent event) {
if (cancelInteract(event.getWhoClicked(), event.getInventory())) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onInventoryDrag(InventoryDragEvent event) {
if (cancelInteract(event.getWhoClicked(), event.getInventory())) {
event.setCancelled(true);
}
}
private boolean cancelInteract(HumanEntity entity, Inventory inventory) {
return plugin.getInventoryAccess().isSpecialPlayerInventory(inventory)
HumanEntity entity = event.getWhoClicked();
Inventory inventory = event.getInventory();
if (plugin.getInventoryAccess().isSpecialPlayerInventory(inventory)
&& !Permissions.EDITINV.hasPermission(entity)
|| plugin.getInventoryAccess().isSpecialEnderChest(inventory)
&& !Permissions.EDITENDER.hasPermission(entity);
}
@EventHandler
public void onWorldChange(PlayerChangedWorldEvent event) {
plugin.changeWorld(event.getPlayer());
&& !Permissions.EDITENDER.hasPermission(entity)) {
event.setCancelled(true);
}
}
}

View File

@@ -14,7 +14,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.lishid.openinv;
package com.lishid.openinv.listeners;
import com.lishid.openinv.OpenInv;
import com.lishid.openinv.util.Permissions;
import org.bukkit.entity.Player;
import org.bukkit.event.Event.Result;
@@ -22,15 +25,16 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
public class OpenInvPlayerListener implements Listener {
public class PlayerListener implements Listener {
private final OpenInv plugin;
public OpenInvPlayerListener(OpenInv plugin) {
public PlayerListener(OpenInv plugin) {
this.plugin = plugin;
}
@@ -44,6 +48,11 @@ public class OpenInvPlayerListener implements Listener {
plugin.setPlayerOffline(event.getPlayer());
}
@EventHandler
public void onWorldChange(PlayerChangedWorldEvent event) {
plugin.changeWorld(event.getPlayer());
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerInteract(PlayerInteractEvent event) {
if (event.getAction() != Action.RIGHT_CLICK_BLOCK || event.getPlayer().isSneaking()

View File

@@ -1,4 +1,4 @@
package com.lishid.openinv;
package com.lishid.openinv.util;
import java.io.File;
import java.io.IOException;
@@ -6,6 +6,8 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import com.lishid.openinv.OpenInv;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.configuration.ConfigurationSection;
@@ -140,7 +142,6 @@ public class ConfigUpdater {
}.runTask(plugin);
}
@SuppressWarnings("deprecation")
private Material getMaterialById(int id) {
Material material = Material.getMaterial(id);

View File

@@ -0,0 +1,28 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.lishid</groupId>
<artifactId>openinvplugin</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>openinvpluginv1_10_r1</artifactId>
<name>OpenInvPluginv1_10_R1</name>
<dependencies>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.10-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.lishid</groupId>
<artifactId>openinvcommon</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,38 @@
package com.lishid.openinv.listeners;
import com.lishid.openinv.IOpenInv;
import com.lishid.openinv.util.Permissions;
import org.bukkit.entity.HumanEntity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.inventory.Inventory;
/**
* Listener for InventoryDragEvents to prevent unpermitted modification of special inventories.
*
* @author Jikoo
*/
public class InventoryDragListener implements Listener {
private final IOpenInv plugin;
public InventoryDragListener(IOpenInv plugin) {
this.plugin = plugin;
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onInventoryDrag(InventoryDragEvent event) {
HumanEntity entity = event.getWhoClicked();
Inventory inventory = event.getInventory();
if (plugin.getInventoryAccess().isSpecialPlayerInventory(inventory)
&& !Permissions.EDITINV.hasPermission(entity)
|| plugin.getInventoryAccess().isSpecialEnderChest(inventory)
&& !Permissions.EDITENDER.hasPermission(entity)) {
event.setCancelled(true);
}
}
}

View File

@@ -4,35 +4,18 @@
<parent>
<groupId>com.lishid</groupId>
<artifactId>openinv</artifactId>
<artifactId>openinvparent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>openinvplugin</artifactId>
<name>OpenInvPlugin</name>
<dependencies>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<!-- Really should use 1.4.5-R1.0, but the InventoryDragEvent doesn't exist. TODO separate module? -->
<version>1.11-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.lishid</groupId>
<artifactId>openinvinternal</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<packaging>pom</packaging>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<modules>
<module>plugin-v1_10_R1</module>
<module>plugin-core</module>
</modules>
</project>

View File

@@ -1,38 +0,0 @@
package com.lishid.openinv;
import org.bukkit.permissions.Permissible;
public enum Permissions {
OPENINV("OpenInv.openinv"),
OVERRIDE("OpenInv.override"),
EXEMPT("OpenInv.exempt"),
CROSSWORLD("OpenInv.crossworld"),
SILENT("OpenInv.silent"),
ANYCHEST("OpenInv.anychest"),
ENDERCHEST("OpenInv.openender"),
ENDERCHEST_ALL("OpenInv.openenderall"),
SEARCH("OpenInv.search"),
EDITINV("OpenInv.editinv"),
EDITENDER("OpenInv.editender"),
OPENSELF("OpenInv.openself");
private final String permission;
private Permissions(String permission) {
this.permission = permission;
}
public boolean hasPermission(Permissible permissible) {
String[] parts = permission.split("\\.");
String perm = "";
for (int i = 0; i < parts.length; i++) {
if (permissible.hasPermission(perm + "*")) {
return true;
}
perm += parts[i] + ".";
}
return permissible.hasPermission(permission);
}
}

View File

@@ -1,160 +0,0 @@
package com.lishid.openinv.util;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import com.google.common.collect.Multimap;
import com.google.common.collect.TreeMultimap;
/**
* A minimal time-based cache implementation backed by a HashMap and TreeMultimap.
*
* @author Jikoo
*/
public class Cache<K, V> {
private final Map<K, V> internal;
private final Multimap<Long, K> expiry;
private final long retention;
private final Function<V> inUseCheck, postRemoval;
/**
* Constructs a Cache with the specified retention duration, in use function, and post-removal function.
*
* @param retention duration after which keys are automatically invalidated if not in use
* @param inUseCheck Function used to check if a key is considered in use
* @param postRemoval Function used to perform any operations required when a key is invalidated
*/
public Cache(long retention, Function<V> inUseCheck, Function<V> postRemoval) {
this.internal = new HashMap<K, V>();
this.expiry = TreeMultimap.create(new Comparator<Long>() {
@Override
public int compare(Long long1, Long long2) {
return long1.compareTo(long2);
}
},
new Comparator<K>() {
@Override
public int compare(K k1, K k2) {
return 0;
}
});
this.retention = retention;
this.inUseCheck = inUseCheck;
this.postRemoval = postRemoval;
}
/**
* Set a key and value pair. Keys are unique. Using an existing key will cause the old value to
* be overwritten and the expiration timer to be reset.
*
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
*/
public void put(K key, V value) {
// Invalidate key - runs lazy check and ensures value won't be cleaned up early
invalidate(key);
internal.put(key, value);
expiry.put(System.currentTimeMillis() + retention, key);
}
/**
* Returns the value to which the specified key is mapped, or null if no value is mapped for the key.
*
* @param key the key whose associated value is to be returned
* @return the value to which the specified key is mapped, or null if no value is mapped for the key
*/
public V get(K key) {
// Run lazy check to clean cache
lazyCheck();
return internal.get(key);
}
/**
* Returns true if the specified key is mapped to a value.
*
* @param key key to check if a mapping exists for
* @return true if a mapping exists for the specified key
*/
public boolean containsKey(K key) {
// Run lazy check to clean cache
lazyCheck();
return internal.containsKey(key);
}
/**
* Forcibly invalidates a key, even if it is considered to be in use.
*
* @param key key to invalidate
*/
public void invalidate(K key) {
// Run lazy check to clean cache
lazyCheck();
if (!internal.containsKey(key)) {
// Value either not present or cleaned by lazy check. Either way, we're good
return;
}
// Remove stored object
internal.remove(key);
// Remove expiration entry - prevents more work later, plus prevents issues with values invalidating early
for (Iterator<Map.Entry<Long, K>> iterator = expiry.entries().iterator(); iterator.hasNext();) {
if (key.equals(iterator.next().getValue())) {
iterator.remove();
break;
}
}
}
/**
* Forcibly invalidates all keys, even if they are considered to be in use.
*/
public void invalidateAll() {
for (V value : internal.values()) {
postRemoval.run(value);
}
expiry.clear();
internal.clear();
}
/**
* Invalidate all expired keys that are not considered in use. If a key is expired but is
* considered in use by the provided Function, its expiration time is reset.
*/
private void lazyCheck() {
long now = System.currentTimeMillis();
long nextExpiry = now + retention;
for (Iterator<Map.Entry<Long, K>> iterator = expiry.entries().iterator(); iterator.hasNext();) {
Map.Entry<Long, K> entry = iterator.next();
if (entry.getKey() > now) {
break;
}
iterator.remove();
if (inUseCheck.run(internal.get(entry.getValue()))) {
expiry.put(nextExpiry, entry.getValue());
continue;
}
V value = internal.remove(entry.getValue());
if (value == null) {
continue;
}
postRemoval.run(value);
}
}
}

View File

@@ -1,12 +0,0 @@
package com.lishid.openinv.util;
/**
* Abstraction for some simple cache calls.
*
* @author Jikoo
*/
public abstract class Function<V> {
public abstract boolean run(V value);
}