From 8f538721cc47cf6f58cea6272b50523ddde9a828 Mon Sep 17 00:00:00 2001 From: fullwall Date: Sun, 24 Mar 2024 00:53:47 +0800 Subject: [PATCH] Modify items in ItemAction --- .../citizensnpcs/trait/shop/ItemAction.java | 154 ++++++++---------- main/src/main/resources/ko-kr.json | 1 + 2 files changed, 72 insertions(+), 83 deletions(-) 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 f69eeb5e5..99c94f6a2 100644 --- a/main/src/main/java/net/citizensnpcs/trait/shop/ItemAction.java +++ b/main/src/main/java/net/citizensnpcs/trait/shop/ItemAction.java @@ -51,43 +51,6 @@ public class ItemAction extends NPCShopAction { this.items = items; } - private boolean containsItems(ItemStack[] contents, int repeats, boolean modify) { - List req = items.stream().map(i -> i.getAmount() * repeats).collect(Collectors.toList()); - for (int i = 0; i < contents.length; i++) { - ItemStack toMatch = contents[i]; - if (toMatch == null || toMatch.getType() == Material.AIR || tooDamaged(toMatch)) - continue; - - toMatch = toMatch.clone(); - for (int j = 0; j < items.size(); j++) { - if (toMatch == null) - break; - - ItemStack item = items.get(j); - if (req.get(j) <= 0 || !matches(item, toMatch)) - continue; - - int remaining = req.get(j); - int taken = toMatch.getAmount() > remaining ? remaining : toMatch.getAmount(); - - if (toMatch.getAmount() == taken) { - toMatch = null; - } else { - toMatch.setAmount(toMatch.getAmount() - taken); - } - if (modify) { - if (toMatch == null) { - contents[i] = null; - } else { - contents[i] = toMatch.clone(); - } - } - req.set(j, remaining - taken); - } - } - return req.stream().collect(Collectors.summingInt(n -> n)) <= 0; - } - @Override public String describe() { if (items.size() == 1) @@ -135,6 +98,36 @@ public class ItemAction extends NPCShopAction { .orElse(0); } + private void giveItems(ItemStack[] inventory, int repeats) { + 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++) { + if (toAdd.isEmpty()) + return; + if (inventory[j] == null) + continue; + ItemStack last = toAdd.get(toAdd.size() - 1); + if (!inventory[j].isSimilar(last) || inventory[j].getAmount() >= inventory[j].getMaxStackSize()) + continue; + int diff = inventory[j].getMaxStackSize() - inventory[j].getAmount(); + if (diff >= last.getAmount()) { + inventory[j].setAmount(inventory[j].getAmount() + last.getAmount()); + toAdd.remove(toAdd.size() - 1); + } else { + inventory[j].setAmount(inventory[j].getAmount() + diff); + last.setAmount(last.getAmount() - diff); + } + } + for (int j = 0; j < inventory.length; j++) { + if (toAdd.isEmpty()) + break; + if (inventory[j] == null || inventory[j].getType() == Material.AIR) { + inventory[j] = toAdd.remove(toAdd.size() - 1); + } + } + } + } + @Override public Transaction grant(Entity entity, InventoryMultiplexer im, int repeats) { if (!(entity instanceof InventoryHolder)) @@ -149,30 +142,8 @@ 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++) { - if (toAdd.isEmpty()) - break; - if (inventory[j] == null || inventory[j].getType() == Material.AIR) { - inventory[j] = toAdd.remove(toAdd.size() - 1); - } - } - } - }), () -> 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++) { - if (toRemove.isEmpty()) - break; - if (toRemove.get(toRemove.size() - 1).equals(inventory[j])) { - inventory[j] = null; - toRemove.remove(toRemove.size() - 1); - } - } - } - })); + }, () -> im.transact(inventory -> giveItems(inventory, repeats)), + () -> im.transact(inventory -> takeItems(inventory, repeats, true))); } private boolean matches(ItemStack a, ItemStack b) { @@ -219,29 +190,46 @@ public class ItemAction extends NPCShopAction { if (!(entity instanceof InventoryHolder)) return Transaction.fail(); - 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; - } - } - } + return Transaction.create(() -> takeItems(im.getInventory(), repeats, false), + () -> im.transact(inventory -> takeItems(inventory, repeats, true)), + () -> im.transact(inventory -> giveItems(inventory, repeats))); + } + + private boolean takeItems(ItemStack[] contents, int repeats, boolean modify) { + List req = items.stream().map(i -> i.getAmount() * repeats).collect(Collectors.toList()); + for (int i = 0; i < contents.length; i++) { + ItemStack toMatch = contents[i]; + if (toMatch == null || toMatch.getType() == Material.AIR || tooDamaged(toMatch)) + continue; + + toMatch = toMatch.clone(); + for (int j = 0; j < items.size(); j++) { + if (toMatch == null) + break; + + ItemStack item = items.get(j); + if (req.get(j) <= 0 || !matches(item, toMatch)) + continue; + + int remaining = req.get(j); + int taken = toMatch.getAmount() > remaining ? remaining : toMatch.getAmount(); + + if (toMatch.getAmount() == taken) { + toMatch = null; + } else { + toMatch.setAmount(toMatch.getAmount() - taken); + } + if (modify) { + if (toMatch == null) { + contents[i] = null; + } else { + contents[i] = toMatch.clone(); } - })); + } + req.set(j, remaining - taken); + } + } + return req.stream().collect(Collectors.summingInt(n -> n)) <= 0; } private boolean tooDamaged(ItemStack toMatch) { diff --git a/main/src/main/resources/ko-kr.json b/main/src/main/resources/ko-kr.json index 21db235cd..99844652b 100644 --- a/main/src/main/resources/ko-kr.json +++ b/main/src/main/resources/ko-kr.json @@ -375,6 +375,7 @@ "citizens.commands.npc.sheep.color-set" : "양의 색상이 [{0}]로 설정되었습니다.", "citizens.commands.npc.sheep.description" : "양 타입 부여", "citizens.commands.npc.sheep.invalid-color" : "유효하지 않은 양 색상이 지정되었습니다. 유효한 색상은 다음과 같습니다: [[{0}]].", + "citizens.commands.npc.shop.deleted" : "상점 [[{0}]]이(가) 삭제되었습니다.", "citizens.commands.npc.shop.description" : "NPC 상점 편집/표시", "citizens.commands.npc.shulker.color-set" : "[[{0}]]의 색상이 [{1}]로 설정되었습니다.", "citizens.commands.npc.shulker.description" : "셜커 타입 부여",