Push InventoryMultiplexer type down to allow for inventory refreshing

This commit is contained in:
fullwall 2024-03-18 23:36:42 +08:00
parent 70ac5c9193
commit c1b7a99bd8
8 changed files with 72 additions and 76 deletions

View File

@ -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) { boolean secondClick) {
if (timesPurchasable > 0 && purchases.getOrDefault(player.getUniqueId(), 0) == timesPurchasable) { if (timesPurchasable > 0 && purchases.getOrDefault(player.getUniqueId(), 0) == timesPurchasable) {
if (alreadyPurchasedMessage != null) { if (alreadyPurchasedMessage != null) {
@ -835,11 +835,9 @@ public class ShopTrait extends Trait {
ctx.getSlot(i).setItemStack(item.getDisplayItem(player)); ctx.getSlot(i).setItemStack(item.getDisplayItem(player));
ctx.getSlot(i).setClickHandler(evt -> { ctx.getSlot(i).setClickHandler(evt -> {
evt.setCancelled(true); evt.setCancelled(true);
InventoryMultiplexer multiplexer = new InventoryMultiplexer( item.onClick(shop, (Player) evt.getWhoClicked(),
((Player) evt.getWhoClicked()).getInventory()); new InventoryMultiplexer(((Player) evt.getWhoClicked()).getInventory()), evt.isShiftClick(),
item.onClick(shop, (Player) evt.getWhoClicked(), multiplexer.getInventory(), evt.isShiftClick(),
lastClickedItem == item); lastClickedItem == item);
multiplexer.save();
lastClickedItem = item; lastClickedItem = item;
}); });
} }
@ -929,9 +927,8 @@ public class ShopTrait extends Trait {
syntheticInventory.setItem(0, evt.getClickedInventory().getItem(0)); syntheticInventory.setItem(0, evt.getClickedInventory().getItem(0));
syntheticInventory.setItem(1, evt.getClickedInventory().getItem(1)); syntheticInventory.setItem(1, evt.getClickedInventory().getItem(1));
InventoryMultiplexer multiplexer = new InventoryMultiplexer(player.getInventory(), syntheticInventory); 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); lastClickedTrade == selectedTrade);
multiplexer.save();
evt.getClickedInventory().setItem(0, syntheticInventory.getItem(0)); evt.getClickedInventory().setItem(0, syntheticInventory.getItem(0));
evt.getClickedInventory().setItem(1, syntheticInventory.getItem(1)); evt.getClickedInventory().setItem(1, syntheticInventory.getItem(1));
lastClickedTrade = selectedTrade; lastClickedTrade = selectedTrade;

View File

@ -17,6 +17,7 @@ import net.citizensnpcs.api.gui.InventoryMenuPage;
import net.citizensnpcs.api.gui.Menu; import net.citizensnpcs.api.gui.Menu;
import net.citizensnpcs.api.gui.MenuContext; import net.citizensnpcs.api.gui.MenuContext;
import net.citizensnpcs.api.persistence.Persist; import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.util.InventoryMultiplexer;
import net.citizensnpcs.util.Util; import net.citizensnpcs.util.Util;
public class CommandAction extends NPCShopAction { public class CommandAction extends NPCShopAction {
@ -48,12 +49,12 @@ public class CommandAction extends NPCShopAction {
} }
@Override @Override
public int getMaxRepeats(Entity entity, ItemStack[] inventory) { public int getMaxRepeats(Entity entity, InventoryMultiplexer inventory) {
return -1; return -1;
} }
@Override @Override
public Transaction grant(Entity entity, ItemStack[] inventory, int repeats) { public Transaction grant(Entity entity, InventoryMultiplexer inventory, int repeats) {
if (!(entity instanceof Player)) if (!(entity instanceof Player))
return Transaction.fail(); return Transaction.fail();
Player player = (Player) entity; Player player = (Player) entity;
@ -63,12 +64,13 @@ public class CommandAction extends NPCShopAction {
Util.runCommand(null, player, command, op, !server); Util.runCommand(null, player, command, op, !server);
} }
} }
inventory.refresh();
}, () -> { }, () -> {
}); });
} }
@Override @Override
public Transaction take(Entity entity, ItemStack[] inventory, int repeats) { public Transaction take(Entity entity, InventoryMultiplexer inventory, int repeats) {
if (!(entity instanceof Player)) if (!(entity instanceof Player))
return Transaction.fail(); return Transaction.fail();
Player player = (Player) entity; Player player = (Player) entity;
@ -78,6 +80,7 @@ public class CommandAction extends NPCShopAction {
Util.runCommand(null, player, command, op, !server); Util.runCommand(null, player, command, op, !server);
} }
} }
inventory.refresh();
}, () -> { }, () -> {
}); });
} }

View File

@ -10,6 +10,7 @@ import org.bukkit.inventory.ItemStack;
import net.citizensnpcs.api.gui.InputMenus; import net.citizensnpcs.api.gui.InputMenus;
import net.citizensnpcs.api.gui.InventoryMenuPage; import net.citizensnpcs.api.gui.InventoryMenuPage;
import net.citizensnpcs.api.persistence.Persist; import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.util.InventoryMultiplexer;
import net.citizensnpcs.util.Util; import net.citizensnpcs.util.Util;
public class ExperienceAction extends NPCShopAction { public class ExperienceAction extends NPCShopAction {
@ -29,7 +30,7 @@ public class ExperienceAction extends NPCShopAction {
} }
@Override @Override
public int getMaxRepeats(Entity entity, ItemStack[] inventory) { public int getMaxRepeats(Entity entity, InventoryMultiplexer inventory) {
if (!(entity instanceof Player)) if (!(entity instanceof Player))
return 0; return 0;
@ -37,7 +38,7 @@ public class ExperienceAction extends NPCShopAction {
} }
@Override @Override
public Transaction grant(Entity entity, ItemStack[] inventory, int repeats) { public Transaction grant(Entity entity, InventoryMultiplexer inventory, int repeats) {
if (!(entity instanceof Player)) if (!(entity instanceof Player))
return Transaction.fail(); return Transaction.fail();
@ -51,7 +52,7 @@ public class ExperienceAction extends NPCShopAction {
} }
@Override @Override
public Transaction take(Entity entity, ItemStack[] inventory, int repeats) { public Transaction take(Entity entity, InventoryMultiplexer inventory, int repeats) {
if (!(entity instanceof Player)) if (!(entity instanceof Player))
return Transaction.fail(); return Transaction.fail();

View File

@ -26,6 +26,7 @@ import net.citizensnpcs.api.jnbt.CompoundTag;
import net.citizensnpcs.api.jnbt.Tag; import net.citizensnpcs.api.jnbt.Tag;
import net.citizensnpcs.api.persistence.Persist; import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.api.util.SpigotUtil; import net.citizensnpcs.api.util.SpigotUtil;
import net.citizensnpcs.util.InventoryMultiplexer;
import net.citizensnpcs.util.NMS; import net.citizensnpcs.util.NMS;
import net.citizensnpcs.util.Util; import net.citizensnpcs.util.Util;
@ -104,10 +105,11 @@ public class ItemAction extends NPCShopAction {
} }
@Override @Override
public int getMaxRepeats(Entity entity, ItemStack[] inventory) { public int getMaxRepeats(Entity entity, InventoryMultiplexer im) {
if (!(entity instanceof InventoryHolder)) if (!(entity instanceof InventoryHolder))
return 0; return 0;
ItemStack[] inventory = im.getInventory();
List<Integer> req = items.stream().map(ItemStack::getAmount).collect(Collectors.toList()); List<Integer> req = items.stream().map(ItemStack::getAmount).collect(Collectors.toList());
List<Integer> has = items.stream().map(i -> 0).collect(Collectors.toList()); List<Integer> has = items.stream().map(i -> 0).collect(Collectors.toList());
for (int i = 0; i < inventory.length; i++) { for (int i = 0; i < inventory.length; i++) {
@ -134,10 +136,11 @@ public class ItemAction extends NPCShopAction {
} }
@Override @Override
public Transaction grant(Entity entity, ItemStack[] inventory, int repeats) { public Transaction grant(Entity entity, InventoryMultiplexer im, int repeats) {
if (!(entity instanceof InventoryHolder)) if (!(entity instanceof InventoryHolder))
return Transaction.fail(); return Transaction.fail();
return Transaction.create(() -> { return Transaction.create(() -> {
ItemStack[] inventory = im.getInventory();
int free = 0; int free = 0;
for (ItemStack stack : inventory) { for (ItemStack stack : inventory) {
if (stack == null || stack.getType() == Material.AIR) { if (stack == null || stack.getType() == Material.AIR) {
@ -146,7 +149,7 @@ public class ItemAction extends NPCShopAction {
} }
} }
return free >= items.size() * repeats; return free >= items.size() * repeats;
}, () -> { }, () -> im.transact(inventory -> {
for (int i = 0; i < repeats; i++) { for (int i = 0; i < repeats; i++) {
List<ItemStack> toAdd = items.stream().map(ItemStack::clone).collect(Collectors.toList()); List<ItemStack> toAdd = items.stream().map(ItemStack::clone).collect(Collectors.toList());
for (int j = 0; j < inventory.length; j++) { 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++) { for (int i = 0; i < repeats; i++) {
List<ItemStack> toRemove = items.stream().map(ItemStack::clone).collect(Collectors.toList()); List<ItemStack> toRemove = items.stream().map(ItemStack::clone).collect(Collectors.toList());
for (int j = 0; j < inventory.length; j++) { for (int j = 0; j < inventory.length; j++) {
@ -169,7 +172,7 @@ public class ItemAction extends NPCShopAction {
} }
} }
} }
}); }));
} }
private boolean matches(ItemStack a, ItemStack b) { private boolean matches(ItemStack a, ItemStack b) {
@ -212,33 +215,33 @@ public class ItemAction extends NPCShopAction {
} }
@Override @Override
public Transaction take(Entity entity, ItemStack[] inventory, int repeats) { public Transaction take(Entity entity, InventoryMultiplexer im, int repeats) {
if (!(entity instanceof InventoryHolder)) if (!(entity instanceof InventoryHolder))
return Transaction.fail(); return Transaction.fail();
return Transaction.create(() -> containsItems(inventory, repeats, false), () -> { return Transaction.create(() -> containsItems(im.getInventory(), repeats, false),
containsItems(inventory, repeats, true); () -> im.transact(inventory -> containsItems(inventory, repeats, true)),
}, () -> { () -> im.transact(inventory -> {
for (ItemStack item : items.stream().map(ItemStack::clone).toArray(ItemStack[]::new)) { for (ItemStack item : items.stream().map(ItemStack::clone).toArray(ItemStack[]::new)) {
for (int i = 0; i < inventory.length; i++) { for (int i = 0; i < inventory.length; i++) {
ItemStack stack = inventory[i]; ItemStack stack = inventory[i];
if (stack == null || stack.getType() == Material.AIR) { if (stack == null || stack.getType() == Material.AIR) {
inventory[i] = item; inventory[i] = item;
break; break;
} }
if (stack.getMaxStackSize() > stack.getAmount() && matches(stack, item)) { if (stack.getMaxStackSize() > stack.getAmount() && matches(stack, item)) {
int free = stack.getMaxStackSize() - stack.getAmount(); int free = stack.getMaxStackSize() - stack.getAmount();
if (item.getAmount() > free) { if (item.getAmount() > free) {
item.setAmount(item.getAmount() - free); item.setAmount(item.getAmount() - free);
stack.setAmount(stack.getMaxStackSize()); stack.setAmount(stack.getMaxStackSize());
} else { } else {
stack.setAmount(stack.getAmount() + item.getAmount()); stack.setAmount(stack.getAmount() + item.getAmount());
break; break;
}
}
} }
} }
} }));
}
});
} }
private boolean tooDamaged(ItemStack toMatch) { private boolean tooDamaged(ItemStack toMatch) {

View File

@ -11,6 +11,7 @@ import org.bukkit.inventory.ItemStack;
import net.citizensnpcs.api.gui.InputMenus; import net.citizensnpcs.api.gui.InputMenus;
import net.citizensnpcs.api.gui.InventoryMenuPage; import net.citizensnpcs.api.gui.InventoryMenuPage;
import net.citizensnpcs.api.persistence.Persist; import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.util.InventoryMultiplexer;
import net.citizensnpcs.util.Util; import net.citizensnpcs.util.Util;
import net.milkbowl.vault.economy.Economy; import net.milkbowl.vault.economy.Economy;
@ -32,7 +33,7 @@ public class MoneyAction extends NPCShopAction {
} }
@Override @Override
public int getMaxRepeats(Entity entity, ItemStack[] inventory) { public int getMaxRepeats(Entity entity, InventoryMultiplexer inventory) {
if (!(entity instanceof Player)) if (!(entity instanceof Player))
return 0; return 0;
@ -41,7 +42,7 @@ public class MoneyAction extends NPCShopAction {
} }
@Override @Override
public Transaction grant(Entity entity, ItemStack[] inventory, int repeats) { public Transaction grant(Entity entity, InventoryMultiplexer inventory, int repeats) {
if (!(entity instanceof Player)) if (!(entity instanceof Player))
return Transaction.fail(); return Transaction.fail();
@ -57,7 +58,7 @@ public class MoneyAction extends NPCShopAction {
} }
@Override @Override
public Transaction take(Entity entity, ItemStack[] inventory, int repeats) { public Transaction take(Entity entity, InventoryMultiplexer inventory, int repeats) {
if (!(entity instanceof Player)) if (!(entity instanceof Player))
return Transaction.fail(); return Transaction.fail();

View File

@ -27,34 +27,18 @@ public abstract class NPCShopAction implements Cloneable {
public abstract String describe(); 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) { public Transaction grant(Player player, int repeats) {
InventoryMultiplexer im = new InventoryMultiplexer(entity.getInventory()); return grant(player, new InventoryMultiplexer(player.getInventory()), repeats);
Transaction tx = grant(entity, im.getInventory(), repeats);
return Transaction.create(tx::isPossible, () -> {
tx.run();
im.save();
}, () -> {
tx.rollback();
im.save();
});
} }
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) { public Transaction take(Player player, int repeats) {
InventoryMultiplexer im = new InventoryMultiplexer(entity.getInventory()); return take(player, new InventoryMultiplexer(player.getInventory()), repeats);
Transaction tx = take(entity, im.getInventory(), repeats);
return Transaction.create(tx::isPossible, () -> {
tx.run();
im.save();
}, () -> {
tx.rollback();
im.save();
});
} }
public static interface GUI { public static interface GUI {

View File

@ -18,6 +18,7 @@ import net.citizensnpcs.api.gui.Menu;
import net.citizensnpcs.api.gui.MenuContext; import net.citizensnpcs.api.gui.MenuContext;
import net.citizensnpcs.api.persistence.Persist; import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.api.util.Placeholders; import net.citizensnpcs.api.util.Placeholders;
import net.citizensnpcs.util.InventoryMultiplexer;
import net.citizensnpcs.util.Util; import net.citizensnpcs.util.Util;
import net.milkbowl.vault.permission.Permission; import net.milkbowl.vault.permission.Permission;
@ -46,12 +47,12 @@ public class PermissionAction extends NPCShopAction {
} }
@Override @Override
public int getMaxRepeats(Entity entity, ItemStack[] inventory) { public int getMaxRepeats(Entity entity, InventoryMultiplexer inventory) {
return -1; return -1;
} }
@Override @Override
public Transaction grant(Entity entity, ItemStack[] inventory, int repeats) { public Transaction grant(Entity entity, InventoryMultiplexer inventory, int repeats) {
if (!(entity instanceof Player)) if (!(entity instanceof Player))
return Transaction.fail(); return Transaction.fail();
Player player = (Player) entity; Player player = (Player) entity;
@ -68,7 +69,7 @@ public class PermissionAction extends NPCShopAction {
} }
@Override @Override
public Transaction take(Entity entity, ItemStack[] inventory, int repeats) { public Transaction take(Entity entity, InventoryMultiplexer inventory, int repeats) {
if (!(entity instanceof Player)) if (!(entity instanceof Player))
return Transaction.fail(); return Transaction.fail();
Player player = (Player) entity; Player player = (Player) entity;

View File

@ -1,6 +1,7 @@
package net.citizensnpcs.util; package net.citizensnpcs.util;
import java.util.Collection; import java.util.Collection;
import java.util.function.Consumer;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@ -15,12 +16,7 @@ public class InventoryMultiplexer {
this.sources = sources; this.sources = sources;
int size = sources.stream().mapToInt(Inventory::getSize).sum(); int size = sources.stream().mapToInt(Inventory::getSize).sum();
this.inventory = new ItemStack[size]; this.inventory = new ItemStack[size];
int i = 0; refresh();
for (Inventory sourceInventory : sources) {
ItemStack[] source = sourceInventory.getContents();
System.arraycopy(source, 0, inventory, i, source.length);
i += source.length;
}
} }
public InventoryMultiplexer(Inventory... inventories) { public InventoryMultiplexer(Inventory... inventories) {
@ -31,7 +27,17 @@ public class InventoryMultiplexer {
return inventory; 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<ItemStack[]> action) {
action.accept(inventory);
int i = 0; int i = 0;
for (Inventory source : sources) { for (Inventory source : sources) {
ItemStack[] result = new ItemStack[source.getSize()]; ItemStack[] result = new ItemStack[source.getSize()];