初始化项目
This commit is contained in:
16
.gitignore
vendored
Normal file
16
.gitignore
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
target/
|
||||
out/
|
||||
lib/
|
||||
libs/
|
||||
.vscode/
|
||||
.codex/
|
||||
.idea/
|
||||
*.iml
|
||||
*.class
|
||||
*.log
|
||||
logs/
|
||||
*.db
|
||||
*.sqlite
|
||||
*.sqlite3
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
130
pom.xml
Normal file
130
pom.xml
Normal file
@@ -0,0 +1,130 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.example</groupId>
|
||||
<artifactId>AuQuestEngine</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>papermc-repo</id>
|
||||
<url>https://repo.papermc.io/repository/maven-public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>public-survive</id>
|
||||
<url>https://repo.aurora-pixels.com/repository/public-survive/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>momi-releases</id>
|
||||
<url>https://repo.momirealms.net/releases/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>5.1.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
<version>8.4.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<version>3.46.1.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.papermc.paper</groupId>
|
||||
<artifactId>paper-api</artifactId>
|
||||
<version>1.21.11-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.clip.placeholderapi</groupId>
|
||||
<artifactId>PlaceholderAPI</artifactId>
|
||||
<version>2.12.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.citizensnpcs</groupId>
|
||||
<artifactId>Citizens</artifactId>
|
||||
<version>2.0.41</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.lumine.mythic.bukkit</groupId>
|
||||
<artifactId>MythicMobs</artifactId>
|
||||
<version>5.12.0-SNAPSHOT-548b7d33</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.momirealms</groupId>
|
||||
<artifactId>custom-fishing</artifactId>
|
||||
<version>2.3.23.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.momirealms</groupId>
|
||||
<artifactId>custom-crops</artifactId>
|
||||
<version>3.6.52</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/*.SF</exclude>
|
||||
<exclude>META-INF/*.DSA</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
|
||||
</transformers>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>com.zaxxer.hikari</pattern>
|
||||
<shadedPattern>com.io.yaohun.questengine.libs.hikari</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
101
src/main/java/com/io/yaohun/questengine/QEMain.java
Normal file
101
src/main/java/com/io/yaohun/questengine/QEMain.java
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
137
src/main/java/com/io/yaohun/questengine/api/AuQuestAPI.java
Normal file
137
src/main/java/com/io/yaohun/questengine/api/AuQuestAPI.java
Normal file
@@ -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<String> 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<String> getActiveQuests(UUID uuid) {
|
||||
PlayerQuestData data = PlayerQuestManager.getPlayerData(uuid);
|
||||
|
||||
List<String> list = new ArrayList<>();
|
||||
|
||||
for (PlayerQuestProgress progress : data.getQuestProgressMap().values()) {
|
||||
if (!progress.isCompleted()) {
|
||||
list.add(progress.getQuestId());
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public static List<String> getCompletedQuests(UUID uuid){
|
||||
PlayerQuestData data = PlayerQuestManager.getPlayerData(uuid);
|
||||
List<String> 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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
36
src/main/java/com/io/yaohun/questengine/config/Config.java
Normal file
36
src/main/java/com/io/yaohun/questengine/config/Config.java
Normal file
@@ -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<String> foodTypeList = new ArrayList<>();
|
||||
private static List<String> 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<String> getFoodTypeList() {
|
||||
return foodTypeList;
|
||||
}
|
||||
|
||||
public static List<String> getOreTypeList() {
|
||||
return oreTypeList;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<BREAK_BLOCK>] 玩家 "+player.getName()+" 破坏了方块 "+target);
|
||||
}
|
||||
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.BREAK_BLOCK,
|
||||
target,
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<PLACE_BLOCK>] 玩家 "+player.getName()+" 放置了方块 "+target);
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.PLACE_BLOCK,
|
||||
target,
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<BREED>] 玩家 "+player.getName()+" 人工繁殖了 "+animals.getType().name());
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.BREED,
|
||||
animals.getType().name(),
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<BREW_POTION>] 玩家 " + player.getName() + " 酿造了 " + potionType.name());
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.BREW_POTION,
|
||||
potionType.name(),
|
||||
1
|
||||
);
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.BREW_POTION_COUNT,
|
||||
"ALL",
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<PLACE_BUCKET>] 玩家 "+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("[调试 - 任务<PLACE_BUCKET>] 玩家 " + player.getName() + " 倒出了 " + material.name());
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.PLACE_BUCKET,
|
||||
material.name(),
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<COLLECT_ENTITY>] 玩家 " + 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("[调试 - 任务<COLLECT_ENTITY>] 玩家 "+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("[调试 - 任务<COLLECT_BLOCK>] 玩家 " + player.getName() + " 收集蜂箱 " + target);
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.COLLECT_BLOCK,
|
||||
target,
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<SEND_COMMAND>] 玩家 "+player.getName()+" 执行了命令 "+command);
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.SEND_COMMAND,
|
||||
command,
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<CRAFT_ITEM>] 玩家 "+player.getName()+" 合成了 "+material.name());
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.CRAFT_ITEM,
|
||||
material.name(),
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<ENCHANT_ITEM>] 玩家 " + player.getName() + " 附魔了 "+material.name());
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.ENCHANT_ITEM,
|
||||
material.name(),
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<EXP_GAIN>] 玩家 "+player.getName()+" 获得经验 "+e.getAmount());
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.EXP_GAIN,
|
||||
null,
|
||||
e.getAmount()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<FEED_ANIMAL>] 玩家 "+player.getName()+" 投喂了 "+animals.getType().name());
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.FEED_ANIMAL,
|
||||
animals.getType().name(),
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<FEED_PLAYER>] 玩家 "+player.getName()+" 吃掉了 "+item.getType().name());
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.FEED_PLAYER,
|
||||
item.getType().name(),
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<FISH_ITEM>] 玩家 "+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("[调试 - 任务<FISH_STAR>] 玩家 "+player.getName()+" 钓起来了星级鱼 "+group);
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.FISH_STAR,
|
||||
group,
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<HARVEST_CROP>] 玩家 " + 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("[调试 - 任务<HARVEST_CROP>] 玩家 " + player.getName() + " 收获了 " + cropId);
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.HARVEST_CROP,
|
||||
cropId,
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<INTERACT_ENTITY>] 玩家 "+player.getName()+" 正在交互实体 "+e.getRightClicked().getType().name());
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.INTERACT_ENTITY,
|
||||
e.getRightClicked().getType().name(),
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<INTERACT_ITEM>] 玩家 " + player.getName() + " 正在交互手持物品 " + material.name());
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.INTERACT_ITEM,
|
||||
material.name(),
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<INTERACT_NPC>] 玩家 "+player.getName()+" 正在交互NPC "+target);
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.INTERACT_NPC,
|
||||
target,
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<KILL_MYTHIC>] 玩家 "+player.getName()+" 击杀了 "+mobType.getInternalName());
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.KILL_MYTHIC,
|
||||
mobType.getInternalName(),
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<KILL_TYPE>] 玩家 "+killer.getName()+" 击杀了 "+e.getEntity().getType().name());
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
killer.getUniqueId(),
|
||||
QuestTaskType.KILL_TYPE,
|
||||
e.getEntity().getType().name(),
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<OPEN_GUI_TITLE>] 玩家 "+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("[调试 - 任务<OPEN_GUI_TYPE>] 玩家 "+player.getName()+" 正在打开 "+inventory.getType().name());
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.OPEN_GUI_TYPE,
|
||||
inventory.getType().name(),
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<PICKUP_ITEM>] 玩家 "+player.getName()+" 拾取了 "+material.name());
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.PICKUP_ITEM,
|
||||
material.name(),
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<SMELT_FOOD>] 玩家 "+player.getName()+" 在熔炉取出了 "+result.name());
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.SMELT_FOOD,
|
||||
result.name(),
|
||||
amount
|
||||
);
|
||||
}
|
||||
|
||||
private boolean isFood(Material material) {
|
||||
List<String> 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;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<SMELT_ORE>] 玩家 "+player.getName()+" 在熔炉取出了 "+result.name());
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.SMELT_ORE,
|
||||
result.name(),
|
||||
amount
|
||||
);
|
||||
}
|
||||
|
||||
private boolean isOre(Material material){
|
||||
List<String> 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;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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("[调试 - 任务<TAME_ENTITY>] 玩家 "+player.getName()+" 驯服了 "+entityType.name());
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.TAME_ENTITY,
|
||||
entityType.name(),
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<USE_ANVIL>] 玩家 " + player.getName() + " 使用了铁砧 "+material.name());
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
player.getUniqueId(),
|
||||
QuestTaskType.USE_ANVIL,
|
||||
material.name(),
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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("[调试 - 任务<VILLAGER_TRADE_ITEM>] 玩家 "+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("[调试 - 任务<VILLAGER_TRADE_JOB>] 玩家 "+player.getName()+" 向 "+villager.getProfession().name()+" 村民进行交易");
|
||||
}
|
||||
PlayerQuestManager.addProgress(
|
||||
playerUuid,
|
||||
QuestTaskType.VILLAGER_TRADE_JOB,
|
||||
villager.getProfession().name(),
|
||||
recipe.getVillagerExperience()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<String, PlayerQuestProgress> 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<String, PlayerQuestProgress> getQuestProgressMap() {
|
||||
return questProgressMap;
|
||||
}
|
||||
|
||||
public PlayerQuestData copy() {
|
||||
PlayerQuestData copy = new PlayerQuestData(uuid);
|
||||
for (PlayerQuestProgress progress : questProgressMap.values()) {
|
||||
copy.addQuest(progress.copy());
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
@@ -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<UUID, PlayerQuestData> 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<String> 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<UUID, PlayerQuestData> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<String, Integer> 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<String, Integer> 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<String, Integer> entry : taskProgressMap.entrySet()) {
|
||||
copy.setProgress(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
@@ -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<String, Integer> 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<String> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<UUID> 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<UUID> 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<UUID> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<String> questIds);
|
||||
|
||||
boolean tryMarkReset(QuestType type, String resetKey);
|
||||
|
||||
void deletePlayer(UUID uuid);
|
||||
|
||||
void close();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<String, Integer> 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<String> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<String, Integer> 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<String> 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");
|
||||
}
|
||||
}
|
||||
75
src/main/java/com/io/yaohun/questengine/quest/Quest.java
Normal file
75
src/main/java/com/io/yaohun/questengine/quest/Quest.java
Normal file
@@ -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<String> description;
|
||||
private final QuestType type;
|
||||
private final List<String> receiveMessages;
|
||||
private final List<String> completeMessages;
|
||||
private final Map<String, QuestTask> tasks;
|
||||
private final QuestCondition condition;
|
||||
private final QuestReward reward;
|
||||
|
||||
|
||||
public Quest(String id, String displayName,
|
||||
List<String> description,
|
||||
QuestType type,
|
||||
List<String> receiveMessages,
|
||||
List<String> completeMessages,
|
||||
Map<String, QuestTask> 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<String> getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public QuestType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public List<String> getReceiveMessages() {
|
||||
return receiveMessages;
|
||||
}
|
||||
|
||||
public List<String> getCompleteMessages() {
|
||||
return completeMessages;
|
||||
}
|
||||
|
||||
public Map<String, QuestTask> getTasks() {
|
||||
return tasks;
|
||||
}
|
||||
|
||||
public QuestCondition getCondition() {
|
||||
return condition;
|
||||
}
|
||||
|
||||
public QuestReward getReward() {
|
||||
return reward;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.io.yaohun.questengine.quest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class QuestCondition {
|
||||
|
||||
private final int level;
|
||||
private final List<String> completedQuests;
|
||||
private final List<String> worlds;
|
||||
|
||||
public QuestCondition(int level, List<String> completedQuests, List<String> worlds) {
|
||||
this.level = level;
|
||||
this.completedQuests = completedQuests;
|
||||
this.worlds = worlds;
|
||||
}
|
||||
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public List<String> getCompletedQuests() {
|
||||
return completedQuests;
|
||||
}
|
||||
|
||||
public List<String> 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();
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
149
src/main/java/com/io/yaohun/questengine/quest/QuestLoader.java
Normal file
149
src/main/java/com/io/yaohun/questengine/quest/QuestLoader.java
Normal file
@@ -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<String, Quest> loadQuests(){
|
||||
Map<String, Quest> 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<String> description = section.getStringList("description");
|
||||
QuestType questType = QuestType.valueOf(
|
||||
section.getString("type", "FIXED").toUpperCase()
|
||||
);
|
||||
List<String> receiveMessages = section.getStringList("messages.receive");
|
||||
List<String> completeMessages = section.getStringList("messages.complete");
|
||||
Map<String, QuestTask> 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<String, QuestTask> loadTasks(ConfigurationSection section, String questId) {
|
||||
Map<String, QuestTask> 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<String> 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<String> completedQuests = section.getStringList("completed_quests");
|
||||
List<String> 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<String> commands = section.getStringList("commands");
|
||||
List<String> 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);
|
||||
}
|
||||
}
|
||||
@@ -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<String, Quest> 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<Quest> getAllQuests() {
|
||||
return Collections.unmodifiableCollection(questMap.values());
|
||||
}
|
||||
|
||||
public static Map<String, Quest> getQuestMap() {
|
||||
return Collections.unmodifiableMap(questMap);
|
||||
}
|
||||
|
||||
public static int size() {
|
||||
return questMap.size();
|
||||
}
|
||||
}
|
||||
@@ -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<String> 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());
|
||||
}
|
||||
}
|
||||
@@ -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<String> commands;
|
||||
private final List<String> messages;
|
||||
|
||||
public QuestReward(List<String> commands, List<String> messages) {
|
||||
this.commands = commands;
|
||||
this.messages = ColorUtil.color(messages);
|
||||
}
|
||||
|
||||
public List<String> getCommands() {
|
||||
return commands;
|
||||
}
|
||||
|
||||
public List<String> getMessages() {
|
||||
return messages;
|
||||
}
|
||||
}
|
||||
46
src/main/java/com/io/yaohun/questengine/quest/QuestTask.java
Normal file
46
src/main/java/com/io/yaohun/questengine/quest/QuestTask.java
Normal file
@@ -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<String> targets;
|
||||
|
||||
public QuestTask(String id, QuestTaskType type, String displayName, int amount, Set<String> 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<String> getTargets() {
|
||||
return targets;
|
||||
}
|
||||
|
||||
public boolean isTarget(String target) {
|
||||
return targets.contains(target);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
19
src/main/java/com/io/yaohun/questengine/quest/QuestType.java
Normal file
19
src/main/java/com/io/yaohun/questengine/quest/QuestType.java
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
37
src/main/java/com/io/yaohun/questengine/util/ColorUtil.java
Normal file
37
src/main/java/com/io/yaohun/questengine/util/ColorUtil.java
Normal file
@@ -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<String> color(List<String> list) {
|
||||
return list.stream().map(ColorUtil::color).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -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<String,String> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
44
src/main/resources/Quests/新手任务.yml
Normal file
44
src/main/resources/Quests/新手任务.yml
Normal file
@@ -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}任务已完成"
|
||||
36
src/main/resources/config.yml
Normal file
36
src/main/resources/config.yml
Normal file
@@ -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
|
||||
4
src/main/resources/lang.yml
Normal file
4
src/main/resources/lang.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
Message:
|
||||
condition_not_level: "等级不足,需要将等级提高至 {level}"
|
||||
condition_not_quest: "需要将 {quest} 任务完成后才能接受此任务."
|
||||
condition_not_world: "需要在指定世界才能执行此任务."
|
||||
14
src/main/resources/plugin.yml
Normal file
14
src/main/resources/plugin.yml
Normal file
@@ -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:
|
||||
Reference in New Issue
Block a user