From a60609bb3b4a6758664d7694438f5ef9e05b44c1 Mon Sep 17 00:00:00 2001 From: yhy <1763917516@qq.com> Date: Thu, 4 Jun 2026 06:58:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E9=A1=B9=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 16 ++ pom.xml | 130 +++++++++ .../com/io/yaohun/questengine/QEMain.java | 101 +++++++ .../io/yaohun/questengine/api/AuQuestAPI.java | 137 ++++++++++ .../command/QuestAdminCommand.java | 76 ++++++ .../questengine/command/QuestCommand.java | 135 +++++++++ .../io/yaohun/questengine/config/Config.java | 36 +++ .../hook/QuestPlaceholderExpansion.java | 126 +++++++++ .../listener/PlayerQuestListener.java | 23 ++ .../task/QuestBlockBreakListener.java | 33 +++ .../task/QuestBlockPlaceListener.java | 29 ++ .../listener/task/QuestBreedListener.java | 31 +++ .../task/QuestBrewPotionListener.java | 57 ++++ .../listener/task/QuestBucketListener.java | 47 ++++ .../listener/task/QuestCollectListener.java | 108 ++++++++ .../listener/task/QuestCommandListener.java | 35 +++ .../listener/task/QuestCraftItemListener.java | 36 +++ .../task/QuestEnchanItemListener.java | 37 +++ .../listener/task/QuestExpGainListener.java | 30 ++ .../task/QuestFeedAnimalListener.java | 38 +++ .../task/QuestFeedPlayerListener.java | 33 +++ .../listener/task/QuestFishItemListener.java | 68 +++++ .../task/QuestHarvestCropListener.java | 65 +++++ .../task/QuestInteractEntityListener.java | 27 ++ .../task/QuestInteractItemListener.java | 38 +++ .../task/QuestInteractNPCListener.java | 33 +++ .../task/QuestKillMythicListener.java | 31 +++ .../listener/task/QuestKillTypeListener.java | 32 +++ .../listener/task/QuestOpenGuiListener.java | 58 ++++ .../task/QuestPickupItemListener.java | 32 +++ .../listener/task/QuestSmeltFoodListener.java | 50 ++++ .../listener/task/QuestSmeltOreListener.java | 51 ++++ .../task/QuestTameEntityListener.java | 32 +++ .../listener/task/QuestUseAnvilListener.java | 45 +++ .../listener/task/QuestVillagerListener.java | 66 +++++ .../questengine/player/PlayerQuestData.java | 47 ++++ .../player/PlayerQuestManager.java | 219 +++++++++++++++ .../player/PlayerQuestProgress.java | 53 ++++ .../storage/MySQLPlayerQuestStorage.java | 247 +++++++++++++++++ .../player/storage/PlayerQuestSaveQueue.java | 78 ++++++ .../player/storage/PlayerQuestStorage.java | 24 ++ .../storage/PlayerQuestStorageManager.java | 40 +++ .../storage/SQLitePlayerQuestStorage.java | 257 ++++++++++++++++++ .../storage/YamlPlayerQuestStorage.java | 159 +++++++++++ .../io/yaohun/questengine/quest/Quest.java | 75 +++++ .../questengine/quest/QuestCondition.java | 40 +++ .../quest/QuestConditionChecker.java | 67 +++++ .../yaohun/questengine/quest/QuestLoader.java | 149 ++++++++++ .../questengine/quest/QuestManager.java | 38 +++ .../questengine/quest/QuestResetManager.java | 98 +++++++ .../yaohun/questengine/quest/QuestReward.java | 25 ++ .../yaohun/questengine/quest/QuestTask.java | 46 ++++ .../questengine/quest/QuestTaskType.java | 54 ++++ .../yaohun/questengine/quest/QuestType.java | 19 ++ .../io/yaohun/questengine/util/ColorUtil.java | 37 +++ .../yaohun/questengine/util/MessageUtil.java | 71 +++++ src/main/resources/Quests/新手任务.yml | 44 +++ src/main/resources/config.yml | 36 +++ src/main/resources/lang.yml | 4 + src/main/resources/plugin.yml | 14 + 60 files changed, 3863 insertions(+) create mode 100644 .gitignore create mode 100644 pom.xml create mode 100644 src/main/java/com/io/yaohun/questengine/QEMain.java create mode 100644 src/main/java/com/io/yaohun/questengine/api/AuQuestAPI.java create mode 100644 src/main/java/com/io/yaohun/questengine/command/QuestAdminCommand.java create mode 100644 src/main/java/com/io/yaohun/questengine/command/QuestCommand.java create mode 100644 src/main/java/com/io/yaohun/questengine/config/Config.java create mode 100644 src/main/java/com/io/yaohun/questengine/hook/QuestPlaceholderExpansion.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/PlayerQuestListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestBlockBreakListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestBlockPlaceListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestBreedListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestBrewPotionListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestBucketListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestCollectListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestCommandListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestCraftItemListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestEnchanItemListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestExpGainListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestFeedAnimalListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestFeedPlayerListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestFishItemListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestHarvestCropListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestInteractEntityListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestInteractItemListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestInteractNPCListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestKillMythicListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestKillTypeListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestOpenGuiListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestPickupItemListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestSmeltFoodListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestSmeltOreListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestTameEntityListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestUseAnvilListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/listener/task/QuestVillagerListener.java create mode 100644 src/main/java/com/io/yaohun/questengine/player/PlayerQuestData.java create mode 100644 src/main/java/com/io/yaohun/questengine/player/PlayerQuestManager.java create mode 100644 src/main/java/com/io/yaohun/questengine/player/PlayerQuestProgress.java create mode 100644 src/main/java/com/io/yaohun/questengine/player/storage/MySQLPlayerQuestStorage.java create mode 100644 src/main/java/com/io/yaohun/questengine/player/storage/PlayerQuestSaveQueue.java create mode 100644 src/main/java/com/io/yaohun/questengine/player/storage/PlayerQuestStorage.java create mode 100644 src/main/java/com/io/yaohun/questengine/player/storage/PlayerQuestStorageManager.java create mode 100644 src/main/java/com/io/yaohun/questengine/player/storage/SQLitePlayerQuestStorage.java create mode 100644 src/main/java/com/io/yaohun/questengine/player/storage/YamlPlayerQuestStorage.java create mode 100644 src/main/java/com/io/yaohun/questengine/quest/Quest.java create mode 100644 src/main/java/com/io/yaohun/questengine/quest/QuestCondition.java create mode 100644 src/main/java/com/io/yaohun/questengine/quest/QuestConditionChecker.java create mode 100644 src/main/java/com/io/yaohun/questengine/quest/QuestLoader.java create mode 100644 src/main/java/com/io/yaohun/questengine/quest/QuestManager.java create mode 100644 src/main/java/com/io/yaohun/questengine/quest/QuestResetManager.java create mode 100644 src/main/java/com/io/yaohun/questengine/quest/QuestReward.java create mode 100644 src/main/java/com/io/yaohun/questengine/quest/QuestTask.java create mode 100644 src/main/java/com/io/yaohun/questengine/quest/QuestTaskType.java create mode 100644 src/main/java/com/io/yaohun/questengine/quest/QuestType.java create mode 100644 src/main/java/com/io/yaohun/questengine/util/ColorUtil.java create mode 100644 src/main/java/com/io/yaohun/questengine/util/MessageUtil.java create mode 100644 src/main/resources/Quests/新手任务.yml create mode 100644 src/main/resources/config.yml create mode 100644 src/main/resources/lang.yml create mode 100644 src/main/resources/plugin.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6d0414d --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +target/ +out/ +lib/ +libs/ +.vscode/ +.codex/ +.idea/ +*.iml +*.class +*.log +logs/ +*.db +*.sqlite +*.sqlite3 +.DS_Store +Thumbs.db \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..dfa04c0 --- /dev/null +++ b/pom.xml @@ -0,0 +1,130 @@ + + + 4.0.0 + + org.example + AuQuestEngine + 1.0-SNAPSHOT + + + 21 + 21 + UTF-8 + + + + + + papermc-repo + https://repo.papermc.io/repository/maven-public/ + + + public-survive + https://repo.aurora-pixels.com/repository/public-survive/ + + + momi-releases + https://repo.momirealms.net/releases/ + + + + + + com.zaxxer + HikariCP + 5.1.0 + compile + + + com.mysql + mysql-connector-j + 8.4.0 + compile + + + org.xerial + sqlite-jdbc + 3.46.1.0 + compile + + + io.papermc.paper + paper-api + 1.21.11-R0.1-SNAPSHOT + provided + + + me.clip.placeholderapi + PlaceholderAPI + 2.12.2 + provided + + + net.citizensnpcs + Citizens + 2.0.41 + provided + + + io.lumine.mythic.bukkit + MythicMobs + 5.12.0-SNAPSHOT-548b7d33 + provided + + + net.momirealms + custom-fishing + 2.3.23.1 + provided + + + net.momirealms + custom-crops + 3.6.52 + provided + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.6.0 + + + package + + shade + + + false + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + + com.zaxxer.hikari + com.io.yaohun.questengine.libs.hikari + + + + + + + + + + diff --git a/src/main/java/com/io/yaohun/questengine/QEMain.java b/src/main/java/com/io/yaohun/questengine/QEMain.java new file mode 100644 index 0000000..d9499f0 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/QEMain.java @@ -0,0 +1,101 @@ +package com.io.yaohun.questengine; + +import com.io.yaohun.questengine.command.QuestAdminCommand; +import com.io.yaohun.questengine.command.QuestCommand; +import com.io.yaohun.questengine.config.Config; +import com.io.yaohun.questengine.hook.QuestPlaceholderExpansion; +import com.io.yaohun.questengine.listener.PlayerQuestListener; +import com.io.yaohun.questengine.listener.task.*; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.player.storage.PlayerQuestSaveQueue; +import com.io.yaohun.questengine.player.storage.PlayerQuestStorageManager; +import com.io.yaohun.questengine.quest.QuestManager; +import com.io.yaohun.questengine.quest.QuestResetManager; +import com.io.yaohun.questengine.util.MessageUtil; +import org.bukkit.Bukkit; +import org.bukkit.plugin.java.JavaPlugin; + +public class QEMain extends JavaPlugin { + + private static QEMain instance; + public static boolean DEBUG = false; + + @Override + public void onEnable() { + instance = this; + saveDefaultConfig(); + Config.reloadConfig(this,false); + MessageUtil.init(this); + PlayerQuestStorageManager.init(this); + + QuestManager.reloadQuestManager(this); + Bukkit.getPluginManager().registerEvents(new PlayerQuestListener(), this); + registerQuestListener(); + getCommand("aquest").setExecutor(new QuestCommand()); + getCommand("aquestadmin").setExecutor(new QuestAdminCommand()); + + if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { + new QuestPlaceholderExpansion().register(); + getLogger().info("已接入 PlaceholderAPI"); + Bukkit.getConsoleSender().sendMessage("[AuQuest] 已接入前置 §ePlaceholderAPI"); + } + + PlayerQuestSaveQueue.start(); + QuestResetManager.start(); + } + + private void registerQuestListener() { + getServer().getPluginManager().registerEvents(new QuestBlockBreakListener(), this); + getServer().getPluginManager().registerEvents(new QuestBlockPlaceListener(), this); + getServer().getPluginManager().registerEvents(new QuestBreedListener(), this); + getServer().getPluginManager().registerEvents(new QuestCraftItemListener(), this); + getServer().getPluginManager().registerEvents(new QuestExpGainListener(), this); + getServer().getPluginManager().registerEvents(new QuestFeedAnimalListener(), this); + getServer().getPluginManager().registerEvents(new QuestFeedPlayerListener(), this); + getServer().getPluginManager().registerEvents(new QuestInteractEntityListener(), this); + getServer().getPluginManager().registerEvents(new QuestKillTypeListener(), this); + getServer().getPluginManager().registerEvents(new QuestSmeltFoodListener(), this); + getServer().getPluginManager().registerEvents(new QuestSmeltOreListener(), this); + getServer().getPluginManager().registerEvents(new QuestCommandListener(), this); + getServer().getPluginManager().registerEvents(new QuestOpenGuiListener(), this); + // 2026-6-4 新增任务前置 + getServer().getPluginManager().registerEvents(new QuestPickupItemListener(), this); + getServer().getPluginManager().registerEvents(new QuestBucketListener(), this); + getServer().getPluginManager().registerEvents(new QuestCollectListener(), this); + getServer().getPluginManager().registerEvents(new QuestTameEntityListener(), this); + getServer().getPluginManager().registerEvents(new QuestVillagerListener(), this); + getServer().getPluginManager().registerEvents(new QuestBrewPotionListener(), this); + getServer().getPluginManager().registerEvents(new QuestUseAnvilListener(), this); + getServer().getPluginManager().registerEvents(new QuestInteractItemListener(), this); + Bukkit.getConsoleSender().sendMessage("[AuQuest] 正在接入任务前置: "); + if (Bukkit.getPluginManager().getPlugin("Citizens") != null) { + getServer().getPluginManager().registerEvents(new QuestInteractNPCListener(), this); + Bukkit.getConsoleSender().sendMessage(" - §eCitizens"); + } + if (Bukkit.getPluginManager().getPlugin("MythicMobs") != null) { + getServer().getPluginManager().registerEvents(new QuestKillMythicListener(), this); + Bukkit.getConsoleSender().sendMessage(" - §eMythicMobs"); + } + if (Bukkit.getPluginManager().getPlugin("CustomFishing") != null) { + getServer().getPluginManager().registerEvents(new QuestFishItemListener(), this); + Bukkit.getConsoleSender().sendMessage(" - §eCustomFishing"); + } + if (Bukkit.getPluginManager().getPlugin("CustomCrops") != null) { + getServer().getPluginManager().registerEvents(new QuestHarvestCropListener(), this); + Bukkit.getConsoleSender().sendMessage(" - §eCustomCrops"); + } + } + + + @Override + public void onDisable() { + QuestResetManager.stop(); + PlayerQuestSaveQueue.flushSync(); + PlayerQuestManager.saveAll(); + PlayerQuestStorageManager.close(); + } + + public static QEMain inst() { + return instance; + } +} diff --git a/src/main/java/com/io/yaohun/questengine/api/AuQuestAPI.java b/src/main/java/com/io/yaohun/questengine/api/AuQuestAPI.java new file mode 100644 index 0000000..2e07bca --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/api/AuQuestAPI.java @@ -0,0 +1,137 @@ +package com.io.yaohun.questengine.api; + +import com.io.yaohun.questengine.player.PlayerQuestData; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.player.PlayerQuestProgress; +import com.io.yaohun.questengine.player.storage.PlayerQuestSaveQueue; +import com.io.yaohun.questengine.quest.Quest; +import com.io.yaohun.questengine.quest.QuestManager; +import com.io.yaohun.questengine.quest.QuestTask; +import com.io.yaohun.questengine.quest.QuestType; +import com.io.yaohun.questengine.util.ColorUtil; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +public class AuQuestAPI { + + public static String getQuestDisplayName(String questId) { + Quest quest = QuestManager.getQuest(questId); + return quest == null ? null : quest.getDisplayName(); + } + + public static List getQuestDescription(String questId) { + Quest quest = QuestManager.getQuest(questId); + + if (quest == null) { + return Collections.emptyList(); + } + + return new ArrayList<>(quest.getDescription()); + } + + public static QuestType getQuestType(String questId) { + Quest quest = QuestManager.getQuest(questId); + return quest == null ? null : quest.getType(); + } + + public static boolean hasCompletedQuest(UUID uuid, String questId) { + PlayerQuestProgress progress = PlayerQuestManager.getProgress(uuid, questId); + return progress != null && progress.isCompleted(); + } + + public static boolean hasActiveQuest(UUID uuid, String questId) { + PlayerQuestProgress progress = PlayerQuestManager.getProgress(uuid, questId); + return progress != null && !progress.isCompleted(); + } + + public static List getActiveQuests(UUID uuid) { + PlayerQuestData data = PlayerQuestManager.getPlayerData(uuid); + + List list = new ArrayList<>(); + + for (PlayerQuestProgress progress : data.getQuestProgressMap().values()) { + if (!progress.isCompleted()) { + list.add(progress.getQuestId()); + } + } + + return list; + } + + public static List getCompletedQuests(UUID uuid){ + PlayerQuestData data = PlayerQuestManager.getPlayerData(uuid); + List list = new ArrayList<>(); + for(PlayerQuestProgress progress : data.getQuestProgressMap().values()){ + if(progress.isCompleted()){ + list.add(progress.getQuestId()); + } + } + return list; + } + + public static boolean abandonQuest(UUID uuid, String questId) { + PlayerQuestData data = PlayerQuestManager.getPlayerData(uuid); + + if (!data.hasQuest(questId)) { + return false; + } + + data.removeQuest(questId); + PlayerQuestSaveQueue.markDirty(uuid); + + return true; + } + + public static boolean startQuest(UUID uuid, String questId) { + if (!QuestManager.hasQuest(questId)) { + return false; + } + + return PlayerQuestManager.acceptQuest(uuid, questId); + } + + public static boolean directCompleteQuest(UUID uuid, String questId){ + Quest quest = QuestManager.getQuest(questId); + if(quest == null){ + return false; + } + PlayerQuestData data = PlayerQuestManager.getPlayerData(uuid); + + PlayerQuestProgress progress = data.getQuestProgress(questId); + + if(progress == null){ + progress = new PlayerQuestProgress(questId); + data.addQuest(progress); + } + if(progress.isCompleted()){ + return false; + } + for (QuestTask task : quest.getTasks().values()){ + progress.setProgress(task.getId(), task.getAmount()); + } + + progress.setCompleted(true); + PlayerQuestSaveQueue.markDirty(uuid); + Player player = Bukkit.getPlayer(uuid); + if(player != null) { + // 完成消息 + for (String msg : quest.getCompleteMessages()) { + player.sendMessage(ColorUtil.color(msg)); + } + // reward message + for (String msg : quest.getReward().getMessages()) { + player.sendMessage(ColorUtil.color(msg.replace("{name}", quest.getDisplayName()))); + } + // reward command + for (String cmd : quest.getReward().getCommands()) { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), cmd.replace("%player%", player.getName())); + } + } + return true; + } +} \ No newline at end of file diff --git a/src/main/java/com/io/yaohun/questengine/command/QuestAdminCommand.java b/src/main/java/com/io/yaohun/questengine/command/QuestAdminCommand.java new file mode 100644 index 0000000..849ce41 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/command/QuestAdminCommand.java @@ -0,0 +1,76 @@ +package com.io.yaohun.questengine.command; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.config.Config; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.player.storage.PlayerQuestSaveQueue; +import com.io.yaohun.questengine.player.storage.PlayerQuestStorage; +import com.io.yaohun.questengine.player.storage.PlayerQuestStorageManager; +import com.io.yaohun.questengine.player.storage.SQLitePlayerQuestStorage; +import com.io.yaohun.questengine.quest.Quest; +import com.io.yaohun.questengine.quest.QuestManager; +import com.io.yaohun.questengine.util.ColorUtil; +import com.io.yaohun.questengine.util.MessageUtil; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.io.File; + +public class QuestAdminCommand implements CommandExecutor { + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!sender.hasPermission("admin.use")) { + return true; + } + String prefix = "§f[§cAuQuest§f] §a"; + if(args.length >= 1 && "debug".equalsIgnoreCase(args[0])){ + QEMain.DEBUG = !QEMain.DEBUG; + sender.sendMessage(prefix+"已切换调试: §e"+QEMain.DEBUG); + return true; + } + if(args.length >= 1 && "reload".equalsIgnoreCase(args[0])){ + // 先强制保存脏数据 + PlayerQuestSaveQueue.flushSync(); + // 再保存全部缓存 + PlayerQuestManager.saveAll(); + QEMain plugin = QEMain.inst(); + plugin.reloadConfig(); + Config.reloadConfig(plugin, true); + MessageUtil.init(plugin); + QuestManager.reloadQuestManager(plugin); + sender.sendMessage(prefix+"配置文件已重载,当前任务数量: §e"+QuestManager.getAllQuests().size()+"个"); + return true; + } + if(args.length >= 2 && "clear".equalsIgnoreCase(args[0])){ + OfflinePlayer target = Bukkit.getOfflinePlayer(args[1]); + if(target.getUniqueId() == null){ + sender.sendMessage(prefix+"玩家 "+target.getName()+" 不存在"); + return true; + } + PlayerQuestManager.deletePlayerData(target.getUniqueId()); + sender.sendMessage(prefix+"已清空玩家任务数据: &e" + target.getName()); + return true; + } + if (args.length >= 1 && "outsqlite".equalsIgnoreCase(args[0])) { + PlayerQuestStorage storage = PlayerQuestStorageManager.getStorage(); + if (!(storage instanceof SQLitePlayerQuestStorage)) { + sender.sendMessage(ColorUtil.color("&7[任务系统] &c当前存储模式不是 SQLite,无法导出。")); + return true; + } + SQLitePlayerQuestStorage sqliteStorage = (SQLitePlayerQuestStorage) storage; + File file = sqliteStorage.exportToYaml(); + if (file == null) { + sender.sendMessage(ColorUtil.color("&7[任务系统] &cSQLite 数据导出失败,请查看后台报错。")); + return true; + } + sender.sendMessage(ColorUtil.color("&7[任务系统] &aSQLite 数据已导出: &f" + file.getName())); + return true; + } + return true; + } +} \ No newline at end of file diff --git a/src/main/java/com/io/yaohun/questengine/command/QuestCommand.java b/src/main/java/com/io/yaohun/questengine/command/QuestCommand.java new file mode 100644 index 0000000..45c7a9c --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/command/QuestCommand.java @@ -0,0 +1,135 @@ +package com.io.yaohun.questengine.command; + +import com.io.yaohun.questengine.api.AuQuestAPI; +import com.io.yaohun.questengine.player.PlayerQuestData; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.player.PlayerQuestProgress; +import com.io.yaohun.questengine.quest.Quest; +import com.io.yaohun.questengine.quest.QuestConditionChecker; +import com.io.yaohun.questengine.quest.QuestManager; +import com.io.yaohun.questengine.quest.QuestTask; +import com.io.yaohun.questengine.util.ColorUtil; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.UUID; + +public class QuestCommand implements CommandExecutor { + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + String prefix = "§f[§cAuQuest§f] §a"; + if(args.length >= 1 && "direc".equalsIgnoreCase(args[0]) && sender.isOp()){ + if(args.length < 2){ + sender.sendMessage(prefix+"用法: /aquest direc <任务ID>"); + return true; + } + if (!(sender instanceof Player player)) { + sender.sendMessage(prefix+"该命令只能由玩家执行"); + return true; + } + String questId = args[1]; + UUID playerUuid = player.getUniqueId(); + AuQuestAPI.directCompleteQuest(playerUuid, questId); + sender.sendMessage(prefix+"已直接完成任务: §e"+questId); + return true; + } + if(args.length >= 1 && "info".equalsIgnoreCase(args[0])){ + String playerName = sender.getName(); + if(sender.hasPermission("admin.use") && args.length >= 2){ + playerName = args[1]; + } + Player player = Bukkit.getPlayer(playerName); + if(player == null){ + sender.sendMessage(prefix+"玩家 "+playerName+" 不在线"); + return true; + } + PlayerQuestData questData = PlayerQuestManager.getPlayerData(player.getUniqueId()); + sender.sendMessage("§8§m————————————————————"); + sender.sendMessage(prefix+"玩家: §e"+playerName); + sender.sendMessage(prefix+"任务数量: §e"+questData.getQuestProgressMap().size()); + int completedCount = 0; + int activeCount = 0; + for(PlayerQuestProgress progress : questData.getQuestProgressMap().values()){ + Quest quest = QuestManager.getQuest(progress.getQuestId()); + String questName = quest == null ? progress.getQuestId() : quest.getDisplayName(); + if(progress.isCompleted()) { + completedCount++; + sender.sendMessage(ColorUtil.color("&a[已完成] &f" + questName + " &7(" + progress.getQuestId() + ")")); + continue; + } + activeCount++; + sender.sendMessage(ColorUtil.color("&e[进行中] &f" + questName + " &7(" + progress.getQuestId() + ")")); + if(quest != null){ + for(QuestTask task : quest.getTasks().values()){ + int current = progress.getProgress(task.getId()); + int max = task.getAmount(); + if(current > max){ + current = max; + } + sender.sendMessage(ColorUtil.color( + " &8- &7" + task.getDisplayName() + + " &f" + current + "&7/&f" + max + )); + } + } + } + sender.sendMessage(ColorUtil.color("&7进行中: &e" + activeCount + " &7已完成: &a" + completedCount)); + sender.sendMessage("§8§m————————————————————"); + return true; + } + if (args.length < 3) { + sender.sendMessage("§c用法: /aquest js <任务ID> <玩家名>"); + return true; + } + String sub = args[0]; + // /aquest js quest_1 yaohun + if (sub.equalsIgnoreCase("js")) { + + String questId = args[1]; + + Player target = Bukkit.getPlayer(args[2]); + + if (target == null) { + sender.sendMessage("§c玩家不存在"); + return true; + } + + Quest quest = QuestManager.getQuest(questId); + + if (quest == null) { + sender.sendMessage("§c任务不存在"); + return true; + } + + if (!QuestConditionChecker.canAccept(target, quest, true)) { + sender.sendMessage(ColorUtil.color("&7[任务系统] &c玩家不满足任务接受条件。")); + return true; + } + + boolean success = PlayerQuestManager.acceptQuest( + target.getUniqueId(), + questId + ); + + if (!success) { + sender.sendMessage("§c该玩家已经接受过这个任务"); + return true; + } + + // 接受消息 + for (String msg : quest.getReceiveMessages()) { + target.sendMessage(ColorUtil.color(msg)); + } + + sender.sendMessage("§a任务发放成功"); + + return true; + } + + return true; + } +} diff --git a/src/main/java/com/io/yaohun/questengine/config/Config.java b/src/main/java/com/io/yaohun/questengine/config/Config.java new file mode 100644 index 0000000..8985c2b --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/config/Config.java @@ -0,0 +1,36 @@ +package com.io.yaohun.questengine.config; + +import com.io.yaohun.questengine.QEMain; +import org.bukkit.configuration.file.FileConfiguration; + +import java.util.ArrayList; +import java.util.List; + +public class Config { + + private static List foodTypeList = new ArrayList<>(); + private static List oreTypeList = new ArrayList<>(); + + + public static void reloadConfig(QEMain plugin, boolean reload){ + if(reload){ + reload(plugin); + } + FileConfiguration config = plugin.getConfig(); + foodTypeList = config.getStringList("FoodType"); + oreTypeList = config.getStringList("OreType"); + } + + private static void reload(QEMain plugin){ + plugin.reloadConfig(); + plugin.saveConfig(); + } + + public static List getFoodTypeList() { + return foodTypeList; + } + + public static List getOreTypeList() { + return oreTypeList; + } +} diff --git a/src/main/java/com/io/yaohun/questengine/hook/QuestPlaceholderExpansion.java b/src/main/java/com/io/yaohun/questengine/hook/QuestPlaceholderExpansion.java new file mode 100644 index 0000000..db9d8c4 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/hook/QuestPlaceholderExpansion.java @@ -0,0 +1,126 @@ +package com.io.yaohun.questengine.hook; + +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.player.PlayerQuestProgress; +import com.io.yaohun.questengine.quest.Quest; +import com.io.yaohun.questengine.quest.QuestManager; +import com.io.yaohun.questengine.quest.QuestTask; +import me.clip.placeholderapi.expansion.PlaceholderExpansion; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +public class QuestPlaceholderExpansion extends PlaceholderExpansion { + + @Override + public @NotNull String getIdentifier() { + return "aquest"; + } + + @Override + public @NotNull String getAuthor() { + return "yaohun"; + } + + @Override + public @NotNull String getVersion() { + return "1.0.0"; + } + + @Override + public boolean persist() { + return true; + } + + @Override + public String onPlaceholderRequest(Player player, String params) { + + if (player == null) { + return ""; + } + // %aqe_quest_quest_1_name% + if (params.startsWith("quest_") && params.endsWith("_name")) { + String questId = params.substring("quest_".length(), params.length() - "_name".length()); + Quest quest = QuestManager.getQuest(questId); + return quest == null ? "" : quest.getDisplayName(); + } + + // %aqe_quest_quest_1_completed% + if (params.startsWith("quest_") && params.endsWith("_completed")) { + String questId = params.substring("quest_".length(), params.length() - "_completed".length()); + PlayerQuestProgress progress = PlayerQuestManager.getProgress(player.getUniqueId(), questId); + return progress != null && progress.isCompleted() ? "已完成" : "未完成"; + } + + // %aqe_quest_quest_1_progress% + if (params.startsWith("quest_") && params.endsWith("_progress")) { + String questId = params.substring("quest_".length(), params.length() - "_progress".length()); + return getQuestProgressText(player, questId); + } + + // %aqe_task_quest_1_id_1% + if (params.startsWith("task_")) { + String raw = params.substring("task_".length()); + + int lastIndex = raw.lastIndexOf("_id_"); + + if (lastIndex == -1) { + return ""; + } + + String questId = raw.substring(0, lastIndex); + String taskId = "id_" + raw.substring(lastIndex + "_id_".length()); + + return getTaskProgressText(player, questId, taskId); + } + + return ""; + } + + private String getQuestProgressText(Player player, String questId) { + Quest quest = QuestManager.getQuest(questId); + + if (quest == null) { + return ""; + } + + PlayerQuestProgress progress = PlayerQuestManager.getProgress(player.getUniqueId(), questId); + + if (progress == null) { + return "未接受"; + } + + int current = 0; + int max = 0; + + for (QuestTask task : quest.getTasks().values()) { + current += Math.min(progress.getProgress(task.getId()), task.getAmount()); + max += task.getAmount(); + } + + return current + "/" + max; + } + + private String getTaskProgressText(Player player, String questId, String taskId) { + Quest quest = QuestManager.getQuest(questId); + + if (quest == null) { + return ""; + } + + QuestTask task = quest.getTasks().get(taskId); + + if (task == null) { + return ""; + } + + PlayerQuestProgress progress = PlayerQuestManager.getProgress(player.getUniqueId(), questId); + + if (progress == null) { + return "0/" + task.getAmount(); + } + + int current = Math.min(progress.getProgress(taskId), task.getAmount()); + + return current + "/" + task.getAmount(); + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/PlayerQuestListener.java b/src/main/java/com/io/yaohun/questengine/listener/PlayerQuestListener.java new file mode 100644 index 0000000..62cafb3 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/PlayerQuestListener.java @@ -0,0 +1,23 @@ +package com.io.yaohun.questengine.listener; + +import com.io.yaohun.questengine.player.PlayerQuestManager; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +public class PlayerQuestListener implements Listener { + + @EventHandler(priority = EventPriority.LOWEST) + public void onJoin(PlayerJoinEvent e){ + PlayerQuestManager.loadPlayer(e.getPlayer().getUniqueId()); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onQuit(PlayerQuitEvent event) { + PlayerQuestManager.savePlayerNow(event.getPlayer().getUniqueId()); + PlayerQuestManager.unloadPlayer(event.getPlayer().getUniqueId()); + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestBlockBreakListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestBlockBreakListener.java new file mode 100644 index 0000000..b644c5a --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestBlockBreakListener.java @@ -0,0 +1,33 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; + +public class QuestBlockBreakListener implements Listener { + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBlockBreak(BlockBreakEvent event) { + + Player player = event.getPlayer(); + + String target = event.getBlock().getType().name(); + + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 破坏了方块 "+target); + } + + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.BREAK_BLOCK, + target, + 1 + ); + } +} \ No newline at end of file diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestBlockPlaceListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestBlockPlaceListener.java new file mode 100644 index 0000000..45fd46f --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestBlockPlaceListener.java @@ -0,0 +1,29 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockPlaceEvent; + +public class QuestBlockPlaceListener implements Listener { + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlace(BlockPlaceEvent e){ + Player player = e.getPlayer(); + String target = e.getBlock().getType().name(); + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 放置了方块 "+target); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.PLACE_BLOCK, + target, + 1 + ); + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestBreedListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestBreedListener.java new file mode 100644 index 0000000..fb3c463 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestBreedListener.java @@ -0,0 +1,31 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import org.bukkit.Bukkit; +import org.bukkit.entity.Animals; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityBreedEvent; + +public class QuestBreedListener implements Listener { + + @EventHandler(ignoreCancelled = true) + public void onBreed(EntityBreedEvent e){ + if(e.getBreeder() instanceof Player player){ + if(e.getEntity() instanceof Animals animals){ + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 人工繁殖了 "+animals.getType().name()); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.BREED, + animals.getType().name(), + 1 + ); + } + } + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestBrewPotionListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestBrewPotionListener.java new file mode 100644 index 0000000..46fd1ba --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestBrewPotionListener.java @@ -0,0 +1,57 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.PortalType; +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityPickupItemEvent; +import org.bukkit.event.inventory.BrewEvent; +import org.bukkit.inventory.BrewerInventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.PotionMeta; +import org.bukkit.potion.PotionType; + +public class QuestBrewPotionListener implements Listener { + //BREW_POTION("酿造药水"), + + @EventHandler(ignoreCancelled = true) + public void onBrew(BrewEvent e){ + BrewerInventory inventory = e.getContents(); + for (int slot = 0; slot < 3; slot++){ + ItemStack item = inventory.getItem(slot); + if(item == null || item.getType().isAir()){ + continue; + } + if (!(item.getItemMeta() instanceof PotionMeta potionMeta)) { + continue; + } + PotionType potionType = potionMeta.getBasePotionType(); + for (HumanEntity viewer : e.getContents().getViewers()){ + if (!(viewer instanceof Player player)) { + continue; + } + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 " + player.getName() + " 酿造了 " + potionType.name()); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.BREW_POTION, + potionType.name(), + 1 + ); + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.BREW_POTION_COUNT, + "ALL", + 1 + ); + } + } + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestBucketListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestBucketListener.java new file mode 100644 index 0000000..fc21c57 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestBucketListener.java @@ -0,0 +1,47 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerBucketEmptyEvent; +import org.bukkit.event.player.PlayerBucketFillEvent; +import org.bukkit.event.player.PlayerFishEvent; + +public class QuestBucketListener implements Listener { + + @EventHandler(ignoreCancelled = true) + public void onFillBucket(PlayerBucketFillEvent e){ + Player player = e.getPlayer(); + Material material = e.getBucket(); + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 装取了 "+material.name()); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.FILL_BUCKET, + material.name(), + 1 + ); + } + + @EventHandler(ignoreCancelled = true) + public void onPlaceBucket(PlayerBucketEmptyEvent e){ + Player player = e.getPlayer(); + Material material = e.getBucket(); + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 " + player.getName() + " 倒出了 " + material.name()); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.PLACE_BUCKET, + material.name(), + 1 + ); + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestCollectListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestCollectListener.java new file mode 100644 index 0000000..c214c54 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestCollectListener.java @@ -0,0 +1,108 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.block.data.type.Beehive; +import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; +import org.bukkit.entity.Cow; +import org.bukkit.entity.Player; +import org.bukkit.entity.Sheep; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerShearEntityEvent; +import org.bukkit.inventory.ItemStack; + +import java.util.UUID; + +public class QuestCollectListener implements Listener { + // COLLECT_ENTITY("剪羊毛,取蘑菇煲"), + // COLLECT_BLOCK("收集蜂蜜"), + + @EventHandler(ignoreCancelled = true) + public void onShearSheep(PlayerShearEntityEvent e){ + if(e.getEntity() instanceof Sheep sheep) { + if (sheep.isSheared()) { + return; + } + Player player = e.getPlayer(); + ItemStack stack = e.getItem(); + Material material = stack.getType(); + if (QEMain.DEBUG) { + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 " + player.getName() + " 剪羊毛 "+material.name()); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.COLLECT_ENTITY, + "SHEEP", + 1 + ); + } + } + + @EventHandler(ignoreCancelled = true) + public void onMilkCow(PlayerInteractEntityEvent e){ + if(e.getRightClicked() instanceof Cow){ + Player player = e.getPlayer(); + ItemStack hand = player.getInventory().getItemInMainHand(); + if(hand == null || hand.getType() != Material.BUCKET){ + return; + } + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 挤牛奶 Cow"); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.COLLECT_ENTITY, + "COW", + 1 + ); + } + } + + @EventHandler(ignoreCancelled = true) + public void onBeehive(PlayerInteractEvent e){ + if(e.getAction() == Action.RIGHT_CLICK_BLOCK){ + Player player = e.getPlayer(); + Block block = e.getClickedBlock(); + if (block == null) { + return; + } + Material blockType = block.getType(); + if(blockType != Material.BEEHIVE && blockType != Material.BEE_NEST){ + return; + } + ItemStack hand = player.getInventory().getItemInMainHand(); + if(hand == null || hand.getType().isAir()){ + return; + } + Material handType = hand.getType(); + if (handType != Material.GLASS_BOTTLE && handType != Material.SHEARS) { + return; + } + BlockData data = block.getBlockData(); + if(data instanceof Beehive hive){ + if(hive.getHoneyLevel() < hive.getMaximumHoneyLevel()){ + return; + } + String target = handType == Material.GLASS_BOTTLE ? "HONEY_BOTTLE" : "HONEYCOMB"; + if (QEMain.DEBUG) { + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 " + player.getName() + " 收集蜂箱 " + target); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.COLLECT_BLOCK, + target, + 1 + ); + } + } + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestCommandListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestCommandListener.java new file mode 100644 index 0000000..c3e3259 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestCommandListener.java @@ -0,0 +1,35 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryOpenEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.inventory.Inventory; + +import java.util.UUID; + +public class QuestCommandListener implements Listener { + + @EventHandler(ignoreCancelled = true) + public void onCommand(PlayerCommandPreprocessEvent e) { + Player player = e.getPlayer(); + String command = e.getMessage(); + if (command == null || command.isEmpty()) { + return; + } + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 执行了命令 "+command); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.SEND_COMMAND, + command, + 1 + ); + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestCraftItemListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestCraftItemListener.java new file mode 100644 index 0000000..b246282 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestCraftItemListener.java @@ -0,0 +1,36 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.CraftItemEvent; + +public class QuestCraftItemListener implements Listener { + + @EventHandler(ignoreCancelled = true) + public void onCraft(CraftItemEvent event) { + if(event.getWhoClicked() instanceof Player player){ + if (event.getRecipe() == null || event.getRecipe().getResult() == null) { + return; + } + Material material = event.getRecipe().getResult().getType(); + if(material.isAir()){ + return; + } + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 合成了 "+material.name()); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.CRAFT_ITEM, + material.name(), + 1 + ); + } + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestEnchanItemListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestEnchanItemListener.java new file mode 100644 index 0000000..7cc1d26 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestEnchanItemListener.java @@ -0,0 +1,37 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.enchantment.EnchantItemEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.AnvilInventory; +import org.bukkit.inventory.ItemStack; + +public class QuestEnchanItemListener implements Listener { + //ENCHANT_ITEM("使用附魔台"), + + @EventHandler(ignoreCancelled = true) + public void onEnchant(EnchantItemEvent e){ + Player player = e.getEnchanter(); + ItemStack item = e.getItem(); + if(item == null || item.getType().isAir()){ + return; + } + Material material = item.getType(); + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 " + player.getName() + " 附魔了 "+material.name()); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.ENCHANT_ITEM, + material.name(), + 1 + ); + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestExpGainListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestExpGainListener.java new file mode 100644 index 0000000..e50fe57 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestExpGainListener.java @@ -0,0 +1,30 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerExpChangeEvent; + +public class QuestExpGainListener implements Listener { + + @EventHandler(ignoreCancelled = true) + public void onExo(PlayerExpChangeEvent e){ + if(e.getAmount() <= 0){ + return; + } + Player player = e.getPlayer(); + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 获得经验 "+e.getAmount()); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.EXP_GAIN, + null, + e.getAmount() + ); + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestFeedAnimalListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestFeedAnimalListener.java new file mode 100644 index 0000000..b83e5cf --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestFeedAnimalListener.java @@ -0,0 +1,38 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import org.bukkit.Bukkit; +import org.bukkit.entity.Animals; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.inventory.ItemStack; + +public class QuestFeedAnimalListener implements Listener { + @EventHandler(ignoreCancelled = true) + public void onFeed(PlayerInteractEntityEvent e) { + if(e.getRightClicked() instanceof Animals animals){ + Player player = e.getPlayer(); + ItemStack hand = player.getInventory().getItemInMainHand(); + if (hand == null || hand.getType().isAir()) { + return; + } + + if (!animals.isBreedItem(hand)) { + return; + } + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 投喂了 "+animals.getType().name()); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.FEED_ANIMAL, + animals.getType().name(), + 1 + ); + } + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestFeedPlayerListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestFeedPlayerListener.java new file mode 100644 index 0000000..d2c2c08 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestFeedPlayerListener.java @@ -0,0 +1,33 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerItemConsumeEvent; +import org.bukkit.inventory.ItemStack; + +public class QuestFeedPlayerListener implements Listener { + + @EventHandler(ignoreCancelled = true) + public void onFeed(PlayerItemConsumeEvent e){ + Player player = e.getPlayer(); + ItemStack item = e.getItem(); + if(item == null || item.getType().isAir()){ + return; + } + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 吃掉了 "+item.getType().name()); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.FEED_PLAYER, + item.getType().name(), + 1 + ); + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestFishItemListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestFishItemListener.java new file mode 100644 index 0000000..8b7cbce --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestFishItemListener.java @@ -0,0 +1,68 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import net.momirealms.customfishing.api.event.FishingResultEvent; +import net.momirealms.customfishing.api.mechanic.loot.Loot; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityPickupItemEvent; +import org.bukkit.event.player.PlayerFishEvent; +import org.bukkit.inventory.ItemStack; + +public class QuestFishItemListener implements Listener { + + // FISH_ITEM("钓鱼获得物品"), + // FISH_STAR("钓起鱼的星级"), + @EventHandler(ignoreCancelled = true) + public void onFishItem(FishingResultEvent e){ + if(e.getResult() != FishingResultEvent.Result.SUCCESS){ + return; + } + Player player = e.getPlayer(); + Loot loot = e.getLoot(); + if(loot == null){ + return; + } + int amount = e.getAmount(); + if(amount <= 0){ + amount = 1; + } + String fishId = loot.id(); + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 钓起来了 "+fishId+"x"+amount); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.FISH_ITEM, + fishId, + amount + ); + String[] startGroup = loot.lootGroup(); + if(startGroup == null){ + return; + } + for (String group : startGroup){ + if(group == null){ + continue; + } + if("no_star".equalsIgnoreCase(group)){ + continue; + } + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 钓起来了星级鱼 "+group); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.FISH_STAR, + group, + 1 + ); + } + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestHarvestCropListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestHarvestCropListener.java new file mode 100644 index 0000000..0afd1c1 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestHarvestCropListener.java @@ -0,0 +1,65 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import net.momirealms.customcrops.api.event.CropBreakEvent; +import org.bukkit.Bukkit; +import org.bukkit.block.Block; +import org.bukkit.block.data.Ageable; +import org.bukkit.block.data.BlockData; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +public class QuestHarvestCropListener implements Listener { + + // HARVEST_CROP("收获农作物"), 原版 + /*@EventHandler(ignoreCancelled = true) + public void onHarvestCrop(BlockBreakEvent event) { + Player player = event.getPlayer(); + Block block = event.getBlock(); + BlockData data = block.getBlockData(); + if(data instanceof Ageable ageable) { + if(ageable.getAge() < ageable.getMaximumAir()){ + return; + } + Material material = block.getType(); + + if (QEMain.DEBUG) { + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 " + player.getName() + " 收获了 " + material.name()); + } + + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.HARVEST_CROP, + material.name(), + 1 + ); + } + }*/ + // HARVEST_CROP("收获农作物"), 星露谷 + @EventHandler(ignoreCancelled = true) + public void onHarvestCrop(CropBreakEvent e){ + if (!(e.entityBreaker() instanceof Player player)) { + return; + } + Block block = e.blockBreaker(); + BlockData data = block.getBlockData(); + if (data instanceof Ageable ageable) { + if (ageable.getAge() < ageable.getMaximumAge()) { + return; + } + } + String cropId = e.cropConfig().id(); + if (QEMain.DEBUG) { + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 " + player.getName() + " 收获了 " + cropId); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.HARVEST_CROP, + cropId, + 1 + ); + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestInteractEntityListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestInteractEntityListener.java new file mode 100644 index 0000000..56cef90 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestInteractEntityListener.java @@ -0,0 +1,27 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerInteractEntityEvent; + +public class QuestInteractEntityListener implements Listener { + + @EventHandler(ignoreCancelled = true) + public void onInteract(PlayerInteractEntityEvent e){ + Player player = e.getPlayer(); + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 正在交互实体 "+e.getRightClicked().getType().name()); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.INTERACT_ENTITY, + e.getRightClicked().getType().name(), + 1 + ); + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestInteractItemListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestInteractItemListener.java new file mode 100644 index 0000000..ba20e41 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestInteractItemListener.java @@ -0,0 +1,38 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +public class QuestInteractItemListener implements Listener { + + // INTERACT_ITEM("交互手持物品"), + @EventHandler(ignoreCancelled = true) + public void onInteract(PlayerInteractEvent e){ + if(e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK) { + ItemStack item = e.getItem(); + if (item == null || item.getType().isAir()) { + return; + } + Material material = item.getType(); + Player player = e.getPlayer(); + if (QEMain.DEBUG) { + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 " + player.getName() + " 正在交互手持物品 " + material.name()); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.INTERACT_ITEM, + material.name(), + 1 + ); + } + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestInteractNPCListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestInteractNPCListener.java new file mode 100644 index 0000000..3ad5e56 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestInteractNPCListener.java @@ -0,0 +1,33 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import net.citizensnpcs.api.event.NPCRightClickEvent; +import net.citizensnpcs.api.npc.NPC; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +public class QuestInteractNPCListener implements Listener { + + @EventHandler + public void onClickNpc(NPCRightClickEvent e){ + Player player = e.getClicker(); + NPC npc = e.getNPC(); + if(npc == null){ + return; + } + String target = String.valueOf(npc.getName()); + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 正在交互NPC "+target); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.INTERACT_NPC, + target, + 1 + ); + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestKillMythicListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestKillMythicListener.java new file mode 100644 index 0000000..946e94f --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestKillMythicListener.java @@ -0,0 +1,31 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import io.lumine.mythic.api.mobs.MythicMob; +import io.lumine.mythic.bukkit.events.MythicMobDeathEvent; +import io.lumine.mythic.core.mobs.MobType; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +public class QuestKillMythicListener implements Listener { + + @EventHandler + public void onKill(MythicMobDeathEvent e){ + if(e.getKiller() instanceof Player player){ + MythicMob mobType = e.getMobType(); + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 击杀了 "+mobType.getInternalName()); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.KILL_MYTHIC, + mobType.getInternalName(), + 1 + ); + } + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestKillTypeListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestKillTypeListener.java new file mode 100644 index 0000000..d8b0a38 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestKillTypeListener.java @@ -0,0 +1,32 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import net.citizensnpcs.api.event.NPCLeftClickEvent; +import org.bukkit.Bukkit; +import org.bukkit.entity.NPC; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDeathEvent; + +public class QuestKillTypeListener implements Listener { + + @EventHandler(ignoreCancelled = true) + public void onKill(EntityDeathEvent e){ + Player killer = e.getEntity().getKiller(); + if(killer == null){ + return; + } + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+killer.getName()+" 击杀了 "+e.getEntity().getType().name()); + } + PlayerQuestManager.addProgress( + killer.getUniqueId(), + QuestTaskType.KILL_TYPE, + e.getEntity().getType().name(), + 1 + ); + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestOpenGuiListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestOpenGuiListener.java new file mode 100644 index 0000000..4ab81ff --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestOpenGuiListener.java @@ -0,0 +1,58 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryOpenEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.inventory.Inventory; + +import java.util.UUID; + +public class QuestOpenGuiListener implements Listener { + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onOpenGui(InventoryOpenEvent e){ + if(e.getPlayer() instanceof Player player){ + String viewTitle = e.getView().getTitle(); + if (viewTitle == null || viewTitle.isEmpty()) { + return; + } + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 正在打开 "+viewTitle); + } + // 去色标题,方便配置不写颜色也能匹配 + String strippedTitle = ChatColor.stripColor(viewTitle); + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.OPEN_GUI_TITLE, + strippedTitle, + 1 + ); + } + } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onOpenType(InventoryOpenEvent e){ + if(e.getPlayer() instanceof Player player){ + Inventory inventory = e.getInventory(); + if (inventory == null) { + return; + } + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 正在打开 "+inventory.getType().name()); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.OPEN_GUI_TYPE, + inventory.getType().name(), + 1 + ); + } + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestPickupItemListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestPickupItemListener.java new file mode 100644 index 0000000..20b1606 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestPickupItemListener.java @@ -0,0 +1,32 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityPickupItemEvent; +import org.bukkit.inventory.ItemStack; + +public class QuestPickupItemListener implements Listener { + + @EventHandler(ignoreCancelled = true) + public void onPickUp(EntityPickupItemEvent e){ + if(e.getEntity() instanceof Player player){ + ItemStack stack = e.getItem().getItemStack(); + Material material = stack.getType(); + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 拾取了 "+material.name()); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.PICKUP_ITEM, + material.name(), + 1 + ); + } + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestSmeltFoodListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestSmeltFoodListener.java new file mode 100644 index 0000000..8d44498 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestSmeltFoodListener.java @@ -0,0 +1,50 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.config.Config; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.FurnaceExtractEvent; + +import java.util.List; + +public class QuestSmeltFoodListener implements Listener { + + @EventHandler(ignoreCancelled = true) + public void onSmelt(FurnaceExtractEvent e){ + Player player = e.getPlayer(); + + Material result = e.getItemType(); + int amount = e.getItemAmount(); + if (!isFood(result)) { + return; + } + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 在熔炉取出了 "+result.name()); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.SMELT_FOOD, + result.name(), + amount + ); + } + + private boolean isFood(Material material) { + List foodTypeList = Config.getFoodTypeList(); + for (String food : foodTypeList) { + if (material.name().contains(food)) { + return true; + } + } + return switch (material) { + case COOKED_BEEF, COOKED_CHICKEN, COOKED_MUTTON, COOKED_RABBIT, BAKED_POTATO -> true; + default -> false; + }; + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestSmeltOreListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestSmeltOreListener.java new file mode 100644 index 0000000..0073b69 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestSmeltOreListener.java @@ -0,0 +1,51 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.config.Config; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.FurnaceExtractEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; + +import java.util.List; + +public class QuestSmeltOreListener implements Listener { + @EventHandler(ignoreCancelled = true) + public void onSmelt(FurnaceExtractEvent e){ + Player player = e.getPlayer(); + Material result = e.getItemType(); + int amount = e.getItemAmount(); + if(!isOre(result)){ + return; + } + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 在熔炉取出了 "+result.name()); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.SMELT_ORE, + result.name(), + amount + ); + } + + private boolean isOre(Material material){ + List oreList = Config.getOreTypeList(); + for (String ore : oreList) { + if(material.name().contains(ore)){ + return true; + } + } + return switch (material) { + case IRON_INGOT, GOLD_INGOT, COPPER_INGOT, NETHERITE_SCRAP, DIAMOND, EMERALD, REDSTONE, COAL, QUARTZ, + LAPIS_LAZULI -> true; + default -> false; + }; + } + +} \ No newline at end of file diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestTameEntityListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestTameEntityListener.java new file mode 100644 index 0000000..f691e5b --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestTameEntityListener.java @@ -0,0 +1,32 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import org.bukkit.Bukkit; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityTameEvent; + +public class QuestTameEntityListener implements Listener { + + // TAME_ENTITY("驯服实体"), + @EventHandler(ignoreCancelled = true) + public void onTameEntity(EntityTameEvent e){ + if(e.getOwner() instanceof Player player){ + EntityType entityType = e.getEntity().getType(); + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 驯服了 "+entityType.name()); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.TAME_ENTITY, + entityType.name(), + 1 + ); + } + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestUseAnvilListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestUseAnvilListener.java new file mode 100644 index 0000000..0dec088 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestUseAnvilListener.java @@ -0,0 +1,45 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.AnvilInventory; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +public class QuestUseAnvilListener implements Listener { + //USE_ANVIL("使用铁砧"), + + @EventHandler(ignoreCancelled = true) + public void onUseAnvil(InventoryClickEvent e){ + if (!(e.getWhoClicked() instanceof Player player)) { + return; + } + if (!(e.getInventory() instanceof AnvilInventory)) { + return; + } + if(e.getRawSlot() != 2){ + return; + } + ItemStack result = e.getCurrentItem(); + if(result == null || result.getType().isAir()){ + return; + } + Material material = result.getType(); + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 " + player.getName() + " 使用了铁砧 "+material.name()); + } + PlayerQuestManager.addProgress( + player.getUniqueId(), + QuestTaskType.USE_ANVIL, + material.name(), + 1 + ); + } +} diff --git a/src/main/java/com/io/yaohun/questengine/listener/task/QuestVillagerListener.java b/src/main/java/com/io/yaohun/questengine/listener/task/QuestVillagerListener.java new file mode 100644 index 0000000..4da8855 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/listener/task/QuestVillagerListener.java @@ -0,0 +1,66 @@ +package com.io.yaohun.questengine.listener.task; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.quest.QuestTaskType; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.entity.Villager; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.MerchantInventory; +import org.bukkit.inventory.MerchantRecipe; + +import java.util.UUID; + +public class QuestVillagerListener implements Listener { + + //VILLAGER_TRADE_ITEM("村民交易物品"), + //VILLAGER_TRADE_JOB("村民交易职业"), + @EventHandler(ignoreCancelled = true) + public void onVillagerTrade(InventoryClickEvent e){ + if (!(e.getWhoClicked() instanceof Player player)) { + return; + } + if (!(e.getInventory() instanceof MerchantInventory inventory)) { + return; + } + if(e.getRawSlot() != 2){ + return; + } + ItemStack current = e.getCurrentItem(); + if(current == null || current.getType().isAir()){ + return; + } + MerchantRecipe recipe = inventory.getSelectedRecipe(); + if(recipe == null){ + return; + } + UUID playerUuid = player.getUniqueId(); + ItemStack result = recipe.getResult(); + // 物品交易任务 + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 向村民交易物品 "+result.getType().name()); + } + PlayerQuestManager.addProgress( + playerUuid, + QuestTaskType.VILLAGER_TRADE_ITEM, + result.getType().name(), + result.getAmount() + ); + // 职业判定任务 + if(inventory.getMerchant() instanceof Villager villager){ + if(QEMain.DEBUG){ + Bukkit.getConsoleSender().sendMessage("[调试 - 任务] 玩家 "+player.getName()+" 向 "+villager.getProfession().name()+" 村民进行交易"); + } + PlayerQuestManager.addProgress( + playerUuid, + QuestTaskType.VILLAGER_TRADE_JOB, + villager.getProfession().name(), + recipe.getVillagerExperience() + ); + } + } +} diff --git a/src/main/java/com/io/yaohun/questengine/player/PlayerQuestData.java b/src/main/java/com/io/yaohun/questengine/player/PlayerQuestData.java new file mode 100644 index 0000000..fb9035e --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/player/PlayerQuestData.java @@ -0,0 +1,47 @@ +package com.io.yaohun.questengine.player; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class PlayerQuestData { + + private final UUID uuid; + private final Map questProgressMap = new ConcurrentHashMap<>(); + + public PlayerQuestData(UUID uuid) { + this.uuid = uuid; + } + + public UUID getUuid() { + return uuid; + } + + public boolean hasQuest(String questId) { + return questProgressMap.containsKey(questId); + } + + public void addQuest(PlayerQuestProgress progress) { + questProgressMap.put(progress.getQuestId(), progress); + } + + public PlayerQuestProgress getQuestProgress(String questId) { + return questProgressMap.get(questId); + } + + public void removeQuest(String questId) { + questProgressMap.remove(questId); + } + + public Map getQuestProgressMap() { + return questProgressMap; + } + + public PlayerQuestData copy() { + PlayerQuestData copy = new PlayerQuestData(uuid); + for (PlayerQuestProgress progress : questProgressMap.values()) { + copy.addQuest(progress.copy()); + } + return copy; + } +} diff --git a/src/main/java/com/io/yaohun/questengine/player/PlayerQuestManager.java b/src/main/java/com/io/yaohun/questengine/player/PlayerQuestManager.java new file mode 100644 index 0000000..d38ce50 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/player/PlayerQuestManager.java @@ -0,0 +1,219 @@ +package com.io.yaohun.questengine.player; + +import java.util.Collection; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.storage.PlayerQuestSaveQueue; +import com.io.yaohun.questengine.player.storage.PlayerQuestStorageManager; +import com.io.yaohun.questengine.quest.*; +import com.io.yaohun.questengine.util.ColorUtil; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +public class PlayerQuestManager { + + private static final Map playerDataMap = new ConcurrentHashMap<>(); + + public static PlayerQuestData getPlayerData(UUID uuid) { + return playerDataMap.computeIfAbsent( + uuid, + id -> PlayerQuestStorageManager.getStorage().load(id) + ); + } + + public static PlayerQuestData getCachedPlayerData(UUID uuid) { + return playerDataMap.get(uuid); + } + + public static void loadPlayer(UUID uuid){ + getPlayerData(uuid); + } + + public static void savePlayer(UUID uuid) { + PlayerQuestData data = playerDataMap.get(uuid); + + if (data != null) { + PlayerQuestSaveQueue.markDirty(uuid); + } + } + + public static void saveAll() { + for (PlayerQuestData data : playerDataMap.values()) { + PlayerQuestStorageManager.getStorage().save(data); + } + } + + public static boolean hasAccepted(UUID uuid, String questId) { + return getPlayerData(uuid).hasQuest(questId); + } + + public static boolean acceptQuest(UUID uuid, String questId) { + PlayerQuestData data = getPlayerData(uuid); + if (data.hasQuest(questId)) { + return false; + } + data.addQuest(new PlayerQuestProgress(questId)); + PlayerQuestSaveQueue.markDirty(uuid); + return true; + } + + public static PlayerQuestProgress getProgress(UUID uuid, String questId) { + return getPlayerData(uuid).getQuestProgress(questId); + } + + public static void removeQuest(UUID uuid, String questId) { + PlayerQuestData data = getPlayerData(uuid); + data.removeQuest(questId); + PlayerQuestSaveQueue.markDirty(uuid); + } + + public static void removeQuestsFromCache(Collection questIds) { + for (PlayerQuestData data : playerDataMap.values()) { + for (String questId : questIds) { + data.removeQuest(questId); + } + PlayerQuestSaveQueue.markDirty(data.getUuid()); + } + } + + public static void clearPlayer(UUID uuid) { + savePlayerNow(uuid); + playerDataMap.remove(uuid); + } + + public static void savePlayerNow(UUID uuid) { + PlayerQuestData data = playerDataMap.get(uuid); + + if (data != null) { + PlayerQuestStorageManager.getStorage().save(data); + } + } + + public static void unloadPlayer(UUID uuid){ + playerDataMap.remove(uuid); + PlayerQuestSaveQueue.removeDirty(uuid); + } + + public static void deletePlayerData(UUID uuid){ + + playerDataMap.remove(uuid); + + PlayerQuestStorageManager + .getStorage() + .deletePlayer(uuid); + } + + public static boolean clearAllQuests(UUID uuid){ + + PlayerQuestData data = playerDataMap.get(uuid); + + if(data != null){ + data.getQuestProgressMap().clear(); + } + + savePlayerNow(uuid); + + return true; + } + + public static Map getPlayerDataMap() { + return playerDataMap; + } + + public static void addProgress(UUID uuid, QuestTaskType type, String target, int amount) { + PlayerQuestData playerData = getPlayerData(uuid); + boolean changed = false; + for (PlayerQuestProgress progress : playerData.getQuestProgressMap().values()) { + // 已完成任务跳过 + if (progress.isCompleted()) { + continue; + } + Quest quest = QuestManager.getQuest(progress.getQuestId()); + if (quest == null) { + continue; + } + Player player = Bukkit.getPlayer(uuid); + if (player == null) { + continue; + } + if (!QuestConditionChecker.canProgress(player, quest)) { + continue; + } + boolean allCompleted = true; + for (QuestTask task : quest.getTasks().values()) { + // 类型不匹配 + if (task.getType() != type) { + allCompleted = false; + continue; + } + // 目标不匹配 + if (!task.isTarget(target)) { + allCompleted = false; + continue; + } + int current = progress.getProgress(task.getId()); + // 已达成 + if (current >= task.getAmount()) { + continue; + } + progress.addProgress(task.getId(), amount); + changed = true; + int newValue = progress.getProgress(task.getId()); + if (QEMain.DEBUG) { + + int fixedValue = Math.min(newValue, task.getAmount()); + + player.sendMessage( + ColorUtil.color( + "&7[任务调试] &f" + + task.getDisplayName() + + " &a+" + + amount + + " &7(" + + fixedValue + + "/" + + task.getAmount() + + ")" + ) + ); + } + // 防止超出 + if (newValue > task.getAmount()) { + progress.setProgress(task.getId(), task.getAmount()); + } + } + // 检查是否全部完成 + for (QuestTask task : quest.getTasks().values()) { + int current = progress.getProgress(task.getId()); + if (current < task.getAmount()) { + allCompleted = false; + break; + } + } + // 完成任务 + if (allCompleted) { + progress.setCompleted(true); + changed = true; + // 完成消息 + for (String msg : quest.getCompleteMessages()) { + player.sendMessage(ColorUtil.color(msg)); + } + // reward message + for (String msg : quest.getReward().getMessages()) { + player.sendMessage(ColorUtil.color(msg.replace("{name}", quest.getDisplayName()))); + } + // reward command + for (String cmd : quest.getReward().getCommands()) { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), cmd.replace("%player%", player.getName())); + } + + } + } + if (changed) { + PlayerQuestSaveQueue.markDirty(uuid); + } + } +} diff --git a/src/main/java/com/io/yaohun/questengine/player/PlayerQuestProgress.java b/src/main/java/com/io/yaohun/questengine/player/PlayerQuestProgress.java new file mode 100644 index 0000000..457235a --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/player/PlayerQuestProgress.java @@ -0,0 +1,53 @@ +package com.io.yaohun.questengine.player; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class PlayerQuestProgress { + + private final String questId; + private final Map taskProgressMap = new ConcurrentHashMap<>(); + private volatile boolean completed; + + public PlayerQuestProgress(String questId) { + this.questId = questId; + } + + public String getQuestId() { + return questId; + } + + public int getProgress(String taskId) { + return taskProgressMap.getOrDefault(taskId, 0); + } + + public void addProgress(String taskId, int amount) { + int current = getProgress(taskId); + taskProgressMap.put(taskId, current + amount); + } + + public void setProgress(String taskId, int amount) { + taskProgressMap.put(taskId, amount); + } + + public Map getTaskProgressMap() { + return taskProgressMap; + } + + public boolean isCompleted() { + return completed; + } + + public void setCompleted(boolean completed) { + this.completed = completed; + } + + public PlayerQuestProgress copy() { + PlayerQuestProgress copy = new PlayerQuestProgress(questId); + copy.setCompleted(completed); + for (Map.Entry entry : taskProgressMap.entrySet()) { + copy.setProgress(entry.getKey(), entry.getValue()); + } + return copy; + } +} diff --git a/src/main/java/com/io/yaohun/questengine/player/storage/MySQLPlayerQuestStorage.java b/src/main/java/com/io/yaohun/questengine/player/storage/MySQLPlayerQuestStorage.java new file mode 100644 index 0000000..3c21670 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/player/storage/MySQLPlayerQuestStorage.java @@ -0,0 +1,247 @@ +package com.io.yaohun.questengine.player.storage; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestData; +import com.io.yaohun.questengine.player.PlayerQuestProgress; +import com.io.yaohun.questengine.quest.QuestType; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.FileConfiguration; + +import java.sql.*; +import java.util.Collection; +import java.util.Map; +import java.util.UUID; + +public class MySQLPlayerQuestStorage implements PlayerQuestStorage{ + private final QEMain plugin; + private HikariDataSource dataSource; + private String table; + + public MySQLPlayerQuestStorage(QEMain plugin){ + this.plugin = plugin; + } + + @Override + public void init() { + try { + FileConfiguration ymal = plugin.getConfig(); + String host = ymal.getString("Storage.MySQL.Host"); + int port = ymal.getInt("Storage.MySQL.Port"); + String database = ymal.getString("Storage.MySQL.Database"); + String username = ymal.getString("Storage.MySQL.Username"); + String password = ymal.getString("Storage.MySQL.Password"); + + String prefix = ymal.getString("Storage.MySQL.TablePrefix","auquest_"); + + this.table = prefix + "player_progress"; + + HikariConfig config = new HikariConfig(); + config.setJdbcUrl( + "jdbc:mysql://" + host + ":" + port + "/" + database + + "?useSSL=false" + + "&characterEncoding=utf8" + + "&serverTimezone=Asia/Shanghai" + + "&rewriteBatchedStatements=true" + ); + + config.setUsername(username); + config.setPassword(password); + + config.setMaximumPoolSize(ymal.getInt("Storage.MySQL.Pool.MaximumPoolSize", 10)); + config.setMinimumIdle(ymal.getInt("Storage.MySQL.Pool.MinimumIdle", 2)); + config.setConnectionTimeout(ymal.getLong("Storage.MySQL.Pool.ConnectionTimeout", 10000)); + config.setIdleTimeout(ymal.getLong("Storage.MySQL.Pool.IdleTimeout", 600000)); + config.setMaxLifetime(ymal.getLong("Storage.MySQL.Pool.MaxLifetime", 1800000)); + + config.addDataSourceProperty("cachePrepStmts", "true"); + config.addDataSourceProperty("prepStmtCacheSize", "250"); + config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); + + dataSource = new HikariDataSource(config); + + createTable(); + + Bukkit.getConsoleSender().sendMessage("[AuQuest] MySQLStorage 初始化完成."); + } catch (Exception e) { + plugin.getLogger().warning("[AuQuest] MySQLStorage 初始化失败."); + e.printStackTrace(); + } + } + + private void createTable() throws SQLException { + String progressSql = + "CREATE TABLE IF NOT EXISTS " + table + " (" + + "uuid VARCHAR(36) NOT NULL," + + "quest_id VARCHAR(64) NOT NULL," + + "task_id VARCHAR(64) NOT NULL," + + "progress INT NOT NULL DEFAULT 0," + + "completed TINYINT(1) NOT NULL DEFAULT 0," + + "PRIMARY KEY(uuid, quest_id, task_id)" + + ");"; + + String resetTable = getResetTable(); + + String resetSql = + "CREATE TABLE IF NOT EXISTS " + resetTable + " (" + + "reset_type VARCHAR(16) NOT NULL," + + "reset_key VARCHAR(32) NOT NULL," + + "reset_time BIGINT NOT NULL," + + "PRIMARY KEY(reset_type, reset_key)" + + ");"; + + try (Connection connection = dataSource.getConnection(); + Statement statement = connection.createStatement()) { + statement.executeUpdate(progressSql); + statement.executeUpdate(resetSql); + } + } + + private String getResetTable() { + String prefix = plugin.getConfig().getString("Storage.MySQL.TablePrefix", "auquest_"); + return prefix + "reset_record"; + } + + @Override + public PlayerQuestData load(UUID uuid) { + PlayerQuestData data = new PlayerQuestData(uuid); + String sql = "SELECT quest_id, task_id, progress, completed FROM " + table + " WHERE uuid=?"; + try (Connection connection = dataSource.getConnection(); + PreparedStatement ps = connection.prepareStatement(sql)) { + ps.setString(1, uuid.toString()); + try (ResultSet rs = ps.executeQuery()) { + while (rs.next()) { + String questId = rs.getString("quest_id"); + String taskId = rs.getString("task_id"); + int progressValue = rs.getInt("progress"); + boolean completed = rs.getBoolean("completed"); + PlayerQuestProgress progress = data.getQuestProgress(questId); + if (progress == null) { + progress = new PlayerQuestProgress(questId); + progress.setCompleted(completed); + data.addQuest(progress); + } + progress.setProgress(taskId, progressValue); + if (completed) { + progress.setCompleted(true); + } + } + } + } catch (SQLException e) { + plugin.getLogger().warning("[AuQuest] 玩家数据读取失败: " + data.getUuid()); + e.printStackTrace(); + } + return data; + } + + @Override + public void save(PlayerQuestData data) { + PlayerQuestData snapshot = data.copy(); + String deleteSql = "DELETE FROM " + table + " WHERE uuid=?"; + String insertSql = "INSERT INTO " + table + " (uuid, quest_id, task_id, progress, completed) " + "VALUES (?, ?, ?, ?, ?)"; + try (Connection connection = dataSource.getConnection()) { + connection.setAutoCommit(false); + try (PreparedStatement deletePs = connection.prepareStatement(deleteSql)) { + deletePs.setString(1, snapshot.getUuid().toString()); + deletePs.executeUpdate(); + } + try (PreparedStatement insertPs = connection.prepareStatement(insertSql)) { + for (PlayerQuestProgress progress : snapshot.getQuestProgressMap().values()) { + if (progress.getTaskProgressMap().isEmpty()) { + insertPs.setString(1, snapshot.getUuid().toString()); + insertPs.setString(2, progress.getQuestId()); + insertPs.setString(3, "__quest__"); + insertPs.setInt(4, 0); + insertPs.setBoolean(5, progress.isCompleted()); + insertPs.addBatch(); + continue; + } + for (Map.Entry entry : progress.getTaskProgressMap().entrySet()) { + insertPs.setString(1, snapshot.getUuid().toString()); + insertPs.setString(2, progress.getQuestId()); + insertPs.setString(3, entry.getKey()); + insertPs.setInt(4, entry.getValue()); + insertPs.setBoolean(5, progress.isCompleted()); + insertPs.addBatch(); + } + } + insertPs.executeBatch(); + } + connection.commit(); + } catch (SQLException e) { + plugin.getLogger().warning("[AuQuest] 玩家数据保存失败: " + snapshot.getUuid()); + e.printStackTrace(); + } + } + @Override + public void close() { + if (dataSource != null && !dataSource.isClosed()) { + dataSource.close(); + Bukkit.getConsoleSender().sendMessage("[AuQuest] MySQLStorage 已正常关闭."); + } + } + + @Override + public void deleteQuestsByIds(Collection questIds) { + if (questIds == null || questIds.isEmpty()) { + return; + } + + String sql = "DELETE FROM " + table + " WHERE quest_id = ?"; + + try (Connection connection = dataSource.getConnection(); + PreparedStatement ps = connection.prepareStatement(sql)) { + + for (String questId : questIds) { + ps.setString(1, questId); + ps.addBatch(); + } + + ps.executeBatch(); + + } catch (SQLException e) { + plugin.getLogger().warning("[AuQuest] MySQLStorage 删除刷新任务数据失败."); + e.printStackTrace(); + } + } + + @Override + public boolean tryMarkReset(QuestType type, String resetKey) { + String sql = "INSERT IGNORE INTO " + getResetTable() + + " (reset_type, reset_key, reset_time) VALUES (?, ?, ?)"; + + try (Connection connection = dataSource.getConnection(); + PreparedStatement ps = connection.prepareStatement(sql)) { + + ps.setString(1, type.name()); + ps.setString(2, resetKey); + ps.setLong(3, System.currentTimeMillis()); + + return ps.executeUpdate() == 1; + + } catch (SQLException e) { + plugin.getLogger().warning("[AuQuest] MySQLStorage 记录任务刷新状态失败: " + type + " / " + resetKey); + e.printStackTrace(); + return false; + } + } + + @Override + public void deletePlayer(UUID uuid) { + + String sql = + "DELETE FROM " + table + " WHERE uuid=?"; + + try(Connection connection = dataSource.getConnection(); + PreparedStatement ps = connection.prepareStatement(sql)){ + + ps.setString(1, uuid.toString()); + + ps.executeUpdate(); + + }catch (Exception e){ + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/io/yaohun/questengine/player/storage/PlayerQuestSaveQueue.java b/src/main/java/com/io/yaohun/questengine/player/storage/PlayerQuestSaveQueue.java new file mode 100644 index 0000000..92bc6df --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/player/storage/PlayerQuestSaveQueue.java @@ -0,0 +1,78 @@ +package com.io.yaohun.questengine.player.storage; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestData; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import org.bukkit.Bukkit; +import org.bukkit.scheduler.BukkitTask; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +public class PlayerQuestSaveQueue { + private static final Set dirtyPlayers = new HashSet<>(); + private static BukkitTask task; + + public static void markDirty(UUID uuid) { + synchronized (dirtyPlayers) { + dirtyPlayers.add(uuid); + } + } + + public static void start() { + int intervalSeconds = QEMain.inst().getConfig().getInt("Storage.SaveInterval", 10); + + task = Bukkit.getScheduler().runTaskTimerAsynchronously( + QEMain.inst(), + PlayerQuestSaveQueue::flushAsync, + intervalSeconds * 20L, + intervalSeconds * 20L + ); + } + + public static void removeDirty(UUID uuid){ + synchronized (dirtyPlayers) { + dirtyPlayers.remove(uuid); + } + } + + public static void flushAsync() { + Set copy; + synchronized (dirtyPlayers) { + if (dirtyPlayers.isEmpty()) { + return; + } + copy = new HashSet<>(dirtyPlayers); + dirtyPlayers.clear(); + } + for (UUID uuid : copy) { + PlayerQuestData data = PlayerQuestManager.getCachedPlayerData(uuid); + if (data != null) { + PlayerQuestStorageManager.getStorage().save(data); + } + } + } + + public static void flushSync() { + if (task != null) { + task.cancel(); + task = null; + } + + Set copy; + + synchronized (dirtyPlayers) { + copy = new HashSet<>(dirtyPlayers); + dirtyPlayers.clear(); + } + + for (UUID uuid : copy) { + PlayerQuestData data = PlayerQuestManager.getCachedPlayerData(uuid); + + if (data != null) { + PlayerQuestStorageManager.getStorage().save(data); + } + } + } +} diff --git a/src/main/java/com/io/yaohun/questengine/player/storage/PlayerQuestStorage.java b/src/main/java/com/io/yaohun/questengine/player/storage/PlayerQuestStorage.java new file mode 100644 index 0000000..70f0c16 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/player/storage/PlayerQuestStorage.java @@ -0,0 +1,24 @@ +package com.io.yaohun.questengine.player.storage; + +import com.io.yaohun.questengine.player.PlayerQuestData; +import com.io.yaohun.questengine.quest.QuestType; + +import java.util.Collection; +import java.util.UUID; + +public interface PlayerQuestStorage { + + void init(); + + PlayerQuestData load(UUID uuid); + + void save(PlayerQuestData data); + + void deleteQuestsByIds(Collection questIds); + + boolean tryMarkReset(QuestType type, String resetKey); + + void deletePlayer(UUID uuid); + + void close(); +} diff --git a/src/main/java/com/io/yaohun/questengine/player/storage/PlayerQuestStorageManager.java b/src/main/java/com/io/yaohun/questengine/player/storage/PlayerQuestStorageManager.java new file mode 100644 index 0000000..de25443 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/player/storage/PlayerQuestStorageManager.java @@ -0,0 +1,40 @@ +package com.io.yaohun.questengine.player.storage; + +import com.io.yaohun.questengine.QEMain; +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.FileConfiguration; + +public class PlayerQuestStorageManager { + + private static PlayerQuestStorage storage; + + public static void init(QEMain plugin){ + FileConfiguration config = plugin.getConfig(); + String type = config.getString("Storage.Type","yaml").toLowerCase(); + Bukkit.getConsoleSender().sendMessage("[AuQuest] 数据存储模式: §e"+type); + switch (type){ + case "yaml": + storage = new YamlPlayerQuestStorage(plugin); + break; + case "sqlite": + storage = new SQLitePlayerQuestStorage(plugin); + break; + case "mysql": + storage = new MySQLPlayerQuestStorage(plugin); + break; + default: + storage = new YamlPlayerQuestStorage(plugin); + } + storage.init(); + } + + public static PlayerQuestStorage getStorage(){ + return storage; + } + + public static void close(){ + if(storage != null){ + storage.close(); + } + } +} diff --git a/src/main/java/com/io/yaohun/questengine/player/storage/SQLitePlayerQuestStorage.java b/src/main/java/com/io/yaohun/questengine/player/storage/SQLitePlayerQuestStorage.java new file mode 100644 index 0000000..e3b5835 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/player/storage/SQLitePlayerQuestStorage.java @@ -0,0 +1,257 @@ +package com.io.yaohun.questengine.player.storage; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestData; +import com.io.yaohun.questengine.player.PlayerQuestProgress; +import com.io.yaohun.questengine.quest.QuestType; +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.sql.*; +import java.util.Collection; +import java.util.Map; +import java.util.UUID; + +public class SQLitePlayerQuestStorage implements PlayerQuestStorage{ + + private final QEMain plugin; + private Connection connection; + + public SQLitePlayerQuestStorage(QEMain plugin){ + this.plugin = plugin; + } + + // plugin.getLogger().warning("[AuQuest] 玩家数据保存失败: " + data.getUuid()); + @Override + public void init() { + try { + File folder = plugin.getDataFolder(); + if (!folder.exists()) { + folder.mkdirs(); + } + FileConfiguration config = plugin.getConfig(); + String fileName = config.getString("Storage.SQLite.File", "PlayerData.db"); + File databaseFile = new File(folder, fileName); + + connection = DriverManager.getConnection("jdbc:sqlite:" + databaseFile.getAbsolutePath()); + + createTable(); + + Bukkit.getConsoleSender().sendMessage("[AuQuest] SQLiteStorage 初始化完成."); + } catch (SQLException e) { + plugin.getLogger().warning("[AuQuest] SQLiteStorage 初始化失败."); + e.printStackTrace(); + } + } + + private void createTable() throws SQLException { + String sql = """ + CREATE TABLE IF NOT EXISTS quest_player_progress ( + uuid TEXT NOT NULL, + quest_id TEXT NOT NULL, + task_id TEXT NOT NULL, + progress INTEGER NOT NULL DEFAULT 0, + completed INTEGER NOT NULL DEFAULT 0, + PRIMARY KEY (uuid, quest_id, task_id) + ); + """; + try (Statement statement = connection.createStatement()) { + statement.executeUpdate(sql); + } + + String resetSql = """ + CREATE TABLE IF NOT EXISTS quest_reset_record ( + reset_type TEXT NOT NULL, + reset_key TEXT NOT NULL, + reset_time INTEGER NOT NULL, + PRIMARY KEY(reset_type, reset_key) + ); + """; + + try (Statement statement = connection.createStatement()) { + statement.executeUpdate(sql); + statement.executeUpdate(resetSql); + } + } + + @Override + public synchronized PlayerQuestData load(UUID uuid) { + PlayerQuestData data = new PlayerQuestData(uuid); + String sql = "SELECT quest_id, task_id, progress, completed FROM quest_player_progress WHERE uuid = ?"; + + try (PreparedStatement ps = connection.prepareStatement(sql)) { + ps.setString(1, uuid.toString()); + try (ResultSet rs = ps.executeQuery()) { + while (rs.next()) { + String questId = rs.getString("quest_id"); + String taskId = rs.getString("task_id"); + int progressValue = rs.getInt("progress"); + boolean completed = rs.getInt("completed") == 1; + PlayerQuestProgress progress = data.getQuestProgress(questId); + if (progress == null) { + progress = new PlayerQuestProgress(questId); + progress.setCompleted(completed); + data.addQuest(progress); + } + progress.setProgress(taskId, progressValue); + if (completed) { + progress.setCompleted(true); + } + } + } + } catch (SQLException e) { + plugin.getLogger().warning("[AuQuest] 玩家数据读取失败: " + data.getUuid()); + e.printStackTrace(); + } + return data; + } + + @Override + public synchronized void save(PlayerQuestData data) { + PlayerQuestData snapshot = data.copy(); + String deleteSql = "DELETE FROM quest_player_progress WHERE uuid = ?"; + String insertSql = """ + INSERT INTO quest_player_progress + (uuid, quest_id, task_id, progress, completed) + VALUES (?, ?, ?, ?, ?) + """; + try { + connection.setAutoCommit(false); + try (PreparedStatement deletePs = connection.prepareStatement(deleteSql)) { + deletePs.setString(1, snapshot.getUuid().toString()); + deletePs.executeUpdate(); + } + try (PreparedStatement insertPs = connection.prepareStatement(insertSql)) { + for (PlayerQuestProgress progress : snapshot.getQuestProgressMap().values()) { + for (Map.Entry entry : progress.getTaskProgressMap().entrySet()) { + insertPs.setString(1, snapshot.getUuid().toString()); + insertPs.setString(2, progress.getQuestId()); + insertPs.setString(3, entry.getKey()); + insertPs.setInt(4, entry.getValue()); + insertPs.setInt(5, progress.isCompleted() ? 1 : 0); + insertPs.addBatch(); + } + if (progress.getTaskProgressMap().isEmpty()) { + insertPs.setString(1, snapshot.getUuid().toString()); + insertPs.setString(2, progress.getQuestId()); + insertPs.setString(3, "__quest__"); + insertPs.setInt(4, 0); + insertPs.setInt(5, progress.isCompleted() ? 1 : 0); + insertPs.addBatch(); + } + } + insertPs.executeBatch(); + } + connection.commit(); + } catch (SQLException e) { + try { + connection.rollback(); + } catch (SQLException ignored) { + } + plugin.getLogger().warning("[AuQuest] 玩家数据保存失败: " + snapshot.getUuid()); + e.printStackTrace(); + }finally { + try { + connection.setAutoCommit(true); + } catch (SQLException ignored) { + } + } + } + + @Override + public synchronized void close() { + if (connection == null) { + return; + }try { + connection.close(); + Bukkit.getConsoleSender().sendMessage("[AuQuest] SQLiteStorage 已正常关闭."); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Override + public synchronized void deleteQuestsByIds(Collection questIds) { + if (questIds == null || questIds.isEmpty()) { + return; + } + String sql = "DELETE FROM quest_player_progress WHERE quest_id = ?"; + + try (PreparedStatement ps = connection.prepareStatement(sql)) { + for (String questId : questIds) { + ps.setString(1, questId); + ps.addBatch(); + } + ps.executeBatch(); + } catch (SQLException e) { + plugin.getLogger().warning("[AuQuest] SQLiteStorage 删除刷新任务数据失败."); + e.printStackTrace(); + } + } + + @Override + public synchronized void deletePlayer(UUID uuid) { + + String sql = + "DELETE FROM quest_player_progress WHERE uuid=?"; + + try(PreparedStatement ps = connection.prepareStatement(sql)){ + + ps.setString(1, uuid.toString()); + + ps.executeUpdate(); + + }catch (Exception e){ + e.printStackTrace(); + } + } + + @Override + public synchronized boolean tryMarkReset(QuestType type, String resetKey) { + String sql = "INSERT OR IGNORE INTO quest_reset_record (reset_type, reset_key, reset_time) VALUES (?, ?, ?)"; + + try (PreparedStatement ps = connection.prepareStatement(sql)) { + ps.setString(1, type.name()); + ps.setString(2, resetKey); + ps.setLong(3, System.currentTimeMillis()); + + return ps.executeUpdate() == 1; + + } catch (SQLException e) { + plugin.getLogger().warning("[AuQuest] SQLiteStorage 记录任务刷新状态失败: " + type + " / " + resetKey); + e.printStackTrace(); + return false; + } + } + + public synchronized File exportToYaml() { + + File outFile = new File(plugin.getDataFolder(), "out-sqlite-" + System.currentTimeMillis() + ".yml"); + YamlConfiguration yaml = new YamlConfiguration(); + String sql = "SELECT uuid, quest_id, task_id, progress, completed FROM quest_player_progress ORDER BY uuid, quest_id, task_id"; + + try (PreparedStatement ps = connection.prepareStatement(sql); + ResultSet rs = ps.executeQuery()) { + while (rs.next()) { + String uuid = rs.getString("uuid"); + String questId = rs.getString("quest_id"); + String taskId = rs.getString("task_id"); + int progress = rs.getInt("progress"); + boolean completed = rs.getInt("completed") == 1; + String path = "players." + uuid + ".quests." + questId; + yaml.set(path + ".completed", completed); + yaml.set(path + ".progress." + taskId, progress); + } + + yaml.save(outFile); + return outFile; + + } catch (Exception e) { + plugin.getLogger().warning("[AuQuest] SQLiteStorage 数据导出失败"); + e.printStackTrace(); + return null; + } + } +} diff --git a/src/main/java/com/io/yaohun/questengine/player/storage/YamlPlayerQuestStorage.java b/src/main/java/com/io/yaohun/questengine/player/storage/YamlPlayerQuestStorage.java new file mode 100644 index 0000000..918094e --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/player/storage/YamlPlayerQuestStorage.java @@ -0,0 +1,159 @@ +package com.io.yaohun.questengine.player.storage; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestData; +import com.io.yaohun.questengine.player.PlayerQuestProgress; +import com.io.yaohun.questengine.quest.QuestType; +import org.bukkit.Bukkit; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.Map; +import java.util.UUID; + +public class YamlPlayerQuestStorage implements PlayerQuestStorage { + + private final QEMain plugin; + + public YamlPlayerQuestStorage(QEMain plugin){ + this.plugin = plugin; + } + @Override + public void init() { + File folder = getPlayerFolder(); + if (!folder.exists()) { + folder.mkdirs(); + } + Bukkit.getConsoleSender().sendMessage("[AuQuest] YamlStorage 初始化完成."); + } + + @Override + public PlayerQuestData load(UUID uuid) { + PlayerQuestData data = new PlayerQuestData(uuid); + File file = getPlayerFile(uuid); + if(!file.exists()){ + return data; + } + FileConfiguration yaml = YamlConfiguration.loadConfiguration(file); + ConfigurationSection questsSection = yaml.getConfigurationSection("quests"); + if(questsSection == null){ + return data; + } + for (String questId : questsSection.getKeys(false)){ + PlayerQuestProgress progress = new PlayerQuestProgress(questId); + boolean completed = yaml.getBoolean("quests." + questId + ".completed", false); + progress.setCompleted(completed); + ConfigurationSection progressSection = yaml.getConfigurationSection("quests." + questId + ".progress"); + if (progressSection != null) { + for (String taskId : progressSection.getKeys(false)) { + int value = progressSection.getInt(taskId); + progress.setProgress(taskId, value); + } + } + data.addQuest(progress); + } + return data; + } + + @Override + public void save(PlayerQuestData data) { + PlayerQuestData snapshot = data.copy(); + File file = getPlayerFile(snapshot.getUuid()); + YamlConfiguration yaml = new YamlConfiguration(); + for (PlayerQuestProgress progress : snapshot.getQuestProgressMap().values()) { + String path = "quests." + progress.getQuestId(); + yaml.set(path + ".completed", progress.isCompleted()); + for (Map.Entry entry : progress.getTaskProgressMap().entrySet()) { + yaml.set(path + ".progress." + entry.getKey(), entry.getValue()); + } + } + try { + yaml.save(file); + } catch (IOException e) { + plugin.getLogger().warning("[AuQuest] 玩家数据保存失败: " + snapshot.getUuid()); + e.printStackTrace(); + } + } + + @Override + public void deleteQuestsByIds(Collection questIds) { + File folder = getPlayerFolder(); + File[] files = folder.listFiles((dir, name) -> name.endsWith(".yml")); + if (files == null) { + return; + } + for (File file : files) { + YamlConfiguration yaml = YamlConfiguration.loadConfiguration(file); + boolean changed = false; + for (String questId : questIds) { + String path = "quests." + questId; + + if (yaml.contains(path)) { + yaml.set(path, null); + changed = true; + } + } + if (changed) { + try { + yaml.save(file); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } + + @Override + public boolean tryMarkReset(QuestType type, String resetKey) { + File file = new File(plugin.getDataFolder(), "last_reset.yml"); + + YamlConfiguration yaml = YamlConfiguration.loadConfiguration(file); + + String path = "reset." + type.name(); + + String oldKey = yaml.getString(path); + + if (resetKey.equals(oldKey)) { + return false; + } + + yaml.set(path, resetKey); + yaml.set(path + "_time", System.currentTimeMillis()); + + try { + yaml.save(file); + return true; + } catch (Exception e) { + plugin.getLogger().warning("YAML 记录任务刷新状态失败: " + type + " / " + resetKey); + e.printStackTrace(); + return false; + } + } + + @Override + public void close() { + Bukkit.getConsoleSender().sendMessage("[AuQuest] YamlStorage 已正常关闭."); + } + + @Override + public void deletePlayer(UUID uuid) { + + File file = getPlayerFile(uuid); + + if(file.exists()){ + file.delete(); + } + } + + private File getPlayerFolder() { + return new File(plugin.getDataFolder(), "PlayerData"); + } + + private File getPlayerFile(UUID uuid) { + return new File(getPlayerFolder(), uuid + ".yml"); + } +} diff --git a/src/main/java/com/io/yaohun/questengine/quest/Quest.java b/src/main/java/com/io/yaohun/questengine/quest/Quest.java new file mode 100644 index 0000000..19ff4c9 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/quest/Quest.java @@ -0,0 +1,75 @@ +package com.io.yaohun.questengine.quest; + +import com.io.yaohun.questengine.util.ColorUtil; + +import java.util.List; +import java.util.Map; + +public class Quest { + + private final String id; + private final String displayName; + private final List description; + private final QuestType type; + private final List receiveMessages; + private final List completeMessages; + private final Map tasks; + private final QuestCondition condition; + private final QuestReward reward; + + + public Quest(String id, String displayName, + List description, + QuestType type, + List receiveMessages, + List completeMessages, + Map tasks, + QuestCondition condition, + QuestReward reward) { + this.id = id; + this.displayName = ColorUtil.color(displayName); + this.description = ColorUtil.color(description); + this.type = type; + this.receiveMessages = ColorUtil.color(receiveMessages); + this.completeMessages = ColorUtil.color(completeMessages); + this.tasks = tasks; + this.condition = condition; + this.reward = reward; + } + + public String getId() { + return id; + } + + public String getDisplayName() { + return displayName; + } + + public List getDescription() { + return description; + } + + public QuestType getType() { + return type; + } + + public List getReceiveMessages() { + return receiveMessages; + } + + public List getCompleteMessages() { + return completeMessages; + } + + public Map getTasks() { + return tasks; + } + + public QuestCondition getCondition() { + return condition; + } + + public QuestReward getReward() { + return reward; + } +} \ No newline at end of file diff --git a/src/main/java/com/io/yaohun/questengine/quest/QuestCondition.java b/src/main/java/com/io/yaohun/questengine/quest/QuestCondition.java new file mode 100644 index 0000000..75da4cf --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/quest/QuestCondition.java @@ -0,0 +1,40 @@ +package com.io.yaohun.questengine.quest; + +import java.util.List; + +public class QuestCondition { + + private final int level; + private final List completedQuests; + private final List worlds; + + public QuestCondition(int level, List completedQuests, List worlds) { + this.level = level; + this.completedQuests = completedQuests; + this.worlds = worlds; + } + + public int getLevel() { + return level; + } + + public List getCompletedQuests() { + return completedQuests; + } + + public List getWorlds() { + return worlds; + } + + public boolean hasLevelLimit() { + return level > 0; + } + + public boolean hasCompletedQuestLimit() { + return completedQuests != null && !completedQuests.isEmpty(); + } + + public boolean hasWorldLimit() { + return worlds != null && !worlds.isEmpty(); + } +} \ No newline at end of file diff --git a/src/main/java/com/io/yaohun/questengine/quest/QuestConditionChecker.java b/src/main/java/com/io/yaohun/questengine/quest/QuestConditionChecker.java new file mode 100644 index 0000000..827be0f --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/quest/QuestConditionChecker.java @@ -0,0 +1,67 @@ +package com.io.yaohun.questengine.quest; + +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.player.PlayerQuestProgress; +import com.io.yaohun.questengine.util.ColorUtil; +import com.io.yaohun.questengine.util.MessageUtil; +import org.bukkit.Sound; +import org.bukkit.entity.Player; + +public class QuestConditionChecker { + + public static boolean canAccept(Player player, Quest quest, boolean sendMessage) { + QuestCondition condition = quest.getCondition(); + if (condition == null) { + return true; + } + if (condition.hasLevelLimit()) { + int playerLevel = getPlayerLevel(player); + if (playerLevel < condition.getLevel()) { + if (sendMessage) { + String message = MessageUtil.getMessage("condition_not_quest"); + message = message.replace("{level}", String.valueOf(condition.getLevel())); + MessageUtil.sendMessage(player, message, Sound.ENTITY_VILLAGER_NO); + } + return false; + } + } + if (condition.hasCompletedQuestLimit()) { + for (String needQuestId : condition.getCompletedQuests()) { + PlayerQuestProgress progress = PlayerQuestManager.getProgress(player.getUniqueId(), needQuestId); + if (progress == null || !progress.isCompleted()) { + if (sendMessage) { + String message = MessageUtil.getMessage("condition_not_quest"); + message = message.replace("{quest}", needQuestId); + MessageUtil.sendMessage(player, message, Sound.ENTITY_VILLAGER_NO); + } + return false; + } + } + } + if (condition.hasWorldLimit()) { + String worldName = player.getWorld().getName(); + if (!condition.getWorlds().contains(worldName)) { + if (sendMessage) { + MessageUtil.sendMessageKey(player, "condition_not_world", Sound.ENTITY_VILLAGER_NO); + } + return false; + } + } + return true; + } + + public static boolean canProgress(Player player, Quest quest) { + + QuestCondition condition = quest.getCondition(); + + if (condition == null || !condition.hasWorldLimit()) { + return true; + } + + return condition.getWorlds().contains(player.getWorld().getName()); + } + + private static int getPlayerLevel(Player player) { + return player.getLevel(); // 这里先用原版等级,后续可替换成你的等级系统API + } +} \ No newline at end of file diff --git a/src/main/java/com/io/yaohun/questengine/quest/QuestLoader.java b/src/main/java/com/io/yaohun/questengine/quest/QuestLoader.java new file mode 100644 index 0000000..11d225f --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/quest/QuestLoader.java @@ -0,0 +1,149 @@ +package com.io.yaohun.questengine.quest; + +import com.io.yaohun.questengine.QEMain; +import org.bukkit.Bukkit; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.util.*; + +public class QuestLoader { + + private final QEMain plugin; + + public QuestLoader(QEMain plugin){ + this.plugin = plugin; + } + + public Map loadQuests(){ + Map questMap = new HashMap<>(); + + File folder = new File(plugin.getDataFolder(), "Quests"); + if(!folder.exists()){ + folder.mkdirs(); + return questMap; + } + File[] files = folder.listFiles(((dir, name) -> name.endsWith(".yml"))); + if(files == null || files.length == 0){ + return questMap; + } + int dayCount = 0; + int weekCount = 0; + int monthCount = 0; + int fixedCount = 0; + for (File file : files){ + FileConfiguration config = YamlConfiguration.loadConfiguration(file); + for (String questId : config.getKeys(false)){ + ConfigurationSection section = config.getConfigurationSection(questId); + if(section == null){ + continue; + } + Quest quest = loadQuest(questId, section, file.getName()); + if(quest == null){ + continue; + } + questMap.put(questId, quest); + switch (quest.getType()){ + case DAILY: + dayCount++; + break; + case WEEKLY: + weekCount++; + break; + case MONTHLY: + monthCount++; + break; + case FIXED: + fixedCount++; + break; + } + } + } + Bukkit.getConsoleSender().sendMessage("[AuQuest] 已载入任务: ["+questMap.size()+"个]"); + Bukkit.getConsoleSender().sendMessage(" - 每日 > §e"+dayCount+"个"); + Bukkit.getConsoleSender().sendMessage(" - 每周 > §e"+weekCount+"个"); + Bukkit.getConsoleSender().sendMessage(" - 每月 > §e"+monthCount+"个"); + Bukkit.getConsoleSender().sendMessage(" - 长期 > §e"+fixedCount+"个"); + return questMap; + } + + private Quest loadQuest(String questId, ConfigurationSection section, String fileName){ + try { + String displayName = section.getString("display_name", questId); + List description = section.getStringList("description"); + QuestType questType = QuestType.valueOf( + section.getString("type", "FIXED").toUpperCase() + ); + List receiveMessages = section.getStringList("messages.receive"); + List completeMessages = section.getStringList("messages.complete"); + Map tasks = loadTasks(section.getConfigurationSection("tasks"), questId); + if (tasks.isEmpty()) { + plugin.getLogger().warning("任务 " + questId + " 没有有效任务目标,文件: " + fileName); + return null; + } + QuestCondition condition = loadCondition(section.getConfigurationSection("conditions")); + QuestReward reward = loadReward(section.getConfigurationSection("rewards"), displayName); + return new Quest(questId, displayName, description, questType, receiveMessages, completeMessages, tasks, condition, reward); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + private Map loadTasks(ConfigurationSection section, String questId) { + Map taskMap = new LinkedHashMap<>(); + if (section == null) { + return taskMap; + } + for (String taskId : section.getKeys(false)) { + ConfigurationSection taskSection = section.getConfigurationSection(taskId); + if (taskSection == null) { + continue; + } + try { + QuestTaskType taskType = QuestTaskType.valueOf(taskSection.getString("type", "BREAK").toUpperCase()); + String displayName = taskSection.getString("display_name", taskId); + int amount = taskSection.getInt("amount", 1); + Set targets = new HashSet<>(taskSection.getStringList("targets") + ); + if (targets.isEmpty()) { + //plugin.getLogger().warning("任务 " + questId + " 的目标 " + taskId + " 没有配置 targets"); + continue; + } + QuestTask task = new QuestTask(taskId, taskType, displayName, amount, targets); + taskMap.put(taskId, task); + } catch (Exception e) { + e.printStackTrace(); + } + } + + return taskMap; + } + + private QuestCondition loadCondition(ConfigurationSection section) { + if (section == null) { + return new QuestCondition(0, Collections.emptyList(), Collections.emptyList()); + } + int level = section.getInt("level", 0); + List completedQuests = section.getStringList("completed_quests"); + List worlds = section.getStringList("worlds"); + return new QuestCondition(level, completedQuests, worlds); + } + + private QuestReward loadReward(ConfigurationSection section,String questName) { + if (section == null) { + return new QuestReward(Collections.emptyList(), Collections.emptyList()); + } + List commands = section.getStringList("commands"); + List messages = new ArrayList<>(section.getStringList("messages")); + for (int i = 0; i < messages.size(); i++) { + String line = messages.get(i); + if (line.contains("{name}")) { + messages.set(i, line.replace("{name}", questName)); + } + } + return new QuestReward(commands, messages); + } +} diff --git a/src/main/java/com/io/yaohun/questengine/quest/QuestManager.java b/src/main/java/com/io/yaohun/questengine/quest/QuestManager.java new file mode 100644 index 0000000..95cdb21 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/quest/QuestManager.java @@ -0,0 +1,38 @@ +package com.io.yaohun.questengine.quest; + +import com.io.yaohun.questengine.QEMain; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class QuestManager { + + private static Map questMap = new HashMap<>(); + + public static void reloadQuestManager(QEMain plugin) { + QuestLoader questLoader = new QuestLoader(plugin); + questMap = questLoader.loadQuests(); + } + + public static Quest getQuest(String questId) { + return questMap.get(questId); + } + + public static boolean hasQuest(String questId) { + return questMap.containsKey(questId); + } + + public static Collection getAllQuests() { + return Collections.unmodifiableCollection(questMap.values()); + } + + public static Map getQuestMap() { + return Collections.unmodifiableMap(questMap); + } + + public static int size() { + return questMap.size(); + } +} \ No newline at end of file diff --git a/src/main/java/com/io/yaohun/questengine/quest/QuestResetManager.java b/src/main/java/com/io/yaohun/questengine/quest/QuestResetManager.java new file mode 100644 index 0000000..27cdbe4 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/quest/QuestResetManager.java @@ -0,0 +1,98 @@ +package com.io.yaohun.questengine.quest; + +import com.io.yaohun.questengine.QEMain; +import com.io.yaohun.questengine.player.PlayerQuestManager; +import com.io.yaohun.questengine.player.storage.PlayerQuestStorageManager; +import org.bukkit.Bukkit; +import org.bukkit.scheduler.BukkitTask; + +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.temporal.WeekFields; +import java.util.List; +import java.util.Locale; +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Collectors; + +public class QuestResetManager { + + private static int lastCheckMinute = -1; + private static BukkitTask task; + + public static void start() { + stop(); + int min = 60; + int max = 180; + int rand = ThreadLocalRandom.current().nextInt(min, max + 1); + task = Bukkit.getScheduler().runTaskTimerAsynchronously( + QEMain.inst(), + QuestResetManager::checkReset, + 20L, + 20L * rand + ); + } + + public static void stop() { + if (task != null) { + task.cancel(); + task = null; + } + } + + private static void checkReset() { + LocalDateTime now = LocalDateTime.now(); + if (now.getHour() != 0 || now.getMinute() != 0) { + return; + } + int minuteKey = now.getYear() * 100000 + now.getDayOfYear() * 100 + now.getMinute(); + if (lastCheckMinute == minuteKey) { + return; + } + lastCheckMinute = minuteKey; + resetByType(QuestType.DAILY, getDailyKey(now.toLocalDate())); + if (now.getDayOfWeek() == DayOfWeek.MONDAY) { + resetByType(QuestType.WEEKLY, getWeeklyKey(now.toLocalDate())); + } + if (now.getDayOfMonth() == 1) { + resetByType(QuestType.MONTHLY, getMonthlyKey(now.toLocalDate())); + } + } + + private static void resetByType(QuestType type, String resetKey) { + List questIds = QuestManager.getAllQuests().stream() + .filter(quest -> quest.getType() == type) + .map(Quest::getId) + .collect(Collectors.toList()); + if (questIds.isEmpty()) { + return; + } + boolean canReset = PlayerQuestStorageManager.getStorage().tryMarkReset(type, resetKey); + if (!canReset) { + QEMain.inst().getLogger().info(type + " 任务今日/本期已由其他实例刷新,跳过: " + resetKey); + return; + } + PlayerQuestStorageManager.getStorage().deleteQuestsByIds(questIds); + Bukkit.getScheduler().runTask( + QEMain.inst(), + () -> PlayerQuestManager.removeQuestsFromCache(questIds) + ); + QEMain.inst().getLogger().info("[AuQests] 已刷新 " + type + " 任务,resetKey=" + resetKey + ",清理任务数: " + questIds.size()); + } + + private static String getDailyKey(LocalDate date) { + return "DAILY_" + date; + } + + private static String getWeeklyKey(LocalDate date) { + WeekFields weekFields = WeekFields.of(Locale.CHINA); + int week = date.get(weekFields.weekOfWeekBasedYear()); + int year = date.get(weekFields.weekBasedYear()); + return "WEEKLY_" + year + "-W" + week; + } + + private static String getMonthlyKey(LocalDate date) { + return "MONTHLY_" + date.getYear() + "-" + String.format("%02d", date.getMonthValue()); + } +} diff --git a/src/main/java/com/io/yaohun/questengine/quest/QuestReward.java b/src/main/java/com/io/yaohun/questengine/quest/QuestReward.java new file mode 100644 index 0000000..839576f --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/quest/QuestReward.java @@ -0,0 +1,25 @@ +package com.io.yaohun.questengine.quest; + +import com.io.yaohun.questengine.util.ColorUtil; +import org.bukkit.entity.Player; + +import java.util.List; + +public class QuestReward { + + private final List commands; + private final List messages; + + public QuestReward(List commands, List messages) { + this.commands = commands; + this.messages = ColorUtil.color(messages); + } + + public List getCommands() { + return commands; + } + + public List getMessages() { + return messages; + } +} diff --git a/src/main/java/com/io/yaohun/questengine/quest/QuestTask.java b/src/main/java/com/io/yaohun/questengine/quest/QuestTask.java new file mode 100644 index 0000000..fe711c4 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/quest/QuestTask.java @@ -0,0 +1,46 @@ +package com.io.yaohun.questengine.quest; + +import org.bukkit.Bukkit; + +import java.util.Set; + +public class QuestTask { + + private final String id; + private final QuestTaskType type; + private final String displayName; + private final int amount; + private final Set targets; + + public QuestTask(String id, QuestTaskType type, String displayName, int amount, Set targets) { + this.id = id; + this.type = type; + this.displayName = displayName; + this.amount = amount; + this.targets = targets; + } + + public String getId() { + return id; + } + + public QuestTaskType getType() { + return type; + } + + public String getDisplayName() { + return displayName; + } + + public int getAmount() { + return amount; + } + + public Set getTargets() { + return targets; + } + + public boolean isTarget(String target) { + return targets.contains(target); + } +} diff --git a/src/main/java/com/io/yaohun/questengine/quest/QuestTaskType.java b/src/main/java/com/io/yaohun/questengine/quest/QuestTaskType.java new file mode 100644 index 0000000..8772f43 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/quest/QuestTaskType.java @@ -0,0 +1,54 @@ +package com.io.yaohun.questengine.quest; + +public enum QuestTaskType { + + BREAK_BLOCK("破坏方块"), + PLACE_BLOCK("放置方块"), + CRAFT_ITEM("合成物品"), + PICKUP_ITEM("拾取物品"), + FISH_ITEM("钓鱼获得物品"), + FISH_STAR("钓起鱼的星级"), + PLACE_BUCKET("监听倒水、倒岩浆、放置粉雪"), + FILL_BUCKET("监听装水、装岩浆、装牛奶"), + HARVEST_CROP("收获农作物"), + EXP_GAIN("经验获取"), + EXP_RPG("RPG经验获取"), // 预留接口 + ONLINE_TODAY("今日在线时长"), // 预留接口 + ONLINE_WEEK("本周在线时长"), // 预留接口 + ONLINE_MONTH("本月在线时长"), // 预留接口 + BREED("繁殖动物"), + COLLECT_LOOT("战利品获取"), // 预留接口 + COLLECT_ENTITY("剪羊毛,取蘑菇煲"), + COLLECT_BLOCK("收集蜂蜜"), + TAME_ENTITY("驯服实体"), + VILLAGER_TRADE_ITEM("村民交易"), + VILLAGER_TRADE_JOB("村民交易"), + BREW_POTION("酿造药水"), + BREW_POTION_COUNT("酿造药水次数"), + USE_ANVIL("铁砧使用"), + USE_ITEM("使用物品"), // 预留接口 + ENCHANT_ITEM("附魔物品"), + FEED_ANIMAL("喂动物"), + FEED_PLAYER("玩家东西"), + SMELT_ORE("烧制矿物"), + SMELT_FOOD("烧制食物"), + INTERACT_NPC("交互NPC"), + INTERACT_ENTITY("交互实体"), + INTERACT_ITEM("交互手持物品"), + SEND_COMMAND("发送命令"), + SEND_CHAT("发送聊天"), + OPEN_GUI_TITLE("打开指定标题菜单"), + OPEN_GUI_TYPE("打开指定Type菜单"), + KILL_TYPE("击杀原版怪"), + KILL_MYTHIC("击杀MM怪"); + + private final String displayName; + + QuestTaskType(String displayName){ + this.displayName = displayName; + } + + public String getDisplayName() { + return displayName; + } +} diff --git a/src/main/java/com/io/yaohun/questengine/quest/QuestType.java b/src/main/java/com/io/yaohun/questengine/quest/QuestType.java new file mode 100644 index 0000000..072cfb0 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/quest/QuestType.java @@ -0,0 +1,19 @@ +package com.io.yaohun.questengine.quest; + +public enum QuestType { + + DAILY("每日"), + WEEKLY("每周"), + MONTHLY("每月"), + FIXED("长期"); + + private final String displayName; + + QuestType(String displayName){ + this.displayName = displayName; + } + + public String getDisplayName(){ + return displayName; + } +} diff --git a/src/main/java/com/io/yaohun/questengine/util/ColorUtil.java b/src/main/java/com/io/yaohun/questengine/util/ColorUtil.java new file mode 100644 index 0000000..7ad7216 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/util/ColorUtil.java @@ -0,0 +1,37 @@ +package com.io.yaohun.questengine.util; + +import org.bukkit.ChatColor; + +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +public class ColorUtil { + + private static final Pattern HEX_PATTERN = Pattern.compile("#[a-fA-F0-9]{6}"); + + public static String color(String text) { + if (text == null) { + return ""; + } + Matcher matcher = HEX_PATTERN.matcher(text); + while (matcher.find()) { + String hexCode = text.substring(matcher.start(), matcher.end()); + String replaceSharp = hexCode.replace('#', 'x'); + char[] ch = replaceSharp.toCharArray(); + StringBuilder builder = new StringBuilder(); + for (char c : ch) { + builder.append("&").append(c); + } + text = text.replace(hexCode, builder.toString()); + matcher = HEX_PATTERN.matcher(text); + } + + return ChatColor.translateAlternateColorCodes('&', text); + } + + public static List color(List list) { + return list.stream().map(ColorUtil::color).collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/src/main/java/com/io/yaohun/questengine/util/MessageUtil.java b/src/main/java/com/io/yaohun/questengine/util/MessageUtil.java new file mode 100644 index 0000000..a3229e9 --- /dev/null +++ b/src/main/java/com/io/yaohun/questengine/util/MessageUtil.java @@ -0,0 +1,71 @@ +package com.io.yaohun.questengine.util; + +import com.io.yaohun.questengine.QEMain; +import org.bukkit.Bukkit; +import org.bukkit.Sound; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; + +import java.io.File; +import java.util.HashMap; + +public class MessageUtil { + + private static HashMap messageMap = new HashMap<>(); + + public static void init(QEMain plugin) { + messageMap.clear(); + File file = new File(plugin.getDataFolder(),"lang.yml"); + // 如果没有这个文件就新建一个~ + if(!file.exists()){ + plugin.saveResource("lang.yml",false); + } + FileConfiguration yml = YamlConfiguration.loadConfiguration(file); + for (String ymlKey : yml.getKeys(false)){ + ConfigurationSection section = yml.getConfigurationSection(ymlKey); + for (String key : section.getKeys(false)){ + String message = ColorUtil.color(section.getString(key)); + messageMap.put(key,message.replace("&","§")); + } + } + } + + public static String getMessage(String key){ + if(messageMap.containsKey(key)){ + return messageMap.get(key); + } + return "§c未找到节点.§7#"+key; + } + + public static void broadcast(String msg) { + Bukkit.getServer().broadcastMessage( msg.replace("&","§")); + } + + public static void sendMessage(CommandSender sender, String message){ + sender.sendMessage(message); + } + + public static void sendMessageKey(CommandSender sender, String key, Sound sound){ + sender.sendMessage(getMessage(key)); + if(sender instanceof Player player){ + player.playSound(player.getLocation(),sound,1,1); + } + } + + public static void sendMessage(CommandSender sender, String message, Sound sound){ + sender.sendMessage(message); + if(sender instanceof Player player){ + player.playSound(player.getLocation(),sound,1,1); + } + } + + public static void sendDescMessage(CommandSender sender, String message, Sound sound){ + sender.sendMessage("§f[§c消息§f] §a正确用法: §e"+message); + if(sender instanceof Player player){ + player.playSound(player.getLocation(),sound,1,1); + } + } +} diff --git a/src/main/resources/Quests/新手任务.yml b/src/main/resources/Quests/新手任务.yml new file mode 100644 index 0000000..b6fbcfb --- /dev/null +++ b/src/main/resources/Quests/新手任务.yml @@ -0,0 +1,44 @@ +# 任务代号 玩家接受任务 /aquest js 代号 玩家名 +quest_1: + # 任务名 + display_name: "&a[初级] 新手成长之路①" + # 任务描述内容 + description: + - "&7完成基础生存挑战任务" + - "&7砍伐指定木材,熟悉基础资源收集" + # 任务类型 DAILY、WEEKLY、MONTHLY、FIXED + type: DAILY + # 消息 + messages: + receive: + - "&a你接受了任务:&f新手成长之路①" + complete: + - "&a任务完成:&f新手成长之路①" + - "&7奖励已发放,请继续成长。" + conditions: + level: 0 + completed_quests: [] + worlds: [] + # 任务列表 + tasks: + # 任务id + id_1: + # 任务类型暂定: BREAK、PLACE、KILL + type: BREAK_BLOCK + # 任务名 + display_name: 砍伐橡木*128 + # 任务数量 + amount: 128 + # 触发目标列表 + targets: + - SPRUCE_LOG + - SPRUCE_WOOD + - STRIPPED_SPRUCE_LOG + - STRIPPED_SPRUCE_WOOD + # 完成任务后触发的内容 + rewards: + commands: + - "dlevel give %player% 12000" + - "points give %player% 5" + messages: + - "&a{name}任务已完成" \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..c42a5a7 --- /dev/null +++ b/src/main/resources/config.yml @@ -0,0 +1,36 @@ +Storage: + Type: yaml # yaml / sqlite / mysql + SQLite: + File: PlayerData.db + SaveInterval: 10 + MySQL: + Host: localhost + Port: 3306 + Database: quest + Username: root + Password: root + TablePrefix: AuQuest_ + + Pool: + MaximumPoolSize: 10 + MinimumIdle: 2 + ConnectionTimeout: 10000 + IdleTimeout: 600000 + MaxLifetime: 1800000 +FoodType: + - COOKED_BEEF + - COOKED_CHICKEN + - COOKED_MUTTON + - COOKED_RABBIT + - BAKED_POTATO +OreType: + - IRON_INGOT + - GOLD_INGOT + - COPPER_INGOT + - NETHERITE_SCRAP + - DIAMOND + - EMERALD + - REDSTONE + - COAL + - QUARTZ + - LAPIS_LAZULI \ No newline at end of file diff --git a/src/main/resources/lang.yml b/src/main/resources/lang.yml new file mode 100644 index 0000000..3f1ccaa --- /dev/null +++ b/src/main/resources/lang.yml @@ -0,0 +1,4 @@ +Message: + condition_not_level: "等级不足,需要将等级提高至 {level}" + condition_not_quest: "需要将 {quest} 任务完成后才能接受此任务." + condition_not_world: "需要在指定世界才能执行此任务." \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..601da9f --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,14 @@ +name: AuQuestEngine +main: com.io.yaohun.questengine.QEMain +version: 1.0.6 +api-version: 1.21 +author: yaohun +softdepend: + - Citizens + - MythicMobs + - PlaceholderAPI + - CustomFishing + - CustomCrops +commands: + aquest: + aquestadmin: