diff --git a/com/Acrobot/ChestShop/ChestShop.java b/com/Acrobot/ChestShop/ChestShop.java index 04edf19..7986c04 100644 --- a/com/Acrobot/ChestShop/ChestShop.java +++ b/com/Acrobot/ChestShop/ChestShop.java @@ -65,6 +65,9 @@ public class ChestShop extends JavaPlugin { getCommand("iteminfo").setExecutor(new ItemInfo()); getCommand("csVersion").setExecutor(new Version()); + //Start the statistics pinger + startStatistics(); + System.out.println('[' + getPluginName() + "] version " + getVersion() + " initialized!"); } @@ -72,7 +75,7 @@ public class ChestShop extends JavaPlugin { System.out.println('[' + getPluginName() + "] version " + getVersion() + " shutting down!"); } - ////////////////// REGISTER EVENTS & SCHEDULER /////////////////////////// + ////////////////// REGISTER EVENTS, SCHEDULER & STATS /////////////////////////// private void registerEvents() { blockBreak blockBreak = new blockBreak(); registerEvent(Event.Type.BLOCK_BREAK, blockBreak); @@ -80,7 +83,6 @@ public class ChestShop extends JavaPlugin { registerEvent(Event.Type.SIGN_CHANGE, new signChange()); registerEvent(Event.Type.PLAYER_INTERACT, new playerInteract(), Event.Priority.Highest); registerEvent(Event.Type.PLUGIN_ENABLE, new pluginEnable()); - registerEvent(Event.Type.PLUGIN_DISABLE, new pluginDisable()); if (!Config.getBoolean(Property.USE_BUILT_IN_PROTECTION)) return; registerEvent(Event.Type.BLOCK_PISTON_EXTEND, blockBreak); registerEvent(Event.Type.BLOCK_PISTON_RETRACT, blockBreak); @@ -99,6 +101,14 @@ public class ChestShop extends JavaPlugin { server.getScheduler().scheduleAsyncRepeatingTask(this, runnable, startTime, repetetionTime); } + private void startStatistics(){ + try{ + new Metrics().beginMeasuringPlugin(this); + } catch (Exception ex){ + System.out.println(chatPrefix + "There was an error while submitting statistics."); + } + } + ///////////////////// DATABASE STUFF //////////////////////////////// private static Configuration getBukkitConfig() { Configuration config = new Configuration(new File("bukkit.yml")); diff --git a/com/Acrobot/ChestShop/Config/Language.java b/com/Acrobot/ChestShop/Config/Language.java index f7f2239..eaa3467 100644 --- a/com/Acrobot/ChestShop/Config/Language.java +++ b/com/Acrobot/ChestShop/Config/Language.java @@ -35,6 +35,7 @@ public enum Language { PROTECTED_SHOP("Successfully protected the shop with LWC!"), SHOP_CREATED("Shop successfully created!"), + SHOP_REFUNDED("You have been refunded %amount."), NO_PERMISSION("You don't have permissions to do that!"), INCORRECT_ITEM_ID("You have specified invalid item id!"), diff --git a/com/Acrobot/ChestShop/Config/Property.java b/com/Acrobot/ChestShop/Config/Property.java index 46efc1e..4275af3 100644 --- a/com/Acrobot/ChestShop/Config/Property.java +++ b/com/Acrobot/ChestShop/Config/Property.java @@ -4,7 +4,7 @@ package com.Acrobot.ChestShop.Config; * @author Acrobot */ public enum Property { - PREFERRED_ECONOMY_PLUGIN("", "Preferred economy plugin (iConomy, BOSEconomy, Essentials). If you do not want to specify this, leave it blank."), + PREFERRED_ECONOMY_PLUGIN("", "WHEN NOT USING VAULT. Preferred economy plugin (iConomy, BOSEconomy, Essentials). If you do not want to specify this, leave it blank."), REVERSE_BUTTONS(false, "If true, people will buy with left-click and sell with right-click."), ALLOW_LEFT_CLICK_DESTROYING(true, "If true, if you left-click your own shop sign you won't open chest's inventory, but instead you will start destroying the sign."), STACK_UNSTACKABLES(false, "If true, ALL things (including food, etc.) will stack up to 64"), @@ -30,9 +30,12 @@ public enum Property { 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?"), 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?"), ALLOW_MULTIPLE_SHOPS_AT_ONE_BLOCK(false, "Do you want to allow other players to build a shop on a block where there's one already?"), - SHOP_INTERACTION_INTERVAL(100, "(In 1/1000th of a second) How often can a player use a shop sign?"); + SHOP_INTERACTION_INTERVAL(100, "(In 1/1000th of a second) How often can a player use a shop sign?"), + HEROES_EXP(100, "How much Heroes exp should people get for creating a ChestShop?"), + BLOCK_UPDATE(false, "EXPERIMENTAL: Should every ChestShop transaction result in a block update?"); private final Object value; diff --git a/com/Acrobot/ChestShop/Economy.java b/com/Acrobot/ChestShop/Economy.java deleted file mode 100644 index 618cfa3..0000000 --- a/com/Acrobot/ChestShop/Economy.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.Acrobot.ChestShop; - -import com.Acrobot.ChestShop.Config.Config; -import com.Acrobot.ChestShop.Config.Property; -import com.Acrobot.ChestShop.Utils.uLongName; -import com.nijikokun.register.payment.forChestShop.Method; - -/** - * @author Acrobot - * Economy management - */ -public class Economy { - public static Method economy; - - public static boolean hasAccount(String p) { - return economy.hasAccount(uLongName.getName(p)); - } - - public static void add(String name, float amount) { - if (Config.getFloat(Property.TAX_AMOUNT) != 0F && !Config.getString(Property.SERVER_ECONOMY_ACCOUNT).isEmpty()) { - float tax = (Config.getFloat(Property.TAX_AMOUNT) / 100F) * amount; - economy.getAccount(Config.getString(Property.SERVER_ECONOMY_ACCOUNT)).add(tax); - amount = amount - tax; - } - economy.getAccount(uLongName.getName(name)).add(amount); - } - - public static void substract(String name, float amount) { - economy.getAccount(uLongName.getName(name)).subtract(amount); - } - - public static boolean hasEnough(String name, float amount) { - return economy.getAccount(uLongName.getName(name)).hasEnough(amount); - } - - public static double balance(String name) { - return economy.getAccount(uLongName.getName(name)).balance(); - } - - public static String formatBalance(double amount) { - return economy.format(amount); - } -} diff --git a/com/Acrobot/ChestShop/Economy/EcoPlugin.java b/com/Acrobot/ChestShop/Economy/EcoPlugin.java new file mode 100644 index 0000000..cfb32cd --- /dev/null +++ b/com/Acrobot/ChestShop/Economy/EcoPlugin.java @@ -0,0 +1,13 @@ +package com.Acrobot.ChestShop.Economy; + +/** + * @author Acrobot + */ +public interface EcoPlugin { + public boolean hasAccount(String player); + public void add(String player, double amount); + public void subtract(String player, double amount); + public boolean hasEnough(String player, double amount); + public double balance(String player); + public String format(double amount); +} diff --git a/com/Acrobot/ChestShop/Economy/Economy.java b/com/Acrobot/ChestShop/Economy/Economy.java new file mode 100644 index 0000000..f1117f4 --- /dev/null +++ b/com/Acrobot/ChestShop/Economy/Economy.java @@ -0,0 +1,58 @@ +package com.Acrobot.ChestShop.Economy; + +import com.Acrobot.ChestShop.Config.Config; +import com.Acrobot.ChestShop.Config.Property; +import com.Acrobot.ChestShop.Utils.uLongName; + +/** + * @author Acrobot + * Economy management + */ +public class Economy { + public static EcoPlugin economy; + + public static boolean hasAccount(String p) { + return economy.hasAccount(uLongName.getName(p)); + } + + public static void add(String name, float amount) { + String account = Config.getString(Property.SERVER_ECONOMY_ACCOUNT); + if (!account.isEmpty()) { + float tax = getTax(Property.TAX_AMOUNT, amount); + economy.add(account, tax); + amount = amount - tax; + } + + economy.add(uLongName.getName(name), amount); + } + + public static void addServer(String name, float amount){ + String account = Config.getString(Property.SERVER_ECONOMY_ACCOUNT); + if (!account.isEmpty()) { + float tax = getTax(Property.SERVER_TAX_AMOUNT, amount); + economy.add(account, tax); + amount = amount - tax; + } + economy.add(uLongName.getName(name), amount); + } + + public static float getTax(Property tax, float price){ + return (Config.getFloat(tax) / 100F) * price; + } + + public static void subtract(String name, float amount) { + economy.subtract(name, amount); + } + + public static boolean hasEnough(String name, float amount) { + return economy.hasEnough(uLongName.getName(name), amount); + } + + public static double balance(String name) { + return economy.balance(uLongName.getName(name)); + } + + public static String formatBalance(double amount) { + return economy.format(amount); + } +} diff --git a/com/Acrobot/ChestShop/Economy/NoProvider.java b/com/Acrobot/ChestShop/Economy/NoProvider.java new file mode 100644 index 0000000..fbd1687 --- /dev/null +++ b/com/Acrobot/ChestShop/Economy/NoProvider.java @@ -0,0 +1,34 @@ +package com.Acrobot.ChestShop.Economy; + +/** + * @author Acrobot + */ +public class NoProvider implements EcoPlugin{ + public boolean hasAccount(String player) { + System.out.println("[ChestShop] You haven't got any economy plugin!"); + return false; + } + + public void add(String player, double amount) { + System.out.println("[ChestShop] You haven't got any economy plugin!"); + } + + public void subtract(String player, double amount) { + System.out.println("[ChestShop] You haven't got any economy plugin!"); + } + + public boolean hasEnough(String player, double amount) { + System.out.println("[ChestShop] You haven't got any economy plugin!"); + return false; + } + + public double balance(String player) { + System.out.println("[ChestShop] You haven't got any economy plugin!"); + return 0; + } + + public String format(double amount) { + System.out.println("[ChestShop] You haven't got any economy plugin!"); + return null; + } +} diff --git a/com/Acrobot/ChestShop/Economy/Register.java b/com/Acrobot/ChestShop/Economy/Register.java new file mode 100644 index 0000000..2fdc13f --- /dev/null +++ b/com/Acrobot/ChestShop/Economy/Register.java @@ -0,0 +1,33 @@ +package com.Acrobot.ChestShop.Economy; + +import com.nijikokun.register.payment.forChestShop.Method; + +/** + * @author Acrobot + */ +public class Register implements EcoPlugin{ + public static Method eco; + public boolean hasAccount(String player) { + return eco.hasAccount(player); + } + + public void add(String player, double amount) { + eco.getAccount(player).add(amount); + } + + public void subtract(String player, double amount) { + eco.getAccount(player).subtract(amount); + } + + public boolean hasEnough(String player, double amount) { + return eco.getAccount(player).hasEnough(amount); + } + + public double balance(String player) { + return eco.getAccount(player).balance(); + } + + public String format(double amount) { + return eco.format(amount); + } +} diff --git a/com/Acrobot/ChestShop/Economy/Vault.java b/com/Acrobot/ChestShop/Economy/Vault.java new file mode 100644 index 0000000..907d1f1 --- /dev/null +++ b/com/Acrobot/ChestShop/Economy/Vault.java @@ -0,0 +1,32 @@ +package com.Acrobot.ChestShop.Economy; + +/** + * @author Acrobot + */ +public class Vault implements EcoPlugin { + public static net.milkbowl.vault.economy.Economy economy; + + public boolean hasAccount(String player) { + return economy.hasAccount(player); + } + + public void add(String player, double amount) { + economy.depositPlayer(player, amount); + } + + public void subtract(String player, double amount) { + economy.withdrawPlayer(player, amount); + } + + public boolean hasEnough(String player, double amount) { + return economy.has(player, amount); + } + + public double balance(String player) { + return economy.getBalance(player); + } + + public String format(double amount) { + return economy.format(amount); + } +} diff --git a/com/Acrobot/ChestShop/Listeners/blockBreak.java b/com/Acrobot/ChestShop/Listeners/blockBreak.java index 9ebb8c1..f88871a 100644 --- a/com/Acrobot/ChestShop/Listeners/blockBreak.java +++ b/com/Acrobot/ChestShop/Listeners/blockBreak.java @@ -1,8 +1,9 @@ package com.Acrobot.ChestShop.Listeners; import com.Acrobot.ChestShop.Config.Config; +import com.Acrobot.ChestShop.Config.Language; import com.Acrobot.ChestShop.Config.Property; -import com.Acrobot.ChestShop.Economy; +import com.Acrobot.ChestShop.Economy.Economy; import com.Acrobot.ChestShop.Permission; import com.Acrobot.ChestShop.Signs.restrictedSign; import com.Acrobot.ChestShop.Utils.uBlock; @@ -37,7 +38,11 @@ public class blockBreak extends BlockListener { Sign sign = uBlock.findSign(block, (player != null ? uLongName.stripName(player.getName()) : null)); if (!isCorrectSign(sign, block)) return false; //It's not a correct shop sign, so don't cancel it if (playerIsNotOwner(player, sign)) return true; //Player is not the owner of the shop - cancel! - if (weShouldReturnMoney()) Economy.add(uLongName.getName(sign.getLine(0)), Config.getFloat(Property.SHOP_REFUND_PRICE)); //Add some money + if (weShouldReturnMoney() && !Permission.has(player, Permission.NOFEE)){ + float refundPrice = Config.getFloat(Property.SHOP_REFUND_PRICE); + Economy.add(uLongName.getName(sign.getLine(0)), refundPrice); //Add some money + player.sendMessage(Config.getLocal(Language.SHOP_REFUNDED).replace("%amount", Economy.formatBalance(refundPrice))); + } return false; //Player is the owner, so we don't want to cancel this :) } diff --git a/com/Acrobot/ChestShop/Listeners/pluginDisable.java b/com/Acrobot/ChestShop/Listeners/pluginDisable.java deleted file mode 100644 index b174093..0000000 --- a/com/Acrobot/ChestShop/Listeners/pluginDisable.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.Acrobot.ChestShop.Listeners; - -import com.Acrobot.ChestShop.Economy; -import com.nijikokun.register.payment.forChestShop.Methods; -import org.bukkit.event.server.PluginDisableEvent; -import org.bukkit.event.server.ServerListener; - -/** - * @author Acrobot - */ -public class pluginDisable extends ServerListener { - public void onPluginDisable(PluginDisableEvent event) { - if (Economy.economy != null && Methods.hasMethod() && Methods.checkDisabled(event.getPlugin())) { - Economy.economy = null; - System.out.println("[ChestShop] Economy plugin disabled!"); - } - } -} diff --git a/com/Acrobot/ChestShop/Listeners/pluginEnable.java b/com/Acrobot/ChestShop/Listeners/pluginEnable.java index 2524c57..bc7a0fd 100644 --- a/com/Acrobot/ChestShop/Listeners/pluginEnable.java +++ b/com/Acrobot/ChestShop/Listeners/pluginEnable.java @@ -1,7 +1,8 @@ package com.Acrobot.ChestShop.Listeners; import com.Acrobot.ChestShop.ChestShop; -import com.Acrobot.ChestShop.Economy; +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.DeadboltPlugin; @@ -9,19 +10,23 @@ import com.Acrobot.ChestShop.Protection.Plugins.Default; import com.Acrobot.ChestShop.Protection.Plugins.LWCplugin; import com.Acrobot.ChestShop.Protection.Plugins.LockettePlugin; import com.Acrobot.ChestShop.Protection.Security; +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; import com.sk89q.worldguard.bukkit.WorldGuardPlugin; -import org.bukkit.event.server.PluginEnableEvent; +import net.milkbowl.vault.economy.Economy; import org.bukkit.event.server.ServerListener; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.PluginDescriptionFile; +import org.bukkit.plugin.RegisteredServiceProvider; import org.yi.acru.bukkit.Lockette.Lockette; /** @@ -29,35 +34,35 @@ import org.yi.acru.bukkit.Lockette.Lockette; */ public class pluginEnable extends ServerListener { - public void onPluginEnable(PluginEnableEvent event) { - if (!Methods.hasMethod() && Methods.setMethod(ChestShop.pm)) { - Economy.economy = Methods.getMethod(); - System.out.println(ChestShop.chatPrefix + Economy.economy.getName() + ' ' + Economy.economy.getVersion() + " loaded."); - } - } - public static void initializePlugins() { Security.protections.add(new Default()); //Initialize basic protection for (Object plugin : ChestShop.getDependencies()) { Plugin pl = ChestShop.pm.getPlugin((String) plugin); if (pl != null) initializePlugin((String) plugin, pl); } + loadRegister(); + } + + private static void loadRegister(){ + if (com.Acrobot.ChestShop.Economy.Economy.economy == null) { + Method m = Methods.load(ChestShop.pm); + if (m == null) return; + Register.eco = m; + com.Acrobot.ChestShop.Economy.Economy.economy = new Register(); + System.out.println(ChestShop.chatPrefix + m.getName() + " loaded."); + } } private static void initializePlugin(String name, Plugin plugin) { //Really messy, right? But it's short and fast :) if (name.equals("Permissions")) { - if (Permission.permissions != null) return; Permission.permissions = ((Permissions) plugin).getHandler(); } else if (name.equals("LWC")) { - if (LWCplugin.lwc != null) return; LWCplugin.setLWC(((LWCPlugin) plugin).getLWC()); Security.protections.add(new LWCplugin()); } else if (name.equals("Lockette")) { - if (LockettePlugin.lockette != null) return; LockettePlugin.lockette = (Lockette) plugin; Security.protections.add(new LockettePlugin()); } else if (name.equals("Deadbolt")) { - if (DeadboltPlugin.deadbolt != null) return; DeadboltPlugin.deadbolt = (Deadbolt) plugin; Security.protections.add(new DeadboltPlugin()); } else if (name.equals("OddItem")) { @@ -65,16 +70,25 @@ public class pluginEnable extends ServerListener { if (plugin.getDescription().getVersion().startsWith("0.7")) { System.out.println(generateOutdatedVersion(name, plugin.getDescription().getVersion(), "0.8")); return; } Odd.isInitialized = true; } else if (name.equals("Towny")) { - if (uSign.towny != null) return; int versionNumber = 0; String[] split = plugin.getDescription().getVersion().split("\\."); for (int i = 0; i < 4; i++) if (split.length >= i + 1 && uNumber.isInteger(split[i])) versionNumber += (Math.pow(10, (3 - i) << 1) * Integer.parseInt(split[i])); //EPIC CODE RIGHT HERE if (versionNumber < 760047) { System.out.println(generateOutdatedVersion(name, plugin.getDescription().getVersion(), "0.76.0.47")); return; } uSign.towny = (Towny) plugin; } else if (name.equals("WorldGuard")) { - if (uWorldGuard.worldGuard != null) return; uWorldGuard.worldGuard = (WorldGuardPlugin) plugin; + } else if (name.equals("Vault")) { + if (com.Acrobot.ChestShop.Economy.Economy.economy != null) return; + RegisteredServiceProvider rsp = ChestShop.getBukkitServer().getServicesManager().getRegistration(Economy.class); + Vault.economy = rsp.getProvider(); + if (Vault.economy == null) return; + com.Acrobot.ChestShop.Economy.Economy.economy = new Vault(); + System.out.println(ChestShop.chatPrefix + "Vault loaded using economy plugin " + Vault.economy.getName()); + return; + } else if (name.equals("Heroes")){ + uHeroes.heroes = (Heroes) plugin; } + PluginDescriptionFile description = plugin.getDescription(); System.out.println(ChestShop.chatPrefix + description.getName() + " version " + description.getVersion() + " loaded."); } diff --git a/com/Acrobot/ChestShop/Listeners/signChange.java b/com/Acrobot/ChestShop/Listeners/signChange.java index 6be9df2..cdbde2e 100644 --- a/com/Acrobot/ChestShop/Listeners/signChange.java +++ b/com/Acrobot/ChestShop/Listeners/signChange.java @@ -3,7 +3,7 @@ package com.Acrobot.ChestShop.Listeners; import com.Acrobot.ChestShop.Config.Config; import com.Acrobot.ChestShop.Config.Language; import com.Acrobot.ChestShop.Config.Property; -import com.Acrobot.ChestShop.Economy; +import com.Acrobot.ChestShop.Economy.Economy; import com.Acrobot.ChestShop.Items.Items; import com.Acrobot.ChestShop.Permission; import com.Acrobot.ChestShop.Protection.Security; @@ -108,7 +108,7 @@ public class signChange extends BlockListener { float shopCreationPrice = Config.getFloat(Property.SHOP_CREATION_PRICE); - boolean paid = shopCreationPrice != 0 && !isAdminShop; + boolean paid = shopCreationPrice != 0 && !isAdminShop && !Permission.has(player, Permission.NOFEE); if (paid) { if (!Economy.hasEnough(player.getName(), shopCreationPrice)) { player.sendMessage(Config.getLocal(Language.NOT_ENOUGH_MONEY)); @@ -116,7 +116,7 @@ public class signChange extends BlockListener { return; } - Economy.substract(player.getName(), shopCreationPrice); + Economy.subtract(player.getName(), shopCreationPrice); } if (Config.getBoolean(Property.PROTECT_SIGN_WITH_LWC)) { @@ -128,6 +128,8 @@ public class signChange extends BlockListener { uLongName.saveName(player.getName()); player.sendMessage(Config.getLocal(Language.SHOP_CREATED) + (paid ? " - " + Economy.formatBalance(shopCreationPrice) : "")); + + uHeroes.addHeroExp(player); } private static boolean canCreateShop(Player player, boolean isAdmin, int ID) { diff --git a/com/Acrobot/ChestShop/Metrics.java b/com/Acrobot/ChestShop/Metrics.java new file mode 100644 index 0000000..e6f52a2 --- /dev/null +++ b/com/Acrobot/ChestShop/Metrics.java @@ -0,0 +1,263 @@ +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 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.URL; +import java.net.URLConnection; +import java.net.URLEncoder; +import java.util.Collections; +import java.util.HashMap; +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 + */ + 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(); + + @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 = 3; + + /** + * The base url of the metrics domain + */ + private static final String BASE_URL = "http://metrics.griefcraft.com"; + + /** + * The url used to report a server's status + */ + private static final String REPORT_URL = "/report/%s"; + + /** + * The file where guid and opt out is stored in + */ + private static final String CONFIG_FILE = "plugins/PluginMetrics/config.yml"; + + /** + * Interval of time to ping in minutes + */ + private final static int PING_INTERVAL = 10; + + /** + * A map of the custom data plotters for plugins + */ + private Map> customData = Collections.synchronizedMap(new HashMap>()); + + /** + * The plugin configuration file + */ + private final YamlConfiguration configuration; + + /** + * Unique server id + */ + private String guid; + + public Metrics() throws IOException { + // load the config + File file = new File(CONFIG_FILE); + configuration = YamlConfiguration.loadConfiguration(file); + + // add some defaults + configuration.addDefault("opt-out", false); + configuration.addDefault("guid", UUID.randomUUID().toString()); + + // Do we need to create the file? + if (configuration.get("guid", null) == null) { + configuration.options().header("http://metrics.griefcraft.com").copyDefaults(true); + configuration.save(file); + } + + // Load the guid then + guid = configuration.getString("guid"); + } + + /** + * Adds a custom data plotter for a given plugin + * + * @param plugin + * @param plotter + */ + public void addCustomData(Plugin plugin, Plotter plotter) { + Set plotters = customData.get(plugin); + + if (plotters == null) { + plotters = Collections.synchronizedSet(new LinkedHashSet()); + customData.put(plugin, plotters); + } + + plotters.add(plotter); + } + + /** + * Begin measuring a plugin + * + * @param plugin + */ + public void beginMeasuringPlugin(final Plugin plugin) throws IOException { + // Did we opt out? + if (configuration.getBoolean("opt-out", false)) return; + + // First tell the server about us + postPlugin(plugin, false); + + // Ping the server in intervals + plugin.getServer().getScheduler().scheduleAsyncRepeatingTask(plugin, new Runnable() { + public void run() { + try { + postPlugin(plugin, true); + } catch (IOException e) { + System.out.println("[ChestShop] There was an error while submitting statistics."); + } + } + }, PING_INTERVAL * 1200, PING_INTERVAL * 1200); + } + + /** + * Generates a field + * @param name Field name + * @param data Data assigned to the field + * @return Field + * @throws UnsupportedEncodingException + */ + private static String gField(String name, String data) throws UnsupportedEncodingException { + return '&' + encode(name) + '=' + encode(data); + } + + /** + * Generic method that posts a plugin to the metrics website + * + * @param plugin + */ + private void postPlugin(Plugin plugin, boolean isPing) throws IOException { + // Construct the post data + String response = "ERR No response"; + String data = encode("guid") + '=' + encode(guid) + + gField("version", plugin.getDescription().getVersion()) + + gField("server", Bukkit.getVersion()) + + gField("players", String.valueOf(Bukkit.getServer().getOnlinePlayers().length)) + + gField("revision", String.valueOf(REVISION)); + + // If we're pinging, append it + if (isPing) { + data += gField("ping", "true"); + } + + // Add any custom data (if applicable) + Set plotters = customData.get(plugin); + + if (plotters != null) { + for (Plotter plotter : plotters) { + data += gField("Custom" + plotter.getColumnName(), Integer.toString(plotter.getValue())); + } + } + + // Create the url + URL url = new URL(BASE_URL + String.format(REPORT_URL, plugin.getDescription().getName())); + + // Connect to the website + URLConnection connection = url.openConnection(); + connection.setDoOutput(true); + + // Write the data + OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream()); + writer.write(data); + writer.flush(); + + // Now read the response + BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + response = reader.readLine(); + + // close resources + writer.close(); + reader.close(); + if (response.startsWith("ERR")) throw new IOException(response); + } + + /** + * Encode text as UTF-8 + * + * @param text + * @return + */ + private static String encode(String text) throws UnsupportedEncodingException { + return URLEncoder.encode(text, "UTF-8"); + } + +} \ No newline at end of file diff --git a/com/Acrobot/ChestShop/Permission.java b/com/Acrobot/ChestShop/Permission.java index 781e8c6..cc55745 100644 --- a/com/Acrobot/ChestShop/Permission.java +++ b/com/Acrobot/ChestShop/Permission.java @@ -15,7 +15,8 @@ public enum Permission { ADMIN("ChestShop.admin"), MOD("ChestShop.mod"), OTHER_NAME("ChestShop.name."), - GROUP("ChestShop.group."); + GROUP("ChestShop.group."), + NOFEE("ChestShop.nofee"); private final String permission; @@ -35,6 +36,7 @@ public enum Permission { } 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/Shop/Shop.java b/com/Acrobot/ChestShop/Shop/Shop.java index 8483da9..bd18d4c 100644 --- a/com/Acrobot/ChestShop/Shop/Shop.java +++ b/com/Acrobot/ChestShop/Shop/Shop.java @@ -5,9 +5,10 @@ import com.Acrobot.ChestShop.Chests.ChestObject; import com.Acrobot.ChestShop.Config.Config; import com.Acrobot.ChestShop.Config.Language; import com.Acrobot.ChestShop.Config.Property; -import com.Acrobot.ChestShop.Economy; +import com.Acrobot.ChestShop.Economy.Economy; import com.Acrobot.ChestShop.Logging.Logging; import com.Acrobot.ChestShop.Permission; +import com.Acrobot.ChestShop.Utils.uBlock; import com.Acrobot.ChestShop.Utils.uInventory; import com.Acrobot.ChestShop.Utils.uSign; import org.bukkit.block.Sign; @@ -26,6 +27,7 @@ public class Shop { public final float buyPrice; public final float sellPrice; public final String owner; + private final Sign sign; public Shop(ChestObject chest, boolean buy, Sign sign, ItemStack... itemStacks) { this.stock = itemStacks[0]; @@ -35,6 +37,7 @@ public class Shop { this.sellPrice = (!buy ? uSign.sellPrice(sign.getLine(2)) : -1); this.owner = sign.getLine(0); this.stockAmount = uSign.itemAmount(sign.getLine(1)); + this.sign = sign; } public void buy(Player player) { @@ -70,9 +73,12 @@ public class Shop { } String account = getOwnerAccount(); - if (!account.isEmpty() && Economy.hasAccount(account)) Economy.add(account, buyPrice); + if (!account.isEmpty() && Economy.hasAccount(account)) { + if (!isAdminShop()) Economy.add(account, buyPrice); + else Economy.addServer(account, buyPrice); + } - Economy.substract(playerName, buyPrice); + Economy.subtract(playerName, buyPrice); if (!isAdminShop()) chest.removeItem(stock, durability, stockAmount); @@ -96,6 +102,8 @@ public class Shop { .replace("%buyer", playerName) .replace("%price", formatedPrice)); } + + if (Config.getBoolean(Property.BLOCK_UPDATE)) uBlock.blockUpdate(sign.getBlock()); } public void sell(Player player) { @@ -130,10 +138,11 @@ public class Shop { } - if (accountExists) Economy.substract(account, sellPrice); + if (accountExists) Economy.subtract(account, sellPrice); if (!isAdminShop()) chest.addItem(stock, stockAmount); - Economy.add(player.getName(), sellPrice); + if (!isAdminShop()) Economy.add(player.getName(), sellPrice); + else Economy.addServer(player.getName(), sellPrice); String materialName = stock.getType().name(); String formatedBalance = Economy.formatBalance(sellPrice); @@ -157,6 +166,7 @@ public class Shop { .replace("%seller", player.getName()) .replace("%price", formatedBalance)); } + if (Config.getBoolean(Property.BLOCK_UPDATE)) uBlock.blockUpdate(sign.getBlock()); } private String getOwnerAccount() { diff --git a/com/Acrobot/ChestShop/Utils/uBlock.java b/com/Acrobot/ChestShop/Utils/uBlock.java index 0335572..c26969e 100644 --- a/com/Acrobot/ChestShop/Utils/uBlock.java +++ b/com/Acrobot/ChestShop/Utils/uBlock.java @@ -28,6 +28,12 @@ public class uBlock { } return null; } + + public static void blockUpdate(Block block){ + for (BlockFace bf : shopFaces){ + block.getRelative(bf).getState().update(true); + } + } public static Sign findSign(Block block, String originalName) { for (BlockFace bf : shopFaces) { diff --git a/com/Acrobot/ChestShop/Utils/uHeroes.java b/com/Acrobot/ChestShop/Utils/uHeroes.java new file mode 100644 index 0000000..db84582 --- /dev/null +++ b/com/Acrobot/ChestShop/Utils/uHeroes.java @@ -0,0 +1,26 @@ +package com.Acrobot.ChestShop.Utils; + +import com.Acrobot.ChestShop.Config.Config; +import com.Acrobot.ChestShop.Config.Property; +import com.herocraftonline.dev.heroes.Heroes; +import com.herocraftonline.dev.heroes.classes.HeroClass; +import com.herocraftonline.dev.heroes.hero.Hero; +import org.bukkit.entity.Player; + +/** + * @author Acrobot + */ +public class uHeroes { + public static Heroes heroes; + + public static void addHeroExp(Player p) { + if (uHeroes.heroes != null) { + Hero hero = uHeroes.heroes.getHeroManager().getHero(p); + if (hero.hasParty()) { + hero.getParty().gainExp(Config.getDouble(Property.HEROES_EXP), HeroClass.ExperienceType.EXTERNAL, p.getLocation()); + } else { + hero.gainExp(Config.getDouble(Property.HEROES_EXP), HeroClass.ExperienceType.EXTERNAL); + } + } + } +} diff --git a/com/nijikokun/register/payment/forChestShop/Methods.java b/com/nijikokun/register/payment/forChestShop/Methods.java index 1760f1d..46cbd77 100644 --- a/com/nijikokun/register/payment/forChestShop/Methods.java +++ b/com/nijikokun/register/payment/forChestShop/Methods.java @@ -1,105 +1,56 @@ package com.nijikokun.register.payment.forChestShop; +import com.nijikokun.register.payment.forChestShop.methods.*; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.PluginManager; -import java.util.HashSet; -import java.util.Set; - /** - * The methods initializes methods that utilize the Method interface - * based on a "first come, first served" basis. - *

- * Allowing you to check whether a payment method exists or not. - *

- * methods also allows you to set a preferred method of payment before it captures - * payment plugins in the initialization process. - *

- * in bukkit.yml: - *

- *  economy:
- *      preferred: "iConomy"
- * 
- * - * @author: Nijikokun (@nijikokun) - * @copyright: Copyright (C) 2011 - * @license: AOL license + * @author Acrobot */ public class Methods { - private static String version = null; - private static boolean self = false; - private static Method Method = null; - private static String preferred = ""; - private static Set methods = new HashSet(); - private static Set dependencies = new HashSet(); - private static Set attachables = new HashSet(); + private static String preferred; + private static final String[] toLoad = new String[]{ + "iConomy", + "BOSEconomy", + "Essentials", + "Currency", + "MultiCurrency", + "3co" + }; + private static final Method[] methods = new Method[]{ + new iCo4(), + new iCo5(), + new iCo6(), + new BOSE6(), + new BOSE7(), + new MCUR(), + new ECO3(), + new EE17() + }; - static { - init(); + public static void setPreferred(String plugin) { + preferred = plugin; } - /** - * Implement all methods along with their respective name & class. - */ - private static void init() { - addMethod("iConomy", new com.nijikokun.register.payment.forChestShop.methods.iCo6()); - addMethod("iConomy", new com.nijikokun.register.payment.forChestShop.methods.iCo5()); - addMethod("iConomy", new com.nijikokun.register.payment.forChestShop.methods.iCo4()); - addMethod("BOSEconomy", new com.nijikokun.register.payment.forChestShop.methods.BOSE6()); - addMethod("BOSEconomy", new com.nijikokun.register.payment.forChestShop.methods.BOSE7()); - addMethod("Essentials", new com.nijikokun.register.payment.forChestShop.methods.EE17()); - addMethod("Currency", new com.nijikokun.register.payment.forChestShop.methods.MCUR()); - addMethod("3co", new com.nijikokun.register.payment.forChestShop.methods.ECO3()); - dependencies.add("MultiCurrency"); + public static Method load(PluginManager pm) { + if (!preferred.isEmpty()){ + Plugin plugin = pm.getPlugin(preferred); + if (plugin != null){ + Method m = createMethod(plugin); + if (m != null) return m; + } + } + + for (String plugin : toLoad){ + Plugin pl = pm.getPlugin(plugin); + if (pl != null){ + Method m = createMethod(pl); + if (m != null) return m; + } + } + return null; } - /** - * Used by the plugin to setup version - * - * @param v version - */ - public static void setVersion(String v) { - version = v; - } - - /** - * Use to reset methods during disable - */ - public static void reset() { - version = null; - self = false; - Method = null; - preferred = ""; - attachables.clear(); - } - - /** - * Use to get version of Register plugin - * - * @return version - */ - public static String getVersion() { - return version; - } - - /** - * Returns an array of payment method names that have been loaded - * through the init method. - * - * @return Set - Array of payment methods that are loaded. - * @see #setMethod(org.bukkit.plugin.PluginManager) - */ - public static Set getDependencies() { - return dependencies; - } - - /** - * Interprets Plugin class data to verify whether it is compatible with an existing payment - * method to use for payments and other various economic activity. - * - * @param plugin Plugin data from bukkit, Internal Class file. - * @return Method or Null - */ public static Method createMethod(Plugin plugin) { for (Method method : methods){ if (method.isCompatible(plugin)) { @@ -109,129 +60,4 @@ public class Methods { } return null; } - - private static void addMethod(String name, Method method) { - dependencies.add(name); - methods.add(method); - } - - /** - * Verifies if Register has set a payment method for usage yet. - * - * @return boolean - * @see #setMethod(org.bukkit.plugin.PluginManager) - * @see #checkDisabled(org.bukkit.plugin.Plugin) - */ - public static boolean hasMethod() { - return (Method != null); - } - - /** - * Checks Plugin Class against a multitude of checks to verify it's usability - * as a payment method. - * - * @param manager the plugin manager for the server - * @return boolean True on success, False on failure. - */ - public static boolean setMethod(PluginManager manager) { - if (hasMethod()) - return true; - - if (self) { - self = false; - return false; - } - - int count = 0; - boolean match = false; - Plugin plugin; - - for (String name : dependencies) { - if (hasMethod()) - break; - - plugin = manager.getPlugin(name); - if (plugin == null || !plugin.isEnabled()) - continue; - - Method current = createMethod(plugin); - if (current == null) - continue; - - if (preferred.isEmpty()) - Method = current; - else - attachables.add(current); - } - - if (!preferred.isEmpty()) { - do { - if (hasMethod()) - match = true; - else { - for (Method attached : attachables) { - if (attached == null) continue; - - if (hasMethod()) { - match = true; break; - } - - if (preferred.isEmpty()) - Method = attached; - - if (count == 0) { - if (preferred.equalsIgnoreCase(attached.getName())) Method = attached; - } else { - Method = attached; - } - } - - count++; - } - } while (!match); - } - - return hasMethod(); - } - - /** - * Sets the preferred economy - * - * @param check The plugin name to check - * @return boolean - */ - public static boolean setPreferred(String check) { - if (dependencies.contains(check)) { - preferred = check; - return true; - } - - return false; - } - - /** - * Grab the existing and initialized (hopefully) Method Class. - * - * @return Method or Null - */ - public static Method getMethod() { - return Method; - } - - /** - * Verify is a plugin is disabled, only does this if we there is an existing payment - * method initialized in Register. - * - * @param method Plugin data from bukkit, Internal Class file. - * @return boolean - */ - public static boolean checkDisabled(Plugin method) { - if (!hasMethod()) - return true; - - if (Method.isCompatible(method)) - Method = null; - - return (Method == null); - } } diff --git a/com/nijikokun/register/payment/forChestShop/methods/BOSE7.java b/com/nijikokun/register/payment/forChestShop/methods/BOSE7.java index 0b6bf4f..e17787e 100644 --- a/com/nijikokun/register/payment/forChestShop/methods/BOSE7.java +++ b/com/nijikokun/register/payment/forChestShop/methods/BOSE7.java @@ -155,7 +155,7 @@ public class BOSE7 implements Method { } } - public class BOSEBankAccount implements MethodBankAccount { + public class BOSEBankAccount implements MethodBankAccount, MethodAccount { private String bank; private BOSEconomy BOSEconomy; diff --git a/plugin.yml b/plugin.yml index bb08180..28e3948 100644 --- a/plugin.yml +++ b/plugin.yml @@ -2,7 +2,7 @@ name: ChestShop main: com.Acrobot.ChestShop.ChestShop -version: 3.32 +version: 3.34 author: Acrobot @@ -10,7 +10,7 @@ description: > A chest shop for economy plugins. -softdepend: [Permissions, LWC, Lockette, Deadbolt, OddItem, Towny, WorldGuard] +softdepend: [Permissions, LWC, Lockette, Deadbolt, OddItem, Towny, WorldGuard, Vault, Heroes] commands: iteminfo: aliases: [iinfo] @@ -51,6 +51,8 @@ permissions: description: Allows user to buy from a shop ChestShop.shop.sell: description: Allows user to sell to a shop + ChestShop.nofee: + description: User doesn't have to pay the shop creation fee. ChestShop.admin: description: Allows user to modify/destroy other stores and create an Admin Shops default: op