Files
PlayerBlockLife/src/main/java/com/playerblocklife/PlayerBlockLife.java
xiaobai ad5cdf1c64 2.2.0-1.20.4
将生命方块由玩家头换为其他原版多颜色方块
2026-02-16 17:44:38 +08:00

297 lines
9.2 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.playerblocklife;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.logging.Level;
/**
* PlayerBlockLife插件主类 - PlayerBlockLife生存游戏模式的核心控制器
*
* <p>这个插件为Minecraft服务器添加了一个独特的生存游戏模式每个非OP玩家拥有一定数量的生命方块
* 这些方块使用不同颜色的羊毛、玻璃或水泥方块表示。当其他玩家挖光某个玩家的所有生命方块时,该玩家会被淘汰。
* 游戏需要管理员使用/pbl start命令开始支持限时模式最后存活的玩家获胜。</p>
*
* <p>主要功能:</p>
* <ul>
* <li>管理PlayerBlockLife游戏的完整生命周期等待、进行、结束</li>
* <li>为非OP玩家分配独特的颜色生命方块</li>
* <li>处理生命方块的生成和销毁</li>
* <li>监控游戏状态和玩家存活情况</li>
* <li>提供PlayerBlockLife专用命令系统/pbl start, /pbl rstgm</li>
* <li>支持游戏计分板显示</li>
* <li>管理员可使用传统命令进行管理</li>
* </ul>
*
* @author xiaobai
* @version 2.2.0-1.20.4
* @since 1.0.0
*/
public class PlayerBlockLife extends JavaPlugin {
private static PlayerBlockLife instance;
private PlayerBlockManager blockManager;
private SkinManager skinManager;
private LifeSystem lifeSystem;
private ConfigManager configManager;
private MessageManager messageManager;
private GameStateManager gameStateManager;
/**
* 插件启用时调用,执行初始化操作
*
* <p>初始化流程:
* <ol>
* <li>保存默认配置文件</li>
* <li>初始化所有管理器(注意依赖顺序)</li>
* <li>加载配置和消息数据</li>
* <li>注册事件监听器</li>
* <li>注册命令执行器</li>
* <li>加载玩家数据和皮肤缓存</li>
* <li>启动定时任务</li>
* </ol>
*
* @see #onDisable()
*/
@Override
public void onEnable() {
instance = this;
// 第一步:保存默认配置
saveDefaultConfig();
// 第二步:初始化管理器(注意顺序!)
this.configManager = new ConfigManager(this);
this.messageManager = new MessageManager(this);
this.skinManager = new SkinManager(this);
this.blockManager = new PlayerBlockManager(this, skinManager);
this.lifeSystem = new LifeSystem(this);
// 第三步:加载数据(必须在管理器初始化之后)
this.configManager.loadConfig();
this.messageManager.loadMessages();
// 第四步:注册事件监听器
getServer().getPluginManager().registerEvents(new BlockBreakListener(this), this);
getServer().getPluginManager().registerEvents(new PlayerJoinListener(this), this);
getServer().getPluginManager().registerEvents(new PlayerQuitListener(this), this);
// 第五步:注册命令
getCommand("setlifeblocks").setExecutor(new SetLifeBlocksCommand(this));
getCommand("checklifeblocks").setExecutor(new CheckLifeBlocksCommand(this));
getCommand("pblreload").setExecutor(new AdminCommands(this));
getCommand("pbldelete").setExecutor(new AdminCommands(this));
getCommand("pblrevive").setExecutor(new AdminCommands(this));
getCommand("pblstats").setExecutor(new AdminCommands(this));
getCommand("pbl").setExecutor(new PBLCommands(this));
// 第六步:初始化游戏状态管理器(先于其他数据加载)
this.gameStateManager = new GameStateManager(this);
// 第七步:加载其他数据
// 注意在新模式下我们不再使用原有的blockManager和skinManager
// 因此不再调用blockManager.loadData()和skinManager.loadAllSkins()
// 第八步:启动定时任务
startScheduler();
getLogger().info("§a========================================");
getLogger().info("§ePlayerBlockLife v" + getDescription().getVersion() + " 已启用");
getLogger().info("§e作者: " + getDescription().getAuthors());
getLogger().info("§a========================================");
}
/**
* 插件禁用时调用,执行清理操作
*
* <p>执行以下清理操作:
* <ul>
* <li>保存玩家方块数据到文件</li>
* <li>保存皮肤缓存数据</li>
* <li>记录插件禁用日志</li>
* </ul>
*
* @see #onEnable()
*/
@Override
public void onDisable() {
// 保存数据
if (blockManager != null) {
blockManager.saveData();
}
if (skinManager != null) {
skinManager.saveSkinData();
}
getLogger().info("§cPlayerBlockLife 插件已禁用");
}
/**
* 重写 reloadConfig 方法,避免循环依赖
*/
@Override
public void reloadConfig() {
// 只调用父类的reloadConfig不调用configManager的方法
super.reloadConfig();
getLogger().info("基础配置文件已重新加载");
}
/**
* 插件的完整重载方法(用于命令)
*
* <p>重新加载所有插件配置和数据,包括:
* <ul>
* <li>主配置文件 (config.yml)</li>
* <li>消息配置文件 (messages.yml)</li>
* <li>玩家方块数据</li>
* <li>皮肤缓存数据</li>
* </ul>
*
* <p>这个方法通常由管理员通过/pblreload命令调用。</p>
*/
public void reloadPluginConfig() {
if (configManager != null) {
configManager.reloadConfig();
}
if (messageManager != null) {
messageManager.reloadMessages();
}
if (blockManager != null) {
blockManager.loadData();
}
if (skinManager != null) {
skinManager.loadAllSkins();
}
getLogger().info("插件配置已完全重载");
}
private void startScheduler() {
// 每5分钟自动保存数据
getServer().getScheduler().runTaskTimerAsynchronously(this, () -> {
if (blockManager != null) {
blockManager.saveData();
}
if (skinManager != null) {
skinManager.saveSkinData();
}
getLogger().info("数据已自动保存");
}, 6000L, 6000L);
// 每10秒检查玩家生命方块
getServer().getScheduler().runTaskTimer(this, () -> {
if (lifeSystem != null) {
lifeSystem.checkAllPlayers();
}
// 每10秒检查游戏结束条件
if (gameStateManager != null) {
gameStateManager.checkGameEnd();
}
}, 200L, 200L);
// 每分钟清理一次过期缓存
getServer().getScheduler().runTaskTimerAsynchronously(this, () -> {
if (skinManager != null) {
skinManager.cleanupOldCache();
}
}, 1200L, 1200L);
// 每秒更新计分板
getServer().getScheduler().runTaskTimer(this, () -> {
if (gameStateManager != null) {
gameStateManager.updateScoreboard();
}
}, 20L, 20L);
}
/**
* 获取插件单例实例
*
* <p>提供全局访问点,允许其他类访问插件主实例。</p>
*
* @return PlayerBlockLife插件实例
* @throws IllegalStateException 如果插件尚未启用实例为null
*/
public static PlayerBlockLife getInstance() {
return instance;
}
/**
* 获取方块管理器
*
* @return 方块管理器实例
*/
public PlayerBlockManager getBlockManager() {
return blockManager;
}
/**
* 获取皮肤管理器
*
* @return 皮肤管理器实例
*/
public SkinManager getSkinManager() {
return skinManager;
}
/**
* 获取生命值系统
*
* @return 生命值系统实例
*/
public LifeSystem getLifeSystem() {
return lifeSystem;
}
/**
* 获取配置管理器
*
* @return 配置管理器实例
*/
public ConfigManager getConfigManager() {
return configManager;
}
/**
* 获取消息管理器
*
* @return 消息管理器实例
*/
public MessageManager getMessageManager() {
return messageManager;
}
/**
* 获取游戏状态管理器
*
* @return 游戏状态管理器实例
*/
public GameStateManager getGameStateManager() {
return gameStateManager;
}
/**
* 记录信息级别日志
*
* @param message 日志消息
*/
public void logInfo(String message) {
getLogger().info(message);
}
/**
* 记录警告级别日志
*
* @param message 日志消息
*/
public void logWarning(String message) {
getLogger().warning(message);
}
/**
* 记录错误级别日志
*
* @param message 日志消息
* @param throwable 异常对象
*/
public void logError(String message, Throwable throwable) {
getLogger().log(Level.SEVERE, message, throwable);
}
}