本文最后更新于227 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com
源代码
package com.example.sjrplugin;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
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.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.logging.Level;
public class SJRPlugin extends JavaPlugin implements Listener {
private FileConfiguration tasksConfig;
private FileConfiguration materialsConfig;
private File tasksFile;
private File materialsFile;
@Override
public void onEnable() {
// 创建/加载配置文件
if (!getDataFolder().exists()) {
getDataFolder().mkdir();
}
tasksFile = new File(getDataFolder(), "tasks.yml");
materialsFile = new File(getDataFolder(), "materials.yml");
if (!tasksFile.exists()) {
try {
tasksFile.createNewFile();
} catch (IOException e) {
getLogger().log(Level.SEVERE, "无法创建任务配置文件", e);
}
}
if (!materialsFile.exists()) {
try {
materialsFile.createNewFile();
} catch (IOException e) {
getLogger().log(Level.SEVERE, "无法创建材料配置文件", e);
}
}
tasksConfig = YamlConfiguration.loadConfiguration(tasksFile);
materialsConfig = YamlConfiguration.loadConfiguration(materialsFile);
// 注册事件监听器
getServer().getPluginManager().registerEvents(this, this);
getLogger().info("物品收集任务插件已启用!");
}
@Override
public void onDisable() {
saveConfigs();
getLogger().info("物品收集任务插件已禁用!");
}
private void saveConfigs() {
try {
tasksConfig.save(tasksFile);
materialsConfig.save(materialsFile);
} catch (IOException e) {
getLogger().log(Level.SEVERE, "保存配置文件时出错", e);
}
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (args.length == 0) {
sender.sendMessage(ChatColor.RED + "用法: /sjr <create|delete|bind|rw|sj|setrw> ...");
return true;
}
String subCommand = args[0].toLowerCase();
switch (subCommand) {
case "create":
return handleCreate(sender, args);
case "delete":
return handleDelete(sender, args);
case "bind":
return handleBind(sender, args);
case "rw":
return handleRW(sender, args);
case "sj":
return handleSJ(sender, args);
case "setrw":
return handleSetRW(sender, args);
default:
sender.sendMessage(ChatColor.RED + "未知命令。用法: /sjr <create|delete|bind|rw|sj|setrw> ...");
return true;
}
}
private boolean handleCreate(CommandSender sender, String[] args) {
if (args.length < 3) {
sender.sendMessage(ChatColor.RED + "用法: /sjr create <rw|cl> <名称>");
return true;
}
String type = args[1].toLowerCase();
String name = args[2];
if (type.equals("rw")) {
// 创建任务
if (tasksConfig.contains("tasks." + name)) {
sender.sendMessage(ChatColor.RED + "任务 '" + name + "' 已存在!");
return true;
}
tasksConfig.set("tasks." + name + ".commands", new ArrayList<String>());
saveConfigs();
sender.sendMessage(ChatColor.GREEN + "任务 '" + name + "' 创建成功!");
} else if (type.equals("cl")) {
// 创建材料
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "只有玩家可以执行此命令!");
return true;
}
Player player = (Player) sender;
ItemStack item = player.getInventory().getItemInMainHand();
if (item.getType() == Material.AIR) {
sender.sendMessage(ChatColor.RED + "你必须手持一个物品!");
return true;
}
if (materialsConfig.contains("materials." + name)) {
sender.sendMessage(ChatColor.RED + "材料 '" + name + "' 已存在!");
return true;
}
ItemMeta meta = item.getItemMeta();
String displayName = meta.hasDisplayName() ? meta.getDisplayName() : "";
String lore = meta.hasLore() && !meta.getLore().isEmpty() ? meta.getLore().get(0) : "";
materialsConfig.set("materials." + name + ".material", item.getType().toString());
materialsConfig.set("materials." + name + ".displayname", displayName);
materialsConfig.set("materials." + name + ".lore", lore);
saveConfigs();
sender.sendMessage(ChatColor.GREEN + "材料 '" + name + "' 创建成功!");
} else {
sender.sendMessage(ChatColor.RED + "用法: /sjr create <rw|cl> <名称>");
return true;
}
return true;
}
private boolean handleDelete(CommandSender sender, String[] args) {
if (args.length < 3) {
sender.sendMessage(ChatColor.RED + "用法: /sjr delete rw <任务名称>");
return true;
}
String type = args[1].toLowerCase();
String name = args[2];
if (type.equals("rw")) {
if (!tasksConfig.contains("tasks." + name)) {
sender.sendMessage(ChatColor.RED + "任务 '" + name + "' 不存在!");
return true;
}
tasksConfig.set("tasks." + name, null);
saveConfigs();
sender.sendMessage(ChatColor.GREEN + "任务 '" + name + "' 删除成功!");
} else {
sender.sendMessage(ChatColor.RED + "用法: /sjr delete rw <任务名称>");
return true;
}
return true;
}
private boolean handleBind(CommandSender sender, String[] args) {
if (args.length < 3) {
sender.sendMessage(ChatColor.RED + "用法: /sjr bind <任务名称> <命令>");
return true;
}
String taskName = args[1];
if (!tasksConfig.contains("tasks." + taskName)) {
sender.sendMessage(ChatColor.RED + "任务 '" + taskName + "' 不存在!");
return true;
}
String command = String.join(" ", Arrays.copyOfRange(args, 2, args.length));
List<String> commands = tasksConfig.getStringList("tasks." + taskName + ".commands");
commands.add(command);
tasksConfig.set("tasks." + taskName + ".commands", commands);
saveConfigs();
sender.sendMessage(ChatColor.GREEN + "命令已绑定到任务 '" + taskName + "'!");
return true;
}
private boolean handleRW(CommandSender sender, String[] args) {
if (args.length < 2) {
sender.sendMessage(ChatColor.RED + "用法: /sjr rw <list|listcommand>");
return true;
}
String sub = args[1].toLowerCase();
if (sub.equals("list")) {
Set<String> tasks = tasksConfig.getConfigurationSection("tasks").getKeys(false);
if (tasks.isEmpty()) {
sender.sendMessage(ChatColor.YELLOW + "没有可用的任务。");
} else {
sender.sendMessage(ChatColor.GREEN + "可用任务:");
for (String task : tasks) {
sender.sendMessage(ChatColor.GRAY + " - " + task);
}
}
} else if (sub.equals("listcommand")) {
if (args.length < 3) {
sender.sendMessage(ChatColor.RED + "用法: /sjr rw listcommand <任务名称>");
return true;
}
String taskName = args[2];
if (!tasksConfig.contains("tasks." + taskName)) {
sender.sendMessage(ChatColor.RED + "任务 '" + taskName + "' 不存在!");
return true;
}
List<String> commands = tasksConfig.getStringList("tasks." + taskName + ".commands");
if (commands.isEmpty()) {
sender.sendMessage(ChatColor.YELLOW + "任务 '" + taskName + "' 没有绑定任何命令。");
} else {
sender.sendMessage(ChatColor.GREEN + "任务 '" + taskName + "' 绑定的命令:");
for (int i = 0; i < commands.size(); i++) {
sender.sendMessage(ChatColor.GRAY + " " + (i + 1) + ". " + commands.get(i));
}
}
} else {
sender.sendMessage(ChatColor.RED + "用法: /sjr rw <list|listcommand>");
return true;
}
return true;
}
private boolean handleSJ(CommandSender sender, String[] args) {
if (args.length < 4) {
sender.sendMessage(ChatColor.RED + "用法: /sjr sj add <材料名称> <数量>");
return true;
}
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "只有玩家可以执行此命令!");
return true;
}
Player player = (Player) sender;
if (!player.isOp()) {
sender.sendMessage(ChatColor.RED + "你没有权限执行此命令!");
return true;
}
String action = args[1].toLowerCase();
if (action.equals("add")) {
String materialName = args[2];
if (!materialsConfig.contains("materials." + materialName)) {
sender.sendMessage(ChatColor.RED + "材料 '" + materialName + "' 不存在!");
return true;
}
int amount;
try {
amount = Integer.parseInt(args[3]);
} catch (NumberFormatException e) {
sender.sendMessage(ChatColor.RED + "数量必须是有效的数字!");
return true;
}
ItemStack item = player.getInventory().getItemInMainHand();
if (item.getType() == Material.AIR) {
sender.sendMessage(ChatColor.RED + "你必须手持一个物品!");
return true;
}
ItemMeta meta = item.getItemMeta();
List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();
// 检查是否已存在该材料的收集进度
boolean found = false;
for (int i = 0; i < lore.size(); i++) {
String line = ChatColor.stripColor(lore.get(i));
if (line.startsWith(materialName + " (")) {
lore.set(i, ChatColor.GRAY + materialName + " (0/" + amount + ")");
found = true;
break;
}
}
if (!found) {
lore.add(ChatColor.GRAY + materialName + " (0/" + amount + ")");
}
meta.setLore(lore);
item.setItemMeta(meta);
sender.sendMessage(ChatColor.GREEN + "已添加材料收集进度到手持物品!");
} else {
sender.sendMessage(ChatColor.RED + "用法: /sjr sj add <材料名称> <数量>");
return true;
}
return true;
}
private boolean handleSetRW(CommandSender sender, String[] args) {
if (args.length < 2) {
sender.sendMessage(ChatColor.RED + "用法: /sjr setrw <任务名称>");
return true;
}
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "只有玩家可以执行此命令!");
return true;
}
Player player = (Player) sender;
String taskName = args[1];
if (!tasksConfig.contains("tasks." + taskName)) {
sender.sendMessage(ChatColor.RED + "任务 '" + taskName + "' 不存在!");
return true;
}
ItemStack item = player.getInventory().getItemInMainHand();
if (item.getType() == Material.AIR) {
sender.sendMessage(ChatColor.RED + "你必须手持一个物品!");
return true;
}
ItemMeta meta = item.getItemMeta();
List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();
// 检查是否已存在任务
boolean found = false;
for (int i = 0; i < lore.size(); i++) {
String line = ChatColor.stripColor(lore.get(i));
if (line.startsWith("[任务] ")) {
lore.set(i, ChatColor.GREEN + "[任务] " + taskName);
found = true;
break;
}
}
if (!found) {
lore.add(ChatColor.GREEN + "[任务] " + taskName);
}
meta.setLore(lore);
item.setItemMeta(meta);
sender.sendMessage(ChatColor.GREEN + "已设置手持物品的任务为: " + taskName);
return true;
}
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
if (event.getHand() != EquipmentSlot.HAND) return;
Player player = event.getPlayer();
ItemStack item = event.getItem();
if (item == null || item.getType() == Material.AIR) return;
if (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) {
// 检查是否Shift+右键(完成任务)
if (player.isSneaking()) {
handleTaskCompletion(player, item);
} else {
// 普通右键(收集材料)
handleMaterialCollection(player, item);
}
}
}
private void handleMaterialCollection(Player player, ItemStack taskItem) {
ItemMeta meta = taskItem.getItemMeta();
if (!meta.hasLore()) return;
List<String> lore = meta.getLore();
boolean updated = false;
for (int i = 0; i < lore.size(); i++) {
String line = ChatColor.stripColor(lore.get(i));
if (line.contains("(") && line.contains("/") && line.contains(")")) {
// 可能是材料进度行
String[] parts = line.split("\\s+\\(");
if (parts.length < 2) continue;
String materialName = parts[0];
if (!materialsConfig.contains("materials." + materialName)) continue;
String progressPart = parts[1].replace(")", "");
String[] progress = progressPart.split("/");
if (progress.length != 2) continue;
int current, required;
try {
current = Integer.parseInt(progress[0]);
required = Integer.parseInt(progress[1]);
} catch (NumberFormatException e) {
continue;
}
if (current >= required) continue; // 已经完成
// 获取材料定义
String materialType = materialsConfig.getString("materials." + materialName + ".material");
String displayName = materialsConfig.getString("materials." + materialName + ".displayname");
String materialLore = materialsConfig.getString("materials." + materialName + ".lore");
// 在玩家背包中查找匹配的材料
for (ItemStack item : player.getInventory().getContents()) {
if (item == null || item.getType() == Material.AIR) continue;
ItemMeta itemMeta = item.getItemMeta();
boolean typeMatches = item.getType().toString().equals(materialType);
boolean nameMatches = (displayName.isEmpty() && !itemMeta.hasDisplayName()) ||
(itemMeta.hasDisplayName() && itemMeta.getDisplayName().equals(displayName));
boolean loreMatches = (materialLore.isEmpty() && (!itemMeta.hasLore() || itemMeta.getLore().isEmpty())) ||
(itemMeta.hasLore() && !itemMeta.getLore().isEmpty() &&
itemMeta.getLore().get(0).equals(materialLore));
if (typeMatches && nameMatches && loreMatches) {
int toCollect = Math.min(required - current, item.getAmount());
item.setAmount(item.getAmount() - toCollect);
current += toCollect;
lore.set(i, ChatColor.GRAY + materialName + " (" + current + "/" + required + ")");
updated = true;
if (current >= required) break;
}
}
}
}
if (updated) {
meta.setLore(lore);
taskItem.setItemMeta(meta);
player.sendMessage(ChatColor.GREEN + "材料收集进度已更新!");
}
}
private void handleTaskCompletion(Player player, ItemStack taskItem) {
ItemMeta meta = taskItem.getItemMeta();
if (!meta.hasLore()) return;
List<String> lore = meta.getLore();
String taskName = null;
// 查找任务名称
for (String line : lore) {
String plainLine = ChatColor.stripColor(line);
if (plainLine.startsWith("[任务] ")) {
taskName = plainLine.substring(4);
break;
}
}
if (taskName == null || !tasksConfig.contains("tasks." + taskName)) {
player.sendMessage(ChatColor.RED + "此物品没有有效的任务!");
return;
}
// 检查所有材料是否收集完成
boolean allCompleted = true;
for (String line : lore) {
String plainLine = ChatColor.stripColor(line);
if (plainLine.contains("(") && plainLine.contains("/") && plainLine.contains(")")) {
String[] parts = plainLine.split("\\s+\\(");
if (parts.length < 2) continue;
String progressPart = parts[1].replace(")", "");
String[] progress = progressPart.split("/");
if (progress.length != 2) continue;
int current, required;
try {
current = Integer.parseInt(progress[0]);
required = Integer.parseInt(progress[1]);
} catch (NumberFormatException e) {
continue;
}
if (current < required) {
allCompleted = false;
break;
}
}
}
if (!allCompleted) {
player.sendMessage(ChatColor.RED + "材料收集未完成,无法提交任务!");
return;
}
// 执行任务命令
List<String> commands = tasksConfig.getStringList("tasks." + taskName + ".commands");
for (String cmd : commands) {
String processedCmd = cmd.replace("%player%", player.getName());
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), processedCmd);
}
// 移除物品
taskItem.setAmount(taskItem.getAmount() - 1);
player.sendMessage(ChatColor.GREEN + "任务 '" + taskName + "' 已完成!");
}
}
plugin.yml文件
name: SJRPlugin
version: 1.0
main: com.example.sjrplugin.SJRPlugin
api-version: 1.20
commands:
sjr:
description: 物品收集任务命令
usage: /sjr …
permission: sjr.use
permission-message: 你没有权限使用此命令
permissions:
sjr.use:
description: 允许使用物品收集任务命令
default: op
使用说明
- 创建任务:
/sjr create rw 任务名字– 创建一个新任务 - 删除任务:
/sjr delete rw 任务名字– 删除一个任务 - 绑定命令:
/sjr bind 任务名字 命令– 为任务绑定完成时执行的命令(支持 %player% 变量) - 查看任务列表:
/sjr rw list– 查看所有任务 - 查看任务命令:
/sjr rw listcommand 任务名字– 查看任务绑定的命令 - 创建材料:
/sjr create cl 材料名字– 保存手持物品为材料 - 添加材料收集:
/sjr sj add 材料名字 数量– 为手持物品添加材料收集进度 - 设置任务:
/sjr setrw 任务名字– 为手持物品设置任务
功能说明
- 玩家手持任务物品右键可以收集背包中的材料
- 材料收集完成后,Shift+右键可以完成任务
- 任务完成后会执行绑定的命令并消耗任务物品
- 材料匹配基于物品ID、名称和第一行Lore





