Convert to a multi-module Maven setup

This is much more user-friendly - users can either compile a specific module or create a profile to compile for the specific Minecraft versions they're looking to support. It means that it's much easier for people to continue assisting with the development of OpenInv in the future without access to every version of CB since 1.4.5.

This commit restores and updates most of the old system.
This commit is contained in:
Jikoo 2016-11-25 08:01:44 -05:00
parent b76440ab9a
commit 3bf7225712
40 changed files with 1088 additions and 196 deletions

19
.gitignore vendored
View file

@ -1,9 +1,10 @@
/.settings
/.gitignore
/.project
/.classpath
/.idea
/target
/bin
/lib
/out
**/.settings
**/.gitignore
**/.project
**/.classpath
**/.idea
**/target
**/bin
**/lib
**/out
**dependency-reduced-pom.xml

77
assembly/pom.xml Normal file
View file

@ -0,0 +1,77 @@
<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>openinv</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>openinvassembly</artifactId>
<name>OpenInvAssembly</name>
<profiles>
<profile>
<id>latest</id>
<dependencies>
<dependency>
<groupId>com.lishid</groupId>
<artifactId>openinvadapter1_11_R1</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>all</id>
<dependencies>
<dependency>
<groupId>com.lishid</groupId>
<artifactId>openinvadapter1_11_R1</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</profile>
</profiles>
<build>
<directory>../target</directory>
<finalName>OpenInv</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<configuration>
<!--
~ This keeps the final file clean, but may cause issues for people not familiar with the setup.
~ If you're having trouble with the final product missing files, remove or tweak this configuration.
-->
<minimizeJar>true</minimizeJar>
<filters>
<filter>
<artifact>com.lishid:*</artifact>
<includes>
<include>com/lishid/openinv/**/*</include>
<include>plugin.yml</include>
</includes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

23
internal/pom.xml Normal file
View file

@ -0,0 +1,23 @@
<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>openinv</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>openinvinternal</artifactId>
<name>OpenInvInternal</name>
<dependencies>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.4.5-R1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View file

@ -0,0 +1,40 @@
/*
* Copyright (C) 2011-2014 lishid. All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.lishid.openinv.internal;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
/**
* @deprecated Use {@link IAnySilentContainer}
*/
@Deprecated
public interface IAnySilentChest {
/**
* @deprecated Use {@link IAnySilentContainer#activateContainer(Player, boolean, Block)}.
*/
@Deprecated
public boolean activateChest(Player player, boolean anychest, boolean silentchest, int x, int y, int z);
/**
* @deprecated Use {@link IAnySilentContainer#isAnyContainerNeeded(Player, Block)}.
*/
@Deprecated
public boolean isAnyChestNeeded(Player player, int x, int y, int z);
}

View file

@ -0,0 +1,38 @@
package com.lishid.openinv.internal;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
@SuppressWarnings("deprecation")
public interface IAnySilentContainer extends IAnySilentChest {
/**
* Checks if the given block is a container which can be unblocked or silenced.
*
* @param block the BlockState
* @return true if the Block is a supported container
*/
public boolean isAnySilentContainer(Block block);
/**
* Checks if the container at the given coordinates is blocked.
*
* @param player the Player opening the container
* @param block the Block
* @return true if the container is blocked
*/
public boolean isAnyContainerNeeded(Player player, Block block);
/**
* Opens the container at the given coordinates for the Player. If you do not want blocked
* containers to open, be sure to check {@link #isAnyContainerNeeded(Player, Block)}
* first.
*
* @param player
* @param silentchest whether the container's noise is to be silenced
* @param block the Block
* @return true if the container can be opened
*/
public boolean activateContainer(Player player, boolean silentchest, Block block);
}

View file

@ -0,0 +1,33 @@
/*
* Copyright (C) 2011-2014 lishid. All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.lishid.openinv.internal;
import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.Inventory;
public interface IInventoryAccess {
/**
* Check if an entity has permission to modify the contents of an inventory.
*
* @param inventory the Inventory
* @param player the HumanEntity
* @return true if the HumanEntity can modify the Inventory
*/
public boolean check(Inventory inventory, HumanEntity player);
}

View file

@ -0,0 +1,50 @@
/*
* Copyright (C) 2011-2014 lishid. All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.lishid.openinv.internal;
import java.util.UUID;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
public interface IPlayerDataManager {
/**
* Loads a Player for an OfflinePlayer.
* </p>
* This method is potentially blocking, and should not be called on the main thread.
*
* @param offline
* @return
*/
public Player loadPlayer(OfflinePlayer offline);
/**
* @deprecated use {@link #loadPlayer(OfflinePlayer)}
*/
@Deprecated
public Player loadPlayer(UUID uuid);
/**
* Gets a unique identifying string for an OfflinePlayer.
*
* @param player
* @return
*/
public String getPlayerDataID(OfflinePlayer player);
}

View file

@ -0,0 +1,62 @@
/*
* Copyright (C) 2011-2014 lishid. All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.lishid.openinv.internal;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
public interface ISpecialEnderChest {
/**
* Gets the Inventory associated with this ISpecialEnderChest.
*
* @return the Inventory
*/
public Inventory getBukkitInventory();
/**
* Sets the Player associated with this ISpecialEnderChest online.
*
* @param player the Player coming online
*/
public void setPlayerOnline(Player player);
/**
* @deprecated use {@link #setPlayerOnline(Player)}
*/
@Deprecated
public void playerOnline(Player player);
/**
* Sets the Player associated with this ISpecialEnderChest offline.
*/
public void setPlayerOffline();
/**
* @deprecated use {@link #setPlayerOffline()}
*/
@Deprecated
public void playerOffline();
/**
* Gets whether or not this ISpecialEnderChest is in use.
*
* @return true if the ISpecialEnderChest is in use
*/
public boolean isInUse();
}

View file

@ -0,0 +1,62 @@
/*
* Copyright (C) 2011-2014 lishid. All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.lishid.openinv.internal;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
public interface ISpecialPlayerInventory {
/**
* Gets the Inventory associated with this ISpecialPlayerInventory.
*
* @return the Inventory
*/
public Inventory getBukkitInventory();
/**
* Sets the Player associated with this ISpecialPlayerInventory online.
*
* @param player the Player coming online
*/
public void setPlayerOnline(Player player);
/**
* @deprecated use {@link #setPlayerOnline(Player)}
*/
@Deprecated
public void playerOnline(Player player);
/**
* Sets the Player associated with this ISpecialPlayerInventory offline.
*/
public void setPlayerOffline();
/**
* @deprecated use {@link #setPlayerOffline()}
*/
@Deprecated
public void playerOffline();
/**
* Gets whether or not this ISpecialPlayerInventory is in use.
*
* @return true if the ISpecialPlayerInventory is in use
*/
public boolean isInUse();
}

View file

@ -0,0 +1,183 @@
/*
* Copyright (C) 2011-2014 lishid. All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.lishid.openinv.internal;
import java.lang.reflect.Constructor;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
public class InternalAccessor {
private final Plugin plugin;
private String version;
private boolean supported = false;
public InternalAccessor(Plugin plugin) {
this.plugin = plugin;
}
/**
* Check if the current server version is supported, and, if it is, prepare to load version-specific code.
*
* @param server the Server
*
* @return true if supported
*/
public boolean initialize(Server server) {
String packageName = server.getClass().getPackage().getName();
version = packageName.substring(packageName.lastIndexOf('.') + 1);
try {
Class.forName("com.lishid.openinv.internal." + version + ".PlayerDataManager");
return (supported = true);
} catch (Exception e) {
return false;
}
}
/**
* Gets the server implementation version. If not initialized, returns the string "null"
* instead.
*
* @return the version, or "null"
*/
public String getVersion() {
return this.version != null ? this.version : "null";
}
/**
* Checks if the server implementation is supported.
*
* @return true if initialized for a supported server version
*/
public boolean isSupported() {
return this.supported;
}
/**
* Creates an instance of the IPlayerDataManager implementation for the current server version,
* or null if unsupported.
*
* @return the IPlayerDataManager
*/
public IPlayerDataManager newPlayerDataManager() {
return createObject(IPlayerDataManager.class, "PlayerDataManager");
}
/**
* Creates an instance of the IInventoryAccess implementation for the current server version, or
* null if unsupported.
*
* @return the IInventoryAccess
*/
public IInventoryAccess newInventoryAccess() {
return createObject(IInventoryAccess.class, "InventoryAccess");
}
/**
* Creates an instance of the IAnySilentContainer implementation for the current server version,
* or null if unsupported.
*
* @return the IAnySilentContainer
*/
public IAnySilentContainer newAnySilentContainer() {
return createObject(IAnySilentContainer.class, "AnySilentContainer");
}
/**
* @deprecated Use {@link #newAnySilentContainer()}
*/
@Deprecated
public IAnySilentChest newAnySilentChest() {
IAnySilentChest iAnySilentChest = createObject(IAnySilentChest.class, "AnySilentChest");
return iAnySilentChest != null ? iAnySilentChest : newAnySilentContainer();
}
/**
* Creates an instance of the ISpecialPlayerInventory implementation for the given Player, or
* null if the current version is unsupported.
*
* @param player the Player
* @param online true if the Player is online
* @return the ISpecialPlayerInventory created
*/
public ISpecialPlayerInventory newSpecialPlayerInventory(Player player, boolean online) {
return createObject(ISpecialPlayerInventory.class, "SpecialPlayerInventory", player, online);
}
/**
* Creates an instance of the ISpecialEnderChest implementation for the given Player, or
* null if the current version is unsupported.
*
* @param player the Player
* @param online true if the Player is online
* @return the ISpecialEnderChest created
*/
public ISpecialEnderChest newSpecialEnderChest(Player player, boolean online) {
return createObject(ISpecialEnderChest.class, "SpecialEnderChest", player, online);
}
private <T> T createObject(Class<? extends T> assignableClass, String className, Object... params) {
try {
// Check if internal versioned class exists
Class<?> internalClass = Class.forName("com.lishid.openinv.internal." + version + "." + className);
if (!assignableClass.isAssignableFrom(internalClass)) {
plugin.getLogger().warning("Found class " + internalClass.getName() + " but cannot cast to " + assignableClass.getName());
return null;
}
// Quick return: no parameters, no need to fiddle about finding the correct constructor.
if (params.length == 0) {
return assignableClass.cast(internalClass.getConstructor().newInstance());
}
// Search constructors for one matching the given parameters
nextConstructor: for (Constructor<?> constructor : internalClass.getConstructors()) {
Class<?>[] requiredClasses = constructor.getParameterTypes();
if (requiredClasses.length != params.length) {
continue;
}
for (int i = 0; i < params.length; ++i) {
if (!requiredClasses[i].isAssignableFrom(params[i].getClass())) {
continue nextConstructor;
}
}
return assignableClass.cast(constructor.newInstance(params));
}
StringBuilder message = new StringBuilder("Found class ").append(internalClass.getName())
.append(" but cannot find any matching constructors for [");
for (Object object : params) {
message.append(object.getClass().getName()).append(", ");
}
if (params.length > 0) {
message.delete(message.length() - 2, message.length());
}
plugin.getLogger().warning(message.append(']').toString());
} catch (Exception e) {
plugin.getLogger().warning("OpenInv encountered an error with the CraftBukkit version \"" + version + "\". Please look for an updated version of OpenInv.");
e.printStackTrace();
}
return null;
}
}

38
plugin/pom.xml Normal file
View file

@ -0,0 +1,38 @@
<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>openinv</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>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>

View file

@ -20,13 +20,6 @@ import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permissible;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import com.lishid.openinv.commands.AnyChestCommand;
import com.lishid.openinv.commands.OpenEnderCommand;
import com.lishid.openinv.commands.OpenInvCommand;
@ -34,25 +27,34 @@ import com.lishid.openinv.commands.SearchEnderCommand;
import com.lishid.openinv.commands.SearchInvCommand;
import com.lishid.openinv.commands.SilentChestCommand;
import com.lishid.openinv.commands.ToggleOpenInvCommand;
import com.lishid.openinv.internal.AnySilentChest;
import com.lishid.openinv.internal.InventoryAccess;
import com.lishid.openinv.internal.PlayerDataManager;
import com.lishid.openinv.internal.SpecialEnderChest;
import com.lishid.openinv.internal.SpecialPlayerInventory;
import com.lishid.openinv.internal.IAnySilentChest;
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.OpenInvEntityListener;
import com.lishid.openinv.listeners.OpenInvInventoryListener;
import com.lishid.openinv.listeners.OpenInvPlayerListener;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permissible;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
public class OpenInv extends JavaPlugin {
private final Map<UUID, SpecialPlayerInventory> inventories = new HashMap<UUID, SpecialPlayerInventory>();
private final Map<UUID, SpecialEnderChest> enderChests = new HashMap<UUID, SpecialEnderChest>();
private final Map<UUID, ISpecialPlayerInventory> inventories = new HashMap<UUID, ISpecialPlayerInventory>();
private final Map<UUID, ISpecialEnderChest> enderChests = new HashMap<UUID, ISpecialEnderChest>();
private Configuration configuration;
private PlayerDataManager playerLoader;
private InventoryAccess inventoryAccess;
private AnySilentChest anySilentChest;
private InternalAccessor accessor;
private IPlayerDataManager playerLoader;
private IInventoryAccess inventoryAccess;
private IAnySilentChest anySilentChest;
@Override
public void onEnable() {
@ -62,14 +64,21 @@ public class OpenInv extends JavaPlugin {
// Config
configuration = new Configuration(this);
// Initialize
playerLoader = new PlayerDataManager(this);
inventoryAccess = new InventoryAccess(this);
anySilentChest = new AnySilentChest(this);
// Register the plugin's events
PluginManager pm = getServer().getPluginManager();
// Version check
if (!accessor.initialize(getServer())) {
getLogger().info("Your version of CraftBukkit (" + accessor.getVersion() + ") is not supported.");
getLogger().info("Please look for an updated version of OpenInv.");
pm.disablePlugin(this);
return;
}
playerLoader = accessor.newPlayerDataManager();
inventoryAccess = accessor.newInventoryAccess();
anySilentChest = accessor.newAnySilentChest();
// Register the plugin's events
pm.registerEvents(new OpenInvPlayerListener(this), this);
pm.registerEvents(new OpenInvEntityListener(this), this);
pm.registerEvents(new OpenInvInventoryListener(this), this);
@ -98,7 +107,7 @@ public class OpenInv extends JavaPlugin {
*
* @return an instance of PlayerDataManager
*/
public PlayerDataManager getPlayerLoader() {
public IPlayerDataManager getPlayerLoader() {
return playerLoader;
}
@ -107,7 +116,7 @@ public class OpenInv extends JavaPlugin {
*
* @return an instance of InventoryAccess
*/
public InventoryAccess getInventoryAccess() {
public IInventoryAccess getInventoryAccess() {
return inventoryAccess;
}
@ -116,7 +125,7 @@ public class OpenInv extends JavaPlugin {
*
* @return an instance of AnySilentChest
*/
public AnySilentChest getAnySilentChest() {
public IAnySilentChest getAnySilentChest() {
return anySilentChest;
}
@ -127,11 +136,11 @@ public class OpenInv extends JavaPlugin {
* @param createIfNull whether or not to create it if it doesn't exist
* @return the player's SpecialPlayerInventory or null
*/
public SpecialPlayerInventory getPlayerInventory(Player player, boolean createIfNull) {
SpecialPlayerInventory inventory = inventories.get(player.getUniqueId());
public ISpecialPlayerInventory getPlayerInventory(Player player, boolean createIfNull) {
ISpecialPlayerInventory inventory = inventories.get(player.getUniqueId());
if (inventory == null && createIfNull) {
inventory = new SpecialPlayerInventory(player, player.isOnline());
inventory = accessor.newSpecialPlayerInventory(player, !player.isOnline());
inventories.put(player.getUniqueId(), inventory);
}
@ -145,11 +154,11 @@ public class OpenInv extends JavaPlugin {
* @param createIfNull whether or not to create it if it doesn't exist
* @return the player's SpecialEnderChest or null
*/
public SpecialEnderChest getPlayerEnderChest(Player player, boolean createIfNull) {
SpecialEnderChest enderChest = enderChests.get(player.getUniqueId());
public ISpecialEnderChest getPlayerEnderChest(Player player, boolean createIfNull) {
ISpecialEnderChest enderChest = enderChests.get(player.getUniqueId());
if (enderChest == null && createIfNull) {
enderChest = new SpecialEnderChest(player, player.isOnline());
enderChest = accessor.newSpecialEnderChest(player, player.isOnline());
enderChests.put(player.getUniqueId(), enderChest);
}

View file

@ -1,19 +1,19 @@
package com.lishid.openinv;
public final class Permissions {
private Permissions() {}
public static final String PERM_OPENINV = "OpenInv.openinv";
public static final String PERM_OVERRIDE = "OpenInv.override";
public static final String PERM_EXEMPT = "OpenInv.exempt";
public static final String PERM_CROSSWORLD = "OpenInv.crossworld";
public static final String PERM_SILENT = "OpenInv.silent";
public static final String PERM_ANYCHEST = "OpenInv.anychest";
public static final String PERM_ENDERCHEST = "OpenInv.openender";
public static final String PERM_ENDERCHEST_ALL = "OpenInv.openenderall";
public static final String PERM_SEARCH = "OpenInv.search";
public static final String PERM_EDITINV = "OpenInv.editinv";
public static final String PERM_EDITENDER = "OpenInv.editender";
public static final String PERM_OPENSELF = "OpenInv.openself";
}
package com.lishid.openinv;
public final class Permissions {
private Permissions() {}
public static final String PERM_OPENINV = "OpenInv.openinv";
public static final String PERM_OVERRIDE = "OpenInv.override";
public static final String PERM_EXEMPT = "OpenInv.exempt";
public static final String PERM_CROSSWORLD = "OpenInv.crossworld";
public static final String PERM_SILENT = "OpenInv.silent";
public static final String PERM_ANYCHEST = "OpenInv.anychest";
public static final String PERM_ENDERCHEST = "OpenInv.openender";
public static final String PERM_ENDERCHEST_ALL = "OpenInv.openenderall";
public static final String PERM_SEARCH = "OpenInv.search";
public static final String PERM_EDITINV = "OpenInv.editinv";
public static final String PERM_EDITENDER = "OpenInv.editender";
public static final String PERM_OPENSELF = "OpenInv.openself";
}

View file

@ -20,6 +20,11 @@ import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import com.lishid.openinv.OpenInv;
import com.lishid.openinv.Permissions;
import com.lishid.openinv.internal.ISpecialEnderChest;
import com.lishid.openinv.utils.UUIDUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
@ -27,11 +32,6 @@ import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import com.lishid.openinv.OpenInv;
import com.lishid.openinv.Permissions;
import com.lishid.openinv.internal.SpecialEnderChest;
import com.lishid.openinv.utils.UUIDUtils;
public class OpenEnderCommand implements CommandExecutor {
private final OpenInv plugin;
@ -155,7 +155,7 @@ public class OpenEnderCommand implements CommandExecutor {
openEnderHistory.put(player.getUniqueId(), target.getUniqueId());
// Get the inventory and open it
SpecialEnderChest enderChest = plugin.getPlayerEnderChest(target, true);
ISpecialEnderChest enderChest = plugin.getPlayerEnderChest(target, true);
player.openInventory(enderChest.getBukkitInventory());
}
}

View file

@ -20,20 +20,17 @@ import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import com.lishid.openinv.OpenInv;
import com.lishid.openinv.Permissions;
import com.lishid.openinv.internal.ISpecialPlayerInventory;
import com.lishid.openinv.utils.UUIDUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import com.lishid.openinv.OpenInv;
import com.lishid.openinv.Permissions;
import com.lishid.openinv.internal.SpecialPlayerInventory;
import com.lishid.openinv.utils.UUIDUtils;
public class OpenInvCommand implements CommandExecutor {
@ -153,7 +150,7 @@ public class OpenInvCommand implements CommandExecutor {
openInvHistory.put(player.getUniqueId(), target.getUniqueId());
// Get the inventory and open it
SpecialPlayerInventory inventory = plugin.getPlayerInventory(target, true);
ISpecialPlayerInventory inventory = plugin.getPlayerInventory(target, true);
player.openInventory(inventory.getBukkitInventory());
}
}

View file

@ -16,6 +16,12 @@
package com.lishid.openinv.listeners;
import com.lishid.openinv.Configuration;
import com.lishid.openinv.OpenInv;
import com.lishid.openinv.Permissions;
import com.lishid.openinv.internal.ISpecialEnderChest;
import com.lishid.openinv.internal.ISpecialPlayerInventory;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.Block;
@ -32,12 +38,6 @@ import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.scheduler.BukkitRunnable;
import com.lishid.openinv.OpenInv;
import com.lishid.openinv.Permissions;
import com.lishid.openinv.Configuration;
import com.lishid.openinv.internal.SpecialEnderChest;
import com.lishid.openinv.internal.SpecialPlayerInventory;
public class OpenInvPlayerListener implements Listener {
private final OpenInv plugin;
@ -60,13 +60,13 @@ public class OpenInvPlayerListener implements Listener {
return;
}
SpecialPlayerInventory inventory = plugin.getPlayerInventory(player, false);
ISpecialPlayerInventory inventory = plugin.getPlayerInventory(player, false);
if (inventory != null) {
inventory.playerOnline(player);
player.updateInventory();
}
SpecialEnderChest enderChest = plugin.getPlayerEnderChest(player, false);
ISpecialEnderChest enderChest = plugin.getPlayerEnderChest(player, false);
if (enderChest != null) {
enderChest.playerOnline(player);
}
@ -78,16 +78,18 @@ public class OpenInvPlayerListener implements Listener {
public void onPlayerQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();
SpecialPlayerInventory inventory = plugin.getPlayerInventory(player, false);
ISpecialPlayerInventory inventory = plugin.getPlayerInventory(player, false);
if (inventory != null) {
if (inventory.playerOffline()) {
inventory.playerOffline();
if (inventory.isInUse()) {
plugin.removeLoadedInventory(event.getPlayer());
}
}
SpecialEnderChest enderChest = plugin.getPlayerEnderChest(player, false);
ISpecialEnderChest enderChest = plugin.getPlayerEnderChest(player, false);
if (enderChest != null) {
if (enderChest.playerOffline()) {
enderChest.playerOffline();
if (!enderChest.isInUse()) {
plugin.removeLoadedEnderChest(event.getPlayer());
}
}

View file

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

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

View file

@ -1,45 +1,45 @@
name: OpenInv
main: com.lishid.openinv.OpenInv
version: 2.4.0
author: lishid
authors: [ShadowRanger]
description: >
This plugin allows you to open a player's inventory as a chest and interact with it in real time.
commands:
openinv:
aliases: [oi, inv, open]
description: Opens a player's inventory.
usage: |
/<command> - Opens last person's inventory.
/<command> <player> - Opens a player's inventory.
openender:
aliases: [oe]
description: Opens a player's ender chest.
usage: |
/<command> - Opens last person's ender chest.
/<command> <player> - Opens a player's ender chest.
searchinv:
aliases: [si]
description: Searches and lists players that have a specific item in their inventory.
usage: |
/<command> <item> [minAmount] - Item can be the Item ID or the CraftBukkit Item Name, minAmount is the minimum amount to be considered.
searchender:
aliases: [se]
description: Searches and lists players that have a specific item in their ender chest.
usage: |
/<command> <item> [minAmount] - Item can be the Item ID or the CraftBukkit Item Name, minAmount is the minimum amount to be considered.
toggleopeninv:
aliases: [toi, toggleoi, toggleinv]
description: Toggles the item openinv function.
usage: |
/<command> [check] - Checks whether item openinv is enabled.
anychest:
aliases: [ac]
description: Toggles the any chest function, which allows opening of blocked chests.
usage: |
/<command> [check] - Checks whether any chest is enabled.
silentchest:
aliases: [sc, silent]
description: Toggles the silent chest function, which hides the animation of a chest when opened or closed, and suppresses the sound.
usage: |
/<command> [check] - Checks whether silent chest is enabled.
name: OpenInv
main: com.lishid.openinv.OpenInv
version: ${openinv.version}
author: lishid
authors: [ShadowRanger]
description: >
This plugin allows you to open a player's inventory as a chest and interact with it in real time.
commands:
openinv:
aliases: [oi, inv, open]
description: Opens a player's inventory.
usage: |
/<command> - Opens last person's inventory.
/<command> <player> - Opens a player's inventory.
openender:
aliases: [oe]
description: Opens a player's ender chest.
usage: |
/<command> - Opens last person's ender chest.
/<command> <player> - Opens a player's ender chest.
searchinv:
aliases: [si]
description: Searches and lists players that have a specific item in their inventory.
usage: |
/<command> <item> [minAmount] - Item can be the Item ID or the CraftBukkit Item Name, minAmount is the minimum amount to be considered.
searchender:
aliases: [se]
description: Searches and lists players that have a specific item in their ender chest.
usage: |
/<command> <item> [minAmount] - Item can be the Item ID or the CraftBukkit Item Name, minAmount is the minimum amount to be considered.
toggleopeninv:
aliases: [toi, toggleoi, toggleinv]
description: Toggles the item openinv function.
usage: |
/<command> [check] - Checks whether item openinv is enabled.
anychest:
aliases: [ac]
description: Toggles the any chest function, which allows opening of blocked chests.
usage: |
/<command> [check] - Checks whether any chest is enabled.
silentchest:
aliases: [sc, silent]
description: Toggles the silent chest function, which hides the animation of a chest when opened or closed, and suppresses the sound.
usage: |
/<command> [check] - Checks whether silent chest is enabled.

169
pom.xml
View file

@ -1,55 +1,128 @@
<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>
<groupId>com.lishid</groupId>
<artifactId>openinv</artifactId>
<packaging>jar</packaging>
<version>2.4.0</version>
<name>OpenInv</name>
<url>http://dev.bukkit.org/bukkit-plugins/openinv/</url>
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>
<groupId>com.lishid</groupId>
<artifactId>openinv</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<name>OpenInv</name>
<url>http://dev.bukkit.org/bukkit-plugins/openinv/</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<openinv.version>3.0.0-SNAPSHOT</openinv.version>
</properties>
<repositories>
<repository>
<id>bukkit-repo</id>
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
</repository>
</repositories>
<profiles>
<dependencies>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.11-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
<!--
~ N.B.: All dependencies for profiles are set in ./assembly/pom.xml
~
~ This is to prevent recursive dependencies. It's not ideal, but it works.
~ The parent project always builds first. Then, due to profile ordering here,
~ whatever modules are enabled are built. Finally, the assembly module is built,
~ which contains no actual code, but shades all its "dependencies" into one jar.
-->
<build>
<defaultGoal>clean install</defaultGoal>
<sourceDirectory>src/main/java</sourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<!--
~ This profile exists to simplify profile usage.
~ The interface and plugin modules should be built first to ensure that they are up to date.
-->
<profile>
<id>reactorbuildfirst</id>
<activation>
<property>
<name>!breakBuildProcess</name>
</property>
</activation>
<modules>
<module>internal</module>
<module>plugin</module>
</modules>
</profile>
<profile>
<id>latest</id>
<activation>
<property>
<name>latest</name>
<value>true</value>
</property>
</activation>
<modules>
<module>v1_11_R1</module>
</modules>
</profile>
<profile>
<id>all</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<modules>
<module>v1_11_R1</module>
</modules>
</profile>
<!--
~ This profile exists to fix reactor build order.
~ The assembly module must be built last to aggregate all active modules into the final jar.
-->
<profile>
<id>reactorbuildlast</id>
<activation>
<property>
<name>!breakBuildProcess</name>
</property>
</activation>
<modules>
<module>assembly</module>
</modules>
</profile>
</profiles>
<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<!-- Keep the file clean, don't include every single pom from all modules -->
<excludes>META-INF/maven/**</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

28
v1_11_R1/pom.xml Normal file
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>openinv</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>openinvadapter1_11_R1</artifactId>
<name>OpenInvAdapter1_11_R1</name>
<dependencies>
<dependency>
<groupId>com.lishid</groupId>
<artifactId>openinvplugin</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.11-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View file

@ -14,14 +14,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.lishid.openinv.internal;
package com.lishid.openinv.internal.v1_11_R1;
import java.util.Iterator;
import org.bukkit.craftbukkit.v1_11_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import com.lishid.openinv.OpenInv;
import com.lishid.openinv.internal.IAnySilentChest;
import org.bukkit.entity.Player;
import net.minecraft.server.v1_11_R1.AxisAlignedBB;
import net.minecraft.server.v1_11_R1.Block;
@ -38,7 +38,9 @@ import net.minecraft.server.v1_11_R1.TileEntity;
import net.minecraft.server.v1_11_R1.TileEntityChest;
import net.minecraft.server.v1_11_R1.World;
public class AnySilentChest {
import org.bukkit.craftbukkit.v1_11_R1.entity.CraftPlayer;
public class AnySilentChest implements IAnySilentChest {
private final OpenInv plugin;
@ -46,7 +48,8 @@ public class AnySilentChest {
this.plugin = plugin;
}
public boolean isAnyChestNeeded(Player p, int x, int y, int z) {
@Override
public boolean isAnyChestNeeded(Player p, int x, int y, int z) {
// FOR REFERENCE, LOOK AT net.minecraft.server.BlockChest
BlockPosition position = new BlockPosition(x, y, z);
EntityPlayer player = ((CraftPlayer) p).getHandle();
@ -86,9 +89,9 @@ public class AnySilentChest {
private boolean ocelotOnTop(World world, BlockPosition position) {
Iterator iterator = world.a(EntityOcelot.class,
new AxisAlignedBB((double) position.getX(), (double) (position.getY() + 1),
(double) position.getZ(), (double) (position.getX() + 1),
(double) (position.getY() + 2), (double) (position.getZ() + 1))).iterator();
new AxisAlignedBB(position.getX(), position.getY() + 1,
position.getZ(), position.getX() + 1,
position.getY() + 2, position.getZ() + 1)).iterator();
EntityOcelot entityOcelot;
@ -105,7 +108,8 @@ public class AnySilentChest {
return true;
}
public boolean activateChest(Player p, boolean anyChest, boolean silentChest, int x, int y, int z) {
@Override
public boolean activateChest(Player p, boolean anyChest, boolean silentChest, int x, int y, int z) {
BlockPosition position = new BlockPosition(x, y, z);
EntityPlayer player = ((CraftPlayer) p).getHandle();
World world = player.world;

View file

@ -1,4 +1,4 @@
package com.lishid.openinv.internal;
package com.lishid.openinv.internal.v1_11_R1;
import java.util.Iterator;

View file

@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.lishid.openinv.internal;
package com.lishid.openinv.internal.v1_11_R1;
import java.lang.reflect.Field;

View file

@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.lishid.openinv.internal;
package com.lishid.openinv.internal.v1_11_R1;
import java.util.UUID;

View file

@ -1,4 +1,4 @@
package com.lishid.openinv.internal;
package com.lishid.openinv.internal.v1_11_R1;
import java.util.List;

View file

@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.lishid.openinv.internal;
package com.lishid.openinv.internal.v1_11_R1;
import java.lang.reflect.Field;
import java.util.List;

View file

@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.lishid.openinv.internal;
package com.lishid.openinv.internal.v1_11_R1;
import java.lang.reflect.Field;