diff --git a/src/main/java/emu/grasscutter/game/gacha/GachaManager.java b/src/main/java/emu/grasscutter/game/gacha/GachaManager.java index f0baf65a9..c730a646a 100644 --- a/src/main/java/emu/grasscutter/game/gacha/GachaManager.java +++ b/src/main/java/emu/grasscutter/game/gacha/GachaManager.java @@ -13,6 +13,7 @@ import com.google.gson.reflect.TypeToken; import com.sun.nio.file.SensitivityWatchEventModifier; import emu.grasscutter.Grasscutter; import emu.grasscutter.data.GameData; +import emu.grasscutter.data.common.ItemParamData; import emu.grasscutter.data.def.ItemData; import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.game.avatar.Avatar; @@ -127,13 +128,8 @@ public class GachaManager { } // Spend currency - if (banner.getCostItem() > 0) { - GameItem costItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(banner.getCostItem()); - if (costItem == null || costItem.getCount() < times) { - return; - } - - player.getInventory().removeItem(costItem, times); + if (banner.getCostItem() > 0 && !player.getInventory().payItems(new ItemParamData[] {new ItemParamData(banner.getCostItem(), times)})) { + return; } // Roll diff --git a/src/main/java/emu/grasscutter/game/inventory/Inventory.java b/src/main/java/emu/grasscutter/game/inventory/Inventory.java index 2c0478dda..6936ca066 100644 --- a/src/main/java/emu/grasscutter/game/inventory/Inventory.java +++ b/src/main/java/emu/grasscutter/game/inventory/Inventory.java @@ -272,14 +272,18 @@ public class Inventory implements Iterable { } } - public boolean payItems(Collection items) { - return payItems(items, null); + public boolean payItems(ItemParamData[] costItems) { + return payItems(costItems, 1, null); + } + + public boolean payItems(ItemParamData[] costItems, int quantity) { + return payItems(costItems, quantity, null); } - public synchronized boolean payItems(Collection costItems, ActionReason reason) { + public synchronized boolean payItems(ItemParamData[] costItems, int quantity, ActionReason reason) { // Make sure player has requisite items for (ItemParamData cost : costItems) { - if (getVirtualItemCount(cost.getId()) < cost.getCount()) { + if (getVirtualItemCount(cost.getId()) < (cost.getCount() * quantity)) { return false; } } @@ -287,13 +291,13 @@ public class Inventory implements Iterable { for (ItemParamData cost : costItems) { switch (cost.getId()) { case 201 -> // Primogem - player.setPrimogems(player.getPrimogems() - cost.getCount()); + player.setPrimogems(player.getPrimogems() - (cost.getCount() * quantity)); case 202 -> // Mora - player.setMora(player.getMora() - cost.getCount()); + player.setMora(player.getMora() - (cost.getCount() * quantity)); case 203 -> // Genesis Crystals - player.setCrystals(player.getCrystals() - cost.getCount()); + player.setCrystals(player.getCrystals() - (cost.getCount() * quantity)); default -> - removeItem(getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId()), cost.getCount()); + removeItem(getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId()), cost.getCount() * quantity); } } diff --git a/src/main/java/emu/grasscutter/game/managers/InventoryManager.java b/src/main/java/emu/grasscutter/game/managers/InventoryManager.java index f3b9c0293..f75f8b074 100644 --- a/src/main/java/emu/grasscutter/game/managers/InventoryManager.java +++ b/src/main/java/emu/grasscutter/game/managers/InventoryManager.java @@ -1,6 +1,7 @@ package emu.grasscutter.game.managers; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -496,27 +497,16 @@ public class InventoryManager { return; } - // Make sure player has promote items - for (ItemParamData cost : nextPromoteData.getCostItems()) { - GameItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId()); - if (feedItem == null || feedItem.getCount() < cost.getCount()) { - return; - } + // Pay materials and mora if possible + ItemParamData[] costs = nextPromoteData.getCostItems(); // Can this be null? + if (nextPromoteData.getCoinCost() > 0) { + costs = Arrays.copyOf(costs, costs.length + 1); + costs[costs.length-1] = new ItemParamData(202, nextPromoteData.getCoinCost()); } - - // Mora check - if (player.getMora() >= nextPromoteData.getCoinCost()) { - player.setMora(player.getMora() - nextPromoteData.getCoinCost()); - } else { + if (!player.getInventory().payItems(costs)) { return; } - // Consume promote filler items - for (ItemParamData cost : nextPromoteData.getCostItems()) { - GameItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId()); - player.getInventory().removeItem(feedItem, cost.getCount()); - } - int oldPromoteLevel = weapon.getPromoteLevel(); weapon.setPromoteLevel(nextPromoteLevel); weapon.save(); @@ -552,27 +542,16 @@ public class InventoryManager { return; } - // Make sure player has cost items - for (ItemParamData cost : nextPromoteData.getCostItems()) { - GameItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId()); - if (feedItem == null || feedItem.getCount() < cost.getCount()) { - return; - } + // Pay materials and mora if possible + ItemParamData[] costs = nextPromoteData.getCostItems(); // Can this be null? + if (nextPromoteData.getCoinCost() > 0) { + costs = Arrays.copyOf(costs, costs.length + 1); + costs[costs.length-1] = new ItemParamData(202, nextPromoteData.getCoinCost()); } - - // Mora check - if (player.getMora() >= nextPromoteData.getCoinCost()) { - player.setMora(player.getMora() - nextPromoteData.getCoinCost()); - } else { + if (!player.getInventory().payItems(costs)) { return; } - // Consume promote filler items - for (ItemParamData cost : nextPromoteData.getCostItems()) { - GameItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId()); - player.getInventory().removeItem(feedItem, cost.getCount()); - } - // Update promote level avatar.setPromoteLevel(nextPromoteLevel); @@ -764,33 +743,15 @@ public class InventoryManager { return; } - // Make sure player has cost items - for (ItemParamData cost : proudSkill.getCostItems()) { - if (cost.getId() == 0) { - continue; - } - GameItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId()); - if (feedItem == null || feedItem.getCount() < cost.getCount()) { - return; - } + // Pay materials and mora if possible + List costs = proudSkill.getCostItems(); // Can this be null? + if (proudSkill.getCoinCost() > 0) { + costs.add(new ItemParamData(202, proudSkill.getCoinCost())); } - - // Mora check - if (player.getMora() >= proudSkill.getCoinCost()) { - player.setMora(player.getMora() - proudSkill.getCoinCost()); - } else { + if (!player.getInventory().payItems(costs.toArray(new ItemParamData[0]))) { return; } - // Consume promote filler items - for (ItemParamData cost : proudSkill.getCostItems()) { - if (cost.getId() == 0) { - continue; - } - GameItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId()); - player.getInventory().removeItem(feedItem, cost.getCount()); - } - // Upgrade skill avatar.getSkillLevelMap().put(skillId, nextLevel); avatar.save(); diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyGoodsReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyGoodsReq.java index 0a2c30802..fc9564734 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyGoodsReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyGoodsReq.java @@ -18,7 +18,7 @@ import emu.grasscutter.server.packet.send.PacketBuyGoodsRsp; import emu.grasscutter.server.packet.send.PacketStoreItemChangeNotify; import emu.grasscutter.utils.Utils; -import java.util.HashMap; +import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -56,36 +56,13 @@ public class HandlerBuyGoodsReq extends PacketHandler { return; } - if (sg.getScoin() > 0 && session.getPlayer().getMora() < buyGoodsReq.getBoughtNum() * sg.getScoin()) { + List costs = sg.getCostItemList(); // Can this even be null? + costs.add(new ItemParamData(202, sg.getScoin())); + costs.add(new ItemParamData(201, sg.getHcoin())); + costs.add(new ItemParamData(203, sg.getMcoin())); + if (!session.getPlayer().getInventory().payItems(costs.toArray(new ItemParamData[0]), buyGoodsReq.getBoughtNum())) { return; } - if (sg.getHcoin() > 0 && session.getPlayer().getPrimogems() < buyGoodsReq.getBoughtNum() * sg.getHcoin()) { - return; - } - if (sg.getMcoin() > 0 && session.getPlayer().getCrystals() < buyGoodsReq.getBoughtNum() * sg.getMcoin()) { - return; - } - - HashMap itemsCache = new HashMap<>(); - if (sg.getCostItemList() != null) { - for (ItemParamData p : sg.getCostItemList()) { - Optional invItem = session.getPlayer().getInventory().getItems().values().stream().filter(x -> x.getItemId() == p.getId()).findFirst(); - if (invItem.isEmpty() || invItem.get().getCount() < p.getCount()) - return; - itemsCache.put(invItem.get(), p.getCount() * buyGoodsReq.getBoughtNum()); - } - } - - session.getPlayer().setMora(session.getPlayer().getMora() - buyGoodsReq.getBoughtNum() * sg.getScoin()); - session.getPlayer().setPrimogems(session.getPlayer().getPrimogems() - buyGoodsReq.getBoughtNum() * sg.getHcoin()); - session.getPlayer().setCrystals(session.getPlayer().getCrystals() - buyGoodsReq.getBoughtNum() * sg.getMcoin()); - - if (!itemsCache.isEmpty()) { - for (GameItem gi : itemsCache.keySet()) { - session.getPlayer().getInventory().removeItem(gi, itemsCache.get(gi)); - } - itemsCache.clear(); - } session.getPlayer().addShopLimit(sg.getGoodsId(), buyGoodsReq.getBoughtNum(), ShopManager.getShopNextRefreshTime(sg)); GameItem item = new GameItem(GameData.getItemDataMap().get(sg.getGoodsItem().getId()));