ShopChest/src/main/java/de/epiceric/shopchest/utils/ShopUtils.java

393 lines
14 KiB
Java
Raw Normal View History

2015-09-02 13:06:48 +02:00
package de.epiceric.shopchest.utils;
import de.epiceric.shopchest.ShopChest;
import de.epiceric.shopchest.config.Config;
import de.epiceric.shopchest.shop.Shop;
2017-05-22 20:21:13 +02:00
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
2015-09-02 13:06:48 +02:00
import org.bukkit.block.Chest;
import org.bukkit.block.DoubleChest;
import org.bukkit.entity.Player;
2015-09-02 13:06:48 +02:00
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.util.Vector;
2015-09-02 13:06:48 +02:00
import java.util.ArrayList;
2016-11-25 13:55:39 +01:00
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
2015-09-02 13:06:48 +02:00
public class ShopUtils {
private HashMap<Location, Shop> shopLocation = new HashMap<>();
2017-03-17 14:04:05 +01:00
private HashMap<Player, Location> playerLocation = new HashMap<>();
private ShopChest plugin;
public ShopUtils(ShopChest plugin) {
this.plugin = plugin;
}
2016-06-30 21:59:06 +02:00
/**
* Get the shop at a given location
*
* @param location Location of the shop
* @return Shop at the given location or <b>null</b> if no shop is found there
*/
public Shop getShop(Location location) {
Location newLocation = new Location(location.getWorld(), location.getX(), location.getY(), location.getZ());
return shopLocation.get(newLocation);
}
2016-06-30 21:59:06 +02:00
/**
* Checks whether there is a shop at a given location
* @param location Location to check
* @return Whether there is a shop at the given location
*/
public boolean isShop(Location location) {
Location newLocation = new Location(location.getWorld(), location.getX(), location.getY(), location.getZ());
return shopLocation.containsKey(newLocation);
}
2016-06-30 21:59:06 +02:00
/**
* Get all Shops
* @return Array of all Shops
*/
public Shop[] getShops() {
2016-11-25 13:55:39 +01:00
Collection<Shop> shops = shopLocation.values();
return shops.toArray(new Shop[shops.size()]);
}
2016-06-30 21:59:06 +02:00
/**
* Add a shop
* @param shop Shop to add
* @param addToDatabase Whether the shop should also be added to the database
*/
public void addShop(Shop shop, boolean addToDatabase) {
InventoryHolder ih = shop.getInventoryHolder();
plugin.debug("Adding shop... (#" + shop.getID() + ")");
if (ih instanceof DoubleChest) {
DoubleChest dc = (DoubleChest) ih;
Chest r = (Chest) dc.getRightSide();
Chest l = (Chest) dc.getLeftSide();
plugin.debug("Added shop as double chest. (#" + shop.getID() + ")");
shopLocation.put(r.getLocation(), shop);
shopLocation.put(l.getLocation(), shop);
} else {
plugin.debug("Added shop as single chest. (#" + shop.getID() + ")");
shopLocation.put(shop.getLocation(), shop);
}
if (addToDatabase)
plugin.getShopDatabase().addShop(shop, null);
}
2016-06-30 21:59:06 +02:00
/**
* Remove a shop
* @param shop Shop to remove
* @param removeFromDatabase Whether the shop should also be removed from the database
* @param useCurrentThread Whether the current thread should be used instead of a new async task
2016-06-30 21:59:06 +02:00
*/
public void removeShop(Shop shop, boolean removeFromDatabase, boolean useCurrentThread) {
plugin.debug("Removing shop (#" + shop.getID() + ")");
InventoryHolder ih = shop.getInventoryHolder();
if (ih instanceof DoubleChest) {
DoubleChest dc = (DoubleChest) ih;
Chest r = (Chest) dc.getRightSide();
Chest l = (Chest) dc.getLeftSide();
shopLocation.remove(r.getLocation());
shopLocation.remove(l.getLocation());
} else {
shopLocation.remove(shop.getLocation());
}
shop.removeItem();
shop.removeHologram(useCurrentThread);
if (removeFromDatabase)
plugin.getShopDatabase().removeShop(shop, null);
}
/**
* Remove a shop
* @param shop Shop to remove
* @param removeFromDatabase Whether the shop should also be removed from the database
*/
public void removeShop(Shop shop, boolean removeFromDatabase) {
removeShop(shop, removeFromDatabase, false);
}
2016-06-30 21:59:06 +02:00
/**
* Get the shop limits of a player
* @param p Player, whose shop limits should be returned
* @return The shop limits of the given player
*/
public int getShopLimit(Player p) {
int limit = 0;
boolean useDefault = true;
for (PermissionAttachmentInfo permInfo : p.getEffectivePermissions()) {
if (permInfo.getPermission().startsWith("shopchest.limit.") && p.hasPermission(permInfo.getPermission())) {
if (permInfo.getPermission().equalsIgnoreCase(Permissions.NO_LIMIT)) {
limit = -1;
useDefault = false;
break;
} else {
String[] spl = permInfo.getPermission().split("shopchest.limit.");
if (spl.length > 1) {
try {
int newLimit = Integer.valueOf(spl[1]);
if (newLimit < 0) {
limit = -1;
break;
}
limit = Math.max(limit, newLimit);
useDefault = false;
} catch (NumberFormatException ignored) {
/* Ignore and continue */
}
}
}
}
}
if (limit < -1) limit = -1;
return (useDefault ? plugin.getShopChestConfig().default_limit : limit);
}
2016-06-30 21:59:06 +02:00
/**
* Get the amount of shops of a player
* @param p Player, whose shops should be counted
* @return The amount of a shops a player has (if {@link Config#exclude_admin_shops} is true, admin shops won't be counted)
*/
public int getShopAmount(OfflinePlayer p) {
float shopCount = 0;
for (Shop shop : getShops()) {
if (shop.getVendor().equals(p)) {
if (shop.getShopType() != Shop.ShopType.ADMIN || !plugin.getShopChestConfig().exclude_admin_shops) {
shopCount++;
InventoryHolder ih = shop.getInventoryHolder();
if (ih instanceof DoubleChest)
shopCount -= 0.5;
}
}
}
return Math.round(shopCount);
}
2016-06-30 21:59:06 +02:00
/**
* Reload the shops
* @param reloadConfig Whether the configuration should also be reloaded
* @param showConsoleMessages Whether messages about the language file should be shown in the console
* @param callback Callback that - if succeeded - returns the amount of shops that were reloaded (as {@code int})
2016-06-30 21:59:06 +02:00
*/
2017-04-10 20:01:47 +02:00
public void reloadShops(boolean reloadConfig, final boolean showConsoleMessages, final Callback callback) {
plugin.debug("Reloading shops...");
if (reloadConfig) {
plugin.getShopChestConfig().reload(false, true, showConsoleMessages);
2017-05-22 20:21:13 +02:00
plugin.getHologramFormat().reload();
plugin.getUpdater().setMaxDelta(plugin.getShopChestConfig().update_quality.getTime());
}
plugin.getShopDatabase().connect(new Callback(plugin) {
@Override
public void onResult(Object result) {
for (Shop shop : getShops()) {
removeShop(shop, false);
plugin.debug("Removed shop (#" + shop.getID() + ")");
}
2017-04-10 20:01:47 +02:00
plugin.getShopDatabase().getShops(showConsoleMessages, new Callback(plugin) {
@Override
public void onResult(Object result) {
2017-02-09 21:51:39 +01:00
if (result instanceof Shop[]) {
Shop[] shops = (Shop[]) result;
for (Shop shop : shops) {
2017-04-10 20:01:47 +02:00
if (shop.create(showConsoleMessages)) {
2017-02-09 21:51:39 +01:00
addShop(shop, false);
}
}
2017-05-22 20:21:13 +02:00
for (Player player : Bukkit.getOnlinePlayers()) {
updateShops(player, true);
}
2017-02-09 21:51:39 +01:00
if (callback != null) callback.callSyncResult(shops.length);
}
}
2017-02-09 21:51:39 +01:00
@Override
public void onError(Throwable throwable) {
2017-02-10 18:13:16 +01:00
if (callback != null) callback.callSyncError(throwable);
2017-02-09 21:51:39 +01:00
plugin.debug("Error while adding shops");
plugin.debug(throwable);
}
});
}
});
}
/**
* Update hologram and item of all shops for a player
* @param player Player to show the updates
*/
2017-03-17 14:04:05 +01:00
public void updateShops(Player player) {
2017-05-22 20:21:13 +02:00
updateShops(player, false);
}
/**
* Update hologram and item of all shops for a player
* @param player Player to show the updates
* @param force Whether update should be forced even if player has not moved
*/
public void updateShops(Player player, boolean force) {
if (!force && player.getLocation().equals(playerLocation.get(player))) {
2017-03-17 14:04:05 +01:00
// Player has not moved, so don't calculate shops again.
return;
}
if (plugin.getShopChestConfig().only_show_shops_in_sight) {
Set<Block> sight = getBlocksInSight(player);
ArrayList<Shop> shopsInSight = new ArrayList<>();
for (Block block : sight) {
if (block.getType() == Material.CHEST || block.getType() == Material.TRAPPED_CHEST) {
Shop shop = getShop(block.getLocation());
if (shop != null) {
shopsInSight.add(shop);
if (shop.getHologram() != null && !shop.getHologram().isVisible(player)) {
shop.getHologram().showPlayer(player);
}
if (plugin.getShopChestConfig().only_show_first_shop_in_sight) break;
}
} else {
Block below = block.getRelative(BlockFace.DOWN);
Shop shop = getShop(below.getLocation());
if (shop != null) {
shopsInSight.add(shop);
if (shop.getHologram() != null && !shop.getHologram().isVisible(player)) {
shop.getHologram().showPlayer(player);
}
if (plugin.getShopChestConfig().only_show_first_shop_in_sight) break;
}
}
}
double itemDistSqr = Math.pow(plugin.getShopChestConfig().maximal_item_distance, 2);
for (Shop shop : getShops()) {
if (shop.getItem() != null && shop.getLocation().getWorld().getName().equals(player.getWorld().getName())) {
if (shop.getLocation().distanceSquared(player.getEyeLocation()) <= itemDistSqr) {
shop.getItem().setVisible(player, true);
} else {
shop.getItem().setVisible(player, false);
}
}
if (!shopsInSight.contains(shop)) {
if (shop.getHologram() != null) {
shop.getHologram().hidePlayer(player);
}
}
}
} else {
for (Shop shop : getShops()) {
2017-03-17 14:04:05 +01:00
updateShop(shop, player);
}
}
2017-03-17 14:04:05 +01:00
playerLocation.put(player, player.getLocation());
}
private Set<Block> getBlocksInSight(Player player) {
double dist = plugin.getShopChestConfig().maximal_distance;
Location loc = player.getEyeLocation();
Vector direction = loc.getDirection();
Set<Block> blocks = new HashSet<>();
blocks.add(loc.getBlock());
double i = 0;
do {
blocks.add(loc.add(direction).getBlock());
i++;
} while (i < dist - (dist%1));
direction.multiply(dist - (dist%1));
blocks.add(loc.add(direction).getBlock());
return blocks;
}
/**
* Update hologram and item of the shop for a player based on their distance to each other
* @param shop Shop to update
* @param player Player to show the update
*/
2017-03-17 14:04:05 +01:00
public void updateShop(Shop shop, Player player) {
2017-05-17 17:12:45 +02:00
if (!shop.getLocation().getChunk().isLoaded()) return;
double holoDistSqr = Math.pow(plugin.getShopChestConfig().maximal_distance, 2);
double itemDistSqr = Math.pow(plugin.getShopChestConfig().maximal_item_distance, 2);
2017-03-17 14:04:05 +01:00
if (player.getLocation().getWorld().getName().equals(shop.getLocation().getWorld().getName())) {
double distSqr = shop.getLocation().distanceSquared(player.getLocation());
if (distSqr <= holoDistSqr) {
if (shop.getHologram() != null) {
2017-02-05 17:22:37 +01:00
Material type = shop.getLocation().getBlock().getType();
2017-02-05 17:22:37 +01:00
if (type != Material.CHEST && type != Material.TRAPPED_CHEST) {
plugin.getShopUtils().removeShop(shop, plugin.getShopChestConfig().remove_shop_on_error);
return;
}
if (!shop.getHologram().isVisible(player)) {
shop.getHologram().showPlayer(player);
}
}
} else {
2017-02-05 17:22:37 +01:00
if (shop.getHologram() != null) {
shop.getHologram().hidePlayer(player);
}
}
if (distSqr <= itemDistSqr) {
if (shop.getItem() != null) {
shop.getItem().setVisible(player, true);
}
} else {
if (shop.getItem() != null) shop.getItem().setVisible(player, false);
}
}
}
2015-09-02 13:06:48 +02:00
}