1
mirror of https://github.com/CarmJos/UserPrefix.git synced 2026-06-05 09:01:39 +08:00

Compare commits

...

67 Commits

Author SHA1 Message Date
carm e5013b76e0 feat: 新增prefix变量支持 2025-07-22 16:05:22 +08:00
carm 6604cec136 feat: 添加 description 变量 2025-07-20 21:33:59 +08:00
renovate[bot] c7f3286d81 fix(deps): update dependency net.luckperms:api to v5.5 (#103)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-20 08:58:11 +00:00
renovate[bot] 5ed6f1a301 chore(deps): update dependency org.apache.maven.plugins:maven-clean-plugin to v3.5.0 (#102)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-20 04:43:17 +00:00
renovate[bot] 9864d5a75e chore(deps): update dependency com.github.cryptomorin:xseries to v13.3.3 (#101)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-20 02:05:27 +00:00
renovate[bot] 2b8a7e7545 chore(deps): update deps.easyplugin.version to v1.5.14 (#100)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-19 21:48:43 +00:00
renovate[bot] 25b961b913 chore(deps): update dependency cc.carm.lib:mineconfiguration-bukkit to v3.1.3 (#99)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-19 18:50:35 +00:00
carm 8e8427a937 feat: 为物品配置支持变量与描述插入。 2025-07-19 20:38:16 +08:00
renovate[bot] 748335a962 chore(deps): update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.5.3 2025-05-12 18:15:10 +08:00
renovate[bot] 1e0fd2bcd4 chore(deps): update dependency com.github.cryptomorin:xseries to v13.2.0 2025-05-12 18:15:00 +08:00
flowerinsnow 04caf2df73 revert: change api-version to 1.13 2025-05-12 18:14:49 +08:00
flowerinsnow 0eba124f08 revert: no more mirror repo 2025-05-12 18:14:49 +08:00
flowerinsnow d54349da98 feat: use reflection instead folia dependencies, java 8 supported 2025-05-12 18:14:49 +08:00
flowerinsnow eab9b2385c feat: folia support 2025-05-12 18:14:49 +08:00
flowerinsnow 003884d772 fix: use 3.0 MineConfiguration 2025-05-12 18:14:49 +08:00
renovate[bot] 610242ff62 chore(deps): update dependency cc.carm.lib:mineconfiguration-bukkit to v3.1.1 2025-04-18 10:56:29 +08:00
renovate[bot] 289ab87273 chore(deps): update dependency com.github.cryptomorin:xseries to v13.1.0 2025-04-18 10:56:22 +08:00
renovate[bot] 46c1c03113 chore(deps): update dependency cc.carm.lib:mineconfiguration-bukkit to v3 2025-03-12 04:37:14 +08:00
renovate[bot] 5ddde2aa99 chore(deps): update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.14.0 (#87)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-09 18:57:52 +00:00
renovate[bot] 38a9b0866c chore(deps): update dependency org.apache.maven.plugins:maven-clean-plugin to v3.4.1 (#86)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-09 15:55:02 +00:00
carm e7b5b78d66 ci(doc): 修复javadoc地址错误的问题 2025-02-05 00:24:46 +08:00
carm ca83cc63a5 feat: 小版本更新 2025-02-05 00:18:00 +08:00
carm 3c19c8165f feat(content): 为前缀内容支持PAPI。 2025-02-04 15:03:39 +08:00
carm 844f59af20 chore: 打开界面前不再强制关闭GUI 2025-02-04 12:50:57 +08:00
renovate[bot] 4d42982659 fix(deps): update dependency org.jetbrains:annotations to v26.0.2 (#82)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-24 09:46:22 +00:00
renovate[bot] f272456079 fix(deps): update dependency org.bstats:bstats-bukkit to v3.1.0 2025-01-18 02:18:26 +08:00
renovate[bot] 50be238b36 fix(deps): update dependency me.clip:placeholderapi to v2.11.6 2025-01-18 02:18:23 +08:00
renovate[bot] b7341290ec chore(deps): update dependency org.apache.maven.plugins:maven-source-plugin to v3.3.1 2025-01-18 02:18:20 +08:00
renovate[bot] af59a8cb4b chore(deps): update dependency org.apache.maven.plugins:maven-shade-plugin to v3.6.0 2025-01-18 02:18:16 +08:00
renovate[bot] 30f4ca9af1 chore(deps): update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.11.2 2025-01-18 02:18:12 +08:00
renovate[bot] 61350cde57 chore(deps): update dependency org.apache.maven.plugins:maven-jar-plugin to v3.4.2 2025-01-18 02:18:09 +08:00
renovate[bot] ba3c7d5c32 chore(deps): update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.13.0 2025-01-18 02:18:06 +08:00
renovate[bot] 3b06ca8109 chore(deps): update dependency cc.carm.lib:mineconfiguration-bukkit to v2.9.3 2025-01-18 02:16:26 +08:00
renovate[bot] 5edde945d1 chore(deps): update actions/checkout action to v4 2025-01-18 02:03:01 +08:00
renovate[bot] 4de8863ab6 chore(deps): update actions/setup-java action to v4 2025-01-18 02:02:51 +08:00
renovate[bot] 3c40419437 chore(deps): update dependency com.github.cryptomorin:xseries to v13 2025-01-18 02:02:41 +08:00
renovate[bot] d18ce24841 chore(deps): update deps.easyplugin.version to v1.5.12 2025-01-18 02:02:27 +08:00
renovate[bot] 0b62bcd1ef chore(deps): update dependency org.apache.maven.plugins:maven-clean-plugin to v3 2025-01-18 02:02:15 +08:00
carm e2aadfde23 chore:Update renovate.json 2025-01-18 01:58:19 +08:00
renovate[bot] 4ca145dbef chore(deps): update github/codeql-action action to v3 2025-01-18 01:52:47 +08:00
renovate[bot] 1b8d499d28 chore(deps): update dependency org.apache.maven.plugins:maven-surefire-plugin to v3 2025-01-18 01:33:46 +08:00
renovate[bot] 0c182a8ed3 fix(deps): update dependency org.jetbrains:annotations to v26 2025-01-18 01:33:19 +08:00
carm 66e2302fd0 Update renovate.json 2025-01-18 01:31:34 +08:00
carm 824a65b21c chore: Update renovate.json 2025-01-18 01:29:33 +08:00
renovate[bot] 2c49377c33 Add renovate.json (#60)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-18 00:00:55 +08:00
carm a0f8382830 doc(color): 添加渐变色用法实例 2024-09-28 23:48:35 +08:00
carm 675bbe4cf2 chore(deps): 升级依赖版本 2024-09-26 22:40:43 +08:00
carm 3b8fd6febf chore(deps): 升级依赖版本 2024-09-26 22:35:24 +08:00
carm d8282b9641 chore(deps): 升级依赖版本 2024-09-26 21:46:20 +08:00
carm ad616e5470 chore(deps): 支持1.21版本 2024-07-20 19:17:56 +08:00
carm f741723204 chore(deps): 更新 XSeries 尝试解决 #51 2024-07-17 06:40:34 +08:00
carm 54f526300a chore(deps): 更新 XSeries 尝试解决 #51 2024-07-17 06:35:53 +08:00
carm 5a0e5b8e96 chore(deps): 更新 XSeries 尝试解决 #51 2024-07-17 06:35:44 +08:00
skylandnewmc c89a9c6ccc Update ejemplo-prefijo.yml (#49) 2023-12-21 15:06:02 +08:00
skylandnewmc e321a1ec66 Update ejemplo-prefijo.yml (#48) 2023-11-06 00:41:40 +08:00
carm 9054161135 fix(msg): 修复消息占位符顺序错误 #47 2023-10-23 13:00:59 +08:00
carm 53281b80e3 chore(item): 更换物品的配置逻辑,支持跨版本的物品读取、保存。
BREAKING-CHANGE: 旧的配置文件需要进行变更。
2023-10-12 20:15:30 +08:00
carm 12489fe1a8 chore(item): 更换物品的配置逻辑,支持跨版本的物品读取、保存。
BREAKING-CHANGE: 旧的配置文件需要进行变更。
2023-10-12 20:09:24 +08:00
carm 7d62f68662 chore(item): 更换物品的配置逻辑,支持跨版本的物品读取、保存。
BREAKING-CHANGE: 旧的配置文件需要进行变更。
2023-10-10 15:20:40 +08:00
carm 4cc50c21d5 chore(item): 更换物品的配置逻辑,支持跨版本的物品读取、保存。
BREAKING-CHANGE: 旧的配置文件需要进行变更。
2023-10-10 15:01:51 +08:00
skylandnewmc 0d25490d0f feat(i18n): example-prefix.yml translated to Spanish 2023-09-28 12:57:12 +08:00
carm a805aba42e fix(auto): 修复自动前缀判断错误的问题 2023-09-21 22:26:21 +08:00
Snowball_233 2a0d6b8582 fix(papi): 添加“持久”标签 避免卸载。
Co-authored-by: Carm <KarmunJ@outlook.com>
2023-07-16 23:22:18 +08:00
carm 1ea993a31b feat(gui): 支持配置更多GUI按钮。(#44) 2023-02-23 22:27:22 +08:00
carm 8ce82ec7fd chore(expansion): 适配新版EasyPlugin提供的解析器 2023-02-19 04:19:51 +08:00
carm 6fb9daa3d3 docs(donate): Thanks for Jetbrains! 2023-02-15 00:33:08 +08:00
carm da23eaa8fe fix(placeholder): 修复PlaceholderAPI重载后变量失效的问题 2023-02-01 15:32:08 +08:00
31 changed files with 711 additions and 311 deletions
+4 -4
View File
@@ -38,11 +38,11 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v2 uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v1 uses: github/codeql-action/init@v3
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file. # If you wish to specify custom queries, you can do so here or in a config file.
@@ -53,7 +53,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@v1 uses: github/codeql-action/autobuild@v3
# ️ Command-line programs to run using the OS shell. # ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl # 📚 https://git.io/JvXDl
@@ -67,4 +67,4 @@ jobs:
# make release # make release
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1 uses: github/codeql-action/analyze@v3
+3 -3
View File
@@ -16,9 +16,9 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: "Set up JDK" - name: "Set up JDK"
uses: actions/setup-java@v2 uses: actions/setup-java@v4
with: with:
java-version: '11' java-version: '11'
distribution: 'adopt' distribution: 'adopt'
@@ -47,7 +47,7 @@ jobs:
run: | run: |
rm -rf docs rm -rf docs
mkdir -vp docs mkdir -vp docs
cp -vrf target/apidocs/* docs/ cp -vrf target/reports/apidocs/* docs/
cp -vrf .documentation/JAVADOC-README.md docs/README.md cp -vrf .documentation/JAVADOC-README.md docs/README.md
- name: "Generate the Javadoc sitemap" - name: "Generate the Javadoc sitemap"
+5 -4
View File
@@ -14,9 +14,9 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: "Set up JDK" - name: "Set up JDK"
uses: actions/setup-java@v2 uses: actions/setup-java@v4
with: with:
java-version: '11' java-version: '11'
distribution: 'adopt' distribution: 'adopt'
@@ -37,7 +37,8 @@ jobs:
cp -vrf asset/*.jar artifacts cp -vrf asset/*.jar artifacts
- name: "Upload artifact" - name: "Upload artifact"
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v4
with: with:
name: Artifact name: Artifact
path: artifacts path: artifacts
include-hidden-files: true
+2
View File
@@ -49,6 +49,8 @@ For development dependencies, please see [Dependencies](https://github.com/Carm
- Support PlaceholderAPI variables! - Support PlaceholderAPI variables!
- Support [Hex Color](https://www.hexcolortool.com/)! (Version 1.16 and above) `&(#Color)` - Support [Hex Color](https://www.hexcolortool.com/)! (Version 1.16 and above) `&(#Color)`
- Example: LightSlateBlue `&(#8470FF)` 、 DarkSlateBlue `&(#483D8B)` - Example: LightSlateBlue `&(#8470FF)` 、 DarkSlateBlue `&(#483D8B)`
- Support Gradient Color! (Version 1.16 and above) `&<#Color1>Message&<#Color2>`
- Example: `&<#8470FF>Hello World!&<#483D8B>`
## Notice ## Notice
+9 -5
View File
@@ -45,6 +45,9 @@ README LANGUAGES [ [**中文**](README.md) | [English](README-en.md) ]
- 支持[Hex颜色](https://www.hexcolortool.com/)(1.16以上版本) `[自 v1.2.3 版本起]` - 支持[Hex颜色](https://www.hexcolortool.com/)(1.16以上版本) `[自 v1.2.3 版本起]`
- 格式: `&(#颜色代码)` - 格式: `&(#颜色代码)`
- 示例: LightSlateBlue `&(#8470FF)` 、 DarkSlateBlue `&(#483D8B)` - 示例: LightSlateBlue `&(#8470FF)` 、 DarkSlateBlue `&(#483D8B)`
- 支持渐变色!(1.16以上版本) `[自 v1.2.3 版本起]`
- 格式: `&<#颜色代码1>消息内容&<#颜色代码2>`
- 示例: `&<#8470FF>Hello World!&<#483D8B>`
## 注意事项 ## 注意事项
@@ -117,11 +120,10 @@ README LANGUAGES [ [**中文**](README.md) | [English](README-en.md) ]
本项目由 [YourCraft(你的世界)](https://www.ycraft.cn) 团队提供长期支持与维护。 本项目由 [YourCraft(你的世界)](https://www.ycraft.cn) 团队提供长期支持与维护。
![TeamLogo](.documentation/images/team-logo.png) ![TeamLogo](.documentation/images/team-logo.png)
若您觉得本插件做的不错,您可以捐赠支持我! 若您觉得本插件做的不错,您可以捐赠支持我!感谢您成为开源项目的支持者!
感谢您成为开源项目的支持者! Many thanks to Jetbrains for kindly providing a license for me to work on this and other open-source projects.
[![](https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg)](https://www.jetbrains.com/?from=https://github.com/CarmJos/UserPrefix)
<img height=25% width=25% src="https://raw.githubusercontent.com/CarmJos/CarmJos/main/img/donate-code.jpg" alt=""/>
## 开源协议 ## 开源协议
@@ -145,4 +147,6 @@ README LANGUAGES [ [**中文**](README.md) | [English](README-en.md) ]
> 协议,你必须在源代码代码中包含相应信息,以及协议本身。 > 协议,你必须在源代码代码中包含相应信息,以及协议本身。
> >
> *以上文字来自 [五种开源协议GPL,LGPL,BSD,MIT,Apache](https://www.oschina.net/question/54100_9455) 。* > *以上文字来自 [五种开源协议GPL,LGPL,BSD,MIT,Apache](https://www.oschina.net/question/54100_9455) 。*
</details> </details>
## Project supported by JetBrains
+65 -21
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<properties> <properties>
@@ -13,13 +13,13 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding> <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<easyplugin.version>1.4.18</easyplugin.version> <deps.easyplugin.version>1.5.14</deps.easyplugin.version>
<mineconfig.version>2.3.0</mineconfig.version> <deps.mineconfig.version>3.1.3</deps.mineconfig.version>
</properties> </properties>
<groupId>cc.carm.plugin</groupId> <groupId>cc.carm.plugin</groupId>
<artifactId>userprefix</artifactId> <artifactId>userprefix</artifactId>
<version>3.1.1</version> <version>3.2.7</version>
<name>UserPrefix</name> <name>UserPrefix</name>
<description>轻便、高效、实时的用户前缀系统。</description> <description>轻便、高效、实时的用户前缀系统。</description>
@@ -81,6 +81,12 @@
<url>https://repo.lucko.me/</url> <url>https://repo.lucko.me/</url>
</repository> </repository>
<repository>
<id>minecraft-libraries</id>
<name>Minecraft Libraries</name>
<url>https://libraries.minecraft.net/</url>
</repository>
<repository> <repository>
<id>EasyPlugin</id> <id>EasyPlugin</id>
<url>https://raw.githubusercontent.com/CarmJos/EasyPlugin/repo/</url> <url>https://raw.githubusercontent.com/CarmJos/EasyPlugin/repo/</url>
@@ -108,7 +114,7 @@
<dependency> <dependency>
<groupId>cc.carm.lib</groupId> <groupId>cc.carm.lib</groupId>
<artifactId>easyplugin-main</artifactId> <artifactId>easyplugin-main</artifactId>
<version>${easyplugin.version}</version> <version>${deps.easyplugin.version}</version>
<scope>compile</scope> <scope>compile</scope>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
@@ -116,7 +122,7 @@
<dependency> <dependency>
<groupId>cc.carm.lib</groupId> <groupId>cc.carm.lib</groupId>
<artifactId>easyplugin-command</artifactId> <artifactId>easyplugin-command</artifactId>
<version>${easyplugin.version}</version> <version>${deps.easyplugin.version}</version>
<scope>compile</scope> <scope>compile</scope>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
@@ -124,15 +130,24 @@
<dependency> <dependency>
<groupId>cc.carm.lib</groupId> <groupId>cc.carm.lib</groupId>
<artifactId>easyplugin-gui</artifactId> <artifactId>easyplugin-gui</artifactId>
<version>${easyplugin.version}</version> <version>${deps.easyplugin.version}</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<!--suppress VulnerableLibrariesLocal -->
<dependency>
<groupId>cc.carm.lib</groupId>
<artifactId>easyplugin-githubchecker</artifactId>
<version>${deps.easyplugin.version}</version>
<scope>compile</scope> <scope>compile</scope>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>
<groupId>cc.carm.lib</groupId> <groupId>cc.carm.lib</groupId>
<artifactId>easyplugin-githubchecker</artifactId> <artifactId>easyplugin-placeholderapi</artifactId>
<version>${easyplugin.version}</version> <version>${deps.easyplugin.version}</version>
<scope>compile</scope> <scope>compile</scope>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
@@ -140,9 +155,34 @@
<dependency> <dependency>
<groupId>cc.carm.lib</groupId> <groupId>cc.carm.lib</groupId>
<artifactId>mineconfiguration-bukkit</artifactId> <artifactId>mineconfiguration-bukkit</artifactId>
<version>${mineconfig.version}</version> <version>${deps.mineconfig.version}</version>
<scope>compile</scope> <scope>compile</scope>
<optional>true</optional> <optional>true</optional>
<exclusions>
<exclusion>
<groupId>com.cryptomorin.xseries</groupId>
<artifactId>XSeries</artifactId>
</exclusion>
<exclusion>
<groupId>com.github.cryptomorin</groupId>
<artifactId>XSeries</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.cryptomorin</groupId>
<artifactId>XSeries</artifactId>
<version>13.3.3</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.mojang</groupId>
<artifactId>authlib</artifactId>
<version>6.0.54</version>
<scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
@@ -155,28 +195,28 @@
<dependency> <dependency>
<groupId>me.clip</groupId> <groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId> <artifactId>placeholderapi</artifactId>
<version>2.10.9</version> <version>2.11.6</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.luckperms</groupId> <groupId>net.luckperms</groupId>
<artifactId>api</artifactId> <artifactId>api</artifactId>
<version>5.4</version> <version>5.5</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.bstats</groupId> <groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId> <artifactId>bstats-bukkit</artifactId>
<version>3.0.0</version> <version>3.1.0</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.jetbrains</groupId> <groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId> <artifactId>annotations</artifactId>
<version>23.0.0</version> <version>26.0.2</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
@@ -193,7 +233,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId> <artifactId>maven-clean-plugin</artifactId>
<version>2.5</version> <version>3.5.0</version>
<configuration> <configuration>
<filesets> <filesets>
<fileset> <fileset>
@@ -216,7 +256,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version> <version>3.14.0</version>
<configuration> <configuration>
<source>${project.jdk.version}</source> <source>${project.jdk.version}</source>
<target>${project.jdk.version}</target> <target>${project.jdk.version}</target>
@@ -227,12 +267,12 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId> <artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version> <version>3.4.2</version>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId> <artifactId>maven-source-plugin</artifactId>
<version>3.2.0</version> <version>3.3.1</version>
<executions> <executions>
<execution> <execution>
<phase>package</phase> <phase>package</phase>
@@ -245,7 +285,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId> <artifactId>maven-shade-plugin</artifactId>
<version>3.2.3</version> <version>3.6.0</version>
<executions> <executions>
<execution> <execution>
<phase>package</phase> <phase>package</phase>
@@ -272,6 +312,10 @@
<pattern>org.json</pattern> <pattern>org.json</pattern>
<shadedPattern>${project.package}.lib.json</shadedPattern> <shadedPattern>${project.package}.lib.json</shadedPattern>
</relocation> </relocation>
<relocation>
<pattern>com.cryptomorin.xseries</pattern>
<shadedPattern>${project.package}.lib.xseries</shadedPattern>
</relocation>
</relocations> </relocations>
<filters> <filters>
<filter> <filter>
@@ -287,7 +331,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version> <version>3.11.2</version>
<configuration> <configuration>
<classifier>javadoc</classifier> <classifier>javadoc</classifier>
<links> <links>
@@ -314,7 +358,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version> <version>3.5.3</version>
<configuration> <configuration>
<useSystemClassLoader>false</useSystemClassLoader> <useSystemClassLoader>false</useSystemClassLoader>
</configuration> </configuration>
+13
View File
@@ -0,0 +1,13 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base","mergeConfidence:all-badges"
],
"packageRules": [
{
"description": "Automerge non-major updates",
"matchUpdateTypes": ["minor", "patch"],
"automerge": true
}
]
}
@@ -8,6 +8,7 @@ import cc.carm.lib.easyplugin.utils.MessageUtils;
import cc.carm.plugin.userprefix.command.AdminCommand; import cc.carm.plugin.userprefix.command.AdminCommand;
import cc.carm.plugin.userprefix.command.UserCommand; import cc.carm.plugin.userprefix.command.UserCommand;
import cc.carm.plugin.userprefix.conf.PluginConfig; import cc.carm.plugin.userprefix.conf.PluginConfig;
import cc.carm.plugin.userprefix.folia.FoliaScheduler;
import cc.carm.plugin.userprefix.hooker.UserPrefixExpansion; import cc.carm.plugin.userprefix.hooker.UserPrefixExpansion;
import cc.carm.plugin.userprefix.listener.ChatListener; import cc.carm.plugin.userprefix.listener.ChatListener;
import cc.carm.plugin.userprefix.listener.UserListener; import cc.carm.plugin.userprefix.listener.UserListener;
@@ -28,6 +29,9 @@ public class Main extends EasyPlugin {
private static Main instance; private static Main instance;
protected FoliaScheduler foliaScheduler;
protected boolean onFolia;
protected ConfigManager configManager; protected ConfigManager configManager;
protected PrefixManager prefixManager; protected PrefixManager prefixManager;
protected UserManager userManager; protected UserManager userManager;
@@ -36,6 +40,14 @@ public class Main extends EasyPlugin {
protected boolean initialize() { protected boolean initialize() {
instance = this; instance = this;
try {
Class.forName("io.papermc.paper.threadedregions.RegionizedServerInitEvent");
this.onFolia = true;
} catch (ClassNotFoundException e) {
this.onFolia = false;
}
this.foliaScheduler = new FoliaScheduler(this, this.onFolia);
log("加载插件配置..."); log("加载插件配置...");
this.configManager = new ConfigManager(getDataFolder()); this.configManager = new ConfigManager(getDataFolder());
this.prefixManager = new PrefixManager(); this.prefixManager = new PrefixManager();
@@ -61,12 +73,12 @@ public class Main extends EasyPlugin {
log("初始化GUI管理器..."); log("初始化GUI管理器...");
GUI.initialize(this); GUI.initialize(this);
AutoPagedGUI.defaultNextPage = (PluginConfig.GUI.ITEMS.NEXT_PAGE::getItem); AutoPagedGUI.defaultNextPage = (PluginConfig.GUI.BOTTOMS.NEXT_PAGE::get);
AutoPagedGUI.defaultPreviousPage = (PluginConfig.GUI.ITEMS.PREV_PAGE::getItem); AutoPagedGUI.defaultPreviousPage = (PluginConfig.GUI.BOTTOMS.PREV_PAGE::get);
if (MessageUtils.hasPlaceholderAPI()) { if (MessageUtils.hasPlaceholderAPI()) {
log("注册变量..."); log("注册变量...");
new UserPrefixExpansion(getInstance()).register(); new UserPrefixExpansion(this, getName()).register();
} else { } else {
log("未安装 PlaceholderAPI ,跳过变量注册..."); log("未安装 PlaceholderAPI ,跳过变量注册...");
log("若您想使用变量进行前缀的显示,请安装PlaceholderAPI"); log("若您想使用变量进行前缀的显示,请安装PlaceholderAPI");
@@ -87,11 +99,14 @@ public class Main extends EasyPlugin {
if (PluginConfig.CHECK_UPDATE.getNotNull()) { if (PluginConfig.CHECK_UPDATE.getNotNull()) {
log("开始检查更新..."); log("开始检查更新...");
getScheduler().runAsync(GHUpdateChecker.runner(this)); this.foliaScheduler.runAsync(GHUpdateChecker.runner(this));
} else { } else {
log("已禁用检查更新,跳过。"); log("已禁用检查更新,跳过。");
} }
if (PluginConfig.FUNCTIONS.NAME_PREFIX.ENABLE.getNotNull() && this.isOnFolia()) {
log("插件正运行在 Folia 服务端上,头顶前缀功能不可用");
}
Bukkit.getOnlinePlayers().forEach(userManager::initPlayer); // 适配热重载 Bukkit.getOnlinePlayers().forEach(userManager::initPlayer); // 适配热重载
log("&7感谢您使用 &3&lUserPrefix " + getDescription().getVersion() + "&7!"); log("&7感谢您使用 &3&lUserPrefix " + getDescription().getVersion() + "&7!");
@@ -113,6 +128,14 @@ public class Main extends EasyPlugin {
log("&7本插件由 &b&lYourCraft &7提供长期支持与维护。"); log("&7本插件由 &b&lYourCraft &7提供长期支持与维护。");
} }
public boolean isOnFolia() {
return this.onFolia;
}
public FoliaScheduler getFoliaScheduler() {
return this.foliaScheduler;
}
@Override @Override
public boolean isDebugging() { public boolean isDebugging() {
return PluginConfig.DEBUG.getNotNull(); return PluginConfig.DEBUG.getNotNull();
@@ -26,12 +26,12 @@ public class AdminCommand extends CommandHandler {
@Override @Override
public Void noPermission(CommandSender sender) { public Void noPermission(CommandSender sender) {
PluginMessages.COMMAND_USAGE.NO_PERM.send(sender); PluginMessages.COMMAND_USAGE.NO_PERM.sendTo(sender);
return null; return null;
} }
public static Void help(CommandSender sender) { public static Void help(CommandSender sender) {
PluginMessages.COMMAND_USAGE.ADMIN.send(sender); PluginMessages.COMMAND_USAGE.ADMIN.sendTo(sender);
return null; return null;
} }
@@ -18,7 +18,7 @@ public class UserCommand implements CommandExecutor {
PrefixSelectGUI.open((Player) sender); PrefixSelectGUI.open((Player) sender);
} else { } else {
if (strings.length != 1) { if (strings.length != 1) {
PluginMessages.COMMAND_USAGE.CONSOLE.send(sender); PluginMessages.COMMAND_USAGE.CONSOLE.sendTo(sender);
} else { } else {
Player player = Bukkit.getPlayer(strings[0]); Player player = Bukkit.getPlayer(strings[0]);
if (player != null) { if (player != null) {
@@ -17,12 +17,12 @@ public class ListCommand extends SubCommand<AdminCommand> {
@Override @Override
public Void execute(JavaPlugin plugin, CommandSender sender, String[] args) { public Void execute(JavaPlugin plugin, CommandSender sender, String[] args) {
PluginMessages.LIST.HEADER.send(sender); PluginMessages.LIST.HEADER.sendTo(sender);
for (PrefixConfig value : UserPrefixAPI.getPrefixManager().getPrefixes().values()) { for (PrefixConfig value : UserPrefixAPI.getPrefixManager().getPrefixes().values()) {
PluginMessages.LIST.VALUE.send(sender, PluginMessages.LIST.VALUE.sendTo(sender,
value.getWeight(), value.getIdentifier(), value.getWeight(), value.getIdentifier(),
value.getName(), value.getPermission(), value.getName(), value.getPermission(),
value.getContent(), sender.getName() value.getContent(sender), sender.getName()
); );
} }
return null; return null;
@@ -33,9 +33,9 @@ public class ReloadCommand extends SubCommand<AdminCommand> {
*/ */
UserPrefixAPI.getUserManager().updatePrefixView(onlinePlayer, false); UserPrefixAPI.getUserManager().updatePrefixView(onlinePlayer, false);
} }
PluginMessages.RELOAD.SUCCESS.send(sender, System.currentTimeMillis() - s1, num); PluginMessages.RELOAD.SUCCESS.sendTo(sender, System.currentTimeMillis() - s1, num);
} catch (Exception e) { } catch (Exception e) {
PluginMessages.RELOAD.FAILED.send(sender, e.getMessage()); PluginMessages.RELOAD.FAILED.sendTo(sender, e.getMessage());
e.printStackTrace(); e.printStackTrace();
} }
return null; return null;
@@ -23,7 +23,7 @@ public class SetCommand extends SubCommand<AdminCommand> {
Player target = Bukkit.getPlayer(args[0]); Player target = Bukkit.getPlayer(args[0]);
if (target == null) { if (target == null) {
PluginMessages.NOT_ONLINE.send(sender, args[0]); PluginMessages.NOT_ONLINE.sendTo(sender, args[0]);
return null; return null;
} }
@@ -37,17 +37,17 @@ public class SetCommand extends SubCommand<AdminCommand> {
} }
if (prefixConfig == null) { if (prefixConfig == null) {
PluginMessages.SET.PREFIX_NOT_FOUND.send(sender, prefixInput); PluginMessages.SET.PREFIX_NOT_FOUND.sendTo(sender, prefixInput);
return null; return null;
} }
if (!prefixConfig.checkPermission(target)) { if (!prefixConfig.checkPermission(target)) {
PluginMessages.SET.NO_PERM.send(sender, target.getName(), prefixConfig.getName()); PluginMessages.SET.NO_PERM.sendTo(sender, target.getName(), prefixConfig.getName());
return null; return null;
} }
UserPrefixAPI.getUserManager().setPrefix(target, prefixConfig, true); UserPrefixAPI.getUserManager().setPrefix(target, prefixConfig, true);
PluginMessages.SET.SUCCESS.send(sender, target.getName(), prefixConfig.getName()); PluginMessages.SET.SUCCESS.sendTo(sender, target.getName(), prefixConfig.getName());
return null; return null;
} }
@@ -1,108 +1,102 @@
package cc.carm.plugin.userprefix.conf; package cc.carm.plugin.userprefix.conf;
import cc.carm.lib.configuration.core.ConfigurationRoot; import cc.carm.lib.configuration.Configuration;
import cc.carm.lib.configuration.core.annotation.ConfigPath; import cc.carm.lib.configuration.annotation.ConfigPath;
import cc.carm.lib.configuration.core.annotation.HeaderComment; import cc.carm.lib.configuration.annotation.HeaderComments;
import cc.carm.lib.configuration.core.value.ConfigValue; import cc.carm.lib.configuration.value.standard.ConfiguredList;
import cc.carm.lib.configuration.core.value.type.ConfiguredList; import cc.carm.lib.configuration.value.standard.ConfiguredValue;
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
import cc.carm.lib.easyplugin.gui.configuration.GUIActionConfiguration;
import cc.carm.lib.easyplugin.gui.configuration.GUIActionType;
import cc.carm.lib.easyplugin.gui.configuration.GUIItemConfiguration;
import cc.carm.lib.mineconfiguration.bukkit.source.CraftSectionWrapper;
import cc.carm.lib.mineconfiguration.bukkit.value.ConfiguredItem;
import cc.carm.lib.mineconfiguration.bukkit.value.ConfiguredSound; import cc.carm.lib.mineconfiguration.bukkit.value.ConfiguredSound;
import cc.carm.lib.mineconfiguration.bukkit.value.item.ConfiguredItem;
import cc.carm.plugin.userprefix.conf.gui.GUIItems;
import cc.carm.plugin.userprefix.folia.MajorUtil;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemFlag;
import java.util.Collections; public class PluginConfig implements Configuration {
public class PluginConfig extends ConfigurationRoot { @HeaderComments({"开发者查错模式"})
public static final ConfiguredValue<Boolean> DEBUG = ConfiguredValue.of(Boolean.class, false);
@HeaderComment({"开发者查错模式"}) @HeaderComments({
public static final ConfigValue<Boolean> DEBUG = ConfiguredValue.of(Boolean.class, false);
@HeaderComment({
"统计数据设定", "统计数据设定",
" 该选项用于帮助开发者统计插件版本与使用情况,且绝不会影响性能与使用体验。", " 该选项用于帮助开发者统计插件版本与使用情况,且绝不会影响性能与使用体验。",
" 当然,您也可以选择在这里关闭,或在plugins/bStats下的配置文件中关闭。" " 当然,您也可以选择在这里关闭,或在plugins/bStats下的配置文件中关闭。"
}) })
public static final ConfigValue<Boolean> METRICS = ConfiguredValue.of(Boolean.class, true); public static final ConfiguredValue<Boolean> METRICS = ConfiguredValue.of(Boolean.class, true);
@HeaderComment({ @HeaderComments({
"检查更新设定", "检查更新设定",
"该选项用于插件判断是否要检查更新,若您不希望插件检查更新并提示您,可以选择关闭。", "该选项用于插件判断是否要检查更新,若您不希望插件检查更新并提示您,可以选择关闭。",
"检查更新为异步操作,绝不会影响性能与使用体验。" "检查更新为异步操作,绝不会影响性能与使用体验。"
}) })
public static final ConfigValue<Boolean> CHECK_UPDATE = ConfiguredValue.of(Boolean.class, true); public static final ConfiguredValue<Boolean> CHECK_UPDATE = ConfiguredValue.of(Boolean.class, true);
@HeaderComment({"自定义存储位置设定", "可以规定到远程文件夹中去加载前缀配置"}) @HeaderComments({"自定义存储位置设定", "可以规定到远程文件夹中去加载前缀配置"})
public static final class CUSTOM_STORAGE extends ConfigurationRoot { public static final class CUSTOM_STORAGE implements Configuration {
@HeaderComment({"是否启用自定义存储位置"}) @HeaderComments({"是否启用自定义存储位置"})
public static final ConfigValue<Boolean> ENABLE = ConfiguredValue.of(Boolean.class, false); public static final ConfiguredValue<Boolean> ENABLE = ConfiguredValue.of(Boolean.class, false);
@HeaderComment({ @HeaderComments({
"目标存储路径,必须指向一个文件夹。", "目标存储路径,必须指向一个文件夹。",
"默认存储位置为 “插件文件夹”/prefixes", "默认存储位置为 “插件文件夹”/prefixes",
"支持绝对文件路径,如 \"/etc/minecraft/configurations/prefixes/\"" "支持绝对文件路径,如 \"/etc/minecraft/configurations/prefixes/\""
}) })
public static final ConfigValue<String> PATH = ConfiguredValue.of(String.class, "prefixes/"); public static final ConfiguredValue<String> PATH = ConfiguredValue.of(String.class, "prefixes/");
} }
@HeaderComment("功能设定") @HeaderComments("功能设定")
public static class FUNCTIONS extends ConfigurationRoot { public static class FUNCTIONS implements Configuration {
@ConfigPath("on-name-prefix") @ConfigPath("on-name-prefix")
@HeaderComment({"头顶与TabList前缀功能,该方法用到了玩家名计分板接口,如有冲突请关掉哦~"}) @HeaderComments({"头顶与TabList前缀功能,该方法用到了玩家名计分板接口,如有冲突请关掉哦~"})
public static final class NAME_PREFIX extends ConfigurationRoot { public static final class NAME_PREFIX implements Configuration {
@HeaderComment("是否开启本功能") @HeaderComments("是否开启本功能")
public static final ConfigValue<Boolean> ENABLE = ConfiguredValue.of(Boolean.class, true); public static final ConfiguredValue<Boolean> ENABLE = ConfiguredValue.of(Boolean.class, true);
@HeaderComment("是否按降序排列,即权重越高的前缀显示在越上面;若为false则按升序排列。") @HeaderComments("是否按降序排列,即权重越高的前缀显示在越上面;若为false则按升序排列。")
public static final ConfigValue<Boolean> ORDER_DESC = ConfiguredValue.of(Boolean.class, true); public static final ConfiguredValue<Boolean> ORDER_DESC = ConfiguredValue.of(Boolean.class, true);
} }
@ConfigPath("auto-prefix-use") @ConfigPath("auto-prefix-use")
@HeaderComment("自动使用前缀,即当玩家没有自己选择一个前缀的时候,会自动使用所拥有的的前缀中权重最高的那一个") @HeaderComments("自动使用前缀,即当玩家没有自己选择一个前缀的时候,会自动使用所拥有的的前缀中权重最高的那一个")
public static final ConfigValue<Boolean> AUTO_USE = ConfiguredValue.of(Boolean.class, true); public static final ConfiguredValue<Boolean> AUTO_USE = ConfiguredValue.of(Boolean.class, true);
@HeaderComment({ @HeaderComments({
"聊天功能设定", "聊天功能设定",
"- 我不推荐使用本插件的聊天功能,而是建议使用其他的聊天插件。", "- 我不推荐使用本插件的聊天功能,而是建议使用其他的聊天插件。",
"- 本插件仅仅提供了**最基本**的格式变量支持,不包含其他任何功能。", "- 本插件仅仅提供了**最基本**的格式变量支持,不包含其他任何功能。",
"- 注意聊天格式需要遵守Bukkit原格式,即不得缺失 “%1$s” 和 “%2$s” 。", "- 注意聊天格式需要遵守Bukkit原格式,即不得缺失 “%1$s” 和 “%2$s” 。",
"- 本插件的聊天功能不影响其他插件对聊天事件的操作。" "- 本插件的聊天功能不影响其他插件对聊天事件的操作。"
}) })
public static final class CHAT extends ConfigurationRoot { public static final class CHAT implements Configuration {
@HeaderComment("是否开启本功能") @HeaderComments("是否开启本功能")
public static final ConfigValue<Boolean> ENABLE = ConfiguredValue.of(Boolean.class, false); public static final ConfiguredValue<Boolean> ENABLE = ConfiguredValue.of(Boolean.class, false);
@HeaderComment({ @HeaderComments({
"聊天的格式,注意 “%1$s” 和 “%2$s” 不可缺少。", "聊天的格式,注意 “%1$s” 和 “%2$s” 不可缺少。",
"- %1$s -> 玩家名", "- %2$s -> 聊天内容" "- %1$s -> 玩家名", "- %2$s -> 聊天内容"
}) })
public static final ConfigValue<String> FORMAT = ConfiguredValue.of(String.class, "<%1$s> %2$s"); public static final ConfiguredValue<String> FORMAT = ConfiguredValue.of(String.class, "<%1$s> %2$s");
} }
} }
@HeaderComment({"前缀GUI界面设定"}) @HeaderComments({"前缀GUI界面设定"})
public static class GUI extends ConfigurationRoot { public static class GUI implements Configuration {
@HeaderComment("GUI的标题") @HeaderComments("GUI的标题")
public static final ConfigValue<String> TITLE = ConfiguredValue.of(String.class, "&f&l我的前缀 &8| 列表"); public static final ConfiguredValue<String> TITLE = ConfiguredValue.of(String.class, "&f&l我的前缀 &8| 列表");
@HeaderComment("GUI中的按钮") @HeaderComments("GUI中的基本按钮物品")
public static final class ITEMS extends ConfigurationRoot { public static final class BOTTOMS implements Configuration {
@HeaderComment("前往下一页的物品 (只有存在下一页时才会显示)") @HeaderComments("前往下一页的物品 (只有存在下一页时才会显示)")
public static final ConfiguredItem NEXT_PAGE = ConfiguredItem.create() public static final ConfiguredItem NEXT_PAGE = ConfiguredItem.create()
.defaultType(Material.ARROW) .defaultType(Material.ARROW)
.defaultName("下一页") .defaultName("下一页")
@@ -110,34 +104,27 @@ public class PluginConfig extends ConfigurationRoot {
.build(); .build();
@ConfigPath("previous-page") @ConfigPath("previous-page")
@HeaderComment({"前往上一页时的物品 (只有当前页不是第一页时才会显示)"}) @HeaderComments({"前往上一页时的物品 (只有当前页不是第一页时才会显示)"})
public static final ConfiguredItem PREV_PAGE = ConfiguredItem.create() public static final ConfiguredItem PREV_PAGE = ConfiguredItem.create()
.defaultType(Material.ARROW) .defaultType(Material.ARROW)
.defaultName("上一页") .defaultName("上一页")
.defaultLore("&7&o右键可前往第一页哦") .defaultLore("&7&o右键可前往第一页哦")
.build(); .build();
@HeaderComment("GUI中其他的物品配置")
public static final ConfigValue<GUIItemConfiguration> BACK = ConfiguredValue.builder(GUIItemConfiguration.class)
.fromSection()
.serializeValue(GUIItemConfiguration::serialize)
.parseValue((v, d) -> {
if (!(v instanceof CraftSectionWrapper)) return null;
return GUIItemConfiguration.readFrom(((CraftSectionWrapper) v).getSource());
})
.defaults(new GUIItemConfiguration(
Material.BARRIER, 1, 0, "&c&l返回",
Collections.singletonList("&f点击即可返回上一菜单"),
Collections.singletonList(GUIActionConfiguration.of(GUIActionType.CHAT, "/menu")),
Collections.singletonList(49)
)).build();
} }
@HeaderComments("GUI中的其他按钮物品 (若与现有物品位置冲突,将被覆盖)")
public static final ConfiguredValue<GUIItems> ITEMS = ConfiguredValue
.builderOf(GUIItems.class).fromSection()
.defaults(GUIItems::defaults)
.serialize(GUIItems::serialize)
.parse(GUIItems::parse)
.build();
} }
@HeaderComment({"相关的声音,留空则不播放声音", "格式为 【声音名:音量:音调】 或 【声音名:音量】 或 【声音名】"}) @HeaderComments({"相关的声音,留空则不播放声音", "格式为 【声音名:音量:音调】 或 【声音名:音量】 或 【声音名】"})
public static final class SOUNDS extends ConfigurationRoot { public static final class SOUNDS implements Configuration {
public static final ConfiguredSound GUI_OPEN = ConfiguredSound.of("BLOCK_NOTE_BLOCK_PLING", 0.5F, 0.8F); public static final ConfiguredSound GUI_OPEN = ConfiguredSound.of("BLOCK_NOTE_BLOCK_PLING", 0.5F, 0.8F);
public static final ConfiguredSound GUI_CLICK = ConfiguredSound.of("UI_BUTTON_CLICK"); public static final ConfiguredSound GUI_CLICK = ConfiguredSound.of("UI_BUTTON_CLICK");
@@ -146,40 +133,45 @@ public class PluginConfig extends ConfigurationRoot {
} }
@HeaderComment({"默认前缀配置"}) @HeaderComments({"默认前缀配置"})
public static final class DEFAULT_PREFIX extends ConfigurationRoot { public static final class DEFAULT_PREFIX implements Configuration {
@HeaderComment("默认前缀的显示名称,用于在消息提示中显示。") @HeaderComments("默认前缀的显示名称,用于在消息提示中显示。")
public static final ConfigValue<String> NAME = ConfiguredValue.of(String.class, "默认前缀"); public static final ConfiguredValue<String> NAME = ConfiguredValue.of(String.class, "默认前缀");
@HeaderComment({"默认前缀的权重,默认为0"}) @HeaderComments({"默认前缀的描述信息"})
public static final ConfigValue<Integer> WEIGHT = ConfiguredValue.of(Integer.class, 0); public static final ConfiguredList<String> DESCRIPTION = ConfiguredList.builderOf(String.class).fromString()
.defaults("&7这是一个默认前缀", "&7您可以在前缀列表中选择其他前缀")
.build();
@HeaderComment({"默认前缀的内容,即用于显示的实际前缀"}) @HeaderComments({"默认前缀的权重,默认为0。"})
public static final ConfigValue<String> CONTENT = ConfiguredValue.of(String.class, "&r"); public static final ConfiguredValue<Integer> WEIGHT = ConfiguredValue.of(Integer.class, 0);
@HeaderComment({"选择默认前缀时执行的操作"}) @HeaderComments({"默认前缀的内容,即用于显示的实际前缀"})
public static final ConfiguredList<String> ACTIONS = ConfiguredList.builder(String.class).fromString() public static final ConfiguredValue<String> CONTENT = ConfiguredValue.of(String.class, "&r");
@HeaderComments({"选择默认前缀时执行的操作"})
public static final ConfiguredList<String> ACTIONS = ConfiguredList.builderOf(String.class).fromString()
.defaults("[CONSOLE] " + "say %player_name% 选择了默认前缀") .defaults("[CONSOLE] " + "say %player_name% 选择了默认前缀")
.build(); .build();
@HeaderComment({"默认前缀的显示物品"}) @HeaderComments({"默认前缀的显示物品"})
public static final class ITEM extends ConfigurationRoot { public static final class ITEM implements Configuration {
@HeaderComment({"当未选择默认前缀时显示的物品"}) @HeaderComments({"当未选择默认前缀时显示的物品"})
public static final ConfiguredItem NOT_USING = ConfiguredItem.create() public static final ConfiguredItem NOT_USING = ConfiguredItem.create()
.defaultType(Material.NAME_TAG) .defaultType(Material.NAME_TAG)
.defaultName("&f默认玩家前缀 &f(点击切换)") .defaultName("&f默认玩家前缀 &f(点击切换)")
.defaultLore("", "&a➥ 点击切换到该前缀") .defaultLore("","{&f&o }#description#{1,1}", "&a➥ 点击切换到该前缀")
.build(); .build();
@HeaderComment({"当选择了默认前缀时显示的物品"}) @HeaderComments({"当选择了默认前缀时显示的物品"})
public static final ConfiguredItem USING = ConfiguredItem.create() public static final ConfiguredItem USING = ConfiguredItem.create()
.defaultType(Material.NAME_TAG) .defaultType(Material.NAME_TAG)
.defaultEnchant(Enchantment.PROTECTION_ENVIRONMENTAL, 1) .defaultEnchant(MajorUtil.getEnchantProtection(), 1) // 附魔改过名
.defaultFlags(ItemFlag.HIDE_ENCHANTS) .defaultFlags(ItemFlag.HIDE_ENCHANTS)
.defaultName("&f默认玩家前缀") .defaultName("&f默认玩家前缀")
.defaultLore("", "&a✔ 您正在使用该前缀") .defaultLore("","{&f&o }#description#{1,1}", "&a✔ 您正在使用该前缀")
.build(); .build();
} }
@@ -1,18 +1,18 @@
package cc.carm.plugin.userprefix.conf; package cc.carm.plugin.userprefix.conf;
import cc.carm.lib.configuration.core.ConfigurationRoot; import cc.carm.lib.configuration.Configuration;
import cc.carm.lib.configuration.core.annotation.HeaderComment; import cc.carm.lib.configuration.annotation.HeaderComments;
import cc.carm.lib.mineconfiguration.bukkit.value.ConfiguredMessageList; import cc.carm.lib.mineconfiguration.bukkit.value.ConfiguredMessage;
public class PluginMessages extends ConfigurationRoot { public class PluginMessages implements Configuration {
public static final class COMMAND_USAGE extends ConfigurationRoot { public static final class COMMAND_USAGE implements Configuration {
public static ConfiguredMessageList<String> CONSOLE = ConfiguredMessageList.asStrings().defaults( public static final ConfiguredMessage<String> CONSOLE = ConfiguredMessage.asString().defaults(
"&f请输入 &b/prefix <玩家ID> &f为指定玩家打开前缀GUI。" "&f请输入 &b/prefix <玩家ID> &f为指定玩家打开前缀GUI。"
).build(); ).build();
public static ConfiguredMessageList<String> ADMIN = ConfiguredMessageList.asStrings().defaults( public static final ConfiguredMessage<String> ADMIN = ConfiguredMessage.asString().defaults(
"&3&l用户前缀系统 &f帮助", "&3&l用户前缀系统 &f帮助",
"&8# &f/upa list", "&8# &f/upa list",
"&8- &7查看当前前缀列表。", "&8- &7查看当前前缀列表。",
@@ -23,52 +23,52 @@ public class PluginMessages extends ConfigurationRoot {
"&8- &7重载前缀配置。" "&8- &7重载前缀配置。"
).build(); ).build();
public static ConfiguredMessageList<String> NO_PERM = ConfiguredMessageList.asStrings() public static final ConfiguredMessage<String> NO_PERM = ConfiguredMessage.asString()
.defaults("&c&l抱歉!&f但您没有权限使用该指令。") .defaults("&c&l抱歉!&f但您没有权限使用该指令。")
.build(); .build();
} }
public static ConfiguredMessageList<String> NOT_ONLINE = ConfiguredMessageList.asStrings() public static final ConfiguredMessage<String> NOT_ONLINE = ConfiguredMessage.asString()
.defaults("&7玩家 &b%(player) &7并不在线。") .defaults("&7玩家 &b%(player) &7并不在线。")
.params("player").build(); .params("player").build();
public static ConfiguredMessageList<String> SELECTED = ConfiguredMessageList.asStrings() public static final ConfiguredMessage<String> SELECTED = ConfiguredMessage.asString()
.defaults("&7您选择了 &f%(name) &7作为当前显示的前缀。") .defaults("&7您选择了 &f%(name) &7作为当前显示的前缀。")
.params("name").build(); .params("name").build();
public static ConfiguredMessageList<String> EXPIRED = ConfiguredMessageList.asStrings() public static final ConfiguredMessage<String> EXPIRED = ConfiguredMessage.asString()
.defaults( .defaults(
"&7您先前使用的前缀 &f%(oldName) &7已到期。", "&7您先前使用的前缀 &f%(oldName) &7已到期。",
"&7现在已为您重新调整为 &f%(newName) &7。" "&7现在已为您重新调整为 &f%(newName) &7。"
).params("oldName", "newName").build(); ).params("oldName", "newName").build();
public static ConfiguredMessageList<String> REMOVED = ConfiguredMessageList.asStrings() public static final ConfiguredMessage<String> REMOVED = ConfiguredMessage.asString()
.defaults("&7您先前使用的前缀已被移除,现在已为您重新调整为 &f%(newName) &7。") .defaults("&7您先前使用的前缀已被移除,现在已为您重新调整为 &f%(newName) &7。")
.params("newName").build(); .params("newName").build();
public static final class RELOAD extends ConfigurationRoot { public static final class RELOAD implements Configuration {
public static ConfiguredMessageList<String> SUCCESS = ConfiguredMessageList.asStrings() public static final ConfiguredMessage<String> SUCCESS = ConfiguredMessage.asString()
.defaults("&a&l重载完成!&7耗时 &f%(time)ms&7,共加载了 &b%(count) &7个前缀。") .defaults("&a&l重载完成!&7耗时 &f%(time)ms&7,共加载了 &b%(count) &7个前缀。")
.params("time", "count").build(); .params("time", "count").build();
public static ConfiguredMessageList<String> FAILED = ConfiguredMessageList.asStrings() public static final ConfiguredMessage<String> FAILED = ConfiguredMessage.asString()
.defaults("&c&l重载出错!&7错误提示为 &8“&r%(error)&8”。") .defaults("&c&l重载出错!&7错误提示为 &8“&r%(error)&8”。")
.params("error").build(); .params("error").build();
} }
public static final class SET extends ConfigurationRoot { public static final class SET implements Configuration {
public static ConfiguredMessageList<String> SUCCESS = ConfiguredMessageList.asStrings() public static final ConfiguredMessage<String> SUCCESS = ConfiguredMessage.asString()
.defaults("&a&l设置成功!&7成功设定玩家 &b%(player) &f的前缀为 &r%(prefix) &f。") .defaults("&a&l设置成功!&7成功设定玩家 &b%(player) &f的前缀为 &r%(prefix) &f。")
.params("player", "prefix").build(); .params("player", "prefix").build();
public static ConfiguredMessageList<String> PREFIX_NOT_FOUND = ConfiguredMessageList.asStrings() public static final ConfiguredMessage<String> PREFIX_NOT_FOUND = ConfiguredMessage.asString()
.defaults("&c&l无法设置!&7不存在ID为 &b%(prefix) &7的前缀。") .defaults("&c&l无法设置!&7不存在ID为 &b%(prefix) &7的前缀。")
.params("prefix").build(); .params("prefix").build();
public static ConfiguredMessageList<String> NO_PERM = ConfiguredMessageList.asStrings() public static final ConfiguredMessage<String> NO_PERM = ConfiguredMessage.asString()
.defaults("&c&l无法设置!&7玩家 &b%(player) &7并没有前缀 &r%(prefix) &7的前缀。") .defaults("&c&l无法设置!&7玩家 &b%(player) &7并没有前缀 &r%(prefix) &7的前缀。")
.params("player", "prefix") .params("player", "prefix")
.build(); .build();
@@ -76,13 +76,13 @@ public class PluginMessages extends ConfigurationRoot {
} }
@HeaderComment("管理员使用的 “/upa list” 指令的格式") @HeaderComments("管理员使用的 “/upa list” 指令的格式")
public static final class LIST extends ConfigurationRoot { public static final class LIST implements Configuration {
public static ConfiguredMessageList<String> HEADER = ConfiguredMessageList.asStrings() public static final ConfiguredMessage<String> HEADER = ConfiguredMessage.asString()
.defaults("&3&l用户前缀系统 &f前缀列表").build(); .defaults("&3&l用户前缀系统 &f前缀列表").build();
public static ConfiguredMessageList<String> VALUE = ConfiguredMessageList.asStrings().defaults( public static final ConfiguredMessage<String> VALUE = ConfiguredMessage.asString().defaults(
"&8#%(weight) &f%(identifier)", "&8#%(weight) &f%(identifier)",
"&8- &7显示名 &r%(name) &7权限 &r%(permission)", "&8- &7显示名 &r%(name) &7权限 &r%(permission)",
"&8- &7内容示例&r %(content) %(sender_name)" "&8- &7内容示例&r %(content) %(sender_name)"
@@ -0,0 +1,59 @@
package cc.carm.plugin.userprefix.conf.gui;
import cc.carm.lib.configuration.source.section.ConfigureSection;
import cc.carm.lib.easyplugin.gui.configuration.GUIActionConfiguration;
import cc.carm.lib.easyplugin.gui.configuration.GUIActionType;
import cc.carm.lib.easyplugin.gui.configuration.GUIConfiguration;
import cc.carm.lib.easyplugin.gui.configuration.GUIItemConfiguration;
import cc.carm.lib.mineconfiguration.bukkit.source.BukkitSection;
import cc.carm.plugin.userprefix.Main;
import org.bukkit.Material;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
public class GUIItems {
protected final Map<String, GUIItemConfiguration> items;
public GUIItems(Map<String, GUIItemConfiguration> items) {
this.items = items;
}
public Map<String, GUIItemConfiguration> getItems() {
return items;
}
public Map<String, Object> serialize() {
return items.entrySet().stream().collect(Collectors.toMap(
Map.Entry::getKey,
entry -> entry.getValue().serialize(), (a, b) -> b,
LinkedHashMap::new
));
}
public static GUIItems parse(ConfigureSection section) {
if (!(section instanceof BukkitSection)) {
Main.severe("Unknown configure source, it should never happened!");
Main.severe("Required: " + BukkitSection.class.getSimpleName());
Main.severe("Found: " + section.getClass().getSimpleName());
return new GUIItems(new LinkedHashMap<>());
}
BukkitSection craft = (BukkitSection) section;
return new GUIItems(GUIConfiguration.readItems(craft.data()));
}
public static GUIItems defaults() {
LinkedHashMap<String, GUIItemConfiguration> map = new LinkedHashMap<>();
map.put("back", new GUIItemConfiguration(
Material.BARRIER, 1, 0, "&c&l返回",
Collections.singletonList("&f点击即可返回上一菜单"),
Collections.singletonList(GUIActionConfiguration.of(GUIActionType.CHAT, "/menu")),
Collections.singletonList(49)
));
return new GUIItems(map);
}
}
@@ -1,14 +1,19 @@
package cc.carm.plugin.userprefix.conf.prefix; package cc.carm.plugin.userprefix.conf.prefix;
import cc.carm.lib.easyplugin.gui.configuration.GUIActionConfiguration; import cc.carm.lib.easyplugin.gui.configuration.GUIActionConfiguration;
import cc.carm.lib.easyplugin.utils.ColorParser; import cc.carm.lib.easyplugin.gui.configuration.GUIActionType;
import cc.carm.lib.mineconfiguration.bukkit.data.ItemConfig; import cc.carm.lib.easyplugin.utils.MessageUtils;
import cc.carm.lib.mineconfiguration.bukkit.value.item.PreparedItem;
import cc.carm.plugin.userprefix.Main;
import cc.carm.plugin.userprefix.manager.ServiceManager; import cc.carm.plugin.userprefix.manager.ServiceManager;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class PrefixConfig { public class PrefixConfig {
@@ -17,6 +22,7 @@ public class PrefixConfig {
protected final @NotNull String name; protected final @NotNull String name;
protected final @NotNull String content; protected final @NotNull String content;
protected final @NotNull List<String> description;
protected final int weight; protected final int weight;
@@ -24,18 +30,33 @@ public class PrefixConfig {
protected final @NotNull List<GUIActionConfiguration> actions; protected final @NotNull List<GUIActionConfiguration> actions;
protected final @NotNull ItemConfig itemHasPermission; protected final @NotNull ItemStack itemHasPermission;
protected final @Nullable ItemConfig itemNoPermission; protected final @Nullable ItemStack itemNoPermission;
protected final @Nullable ItemConfig itemWhenUsing; protected final @Nullable ItemStack itemWhenUsing;
public PrefixConfig(@NotNull String identifier, @NotNull String name, public PrefixConfig(@NotNull String identifier, @NotNull String name,
@NotNull String content, int weight, @Nullable String permission, @NotNull String content, int weight, @Nullable String permission,
@NotNull List<GUIActionConfiguration> actions, @NotNull List<GUIActionConfiguration> actions,
@NotNull ItemConfig itemHasPermission, @NotNull ItemStack itemHasPermission,
@Nullable ItemConfig itemWhenUsing, @Nullable ItemStack itemWhenUsing,
@Nullable ItemConfig itemNoPermission) { @Nullable ItemStack itemNoPermission) {
this(
identifier, name, new ArrayList<>(),
content, weight, permission, actions,
itemHasPermission, itemWhenUsing, itemNoPermission
);
}
public PrefixConfig(@NotNull String identifier,
@NotNull String name, @NotNull List<String> description,
@NotNull String content, int weight, @Nullable String permission,
@NotNull List<GUIActionConfiguration> actions,
@NotNull ItemStack itemHasPermission,
@Nullable ItemStack itemWhenUsing,
@Nullable ItemStack itemNoPermission) {
this.identifier = identifier; this.identifier = identifier;
this.name = name; this.name = name;
this.description = description;
this.content = content; this.content = content;
this.weight = weight; this.weight = weight;
this.permission = permission; this.permission = permission;
@@ -56,8 +77,13 @@ public class PrefixConfig {
} }
@NotNull @NotNull
public String getContent() { public List<String> getDescription() {
return ColorParser.parse(content); return description;
}
@NotNull
public String getContent(CommandSender viewer) {
return MessageUtils.setPlaceholders(viewer, content);
} }
public int getWeight() { public int getWeight() {
@@ -71,27 +97,53 @@ public class PrefixConfig {
@NotNull @NotNull
public ItemStack getItemHasPermission(@Nullable Player player) { public ItemStack getItemHasPermission(@Nullable Player player) {
return this.itemHasPermission.getItemStack(player); return getItem(player, this.itemHasPermission);
} }
@Nullable @Nullable
public ItemStack getItemNoPermission(@Nullable Player player) { public ItemStack getItemNoPermission(@Nullable Player player) {
if (this.itemNoPermission == null) return null; return getItem(player, this.itemNoPermission);
return this.itemNoPermission.getItemStack(player);
} }
@Nullable @Nullable
public ItemStack getItemWhenUsing(@Nullable Player player) { public ItemStack getItemWhenUsing(@Nullable Player player) {
if (this.itemWhenUsing == null) return null; return getItem(player, this.itemWhenUsing);
else return this.itemWhenUsing.getItemStack(player);
} }
@Contract("_,!null->!null")
protected @Nullable ItemStack getItem(@Nullable Player player, @Nullable ItemStack item) {
PreparedItem prepared = PreparedItem.of(item);
if (!getDescription().isEmpty()) {
prepared.insert("description", getDescription());
prepared.placeholder("description", String.join("\n", getDescription()));
}
prepared.placeholder("name", getName());
prepared.placeholder("identifier", getIdentifier());
prepared.placeholder("content", getContent(player));
prepared.placeholder("permission", getPermission());
prepared.placeholder("weight", String.valueOf(getWeight()));
prepared.placeholder("hasPermission", String.valueOf(checkPermission(player)));
prepared.placeholder("public", String.valueOf(isPublic()));
prepared.placeholder("visible", String.valueOf(isVisible(player)));
return prepared.get(player);
}
public boolean isPublic() { public boolean isPublic() {
return getPermission() == null; return getPermission() == null;
} }
public void executeActions(@NotNull Player player) { public void executeActions(@NotNull Player player) {
this.actions.forEach(action -> action.executeAction(player)); this.actions.forEach(action -> {
if (action.getActionType() == GUIActionType.CONSOLE) { // 控制台执行命令必须在全局调度器中执行
Main.getInstance().getFoliaScheduler().runGlobal(false, () -> action.executeAction(player));
} else {
action.executeAction(player);
}
});
} }
public boolean isVisible(Player player) { public boolean isVisible(Player player) {
@@ -2,6 +2,7 @@ package cc.carm.plugin.userprefix.event;
import cc.carm.plugin.userprefix.Main; import cc.carm.plugin.userprefix.Main;
import cc.carm.plugin.userprefix.conf.prefix.PrefixConfig; import cc.carm.plugin.userprefix.conf.prefix.PrefixConfig;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable; import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
@@ -61,8 +62,11 @@ public class UserPrefixChangeEvent extends UserPrefixEvent implements Cancellabl
@Nullable PrefixConfig before, @Nullable PrefixConfig before,
@NotNull PrefixConfig after, @NotNull PrefixConfig after,
@Nullable Consumer<@Nullable PrefixConfig> finish) { @Nullable Consumer<@Nullable PrefixConfig> finish) {
Main.getInstance().callSync(new UserPrefixChangeEvent(who, before, after)) UserPrefixChangeEvent event = new UserPrefixChangeEvent(who, before, after);
.thenAccept((e) -> Optional.ofNullable(finish).ifPresent(f -> f.accept(e.getAfter()))); Main.getInstance().getFoliaScheduler().runGlobal(true, () -> {
Bukkit.getPluginManager().callEvent(event);
Optional.ofNullable(finish).ifPresent(f -> f.accept(event.getAfter()));
});
} }
} }
@@ -2,6 +2,7 @@ package cc.carm.plugin.userprefix.event;
import cc.carm.plugin.userprefix.Main; import cc.carm.plugin.userprefix.Main;
import cc.carm.plugin.userprefix.conf.prefix.PrefixConfig; import cc.carm.plugin.userprefix.conf.prefix.PrefixConfig;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -30,7 +31,7 @@ public class UserPrefixExpireEvent extends UserPrefixEvent {
} }
public static void call(@NotNull Player player, @NotNull PrefixConfig currentPrefix) { public static void call(@NotNull Player player, @NotNull PrefixConfig currentPrefix) {
Main.getInstance().callSync(new UserPrefixExpireEvent(player, currentPrefix)); Main.getInstance().getFoliaScheduler().runGlobal(true, () -> Bukkit.getPluginManager().callEvent(new UserPrefixExpireEvent(player, currentPrefix)));
} }
} }
@@ -0,0 +1,121 @@
package cc.carm.plugin.userprefix.folia;
import cc.carm.plugin.userprefix.Main;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.plugin.Plugin;
import java.lang.reflect.InvocationTargetException;
import java.util.function.Consumer;
public class FoliaScheduler {
private final Main plugin;
private final boolean folia;
public FoliaScheduler(Main plugin, boolean folia) {
this.plugin = plugin;
this.folia = folia;
}
public void runAsync(Runnable task) {
if (this.folia) {
this.runAsyncFolia(task);
} else {
this.runAsyncBukkit(task);
}
}
private void runAsyncBukkit(Runnable task) {
Bukkit.getScheduler().runTaskAsynchronously(this.plugin, task);
}
private void runAsyncFolia(Runnable task) {
// AsyncScheduler asyncScheduler = Bukkit.getAsyncScheduler();
// asyncScheduler.runNow(this.plugin, t -> task.run());
try {
Object asyncScheduler = Bukkit.class.getMethod("getAsyncScheduler")
.invoke(null);
asyncScheduler.getClass().getMethod("runNow", Plugin.class, Consumer.class)
.invoke(asyncScheduler, this.plugin, (Consumer<?>) t -> task.run());
} catch (IllegalAccessException | NoSuchMethodException e) {
Main.severe("unexpected exception during reflection (#runAsyncFolia), it should never happen!");
e.printStackTrace();
} catch (InvocationTargetException e) {
throw (RuntimeException) e.getTargetException();
}
}
/**
* Folia 上在实体所在的调度器上执行任务,或在 Bukkit 上同步执行任务
*
* @param entity 实体
* @param forceSync 若为 trueBukkit 下强制同步运行;若为 false,Bukkit 下直接执行
* @param task 任务
* @see FoliaScheduler#runBukkit(boolean, Runnable)
* @see FoliaScheduler#runOnEntityFolia(Entity, Runnable)
*/
public void runOnEntity(Entity entity, boolean forceSync, Runnable task) {
if (this.folia) {
this.runOnEntityFolia(entity, task);
} else {
this.runBukkit(forceSync, task);
}
}
private void runOnEntityFolia(Entity entity, Runnable task) {
// EntityScheduler entityScheduler = entity.getScheduler();
// entityScheduler.run(this.plugin, t -> task.run(), null);
try {
Object entityScheduler = Entity.class.getMethod("getScheduler")
.invoke(entity);
entityScheduler.getClass().getMethod("run", Plugin.class, Consumer.class, Runnable.class)
.invoke(entityScheduler, this.plugin, (Consumer<?>) t -> task.run(), null);
} catch (IllegalAccessException | NoSuchMethodException e) {
Main.severe("unexpected exception during reflection (#runOnEntityFolia), it should never happen!");
e.printStackTrace();
} catch (InvocationTargetException e) {
throw (RuntimeException) e.getTargetException();
}
}
/**
* Folia 上在全局调度器上执行任务,或在 Bukkit 上同步执行任务
*
* @param forceSync 若为 trueBukkit 下强制同步运行;若为 false,Bukkit 下直接执行
* @param task 任务
* @see FoliaScheduler#runBukkit(boolean, Runnable)
* @see FoliaScheduler#runGlobalFolia(Runnable)
*/
public void runGlobal(boolean forceSync, Runnable task) {
if (this.folia) {
this.runGlobalFolia(task);
} else {
this.runBukkit(forceSync, task);
}
}
private void runGlobalFolia(Runnable task) {
// GlobalRegionScheduler globalRegionScheduler = Bukkit.getGlobalRegionScheduler();
// globalRegionScheduler.execute(this.plugin, task);
try {
Object globalRegionScheduler = Bukkit.class.getMethod("getGlobalRegionScheduler")
.invoke(null);
globalRegionScheduler.getClass().getMethod("execute", Plugin.class, Runnable.class)
.invoke(globalRegionScheduler, this.plugin, task);
} catch (IllegalAccessException | NoSuchMethodException e) {
Main.severe("unexpected exception during reflection (#runGlobalFolia), it should never happen!");
e.printStackTrace();
} catch (InvocationTargetException e) {
throw (RuntimeException) e.getTargetException();
}
}
private void runBukkit(boolean forceSync, Runnable task) {
if (forceSync) {
Bukkit.getScheduler().runTask(this.plugin, task);
} else {
task.run();
}
}
}
@@ -0,0 +1,23 @@
package cc.carm.plugin.userprefix.folia;
import cc.carm.plugin.userprefix.Main;
import org.bukkit.enchantments.Enchantment;
public interface MajorUtil {
static Enchantment getEnchantProtection() {
Class<Enchantment> enchantmentClass = Enchantment.class;
try {
return (Enchantment) enchantmentClass.getField("PROTECTION_ENVIRONMENTAL").get(null);
} catch (NoSuchFieldException e1) {
try {
return (Enchantment) enchantmentClass.getField("PROTECTION").get(null);
} catch (NoSuchFieldException | IllegalAccessException e2) {
Main.severe("unexpected exception during reflection (#getEnchantProtection), it should never happen!");
throw new RuntimeException(e2);
}
} catch (IllegalAccessException e) {
Main.severe("unexpected exception during reflection (#getEnchantProtection), it should never happen!");
throw new RuntimeException(e);
}
}
}
@@ -1,92 +1,82 @@
package cc.carm.plugin.userprefix.hooker; package cc.carm.plugin.userprefix.hooker;
import cc.carm.plugin.userprefix.Main; import cc.carm.lib.easyplugin.papi.EasyPlaceholder;
import cc.carm.lib.easyplugin.papi.expansion.SubExpansion;
import cc.carm.lib.easyplugin.papi.handler.PlaceholderHandler;
import cc.carm.plugin.userprefix.UserPrefixAPI; import cc.carm.plugin.userprefix.UserPrefixAPI;
import cc.carm.plugin.userprefix.conf.prefix.PrefixConfig; import cc.carm.plugin.userprefix.conf.prefix.PrefixConfig;
import me.clip.placeholderapi.expansion.PlaceholderExpansion; import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays; import java.util.Collections;
import java.util.List; import java.util.function.BiFunction;
import java.util.function.Function;
public class UserPrefixExpansion extends PlaceholderExpansion { public class UserPrefixExpansion extends EasyPlaceholder {
protected final @NotNull Main plugin; public UserPrefixExpansion(@NotNull JavaPlugin plugin, @NotNull String rootIdentifier) {
protected final @NotNull List<String> placeholders = Arrays.asList( super(plugin, rootIdentifier);
"%UserPrefix_prefix%", "%UserPrefix_amount%", "%UserPrefix_weight%",
"%UserPrefix_identifier%", "%UserPrefix_name%", handle("version", (player, args) -> getVersion());
"%UserPrefix_has_<Identifier>%"
); handle("identifier", handlePrefix(PrefixConfig::getIdentifier), "id");
handle("prefix", handlePrefix(PrefixConfig::getContent));
handle("name", handlePrefix(PrefixConfig::getName));
handle("description", handlePrefix(p -> String.join("\n", p.getDescription())));
handle("weight", handlePrefix(PrefixConfig::getWeight));
handle("amount", handlePlayer(
(player) -> UserPrefixAPI.getUserManager().getUsablePrefixes(player).size() + 1)
);
handle("has", handlePlayer((player, args) -> {
if (args.length < 1) return "参数不足";
PrefixConfig prefix = UserPrefixAPI.getPrefixManager().getPrefix(args[0]);
if (prefix == null) return "该前缀不存在";
return prefix.checkPermission(player);
}), Collections.singletonList("<前缀ID>"));
public UserPrefixExpansion(@NotNull Main plugin) {
this.plugin = plugin;
} }
@Override public PlaceholderHandler handlePrefix(Function<PrefixConfig, Object> handler) {
public @NotNull List<String> getPlaceholders() { return handlePlayer((player, args) -> handler.apply(UserPrefixAPI.getUserManager().getPrefix(player)));
return this.placeholders;
} }
public PlaceholderHandler handlePrefix(BiFunction<PrefixConfig, Player, Object> handler) {
return handlePlayer((player, args) -> handler.apply(UserPrefixAPI.getUserManager().getPrefix(player), player));
}
/**
* This is required or else PlaceholderAPI will unregister the Expansion on reload
*/
@Override @Override
public boolean canRegister() { public boolean persist() {
return true; return true;
} }
@Override public PlaceholderHandler handlePlayer(BiFunction<Player, String[], Object> handler) {
public @NotNull String getAuthor() { return (player, args) -> {
return plugin.getDescription().getAuthors().toString(); if (player == null || !player.isOnline()) return "Loading...";
return handler.apply((Player) player, args);
};
}
public PlaceholderHandler handlePlayer(Function<Player, Object> handler) {
return handlePlayer((player, args) -> handler.apply(player));
} }
@Override @Override
public @NotNull String getIdentifier() { public String onErrorParams(@Nullable OfflinePlayer player) {
return "UserPrefix"; return "参数不足";
} }
@Override @Override
public @NotNull String getVersion() { public String onException(@Nullable OfflinePlayer player, @NotNull SubExpansion<?> expansion,
return plugin.getDescription().getVersion(); @NotNull Exception exception) {
} exception.printStackTrace();
return "参数错误";
@Override
public String onPlaceholderRequest(Player player, @NotNull String identifier) {
if (player == null) return "加载中...";
String[] args = identifier.split("_");
if (args.length < 1) {
return "参数不足";
}
switch (args[0].toLowerCase()) {
case "identifier": {
return UserPrefixAPI.getUserManager().getPrefix(player).getIdentifier();
}
case "prefix": {
return UserPrefixAPI.getUserManager().getPrefix(player).getContent();
}
case "amount": {
return String.valueOf(UserPrefixAPI.getUserManager().getUsablePrefixes(player).size() + 1);
}
case "name": {
return UserPrefixAPI.getUserManager().getPrefix(player).getName();
}
case "weight": {
return Integer.toString(UserPrefixAPI.getUserManager().getPrefix(player).getWeight());
}
case "has": {
if (args.length < 2) return "参数不足";
PrefixConfig prefix = UserPrefixAPI.getPrefixManager().getPrefix(args[1]);
if (prefix == null) return "该前缀不存在";
return Boolean.toString(prefix.checkPermission(player));
}
case "version": {
return getVersion();
}
default: {
return "参数错误";
}
}
} }
} }
@@ -14,7 +14,7 @@ public class UserPermListener {
if (player == null) return; if (player == null) return;
UserPrefixAPI.getUserManager().checkPrefix(player, true); UserPrefixAPI.getUserManager().checkPrefix(player, true);
if (PrefixSelectGUI.openingUsers.contains(player)) { if (PrefixSelectGUI.openingUsers.contains(player)) {
Main.getInstance().getScheduler().run(() -> { Main.getInstance().getFoliaScheduler().runOnEntity(player, true, () -> {
// 玩家权限更新,同步关闭其GUI,以令其重新打开刷新自己的前缀。 // 玩家权限更新,同步关闭其GUI,以令其重新打开刷新自己的前缀。
player.closeInventory(); player.closeInventory();
PrefixSelectGUI.removeOpening(player); PrefixSelectGUI.removeOpening(player);
@@ -1,6 +1,6 @@
package cc.carm.plugin.userprefix.manager; package cc.carm.plugin.userprefix.manager;
import cc.carm.lib.configuration.core.source.ConfigurationProvider; import cc.carm.lib.configuration.source.ConfigurationHolder;
import cc.carm.lib.easyplugin.utils.JarResourceUtils; import cc.carm.lib.easyplugin.utils.JarResourceUtils;
import cc.carm.lib.mineconfiguration.bukkit.MineConfiguration; import cc.carm.lib.mineconfiguration.bukkit.MineConfiguration;
import cc.carm.plugin.userprefix.conf.PluginConfig; import cc.carm.plugin.userprefix.conf.PluginConfig;
@@ -11,13 +11,13 @@ import java.io.IOException;
public class ConfigManager { public class ConfigManager {
private final ConfigurationProvider<?> configProvider; private final ConfigurationHolder<?> configProvider;
private final ConfigurationProvider<?> messageProvider; private final ConfigurationHolder<?> messageProvider;
public ConfigManager(File dataFolder) { public ConfigManager(File dataFolder) {
firstInitialize(dataFolder); firstInitialize(dataFolder);
this.configProvider = MineConfiguration.from(new File(dataFolder, "config.yml")); this.configProvider = MineConfiguration.from(new File(dataFolder, "config.yml"), null);
this.messageProvider = MineConfiguration.from(new File(dataFolder, "messages.yml")); this.messageProvider = MineConfiguration.from(new File(dataFolder, "messages.yml"), null);
this.configProvider.initialize(PluginConfig.class); this.configProvider.initialize(PluginConfig.class);
this.messageProvider.initialize(PluginMessages.class); this.messageProvider.initialize(PluginMessages.class);
} }
@@ -26,7 +26,7 @@ public class ConfigManager {
File configFile = new File(dataFolder, "config.yml"); File configFile = new File(dataFolder, "config.yml");
if (!configFile.exists()) { if (!configFile.exists()) {
try { try {
JarResourceUtils.copyFolderFromJar("en_US", dataFolder, JarResourceUtils.CopyOption.COPY_IF_NOT_EXIST); JarResourceUtils.copyFolderFromJar("i18n", dataFolder, JarResourceUtils.CopyOption.COPY_IF_NOT_EXIST);
JarResourceUtils.copyFolderFromJar("prefixes", dataFolder, JarResourceUtils.CopyOption.COPY_IF_NOT_EXIST); JarResourceUtils.copyFolderFromJar("prefixes", dataFolder, JarResourceUtils.CopyOption.COPY_IF_NOT_EXIST);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
@@ -35,11 +35,11 @@ public class ConfigManager {
} }
public ConfigurationProvider<?> getConfigProvider() { public ConfigurationHolder<?> getConfigProvider() {
return configProvider; return configProvider;
} }
public ConfigurationProvider<?> getMessageProvider() { public ConfigurationHolder<?> getMessageProvider() {
return messageProvider; return messageProvider;
} }
@@ -1,15 +1,17 @@
package cc.carm.plugin.userprefix.manager; package cc.carm.plugin.userprefix.manager;
import cc.carm.lib.easyplugin.gui.configuration.GUIActionConfiguration; import cc.carm.lib.easyplugin.gui.configuration.GUIActionConfiguration;
import cc.carm.lib.mineconfiguration.bukkit.data.ItemConfig; import cc.carm.lib.easyplugin.utils.ItemStackFactory;
import cc.carm.plugin.userprefix.Main; import cc.carm.plugin.userprefix.Main;
import cc.carm.plugin.userprefix.conf.PluginConfig; import cc.carm.plugin.userprefix.conf.PluginConfig;
import cc.carm.plugin.userprefix.conf.prefix.PrefixConfig; import cc.carm.plugin.userprefix.conf.prefix.PrefixConfig;
import com.cryptomorin.xseries.XItemStack;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -75,13 +77,13 @@ public class PrefixManager {
this.defaultPrefix = new PrefixConfig( this.defaultPrefix = new PrefixConfig(
"default", "default",
PluginConfig.DEFAULT_PREFIX.NAME.getNotNull(), PluginConfig.DEFAULT_PREFIX.NAME.getNotNull(),
PluginConfig.DEFAULT_PREFIX.DESCRIPTION.getNotNull(),
PluginConfig.DEFAULT_PREFIX.CONTENT.getNotNull(), PluginConfig.DEFAULT_PREFIX.CONTENT.getNotNull(),
PluginConfig.DEFAULT_PREFIX.WEIGHT.getNotNull(), PluginConfig.DEFAULT_PREFIX.WEIGHT.getNotNull(),
null, null,
readActions(PluginConfig.DEFAULT_PREFIX.ACTIONS.get()), readActions(PluginConfig.DEFAULT_PREFIX.ACTIONS.get()),
PluginConfig.DEFAULT_PREFIX.ITEM.NOT_USING.getNotNull(), PluginConfig.DEFAULT_PREFIX.ITEM.NOT_USING.getNotNull(),
PluginConfig.DEFAULT_PREFIX.ITEM.USING.get(), PluginConfig.DEFAULT_PREFIX.ITEM.USING.get(), null
null
); );
Main.debugging(" 完成默认前缀加载 " + defaultPrefix.getName()); Main.debugging(" 完成默认前缀加载 " + defaultPrefix.getName());
} }
@@ -124,34 +126,39 @@ public class PrefixManager {
} }
public static @NotNull PrefixConfig addPrefix(@NotNull File file) throws Exception { public static @NotNull PrefixConfig addPrefix(@NotNull File file) throws Exception {
FileConfiguration configuration = YamlConfiguration.loadConfiguration(file); FileConfiguration conf = YamlConfiguration.loadConfiguration(file);
String identifier = configuration.getString("identifier"); String identifier = conf.getString("identifier");
if (identifier == null) if (identifier == null)
throw new Exception("配置文件 " + file.getAbsolutePath() + " 中没有配置前缀的唯一标识。"); throw new Exception("配置文件 " + file.getAbsolutePath() + " 中没有配置前缀的唯一标识。");
String name = configuration.getString("name"); String name = conf.getString("name");
if (name == null) throw new Exception("配置文件 " + file.getAbsolutePath() + " 中没有配置前缀的显示名称。"); if (name == null) throw new Exception("配置文件 " + file.getAbsolutePath() + " 中没有配置前缀的显示名称。");
return new PrefixConfig( return new PrefixConfig(
identifier, name, identifier, name,
configuration.getString("content", "&r"), conf.getStringList("description"),
configuration.getInt("weight", 1), conf.getString("content", "&r"),
configuration.getString("permission"), conf.getInt("weight", 1),
readActions(configuration.getStringList("actions")), conf.getString("permission"),
readActions(conf.getStringList("actions")),
readItem( readItem(
configuration.getConfigurationSection("item.has-perm"), conf.getConfigurationSection("item.has-perm"),
new ItemConfig(Material.STONE, name, Arrays.asList(" ", "§a➥ 点击切换到该前缀")) new ItemStackFactory(Material.STONE)
.setDisplayName(name)
.addLore("§a➥ 点击切换到该前缀")
.toItemStack()
), ),
readItem(configuration.getConfigurationSection("item.using"), null), readItem(conf.getConfigurationSection("item.using"), null),
readItem(configuration.getConfigurationSection("item.no-perm"), null) readItem(conf.getConfigurationSection("item.no-perm"), null)
); );
} }
@Contract("_,!null->!null") @Contract("_,!null->!null")
protected static ItemConfig readItem(@Nullable ConfigurationSection section, @Nullable ItemConfig defaultValue) throws Exception { protected static ItemStack readItem(@Nullable ConfigurationSection section,
@Nullable ItemStack defaultValue) throws Exception {
if (section == null) return defaultValue; if (section == null) return defaultValue;
else return ItemConfig.deserialize(section); else return XItemStack.deserialize(section);
} }
protected static List<GUIActionConfiguration> readActions(@NotNull List<String> strings) { protected static List<GUIActionConfiguration> readActions(@NotNull List<String> strings) {
@@ -32,7 +32,7 @@ public class UserManager {
@Nullable @Nullable
public UserNameTag getNameTag(Player player) { public UserNameTag getNameTag(Player player) {
if (PluginConfig.FUNCTIONS.NAME_PREFIX.ENABLE.getNotNull()) { if (this.isNamePrefixEnabled()) {
if (nameTags.containsKey(player.getUniqueId())) { if (nameTags.containsKey(player.getUniqueId())) {
return nameTags.get(player.getUniqueId()); return nameTags.get(player.getUniqueId());
} else { } else {
@@ -53,7 +53,7 @@ public class UserManager {
public void initPlayer(Player player) { public void initPlayer(Player player) {
checkPrefix(player, false); checkPrefix(player, false);
if (PluginConfig.FUNCTIONS.NAME_PREFIX.ENABLE.getNotNull()) { if (this.isNamePrefixEnabled()) {
createNameTag(player); createNameTag(player);
updatePrefixView(player, true); updatePrefixView(player, true);
} }
@@ -73,14 +73,14 @@ public class UserManager {
* @param loadOthers 是否为玩家更新其他人的前缀(一般用于加入游戏) * @param loadOthers 是否为玩家更新其他人的前缀(一般用于加入游戏)
*/ */
public void updatePrefixView(Player player, boolean loadOthers) { public void updatePrefixView(Player player, boolean loadOthers) {
if (!PluginConfig.FUNCTIONS.NAME_PREFIX.ENABLE.getNotNull()) return; //未启用的情况下,不需要进行任何操作。 if (!this.isNamePrefixEnabled()) return; //未启用的情况下,不需要进行任何操作。
UserNameTag tag = getNameTag(player); UserNameTag tag = getNameTag(player);
if (tag == null) return; //未启用的情况下,不需要进行任何操作。 if (tag == null) return; //未启用的情况下,不需要进行任何操作。
PrefixConfig playerPrefix = getPrefix(player); PrefixConfig playerPrefix = getPrefix(player);
boolean descOrder = PluginConfig.FUNCTIONS.NAME_PREFIX.ORDER_DESC.getNotNull(); boolean descOrder = PluginConfig.FUNCTIONS.NAME_PREFIX.ORDER_DESC.getNotNull();
tag.setPrefix(playerPrefix.getContent()); tag.setPrefix(playerPrefix.getContent(player));
tag.setOrder(descOrder ? 999 - playerPrefix.getWeight() : playerPrefix.getWeight()); tag.setOrder(descOrder ? 999 - playerPrefix.getWeight() : playerPrefix.getWeight());
Main.debugging("为玩家 " + player.getName() + " 设置了 " + player.getName() + "的前缀为 #" + playerPrefix.getWeight() + " " + playerPrefix.getName()); Main.debugging("为玩家 " + player.getName() + " 设置了 " + player.getName() + "的前缀为 #" + playerPrefix.getWeight() + " " + playerPrefix.getName());
@@ -90,7 +90,7 @@ public class UserManager {
UserNameTag onlinePlayerTag = getNameTag(onlinePlayer); UserNameTag onlinePlayerTag = getNameTag(onlinePlayer);
if (onlinePlayerTag != null) { if (onlinePlayerTag != null) {
onlinePlayerTag.setPrefix(player, playerPrefix.getContent()); onlinePlayerTag.setPrefix(player, playerPrefix.getContent(onlinePlayer));
onlinePlayerTag.setOrder(player, descOrder ? 999 - playerPrefix.getWeight() : playerPrefix.getWeight()); onlinePlayerTag.setOrder(player, descOrder ? 999 - playerPrefix.getWeight() : playerPrefix.getWeight());
Main.debugging("为玩家 " + onlinePlayer.getName() + " 设置了 " + player.getName() + "的前缀为 #" + playerPrefix.getWeight() + " " + playerPrefix.getName()); Main.debugging("为玩家 " + onlinePlayer.getName() + " 设置了 " + player.getName() + "的前缀为 #" + playerPrefix.getWeight() + " " + playerPrefix.getName());
@@ -98,7 +98,7 @@ public class UserManager {
if (loadOthers) { if (loadOthers) {
PrefixConfig onlinePlayerPrefix = getPrefix(onlinePlayer); PrefixConfig onlinePlayerPrefix = getPrefix(onlinePlayer);
tag.setPrefix(onlinePlayer, onlinePlayerPrefix.getContent()); tag.setPrefix(onlinePlayer, onlinePlayerPrefix.getContent(player));
tag.setOrder(onlinePlayer, descOrder ? 999 - onlinePlayerPrefix.getWeight() : onlinePlayerPrefix.getWeight()); tag.setOrder(onlinePlayer, descOrder ? 999 - onlinePlayerPrefix.getWeight() : onlinePlayerPrefix.getWeight());
Main.debugging("为玩家 " + player.getName() + " 设置了 " + onlinePlayer.getName() + "的前缀为 #" + onlinePlayerPrefix.getWeight() + " " + onlinePlayerPrefix.getName()); Main.debugging("为玩家 " + player.getName() + " 设置了 " + onlinePlayer.getName() + "的前缀为 #" + onlinePlayerPrefix.getWeight() + " " + onlinePlayerPrefix.getName());
} }
@@ -131,13 +131,13 @@ public class UserManager {
UserPrefixExpireEvent.call(player, currentPrefix); UserPrefixExpireEvent.call(player, currentPrefix);
// 发送消息 // 发送消息
PluginMessages.EXPIRED.send(player, newPrefix.getName(), currentPrefix.getName()); PluginMessages.EXPIRED.sendTo(player, currentPrefix.getName(), newPrefix.getName());
// 播放声音 // 播放声音
PluginConfig.SOUNDS.PREFIX_EXPIRED.playTo(player); PluginConfig.SOUNDS.PREFIX_EXPIRED.playTo(player);
} else { } else {
// 当前前缀为空,则代表是旧的前缀不存在了, // 当前前缀为空,则代表是旧的前缀不存在了,
PluginMessages.REMOVED.send(player, newPrefix.getName(), currentPrefixData); PluginMessages.REMOVED.sendTo(player, newPrefix.getName());
} }
UserPrefixChangeEvent.call(player, currentPrefix, newPrefix, (after) -> { UserPrefixChangeEvent.call(player, currentPrefix, newPrefix, (after) -> {
@@ -209,7 +209,7 @@ public class UserManager {
*/ */
@NotNull @NotNull
public PrefixConfig getHighestPrefix(Player player) { public PrefixConfig getHighestPrefix(Player player) {
if (PluginConfig.FUNCTIONS.AUTO_USE.getNotNull()) { if (!PluginConfig.FUNCTIONS.AUTO_USE.getNotNull()) {
// 关闭了自动选择,就直接给默认的前缀,让玩家自己去设置吧~ // 关闭了自动选择,就直接给默认的前缀,让玩家自己去设置吧~
return UserPrefixAPI.getDefaultPrefix(); return UserPrefixAPI.getDefaultPrefix();
} }
@@ -273,4 +273,7 @@ public class UserManager {
user.data().clear(NodeType.META.predicate(mn -> mn.getMetaKey().equals(META_KEY))); user.data().clear(NodeType.META.predicate(mn -> mn.getMetaKey().equals(META_KEY)));
} }
private boolean isNamePrefixEnabled() {
return PluginConfig.FUNCTIONS.NAME_PREFIX.ENABLE.getNotNull() && !Main.getInstance().isOnFolia();
}
} }
@@ -14,12 +14,13 @@ import org.bukkit.event.inventory.ClickType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Optional;
public class PrefixSelectGUI extends AutoPagedGUI { public class PrefixSelectGUI extends AutoPagedGUI {
public static HashSet<Player> openingUsers = new HashSet<>(); public static HashSet<Player> openingUsers = new HashSet<>();
Player player; protected final Player player;
public PrefixSelectGUI(Player player) { public PrefixSelectGUI(Player player) {
super(GUIType.SIX_BY_NINE, PluginConfig.GUI.TITLE.get(), 10, 43); super(GUIType.SIX_BY_NINE, PluginConfig.GUI.TITLE.get(), 10, 43);
@@ -28,7 +29,7 @@ public class PrefixSelectGUI extends AutoPagedGUI {
setPreviousPageSlot(18); setPreviousPageSlot(18);
setNextPageSlot(26); setNextPageSlot(26);
loadBackButton(); loadExtraIcons();
loadItems(); loadItems();
} }
@@ -36,8 +37,8 @@ public class PrefixSelectGUI extends AutoPagedGUI {
return player; return player;
} }
public void loadBackButton() { public void loadExtraIcons() {
PluginConfig.GUI.ITEMS.BACK.getOptional().ifPresent(item -> item.setupItems(player, this)); PluginConfig.GUI.ITEMS.getNotNull().getItems().values().forEach(v -> v.setupItems(player, this));
} }
public void loadItems() { public void loadItems() {
@@ -49,7 +50,10 @@ public class PrefixSelectGUI extends AutoPagedGUI {
for (PrefixConfig prefix : prefixList) { for (PrefixConfig prefix : prefixList) {
if (prefix.getIdentifier().equals(usingPrefix.getIdentifier())) { if (prefix.getIdentifier().equals(usingPrefix.getIdentifier())) {
addItem(new GUIItem(prefix.getItemWhenUsing(player) != null ? prefix.getItemWhenUsing(player) : prefix.getItemHasPermission(player))); addItem(new GUIItem(Optional
.ofNullable(prefix.getItemWhenUsing(player))
.orElse(prefix.getItemHasPermission(player))
));
} else if (prefix.checkPermission(player)) { } else if (prefix.checkPermission(player)) {
addItem(new GUIItem(prefix.getItemHasPermission(player)) { addItem(new GUIItem(prefix.getItemHasPermission(player)) {
@@ -61,7 +65,7 @@ public class PrefixSelectGUI extends AutoPagedGUI {
// 发送消息与提示 // 发送消息与提示
PluginConfig.SOUNDS.PREFIX_CHANGE.playTo(player); PluginConfig.SOUNDS.PREFIX_CHANGE.playTo(player);
PluginMessages.SELECTED.send(player, prefix.getName()); PluginMessages.SELECTED.sendTo(player, prefix.getName());
UserPrefixChangeEvent.call(player, usingPrefix, prefix, config -> { UserPrefixChangeEvent.call(player, usingPrefix, prefix, config -> {
if (config == null) return; if (config == null) return;
@@ -103,7 +107,7 @@ public class PrefixSelectGUI extends AutoPagedGUI {
} }
public static void open(Player player) { public static void open(Player player) {
player.closeInventory(); // 防止冲突 // player.closeInventory(); // 防止冲突
PluginConfig.SOUNDS.GUI_OPEN.playTo(player); PluginConfig.SOUNDS.GUI_OPEN.playTo(player);
new PrefixSelectGUI(player).openGUI(player); new PrefixSelectGUI(player).openGUI(player);
openingUsers.add(player); openingUsers.add(player);
@@ -27,11 +27,13 @@ permission: "yc.vip"
actions: actions:
- "[CONSOLE] say %player_name% selected PRO " - "[CONSOLE] say %player_name% selected PRO "
# Display item configuration
# More details please see https://github.com/CryptoMorin/XSeries/wiki/XItemStack
item: item:
# itemHasPermission [Necessary] # itemHasPermission [Necessary]
# This Item will be displayed when player has permission # This Item will be displayed when player has permission
has-perm: has-perm:
type: DIAMOND material: DIAMOND
name: "&b&lVIP Prefix" name: "&b&lVIP Prefix"
lore: lore:
- "" - ""
@@ -41,7 +43,7 @@ item:
# This Item will be displayed when the prefix is selected. # This Item will be displayed when the prefix is selected.
# If there is no such configuration, it will automatically display "itemHasPermission". # If there is no such configuration, it will automatically display "itemHasPermission".
using: using:
type: DIAMOND material: DIAMOND
name: "&b&lVIP Prefix" name: "&b&lVIP Prefix"
enchants: enchants:
PROTECTION_ENVIRONMENTAL: 1 #Add an enchantment so it looks like its selected PROTECTION_ENVIRONMENTAL: 1 #Add an enchantment so it looks like its selected
@@ -53,7 +55,7 @@ item:
# If player doesn't have the permission,this item will be displayed. # If player doesn't have the permission,this item will be displayed.
# If this item is not configured, it will not be displayed in the GUI when the player does not have permission to use it. # If this item is not configured, it will not be displayed in the GUI when the player does not have permission to use it.
no-perm: no-perm:
type: INK_SACK material: INK_SACK
data: 8 data: 8
name: "&b&lVIP &c(Buy it!)" name: "&b&lVIP &c(Buy it!)"
lore: lore:
@@ -0,0 +1,58 @@
# Nombre [Necesario]
# Uso en mensajes.
name: "&b&lPro&b"
# Contenido [Necesario]
# Uso en Placeholders
content: "&b&lPro &b"
# Weight [Necesario]
# utilizado para ordenar en la GUI y TabList
# En GUI : el más grande se muestra en la parte posterior
# En TabList : el más grande se muestra en la parte superior
weight: 1
# Permisos [Innecesario]
# Si no hay permiso para la detección, todo el mundo puede utilizarlo,
# lo que significa que no es necesario configurar "itemNoPermission"
# (porque es imposible mostrar elementos sin permiso en absoluto)
permission: "yc.vip"
# Acciones al seleccionar [Innecesario]
# Por favor, compruebe https://github.com/CarmJos/UserPrefix/tree/master/.documentation/ACTIONS.md
actions:
- "[CONSOLE] say %player_name% Has seleccionado La etiqueta PRO"
item:
# itemHasPermission [Necesario]
# Este elemento se mostrará cuando el jugador tenga permiso
has-perm:
material: DIAMOND
name: "&b&lVIP Prefix"
lore:
- ""
- "&a➥ Pulsa para utilizar"
# itemUsing [Innecesario]
# Este elemento se mostrará cuando se seleccione el prefijo.
# Si no existe tal configuración, se mostrará automáticamente "itemHasPermission".
using:
material: DIAMOND
name: "&b&lPrefix VIP"
enchants:
PROTECTION_ENVIRONMENTAL: 1 #Añade un encantamiento para que parezca que está seleccionado
lore:
- ""
- "&a✔ Seleccionado"
# itemNoPermission [Innecesario]
# Si el jugador no tiene el permiso,este item sera mostrado.
# Si este elemento no está configurado, no se mostrará en la GUI cuando el jugador no tenga permiso para usarlo.
no-perm:
material: INK_SACK
data: 8
name: "&b&lVIP &c(¡Cómpralo!)"
lore:
- ""
- "&e✯ Necesitas Comprar el VIP para utilizarlo!"
+1
View File
@@ -8,6 +8,7 @@ authors:
website: ${project.url} website: ${project.url}
description: ${project.description} description: ${project.description}
api-version: 1.13 api-version: 1.13
folia-supported: true
depend: depend:
- LuckPerms - LuckPerms
+18 -22
View File
@@ -5,7 +5,7 @@ identifier: "pro"
# 名字 [必须] # 名字 [必须]
# 切换的时候左下角会弹提示 用的就是这个名字 # 切换的时候左下角会弹提示 用的就是这个名字
name: "&b&lPro&b" name: "&b&lPro &b会员"
# 内容 [必须] # 内容 [必须]
# 显示在名字前面的内容 # 显示在名字前面的内容
@@ -29,50 +29,46 @@ permission: "yc.pro"
actions: actions:
- "[CONSOLE] say %player_name% 选择了 Pro会员前缀 " - "[CONSOLE] say %player_name% 选择了 Pro会员前缀 "
description: # 描述 [非必须]
- "&f尊贵的Pro会员专属称号。"
- "&f您将获得多种特权与更好的游戏体验。"
- "&f您可以输入 &b/vip &f指令查看详细特权!"
# 该前缀的GUI物品配置 # 该前缀的GUI物品配置
# 物品配置方式详见 https://github.com/CryptoMorin/XSeries/wiki/XItemStack
item: item:
# 有权限时显示的物品 [必须] # 有权限时显示的物品 [必须]
# 当用户有权限且未选中时,会显示该物品 # 当用户有权限且未选中时,会显示该物品
has-perm: has-perm:
type: DIAMOND material: DIAMOND
name: "&b&lPro &b会员前缀" name: "%(name)"
lore: lore:
- "&7Pro会员专属称号" - "&7Pro会员专属称号"
- "" - "#desciption#{1,1}"
- "&f尊贵的Pro会员专属称号。"
- "&f您将获得多种特权与更好的游戏体验。"
- ""
- "&a➥ 点击切换到该前缀" - "&a➥ 点击切换到该前缀"
# 正在使用时显示的物品 [非必需] # 正在使用时显示的物品 [非必需]
# 当用户正在使用时会显示这个物品,不配置即自动加载“itemHasPermission” # 当用户正在使用时会显示这个物品,不配置即自动加载“itemHasPermission”
using: using:
type: DIAMOND material: DIAMOND
name: "&b&lPro &b会员前缀" name: "%(name)"
flags: flags:
- HIDE_ENCHANTS # 隐藏附魔显示 - HIDE_ENCHANTS # 隐藏附魔显示
enchants: enchants:
PROTECTION_ENVIRONMENTAL: 1 #加一个附魔这样看上去就像是选中了的 PROTECTION_ENVIRONMENTAL: 1 #加一个附魔这样看上去就像是选中了的
lore: lore:
- "&7Pro会员专属称号" - "&7Pro会员专属称号"
- "" - "#desciption#{1,1}"
- "&f尊贵的Pro会员专属称号。"
- "&f您将获得多种特权与更好的游戏体验。"
- ""
- "&a✔ 您正在使用该前缀" - "&a✔ 您正在使用该前缀"
# 没有权限时显示的物品 [非必需] # 没有权限时显示的物品 [非必需]
# 如果没有权限就会显示这个item。如果不配置该物品,则玩家没有使用权限时不会显示在GUI里面。 # 如果没有权限就会显示这个item。如果不配置该物品,则玩家没有使用权限时不会显示在GUI里面。
no-perm: no-perm:
type: INK_SACK material: INK_SACK
data: 8 data: 8
name: "&b&lPro+ &b会员前缀 &c(未拥有)" name: "%(name) &c(未拥有)"
lore: lore:
- "&7Pro+会员专属称号" - "&7Pro 会员专属称号"
- "" - "#desciption#{1,1}"
- "&f尊贵的Pro会员专属称号。" - "&e✯ 加入Pro会员以使用该前缀!"
- "&f您将获得多种特权与更好的游戏体验。"
- "&f您可以输入 &b/vip &f指令查看详细特权!"
- ""
- "&e✯ 加入Pro+会员以使用该前缀!"