Add requireUndamaged to item cost

This commit is contained in:
fullwall 2022-10-26 15:44:03 +08:00
parent a91f0cd2ee
commit 891b480bea
2 changed files with 57 additions and 34 deletions

View File

@ -156,12 +156,19 @@ public class ShopTrait extends Trait {
public void changePage(int newPage) {
this.page = newPage;
NPCShopPage sp = shop.getOrCreatePage(page);
NPCShopPage shopPage = shop.getOrCreatePage(page);
for (int i = 0; i < ctx.getInventory().getSize(); i++) {
ctx.getSlot(i).clear();
NPCShopItem item = sp.getItem(i);
InventoryMenuSlot slot = ctx.getSlot(i);
slot.clear();
NPCShopItem item = shopPage.getItem(i);
if (item != null) {
slot.setItemStack(item.display);
}
final int idx = i;
ctx.getSlot(i).setClickHandler(evt -> {
slot.setClickHandler(evt -> {
evt.setCancelled(true);
ctx.clearSlots();
NPCShopItem display = item;
if (display == null) {
@ -173,18 +180,14 @@ public class ShopTrait extends Trait {
ctx.getMenu().transition(new NPCShopItemEditor(display, modified -> {
if (modified == null) {
sp.removeItem(idx);
shopPage.removeItem(idx);
} else {
sp.setItem(idx, modified);
shopPage.setItem(idx, modified);
}
}));
});
if (item == null)
continue;
ctx.getSlot(i).setItemStack(item.display);
}
InventoryMenuSlot prev = ctx.getSlot(4 * 9 + 3);
InventoryMenuSlot edit = ctx.getSlot(4 * 9 + 4);
InventoryMenuSlot next = ctx.getSlot(4 * 9 + 5);

View File

@ -3,18 +3,22 @@ package net.citizensnpcs.trait.shop;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import com.google.common.collect.Lists;
import net.citizensnpcs.api.gui.BooleanSlotHandler;
import net.citizensnpcs.api.gui.InventoryMenuPage;
import net.citizensnpcs.api.gui.InventoryMenuSlot;
import net.citizensnpcs.api.gui.Menu;
@ -25,6 +29,8 @@ import net.citizensnpcs.util.Util;
public class ItemAction extends NPCShopAction {
@Persist
public List<ItemStack> items = Lists.newArrayList();
@Persist
public boolean requireUndamaged = true;
public ItemAction() {
}
@ -37,6 +43,32 @@ public class ItemAction extends NPCShopAction {
this.items = items;
}
private boolean containsItems(Inventory source, BiFunction<ItemStack, Integer, ItemStack> filter) {
Map<Material, Integer> required = items.stream()
.collect(Collectors.toMap(k -> k.getType(), v -> v.getAmount()));
ItemStack[] contents = source.getContents();
for (int i = 0; i < contents.length; i++) {
ItemStack stack = contents[i];
if (stack == null || stack.getType() == Material.AIR || !required.containsKey(stack.getType()))
continue;
if (requireUndamaged && stack.getItemMeta() instanceof Damageable
&& ((Damageable) stack.getItemMeta()).getDamage() != 0)
continue;
int remaining = required.remove(stack.getType());
int taken = stack.getAmount() > remaining ? remaining : stack.getAmount();
ItemStack res = filter.apply(stack, taken);
if (res == null) {
source.clear(i);
} else {
source.setItem(i, res);
}
if (remaining - taken > 0) {
required.put(stack.getType(), remaining - taken);
}
}
return required.size() == 0;
}
@Override
public Transaction grant(Entity entity) {
if (!(entity instanceof InventoryHolder))
@ -64,12 +96,7 @@ public class ItemAction extends NPCShopAction {
return Transaction.fail();
Inventory source = ((InventoryHolder) entity).getInventory();
return Transaction.create(() -> {
Map<Material, Integer> required = items.stream()
.collect(Collectors.toMap(k -> k.getType(), v -> v.getAmount()));
boolean contains = true;
for (Map.Entry<Material, Integer> entry : required.entrySet()) {
contains &= source.contains(entry.getKey(), entry.getValue());
}
boolean contains = containsItems(source, (s, t) -> s);
for (ItemStack item : items) {
if (item.hasItemMeta() && !source.contains(item)) {
contains = false;
@ -77,32 +104,20 @@ public class ItemAction extends NPCShopAction {
}
return contains;
}, () -> {
Map<Material, Integer> required = items.stream()
.collect(Collectors.toMap(k -> k.getType(), v -> v.getAmount()));
ItemStack[] contents = source.getContents();
for (int i = 0; i < contents.length; i++) {
ItemStack stack = contents[i];
if (stack == null || stack.getType() == Material.AIR || !required.containsKey(stack.getType()))
continue;
Material type = stack.getType();
int remaining = required.remove(type);
int taken = stack.getAmount() > remaining ? remaining : stack.getAmount();
containsItems(source, (stack, taken) -> {
if (stack.getAmount() == taken) {
source.clear(i);
return null;
} else {
stack.setAmount(stack.getAmount() - taken);
source.setItem(i, stack);
return stack;
}
if (remaining - taken > 0) {
required.put(type, remaining - taken);
}
}
});
}, () -> {
source.addItem(items.toArray(new ItemStack[items.size()]));
});
}
@Menu(title = "Item editor", dimensions = { 3, 9 })
@Menu(title = "Item editor", dimensions = { 4, 9 })
public static class ItemActionEditor extends InventoryMenuPage {
private ItemAction base;
private Consumer<NPCShopAction> callback;
@ -130,6 +145,11 @@ public class ItemAction extends NPCShopAction {
event.setCurrentItem(event.getCursorNonNull());
});
}
ctx.getSlot(3 * 9 + 1).setItemStack(new ItemStack(Material.ANVIL), "Must have no damage");
ctx.getSlot(3 * 9 + 1).addClickHandler(new BooleanSlotHandler((res) -> {
base.requireUndamaged = res;
return res ? ChatColor.GREEN + "On" : ChatColor.RED + "Off";
}, base == null ? false : base.requireUndamaged));
}
@Override