diff --git a/data/ShopChest.json b/data/ShopChest.json new file mode 100644 index 000000000..b9d6b2359 --- /dev/null +++ b/data/ShopChest.json @@ -0,0 +1,153 @@ +[ + { + "itemId": 115019, + "containsItem": [ + { + "Id": 104002, + "Count": 40 + }, + { + "Id": 202, + "Count": 30000 + } + ] + }, + { + "itemId": 115020, + "containsItem": [ + { + "Id": 104013, + "Count": 25 + }, + { + "Id": 202, + "Count": 30000 + } + ] + }, + { + "itemId": 115021, + "containsItem": [ + { + "Id": 115013, + "Count": 5 + }, + { + "Id": 104003, + "Count": 40 + }, + { + "Id": 202, + "Count": 120000 + } + ] + }, + { + "itemId": 115022, + "containsItem": [ + { + "Id": 115017, + "Count": 25 + }, + { + "Id": 202, + "Count": 150000 + } + ] + }, + { + "itemId": 115023, + "containsItem": [ + { + "Id": 115025, + "Count": 10 + }, + { + "Id": 202, + "Count": 60000 + } + ] + }, + { + "itemId": 115029, + "containsItem": [ + { + "Id": 104013, + "Count": 100 + }, + { + "Id": 202, + "Count": 100000 + } + ] + }, + { + "itemId": 115030, + "containsItem": [ + { + "Id": 104003, + "Count": 12 + }, + { + "Id": 202, + "Count": 10000 + } + ] + }, + { + "itemId": 115034, + "containsItem": [ + { + "Id": 115013, + "Count": 6 + }, + { + "Id": 202, + "Count": 60000 + } + ] + }, + { + "itemId": 115032, + "containsItem": [ + { + "Id": 115024, + "Count": 12 + } + ] + }, + { + "itemId": 115010, + "containsItem": [ + { + "Id": 104002, + "Count": 80 + }, + { + "Id": 104012, + "Count": 40 + } + ] + }, + { + "itemId": 115011, + "containsItem": [ + { + "Id": 104003, + "Count": 50 + }, + { + "Id": 104013, + "Count": 25 + }, + { + "Id": 107009, + "Count": 1 + }, + { + "Id": 202, + "Count": 50000 + } + ] + } +] diff --git a/data/ShopChestBatchUse.json b/data/ShopChestBatchUse.json new file mode 100644 index 000000000..38de4e16a --- /dev/null +++ b/data/ShopChestBatchUse.json @@ -0,0 +1,55 @@ +[ + { + "itemId": 115017, + "optionItem": [ + 104302, + 104305, + 104308, + 104311, + 104314, + 104317, + 104321, + 104324, + 104327 + ] + }, + { + "itemId": 115024, + "optionItem": [ + 114001, + 114005, + 114009, + 114013, + 114017, + 114021, + 114025, + 114029, + 114033 + ] + }, + { + "itemId": 115013, + "optionItem": [ + 104112, + 104122, + 104142, + 104152, + 104162, + 104172 + ] + }, + { + "itemId": 115025, + "optionItem": [ + 114002, + 114006, + 114010, + 114014, + 114018, + 114022, + 114026, + 114030, + 114034 + ] + } +] diff --git a/src/main/java/emu/grasscutter/data/GameData.java b/src/main/java/emu/grasscutter/data/GameData.java index 2ba251e71..c187a1819 100644 --- a/src/main/java/emu/grasscutter/data/GameData.java +++ b/src/main/java/emu/grasscutter/data/GameData.java @@ -62,7 +62,6 @@ public class GameData { private static final Int2ObjectMap fetterDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap fetterCharacterCardDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap rewardDataMap = new Int2ObjectOpenHashMap<>(); - private static final Int2ObjectMap rewardBoxDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap worldLevelDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap dailyDungeonDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap dungeonDataMap = new Int2ObjectOpenHashMap<>(); @@ -264,10 +263,6 @@ public class GameData { return rewardDataMap; } - public static Int2ObjectMap getRewardBoxDataMap() { - return rewardBoxDataMap; - } - public static Map> getFetterDataEntries() { if (fetters.isEmpty()) { fetterDataMap.forEach((k, v) -> { diff --git a/src/main/java/emu/grasscutter/data/common/RewardBoxItemData.java b/src/main/java/emu/grasscutter/data/common/RewardBoxItemData.java deleted file mode 100644 index b32e2c650..000000000 --- a/src/main/java/emu/grasscutter/data/common/RewardBoxItemData.java +++ /dev/null @@ -1,22 +0,0 @@ -package emu.grasscutter.data.common; - -public class RewardBoxItemData { - private int Id; - private String Count; - - public int getItemId() { - return Id; - } - - public void setItemId(int itemId) { - Id = itemId; - } - - public String getItemCount() { - return Count; - } - - public void setItemCount(String itemCount) { - Count = itemCount; - } -} diff --git a/src/main/java/emu/grasscutter/data/def/RewardBoxData.java b/src/main/java/emu/grasscutter/data/def/RewardBoxData.java deleted file mode 100644 index c4c3ce527..000000000 --- a/src/main/java/emu/grasscutter/data/def/RewardBoxData.java +++ /dev/null @@ -1,27 +0,0 @@ -package emu.grasscutter.data.def; - -import java.util.List; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.common.RewardBoxItemData; - -@ResourceType(name = "RewardPreviewExcelConfigData.json") -public class RewardBoxData extends GameResource { - public int Id; - public List PreviewItems; - - @Override - public int getId() { - return Id; - } - - public List getRewardBoxItemList() { - return PreviewItems; - } - - @Override - public void onLoad() { - - } -} diff --git a/src/main/java/emu/grasscutter/data/def/ShopGoodsData.java b/src/main/java/emu/grasscutter/data/def/ShopGoodsData.java index a4d91e933..1a4168637 100644 --- a/src/main/java/emu/grasscutter/data/def/ShopGoodsData.java +++ b/src/main/java/emu/grasscutter/data/def/ShopGoodsData.java @@ -30,7 +30,6 @@ public class ShopGoodsData extends GameResource { private transient ShopInfo.ShopRefreshType RefreshTypeEnum; private int RefreshParam; - private int ShowId; @Override public void onLoad() { @@ -106,8 +105,4 @@ public class ShopGoodsData extends GameResource { public int getRefreshParam() { return RefreshParam; } - - public int getShowId() { - return ShowId; - } } diff --git a/src/main/java/emu/grasscutter/game/inventory/GameItem.java b/src/main/java/emu/grasscutter/game/inventory/GameItem.java index 02ff8cd25..ddc61988a 100644 --- a/src/main/java/emu/grasscutter/game/inventory/GameItem.java +++ b/src/main/java/emu/grasscutter/game/inventory/GameItem.java @@ -58,9 +58,6 @@ public class GameItem { // Relic private int mainPropId; private List appendPropIdList; - - // shopMailBox - private int rewardBoxId; private int equipCharacter; @Transient private int weaponEntityId; @@ -251,14 +248,6 @@ public class GameItem { this.mainPropId = mainPropId; } - public int getRewardBoxId() { - return rewardBoxId; - } - - public void setRewardBoxId(int rewardBoxId) { - this.rewardBoxId = rewardBoxId; - } - public List getAppendPropIdList() { return appendPropIdList; } diff --git a/src/main/java/emu/grasscutter/game/managers/InventoryManager.java b/src/main/java/emu/grasscutter/game/managers/InventoryManager.java index 55663b844..f3b9c0293 100644 --- a/src/main/java/emu/grasscutter/game/managers/InventoryManager.java +++ b/src/main/java/emu/grasscutter/game/managers/InventoryManager.java @@ -7,13 +7,12 @@ import java.util.stream.Collectors; import emu.grasscutter.data.GameData; import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.data.common.RewardBoxItemData; import emu.grasscutter.data.custom.OpenConfigEntry; import emu.grasscutter.data.custom.OpenConfigEntry.SkillPointModifier; import emu.grasscutter.data.def.AvatarPromoteData; import emu.grasscutter.data.def.AvatarSkillData; import emu.grasscutter.data.def.AvatarSkillDepotData; -import emu.grasscutter.data.def.RewardBoxData; +import emu.grasscutter.data.def.ItemData; import emu.grasscutter.data.def.WeaponPromoteData; import emu.grasscutter.data.def.AvatarSkillDepotData.InherentProudSkillOpens; import emu.grasscutter.data.def.AvatarTalentData; @@ -24,6 +23,8 @@ import emu.grasscutter.game.inventory.ItemType; import emu.grasscutter.game.inventory.MaterialType; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.game.shop.ShopChestBatchUseTable; +import emu.grasscutter.game.shop.ShopChestTable; import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; import emu.grasscutter.net.proto.MaterialInfoOuterClass.MaterialInfo; import emu.grasscutter.server.game.GameServer; @@ -900,27 +901,7 @@ public class InventoryManager { player.sendPacket(new PacketDestroyMaterialRsp(returnMaterialMap)); } - private boolean handleRewardBox(Player player, GameItem useItem) { - List rewardBoxDataList = GameData.getRewardBoxDataMap().values().stream().filter(x -> x.getId() == useItem.getRewardBoxId()).collect(Collectors.toList()); - if (rewardBoxDataList.isEmpty()) { - return false; - } - List rewardItemList = new ArrayList<>(); - for (RewardBoxItemData itemData : rewardBoxDataList.get(0).getRewardBoxItemList()) { - if (itemData.getItemId() == 0) { - continue; - } - String[] split = itemData.getItemCount().split(";"); - int itemCount = Integer.parseInt(split[(int) (Math.random()* split.length)]); - rewardItemList.add(new GameItem(itemData.getItemId(), itemCount)); - } - if (!rewardItemList.isEmpty()) { - player.getInventory().addItems(rewardItemList, ActionReason.Shop); - } - return true; - } - - public GameItem useItem(Player player, long targetGuid, long itemGuid, int count) { + public GameItem useItem(Player player, long targetGuid, long itemGuid, int count, int optionId) { Avatar target = player.getAvatars().getAvatarByGuid(targetGuid); GameItem useItem = player.getInventory().getItemByGuid(itemGuid); @@ -952,8 +933,57 @@ public class InventoryManager { } break; case MATERIAL_CHEST: - if (useItem.getRewardBoxId() > 0) { - used = handleRewardBox(player, useItem) ? 1 : 0; + List shopChestTableList = player.getServer().getShopManager().getShopChestData(); + List rewardItemList = new ArrayList<>(); + for (ShopChestTable shopChestTable : shopChestTableList) { + if (shopChestTable.getItemId() != useItem.getItemId()) { + continue; + } + + if (shopChestTable.getContainsItem() == null) { + break; + } + + for (ItemParamData itemParamData : shopChestTable.getContainsItem()) { + ItemData itemData = GameData.getItemDataMap().get(itemParamData.getId()); + if (itemData == null) { + continue; + } + rewardItemList.add(new GameItem(itemData, itemParamData.getCount())); + } + + if (!rewardItemList.isEmpty()) { + player.getInventory().addItems(rewardItemList, ActionReason.Shop); + } + + used = 1; + break; + } + break; + case MATERIAL_CHEST_BATCH_USE: + if (optionId < 1) { + break; + } + List shopChestBatchUseTableList = player.getServer().getShopManager().getShopChestBatchUseData(); + for (ShopChestBatchUseTable shopChestBatchUseTable : shopChestBatchUseTableList) { + if (shopChestBatchUseTable.getItemId() != useItem.getItemId()) { + continue; + } + + if (shopChestBatchUseTable.getOptionItem() == null || optionId > shopChestBatchUseTable.getOptionItem().size()) { + break; + } + + int optionItemId = shopChestBatchUseTable.getOptionItem().get(optionId - 1); + ItemData itemData = GameData.getItemDataMap().get(optionItemId); + if (itemData == null) { + break; + } + + player.getInventory().addItem(new GameItem(itemData, count), ActionReason.Shop); + + used = count; + break; } break; default: @@ -965,12 +995,12 @@ public class InventoryManager { player.rechargeMoonCard(); used = 1; } - + if (used > 0) { player.getInventory().removeItem(useItem, used); return useItem; } - + return null; } } diff --git a/src/main/java/emu/grasscutter/game/shop/ShopChestBatchUseTable.java b/src/main/java/emu/grasscutter/game/shop/ShopChestBatchUseTable.java new file mode 100644 index 000000000..c3b15da86 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/shop/ShopChestBatchUseTable.java @@ -0,0 +1,25 @@ +package emu.grasscutter.game.shop; + +import java.util.ArrayList; +import java.util.List; + +public class ShopChestBatchUseTable { + private int itemId; + private List optionItem = new ArrayList<>(); + + public int getItemId() { + return itemId; + } + + public void setItemId(int itemId) { + this.itemId = itemId; + } + + public List getOptionItem() { + return optionItem; + } + + public void setOptionItem(List optionItem) { + this.optionItem = optionItem; + } +} diff --git a/src/main/java/emu/grasscutter/game/shop/ShopChestTable.java b/src/main/java/emu/grasscutter/game/shop/ShopChestTable.java new file mode 100644 index 000000000..d4b850b54 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/shop/ShopChestTable.java @@ -0,0 +1,27 @@ +package emu.grasscutter.game.shop; + +import emu.grasscutter.data.common.ItemParamData; + +import java.util.ArrayList; +import java.util.List; + +public class ShopChestTable { + private int itemId; + private List containsItem = new ArrayList<>(); + + public int getItemId() { + return itemId; + } + + public void setItemId(int itemId) { + this.itemId = itemId; + } + + public List getContainsItem() { + return containsItem; + } + + public void setContainsItem(List containsItem) { + this.containsItem = containsItem; + } +} diff --git a/src/main/java/emu/grasscutter/game/shop/ShopInfo.java b/src/main/java/emu/grasscutter/game/shop/ShopInfo.java index ab5de27f6..ebbeea2cd 100644 --- a/src/main/java/emu/grasscutter/game/shop/ShopInfo.java +++ b/src/main/java/emu/grasscutter/game/shop/ShopInfo.java @@ -13,7 +13,6 @@ public class ShopInfo { private List costItemList; private int boughtNum = 0; private int buyLimit = 0; - private int showId = 0; private int beginTime = 0; private int endTime = 1924992000; private int minLevel = 0; @@ -52,7 +51,6 @@ public class ShopInfo { this.mcoin = sgd.getCostMcoin(); this.hcoin = sgd.getCostHcoin(); this.buyLimit = sgd.getBuyLimit(); - this.showId = sgd.getShowId(); this.minLevel = sgd.getMinPlayerLevel(); this.maxLevel = sgd.getMaxPlayerLevel(); @@ -182,14 +180,6 @@ public class ShopInfo { this.maxLevel = maxLevel; } - public int getShowId() { - return showId; - } - - public void setShowId(int showId) { - this.showId = showId; - } - public ShopRefreshType getShopRefreshType() { if (refreshType == null) return ShopRefreshType.NONE; diff --git a/src/main/java/emu/grasscutter/game/shop/ShopManager.java b/src/main/java/emu/grasscutter/game/shop/ShopManager.java index bad68afff..7222db816 100644 --- a/src/main/java/emu/grasscutter/game/shop/ShopManager.java +++ b/src/main/java/emu/grasscutter/game/shop/ShopManager.java @@ -4,7 +4,11 @@ import com.google.gson.reflect.TypeToken; import emu.grasscutter.Grasscutter; import emu.grasscutter.data.GameData; import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.data.def.ItemData; import emu.grasscutter.data.def.ShopGoodsData; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.managers.InventoryManager; +import emu.grasscutter.game.props.ActionReason; import emu.grasscutter.net.proto.ItemParamOuterClass; import emu.grasscutter.net.proto.ShopGoodsOuterClass; import emu.grasscutter.server.game.GameServer; @@ -25,11 +29,23 @@ public class ShopManager { return shopData; } + public List getShopChestData() { + return shopChestData; + } + + public List getShopChestBatchUseData() { + return shopChestBatchUseData; + } + private final Int2ObjectMap> shopData; + private final List shopChestData; + private final List shopChestBatchUseData; public ShopManager(GameServer server) { this.server = server; this.shopData = new Int2ObjectOpenHashMap<>(); + this.shopChestData = new ArrayList<>(); + this.shopChestBatchUseData = new ArrayList<>(); this.load(); } @@ -45,7 +61,7 @@ public class ShopManager { }; } - public synchronized void load() { + private void loadShop() { try (FileReader fileReader = new FileReader(Grasscutter.getConfig().DATA_FOLDER + "Shop.json")) { getShopData().clear(); List banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ShopTable.class).getType()); @@ -89,6 +105,42 @@ public class ShopManager { } } + private void loadShopChest() { + try (FileReader fileReader = new FileReader(Grasscutter.getConfig().DATA_FOLDER + "ShopChest.json")) { + getShopChestData().clear(); + List shopChestTableList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ShopChestTable.class).getType()); + if (shopChestTableList.size() > 0) { + getShopChestData().addAll(shopChestTableList); + Grasscutter.getLogger().info("ShopChest data successfully loaded."); + } else { + Grasscutter.getLogger().error("Unable to load ShopChest data. ShopChest data size is 0."); + } + } catch (Exception e) { + Grasscutter.getLogger().error("Unable to load ShopChest data.", e); + } + } + + private void loadShopChestBatchUse() { + try (FileReader fileReader = new FileReader(Grasscutter.getConfig().DATA_FOLDER + "ShopChestBatchUse.json")) { + getShopChestBatchUseData().clear(); + List shopChestBatchUseTableList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ShopChestBatchUseTable.class).getType()); + if (shopChestBatchUseTableList.size() > 0) { + getShopChestBatchUseData().addAll(shopChestBatchUseTableList); + Grasscutter.getLogger().info("ShopChestBatchUse data successfully loaded."); + } else { + Grasscutter.getLogger().error("Unable to load ShopChestBatchUse data. ShopChestBatchUse data size is 0."); + } + } catch (Exception e) { + Grasscutter.getLogger().error("Unable to load ShopChestBatchUse data.", e); + } + } + + public synchronized void load() { + loadShop(); + loadShopChest(); + loadShopChestBatchUse(); + } + public GameServer getServer() { return server; } 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 7b773995d..0a2c30802 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyGoodsReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyGoodsReq.java @@ -90,9 +90,6 @@ public class HandlerBuyGoodsReq extends PacketHandler { session.getPlayer().addShopLimit(sg.getGoodsId(), buyGoodsReq.getBoughtNum(), ShopManager.getShopNextRefreshTime(sg)); GameItem item = new GameItem(GameData.getItemDataMap().get(sg.getGoodsItem().getId())); item.setCount(buyGoodsReq.getBoughtNum() * sg.getGoodsItem().getCount()); - if (sg.getShowId() > 0) { - item.setRewardBoxId(sg.getShowId()); - } session.getPlayer().getInventory().addItem(item, ActionReason.Shop, true); // fix: not notify when got virtual item from shop session.send(new PacketBuyGoodsRsp(buyGoodsReq.getShopType(), session.getPlayer().getGoodsLimit(sg.getGoodsId()).getHasBoughtInPeriod(), buyGoodsReq.getGoodsListList().stream().filter(x -> x.getGoodsId() == goodsId).findFirst().get())); } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerUseItemReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerUseItemReq.java index 81a1f160b..daf4e4c04 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerUseItemReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerUseItemReq.java @@ -15,7 +15,7 @@ public class HandlerUseItemReq extends PacketHandler { public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { UseItemReq req = UseItemReq.parseFrom(payload); - GameItem useItem = session.getServer().getInventoryManager().useItem(session.getPlayer(), req.getTargetGuid(), req.getGuid(), req.getCount()); + GameItem useItem = session.getServer().getInventoryManager().useItem(session.getPlayer(), req.getTargetGuid(), req.getGuid(), req.getCount(), req.getOptionIdx()); if (useItem != null) { session.send(new PacketUseItemRsp(req.getTargetGuid(), useItem)); } else {