From 7f8af7b5b32b443e4f7ef5dddd57ecd27ac6b65d Mon Sep 17 00:00:00 2001 From: Acrobot Date: Thu, 1 Mar 2012 22:03:59 +0100 Subject: [PATCH] Breaking changes: - Permissions 2/3 are no longer supported - Changed ChestShop.shop.create permission to consist of 2 different permissions: ChestShop.shop.create.buy and ChestShop.shop.create.sell - (Experimental) Ability to add max item prices to the config - (Experimental) Added a custom "chestshop" WorldGuard flag using reflection - Switched to new Config system - Updated Metrics - Removed chest masking option --- .../ChestShop/BukkitFixes/bInventoryFix.java | 30 + com/Acrobot/ChestShop/ChestShop.java | 19 +- .../ChestShop/Chests/MinecraftChest.java | 2 +- com/Acrobot/ChestShop/Config/Config.java | 8 + .../ChestShop/Config/ConfigObject.java | 45 +- com/Acrobot/ChestShop/Config/MaxPrice.java | 29 + com/Acrobot/ChestShop/Config/Property.java | 3 +- com/Acrobot/ChestShop/DB/Generator.java | 13 +- com/Acrobot/ChestShop/DB/Queue.java | 3 +- com/Acrobot/ChestShop/Items/Items.java | 2 + .../ChestShop/Listeners/playerInteract.java | 15 +- .../ChestShop/Listeners/pluginEnable.java | 13 +- .../ChestShop/Listeners/signChange.java | 31 +- com/Acrobot/ChestShop/Metrics.java | 536 ++++++++++++++---- com/Acrobot/ChestShop/Permission.java | 13 +- .../ChestShop/Protection/MaskChest.java | 62 -- .../ChestShop/Signs/restrictedSign.java | 3 - .../Utils/WorldGuard/uWorldGuard.java | 87 +++ com/Acrobot/ChestShop/Utils/uLongName.java | 16 +- com/Acrobot/ChestShop/Utils/uWorldGuard.java | 18 - .../payment/forChestShop/methods/BOSE6.java | 4 +- .../payment/forChestShop/methods/EE17.java | 4 +- .../payment/forChestShop/methods/MCUR.java | 2 +- .../payment/forChestShop/methods/iCo4.java | 2 +- .../payment/forChestShop/methods/iCo5.java | 4 +- .../payment/forChestShop/methods/iCo6.java | 2 +- plugin.yml | 15 +- 27 files changed, 679 insertions(+), 302 deletions(-) create mode 100644 com/Acrobot/ChestShop/BukkitFixes/bInventoryFix.java create mode 100644 com/Acrobot/ChestShop/Config/MaxPrice.java delete mode 100644 com/Acrobot/ChestShop/Protection/MaskChest.java create mode 100644 com/Acrobot/ChestShop/Utils/WorldGuard/uWorldGuard.java delete mode 100644 com/Acrobot/ChestShop/Utils/uWorldGuard.java diff --git a/com/Acrobot/ChestShop/BukkitFixes/bInventoryFix.java b/com/Acrobot/ChestShop/BukkitFixes/bInventoryFix.java new file mode 100644 index 0000000..bc9a8e3 --- /dev/null +++ b/com/Acrobot/ChestShop/BukkitFixes/bInventoryFix.java @@ -0,0 +1,30 @@ +package com.Acrobot.ChestShop.BukkitFixes; + +import com.Acrobot.ChestShop.Chests.MinecraftChest; +import net.minecraft.server.TileEntityChest; +import org.bukkit.block.Chest; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.inventory.CraftInventory; +import org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest; +import org.bukkit.inventory.Inventory; + +/** + * Temporary class until this is fixed in Bukkit + * @author Acrobot + */ +public class bInventoryFix { + public static Inventory getInventory(Chest chest) { + MinecraftChest mchest = new MinecraftChest(chest); + + TileEntityChest teChest = (TileEntityChest) ((CraftWorld) chest.getWorld()).getTileEntityAt(chest.getX(), chest.getY(), chest.getZ()); + CraftInventory ci = new CraftInventory(teChest); + + if (mchest.getNeighbor() != null) { + Chest nb = mchest.getNeighbor(); + TileEntityChest neighbor = (TileEntityChest) ((CraftWorld) chest.getWorld()).getTileEntityAt(nb.getX(), nb.getY(), nb.getZ()); + return new CraftInventoryDoubleChest(ci, new CraftInventory(neighbor)); + } + + return ci; + } +} diff --git a/com/Acrobot/ChestShop/ChestShop.java b/com/Acrobot/ChestShop/ChestShop.java index 7afc1b2..92eaa64 100644 --- a/com/Acrobot/ChestShop/ChestShop.java +++ b/com/Acrobot/ChestShop/ChestShop.java @@ -13,10 +13,10 @@ import com.Acrobot.ChestShop.Logging.FileWriterQueue; import com.avaje.ebean.EbeanServer; import com.lennardf1989.bukkitex.Database; import org.bukkit.Server; +import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; -import org.bukkit.util.config.Configuration; import java.io.File; import java.util.ArrayList; @@ -56,7 +56,6 @@ public class ChestShop extends JavaPlugin { if (Config.getBoolean(Property.LOG_TO_DATABASE) || Config.getBoolean(Property.GENERATE_STATISTICS_PAGE)) setupDB(); if (Config.getBoolean(Property.GENERATE_STATISTICS_PAGE)) scheduleTask(new Generator(), 300L, (long) Config.getDouble(Property.STATISTICS_PAGE_GENERATION_INTERVAL) * 20L); if (Config.getBoolean(Property.LOG_TO_FILE)) scheduleTask(new FileWriterQueue(), 201L, 201L); - //if (Config.getBoolean(Property.MASK_CHESTS_AS_OTHER_BLOCKS)) scheduleTask(new MaskChest(), 40L, 40L); //Disabled due to bug //TODO Fix that playerInteract.interval = Config.getInteger(Property.SHOP_INTERACTION_INTERVAL); //Register our commands! @@ -65,12 +64,10 @@ public class ChestShop extends JavaPlugin { //Start the statistics pinger startStatistics(); - - System.out.println('[' + getPluginName() + "] version " + getVersion() + " initialized!"); } public void onDisable() { - System.out.println('[' + getPluginName() + "] version " + getVersion() + " shutting down!"); + getServer().getScheduler().cancelTasks(this); } ////////////////// REGISTER EVENTS, SCHEDULER & STATS /////////////////////////// @@ -97,10 +94,8 @@ public class ChestShop extends JavaPlugin { } ///////////////////// DATABASE STUFF //////////////////////////////// - private static Configuration getBukkitConfig() { - Configuration config = new Configuration(new File("bukkit.yml")); - config.load(); - return config; + private static YamlConfiguration getBukkitConfig() { + return YamlConfiguration.loadConfiguration(new File("bukkit.yml")); } private static Database database; @@ -114,7 +109,7 @@ public class ChestShop extends JavaPlugin { } }; - Configuration config = getBukkitConfig(); + YamlConfiguration config = getBukkitConfig(); database.initializeDatabase( config.getString("database.driver"), @@ -150,7 +145,7 @@ public class ChestShop extends JavaPlugin { return DB; } - public static ArrayList getDependencies() { - return (ArrayList) description.getSoftDepend(); + public static List getDependencies() { + return (List) description.getSoftDepend(); } } diff --git a/com/Acrobot/ChestShop/Chests/MinecraftChest.java b/com/Acrobot/ChestShop/Chests/MinecraftChest.java index 8e6ccf1..4165cd8 100644 --- a/com/Acrobot/ChestShop/Chests/MinecraftChest.java +++ b/com/Acrobot/ChestShop/Chests/MinecraftChest.java @@ -74,7 +74,7 @@ public class MinecraftChest implements ChestObject { return main.getInventory().getSize() + (neighbor != null ? neighbor.getInventory().getSize() : 0); } - private Chest getNeighbor() { + public Chest getNeighbor() { return uBlock.findNeighbor(main); } diff --git a/com/Acrobot/ChestShop/Config/Config.java b/com/Acrobot/ChestShop/Config/Config.java index e657f2c..77483bc 100644 --- a/com/Acrobot/ChestShop/Config/Config.java +++ b/com/Acrobot/ChestShop/Config/Config.java @@ -20,6 +20,10 @@ public class Config { public static float getFloat(Property value) { return new Float(getValue(value.name()).toString()); } + + public static float getFloat(String value) { + return new Float(getValue(value).toString()); + } public static String getString(Property value) { return (String) getValue(value.name()); @@ -40,6 +44,10 @@ public class Config { public static String getLocal(Language lang) { return getColored(config.getLanguageConfig().getString(Language.prefix.name()) + config.getLanguageConfig().getString(lang.name())); } + + public static boolean exists(String value) { + return getValue(value) != null; + } private static Object getValue(String node) { return config.getProperty(node); diff --git a/com/Acrobot/ChestShop/Config/ConfigObject.java b/com/Acrobot/ChestShop/Config/ConfigObject.java index ba7c548..4ce945c 100644 --- a/com/Acrobot/ChestShop/Config/ConfigObject.java +++ b/com/Acrobot/ChestShop/Config/ConfigObject.java @@ -2,7 +2,9 @@ package com.Acrobot.ChestShop.Config; import com.Acrobot.ChestShop.ChestShop; import com.Acrobot.ChestShop.Utils.uLongName; -import org.bukkit.util.config.Configuration; +import org.bukkit.configuration.Configuration; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; import java.io.File; import java.io.FileWriter; @@ -13,35 +15,33 @@ import java.io.FileWriter; public class ConfigObject { private final File configFile = new File(ChestShop.folder, "config.yml"); private final File langFile = new File(ChestShop.folder, "local.yml"); - private final Configuration config = new Configuration(configFile); - private final Configuration language = new Configuration(langFile); + private final YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); + private final YamlConfiguration language = YamlConfiguration.loadConfiguration(langFile); public ConfigObject() { if (!ChestShop.folder.exists()) ChestShop.folder.mkdir(); reloadConfig(); - config.load(); + load(config, configFile); reloadLanguage(); - language.load(); + load(language, langFile); - uLongName.config = new Configuration(new File(ChestShop.folder, "longName.storage")); - uLongName.config.load(); + uLongName.configFile = new File(ChestShop.folder, "longName.storage"); + uLongName.config = YamlConfiguration.loadConfiguration(uLongName.configFile); } private void reloadConfig() { - config.load(); for (Property def : Property.values()) { - if (config.getProperty(def.name()) == null) { + if (config.get(def.name()) == null) { writeToFile('\n' + def.name() + ": " + def.getValue() + "\n#" + def.getComment(), configFile); } } } private void reloadLanguage() { - language.load(); for (Language def : Language.values()) { - if (language.getProperty(def.name()) == null) { + if (language.get(def.name()) == null) { writeToFile('\n' + def.name() + ": \"" + def.toString() + '\"', langFile); } } @@ -62,6 +62,27 @@ public class ConfigObject { } public Object getProperty(String property) { - return config.getProperty(property); + return config.get(property); + } + + public static void load(FileConfiguration config, File file) { + try { + config.load(file); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static void save(FileConfiguration config, File file) { + try { + config.save(file); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static void reloadConfig(FileConfiguration config, File file) { + save(config, file); + load(config, file); } } diff --git a/com/Acrobot/ChestShop/Config/MaxPrice.java b/com/Acrobot/ChestShop/Config/MaxPrice.java new file mode 100644 index 0000000..1248d46 --- /dev/null +++ b/com/Acrobot/ChestShop/Config/MaxPrice.java @@ -0,0 +1,29 @@ +package com.Acrobot.ChestShop.Config; + +import org.bukkit.Material; + +/** + * @author Acrobot + */ +public class MaxPrice { + public static boolean canCreate(float buyPrice, float sellPrice, Material mat) { + float bPrice = maxBuyPrice(mat.getId()); + float sPrice = maxSellPrice(mat.getId()); + + return (bPrice == -1 || buyPrice <= maxBuyPrice(mat.getId())) + && (sPrice == -1 || sellPrice <= maxSellPrice(mat.getId())); + } + + public static float maxBuyPrice(int itemID) { + return getPrice("buy", itemID); + } + + public static float maxSellPrice(int itemID) { + return getPrice("sell", itemID); + } + + public static float getPrice(String value, int itemID) { + String node = "max-" + value + "-price-" + itemID; + return Config.exists(node) ? Config.getFloat(node) : -1; + } +} diff --git a/com/Acrobot/ChestShop/Config/Property.java b/com/Acrobot/ChestShop/Config/Property.java index 5368b46..f67d5f0 100644 --- a/com/Acrobot/ChestShop/Config/Property.java +++ b/com/Acrobot/ChestShop/Config/Property.java @@ -21,14 +21,13 @@ public enum Property { USE_BUILT_IN_PROTECTION(true, "Do you want to use built-in protection against chest destruction?"), PROTECT_CHEST_WITH_LWC(false, "Do you want to protect shop chests with LWC?"), PROTECT_SIGN_WITH_LWC(false, "Do you want to protect shop signs with LWC?"), - //MASK_CHESTS_AS_OTHER_BLOCKS(false, "Do you want to mask shop chests as other blocks? HIGHLY EXPERIMENTAL, CAN LAG!"), IGNORE_CREATIVE_MODE(true, "Do you want to allow using shops to people in creative mode?"), SHOW_MESSAGE_OUT_OF_STOCK(true, "Do you want to show \"Out of stock\" messages?"), SHOW_TRANSACTION_INFORMATION_CLIENT(true, "Do you want to show \"You bought/sold... \" messages?"), SHOW_TRANSACTION_INFORMATION_OWNER(true, "Do you want to show \"Somebody bought/sold... \" messages?"), TOWNY_INTEGRATION(false, "Do you want to only let people build inside shop plots?"), TOWNY_SHOPS_FOR_OWNERS_ONLY(true, "If true, only plot owners are able to build inside a shop plot. If false, every town's resident is able to build there."), - WORLDGUARD_INTEGRATION(false, "Do you want to only let people build inside plots?"), + WORLDGUARD_INTEGRATION(false, "Do you want to only let people build inside regions with /region flag chestshop allowed?"), TAX_AMOUNT(0, "Percent of the price that should go to the server's account. (100 = 100 percent)"), SERVER_TAX_AMOUNT(0, "Percent of the price that should go to the server's account when buying from an Admin Shop"), SHOP_REFUND_PRICE(0, "How much money do you get back when destroying a sign?"), diff --git a/com/Acrobot/ChestShop/DB/Generator.java b/com/Acrobot/ChestShop/DB/Generator.java index ea1437d..90228ff 100644 --- a/com/Acrobot/ChestShop/DB/Generator.java +++ b/com/Acrobot/ChestShop/DB/Generator.java @@ -17,13 +17,17 @@ public class Generator implements Runnable { private static double generationTime; - private static final String header = fileToString("header"); - private static final String row = fileToString("row"); - private static final String footer = fileToString("footer"); + private static String header; + private static String row; + private static String footer; private static BufferedWriter buf; public void run() { + header = fileToString("header"); + row = fileToString("row"); + footer = fileToString("footer"); + if (row.isEmpty()) System.out.println(ChestShop.chatPrefix + "You lack the necessary HTML files in your plugins/ChestShop/HTML folder!"); generateStats(); } @@ -42,7 +46,7 @@ public class Generator implements Runnable { private static String fileToString(String fileName) { try { - File f = new File(ChestShop.folder + "/HTML/" + fileName + ".html"); + File f = new File(ChestShop.folder + File.separator + "HTML" + File.separator + fileName + ".html"); FileReader rd = new FileReader(f); char[] buf = new char[(int) f.length()]; rd.read(buf); @@ -113,6 +117,7 @@ public class Generator implements Runnable { private static void generateStats() { try { + File f = new File(filePath).getParentFile(); if (!f.exists()) f.mkdir(); diff --git a/com/Acrobot/ChestShop/DB/Queue.java b/com/Acrobot/ChestShop/DB/Queue.java index 336151b..d6ce89c 100644 --- a/com/Acrobot/ChestShop/DB/Queue.java +++ b/com/Acrobot/ChestShop/DB/Queue.java @@ -19,7 +19,8 @@ public class Queue implements Runnable { } public void run() { - deleteOld(); + if (Config.getInteger(Property.RECORD_TIME_TO_LIVE) != -1) + deleteOld(); ChestShop.getDB().save(queue); queue.clear(); diff --git a/com/Acrobot/ChestShop/Items/Items.java b/com/Acrobot/ChestShop/Items/Items.java index a521bcf..71fe55b 100644 --- a/com/Acrobot/ChestShop/Items/Items.java +++ b/com/Acrobot/ChestShop/Items/Items.java @@ -58,6 +58,8 @@ public class Items { String first = split[0]; String[] space = first.split(" "); + if (space.length == 0) return null; + Material material = getMaterial(first); for (int i = (space.length > 1 ? 1 : 0); i >= 0 && material == null; i--) material = getMaterial(space[i]); diff --git a/com/Acrobot/ChestShop/Listeners/playerInteract.java b/com/Acrobot/ChestShop/Listeners/playerInteract.java index e0ff02e..1c2a0cb 100644 --- a/com/Acrobot/ChestShop/Listeners/playerInteract.java +++ b/com/Acrobot/ChestShop/Listeners/playerInteract.java @@ -1,5 +1,6 @@ package com.Acrobot.ChestShop.Listeners; +import com.Acrobot.ChestShop.BukkitFixes.bInventoryFix; import com.Acrobot.ChestShop.Config.Config; import com.Acrobot.ChestShop.Config.Language; import com.Acrobot.ChestShop.Config.Property; @@ -9,21 +10,18 @@ import com.Acrobot.ChestShop.Shop.ShopManagement; import com.Acrobot.ChestShop.Signs.restrictedSign; import com.Acrobot.ChestShop.Utils.uBlock; import com.Acrobot.ChestShop.Utils.uSign; -import net.minecraft.server.IInventory; -import net.minecraft.server.InventoryLargeChest; import org.bukkit.GameMode; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.Chest; import org.bukkit.block.Sign; -import org.bukkit.craftbukkit.entity.CraftPlayer; -import org.bukkit.craftbukkit.inventory.CraftInventory; import org.bukkit.entity.Player; 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.PlayerInteractEvent; +import org.bukkit.inventory.Inventory; import java.util.HashMap; @@ -96,12 +94,7 @@ public class playerInteract implements Listener { player.sendMessage(Config.getLocal(Language.NO_CHEST_DETECTED)); return; } - - IInventory inventory = ((CraftInventory) chest.getInventory()).getInventory(); - chest = uBlock.findNeighbor(chest); - - if (chest != null) inventory = new InventoryLargeChest("Large chest", inventory, ((CraftInventory) chest.getInventory()).getInventory()); - - ((CraftPlayer) player).getHandle().a(inventory); //Show inventory on the screen + Inventory chestInv = bInventoryFix.getInventory(chest); + player.openInventory(chestInv); } } diff --git a/com/Acrobot/ChestShop/Listeners/pluginEnable.java b/com/Acrobot/ChestShop/Listeners/pluginEnable.java index 2e737ee..e508c34 100644 --- a/com/Acrobot/ChestShop/Listeners/pluginEnable.java +++ b/com/Acrobot/ChestShop/Listeners/pluginEnable.java @@ -5,17 +5,15 @@ import com.Acrobot.ChestShop.Economy.NoProvider; import com.Acrobot.ChestShop.Economy.Register; import com.Acrobot.ChestShop.Economy.Vault; import com.Acrobot.ChestShop.Items.Odd; -import com.Acrobot.ChestShop.Permission; import com.Acrobot.ChestShop.Protection.Plugins.*; import com.Acrobot.ChestShop.Protection.Security; +import com.Acrobot.ChestShop.Utils.WorldGuard.uWorldGuard; import com.Acrobot.ChestShop.Utils.uHeroes; import com.Acrobot.ChestShop.Utils.uNumber; import com.Acrobot.ChestShop.Utils.uSign; -import com.Acrobot.ChestShop.Utils.uWorldGuard; import com.daemitus.deadbolt.Deadbolt; import com.griefcraft.lwc.LWCPlugin; import com.herocraftonline.dev.heroes.Heroes; -import com.nijikokun.bukkit.Permissions.Permissions; import com.nijikokun.register.payment.forChestShop.Method; import com.nijikokun.register.payment.forChestShop.Methods; import com.palmergames.bukkit.towny.Towny; @@ -50,14 +48,12 @@ public class pluginEnable { } Register.eco = m; com.Acrobot.ChestShop.Economy.Economy.economy = new Register(); - System.out.println(ChestShop.chatPrefix + m.getName() + " loaded."); + System.out.println(ChestShop.chatPrefix + m.getName() + " version " + m.getName() + " loaded."); } } private static void initializePlugin(String name, Plugin plugin) { //Really messy, right? But it's short and fast :) - if (name.equals("Permissions")) { - Permission.permissions = ((Permissions) plugin).getHandler(); - } else if (name.equals("LWC")) { + if (name.equals("LWC")) { LWCplugin.setLWC(((LWCPlugin) plugin).getLWC()); Security.protections.add(new LWCplugin()); } else if (name.equals("Lockette")) { @@ -77,6 +73,7 @@ public class pluginEnable { uSign.towny = (Towny) plugin; } else if (name.equals("WorldGuard")) { uWorldGuard.worldGuard = (WorldGuardPlugin) plugin; + uWorldGuard.injectHax(); //Inject hax into WorldGuard } else if (name.equals("Vault")) { if (com.Acrobot.ChestShop.Economy.Economy.economy != null) return; RegisteredServiceProvider rsp = ChestShop.getBukkitServer().getServicesManager().getRegistration(Economy.class); @@ -90,6 +87,8 @@ public class pluginEnable { } else if (name.equals("SimpleChestLock")) { SCLplugin.scl = (SCL) plugin; Security.protections.add(new SCLplugin()); + } else { + return; } PluginDescriptionFile description = plugin.getDescription(); diff --git a/com/Acrobot/ChestShop/Listeners/signChange.java b/com/Acrobot/ChestShop/Listeners/signChange.java index bb878c0..50754a4 100644 --- a/com/Acrobot/ChestShop/Listeners/signChange.java +++ b/com/Acrobot/ChestShop/Listeners/signChange.java @@ -2,6 +2,7 @@ package com.Acrobot.ChestShop.Listeners; import com.Acrobot.ChestShop.Config.Config; import com.Acrobot.ChestShop.Config.Language; +import com.Acrobot.ChestShop.Config.MaxPrice; import com.Acrobot.ChestShop.Config.Property; import com.Acrobot.ChestShop.Economy.Economy; import com.Acrobot.ChestShop.Items.Items; @@ -9,6 +10,7 @@ import com.Acrobot.ChestShop.Permission; import com.Acrobot.ChestShop.Protection.Security; import com.Acrobot.ChestShop.Signs.restrictedSign; import com.Acrobot.ChestShop.Utils.*; +import com.Acrobot.ChestShop.Utils.WorldGuard.uWorldGuard; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -38,18 +40,12 @@ public class signChange implements Listener { boolean playerIsAdmin = Permission.has(player, Permission.ADMIN); - if (isAlmostReady) { if (mat == null) { player.sendMessage(Config.getLocal(Language.INCORRECT_ITEM_ID)); dropSign(event); return; } - if (!canCreateShop(player, mat.getId())) { - player.sendMessage(Config.getLocal(Language.YOU_CANNOT_CREATE_SHOP)); - dropSign(event); - return; - } } else { if (restrictedSign.isRestricted(line)) { if (!restrictedSign.hasPermission(player, line)) { @@ -91,8 +87,9 @@ public class signChange implements Listener { } Block chestBlock = chest.getBlock(); + boolean cantBuildTowny = uSign.towny != null && !uTowny.canBuild(player, signBlock.getLocation(), chestBlock.getLocation()); - if (!uWorldGuard.isNotOutsideWGplot(signBlock.getLocation()) || (uSign.towny != null && !uTowny.canBuild(player, signBlock.getLocation(), chestBlock.getLocation()))) { + if (!uWorldGuard.canBuildShopHere(signBlock.getLocation()) && cantBuildTowny){ player.sendMessage(Config.getLocal(Language.TOWNY_CANNOT_CREATE_SHOP_HERE)); dropSign(event); return; @@ -107,7 +104,14 @@ public class signChange implements Listener { } } + float buyPrice = uSign.buyPrice(thirdLine); + float sellPrice = uSign.sellPrice(thirdLine); + if (!playerIsAdmin && (!canCreateShop(player, mat.getId(), buyPrice != -1, sellPrice != -1) || !MaxPrice.canCreate(buyPrice, sellPrice, mat))) { + player.sendMessage(Config.getLocal(Language.YOU_CANNOT_CREATE_SHOP)); + dropSign(event); + return; + } float shopCreationPrice = Config.getFloat(Property.SHOP_CREATION_PRICE); boolean paid = shopCreationPrice != 0 && !isAdminShop && !Permission.has(player, Permission.NOFEE); @@ -134,14 +138,13 @@ public class signChange implements Listener { uHeroes.addHeroExp(player); } - private static boolean canCreateShop(Player player, boolean isAdmin, int ID) { - return isAdmin || - Permission.has(player, Permission.SHOP_CREATION) || - Permission.has(player, Permission.SHOP_CREATION.toString() + '.' + ID); - } + private static boolean canCreateShop(Player player, int ID, boolean buy, boolean sell) { + if (Permission.has(player, Permission.SHOP_CREATION_ID + Integer.toString(ID))) return true; + + if (buy && !Permission.has(player, Permission.SHOP_CREATION_BUY)) return false; + if (sell && !Permission.has(player, Permission.SHOP_CREATION_SELL)) return false; - private static boolean canCreateShop(Player player, int ID) { - return canCreateShop(player, Permission.has(player, Permission.ADMIN), ID); + return true; } private static String formatThirdLine(String thirdLine) { diff --git a/com/Acrobot/ChestShop/Metrics.java b/com/Acrobot/ChestShop/Metrics.java index 89f4740..ede5419 100644 --- a/com/Acrobot/ChestShop/Metrics.java +++ b/com/Acrobot/ChestShop/Metrics.java @@ -1,92 +1,63 @@ -package com.Acrobot.ChestShop;/* -* Copyright 2011 Tyler Blair. All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, are -* permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this list of -* conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, this list -* of conditions and the following disclaimer in the documentation and/or other materials -* provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED -* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR -* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -* The views and conclusions contained in the software and documentation are those of the -* authors and contributors and should not be interpreted as representing official policies, -* either expressed or implied, of anybody else. -*/ +package com.Acrobot.ChestShop; + +/* + * Copyright 2011 Tyler Blair. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and contributors and should not be interpreted as representing official policies, + * either expressed or implied, of anybody else. + */ import org.bukkit.Bukkit; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginDescriptionFile; -import java.io.*; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; +import java.net.Proxy; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; -import java.util.*; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; -/** - * Tooling to post to metrics.griefcraft.com - */ public class Metrics { /** - * Interface used to collect custom data for a plugin + * The current revision number */ - public static abstract class Plotter { - - /** - * Get the column name for the plotted point - * - * @return the plotted point's column name - */ - public abstract String getColumnName(); - - /** - * Get the current value for the plotted point - * - * @return - */ - public abstract int getValue(); - - /** - * Called after the website graphs have been updated - */ - public void reset() { - } - - @Override - public int hashCode() { - return getColumnName().hashCode() + getValue(); - } - - @Override - public boolean equals(Object object) { - if (!(object instanceof Plotter)) { - return false; - } - - Plotter plotter = (Plotter) object; - return plotter.getColumnName().equals(getColumnName()) && plotter.getValue() == getValue(); - } - - } - - /** - * The metrics revision number - */ - private final static int REVISION = 4; + private final static int REVISION = 5; /** * The base url of the metrics domain @@ -104,14 +75,25 @@ public class Metrics { private static final String CONFIG_FILE = "plugins/PluginMetrics/config.yml"; /** - * Interval of time to ping in minutes + * The separator to use for custom data. This MUST NOT change unless you are hosting your own + * version of metrics and want to change it. + */ + private static final String CUSTOM_DATA_SEPARATOR = "~~"; + + /** + * Interval of time to ping (in minutes) */ private final static int PING_INTERVAL = 10; /** - * A map of the custom data plotters for plugins + * A map of all of the graphs for each plugin */ - private Map> customData = Collections.synchronizedMap(new HashMap>()); + private Map> graphs = Collections.synchronizedMap(new HashMap>()); + + /** + * A convenient map of the default Graph objects (used by addCustomData mainly) + */ + private Map defaultGraphs = Collections.synchronizedMap(new HashMap()); /** * The plugin configuration file @@ -142,6 +124,33 @@ public class Metrics { guid = configuration.getString("guid"); } + /** + * Construct and create a Graph that can be used to separate specific plotters to their own graphs + * on the metrics website. Plotters can be added to the graph object returned. + * + * @param plugin + * @param type + * @param name + * @return Graph object created. Will never return NULL under normal circumstances unless bad parameters are given + */ + public Graph createGraph(Plugin plugin, Graph.Type type, String name) { + if (plugin == null || type == null || name == null) { + throw new IllegalArgumentException("All arguments must not be null"); + } + + // Construct the graph object + Graph graph = new Graph(type, name); + + // Get the graphs for the plugin + Set graphs = getOrCreateGraphs(plugin); + + // Now we can add our graph + graphs.add(graph); + + // and return back + return graph; + } + /** * Adds a custom data plotter for a given plugin * @@ -149,14 +158,14 @@ public class Metrics { * @param plotter */ public void addCustomData(Plugin plugin, Plotter plotter) { - Set plotters = customData.get(plugin); + // The default graph for the plugin + Graph graph = getOrCreateDefaultGraph(plugin); - if (plotters == null) { - plotters = Collections.synchronizedSet(new LinkedHashSet()); - customData.put(plugin, plotters); - } + // Add the plotter to the graph o/ + graph.addPlotter(plotter); - plotters.add(plotter); + // Ensure the default graph is included in the submitted graphs + getOrCreateGraphs(plugin).add(graph); } /** @@ -164,33 +173,31 @@ public class Metrics { * * @param plugin */ - public void beginMeasuringPlugin(final Plugin plugin) throws IOException { + public void beginMeasuringPlugin(final Plugin plugin) { // Did we opt out? if (configuration.getBoolean("opt-out", false)) { return; } - // First tell the server about us - plugin.getServer().getScheduler().scheduleAsyncDelayedTask(plugin, new Runnable() { - public void run() { - try { - postPlugin(plugin, false); - } catch (IOException e) { - System.out.println("[Metrics] " + e.getMessage()); - } - } - }, 20L); - - // Ping the server in intervals + // Begin hitting the server with glorious data plugin.getServer().getScheduler().scheduleAsyncRepeatingTask(plugin, new Runnable() { + private boolean firstPost = true; + public void run() { try { - postPlugin(plugin, true); + // We use the inverse of firstPost because if it is the first time we are posting, + // it is not a interval ping, so it evaluates to FALSE + // Each time thereafter it will evaluate to TRUE, i.e PING! + postPlugin(plugin, !firstPost); + + // After the first post we set firstPost to false + // Each post thereafter will be a ping + firstPost = false; } catch (IOException e) { System.out.println("[Metrics] " + e.getMessage()); } } - }, PING_INTERVAL * 1200, PING_INTERVAL * 1200); + }, 0, PING_INTERVAL * 1200); } /** @@ -199,26 +206,61 @@ public class Metrics { * @param plugin */ private void postPlugin(Plugin plugin, boolean isPing) throws IOException { + // The plugin's description file containg all of the plugin data such as name, version, author, etc + PluginDescriptionFile description = plugin.getDescription(); + + // The author string, created with description.getAuthors() + // Authors are separated by a comma + String authors = ""; + + // Add each author to the string + for (String author : description.getAuthors()) { + authors += author + ", "; + } + + // If there were any authors at all, we need to remove the last 2 characters + // the last 2 characters are the last comma and space + if (!authors.isEmpty()) { + authors = authors.substring(0, authors.length() - 2); + } + // Construct the post data - String response = "ERR No response"; - StringBuilder data = new StringBuilder(10); - data.append(encode("guid")).append('=').append(encode(guid)) - .append(gField("version", plugin.getDescription().getVersion())) - .append(gField("server", Bukkit.getVersion())) - .append(gField("players", String.valueOf(Bukkit.getServer().getOnlinePlayers().length))) - .append(gField("revision", String.valueOf(REVISION))); + String data = encode("guid") + '=' + encode(guid) + + encodeDataPair("authors", authors) + + encodeDataPair("version", description.getVersion()) + + encodeDataPair("server", Bukkit.getVersion()) + + encodeDataPair("players", Integer.toString(Bukkit.getServer().getOnlinePlayers().length)) + + encodeDataPair("revision", String.valueOf(REVISION)); // If we're pinging, append it if (isPing) { - data.append(gField("ping", "true")); + data += encodeDataPair("ping", "true"); } - // Add any custom data (if applicable) - Set plotters = customData.get(plugin); + // Add any custom data available for the plugin + Set graphs = getOrCreateGraphs(plugin); - if (plotters != null) { - for (Plotter plotter : plotters) { - data.append(gField("Custom" + plotter.getColumnName(), Integer.toString(plotter.getValue()))); + // Acquire a lock on the graphs, which lets us make the assumption we also lock everything + // inside of the graph (e.g plotters) + synchronized(graphs) { + for (Graph graph : graphs) { + // Because we have a lock on the graphs set already, it is reasonable to assume + // that our lock transcends down to the individual plotters in the graphs also. + // Because our methods are private, no one but us can reasonably access this list + // without reflection so this is a safe assumption without adding more code. + for (Plotter plotter : graph.getPlotters()) { + // The key name to send to the metrics server + // The format is C-GRAPHNAME-PLOTTERNAME where separator - is defined at the top + // Legacy (R4) submitters use the format Custom%s, or CustomPLOTTERNAME + String key = String.format("C%s%s%s%s", CUSTOM_DATA_SEPARATOR, graph.getName(), CUSTOM_DATA_SEPARATOR, plotter.getColumnName()); + + // The value to send, which for the foreseeable future is just the string + // value of plotter.getValue() + String value = Integer.toString(plotter.getValue()); + + // Add it to the http post data :) + data += encodeDataPair(key, value); + } } } @@ -226,17 +268,26 @@ public class Metrics { URL url = new URL(BASE_URL + String.format(REPORT_URL, plugin.getDescription().getName())); // Connect to the website - URLConnection connection = url.openConnection(); + URLConnection connection; + + // Mineshafter creates a socks proxy, so we can safely bypass it + // It does not reroute POST requests so we need to go around it + if (isMineshafterPresent()) { + connection = url.openConnection(Proxy.NO_PROXY); + } else { + connection = url.openConnection(); + } + connection.setDoOutput(true); // Write the data OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream()); - writer.write(data.toString()); + writer.write(data); writer.flush(); // Now read the response BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); - response = reader.readLine(); + String response = reader.readLine(); // close resources writer.close(); @@ -247,9 +298,15 @@ public class Metrics { } else { // Is this the first update this hour? if (response.contains("OK This is your first update this hour")) { - if (plotters != null) { - for (Plotter plotter : plotters) { - plotter.reset(); + synchronized (graphs) { + Iterator iter = graphs.iterator(); + + while (iter.hasNext()) { + Graph graph = iter.next(); + + for (Plotter plotter : graph.getPlotters()) { + plotter.reset(); + } } } } @@ -258,14 +315,68 @@ public class Metrics { } /** - * Generates a field - * @param name Field name - * @param data Data assigned to the field - * @return Field - * @throws UnsupportedEncodingException + * Get or create the Set of graphs for a specific plugin + * + * @param plugin + * @return */ - private static String gField(String name, String data) throws UnsupportedEncodingException { - return '&' + encode(name) + '=' + encode(data); + private Set getOrCreateGraphs(Plugin plugin) { + Set theGraphs = graphs.get(plugin); + + // Create the Set if it does not already exist + if (theGraphs == null) { + theGraphs = Collections.synchronizedSet(new HashSet()); + graphs.put(plugin, theGraphs); + } + + return theGraphs; + } + + /** + * Get the default graph for a plugin and if it does not exist, create one + * + * @param plugin + * @return + */ + private Graph getOrCreateDefaultGraph(Plugin plugin) { + Graph graph = defaultGraphs.get(plugin); + + // Not yet created :( + if (graph == null) { + graph = new Graph(Graph.Type.Line, "Default"); + defaultGraphs.put(plugin, graph); + } + + return graph; + } + + /** + * Check if mineshafter is present. If it is, we need to bypass it to send POST requests + * + * @return + */ + private static boolean isMineshafterPresent() { + try { + Class.forName("mineshafter.MineServer"); + return true; + } catch (Exception e) { + return false; + } + } + + /** + * Encode a key/value data pair to be used in a HTTP post request. This INCLUDES a & so the first + * key/value pair MUST be included manually, e.g: + *

+ * String httpData = encode("guid") + "=" + encode("1234") + encodeDataPair("authors") + ".."; + *

+ * + * @param key + * @param value + * @return + */ + private static String encodeDataPair(String key, String value) throws UnsupportedEncodingException { + return '&' + encode(key) + '=' + encode(value); } /** @@ -278,4 +389,177 @@ public class Metrics { return URLEncoder.encode(text, "UTF-8"); } + /** + * Represents a custom graph on the website + */ + public static class Graph { + + /** + * The graph's type that will be visible on the website + */ + public static enum Type { + + /** + * A simple line graph which also includes a scrollable timeline viewer to view + * as little or as much of the data as possible. + */ + Line, + + /** + * An area graph. This is the same as a line graph except the area under the curve is shaded + */ + Area, + + /** + * A column graph, which is a graph where the data is represented by columns on the vertical axis, + * i.e they go up and down. + */ + Column, + + /** + * A pie graph. The graph is generated by taking the data for the last hour and summing it + * together. Then the percentage for each plotter is calculated via round( (plot / total) * 100, 2 ) + */ + Pie + + } + + /** + * What the graph should be plotted as + */ + private final Type type; + + /** + * The graph's name, alphanumeric and spaces only :) + * If it does not comply to the above when submitted, it is rejected + */ + private final String name; + + /** + * The set of plotters that are contained within this graph + */ + private final Set plotters = new LinkedHashSet(); + + private Graph(Type type, String name) { + this.type = type; + this.name = name; + } + + /** + * Gets the graph's name + * + * @return + */ + public String getName() { + return name; + } + + /** + * Add a plotter to the graph, which will be used to plot entries + * + * @param plotter + */ + public void addPlotter(Plotter plotter) { + plotters.add(plotter); + } + + /** + * Remove a plotter from the graph + * + * @param plotter + */ + public void removePlotter(Plotter plotter) { + plotters.remove(plotter); + } + + /** + * Gets an unmodifiable set of the plotter objects in the graph + * @return + */ + public Set getPlotters() { + return Collections.unmodifiableSet(plotters); + } + + @Override + public int hashCode() { + return (type.hashCode() * 17) ^ name.hashCode(); + } + + @Override + public boolean equals(Object object) { + if (!(object instanceof Graph)) { + return false; + } + + Graph graph = (Graph) object; + return graph.type == type && graph.name.equals(name); + } + + } + + /** + * Interface used to collect custom data for a plugin + */ + public static abstract class Plotter { + + /** + * The plot's name + */ + private final String name; + + /** + * Construct a plotter with the default plot name + */ + public Plotter() { + this("Default"); + } + + /** + * Construct a plotter with a specific plot name + * + * @param name + */ + public Plotter(String name) { + this.name = name; + } + + /** + * Get the current value for the plotted point + * + * @return + */ + public abstract int getValue(); + + /** + * Get the column name for the plotted point + * + * @return the plotted point's column name + */ + public String getColumnName() { + return name; + } + + /** + * Called after the website graphs have been updated + */ + public void reset() { + } + + @Override + public int hashCode() { + return getColumnName().hashCode() + getValue(); + } + + @Override + public boolean equals(Object object) { + if (!(object instanceof Plotter)) { + return false; + } + + Plotter plotter = (Plotter) object; + return plotter.name.equals(name) && plotter.getValue() == getValue(); + } + + } + } \ No newline at end of file diff --git a/com/Acrobot/ChestShop/Permission.java b/com/Acrobot/ChestShop/Permission.java index cc55745..4faf138 100644 --- a/com/Acrobot/ChestShop/Permission.java +++ b/com/Acrobot/ChestShop/Permission.java @@ -1,17 +1,22 @@ package com.Acrobot.ChestShop; -import com.nijiko.permissions.PermissionHandler; import org.bukkit.entity.Player; /** * @author Acrobot */ public enum Permission { - SHOP_CREATION("ChestShop.shop.create"), + SHOP_CREATION_BUY("ChestShop.shop.create.buy"), + SHOP_CREATION_SELL("ChestShop.shop.create.sell"), + + SHOP_CREATION_ID("ChestShop.shop.create."), + BUY("ChestShop.shop.buy"), BUY_ID("ChestShop.shop.buy."), + SELL_ID("ChestShop.shop.sell."), SELL("ChestShop.shop.sell"), + ADMIN("ChestShop.admin"), MOD("ChestShop.mod"), OTHER_NAME("ChestShop.name."), @@ -24,21 +29,17 @@ public enum Permission { this.permission = permission; } - public static PermissionHandler permissions; - public static boolean has(Player player, Permission permission) { return has(player, permission.permission); } public static boolean has(Player player, String node) { - if (permissions != null) return permissions.has(player, node) || permissions.has(player, node.toLowerCase()); return player.hasPermission(node) || player.hasPermission(node.toLowerCase()); } public static boolean otherName(Player p, String name){ if (has(p, Permission.ADMIN)) return false; String node = OTHER_NAME + name; - if (permissions != null) return permissions.has(p, node) || permissions.has(p, node.toLowerCase()); return hasPermissionSet(p, node) || hasPermissionSet(p, node.toLowerCase()); } diff --git a/com/Acrobot/ChestShop/Protection/MaskChest.java b/com/Acrobot/ChestShop/Protection/MaskChest.java deleted file mode 100644 index ecf0c89..0000000 --- a/com/Acrobot/ChestShop/Protection/MaskChest.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.Acrobot.ChestShop.Protection; - -import com.Acrobot.ChestShop.ChestShop; -import com.Acrobot.ChestShop.Utils.uBlock; -import com.Acrobot.ChestShop.Utils.uSign; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.Chest; -import org.bukkit.entity.Player; - -/** - * @author Acrobot - */ -public class MaskChest implements Runnable { - private final BlockFace[] bf = {BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST, BlockFace.UP, BlockFace.DOWN}; - - public void run() { - Player[] players = ChestShop.getBukkitServer().getOnlinePlayers(); - - for (Player player : players) { - World world = player.getWorld(); - Location location = player.getLocation(); - - int pX = location.getBlockX(); - int pY = location.getBlockY(); - int pZ = location.getBlockZ(); - - int radius = 25; - - for (int x = -radius; x < radius; x++) { - for (int y = -radius; y < radius; y++) { - for (int z = -radius; z < radius; z++) { - Block block = world.getBlockAt(x + pX, y + pY, z + pZ); - - if (block.getType() == Material.CHEST) { - if (uBlock.findSign2(block) != null) { - Chest neighbor = uBlock.findNeighbor(block); - Material nMat = returnNearestMat(block); - if (neighbor != null) { - player.sendBlockChange(neighbor.getBlock().getLocation(), nMat, (byte) 0); - } - player.sendBlockChange(block.getLocation(), nMat, (byte) 0); - } - } - } - } - } - } - } - - private Material returnNearestMat(Block block) { - for (BlockFace face : bf) { - Block faceBlock = block.getRelative(face); - Material type = faceBlock.getType(); - if (type != Material.AIR && !uSign.isSign(faceBlock) && type != Material.CHEST) return type; - } - return Material.CHEST; - } -} diff --git a/com/Acrobot/ChestShop/Signs/restrictedSign.java b/com/Acrobot/ChestShop/Signs/restrictedSign.java index 1df69d5..cf3d3bc 100644 --- a/com/Acrobot/ChestShop/Signs/restrictedSign.java +++ b/com/Acrobot/ChestShop/Signs/restrictedSign.java @@ -43,10 +43,7 @@ public class restrictedSign { public static boolean hasPermission(Player p, String[] lines){ if (Permission.has(p, Permission.ADMIN)) return true; - String world = p.getWorld().getName(); - String playerName = p.getName(); for (int i = 1; i <= 3; i++) { - if (Permission.permissions != null && Permission.permissions.inGroup(world, playerName, lines[i])) return true; if (p.hasPermission(Permission.GROUP.toString() + lines[i])) return true; } return false; diff --git a/com/Acrobot/ChestShop/Utils/WorldGuard/uWorldGuard.java b/com/Acrobot/ChestShop/Utils/WorldGuard/uWorldGuard.java new file mode 100644 index 0000000..8fa54a9 --- /dev/null +++ b/com/Acrobot/ChestShop/Utils/WorldGuard/uWorldGuard.java @@ -0,0 +1,87 @@ +package com.Acrobot.ChestShop.Utils.WorldGuard; + +import com.Acrobot.ChestShop.ChestShop; +import com.Acrobot.ChestShop.Config.Config; +import com.Acrobot.ChestShop.Config.Property; +import com.sk89q.worldguard.bukkit.BukkitUtil; +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import com.sk89q.worldguard.protection.ApplicableRegionSet; +import com.sk89q.worldguard.protection.GlobalRegionManager; +import com.sk89q.worldguard.protection.flags.DefaultFlag; +import com.sk89q.worldguard.protection.flags.Flag; +import com.sk89q.worldguard.protection.flags.StateFlag; +import org.bukkit.Location; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @author Acrobot + */ +public class uWorldGuard { + public static WorldGuardPlugin worldGuard; + private static final ChestShopFlag flag = new ChestShopFlag(); + + /*public static boolean isNotOutsideWGplot(Location l2) { + return worldGuard == null || !Config.getBoolean(Property.WORLDGUARD_INTEGRATION) || worldGuard.getGlobalRegionManager().get(l2.getWorld()).getApplicableRegions(BukkitUtil.toVector(l2)).size() != 0; + }*/ + + public static void injectHax() { + if (!Config.getBoolean(Property.WORLDGUARD_INTEGRATION)) return; + + try { + Field field = DefaultFlag.class.getDeclaredField("flagsList"); + + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + + field.setAccessible(true); + + List elements = new ArrayList(Arrays.asList(DefaultFlag.getFlags())); + elements.add(flag); + + Flag list[] = new Flag[elements.size()]; + for (int i = 0; i < elements.size(); i++) { + list[i] = elements.get(i); + } + + field.set(null, list); + + Field grm = WorldGuardPlugin.class.getDeclaredField("globalRegionManager"); + grm.setAccessible(true); + GlobalRegionManager globalRegionManager = (GlobalRegionManager) grm.get(ChestShop.getBukkitServer().getPluginManager().getPlugin("WorldGuard")); + + globalRegionManager.preload(); + + } catch (Exception e) { + System.out.println(ChestShop.chatPrefix + "Oh noes! Something wrong happened! Be sure to paste that in your bug report:"); + e.printStackTrace(); + } + } + + public static boolean canBuildShopHere(Location loc) { + return turnedOn() && canCreateShops(getRegions(loc)); + } + + public static boolean canCreateShops(ApplicableRegionSet set){ + return set.allows(flag); + } + + public static ApplicableRegionSet getRegions(Location loc) { + return worldGuard.getGlobalRegionManager().get(loc.getWorld()).getApplicableRegions(BukkitUtil.toVector(loc)); + } + + private static boolean turnedOn() { + return worldGuard != null && Config.getBoolean(Property.WORLDGUARD_INTEGRATION); + } + + private static class ChestShopFlag extends StateFlag { + public ChestShopFlag() { + super("chestshop", false); + } + } +} diff --git a/com/Acrobot/ChestShop/Utils/uLongName.java b/com/Acrobot/ChestShop/Utils/uLongName.java index 350a050..303a95b 100644 --- a/com/Acrobot/ChestShop/Utils/uLongName.java +++ b/com/Acrobot/ChestShop/Utils/uLongName.java @@ -1,7 +1,7 @@ package com.Acrobot.ChestShop.Utils; -import com.Acrobot.ChestShop.ChestShop; -import org.bukkit.util.config.Configuration; +import com.Acrobot.ChestShop.Config.ConfigObject; +import org.bukkit.configuration.file.YamlConfiguration; import java.io.File; @@ -9,7 +9,8 @@ import java.io.File; * @author Acrobot */ public class uLongName { - public static Configuration config = new Configuration(new File(ChestShop.folder, "longName.storage")); + public static YamlConfiguration config; + public static File configFile; public static String getName(final String shortName) { return config.getString(shortName, shortName); @@ -17,16 +18,11 @@ public class uLongName { public static void saveName(String name) { if (name.length() != 16) return; - config.setProperty(name.substring(0, 15), name); - reloadConfig(); + config.set(name.substring(0, 15), name); + ConfigObject.reloadConfig(config, configFile); } public static String stripName(String name) { return (name.length() > 15 ? name.substring(0, 15) : name); } - - private static void reloadConfig() { - config.save(); - config.load(); - } } diff --git a/com/Acrobot/ChestShop/Utils/uWorldGuard.java b/com/Acrobot/ChestShop/Utils/uWorldGuard.java deleted file mode 100644 index a9ea8e6..0000000 --- a/com/Acrobot/ChestShop/Utils/uWorldGuard.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.Acrobot.ChestShop.Utils; - -import com.Acrobot.ChestShop.Config.Config; -import com.Acrobot.ChestShop.Config.Property; -import com.sk89q.worldguard.bukkit.BukkitUtil; -import com.sk89q.worldguard.bukkit.WorldGuardPlugin; -import org.bukkit.Location; - -/** - * @author Acrobot - */ -public class uWorldGuard { - public static WorldGuardPlugin worldGuard; - - public static boolean isNotOutsideWGplot(Location l2) { - return worldGuard == null || !Config.getBoolean(Property.WORLDGUARD_INTEGRATION) || worldGuard.getGlobalRegionManager().get(l2.getWorld()).getApplicableRegions(BukkitUtil.toVector(l2)).size() != 0; - } -} diff --git a/com/nijikokun/register/payment/forChestShop/methods/BOSE6.java b/com/nijikokun/register/payment/forChestShop/methods/BOSE6.java index 160ad0c..e94f968 100644 --- a/com/nijikokun/register/payment/forChestShop/methods/BOSE6.java +++ b/com/nijikokun/register/payment/forChestShop/methods/BOSE6.java @@ -99,7 +99,7 @@ public class BOSE6 implements Method { BOSEconomy = (BOSEconomy) plugin; } - public class BOSEAccount implements MethodAccount { + public static class BOSEAccount implements MethodAccount { private final String name; private final BOSEconomy BOSEconomy; @@ -161,7 +161,7 @@ public class BOSE6 implements Method { } } - public class BOSEBankAccount implements MethodBankAccount { + public static class BOSEBankAccount implements MethodBankAccount { private final String bank; private final BOSEconomy BOSEconomy; diff --git a/com/nijikokun/register/payment/forChestShop/methods/EE17.java b/com/nijikokun/register/payment/forChestShop/methods/EE17.java index 42d3ea3..f8320e6 100644 --- a/com/nijikokun/register/payment/forChestShop/methods/EE17.java +++ b/com/nijikokun/register/payment/forChestShop/methods/EE17.java @@ -28,7 +28,7 @@ public class EE17 implements Method { } public String getVersion() { - return "2.2"; + return "2.8.2"; } public int fractionalDigits() { @@ -102,7 +102,7 @@ public class EE17 implements Method { Essentials = (Essentials)plugin; } - public class EEcoAccount implements MethodAccount { + public static class EEcoAccount implements MethodAccount { private String name; public EEcoAccount(String name) { diff --git a/com/nijikokun/register/payment/forChestShop/methods/MCUR.java b/com/nijikokun/register/payment/forChestShop/methods/MCUR.java index 536999c..8183eba 100644 --- a/com/nijikokun/register/payment/forChestShop/methods/MCUR.java +++ b/com/nijikokun/register/payment/forChestShop/methods/MCUR.java @@ -81,7 +81,7 @@ public class MCUR implements Method { currencyList = (Currency) plugin; } - public class MCurrencyAccount implements MethodAccount{ + public static class MCurrencyAccount implements MethodAccount{ private String name; public MCurrencyAccount(String name) { diff --git a/com/nijikokun/register/payment/forChestShop/methods/iCo4.java b/com/nijikokun/register/payment/forChestShop/methods/iCo4.java index 3f76f51..e9e57cc 100644 --- a/com/nijikokun/register/payment/forChestShop/methods/iCo4.java +++ b/com/nijikokun/register/payment/forChestShop/methods/iCo4.java @@ -97,7 +97,7 @@ public class iCo4 implements Method { iConomy = (iConomy)plugin; } - public class iCoAccount implements MethodAccount { + public static class iCoAccount implements MethodAccount { private Account account; public iCoAccount(Account account) { diff --git a/com/nijikokun/register/payment/forChestShop/methods/iCo5.java b/com/nijikokun/register/payment/forChestShop/methods/iCo5.java index 3f9f7ab..c1b93c9 100644 --- a/com/nijikokun/register/payment/forChestShop/methods/iCo5.java +++ b/com/nijikokun/register/payment/forChestShop/methods/iCo5.java @@ -91,7 +91,7 @@ public class iCo5 implements Method { iConomy = (iConomy)plugin; } - public class iCoAccount implements MethodAccount { + public static class iCoAccount implements MethodAccount { private Account account; private Holdings holdings; @@ -161,7 +161,7 @@ public class iCo5 implements Method { } } - public class iCoBankAccount implements MethodBankAccount { + public static class iCoBankAccount implements MethodBankAccount { private BankAccount account; private Holdings holdings; diff --git a/com/nijikokun/register/payment/forChestShop/methods/iCo6.java b/com/nijikokun/register/payment/forChestShop/methods/iCo6.java index f4dee5d..80eb2bd 100644 --- a/com/nijikokun/register/payment/forChestShop/methods/iCo6.java +++ b/com/nijikokun/register/payment/forChestShop/methods/iCo6.java @@ -83,7 +83,7 @@ public class iCo6 implements Method { iConomy = (iConomy)plugin; } - public class iCoAccount implements MethodAccount { + public static class iCoAccount implements MethodAccount { private Account account; private Holdings holdings; diff --git a/plugin.yml b/plugin.yml index 5a7bf3a..7938601 100644 --- a/plugin.yml +++ b/plugin.yml @@ -2,7 +2,7 @@ name: ChestShop main: com.Acrobot.ChestShop.ChestShop -version: 3.35 +version: 3.36 author: Acrobot @@ -10,7 +10,7 @@ description: > A chest shop for economy plugins. -softdepend: [Permissions, LWC, Lockette, Deadbolt, OddItem, Towny, WorldGuard, Vault, Heroes, +softdepend: [LWC, Lockette, Deadbolt, OddItem, Towny, WorldGuard, Vault, Heroes, iConomy, BOSEconomy, Essentials, 3co, MultiCurrency, Currency, SimpleChestLock] commands: iteminfo: @@ -40,14 +40,21 @@ permissions: ChestShop.shop.buy: true ChestShop.shop.sell: true default: true + ChestShop.shop.create: + description: Allows the user to create a shop that sells and buys any item + children: + ChestShop.shop.create.buy: true + ChestShop.shop.create.sell: true + ChestShop.shop.create.buy: + description: Allows the user to create a shop that sells any item + ChestShop.shop.create.sell: + description: Allows the user to create a shop that buy any item ChestShop.shop.create.(itemID): description: Allows user to create a shop that sells item with itemID like in the permission node (replace (itemID) with NUMERICAL item ID) ChestShop.shop.buy.(itemID): description: Allows user to buy certain (itemID) from a shop (replace (itemID) with NUMERICAL item ID) ChestShop.shop.sell.(itemID): description: Allows user to sell certain (itemID) from a shop (replace (itemID) with NUMERICAL item ID) - ChestShop.shop.create: - description: Allows user to create a shop that sells any item ChestShop.shop.buy: description: Allows user to buy from a shop ChestShop.shop.sell: