Stock Counter (Resolves #365) (#368)

This commit is contained in:
Brice Frisco 2020-10-30 16:45:16 -05:00 committed by GitHub
parent 15b9382b09
commit 8d98958c2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 261 additions and 5 deletions

View File

@ -0,0 +1,22 @@
package com.Acrobot.Breeze.Utils;
import java.util.regex.Pattern;
/**
* @author bricefrisco
*/
public class QuantityUtil {
private static final Pattern QUANTITY_LINE_WITH_COUNTER_PATTERN = Pattern.compile("^Q [1-9][0-9]{0,4} : C [0-9]{0,5}$");
public static int parseQuantity(String quantityLine) throws IllegalArgumentException {
if (quantityLineContainsCounter(quantityLine)) {
return Integer.parseInt(quantityLine.split(" : ")[0].replace("Q ", ""));
}
return Integer.parseInt(quantityLine);
}
public static boolean quantityLineContainsCounter(String quantityLine) {
return QUANTITY_LINE_WITH_COUNTER_PATTERN.matcher(quantityLine).matches();
}
}

View File

@ -20,6 +20,7 @@ import com.Acrobot.ChestShop.Listeners.GarbageTextListener;
import com.Acrobot.ChestShop.Listeners.Item.ItemMoveListener; import com.Acrobot.ChestShop.Listeners.Item.ItemMoveListener;
import com.Acrobot.ChestShop.Listeners.ItemInfoListener; import com.Acrobot.ChestShop.Listeners.ItemInfoListener;
import com.Acrobot.ChestShop.Listeners.Modules.MetricsModule; import com.Acrobot.ChestShop.Listeners.Modules.MetricsModule;
import com.Acrobot.ChestShop.Listeners.Modules.StockCounterModule;
import com.Acrobot.ChestShop.Listeners.SignParseListener; import com.Acrobot.ChestShop.Listeners.SignParseListener;
import com.Acrobot.ChestShop.Listeners.Modules.DiscountModule; import com.Acrobot.ChestShop.Listeners.Modules.DiscountModule;
import com.Acrobot.ChestShop.Listeners.Modules.PriceRestrictionModule; import com.Acrobot.ChestShop.Listeners.Modules.PriceRestrictionModule;
@ -77,7 +78,6 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.logging.FileHandler; import java.util.logging.FileHandler;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -394,6 +394,7 @@ public class ChestShop extends JavaPlugin {
registerEvent(new DiscountModule()); registerEvent(new DiscountModule());
registerEvent(new MetricsModule()); registerEvent(new MetricsModule());
registerEvent(new PriceRestrictionModule()); registerEvent(new PriceRestrictionModule());
registerEvent(new StockCounterModule());
registerEconomicalModules(); registerEconomicalModules();
} }

View File

@ -315,4 +315,8 @@ public class Properties {
@PrecededBySpace @PrecededBySpace
@ConfigurationComment("Add icons and make item names hoverable in transaction messages when ShowItem is installed?") @ConfigurationComment("Add icons and make item names hoverable in transaction messages when ShowItem is installed?")
public static boolean SHOWITEM_MESSAGE = true; public static boolean SHOWITEM_MESSAGE = true;
@PrecededBySpace
@ConfigurationComment("Add stock counter to quantity line?")
public static boolean USE_STOCK_COUNTER = false;
} }

View File

@ -1,6 +1,7 @@
package com.Acrobot.ChestShop.Listeners.Modules; package com.Acrobot.ChestShop.Listeners.Modules;
import com.Acrobot.Breeze.Utils.PriceUtil; import com.Acrobot.Breeze.Utils.PriceUtil;
import com.Acrobot.Breeze.Utils.QuantityUtil;
import com.Acrobot.ChestShop.ChestShop; import com.Acrobot.ChestShop.ChestShop;
import com.Acrobot.ChestShop.Events.ChestShopReloadEvent; import com.Acrobot.ChestShop.Events.ChestShopReloadEvent;
import com.Acrobot.ChestShop.Events.ItemParseEvent; import com.Acrobot.ChestShop.Events.ItemParseEvent;
@ -115,7 +116,7 @@ public class PriceRestrictionModule implements Listener {
String itemType = material.getType().toString().toLowerCase(Locale.ROOT); String itemType = material.getType().toString().toLowerCase(Locale.ROOT);
int amount; int amount;
try { try {
amount = Integer.parseInt(event.getSignLine(QUANTITY_LINE)); amount = QuantityUtil.parseQuantity(event.getSignLine(QUANTITY_LINE));
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
return; return;
} }

View File

@ -0,0 +1,164 @@
package com.Acrobot.ChestShop.Listeners.Modules;
import com.Acrobot.Breeze.Utils.InventoryUtil;
import com.Acrobot.Breeze.Utils.QuantityUtil;
import com.Acrobot.ChestShop.ChestShop;
import com.Acrobot.ChestShop.Configuration.Properties;
import com.Acrobot.ChestShop.Events.ItemParseEvent;
import com.Acrobot.ChestShop.Events.PreShopCreationEvent;
import com.Acrobot.ChestShop.Events.TransactionEvent;
import com.Acrobot.ChestShop.Signs.ChestShopSign;
import com.Acrobot.ChestShop.Utils.uBlock;
import org.bukkit.Bukkit;
import org.bukkit.block.Sign;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import java.util.IllegalFormatException;
import static com.Acrobot.ChestShop.Signs.ChestShopSign.NAME_LINE;
import static com.Acrobot.ChestShop.Signs.ChestShopSign.ITEM_LINE;
import static com.Acrobot.ChestShop.Signs.ChestShopSign.QUANTITY_LINE;
/**
* @author bricefrisco
*/
public class StockCounterModule implements Listener {
private static final String PRICE_LINE_WITH_COUNT = "Q %d : C %d";
@EventHandler(priority = EventPriority.HIGH)
public static void onPreShopCreation(PreShopCreationEvent event) {
int quantity;
try {
quantity = QuantityUtil.parseQuantity(event.getSignLine(QUANTITY_LINE));
} catch (IllegalArgumentException invalidQuantity) {
return;
}
if (QuantityUtil.quantityLineContainsCounter(event.getSignLine(QUANTITY_LINE))) {
event.setSignLine(QUANTITY_LINE, Integer.toString(quantity));
}
if (!Properties.USE_STOCK_COUNTER || ChestShopSign.isAdminShop(event.getSignLine(NAME_LINE))) {
return;
}
if (Properties.MAX_SHOP_AMOUNT > 99999) {
ChestShop.getBukkitLogger().warning("Stock counter cannot be used if MAX_SHOP_AMOUNT is over 5 digits");
return;
}
ItemStack itemTradedByShop = determineItemTradedByShop(event.getSignLine(ITEM_LINE));
Inventory chestShopInventory = uBlock.findConnectedContainer(event.getSign()).getInventory();
event.setSignLine(QUANTITY_LINE, getQuantityLineWithCounter(quantity, itemTradedByShop, chestShopInventory));
}
@EventHandler
public static void onInventoryClose(InventoryCloseEvent event) {
if (event.getInventory().getLocation() == null || !ChestShopSign.isShopBlock(event.getInventory().getLocation().getBlock())) {
return;
}
for (Sign shopSign : uBlock.findConnectedShopSigns(event.getInventory().getHolder())) {
if (ChestShopSign.isAdminShop(shopSign)) {
return;
}
if (!Properties.USE_STOCK_COUNTER) {
if (QuantityUtil.quantityLineContainsCounter(shopSign.getLine(QUANTITY_LINE))) {
removeCounterFromQuantityLine(shopSign);
}
continue;
}
if (Properties.MAX_SHOP_AMOUNT > 99999) {
ChestShop.getBukkitLogger().warning("Stock counter cannot be used if MAX_SHOP_AMOUNT is over 5 digits");
if (QuantityUtil.quantityLineContainsCounter(shopSign.getLine(QUANTITY_LINE))) {
removeCounterFromQuantityLine(shopSign);
}
return;
}
updateCounterOnQuantityLine(shopSign, event.getInventory());
}
}
@EventHandler(priority = EventPriority.HIGH)
public static void onTransaction(final TransactionEvent event) {
if (!Properties.USE_STOCK_COUNTER) {
if (QuantityUtil.quantityLineContainsCounter(event.getSign().getLine(QUANTITY_LINE))) {
removeCounterFromQuantityLine(event.getSign());
}
return;
}
if (Properties.MAX_SHOP_AMOUNT > 99999) {
ChestShop.getBukkitLogger().warning("Stock counter cannot be used if MAX_SHOP_AMOUNT is over 5 digits");
if (QuantityUtil.quantityLineContainsCounter(event.getSign().getLine(QUANTITY_LINE))) {
removeCounterFromQuantityLine(event.getSign());
}
return;
}
if (ChestShopSign.isAdminShop(event.getSign())) {
return;
}
for (Sign shopSign : uBlock.findConnectedShopSigns(event.getOwnerInventory().getHolder())) {
updateCounterOnQuantityLine(shopSign, event.getOwnerInventory());
}
}
public static void updateCounterOnQuantityLine(Sign sign, Inventory chestShopInventory) {
ItemStack itemTradedByShop = determineItemTradedByShop(sign);
if (itemTradedByShop == null) {
return;
}
int quantity;
try {
quantity = QuantityUtil.parseQuantity(sign.getLine(QUANTITY_LINE));
} catch (IllegalFormatException invalidQuantity) {
return;
}
int numTradedItemsInChest = InventoryUtil.getAmount(itemTradedByShop, chestShopInventory);
sign.setLine(QUANTITY_LINE, String.format(PRICE_LINE_WITH_COUNT, quantity, numTradedItemsInChest));
sign.update(true);
}
public static void removeCounterFromQuantityLine(Sign sign) {
int quantity;
try {
quantity = QuantityUtil.parseQuantity(sign.getLine(QUANTITY_LINE));
} catch (IllegalFormatException invalidQuantity) {
return;
}
sign.setLine(QUANTITY_LINE, Integer.toString(quantity));
sign.update(true);
}
public static String getQuantityLineWithCounter(int amount, ItemStack itemTransacted, Inventory chestShopInventory) {
int numTransactionItemsInChest = InventoryUtil.getAmount(itemTransacted, chestShopInventory);
return String.format(PRICE_LINE_WITH_COUNT, amount, numTransactionItemsInChest);
}
public static ItemStack determineItemTradedByShop(Sign sign) {
return determineItemTradedByShop(sign.getLine(ITEM_LINE));
}
public static ItemStack determineItemTradedByShop(String material) {
ItemParseEvent parseEvent = new ItemParseEvent(material);
Bukkit.getPluginManager().callEvent(parseEvent);
return parseEvent.getItem();
}
}

View File

@ -196,7 +196,7 @@ public class PlayerInteract implements Listener {
int amount = -1; int amount = -1;
try { try {
amount = Integer.parseInt(quantity); amount = QuantityUtil.parseQuantity(quantity);
} catch (NumberFormatException notANumber) {} } catch (NumberFormatException notANumber) {}
if (amount < 1 || amount > Properties.MAX_SHOP_AMOUNT) { if (amount < 1 || amount > Properties.MAX_SHOP_AMOUNT) {

View File

@ -1,5 +1,6 @@
package com.Acrobot.ChestShop.Listeners.PreShopCreation; package com.Acrobot.ChestShop.Listeners.PreShopCreation;
import com.Acrobot.Breeze.Utils.QuantityUtil;
import com.Acrobot.ChestShop.Configuration.Properties; import com.Acrobot.ChestShop.Configuration.Properties;
import com.Acrobot.ChestShop.Events.PreShopCreationEvent; import com.Acrobot.ChestShop.Events.PreShopCreationEvent;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@ -18,7 +19,7 @@ public class QuantityChecker implements Listener {
public static void onPreShopCreation(PreShopCreationEvent event) { public static void onPreShopCreation(PreShopCreationEvent event) {
int amount = -1; int amount = -1;
try { try {
amount = Integer.parseInt(event.getSignLine(QUANTITY_LINE)); amount = QuantityUtil.parseQuantity(event.getSignLine(QUANTITY_LINE));
} catch (NumberFormatException notANumber) {} } catch (NumberFormatException notANumber) {}
if (amount < 1 || amount > Properties.MAX_SHOP_AMOUNT) { if (amount < 1 || amount > Properties.MAX_SHOP_AMOUNT) {

View File

@ -33,7 +33,7 @@ public class ChestShopSign {
public static final Pattern[] SHOP_SIGN_PATTERN = { public static final Pattern[] SHOP_SIGN_PATTERN = {
Pattern.compile("^?[\\w -.:]*$"), Pattern.compile("^?[\\w -.:]*$"),
Pattern.compile("^[1-9][0-9]{0,5}$"), Pattern.compile("^[1-9][0-9]{0,5}$|^Q [1-9][0-9]{0,4} : C [0-9]{0,5}$"),
Pattern.compile("(?i)^[\\d.bs(free) :]+$"), Pattern.compile("(?i)^[\\d.bs(free) :]+$"),
Pattern.compile("^[\\w? #:-]+$") Pattern.compile("^[\\w? #:-]+$")
}; };

View File

@ -9,11 +9,15 @@ import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState; import org.bukkit.block.BlockState;
import org.bukkit.block.Container; import org.bukkit.block.Container;
import org.bukkit.block.Sign; import org.bukkit.block.Sign;
import org.bukkit.block.DoubleChest;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Chest; import org.bukkit.block.data.type.Chest;
import org.bukkit.block.data.type.WallSign; import org.bukkit.block.data.type.WallSign;
import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.InventoryHolder;
import java.util.ArrayList;
import java.util.List;
/** /**
* @author Acrobot * @author Acrobot
*/ */
@ -152,6 +156,65 @@ public class uBlock {
return ownerShopSign; return ownerShopSign;
} }
public static List<Sign> findConnectedShopSigns(InventoryHolder chestShopInventoryHolder) {
List<Sign> result = new ArrayList<>();
if (chestShopInventoryHolder instanceof DoubleChest) {
BlockState leftChestSide = (BlockState) ((DoubleChest) chestShopInventoryHolder).getLeftSide();
BlockState rightChestSide = (BlockState) ((DoubleChest) chestShopInventoryHolder).getRightSide();
if (leftChestSide == null || rightChestSide == null) {
return result;
}
Block leftChest = leftChestSide.getBlock();
Block rightChest = rightChestSide.getBlock();
if (ChestShopSign.isShopBlock(leftChest)) {
result.addAll(uBlock.findConnectedShopSigns(leftChest));
}
if (ChestShopSign.isShopBlock(rightChest)) {
result.addAll(uBlock.findConnectedShopSigns(rightChest));
}
}
else if (chestShopInventoryHolder instanceof BlockState) {
Block chestBlock = ((BlockState) chestShopInventoryHolder).getBlock();
if (ChestShopSign.isShopBlock(chestBlock)) {
result.addAll(uBlock.findConnectedShopSigns(chestBlock));
}
}
return result;
}
public static List<Sign> findConnectedShopSigns(Block chestBlock) {
List<Sign> result = new ArrayList<>();
for (BlockFace bf : SHOP_FACES) {
Block faceBlock = chestBlock.getRelative(bf);
if (!BlockUtil.isSign(faceBlock)) {
continue;
}
Sign sign = (Sign) faceBlock.getState();
Container signContainer = findConnectedContainer(sign);
if (!chestBlock.equals(signContainer.getBlock())) {
continue;
}
if (ChestShopSign.isValid(sign)) {
result.add(sign);
}
}
return result;
}
public static Sign findAnyNearbyShopSign(Block block) { public static Sign findAnyNearbyShopSign(Block block) {
for (BlockFace bf : SHOP_FACES) { for (BlockFace bf : SHOP_FACES) {
Block faceBlock = block.getRelative(bf); Block faceBlock = block.getRelative(bf);