From a49d51ce972de38550cda14ccf7dfd3a04d5a240 Mon Sep 17 00:00:00 2001 From: Acrobot Date: Thu, 16 Feb 2012 19:09:37 +0100 Subject: [PATCH] - Changed to the new, more robust event system - Added partial transactions (You have 5 items, shop wants 10 - you can sell your items for half the price) - Added a warning to the HTML generator - Fixed Towny integration - Fixed occasional ArrayOutOfBoundsExceptions - Fixed an error when a shop couldn't be created because a sign (not shop sign) was on other side of the block - Added SCL (SimpleChestLock) protection plugin to supported plugins - Updated Metrics (and added a new asynch thread for startup) - Removed Bukkit-1.0 workaround - Fixed plugin.yml formatting --- com/Acrobot/ChestShop/ChestShop.java | 27 +-- com/Acrobot/ChestShop/Commands/ItemInfo.java | 2 +- com/Acrobot/ChestShop/Config/Property.java | 3 +- com/Acrobot/ChestShop/DB/Generator.java | 1 + com/Acrobot/ChestShop/DB/Queue.java | 2 +- com/Acrobot/ChestShop/Economy/Economy.java | 2 +- com/Acrobot/ChestShop/Items/Items.java | 8 +- .../ChestShop/Listeners/blockBreak.java | 14 +- .../ChestShop/Listeners/blockPlace.java | 8 +- .../ChestShop/Listeners/entityExplode.java | 8 +- .../ChestShop/Listeners/playerInteract.java | 9 +- .../ChestShop/Listeners/pluginEnable.java | 19 +- .../ChestShop/Listeners/signChange.java | 8 +- com/Acrobot/ChestShop/Metrics.java | 208 ++++++++++-------- .../Protection/Plugins/SCLplugin.java | 25 +++ .../ChestShop/Protection/Security.java | 2 +- com/Acrobot/ChestShop/Shop/Shop.java | 68 ++++-- com/Acrobot/ChestShop/Utils/uInventory.java | 24 +- com/Acrobot/ChestShop/Utils/uNumber.java | 6 +- com/Acrobot/ChestShop/Utils/uTowny.java | 11 +- .../payment/forChestShop/methods/BOSE7.java | 6 +- plugin.yml | 11 +- 22 files changed, 279 insertions(+), 193 deletions(-) create mode 100644 com/Acrobot/ChestShop/Protection/Plugins/SCLplugin.java diff --git a/com/Acrobot/ChestShop/ChestShop.java b/com/Acrobot/ChestShop/ChestShop.java index 7986c04..7afc1b2 100644 --- a/com/Acrobot/ChestShop/ChestShop.java +++ b/com/Acrobot/ChestShop/ChestShop.java @@ -13,8 +13,6 @@ import com.Acrobot.ChestShop.Logging.FileWriterQueue; import com.avaje.ebean.EbeanServer; import com.lennardf1989.bukkitex.Database; import org.bukkit.Server; -import org.bukkit.event.Event; -import org.bukkit.event.Listener; import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; @@ -77,24 +75,13 @@ public class ChestShop extends JavaPlugin { ////////////////// REGISTER EVENTS, SCHEDULER & STATS /////////////////////////// private void registerEvents() { - blockBreak blockBreak = new blockBreak(); - registerEvent(Event.Type.BLOCK_BREAK, blockBreak); - registerEvent(Event.Type.BLOCK_PLACE, new blockPlace()); - registerEvent(Event.Type.SIGN_CHANGE, new signChange()); - registerEvent(Event.Type.PLAYER_INTERACT, new playerInteract(), Event.Priority.Highest); - registerEvent(Event.Type.PLUGIN_ENABLE, new pluginEnable()); - if (!Config.getBoolean(Property.USE_BUILT_IN_PROTECTION)) return; - registerEvent(Event.Type.BLOCK_PISTON_EXTEND, blockBreak); - registerEvent(Event.Type.BLOCK_PISTON_RETRACT, blockBreak); - registerEvent(Event.Type.ENTITY_EXPLODE, new entityExplode()); - } - - private void registerEvent(Event.Type type, Listener listener) { - registerEvent(type, listener, Event.Priority.Normal); - } - - private void registerEvent(Event.Type type, Listener listener, Event.Priority priority) { - pm.registerEvent(type, listener, priority, this); + PluginManager pm = getServer().getPluginManager(); + + pm.registerEvents(new blockBreak(), this); + pm.registerEvents(new blockPlace(), this); + pm.registerEvents(new signChange(), this); + pm.registerEvents(new playerInteract(), this); + pm.registerEvents(new entityExplode(), this); } private void scheduleTask(Runnable runnable, long startTime, long repetetionTime) { diff --git a/com/Acrobot/ChestShop/Commands/ItemInfo.java b/com/Acrobot/ChestShop/Commands/ItemInfo.java index c75f3a8..19c28cc 100644 --- a/com/Acrobot/ChestShop/Commands/ItemInfo.java +++ b/com/Acrobot/ChestShop/Commands/ItemInfo.java @@ -54,7 +54,7 @@ public class ItemInfo implements CommandExecutor { if (integer == 3) return "III"; if (integer == 4) return "IV"; if (integer == 5) return "V"; - return null; + return Integer.toString(integer); } diff --git a/com/Acrobot/ChestShop/Config/Property.java b/com/Acrobot/ChestShop/Config/Property.java index 4275af3..5368b46 100644 --- a/com/Acrobot/ChestShop/Config/Property.java +++ b/com/Acrobot/ChestShop/Config/Property.java @@ -35,7 +35,8 @@ public enum Property { 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?"), 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?"); + BLOCK_UPDATE(false, "EXPERIMENTAL: Should every ChestShop transaction result in a block update?"), + ALLOW_PARTIAL_TRANSACTIONS(true, "Can shops be used even when the seller doesn't have enough items? (The price will be scaled adequatly to the item amount)"); private final Object value; diff --git a/com/Acrobot/ChestShop/DB/Generator.java b/com/Acrobot/ChestShop/DB/Generator.java index af24080..ea1437d 100644 --- a/com/Acrobot/ChestShop/DB/Generator.java +++ b/com/Acrobot/ChestShop/DB/Generator.java @@ -24,6 +24,7 @@ public class Generator implements Runnable { private static BufferedWriter buf; public void run() { + if (row.isEmpty()) System.out.println(ChestShop.chatPrefix + "You lack the necessary HTML files in your plugins/ChestShop/HTML folder!"); generateStats(); } diff --git a/com/Acrobot/ChestShop/DB/Queue.java b/com/Acrobot/ChestShop/DB/Queue.java index 8790c9f..336151b 100644 --- a/com/Acrobot/ChestShop/DB/Queue.java +++ b/com/Acrobot/ChestShop/DB/Queue.java @@ -39,7 +39,7 @@ public class Queue implements Runnable { .getDB() .find(Transaction.class) .where() - .lt("sec", System.currentTimeMillis() / 1000 - Config.getInteger(Property.RECORD_TIME_TO_LIVE)) + .lt("sec", (System.currentTimeMillis() / 1000L) - Config.getInteger(Property.RECORD_TIME_TO_LIVE)) .findList(); } } diff --git a/com/Acrobot/ChestShop/Economy/Economy.java b/com/Acrobot/ChestShop/Economy/Economy.java index f1117f4..d8f287e 100644 --- a/com/Acrobot/ChestShop/Economy/Economy.java +++ b/com/Acrobot/ChestShop/Economy/Economy.java @@ -41,7 +41,7 @@ public class Economy { } public static void subtract(String name, float amount) { - economy.subtract(name, amount); + economy.subtract(uLongName.getName(name), amount); } public static boolean hasEnough(String name, float amount) { diff --git a/com/Acrobot/ChestShop/Items/Items.java b/com/Acrobot/ChestShop/Items/Items.java index 98df190..a521bcf 100644 --- a/com/Acrobot/ChestShop/Items/Items.java +++ b/com/Acrobot/ChestShop/Items/Items.java @@ -50,8 +50,12 @@ public class Items { public static ItemStack getItemStack(String itemName) { ItemStack toReturn = getFromOddItem(itemName); if (toReturn != null) return toReturn; - - String first = itemName.split(":|-")[0]; + + if (itemName == null) itemName = ""; + String[] split = itemName.split(":|-"); + + if (split.length == 0) return null; + String first = split[0]; String[] space = first.split(" "); Material material = getMaterial(first); diff --git a/com/Acrobot/ChestShop/Listeners/blockBreak.java b/com/Acrobot/ChestShop/Listeners/blockBreak.java index f88871a..21dd3ca 100644 --- a/com/Acrobot/ChestShop/Listeners/blockBreak.java +++ b/com/Acrobot/ChestShop/Listeners/blockBreak.java @@ -14,8 +14,9 @@ import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.Sign; import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.block.BlockListener; import org.bukkit.event.block.BlockPistonExtendEvent; import org.bukkit.event.block.BlockPistonRetractEvent; import org.bukkit.material.PistonBaseMaterial; @@ -26,7 +27,7 @@ import java.util.List; /** * @author Acrobot */ -public class blockBreak extends BlockListener { +public class blockBreak implements Listener { public static boolean cancellingBlockBreak(Block block, Player player) { if (block == null) return false; if (player != null && (Permission.has(player, Permission.ADMIN) || Permission.has(player, Permission.MOD))) return false; @@ -55,7 +56,8 @@ public class blockBreak extends BlockListener { return uBlock.findRestrictedSign(block) != null; } - public void onBlockBreak(BlockBreakEvent event) { + @EventHandler + public static void onBlockBreak(BlockBreakEvent event) { if (cancellingBlockBreak(event.getBlock(), event.getPlayer())) event.setCancelled(true); } @@ -72,7 +74,8 @@ public class blockBreak extends BlockListener { && !Permission.otherName(player, sign.getLine(0))); } - public void onBlockPistonExtend(BlockPistonExtendEvent event) { + @EventHandler + public static void onBlockPistonExtend(BlockPistonExtendEvent event) { for (Block b : getExtendBlocks(event)) { if (cancellingBlockBreak(b, null)) { event.setCancelled(true); @@ -81,7 +84,8 @@ public class blockBreak extends BlockListener { } } - public void onBlockPistonRetract(BlockPistonRetractEvent event) { + @EventHandler + public static void onBlockPistonRetract(BlockPistonRetractEvent event) { if (cancellingBlockBreak(getRetractBlock(event), null)) event.setCancelled(true); } diff --git a/com/Acrobot/ChestShop/Listeners/blockPlace.java b/com/Acrobot/ChestShop/Listeners/blockPlace.java index f79ff98..cb70f3e 100644 --- a/com/Acrobot/ChestShop/Listeners/blockPlace.java +++ b/com/Acrobot/ChestShop/Listeners/blockPlace.java @@ -9,14 +9,16 @@ import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.Chest; import org.bukkit.block.Sign; -import org.bukkit.event.block.BlockListener; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; import org.bukkit.event.block.BlockPlaceEvent; /** * @author Acrobot */ -public class blockPlace extends BlockListener { - public void onBlockPlace(BlockPlaceEvent event) { +public class blockPlace implements Listener { + @EventHandler + public static void onBlockPlace(BlockPlaceEvent event) { Block block = event.getBlockAgainst(); if (uSign.isSign(block) && uSign.isValid((Sign) block.getState())) { event.setCancelled(true); diff --git a/com/Acrobot/ChestShop/Listeners/entityExplode.java b/com/Acrobot/ChestShop/Listeners/entityExplode.java index a71fe52..507ebd2 100644 --- a/com/Acrobot/ChestShop/Listeners/entityExplode.java +++ b/com/Acrobot/ChestShop/Listeners/entityExplode.java @@ -1,14 +1,16 @@ package com.Acrobot.ChestShop.Listeners; import org.bukkit.block.Block; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityExplodeEvent; -import org.bukkit.event.entity.EntityListener; /** * @author Acrobot */ -public class entityExplode extends EntityListener { - public void onEntityExplode(EntityExplodeEvent event) { +public class entityExplode implements Listener { + @EventHandler + public static void onEntityExplode(EntityExplodeEvent event) { if (event.isCancelled() || event.blockList() == null) return; for (Block block : event.blockList()) { if (blockBreak.cancellingBlockBreak(block, null)) { diff --git a/com/Acrobot/ChestShop/Listeners/playerInteract.java b/com/Acrobot/ChestShop/Listeners/playerInteract.java index 4e77939..e0ff02e 100644 --- a/com/Acrobot/ChestShop/Listeners/playerInteract.java +++ b/com/Acrobot/ChestShop/Listeners/playerInteract.java @@ -19,21 +19,24 @@ 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.event.player.PlayerListener; import java.util.HashMap; /** * @author Acrobot */ -public class playerInteract extends PlayerListener { +public class playerInteract implements Listener { private static final HashMap lastTransactionTime = new HashMap(); //Last player's transaction public static int interval = 100;//Minimal interval between transactions - public void onPlayerInteract(PlayerInteractEvent event) { + @EventHandler(priority = EventPriority.HIGHEST) + public static void onPlayerInteract(PlayerInteractEvent event) { Action action = event.getAction(); if (action != Action.LEFT_CLICK_BLOCK && action != Action.RIGHT_CLICK_BLOCK) return; diff --git a/com/Acrobot/ChestShop/Listeners/pluginEnable.java b/com/Acrobot/ChestShop/Listeners/pluginEnable.java index bc7a0fd..2e737ee 100644 --- a/com/Acrobot/ChestShop/Listeners/pluginEnable.java +++ b/com/Acrobot/ChestShop/Listeners/pluginEnable.java @@ -1,14 +1,12 @@ package com.Acrobot.ChestShop.Listeners; import com.Acrobot.ChestShop.ChestShop; +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.DeadboltPlugin; -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.Plugins.*; import com.Acrobot.ChestShop.Protection.Security; import com.Acrobot.ChestShop.Utils.uHeroes; import com.Acrobot.ChestShop.Utils.uNumber; @@ -22,8 +20,8 @@ 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 com.webkonsept.bukkit.simplechestlock.SCL; 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; @@ -32,7 +30,7 @@ import org.yi.acru.bukkit.Lockette.Lockette; /** * @author Acrobot */ -public class pluginEnable extends ServerListener { +public class pluginEnable { public static void initializePlugins() { Security.protections.add(new Default()); //Initialize basic protection @@ -46,7 +44,10 @@ public class pluginEnable extends ServerListener { private static void loadRegister(){ if (com.Acrobot.ChestShop.Economy.Economy.economy == null) { Method m = Methods.load(ChestShop.pm); - if (m == null) return; + if (m == null) { + com.Acrobot.ChestShop.Economy.Economy.economy = new NoProvider(); + return; + } Register.eco = m; com.Acrobot.ChestShop.Economy.Economy.economy = new Register(); System.out.println(ChestShop.chatPrefix + m.getName() + " loaded."); @@ -66,7 +67,6 @@ public class pluginEnable extends ServerListener { DeadboltPlugin.deadbolt = (Deadbolt) plugin; Security.protections.add(new DeadboltPlugin()); } else if (name.equals("OddItem")) { - if (Odd.isInitialized()) return; 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")) { @@ -87,6 +87,9 @@ public class pluginEnable extends ServerListener { return; } else if (name.equals("Heroes")){ uHeroes.heroes = (Heroes) plugin; + } else if (name.equals("SimpleChestLock")) { + SCLplugin.scl = (SCL) plugin; + Security.protections.add(new SCLplugin()); } PluginDescriptionFile description = plugin.getDescription(); diff --git a/com/Acrobot/ChestShop/Listeners/signChange.java b/com/Acrobot/ChestShop/Listeners/signChange.java index cdbde2e..bb878c0 100644 --- a/com/Acrobot/ChestShop/Listeners/signChange.java +++ b/com/Acrobot/ChestShop/Listeners/signChange.java @@ -15,16 +15,18 @@ import org.bukkit.block.BlockFace; import org.bukkit.block.Chest; import org.bukkit.block.Sign; import org.bukkit.entity.Player; -import org.bukkit.event.block.BlockListener; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; import org.bukkit.event.block.SignChangeEvent; import org.bukkit.inventory.ItemStack; /** * @author Acrobot */ -public class signChange extends BlockListener { +public class signChange implements Listener { - public void onSignChange(SignChangeEvent event) { + @EventHandler + public static void onSignChange(SignChangeEvent event) { Block signBlock = event.getBlock(); String[] line = event.getLines(); diff --git a/com/Acrobot/ChestShop/Metrics.java b/com/Acrobot/ChestShop/Metrics.java index e6f52a2..89f4740 100644 --- a/com/Acrobot/ChestShop/Metrics.java +++ b/com/Acrobot/ChestShop/Metrics.java @@ -1,52 +1,40 @@ -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 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.io.*; 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; +import java.util.*; /** * Tooling to post to metrics.griefcraft.com @@ -72,6 +60,12 @@ public class Metrics { */ public abstract int getValue(); + /** + * Called after the website graphs have been updated + */ + public void reset() { + } + @Override public int hashCode() { return getColumnName().hashCode() + getValue(); @@ -92,7 +86,7 @@ public class Metrics { /** * The metrics revision number */ - private final static int REVISION = 3; + private final static int REVISION = 4; /** * The base url of the metrics domain @@ -172,10 +166,20 @@ public class Metrics { */ public void beginMeasuringPlugin(final Plugin plugin) throws IOException { // Did we opt out? - if (configuration.getBoolean("opt-out", false)) return; + if (configuration.getBoolean("opt-out", false)) { + return; + } // First tell the server about us - postPlugin(plugin, false); + 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 plugin.getServer().getScheduler().scheduleAsyncRepeatingTask(plugin, new Runnable() { @@ -183,12 +187,76 @@ public class Metrics { try { postPlugin(plugin, true); } catch (IOException e) { - System.out.println("[ChestShop] There was an error while submitting statistics."); + System.out.println("[Metrics] " + e.getMessage()); } } }, PING_INTERVAL * 1200, PING_INTERVAL * 1200); } + /** + * 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"; + 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))); + + // If we're pinging, append it + if (isPing) { + data.append(gField("ping", "true")); + } + + // Add any custom data (if applicable) + Set plotters = customData.get(plugin); + + if (plotters != null) { + for (Plotter plotter : plotters) { + data.append(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.toString()); + 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); //Throw the exception + } 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(); + } + } + } + } + //if (response.startsWith("OK")) - We should get "OK" followed by an optional description if everything goes right + } + /** * Generates a field * @param name Field name @@ -200,56 +268,6 @@ public class Metrics { 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 * diff --git a/com/Acrobot/ChestShop/Protection/Plugins/SCLplugin.java b/com/Acrobot/ChestShop/Protection/Plugins/SCLplugin.java new file mode 100644 index 0000000..d78885b --- /dev/null +++ b/com/Acrobot/ChestShop/Protection/Plugins/SCLplugin.java @@ -0,0 +1,25 @@ +package com.Acrobot.ChestShop.Protection.Plugins; + +import com.Acrobot.ChestShop.Protection.Protection; +import com.webkonsept.bukkit.simplechestlock.SCL; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; + +/** + * @author Acrobot + */ +public class SCLplugin implements Protection { + public static SCL scl; + + public boolean isProtected(Block block) { + return scl.chests.isLocked(block); + } + + public boolean canAccess(Player player, Block block) { + return scl.chests.getOwner(block).equalsIgnoreCase(player.getName()); + } + + public boolean protect(String name, Block block) { + return false; + } +} diff --git a/com/Acrobot/ChestShop/Protection/Security.java b/com/Acrobot/ChestShop/Protection/Security.java index a98c1d4..c499b32 100644 --- a/com/Acrobot/ChestShop/Protection/Security.java +++ b/com/Acrobot/ChestShop/Protection/Security.java @@ -42,7 +42,7 @@ public class Security { private static boolean thereIsAnotherSignByPlayer(Block baseBlock, Block signBlock, String shortName) { for (BlockFace bf : faces) { Block block = baseBlock.getRelative(bf); - if (uSign.isSign(block) && !block.equals(signBlock) && blockBreak.getAttachedFace((Sign) block.getState()).equals(baseBlock) && !((Sign) block.getState()).getLine(0).equals(shortName)) + if (uSign.isSign(block) && uSign.isValid((Sign) block.getState()) && !block.equals(signBlock) && blockBreak.getAttachedFace((Sign) block.getState()).equals(baseBlock) && !((Sign) block.getState()).getLine(0).equals(shortName)) return true; } return false; diff --git a/com/Acrobot/ChestShop/Shop/Shop.java b/com/Acrobot/ChestShop/Shop/Shop.java index bd18d4c..6bdb3b5 100644 --- a/com/Acrobot/ChestShop/Shop/Shop.java +++ b/com/Acrobot/ChestShop/Shop/Shop.java @@ -23,9 +23,9 @@ public class Shop { private final ChestObject chest; public final ItemStack stock; - public final int stockAmount; - public final float buyPrice; - public final float sellPrice; + public int stockAmount; + public float buyPrice; + public float sellPrice; public final String owner; private final Sign sign; @@ -55,8 +55,14 @@ public class Shop { } String playerName = player.getName(); if (!Economy.hasEnough(playerName, buyPrice)) { - player.sendMessage(Config.getLocal(Language.NOT_ENOUGH_MONEY)); - return; + int items = calculateItemAmount(Economy.balance(playerName), true); + if (!Config.getBoolean(Property.ALLOW_PARTIAL_TRANSACTIONS) || items < 1) { + player.sendMessage(Config.getLocal(Language.NOT_ENOUGH_MONEY)); + return; + } else { + buyPrice = (buyPrice / stockAmount) * items; + stockAmount = items; + } } if (!stockFitsPlayer(player)) { player.sendMessage(Config.getLocal(Language.NOT_ENOUGH_SPACE_IN_INVENTORY)); @@ -66,10 +72,17 @@ public class Shop { String materialName = stock.getType().name(); if (!isAdminShop() && !hasEnoughStock()) { - player.sendMessage(Config.getLocal(Language.NOT_ENOUGH_STOCK)); - if (!Config.getBoolean(Property.SHOW_MESSAGE_OUT_OF_STOCK)) return; - sendMessageToOwner(Config.getLocal(Language.NOT_ENOUGH_STOCK_IN_YOUR_SHOP).replace("%material", materialName)); - return; + int items = stockAmount(stock, durability); + if (!Config.getBoolean(Property.ALLOW_PARTIAL_TRANSACTIONS) || items < 1) { + player.sendMessage(Config.getLocal(Language.NOT_ENOUGH_STOCK)); + + if (!Config.getBoolean(Property.SHOW_MESSAGE_OUT_OF_STOCK)) return; + sendMessageToOwner(Config.getLocal(Language.NOT_ENOUGH_STOCK_IN_YOUR_SHOP).replace("%material", materialName)); + return; + } else { + buyPrice = (buyPrice / stockAmount) * items; + stockAmount = items; + } } String account = getOwnerAccount(); @@ -102,7 +115,7 @@ public class Shop { .replace("%buyer", playerName) .replace("%price", formatedPrice)); } - + if (Config.getBoolean(Property.BLOCK_UPDATE)) uBlock.blockUpdate(sign.getBlock()); } @@ -124,20 +137,31 @@ public class Shop { boolean accountExists = !account.isEmpty() && Economy.hasAccount(account); if (accountExists && !Economy.hasEnough(account, sellPrice)) { - player.sendMessage(Config.getLocal(Language.NOT_ENOUGH_MONEY_SHOP)); - return; + int items = calculateItemAmount(Economy.balance(account), false); + if (!Config.getBoolean(Property.ALLOW_PARTIAL_TRANSACTIONS) || items < 1) { + player.sendMessage(Config.getLocal(Language.NOT_ENOUGH_MONEY_SHOP)); + return; + } else { + sellPrice = (sellPrice / stockAmount) * items; + stockAmount = items; + } } + if (uInventory.amount(player.getInventory(), stock, durability) < stockAmount) { + int items = uInventory.amount(player.getInventory(), stock, durability); + if (!Config.getBoolean(Property.ALLOW_PARTIAL_TRANSACTIONS) || items < 1) { + player.sendMessage(Config.getLocal(Language.NOT_ENOUGH_ITEMS_TO_SELL)); + return; + } else { + sellPrice = (sellPrice / stockAmount) * items; + stockAmount = items; + } + } + if (!isAdminShop() && !stockFitsChest(chest)) { player.sendMessage(Config.getLocal(Language.NOT_ENOUGH_SPACE_IN_CHEST)); return; } - if (uInventory.amount(player.getInventory(), stock, durability) < stockAmount) { - player.sendMessage(Config.getLocal(Language.NOT_ENOUGH_ITEMS_TO_SELL)); - return; - } - - if (accountExists) Economy.subtract(account, sellPrice); if (!isAdminShop()) chest.addItem(stock, stockAmount); @@ -180,6 +204,10 @@ public class Shop { private boolean hasEnoughStock() { return chest.hasEnough(stock, stockAmount, durability); } + + private int stockAmount(ItemStack item, short durability){ + return chest.amount(item, durability); + } private boolean stockFitsPlayer(Player player) { return uInventory.fits(player.getInventory(), stock, stockAmount, durability) <= 0; @@ -189,6 +217,10 @@ public class Shop { return chest.fits(stock, stockAmount, durability); } + private int calculateItemAmount(double money, boolean buy) { + return (int) Math.floor(money / ((buy ? buyPrice : sellPrice) / stockAmount)); + } + private void sendMessageToOwner(String msg) { if (!isAdminShop()) { Player player = ChestShop.getBukkitServer().getPlayer(owner); diff --git a/com/Acrobot/ChestShop/Utils/uInventory.java b/com/Acrobot/ChestShop/Utils/uInventory.java index 1d99633..bed9a9b 100644 --- a/com/Acrobot/ChestShop/Utils/uInventory.java +++ b/com/Acrobot/ChestShop/Utils/uInventory.java @@ -6,6 +6,8 @@ import org.bukkit.Material; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import java.util.HashMap; + /** * @author Acrobot */ @@ -45,29 +47,24 @@ public class uInventory { public static int add(Inventory inv, ItemStack item, int amount) { amount = (amount > 0 ? amount : 1); if (Config.getBoolean(Property.STACK_UNSTACKABLES)) return addAndStackTo64(inv, item, amount); - /*ItemStack itemstack = new ItemStack(item.getType(), amount, item.getDurability()); + ItemStack itemstack = new ItemStack(item.getType(), amount, item.getDurability()); itemstack.addEnchantments(item.getEnchantments()); + HashMap items = inv.addItem(itemstack); amount = 0; for (ItemStack toAdd : items.values()) amount += toAdd.getAmount(); - return amount;*/ //TODO: revert when Bukkit releases new RB - - return addManually(inv, item, amount); - } - - private static int addManually(Inventory inv, ItemStack item, int amount) { - return addManually(inv, item, amount, (item.getType() != Material.POTION ? item.getType().getMaxStackSize() : 1)); //TODO Change it when it's repaired in Bukkit + return amount; } public static int addAndStackTo64(Inventory inv, ItemStack item, int amount) { return addManually(inv, item, amount, 64); } - - public static int addManually(Inventory inv, ItemStack item, int amount, int max){ + + public static int addManually(Inventory inv, ItemStack item, int amount, int max) { if (amount <= 0) return 0; - for (int slot = 0; slot < inv.getSize() && amount > 0; slot++){ + for (int slot = 0; slot < inv.getSize() && amount > 0; slot++) { ItemStack curItem = inv.getItem(slot); ItemStack dupe = item.clone(); @@ -101,7 +98,6 @@ public class uInventory { public static int fits(Inventory inv, ItemStack item, int amount, short durability) { int maxStackSize = (Config.getBoolean(Property.STACK_UNSTACKABLES) ? 64 : item.getType().getMaxStackSize()); - if (item.getType() == Material.POTION) maxStackSize = 1; //TODO Bukkit, can you fix that? int amountLeft = amount; @@ -122,8 +118,8 @@ public class uInventory { return amountLeft; } - - private static boolean equals(ItemStack i, ItemStack item, short durability){ + + private static boolean equals(ItemStack i, ItemStack item, short durability) { return i != null && i.getType() == item.getType() && i.getEnchantments().equals(item.getEnchantments()) diff --git a/com/Acrobot/ChestShop/Utils/uNumber.java b/com/Acrobot/ChestShop/Utils/uNumber.java index 7d0f840..d70ed72 100644 --- a/com/Acrobot/ChestShop/Utils/uNumber.java +++ b/com/Acrobot/ChestShop/Utils/uNumber.java @@ -10,7 +10,7 @@ public class uNumber { try { Integer.parseInt(string); return true; - } catch (Exception e) { + } catch (NumberFormatException e) { return false; } } @@ -19,7 +19,7 @@ public class uNumber { try { Float.parseFloat(string); return true; - } catch (Exception e) { + } catch (NumberFormatException e) { return false; } } @@ -28,7 +28,7 @@ public class uNumber { try { Double.parseDouble(string); return true; - } catch (Exception e) { + } catch (NumberFormatException e) { return false; } } diff --git a/com/Acrobot/ChestShop/Utils/uTowny.java b/com/Acrobot/ChestShop/Utils/uTowny.java index b26b1b7..8a2b89d 100644 --- a/com/Acrobot/ChestShop/Utils/uTowny.java +++ b/com/Acrobot/ChestShop/Utils/uTowny.java @@ -5,6 +5,7 @@ import com.Acrobot.ChestShop.Config.Property; import com.palmergames.bukkit.towny.NotRegisteredException; import com.palmergames.bukkit.towny.object.TownBlockType; import org.bukkit.Location; +import org.bukkit.block.Block; import org.bukkit.entity.Player; @@ -21,12 +22,16 @@ public class uTowny { return isResident(player, chestLocation) && isResident(player, signLocation); } - public static boolean isNotInTheWilderness(Location chestLocation, Location signLocation) { - return !uSign.towny.getTownyUniverse().isWilderness(chestLocation.getBlock()) && !uSign.towny.getTownyUniverse().isWilderness(signLocation.getBlock()); + public static boolean isInWilderness(Location chestLocation, Location signLocation) { + return isInWilderness(chestLocation.getBlock()) || isInWilderness(signLocation.getBlock()); + } + + private static boolean isInWilderness(Block block){ + return uSign.towny.getTownyUniverse().isWilderness(block); } public static boolean canBuild(Player player, Location chestLocation, Location signLocation) { - return uSign.towny == null || !Config.getBoolean(Property.TOWNY_INTEGRATION) || (isNotInTheWilderness(chestLocation, signLocation) && isInsideShopPlot(chestLocation, signLocation) && isPlotOwner(player, chestLocation, signLocation)); + return uSign.towny == null || !Config.getBoolean(Property.TOWNY_INTEGRATION) || (!isInWilderness(chestLocation, signLocation) && isInsideShopPlot(chestLocation, signLocation) && isPlotOwner(player, chestLocation, signLocation)); } private static boolean isBlockOwner(Player player, Location location) { diff --git a/com/nijikokun/register/payment/forChestShop/methods/BOSE7.java b/com/nijikokun/register/payment/forChestShop/methods/BOSE7.java index e17787e..c83d4be 100644 --- a/com/nijikokun/register/payment/forChestShop/methods/BOSE7.java +++ b/com/nijikokun/register/payment/forChestShop/methods/BOSE7.java @@ -75,7 +75,7 @@ public class BOSE7 implements Method { } public MethodAccount getAccount(String name) { - if(!hasAccount(name)) + if(!hasAccount(name)) return null; return new BOSEAccount(name, this.BOSEconomy); @@ -98,7 +98,7 @@ public class BOSE7 implements Method { BOSEconomy = (BOSEconomy)plugin; } - public class BOSEAccount implements MethodAccount { + public static class BOSEAccount implements MethodAccount { private String name; private BOSEconomy BOSEconomy; @@ -155,7 +155,7 @@ public class BOSE7 implements Method { } } - public class BOSEBankAccount implements MethodBankAccount, MethodAccount { + public static class BOSEBankAccount implements MethodBankAccount, MethodAccount { private String bank; private BOSEconomy BOSEconomy; diff --git a/plugin.yml b/plugin.yml index 28e3948..5a7bf3a 100644 --- a/plugin.yml +++ b/plugin.yml @@ -2,7 +2,7 @@ name: ChestShop main: com.Acrobot.ChestShop.ChestShop -version: 3.34 +version: 3.35 author: Acrobot @@ -10,7 +10,8 @@ description: > A chest shop for economy plugins. -softdepend: [Permissions, LWC, Lockette, Deadbolt, OddItem, Towny, WorldGuard, Vault, Heroes] +softdepend: [Permissions, LWC, Lockette, Deadbolt, OddItem, Towny, WorldGuard, Vault, Heroes, + iConomy, BOSEconomy, Essentials, 3co, MultiCurrency, Currency, SimpleChestLock] commands: iteminfo: aliases: [iinfo] @@ -106,7 +107,7 @@ permissions: ChestShop.shop.create.292: true #IronHoe ChestShop.shop.create.goldgrade: description: Allows to create a shop that sells gold gear - children: + children: ChestShop.shop.create.314: true #GoldHelm ChestShop.shop.create.315: true #GoldChestplate ChestShop.shop.create.316: true #GoldLeggings @@ -118,7 +119,7 @@ permissions: ChestShop.shop.create.294: true #GoldHoe ChestShop.shop.create.stonegrade: description: Allows to create a shop that sells stone tools and chain armor - children: + children: ChestShop.shop.create.302: true #ChainHelm ChestShop.shop.create.303: true #ChainChestplate ChestShop.shop.create.304: true #ChainLeggings @@ -130,7 +131,7 @@ permissions: ChestShop.shop.create.291: true #StoneHoe ChestShop.shop.create.woodgrade: description: Allows to create a shop that sells wood tools and leather armor - children: + children: ChestShop.shop.create.298: true #LeatherHelm ChestShop.shop.create.299: true #LeatherChestplate ChestShop.shop.create.300: true #LeatherLeggings