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) {
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;

View File

@ -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();
}, () -> {
});
}

View File

@ -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();

View File

@ -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<Integer> req = items.stream().map(ItemStack::getAmount).collect(Collectors.toList());
List<Integer> 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<ItemStack> 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<ItemStack> 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) {

View File

@ -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();

View File

@ -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 {

View File

@ -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;

View File

@ -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<ItemStack[]> action) {
action.accept(inventory);
int i = 0;
for (Inventory source : sources) {
ItemStack[] result = new ItemStack[source.getSize()];