From 0e3a80407ef24dbcf9b0fe6e5ca5f61eef800e3f Mon Sep 17 00:00:00 2001 From: ayy lmao Date: Wed, 27 Apr 2022 14:39:20 +0300 Subject: [PATCH 1/3] Added missing isGiftMail section to GetAllMailRsp --- .../packet/send/PacketGetAllMailRsp.java | 28 ++++--------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetAllMailRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetAllMailRsp.java index 8c8fb4b07..59af30f42 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetAllMailRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetAllMailRsp.java @@ -14,32 +14,23 @@ import emu.grasscutter.net.proto.MailTextContentOuterClass.MailTextContent; import java.time.Instant; import java.util.ArrayList; -import java.util.Base64; import java.util.List; public class PacketGetAllMailRsp extends BasePacket { public PacketGetAllMailRsp(Player player, boolean isGiftMail) { super(PacketOpcodes.GetAllMailRsp); + GetAllMailRsp.Builder proto = GetAllMailRsp.newBuilder(); if (isGiftMail) { - // TODO: Gift Mail - // Make sure to send the stupid empty packet - Base64.Decoder decoder = Base64.getDecoder(); - byte[] rsp = decoder.decode("IAE="); - try { - GetAllMailRsp var = GetAllMailRsp.parseFrom(rsp); - this.setData(var.toBuilder().build()); - } catch (Exception e) { - } - + proto.setIsGiftMail(true); } else { + proto.setIsGiftMail(false); + if (player.getAllMail().size() != 0) { // Make sure the player has mail - GetAllMailRsp.Builder proto = GetAllMailRsp.newBuilder(); List mailDataList = new ArrayList(); for (Mail message : player.getAllMail()) { - if(message.stateValue == 1) { // Make sure it isn't a gift if (message.expireTime > (int) Instant.now().getEpochSecond()) { // Make sure the message isn't expired (The game won't show expired mail, but I don't want to send unnecessary information). if(mailDataList.size() <= 1000) { // Make sure that there isn't over 1000 messages in the mailbox. (idk what will happen if there is but the game probably won't like it.) @@ -79,17 +70,8 @@ public class PacketGetAllMailRsp extends BasePacket { proto.addAllMailList(mailDataList); proto.setIsTruncated(mailDataList.size() <= 1000 ? false : true); // When enabled this will send a notification to the user telling them their inbox is full and they should delete old messages when opening the mailbox. - - this.setData(proto.build()); - } else { - // Make sure to send the stupid empty packet - Base64.Decoder decoder = Base64.getDecoder(); - byte[] rsp = decoder.decode("IAE="); - try { - GetAllMailRsp var = GetAllMailRsp.parseFrom(rsp); - this.setData(var.toBuilder().build()); - } catch (Exception e) {} } } + this.setData(proto.build()); } } From 3e0ccbbbdea49e086b9116d7fba5433fcacc5a8c Mon Sep 17 00:00:00 2001 From: Kengxxiao <11478651+Kengxxiao@users.noreply.github.com> Date: Wed, 27 Apr 2022 18:51:48 +0800 Subject: [PATCH 2/3] implement npc shop --- data/Shop.json | 86 ++++++++++ .../command/commands/ReloadCommand.java | 1 + .../grasscutter/game/inventory/Inventory.java | 10 ++ .../emu/grasscutter/game/player/Player.java | 33 ++++ .../emu/grasscutter/game/shop/ShopInfo.java | 159 +++++++++++++++++- .../emu/grasscutter/game/shop/ShopLimit.java | 25 +++ .../grasscutter/game/shop/ShopManager.java | 38 +++++ .../packet/recv/HandlerBuyGoodsReq.java | 67 ++++++++ .../server/packet/recv/HandlerGetShopReq.java | 7 +- .../server/packet/send/PacketBuyGoodsRsp.java | 22 +++ .../server/packet/send/PacketGetShopRsp.java | 57 ++++++- 11 files changed, 492 insertions(+), 13 deletions(-) create mode 100644 data/Shop.json create mode 100644 src/main/java/emu/grasscutter/game/shop/ShopLimit.java create mode 100644 src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyGoodsReq.java create mode 100644 src/main/java/emu/grasscutter/server/packet/send/PacketBuyGoodsRsp.java diff --git a/data/Shop.json b/data/Shop.json new file mode 100644 index 000000000..85d6ad9e8 --- /dev/null +++ b/data/Shop.json @@ -0,0 +1,86 @@ +[ + { + "shopId": 1004, + "goodsId": 1004202, + "goodsItem": { + "Id": 202, + "Count": 1000000 + }, + "scoin": 1, + "buyLimit": 500, + "beginTime": 1575129600, + "endTime": 2051193600, + "minLevel": 1, + "maxLevel": 99 + }, + { + "shopId": 1004, + "goodsId": 10048006, + "goodsItem": { + "Id": 108006, + "Count": 20 + }, + "scoin": 1, + "buyLimit": 50000, + "beginTime": 1575129600, + "endTime": 2051193600, + "minLevel": 1, + "maxLevel": 99 + }, + { + "shopId": 1004, + "goodsId": 10048033, + "goodsItem": { + "Id": 108033, + "Count": 20 + }, + "scoin": 1, + "buyLimit": 50000, + "beginTime": 1575129600, + "endTime": 2051193600, + "minLevel": 1, + "maxLevel": 99 + }, + { + "shopId": 1004, + "goodsId": 10040008, + "goodsItem": { + "Id": 220008, + "Count": 1 + }, + "scoin": 1, + "buyLimit": 1, + "beginTime": 1575129600, + "endTime": 2051193600, + "minLevel": 1, + "maxLevel": 99 + }, + { + "shopId": 1004, + "goodsId": 10044003, + "goodsItem": { + "Id": 104003, + "Count": 200 + }, + "scoin": 1, + "buyLimit": 50000, + "beginTime": 1575129600, + "endTime": 2051193600, + "minLevel": 1, + "maxLevel": 99 + }, + { + "shopId": 1004, + "goodsId": 10044013, + "goodsItem": { + "Id": 104013, + "Count": 200 + }, + "scoin": 1, + "buyLimit": 50000, + "beginTime": 1575129600, + "endTime": 2051193600, + "minLevel": 1, + "maxLevel": 99 + } +] \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/command/commands/ReloadCommand.java b/src/main/java/emu/grasscutter/command/commands/ReloadCommand.java index 26dbb903b..bad97a20a 100644 --- a/src/main/java/emu/grasscutter/command/commands/ReloadCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/ReloadCommand.java @@ -16,6 +16,7 @@ public final class ReloadCommand implements CommandHandler { CommandHandler.sendMessage(sender, "Reloading config."); Grasscutter.loadConfig(); Grasscutter.getGameServer().getGachaManager().load(); + Grasscutter.getGameServer().getShopManager().load(); Grasscutter.getDispatchServer().loadQueries(); CommandHandler.sendMessage(sender, "Reload complete."); } diff --git a/src/main/java/emu/grasscutter/game/inventory/Inventory.java b/src/main/java/emu/grasscutter/game/inventory/Inventory.java index bb8dfad46..d407e077b 100644 --- a/src/main/java/emu/grasscutter/game/inventory/Inventory.java +++ b/src/main/java/emu/grasscutter/game/inventory/Inventory.java @@ -109,6 +109,16 @@ public class Inventory implements Iterable { return result; } + + public boolean addItem(GameItem item, ActionReason reason, boolean forceNotify) { + boolean result = addItem(item); + + if (reason != null && (forceNotify || result)) { + getPlayer().sendPacket(new PacketItemAddHintNotify(item, reason)); + } + + return result; + } public void addItems(Collection items) { this.addItems(items, null); diff --git a/src/main/java/emu/grasscutter/game/player/Player.java b/src/main/java/emu/grasscutter/game/player/Player.java index 5970c3f13..059292497 100644 --- a/src/main/java/emu/grasscutter/game/player/Player.java +++ b/src/main/java/emu/grasscutter/game/player/Player.java @@ -25,6 +25,7 @@ import emu.grasscutter.game.inventory.Inventory; import emu.grasscutter.game.mail.Mail; import emu.grasscutter.game.props.ActionReason; import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.game.shop.ShopLimit; import emu.grasscutter.game.world.Scene; import emu.grasscutter.game.world.World; import emu.grasscutter.net.packet.BasePacket; @@ -84,6 +85,7 @@ public class Player { private ArrayList shownAvatars; private Set rewardedLevels; private ArrayList mail; + private ArrayList shopLimit; private int sceneId; private int regionId; @@ -141,6 +143,8 @@ public class Player { this.birthday = new PlayerBirthday(); this.rewardedLevels = new HashSet<>(); this.moonCardGetTimes = new HashSet<>(); + + this.shopLimit = new ArrayList<>(); } // On player creation @@ -592,6 +596,35 @@ public class Player { session.send(new PacketCardProductRewardNotify(getMoonCardRemainDays())); } + public List getShopLimit() { + return shopLimit; + } + + public int getGoodsLimitNum(int goodsId) { + for (ShopLimit sl : getShopLimit()) { + if (sl.getShopGoodId() == goodsId) + return sl.getHasBought(); + } + return 0; + } + + public void addShopLimit(int goodsId, int boughtCount) { + boolean found = false; + for (ShopLimit sl : getShopLimit()) { + if (sl.getShopGoodId() == goodsId){ + sl.setHasBought(sl.getHasBought() + boughtCount); + found = true; + } + } + if (!found) { + ShopLimit sl = new ShopLimit(); + sl.setShopGoodId(goodsId); + sl.setHasBought(boughtCount); + shopLimit.add(sl); + } + this.save(); + } + public boolean inGodmode() { return godmode; } diff --git a/src/main/java/emu/grasscutter/game/shop/ShopInfo.java b/src/main/java/emu/grasscutter/game/shop/ShopInfo.java index 768a3a7ca..510f0d479 100644 --- a/src/main/java/emu/grasscutter/game/shop/ShopInfo.java +++ b/src/main/java/emu/grasscutter/game/shop/ShopInfo.java @@ -1,5 +1,162 @@ package emu.grasscutter.game.shop; -public class ShopInfo { +import emu.grasscutter.data.common.ItemParamData; +import java.util.ArrayList; +import java.util.List; + +public class ShopInfo { + public int shopId = 1004; + public int goodsId = 0; + public ItemParamData goodsItem; + public int scoin = 0; + public List costItemList; + public int boughtNum = 0; + public int buyLimit = 0; + public int beginTime = 0; + public int endTime = 1924992000; + public int nextRefreshTime = 1924992000; + public int minLevel = 0; + public int maxLevel = 61; + public List preGoodsIdList = new ArrayList<>(); + public int mcoin = 0; + public int hcoin = 0; + public int disableType = 0; + public int secondarySheetId = 0; + + public int getHcoin() { + return hcoin; + } + + public void setHcoin(int hcoin) { + this.hcoin = hcoin; + } + + public List getPreGoodsIdList() { + return preGoodsIdList; + } + + public void setPreGoodsIdList(List preGoodsIdList) { + this.preGoodsIdList = preGoodsIdList; + } + + public int getMcoin() { + return mcoin; + } + + public void setMcoin(int mcoin) { + this.mcoin = mcoin; + } + + public int getDisableType() { + return disableType; + } + + public void setDisableType(int disableType) { + this.disableType = disableType; + } + + public int getSecondarySheetId() { + return secondarySheetId; + } + + public void setSecondarySheetId(int secondarySheetId) { + this.secondarySheetId = secondarySheetId; + } + + public int getShopId() { + return shopId; + } + + public void setShopId(int shopId) { + this.shopId = shopId; + } + + public int getGoodsId() { + return goodsId; + } + + public void setGoodsId(int goodsId) { + this.goodsId = goodsId; + } + + public ItemParamData getGoodsItem() { + return goodsItem; + } + + public void setGoodsItem(ItemParamData goodsItem) { + this.goodsItem = goodsItem; + } + + public int getScoin() { + return scoin; + } + + public void setScoin(int scoin) { + this.scoin = scoin; + } + + public List getCostItemList() { + return costItemList; + } + + public void setCostItemList(List costItemList) { + this.costItemList = costItemList; + } + + public int getBoughtNum() { + return boughtNum; + } + + public void setBoughtNum(int boughtNum) { + this.boughtNum = boughtNum; + } + + public int getBuyLimit() { + return buyLimit; + } + + public void setBuyLimit(int buyLimit) { + this.buyLimit = buyLimit; + } + + public int getBeginTime() { + return beginTime; + } + + public void setBeginTime(int beginTime) { + this.beginTime = beginTime; + } + + public int getEndTime() { + return endTime; + } + + public void setEndTime(int endTime) { + this.endTime = endTime; + } + + public int getNextRefreshTime() { + return nextRefreshTime; + } + + public void setNextRefreshTime(int nextRefreshTime) { + this.nextRefreshTime = nextRefreshTime; + } + + public int getMinLevel() { + return minLevel; + } + + public void setMinLevel(int minLevel) { + this.minLevel = minLevel; + } + + public int getMaxLevel() { + return maxLevel; + } + + public void setMaxLevel(int maxLevel) { + this.maxLevel = maxLevel; + } } diff --git a/src/main/java/emu/grasscutter/game/shop/ShopLimit.java b/src/main/java/emu/grasscutter/game/shop/ShopLimit.java new file mode 100644 index 000000000..ded87102e --- /dev/null +++ b/src/main/java/emu/grasscutter/game/shop/ShopLimit.java @@ -0,0 +1,25 @@ +package emu.grasscutter.game.shop; + +import dev.morphia.annotations.Entity; + +@Entity +public class ShopLimit { + public int getShopGoodId() { + return shopGoodId; + } + + public void setShopGoodId(int shopGoodId) { + this.shopGoodId = shopGoodId; + } + + public int getHasBought() { + return hasBought; + } + + public void setHasBought(int hasBought) { + this.hasBought = hasBought; + } + + private int shopGoodId; + private int hasBought; +} diff --git a/src/main/java/emu/grasscutter/game/shop/ShopManager.java b/src/main/java/emu/grasscutter/game/shop/ShopManager.java index a21888f25..e591aa65e 100644 --- a/src/main/java/emu/grasscutter/game/shop/ShopManager.java +++ b/src/main/java/emu/grasscutter/game/shop/ShopManager.java @@ -1,12 +1,50 @@ package emu.grasscutter.game.shop; +import com.google.gson.reflect.TypeToken; +import emu.grasscutter.Grasscutter; import emu.grasscutter.server.game.GameServer; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + +import java.io.FileReader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; public class ShopManager { private final GameServer server; + + public Int2ObjectMap> getShopData() { + return shopData; + } + + private final Int2ObjectMap> shopData; public ShopManager(GameServer server) { this.server = server; + this.shopData = new Int2ObjectOpenHashMap<>(); + this.load(); + } + + public synchronized void load() { + try (FileReader fileReader = new FileReader(Grasscutter.getConfig().DATA_FOLDER + "Shop.json")) { + getShopData().clear(); + List banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ShopInfo.class).getType()); + if(banners.size() > 0) { + for (ShopInfo shopInfo : banners) { + if (!getShopData().containsKey(shopInfo.getShopId())) + getShopData().put(shopInfo.getShopId(), new ArrayList<>()); + getShopData().get(shopInfo.getShopId()).add(shopInfo); + Grasscutter.getLogger().info(String.format("Shop add: id [%d], data [%d*%d]", shopInfo.getShopId(), shopInfo.getGoodsItem().getId(), shopInfo.getGoodsItem().getCount())); + } + Grasscutter.getLogger().info("Shop data successfully loaded."); + } else { + Grasscutter.getLogger().error("Unable to load shop data. Shop data size is 0."); + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } public GameServer getServer() { diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyGoodsReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyGoodsReq.java new file mode 100644 index 000000000..c83808ada --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyGoodsReq.java @@ -0,0 +1,67 @@ +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.BuyGoodsReqOuterClass; +import emu.grasscutter.net.proto.ItemParamOuterClass; +import emu.grasscutter.net.proto.ShopGoodsOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketBuyGoodsRsp; +import emu.grasscutter.server.packet.send.PacketStoreItemChangeNotify; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Optional; + +@Opcodes(PacketOpcodes.BuyGoodsReq) +public class HandlerBuyGoodsReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + BuyGoodsReqOuterClass.BuyGoodsReq buyGoodsReq = BuyGoodsReqOuterClass.BuyGoodsReq.parseFrom(payload); + + for (ShopGoodsOuterClass.ShopGoods sg : buyGoodsReq.getGoodsListList()) { + if (sg.getScoin() > 0 && session.getPlayer().getMora() < buyGoodsReq.getBoughtNum() * sg.getScoin()) { + return; + } + if (sg.getHcoin() > 0 && session.getPlayer().getPrimogems() < buyGoodsReq.getBoughtNum() * sg.getHcoin()) { + return; + } + if (sg.getMcoin() > 0 && session.getPlayer().getProperty(PlayerProperty.PROP_PLAYER_MCOIN) < buyGoodsReq.getBoughtNum() * sg.getMcoin()) { + return; + } + + HashMap itemsCache = new HashMap<>(); + for (ItemParamOuterClass.ItemParam p : sg.getCostItemListList()) { + Optional invItem = session.getPlayer().getInventory().getItems().values().stream().filter(x -> x.getItemId() == p.getItemId()).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().setProperty(PlayerProperty.PROP_PLAYER_MCOIN, session.getPlayer().getProperty(PlayerProperty.PROP_PLAYER_MCOIN) - 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()); + GameItem item = new GameItem(GameData.getItemDataMap().get(sg.getGoodsItem().getItemId())); + item.setCount(buyGoodsReq.getBoughtNum() * sg.getGoodsItem().getCount()); + 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().getGoodsLimitNum(sg.getGoodsId()), sg)); + } + + session.getPlayer().save(); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetShopReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetShopReq.java index 9b7c6e96d..1dbe1c3ff 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetShopReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetShopReq.java @@ -1,9 +1,9 @@ package emu.grasscutter.server.packet.recv; import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.GetShopReqOuterClass.GetShopReq; -import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.packet.send.PacketGetShopRsp; @@ -12,8 +12,7 @@ public class HandlerGetShopReq extends PacketHandler { @Override public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { GetShopReq req = GetShopReq.parseFrom(payload); - - // TODO - session.send(new PacketGetShopRsp(req.getShopType())); + + session.send(new PacketGetShopRsp(session.getPlayer(), req.getShopType())); } } diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketBuyGoodsRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketBuyGoodsRsp.java new file mode 100644 index 000000000..07371440d --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketBuyGoodsRsp.java @@ -0,0 +1,22 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.BuyGoodsRspOuterClass; +import emu.grasscutter.net.proto.ShopGoodsOuterClass; + +public class PacketBuyGoodsRsp extends BasePacket { + public PacketBuyGoodsRsp(int shopType, int boughtNum, ShopGoodsOuterClass.ShopGoods sg) { + super(PacketOpcodes.BuyGoodsRsp); + + BuyGoodsRspOuterClass.BuyGoodsRsp buyGoodsRsp = BuyGoodsRspOuterClass.BuyGoodsRsp.newBuilder() + .setShopType(shopType) + .setBoughtNum(boughtNum) + .addGoodsList(ShopGoodsOuterClass.ShopGoods.newBuilder() + .mergeFrom(sg) + .setBoughtNum(boughtNum) + ).build(); + + this.setData(buyGoodsRsp); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetShopRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetShopRsp.java index 64d415763..4f57c72e6 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetShopRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetShopRsp.java @@ -1,19 +1,60 @@ package emu.grasscutter.server.packet.send; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.shop.ShopInfo; +import emu.grasscutter.game.shop.ShopManager; import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetShopRspOuterClass.GetShopRsp; +import emu.grasscutter.net.proto.GetShopRspOuterClass; +import emu.grasscutter.net.proto.ItemParamOuterClass; +import emu.grasscutter.net.proto.ShopGoodsOuterClass.ShopGoods; import emu.grasscutter.net.proto.ShopOuterClass.Shop; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + public class PacketGetShopRsp extends BasePacket { - - public PacketGetShopRsp(int shopType) { + + public PacketGetShopRsp(Player inv, int shopType) { super(PacketOpcodes.GetShopRsp); - GetShopRsp proto = GetShopRsp.newBuilder() - .setShop(Shop.newBuilder().setShopType(shopType)) - .build(); - - this.setData(proto); + // TODO: CityReputationLevel + Shop.Builder shop = Shop.newBuilder() + .setShopType(shopType) + .setCityId(1) //mock + .setCityReputationLevel(10); //mock + + ShopManager manager = Grasscutter.getGameServer().getShopManager(); + if (manager.getShopData().get(shopType) != null) { + List list = manager.getShopData().get(shopType); + List goodsList = new ArrayList<>(); + for (ShopInfo info : list) { + ShopGoods.Builder goods = ShopGoods.newBuilder() + .setGoodsId(info.getGoodsId()) + .setGoodsItem(ItemParamOuterClass.ItemParam.newBuilder().setItemId(info.getGoodsItem().getId()).setCount(info.getGoodsItem().getCount()).build()) + .setScoin(info.getScoin()) + .setHcoin(info.getHcoin()) + .setBoughtNum(inv.getGoodsLimitNum(info.getGoodsId())) + .setBuyLimit(info.getBuyLimit()) + .setBeginTime(info.getBeginTime()) + .setEndTime(info.getEndTime()) + .setNextRefreshTime(info.getNextRefreshTime()) + .setMinLevel(info.getMinLevel()) + .setMaxLevel(info.getMaxLevel()) + .addAllPreGoodsIdList(info.getPreGoodsIdList()) + .setMcoin(info.getMcoin()) + .setDisableType(info.getDisableType()) + .setSecondarySheetId(info.getSecondarySheetId()); + if (info.getCostItemList() != null) { + goods.addAllCostItemList(info.getCostItemList().stream().map(x -> ItemParamOuterClass.ItemParam.newBuilder().setItemId(x.getId()).setCount(x.getCount()).build()).collect(Collectors.toList())); + } + goodsList.add(goods.build()); + } + shop.addAllGoodsList(goodsList); + } + + this.setData(GetShopRspOuterClass.GetShopRsp.newBuilder().setShop(shop).build()); } } From ee3a0c32fc89413d34433a661e8f4584d9102e9e Mon Sep 17 00:00:00 2001 From: Kengxxiao <11478651+Kengxxiao@users.noreply.github.com> Date: Wed, 27 Apr 2022 19:56:53 +0800 Subject: [PATCH 3/3] use better shop config structure --- data/Shop.json | 130 +++++++----------- .../emu/grasscutter/game/shop/ShopInfo.java | 41 +++--- .../grasscutter/game/shop/ShopManager.java | 12 +- .../emu/grasscutter/game/shop/ShopTable.java | 25 ++++ 4 files changed, 94 insertions(+), 114 deletions(-) create mode 100644 src/main/java/emu/grasscutter/game/shop/ShopTable.java diff --git a/data/Shop.json b/data/Shop.json index 85d6ad9e8..9670b0bfc 100644 --- a/data/Shop.json +++ b/data/Shop.json @@ -1,86 +1,54 @@ [ { "shopId": 1004, - "goodsId": 1004202, - "goodsItem": { - "Id": 202, - "Count": 1000000 - }, - "scoin": 1, - "buyLimit": 500, - "beginTime": 1575129600, - "endTime": 2051193600, - "minLevel": 1, - "maxLevel": 99 - }, - { - "shopId": 1004, - "goodsId": 10048006, - "goodsItem": { - "Id": 108006, - "Count": 20 - }, - "scoin": 1, - "buyLimit": 50000, - "beginTime": 1575129600, - "endTime": 2051193600, - "minLevel": 1, - "maxLevel": 99 - }, - { - "shopId": 1004, - "goodsId": 10048033, - "goodsItem": { - "Id": 108033, - "Count": 20 - }, - "scoin": 1, - "buyLimit": 50000, - "beginTime": 1575129600, - "endTime": 2051193600, - "minLevel": 1, - "maxLevel": 99 - }, - { - "shopId": 1004, - "goodsId": 10040008, - "goodsItem": { - "Id": 220008, - "Count": 1 - }, - "scoin": 1, - "buyLimit": 1, - "beginTime": 1575129600, - "endTime": 2051193600, - "minLevel": 1, - "maxLevel": 99 - }, - { - "shopId": 1004, - "goodsId": 10044003, - "goodsItem": { - "Id": 104003, - "Count": 200 - }, - "scoin": 1, - "buyLimit": 50000, - "beginTime": 1575129600, - "endTime": 2051193600, - "minLevel": 1, - "maxLevel": 99 - }, - { - "shopId": 1004, - "goodsId": 10044013, - "goodsItem": { - "Id": 104013, - "Count": 200 - }, - "scoin": 1, - "buyLimit": 50000, - "beginTime": 1575129600, - "endTime": 2051193600, - "minLevel": 1, - "maxLevel": 99 + "items": [ + { + "goodsId": 1004202, + "goodsItem": { + "Id": 202, + "Count": 1000000 + }, + "scoin": 1, + "buyLimit": 500, + "beginTime": 1575129600, + "endTime": 2051193600, + "minLevel": 1, + "maxLevel": 99, + "costItemList": [ + { + "Id": 223, + "Count": 100 + } + ] + }, + { + "goodsId": 10048006, + "goodsItem": { + "Id": 108006, + "Count": 20 + }, + "scoin": 100, + "hcoin": 100, + "mcoin": 100, + "buyLimit": 50000, + "beginTime": 1575129600, + "endTime": 2051193600, + "minLevel": 1, + "maxLevel": 99 + }, + { + "goodsId": 10048033, + "goodsItem": { + "Id": 108033, + "Count": 20 + }, + "scoin": 1, + "buyLimit": 50000, + "beginTime": 1575129600, + "endTime": 2051193600, + "minLevel": 1, + "maxLevel": 99 + } + ] } ] \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/game/shop/ShopInfo.java b/src/main/java/emu/grasscutter/game/shop/ShopInfo.java index 510f0d479..b0e3b819b 100644 --- a/src/main/java/emu/grasscutter/game/shop/ShopInfo.java +++ b/src/main/java/emu/grasscutter/game/shop/ShopInfo.java @@ -6,23 +6,22 @@ import java.util.ArrayList; import java.util.List; public class ShopInfo { - public int shopId = 1004; - public int goodsId = 0; - public ItemParamData goodsItem; - public int scoin = 0; - public List costItemList; - public int boughtNum = 0; - public int buyLimit = 0; - public int beginTime = 0; - public int endTime = 1924992000; - public int nextRefreshTime = 1924992000; - public int minLevel = 0; - public int maxLevel = 61; - public List preGoodsIdList = new ArrayList<>(); - public int mcoin = 0; - public int hcoin = 0; - public int disableType = 0; - public int secondarySheetId = 0; + private int goodsId = 0; + private ItemParamData goodsItem; + private int scoin = 0; + private List costItemList; + private int boughtNum = 0; + private int buyLimit = 0; + private int beginTime = 0; + private int endTime = 1924992000; + private int nextRefreshTime = 1924992000; + private int minLevel = 0; + private int maxLevel = 61; + private List preGoodsIdList = new ArrayList<>(); + private int mcoin = 0; + private int hcoin = 0; + private int disableType = 0; + private int secondarySheetId = 0; public int getHcoin() { return hcoin; @@ -64,14 +63,6 @@ public class ShopInfo { this.secondarySheetId = secondarySheetId; } - public int getShopId() { - return shopId; - } - - public void setShopId(int shopId) { - this.shopId = shopId; - } - public int getGoodsId() { return goodsId; } diff --git a/src/main/java/emu/grasscutter/game/shop/ShopManager.java b/src/main/java/emu/grasscutter/game/shop/ShopManager.java index e591aa65e..63436e517 100644 --- a/src/main/java/emu/grasscutter/game/shop/ShopManager.java +++ b/src/main/java/emu/grasscutter/game/shop/ShopManager.java @@ -7,7 +7,6 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import java.io.FileReader; -import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -19,7 +18,7 @@ public class ShopManager { } private final Int2ObjectMap> shopData; - + public ShopManager(GameServer server) { this.server = server; this.shopData = new Int2ObjectOpenHashMap<>(); @@ -29,13 +28,10 @@ public class ShopManager { public synchronized void load() { try (FileReader fileReader = new FileReader(Grasscutter.getConfig().DATA_FOLDER + "Shop.json")) { getShopData().clear(); - List banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ShopInfo.class).getType()); + List banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ShopTable.class).getType()); if(banners.size() > 0) { - for (ShopInfo shopInfo : banners) { - if (!getShopData().containsKey(shopInfo.getShopId())) - getShopData().put(shopInfo.getShopId(), new ArrayList<>()); - getShopData().get(shopInfo.getShopId()).add(shopInfo); - Grasscutter.getLogger().info(String.format("Shop add: id [%d], data [%d*%d]", shopInfo.getShopId(), shopInfo.getGoodsItem().getId(), shopInfo.getGoodsItem().getCount())); + for (ShopTable shopTable : banners) { + getShopData().put(shopTable.getShopId(), shopTable.getItems()); } Grasscutter.getLogger().info("Shop data successfully loaded."); } else { diff --git a/src/main/java/emu/grasscutter/game/shop/ShopTable.java b/src/main/java/emu/grasscutter/game/shop/ShopTable.java new file mode 100644 index 000000000..7396cd028 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/shop/ShopTable.java @@ -0,0 +1,25 @@ +package emu.grasscutter.game.shop; + +import java.util.ArrayList; +import java.util.List; + +public class ShopTable { + private int shopId; + private List items = new ArrayList<>(); + + public int getShopId() { + return shopId; + } + + public void setShopId(int shopId) { + this.shopId = shopId; + } + + public List getItems() { + return items; + } + + public void setItems(List items) { + this.items = items; + } +}