refactor: 改为运行期模块开关并简化构建
This commit is contained in:
@@ -26,8 +26,8 @@ jobs:
|
|||||||
- name: 授予执行权限
|
- name: 授予执行权限
|
||||||
run: chmod +x gradlew
|
run: chmod +x gradlew
|
||||||
|
|
||||||
- name: 构建全部版本
|
- name: 构建插件
|
||||||
run: ./gradlew buildAllVersions
|
run: ./gradlew build
|
||||||
|
|
||||||
- name: 创建发行版
|
- name: 创建发行版
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
|
|||||||
@@ -12,8 +12,8 @@
|
|||||||
- 最低支持版本为 `Paper 1.21.11`
|
- 最低支持版本为 `Paper 1.21.11`
|
||||||
- 已适配 `Paper 26.1.2`
|
- 已适配 `Paper 26.1.2`
|
||||||
- 构建环境固定为 `Java 21`
|
- 构建环境固定为 `Java 21`
|
||||||
- 配置与文本分离:行为配置放在 `config.yml`,提示文本放在 `lang/`
|
- 配置、模块开关与文本分离:行为配置放在 `config.yml`,模块开关放在 `modules.yml`,提示文本放在 `lang/`
|
||||||
- 支持模块裁剪,便于按需构建不同版本
|
- 支持运行期模块开关,避免为不同功能组合构建多个插件版本
|
||||||
|
|
||||||
## 主要功能
|
## 主要功能
|
||||||
|
|
||||||
@@ -52,17 +52,20 @@
|
|||||||
- Enderman 掉落方块控制
|
- Enderman 掉落方块控制
|
||||||
- JEI 配方同步修复
|
- JEI 配方同步修复
|
||||||
|
|
||||||
## 构建变体
|
## 模块配置
|
||||||
|
|
||||||
项目目前提供三个常用构建版本:
|
项目现在默认构建一个完整插件,功能是否启用由 `plugins/EssentialsC/modules.yml` 控制。
|
||||||
|
|
||||||
| 版本 | 产物名 | 说明 |
|
| 模块 | 默认状态 | 说明 |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| 标准版 | `EssentialsC-<version>.jar` | 默认版本,不包含 `mob-drops` 模块 |
|
| `blocks` | 开启 | 便捷方块命令、`/essc blocks` 菜单、潜影盒快捷打开 |
|
||||||
| 完整版 | `EssentialsC-all-<version>.jar` | 包含全部模块 |
|
| `player` | 开启 | 飞行、夜视、发光、治疗、喂食、修复、帽子、自杀、隐身、查询玩家 |
|
||||||
| 精简版 | `EssentialsC-lite-<version>.jar` | 仅排除 `blocks` 模块,保留 `mob-drops` |
|
| `admin-mode` | 开启 | `/essc admin` 管理模式与独立状态保存 |
|
||||||
|
| `tpsbar` | 开启 | 插件版 TPSBar,仍受 `config.yml` 中 `tpsbar.mode` 控制 |
|
||||||
|
| `jei-sync` | 开启 | Fabric / NeoForge JEI 配方同步修复 |
|
||||||
|
| `mob-drops` | 关闭 | 末影人掉落控制,默认关闭以保留过去标准版行为 |
|
||||||
|
|
||||||
如果需要进一步裁剪模块,也可以使用自定义构建参数生成 `custom` 版本。
|
修改模块开关后建议重启服务器,使命令注册表和监听器状态完全刷新。`/essc reload` 可以刷新配置和已注册命令的执行检查,但无法从 Bukkit 命令表中真正热移除或新增直连命令。
|
||||||
|
|
||||||
## 安装说明
|
## 安装说明
|
||||||
|
|
||||||
@@ -83,6 +86,8 @@
|
|||||||
- 掉落控制
|
- 掉落控制
|
||||||
- TPSBar 模式
|
- TPSBar 模式
|
||||||
- 便捷菜单布局
|
- 便捷菜单布局
|
||||||
|
- `modules.yml`
|
||||||
|
- 功能模块开关
|
||||||
- `lang/zh_CN.yml`、`lang/en_US.yml`
|
- `lang/zh_CN.yml`、`lang/en_US.yml`
|
||||||
- 命令反馈
|
- 命令反馈
|
||||||
- 帮助信息
|
- 帮助信息
|
||||||
@@ -122,29 +127,28 @@ essentialsc.*
|
|||||||
```bash
|
```bash
|
||||||
git clone https://github.com/Coldsmiles/EssentialsC.git
|
git clone https://github.com/Coldsmiles/EssentialsC.git
|
||||||
cd EssentialsC
|
cd EssentialsC
|
||||||
./gradlew buildAllVersions
|
./gradlew build
|
||||||
```
|
```
|
||||||
|
|
||||||
Windows 可使用:
|
Windows 可使用:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
.\gradlew.bat buildAllVersions
|
.\gradlew.bat build
|
||||||
```
|
```
|
||||||
|
|
||||||
构建产物输出到 `build/libs/`。
|
构建产物输出到 `build/libs/EssentialsC-<version>.jar`。
|
||||||
|
|
||||||
常用任务:
|
常用任务:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./gradlew shadowJarStandard
|
./gradlew shadowJar
|
||||||
./gradlew shadowJarAll
|
./gradlew build
|
||||||
./gradlew shadowJarLite
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 开发说明
|
## 开发说明
|
||||||
|
|
||||||
- 使用 `paperweight-userdev` 进行 Paper 开发
|
- 使用 `paperweight-userdev` 进行 Paper 开发
|
||||||
- 运行时通过反射加载可选模块,避免裁剪版本因类缺失而启动失败
|
- 运行时通过 `modules.yml` 控制模块加载,命令与监听器按模块状态注册
|
||||||
- 发布流程基于 GitHub Actions 和 Gradle Wrapper
|
- 发布流程基于 GitHub Actions 和 Gradle Wrapper
|
||||||
|
|
||||||
## 许可证
|
## 许可证
|
||||||
|
|||||||
+10
-165
@@ -1,8 +1,6 @@
|
|||||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||||
import org.gradle.language.jvm.tasks.ProcessResources
|
import org.gradle.language.jvm.tasks.ProcessResources
|
||||||
|
|
||||||
import java.util.Collections
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
id 'java'
|
||||||
id 'io.papermc.paperweight.userdev' version '2.0.0-beta.21'
|
id 'io.papermc.paperweight.userdev' version '2.0.0-beta.21'
|
||||||
@@ -28,96 +26,6 @@ java {
|
|||||||
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
|
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
|
||||||
}
|
}
|
||||||
|
|
||||||
def moduleExcludes = [
|
|
||||||
'blocks': [
|
|
||||||
'**/commands/WorkbenchCommand.java',
|
|
||||||
'**/commands/AnvilCommand.java',
|
|
||||||
'**/commands/CartographyTableCommand.java',
|
|
||||||
'**/commands/GrindstoneCommand.java',
|
|
||||||
'**/commands/LoomCommand.java',
|
|
||||||
'**/commands/SmithingTableCommand.java',
|
|
||||||
'**/commands/StonecutterCommand.java',
|
|
||||||
'**/commands/EnderChestCommand.java',
|
|
||||||
'**/commands/BlocksMenuCommand.java',
|
|
||||||
'**/listeners/ShulkerBoxListener.java'
|
|
||||||
],
|
|
||||||
'player': [
|
|
||||||
'**/commands/FlyCommand.java',
|
|
||||||
'**/commands/NightVisionCommand.java',
|
|
||||||
'**/commands/GlowCommand.java',
|
|
||||||
'**/commands/HealCommand.java',
|
|
||||||
'**/commands/FeedCommand.java',
|
|
||||||
'**/commands/VanishCommand.java',
|
|
||||||
'**/commands/SeenCommand.java',
|
|
||||||
'**/commands/HatCommand.java',
|
|
||||||
'**/commands/SuicideCommand.java',
|
|
||||||
'**/commands/RepairCommand.java',
|
|
||||||
'**/commands/AdminCommand.java',
|
|
||||||
'**/commands/TpsBarCommand.java',
|
|
||||||
'**/tpsbar/TpsBarManager.java'
|
|
||||||
],
|
|
||||||
'jei-fix': [
|
|
||||||
'**/listeners/JeiRecipeSyncListener.java'
|
|
||||||
],
|
|
||||||
'mob-drops': [
|
|
||||||
'**/listeners/MobDropListener.java',
|
|
||||||
'**/listeners/MobDropMenuListener.java',
|
|
||||||
'**/commands/MobDropCommand.java'
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
def variantDefinitions = [
|
|
||||||
standard: [
|
|
||||||
archiveFileName: "EssentialsC-${project.version}.jar",
|
|
||||||
excludedModules: ['mob-drops']
|
|
||||||
],
|
|
||||||
all: [
|
|
||||||
archiveFileName: "EssentialsC-all-${project.version}.jar",
|
|
||||||
excludedModules: []
|
|
||||||
],
|
|
||||||
lite: [
|
|
||||||
archiveFileName: "EssentialsC-lite-${project.version}.jar",
|
|
||||||
excludedModules: ['blocks']
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
if (project.hasProperty('excludeModules')) {
|
|
||||||
def customExcludedModules = project.property('excludeModules')
|
|
||||||
.split(',')
|
|
||||||
.collect { it.trim() }
|
|
||||||
.findAll { !it.isEmpty() }
|
|
||||||
|
|
||||||
variantDefinitions.custom = [
|
|
||||||
archiveFileName: "EssentialsC-custom-${project.version}.jar",
|
|
||||||
excludedModules: customExcludedModules
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
def resolveExcludePatterns = { Collection<String> modules ->
|
|
||||||
modules.collectMany { module -> moduleExcludes.get(module, Collections.emptyList()) }.unique()
|
|
||||||
}
|
|
||||||
|
|
||||||
variantDefinitions.each { variantName, variantConfig ->
|
|
||||||
def unknownModules = variantConfig.excludedModules.findAll { !moduleExcludes.containsKey(it) }
|
|
||||||
if (!unknownModules.isEmpty()) {
|
|
||||||
throw new GradleException("Unknown modules for variant '${variantName}': ${unknownModules.join(', ')}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def variantSourceSets = [:]
|
|
||||||
|
|
||||||
variantDefinitions.each { variantName, variantConfig ->
|
|
||||||
def sourceSet = sourceSets.create(variantName)
|
|
||||||
sourceSet.java.srcDirs = sourceSets.main.java.srcDirs
|
|
||||||
sourceSet.resources.srcDirs = sourceSets.main.resources.srcDirs
|
|
||||||
resolveExcludePatterns(variantConfig.excludedModules).each { pattern ->
|
|
||||||
sourceSet.java.exclude(pattern)
|
|
||||||
}
|
|
||||||
sourceSet.compileClasspath += sourceSets.main.compileClasspath
|
|
||||||
sourceSet.runtimeClasspath += sourceSet.output + sourceSet.compileClasspath
|
|
||||||
variantSourceSets[variantName] = sourceSet
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType(JavaCompile).configureEach {
|
tasks.withType(JavaCompile).configureEach {
|
||||||
options.encoding = 'UTF-8'
|
options.encoding = 'UTF-8'
|
||||||
}
|
}
|
||||||
@@ -126,14 +34,10 @@ tasks.withType(ProcessResources).configureEach {
|
|||||||
filteringCharset = 'UTF-8'
|
filteringCharset = 'UTF-8'
|
||||||
}
|
}
|
||||||
|
|
||||||
variantDefinitions.keySet().each { variantName ->
|
tasks.named('processResources', ProcessResources).configure {
|
||||||
def sourceSet = variantSourceSets[variantName]
|
inputs.property('version', project.version)
|
||||||
def processTaskName = sourceSet.processResourcesTaskName
|
filesMatching('paper-plugin.yml') {
|
||||||
tasks.named(processTaskName, ProcessResources).configure {
|
expand('version': project.version)
|
||||||
inputs.property('version', project.version)
|
|
||||||
filesMatching('paper-plugin.yml') {
|
|
||||||
expand('version': project.version)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,72 +45,13 @@ tasks.named('jar').configure {
|
|||||||
enabled = false
|
enabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.named('shadowJar').configure {
|
tasks.named('shadowJar', ShadowJar).configure {
|
||||||
enabled = false
|
group = 'build'
|
||||||
}
|
description = '构建包含全部运行期可开关模块的 EssentialsC 插件。'
|
||||||
|
archiveFileName.set("EssentialsC-${project.version}.jar")
|
||||||
def variantJarTasks = variantDefinitions.collect { variantName, variantConfig ->
|
configurations = [project.configurations.runtimeClasspath]
|
||||||
def taskName = "shadowJar${variantName.capitalize()}"
|
|
||||||
def sourceSet = variantSourceSets[variantName]
|
|
||||||
|
|
||||||
tasks.register(taskName, ShadowJar) {
|
|
||||||
group = 'build'
|
|
||||||
description = "Builds the ${variantName} plugin jar."
|
|
||||||
archiveFileName.set(variantConfig.archiveFileName as String)
|
|
||||||
from(sourceSet.output)
|
|
||||||
configurations = [project.configurations.runtimeClasspath]
|
|
||||||
dependsOn(tasks.named(sourceSet.classesTaskName))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.named('assemble').configure {
|
tasks.named('assemble').configure {
|
||||||
dependsOn(variantJarTasks)
|
dependsOn(tasks.named('shadowJar'))
|
||||||
}
|
|
||||||
|
|
||||||
tasks.register('buildAllVersions') {
|
|
||||||
group = 'build'
|
|
||||||
description = 'Builds standard, all, and lite plugin jars.'
|
|
||||||
dependsOn(variantJarTasks)
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.register('deployToPaper12111', Copy) {
|
|
||||||
group = 'deployment'
|
|
||||||
description = 'Deploys the all variant to the local Paper 1.21.11 test server.'
|
|
||||||
def artifact = tasks.named('shadowJarAll').flatMap { it.archiveFile }
|
|
||||||
dependsOn(tasks.named('shadowJarAll'))
|
|
||||||
from(artifact)
|
|
||||||
into(layout.projectDirectory.dir('test-server/paper-1.21.11/plugins'))
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.register('deployToPaper26') {
|
|
||||||
group = 'deployment'
|
|
||||||
description = 'Deploys the all variant to the local Paper 26.1.2 test server.'
|
|
||||||
dependsOn(tasks.named('shadowJarAll'))
|
|
||||||
|
|
||||||
doFirst {
|
|
||||||
def pluginsDir = file("${projectDir}/test-server/paper-26.1.2/plugins")
|
|
||||||
if (!pluginsDir.exists()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fileTree(pluginsDir).matching {
|
|
||||||
include 'EssentialsC*.jar'
|
|
||||||
}.each { pluginJar ->
|
|
||||||
pluginJar.delete()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
doLast {
|
|
||||||
def artifact = tasks.named('shadowJarAll').flatMap { it.archiveFile }
|
|
||||||
copy {
|
|
||||||
from(artifact)
|
|
||||||
into("${projectDir}/test-server/paper-26.1.2/plugins")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.register('buildAndDeployToPaper26') {
|
|
||||||
group = 'deployment'
|
|
||||||
description = 'Builds and deploys the all variant to the local Paper 26.1.2 test server.'
|
|
||||||
dependsOn(tasks.named('clean'), tasks.named('deployToPaper26'))
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,15 +16,23 @@ import java.lang.reflect.Field;
|
|||||||
public final class EssentialsC extends JavaPlugin {
|
public final class EssentialsC extends JavaPlugin {
|
||||||
|
|
||||||
private static LangManager langManager;
|
private static LangManager langManager;
|
||||||
|
private ModuleManager moduleManager;
|
||||||
private AdminModeManager adminModeManager;
|
private AdminModeManager adminModeManager;
|
||||||
private TpsBarService tpsBarManager;
|
private TpsBarService tpsBarManager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
langManager = new LangManager(this);
|
langManager = new LangManager(this);
|
||||||
adminModeManager = new AdminModeManager(this);
|
moduleManager = new ModuleManager(this);
|
||||||
getServer().getPluginManager().registerEvents(adminModeManager, this);
|
|
||||||
tpsBarManager = createOptionalService("cn.infstar.essentialsC.tpsbar.TpsBarManager", TpsBarService.class);
|
if (moduleManager.isEnabled(ModuleManager.ADMIN_MODE)) {
|
||||||
|
adminModeManager = new AdminModeManager(this);
|
||||||
|
getServer().getPluginManager().registerEvents(adminModeManager, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (moduleManager.isEnabled(ModuleManager.TPSBAR)) {
|
||||||
|
tpsBarManager = createOptionalService("cn.infstar.essentialsC.tpsbar.TpsBarManager", TpsBarService.class);
|
||||||
|
}
|
||||||
if (tpsBarManager instanceof Listener listener) {
|
if (tpsBarManager instanceof Listener listener) {
|
||||||
getServer().getPluginManager().registerEvents(listener, this);
|
getServer().getPluginManager().registerEvents(listener, this);
|
||||||
}
|
}
|
||||||
@@ -32,7 +40,7 @@ public final class EssentialsC extends JavaPlugin {
|
|||||||
registerListeners();
|
registerListeners();
|
||||||
registerCommands();
|
registerCommands();
|
||||||
|
|
||||||
getLogger().info("EssentialsC enabled. Version: " + getDescription().getVersion());
|
getLogger().info("EssentialsC 已启用,版本: " + getDescription().getVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -43,7 +51,7 @@ public final class EssentialsC extends JavaPlugin {
|
|||||||
if (adminModeManager != null) {
|
if (adminModeManager != null) {
|
||||||
adminModeManager.shutdown();
|
adminModeManager.shutdown();
|
||||||
}
|
}
|
||||||
getLogger().info("EssentialsC disabled.");
|
getLogger().info("EssentialsC 已禁用。");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LangManager getLangManager() {
|
public static LangManager getLangManager() {
|
||||||
@@ -54,28 +62,38 @@ public final class EssentialsC extends JavaPlugin {
|
|||||||
return adminModeManager;
|
return adminModeManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ModuleManager getModuleManager() {
|
||||||
|
return moduleManager;
|
||||||
|
}
|
||||||
|
|
||||||
public TpsBarService getTpsBarManager() {
|
public TpsBarService getTpsBarManager() {
|
||||||
return tpsBarManager;
|
return tpsBarManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerPluginChannels() {
|
private void registerPluginChannels() {
|
||||||
|
if (!moduleManager.isEnabled(ModuleManager.JEI_SYNC)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
org.bukkit.plugin.messaging.Messenger messenger = getServer().getMessenger();
|
org.bukkit.plugin.messaging.Messenger messenger = getServer().getMessenger();
|
||||||
messenger.registerOutgoingPluginChannel(this, "fabric:recipe_sync");
|
messenger.registerOutgoingPluginChannel(this, "fabric:recipe_sync");
|
||||||
messenger.registerOutgoingPluginChannel(this, "neoforge:recipe_content");
|
messenger.registerOutgoingPluginChannel(this, "neoforge:recipe_content");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerListeners() {
|
private void registerListeners() {
|
||||||
if (registerListener("cn.infstar.essentialsC.listeners.ShulkerBoxListener")) {
|
if (moduleManager.isEnabled(ModuleManager.BLOCKS)
|
||||||
getLogger().info("- Shulker box module");
|
&& registerListener("cn.infstar.essentialsC.listeners.ShulkerBoxListener")) {
|
||||||
|
getLogger().info("- 潜影盒模块");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (registerListener("cn.infstar.essentialsC.listeners.JeiRecipeSyncListener")) {
|
if (moduleManager.isEnabled(ModuleManager.JEI_SYNC)
|
||||||
getLogger().info("- JEI recipe sync");
|
&& registerListener("cn.infstar.essentialsC.listeners.JeiRecipeSyncListener")) {
|
||||||
|
getLogger().info("- JEI 配方同步");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (registerListener("cn.infstar.essentialsC.listeners.MobDropListener")) {
|
if (moduleManager.isEnabled(ModuleManager.MOB_DROPS)
|
||||||
|
&& registerListener("cn.infstar.essentialsC.listeners.MobDropListener")) {
|
||||||
createOptionalInstance("cn.infstar.essentialsC.listeners.MobDropMenuListener");
|
createOptionalInstance("cn.infstar.essentialsC.listeners.MobDropMenuListener");
|
||||||
getLogger().info("- Mob drop control");
|
getLogger().info("- 生物掉落控制");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +145,7 @@ public final class EssentialsC extends JavaPlugin {
|
|||||||
|
|
||||||
registerCommandWithAliases(commandMap, "essentialsc", new HelpCommand(), "essc");
|
registerCommandWithAliases(commandMap, "essentialsc", new HelpCommand(), "essc");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
getLogger().severe("Failed to register commands: " + e.getMessage());
|
getLogger().severe("注册命令失败: " + e.getMessage());
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,6 +154,10 @@ public final class EssentialsC extends JavaPlugin {
|
|||||||
Command command = new Command(name) {
|
Command command = new Command(name) {
|
||||||
@Override
|
@Override
|
||||||
public boolean execute(CommandSender sender, String commandLabel, String[] args) {
|
public boolean execute(CommandSender sender, String commandLabel, String[] args) {
|
||||||
|
if (CommandRegistry.resolveCommandName(name) != null && !CommandRegistry.isAvailable(name)) {
|
||||||
|
sender.sendMessage(EssentialsC.getLangManager().getPrefixedString("messages.module-disabled"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return executor.onCommand(sender, this, commandLabel, args);
|
return executor.onCommand(sender, this, commandLabel, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,6 +177,10 @@ public final class EssentialsC extends JavaPlugin {
|
|||||||
Command aliasCmd = new Command(alias) {
|
Command aliasCmd = new Command(alias) {
|
||||||
@Override
|
@Override
|
||||||
public boolean execute(CommandSender sender, String commandLabel, String[] args) {
|
public boolean execute(CommandSender sender, String commandLabel, String[] args) {
|
||||||
|
if (CommandRegistry.resolveCommandName(name) != null && !CommandRegistry.isAvailable(name)) {
|
||||||
|
sender.sendMessage(EssentialsC.getLangManager().getPrefixedString("messages.module-disabled"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return executor.onCommand(sender, this, commandLabel, args);
|
return executor.onCommand(sender, this, commandLabel, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public class LangManager {
|
|||||||
public String getString(String path) {
|
public String getString(String path) {
|
||||||
String value = langFile.getString(path);
|
String value = langFile.getString(path);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return translateColorCodes("&cMissing translation: " + path);
|
return translateColorCodes("&c缺少语言文本: " + path);
|
||||||
}
|
}
|
||||||
return translateColorCodes(value);
|
return translateColorCodes(value);
|
||||||
}
|
}
|
||||||
@@ -58,7 +58,7 @@ public class LangManager {
|
|||||||
public List<String> getStringList(String path) {
|
public List<String> getStringList(String path) {
|
||||||
List<String> values = langFile.getStringList(path);
|
List<String> values = langFile.getStringList(path);
|
||||||
if (values.isEmpty()) {
|
if (values.isEmpty()) {
|
||||||
values = List.of("&cMissing translation: " + path);
|
values = List.of("&c缺少语言文本: " + path);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> translated = new ArrayList<>();
|
List<String> translated = new ArrayList<>();
|
||||||
@@ -92,7 +92,7 @@ public class LangManager {
|
|||||||
try {
|
try {
|
||||||
config.save(configFile);
|
config.save(configFile);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
plugin.getLogger().severe("Failed to save config.yml: " + e.getMessage());
|
plugin.getLogger().severe("保存 config.yml 失败: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,10 +115,10 @@ public class LangManager {
|
|||||||
newConfig.set("language", language);
|
newConfig.set("language", language);
|
||||||
newConfig.save(configFile);
|
newConfig.save(configFile);
|
||||||
|
|
||||||
plugin.getLogger().info("Migrated config.yml from version " + existingVersion
|
plugin.getLogger().info("已将 config.yml 从版本 " + existingVersion
|
||||||
+ " to " + CURRENT_CONFIG_VERSION + ". Backup saved to " + backupFile.getName());
|
+ " 迁移到 " + CURRENT_CONFIG_VERSION + ",备份文件: " + backupFile.getName());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
plugin.getLogger().severe("Failed to migrate config.yml: " + e.getMessage());
|
plugin.getLogger().severe("迁移 config.yml 失败: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ public class LangManager {
|
|||||||
|
|
||||||
File langFolder = new File(plugin.getDataFolder(), "lang");
|
File langFolder = new File(plugin.getDataFolder(), "lang");
|
||||||
if (!langFolder.exists() && !langFolder.mkdirs()) {
|
if (!langFolder.exists() && !langFolder.mkdirs()) {
|
||||||
plugin.getLogger().warning("Failed to create language folder: " + langFolder.getAbsolutePath());
|
plugin.getLogger().warning("创建语言文件夹失败: " + langFolder.getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
File langFileObj = new File(langFolder, currentLanguage + ".yml");
|
File langFileObj = new File(langFolder, currentLanguage + ".yml");
|
||||||
@@ -135,7 +135,7 @@ public class LangManager {
|
|||||||
if (plugin.getResource("lang/" + currentLanguage + ".yml") != null) {
|
if (plugin.getResource("lang/" + currentLanguage + ".yml") != null) {
|
||||||
plugin.saveResource("lang/" + currentLanguage + ".yml", false);
|
plugin.saveResource("lang/" + currentLanguage + ".yml", false);
|
||||||
} else {
|
} else {
|
||||||
plugin.getLogger().warning("Language file not found: " + currentLanguage + ".yml, falling back to en_US");
|
plugin.getLogger().warning("未找到语言文件: " + currentLanguage + ".yml,已回退到 en_US");
|
||||||
currentLanguage = "en_US";
|
currentLanguage = "en_US";
|
||||||
plugin.saveResource("lang/en_US.yml", false);
|
plugin.saveResource("lang/en_US.yml", false);
|
||||||
langFileObj = new File(langFolder, "en_US.yml");
|
langFileObj = new File(langFolder, "en_US.yml");
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package cn.infstar.essentialsC;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public final class ModuleManager {
|
||||||
|
|
||||||
|
private static final int CURRENT_CONFIG_VERSION = 1;
|
||||||
|
|
||||||
|
public static final String BLOCKS = "blocks";
|
||||||
|
public static final String PLAYER = "player";
|
||||||
|
public static final String ADMIN_MODE = "admin-mode";
|
||||||
|
public static final String TPSBAR = "tpsbar";
|
||||||
|
public static final String JEI_SYNC = "jei-sync";
|
||||||
|
public static final String MOB_DROPS = "mob-drops";
|
||||||
|
|
||||||
|
private static final Map<String, Boolean> DEFAULT_MODULES = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
DEFAULT_MODULES.put(BLOCKS, true);
|
||||||
|
DEFAULT_MODULES.put(PLAYER, true);
|
||||||
|
DEFAULT_MODULES.put(ADMIN_MODE, true);
|
||||||
|
DEFAULT_MODULES.put(TPSBAR, true);
|
||||||
|
DEFAULT_MODULES.put(JEI_SYNC, true);
|
||||||
|
DEFAULT_MODULES.put(MOB_DROPS, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final JavaPlugin plugin;
|
||||||
|
private final File modulesFile;
|
||||||
|
private FileConfiguration modulesConfig;
|
||||||
|
|
||||||
|
public ModuleManager(JavaPlugin plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.modulesFile = new File(plugin.getDataFolder(), "modules.yml");
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reload() {
|
||||||
|
if (!modulesFile.exists()) {
|
||||||
|
plugin.saveResource("modules.yml", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
modulesConfig = YamlConfiguration.loadConfiguration(modulesFile);
|
||||||
|
modulesConfig.addDefault("config-version", CURRENT_CONFIG_VERSION);
|
||||||
|
for (Map.Entry<String, Boolean> module : DEFAULT_MODULES.entrySet()) {
|
||||||
|
modulesConfig.addDefault(path(module.getKey()), module.getValue());
|
||||||
|
}
|
||||||
|
modulesConfig.options().copyDefaults(true);
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnabled(String moduleKey) {
|
||||||
|
if (moduleKey == null || moduleKey.isBlank()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return modulesConfig.getBoolean(path(moduleKey), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String path(String moduleKey) {
|
||||||
|
return "modules." + moduleKey + ".enabled";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void save() {
|
||||||
|
try {
|
||||||
|
modulesConfig.save(modulesFile);
|
||||||
|
} catch (IOException e) {
|
||||||
|
plugin.getLogger().warning("保存 modules.yml 失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -328,7 +328,7 @@ public final class AdminModeManager implements Listener {
|
|||||||
try {
|
try {
|
||||||
data.save(dataFile);
|
data.save(dataFile);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
plugin.getLogger().warning("Failed to save admin-mode.yml: " + e.getMessage());
|
plugin.getLogger().warning("保存 admin-mode.yml 失败: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ public class AdminCommand extends BaseCommand {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean execute(Player player, String[] args) {
|
protected boolean execute(Player player, String[] args) {
|
||||||
|
if (plugin.getAdminModeManager() == null) {
|
||||||
|
player.sendMessage(getLang().getPrefixedString("messages.module-disabled"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
plugin.getAdminModeManager().toggle(player);
|
plugin.getAdminModeManager().toggle(player);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package cn.infstar.essentialsC.commands;
|
package cn.infstar.essentialsC.commands;
|
||||||
|
|
||||||
import cn.infstar.essentialsC.EssentialsC;
|
import cn.infstar.essentialsC.EssentialsC;
|
||||||
|
import cn.infstar.essentialsC.ModuleManager;
|
||||||
import cn.infstar.essentialsC.tpsbar.TpsBarService;
|
import cn.infstar.essentialsC.tpsbar.TpsBarService;
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
@@ -20,44 +21,44 @@ public final class CommandRegistry {
|
|||||||
private static final Set<String> UNAVAILABLE_COMMANDS = new java.util.HashSet<>();
|
private static final Set<String> UNAVAILABLE_COMMANDS = new java.util.HashSet<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
register("workbench", "essentialsc.command.workbench", "cn.infstar.essentialsC.commands.WorkbenchCommand", "wb");
|
register("workbench", "essentialsc.command.workbench", ModuleManager.BLOCKS, "cn.infstar.essentialsC.commands.WorkbenchCommand", "wb");
|
||||||
register("anvil", "essentialsc.command.anvil", "cn.infstar.essentialsC.commands.AnvilCommand");
|
register("anvil", "essentialsc.command.anvil", ModuleManager.BLOCKS, "cn.infstar.essentialsC.commands.AnvilCommand");
|
||||||
register("cartographytable", "essentialsc.command.cartographytable", "cn.infstar.essentialsC.commands.CartographyTableCommand", "ct", "cartography");
|
register("cartographytable", "essentialsc.command.cartographytable", ModuleManager.BLOCKS, "cn.infstar.essentialsC.commands.CartographyTableCommand", "ct", "cartography");
|
||||||
register("grindstone", "essentialsc.command.grindstone", "cn.infstar.essentialsC.commands.GrindstoneCommand", "gs");
|
register("grindstone", "essentialsc.command.grindstone", ModuleManager.BLOCKS, "cn.infstar.essentialsC.commands.GrindstoneCommand", "gs");
|
||||||
register("loom", "essentialsc.command.loom", "cn.infstar.essentialsC.commands.LoomCommand");
|
register("loom", "essentialsc.command.loom", ModuleManager.BLOCKS, "cn.infstar.essentialsC.commands.LoomCommand");
|
||||||
register("smithingtable", "essentialsc.command.smithingtable", "cn.infstar.essentialsC.commands.SmithingTableCommand", "st", "smithing");
|
register("smithingtable", "essentialsc.command.smithingtable", ModuleManager.BLOCKS, "cn.infstar.essentialsC.commands.SmithingTableCommand", "st", "smithing");
|
||||||
register("stonecutter", "essentialsc.command.stonecutter", "cn.infstar.essentialsC.commands.StonecutterCommand", "sc");
|
register("stonecutter", "essentialsc.command.stonecutter", ModuleManager.BLOCKS, "cn.infstar.essentialsC.commands.StonecutterCommand", "sc");
|
||||||
register("enderchest", "essentialsc.command.enderchest", "cn.infstar.essentialsC.commands.EnderChestCommand", "ec");
|
register("enderchest", "essentialsc.command.enderchest", ModuleManager.BLOCKS, "cn.infstar.essentialsC.commands.EnderChestCommand", "ec");
|
||||||
register("blocks", "essentialsc.command.blocks", "cn.infstar.essentialsC.commands.BlocksMenuCommand");
|
register("blocks", "essentialsc.command.blocks", ModuleManager.BLOCKS, "cn.infstar.essentialsC.commands.BlocksMenuCommand");
|
||||||
register("hat", "essentialsc.command.hat", "cn.infstar.essentialsC.commands.HatCommand");
|
register("hat", "essentialsc.command.hat", ModuleManager.PLAYER, "cn.infstar.essentialsC.commands.HatCommand");
|
||||||
register("suicide", "essentialsc.command.suicide", "cn.infstar.essentialsC.commands.SuicideCommand", "die");
|
register("suicide", "essentialsc.command.suicide", ModuleManager.PLAYER, "cn.infstar.essentialsC.commands.SuicideCommand", "die");
|
||||||
register("fly", "essentialsc.command.fly", "cn.infstar.essentialsC.commands.FlyCommand");
|
register("fly", "essentialsc.command.fly", ModuleManager.PLAYER, "cn.infstar.essentialsC.commands.FlyCommand");
|
||||||
register("nightvision", "essentialsc.command.nightvision", "cn.infstar.essentialsC.commands.NightVisionCommand", "nv");
|
register("nightvision", "essentialsc.command.nightvision", ModuleManager.PLAYER, "cn.infstar.essentialsC.commands.NightVisionCommand", "nv");
|
||||||
register("glow", "essentialsc.command.glow", "cn.infstar.essentialsC.commands.GlowCommand");
|
register("glow", "essentialsc.command.glow", ModuleManager.PLAYER, "cn.infstar.essentialsC.commands.GlowCommand");
|
||||||
register("heal", "essentialsc.command.heal", "cn.infstar.essentialsC.commands.HealCommand");
|
register("heal", "essentialsc.command.heal", ModuleManager.PLAYER, "cn.infstar.essentialsC.commands.HealCommand");
|
||||||
register("vanish", "essentialsc.command.vanish", "cn.infstar.essentialsC.commands.VanishCommand", "v");
|
register("vanish", "essentialsc.command.vanish", ModuleManager.PLAYER, "cn.infstar.essentialsC.commands.VanishCommand", "v");
|
||||||
register("seen", "essentialsc.command.seen", "cn.infstar.essentialsC.commands.SeenCommand", "info");
|
register("seen", "essentialsc.command.seen", ModuleManager.PLAYER, "cn.infstar.essentialsC.commands.SeenCommand", "info");
|
||||||
register("feed", "essentialsc.command.feed", "cn.infstar.essentialsC.commands.FeedCommand");
|
register("feed", "essentialsc.command.feed", ModuleManager.PLAYER, "cn.infstar.essentialsC.commands.FeedCommand");
|
||||||
register("repair", "essentialsc.command.repair", "cn.infstar.essentialsC.commands.RepairCommand", "rep");
|
register("repair", "essentialsc.command.repair", ModuleManager.PLAYER, "cn.infstar.essentialsC.commands.RepairCommand", "rep");
|
||||||
register("tpsbar", "essentialsc.command.tpsbar", "cn.infstar.essentialsC.commands.TpsBarCommand");
|
register("tpsbar", "essentialsc.command.tpsbar", ModuleManager.TPSBAR, "cn.infstar.essentialsC.commands.TpsBarCommand");
|
||||||
register("mobdrops", "essentialsc.mobdrops.enderman", "cn.infstar.essentialsC.commands.MobDropCommand");
|
register("mobdrops", "essentialsc.mobdrops.enderman", ModuleManager.MOB_DROPS, "cn.infstar.essentialsC.commands.MobDropCommand");
|
||||||
registerSubCommand("admin", "essentialsc.command.admin", "cn.infstar.essentialsC.commands.AdminCommand");
|
registerSubCommand("admin", "essentialsc.command.admin", ModuleManager.ADMIN_MODE, "cn.infstar.essentialsC.commands.AdminCommand");
|
||||||
}
|
}
|
||||||
|
|
||||||
private CommandRegistry() {
|
private CommandRegistry() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void register(String name, String permission, String className, String... aliases) {
|
private static void register(String name, String permission, String moduleKey, String className, String... aliases) {
|
||||||
register(name, permission, className, true, aliases);
|
register(name, permission, moduleKey, className, true, aliases);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void registerSubCommand(String name, String permission, String className, String... aliases) {
|
private static void registerSubCommand(String name, String permission, String moduleKey, String className, String... aliases) {
|
||||||
register(name, permission, className, false, aliases);
|
register(name, permission, moduleKey, className, false, aliases);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void register(String name, String permission, String className, boolean standalone, String... aliases) {
|
private static void register(String name, String permission, String moduleKey, String className, boolean standalone, String... aliases) {
|
||||||
List<String> aliasList = List.of(aliases);
|
List<String> aliasList = List.of(aliases);
|
||||||
CommandSpec spec = new CommandSpec(name, permission, className, aliasList, standalone);
|
CommandSpec spec = new CommandSpec(name, permission, moduleKey, className, aliasList, standalone);
|
||||||
COMMANDS.put(name, spec);
|
COMMANDS.put(name, spec);
|
||||||
ALIAS_TO_COMMAND.put(name, name);
|
ALIAS_TO_COMMAND.put(name, name);
|
||||||
for (String alias : aliasList) {
|
for (String alias : aliasList) {
|
||||||
@@ -91,6 +92,10 @@ public final class CommandRegistry {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isRuntimeDisabled(resolvedName)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
BaseCommand cached = COMMAND_CACHE.get(resolvedName);
|
BaseCommand cached = COMMAND_CACHE.get(resolvedName);
|
||||||
if (cached != null) {
|
if (cached != null) {
|
||||||
return cached;
|
return cached;
|
||||||
@@ -98,9 +103,6 @@ public final class CommandRegistry {
|
|||||||
if (UNAVAILABLE_COMMANDS.contains(resolvedName)) {
|
if (UNAVAILABLE_COMMANDS.contains(resolvedName)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (isRuntimeDisabled(resolvedName)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandSpec spec = COMMANDS.get(resolvedName);
|
CommandSpec spec = COMMANDS.get(resolvedName);
|
||||||
if (spec == null) {
|
if (spec == null) {
|
||||||
@@ -125,6 +127,21 @@ public final class CommandRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isRuntimeDisabled(String resolvedName) {
|
private static boolean isRuntimeDisabled(String resolvedName) {
|
||||||
|
CommandSpec spec = COMMANDS.get(resolvedName);
|
||||||
|
if (spec == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
EssentialsC plugin = EssentialsC.getPlugin(EssentialsC.class);
|
||||||
|
ModuleManager moduleManager = plugin.getModuleManager();
|
||||||
|
if (moduleManager != null && !moduleManager.isEnabled(spec.moduleKey())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (IllegalStateException ignored) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!"tpsbar".equals(resolvedName)) {
|
if (!"tpsbar".equals(resolvedName)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -138,6 +155,11 @@ public final class CommandRegistry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record CommandSpec(String name, String permission, String className, List<String> aliases, boolean standalone) {
|
public static void clearCache() {
|
||||||
|
COMMAND_CACHE.clear();
|
||||||
|
UNAVAILABLE_COMMANDS.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public record CommandSpec(String name, String permission, String moduleKey, String className, List<String> aliases, boolean standalone) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package cn.infstar.essentialsC.commands;
|
|||||||
|
|
||||||
import cn.infstar.essentialsC.EssentialsC;
|
import cn.infstar.essentialsC.EssentialsC;
|
||||||
import cn.infstar.essentialsC.LangManager;
|
import cn.infstar.essentialsC.LangManager;
|
||||||
|
import cn.infstar.essentialsC.ModuleManager;
|
||||||
import cn.infstar.essentialsC.tpsbar.TpsBarService;
|
import cn.infstar.essentialsC.tpsbar.TpsBarService;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
@@ -34,9 +35,15 @@ public class HelpCommand extends BaseCommand implements TabCompleter {
|
|||||||
}
|
}
|
||||||
plugin.reloadConfig();
|
plugin.reloadConfig();
|
||||||
EssentialsC.getLangManager().reload();
|
EssentialsC.getLangManager().reload();
|
||||||
|
plugin.getModuleManager().reload();
|
||||||
|
CommandRegistry.clearCache();
|
||||||
TpsBarService tpsBarService = plugin.getTpsBarManager();
|
TpsBarService tpsBarService = plugin.getTpsBarManager();
|
||||||
if (tpsBarService != null) {
|
if (tpsBarService != null) {
|
||||||
tpsBarService.reloadSettings();
|
if (plugin.getModuleManager().isEnabled(ModuleManager.TPSBAR)) {
|
||||||
|
tpsBarService.reloadSettings();
|
||||||
|
} else {
|
||||||
|
tpsBarService.shutdown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sender.sendMessage(getLang().getPrefixedString("messages.config-reloaded"));
|
sender.sendMessage(getLang().getPrefixedString("messages.config-reloaded"));
|
||||||
return true;
|
return true;
|
||||||
@@ -56,9 +63,15 @@ public class HelpCommand extends BaseCommand implements TabCompleter {
|
|||||||
}
|
}
|
||||||
plugin.reloadConfig();
|
plugin.reloadConfig();
|
||||||
EssentialsC.getLangManager().reload();
|
EssentialsC.getLangManager().reload();
|
||||||
|
plugin.getModuleManager().reload();
|
||||||
|
CommandRegistry.clearCache();
|
||||||
TpsBarService tpsBarService = plugin.getTpsBarManager();
|
TpsBarService tpsBarService = plugin.getTpsBarManager();
|
||||||
if (tpsBarService != null) {
|
if (tpsBarService != null) {
|
||||||
tpsBarService.reloadSettings();
|
if (plugin.getModuleManager().isEnabled(ModuleManager.TPSBAR)) {
|
||||||
|
tpsBarService.reloadSettings();
|
||||||
|
} else {
|
||||||
|
tpsBarService.shutdown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sender.sendMessage(getLang().getPrefixedString("messages.config-reloaded"));
|
sender.sendMessage(getLang().getPrefixedString("messages.config-reloaded"));
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -30,26 +30,26 @@ public class SeenCommand extends BaseCommand {
|
|||||||
|
|
||||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
StringBuilder info = new StringBuilder();
|
StringBuilder info = new StringBuilder();
|
||||||
info.append(getLang().getPrefix()).append(ChatColor.GOLD).append("Player info: ")
|
info.append(getLang().getPrefix()).append(ChatColor.GOLD).append("玩家信息: ")
|
||||||
.append(ChatColor.WHITE).append(target.getName()).append("\n");
|
.append(ChatColor.WHITE).append(target.getName()).append("\n");
|
||||||
|
|
||||||
if (target.isOnline()) {
|
if (target.isOnline()) {
|
||||||
info.append(ChatColor.GRAY).append("Status: ").append(ChatColor.GREEN).append("Online").append("\n");
|
info.append(ChatColor.GRAY).append("状态: ").append(ChatColor.GREEN).append("在线").append("\n");
|
||||||
Player onlinePlayer = target.getPlayer();
|
Player onlinePlayer = target.getPlayer();
|
||||||
if (onlinePlayer != null) {
|
if (onlinePlayer != null) {
|
||||||
info.append(ChatColor.GRAY).append("World: ").append(ChatColor.WHITE)
|
info.append(ChatColor.GRAY).append("所在世界: ").append(ChatColor.WHITE)
|
||||||
.append(onlinePlayer.getWorld().getName()).append("\n");
|
.append(onlinePlayer.getWorld().getName()).append("\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
info.append(ChatColor.GRAY).append("Status: ").append(ChatColor.RED).append("Offline").append("\n");
|
info.append(ChatColor.GRAY).append("状态: ").append(ChatColor.RED).append("离线").append("\n");
|
||||||
long lastSeen = target.getLastSeen();
|
long lastSeen = target.getLastSeen();
|
||||||
if (lastSeen > 0) {
|
if (lastSeen > 0) {
|
||||||
info.append(ChatColor.GRAY).append("Last seen: ").append(ChatColor.WHITE)
|
info.append(ChatColor.GRAY).append("最后在线: ").append(ChatColor.WHITE)
|
||||||
.append(format.format(new Date(lastSeen))).append("\n");
|
.append(format.format(new Date(lastSeen))).append("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
info.append(ChatColor.GRAY).append("First joined: ").append(ChatColor.WHITE)
|
info.append(ChatColor.GRAY).append("首次加入: ").append(ChatColor.WHITE)
|
||||||
.append(format.format(new Date(target.getFirstPlayed())));
|
.append(format.format(new Date(target.getFirstPlayed())));
|
||||||
|
|
||||||
player.sendMessage(info.toString());
|
player.sendMessage(info.toString());
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public class TpsBarCommand extends BaseCommand implements TabCompleter {
|
|||||||
protected boolean execute(Player player, String[] args) {
|
protected boolean execute(Player player, String[] args) {
|
||||||
TpsBarService tpsBarService = plugin.getTpsBarManager();
|
TpsBarService tpsBarService = plugin.getTpsBarManager();
|
||||||
if (tpsBarService == null) {
|
if (tpsBarService == null) {
|
||||||
player.sendMessage(getLang().getPrefixedString("messages.player-only"));
|
player.sendMessage(getLang().getPrefixedString("messages.module-disabled"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -274,12 +274,12 @@ public class ShulkerBoxListener implements Listener {
|
|||||||
|
|
||||||
private void writeInventoryBack(ItemStack shulkerItem, ItemStack[] contents) {
|
private void writeInventoryBack(ItemStack shulkerItem, ItemStack[] contents) {
|
||||||
if (!(shulkerItem.getItemMeta() instanceof BlockStateMeta blockStateMeta)) {
|
if (!(shulkerItem.getItemMeta() instanceof BlockStateMeta blockStateMeta)) {
|
||||||
plugin.getLogger().warning("Failed to save shulker box contents: missing BlockStateMeta.");
|
plugin.getLogger().warning("保存潜影盒内容失败: 缺少 BlockStateMeta。");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(blockStateMeta.getBlockState() instanceof ShulkerBox shulkerBox)) {
|
if (!(blockStateMeta.getBlockState() instanceof ShulkerBox shulkerBox)) {
|
||||||
plugin.getLogger().warning("Failed to save shulker box contents: block state is not a ShulkerBox.");
|
plugin.getLogger().warning("保存潜影盒内容失败: 方块状态不是 ShulkerBox。");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ messages:
|
|||||||
paper-version: "&7Running on Paper {version}"
|
paper-version: "&7Running on Paper {version}"
|
||||||
unknown-subcommand: "&cUnknown subcommand: {command}"
|
unknown-subcommand: "&cUnknown subcommand: {command}"
|
||||||
help-usage: "&7Use &f/essc help &7to view available commands."
|
help-usage: "&7Use &f/essc help &7to view available commands."
|
||||||
|
module-disabled: "&cThis feature module is currently disabled. Please contact an administrator."
|
||||||
blocks-menu-empty: "&cYou do not currently have any available shortcut menu entries."
|
blocks-menu-empty: "&cYou do not currently have any available shortcut menu entries."
|
||||||
|
|
||||||
hat-success: "&aYou are now wearing {item} on your head!"
|
hat-success: "&aYou are now wearing {item} on your head!"
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ messages:
|
|||||||
paper-version: "&7当前运行于 Paper {version}"
|
paper-version: "&7当前运行于 Paper {version}"
|
||||||
unknown-subcommand: "&c未知子命令:{command}"
|
unknown-subcommand: "&c未知子命令:{command}"
|
||||||
help-usage: "&7使用 &f/essc help &7查看可用命令。"
|
help-usage: "&7使用 &f/essc help &7查看可用命令。"
|
||||||
|
module-disabled: "&c该功能模块当前已关闭,请联系管理员。"
|
||||||
blocks-menu-empty: "&c你当前没有可用的便捷菜单项目。"
|
blocks-menu-empty: "&c你当前没有可用的便捷菜单项目。"
|
||||||
|
|
||||||
hat-success: "&a你已将 {item} 戴在头上!"
|
hat-success: "&a你已将 {item} 戴在头上!"
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# EssentialsC 模块配置
|
||||||
|
#
|
||||||
|
# modules.yml 用于控制功能模块是否在运行时加载。
|
||||||
|
# config.yml 仍然用于控制已启用模块内部的具体行为。
|
||||||
|
#
|
||||||
|
# 将模块设置为 false 后,建议重启服务器,以完全注销对应命令和监听器。
|
||||||
|
|
||||||
|
config-version: 1
|
||||||
|
|
||||||
|
modules:
|
||||||
|
blocks:
|
||||||
|
# 工作台、铁砧等便捷方块命令、/essc blocks 菜单和潜影盒快捷打开。
|
||||||
|
enabled: true
|
||||||
|
player:
|
||||||
|
# 玩家常用命令:飞行、夜视、发光、治疗、喂食、修复、帽子、自杀、隐身和查询玩家。
|
||||||
|
enabled: true
|
||||||
|
admin-mode:
|
||||||
|
# /essc admin 管理模式,以及独立背包和状态管理。
|
||||||
|
enabled: true
|
||||||
|
tpsbar:
|
||||||
|
# 插件版 TPSBar。config.yml 中的 tpsbar.mode 仍会决定遇到原生 /tpsbar 时的行为。
|
||||||
|
enabled: true
|
||||||
|
jei-sync:
|
||||||
|
# Fabric / NeoForge JEI 配方同步兼容修复。
|
||||||
|
enabled: true
|
||||||
|
mob-drops:
|
||||||
|
# 末影人掉落控制菜单和监听器。默认关闭,用于保留过去标准版的行为。
|
||||||
|
enabled: false
|
||||||
@@ -89,6 +89,9 @@ permissions:
|
|||||||
essentialsc.command.tpsbar:
|
essentialsc.command.tpsbar:
|
||||||
description: 允许使用 /tpsbar
|
description: 允许使用 /tpsbar
|
||||||
default: op
|
default: op
|
||||||
|
essentialsc.command.tpsbar.others:
|
||||||
|
description: 允许为其他玩家切换 /tpsbar
|
||||||
|
default: op
|
||||||
essentialsc.shulkerbox.open:
|
essentialsc.shulkerbox.open:
|
||||||
description: 允许通过 Shift+右键快捷打开潜影盒
|
description: 允许通过 Shift+右键快捷打开潜影盒
|
||||||
default: op
|
default: op
|
||||||
@@ -125,5 +128,6 @@ permissions:
|
|||||||
essentialsc.command.help: true
|
essentialsc.command.help: true
|
||||||
essentialsc.command.reload: true
|
essentialsc.command.reload: true
|
||||||
essentialsc.command.tpsbar: true
|
essentialsc.command.tpsbar: true
|
||||||
|
essentialsc.command.tpsbar.others: true
|
||||||
essentialsc.shulkerbox.open: true
|
essentialsc.shulkerbox.open: true
|
||||||
essentialsc.mobdrops.enderman: true
|
essentialsc.mobdrops.enderman: true
|
||||||
|
|||||||
Reference in New Issue
Block a user