一、前言
在 Minecraft 服务器开发中,属性系统是 RPG 玩法的核心组件之一。本文将基于 Java 和 Spigot/Paper API,详细介绍如何开发一个名为 **EnhancedAttributeCore(EACore)** 的属性增强插件。该插件支持 1.12.2-1.21.5 全版本兼容,具备属性注册、临时 / 永久属性管理、怪物属性注入等功能,并提供指令交互接口。
二、插件功能概述
核心功能列表
- 属性注册系统:动态注册自定义属性到主流属性插件(如 AttributePlus、SXAttribute)。
- 临时 / 永久属性管理:支持按时间或永久为玩家添加属性,自动清理过期属性。
- 怪物属性注入:兼容 MythicMobs,支持自定义生物属性配置。
- 区域与世界属性:玩家进入指定区域或世界时自动应用属性。
- 指令系统:提供
/eac
指令用于管理属性和重载配置。
技术架构
- 兼容性:基于 Bukkit 通用 API,通过版本适配层处理 NMS 差异。
- 模块化:核心功能拆分为独立模块(属性注册、临时属性、兼容层等)。
- 数据存储:使用 Gson 存储玩家永久属性,内存缓存临时属性。
三、开发环境搭建
1. 项目配置(pom.xml
)
xml
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.enhancedattribute</groupId>
<artifactId>EnhancedAttributeCore</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<spigot.version>1.21.1-R0.1-SNAPSHOT</spigot.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
2. 核心代码结构
plaintext
EnhancedAttributeCore/
├─ src/main/java/com/ea/core/
│ ├─ EACore.java # 主类(插件生命周期管理)
│ ├─ core/ # 核心模块
│ │ ├─ AttributeRegistry # 属性注册中心
│ │ └─ PlayerDataManager # 玩家数据管理
│ ├─ modules/ # 功能模块
│ │ └─ TemporaryAttributeModule # 临时属性管理
│ ├─ compatibility/ # 兼容层
│ │ └─ MythicMobsListener # MythicMobs兼容
│ └─ commands/ # 指令模块
│ └─ EACCommandExecutor # 指令执行器
├─ src/main/resources/
│ └─ config.yml # 配置文件
└─ target/ # 构建输出目录
四、关键功能实现
1. 主类初始化(EACore.java
)
java
public final class EACore extends JavaPlugin {
private static EACore instance;
private AttributeRegistry attributeRegistry;
private TemporaryAttributeModule tempAttrModule;
@Override
public void onEnable() {
instance = this;
// 初始化模块
new YamlConfig(this, "config.yml");
attributeRegistry = new AttributeRegistry(this);
tempAttrModule = new TemporaryAttributeModule(this);
// 注册事件与指令
getCommand("eac").setExecutor(new EACCommandExecutor(this));
Bukkit.getPluginManager().registerEvents(new MythicMobsListener(this), this);
// 定时清理过期属性(每分钟一次)
Bukkit.getScheduler().runTaskTimer(this,
tempAttrModule::cleanExpiredAttributes, 1200, 1200);
}
public static EACore getInstance() { return instance; }
}
2. 属性注册与管理
属性注册中心
java
public class AttributeRegistry {
private final Map<String, Class<?>> registeredAttributes = new HashMap<>();
public void registerAttribute(String attributeId, Class<?> attributeClass) {
registeredAttributes.put(attributeId, attributeClass);
// 兼容目标插件(如AttributePlus)的反射注册逻辑
}
}
玩家数据管理
java
public class PlayerDataManager {
private static final ConcurrentHashMap<UUID, PlayerAttributeData> playerData = new ConcurrentHashMap<>();
private static final File DATA_FOLDER = new File("player_data");
public static PlayerAttributeData getPlayerData(UUID playerId) {
return playerData.computeIfAbsent(playerId, PlayerAttributeData::new);
}
public static void saveAll() {
playerData.forEach((uuid, data) -> {
try (FileWriter writer = new FileWriter(DATA_FOLDER + "/" + uuid + ".json")) {
new Gson().toJson(data, writer);
}
});
}
}
3. 临时属性模块
java
public class TemporaryAttributeModule {
public void addTemporaryAttribute(UUID playerId, String attrId, double value, long durationMs) {
PlayerAttributeData data = PlayerDataManager.getPlayerData(playerId);
data.getTemporaryAttributes().put(attrId,
new AttributeEntry(value, System.currentTimeMillis() + durationMs));
applyAttributesToPlayer(Bukkit.getPlayer(playerId)); // 应用属性逻辑
}
public void cleanExpiredAttributes() {
playerData.forEach((uuid, data) -> {
data.getTemporaryAttributes().values().removeIf(AttributeEntry::isExpired);
});
}
}
4. 指令系统实现
java
public class EACCommandExecutor implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (args[0].equals("addtempattr")) {
Player target = Bukkit.getPlayer(args[1]);
String attrId = args[2];
double value = Double.parseDouble(args[3]);
long duration = Long.parseLong(args[4]);
EACore.getInstance().getTempAttrModule()
.addTemporaryAttribute(target.getUniqueId(), attrId, value, duration);
sender.sendMessage("属性已添加!");
return true;
}
if (args[0].equals("reload")) {
EACore.getInstance().getConfigManager().reloadConfig();
sender.sendMessage("配置已重载!");
return true;
}
return false;
}
}
五、兼容性与性能优化
1. 多版本兼容
- NMS 适配:通过
VersionAdapter
类封装不同版本的 NMS 操作,例如:java
public class VersionAdapter { public static void setEntityHealth(Entity entity, double health) { if (Bukkit.getServer().getVersion().contains("1.12")) { // 使用1.12的NMS接口 } else { // 使用高版本接口 entity.setHealth(health); } } }
2. 性能优化
- 异步存储:玩家数据使用
ConcurrentHashMap
缓存,异步保存到 JSON/MySQL。 - 事件优化:区域检测缓存玩家上次所在区域,避免重复计算。
六、构建与部署
1. 生成插件 JAR
bash
mvn clean package -DskipTests
生成的 JAR 位于target/EnhancedAttributeCore-1.0-SNAPSHOT.jar
。
2. 服务器部署
- 将 JAR 放入服务器
plugins
目录。 - 确保依赖插件已安装:
PlaceholderAPI
、目标属性插件(如AttributePlus
)。 - 首次运行自动生成配置文件
config.yml
。
七、扩展与未来计划
- 自定义属性处理器:允许开发者通过 API 注册自定义属性逻辑。
- 表达式解析器:集成 MVEL/SpEL 实现动态属性计算(如
max_health: 10 + %level%*2
)。 - 权限系统集成:基于 Vault 权限组自动应用属性。