From b82567d9d98c9a6374ef7f1f090372ecaf7acb60 Mon Sep 17 00:00:00 2001 From: KingRainbow44 Date: Mon, 31 Jul 2023 15:42:52 -0400 Subject: [PATCH] Attempt to implement item giving to NPCs (untested) --- .../java/emu/grasscutter/data/GameData.java | 61 +++++++----------- .../data/excels/giving/GivingData.java | 42 +++++++++++++ .../data/excels/giving/GivingGroupData.java | 21 +++++++ .../grasscutter/game/inventory/BagTab.java | 55 ++++++++++++++++ .../grasscutter/game/inventory/Inventory.java | 62 +++++++++++++++++- .../emu/grasscutter/game/player/Player.java | 2 +- .../grasscutter/game/quest/QuestManager.java | 9 ++- .../game/quest/enums/QuestContent.java | 2 +- .../game/quest/enums/QuestExec.java | 4 +- .../game/quest/exec/ExecActiveItemGiving.java | 26 ++++++++ .../quest/exec/ExecDeactivateItemGiving.java | 26 ++++++++ .../packet/recv/HandlerItemGivingReq.java | 63 +++++++++++++++++++ .../packet/send/PacketItemGivingRsp.java | 30 +++++++++ 13 files changed, 354 insertions(+), 49 deletions(-) create mode 100644 src/main/java/emu/grasscutter/data/excels/giving/GivingData.java create mode 100644 src/main/java/emu/grasscutter/data/excels/giving/GivingGroupData.java create mode 100644 src/main/java/emu/grasscutter/game/inventory/BagTab.java create mode 100644 src/main/java/emu/grasscutter/game/quest/exec/ExecActiveItemGiving.java create mode 100644 src/main/java/emu/grasscutter/game/quest/exec/ExecDeactivateItemGiving.java create mode 100644 src/main/java/emu/grasscutter/server/packet/recv/HandlerItemGivingReq.java create mode 100644 src/main/java/emu/grasscutter/server/packet/send/PacketItemGivingRsp.java diff --git a/src/main/java/emu/grasscutter/data/GameData.java b/src/main/java/emu/grasscutter/data/GameData.java index 3b99f1f26..a688bf753 100644 --- a/src/main/java/emu/grasscutter/data/GameData.java +++ b/src/main/java/emu/grasscutter/data/GameData.java @@ -4,58 +4,33 @@ import emu.grasscutter.Grasscutter; import emu.grasscutter.data.binout.*; import emu.grasscutter.data.binout.config.*; import emu.grasscutter.data.binout.routes.Route; -import emu.grasscutter.data.custom.TrialAvatarActivityCustomData; -import emu.grasscutter.data.custom.TrialAvatarCustomData; +import emu.grasscutter.data.custom.*; import emu.grasscutter.data.excels.*; -import emu.grasscutter.data.excels.achievement.AchievementData; -import emu.grasscutter.data.excels.achievement.AchievementGoalData; -import emu.grasscutter.data.excels.activity.ActivityCondExcelConfigData; -import emu.grasscutter.data.excels.activity.ActivityData; -import emu.grasscutter.data.excels.activity.ActivityShopData; -import emu.grasscutter.data.excels.activity.ActivityWatcherData; +import emu.grasscutter.data.excels.achievement.*; +import emu.grasscutter.data.excels.activity.*; import emu.grasscutter.data.excels.avatar.*; import emu.grasscutter.data.excels.codex.*; import emu.grasscutter.data.excels.dungeon.*; -import emu.grasscutter.data.excels.monster.MonsterCurveData; -import emu.grasscutter.data.excels.monster.MonsterData; -import emu.grasscutter.data.excels.monster.MonsterDescribeData; -import emu.grasscutter.data.excels.monster.MonsterSpecialNameData; -import emu.grasscutter.data.excels.quest.QuestData; -import emu.grasscutter.data.excels.quest.QuestGlobalVarData; -import emu.grasscutter.data.excels.reliquary.ReliquaryAffixData; -import emu.grasscutter.data.excels.reliquary.ReliquaryLevelData; -import emu.grasscutter.data.excels.reliquary.ReliquaryMainPropData; -import emu.grasscutter.data.excels.reliquary.ReliquarySetData; -import emu.grasscutter.data.excels.tower.TowerFloorData; -import emu.grasscutter.data.excels.tower.TowerLevelData; -import emu.grasscutter.data.excels.tower.TowerScheduleData; +import emu.grasscutter.data.excels.giving.*; +import emu.grasscutter.data.excels.monster.*; +import emu.grasscutter.data.excels.quest.*; +import emu.grasscutter.data.excels.reliquary.*; +import emu.grasscutter.data.excels.tower.*; import emu.grasscutter.data.excels.trial.*; -import emu.grasscutter.data.excels.weapon.WeaponCurveData; -import emu.grasscutter.data.excels.weapon.WeaponLevelData; -import emu.grasscutter.data.excels.weapon.WeaponPromoteData; -import emu.grasscutter.data.excels.world.WeatherData; -import emu.grasscutter.data.excels.world.WorldAreaData; -import emu.grasscutter.data.excels.world.WorldLevelData; -import emu.grasscutter.data.server.ActivityCondGroup; -import emu.grasscutter.data.server.DropSubfieldMapping; -import emu.grasscutter.data.server.DropTableExcelConfigData; -import emu.grasscutter.data.server.GadgetMapping; -import emu.grasscutter.data.server.MonsterMapping; -import emu.grasscutter.data.server.SubfieldMapping; +import emu.grasscutter.data.excels.weapon.*; +import emu.grasscutter.data.excels.world.*; +import emu.grasscutter.data.server.*; import emu.grasscutter.game.dungeons.DungeonDropEntry; -import emu.grasscutter.game.quest.QuestEncryptionKey; -import emu.grasscutter.game.quest.RewindData; -import emu.grasscutter.game.quest.TeleportData; +import emu.grasscutter.game.quest.*; import emu.grasscutter.game.quest.enums.QuestCond; import emu.grasscutter.game.world.GroupReplacementData; import emu.grasscutter.utils.Utils; import it.unimi.dsi.fastutil.ints.*; +import lombok.*; + +import javax.annotation.Nullable; import java.lang.reflect.Field; import java.util.*; -import javax.annotation.Nullable; -import lombok.Getter; -import lombok.Setter; -import lombok.val; @SuppressWarnings({"unused", "MismatchedQueryAndUpdateOfCollection"}) public final class GameData { @@ -266,6 +241,12 @@ public final class GameData { @Getter private static final Int2ObjectMap gatherDataMap = new Int2ObjectOpenHashMap<>(); + @Getter + private static final Int2ObjectMap givingDataMap = new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap givingGroupDataMap = new Int2ObjectOpenHashMap<>(); + @Getter @Deprecated // This is to prevent people from using this map. This is for the resource loader // only! diff --git a/src/main/java/emu/grasscutter/data/excels/giving/GivingData.java b/src/main/java/emu/grasscutter/data/excels/giving/GivingData.java new file mode 100644 index 000000000..dab20c6d9 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/giving/GivingData.java @@ -0,0 +1,42 @@ +package emu.grasscutter.data.excels.giving; + +import com.google.gson.annotations.SerializedName; +import emu.grasscutter.data.*; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.game.inventory.BagTab; +import lombok.*; + +import java.util.List; + +@Data +@EqualsAndHashCode(callSuper = false) +@ResourceType(name = "GivingExcelConfigData.json") +public final class GivingData extends GameResource { + @SerializedName(value = "id", alternate = "Id") + private int id; + private int talkId; + private int mistakeTalkId; + + private BagTab tab; + private GiveMethod givingMethod; + + private List exactItems; + private int exactFinishTalkId; + + private List givingGroupIds; + private int givingGroupCount; + + private boolean isRemoveItem; + private GiveType giveType; + + public enum GiveMethod { + @SerializedName("GIVING_METHOD_EXACT") EXACT, + @SerializedName("GIVING_METHOD_GROUP") GROUP, + @SerializedName("GIVING_METHOD_VAGUE_GROUP") GROUP_VAGUE + } + + public enum GiveType { + @SerializedName("GIVING_TYPE_QUEST") QUEST, + @SerializedName("GIVING_TYPE_GROUP") GROUP + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/giving/GivingGroupData.java b/src/main/java/emu/grasscutter/data/excels/giving/GivingGroupData.java new file mode 100644 index 000000000..4c5bb7d1a --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/giving/GivingGroupData.java @@ -0,0 +1,21 @@ +package emu.grasscutter.data.excels.giving; + +import com.google.gson.annotations.SerializedName; +import emu.grasscutter.data.*; +import lombok.*; + +import java.util.List; + +@Data +@EqualsAndHashCode(callSuper = false) +@ResourceType(name = "GivingGroupExcelConfigData.json") +public final class GivingGroupData extends GameResource { + @SerializedName(value = "id", alternate = "Id") + private int id; + + @SerializedName(value = "itemIds", alternate = "ItemIds") + private List itemIds; + + private int finishTalkId; + private int mistakeTalkId; +} diff --git a/src/main/java/emu/grasscutter/game/inventory/BagTab.java b/src/main/java/emu/grasscutter/game/inventory/BagTab.java new file mode 100644 index 000000000..a089912f7 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/inventory/BagTab.java @@ -0,0 +1,55 @@ +package emu.grasscutter.game.inventory; + +import it.unimi.dsi.fastutil.ints.*; +import lombok.*; + +import java.util.*; +import java.util.stream.Stream; + +@RequiredArgsConstructor +public enum BagTab { + TAB_NONE(0), + TAB_WEAPON(1), + TAB_EQUIP(2), + TAB_AVATAR(3), + TAB_FOOD(4), + TAB_MATERIAL(5), + TAB_QUEST(6), + TAB_CONSUME(7), + TAB_WIDGET(8), + TAB_HOMEWORLD(9); + + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + private static final Map stringMap = new HashMap<>(); + + static { + Stream.of(BagTab.values()) + .forEach( + entry -> { + map.put(entry.getValue(), entry); + stringMap.put(entry.name(), entry); + }); + } + + @Getter private final int value; + + /** + * Fetches the bag tab by its value. + * + * @param value The name of the bag tab. + * @return The bag tab. + */ + public static BagTab getTypeByValue(int value) { + return map.getOrDefault(value, TAB_NONE); + } + + /** + * Fetches the bag tab by its name. + * + * @param name The name of the bag tab. + * @return The bag tab. + */ + public static BagTab getTypeByName(String name) { + return stringMap.getOrDefault(name, TAB_NONE); + } +} diff --git a/src/main/java/emu/grasscutter/game/inventory/Inventory.java b/src/main/java/emu/grasscutter/game/inventory/Inventory.java index a06d55ed1..a49ee4081 100644 --- a/src/main/java/emu/grasscutter/game/inventory/Inventory.java +++ b/src/main/java/emu/grasscutter/game/inventory/Inventory.java @@ -1,7 +1,5 @@ package emu.grasscutter.game.inventory; -import static emu.grasscutter.config.Configuration.INVENTORY_LIMITS; - import emu.grasscutter.Grasscutter; import emu.grasscutter.data.GameData; import emu.grasscutter.data.common.ItemParamData; @@ -17,8 +15,11 @@ import emu.grasscutter.server.packet.send.*; import emu.grasscutter.utils.Utils; import it.unimi.dsi.fastutil.ints.*; import it.unimi.dsi.fastutil.longs.*; + import java.util.*; +import static emu.grasscutter.config.Configuration.INVENTORY_LIMITS; + public class Inventory extends BasePlayerManager implements Iterable { private final Long2ObjectMap store; private final Int2ObjectMap inventoryTypes; @@ -150,6 +151,52 @@ public class Inventory extends BasePlayerManager implements Iterable { getPlayer().sendPacket(new PacketStoreItemChangeNotify(changedItems)); } + /** + * Checks to see if the player has the item in their inventory. + * This will succeed if the player has at least the minimum count of the item. + * + * @param itemGuid The item id to check for. + * @param minCount The minimum count of the item to check for. + * @return True if the player has the item, false otherwise. + */ + public boolean hasItem(long itemGuid, int minCount) { + return hasItem(itemGuid, minCount, false); + } + + /** + * Checks to see if the player has the item in their inventory. + * + * @param itemGuid The item id to check for. + * @param count The count of the item to check for. + * @param enforce If true, the player must have the exact amount. + * If false, the player must have at least the amount. + * @return True if the player has the item, false otherwise. + */ + public boolean hasItem(long itemGuid, int count, boolean enforce) { + var item = this.getItemByGuid(itemGuid); + if (item == null) return false; + + return enforce ? + item.getCount() == count : + item.getCount() >= count; + } + + /** + * Checks to see if the player has the item in their inventory. + * This is exact. + * + * @param items A map of item game IDs to their count. + * @return True if the player has the items, false otherwise. + */ + public boolean hasAllItems(Map items) { + for (var item : items.entrySet()) { + if (!this.hasItem(item.getKey(), item.getValue(), true)) + return false; + } + + return true; + } + private void triggerAddItemEvents(GameItem result) { try { getPlayer() @@ -434,6 +481,17 @@ public class Inventory extends BasePlayerManager implements Iterable { } } + /** + * Performs a bulk delete of items. + * + * @param items A map of item game IDs to the amount of items to remove. + */ + public void removeItems(Map items) { + for (var entry : items.entrySet()) { + this.removeItem(entry.getKey(), entry.getValue()); + } + } + public boolean removeItem(long guid) { return removeItem(guid, 1); } diff --git a/src/main/java/emu/grasscutter/game/player/Player.java b/src/main/java/emu/grasscutter/game/player/Player.java index 26e091bb2..075545985 100644 --- a/src/main/java/emu/grasscutter/game/player/Player.java +++ b/src/main/java/emu/grasscutter/game/player/Player.java @@ -159,7 +159,7 @@ public class Player implements PlayerHook, FieldFetch { @Getter private transient FriendsList friendsList; @Getter private transient MailHandler mailHandler; @Getter private transient AbilityManager abilityManager; - @Getter @Setter private transient QuestManager questManager; + @Getter private transient QuestManager questManager; @Getter private transient TowerManager towerManager; @Getter private transient SotSManager sotsManager; @Getter private transient MapMarksManager mapMarksManager; diff --git a/src/main/java/emu/grasscutter/game/quest/QuestManager.java b/src/main/java/emu/grasscutter/game/quest/QuestManager.java index 572731edb..e7c21ad7f 100644 --- a/src/main/java/emu/grasscutter/game/quest/QuestManager.java +++ b/src/main/java/emu/grasscutter/game/quest/QuestManager.java @@ -1,6 +1,5 @@ package emu.grasscutter.game.quest; -import dev.morphia.annotations.Transient; import emu.grasscutter.Grasscutter; import emu.grasscutter.data.GameData; import emu.grasscutter.data.binout.MainQuestData; @@ -31,10 +30,13 @@ import static emu.grasscutter.GameConstants.DEBUG; import static emu.grasscutter.config.Configuration.GAME_OPTIONS; import static emu.grasscutter.config.Configuration.SERVER; -public class QuestManager extends BasePlayerManager { +public final class QuestManager extends BasePlayerManager { @Getter private final Player player; + @Getter private final Int2ObjectMap mainQuests; - @Transient @Getter private final List loggedQuests; + @Getter private final List loggedQuests; + + @Getter private final List activeGivings = new ArrayList<>(); private long lastHourCheck = 0; private long lastDayCheck = 0; @@ -45,6 +47,7 @@ public class QuestManager extends BasePlayerManager { 60, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1000), FastThreadLocalThread::new, new ThreadPoolExecutor.AbortPolicy()); } + /* On SetPlayerBornDataReq, the server sends FinishedParentQuestNotify, with this exact parentQuestList. Captured on Game version 2.7 diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestContent.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestContent.java index 3c3f378a3..ba805674e 100644 --- a/src/main/java/emu/grasscutter/game/quest/enums/QuestContent.java +++ b/src/main/java/emu/grasscutter/game/quest/enums/QuestContent.java @@ -34,7 +34,7 @@ public enum QuestContent implements QuestTrigger { QUEST_CONTENT_ADD_QUEST_PROGRESS(24), QUEST_CONTENT_INTERACT_GADGET(25), QUEST_CONTENT_DAILY_TASK_COMP_FINISH(26), // missing, currently unused - QUEST_CONTENT_FINISH_ITEM_GIVING(27), // missing, finish + QUEST_CONTENT_FINISH_ITEM_GIVING(27), QUEST_CONTENT_SKILL(107), QUEST_CONTENT_CITY_LEVEL_UP(109), // missing, finish QUEST_CONTENT_PATTERN_GROUP_CLEAR_MONSTER(110), // missing, finish, for random quests diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestExec.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestExec.java index faba81e32..1466c15ff 100644 --- a/src/main/java/emu/grasscutter/game/quest/enums/QuestExec.java +++ b/src/main/java/emu/grasscutter/game/quest/enums/QuestExec.java @@ -35,7 +35,7 @@ public enum QuestExec implements QuestTrigger { QUEST_EXEC_CREATE_PATTERN_GROUP(25), // missing, used for random quests QUEST_EXEC_REMOVE_PATTERN_GROUP(26), // missing, used for random quests QUEST_EXEC_REFRESH_GROUP_SUITE_RANDOM(27), // missing - QUEST_EXEC_ACTIVE_ITEM_GIVING(28), // missing + QUEST_EXEC_ACTIVE_ITEM_GIVING(28), QUEST_EXEC_DEL_ALL_SPECIFIC_PACK_ITEM(29), // missing QUEST_EXEC_ROLLBACK_PARENT_QUEST(30), QUEST_EXEC_LOCK_AVATAR_TEAM(31), // missing @@ -71,7 +71,7 @@ public enum QuestExec implements QuestTrigger { QUEST_EXEC_MODIFY_CLIMATE_AREA(60), // missing QUEST_EXEC_GRANT_TRIAL_AVATAR_AND_LOCK_TEAM(61), // missing QUEST_EXEC_CHANGE_MAP_AREA_STATE(62), // missing - QUEST_EXEC_DEACTIVE_ITEM_GIVING(63), // missing + QUEST_EXEC_DEACTIVE_ITEM_GIVING(63), QUEST_EXEC_CHANGE_SCENE_LEVEL_TAG(64), // missing QUEST_EXEC_UNLOCK_PLAYER_WORLD_SCENE(65), // missing QUEST_EXEC_LOCK_PLAYER_WORLD_SCENE(66), // missing diff --git a/src/main/java/emu/grasscutter/game/quest/exec/ExecActiveItemGiving.java b/src/main/java/emu/grasscutter/game/quest/exec/ExecActiveItemGiving.java new file mode 100644 index 000000000..6b426aa30 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/exec/ExecActiveItemGiving.java @@ -0,0 +1,26 @@ +package emu.grasscutter.game.quest.exec; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.excels.quest.QuestData.QuestExecParam; +import emu.grasscutter.game.quest.*; +import emu.grasscutter.game.quest.enums.QuestExec; +import emu.grasscutter.game.quest.handlers.QuestExecHandler; + +@QuestValueExec(QuestExec.QUEST_EXEC_ACTIVE_ITEM_GIVING) +public final class ExecActiveItemGiving extends QuestExecHandler { + @Override + public boolean execute(GameQuest quest, QuestExecParam condition, String... paramStr) { + var questManager = quest.getOwner().getQuestManager(); + var activeGivings = questManager.getActiveGivings(); + + var givingId = Integer.parseInt(condition.getParam()[0]); + if (activeGivings.contains(givingId)) { + Grasscutter.getLogger().debug("Quest {} attempted to add give action {} twice.", + quest.getSubQuestId(), givingId); + return false; + } else { + activeGivings.add(givingId); + return true; + } + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/exec/ExecDeactivateItemGiving.java b/src/main/java/emu/grasscutter/game/quest/exec/ExecDeactivateItemGiving.java new file mode 100644 index 000000000..2298a6570 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/exec/ExecDeactivateItemGiving.java @@ -0,0 +1,26 @@ +package emu.grasscutter.game.quest.exec; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.excels.quest.QuestData; +import emu.grasscutter.game.quest.*; +import emu.grasscutter.game.quest.enums.QuestExec; +import emu.grasscutter.game.quest.handlers.QuestExecHandler; + +@QuestValueExec(QuestExec.QUEST_EXEC_DEACTIVE_ITEM_GIVING) +public final class ExecDeactivateItemGiving extends QuestExecHandler { + @Override + public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) { + var questManager = quest.getOwner().getQuestManager(); + var activeGivings = questManager.getActiveGivings(); + + var givingId = Integer.parseInt(condition.getParam()[0]); + if (!activeGivings.contains(givingId)) { + Grasscutter.getLogger().debug("Quest {} attempted to remove give action {} when it isn't active.", + quest.getSubQuestId(), givingId); + return false; + } else { + activeGivings.remove(givingId); + return true; + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerItemGivingReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerItemGivingReq.java new file mode 100644 index 000000000..8c9deac7f --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerItemGivingReq.java @@ -0,0 +1,63 @@ +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.giving.GivingData.GiveMethod; +import emu.grasscutter.game.quest.enums.QuestContent; +import emu.grasscutter.net.packet.*; +import emu.grasscutter.net.proto.ItemGivingReqOuterClass.ItemGivingReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketItemGivingRsp; +import emu.grasscutter.server.packet.send.PacketItemGivingRsp.Mode; + +@Opcodes(PacketOpcodes.ItemGivingReq) +public final class HandlerItemGivingReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = ItemGivingReq.parseFrom(payload); + + var player = session.getPlayer(); + var inventory = player.getInventory(); + + var giveId = req.getGivingId(); + var items = req.getItemGuidCountMapMap(); + + switch (req.getItemGivingType()) { + case QUEST -> { + var questManager = player.getQuestManager(); + var activeGivings = questManager.getActiveGivings(); + if (!activeGivings.contains(giveId)) return; + + // Check the items against the resources. + var data = GameData.getGivingDataMap().get(giveId); + if (data == null) throw new IllegalArgumentException("No giving data found for " + giveId + "."); + + if (data.getGivingMethod() == GiveMethod.EXACT) { + if (!inventory.hasAllItems(items)) { + player.sendPacket(new PacketItemGivingRsp()); + return; + } + + // Remove the items if the quest specifies. + if (data.isRemoveItem()) { + inventory.removeItems(items); + } + + // Send the response packet. + player.sendPacket(new PacketItemGivingRsp(giveId, Mode.EXACT_SUCCESS)); + // Remove the action from the active givings. + activeGivings.remove(giveId); + // Queue the content action. + questManager.queueEvent(QuestContent.QUEST_CONTENT_FINISH_ITEM_GIVING, giveId); + } else { + // TODO: Handle group givings. + player.sendPacket(new PacketItemGivingRsp()); + } + } + case GADGET -> { + Grasscutter.getLogger().debug("Unimplemented gadget giving was executed for {}.", giveId); + player.sendPacket(new PacketItemGivingRsp()); + } + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketItemGivingRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketItemGivingRsp.java new file mode 100644 index 000000000..250842a3f --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketItemGivingRsp.java @@ -0,0 +1,30 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.*; +import emu.grasscutter.net.proto.ItemGivingRspOuterClass.ItemGivingRsp; + +public final class PacketItemGivingRsp extends BasePacket { + public PacketItemGivingRsp() { + this(0, Mode.FAILURE); + } + + public PacketItemGivingRsp(int value, Mode mode) { + super(PacketOpcodes.ItemGivingRsp); + + var packet = ItemGivingRsp.newBuilder() + .setRetcode(mode == Mode.FAILURE ? 1 : 0); + if (mode == Mode.EXACT_SUCCESS) { + packet.setGivingId(value); + } else if (mode == Mode.GROUP_SUCCESS) { + packet.setGivingGroupId(value); + } + + this.setData(packet); + } + + public enum Mode { + GROUP_SUCCESS, + EXACT_SUCCESS, + FAILURE + } +}