Modify items in ItemAction

This commit is contained in:
fullwall 2024-03-24 00:53:47 +08:00
parent 8696a5709e
commit 8f538721cc
2 changed files with 72 additions and 83 deletions

View File

@ -51,43 +51,6 @@ public class ItemAction extends NPCShopAction {
this.items = items; this.items = items;
} }
private boolean containsItems(ItemStack[] contents, int repeats, boolean modify) {
List<Integer> 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 @Override
public String describe() { public String describe() {
if (items.size() == 1) if (items.size() == 1)
@ -135,6 +98,36 @@ public class ItemAction extends NPCShopAction {
.orElse(0); .orElse(0);
} }
private void giveItems(ItemStack[] inventory, int repeats) {
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++) {
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 @Override
public Transaction grant(Entity entity, InventoryMultiplexer im, int repeats) { public Transaction grant(Entity entity, InventoryMultiplexer im, int repeats) {
if (!(entity instanceof InventoryHolder)) if (!(entity instanceof InventoryHolder))
@ -149,30 +142,8 @@ public class ItemAction extends NPCShopAction {
} }
} }
return free >= items.size() * repeats; return free >= items.size() * repeats;
}, () -> im.transact(inventory -> { }, () -> im.transact(inventory -> giveItems(inventory, repeats)),
for (int i = 0; i < repeats; i++) { () -> im.transact(inventory -> takeItems(inventory, repeats, true)));
List<ItemStack> 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<ItemStack> 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);
}
}
}
}));
} }
private boolean matches(ItemStack a, ItemStack b) { private boolean matches(ItemStack a, ItemStack b) {
@ -219,29 +190,46 @@ public class ItemAction extends NPCShopAction {
if (!(entity instanceof InventoryHolder)) if (!(entity instanceof InventoryHolder))
return Transaction.fail(); return Transaction.fail();
return Transaction.create(() -> containsItems(im.getInventory(), repeats, false), return Transaction.create(() -> takeItems(im.getInventory(), repeats, false),
() -> im.transact(inventory -> containsItems(inventory, repeats, true)), () -> im.transact(inventory -> takeItems(inventory, repeats, true)),
() -> im.transact(inventory -> { () -> im.transact(inventory -> giveItems(inventory, repeats)));
for (ItemStack item : items.stream().map(ItemStack::clone).toArray(ItemStack[]::new)) { }
for (int i = 0; i < inventory.length; i++) {
ItemStack stack = inventory[i]; private boolean takeItems(ItemStack[] contents, int repeats, boolean modify) {
if (stack == null || stack.getType() == Material.AIR) { List<Integer> req = items.stream().map(i -> i.getAmount() * repeats).collect(Collectors.toList());
inventory[i] = item; for (int i = 0; i < contents.length; i++) {
break; ItemStack toMatch = contents[i];
} if (toMatch == null || toMatch.getType() == Material.AIR || tooDamaged(toMatch))
if (stack.getMaxStackSize() > stack.getAmount() && matches(stack, item)) { continue;
int free = stack.getMaxStackSize() - stack.getAmount();
if (item.getAmount() > free) { toMatch = toMatch.clone();
item.setAmount(item.getAmount() - free); for (int j = 0; j < items.size(); j++) {
stack.setAmount(stack.getMaxStackSize()); if (toMatch == null)
} else { break;
stack.setAmount(stack.getAmount() + item.getAmount());
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) { private boolean tooDamaged(ItemStack toMatch) {

View File

@ -375,6 +375,7 @@
"citizens.commands.npc.sheep.color-set" : "양의 색상이 [{0}]로 설정되었습니다.", "citizens.commands.npc.sheep.color-set" : "양의 색상이 [{0}]로 설정되었습니다.",
"citizens.commands.npc.sheep.description" : "양 타입 부여", "citizens.commands.npc.sheep.description" : "양 타입 부여",
"citizens.commands.npc.sheep.invalid-color" : "유효하지 않은 양 색상이 지정되었습니다. 유효한 색상은 다음과 같습니다: [[{0}]].", "citizens.commands.npc.sheep.invalid-color" : "유효하지 않은 양 색상이 지정되었습니다. 유효한 색상은 다음과 같습니다: [[{0}]].",
"citizens.commands.npc.shop.deleted" : "상점 [[{0}]]이(가) 삭제되었습니다.",
"citizens.commands.npc.shop.description" : "NPC 상점 편집/표시", "citizens.commands.npc.shop.description" : "NPC 상점 편집/표시",
"citizens.commands.npc.shulker.color-set" : "[[{0}]]의 색상이 [{1}]로 설정되었습니다.", "citizens.commands.npc.shulker.color-set" : "[[{0}]]의 색상이 [{1}]로 설정되었습니다.",
"citizens.commands.npc.shulker.description" : "셜커 타입 부여", "citizens.commands.npc.shulker.description" : "셜커 타입 부여",