From e9d7d5d5f2a4942af7d9e92e9685a79229f9e7b8 Mon Sep 17 00:00:00 2001 From: Melledy <52122272+Melledy@users.noreply.github.com> Date: Wed, 11 May 2022 03:56:40 -0700 Subject: [PATCH 1/6] Implement quests --- .../command/commands/QuestCommand.java | 66 ++++++ .../java/emu/grasscutter/data/GameData.java | 6 + .../emu/grasscutter/data/ResourceLoader.java | 34 +++- .../grasscutter/data/custom/QuestConfig.java | 25 +++ .../data/custom/QuestConfigData.java | 104 ++++++++++ .../grasscutter/database/DatabaseHelper.java | 15 ++ .../grasscutter/database/DatabaseManager.java | 5 +- .../emu/grasscutter/game/player/Player.java | 38 +++- .../grasscutter/game/quest/GameMainQuest.java | 124 ++++++++++++ .../emu/grasscutter/game/quest/GameQuest.java | 188 ++++++++++++++++++ .../grasscutter/game/quest/QuestManager.java | 119 +++++++++++ .../game/quest/enums/LogicType.java | 23 +++ .../game/quest/enums/ParentQuestState.java | 18 ++ .../game/quest/enums/QuestCondType.java | 92 +++++++++ .../game/quest/enums/QuestExecType.java | 82 ++++++++ .../game/quest/enums/QuestGuideType.java | 17 ++ .../game/quest/enums/QuestShowType.java | 16 ++ .../game/quest/enums/QuestState.java | 19 ++ .../game/quest/enums/QuestType.java | 22 ++ .../game/quest/enums/ShowQuestGuideType.java | 17 ++ .../send/PacketFinishedParentQuestNotify.java | 22 ++ ...PacketFinishedParentQuestUpdateNotify.java | 19 ++ .../packet/send/PacketQuestListNotify.java | 23 +++ .../send/PacketQuestListUpdateNotify.java | 20 ++ .../send/PacketQuestProgressUpdateNotify.java | 30 +++ ...etServerCondMeetQuestListUpdateNotify.java | 37 ++++ src/main/resources/languages/en-US.json | 8 + 27 files changed, 1183 insertions(+), 6 deletions(-) create mode 100644 src/main/java/emu/grasscutter/command/commands/QuestCommand.java create mode 100644 src/main/java/emu/grasscutter/data/custom/QuestConfig.java create mode 100644 src/main/java/emu/grasscutter/data/custom/QuestConfigData.java create mode 100644 src/main/java/emu/grasscutter/game/quest/GameMainQuest.java create mode 100644 src/main/java/emu/grasscutter/game/quest/GameQuest.java create mode 100644 src/main/java/emu/grasscutter/game/quest/QuestManager.java create mode 100644 src/main/java/emu/grasscutter/game/quest/enums/LogicType.java create mode 100644 src/main/java/emu/grasscutter/game/quest/enums/ParentQuestState.java create mode 100644 src/main/java/emu/grasscutter/game/quest/enums/QuestCondType.java create mode 100644 src/main/java/emu/grasscutter/game/quest/enums/QuestExecType.java create mode 100644 src/main/java/emu/grasscutter/game/quest/enums/QuestGuideType.java create mode 100644 src/main/java/emu/grasscutter/game/quest/enums/QuestShowType.java create mode 100644 src/main/java/emu/grasscutter/game/quest/enums/QuestState.java create mode 100644 src/main/java/emu/grasscutter/game/quest/enums/QuestType.java create mode 100644 src/main/java/emu/grasscutter/game/quest/enums/ShowQuestGuideType.java create mode 100644 src/main/java/emu/grasscutter/server/packet/send/PacketFinishedParentQuestNotify.java create mode 100644 src/main/java/emu/grasscutter/server/packet/send/PacketFinishedParentQuestUpdateNotify.java create mode 100644 src/main/java/emu/grasscutter/server/packet/send/PacketQuestListNotify.java create mode 100644 src/main/java/emu/grasscutter/server/packet/send/PacketQuestListUpdateNotify.java create mode 100644 src/main/java/emu/grasscutter/server/packet/send/PacketQuestProgressUpdateNotify.java create mode 100644 src/main/java/emu/grasscutter/server/packet/send/PacketServerCondMeetQuestListUpdateNotify.java diff --git a/src/main/java/emu/grasscutter/command/commands/QuestCommand.java b/src/main/java/emu/grasscutter/command/commands/QuestCommand.java new file mode 100644 index 000000000..70fae0120 --- /dev/null +++ b/src/main/java/emu/grasscutter/command/commands/QuestCommand.java @@ -0,0 +1,66 @@ +package emu.grasscutter.command.commands; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.command.Command; +import emu.grasscutter.command.CommandHandler; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.GameQuest; + +import java.util.List; + +import static emu.grasscutter.utils.Language.translate; + +@Command(label = "quest", usage = "quest [quest id]", permission = "player.quest", permissionTargeted = "player.quest.others", description = "commands.quest.description") +public final class QuestCommand implements CommandHandler { + + @Override + public void execute(Player sender, Player targetPlayer, List args) { + if (targetPlayer == null) { + CommandHandler.sendMessage(sender, translate(sender, "commands.execution.need_target")); + return; + } + + if (args.size() != 2) { + CommandHandler.sendMessage(sender, translate(sender, "commands.quest.usage")); + return; + } + + String cmd = args.get(0).toLowerCase(); + int questId; + + try { + questId = Integer.parseInt(args.get(1)); + } catch (Exception e) { + CommandHandler.sendMessage(sender, translate(sender, "commands.quest.invalid_id")); + return; + } + + switch (cmd) { + case "add" -> { + GameQuest quest = sender.getQuestManager().addQuest(questId); + + if (quest != null) { + CommandHandler.sendMessage(sender, translate(sender, "commands.quest.added", questId)); + return; + } + + CommandHandler.sendMessage(sender, translate(sender, "commands.quest.not_found")); + } + case "finish" -> { + GameQuest quest = sender.getQuestManager().getQuestById(questId); + + if (quest == null) { + CommandHandler.sendMessage(sender, translate(sender, "commands.quest.not_found")); + return; + } + + quest.finish(); + + CommandHandler.sendMessage(sender, translate(sender, "commands.quest.finished", questId)); + } + default -> { + CommandHandler.sendMessage(sender, translate(sender, "commands.quest.usage")); + } + } + } +} diff --git a/src/main/java/emu/grasscutter/data/GameData.java b/src/main/java/emu/grasscutter/data/GameData.java index ac2472192..2b40818e1 100644 --- a/src/main/java/emu/grasscutter/data/GameData.java +++ b/src/main/java/emu/grasscutter/data/GameData.java @@ -12,6 +12,7 @@ import emu.grasscutter.data.custom.AbilityEmbryoEntry; import emu.grasscutter.data.custom.AbilityModifier; import emu.grasscutter.data.custom.AbilityModifierEntry; import emu.grasscutter.data.custom.OpenConfigEntry; +import emu.grasscutter.data.custom.QuestConfig; import emu.grasscutter.data.custom.ScenePointEntry; import emu.grasscutter.data.def.*; import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; @@ -27,6 +28,7 @@ public class GameData { private static final Map abilityModifiers = new HashMap<>(); private static final Map openConfigEntries = new HashMap<>(); private static final Map scenePointEntries = new HashMap<>(); + private static final Int2ObjectMap questConfigs = new Int2ObjectOpenHashMap<>(); // ExcelConfigs private static final Int2ObjectMap playerLevelDataMap = new Int2ObjectOpenHashMap<>(); @@ -122,6 +124,10 @@ public class GameData { return getScenePointEntries().get(sceneId + "_" + pointId); } + public static Int2ObjectMap getQuestConfigs() { + return questConfigs; + } + public static Int2ObjectMap getAvatarDataMap() { return avatarDataMap; } diff --git a/src/main/java/emu/grasscutter/data/ResourceLoader.java b/src/main/java/emu/grasscutter/data/ResourceLoader.java index c2708bd63..ae73de8ff 100644 --- a/src/main/java/emu/grasscutter/data/ResourceLoader.java +++ b/src/main/java/emu/grasscutter/data/ResourceLoader.java @@ -24,6 +24,9 @@ import emu.grasscutter.data.custom.AbilityModifier.AbilityModifierAction; import emu.grasscutter.data.custom.AbilityModifier.AbilityModifierActionType; import emu.grasscutter.data.custom.AbilityModifierEntry; import emu.grasscutter.data.custom.OpenConfigEntry; +import emu.grasscutter.data.custom.QuestConfig; +import emu.grasscutter.data.custom.QuestConfigData; +import emu.grasscutter.data.custom.QuestConfigData.SubQuestConfigData; import emu.grasscutter.data.custom.ScenePointEntry; import emu.grasscutter.game.world.SpawnDataEntry; import emu.grasscutter.game.world.SpawnDataEntry.SpawnGroupEntry; @@ -57,8 +60,9 @@ public class ResourceLoader { loadResources(); // Process into depots GameDepot.load(); - // Load spawn data + // Load spawn data and quests loadSpawnData(); + loadQuests(); // Load scene points - must be done AFTER resources are loaded loadScenePoints(); // Custom - TODO move this somewhere else @@ -396,6 +400,34 @@ public class ResourceLoader { GameData.getOpenConfigEntries().put(entry.getName(), entry); } } + + private static void loadQuests() { + File folder = new File(Grasscutter.getConfig().RESOURCE_FOLDER + "BinOutput/Quest/"); + + if (!folder.exists()) { + return; + } + + for (File file : folder.listFiles()) { + QuestConfigData mainQuest = null; + + try (FileReader fileReader = new FileReader(file)) { + mainQuest = Grasscutter.getGsonFactory().fromJson(fileReader, QuestConfigData.class); + } catch (Exception e) { + e.printStackTrace(); + continue; + } + + if (mainQuest.getSubQuests() != null) { + for (SubQuestConfigData subQuest : mainQuest.getSubQuests()) { + QuestConfig quest = new QuestConfig(mainQuest, subQuest); + GameData.getQuestConfigs().put(quest.getId(), quest); + } + } + } + + Grasscutter.getLogger().info("Loaded " + GameData.getQuestConfigs().size() + " Quest Configs"); + } // BinOutput configs diff --git a/src/main/java/emu/grasscutter/data/custom/QuestConfig.java b/src/main/java/emu/grasscutter/data/custom/QuestConfig.java new file mode 100644 index 000000000..8674ff7ab --- /dev/null +++ b/src/main/java/emu/grasscutter/data/custom/QuestConfig.java @@ -0,0 +1,25 @@ +package emu.grasscutter.data.custom; + +import emu.grasscutter.data.custom.QuestConfigData.SubQuestConfigData; + +public class QuestConfig { + private final QuestConfigData mainQuest; + private final SubQuestConfigData subQuest; + + public QuestConfig(QuestConfigData mainQuest, SubQuestConfigData subQuest) { + this.mainQuest = mainQuest; + this.subQuest = subQuest; + } + + public int getId() { + return subQuest.getSubId(); + } + + public QuestConfigData getMainQuest() { + return mainQuest; + } + + public SubQuestConfigData getSubQuest() { + return subQuest; + } +} diff --git a/src/main/java/emu/grasscutter/data/custom/QuestConfigData.java b/src/main/java/emu/grasscutter/data/custom/QuestConfigData.java new file mode 100644 index 000000000..4ba0ce47c --- /dev/null +++ b/src/main/java/emu/grasscutter/data/custom/QuestConfigData.java @@ -0,0 +1,104 @@ +package emu.grasscutter.data.custom; + +import emu.grasscutter.game.quest.enums.LogicType; +import emu.grasscutter.game.quest.enums.QuestCondType; +import emu.grasscutter.game.quest.enums.QuestType; + +public class QuestConfigData { + private int id; + private int series; + private QuestType type; + + private long titleTextMapHash; + private int[] suggestTrackMainQuestList; + private int[] rewardIdList; + + private SubQuestConfigData[] subQuests; + + public int getId() { + return id; + } + + public int getSeries() { + return series; + } + + public QuestType getType() { + return type; + } + + public long getTitleTextMapHash() { + return titleTextMapHash; + } + + public int[] getSuggestTrackMainQuestList() { + return suggestTrackMainQuestList; + } + + public int[] getRewardIdList() { + return rewardIdList; + } + + public SubQuestConfigData[] getSubQuests() { + return subQuests; + } + + public class SubQuestConfigData { + private int subId; + private int mainId; + + private LogicType acceptCondComb; + private QuestCondition[] acceptCond; + + private LogicType finishCondComb; + private QuestCondition[] finishCond; + + private LogicType failCondComb; + private QuestCondition[] failCond; + + public int getSubId() { + return subId; + } + + public int getMainId() { + return mainId; + } + + public LogicType getAcceptCondComb() { + return acceptCondComb; + } + + public QuestCondition[] getAcceptCond() { + return acceptCond; + } + + public LogicType getFinishCondComb() { + return finishCondComb; + } + + public QuestCondition[] getFinishCond() { + return finishCond; + } + + public LogicType getFailCondComb() { + return failCondComb; + } + + public QuestCondition[] getFailCond() { + return failCond; + } + } + + public class QuestCondition { + private QuestCondType type; + private int[] param; + + public QuestCondType getType() { + return type; + } + + public int[] getParam() { + return param; + } + } +} diff --git a/src/main/java/emu/grasscutter/database/DatabaseHelper.java b/src/main/java/emu/grasscutter/database/DatabaseHelper.java index 8f1de0bb9..fe931bdc3 100644 --- a/src/main/java/emu/grasscutter/database/DatabaseHelper.java +++ b/src/main/java/emu/grasscutter/database/DatabaseHelper.java @@ -15,6 +15,7 @@ import emu.grasscutter.game.gacha.GachaRecord; import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.mail.Mail; import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.GameMainQuest; import static com.mongodb.client.model.Filters.eq; @@ -111,6 +112,8 @@ public final class DatabaseHelper { DatabaseManager.getDatabase().getCollection("gachas").deleteMany(eq("ownerId", target.getPlayerUid())); // Delete GameItem.class data DatabaseManager.getDatabase().getCollection("items").deleteMany(eq("ownerId", target.getPlayerUid())); + // Delete GameMainQuest.class data + DatabaseManager.getDatabase().getCollection("quests").deleteMany(eq("ownerUid", target.getPlayerUid())); // Delete friendships. // Here, we need to make sure to not only delete the deleted account's friendships, @@ -260,4 +263,16 @@ public final class DatabaseHelper { DeleteResult result = DatabaseManager.getDatastore().delete(mail); return result.wasAcknowledged(); } + + public static List getAllQuests(Player player) { + return DatabaseManager.getDatastore().find(GameMainQuest.class).filter(Filters.eq("ownerUid", player.getUid())).stream().toList(); + } + + public static void saveQuest(GameMainQuest quest) { + DatabaseManager.getDatastore().save(quest); + } + + public static boolean deleteQuest(GameMainQuest quest) { + return DatabaseManager.getDatastore().delete(quest).wasAcknowledged(); + } } diff --git a/src/main/java/emu/grasscutter/database/DatabaseManager.java b/src/main/java/emu/grasscutter/database/DatabaseManager.java index 90ff17238..12bb444b8 100644 --- a/src/main/java/emu/grasscutter/database/DatabaseManager.java +++ b/src/main/java/emu/grasscutter/database/DatabaseManager.java @@ -20,6 +20,8 @@ import emu.grasscutter.game.gacha.GachaRecord; import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.mail.Mail; import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.game.quest.GameQuest; public final class DatabaseManager { @@ -30,7 +32,8 @@ public final class DatabaseManager { private static Datastore dispatchDatastore; private static final Class[] mappedClasses = new Class[] { - DatabaseCounter.class, Account.class, Player.class, Avatar.class, GameItem.class, Friendship.class, GachaRecord.class, Mail.class + DatabaseCounter.class, Account.class, Player.class, Avatar.class, GameItem.class, Friendship.class, + GachaRecord.class, Mail.class, GameMainQuest.class }; public static Datastore getDatastore() { diff --git a/src/main/java/emu/grasscutter/game/player/Player.java b/src/main/java/emu/grasscutter/game/player/Player.java index 477f974ea..e8c4cd61b 100644 --- a/src/main/java/emu/grasscutter/game/player/Player.java +++ b/src/main/java/emu/grasscutter/game/player/Player.java @@ -29,6 +29,9 @@ import emu.grasscutter.game.props.ActionReason; import emu.grasscutter.game.props.EntityType; import emu.grasscutter.game.props.PlayerProperty; import emu.grasscutter.game.props.SceneType; +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestManager; import emu.grasscutter.game.shop.ShopLimit; import emu.grasscutter.game.managers.MapMarkManager.*; import emu.grasscutter.game.tower.TowerManager; @@ -91,6 +94,7 @@ public class Player { @Transient private MailHandler mailHandler; @Transient private MessageHandler messageHandler; @Transient private AbilityManager abilityManager; + @Transient private QuestManager questManager; @Transient private SotSManager sotsManager; @@ -145,6 +149,7 @@ public class Player { this.mailHandler = new MailHandler(this); this.towerManager = new TowerManager(this); this.abilityManager = new AbilityManager(this); + this.setQuestManager(new QuestManager(this)); this.pos = new Position(); this.rotation = new Position(); this.properties = new HashMap<>(); @@ -409,6 +414,14 @@ public class Player { return towerManager; } + public QuestManager getQuestManager() { + return questManager; + } + + public void setQuestManager(QuestManager questManager) { + this.questManager = questManager; + } + public PlayerGachaInfo getGachaInfo() { return gachaInfo; } @@ -883,9 +896,7 @@ public class Player { } public void sendPacket(BasePacket packet) { - if (this.hasSentAvatarDataNotify) { - this.getSession().send(packet); - } + this.getSession().send(packet); } public OnlinePlayerInfo getOnlinePlayerInfo() { @@ -1118,7 +1129,23 @@ public class Player { this.getFriendsList().loadFromDatabase(); this.getMailHandler().loadFromDatabase(); + this.getQuestManager().loadFromDatabase(); + + // Quest - Commented out because a problem is caused if you log out while this quest is active + /* + if (getQuestManager().getMainQuestById(351) == null) { + GameQuest quest = getQuestManager().addQuest(35104); + if (quest != null) { + quest.finish(); + } + getQuestManager().addQuest(35101); + + this.setSceneId(3); + this.getPos().set(GameConstants.START_POSITION); + } + */ + // Create world World world = new World(this); world.addPlayer(this); @@ -1138,7 +1165,10 @@ public class Player { session.send(new PacketStoreWeightLimitNotify()); session.send(new PacketPlayerStoreNotify(this)); session.send(new PacketAvatarDataNotify(this)); - + session.send(new PacketFinishedParentQuestNotify(this)); + session.send(new PacketQuestListNotify(this)); + session.send(new PacketServerCondMeetQuestListUpdateNotify(this)); + getTodayMoonCard(); // The timer works at 0:0, some users log in after that, use this method to check if they have received a reward today or not. If not, send the reward. session.send(new PacketPlayerEnterSceneNotify(this)); // Enter game world diff --git a/src/main/java/emu/grasscutter/game/quest/GameMainQuest.java b/src/main/java/emu/grasscutter/game/quest/GameMainQuest.java new file mode 100644 index 000000000..1ceda3356 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/GameMainQuest.java @@ -0,0 +1,124 @@ +package emu.grasscutter.game.quest; + +import java.util.HashMap; +import java.util.Map; + +import org.bson.types.ObjectId; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Id; +import dev.morphia.annotations.Indexed; +import dev.morphia.annotations.Transient; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.custom.QuestConfig; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.enums.ParentQuestState; +import emu.grasscutter.game.quest.enums.QuestState; +import emu.grasscutter.net.proto.ChildQuestOuterClass.ChildQuest; +import emu.grasscutter.net.proto.ParentQuestOuterClass.ParentQuest; +import emu.grasscutter.net.proto.QuestOuterClass.Quest; +import emu.grasscutter.server.packet.send.PacketFinishedParentQuestUpdateNotify; +import emu.grasscutter.server.packet.send.PacketQuestListUpdateNotify; +import emu.grasscutter.server.packet.send.PacketQuestProgressUpdateNotify; +import emu.grasscutter.utils.Utils; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + +@Entity(value = "quests", useDiscriminator = false) +public class GameMainQuest { + @Id private ObjectId id; + + @Indexed private int ownerUid; + @Transient private Player owner; + + private Map childQuests; + + private int parentQuestId; + private int[] questVars; + private ParentQuestState state; + private boolean isFinished; + + @Deprecated // Morphia only. Do not use. + public GameMainQuest() {} + + public GameMainQuest(Player player, int parentQuestId) { + this.owner = player; + this.ownerUid = player.getUid(); + this.parentQuestId = parentQuestId; + this.childQuests = new HashMap<>(); + this.questVars = new int[5]; + this.state = ParentQuestState.PARENT_QUEST_STATE_NONE; + } + + public int getParentQuestId() { + return parentQuestId; + } + + public int getOwnerUid() { + return ownerUid; + } + + public Player getOwner() { + return owner; + } + + public void setOwner(Player player) { + if (player.getUid() != this.getOwnerUid()) return; + this.owner = player; + } + + public Map getChildQuests() { + return childQuests; + } + + public GameQuest getChildQuestById(int id) { + return this.getChildQuests().get(id); + } + + public int[] getQuestVars() { + return questVars; + } + + public ParentQuestState getState() { + return state; + } + + public boolean isFinished() { + return isFinished; + } + + public void finish() { + this.isFinished = true; + this.state = ParentQuestState.PARENT_QUEST_STATE_FINISHED; + this.getOwner().getSession().send(new PacketFinishedParentQuestUpdateNotify(this)); + } + + public void save() { + DatabaseHelper.saveQuest(this); + } + + public ParentQuest toProto() { + ParentQuest.Builder proto = ParentQuest.newBuilder() + .setParentQuestId(getParentQuestId()) + .setIsFinished(isFinished()) + .setParentQuestState(getState().getValue()); + + for (GameQuest quest : this.getChildQuests().values()) { + ChildQuest childQuest = ChildQuest.newBuilder() + .setQuestId(quest.getQuestId()) + .setState(quest.getState().getValue()) + .build(); + + proto.addChildQuestList(childQuest); + } + + if (getQuestVars() != null) { + for (int i : getQuestVars()) { + proto.addQuestVar(i); + } + } + + return proto.build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/GameQuest.java b/src/main/java/emu/grasscutter/game/quest/GameQuest.java new file mode 100644 index 000000000..53599830c --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/GameQuest.java @@ -0,0 +1,188 @@ +package emu.grasscutter.game.quest; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Transient; +import emu.grasscutter.data.custom.QuestConfig; +import emu.grasscutter.data.custom.QuestConfigData.SubQuestConfigData; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.enums.QuestState; +import emu.grasscutter.net.proto.QuestOuterClass.Quest; +import emu.grasscutter.server.packet.send.PacketQuestProgressUpdateNotify; +import emu.grasscutter.utils.Utils; + +@Entity +public class GameQuest { + @Transient private GameMainQuest mainQuest; + @Transient private QuestConfig config; + + private int questId; + private int mainQuestId; + private QuestState state; + + private int startTime; + private int acceptTime; + private int finishTime; + + private int[] finishProgressList; + private int[] failProgressList; + + @Deprecated // Morphia only. Do not use. + public GameQuest() {} + + public GameQuest(GameMainQuest mainQuest, QuestConfig config) { + this.mainQuest = mainQuest; + this.questId = config.getId(); + this.mainQuestId = config.getMainQuest().getId(); + this.config = config; + this.acceptTime = Utils.getCurrentSeconds(); + this.startTime = this.acceptTime; + this.state = QuestState.QUEST_STATE_UNFINISHED; + + if (config.getSubQuest().getFinishCond() != null) { + this.finishProgressList = new int[config.getSubQuest().getFinishCond().length]; + } + + if (config.getSubQuest().getFailCond() != null) { + this.failProgressList = new int[config.getSubQuest().getFailCond().length]; + } + + this.mainQuest.getChildQuests().put(this.questId, this); + } + + public GameMainQuest getMainQuest() { + return mainQuest; + } + + public void setMainQuest(GameMainQuest mainQuest) { + this.mainQuest = mainQuest; + } + + public Player getOwner() { + return getMainQuest().getOwner(); + } + + public int getQuestId() { + return questId; + } + + public int getMainQuestId() { + return mainQuestId; + } + + public QuestConfig getConfig() { + return config; + } + + public void setConfig(QuestConfig config) { + if (this.getQuestId() != config.getId()) return; + this.config = config; + } + + public QuestState getState() { + return state; + } + + public void setState(QuestState state) { + this.state = state; + } + + public int getStartTime() { + return startTime; + } + + public void setStartTime(int startTime) { + this.startTime = startTime; + } + + public int getAcceptTime() { + return acceptTime; + } + + public void setAcceptTime(int acceptTime) { + this.acceptTime = acceptTime; + } + + public int getFinishTime() { + return finishTime; + } + + public void setFinishTime(int finishTime) { + this.finishTime = finishTime; + } + + public int[] getFinishProgressList() { + return finishProgressList; + } + + public void setFinishProgress(int index, int value) { + finishProgressList[index] = value; + } + + public int[] getFailProgressList() { + return failProgressList; + } + + public void setFailProgress(int index, int value) { + failProgressList[index] = value; + } + + public void finish() { + this.state = QuestState.QUEST_STATE_FINISHED; + this.finishTime = Utils.getCurrentSeconds(); + + if (this.getFinishProgressList() != null) { + for (int i = 0 ; i < getFinishProgressList().length; i++) { + getFinishProgressList()[i] = 1; + } + } + + this.getOwner().getSession().send(new PacketQuestProgressUpdateNotify(this)); + + // Finish main quest if all child quests are done + this.tryFinishMainQuest(); + this.save(); + } + + public boolean tryFinishMainQuest() { + try { + SubQuestConfigData subQuestData = getConfig().getMainQuest().getSubQuests()[getConfig().getMainQuest().getSubQuests().length - 1]; + + if (subQuestData.getSubId() == this.getQuestId()) { + getMainQuest().finish(); + return true; + } + } catch (Exception e) { + + } + + return false; + } + + public void save() { + getMainQuest().save(); + } + + public Quest toProto() { + Quest.Builder proto = Quest.newBuilder() + .setQuestId(this.getQuestId()) + .setState(this.getState().getValue()) + .setParentQuestId(this.getMainQuestId()) + .setStartTime(this.getStartTime()) + .setStartGameTime(438) + .setAcceptTime(this.getAcceptTime()); + + if (this.getFinishProgressList() != null) { + for (int i : this.getFinishProgressList()) { + proto.addFinishProgressList(i); + } + } + + if (this.getFailProgressList() != null) { + for (int i : this.getFailProgressList()) { + proto.addFailProgressList(i); + } + } + + return proto.build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/QuestManager.java b/src/main/java/emu/grasscutter/game/quest/QuestManager.java new file mode 100644 index 000000000..e1c26704c --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/QuestManager.java @@ -0,0 +1,119 @@ +package emu.grasscutter.game.quest; + +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Function; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.custom.QuestConfig; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.enums.QuestState; +import emu.grasscutter.server.packet.send.PacketFinishedParentQuestUpdateNotify; +import emu.grasscutter.server.packet.send.PacketQuestListUpdateNotify; +import emu.grasscutter.server.packet.send.PacketServerCondMeetQuestListUpdateNotify; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + +public class QuestManager { + private final Player player; + private final Int2ObjectMap quests; + + public QuestManager(Player player) { + this.player = player; + this.quests = new Int2ObjectOpenHashMap<>(); + } + + public Player getPlayer() { + return player; + } + + public Int2ObjectMap getQuests() { + return quests; + } + + public GameMainQuest getMainQuestById(int mainQuestId) { + return getQuests().get(mainQuestId); + } + + public GameQuest getQuestById(int questId) { + QuestConfig questConfig = GameData.getQuestConfigs().get(questId); + if (questConfig == null) { + return null; + } + + GameMainQuest mainQuest = getQuests().get(questConfig.getMainQuest().getId()); + + if (mainQuest == null) { + return null; + } + + return mainQuest.getChildQuests().get(questId); + } + + public void forEachQuest(Consumer callback) { + for (GameMainQuest mainQuest : getQuests().values()) { + for (GameQuest quest : mainQuest.getChildQuests().values()) { + callback.accept(quest); + } + } + } + + public GameMainQuest addMainQuest(QuestConfig questConfig) { + GameMainQuest mainQuest = new GameMainQuest(getPlayer(), questConfig.getMainQuest().getId()); + getQuests().put(mainQuest.getParentQuestId(), mainQuest); + + getPlayer().sendPacket(new PacketFinishedParentQuestUpdateNotify(mainQuest)); + + return mainQuest; + } + + public GameQuest addQuest(int questId) { + QuestConfig questConfig = GameData.getQuestConfigs().get(questId); + if (questConfig == null) { + return null; + } + + // Main quest + GameMainQuest mainQuest = this.getMainQuestById(questConfig.getMainQuest().getId()); + + // Create main quest if it doesnt exist + if (mainQuest == null) { + mainQuest = addMainQuest(questConfig); + } + + // Sub quest + GameQuest quest = mainQuest.getChildQuestById(questId); + + if (quest != null) { + return null; + } + + // Create + quest = new GameQuest(mainQuest, questConfig); + + // Save main quest + mainQuest.save(); + + // Send packet + getPlayer().sendPacket(new PacketServerCondMeetQuestListUpdateNotify(quest)); + getPlayer().sendPacket(new PacketQuestListUpdateNotify(quest)); + + return quest; + } + + public void loadFromDatabase() { + List quests = DatabaseHelper.getAllQuests(getPlayer()); + + for (GameMainQuest mainQuest : quests) { + mainQuest.setOwner(this.getPlayer()); + + for (GameQuest quest : mainQuest.getChildQuests().values()) { + quest.setMainQuest(mainQuest); + quest.setConfig(GameData.getQuestConfigs().get(quest.getQuestId())); + } + + this.getQuests().put(mainQuest.getParentQuestId(), mainQuest); + } + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/LogicType.java b/src/main/java/emu/grasscutter/game/quest/enums/LogicType.java new file mode 100644 index 000000000..608ec9c28 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/enums/LogicType.java @@ -0,0 +1,23 @@ +package emu.grasscutter.game.quest.enums; + +public enum LogicType { + LOGIC_NONE (0), + LOGIC_AND (1), + LOGIC_OR (2), + LOGIC_NOT (3), + LOGIC_A_AND_ETCOR (4), + LOGIC_A_AND_B_AND_ETCOR (5), + LOGIC_A_OR_ETCAND (6), + LOGIC_A_OR_B_OR_ETCAND (7), + LOGIC_A_AND_B_OR_ETCAND (8); + + private final int value; + + LogicType(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/ParentQuestState.java b/src/main/java/emu/grasscutter/game/quest/enums/ParentQuestState.java new file mode 100644 index 000000000..6c7805f8d --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/enums/ParentQuestState.java @@ -0,0 +1,18 @@ +package emu.grasscutter.game.quest.enums; + +public enum ParentQuestState { + PARENT_QUEST_STATE_NONE (0), + PARENT_QUEST_STATE_FINISHED (1), + PARENT_QUEST_STATE_FAILED (2), + PARENT_QUEST_STATE_CANCELED (3); + + private final int value; + + ParentQuestState(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestCondType.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestCondType.java new file mode 100644 index 000000000..42db14f2d --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/enums/QuestCondType.java @@ -0,0 +1,92 @@ +package emu.grasscutter.game.quest.enums; + +public enum QuestCondType { + QUEST_COND_NONE (0), + QUEST_COND_STATE_EQUAL (1), + QUEST_COND_STATE_NOT_EQUAL (2), + QUEST_COND_PACK_HAVE_ITEM (3), + QUEST_COND_AVATAR_ELEMENT_EQUAL (4), + QUEST_COND_AVATAR_ELEMENT_NOT_EQUAL (5), + QUEST_COND_AVATAR_CAN_CHANGE_ELEMENT (6), + QUEST_COND_CITY_LEVEL_EQUAL_GREATER (7), + QUEST_COND_ITEM_NUM_LESS_THAN (8), + QUEST_COND_DAILY_TASK_START (9), + QUEST_COND_OPEN_STATE_EQUAL (10), + QUEST_COND_DAILY_TASK_OPEN (11), + QUEST_COND_DAILY_TASK_REWARD_CAN_GET (12), + QUEST_COND_DAILY_TASK_REWARD_RECEIVED (13), + QUEST_COND_PLAYER_LEVEL_REWARD_CAN_GET (14), + QUEST_COND_EXPLORATION_REWARD_CAN_GET (15), + QUEST_COND_IS_WORLD_OWNER (16), + QUEST_COND_PLAYER_LEVEL_EQUAL_GREATER (17), + QUEST_COND_SCENE_AREA_UNLOCKED (18), + QUEST_COND_ITEM_GIVING_ACTIVED (19), + QUEST_COND_ITEM_GIVING_FINISHED (20), + QUEST_COND_IS_DAYTIME (21), + QUEST_COND_CURRENT_AVATAR (22), + QUEST_COND_CURRENT_AREA (23), + QUEST_COND_QUEST_VAR_EQUAL (24), + QUEST_COND_QUEST_VAR_GREATER (25), + QUEST_COND_QUEST_VAR_LESS (26), + QUEST_COND_FORGE_HAVE_FINISH (27), + QUEST_COND_DAILY_TASK_IN_PROGRESS (28), + QUEST_COND_DAILY_TASK_FINISHED (29), + QUEST_COND_ACTIVITY_COND (30), + QUEST_COND_ACTIVITY_OPEN (31), + QUEST_COND_DAILY_TASK_VAR_GT (32), + QUEST_COND_DAILY_TASK_VAR_EQ (33), + QUEST_COND_DAILY_TASK_VAR_LT (34), + QUEST_COND_BARGAIN_ITEM_GT (35), + QUEST_COND_BARGAIN_ITEM_EQ (36), + QUEST_COND_BARGAIN_ITEM_LT (37), + QUEST_COND_COMPLETE_TALK (38), + QUEST_COND_NOT_HAVE_BLOSSOM_TALK (39), + QUEST_COND_IS_CUR_BLOSSOM_TALK (40), + QUEST_COND_QUEST_NOT_RECEIVE (41), + QUEST_COND_QUEST_SERVER_COND_VALID (42), + QUEST_COND_ACTIVITY_CLIENT_COND (43), + QUEST_COND_QUEST_GLOBAL_VAR_EQUAL (44), + QUEST_COND_QUEST_GLOBAL_VAR_GREATER (45), + QUEST_COND_QUEST_GLOBAL_VAR_LESS (46), + QUEST_COND_PERSONAL_LINE_UNLOCK (47), + QUEST_COND_CITY_REPUTATION_REQUEST (48), + QUEST_COND_MAIN_COOP_START (49), + QUEST_COND_MAIN_COOP_ENTER_SAVE_POINT (50), + QUEST_COND_CITY_REPUTATION_LEVEL (51), + QUEST_COND_CITY_REPUTATION_UNLOCK (52), + QUEST_COND_LUA_NOTIFY (53), + QUEST_COND_CUR_CLIMATE (54), + QUEST_COND_ACTIVITY_END (55), + QUEST_COND_COOP_POINT_RUNNING (56), + QUEST_COND_GADGET_TALK_STATE_EQUAL (57), + QUEST_COND_AVATAR_FETTER_GT (58), + QUEST_COND_AVATAR_FETTER_EQ (59), + QUEST_COND_AVATAR_FETTER_LT (60), + QUEST_COND_NEW_HOMEWORLD_MOUDLE_UNLOCK (61), + QUEST_COND_NEW_HOMEWORLD_LEVEL_REWARD (62), + QUEST_COND_NEW_HOMEWORLD_MAKE_FINISH (63), + QUEST_COND_HOMEWORLD_NPC_EVENT (64), + QUEST_COND_TIME_VAR_GT_EQ (65), + QUEST_COND_TIME_VAR_PASS_DAY (66), + QUEST_COND_HOMEWORLD_NPC_NEW_TALK (67), + QUEST_COND_PLAYER_CHOOSE_MALE (68), + QUEST_COND_HISTORY_GOT_ANY_ITEM (69), + QUEST_COND_LEARNED_RECIPE (70), + QUEST_COND_LUNARITE_REGION_UNLOCKED (71), + QUEST_COND_LUNARITE_HAS_REGION_HINT_COUNT (72), + QUEST_COND_LUNARITE_COLLECT_FINISH (73), + QUEST_COND_LUNARITE_MARK_ALL_FINISH (74), + QUEST_COND_NEW_HOMEWORLD_SHOP_ITEM (75), + QUEST_COND_SCENE_POINT_UNLOCK (76), + QUEST_COND_SCENE_LEVEL_TAG_EQ (77); + + private final int value; + + QuestCondType(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestExecType.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestExecType.java new file mode 100644 index 000000000..4f3c2557c --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/enums/QuestExecType.java @@ -0,0 +1,82 @@ +package emu.grasscutter.game.quest.enums; + +public enum QuestExecType { + QUEST_EXEC_NONE (0), + QUEST_EXEC_DEL_PACK_ITEM (1), + QUEST_EXEC_UNLOCK_POINT (2), + QUEST_EXEC_UNLOCK_AREA (3), + QUEST_EXEC_UNLOCK_FORCE (4), + QUEST_EXEC_LOCK_FORCE (5), + QUEST_EXEC_CHANGE_AVATAR_ELEMET (6), + QUEST_EXEC_REFRESH_GROUP_MONSTER (7), + QUEST_EXEC_SET_IS_FLYABLE (8), + QUEST_EXEC_SET_IS_WEATHER_LOCKED (9), + QUEST_EXEC_SET_IS_GAME_TIME_LOCKED (10), + QUEST_EXEC_SET_IS_TRANSFERABLE (11), + QUEST_EXEC_GRANT_TRIAL_AVATAR (12), + QUEST_EXEC_OPEN_BORED (13), + QUEST_EXEC_ROLLBACK_QUEST (14), + QUEST_EXEC_NOTIFY_GROUP_LUA (15), + QUEST_EXEC_SET_OPEN_STATE (16), + QUEST_EXEC_LOCK_POINT (17), + QUEST_EXEC_DEL_PACK_ITEM_BATCH (18), + QUEST_EXEC_REFRESH_GROUP_SUITE (19), + QUEST_EXEC_REMOVE_TRIAL_AVATAR (20), + QUEST_EXEC_SET_GAME_TIME (21), + QUEST_EXEC_SET_WEATHER_GADGET (22), + QUEST_EXEC_ADD_QUEST_PROGRESS (23), + QUEST_EXEC_NOTIFY_DAILY_TASK (24), + QUEST_EXEC_CREATE_PATTERN_GROUP (25), + QUEST_EXEC_REMOVE_PATTERN_GROUP (26), + QUEST_EXEC_REFRESH_GROUP_SUITE_RANDOM (27), + QUEST_EXEC_ACTIVE_ITEM_GIVING (28), + QUEST_EXEC_DEL_ALL_SPECIFIC_PACK_ITEM (29), + QUEST_EXEC_ROLLBACK_PARENT_QUEST (30), + QUEST_EXEC_LOCK_AVATAR_TEAM (31), + QUEST_EXEC_UNLOCK_AVATAR_TEAM (32), + QUEST_EXEC_UPDATE_PARENT_QUEST_REWARD_INDEX (33), + QUEST_EXEC_SET_DAILY_TASK_VAR (34), + QUEST_EXEC_INC_DAILY_TASK_VAR (35), + QUEST_EXEC_DEC_DAILY_TASK_VAR (36), + QUEST_EXEC_ACTIVE_ACTIVITY_COND_STATE (37), + QUEST_EXEC_INACTIVE_ACTIVITY_COND_STATE (38), + QUEST_EXEC_ADD_CUR_AVATAR_ENERGY (39), + QUEST_EXEC_START_BARGAIN (41), + QUEST_EXEC_STOP_BARGAIN (42), + QUEST_EXEC_SET_QUEST_GLOBAL_VAR (43), + QUEST_EXEC_INC_QUEST_GLOBAL_VAR (44), + QUEST_EXEC_DEC_QUEST_GLOBAL_VAR (45), + QUEST_EXEC_REGISTER_DYNAMIC_GROUP (46), + QUEST_EXEC_UNREGISTER_DYNAMIC_GROUP (47), + QUEST_EXEC_SET_QUEST_VAR (48), + QUEST_EXEC_INC_QUEST_VAR (49), + QUEST_EXEC_DEC_QUEST_VAR (50), + QUEST_EXEC_RANDOM_QUEST_VAR (51), + QUEST_EXEC_ACTIVATE_SCANNING_PIC (52), + QUEST_EXEC_RELOAD_SCENE_TAG (53), + QUEST_EXEC_REGISTER_DYNAMIC_GROUP_ONLY (54), + QUEST_EXEC_CHANGE_SKILL_DEPOT (55), + QUEST_EXEC_ADD_SCENE_TAG (56), + QUEST_EXEC_DEL_SCENE_TAG (57), + QUEST_EXEC_INIT_TIME_VAR (58), + QUEST_EXEC_CLEAR_TIME_VAR (59), + QUEST_EXEC_MODIFY_CLIMATE_AREA (60), + QUEST_EXEC_GRANT_TRIAL_AVATAR_AND_LOCK_TEAM (61), + QUEST_EXEC_CHANGE_MAP_AREA_STATE (62), + QUEST_EXEC_DEACTIVE_ITEM_GIVING (63), + QUEST_EXEC_CHANGE_SCENE_LEVEL_TAG (64), + QUEST_EXEC_UNLOCK_PLAYER_WORLD_SCENE (65), + QUEST_EXEC_LOCK_PLAYER_WORLD_SCENE (66), + QUEST_EXEC_FAIL_MAINCOOP (67), + QUEST_EXEC_MODIFY_WEATHER_AREA (68); + + private final int value; + + QuestExecType(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestGuideType.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestGuideType.java new file mode 100644 index 000000000..45915c6b7 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/enums/QuestGuideType.java @@ -0,0 +1,17 @@ +package emu.grasscutter.game.quest.enums; + +public enum QuestGuideType { + QUEST_GUIDE_NONE (0), + QUEST_GUIDE_LOCATION (1), + QUEST_GUIDE_NPC (2); + + private final int value; + + QuestGuideType(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestShowType.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestShowType.java new file mode 100644 index 000000000..014c1ee06 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/enums/QuestShowType.java @@ -0,0 +1,16 @@ +package emu.grasscutter.game.quest.enums; + +public enum QuestShowType { + QUEST_SHOW (0), + QUEST_HIDDEN (1); + + private final int value; + + QuestShowType(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestState.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestState.java new file mode 100644 index 000000000..d258a2582 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/enums/QuestState.java @@ -0,0 +1,19 @@ +package emu.grasscutter.game.quest.enums; + +public enum QuestState { + QUEST_STATE_NONE (0), + QUEST_STATE_UNSTARTED (1), + QUEST_STATE_UNFINISHED (2), + QUEST_STATE_FINISHED (3), + QUEST_STATE_FAILED (4); + + private final int value; + + QuestState(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestType.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestType.java new file mode 100644 index 000000000..fbbac2ae0 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/enums/QuestType.java @@ -0,0 +1,22 @@ +package emu.grasscutter.game.quest.enums; + +public enum QuestType { + AQ (0), + FQ (1), + LQ (2), + EQ (3), + DQ (4), + IQ (5), + VQ (6), + WQ (7); + + private final int value; + + QuestType(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/ShowQuestGuideType.java b/src/main/java/emu/grasscutter/game/quest/enums/ShowQuestGuideType.java new file mode 100644 index 000000000..d4e985592 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/enums/ShowQuestGuideType.java @@ -0,0 +1,17 @@ +package emu.grasscutter.game.quest.enums; + +public enum ShowQuestGuideType { + QUEST_GUIDE_ITEM_ENABLE (0), + QUEST_GUIDE_ITEM_DISABLE (1), + QUEST_GUIDE_ITEM_MOVE_HIDE (2); + + private final int value; + + ShowQuestGuideType(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketFinishedParentQuestNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketFinishedParentQuestNotify.java new file mode 100644 index 000000000..7d64da48f --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketFinishedParentQuestNotify.java @@ -0,0 +1,22 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.FinishedParentQuestNotifyOuterClass.FinishedParentQuestNotify; + +public class PacketFinishedParentQuestNotify extends BasePacket { + + public PacketFinishedParentQuestNotify(Player player) { + super(PacketOpcodes.FinishedParentQuestNotify, true); + + FinishedParentQuestNotify.Builder proto = FinishedParentQuestNotify.newBuilder(); + + for (GameMainQuest mainQuest : player.getQuestManager().getQuests().values()) { + proto.addParentQuestList(mainQuest.toProto()); + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketFinishedParentQuestUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketFinishedParentQuestUpdateNotify.java new file mode 100644 index 000000000..68eab7222 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketFinishedParentQuestUpdateNotify.java @@ -0,0 +1,19 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.FinishedParentQuestUpdateNotifyOuterClass.FinishedParentQuestUpdateNotify; + +public class PacketFinishedParentQuestUpdateNotify extends BasePacket { + + public PacketFinishedParentQuestUpdateNotify(GameMainQuest quest) { + super(PacketOpcodes.FinishedParentQuestUpdateNotify); + + FinishedParentQuestUpdateNotify proto = FinishedParentQuestUpdateNotify.newBuilder() + .addParentQuestList(quest.toProto()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketQuestListNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketQuestListNotify.java new file mode 100644 index 000000000..ccf0d765a --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketQuestListNotify.java @@ -0,0 +1,23 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.game.quest.QuestManager; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.QuestListNotifyOuterClass.QuestListNotify; + +public class PacketQuestListNotify extends BasePacket { + + public PacketQuestListNotify(Player player) { + super(PacketOpcodes.QuestListNotify, true); + + QuestListNotify.Builder proto = QuestListNotify.newBuilder(); + + player.getQuestManager().forEachQuest(quest -> { + proto.addQuestList(quest.toProto()); + }); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketQuestListUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketQuestListUpdateNotify.java new file mode 100644 index 000000000..adc0767a8 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketQuestListUpdateNotify.java @@ -0,0 +1,20 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.QuestListUpdateNotifyOuterClass.QuestListUpdateNotify; + +public class PacketQuestListUpdateNotify extends BasePacket { + + public PacketQuestListUpdateNotify(GameQuest quest) { + super(PacketOpcodes.QuestListUpdateNotify); + + QuestListUpdateNotify proto = QuestListUpdateNotify.newBuilder() + .addQuestList(quest.toProto()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketQuestProgressUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketQuestProgressUpdateNotify.java new file mode 100644 index 000000000..76ee56316 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketQuestProgressUpdateNotify.java @@ -0,0 +1,30 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.QuestProgressUpdateNotifyOuterClass.QuestProgressUpdateNotify; + +public class PacketQuestProgressUpdateNotify extends BasePacket { + + public PacketQuestProgressUpdateNotify(GameQuest quest) { + super(PacketOpcodes.QuestProgressUpdateNotify); + + QuestProgressUpdateNotify.Builder proto = QuestProgressUpdateNotify.newBuilder().setQuestId(quest.getQuestId()); + + if (quest.getFinishProgressList() != null) { + for (int i : quest.getFinishProgressList()) { + proto.addFinishProgressList(i); + } + } + + if (quest.getFailProgressList() != null) { + for (int i : quest.getFailProgressList()) { + proto.addFailProgressList(i); + } + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketServerCondMeetQuestListUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketServerCondMeetQuestListUpdateNotify.java new file mode 100644 index 000000000..b2ea3d577 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketServerCondMeetQuestListUpdateNotify.java @@ -0,0 +1,37 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.custom.QuestConfig; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ServerCondMeetQuestListUpdateNotifyOuterClass.ServerCondMeetQuestListUpdateNotify; + +public class PacketServerCondMeetQuestListUpdateNotify extends BasePacket { + + public PacketServerCondMeetQuestListUpdateNotify(Player player) { + super(PacketOpcodes.ServerCondMeetQuestListUpdateNotify); + + ServerCondMeetQuestListUpdateNotify.Builder proto = ServerCondMeetQuestListUpdateNotify.newBuilder(); + + player.getQuestManager().forEachQuest(quest -> { + if (quest.getState().getValue() <= 2) { + proto.addAddQuestIdList(quest.getQuestId()); + } + }); + + this.setData(proto); + } + + public PacketServerCondMeetQuestListUpdateNotify(GameQuest quest) { + super(PacketOpcodes.ServerCondMeetQuestListUpdateNotify); + + ServerCondMeetQuestListUpdateNotify proto = ServerCondMeetQuestListUpdateNotify.newBuilder() + .addAddQuestIdList(quest.getQuestId()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/resources/languages/en-US.json b/src/main/resources/languages/en-US.json index 893f490af..107a12d71 100644 --- a/src/main/resources/languages/en-US.json +++ b/src/main/resources/languages/en-US.json @@ -210,6 +210,14 @@ "success": "Coordinates: %s, %s, %s\nScene id: %s", "description": "Get coordinates." }, + "quest": { + "description": "Add or finish quests", + "usage": "quest [quest id]", + "added": "Quest %s added", + "finished": "Finished quest %s", + "not_found": "Quest not found", + "invalid_id": "Invalid quest id" + }, "reload": { "reload_start": "Reloading config.", "reload_done": "Reload complete.", From dfd8fcb250a5c456dc79affbeab1e3442300788a Mon Sep 17 00:00:00 2001 From: Melledy <52122272+Melledy@users.noreply.github.com> Date: Wed, 11 May 2022 04:01:38 -0700 Subject: [PATCH 2/6] Fix build error from merge --- src/main/java/emu/grasscutter/data/ResourceLoader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/emu/grasscutter/data/ResourceLoader.java b/src/main/java/emu/grasscutter/data/ResourceLoader.java index 92fda7bb1..5c2ac1ee6 100644 --- a/src/main/java/emu/grasscutter/data/ResourceLoader.java +++ b/src/main/java/emu/grasscutter/data/ResourceLoader.java @@ -400,7 +400,7 @@ public class ResourceLoader { } private static void loadQuests() { - File folder = new File(Grasscutter.getConfig().RESOURCE_FOLDER + "BinOutput/Quest/"); + File folder = new File(RESOURCE("BinOutput/Quest/")); if (!folder.exists()) { return; From 7befebe37fcbe26cbd09bfeea51879bdf8e8daba Mon Sep 17 00:00:00 2001 From: Melledy <52122272+Melledy@users.noreply.github.com> Date: Wed, 11 May 2022 12:47:16 -0700 Subject: [PATCH 3/6] Add quest ids to handbook --- src/main/java/emu/grasscutter/tools/Tools.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/emu/grasscutter/tools/Tools.java b/src/main/java/emu/grasscutter/tools/Tools.java index 4a5af6e49..8b28c027e 100644 --- a/src/main/java/emu/grasscutter/tools/Tools.java +++ b/src/main/java/emu/grasscutter/tools/Tools.java @@ -19,6 +19,7 @@ import emu.grasscutter.command.Command; import emu.grasscutter.command.CommandMap; import emu.grasscutter.data.GameData; import emu.grasscutter.data.ResourceLoader; +import emu.grasscutter.data.custom.QuestConfig; import emu.grasscutter.data.def.AvatarData; import emu.grasscutter.data.def.ItemData; import emu.grasscutter.data.def.MonsterData; @@ -88,7 +89,7 @@ public final class Tools { final class ToolsWithLanguageOption { @SuppressWarnings("deprecation") public static void createGmHandbook(String language) throws Exception { - ResourceLoader.loadResources(); + ResourceLoader.loadAll(); Map map; try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream(Utils.toFilePath(RESOURCE("TextMap/TextMap"+language+".json"))), StandardCharsets.UTF_8)) { @@ -148,6 +149,15 @@ final class ToolsWithLanguageOption { writer.println(data.getId() + " : " + data.getScriptData()); } + writer.println("// Quests"); + list = new ArrayList<>(GameData.getQuestConfigs().keySet()); + Collections.sort(list); + + for (Integer id : list) { + QuestConfig data = GameData.getQuestConfigs().get(id); + writer.println(data.getId() + " : " + map.get(data.getMainQuest().getTitleTextMapHash())); + } + writer.println(); writer.println("// Monsters"); From 1231802192a66b3e15390d811efefe91877f6d77 Mon Sep 17 00:00:00 2001 From: Melledy <52122272+Melledy@users.noreply.github.com> Date: Thu, 12 May 2022 02:30:34 -0700 Subject: [PATCH 4/6] Implement basic quest condition handling Quests that require talking to npcs now work. --- .../data/custom/QuestConfigData.java | 6 +- .../emu/grasscutter/game/quest/GameQuest.java | 36 ++- .../grasscutter/game/quest/QuestManager.java | 64 +++++ .../grasscutter/game/quest/QuestValue.java | 11 + .../game/quest/ServerQuestHandler.java | 91 +++++++ .../game/quest/conditions/BaseCondition.java | 18 ++ .../ConditionPlayerLevelEqualGreater.java | 17 ++ .../quest/conditions/ConditionStateEqual.java | 23 ++ .../game/quest/content/BaseContent.java | 18 ++ .../quest/content/ContentCompleteTalk.java | 17 ++ .../game/quest/enums/LogicType.java | 20 ++ .../game/quest/enums/QuestCondType.java | 92 ------- .../game/quest/enums/QuestExecType.java | 82 ------ .../game/quest/enums/QuestTriggerType.java | 235 ++++++++++++++++++ .../game/quest/handlers/QuestBaseHandler.java | 10 + .../grasscutter/server/game/GameServer.java | 10 +- .../server/packet/recv/HandlerNpcTalkReq.java | 3 + 17 files changed, 566 insertions(+), 187 deletions(-) create mode 100644 src/main/java/emu/grasscutter/game/quest/QuestValue.java create mode 100644 src/main/java/emu/grasscutter/game/quest/ServerQuestHandler.java create mode 100644 src/main/java/emu/grasscutter/game/quest/conditions/BaseCondition.java create mode 100644 src/main/java/emu/grasscutter/game/quest/conditions/ConditionPlayerLevelEqualGreater.java create mode 100644 src/main/java/emu/grasscutter/game/quest/conditions/ConditionStateEqual.java create mode 100644 src/main/java/emu/grasscutter/game/quest/content/BaseContent.java create mode 100644 src/main/java/emu/grasscutter/game/quest/content/ContentCompleteTalk.java delete mode 100644 src/main/java/emu/grasscutter/game/quest/enums/QuestCondType.java delete mode 100644 src/main/java/emu/grasscutter/game/quest/enums/QuestExecType.java create mode 100644 src/main/java/emu/grasscutter/game/quest/enums/QuestTriggerType.java create mode 100644 src/main/java/emu/grasscutter/game/quest/handlers/QuestBaseHandler.java diff --git a/src/main/java/emu/grasscutter/data/custom/QuestConfigData.java b/src/main/java/emu/grasscutter/data/custom/QuestConfigData.java index 4ba0ce47c..3ede024f2 100644 --- a/src/main/java/emu/grasscutter/data/custom/QuestConfigData.java +++ b/src/main/java/emu/grasscutter/data/custom/QuestConfigData.java @@ -1,7 +1,7 @@ package emu.grasscutter.data.custom; import emu.grasscutter.game.quest.enums.LogicType; -import emu.grasscutter.game.quest.enums.QuestCondType; +import emu.grasscutter.game.quest.enums.QuestTriggerType; import emu.grasscutter.game.quest.enums.QuestType; public class QuestConfigData { @@ -90,10 +90,10 @@ public class QuestConfigData { } public class QuestCondition { - private QuestCondType type; + private QuestTriggerType type; private int[] param; - public QuestCondType getType() { + public QuestTriggerType getType() { return type; } diff --git a/src/main/java/emu/grasscutter/game/quest/GameQuest.java b/src/main/java/emu/grasscutter/game/quest/GameQuest.java index 53599830c..d3a240a07 100644 --- a/src/main/java/emu/grasscutter/game/quest/GameQuest.java +++ b/src/main/java/emu/grasscutter/game/quest/GameQuest.java @@ -3,10 +3,13 @@ package emu.grasscutter.game.quest; import dev.morphia.annotations.Entity; import dev.morphia.annotations.Transient; import emu.grasscutter.data.custom.QuestConfig; +import emu.grasscutter.data.custom.QuestConfigData.QuestCondition; import emu.grasscutter.data.custom.QuestConfigData.SubQuestConfigData; import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.enums.LogicType; import emu.grasscutter.game.quest.enums.QuestState; import emu.grasscutter.net.proto.QuestOuterClass.Quest; +import emu.grasscutter.server.packet.send.PacketQuestListUpdateNotify; import emu.grasscutter.server.packet.send.PacketQuestProgressUpdateNotify; import emu.grasscutter.utils.Utils; @@ -137,19 +140,34 @@ public class GameQuest { } this.getOwner().getSession().send(new PacketQuestProgressUpdateNotify(this)); - - // Finish main quest if all child quests are done - this.tryFinishMainQuest(); + this.getOwner().getSession().send(new PacketQuestListUpdateNotify(this)); this.save(); + + this.tryAcceptQuestLine(); } - public boolean tryFinishMainQuest() { + public boolean tryAcceptQuestLine() { try { - SubQuestConfigData subQuestData = getConfig().getMainQuest().getSubQuests()[getConfig().getMainQuest().getSubQuests().length - 1]; - - if (subQuestData.getSubId() == this.getQuestId()) { - getMainQuest().finish(); - return true; + for (SubQuestConfigData questData : getConfig().getMainQuest().getSubQuests()) { + GameQuest quest = getMainQuest().getChildQuestById(questData.getSubId()); + + if (quest == null) { + int[] accept = new int[questData.getAcceptCond().length]; + + // TODO + for (int i = 0; i < questData.getAcceptCond().length; i++) { + QuestCondition condition = questData.getAcceptCond()[i]; + boolean result = getOwner().getServer().getQuestHandler().triggerCondition(this, condition); + + accept[i] = result ? 1 : 0; + } + + boolean shouldAccept = LogicType.calculate(questData.getAcceptCondComb(), accept); + + if (shouldAccept) { + this.getOwner().getQuestManager().addQuest(questData.getSubId()); + } + } } } catch (Exception e) { diff --git a/src/main/java/emu/grasscutter/game/quest/QuestManager.java b/src/main/java/emu/grasscutter/game/quest/QuestManager.java index e1c26704c..76c098b07 100644 --- a/src/main/java/emu/grasscutter/game/quest/QuestManager.java +++ b/src/main/java/emu/grasscutter/game/quest/QuestManager.java @@ -1,16 +1,25 @@ package emu.grasscutter.game.quest; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.function.Consumer; import java.util.function.Function; import emu.grasscutter.data.GameData; import emu.grasscutter.data.custom.QuestConfig; +import emu.grasscutter.data.custom.QuestConfigData.QuestCondition; +import emu.grasscutter.data.custom.QuestConfigData.SubQuestConfigData; import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.enums.QuestTriggerType; +import emu.grasscutter.game.quest.enums.LogicType; import emu.grasscutter.game.quest.enums.QuestState; import emu.grasscutter.server.packet.send.PacketFinishedParentQuestUpdateNotify; import emu.grasscutter.server.packet.send.PacketQuestListUpdateNotify; +import emu.grasscutter.server.packet.send.PacketQuestProgressUpdateNotify; import emu.grasscutter.server.packet.send.PacketServerCondMeetQuestListUpdateNotify; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; @@ -59,6 +68,17 @@ public class QuestManager { } } + // TODO + public void forEachActiveQuest(Consumer callback) { + for (GameMainQuest mainQuest : getQuests().values()) { + for (GameQuest quest : mainQuest.getChildQuests().values()) { + if (quest.getState() != QuestState.QUEST_STATE_FINISHED) { + callback.accept(quest); + } + } + } + } + public GameMainQuest addMainQuest(QuestConfig questConfig) { GameMainQuest mainQuest = new GameMainQuest(getPlayer(), questConfig.getMainQuest().getId()); getQuests().put(mainQuest.getParentQuestId(), mainQuest); @@ -101,6 +121,50 @@ public class QuestManager { return quest; } + + public void triggerEvent(QuestTriggerType condType, int... params) { + Set changedQuests = new HashSet<>(); + + this.forEachActiveQuest(quest -> { + SubQuestConfigData data = quest.getConfig().getSubQuest(); + + for (int i = 0; i < data.getFinishCond().length; i++) { + if (quest.getFinishProgressList()[i] == 1) { + continue; + } + + QuestCondition condition = data.getFinishCond()[i]; + + if (condition.getType() != condType) { + continue; + } + + boolean result = getPlayer().getServer().getQuestHandler().triggerContent(quest, condition, params); + + if (result) { + quest.getFinishProgressList()[i] = 1; + + changedQuests.add(quest); + } + } + }); + + for (GameQuest quest : changedQuests) { + LogicType logicType = quest.getConfig().getSubQuest().getFailCondComb(); + int[] progress = quest.getFinishProgressList(); + + // Handle logical comb + boolean finish = LogicType.calculate(logicType, progress); + + // Finish + if (finish) { + quest.finish(); + } else { + getPlayer().sendPacket(new PacketQuestProgressUpdateNotify(quest)); + quest.save(); + } + } + } public void loadFromDatabase() { List quests = DatabaseHelper.getAllQuests(getPlayer()); diff --git a/src/main/java/emu/grasscutter/game/quest/QuestValue.java b/src/main/java/emu/grasscutter/game/quest/QuestValue.java new file mode 100644 index 000000000..3042ad5de --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/QuestValue.java @@ -0,0 +1,11 @@ +package emu.grasscutter.game.quest; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import emu.grasscutter.game.quest.enums.QuestTriggerType; + +@Retention(RetentionPolicy.RUNTIME) +public @interface QuestValue { + QuestTriggerType value(); +} diff --git a/src/main/java/emu/grasscutter/game/quest/ServerQuestHandler.java b/src/main/java/emu/grasscutter/game/quest/ServerQuestHandler.java new file mode 100644 index 000000000..1c269de90 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/ServerQuestHandler.java @@ -0,0 +1,91 @@ +package emu.grasscutter.game.quest; + +import java.util.Set; + +import org.reflections.Reflections; + +import emu.grasscutter.data.custom.QuestConfigData.QuestCondition; +import emu.grasscutter.game.quest.enums.QuestTriggerType; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.server.game.GameServer; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + +@SuppressWarnings("unchecked") +public class ServerQuestHandler { + private final Int2ObjectMap condHandlers; + private final Int2ObjectMap contHandlers; + private final Int2ObjectMap execHandlers; + + public ServerQuestHandler() { + this.condHandlers = new Int2ObjectOpenHashMap<>(); + this.contHandlers = new Int2ObjectOpenHashMap<>(); + this.execHandlers = new Int2ObjectOpenHashMap<>(); + + this.registerHandlers(); + } + + public void registerHandlers() { + this.registerHandlers(this.condHandlers, "emu.grasscutter.game.quest.conditions"); + this.registerHandlers(this.contHandlers, "emu.grasscutter.game.quest.content"); + this.registerHandlers(this.execHandlers, "emu.grasscutter.game.quest.exec"); + } + + public void registerHandlers(Int2ObjectMap map, String packageName) { + Reflections reflections = new Reflections(packageName); + Set handlerClasses = reflections.getSubTypesOf(QuestBaseHandler.class); + + for (Object obj : handlerClasses) { + this.registerPacketHandler(map, (Class) obj); + } + } + + public void registerPacketHandler(Int2ObjectMap map, Class handlerClass) { + try { + QuestValue opcode = handlerClass.getAnnotation(QuestValue.class); + + if (opcode == null || opcode.value().getValue() <= 0) { + return; + } + + QuestBaseHandler packetHandler = (QuestBaseHandler) handlerClass.newInstance(); + + map.put(opcode.value().getValue(), packetHandler); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // TODO make cleaner + + public boolean triggerCondition(GameQuest quest, QuestCondition condition, int... params) { + QuestBaseHandler handler = condHandlers.get(condition.getType().getValue()); + + if (handler == null || quest.getConfig() == null) { + return false; + } + + return handler.execute(quest, condition, params); + } + + public boolean triggerContent(GameQuest quest, QuestCondition condition, int... params) { + QuestBaseHandler handler = contHandlers.get(condition.getType().getValue()); + + if (handler == null || quest.getConfig() == null) { + return false; + } + + return handler.execute(quest, condition, params); + } + + public boolean triggerExec(GameQuest quest, QuestCondition condition, int... params) { + QuestBaseHandler handler = execHandlers.get(condition.getType().getValue()); + + if (handler == null || quest.getConfig() == null) { + return false; + } + + return handler.execute(quest, condition, params); + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/conditions/BaseCondition.java b/src/main/java/emu/grasscutter/game/quest/conditions/BaseCondition.java new file mode 100644 index 000000000..903773f0e --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/conditions/BaseCondition.java @@ -0,0 +1,18 @@ +package emu.grasscutter.game.quest.conditions; + +import emu.grasscutter.data.custom.QuestConfigData.QuestCondition; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.enums.QuestTriggerType; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTriggerType.QUEST_CONTENT_NONE) +public class BaseCondition extends QuestBaseHandler { + + @Override + public boolean execute(GameQuest quest, QuestCondition condition, int... params) { + // TODO Auto-generated method stub + return false; + } + +} diff --git a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionPlayerLevelEqualGreater.java b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionPlayerLevelEqualGreater.java new file mode 100644 index 000000000..f5df2b13c --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionPlayerLevelEqualGreater.java @@ -0,0 +1,17 @@ +package emu.grasscutter.game.quest.conditions; + +import emu.grasscutter.data.custom.QuestConfigData.QuestCondition; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.enums.QuestTriggerType; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTriggerType.QUEST_COND_PLAYER_LEVEL_EQUAL_GREATER) +public class ConditionPlayerLevelEqualGreater extends QuestBaseHandler { + + @Override + public boolean execute(GameQuest quest, QuestCondition condition, int... params) { + return quest.getOwner().getLevel() >= condition.getParam()[0]; + } + +} diff --git a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionStateEqual.java b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionStateEqual.java new file mode 100644 index 000000000..71b44c967 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionStateEqual.java @@ -0,0 +1,23 @@ +package emu.grasscutter.game.quest.conditions; + +import emu.grasscutter.data.custom.QuestConfigData.QuestCondition; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.enums.QuestTriggerType; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTriggerType.QUEST_COND_STATE_EQUAL) +public class ConditionStateEqual extends QuestBaseHandler { + + @Override + public boolean execute(GameQuest quest, QuestCondition condition, int... params) { + GameQuest checkQuest = quest.getOwner().getQuestManager().getQuestById(condition.getParam()[0]); + + if (checkQuest != null) { + return checkQuest.getState().getValue() == condition.getParam()[1]; + } + + return false; + } + +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/BaseContent.java b/src/main/java/emu/grasscutter/game/quest/content/BaseContent.java new file mode 100644 index 000000000..820d6f133 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/content/BaseContent.java @@ -0,0 +1,18 @@ +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.data.custom.QuestConfigData.QuestCondition; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.enums.QuestTriggerType; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTriggerType.QUEST_CONTENT_NONE) +public class BaseContent extends QuestBaseHandler { + + @Override + public boolean execute(GameQuest quest, QuestCondition condition, int... params) { + // TODO Auto-generated method stub + return false; + } + +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentCompleteTalk.java b/src/main/java/emu/grasscutter/game/quest/content/ContentCompleteTalk.java new file mode 100644 index 000000000..aad196306 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentCompleteTalk.java @@ -0,0 +1,17 @@ +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.data.custom.QuestConfigData.QuestCondition; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.enums.QuestTriggerType; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTriggerType.QUEST_CONTENT_COMPLETE_TALK) +public class ContentCompleteTalk extends QuestBaseHandler { + + @Override + public boolean execute(GameQuest quest, QuestCondition condition, int... params) { + return condition.getParam()[0] == params[0]; + } + +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/LogicType.java b/src/main/java/emu/grasscutter/game/quest/enums/LogicType.java index 608ec9c28..12677ee0d 100644 --- a/src/main/java/emu/grasscutter/game/quest/enums/LogicType.java +++ b/src/main/java/emu/grasscutter/game/quest/enums/LogicType.java @@ -1,5 +1,7 @@ package emu.grasscutter.game.quest.enums; +import java.util.Arrays; + public enum LogicType { LOGIC_NONE (0), LOGIC_AND (1), @@ -20,4 +22,22 @@ public enum LogicType { public int getValue() { return value; } + + public static boolean calculate(LogicType logicType, int[] progress) { + if (logicType == null) { + return progress[0] == 1; + } + + switch (logicType) { + case LOGIC_AND -> { + return Arrays.stream(progress).allMatch(i -> i == 1); + } + case LOGIC_OR -> { + return Arrays.stream(progress).anyMatch(i -> i == 1); + } + default -> { + return Arrays.stream(progress).anyMatch(i -> i == 1); + } + } + } } diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestCondType.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestCondType.java deleted file mode 100644 index 42db14f2d..000000000 --- a/src/main/java/emu/grasscutter/game/quest/enums/QuestCondType.java +++ /dev/null @@ -1,92 +0,0 @@ -package emu.grasscutter.game.quest.enums; - -public enum QuestCondType { - QUEST_COND_NONE (0), - QUEST_COND_STATE_EQUAL (1), - QUEST_COND_STATE_NOT_EQUAL (2), - QUEST_COND_PACK_HAVE_ITEM (3), - QUEST_COND_AVATAR_ELEMENT_EQUAL (4), - QUEST_COND_AVATAR_ELEMENT_NOT_EQUAL (5), - QUEST_COND_AVATAR_CAN_CHANGE_ELEMENT (6), - QUEST_COND_CITY_LEVEL_EQUAL_GREATER (7), - QUEST_COND_ITEM_NUM_LESS_THAN (8), - QUEST_COND_DAILY_TASK_START (9), - QUEST_COND_OPEN_STATE_EQUAL (10), - QUEST_COND_DAILY_TASK_OPEN (11), - QUEST_COND_DAILY_TASK_REWARD_CAN_GET (12), - QUEST_COND_DAILY_TASK_REWARD_RECEIVED (13), - QUEST_COND_PLAYER_LEVEL_REWARD_CAN_GET (14), - QUEST_COND_EXPLORATION_REWARD_CAN_GET (15), - QUEST_COND_IS_WORLD_OWNER (16), - QUEST_COND_PLAYER_LEVEL_EQUAL_GREATER (17), - QUEST_COND_SCENE_AREA_UNLOCKED (18), - QUEST_COND_ITEM_GIVING_ACTIVED (19), - QUEST_COND_ITEM_GIVING_FINISHED (20), - QUEST_COND_IS_DAYTIME (21), - QUEST_COND_CURRENT_AVATAR (22), - QUEST_COND_CURRENT_AREA (23), - QUEST_COND_QUEST_VAR_EQUAL (24), - QUEST_COND_QUEST_VAR_GREATER (25), - QUEST_COND_QUEST_VAR_LESS (26), - QUEST_COND_FORGE_HAVE_FINISH (27), - QUEST_COND_DAILY_TASK_IN_PROGRESS (28), - QUEST_COND_DAILY_TASK_FINISHED (29), - QUEST_COND_ACTIVITY_COND (30), - QUEST_COND_ACTIVITY_OPEN (31), - QUEST_COND_DAILY_TASK_VAR_GT (32), - QUEST_COND_DAILY_TASK_VAR_EQ (33), - QUEST_COND_DAILY_TASK_VAR_LT (34), - QUEST_COND_BARGAIN_ITEM_GT (35), - QUEST_COND_BARGAIN_ITEM_EQ (36), - QUEST_COND_BARGAIN_ITEM_LT (37), - QUEST_COND_COMPLETE_TALK (38), - QUEST_COND_NOT_HAVE_BLOSSOM_TALK (39), - QUEST_COND_IS_CUR_BLOSSOM_TALK (40), - QUEST_COND_QUEST_NOT_RECEIVE (41), - QUEST_COND_QUEST_SERVER_COND_VALID (42), - QUEST_COND_ACTIVITY_CLIENT_COND (43), - QUEST_COND_QUEST_GLOBAL_VAR_EQUAL (44), - QUEST_COND_QUEST_GLOBAL_VAR_GREATER (45), - QUEST_COND_QUEST_GLOBAL_VAR_LESS (46), - QUEST_COND_PERSONAL_LINE_UNLOCK (47), - QUEST_COND_CITY_REPUTATION_REQUEST (48), - QUEST_COND_MAIN_COOP_START (49), - QUEST_COND_MAIN_COOP_ENTER_SAVE_POINT (50), - QUEST_COND_CITY_REPUTATION_LEVEL (51), - QUEST_COND_CITY_REPUTATION_UNLOCK (52), - QUEST_COND_LUA_NOTIFY (53), - QUEST_COND_CUR_CLIMATE (54), - QUEST_COND_ACTIVITY_END (55), - QUEST_COND_COOP_POINT_RUNNING (56), - QUEST_COND_GADGET_TALK_STATE_EQUAL (57), - QUEST_COND_AVATAR_FETTER_GT (58), - QUEST_COND_AVATAR_FETTER_EQ (59), - QUEST_COND_AVATAR_FETTER_LT (60), - QUEST_COND_NEW_HOMEWORLD_MOUDLE_UNLOCK (61), - QUEST_COND_NEW_HOMEWORLD_LEVEL_REWARD (62), - QUEST_COND_NEW_HOMEWORLD_MAKE_FINISH (63), - QUEST_COND_HOMEWORLD_NPC_EVENT (64), - QUEST_COND_TIME_VAR_GT_EQ (65), - QUEST_COND_TIME_VAR_PASS_DAY (66), - QUEST_COND_HOMEWORLD_NPC_NEW_TALK (67), - QUEST_COND_PLAYER_CHOOSE_MALE (68), - QUEST_COND_HISTORY_GOT_ANY_ITEM (69), - QUEST_COND_LEARNED_RECIPE (70), - QUEST_COND_LUNARITE_REGION_UNLOCKED (71), - QUEST_COND_LUNARITE_HAS_REGION_HINT_COUNT (72), - QUEST_COND_LUNARITE_COLLECT_FINISH (73), - QUEST_COND_LUNARITE_MARK_ALL_FINISH (74), - QUEST_COND_NEW_HOMEWORLD_SHOP_ITEM (75), - QUEST_COND_SCENE_POINT_UNLOCK (76), - QUEST_COND_SCENE_LEVEL_TAG_EQ (77); - - private final int value; - - QuestCondType(int id) { - this.value = id; - } - - public int getValue() { - return value; - } -} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestExecType.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestExecType.java deleted file mode 100644 index 4f3c2557c..000000000 --- a/src/main/java/emu/grasscutter/game/quest/enums/QuestExecType.java +++ /dev/null @@ -1,82 +0,0 @@ -package emu.grasscutter.game.quest.enums; - -public enum QuestExecType { - QUEST_EXEC_NONE (0), - QUEST_EXEC_DEL_PACK_ITEM (1), - QUEST_EXEC_UNLOCK_POINT (2), - QUEST_EXEC_UNLOCK_AREA (3), - QUEST_EXEC_UNLOCK_FORCE (4), - QUEST_EXEC_LOCK_FORCE (5), - QUEST_EXEC_CHANGE_AVATAR_ELEMET (6), - QUEST_EXEC_REFRESH_GROUP_MONSTER (7), - QUEST_EXEC_SET_IS_FLYABLE (8), - QUEST_EXEC_SET_IS_WEATHER_LOCKED (9), - QUEST_EXEC_SET_IS_GAME_TIME_LOCKED (10), - QUEST_EXEC_SET_IS_TRANSFERABLE (11), - QUEST_EXEC_GRANT_TRIAL_AVATAR (12), - QUEST_EXEC_OPEN_BORED (13), - QUEST_EXEC_ROLLBACK_QUEST (14), - QUEST_EXEC_NOTIFY_GROUP_LUA (15), - QUEST_EXEC_SET_OPEN_STATE (16), - QUEST_EXEC_LOCK_POINT (17), - QUEST_EXEC_DEL_PACK_ITEM_BATCH (18), - QUEST_EXEC_REFRESH_GROUP_SUITE (19), - QUEST_EXEC_REMOVE_TRIAL_AVATAR (20), - QUEST_EXEC_SET_GAME_TIME (21), - QUEST_EXEC_SET_WEATHER_GADGET (22), - QUEST_EXEC_ADD_QUEST_PROGRESS (23), - QUEST_EXEC_NOTIFY_DAILY_TASK (24), - QUEST_EXEC_CREATE_PATTERN_GROUP (25), - QUEST_EXEC_REMOVE_PATTERN_GROUP (26), - QUEST_EXEC_REFRESH_GROUP_SUITE_RANDOM (27), - QUEST_EXEC_ACTIVE_ITEM_GIVING (28), - QUEST_EXEC_DEL_ALL_SPECIFIC_PACK_ITEM (29), - QUEST_EXEC_ROLLBACK_PARENT_QUEST (30), - QUEST_EXEC_LOCK_AVATAR_TEAM (31), - QUEST_EXEC_UNLOCK_AVATAR_TEAM (32), - QUEST_EXEC_UPDATE_PARENT_QUEST_REWARD_INDEX (33), - QUEST_EXEC_SET_DAILY_TASK_VAR (34), - QUEST_EXEC_INC_DAILY_TASK_VAR (35), - QUEST_EXEC_DEC_DAILY_TASK_VAR (36), - QUEST_EXEC_ACTIVE_ACTIVITY_COND_STATE (37), - QUEST_EXEC_INACTIVE_ACTIVITY_COND_STATE (38), - QUEST_EXEC_ADD_CUR_AVATAR_ENERGY (39), - QUEST_EXEC_START_BARGAIN (41), - QUEST_EXEC_STOP_BARGAIN (42), - QUEST_EXEC_SET_QUEST_GLOBAL_VAR (43), - QUEST_EXEC_INC_QUEST_GLOBAL_VAR (44), - QUEST_EXEC_DEC_QUEST_GLOBAL_VAR (45), - QUEST_EXEC_REGISTER_DYNAMIC_GROUP (46), - QUEST_EXEC_UNREGISTER_DYNAMIC_GROUP (47), - QUEST_EXEC_SET_QUEST_VAR (48), - QUEST_EXEC_INC_QUEST_VAR (49), - QUEST_EXEC_DEC_QUEST_VAR (50), - QUEST_EXEC_RANDOM_QUEST_VAR (51), - QUEST_EXEC_ACTIVATE_SCANNING_PIC (52), - QUEST_EXEC_RELOAD_SCENE_TAG (53), - QUEST_EXEC_REGISTER_DYNAMIC_GROUP_ONLY (54), - QUEST_EXEC_CHANGE_SKILL_DEPOT (55), - QUEST_EXEC_ADD_SCENE_TAG (56), - QUEST_EXEC_DEL_SCENE_TAG (57), - QUEST_EXEC_INIT_TIME_VAR (58), - QUEST_EXEC_CLEAR_TIME_VAR (59), - QUEST_EXEC_MODIFY_CLIMATE_AREA (60), - QUEST_EXEC_GRANT_TRIAL_AVATAR_AND_LOCK_TEAM (61), - QUEST_EXEC_CHANGE_MAP_AREA_STATE (62), - QUEST_EXEC_DEACTIVE_ITEM_GIVING (63), - QUEST_EXEC_CHANGE_SCENE_LEVEL_TAG (64), - QUEST_EXEC_UNLOCK_PLAYER_WORLD_SCENE (65), - QUEST_EXEC_LOCK_PLAYER_WORLD_SCENE (66), - QUEST_EXEC_FAIL_MAINCOOP (67), - QUEST_EXEC_MODIFY_WEATHER_AREA (68); - - private final int value; - - QuestExecType(int id) { - this.value = id; - } - - public int getValue() { - return value; - } -} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestTriggerType.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestTriggerType.java new file mode 100644 index 000000000..cf8dabdba --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/enums/QuestTriggerType.java @@ -0,0 +1,235 @@ +package emu.grasscutter.game.quest.enums; + +public enum QuestTriggerType { + QUEST_COND_NONE (0), + QUEST_COND_STATE_EQUAL (1), + QUEST_COND_STATE_NOT_EQUAL (2), + QUEST_COND_PACK_HAVE_ITEM (3), + QUEST_COND_AVATAR_ELEMENT_EQUAL (4), + QUEST_COND_AVATAR_ELEMENT_NOT_EQUAL (5), + QUEST_COND_AVATAR_CAN_CHANGE_ELEMENT (6), + QUEST_COND_CITY_LEVEL_EQUAL_GREATER (7), + QUEST_COND_ITEM_NUM_LESS_THAN (8), + QUEST_COND_DAILY_TASK_START (9), + QUEST_COND_OPEN_STATE_EQUAL (10), + QUEST_COND_DAILY_TASK_OPEN (11), + QUEST_COND_DAILY_TASK_REWARD_CAN_GET (12), + QUEST_COND_DAILY_TASK_REWARD_RECEIVED (13), + QUEST_COND_PLAYER_LEVEL_REWARD_CAN_GET (14), + QUEST_COND_EXPLORATION_REWARD_CAN_GET (15), + QUEST_COND_IS_WORLD_OWNER (16), + QUEST_COND_PLAYER_LEVEL_EQUAL_GREATER (17), + QUEST_COND_SCENE_AREA_UNLOCKED (18), + QUEST_COND_ITEM_GIVING_ACTIVED (19), + QUEST_COND_ITEM_GIVING_FINISHED (20), + QUEST_COND_IS_DAYTIME (21), + QUEST_COND_CURRENT_AVATAR (22), + QUEST_COND_CURRENT_AREA (23), + QUEST_COND_QUEST_VAR_EQUAL (24), + QUEST_COND_QUEST_VAR_GREATER (25), + QUEST_COND_QUEST_VAR_LESS (26), + QUEST_COND_FORGE_HAVE_FINISH (27), + QUEST_COND_DAILY_TASK_IN_PROGRESS (28), + QUEST_COND_DAILY_TASK_FINISHED (29), + QUEST_COND_ACTIVITY_COND (30), + QUEST_COND_ACTIVITY_OPEN (31), + QUEST_COND_DAILY_TASK_VAR_GT (32), + QUEST_COND_DAILY_TASK_VAR_EQ (33), + QUEST_COND_DAILY_TASK_VAR_LT (34), + QUEST_COND_BARGAIN_ITEM_GT (35), + QUEST_COND_BARGAIN_ITEM_EQ (36), + QUEST_COND_BARGAIN_ITEM_LT (37), + QUEST_COND_COMPLETE_TALK (38), + QUEST_COND_NOT_HAVE_BLOSSOM_TALK (39), + QUEST_COND_IS_CUR_BLOSSOM_TALK (40), + QUEST_COND_QUEST_NOT_RECEIVE (41), + QUEST_COND_QUEST_SERVER_COND_VALID (42), + QUEST_COND_ACTIVITY_CLIENT_COND (43), + QUEST_COND_QUEST_GLOBAL_VAR_EQUAL (44), + QUEST_COND_QUEST_GLOBAL_VAR_GREATER (45), + QUEST_COND_QUEST_GLOBAL_VAR_LESS (46), + QUEST_COND_PERSONAL_LINE_UNLOCK (47), + QUEST_COND_CITY_REPUTATION_REQUEST (48), + QUEST_COND_MAIN_COOP_START (49), + QUEST_COND_MAIN_COOP_ENTER_SAVE_POINT (50), + QUEST_COND_CITY_REPUTATION_LEVEL (51), + QUEST_COND_CITY_REPUTATION_UNLOCK (52), + QUEST_COND_LUA_NOTIFY (53), + QUEST_COND_CUR_CLIMATE (54), + QUEST_COND_ACTIVITY_END (55), + QUEST_COND_COOP_POINT_RUNNING (56), + QUEST_COND_GADGET_TALK_STATE_EQUAL (57), + QUEST_COND_AVATAR_FETTER_GT (58), + QUEST_COND_AVATAR_FETTER_EQ (59), + QUEST_COND_AVATAR_FETTER_LT (60), + QUEST_COND_NEW_HOMEWORLD_MOUDLE_UNLOCK (61), + QUEST_COND_NEW_HOMEWORLD_LEVEL_REWARD (62), + QUEST_COND_NEW_HOMEWORLD_MAKE_FINISH (63), + QUEST_COND_HOMEWORLD_NPC_EVENT (64), + QUEST_COND_TIME_VAR_GT_EQ (65), + QUEST_COND_TIME_VAR_PASS_DAY (66), + QUEST_COND_HOMEWORLD_NPC_NEW_TALK (67), + QUEST_COND_PLAYER_CHOOSE_MALE (68), + QUEST_COND_HISTORY_GOT_ANY_ITEM (69), + QUEST_COND_LEARNED_RECIPE (70), + QUEST_COND_LUNARITE_REGION_UNLOCKED (71), + QUEST_COND_LUNARITE_HAS_REGION_HINT_COUNT (72), + QUEST_COND_LUNARITE_COLLECT_FINISH (73), + QUEST_COND_LUNARITE_MARK_ALL_FINISH (74), + QUEST_COND_NEW_HOMEWORLD_SHOP_ITEM (75), + QUEST_COND_SCENE_POINT_UNLOCK (76), + QUEST_COND_SCENE_LEVEL_TAG_EQ (77), + + QUEST_CONTENT_NONE (0), + QUEST_CONTENT_KILL_MONSTER (1), + QUEST_CONTENT_COMPLETE_TALK (2), + QUEST_CONTENT_MONSTER_DIE (3), + QUEST_CONTENT_FINISH_PLOT (4), + QUEST_CONTENT_OBTAIN_ITEM (5), + QUEST_CONTENT_TRIGGER_FIRE (6), + QUEST_CONTENT_CLEAR_GROUP_MONSTER (7), + QUEST_CONTENT_NOT_FINISH_PLOT (8), + QUEST_CONTENT_ENTER_DUNGEON (9), + QUEST_CONTENT_ENTER_MY_WORLD (10), + QUEST_CONTENT_FINISH_DUNGEON (11), + QUEST_CONTENT_DESTROY_GADGET (12), + QUEST_CONTENT_OBTAIN_MATERIAL_WITH_SUBTYPE (13), + QUEST_CONTENT_NICK_NAME (14), + QUEST_CONTENT_WORKTOP_SELECT (15), + QUEST_CONTENT_SEAL_BATTLE_RESULT (16), + QUEST_CONTENT_ENTER_ROOM (17), + QUEST_CONTENT_GAME_TIME_TICK (18), + QUEST_CONTENT_FAIL_DUNGEON (19), + QUEST_CONTENT_LUA_NOTIFY (20), + QUEST_CONTENT_TEAM_DEAD (21), + QUEST_CONTENT_COMPLETE_ANY_TALK (22), + QUEST_CONTENT_UNLOCK_TRANS_POINT (23), + QUEST_CONTENT_ADD_QUEST_PROGRESS (24), + QUEST_CONTENT_INTERACT_GADGET (25), + QUEST_CONTENT_DAILY_TASK_COMP_FINISH (26), + QUEST_CONTENT_FINISH_ITEM_GIVING (27), + QUEST_CONTENT_SKILL (107), + QUEST_CONTENT_CITY_LEVEL_UP (109), + QUEST_CONTENT_PATTERN_GROUP_CLEAR_MONSTER (110), + QUEST_CONTENT_ITEM_LESS_THAN (111), + QUEST_CONTENT_PLAYER_LEVEL_UP (112), + QUEST_CONTENT_DUNGEON_OPEN_STATUE (113), + QUEST_CONTENT_UNLOCK_AREA (114), + QUEST_CONTENT_OPEN_CHEST_WITH_GADGET_ID (115), + QUEST_CONTENT_UNLOCK_TRANS_POINT_WITH_TYPE (116), + QUEST_CONTENT_FINISH_DAILY_DUNGEON (117), + QUEST_CONTENT_FINISH_WEEKLY_DUNGEON (118), + QUEST_CONTENT_QUEST_VAR_EQUAL (119), + QUEST_CONTENT_QUEST_VAR_GREATER (120), + QUEST_CONTENT_QUEST_VAR_LESS (121), + QUEST_CONTENT_OBTAIN_VARIOUS_ITEM (122), + QUEST_CONTENT_FINISH_TOWER_LEVEL (123), + QUEST_CONTENT_BARGAIN_SUCC (124), + QUEST_CONTENT_BARGAIN_FAIL (125), + QUEST_CONTENT_ITEM_LESS_THAN_BARGAIN (126), + QUEST_CONTENT_ACTIVITY_TRIGGER_FAILED (127), + QUEST_CONTENT_MAIN_COOP_ENTER_SAVE_POINT (128), + QUEST_CONTENT_ANY_MANUAL_TRANSPORT (129), + QUEST_CONTENT_USE_ITEM (130), + QUEST_CONTENT_MAIN_COOP_ENTER_ANY_SAVE_POINT (131), + QUEST_CONTENT_ENTER_MY_HOME_WORLD (132), + QUEST_CONTENT_ENTER_MY_WORLD_SCENE (133), + QUEST_CONTENT_TIME_VAR_GT_EQ (134), + QUEST_CONTENT_TIME_VAR_PASS_DAY (135), + QUEST_CONTENT_QUEST_STATE_EQUAL (136), + QUEST_CONTENT_QUEST_STATE_NOT_EQUAL (137), + QUEST_CONTENT_UNLOCKED_RECIPE (138), + QUEST_CONTENT_NOT_UNLOCKED_RECIPE (139), + QUEST_CONTENT_FISHING_SUCC (140), + QUEST_CONTENT_ENTER_ROGUE_DUNGEON (141), + QUEST_CONTENT_USE_WIDGET (142), + QUEST_CONTENT_CAPTURE_SUCC (143), + QUEST_CONTENT_CAPTURE_USE_CAPTURETAG_LIST (144), + QUEST_CONTENT_CAPTURE_USE_MATERIAL_LIST (145), + QUEST_CONTENT_ENTER_VEHICLE (147), + QUEST_CONTENT_SCENE_LEVEL_TAG_EQ (148), + QUEST_CONTENT_LEAVE_SCENE (149), + QUEST_CONTENT_LEAVE_SCENE_RANGE (150), + QUEST_CONTENT_IRODORI_FINISH_FLOWER_COMBINATION (151), + QUEST_CONTENT_IRODORI_POETRY_REACH_MIN_PROGRESS (152), + QUEST_CONTENT_IRODORI_POETRY_FINISH_FILL_POETRY (153), + + QUEST_EXEC_NONE (0), + QUEST_EXEC_DEL_PACK_ITEM (1), + QUEST_EXEC_UNLOCK_POINT (2), + QUEST_EXEC_UNLOCK_AREA (3), + QUEST_EXEC_UNLOCK_FORCE (4), + QUEST_EXEC_LOCK_FORCE (5), + QUEST_EXEC_CHANGE_AVATAR_ELEMET (6), + QUEST_EXEC_REFRESH_GROUP_MONSTER (7), + QUEST_EXEC_SET_IS_FLYABLE (8), + QUEST_EXEC_SET_IS_WEATHER_LOCKED (9), + QUEST_EXEC_SET_IS_GAME_TIME_LOCKED (10), + QUEST_EXEC_SET_IS_TRANSFERABLE (11), + QUEST_EXEC_GRANT_TRIAL_AVATAR (12), + QUEST_EXEC_OPEN_BORED (13), + QUEST_EXEC_ROLLBACK_QUEST (14), + QUEST_EXEC_NOTIFY_GROUP_LUA (15), + QUEST_EXEC_SET_OPEN_STATE (16), + QUEST_EXEC_LOCK_POINT (17), + QUEST_EXEC_DEL_PACK_ITEM_BATCH (18), + QUEST_EXEC_REFRESH_GROUP_SUITE (19), + QUEST_EXEC_REMOVE_TRIAL_AVATAR (20), + QUEST_EXEC_SET_GAME_TIME (21), + QUEST_EXEC_SET_WEATHER_GADGET (22), + QUEST_EXEC_ADD_QUEST_PROGRESS (23), + QUEST_EXEC_NOTIFY_DAILY_TASK (24), + QUEST_EXEC_CREATE_PATTERN_GROUP (25), + QUEST_EXEC_REMOVE_PATTERN_GROUP (26), + QUEST_EXEC_REFRESH_GROUP_SUITE_RANDOM (27), + QUEST_EXEC_ACTIVE_ITEM_GIVING (28), + QUEST_EXEC_DEL_ALL_SPECIFIC_PACK_ITEM (29), + QUEST_EXEC_ROLLBACK_PARENT_QUEST (30), + QUEST_EXEC_LOCK_AVATAR_TEAM (31), + QUEST_EXEC_UNLOCK_AVATAR_TEAM (32), + QUEST_EXEC_UPDATE_PARENT_QUEST_REWARD_INDEX (33), + QUEST_EXEC_SET_DAILY_TASK_VAR (34), + QUEST_EXEC_INC_DAILY_TASK_VAR (35), + QUEST_EXEC_DEC_DAILY_TASK_VAR (36), + QUEST_EXEC_ACTIVE_ACTIVITY_COND_STATE (37), + QUEST_EXEC_INACTIVE_ACTIVITY_COND_STATE (38), + QUEST_EXEC_ADD_CUR_AVATAR_ENERGY (39), + QUEST_EXEC_START_BARGAIN (41), + QUEST_EXEC_STOP_BARGAIN (42), + QUEST_EXEC_SET_QUEST_GLOBAL_VAR (43), + QUEST_EXEC_INC_QUEST_GLOBAL_VAR (44), + QUEST_EXEC_DEC_QUEST_GLOBAL_VAR (45), + QUEST_EXEC_REGISTER_DYNAMIC_GROUP (46), + QUEST_EXEC_UNREGISTER_DYNAMIC_GROUP (47), + QUEST_EXEC_SET_QUEST_VAR (48), + QUEST_EXEC_INC_QUEST_VAR (49), + QUEST_EXEC_DEC_QUEST_VAR (50), + QUEST_EXEC_RANDOM_QUEST_VAR (51), + QUEST_EXEC_ACTIVATE_SCANNING_PIC (52), + QUEST_EXEC_RELOAD_SCENE_TAG (53), + QUEST_EXEC_REGISTER_DYNAMIC_GROUP_ONLY (54), + QUEST_EXEC_CHANGE_SKILL_DEPOT (55), + QUEST_EXEC_ADD_SCENE_TAG (56), + QUEST_EXEC_DEL_SCENE_TAG (57), + QUEST_EXEC_INIT_TIME_VAR (58), + QUEST_EXEC_CLEAR_TIME_VAR (59), + QUEST_EXEC_MODIFY_CLIMATE_AREA (60), + QUEST_EXEC_GRANT_TRIAL_AVATAR_AND_LOCK_TEAM (61), + QUEST_EXEC_CHANGE_MAP_AREA_STATE (62), + QUEST_EXEC_DEACTIVE_ITEM_GIVING (63), + QUEST_EXEC_CHANGE_SCENE_LEVEL_TAG (64), + QUEST_EXEC_UNLOCK_PLAYER_WORLD_SCENE (65), + QUEST_EXEC_LOCK_PLAYER_WORLD_SCENE (66), + QUEST_EXEC_FAIL_MAINCOOP (67), + QUEST_EXEC_MODIFY_WEATHER_AREA (68); + + private final int value; + + QuestTriggerType(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/handlers/QuestBaseHandler.java b/src/main/java/emu/grasscutter/game/quest/handlers/QuestBaseHandler.java new file mode 100644 index 000000000..68bf88361 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/handlers/QuestBaseHandler.java @@ -0,0 +1,10 @@ +package emu.grasscutter.game.quest.handlers; + +import emu.grasscutter.data.custom.QuestConfigData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; + +public abstract class QuestBaseHandler { + + public abstract boolean execute(GameQuest quest, QuestCondition condition, int... params); + +} diff --git a/src/main/java/emu/grasscutter/server/game/GameServer.java b/src/main/java/emu/grasscutter/server/game/GameServer.java index 71e1cf856..f44aa1bc4 100644 --- a/src/main/java/emu/grasscutter/server/game/GameServer.java +++ b/src/main/java/emu/grasscutter/server/game/GameServer.java @@ -14,6 +14,8 @@ import emu.grasscutter.game.managers.ChatManager; import emu.grasscutter.game.managers.InventoryManager; import emu.grasscutter.game.managers.MultiplayerManager; import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.ServerQuestHandler; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; import emu.grasscutter.game.shop.ShopManager; import emu.grasscutter.game.tower.TowerScheduleManager; import emu.grasscutter.game.world.World; @@ -37,7 +39,8 @@ import static emu.grasscutter.Configuration.*; public final class GameServer extends KcpServer { private final InetSocketAddress address; private final GameServerPacketHandler packetHandler; - + private final ServerQuestHandler questHandler; + private final Map players; private final Set worlds; @@ -68,6 +71,7 @@ public final class GameServer extends KcpServer { this.setServerInitializer(new GameServerInitializer(this)); this.address = address; this.packetHandler = new GameServerPacketHandler(PacketHandler.class); + this.questHandler = new ServerQuestHandler(); this.players = new ConcurrentHashMap<>(); this.worlds = Collections.synchronizedSet(new HashSet<>()); @@ -91,6 +95,10 @@ public final class GameServer extends KcpServer { return packetHandler; } + public ServerQuestHandler getQuestHandler() { + return questHandler; + } + public Map getPlayers() { return players; } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerNpcTalkReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerNpcTalkReq.java index 309d7e2e2..515552289 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerNpcTalkReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerNpcTalkReq.java @@ -1,6 +1,7 @@ package emu.grasscutter.server.packet.recv; import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.quest.enums.QuestTriggerType; import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.NpcTalkReqOuterClass.NpcTalkReq; @@ -14,6 +15,8 @@ public class HandlerNpcTalkReq extends PacketHandler { @Override public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { NpcTalkReq req = NpcTalkReq.parseFrom(payload); + + session.getPlayer().getQuestManager().triggerEvent(QuestTriggerType.QUEST_CONTENT_COMPLETE_TALK, req.getTalkId()); session.send(new PacketNpcTalkRsp(req.getNpcEntityId(), req.getTalkId(), req.getEntityId())); } From 631a53030c5d86242aa6214aa3a01b4c2a19eb4e Mon Sep 17 00:00:00 2001 From: Melledy <52122272+Melledy@users.noreply.github.com> Date: Fri, 13 May 2022 03:12:25 -0700 Subject: [PATCH 5/6] Switch to using quest excels --- .../java/emu/grasscutter/data/GameData.java | 13 +- .../emu/grasscutter/data/ResourceLoader.java | 17 +-- .../data/custom/MainQuestData.java | 53 ++++++++ .../grasscutter/data/custom/QuestConfig.java | 25 ---- .../data/custom/QuestConfigData.java | 104 ---------------- .../emu/grasscutter/data/def/QuestData.java | 115 ++++++++++++++++++ .../grasscutter/game/quest/GameMainQuest.java | 1 - .../emu/grasscutter/game/quest/GameQuest.java | 49 +++++--- .../grasscutter/game/quest/QuestManager.java | 27 ++-- .../grasscutter/game/quest/QuestValue.java | 4 +- .../game/quest/ServerQuestHandler.java | 12 +- .../game/quest/conditions/BaseCondition.java | 6 +- .../ConditionPlayerLevelEqualGreater.java | 8 +- .../quest/conditions/ConditionStateEqual.java | 10 +- .../game/quest/content/BaseContent.java | 6 +- .../quest/content/ContentCompleteTalk.java | 6 +- ...uestTriggerType.java => QuestTrigger.java} | 4 +- .../game/quest/handlers/QuestBaseHandler.java | 2 +- .../server/packet/recv/HandlerNpcTalkReq.java | 4 +- ...etServerCondMeetQuestListUpdateNotify.java | 3 - .../java/emu/grasscutter/tools/Tools.java | 12 +- 21 files changed, 262 insertions(+), 219 deletions(-) create mode 100644 src/main/java/emu/grasscutter/data/custom/MainQuestData.java delete mode 100644 src/main/java/emu/grasscutter/data/custom/QuestConfig.java delete mode 100644 src/main/java/emu/grasscutter/data/custom/QuestConfigData.java create mode 100644 src/main/java/emu/grasscutter/data/def/QuestData.java rename src/main/java/emu/grasscutter/game/quest/enums/{QuestTriggerType.java => QuestTrigger.java} (99%) diff --git a/src/main/java/emu/grasscutter/data/GameData.java b/src/main/java/emu/grasscutter/data/GameData.java index 2b40818e1..75b840202 100644 --- a/src/main/java/emu/grasscutter/data/GameData.java +++ b/src/main/java/emu/grasscutter/data/GameData.java @@ -12,7 +12,7 @@ import emu.grasscutter.data.custom.AbilityEmbryoEntry; import emu.grasscutter.data.custom.AbilityModifier; import emu.grasscutter.data.custom.AbilityModifierEntry; import emu.grasscutter.data.custom.OpenConfigEntry; -import emu.grasscutter.data.custom.QuestConfig; +import emu.grasscutter.data.custom.MainQuestData; import emu.grasscutter.data.custom.ScenePointEntry; import emu.grasscutter.data.def.*; import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; @@ -28,7 +28,7 @@ public class GameData { private static final Map abilityModifiers = new HashMap<>(); private static final Map openConfigEntries = new HashMap<>(); private static final Map scenePointEntries = new HashMap<>(); - private static final Int2ObjectMap questConfigs = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap mainQuestData = new Int2ObjectOpenHashMap<>(); // ExcelConfigs private static final Int2ObjectMap playerLevelDataMap = new Int2ObjectOpenHashMap<>(); @@ -70,6 +70,7 @@ public class GameData { private static final Int2ObjectMap worldLevelDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap dailyDungeonDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap dungeonDataMap = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap questDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap shopGoodsDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap combineDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap rewardPreviewDataMap = new Int2ObjectOpenHashMap<>(); @@ -124,8 +125,8 @@ public class GameData { return getScenePointEntries().get(sceneId + "_" + pointId); } - public static Int2ObjectMap getQuestConfigs() { - return questConfigs; + public static Int2ObjectMap getMainQuestDataMap() { + return mainQuestData; } public static Int2ObjectMap getAvatarDataMap() { @@ -337,4 +338,8 @@ public class GameData { public static Int2ObjectMap getTowerScheduleDataMap(){ return towerScheduleDataMap; } + + public static Int2ObjectMap getQuestDataMap() { + return questDataMap; + } } diff --git a/src/main/java/emu/grasscutter/data/ResourceLoader.java b/src/main/java/emu/grasscutter/data/ResourceLoader.java index 5c2ac1ee6..4b940c44d 100644 --- a/src/main/java/emu/grasscutter/data/ResourceLoader.java +++ b/src/main/java/emu/grasscutter/data/ResourceLoader.java @@ -24,9 +24,7 @@ import emu.grasscutter.data.custom.AbilityModifier.AbilityModifierAction; import emu.grasscutter.data.custom.AbilityModifier.AbilityModifierActionType; import emu.grasscutter.data.custom.AbilityModifierEntry; import emu.grasscutter.data.custom.OpenConfigEntry; -import emu.grasscutter.data.custom.QuestConfig; -import emu.grasscutter.data.custom.QuestConfigData; -import emu.grasscutter.data.custom.QuestConfigData.SubQuestConfigData; +import emu.grasscutter.data.custom.MainQuestData; import emu.grasscutter.data.custom.ScenePointEntry; import emu.grasscutter.game.world.SpawnDataEntry.*; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; @@ -407,24 +405,19 @@ public class ResourceLoader { } for (File file : folder.listFiles()) { - QuestConfigData mainQuest = null; + MainQuestData mainQuest = null; try (FileReader fileReader = new FileReader(file)) { - mainQuest = Grasscutter.getGsonFactory().fromJson(fileReader, QuestConfigData.class); + mainQuest = Grasscutter.getGsonFactory().fromJson(fileReader, MainQuestData.class); } catch (Exception e) { e.printStackTrace(); continue; } - if (mainQuest.getSubQuests() != null) { - for (SubQuestConfigData subQuest : mainQuest.getSubQuests()) { - QuestConfig quest = new QuestConfig(mainQuest, subQuest); - GameData.getQuestConfigs().put(quest.getId(), quest); - } - } + GameData.getMainQuestDataMap().put(mainQuest.getId(), mainQuest); } - Grasscutter.getLogger().info("Loaded " + GameData.getQuestConfigs().size() + " Quest Configs"); + Grasscutter.getLogger().info("Loaded " + GameData.getMainQuestDataMap().size() + " MainQuestDatas."); } // BinOutput configs diff --git a/src/main/java/emu/grasscutter/data/custom/MainQuestData.java b/src/main/java/emu/grasscutter/data/custom/MainQuestData.java new file mode 100644 index 000000000..e405e3598 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/custom/MainQuestData.java @@ -0,0 +1,53 @@ +package emu.grasscutter.data.custom; + +import emu.grasscutter.game.quest.enums.LogicType; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.enums.QuestType; + +public class MainQuestData { + private int id; + private int series; + private QuestType type; + + private long titleTextMapHash; + private int[] suggestTrackMainQuestList; + private int[] rewardIdList; + + private SubQuestData[] subQuests; + + public int getId() { + return id; + } + + public int getSeries() { + return series; + } + + public QuestType getType() { + return type; + } + + public long getTitleTextMapHash() { + return titleTextMapHash; + } + + public int[] getSuggestTrackMainQuestList() { + return suggestTrackMainQuestList; + } + + public int[] getRewardIdList() { + return rewardIdList; + } + + public SubQuestData[] getSubQuests() { + return subQuests; + } + + public static class SubQuestData { + private int subId; + + public int getSubId() { + return subId; + } + } +} diff --git a/src/main/java/emu/grasscutter/data/custom/QuestConfig.java b/src/main/java/emu/grasscutter/data/custom/QuestConfig.java deleted file mode 100644 index 8674ff7ab..000000000 --- a/src/main/java/emu/grasscutter/data/custom/QuestConfig.java +++ /dev/null @@ -1,25 +0,0 @@ -package emu.grasscutter.data.custom; - -import emu.grasscutter.data.custom.QuestConfigData.SubQuestConfigData; - -public class QuestConfig { - private final QuestConfigData mainQuest; - private final SubQuestConfigData subQuest; - - public QuestConfig(QuestConfigData mainQuest, SubQuestConfigData subQuest) { - this.mainQuest = mainQuest; - this.subQuest = subQuest; - } - - public int getId() { - return subQuest.getSubId(); - } - - public QuestConfigData getMainQuest() { - return mainQuest; - } - - public SubQuestConfigData getSubQuest() { - return subQuest; - } -} diff --git a/src/main/java/emu/grasscutter/data/custom/QuestConfigData.java b/src/main/java/emu/grasscutter/data/custom/QuestConfigData.java deleted file mode 100644 index 3ede024f2..000000000 --- a/src/main/java/emu/grasscutter/data/custom/QuestConfigData.java +++ /dev/null @@ -1,104 +0,0 @@ -package emu.grasscutter.data.custom; - -import emu.grasscutter.game.quest.enums.LogicType; -import emu.grasscutter.game.quest.enums.QuestTriggerType; -import emu.grasscutter.game.quest.enums.QuestType; - -public class QuestConfigData { - private int id; - private int series; - private QuestType type; - - private long titleTextMapHash; - private int[] suggestTrackMainQuestList; - private int[] rewardIdList; - - private SubQuestConfigData[] subQuests; - - public int getId() { - return id; - } - - public int getSeries() { - return series; - } - - public QuestType getType() { - return type; - } - - public long getTitleTextMapHash() { - return titleTextMapHash; - } - - public int[] getSuggestTrackMainQuestList() { - return suggestTrackMainQuestList; - } - - public int[] getRewardIdList() { - return rewardIdList; - } - - public SubQuestConfigData[] getSubQuests() { - return subQuests; - } - - public class SubQuestConfigData { - private int subId; - private int mainId; - - private LogicType acceptCondComb; - private QuestCondition[] acceptCond; - - private LogicType finishCondComb; - private QuestCondition[] finishCond; - - private LogicType failCondComb; - private QuestCondition[] failCond; - - public int getSubId() { - return subId; - } - - public int getMainId() { - return mainId; - } - - public LogicType getAcceptCondComb() { - return acceptCondComb; - } - - public QuestCondition[] getAcceptCond() { - return acceptCond; - } - - public LogicType getFinishCondComb() { - return finishCondComb; - } - - public QuestCondition[] getFinishCond() { - return finishCond; - } - - public LogicType getFailCondComb() { - return failCondComb; - } - - public QuestCondition[] getFailCond() { - return failCond; - } - } - - public class QuestCondition { - private QuestTriggerType type; - private int[] param; - - public QuestTriggerType getType() { - return type; - } - - public int[] getParam() { - return param; - } - } -} diff --git a/src/main/java/emu/grasscutter/data/def/QuestData.java b/src/main/java/emu/grasscutter/data/def/QuestData.java new file mode 100644 index 000000000..31ac2ce7e --- /dev/null +++ b/src/main/java/emu/grasscutter/data/def/QuestData.java @@ -0,0 +1,115 @@ +package emu.grasscutter.data.def; + +import java.util.Arrays; +import java.util.List; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.game.quest.enums.LogicType; +import emu.grasscutter.game.quest.enums.QuestTrigger; + +@ResourceType(name = "QuestExcelConfigData.json") +public class QuestData extends GameResource { + private int SubId; + private int MainId; + private int Order; + private long DescTextMapHash; + + private LogicType AcceptCondComb; + private QuestCondition[] acceptConditons; + private LogicType FinishCondComb; + private QuestCondition[] finishConditons; + private LogicType FailCondComb; + private QuestCondition[] failConditons; + + private List AcceptCond; + private List FinishCond; + private List FailCond; + private List BeginExec; + private List FinishExec; + private List FailExec; + + public int getId() { + return SubId; + } + + public int getMainId() { + return MainId; + } + + public int getOrder() { + return Order; + } + + public long getDescTextMapHash() { + return DescTextMapHash; + } + + public LogicType getAcceptCondComb() { + return AcceptCondComb; + } + + public QuestCondition[] getAcceptCond() { + return acceptConditons; + } + + public LogicType getFinishCondComb() { + return FinishCondComb; + } + + public QuestCondition[] getFinishCond() { + return finishConditons; + } + + public LogicType getFailCondComb() { + return FailCondComb; + } + + public QuestCondition[] getFailCond() { + return failConditons; + } + + public void onLoad() { + this.acceptConditons = AcceptCond.stream().filter(p -> p.Type != null).map(QuestCondition::new).toArray(QuestCondition[]::new); + AcceptCond = null; + this.finishConditons = FinishCond.stream().filter(p -> p.Type != null).map(QuestCondition::new).toArray(QuestCondition[]::new); + FinishCond = null; + this.failConditons = FailCond.stream().filter(p -> p.Type != null).map(QuestCondition::new).toArray(QuestCondition[]::new); + FailCond = null; + } + + public class QuestParam { + QuestTrigger Type; + int[] Param; + String count; + } + + public class QuestExecParam { + QuestTrigger Type; + String[] Param; + String count; + } + + public static class QuestCondition { + private QuestTrigger type; + private int[] param; + private String count; + + public QuestCondition(QuestParam param) { + this.type = param.Type; + this.param = param.Param; + } + + public QuestTrigger getType() { + return type; + } + + public int[] getParam() { + return param; + } + + public String getCount() { + return count; + } + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/GameMainQuest.java b/src/main/java/emu/grasscutter/game/quest/GameMainQuest.java index 1ceda3356..bf88b8efe 100644 --- a/src/main/java/emu/grasscutter/game/quest/GameMainQuest.java +++ b/src/main/java/emu/grasscutter/game/quest/GameMainQuest.java @@ -10,7 +10,6 @@ import dev.morphia.annotations.Id; import dev.morphia.annotations.Indexed; import dev.morphia.annotations.Transient; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.custom.QuestConfig; import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.quest.enums.ParentQuestState; diff --git a/src/main/java/emu/grasscutter/game/quest/GameQuest.java b/src/main/java/emu/grasscutter/game/quest/GameQuest.java index d3a240a07..b242166eb 100644 --- a/src/main/java/emu/grasscutter/game/quest/GameQuest.java +++ b/src/main/java/emu/grasscutter/game/quest/GameQuest.java @@ -2,9 +2,11 @@ package emu.grasscutter.game.quest; import dev.morphia.annotations.Entity; import dev.morphia.annotations.Transient; -import emu.grasscutter.data.custom.QuestConfig; -import emu.grasscutter.data.custom.QuestConfigData.QuestCondition; -import emu.grasscutter.data.custom.QuestConfigData.SubQuestConfigData; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.custom.MainQuestData; +import emu.grasscutter.data.custom.MainQuestData.SubQuestData; +import emu.grasscutter.data.def.QuestData; +import emu.grasscutter.data.def.QuestData.QuestCondition; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.quest.enums.LogicType; import emu.grasscutter.game.quest.enums.QuestState; @@ -16,7 +18,7 @@ import emu.grasscutter.utils.Utils; @Entity public class GameQuest { @Transient private GameMainQuest mainQuest; - @Transient private QuestConfig config; + @Transient private QuestData questData; private int questId; private int mainQuestId; @@ -32,21 +34,21 @@ public class GameQuest { @Deprecated // Morphia only. Do not use. public GameQuest() {} - public GameQuest(GameMainQuest mainQuest, QuestConfig config) { + public GameQuest(GameMainQuest mainQuest, QuestData questData) { this.mainQuest = mainQuest; - this.questId = config.getId(); - this.mainQuestId = config.getMainQuest().getId(); - this.config = config; + this.questId = questData.getId(); + this.mainQuestId = questData.getMainId(); + this.questData = questData; this.acceptTime = Utils.getCurrentSeconds(); this.startTime = this.acceptTime; this.state = QuestState.QUEST_STATE_UNFINISHED; - if (config.getSubQuest().getFinishCond() != null) { - this.finishProgressList = new int[config.getSubQuest().getFinishCond().length]; + if (questData.getFinishCond()!= null) { + this.finishProgressList = new int[questData.getFinishCond().length]; } - if (config.getSubQuest().getFailCond() != null) { - this.failProgressList = new int[config.getSubQuest().getFailCond().length]; + if (questData.getFailCond() != null) { + this.failProgressList = new int[questData.getFailCond().length]; } this.mainQuest.getChildQuests().put(this.questId, this); @@ -72,13 +74,13 @@ public class GameQuest { return mainQuestId; } - public QuestConfig getConfig() { - return config; + public QuestData getData() { + return questData; } - public void setConfig(QuestConfig config) { + public void setConfig(QuestData config) { if (this.getQuestId() != config.getId()) return; - this.config = config; + this.questData = config; } public QuestState getState() { @@ -148,16 +150,23 @@ public class GameQuest { public boolean tryAcceptQuestLine() { try { - for (SubQuestConfigData questData : getConfig().getMainQuest().getSubQuests()) { - GameQuest quest = getMainQuest().getChildQuestById(questData.getSubId()); + MainQuestData questConfig = GameData.getMainQuestDataMap().get(this.getMainQuestId()); + for (SubQuestData subQuest : questConfig.getSubQuests()) { + GameQuest quest = getMainQuest().getChildQuestById(subQuest.getSubId()); if (quest == null) { + QuestData questData = GameData.getQuestDataMap().get(subQuest.getSubId()); + + if (questData == null) { + continue; + } + int[] accept = new int[questData.getAcceptCond().length]; // TODO for (int i = 0; i < questData.getAcceptCond().length; i++) { QuestCondition condition = questData.getAcceptCond()[i]; - boolean result = getOwner().getServer().getQuestHandler().triggerCondition(this, condition); + boolean result = getOwner().getServer().getQuestHandler().triggerCondition(this, condition, condition.getParam()); accept[i] = result ? 1 : 0; } @@ -165,7 +174,7 @@ public class GameQuest { boolean shouldAccept = LogicType.calculate(questData.getAcceptCondComb(), accept); if (shouldAccept) { - this.getOwner().getQuestManager().addQuest(questData.getSubId()); + this.getOwner().getQuestManager().addQuest(questData.getId()); } } } diff --git a/src/main/java/emu/grasscutter/game/quest/QuestManager.java b/src/main/java/emu/grasscutter/game/quest/QuestManager.java index 76c098b07..548e8241a 100644 --- a/src/main/java/emu/grasscutter/game/quest/QuestManager.java +++ b/src/main/java/emu/grasscutter/game/quest/QuestManager.java @@ -9,12 +9,11 @@ import java.util.function.Consumer; import java.util.function.Function; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.custom.QuestConfig; -import emu.grasscutter.data.custom.QuestConfigData.QuestCondition; -import emu.grasscutter.data.custom.QuestConfigData.SubQuestConfigData; +import emu.grasscutter.data.def.QuestData; +import emu.grasscutter.data.def.QuestData.QuestCondition; import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.quest.enums.QuestTriggerType; +import emu.grasscutter.game.quest.enums.QuestTrigger; import emu.grasscutter.game.quest.enums.LogicType; import emu.grasscutter.game.quest.enums.QuestState; import emu.grasscutter.server.packet.send.PacketFinishedParentQuestUpdateNotify; @@ -46,12 +45,12 @@ public class QuestManager { } public GameQuest getQuestById(int questId) { - QuestConfig questConfig = GameData.getQuestConfigs().get(questId); + QuestData questConfig = GameData.getQuestDataMap().get(questId); if (questConfig == null) { return null; } - GameMainQuest mainQuest = getQuests().get(questConfig.getMainQuest().getId()); + GameMainQuest mainQuest = getQuests().get(questConfig.getMainId()); if (mainQuest == null) { return null; @@ -79,8 +78,8 @@ public class QuestManager { } } - public GameMainQuest addMainQuest(QuestConfig questConfig) { - GameMainQuest mainQuest = new GameMainQuest(getPlayer(), questConfig.getMainQuest().getId()); + public GameMainQuest addMainQuest(QuestData questConfig) { + GameMainQuest mainQuest = new GameMainQuest(getPlayer(), questConfig.getMainId()); getQuests().put(mainQuest.getParentQuestId(), mainQuest); getPlayer().sendPacket(new PacketFinishedParentQuestUpdateNotify(mainQuest)); @@ -89,13 +88,13 @@ public class QuestManager { } public GameQuest addQuest(int questId) { - QuestConfig questConfig = GameData.getQuestConfigs().get(questId); + QuestData questConfig = GameData.getQuestDataMap().get(questId); if (questConfig == null) { return null; } // Main quest - GameMainQuest mainQuest = this.getMainQuestById(questConfig.getMainQuest().getId()); + GameMainQuest mainQuest = this.getMainQuestById(questConfig.getMainId()); // Create main quest if it doesnt exist if (mainQuest == null) { @@ -122,11 +121,11 @@ public class QuestManager { return quest; } - public void triggerEvent(QuestTriggerType condType, int... params) { + public void triggerEvent(QuestTrigger condType, int... params) { Set changedQuests = new HashSet<>(); this.forEachActiveQuest(quest -> { - SubQuestConfigData data = quest.getConfig().getSubQuest(); + QuestData data = quest.getData(); for (int i = 0; i < data.getFinishCond().length; i++) { if (quest.getFinishProgressList()[i] == 1) { @@ -150,7 +149,7 @@ public class QuestManager { }); for (GameQuest quest : changedQuests) { - LogicType logicType = quest.getConfig().getSubQuest().getFailCondComb(); + LogicType logicType = quest.getData().getFailCondComb(); int[] progress = quest.getFinishProgressList(); // Handle logical comb @@ -174,7 +173,7 @@ public class QuestManager { for (GameQuest quest : mainQuest.getChildQuests().values()) { quest.setMainQuest(mainQuest); - quest.setConfig(GameData.getQuestConfigs().get(quest.getQuestId())); + quest.setConfig(GameData.getQuestDataMap().get(quest.getQuestId())); } this.getQuests().put(mainQuest.getParentQuestId(), mainQuest); diff --git a/src/main/java/emu/grasscutter/game/quest/QuestValue.java b/src/main/java/emu/grasscutter/game/quest/QuestValue.java index 3042ad5de..42b868fc8 100644 --- a/src/main/java/emu/grasscutter/game/quest/QuestValue.java +++ b/src/main/java/emu/grasscutter/game/quest/QuestValue.java @@ -3,9 +3,9 @@ package emu.grasscutter.game.quest; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import emu.grasscutter.game.quest.enums.QuestTriggerType; +import emu.grasscutter.game.quest.enums.QuestTrigger; @Retention(RetentionPolicy.RUNTIME) public @interface QuestValue { - QuestTriggerType value(); + QuestTrigger value(); } diff --git a/src/main/java/emu/grasscutter/game/quest/ServerQuestHandler.java b/src/main/java/emu/grasscutter/game/quest/ServerQuestHandler.java index 1c269de90..36c929ab3 100644 --- a/src/main/java/emu/grasscutter/game/quest/ServerQuestHandler.java +++ b/src/main/java/emu/grasscutter/game/quest/ServerQuestHandler.java @@ -4,11 +4,9 @@ import java.util.Set; import org.reflections.Reflections; -import emu.grasscutter.data.custom.QuestConfigData.QuestCondition; -import emu.grasscutter.game.quest.enums.QuestTriggerType; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.def.QuestData.QuestCondition; import emu.grasscutter.game.quest.handlers.QuestBaseHandler; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.server.game.GameServer; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; @@ -62,7 +60,7 @@ public class ServerQuestHandler { public boolean triggerCondition(GameQuest quest, QuestCondition condition, int... params) { QuestBaseHandler handler = condHandlers.get(condition.getType().getValue()); - if (handler == null || quest.getConfig() == null) { + if (handler == null || quest.getData() == null) { return false; } @@ -72,7 +70,7 @@ public class ServerQuestHandler { public boolean triggerContent(GameQuest quest, QuestCondition condition, int... params) { QuestBaseHandler handler = contHandlers.get(condition.getType().getValue()); - if (handler == null || quest.getConfig() == null) { + if (handler == null || quest.getData() == null) { return false; } @@ -82,7 +80,7 @@ public class ServerQuestHandler { public boolean triggerExec(GameQuest quest, QuestCondition condition, int... params) { QuestBaseHandler handler = execHandlers.get(condition.getType().getValue()); - if (handler == null || quest.getConfig() == null) { + if (handler == null || quest.getData() == null) { return false; } diff --git a/src/main/java/emu/grasscutter/game/quest/conditions/BaseCondition.java b/src/main/java/emu/grasscutter/game/quest/conditions/BaseCondition.java index 903773f0e..d94e60c22 100644 --- a/src/main/java/emu/grasscutter/game/quest/conditions/BaseCondition.java +++ b/src/main/java/emu/grasscutter/game/quest/conditions/BaseCondition.java @@ -1,12 +1,12 @@ package emu.grasscutter.game.quest.conditions; -import emu.grasscutter.data.custom.QuestConfigData.QuestCondition; +import emu.grasscutter.data.def.QuestData.QuestCondition; import emu.grasscutter.game.quest.QuestValue; import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.enums.QuestTriggerType; +import emu.grasscutter.game.quest.enums.QuestTrigger; import emu.grasscutter.game.quest.handlers.QuestBaseHandler; -@QuestValue(QuestTriggerType.QUEST_CONTENT_NONE) +@QuestValue(QuestTrigger.QUEST_CONTENT_NONE) public class BaseCondition extends QuestBaseHandler { @Override diff --git a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionPlayerLevelEqualGreater.java b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionPlayerLevelEqualGreater.java index f5df2b13c..3e3db87fb 100644 --- a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionPlayerLevelEqualGreater.java +++ b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionPlayerLevelEqualGreater.java @@ -1,17 +1,17 @@ package emu.grasscutter.game.quest.conditions; -import emu.grasscutter.data.custom.QuestConfigData.QuestCondition; +import emu.grasscutter.data.def.QuestData.QuestCondition; import emu.grasscutter.game.quest.QuestValue; import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.enums.QuestTriggerType; +import emu.grasscutter.game.quest.enums.QuestTrigger; import emu.grasscutter.game.quest.handlers.QuestBaseHandler; -@QuestValue(QuestTriggerType.QUEST_COND_PLAYER_LEVEL_EQUAL_GREATER) +@QuestValue(QuestTrigger.QUEST_COND_PLAYER_LEVEL_EQUAL_GREATER) public class ConditionPlayerLevelEqualGreater extends QuestBaseHandler { @Override public boolean execute(GameQuest quest, QuestCondition condition, int... params) { - return quest.getOwner().getLevel() >= condition.getParam()[0]; + return quest.getOwner().getLevel() >= params[0]; } } diff --git a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionStateEqual.java b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionStateEqual.java index 71b44c967..37ecc6d30 100644 --- a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionStateEqual.java +++ b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionStateEqual.java @@ -1,20 +1,20 @@ package emu.grasscutter.game.quest.conditions; -import emu.grasscutter.data.custom.QuestConfigData.QuestCondition; +import emu.grasscutter.data.def.QuestData.QuestCondition; import emu.grasscutter.game.quest.QuestValue; import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.enums.QuestTriggerType; +import emu.grasscutter.game.quest.enums.QuestTrigger; import emu.grasscutter.game.quest.handlers.QuestBaseHandler; -@QuestValue(QuestTriggerType.QUEST_COND_STATE_EQUAL) +@QuestValue(QuestTrigger.QUEST_COND_STATE_EQUAL) public class ConditionStateEqual extends QuestBaseHandler { @Override public boolean execute(GameQuest quest, QuestCondition condition, int... params) { - GameQuest checkQuest = quest.getOwner().getQuestManager().getQuestById(condition.getParam()[0]); + GameQuest checkQuest = quest.getOwner().getQuestManager().getQuestById(params[0]); if (checkQuest != null) { - return checkQuest.getState().getValue() == condition.getParam()[1]; + return checkQuest.getState().getValue() == params[1]; } return false; diff --git a/src/main/java/emu/grasscutter/game/quest/content/BaseContent.java b/src/main/java/emu/grasscutter/game/quest/content/BaseContent.java index 820d6f133..ce700896d 100644 --- a/src/main/java/emu/grasscutter/game/quest/content/BaseContent.java +++ b/src/main/java/emu/grasscutter/game/quest/content/BaseContent.java @@ -1,12 +1,12 @@ package emu.grasscutter.game.quest.content; -import emu.grasscutter.data.custom.QuestConfigData.QuestCondition; +import emu.grasscutter.data.def.QuestData.QuestCondition; import emu.grasscutter.game.quest.QuestValue; import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.enums.QuestTriggerType; +import emu.grasscutter.game.quest.enums.QuestTrigger; import emu.grasscutter.game.quest.handlers.QuestBaseHandler; -@QuestValue(QuestTriggerType.QUEST_CONTENT_NONE) +@QuestValue(QuestTrigger.QUEST_CONTENT_NONE) public class BaseContent extends QuestBaseHandler { @Override diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentCompleteTalk.java b/src/main/java/emu/grasscutter/game/quest/content/ContentCompleteTalk.java index aad196306..3423519ec 100644 --- a/src/main/java/emu/grasscutter/game/quest/content/ContentCompleteTalk.java +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentCompleteTalk.java @@ -1,12 +1,12 @@ package emu.grasscutter.game.quest.content; -import emu.grasscutter.data.custom.QuestConfigData.QuestCondition; +import emu.grasscutter.data.def.QuestData.QuestCondition; import emu.grasscutter.game.quest.QuestValue; import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.enums.QuestTriggerType; +import emu.grasscutter.game.quest.enums.QuestTrigger; import emu.grasscutter.game.quest.handlers.QuestBaseHandler; -@QuestValue(QuestTriggerType.QUEST_CONTENT_COMPLETE_TALK) +@QuestValue(QuestTrigger.QUEST_CONTENT_COMPLETE_TALK) public class ContentCompleteTalk extends QuestBaseHandler { @Override diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestTriggerType.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestTrigger.java similarity index 99% rename from src/main/java/emu/grasscutter/game/quest/enums/QuestTriggerType.java rename to src/main/java/emu/grasscutter/game/quest/enums/QuestTrigger.java index cf8dabdba..def3a399d 100644 --- a/src/main/java/emu/grasscutter/game/quest/enums/QuestTriggerType.java +++ b/src/main/java/emu/grasscutter/game/quest/enums/QuestTrigger.java @@ -1,6 +1,6 @@ package emu.grasscutter.game.quest.enums; -public enum QuestTriggerType { +public enum QuestTrigger { QUEST_COND_NONE (0), QUEST_COND_STATE_EQUAL (1), QUEST_COND_STATE_NOT_EQUAL (2), @@ -225,7 +225,7 @@ public enum QuestTriggerType { private final int value; - QuestTriggerType(int id) { + QuestTrigger(int id) { this.value = id; } diff --git a/src/main/java/emu/grasscutter/game/quest/handlers/QuestBaseHandler.java b/src/main/java/emu/grasscutter/game/quest/handlers/QuestBaseHandler.java index 68bf88361..5a3514200 100644 --- a/src/main/java/emu/grasscutter/game/quest/handlers/QuestBaseHandler.java +++ b/src/main/java/emu/grasscutter/game/quest/handlers/QuestBaseHandler.java @@ -1,6 +1,6 @@ package emu.grasscutter.game.quest.handlers; -import emu.grasscutter.data.custom.QuestConfigData.QuestCondition; +import emu.grasscutter.data.def.QuestData.QuestCondition; import emu.grasscutter.game.quest.GameQuest; public abstract class QuestBaseHandler { diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerNpcTalkReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerNpcTalkReq.java index 515552289..82248c98c 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerNpcTalkReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerNpcTalkReq.java @@ -1,7 +1,7 @@ package emu.grasscutter.server.packet.recv; import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.quest.enums.QuestTriggerType; +import emu.grasscutter.game.quest.enums.QuestTrigger; import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.NpcTalkReqOuterClass.NpcTalkReq; @@ -16,7 +16,7 @@ public class HandlerNpcTalkReq extends PacketHandler { public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { NpcTalkReq req = NpcTalkReq.parseFrom(payload); - session.getPlayer().getQuestManager().triggerEvent(QuestTriggerType.QUEST_CONTENT_COMPLETE_TALK, req.getTalkId()); + session.getPlayer().getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_COMPLETE_TALK, req.getTalkId()); session.send(new PacketNpcTalkRsp(req.getNpcEntityId(), req.getTalkId(), req.getEntityId())); } diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketServerCondMeetQuestListUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketServerCondMeetQuestListUpdateNotify.java index b2ea3d577..fa2e8ab81 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketServerCondMeetQuestListUpdateNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketServerCondMeetQuestListUpdateNotify.java @@ -1,9 +1,6 @@ package emu.grasscutter.server.packet.send; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.custom.QuestConfig; import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.quest.GameMainQuest; import emu.grasscutter.game.quest.GameQuest; import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.PacketOpcodes; diff --git a/src/main/java/emu/grasscutter/tools/Tools.java b/src/main/java/emu/grasscutter/tools/Tools.java index 8b28c027e..5b0f563ee 100644 --- a/src/main/java/emu/grasscutter/tools/Tools.java +++ b/src/main/java/emu/grasscutter/tools/Tools.java @@ -19,10 +19,11 @@ import emu.grasscutter.command.Command; import emu.grasscutter.command.CommandMap; import emu.grasscutter.data.GameData; import emu.grasscutter.data.ResourceLoader; -import emu.grasscutter.data.custom.QuestConfig; +import emu.grasscutter.data.custom.MainQuestData; import emu.grasscutter.data.def.AvatarData; import emu.grasscutter.data.def.ItemData; import emu.grasscutter.data.def.MonsterData; +import emu.grasscutter.data.def.QuestData; import emu.grasscutter.data.def.SceneData; import emu.grasscutter.utils.Utils; @@ -149,13 +150,16 @@ final class ToolsWithLanguageOption { writer.println(data.getId() + " : " + data.getScriptData()); } + writer.println(); + writer.println("// Quests"); - list = new ArrayList<>(GameData.getQuestConfigs().keySet()); + list = new ArrayList<>(GameData.getQuestDataMap().keySet()); Collections.sort(list); for (Integer id : list) { - QuestConfig data = GameData.getQuestConfigs().get(id); - writer.println(data.getId() + " : " + map.get(data.getMainQuest().getTitleTextMapHash())); + QuestData data = GameData.getQuestDataMap().get(id); + MainQuestData mainQuest = GameData.getMainQuestDataMap().get(data.getMainId()); + writer.println(data.getId() + " : " + map.get(mainQuest.getTitleTextMapHash()) + " - " + map.get(data.getDescTextMapHash())); } writer.println(); From cbd46e9215fb02ac625697dff84a6c35dbd42812 Mon Sep 17 00:00:00 2001 From: Melledy <52122272+Melledy@users.noreply.github.com> Date: Fri, 13 May 2022 05:33:43 -0700 Subject: [PATCH 6/6] Add one more quest trigger --- .../game/dungeons/DungeonManager.java | 4 +++- .../game/quest/content/ContentEnterDungeon.java | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/main/java/emu/grasscutter/game/quest/content/ContentEnterDungeon.java diff --git a/src/main/java/emu/grasscutter/game/dungeons/DungeonManager.java b/src/main/java/emu/grasscutter/game/dungeons/DungeonManager.java index 0a68e6ab0..5c0d1fd27 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/DungeonManager.java +++ b/src/main/java/emu/grasscutter/game/dungeons/DungeonManager.java @@ -7,6 +7,7 @@ import emu.grasscutter.data.custom.ScenePointEntry; import emu.grasscutter.data.def.DungeonData; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.props.SceneType; +import emu.grasscutter.game.quest.enums.QuestTrigger; import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.server.game.GameServer; @@ -51,8 +52,9 @@ public class DungeonManager { int sceneId = data.getSceneId(); player.getScene().setPrevScene(sceneId); - if(player.getWorld().transferPlayerToScene(player, sceneId, data)){ + if (player.getWorld().transferPlayerToScene(player, sceneId, data)) { player.getScene().addDungeonSettleObserver(basicDungeonSettleObserver); + player.getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_ENTER_DUNGEON, data.getId()); } player.getScene().setPrevScenePoint(pointId); diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentEnterDungeon.java b/src/main/java/emu/grasscutter/game/quest/content/ContentEnterDungeon.java new file mode 100644 index 000000000..e00e59f9a --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentEnterDungeon.java @@ -0,0 +1,17 @@ +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.data.def.QuestData.QuestCondition; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_ENTER_DUNGEON) +public class ContentEnterDungeon extends QuestBaseHandler { + + @Override + public boolean execute(GameQuest quest, QuestCondition condition, int... params) { + return condition.getParam()[0] == params[0]; + } + +}