diff --git a/main/src/main/java/net/citizensnpcs/trait/ShopTrait.java b/main/src/main/java/net/citizensnpcs/trait/ShopTrait.java index 97410b1bc..363326c12 100644 --- a/main/src/main/java/net/citizensnpcs/trait/ShopTrait.java +++ b/main/src/main/java/net/citizensnpcs/trait/ShopTrait.java @@ -435,7 +435,7 @@ public class ShopTrait extends Trait { } } - public void onClick(NPCShop shop, Player player, ItemStack[] inventory, boolean shiftClick, + public void onClick(NPCShop shop, Player player, InventoryMultiplexer inventory, boolean shiftClick, boolean secondClick) { if (timesPurchasable > 0 && purchases.getOrDefault(player.getUniqueId(), 0) == timesPurchasable) { if (alreadyPurchasedMessage != null) { @@ -835,11 +835,9 @@ public class ShopTrait extends Trait { ctx.getSlot(i).setItemStack(item.getDisplayItem(player)); ctx.getSlot(i).setClickHandler(evt -> { evt.setCancelled(true); - InventoryMultiplexer multiplexer = new InventoryMultiplexer( - ((Player) evt.getWhoClicked()).getInventory()); - item.onClick(shop, (Player) evt.getWhoClicked(), multiplexer.getInventory(), evt.isShiftClick(), + item.onClick(shop, (Player) evt.getWhoClicked(), + new InventoryMultiplexer(((Player) evt.getWhoClicked()).getInventory()), evt.isShiftClick(), lastClickedItem == item); - multiplexer.save(); lastClickedItem = item; }); } @@ -929,9 +927,8 @@ public class ShopTrait extends Trait { syntheticInventory.setItem(0, evt.getClickedInventory().getItem(0)); syntheticInventory.setItem(1, evt.getClickedInventory().getItem(1)); InventoryMultiplexer multiplexer = new InventoryMultiplexer(player.getInventory(), syntheticInventory); - trades.get(selectedTrade).onClick(shop, player, multiplexer.getInventory(), evt.getClick().isShiftClick(), + trades.get(selectedTrade).onClick(shop, player, multiplexer, evt.getClick().isShiftClick(), lastClickedTrade == selectedTrade); - multiplexer.save(); evt.getClickedInventory().setItem(0, syntheticInventory.getItem(0)); evt.getClickedInventory().setItem(1, syntheticInventory.getItem(1)); lastClickedTrade = selectedTrade; diff --git a/main/src/main/java/net/citizensnpcs/trait/shop/CommandAction.java b/main/src/main/java/net/citizensnpcs/trait/shop/CommandAction.java index 085fed55c..297dda8bc 100644 --- a/main/src/main/java/net/citizensnpcs/trait/shop/CommandAction.java +++ b/main/src/main/java/net/citizensnpcs/trait/shop/CommandAction.java @@ -17,6 +17,7 @@ import net.citizensnpcs.api.gui.InventoryMenuPage; import net.citizensnpcs.api.gui.Menu; import net.citizensnpcs.api.gui.MenuContext; import net.citizensnpcs.api.persistence.Persist; +import net.citizensnpcs.util.InventoryMultiplexer; import net.citizensnpcs.util.Util; public class CommandAction extends NPCShopAction { @@ -48,12 +49,12 @@ public class CommandAction extends NPCShopAction { } @Override - public int getMaxRepeats(Entity entity, ItemStack[] inventory) { + public int getMaxRepeats(Entity entity, InventoryMultiplexer inventory) { return -1; } @Override - public Transaction grant(Entity entity, ItemStack[] inventory, int repeats) { + public Transaction grant(Entity entity, InventoryMultiplexer inventory, int repeats) { if (!(entity instanceof Player)) return Transaction.fail(); Player player = (Player) entity; @@ -63,12 +64,13 @@ public class CommandAction extends NPCShopAction { Util.runCommand(null, player, command, op, !server); } } + inventory.refresh(); }, () -> { }); } @Override - public Transaction take(Entity entity, ItemStack[] inventory, int repeats) { + public Transaction take(Entity entity, InventoryMultiplexer inventory, int repeats) { if (!(entity instanceof Player)) return Transaction.fail(); Player player = (Player) entity; @@ -78,6 +80,7 @@ public class CommandAction extends NPCShopAction { Util.runCommand(null, player, command, op, !server); } } + inventory.refresh(); }, () -> { }); } diff --git a/main/src/main/java/net/citizensnpcs/trait/shop/ExperienceAction.java b/main/src/main/java/net/citizensnpcs/trait/shop/ExperienceAction.java index addcb6aec..9cfe858b8 100644 --- a/main/src/main/java/net/citizensnpcs/trait/shop/ExperienceAction.java +++ b/main/src/main/java/net/citizensnpcs/trait/shop/ExperienceAction.java @@ -10,6 +10,7 @@ import org.bukkit.inventory.ItemStack; import net.citizensnpcs.api.gui.InputMenus; import net.citizensnpcs.api.gui.InventoryMenuPage; import net.citizensnpcs.api.persistence.Persist; +import net.citizensnpcs.util.InventoryMultiplexer; import net.citizensnpcs.util.Util; public class ExperienceAction extends NPCShopAction { @@ -29,7 +30,7 @@ public class ExperienceAction extends NPCShopAction { } @Override - public int getMaxRepeats(Entity entity, ItemStack[] inventory) { + public int getMaxRepeats(Entity entity, InventoryMultiplexer inventory) { if (!(entity instanceof Player)) return 0; @@ -37,7 +38,7 @@ public class ExperienceAction extends NPCShopAction { } @Override - public Transaction grant(Entity entity, ItemStack[] inventory, int repeats) { + public Transaction grant(Entity entity, InventoryMultiplexer inventory, int repeats) { if (!(entity instanceof Player)) return Transaction.fail(); @@ -51,7 +52,7 @@ public class ExperienceAction extends NPCShopAction { } @Override - public Transaction take(Entity entity, ItemStack[] inventory, int repeats) { + public Transaction take(Entity entity, InventoryMultiplexer inventory, int repeats) { if (!(entity instanceof Player)) return Transaction.fail(); diff --git a/main/src/main/java/net/citizensnpcs/trait/shop/ItemAction.java b/main/src/main/java/net/citizensnpcs/trait/shop/ItemAction.java index 6aa01f5a5..f69eeb5e5 100644 --- a/main/src/main/java/net/citizensnpcs/trait/shop/ItemAction.java +++ b/main/src/main/java/net/citizensnpcs/trait/shop/ItemAction.java @@ -26,6 +26,7 @@ import net.citizensnpcs.api.jnbt.CompoundTag; import net.citizensnpcs.api.jnbt.Tag; import net.citizensnpcs.api.persistence.Persist; import net.citizensnpcs.api.util.SpigotUtil; +import net.citizensnpcs.util.InventoryMultiplexer; import net.citizensnpcs.util.NMS; import net.citizensnpcs.util.Util; @@ -104,10 +105,11 @@ public class ItemAction extends NPCShopAction { } @Override - public int getMaxRepeats(Entity entity, ItemStack[] inventory) { + public int getMaxRepeats(Entity entity, InventoryMultiplexer im) { if (!(entity instanceof InventoryHolder)) return 0; + ItemStack[] inventory = im.getInventory(); List req = items.stream().map(ItemStack::getAmount).collect(Collectors.toList()); List has = items.stream().map(i -> 0).collect(Collectors.toList()); for (int i = 0; i < inventory.length; i++) { @@ -134,10 +136,11 @@ public class ItemAction extends NPCShopAction { } @Override - public Transaction grant(Entity entity, ItemStack[] inventory, int repeats) { + public Transaction grant(Entity entity, InventoryMultiplexer im, int repeats) { if (!(entity instanceof InventoryHolder)) return Transaction.fail(); return Transaction.create(() -> { + ItemStack[] inventory = im.getInventory(); int free = 0; for (ItemStack stack : inventory) { if (stack == null || stack.getType() == Material.AIR) { @@ -146,7 +149,7 @@ public class ItemAction extends NPCShopAction { } } return free >= items.size() * repeats; - }, () -> { + }, () -> im.transact(inventory -> { for (int i = 0; i < repeats; i++) { List toAdd = items.stream().map(ItemStack::clone).collect(Collectors.toList()); for (int j = 0; j < inventory.length; j++) { @@ -157,7 +160,7 @@ public class ItemAction extends NPCShopAction { } } } - }, () -> { + }), () -> im.transact(inventory -> { for (int i = 0; i < repeats; i++) { List toRemove = items.stream().map(ItemStack::clone).collect(Collectors.toList()); for (int j = 0; j < inventory.length; j++) { @@ -169,7 +172,7 @@ public class ItemAction extends NPCShopAction { } } } - }); + })); } private boolean matches(ItemStack a, ItemStack b) { @@ -212,33 +215,33 @@ public class ItemAction extends NPCShopAction { } @Override - public Transaction take(Entity entity, ItemStack[] inventory, int repeats) { + public Transaction take(Entity entity, InventoryMultiplexer im, int repeats) { if (!(entity instanceof InventoryHolder)) return Transaction.fail(); - return Transaction.create(() -> containsItems(inventory, repeats, false), () -> { - containsItems(inventory, repeats, true); - }, () -> { - for (ItemStack item : items.stream().map(ItemStack::clone).toArray(ItemStack[]::new)) { - for (int i = 0; i < inventory.length; i++) { - ItemStack stack = inventory[i]; - if (stack == null || stack.getType() == Material.AIR) { - inventory[i] = item; - break; - } - if (stack.getMaxStackSize() > stack.getAmount() && matches(stack, item)) { - int free = stack.getMaxStackSize() - stack.getAmount(); - if (item.getAmount() > free) { - item.setAmount(item.getAmount() - free); - stack.setAmount(stack.getMaxStackSize()); - } else { - stack.setAmount(stack.getAmount() + item.getAmount()); - break; + return Transaction.create(() -> containsItems(im.getInventory(), repeats, false), + () -> im.transact(inventory -> containsItems(inventory, repeats, true)), + () -> im.transact(inventory -> { + for (ItemStack item : items.stream().map(ItemStack::clone).toArray(ItemStack[]::new)) { + for (int i = 0; i < inventory.length; i++) { + ItemStack stack = inventory[i]; + if (stack == null || stack.getType() == Material.AIR) { + inventory[i] = item; + break; + } + if (stack.getMaxStackSize() > stack.getAmount() && matches(stack, item)) { + int free = stack.getMaxStackSize() - stack.getAmount(); + if (item.getAmount() > free) { + item.setAmount(item.getAmount() - free); + stack.setAmount(stack.getMaxStackSize()); + } else { + stack.setAmount(stack.getAmount() + item.getAmount()); + break; + } + } } } - } - } - }); + })); } private boolean tooDamaged(ItemStack toMatch) { diff --git a/main/src/main/java/net/citizensnpcs/trait/shop/MoneyAction.java b/main/src/main/java/net/citizensnpcs/trait/shop/MoneyAction.java index 77a359b73..8f69af6e1 100644 --- a/main/src/main/java/net/citizensnpcs/trait/shop/MoneyAction.java +++ b/main/src/main/java/net/citizensnpcs/trait/shop/MoneyAction.java @@ -11,6 +11,7 @@ import org.bukkit.inventory.ItemStack; import net.citizensnpcs.api.gui.InputMenus; import net.citizensnpcs.api.gui.InventoryMenuPage; import net.citizensnpcs.api.persistence.Persist; +import net.citizensnpcs.util.InventoryMultiplexer; import net.citizensnpcs.util.Util; import net.milkbowl.vault.economy.Economy; @@ -32,7 +33,7 @@ public class MoneyAction extends NPCShopAction { } @Override - public int getMaxRepeats(Entity entity, ItemStack[] inventory) { + public int getMaxRepeats(Entity entity, InventoryMultiplexer inventory) { if (!(entity instanceof Player)) return 0; @@ -41,7 +42,7 @@ public class MoneyAction extends NPCShopAction { } @Override - public Transaction grant(Entity entity, ItemStack[] inventory, int repeats) { + public Transaction grant(Entity entity, InventoryMultiplexer inventory, int repeats) { if (!(entity instanceof Player)) return Transaction.fail(); @@ -57,7 +58,7 @@ public class MoneyAction extends NPCShopAction { } @Override - public Transaction take(Entity entity, ItemStack[] inventory, int repeats) { + public Transaction take(Entity entity, InventoryMultiplexer inventory, int repeats) { if (!(entity instanceof Player)) return Transaction.fail(); diff --git a/main/src/main/java/net/citizensnpcs/trait/shop/NPCShopAction.java b/main/src/main/java/net/citizensnpcs/trait/shop/NPCShopAction.java index 61d8e5b16..ae9158264 100644 --- a/main/src/main/java/net/citizensnpcs/trait/shop/NPCShopAction.java +++ b/main/src/main/java/net/citizensnpcs/trait/shop/NPCShopAction.java @@ -27,34 +27,18 @@ public abstract class NPCShopAction implements Cloneable { public abstract String describe(); - public abstract int getMaxRepeats(Entity entity, ItemStack[] inventory); + public abstract int getMaxRepeats(Entity entity, InventoryMultiplexer inventory); - public abstract Transaction grant(Entity entity, ItemStack[] inventory, int repeats); + public abstract Transaction grant(Entity entity, InventoryMultiplexer inventory, int repeats); - public Transaction grant(Player entity, int repeats) { - InventoryMultiplexer im = new InventoryMultiplexer(entity.getInventory()); - Transaction tx = grant(entity, im.getInventory(), repeats); - return Transaction.create(tx::isPossible, () -> { - tx.run(); - im.save(); - }, () -> { - tx.rollback(); - im.save(); - }); + public Transaction grant(Player player, int repeats) { + return grant(player, new InventoryMultiplexer(player.getInventory()), repeats); } - public abstract Transaction take(Entity entity, ItemStack[] inventory, int repeats); + public abstract Transaction take(Entity entity, InventoryMultiplexer inventory, int repeats); - public Transaction take(Player entity, int repeats) { - InventoryMultiplexer im = new InventoryMultiplexer(entity.getInventory()); - Transaction tx = take(entity, im.getInventory(), repeats); - return Transaction.create(tx::isPossible, () -> { - tx.run(); - im.save(); - }, () -> { - tx.rollback(); - im.save(); - }); + public Transaction take(Player player, int repeats) { + return take(player, new InventoryMultiplexer(player.getInventory()), repeats); } public static interface GUI { diff --git a/main/src/main/java/net/citizensnpcs/trait/shop/PermissionAction.java b/main/src/main/java/net/citizensnpcs/trait/shop/PermissionAction.java index 8babb5bc0..d109f25d5 100644 --- a/main/src/main/java/net/citizensnpcs/trait/shop/PermissionAction.java +++ b/main/src/main/java/net/citizensnpcs/trait/shop/PermissionAction.java @@ -18,6 +18,7 @@ import net.citizensnpcs.api.gui.Menu; import net.citizensnpcs.api.gui.MenuContext; import net.citizensnpcs.api.persistence.Persist; import net.citizensnpcs.api.util.Placeholders; +import net.citizensnpcs.util.InventoryMultiplexer; import net.citizensnpcs.util.Util; import net.milkbowl.vault.permission.Permission; @@ -46,12 +47,12 @@ public class PermissionAction extends NPCShopAction { } @Override - public int getMaxRepeats(Entity entity, ItemStack[] inventory) { + public int getMaxRepeats(Entity entity, InventoryMultiplexer inventory) { return -1; } @Override - public Transaction grant(Entity entity, ItemStack[] inventory, int repeats) { + public Transaction grant(Entity entity, InventoryMultiplexer inventory, int repeats) { if (!(entity instanceof Player)) return Transaction.fail(); Player player = (Player) entity; @@ -68,7 +69,7 @@ public class PermissionAction extends NPCShopAction { } @Override - public Transaction take(Entity entity, ItemStack[] inventory, int repeats) { + public Transaction take(Entity entity, InventoryMultiplexer inventory, int repeats) { if (!(entity instanceof Player)) return Transaction.fail(); Player player = (Player) entity; diff --git a/main/src/main/java/net/citizensnpcs/util/InventoryMultiplexer.java b/main/src/main/java/net/citizensnpcs/util/InventoryMultiplexer.java index 073773f30..388de2dcd 100644 --- a/main/src/main/java/net/citizensnpcs/util/InventoryMultiplexer.java +++ b/main/src/main/java/net/citizensnpcs/util/InventoryMultiplexer.java @@ -1,6 +1,7 @@ package net.citizensnpcs.util; import java.util.Collection; +import java.util.function.Consumer; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; @@ -15,12 +16,7 @@ public class InventoryMultiplexer { this.sources = sources; int size = sources.stream().mapToInt(Inventory::getSize).sum(); this.inventory = new ItemStack[size]; - int i = 0; - for (Inventory sourceInventory : sources) { - ItemStack[] source = sourceInventory.getContents(); - System.arraycopy(source, 0, inventory, i, source.length); - i += source.length; - } + refresh(); } public InventoryMultiplexer(Inventory... inventories) { @@ -31,7 +27,17 @@ public class InventoryMultiplexer { return inventory; } - public void save() { + public void refresh() { + int i = 0; + for (Inventory sourceInventory : sources) { + ItemStack[] source = sourceInventory.getContents(); + System.arraycopy(source, 0, inventory, i, source.length); + i += source.length; + } + } + + public void transact(Consumer action) { + action.accept(inventory); int i = 0; for (Inventory source : sources) { ItemStack[] result = new ItemStack[source.getSize()];