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

Compare commits

...

89 Commits

Author SHA1 Message Date
carm 6b601950a3 [v2.3.2] [R] 整合构建、部署(Javadoc)与版本发布。 2022-01-16 08:02:06 +08:00
carm d752461c74 [v2.3.1] [F] 修复前缀数量超过一页时翻页可能出现错误的问题 2022-01-13 01:00:46 +08:00
carm 548f1d366f 修改参考配置的位置 2022-01-07 09:23:40 +08:00
carm 686b28cf93 修改参考配置的位置 2022-01-07 09:13:05 +08:00
carm 92e14e29fe 修复格式错误 2022-01-07 09:01:36 +08:00
carm 78f9639092 [v2.3.0] [U] 修改图片位置 2022-01-07 08:45:46 +08:00
carm 096c23351f Merge remote-tracking branch 'origin/master' 2022-01-07 08:37:36 +08:00
carm b4f8404648 [v2.3.0] 版本更新
- [A] 添加数个事件,方便其他插件调用使用。
- [A] 当原前缀已不存在的情况下的向玩家发送消息。
2022-01-07 08:37:25 +08:00
carm 623356ce21 Update README.md 2022-01-03 15:32:57 +08:00
carm 9164541e4f Merge remote-tracking branch 'origin/master' 2022-01-02 10:14:23 +08:00
carm 2453305420 添加更多统计数据 2022-01-02 10:14:11 +08:00
carm 1856de5e5d Update README.md 2022-01-02 09:33:03 +08:00
carm c38adbeca6 添加统计数据显示 2021-12-31 02:34:31 +08:00
carm 0e90890c67 [v2.2.1] [A] 添加统计数据获取与开关设定。 2021-12-31 02:00:53 +08:00
carm 7e4ca870b5 [v2.2.1] [U] 添加统计数据获取与开关设定。 2021-12-31 01:57:53 +08:00
carm 42b71714aa [v2.2.0] [U] 增添对原生ItemStack配置中 displayName 和 lore的RPG颜色代码支持与PlaceholderAPI变量支持。 2021-12-31 00:08:07 +08:00
carm 0d6247b0f2 [v2.2.0] [U] 增添对原生ItemStack配置中 displayName 和 lore的RPG颜色代码支持与PlaceholderAPI变量支持。 2021-12-30 22:56:33 +08:00
carm 1b9f4f3e55 添加折叠 2021-12-20 18:57:53 +08:00
carm b76081bb6b 添加折叠 2021-12-20 18:55:45 +08:00
carm b8d6862b17 添加折叠 2021-12-20 18:52:42 +08:00
carm 46fb39d7bb 修改路径 2021-11-23 04:37:51 +08:00
carm 523a4f872b 移除样式 2021-11-23 04:31:16 +08:00
carm 5151f1f917 不再整理 2021-11-23 04:27:22 +08:00
carm 296339ca6f 不再整理 2021-11-23 04:22:09 +08:00
carm 63b69defcc 改为中文界面 2021-11-23 04:20:37 +08:00
carm 857ce5c27b 改为中文界面 2021-11-23 04:19:38 +08:00
carm a5189ff314 改为中文界面 2021-11-23 04:16:59 +08:00
carm bacb0b1bed 添加字符集限定 2021-11-23 04:11:31 +08:00
carm 1826f08575 移除自定义css 2021-11-23 04:05:49 +08:00
carm 4df2a49c5b 移除自定义css 2021-11-23 04:03:47 +08:00
carm cbb9928232 自动部署 2021-11-23 03:58:49 +08:00
carm 967984e0c3 自动部署 2021-11-23 03:46:35 +08:00
carm ad780a00bd 自动部署 2021-11-23 03:45:31 +08:00
carm 43c2c14cb3 自动部署 2021-11-23 03:38:26 +08:00
carm 8521d87c46 优化javadoc 2021-11-23 03:36:30 +08:00
carm 378e518e72 Javadoc自动部署 2021-11-23 03:34:03 +08:00
carm 84cbe0c61a 优化javadoc 2021-11-23 03:24:35 +08:00
carm 90f7f7f2e5 优化javadoc 2021-11-23 03:23:39 +08:00
carm 48147aec16 优化javadoc 2021-11-23 03:21:12 +08:00
carm e7c8ce284c 优化javadoc 2021-11-23 03:19:44 +08:00
carm e8b603debc 优化javadoc 2021-11-23 03:17:49 +08:00
carm 72730fad1a 测试Javadoc部署 2021-11-23 03:06:39 +08:00
carm a87e97f744 测试Javadoc部署 2021-11-23 03:02:51 +08:00
carm b2f7338ba6 测试Javadoc部署 2021-11-23 02:58:03 +08:00
carm f91a2aa198 测试Javadoc部署 2021-11-23 02:56:11 +08:00
carm 124ee0f9c3 测试Javadoc部署 2021-11-23 02:46:51 +08:00
carm 9f738ff1ae 修改版本号 2021-11-21 20:01:49 +08:00
carm f23fa03f7a 添加ASCII文字与插件介绍 2021-11-21 19:53:12 +08:00
carm cf749bf5c0 添加下载地址 2021-11-02 11:47:13 +08:00
Carm 01e321686f Merge pull request #6 from CarmJos/dependabot/maven/junit-junit-4.13.1
Bump junit from 4.13 to 4.13.1
2021-10-30 17:59:07 +08:00
dependabot[bot] deba26c713 Bump junit from 4.13 to 4.13.1
Bumps [junit](https://github.com/junit-team/junit4) from 4.13 to 4.13.1.
- [Release notes](https://github.com/junit-team/junit4/releases)
- [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.13.1.md)
- [Commits](https://github.com/junit-team/junit4/compare/r4.13...r4.13.1)

---
updated-dependencies:
- dependency-name: junit:junit
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-30 09:56:26 +00:00
Carm 5b4d49f6ed Create codeql-analysis.yml 2021-10-30 17:54:55 +08:00
carm 2e5250dd36 更新帖子 2021-10-25 08:10:54 +08:00
carm 88730c98f2 更新帖子 2021-10-25 07:58:43 +08:00
carm e003a543f5 支持由控制台为其他玩家打开GUI 2021-10-24 21:22:08 +08:00
Carm 07edaeb401 Merge pull request #5 from Yurinann/master
添加控制台尝试打开称号菜单时的反馈
2021-10-24 21:17:10 +08:00
carm 2357699324 自动提交默认值 2021-10-24 21:14:29 +08:00
“Yurinan” c2fa1a1e95 添加控制台尝试打开称号菜单时的反馈 2021-10-24 14:29:57 +08:00
carm 3b03ec4616 修改readme 2021-10-24 07:22:23 +08:00
carm 1a2644210b 2.1.7 提供自定义配置文件存储位置的功能 2021-10-24 07:12:47 +08:00
carm 83b9ced6f5 2.1.6 补充介绍,优化部署密钥配置。 2021-10-21 21:46:01 +08:00
carm dd96c6d6da 修改源地址 2021-10-19 10:49:35 +08:00
carm ba7d4b90c3 修改源地址 2021-10-19 10:47:55 +08:00
carm ab984acc73 修改源地址 2021-10-19 10:41:18 +08:00
carm 32df1de83d 2.1.5
1. 修复示例config中yaml格式错误的问题
2. 更改构建方式,分开构建与部署的工作流。
2021-10-19 10:40:02 +08:00
carm dfe447393e 2.1.5
1. 修复示例config中yaml格式错误的问题
2. 更改构建方式,分开构建与部署的工作流。
2021-10-19 10:37:41 +08:00
Carm 26ce6d7e66 Merge pull request #3 from OskyEdz/patch-1
YAML formatting
2021-10-19 10:16:04 +08:00
OskyEdz 2e4d1122d9 YAML formatting
Fixed mapping values are not allowed in this context error.
2021-10-19 02:15:38 +02:00
carm b5a2199e1e Update .gitignore 2021-10-19 00:37:07 +08:00
carm 3678a201c7 2.1.4 修改tag机制与测试部署 2021-10-07 23:04:00 +08:00
carm f08a5e84d3 2.1.3 自动构建与部署 (无实质更新) 2021-10-07 22:52:20 +08:00
carm 7743bbb3ff 2.1.3 自动构建与部署 (无实质更新) 2021-10-07 22:50:23 +08:00
carm 1942c50078 2.1.3 自动构建与部署 (无实质更新) 2021-10-07 22:40:53 +08:00
carm 2b701510bc 添加更多maven介绍 2021-10-07 22:37:31 +08:00
carm 0d17e7f1b6 添加packages自动部署 2021-10-07 21:51:16 +08:00
carm 3a41560972 添加packages自动部署 2021-10-07 21:49:39 +08:00
Carm 313aa77d72 Update README.md 2021-10-05 19:40:48 +08:00
Carm dab774a389 Update README.md 2021-10-05 19:29:51 +08:00
Carm 5469c3101f Delete PAY.jpg 2021-10-05 19:29:38 +08:00
Carm dbf826cec8 补全协议介绍 2021-10-05 18:17:08 +08:00
Carm 87c87127b9 Update maven.yml 2021-10-05 18:14:41 +08:00
Carm 50c35488ef Update README.md 2021-10-03 23:54:12 +08:00
Carm 29539ddb6f Update README-en.md 2021-10-03 23:53:40 +08:00
Carm cab2b60abf add code link 2021-10-03 17:57:22 +08:00
Carm 693ff4a4af 添加相关代码参考的地址 2021-10-03 17:28:48 +08:00
Carm 7c90b8ff99 Rename ----.md to feature_issues.md 2021-10-02 17:00:06 +08:00
Carm e5ba217873 Update issue templates 2021-10-02 16:59:42 +08:00
Carm 33e0e64b7d Rename ----.md to bugs_report.md 2021-10-02 16:54:01 +08:00
Carm 6eb60d83d8 添加问题issues模板 2021-10-02 16:53:24 +08:00
44 changed files with 1808 additions and 1342 deletions
+9
View File
@@ -0,0 +1,9 @@
# UserPrefix Javadoc
基于 [Github Pages](https://pages.github.com/) 搭建,请访问 [JavaDoc](https://carmjos.github.io/UserPrefix) 。
## 如何实现?
若您也想通过 [Github Actions](https://docs.github.com/en/actions/learn-github-actions)
自动部署项目的Javadoc到 [Github Pages](https://pages.github.com/)
可以参考我的文章 [《自动部署Javadoc到Github Pages》](https://pages.carm.cc/doc/javadoc-in-github.html) 。
+73
View File
@@ -0,0 +1,73 @@
```text
_ _ _____ __ _
| | | | | __ \ / _|(_)
| | | | ___ ___ _ __ | |__) |_ __ ___ | |_ _ __ __
| | | |/ __| / _ \| '__|| ___/| '__|/ _ \| _|| |\ \/ /
| |__| |\__ \| __/| | | | | | | __/| | | | > <
\____/ |___/ \___||_| |_| |_| \___||_| |_|/_/\_\
```
# UserPrefix 帮助介绍文档
## 插件介绍目录
- 使用示例
- [前缀配置文件预设示例](../src/main/resources/prefixes/example-prefix.yml)
## [开发文档](JAVADOC-README.md)
基于 [Github Pages](https://pages.github.com/) 搭建,请访问 [JavaDoc](https://carmjos.github.io/UltraDepository) 。
## 依赖方式
### Maven 依赖
```xml
<project>
<repositories>
<repository>
<!--采用github依赖库,安全稳定,但需要配置 (推荐)-->
<id>UserPrefix</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/CarmJos/UserPrefix</url>
</repository>
<repository>
<!--采用我的私人依赖库,简单方便,但可能因为变故而无法使用-->
<id>carm-repo</id>
<name>Carm's Repo</name>
<url>https://repo.carm.cc/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>cc.carm.plugin</groupId>
<artifactId>userprefix</artifactId>
<version>[LATEST RELEASE]</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
```
### Gradle 依赖
```groovy
repositories {
// 采用github依赖库,安全稳定,但需要配置 (推荐)
maven { url 'https://maven.pkg.github.com/CarmJos/UserPrefix' }
// 采用我的私人依赖库,简单方便,但可能因为变故而无法使用
maven { url 'https://repo.carm.cc/repository/maven-public/' }
}
dependencies {
compileOnly "cc.carm.plugin:userprefix:[LATEST RELEASE]"
}
```

Before

Width:  |  Height:  |  Size: 723 KiB

After

Width:  |  Height:  |  Size: 723 KiB

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before

Width:  |  Height:  |  Size: 212 KiB

After

Width:  |  Height:  |  Size: 212 KiB

Before

Width:  |  Height:  |  Size: 920 KiB

After

Width:  |  Height:  |  Size: 920 KiB

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

@@ -67,13 +67,89 @@
[hr] [hr]
[size=4][b]基础配置文件 [/b][/size][color=#24292f][font=Tahoma][size=4](config.yml)[/size][/font][/color] [size=4][b]基础配置文件 [/b][/size][color=#24292f][font=Tahoma][size=4](config.yml)[/size][/font][/color]
[spoiler] [spoiler]
[code] version: 1.0.0-SNAPSHOT # 配置文件版本,一般不会动。 [code]
version: ${project.version} #配置文件版本,若与插件版本不同请记得检查配置文件内容
debug: false #debug输出,开发者用的 debug: false
custom-storage:
# 自定义存储位置
# 默认存储位置为 “插件文件夹”/prefixes
# 可以规定到远程文件夹中去寻找前缀相关的设定
# 支持绝对文件路径,如 "/etc/minecraft/configurations/prefixes/"
enable: false # 是否启用
path: "prefixes/" # 一定要指向一个文件夹!
functions: functions:
OnNamePrefix: true # 是否给头顶上添加前缀,该方法用到了头顶的那个计分板,如有冲突请关掉哦~ OnNamePrefix: true # 是否给头顶上添加前缀,该方法用到了头顶的那个计分板,如有冲突请关掉哦~
autoUsePrefix: true # 自动前缀显示 当玩家没有自己选择一个前缀的时候,会自动使用所拥有的的前缀中权重最高的那一个[/code][/spoiler] autoUsePrefix: true # 自动前缀显示 当玩家没有自己选择一个前缀的时候,会自动使用所拥有的的前缀中权重最高的那一个
chat:
# 聊天功能
# - 我不推荐使用本插件的聊天功能,而是建议使用其他的聊天插件。
# - 本插件仅仅提供了**最基本**的格式变量支持,不包含其他任何功能。
# - 注意聊天格式需要遵守Bukkit原格式,即不得缺失 “%1$s” 和 “%2$s” 。
# - 本插件的聊天功能不影响其他插件对聊天事件的操作。
enable: false # 是否启用
format: "<%UserPrefix_prefix%%1$s> %2$s" #聊天的格式,注意 “%1$s” 和 “%2$s” 不可缺少,分别代表 玩家名 与 消息内容 。
GUI:
title: "&f&l我的前缀 &8| 列表"
items:
# 【必须】 GUI中可能存在的其他物品
next-page: # 下一页物品,如果没有下一页则不显示
==: org.bukkit.inventory.ItemStack
type: ARROW
meta:
==: ItemMeta
meta-type: UNSPECIFIC
display-name: "§f下一页"
lore:
- ""
- "§f右键可前往最后一页哦~"
previous-page: # 上一页物品,如果没有上一页则不显示
==: org.bukkit.inventory.ItemStack
type: ARROW
meta:
==: ItemMeta
meta-type: UNSPECIFIC
display-name: "§f上一页"
lore:
- ""
- "§f右键可前往第一页哦~"
Sounds: #相关的声音,注释掉则不播放声音 格式为 【声音名:音量:音调】 或 【声音名:音量】 或 【声音名】
openGUI: "BLOCK_NOTE_BLOCK_PLING:1:1"
guiClick: "UI_BUTTON_CLICK"
prefixChange: "ENTITY_VILLAGER_YES"
prefixExpired: "ENTITY_VILLAGER_NO"
# 默认前缀的配置
# 默认前缀的权重为0哦
defaultPrefix:
name: "默认前缀"
content: "&b"
itemNotUsing:
==: org.bukkit.inventory.ItemStack
type: NAME_TAG
meta:
==: ItemMeta
meta-type: UNSPECIFIC
display-name: "§f默认玩家前缀 §f(点击切换)"
lore:
- ""
- "§a➥ 点击切换到该前缀"
itemUsing:
==: org.bukkit.inventory.ItemStack
type: NAME_TAG
meta:
==: ItemMeta
meta-type: UNSPECIFIC
display-name: "§f默认玩家前缀"
lore:
- ""
- "§a✔ 您正在使用该前缀"
[/code]
[/spoiler]
[b][size=4][backcolor=transparent]消息配置文件[/backcolor][/size] [/b][size=4](messages.yml)[/size] [b][size=4][backcolor=transparent]消息配置文件[/backcolor][/size] [/b][size=4](messages.yml)[/size]
[spoiler][code]selected: [spoiler][code]selected:
@@ -96,7 +172,7 @@ list-value:
- "&8- &7显示名 &r%(name) &7权限 &r%(permission)" - "&8- &7显示名 &r%(name) &7权限 &r%(permission)"
- "&8- &7内容示例&r %(content) %(sender_name)"[/code][/spoiler] - "&8- &7内容示例&r %(content) %(sender_name)"[/code][/spoiler]
[size=4][backcolor=transparent][b]前缀配置文件[/b][/backcolor] (prefixes/*.yml)[/size] [size=4][backcolor=transparent][b]前缀配置文件[/b][/backcolor] (prefixes/*.yml) [自2.1.7可自定义目录][/size]
[align=left][font=-apple-system, BlinkMacSystemFont, &quot;][size=3][color=#000000]所有前缀均为单独的配置文件,存放于 [u]插件配置目录/prefixes[/u] 下,便于管理。[/color][/size][/font][/align][align=left][font=-apple-system, BlinkMacSystemFont, &quot;][size=3][color=#000000]文件名理论上可以随便取,推荐使用英文,部分符号可能会影响正常读取,请避免使用。[/color][/size][/font][/align][align=left][spoiler][/align][code]# 唯一标识 [必须] [align=left][font=-apple-system, BlinkMacSystemFont, &quot;][size=3][color=#000000]所有前缀均为单独的配置文件,存放于 [u]插件配置目录/prefixes[/u] 下,便于管理。[/color][/size][/font][/align][align=left][font=-apple-system, BlinkMacSystemFont, &quot;][size=3][color=#000000]文件名理论上可以随便取,推荐使用英文,部分符号可能会影响正常读取,请避免使用。[/color][/size][/font][/align][align=left][spoiler][/align][code]# 唯一标识 [必须]
# 将用于记录玩家所选的前缀,以及用于数据的缓存。 # 将用于记录玩家所选的前缀,以及用于数据的缓存。
# 必须 必须 必须 保持唯一! # 必须 必须 必须 保持唯一!
@@ -177,11 +253,14 @@ itemNoPermission:
[size=5][b]下载地址[/b][/size] [size=5][b]下载地址[/b][/size]
[hr] [hr]
[size=3][b]最新版本 2.1.0 [/b][/size][attach]1909962[/attach][quote][b][size=3]更新内容[/size][/b] [size=3][b]最新版本 [/b][/size][size=3][b]2.1.7 [/b][/size][attach]1919669[/attach][quote][b][size=3]更新内容[/size][/b]
1. 提供自定义配置文件存储位置的功能,便于多子服共享配置。(custome-storage)
2. 添加控制台打开玩家菜单时的反馈(来自 @Yuri南城 )。
3. 支持由控制台为其他玩家打开GUI。
4. 若出现新配置文件条目,将自动写入默认值,便于配置。[/quote][spoiler][size=3][b]2.1.2 [/b][/size][attach]1912028[/attach][quote][b][size=3]更新内容[/size][/b]
1. 修复不开启插件自带的头顶前缀功能时出现的报错。[/quote]
[size=3][b]2.1.0 [/b][/size][attach]1909962[/attach][quote][b][size=3]更新内容[/size][/b]
1. 添加聊天相关设定,支持聊天前缀。(但不推荐使用哦~)[/quote] 1. 添加聊天相关设定,支持聊天前缀。(但不推荐使用哦~)[/quote]
[spoiler]
[size=3][b] 2.0.0 [/b][/size][attach]1905700[/attach] [size=3][b] 2.0.0 [/b][/size][attach]1905700[/attach]
[quote][b][size=3]更新内容[/size][/b] [quote][b][size=3]更新内容[/size][/b]
1. 修复低版本可能无法读取物品的bug。 1. 修复低版本可能无法读取物品的bug。
@@ -233,8 +312,3 @@ itemNoPermission:
@@ -90,10 +90,17 @@ After installed the [URL='https://github.com/PlaceholderAPI/PlaceholderAPI']Plac
Notice: The default configuration is based on Chinese. You can find the English Version [URL='https://github.com/CarmJos/UserPrefix/blob/master/src/main/resources/en_US/config.yml']here[/URL]. Notice: The default configuration is based on Chinese. You can find the English Version [URL='https://github.com/CarmJos/UserPrefix/blob/master/src/main/resources/en_US/config.yml']here[/URL].
[code=YAML] [code=YAML]
version: ${project.version} # DO NOT EDIT IT version: ${project.version}
debug: false #DEBUG OUT PUT debug: false #DEBUG OUT PUT
custom-storage:
# Custom storage location
# default location is "./prefixes"
# Support absolute file path , such as "/etc/minecraft/configurations/prefixes/"
enable: false
path: "prefixes/" # Must be a folder!
GUI: GUI:
title: "&f&lMy Prefixes List" # Title of the GUI title: "&f&lMy Prefixes List" # Title of the GUI
items: items:
+30
View File
@@ -0,0 +1,30 @@
---
name: 问题提交
about: 描述问题并提交,帮助我们对其进行检查与修复。
title: ''
labels: bug
assignees: ''
---
### **问题简述**
用简短的话语描述一下大概问题。
### **问题来源**
描述一下通过哪些操作才发现的问题,如:
1. 打开 '...'
2. 点击了 '....'
3. 出现了报错 '....'
### **预期结果**(可选)
如果问题不发生,应该是什么情况
### **问题截图/问题报错**
如果有报错或输出,请提供截图。
### **操作环境**
请在后台输入 `version` 并复制相关输出。
### **其他补充**
如有其他补充,可以在这里描述。
+20
View File
@@ -0,0 +1,20 @@
---
name: 功能需求
about: 希望我们提供更多的功能。
title: ''
labels: enhancement
assignees: ''
---
### **功能简述**
简单的描述一下你想要的功能
### **需求来源**
简单的描述一下为什么需要这个功能。
### **功能参考**(可选)
如果有相关功能的参考,如文本、截图,请提供给我们。
### **附加内容**
如果有什么小细节需要重点注意,请在这里告诉我们。
+70
View File
@@ -0,0 +1,70 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL Analysis"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '44 6 * * 4'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'java' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# 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)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
+90
View File
@@ -0,0 +1,90 @@
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
name: Deploy & Upload
on:
# 支持手动触发构建
workflow_dispatch:
release:
# 创建release的时候触发
types: [ published ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: "Set up JDK"
uses: actions/setup-java@v2
with:
java-version: '11'
distribution: 'adopt'
cache: maven
server-id: github
server-username: MAVEN_USERNAME
server-password: MAVEN_TOKEN
- name: "Maven Deploy"
run: mvn -B deploy --file pom.xml -DskipTests
env:
MAVEN_USERNAME: ${{ github.repository_owner }}
MAVEN_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: "Release Asset Upload"
id: upload-release-asset
uses: shogo82148/actions-upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: asset/*.jar
asset_content_type: application/java-archive
- name: "Javadoc Deploy Staging"
run: |
rm -rf docs
mkdir -vp docs
cp -vrf target/apidocs/* docs/
cp -vrf .documentation/JAVADOC-README.md docs/README.md
- name: "Generate the Javadoc sitemap"
id: sitemap
uses: cicirello/generate-sitemap@v1
with:
base-url-path: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}
path-to-root: docs
- name: "Output Javadoc stats"
run: |
echo "sitemap-path = ${{ steps.sitemap.outputs.sitemap-path }}"
echo "url-count = ${{ steps.sitemap.outputs.url-count }}"
echo "excluded-count = ${{ steps.sitemap.outputs.excluded-count }}"
- name: "Configure Git"
env:
DEPLOY_PRI: ${{secrets.DEPLOY_PRI}}
run: |
sudo timedatectl set-timezone "Asia/Shanghai"
mkdir -p ~/.ssh/
echo "$DEPLOY_PRI" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan github.com >> ~/.ssh/known_hosts
git config --global user.name 'CarmJos'
git config --global user.email 'carm@carm.cc'
- name: "Commit Javadocs"
run: |
cd docs
git init
git remote add origin git@github.com:${{ github.repository }}.git
git checkout -b gh-pages
git add -A
git commit -m "API Document generated."
- name: "Push javadocs"
run: |
cd docs
git push origin HEAD:gh-pages --force
+17 -9
View File
@@ -1,13 +1,12 @@
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
name: Java CI with Maven name: Build & Tests
on: on:
# 支持手动触发构建
workflow_dispatch:
push: push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs: jobs:
build: build:
@@ -16,16 +15,25 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Set up JDK 11 - name: "Set up JDK"
uses: actions/setup-java@v2 uses: actions/setup-java@v2
with: with:
java-version: '11' java-version: '11'
distribution: 'adopt' distribution: 'adopt'
cache: maven cache: maven
- name: Build with Maven server-id: github
server-username: MAVEN_USERNAME
server-password: MAVEN_TOKEN
- name: "Package"
run: mvn -B package --file pom.xml run: mvn -B package --file pom.xml
- run: mkdir staging && cp target/*.jar staging env:
- uses: actions/upload-artifact@v2 MAVEN_USERNAME: ${{ github.repository_owner }}
MAVEN_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: "Target Staging"
run: mkdir staging && cp target/*.jar staging
- name: "Upload artifact"
uses: actions/upload-artifact@v2
with: with:
name: Package name: Artifact
path: staging path: staging
+3 -1
View File
@@ -1,3 +1,5 @@
/.idea/ /.idea/
/target/ /target/
./*.iml ./*.iml
*.iml
asset/
+14 -186
View File
@@ -1,4 +1,4 @@
![BANNER](https://raw.githubusercontent.com/CarmJos/UserPrefix/master/img/banner.png) ![BANNER](.documentation/images/banner.png)
# UserPrefix Plugin # UserPrefix Plugin
@@ -16,13 +16,13 @@ This plugin is implemented based on Spigot ,**Theoretically** support ALL MineCr
The development of this plugin is based on Chinese which purpose is to help Chinese developers learn Bukkit plugin The development of this plugin is based on Chinese which purpose is to help Chinese developers learn Bukkit plugin
development. development.
This plugin has been published on [SpigotMC](https://www.spigotmc.org/resources/userprefix.96277/) . > This plugin has been published on [SpigotMC](https://www.spigotmc.org/resources/userprefix.96277/) .
本插件已在 [MCBBS](https://www.mcbbs.net/forum.php?mod=viewthread&tid=1261503) 上发布,欢迎中文用户来这里下载。 > 本插件已在 [MCBBS](https://www.mcbbs.net/forum.php?mod=viewthread&tid=1261503) 上发布,欢迎中文用户来这里下载。
## Examples ## Examples
![example](https://raw.githubusercontent.com/CarmJos/UserPrefix/master/img/using-example.png) ![example](.documentation/images/using-example.png)
## Dependencies ## Dependencies
@@ -42,10 +42,11 @@ For development dependencies, please see [Dependencies](https://github.com/Carm
- The prefix icon can be configured as "Selected", "Has Permission" and “No Permission”. - The prefix icon can be configured as "Selected", "Has Permission" and “No Permission”.
- Item configuration is natively configured through ItemStack, which supports all MC settings! - Item configuration is natively configured through ItemStack, which supports all MC settings!
- TabList is automatically sorted according to the weight of the prefix (if there is a conflict, it can be turned off) - TabList is automatically sorted according to the weight of the prefix (if there is a conflict, it can be turned off)
- The prefix display on the player name (can be turned off if there is a conflict) - The prefix display on the player name (can be turned off if there has any conflict)
- Simple Chat Format Placeholder support. (Not Recommended)
- GUI with automatic sorting and page turning! - GUI with automatic sorting and page turning!
- Support PlaceholderAPI variables! - Support PlaceholderAPI variables!
- Support Hex color! (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)`
## Notice ## Notice
@@ -80,7 +81,7 @@ This plugin's Commands are based on Chinese!
/UserPrefix or /prefix #Open prefix GUI /UserPrefix or /prefix #Open prefix GUI
/UserPrefixAdmin # View Admin Command Help /UserPrefixAdmin # View Admin Command Help
/UserPrefixAdmin reload # Reload Config /UserPrefixAdmin reload # Reload Config
/UserPrefixAdmin list # List all configured prefixes.~~~~ /UserPrefixAdmin list # List all configured prefixes.
``` ```
## Placeholders (PlaceholderAPI) ## Placeholders (PlaceholderAPI)
@@ -103,198 +104,25 @@ type `/papi info UserPrefix` to see all the placeholders.
## Configuration files ## Configuration files
### [Plugin Configuration](https://github.com/CarmJos/UserPrefix/blob/master/src/main/resources/en_US/config.yml) (config.yml) ### Plugin Configuration ([`config.yml`](src/main/resources/en_US/config.yml) .
Notice: The default configuration is based on Chinese. You can find Notice: The default configuration is based on Chinese. You can find
the [English Version here](https://github.com/CarmJos/UserPrefix/blob/master/src/main/resources/en_US/config.yml). the [English Version here](src/main/resources/en_US/config.yml).
```yaml ### Messages Configuration ([`messages.yml`](src/main/resources/en_US/messages.yml))
version: ${project.version} # DO NOT EDIT IT
debug: false #DEBUG OUT PUT Please see the [Source File](src/main/resources/en_US/messages.yml) .
GUI: ### Prefixes Configuration ([`prefixes/*.yml`](src/main/resources/en_US/example-prefix.yml))
title: "&f&lMy Prefixes List" # Title of the GUI
items:
next-page: # only show has next page
==: org.bukkit.inventory.ItemStack
type: ARROW
meta:
==: ItemMeta
meta-type: UNSPECIFIC
display-name: "§fNext Page"
lore:
- ""
- "§fRight-Click to the last page"
previous-page: # only show has previous page
==: org.bukkit.inventory.ItemStack
type: ARROW
meta:
==: ItemMeta
meta-type: UNSPECIFIC
display-name: "§fPrevious Page"
lore:
- ""
- "§fRight-Click to the first page"
functions:
# Whether to add a prefix to the top of the head,
# this method uses the scoreboard above the head,
# please turn it off if there is a conflict.
OnNamePrefix: true
# Automatic prefix select.
# When the player does not choose a prefix by himself,
# the prefix with the highest weight will be used~~~~ automatically
autoUsePrefix: true
chat:
# Chat Function
# - I recommend using other chat plugins instead of using this plugin,
# - this plugin only provides very basic chat format placeholders.
# - Notice that: format must has “%1$s” and “%2$s” for PlayerName and Message (Bukkit Chat Event)
enable: false
format: "<%UserPrefix_prefix%%1$s> %2$s"
Sounds:
# Format is [SOUND_NAME:Volume:Pitch] or [SOUND_NAME:Volume] or [SOUND_NAME]
openGUI: "BLOCK_NOTE_BLOCK_PLING:1:1"
guiClick: "UI_BUTTON_CLICK"
prefixChange: "ENTITY_VILLAGER_YES"
prefixExpired: "ENTITY_VILLAGER_NO"
# The default prefix's weight is 0.
defaultPrefix:
name: "Default prefix"
content: "&b"
itemNotUsing:
==: org.bukkit.inventory.ItemStack
type: NAME_TAG
meta:
==: ItemMeta
meta-type: UNSPECIFIC
display-name: "§fThe default prefix §f(Click to select)"
lore:
- ""
- "§a➥ Click to use"
itemUsing:
==: org.bukkit.inventory.ItemStack
type: NAME_TAG
meta:
==: ItemMeta
meta-type: UNSPECIFIC
display-name: "§fThe default prefix"
lore:
- ""
- "§a✔ Selected"
```
### [Messages Configuration](https://github.com/CarmJos/UserPrefix/blob/master/src/main/resources/en_US/messages.yml) (messages.yml)
```yaml
selected:
- "&7You have selected the &f%(name) &7as current prefix."
expired:
- "&7Your prefix &f%(oldName) &7has expired,"
- "&7Now the prefix is changed to &f%(newName) &7."
reload:
- "&a&lReload completed&7costs &f%(time)ms&7."
help:
- "&3&lUserPrefixAdmin &fHelp"
- "&8#/upa&f list"
- "&8- &7Show configured prefixes."
- "&8#/upa&f reload"
- "&8- &7Reload configuration."
list-title:
- "&3&lUserPrefixAdmin &fList"
list-value:
- "&8#%(weight) &f%(identifier)"
- "&8- &7Name &r%(name) &7Perm &r%(permission)"
- "&8- &7Example&r %(content) %(sender_name)"
```
### [Prefixes Configuration](https://github.com/CarmJos/UserPrefix/blob/master/src/main/resources/en_US/example-prefix.yml) (/prefixes/*.yml)
All prefixes are separate configuration files, stored in the `<Data Folder>/prefixes/` for easy management. All prefixes are separate configuration files, stored in the `<Data Folder>/prefixes/` for easy management.
Some symbols in file name may affect reading, please avoid using them. Some symbols in file name may affect reading, please avoid using them.
```yaml
# identifier [Necessary]
# This will be used for data-storage.
identifier: "pro"
# Name [Necessary]
# Use in messages.
name: "&b&lPro&b"
# Content [Necessary]
# Use in Placeholders
content: "§b§lPro §b"
# Weight [Necessary]
# used for sorting in the GUI and TabList
# In GUI : the larger is displayed at the back
# At TabList : the larger is displayed at the top
weight: 1
# Permission [Unnecessary]
# If there is no permission for detection, everyone can use it,
# which means there is no need to configure "itemNoPermission"
# (because it is impossible to display items without permission at all)
permission: "yc.vip"
# itemHasPermission [Necessary]
# This Item will be displayed when player has permission
itemHasPermission:
==: org.bukkit.inventory.ItemStack
type: DIAMOND
meta:
==: org.bukkit.inventory.ItemStack
type: DIAMOND
meta:
==: ItemMeta
meta-type: UNSPECIFIC
display-name: "§b§lVIP Prefix"
lore:
- ""
- "§a➥ Click to use"
# itemUsing [Unnecessary]
# This Item will be displayed when the prefix is selected.
# If there is no such configuration, it will automatically display "itemHasPermission".
itemUsing:
==: org.bukkit.inventory.ItemStack
type: DIAMOND
meta:
==: ItemMeta
meta-type: UNSPECIFIC
display-name: "§b§lVIP Prefix"
enchants:
PROTECTION_ENVIRONMENTAL: 1 #Add an enchantment so it looks like its selected
lore:
- ""
- "§a✔ Selected"
# itemNoPermission [Unnecessary]
# 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.
itemNoPermission:
==: org.bukkit.inventory.ItemStack
type: INK_SACK
damage: 8
meta:
==: ItemMeta
meta-type: UNSPECIFIC
display-name: "§b§lVIP §c(Buy it!)"
lore:
- ""
- "§e✯ Buy the VIP to use it!"
```
## Support and Donation ## Support and Donation
This project is support by the [YourCraft(你的世界)](https://www.ycraft.cn) . This project is support by the [YourCraft(你的世界)](https://www.ycraft.cn) .
![TeamLogo](https://raw.githubusercontent.com/CarmJos/UserPrefix/master/img/team-logo.png) ![TeamLogo](.documentation/images/team-logo.png)
## Open source agreement ## Open source agreement
+52 -188
View File
@@ -1,25 +1,25 @@
![BANNER](https://raw.githubusercontent.com/CarmJos/UserPrefix/master/img/banner.png) ![BANNER](.documentation/images/banner.png)
# 用户前缀系统插件 # 用户前缀系统插件
[![CodeFactor](https://www.codefactor.io/repository/github/carmjos/userprefix/badge?s=b76fec1f64726b5f19989aace6adb5f85fdab840)](https://www.codefactor.io/repository/github/carmjos/userprefix) [![CodeFactor](https://www.codefactor.io/repository/github/carmjos/userprefix/badge?s=b76fec1f64726b5f19989aace6adb5f85fdab840)](https://www.codefactor.io/repository/github/carmjos/userprefix)
![CodeSize](https://img.shields.io/github/languages/code-size/CarmJos/UserPrefix) ![CodeSize](https://img.shields.io/github/languages/code-size/CarmJos/UserPrefix)
[![License](https://img.shields.io/github/license/CarmJos/UserPrefix)](https://opensource.org/licenses/GPL-3.0) [![Download](https://img.shields.io/github/downloads/CarmJos/UserPrefix/total)](https://github.com/CarmJos/UserPrefix/releases)
[![Java CI with Maven](https://github.com/CarmJos/UserPrefix/actions/workflows/maven.yml/badge.svg?branch=master)](https://github.com/CarmJos/UserPrefix/actions/workflows/maven.yml) [![Java CI with Maven](https://github.com/CarmJos/UserPrefix/actions/workflows/maven.yml/badge.svg?branch=master)](https://github.com/CarmJos/UserPrefix/actions/workflows/maven.yml)
![Support](https://img.shields.io/badge/Minecraft-Java%201.8--Latest-yellow) ![Support](https://img.shields.io/badge/Minecraft-Java%201.8--Latest-green)
![](https://visitor-badge.glitch.me/badge?page_id=userprefix.readme) ![](https://visitor-badge.glitch.me/badge?page_id=userprefix.readme)
轻便、高效、实时的用户前缀系统。 轻便、高效、实时的用户前缀系统。
本插件基于Spigot实现,**理论上支持全版本**。 本插件基于Spigot实现,**理论上支持全版本**。
本插件已在 [MCBBS](https://www.mcbbs.net/forum.php?mod=viewthread&tid=1261503) 与 [SpigotMC](https://www.spigotmc.org/resources/userprefix-hex-color-support-all-version.96277/) 上发布。 The **English version** of the introduction is [here](README-en.md).
The English version of the introduction is [here](https://github.com/CarmJos/UserPrefix/blob/master/README-en.md). > 本插件已在 [MCBBS](https://www.mcbbs.net/forum.php?mod=viewthread&tid=1261503) 与 [SpigotMC](https://www.spigotmc.org/resources/userprefix-hex-color-support-all-version.96277/) 上发布。
## 示例 ## 示例
![example](https://raw.githubusercontent.com/CarmJos/UserPrefix/master/img/using-example.png) ![example](.documentation/images/using-example.png)
## 依赖 ## 依赖
@@ -33,17 +33,19 @@ The English version of the introduction is [here](https://github.com/CarmJos/Use
- 理论上全版本支持! - 理论上全版本支持!
- 游戏内重载配置文件并实时更新到玩家! - 游戏内重载配置文件并实时更新到玩家!
- 当玩家权限变更时会实时监测前缀,若权限不足则自动更换前缀并提示 - 当玩家权限变更时会实时监测前缀,若权限不足则自动更换前缀并提示
- 可配置的声音、消息! - 可配置的声音、消息!
- 前缀图标可配置“选中”、“有权限”与“无权限”三种状态的物品 - 前缀图标可配置“选中”、“有权限”与“无权限”三种状态的物品
- 物品的配置通过ItemStack原生配置,支持MC所有的设定! - 物品的配置通过ItemStack原生配置,支持MC所有的设定!
- 具体的设定请参考其他文档哦~ - 具体的设定请参考其他文档哦~
- TabList自动按照前缀的权重排序 (如有冲突可关掉) - TabList自动按照前缀的权重排序 (如有冲突可关掉)
- 玩家头顶前缀显示 (如有冲突可关掉) - 玩家头顶前缀显示 (如有冲突可关掉)
- 简单的聊天变量修改功能!(不推荐使用) `[自 v2.1.0 版本起]`
- 自动排序,且可翻页的GUI - 自动排序,且可翻页的GUI
- 支持PlaceholderAPI变量!(凡支持的都可以使用,如BungeeTabListPlus) - 支持PlaceholderAPI变量!(凡支持的都可以使用,如BungeeTabListPlus)
- 支持Hex颜色(1.16以上版本) 格式 `&(#颜色代码)` - 支持[Hex颜色](https://www.hexcolortool.com/)(1.16以上版本) `[自 v1.2.3 版本起]`
- 示例: LightSlateBlue `&(#8470FF)` 、 DarkSlateBlue `&(#483D8B)` - 格式: `&(#颜色代码)`
- 示例: LightSlateBlue `&(#8470FF)` 、 DarkSlateBlue `&(#483D8B)`
## 注意事项 ## 注意事项
@@ -95,205 +97,67 @@ The English version of the introduction is [here](https://github.com/CarmJos/Use
## 配置文件示例 ## 配置文件示例
### [基础配置文件](https://github.com/CarmJos/UserPrefix/blob/master/src/main/resources/config.yml) (config.yml) ### 基础配置文件 ([`config.yml`](src/main/resources/config.yml))
```yaml 详见 [源文件](src/main/resources/messages.yml) 。
version: 1.0.0-SNAPSHOT # 配置文件版本,一般不会动。
debug: false #debug输出,开发者用的 ### 消息配置文件 ([`messages.yml`](src/main/resources/messages.yml))
functions: 详见 [源文件](src/main/resources/messages.yml) 。
OnNamePrefix: true # 是否给头顶上添加前缀,该方法用到了头顶的那个计分板,如有冲突请关掉哦~
autoUsePrefix: true # 自动前缀显示 当玩家没有自己选择一个前缀的时候,会自动使用所拥有的的前缀中权重最高的那一个
chat:
# 聊天功能
# - 我不推荐使用本插件的聊天功能,而是建议使用其他的聊天插件。
# - 本插件仅仅提供了**最基本**的格式变量支持,不包含其他任何功能。
# - 注意聊天格式需要遵守Bukkit原格式,即不得缺失 “%1$s” 和 “%2$s” 。
# - 本插件的聊天功能不影响其他插件对聊天事件的操作。
enable: false # 是否启用
format: "<%UserPrefix_prefix%%1$s> %2$s" #聊天的格式,注意 “%1$s” 和 “%2$s” 不可缺少,分别代表 玩家名 与 消息内容 。
GUI: ### 前缀配置文件 ([`prefixes/*.yml`](src/main/resources/prefixes/example-prefix.yml))
title: "&f&l我的前缀 &8| 列表"
items:
# 【必须】 GUI中可能存在的其他物品
next-page: # 下一页物品,如果没有下一页则不显示
==: org.bukkit.inventory.ItemStack
type: ARROW
meta:
==: ItemMeta
meta-type: UNSPECIFIC
display-name: "§f下一页"
lore:
- ""
- "§f右键可前往最后一页哦~"
previous-page: # 上一页物品,如果没有上一页则不显示
==: org.bukkit.inventory.ItemStack
type: ARROW
meta:
==: ItemMeta
meta-type: UNSPECIFIC
display-name: "§f上一页"
lore:
- ""
- "§f右键可前往第一页哦~"
Sounds: #相关的声音,注释掉则不播放声音
# 格式为 【声音名:音量:音调】 或 【声音名:音量】 或 【声音名】
openGUI: "BLOCK_NOTE_BLOCK_PLING:1:1"
guiClick: "UI_BUTTON_CLICK"
prefixChange: "ENTITY_VILLAGER_YES"
prefixExpired: "ENTITY_VILLAGER_NO"
# 默认前缀的配置
# 默认前缀的权重为0哦
defaultPrefix:
name: "默认前缀"
content: "&b"
itemNotUsing:
==: org.bukkit.inventory.ItemStack
type: NAME_TAG
meta:
==: ItemMeta
meta-type: UNSPECIFIC
display-name: "§f默认玩家前缀 §f(点击切换)"
lore:
- ""
- "§a➥ 点击切换到该前缀"
itemUsing:
==: org.bukkit.inventory.ItemStack
type: NAME_TAG
meta:
==: ItemMeta
meta-type: UNSPECIFIC
display-name: "§f默认玩家前缀"
lore:
- ""
- "§a✔ 您正在使用该前缀"
```
### [消息配置文件](https://github.com/CarmJos/UserPrefix/blob/master/src/main/resources/messages.yml) (messages.yml)
```yaml
selected:
- "&7您选择了 &f%(name) &7作为当前显示的前缀。"
expired:
- "&7您先前使用的前缀 &f%(oldName) &7已到期。"
- "&7现在已为您重新调整为 &f%(newName) &7。"
reload:
- "&a&l重载完成!&7共耗时 &f%(time)ms&7。"
help:
- "&3&l用户前缀系统 &f帮助"
- "&8#/upa&f list"
- "&8- &7查看当前前缀列表。"
- "&8#/upa&f reload"
- "&8- &7重载前缀配置。"
list-title:
- "&3&l用户前缀系统 &f前缀列表"
list-value:
- "&8#%(weight) &f%(identifier)"
- "&8- &7显示名 &r%(name) &7权限 &r%(permission)"
- "&8- &7内容示例&r %(content) %(sender_name)"
```
### [前缀配置文件](https://github.com/CarmJos/UserPrefix/blob/master/src/main/resources/prefixes/example-prefix.yml) (prefixes/*.yml)
所有前缀均为单独的配置文件,存放于 `插件配置目录/prefixes` 下,便于管理。 所有前缀均为单独的配置文件,存放于 `插件配置目录/prefixes` 下,便于管理。
文件名理论上可以随便取,推荐使用英文,部分符号可能会影响正常读取,请避免使用。 文件名理论上可以随便取,推荐使用英文,部分符号可能会影响正常读取,请避免使用。
```yaml 您可以 [点击这里](src/main/resources/prefixes/example-prefix.yml) 查看示例前缀配置文件。
# 唯一标识 [必须]
# 将用于记录玩家所选的前缀,以及用于数据的缓存。
# 必须 必须 必须 保持唯一!
identifier: "pro"
# 名字 [必须] ## 使用统计
# 切换的时候左下角会弹提示 用的就是这个名字
name: "&b&lPro&b"
# 内容 [必须]
# 显示在名字前面的内容
content: "§b§lPro §b"
# 权重 [必须]
# 用于GUI、TabList的排序和自动前缀显示
# 在GUI中,权重越高的会显示在越后面
# 在TabList中,权重越高的会显示在越上面
weight: 1
# 检测的权限 [非必须]
# 如果没有就是人人都能用,也代表不用配置“itemNoPermission”了(因为压根不可能显示没权限时候的物品)
permission: "yc.pro"
# 有权限时显示的物品 [必须]
# 当用户有权限且未选中时,会显示该物品
itemHasPermission: #
==: org.bukkit.inventory.ItemStack
type: DIAMOND
meta:
==: ItemMeta
meta-type: UNSPECIFIC
display-name: "§b§lPro §b会员前缀"
lore:
- "§7Pro会员专属称号"
- ""
- "§f尊贵的Pro会员专属称号。"
- "§f您将获得多种特权与更好的游戏体验。"
- ""
- "§a➥ 点击切换到该前缀"
# 正在使用时显示的物品 [非必需]
# 当用户正在使用时会显示这个物品,不配置即自动加载“itemHasPermission”
itemUsing:
==: org.bukkit.inventory.ItemStack
type: DIAMOND
meta:
==: ItemMeta
meta-type: UNSPECIFIC
display-name: "§b§lPro §b会员前缀"
enchants:
PROTECTION_ENVIRONMENTAL: 1 #加一个附魔这样看上去就像是选中了的
lore:
- "§7Pro会员专属称号"
- ""
- "§f尊贵的Pro会员专属称号。"
- "§f您将获得多种特权与更好的游戏体验。"
- ""
- "§a✔ 您正在使用该前缀"
# 没有权限时显示的物品 [非必需]
# 如果没有权限就会显示这个item。如果不配置该物品,则玩家没有使用权限时不会显示在GUI里面。
itemNoPermission:
==: org.bukkit.inventory.ItemStack
type: INK_SACK
damage: 8
meta:
==: ItemMeta
meta-type: UNSPECIFIC
display-name: "§b§lPro+ §b会员前缀 §c(未拥有)"
lore:
- "§7Pro+会员专属称号"
- ""
- "§f尊贵的Pro会员专属称号。"
- "§f您将获得多种特权与更好的游戏体验。"
- "§f您可以输入 §b/vip §f指令查看详细特权!"
- ""
- "§e✯ 加入Pro+会员以使用该前缀!"
```
[![bStats](https://bstats.org/signatures/bukkit/UserPrefix.svg)](https://bstats.org/plugin/bukkit/UserPrefix/13776)
## 支持与捐赠 ## 支持与捐赠
本项目由 [YourCraft(你的世界)](https://www.ycraft.cn) 团队提供长期支持与维护。 本项目由 [YourCraft(你的世界)](https://www.ycraft.cn) 团队提供长期支持与维护。
![TeamLogo](https://raw.githubusercontent.com/CarmJos/UserPrefix/master/img/team-logo.png) ![TeamLogo](.documentation/images/team-logo.png)
若您觉得本插件做的不错,您可以捐赠支持我! 若您觉得本插件做的不错,您可以捐赠支持我!
感谢您成为开源项目的支持者! 感谢您成为开源项目的支持者!
<img height=25% width=25% src="https://raw.githubusercontent.com/CarmJos/UserPrefix/master/img/PAY.jpg" /> <img height=25% width=25% src="https://raw.githubusercontent.com/CarmJos/CarmJos/main/img/donate-code.jpg" alt=""/>
## 开源协议 ## 开源协议
本项目源码采用 [GNU General Public License v3.0](https://opensource.org/licenses/GPL-3.0) 开源协议。 本项目源码采用 [GNU General Public License v3.0](https://opensource.org/licenses/GPL-3.0) 开源协议。
<details>
<summary>关于 GPL 协议</summary>
> GNU General Public Licence (GPL) 有可能是开源界最常用的许可模式。GPL 保证了所有开发者的权利,同时为使用者提供了足够的复制,分发,修改的权利:
>
> #### 可自由复制
> 你可以将软件复制到你的电脑,你客户的电脑,或者任何地方。复制份数没有任何限制。
> #### 可自由分发
> 在你的网站提供下载,拷贝到U盘送人,或者将源代码打印出来从窗户扔出去(环保起见,请别这样做)。
> #### 可以用来盈利
> 你可以在分发软件的时候收费,但你必须在收费前向你的客户提供该软件的 GNU GPL 许可协议,以便让他们知道,他们可以从别的渠道免费得到这份软件,以及你收费的理由。
> #### 可自由修改
> 如果你想添加或删除某个功能,没问题,如果你想在别的项目中使用部分代码,也没问题,唯一的要求是,使用了这段代码的项目也必须使用 GPL 协议。
>
> 需要注意的是,分发的时候,需要明确提供源代码和二进制文件,另外,用于某些程序的某些协议有一些问题和限制,你可以看一下 @PierreJoye 写的 Practical Guide to GPL Compliance 一文。使用 GPL 协议,你必须在源代码代码中包含相应信息,以及协议本身。
>
> *以上文字来自 [五种开源协议GPL,LGPL,BSD,MIT,Apache](https://www.oschina.net/question/54100_9455) 。*
</details>
---
```text
_ _ _____ __ _
| | | | | __ \ / _|(_)
| | | | ___ ___ _ __ | |__) |_ __ ___ | |_ _ __ __
| | | |/ __| / _ \| '__|| ___/| '__|/ _ \| _|| |\ \/ /
| |__| |\__ \| __/| | | | | | | __/| | | | > <
\____/ |___/ \___||_| |_| |_| \___||_| |_|/_/\_\
```
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

+158 -90
View File
@@ -4,23 +4,60 @@
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>cc.carm.plugin</groupId>
<artifactId>UserPrefix</artifactId>
<version>2.1.2</version>
<properties> <properties>
<maven.compiler.source>8</maven.compiler.source> <maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target> <maven.compiler.target>8</maven.compiler.target>
<maven.deploy.skip>true</maven.deploy.skip>
<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>
</properties> </properties>
<groupId>cc.carm.plugin</groupId>
<artifactId>userprefix</artifactId>
<version>v2.3.2</version>
<name>UserPrefix</name>
<description>轻便、高效、实时的用户前缀系统。</description>
<url>https://github.com/CarmJos/UserPrefix</url>
<issueManagement>
<system>GitHub Issues</system>
<url>${project.url}/issues</url>
</issueManagement>
<ciManagement>
<system>GitHub Actions</system>
<url>${project.url}/actions/workflows/maven.yml</url>
</ciManagement>
<developers>
<developer>
<id>CarmJos</id>
<name>Carm Jos</name>
<email>carm@carm.cc</email>
<url>https://work.carm.cc</url>
<roles>
<role>Main Developer</role>
</roles>
</developer>
</developers>
<organization>
<name>YourCraft你的世界</name>
<url>https://www.ycraft.cn/</url>
</organization>
<licenses>
<license>
<name>GNU General Public License v3.0</name>
<url>https://opensource.org/licenses/GPL-3.0</url>
</license>
</licenses>
<repositories> <repositories>
<repository> <repository>
<id>spigotmc-repo</id> <id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/public/</url> <url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository> </repository>
<repository> <repository>
@@ -28,11 +65,6 @@
<url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url> <url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url>
</repository> </repository>
<repository>
<id>lss233-repo</id>
<url>https://lss233.littleservice.cn/repositories/minecraft</url>
</repository>
<repository> <repository>
<id>oss-repo</id> <id>oss-repo</id>
<url>https://oss.sonatype.org/content/groups/public/</url> <url>https://oss.sonatype.org/content/groups/public/</url>
@@ -47,13 +79,29 @@
<id>maven-central</id> <id>maven-central</id>
<url>https://repo1.maven.org/maven2/</url> <url>https://repo1.maven.org/maven2/</url>
</repository> </repository>
<repository>
<id>github</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/CarmJos/${project.name}</url>
</repository>
</repositories> </repositories>
<distributionManagement>
<downloadUrl>${project.url}/releases</downloadUrl>
<repository>
<id>github</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/CarmJos/${project.name}</url>
</repository>
</distributionManagement>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId> <artifactId>spigot-api</artifactId>
<version>1.17-R0.1-SNAPSHOT</version> <version>1.17-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
@@ -72,16 +120,112 @@
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
<version>2.2.1</version>
<scope>compile</scope>
</dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>4.13</version> <version>4.13.2</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<classifier>javadoc</classifier>
<links>
<link>https://javadoc.io/doc/org.jetbrains/annotations/</link>
</links>
<detectJavaApiLink>true</detectJavaApiLink>
<encoding>UTF-8</encoding>
<charset>UTF-8</charset>
<docencoding>UTF-8</docencoding>
<locale>zh_CN</locale>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<compilerArgument>-parameters</compilerArgument>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>${project.name}-${project.version}</finalName>
<outputDirectory>${project.basedir}/asset/</outputDirectory>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
</execution>
</executions>
<configuration>
<relocations>
<relocation>
<pattern>org.bstats</pattern>
<!-- Replace this with your package! -->
<shadedPattern>cc.carm.plugin.userprefix.bstats</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/MANIFEST.MF</exclude>
<exclude>META-INF/*.txt</exclude>
</excludes>
</filter>
</filters>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
@@ -91,82 +235,6 @@
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<classifier>javadoc</classifier>
<links>
<link>https://javadoc.io/doc/org.jetbrains/annotations/</link>
</links>
<detectJavaApiLink>true</detectJavaApiLink>
<encoding>UTF-8</encoding>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<compilerArgument>-parameters</compilerArgument>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
</execution>
</executions>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/MANIFEST.MF</exclude>
<exclude>META-INF/*.txt</exclude>
</excludes>
</filter>
</filters>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<configuration>
<useSystemClassLoader>false</useSystemClassLoader>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<resources> <resources>
<resource> <resource>
<directory>src/main/resources</directory> <directory>src/main/resources</directory>
+116 -62
View File
@@ -2,7 +2,7 @@ package cc.carm.plugin.userprefix;
import cc.carm.plugin.userprefix.command.UserPrefixAdminCommand; import cc.carm.plugin.userprefix.command.UserPrefixAdminCommand;
import cc.carm.plugin.userprefix.command.UserPrefixCommand; import cc.carm.plugin.userprefix.command.UserPrefixCommand;
import cc.carm.plugin.userprefix.configuration.PrefixConfig; import cc.carm.plugin.userprefix.configuration.PluginConfig;
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;
@@ -14,93 +14,147 @@ import cc.carm.plugin.userprefix.manager.UserManager;
import cc.carm.plugin.userprefix.util.ColorParser; import cc.carm.plugin.userprefix.util.ColorParser;
import cc.carm.plugin.userprefix.util.MessageUtil; import cc.carm.plugin.userprefix.util.MessageUtil;
import net.luckperms.api.event.user.UserDataRecalculateEvent; import net.luckperms.api.event.user.UserDataRecalculateEvent;
import org.bstats.bukkit.Metrics;
import org.bstats.charts.SimplePie;
import org.bstats.charts.SingleLineChart;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.TabCompleter;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class Main extends JavaPlugin { public class Main extends JavaPlugin {
private static Main instance; private static Main instance;
@Override @Override
public void onEnable() { public void onEnable() {
instance = this; instance = this;
showPluginName();
log(getName() + " " + getDescription().getVersion() + " &7开始加载...");
long startTime = System.currentTimeMillis();
log(getName() + " " + getDescription().getVersion() + " &7开始加载..."); log("加载配置文件...");
long startTime = System.currentTimeMillis(); ConfigManager.initConfig();
PrefixManager.init();
log("加载配置文件..."); log("注册指令...");
ConfigManager.initConfig(); registerCommand("UserPrefix", new UserPrefixCommand());
PrefixManager.init(); registerCommand("UserPrefixAdmin", new UserPrefixAdminCommand());
log("注册指令..."); log("注册监听器...");
Bukkit.getPluginCommand("UserPrefix").setExecutor(new UserPrefixCommand()); regListener(new UserListener());
Bukkit.getPluginCommand("UserPrefixAdmin").setExecutor(new UserPrefixAdminCommand()); regListener(new ChatListener());
ServiceManager.getService().getEventBus().subscribe(this, UserDataRecalculateEvent.class, UserNodeUpdateProcessor::process);
log("注册监听器..."); if (MessageUtil.hasPlaceholderAPI()) {
regListener(new UserListener()); log("注册变量...");
regListener(new ChatListener()); new UserPrefixExpansion(getInstance()).register();
ServiceManager.getService().getEventBus().subscribe(this, UserDataRecalculateEvent.class, UserNodeUpdateProcessor::process); } else {
log("未安装 PlaceholderAPI 不进行变量注册...");
log("若您想使用变量进行前缀的显示,请安装PlaceholderAPI");
}
if (MessageUtil.hasPlaceholderAPI()) { if (PluginConfig.METRICS.get()) {
log("注册变量..."); log("启用统计数据...");
new UserPrefixExpansion(getInstance()).register(); Metrics metrics = new Metrics(this, 13776);
} else { metrics.addCustomChart(new SingleLineChart("active_prefixes", () -> PrefixManager.getPrefixes().size()));
log("未安装 PlaceholderAPI 不进行变量注册..."); metrics.addCustomChart(new SimplePie("custom_storage", () -> PluginConfig.CustomStorage.ENABLE.get() ? "ENABLE" : "DISABLE"));
log("若您想使用变量进行前缀的显示,请安装PlaceholderAPI"); metrics.addCustomChart(new SimplePie("lp_version", () -> ServiceManager.getService().getPluginMetadata().getVersion()));
} metrics.addCustomChart(new SimplePie("papi_version", () -> {
Plugin plugin = Bukkit.getPluginManager().getPlugin("PlaceholderAPI");
if (plugin == null) return "Not installed";
else return plugin.getDescription().getVersion();
}));
}
log("加载完成 ,共耗时 " + (System.currentTimeMillis() - startTime) + " ms 。");
showAD();
if (Bukkit.getOnlinePlayers().size() > 0) {
Bukkit.getOnlinePlayers().forEach(UserManager::initPlayer); // 适配热重载
}
log("加载完成 ,共耗时 " + (System.currentTimeMillis() - startTime) + " ms 。"); }
showAD(); @Override
public void onDisable() {
showPluginName();
log(getName() + " " + getDescription().getVersion() + " 开始卸载...");
long startTime = System.currentTimeMillis();
if (Bukkit.getOnlinePlayers().size() > 0) { log("卸载监听器...");
Bukkit.getOnlinePlayers().forEach(UserManager::initPlayer); // 适配热重载 Bukkit.getServicesManager().unregisterAll(this);
}
} log("卸载完成 ,共耗时 " + (System.currentTimeMillis() - startTime) + " ms 。");
@Override showAD();
public void onDisable() {
log(getName() + " " + getDescription().getVersion() + " 开始卸载...");
long startTime = System.currentTimeMillis();
log("卸载监听器..."); }
Bukkit.getServicesManager().unregisterAll(this);
log("卸载完成 ,共耗时 " + (System.currentTimeMillis() - startTime) + " ms 。"); /**
* 注册监听器
*
* @param listener 监听器
*/
public static void regListener(Listener listener) {
Bukkit.getPluginManager().registerEvents(listener, getInstance());
}
showAD(); public static void log(String message) {
Bukkit.getConsoleSender().sendMessage(ColorParser.parse("[" + getInstance().getName() + "] " + message));
}
} public static void debug(String message) {
if (PluginConfig.DEBUG.get()) {
log("[DEBUG] " + message);
}
}
/** public static void error(String message) {
* 注册监听器 log("&c[ERROR] &r" + message);
* }
* @param listener 监听器
*/
public static void regListener(Listener listener) {
Bukkit.getPluginManager().registerEvents(listener, getInstance());
}
public static void log(String message) {
Bukkit.getConsoleSender().sendMessage(ColorParser.parse("[" + getInstance().getName() + "] " + message));
}
public static void debug(String message) { public static JavaPlugin getInstance() {
if (PrefixConfig.DEBUG.get()) { return instance;
log("[DEBUG] " + message); }
}
}
public static JavaPlugin getInstance() {
return instance;
}
private void showAD() { public static void registerCommand(String commandName,
log("&7感谢您使用 &3&lUserPrefix " + getDescription().getVersion() + "&7!"); @NotNull CommandExecutor executor) {
log("&7本插件由 &b&lYourCraft &7提供长期支持与维护。"); registerCommand(commandName, executor, null);
} }
public static void registerCommand(String commandName,
@NotNull CommandExecutor executor,
@Nullable TabCompleter tabCompleter) {
PluginCommand command = Bukkit.getPluginCommand(commandName);
if (command == null) return;
command.setExecutor(executor);
if (tabCompleter != null) command.setTabCompleter(tabCompleter);
}
private void showPluginName() {
log("&b _ _ &f _____ __ _ ");
log("&b| | | | &f| __ \\ / _|(_) ");
log("&b| | | | ___ ___ _ __ &f| |__) |_ __ ___ | |_ _ __ __");
log("&b| | | |/ __| / _ \\| '__|&f| ___/| '__|/ _ \\| _|| |\\ \\/ /");
log("&b| |__| |\\__ \\| __/| | &f| | | | | __/| | | | > < ");
log("&b \\____/ |___/ \\___||_| &f|_| |_| \\___||_| |_|/_/\\_\\");
log("&8 ");
log("&8> &f" + getDescription().getWebsite());
}
private void showAD() {
log("&7感谢您使用 &3&lUserPrefix " + getDescription().getVersion() + "&7!");
log("&7本插件由 &b&lYourCraft &7提供长期支持与维护。");
}
} }
@@ -1,6 +1,6 @@
package cc.carm.plugin.userprefix.command; package cc.carm.plugin.userprefix.command;
import cc.carm.plugin.userprefix.configuration.PrefixConfig; import cc.carm.plugin.userprefix.configuration.PluginConfig;
import cc.carm.plugin.userprefix.manager.ConfigManager; import cc.carm.plugin.userprefix.manager.ConfigManager;
import cc.carm.plugin.userprefix.manager.PrefixManager; import cc.carm.plugin.userprefix.manager.PrefixManager;
import cc.carm.plugin.userprefix.manager.UserManager; import cc.carm.plugin.userprefix.manager.UserManager;
@@ -22,10 +22,10 @@ public class UserPrefixAdminCommand implements CommandExecutor {
if (args.length == 1) { if (args.length == 1) {
String aim = args[0]; String aim = args[0];
if (aim.equalsIgnoreCase("list")) { if (aim.equalsIgnoreCase("list")) {
MessageUtil.sendWithPlaceholders(sender, PrefixConfig.Messages.LIST_TITLE.get()); MessageUtil.sendWithPlaceholders(sender, PluginConfig.Messages.LIST_TITLE.get());
for (ConfiguredPrefix value : PrefixManager.getPrefixes().values()) { for (ConfiguredPrefix value : PrefixManager.getPrefixes().values()) {
MessageUtil.sendWithPlaceholders( MessageUtil.sendWithPlaceholders(
sender, PrefixConfig.Messages.LIST_VALUE.get(), sender, PluginConfig.Messages.LIST_VALUE.get(),
new String[]{ new String[]{
"%(weight)", "%(identifier)", "%(weight)", "%(identifier)",
"%(name)", "%(permission)", "%(name)", "%(permission)",
@@ -54,7 +54,7 @@ public class UserPrefixAdminCommand implements CommandExecutor {
UserManager.updatePrefixView(onlinePlayer, false); UserManager.updatePrefixView(onlinePlayer, false);
} }
MessageUtil.sendWithPlaceholders( MessageUtil.sendWithPlaceholders(
sender, PrefixConfig.Messages.RELOAD.get(), sender, PluginConfig.Messages.RELOAD.get(),
new String[]{"%(time)"}, new Object[]{(System.currentTimeMillis() - s1)} new String[]{"%(time)"}, new Object[]{(System.currentTimeMillis() - s1)}
); );
return true; return true;
@@ -65,7 +65,7 @@ public class UserPrefixAdminCommand implements CommandExecutor {
} }
public static boolean help(CommandSender sender) { public static boolean help(CommandSender sender) {
MessageUtil.send(sender, PrefixConfig.Messages.HELP.get()); MessageUtil.send(sender, PluginConfig.Messages.HELP.get());
return true; return true;
} }
@@ -1,6 +1,7 @@
package cc.carm.plugin.userprefix.command; package cc.carm.plugin.userprefix.command;
import cc.carm.plugin.userprefix.ui.PrefixSelectGUI; import cc.carm.plugin.userprefix.ui.PrefixSelectGUI;
import org.bukkit.Bukkit;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@@ -14,6 +15,15 @@ public class UserPrefixCommand implements CommandExecutor {
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) { public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) {
if (sender instanceof Player) { if (sender instanceof Player) {
PrefixSelectGUI.open((Player) sender); PrefixSelectGUI.open((Player) sender);
} else {
if (strings.length != 1) {
sender.sendMessage("输入 /prefix <ID> 为玩家打开前缀GUI。");
} else {
Player player = Bukkit.getPlayer(strings[0]);
if (player != null) {
PrefixSelectGUI.open(player);
}
}
} }
return true; return true;
} }
@@ -0,0 +1,85 @@
package cc.carm.plugin.userprefix.configuration;
import cc.carm.plugin.userprefix.configuration.message.ConfigMessageList;
import cc.carm.plugin.userprefix.configuration.values.ConfigSound;
import cc.carm.plugin.userprefix.configuration.values.ConfigValue;
import cc.carm.plugin.userprefix.util.ItemStackFactory;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
public class PluginConfig {
public static ConfigValue<Boolean> DEBUG = new ConfigValue<>("debug", Boolean.class, false);
public static ConfigValue<Boolean> METRICS = new ConfigValue<>("metrics", Boolean.class, true);
public static class CustomStorage {
public static ConfigValue<Boolean> ENABLE = new ConfigValue<>("custom-storage.enable", Boolean.class, false);
public static ConfigValue<String> PATH = new ConfigValue<>("custom-storage.path", String.class, "prefixes/");
}
public static class Functions {
public static ConfigValue<Boolean> NAME_PREFIX = new ConfigValue<>("functions.OnNamePrefix", Boolean.class, true);
public static ConfigValue<Boolean> AUTO_USE = new ConfigValue<>("functions.autoUsePrefix", Boolean.class, true);
public static class Chat {
public static ConfigValue<Boolean> ENABLE = new ConfigValue<>("functions.chat.enable", Boolean.class, false);
public static ConfigValue<String> FORMAT = new ConfigValue<>("functions.chat.format", String.class, "<%1$s> %2$s");
}
}
public static class GUI {
public static ConfigValue<String> TITLE = new ConfigValue<>("GUI.title", String.class, "&f&l我的前缀 &8| 列表");
public static class Items {
public static ConfigValue<ItemStack> NEXT_PAGE = new ConfigValue<>("GUI.items.next-page", ItemStack.class,
new ItemStackFactory(Material.ARROW)
.setDisplayName("下一页")
.addLore("&7&o右键可前往最后一页哦")
.toItemStack()
);
public static ConfigValue<ItemStack> PREVIOUS_PAGE = new ConfigValue<>("GUI.items.previous-page", ItemStack.class,
new ItemStackFactory(Material.ARROW)
.setDisplayName("上一页")
.addLore("&7&o右键可前往第一页哦")
.toItemStack()
);
}
}
public static class Messages {
public static ConfigMessageList SELECTED = new ConfigMessageList("selected");
public static ConfigMessageList EXPIRED = new ConfigMessageList("expired");
public static ConfigMessageList REMOVED = new ConfigMessageList("removed");
public static ConfigMessageList RELOAD = new ConfigMessageList("reload");
public static ConfigMessageList HELP = new ConfigMessageList("help");
public static ConfigMessageList LIST_TITLE = new ConfigMessageList("list-title");
public static ConfigMessageList LIST_VALUE = new ConfigMessageList("list-value");
}
public static class Sounds {
public static ConfigSound GUI_OPEN = new ConfigSound("Sounds.openGUI");
public static ConfigSound GUI_CLICK = new ConfigSound("Sounds.guiClick");
public static ConfigSound PREFIX_CHANGE = new ConfigSound("Sounds.prefixChange");
public static ConfigSound PREFIX_EXPIRED = new ConfigSound("Sounds.prefixExpired");
}
}
@@ -1,73 +0,0 @@
package cc.carm.plugin.userprefix.configuration;
import cc.carm.plugin.userprefix.configuration.message.ConfigMessageList;
import cc.carm.plugin.userprefix.configuration.values.ConfigSound;
import cc.carm.plugin.userprefix.configuration.values.ConfigValue;
import cc.carm.plugin.userprefix.util.ItemStackFactory;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
public class PrefixConfig {
public static ConfigValue<Boolean> DEBUG = new ConfigValue<>("debug", Boolean.class, false);
public static class Functions {
public static ConfigValue<Boolean> NAME_PREFIX = new ConfigValue<>("functions.OnNamePrefix", Boolean.class, true);
public static ConfigValue<Boolean> AUTO_USE = new ConfigValue<>("functions.autoUsePrefix", Boolean.class, true);
public static class Chat {
public static ConfigValue<Boolean> ENABLE = new ConfigValue<>("functions.chat.enable", Boolean.class, false);
public static ConfigValue<String> FORMAT = new ConfigValue<>("functions.chat.format", String.class, "<%1$s> %2$s");
}
}
public static class GUI {
public static ConfigValue<String> TITLE = new ConfigValue<>("GUI.title", String.class, "&f&l我的前缀 &8| 列表");
public static class Items {
public static ConfigValue<ItemStack> NEXT_PAGE = new ConfigValue<>("GUI.items.next-page", ItemStack.class,
new ItemStackFactory(Material.ARROW)
.setDisplayName("下一页")
.addLore("&7&o右键可前往最后一页哦")
.toItemStack()
);
public static ConfigValue<ItemStack> PREVIOUS_PAGE = new ConfigValue<>("GUI.items.previous-page", ItemStack.class,
new ItemStackFactory(Material.ARROW)
.setDisplayName("上一页")
.addLore("&7&o右键可前往第一页哦")
.toItemStack()
);
}
}
public static class Messages {
public static ConfigMessageList SELECTED = new ConfigMessageList("selected");
public static ConfigMessageList EXPIRED = new ConfigMessageList("expired");
public static ConfigMessageList RELOAD = new ConfigMessageList("reload");
public static ConfigMessageList HELP = new ConfigMessageList("help");
public static ConfigMessageList LIST_TITLE = new ConfigMessageList("list-title");
public static ConfigMessageList LIST_VALUE = new ConfigMessageList("list-value");
}
public static class Sounds {
public static ConfigSound GUI_OPEN = new ConfigSound("Sounds.openGUI");
public static ConfigSound GUI_CLICK = new ConfigSound("Sounds.guiClick");
public static ConfigSound PREFIX_CHANGE = new ConfigSound("Sounds.prefixChange");
public static ConfigSound PREFIX_EXPIRED = new ConfigSound("Sounds.prefixExpired");
}
}
@@ -10,62 +10,64 @@ import org.bukkit.entity.Player;
public class ConfigSound { public class ConfigSound {
FileConfig source; FileConfig source;
String configSection; String configSection;
Sound defaultValue; Sound defaultValue;
public ConfigSound(String configSection) { public ConfigSound(String configSection) {
this(configSection, null); this(configSection, null);
} }
public ConfigSound(String configSection, Sound defaultValue) { public ConfigSound(String configSection, Sound defaultValue) {
this(ConfigManager.getPluginConfig(), configSection, defaultValue); this(ConfigManager.getPluginConfig(), configSection, defaultValue);
} }
public ConfigSound(FileConfig source, String configSection, Sound defaultValue) { public ConfigSound(FileConfig source, String configSection, Sound defaultValue) {
this.source = source; this.source = source;
this.configSection = configSection; this.configSection = configSection;
this.defaultValue = defaultValue; this.defaultValue = defaultValue;
} }
public FileConfiguration getConfiguration() { public FileConfiguration getConfiguration() {
return this.source.getConfig(); return this.source.getConfig();
} }
public void set(Sound value, float volume) { public void set(Sound value, float volume) {
getConfiguration().set(this.configSection, value.name() + ":" + volume); getConfiguration().set(this.configSection, value.name() + ":" + volume);
this.save(); this.save();
} }
public void set(Sound value, float volume, float pitch) { public void set(Sound value, float volume, float pitch) {
getConfiguration().set(this.configSection, value.name() + ":" + volume + ":" + pitch); getConfiguration().set(this.configSection, value.name() + ":" + volume + ":" + pitch);
this.save(); this.save();
} }
public void play(Player player) { public void play(Player player) {
Sound finalSound = defaultValue; Sound finalSound = defaultValue;
float pitch = 1; float pitch = 1;
float volume = 1; float volume = 1;
String soundString = getConfiguration().getString(this.configSection); String soundString = getConfiguration().getString(this.configSection);
if (soundString != null) { if (soundString != null) {
String[] args = soundString.contains(":") ? soundString.split(":") : new String[]{soundString}; String[] args = soundString.contains(":") ? soundString.split(":") : new String[]{soundString};
try { try {
if (args.length >= 1) finalSound = Sound.valueOf(args[0]); if (args.length >= 1) finalSound = Sound.valueOf(args[0]);
if (args.length >= 2) volume = Float.parseFloat(args[1]); if (args.length >= 2) volume = Float.parseFloat(args[1]);
if (args.length >= 3) volume = Float.parseFloat(args[2]); if (args.length >= 3) volume = Float.parseFloat(args[2]);
} catch (Exception exception) { } catch (Exception exception) {
Main.log("声音 " + this.configSection + " 配置错误,不存在 " + soundString + " ,请检查。"); Main.error("声音 " + this.configSection + " 配置错误,不存在 " + soundString + " ,请检查。");
} Main.error("There's no sound matches in " + this.configSection + " , please check the configuration");
}
if (finalSound != null) {
player.playSound(player.getLocation(), finalSound, volume, pitch);
}
} }
}
if (finalSound != null) {
player.playSound(player.getLocation(), finalSound, volume, pitch);
}
public void save() { }
this.source.save();
} public void save() {
this.source.save();
}
} }
@@ -32,8 +32,13 @@ public class ConfigValue<V> {
} }
public V get() { public V get() {
Object val = getConfiguration().get(this.configSection, this.defaultValue); if (getConfiguration().contains(this.configSection)) {
return this.clazz.isInstance(val) ? this.clazz.cast(val) : this.defaultValue; Object val = getConfiguration().get(this.configSection, this.defaultValue);
return this.clazz.isInstance(val) ? this.clazz.cast(val) : this.defaultValue;
} else {
// 如果没有默认值,就把配置写进去,便于配置
return setDefault();
}
} }
public void set(V value) { public void set(V value) {
@@ -45,4 +50,9 @@ public class ConfigValue<V> {
this.source.save(); this.source.save();
} }
public V setDefault() {
set(this.defaultValue);
return this.defaultValue;
}
} }
@@ -0,0 +1,55 @@
package cc.carm.plugin.userprefix.event;
import cc.carm.plugin.userprefix.model.ConfiguredPrefix;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class UserPrefixChangeEvent extends UserPrefixEvent implements Cancellable {
public static HandlerList handler = new HandlerList();
private boolean cancelled;
private final @Nullable ConfiguredPrefix before;
private @NotNull ConfiguredPrefix after;
public UserPrefixChangeEvent(@NotNull Player who,
@Nullable ConfiguredPrefix before,
@NotNull ConfiguredPrefix after) {
super(who);
this.before = before;
this.after = after;
}
public @Nullable ConfiguredPrefix getBefore() {
return before;
}
public @NotNull ConfiguredPrefix getAfter() {
return after;
}
public void setAfter(@NotNull ConfiguredPrefix after) {
this.after = after;
}
@Override
public boolean isCancelled() {
if (before == null) return false; //Could not be cancelled when prefix is null.
else return this.cancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
@NotNull
@Override
public HandlerList getHandlers() {
return handler;
}
}
@@ -0,0 +1,13 @@
package cc.carm.plugin.userprefix.event;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.NotNull;
public abstract class UserPrefixEvent extends PlayerEvent {
public UserPrefixEvent(@NotNull Player who) {
super(who);
}
}
@@ -0,0 +1,30 @@
package cc.carm.plugin.userprefix.event;
import cc.carm.plugin.userprefix.model.ConfiguredPrefix;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class UserPrefixExpireEvent extends UserPrefixEvent {
public static HandlerList handler = new HandlerList();
public final @NotNull ConfiguredPrefix expiredPrefix;
public UserPrefixExpireEvent(@NotNull Player who,
@NotNull ConfiguredPrefix expiredPrefix) {
super(who);
this.expiredPrefix = expiredPrefix;
}
public @NotNull ConfiguredPrefix getExpiredPrefix() {
return expiredPrefix;
}
@NotNull
@Override
public HandlerList getHandlers() {
return handler;
}
}
@@ -1,7 +1,7 @@
package cc.carm.plugin.userprefix.listener; package cc.carm.plugin.userprefix.listener;
import cc.carm.plugin.userprefix.Main; import cc.carm.plugin.userprefix.Main;
import cc.carm.plugin.userprefix.configuration.PrefixConfig; import cc.carm.plugin.userprefix.configuration.PluginConfig;
import cc.carm.plugin.userprefix.util.MessageUtil; import cc.carm.plugin.userprefix.util.MessageUtil;
import me.clip.placeholderapi.PlaceholderAPI; import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@@ -10,23 +10,23 @@ import org.bukkit.event.player.AsyncPlayerChatEvent;
public class ChatListener implements Listener { public class ChatListener implements Listener {
@EventHandler @EventHandler
public void onChat(AsyncPlayerChatEvent event) { public void onChat(AsyncPlayerChatEvent event) {
if (!PrefixConfig.Functions.Chat.ENABLE.get()) return; if (!PluginConfig.Functions.Chat.ENABLE.get()) return;
String format = PrefixConfig.Functions.Chat.FORMAT.get(); String format = PluginConfig.Functions.Chat.FORMAT.get();
if (format == null || format.length() < 1) return; if (format == null || format.length() < 1) return;
if (!MessageUtil.hasPlaceholderAPI()) return; if (!MessageUtil.hasPlaceholderAPI()) return;
try { try {
event.setFormat(PlaceholderAPI.setPlaceholders(event.getPlayer(), format)); event.setFormat(PlaceholderAPI.setPlaceholders(event.getPlayer(), format));
} catch (Exception exception) { } catch (Exception exception) {
Main.log("Please check the chat configuration."); Main.error("请检查配置文件中聊天相关是否配置正确。");
Main.log("请检查配置文件中聊天相关是否配置正确。"); Main.error("Please check the chat configuration.");
exception.printStackTrace(); exception.printStackTrace();
} }
} }
} }
@@ -1,6 +1,7 @@
package cc.carm.plugin.userprefix.manager; package cc.carm.plugin.userprefix.manager;
import cc.carm.plugin.userprefix.Main; import cc.carm.plugin.userprefix.Main;
import cc.carm.plugin.userprefix.configuration.PluginConfig;
import cc.carm.plugin.userprefix.model.ConfiguredPrefix; import cc.carm.plugin.userprefix.model.ConfiguredPrefix;
import cc.carm.plugin.userprefix.util.ItemStackFactory; import cc.carm.plugin.userprefix.util.ItemStackFactory;
import org.bukkit.Material; import org.bukkit.Material;
@@ -20,135 +21,151 @@ import java.util.stream.Collectors;
public class PrefixManager { public class PrefixManager {
public static ConfiguredPrefix defaultPrefix; public static ConfiguredPrefix defaultPrefix;
public static HashMap<String, ConfiguredPrefix> prefixes = new HashMap<>(); public static HashMap<String, ConfiguredPrefix> prefixes = new HashMap<>();
private static final String FOLDER_NAME = "prefixes"; private static final String FOLDER_NAME = "prefixes";
public static void init() { public static void init() {
loadPrefixes(); loadPrefixes();
Main.log("共加载了 " + prefixes.size() + " 个前缀。"); Main.log("共加载了 " + prefixes.size() + " 个前缀。");
} }
public static void loadPrefixes() { public static void loadPrefixes() {
loadDefaultPrefix(); loadDefaultPrefix();
loadConfiguredPrefixes(); loadConfiguredPrefixes();
} }
public static void loadConfiguredPrefixes() { @SuppressWarnings("ResultOfMethodCallIgnored")
public static void loadConfiguredPrefixes() {
File prefixDataFolder = new File(Main.getInstance().getDataFolder() + File.separator + FOLDER_NAME); File prefixDataFolder = getStorageFolder();
if (!prefixDataFolder.isDirectory() || !prefixDataFolder.exists()) { if (!prefixDataFolder.isDirectory() || !prefixDataFolder.exists()) {
prefixDataFolder.mkdir(); prefixDataFolder.mkdir();
} }
String[] filesList = prefixDataFolder.list(); String[] filesList = prefixDataFolder.list();
if (filesList == null || filesList.length < 1) { if (filesList == null || filesList.length < 1) {
Main.log("配置文件中暂无任何前缀配置,请检查。"); Main.error("配置文件中暂无任何前缀配置,请检查。");
Main.log("There's no configured prefix."); Main.error("There's no configured prefix.");
return; Main.error("Path: " + prefixDataFolder.getAbsolutePath());
} return;
List<File> files = Arrays.stream(filesList) }
.map(s -> new File(prefixDataFolder, s))
.filter(File::isFile)
.collect(Collectors.toList());
HashMap<String, ConfiguredPrefix> dataPrefixes = new HashMap<>(); List<File> files = Arrays.stream(filesList)
.map(s -> new File(prefixDataFolder, s))
.filter(File::isFile)
.collect(Collectors.toList());
if (files.size() > 0) { HashMap<String, ConfiguredPrefix> dataPrefixes = new HashMap<>();
for (File file : files) {
try {
ConfiguredPrefix prefix = new ConfiguredPrefix(file);
Main.log("完成前缀加载 " + prefix.getIdentifier() + " : " + prefix.getName());
dataPrefixes.put(prefix.getIdentifier(), prefix);
} catch (Exception ex) {
Main.log("Error occurred when loading prefix #" + file.getAbsolutePath() + " !");
ex.printStackTrace();
}
}
}
PrefixManager.prefixes.clear(); if (files.size() > 0) {
PrefixManager.prefixes = dataPrefixes; for (File file : files) {
} try {
ConfiguredPrefix prefix = new ConfiguredPrefix(file);
Main.log("完成前缀加载 " + prefix.getIdentifier() + " : " + prefix.getName());
Main.log("Successfully loaded " + prefix.getIdentifier() + " : " + prefix.getName());
dataPrefixes.put(prefix.getIdentifier(), prefix);
} catch (Exception ex) {
Main.error("在加载前缀 " + file.getAbsolutePath() + " 时出错,请检查配置!");
Main.error("Error occurred when loading prefix #" + file.getAbsolutePath() + " !");
ex.printStackTrace();
}
}
}
public static void loadDefaultPrefix() { PrefixManager.prefixes.clear();
PrefixManager.defaultPrefix = null; PrefixManager.prefixes = dataPrefixes;
ConfigurationSection defaultPrefixSection = ConfigManager.getPluginConfig().getConfig().getConfigurationSection("defaultPrefix"); }
if (defaultPrefixSection != null) {
try {
String name = defaultPrefixSection.getString("name", "默认前缀");
String content = defaultPrefixSection.getString("content", "&r");
ItemStack itemNotUsing = defaultPrefixSection.getItemStack(
"itemNotUsing",
new ItemStackFactory(Material.NAME_TAG)
.setDisplayName("&f默认前缀")
.addLore(" ")
.addLore("§a➥ 点击切换到该前缀")
.toItemStack()
);
ItemStack itemUsing = defaultPrefixSection.getItemStack("itemUsing",
new ItemStackFactory(Material.NAME_TAG)
.setDisplayName("&f默认前缀")
.addLore(" ")
.addLore("§a✔ 您正在使用该前缀")
.addEnchant(Enchantment.DURABILITY, 1, false)
.addFlag(ItemFlag.HIDE_ENCHANTS)
.toItemStack()
);
PrefixManager.defaultPrefix = new ConfiguredPrefix("default", name, content, 0, null, itemNotUsing, null, itemUsing);
} catch (Exception ex) {
Main.log("在加载默认前缀时出错,请检查配置!");
ex.printStackTrace();
}
} else {
PrefixManager.defaultPrefix = new ConfiguredPrefix("default", "默认前缀", "&r", 0, null,
new ItemStackFactory(Material.NAME_TAG)
.setDisplayName("&f默认前缀")
.addLore(" ")
.addLore("§a➥ 点击切换到该前缀")
.toItemStack(),
null,
new ItemStackFactory(Material.NAME_TAG)
.setDisplayName("&f默认前缀")
.addLore(" ")
.addLore("§a✔ 您正在使用该前缀")
.addEnchant(Enchantment.DURABILITY, 1, false)
.addFlag(ItemFlag.HIDE_ENCHANTS)
.toItemStack()
);
}
Main.log("完成默认前缀加载 " + defaultPrefix.getName()); public static void loadDefaultPrefix() {
} PrefixManager.defaultPrefix = null;
ConfigurationSection defaultPrefixSection = ConfigManager.getPluginConfig()
.getConfig().getConfigurationSection("defaultPrefix");
if (defaultPrefixSection != null) {
try {
String name = defaultPrefixSection.getString("name", "默认前缀");
String content = defaultPrefixSection.getString("content", "&r");
ItemStack itemNotUsing = defaultPrefixSection.getItemStack(
"itemNotUsing",
new ItemStackFactory(Material.NAME_TAG)
.setDisplayName("&f默认前缀")
.addLore(" ")
.addLore("§a➥ 点击切换到该前缀")
.toItemStack()
);
ItemStack itemUsing = defaultPrefixSection.getItemStack("itemUsing",
new ItemStackFactory(Material.NAME_TAG)
.setDisplayName("&f默认前缀")
.addLore(" ")
.addLore("§a✔ 您正在使用该前缀")
.addEnchant(Enchantment.DURABILITY, 1, false)
.addFlag(ItemFlag.HIDE_ENCHANTS)
.toItemStack()
);
PrefixManager.defaultPrefix = new ConfiguredPrefix("default", name, content, 0, null, itemNotUsing, null, itemUsing);
} catch (Exception ex) {
Main.error("在加载默认前缀时出错,请检查配置!");
Main.error("Error occurred when loading default prefix, please check the configuration.");
ex.printStackTrace();
}
} else {
PrefixManager.defaultPrefix = new ConfiguredPrefix("default", "默认前缀", "&r", 0, null,
new ItemStackFactory(Material.NAME_TAG)
.setDisplayName("&f默认前缀")
.addLore(" ")
.addLore("§a➥ 点击切换到该前缀")
.toItemStack(),
null,
new ItemStackFactory(Material.NAME_TAG)
.setDisplayName("&f默认前缀")
.addLore(" ")
.addLore("§a✔ 您正在使用该前缀")
.addEnchant(Enchantment.DURABILITY, 1, false)
.addFlag(ItemFlag.HIDE_ENCHANTS)
.toItemStack()
);
}
public static List<ConfiguredPrefix> getVisiblePrefix() { Main.log("完成默认前缀加载 " + defaultPrefix.getName());
return PrefixManager.getPrefixes().values().stream() Main.log("Successfully loaded default prefix " + defaultPrefix.getName());
.filter(ConfiguredPrefix::isVisibleNoPermission) }
.sorted(Comparator.comparingInt(ConfiguredPrefix::getWeight))
.collect(Collectors.toList());
}
@NotNull public static List<ConfiguredPrefix> getVisiblePrefix() {
public static ConfiguredPrefix getDefaultPrefix() { return PrefixManager.getPrefixes().values().stream()
return defaultPrefix; .filter(ConfiguredPrefix::isVisibleNoPermission)
} .sorted(Comparator.comparingInt(ConfiguredPrefix::getWeight))
.collect(Collectors.toList());
}
@NotNull @NotNull
public static HashMap<String, ConfiguredPrefix> getPrefixes() { public static ConfiguredPrefix getDefaultPrefix() {
return prefixes; return defaultPrefix;
} }
@Nullable @NotNull
public static ConfiguredPrefix getPrefix(String identifier) { public static HashMap<String, ConfiguredPrefix> getPrefixes() {
if (identifier == null) { return prefixes;
return null; }
} else if (identifier.equalsIgnoreCase("default")) {
return getDefaultPrefix(); @Nullable
} else { public static ConfiguredPrefix getPrefix(String identifier) {
return getPrefixes().get(identifier); if (identifier == null) {
} return null;
} } else if (identifier.equalsIgnoreCase("default")) {
return getDefaultPrefix();
} else {
return getPrefixes().get(identifier);
}
}
private static File getStorageFolder() {
if (PluginConfig.CustomStorage.ENABLE.get()) {
return new File(PluginConfig.CustomStorage.PATH.get());
} else {
return new File(Main.getInstance().getDataFolder() + File.separator + FOLDER_NAME);
}
}
} }
@@ -1,11 +1,12 @@
package cc.carm.plugin.userprefix.manager; package cc.carm.plugin.userprefix.manager;
import cc.carm.plugin.userprefix.Main; import cc.carm.plugin.userprefix.Main;
import cc.carm.plugin.userprefix.configuration.PrefixConfig; import cc.carm.plugin.userprefix.configuration.PluginConfig;
import cc.carm.plugin.userprefix.event.UserPrefixChangeEvent;
import cc.carm.plugin.userprefix.event.UserPrefixExpireEvent;
import cc.carm.plugin.userprefix.model.ConfiguredPrefix; import cc.carm.plugin.userprefix.model.ConfiguredPrefix;
import cc.carm.plugin.userprefix.nametag.UserNameTag; import cc.carm.plugin.userprefix.nametag.UserNameTag;
import cc.carm.plugin.userprefix.ui.PrefixSelectGUI; import cc.carm.plugin.userprefix.ui.PrefixSelectGUI;
import cc.carm.plugin.userprefix.util.MessageUtil;
import cc.carm.plugin.userprefix.util.gui.GUI; import cc.carm.plugin.userprefix.util.gui.GUI;
import net.luckperms.api.model.user.User; import net.luckperms.api.model.user.User;
import net.luckperms.api.node.NodeType; import net.luckperms.api.node.NodeType;
@@ -20,247 +21,270 @@ import java.util.stream.Collectors;
public class UserManager { public class UserManager {
public static HashMap<UUID, UserNameTag> nameTags = new HashMap<>(); public static HashMap<UUID, UserNameTag> nameTags = new HashMap<>();
public static HashSet<UUID> checkingPlayers = new HashSet<>(); public static HashSet<UUID> checkingPlayers = new HashSet<>();
@Nullable @Nullable
public static UserNameTag getNameTag(Player player) { public static UserNameTag getNameTag(Player player) {
if (PrefixConfig.Functions.NAME_PREFIX.get()) { if (PluginConfig.Functions.NAME_PREFIX.get()) {
if (nameTags.containsKey(player.getUniqueId())) { if (nameTags.containsKey(player.getUniqueId())) {
return nameTags.get(player.getUniqueId()); return nameTags.get(player.getUniqueId());
} else { } else {
return createNameTag(player); return createNameTag(player);
} }
} else { } else {
return null; return null;
} }
} }
@NotNull @NotNull
public static UserNameTag createNameTag(Player player) { public static UserNameTag createNameTag(Player player) {
if (nameTags.containsKey(player.getUniqueId())) return nameTags.get(player.getUniqueId()); if (nameTags.containsKey(player.getUniqueId())) return nameTags.get(player.getUniqueId());
UserNameTag nameTag = new UserNameTag(player); UserNameTag nameTag = new UserNameTag(player);
nameTags.put(player.getUniqueId(), nameTag); nameTags.put(player.getUniqueId(), nameTag);
return nameTag; return nameTag;
} }
public static void initPlayer(Player player) { public static void initPlayer(Player player) {
UserManager.checkPrefix(player, false); UserManager.checkPrefix(player, false);
if (PrefixConfig.Functions.NAME_PREFIX.get()) { if (PluginConfig.Functions.NAME_PREFIX.get()) {
UserManager.createNameTag(player); UserManager.createNameTag(player);
UserManager.updatePrefixView(player, true); UserManager.updatePrefixView(player, true);
} }
} }
public static void unloadPlayer(Player player) { public static void unloadPlayer(Player player) {
PrefixSelectGUI.removeOpening(player); PrefixSelectGUI.removeOpening(player);
UserManager.unloadNameTag(player.getUniqueId()); UserManager.unloadNameTag(player.getUniqueId());
UserManager.checkingPlayers.remove(player.getUniqueId()); UserManager.checkingPlayers.remove(player.getUniqueId());
GUI.removeOpenedGUI(player); // 清空打开过的GUI缓存 (用于记录物品点击的 GUI.removeOpenedGUI(player); // 清空打开过的GUI缓存 (用于记录物品点击的
} }
/** /**
* 更新前缀显示效果 * 更新前缀显示效果
* *
* @param player 玩家 * @param player 玩家
* @param loadOthers 是否为玩家更新其他人的前缀(一般用于加入游戏) * @param loadOthers 是否为玩家更新其他人的前缀(一般用于加入游戏)
*/ */
public static void updatePrefixView(Player player, boolean loadOthers) { public static void updatePrefixView(Player player, boolean loadOthers) {
if (!PrefixConfig.Functions.NAME_PREFIX.get()) return; //未启用的情况下,不需要进行任何操作。 if (!PluginConfig.Functions.NAME_PREFIX.get()) return; //未启用的情况下,不需要进行任何操作。
ConfiguredPrefix playerPrefix = UserManager.getPrefix(player); UserNameTag tag = getNameTag(player);
if (tag == null) return; //未启用的情况下,不需要进行任何操作。
UserNameTag tag = getNameTag(player); ConfiguredPrefix playerPrefix = UserManager.getPrefix(player);
tag.setPrefix(playerPrefix.getContent()); tag.setPrefix(playerPrefix.getContent());
tag.setOrder(playerPrefix.getWeight()); tag.setOrder(playerPrefix.getWeight());
Main.debug("为玩家 " + player.getName() + " 设置了 " + player.getName() + "的前缀为 #" + playerPrefix.getWeight() + " " + playerPrefix.getName()); Main.debug("为玩家 " + player.getName() + " 设置了 " + player.getName() + "的前缀为 #" + playerPrefix.getWeight() + " " + playerPrefix.getName());
for (Player onlinePlayer : Bukkit.getOnlinePlayers()) { for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
if (onlinePlayer.equals(player)) continue; if (onlinePlayer.equals(player)) continue;
UserNameTag onlinePlayerTag = getNameTag(onlinePlayer); UserNameTag onlinePlayerTag = getNameTag(onlinePlayer);
if (onlinePlayerTag != null) { if (onlinePlayerTag != null) {
onlinePlayerTag.setPrefix(player, playerPrefix.getContent()); onlinePlayerTag.setPrefix(player, playerPrefix.getContent());
onlinePlayerTag.setOrder(player, playerPrefix.getWeight()); onlinePlayerTag.setOrder(player, playerPrefix.getWeight());
Main.debug("为玩家 " + onlinePlayer.getName() + " 设置了 " + player.getName() + "的前缀为 #" + playerPrefix.getWeight() + " " + playerPrefix.getName()); Main.debug("为玩家 " + onlinePlayer.getName() + " 设置了 " + player.getName() + "的前缀为 #" + playerPrefix.getWeight() + " " + playerPrefix.getName());
} }
if (loadOthers) { if (loadOthers) {
ConfiguredPrefix onlinePlayerPrefix = UserManager.getPrefix(onlinePlayer); ConfiguredPrefix onlinePlayerPrefix = UserManager.getPrefix(onlinePlayer);
tag.setPrefix(onlinePlayer, onlinePlayerPrefix.getContent()); tag.setPrefix(onlinePlayer, onlinePlayerPrefix.getContent());
tag.setOrder(onlinePlayer, onlinePlayerPrefix.getWeight()); tag.setOrder(onlinePlayer, onlinePlayerPrefix.getWeight());
Main.debug("为玩家 " + player.getName() + " 设置了 " + onlinePlayer.getName() + "的前缀为 #" + onlinePlayerPrefix.getWeight() + " " + onlinePlayerPrefix.getName()); Main.debug("为玩家 " + player.getName() + " 设置了 " + onlinePlayer.getName() + "的前缀为 #" + onlinePlayerPrefix.getWeight() + " " + onlinePlayerPrefix.getName());
} }
} }
} }
/** /**
* 检查玩家的前缀的使用权 * 检查玩家的前缀的使用权
* *
* @param player 玩家 * @param player 玩家
* @param updateView 是否更新头顶与TabList中的前缀 * @param updateView 是否更新头顶与TabList中的前缀
*/ */
public static void checkPrefix(Player player, boolean updateView) { public static void checkPrefix(Player player, boolean updateView) {
if (checkingPlayers.contains(player.getUniqueId())) { if (checkingPlayers.contains(player.getUniqueId())) {
/* /*
* 这里为了避免极短时间内的重复触发导致多次判断且结果相同误导玩家, * 这里为了避免极短时间内的重复触发导致多次判断且结果相同误导玩家,
* 故没有采用同步锁,而是采用添加到一个临时Set中,对Set中玩家跳过判断。 * 故没有采用同步锁,而是采用添加到一个临时Set中,对Set中玩家跳过判断。
*/ */
return; return;
} }
checkingPlayers.add(player.getUniqueId()); checkingPlayers.add(player.getUniqueId());
String currentPrefixIdentifier = UserManager.getPrefixData(player); String currentPrefixData = UserManager.getPrefixData(player);
ConfiguredPrefix currentPrefix = PrefixManager.getPrefix(currentPrefixIdentifier);
if (!UserManager.isPrefixUsable(player, currentPrefixIdentifier)) {
ConfiguredPrefix newPrefix = UserManager.getHighestPrefix(player);
// 更新前缀
UserManager.setPrefix(player, newPrefix, updateView);
// 发送消息
MessageUtil.sendWithPlaceholders(player, PrefixConfig.Messages.EXPIRED.get(),
new String[]{"%(newName)", "%(oldName)"},
new Object[]{newPrefix.getName(), currentPrefix != null ? currentPrefix.getName() : currentPrefixIdentifier}
);
// 播放声音
PrefixConfig.Sounds.PREFIX_EXPIRED.play(player);
}
checkingPlayers.remove(player.getUniqueId());
}
public static void unloadNameTag(UUID uuid) { if (!UserManager.isPrefixUsable(player, currentPrefixData)) {
nameTags.remove(uuid); ConfiguredPrefix currentPrefix = PrefixManager.getPrefix(currentPrefixData);
} ConfiguredPrefix newPrefix = UserManager.getHighestPrefix(player);
/** if (currentPrefix != null) {
* 得到玩家的前缀。 //当前前缀不为空,则代表属于前缀过期的情况
* 该方法会自动判断玩家当前的前缀是否可用,并返回最终可用的前缀。 Bukkit.getPluginManager().callEvent(new UserPrefixExpireEvent(player, currentPrefix));
*
* @param player 玩家
* @return 前缀配置
*/
@NotNull
public static ConfiguredPrefix getPrefix(Player player) {
String identifier = getPrefixData(player);
if (identifier == null || !isPrefixUsable(player, identifier)) {
return getHighestPrefix(player);
} else {
ConfiguredPrefix prefix = PrefixManager.getPrefix(identifier);
return prefix == null ? PrefixManager.getDefaultPrefix() : prefix;
}
}
/** // 发送消息
* 设定玩家前缀 PluginConfig.Messages.EXPIRED.sendWithPlaceholders(player,
* new String[]{"%(newName)", "%(oldName)"},
* @param player 玩家 new Object[]{newPrefix.getName(), currentPrefix.getName()}
* @param prefix 前缀配置 );
* @param updateView 是否更新头顶上、TabList的前缀
*/
public static void setPrefix(Player player, ConfiguredPrefix prefix, boolean updateView) {
setPrefixData(player, prefix.getIdentifier());
if (updateView) updatePrefixView(player, false);
}
/** // 播放声音
* 得到玩家所有可用的前缀 PluginConfig.Sounds.PREFIX_EXPIRED.play(player);
* } else {
* @param player 玩家 // 当前前缀为空,则代表是旧的前缀不存在了,
* @return 可用前缀列表 PluginConfig.Messages.REMOVED.sendWithPlaceholders(player,
*/ new String[]{"%(newName)", "%(oldName)"},
@NotNull new Object[]{newPrefix.getName(), currentPrefixData}
public static List<ConfiguredPrefix> getUsablePrefixes(Player player) { );
return PrefixManager.getPrefixes().values().stream() }
.filter(configuredPrefix -> isPrefixUsable(player, configuredPrefix)) //过滤出玩家可用的前缀
.sorted(Comparator.comparingInt(ConfiguredPrefix::getWeight)) // 以前缀排序 UserPrefixChangeEvent event = new UserPrefixChangeEvent(player, currentPrefix, newPrefix);
.collect(Collectors.toList()); // 返回集合 Bukkit.getPluginManager().callEvent(event);
}
if (!event.isCancelled()) {
// 更新前缀
UserManager.setPrefix(player, event.getAfter(), updateView);
}
}
checkingPlayers.remove(player.getUniqueId());
}
public static void unloadNameTag(UUID uuid) {
nameTags.remove(uuid);
}
/**
* 得到玩家的前缀。
* 该方法会自动判断玩家当前的前缀是否可用,并返回最终可用的前缀。
*
* @param player 玩家
* @return 前缀配置
*/
@NotNull
public static ConfiguredPrefix getPrefix(Player player) {
String identifier = getPrefixData(player);
if (identifier == null || !isPrefixUsable(player, identifier)) {
return getHighestPrefix(player);
} else {
ConfiguredPrefix prefix = PrefixManager.getPrefix(identifier);
return prefix == null ? PrefixManager.getDefaultPrefix() : prefix;
}
}
/**
* 设定玩家前缀
*
* @param player 玩家
* @param prefix 前缀配置
* @param updateView 是否更新头顶上、TabList的前缀
*/
public static void setPrefix(Player player, ConfiguredPrefix prefix, boolean updateView) {
setPrefixData(player, prefix.getIdentifier());
if (updateView) updatePrefixView(player, false);
}
/**
* 得到玩家所有可用的前缀
*
* @param player 玩家
* @return 可用前缀列表
*/
@NotNull
public static List<ConfiguredPrefix> getUsablePrefixes(Player player) {
return PrefixManager.getPrefixes().values().stream()
.filter(configuredPrefix -> isPrefixUsable(player, configuredPrefix)) //过滤出玩家可用的前缀
.sorted(Comparator.comparingInt(ConfiguredPrefix::getWeight)) // 以前缀排序
.collect(Collectors.toList()); // 返回集合
}
/** /**
* 得到玩家可使用的最高权重的权限 * 得到玩家可使用的最高权重的权限
* 注意:若配置文件中关闭了 “autoUsePrefix” ,则会返回默认前缀。 * 注意:若配置文件中关闭了 “autoUsePrefix” ,则会返回默认前缀。
* *
* @param player 玩家 * @param player 玩家
* @return 权限内容 * @return 权限内容
*/ */
@NotNull @NotNull
public static ConfiguredPrefix getHighestPrefix(Player player) { public static ConfiguredPrefix getHighestPrefix(Player player) {
if (PrefixConfig.Functions.AUTO_USE.get()) { if (PluginConfig.Functions.AUTO_USE.get()) {
// 关闭了自动选择,就直接给默认的前缀,让玩家自己去设置吧~ // 关闭了自动选择,就直接给默认的前缀,让玩家自己去设置吧~
return PrefixManager.getDefaultPrefix(); return PrefixManager.getDefaultPrefix();
} }
return getUsablePrefixes(player).stream() return getUsablePrefixes(player).stream()
.max(Comparator.comparingInt(ConfiguredPrefix::getWeight)) // 取权重最大 .max(Comparator.comparingInt(ConfiguredPrefix::getWeight)) // 取权重最大
.orElseGet(PrefixManager::getDefaultPrefix); // 啥都没有? 返回默认前缀。 .orElseGet(PrefixManager::getDefaultPrefix); // 啥都没有? 返回默认前缀。
} }
/** /**
* 判断一个前缀对某玩家是否可用 * 判断一个前缀对某玩家是否可用
* *
* @param player 玩家 * @param player 玩家
* @param prefixIdentifier 前缀标识 * @param prefixIdentifier 前缀标识
* @return 若前缀标识不存在,则返回false;若前缀为默认前缀,或该前缀无权限,或玩家有该前缀的权限,则返回true。 * @return 若前缀标识不存在,则返回false;若前缀为默认前缀,或该前缀无权限,或玩家有该前缀的权限,则返回true。
*/ */
public static boolean isPrefixUsable(Player player, String prefixIdentifier) { public static boolean isPrefixUsable(Player player, String prefixIdentifier) {
if (prefixIdentifier == null || prefixIdentifier.equalsIgnoreCase("default")) return true; if (prefixIdentifier == null || prefixIdentifier.equalsIgnoreCase("default")) return true;
ConfiguredPrefix prefix = PrefixManager.getPrefix(prefixIdentifier); ConfiguredPrefix prefix = PrefixManager.getPrefix(prefixIdentifier);
if (prefix == null) return false; if (prefix == null) return false;
return isPrefixUsable(player, prefix); return isPrefixUsable(player, prefix);
} }
/** /**
* 判断一个前缀对某玩家是否可用 * 判断一个前缀对某玩家是否可用
* *
* @param player 玩家 * @param player 玩家
* @param configuredPrefix 前缀配置 * @param configuredPrefix 前缀配置
* @return 若前缀标识不存在,则返回false;若前缀为默认前缀,或该前缀无权限,或玩家有该前缀的权限,则返回true。 * @return 若前缀标识不存在,则返回false;若前缀为默认前缀,或该前缀无权限,或玩家有该前缀的权限,则返回true。
*/ */
public static boolean isPrefixUsable(Player player, ConfiguredPrefix configuredPrefix) { public static boolean isPrefixUsable(Player player, ConfiguredPrefix configuredPrefix) {
return configuredPrefix.isPublic() return configuredPrefix.isPublic()
|| ServiceManager.hasPermission(ServiceManager.getUser(player), configuredPrefix.getPermission()); || ServiceManager.hasPermission(ServiceManager.getUser(player), configuredPrefix.getPermission());
} }
/** /**
* 得到用户当前正在使用的前缀Identifier。 * 得到用户当前正在使用的前缀Identifier。
* 该方法通过LuckPerms的MetaData实现,因此可以通过指令去操作。 * 该方法通过LuckPerms的MetaData实现,因此可以通过指令去操作。
* *
* @param player 玩家 * @param player 玩家
* @return 正在使用的前缀Identifier(若不存在则返回null) * @return 正在使用的前缀Identifier(若不存在则返回null, 代表未设置前缀)
*/ */
@Nullable @Nullable
public static String getPrefixData(Player player) { public static String getPrefixData(Player player) {
return ServiceManager.getAPI().getMetaData(player) return ServiceManager.getAPI().getMetaData(player)
.getMetaValue("userprefix", String::valueOf) .getMetaValue("userprefix", String::valueOf)
.orElse(null); .orElse(null);
} }
/** /**
* 设定用户所使用的的prefix。 * 设定用户所使用的的prefix。
* 该方法通过LuckPerms的MetaData实现,因此可以通过指令去操作。 * 该方法通过LuckPerms的MetaData实现,因此可以通过指令去操作。
* *
* @param player 玩家 * @param player 玩家
* @param prefixIdentifier 前缀的标识 * @param prefixIdentifier 前缀的标识
*/ */
public static void setPrefixData(Player player, String prefixIdentifier) { public static void setPrefixData(Player player, String prefixIdentifier) {
User user = ServiceManager.getUser(player); User user = ServiceManager.getUser(player);
clearPrefixData(player); // 清除掉旧的数据,LuckPerms不会去覆盖一个Meta,需要手动清除。 clearPrefixData(player); // 清除掉旧的数据,LuckPerms不会去覆盖一个Meta,需要手动清除。
if (prefixIdentifier != null) { if (prefixIdentifier != null) {
user.data().add(MetaNode.builder("userprefix", prefixIdentifier).build()); user.data().add(MetaNode.builder("userprefix", prefixIdentifier).build());
ServiceManager.getService().getUserManager().saveUser(user); // 保存数据 ServiceManager.getService().getUserManager().saveUser(user); // 保存数据
} }
} }
/** /**
* 清除玩家所选择的前缀数据 * 清除玩家所选择的前缀数据
* *
* @param player 玩家 * @param player 玩家
*/ */
public static void clearPrefixData(Player player) { public static void clearPrefixData(Player player) {
User user = ServiceManager.getUser(player); User user = ServiceManager.getUser(player);
// LuckPerms竟然会把所有的metaKey全部转换为小写... 那我这里就直接写成小写吧~ // LuckPerms竟然会把所有的metaKey全部转换为小写... 那我这里就直接写成小写吧~
user.data().clear(NodeType.META.predicate(mn -> mn.getMetaKey().equals("userprefix"))); user.data().clear(NodeType.META.predicate(mn -> mn.getMetaKey().equals("userprefix")));
} }
} }
@@ -2,122 +2,158 @@ package cc.carm.plugin.userprefix.model;
import cc.carm.plugin.userprefix.util.ColorParser; import cc.carm.plugin.userprefix.util.ColorParser;
import cc.carm.plugin.userprefix.util.ItemStackFactory; import cc.carm.plugin.userprefix.util.ItemStackFactory;
import cc.carm.plugin.userprefix.util.MessageUtil;
import org.bukkit.Material; import org.bukkit.Material;
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.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.io.File; import java.io.File;
import java.util.List;
public class ConfiguredPrefix { public class ConfiguredPrefix {
@Nullable @Nullable
private File dataFile; private File dataFile;
@Nullable @Nullable
private FileConfiguration configuration; private FileConfiguration configuration;
String identifier; String identifier;
String name; String name;
String content; String content;
int weight; int weight;
String permission; String permission;
ItemStack itemHasPermission; ItemStack itemHasPermission;
ItemStack itemNoPermission; ItemStack itemNoPermission;
ItemStack itemWhenUsing; ItemStack itemWhenUsing;
public ConfiguredPrefix(@NotNull File dataFile) { public ConfiguredPrefix(@NotNull File dataFile) {
this.dataFile = dataFile; this.dataFile = dataFile;
this.configuration = YamlConfiguration.loadConfiguration(dataFile); this.configuration = YamlConfiguration.loadConfiguration(dataFile);
if (getConfiguration() != null) { if (getConfiguration() != null) {
this.identifier = getConfiguration().getString("identifier", "ERROR"); this.identifier = getConfiguration().getString("identifier", "ERROR");
this.name = getConfiguration().getString("name", "ERROR"); this.name = getConfiguration().getString("name", "ERROR");
this.content = getConfiguration().getString("content", "&r"); this.content = getConfiguration().getString("content", "&r");
this.permission = getConfiguration().getString("permission"); this.permission = getConfiguration().getString("permission");
this.weight = getConfiguration().getInt("weight", 1); this.weight = getConfiguration().getInt("weight", 1);
this.itemHasPermission = (ItemStack) getConfiguration().get("itemHasPermission", this.itemHasPermission = (ItemStack) getConfiguration().get("itemHasPermission",
new ItemStackFactory(Material.STONE).setDisplayName(name).addLore(" ").addLore("§a➥ 点击切换到该前缀").toItemStack() new ItemStackFactory(Material.STONE).setDisplayName(name).addLore(" ").addLore("§a➥ 点击切换到该前缀").toItemStack()
); );
this.itemNoPermission = (ItemStack) getConfiguration().get("itemNoPermission", itemHasPermission); this.itemNoPermission = (ItemStack) getConfiguration().get("itemNoPermission", itemHasPermission);
this.itemWhenUsing = (ItemStack) getConfiguration().get("itemUsing", itemHasPermission); this.itemWhenUsing = (ItemStack) getConfiguration().get("itemUsing", itemHasPermission);
} }
} }
public ConfiguredPrefix(@NotNull String identifier, public ConfiguredPrefix(@NotNull String identifier,
@NotNull String name, @NotNull String name,
@NotNull String content, @NotNull String content,
int weight, @Nullable String permission, int weight, @Nullable String permission,
@NotNull ItemStack itemHasPermission, @NotNull ItemStack itemHasPermission,
@Nullable ItemStack itemNoPermission, @Nullable ItemStack itemNoPermission,
@Nullable ItemStack itemWhenUsing) { @Nullable ItemStack itemWhenUsing) {
this.identifier = identifier; this.identifier = identifier;
this.name = name; this.name = name;
this.content = content; this.content = content;
this.weight = weight; this.weight = weight;
this.permission = permission; this.permission = permission;
this.itemHasPermission = itemHasPermission; this.itemHasPermission = itemHasPermission;
this.itemNoPermission = itemNoPermission; this.itemNoPermission = itemNoPermission;
this.itemWhenUsing = itemWhenUsing; this.itemWhenUsing = itemWhenUsing;
} }
@Nullable @Nullable
public FileConfiguration getConfiguration() { public FileConfiguration getConfiguration() {
return configuration; return configuration;
} }
@NotNull @NotNull
public String getIdentifier() { public String getIdentifier() {
return identifier; return identifier;
} }
@NotNull @NotNull
public String getName() { public String getName() {
return name; return name;
} }
@NotNull @NotNull
public String getContent() { public String getContent() {
return ColorParser.parse(content); return ColorParser.parse(content);
} }
public int getWeight() { public int getWeight() {
return weight; return weight;
} }
@Nullable @Nullable
public String getPermission() { public String getPermission() {
return permission; return permission;
} }
@NotNull @NotNull
public ItemStack getItemHasPermission() { public ItemStack getItemHasPermission(@Nullable Player player) {
return itemHasPermission; return parseItemStackText(this.itemHasPermission, player);
} }
@Nullable @NotNull
public ItemStack getItemNoPermission() { public ItemStack getItemHasPermission() {
return itemNoPermission; return getItemHasPermission(null);
} }
@Nullable @Nullable
public ItemStack getItemWhenUsing() { public ItemStack getItemNoPermission(@Nullable Player player) {
return itemWhenUsing; return parseItemStackText(itemNoPermission, player);
} }
public boolean isPublic() { @Nullable
return getPermission() == null; public ItemStack getItemNoPermission() {
} return getItemNoPermission(null);
}
public boolean isVisibleNoPermission() { @Nullable
return this.itemNoPermission != null; public ItemStack getItemWhenUsing(@Nullable Player player) {
} return parseItemStackText(itemWhenUsing, player);
}
@Nullable
public ItemStack getItemWhenUsing() {
return getItemWhenUsing(null);
}
public boolean isPublic() {
return getPermission() == null;
}
public boolean isVisibleNoPermission() {
return this.itemNoPermission != null;
}
@NotNull
private static ItemStack parseItemStackText(@NotNull ItemStack source, @Nullable Player player) {
if (player == null) return source;
ItemMeta meta = source.getItemMeta();
String displayName = null;
List<String> lore = null;
if (meta != null) {
if (meta.hasDisplayName()) displayName = meta.getDisplayName();
if (meta.hasLore()) lore = meta.getLore();
}
ItemStackFactory factory = new ItemStackFactory(source);
if (displayName != null) factory.setDisplayName(MessageUtil.setPlaceholders(player, displayName));
if (lore != null) factory.setLore(MessageUtil.setPlaceholders(player, lore));
return factory.toItemStack();
}
} }
@@ -1,6 +1,6 @@
package cc.carm.plugin.userprefix.ui; package cc.carm.plugin.userprefix.ui;
import cc.carm.plugin.userprefix.configuration.PrefixConfig; import cc.carm.plugin.userprefix.configuration.PluginConfig;
import cc.carm.plugin.userprefix.manager.PrefixManager; import cc.carm.plugin.userprefix.manager.PrefixManager;
import cc.carm.plugin.userprefix.manager.UserManager; import cc.carm.plugin.userprefix.manager.UserManager;
import cc.carm.plugin.userprefix.model.ConfiguredPrefix; import cc.carm.plugin.userprefix.model.ConfiguredPrefix;
@@ -17,80 +17,81 @@ import java.util.List;
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; Player player;
public PrefixSelectGUI(Player player) { public PrefixSelectGUI(Player player) {
super(GUIType.SIXBYNINE, PrefixConfig.GUI.TITLE.get(), 10, 43); super(GUIType.SIXBYNINE, PluginConfig.GUI.TITLE.get(), 10, 43);
this.player = player; this.player = player;
setPreviousPageSlot(18); setPreviousPageSlot(18);
setNextPageSlot(26); setNextPageSlot(26);
loadItems(); loadItems();
} }
public Player getPlayer() { public Player getPlayer() {
return player; return player;
} }
public void loadItems() { public void loadItems() {
List<ConfiguredPrefix> prefixList = new ArrayList<>(); List<ConfiguredPrefix> prefixList = new ArrayList<>();
prefixList.add(PrefixManager.getDefaultPrefix()); prefixList.add(PrefixManager.getDefaultPrefix());
prefixList.addAll(PrefixManager.getVisiblePrefix()); //只需要读取看得见的 prefixList.addAll(PrefixManager.getVisiblePrefix()); //只需要读取看得见的
ConfiguredPrefix usingPrefix = UserManager.getPrefix(getPlayer()); ConfiguredPrefix usingPrefix = UserManager.getPrefix(getPlayer());
for (ConfiguredPrefix prefix : prefixList) { for (ConfiguredPrefix prefix : prefixList) {
if (prefix.getIdentifier().equals(usingPrefix.getIdentifier())) { if (prefix.getIdentifier().equals(usingPrefix.getIdentifier())) {
addItem(new GUIItem(prefix.getItemWhenUsing() != null ? prefix.getItemWhenUsing() : prefix.getItemHasPermission())); addItem(new GUIItem(prefix.getItemWhenUsing(player) != null ? prefix.getItemWhenUsing(player) : prefix.getItemHasPermission(player)));
} else if (UserManager.isPrefixUsable(player, prefix)) { } else if (UserManager.isPrefixUsable(player, prefix)) {
addItem(new GUIItem(prefix.getItemHasPermission()) { addItem(new GUIItem(prefix.getItemHasPermission(player)) {
@Override @Override
public void onClick(ClickType type) { public void onClick(ClickType type) {
//再次检查,防止打开GUI后、选择前的时间段内权限消失 //再次检查,防止打开GUI后、选择前的时间段内权限消失
if (UserManager.isPrefixUsable(player, prefix)) { if (UserManager.isPrefixUsable(player, prefix)) {
player.closeInventory(); player.closeInventory();
UserManager.setPrefix(player, prefix, true); UserManager.setPrefix(player, prefix, true);
PrefixConfig.Sounds.PREFIX_CHANGE.play(player); PluginConfig.Sounds.PREFIX_CHANGE.play(player);
MessageUtil.sendWithPlaceholders(player, PrefixConfig.Messages.SELECTED.get(), MessageUtil.sendWithPlaceholders(player, PluginConfig.Messages.SELECTED.get(),
new String[]{"%(name)"}, new String[]{"%(name)"},
new Object[]{prefix.getName()}); new Object[]{prefix.getName()});
} }
} }
}); });
} else { } else {
addItem(new GUIItem(prefix.getItemNoPermission())); addItem(new GUIItem(prefix.getItemNoPermission(player)));
} }
} }
} }
@Override @Override
public void onClose() { public void onClose() {
removeOpening(player); removeOpening(player);
} }
public static void removeOpening(Player player) { public static void removeOpening(Player player) {
openingUsers.remove(player); openingUsers.remove(player);
} }
public static void closeAll() { public static void closeAll() {
for (Player player : new HashSet<>(openingUsers)) { for (Player player : new HashSet<>(openingUsers)) {
player.closeInventory(); player.closeInventory();
} }
openingUsers.clear(); openingUsers.clear();
} }
public static void open(Player player) { public static void open(Player player) {
PrefixConfig.Sounds.GUI_OPEN.play(player); player.closeInventory(); // 防止冲突
new PrefixSelectGUI(player).openGUI(player); PluginConfig.Sounds.GUI_OPEN.play(player);
openingUsers.add(player); new PrefixSelectGUI(player).openGUI(player);
} openingUsers.add(player);
}
} }
@@ -4,71 +4,99 @@ import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
public class MessageUtil { public class MessageUtil {
public static boolean hasPlaceholderAPI() { public static boolean hasPlaceholderAPI() {
return Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null; return Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null;
} }
public static void send(CommandSender sender, List<String> messages) { public static void send(@Nullable CommandSender sender, List<String> messages) {
for (String s : messages) { if (messages == null || messages.isEmpty() || sender == null) return;
sender.sendMessage(ColorParser.parse(s)); for (String s : messages) {
} sender.sendMessage(ColorParser.parse(s));
} }
}
public static void send(CommandSender sender, String... messages) { public static void send(@Nullable CommandSender sender, String... messages) {
send(sender, Arrays.asList(messages)); send(sender, Arrays.asList(messages));
} }
public static void sendWithPlaceholders(CommandSender sender, String... messages) { public static void sendWithPlaceholders(CommandSender sender, String... messages) {
sendWithPlaceholders(sender, Arrays.asList(messages)); sendWithPlaceholders(sender, Arrays.asList(messages));
} }
public static void sendWithPlaceholders(CommandSender sender, List<String> messages) { public static void sendWithPlaceholders(@Nullable CommandSender sender, List<String> messages) {
if (messages == null || messages.isEmpty()) return; if (messages == null || messages.isEmpty() || sender == null) return;
if (hasPlaceholderAPI() && sender instanceof Player) { send(sender, setPlaceholders(sender, messages));
send(sender, PlaceholderAPI.setPlaceholders((Player) sender, messages)); }
} else {
send(sender, messages);
}
}
public static void sendWithPlaceholders(CommandSender sender, List<String> messages, String param, Object value) { public static void sendWithPlaceholders(@Nullable CommandSender sender, List<String> messages, String param, Object value) {
sendWithPlaceholders(sender, messages, new String[]{param}, new Object[]{value}); sendWithPlaceholders(sender, messages, new String[]{param}, new Object[]{value});
} }
public static void sendWithPlaceholders(CommandSender sender, List<String> messages, String[] params, Object[] values) { public static void sendWithPlaceholders(@Nullable CommandSender sender, List<String> messages, String[] params, Object[] values) {
sendWithPlaceholders(sender, setCustomParams(messages, params, values)); sendWithPlaceholders(sender, setCustomParams(messages, params, values));
} }
public static List<String> setCustomParams(List<String> messages, String param, Object value) { public static String setPlaceholders(@Nullable CommandSender sender, String message) {
return setCustomParams(messages, new String[]{param}, new Object[]{value}); if (message == null) return null;
}
public static List<String> setCustomParams(List<String> messages, String[] params, Object[] values) { message = ColorParser.parse(message);
if (params.length != values.length) return messages; if (sender == null) return message;
HashMap<String, Object> paramsMap = new HashMap<>();
for (int i = 0; i < params.length; i++) { if (hasPlaceholderAPI() && sender instanceof Player) {
paramsMap.put(params[i], values[i]); return PlaceholderAPI.setPlaceholders((Player) sender, message);
} } else {
return setCustomParams(messages, paramsMap); return message;
} }
}
public static List<String> setPlaceholders(@Nullable CommandSender sender, List<String> messages) {
if (messages == null || messages.isEmpty()) return new ArrayList<>();
messages = messages.stream().map(ColorParser::parse).collect(Collectors.toList());
if (sender == null) return messages;
if (hasPlaceholderAPI() && sender instanceof Player) {
return PlaceholderAPI.setPlaceholders((Player) sender, messages);
} else {
return messages;
}
}
public static List<String> setPlaceholders(@Nullable CommandSender sender, List<String> messages, String[] params, Object[] values) {
return setPlaceholders(sender, setCustomParams(messages, params, values));
}
public static List<String> setCustomParams(List<String> messages, String param, Object value) {
return setCustomParams(messages, new String[]{param}, new Object[]{value});
}
public static List<String> setCustomParams(List<String> messages, String[] params, Object[] values) {
if (params.length != values.length) return messages;
HashMap<String, Object> paramsMap = new HashMap<>();
for (int i = 0; i < params.length; i++) {
paramsMap.put(params[i], values[i]);
}
return setCustomParams(messages, paramsMap);
}
public static List<String> setCustomParams(List<String> messages, HashMap<String, Object> params) { public static List<String> setCustomParams(List<String> messages, HashMap<String, Object> params) {
List<String> list = new ArrayList<>(); List<String> list = new ArrayList<>();
for (String message : messages) { for (String message : messages) {
String afterMessage = message; String afterMessage = message;
for (Map.Entry<String, Object> entry : params.entrySet()) { for (Map.Entry<String, Object> entry : params.entrySet()) {
afterMessage = afterMessage.replace(entry.getKey(), entry.getValue().toString()); afterMessage = afterMessage.replace(entry.getKey(), entry.getValue().toString());
} }
list.add(afterMessage); list.add(afterMessage);
} }
return list; return list;
} }
} }
@@ -1,87 +1,93 @@
package cc.carm.plugin.userprefix.util.gui; package cc.carm.plugin.userprefix.util.gui;
import cc.carm.plugin.userprefix.configuration.PrefixConfig; import cc.carm.plugin.userprefix.configuration.PluginConfig;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
public class AutoPagedGUI extends CommonPagedGUI { public class AutoPagedGUI extends CommonPagedGUI {
ItemStack previousPageUI; ItemStack previousPageUI;
ItemStack nextPageUI; ItemStack nextPageUI;
ItemStack noPreviousPageUI; ItemStack noPreviousPageUI;
ItemStack noNextPageUI; ItemStack noNextPageUI;
int previousPageSlot = -1; int previousPageSlot = -1;
int nextPageSlot = -1; int nextPageSlot = -1;
public AutoPagedGUI(GUIType type, String name, int[] range) { public AutoPagedGUI(GUIType type, String name, int[] range) {
super(type, name, range); super(type, name, range);
} }
public AutoPagedGUI(GUIType type, String name, int a, int b) { public AutoPagedGUI(GUIType type, String name, int a, int b) {
super(type, name, a, b); super(type, name, a, b);
} }
public void setPreviousPageUI(ItemStack lastPageUI) { public void setPreviousPageUI(ItemStack lastPageUI) {
this.previousPageUI = lastPageUI; this.previousPageUI = lastPageUI;
} }
public void setNextPageUI(ItemStack nextPageUI) { public void setNextPageUI(ItemStack nextPageUI) {
this.nextPageUI = nextPageUI; this.nextPageUI = nextPageUI;
} }
public void setNoPreviousPageUI(ItemStack noPreviousPageUI) { public void setNoPreviousPageUI(ItemStack noPreviousPageUI) {
this.noPreviousPageUI = noPreviousPageUI; this.noPreviousPageUI = noPreviousPageUI;
} }
public void setNoNextPageUI(ItemStack noNextPageUI) { public void setNoNextPageUI(ItemStack noNextPageUI) {
this.noNextPageUI = noNextPageUI; this.noNextPageUI = noNextPageUI;
} }
public void setPreviousPageSlot(int slot) { public void setPreviousPageSlot(int slot) {
this.previousPageSlot = slot; this.previousPageSlot = slot;
} }
public void setNextPageSlot(int slot) { public void setNextPageSlot(int slot) {
this.nextPageSlot = slot; this.nextPageSlot = slot;
} }
@Override @Override
public void openGUI(Player user) { public void openGUI(Player user) {
if (previousPageSlot >= 0) if (previousPageSlot >= 0) {
if (hasPreviousPage()) { if (hasPreviousPage()) {
setItem(previousPageSlot, new GUIItem(previousPageUI == null ? PrefixConfig.GUI.Items.PREVIOUS_PAGE.get() : previousPageUI) { setItem(previousPageSlot, new GUIItem(previousPageUI == null ? PluginConfig.GUI.Items.PREVIOUS_PAGE.get() : previousPageUI) {
@Override @Override
public void onClick(ClickType type) { public void onClick(ClickType type) {
if (type == ClickType.RIGHT) { if (type == ClickType.RIGHT) {
goFirstPage(); goFirstPage();
} else { } else {
goPreviousPage(); goPreviousPage();
} }
PrefixConfig.Sounds.GUI_CLICK.play(user); PluginConfig.Sounds.GUI_CLICK.play(user);
openGUI(user); openGUI(user);
} }
}); });
} } else {
setItem(previousPageSlot, null);
}
}
if (nextPageSlot >= 0) if (nextPageSlot >= 0) {
if (hasNextPage()) { if (hasNextPage()) {
setItem(nextPageSlot, new GUIItem(nextPageUI == null ? PrefixConfig.GUI.Items.NEXT_PAGE.get() : nextPageUI) { setItem(nextPageSlot, new GUIItem(nextPageUI == null ? PluginConfig.GUI.Items.NEXT_PAGE.get() : nextPageUI) {
@Override @Override
public void onClick(ClickType type) { public void onClick(ClickType type) {
if (type == ClickType.RIGHT) { if (type == ClickType.RIGHT) {
goLastPage(); goLastPage();
} else { } else {
goNextPage(); goNextPage();
} }
PrefixConfig.Sounds.GUI_CLICK.play(user); PluginConfig.Sounds.GUI_CLICK.play(user);
openGUI(user); openGUI(user);
} }
}); });
} } else {
setItem(nextPageSlot, null);
}
}
super.openGUI(user); super.openGUI(user);
} }
} }
+22 -9
View File
@@ -1,7 +1,20 @@
version: ${project.version} version: ${project.version} #配置文件版本,若与插件版本不同请记得检查配置文件内容
debug: false debug: false
# 统计数据设定
# 改选项用于帮助开发者统计插件版本与使用情况,且绝不会影响性能与使用体验。
# 当然,您也可以选择在这里关闭,或在plugins/bStats下的配置文件中关闭。
metrics: true
custom-storage:
# 自定义存储位置
# 默认存储位置为 “插件文件夹”/prefixes
# 可以规定到远程文件夹中去寻找前缀相关的设定
# 支持绝对文件路径,如 "/etc/minecraft/configurations/prefixes/"
enable: false # 是否启用
path: "prefixes/" # 一定要指向一个文件夹!
functions: functions:
OnNamePrefix: true # 是否给头顶上添加前缀,该方法用到了头顶的那个计分板,如有冲突请关掉哦~ OnNamePrefix: true # 是否给头顶上添加前缀,该方法用到了头顶的那个计分板,如有冲突请关掉哦~
autoUsePrefix: true # 自动前缀显示 当玩家没有自己选择一个前缀的时候,会自动使用所拥有的的前缀中权重最高的那一个 autoUsePrefix: true # 自动前缀显示 当玩家没有自己选择一个前缀的时候,会自动使用所拥有的的前缀中权重最高的那一个
@@ -24,20 +37,20 @@ GUI:
meta: meta:
==: ItemMeta ==: ItemMeta
meta-type: UNSPECIFIC meta-type: UNSPECIFIC
display-name: "§f下一页" display-name: "&f下一页"
lore: lore:
- "" - ""
- "§f右键可前往最后一页哦~" - "&f右键可前往最后一页哦~"
previous-page: # 上一页物品,如果没有上一页则不显示 previous-page: # 上一页物品,如果没有上一页则不显示
==: org.bukkit.inventory.ItemStack ==: org.bukkit.inventory.ItemStack
type: ARROW type: ARROW
meta: meta:
==: ItemMeta ==: ItemMeta
meta-type: UNSPECIFIC meta-type: UNSPECIFIC
display-name: "§f上一页" display-name: "&f上一页"
lore: lore:
- "" - ""
- "§f右键可前往第一页哦~" - "&f右键可前往第一页哦~"
Sounds: #相关的声音,注释掉则不播放声音 格式为 【声音名:音量:音调】 或 【声音名:音量】 或 【声音名】 Sounds: #相关的声音,注释掉则不播放声音 格式为 【声音名:音量:音调】 或 【声音名:音量】 或 【声音名】
openGUI: "BLOCK_NOTE_BLOCK_PLING:1:1" openGUI: "BLOCK_NOTE_BLOCK_PLING:1:1"
@@ -56,17 +69,17 @@ defaultPrefix:
meta: meta:
==: ItemMeta ==: ItemMeta
meta-type: UNSPECIFIC meta-type: UNSPECIFIC
display-name: "§f默认玩家前缀 §f(点击切换)" display-name: "&f默认玩家前缀 &f(点击切换)"
lore: lore:
- "" - ""
- "§a➥ 点击切换到该前缀" - "&a➥ 点击切换到该前缀"
itemUsing: itemUsing:
==: org.bukkit.inventory.ItemStack ==: org.bukkit.inventory.ItemStack
type: NAME_TAG type: NAME_TAG
meta: meta:
==: ItemMeta ==: ItemMeta
meta-type: UNSPECIFIC meta-type: UNSPECIFIC
display-name: "§f默认玩家前缀" display-name: "&f默认玩家前缀"
lore: lore:
- "" - ""
- "§a✔ 您正在使用该前缀" - "&a✔ 您正在使用该前缀"
+9
View File
@@ -2,6 +2,15 @@ version: ${project.version} # DO NOT EDIT IT
debug: false #DEBUG OUT PUT debug: false #DEBUG OUT PUT
metrics: true #Metrics stats (to help developer know the stats)
custom-storage:
# Custom storage location
# default location is "./prefixes"
# Support absolute file path , such as "/etc/minecraft/configurations/prefixes/"
enable: false
path: "prefixes/" # Must be a folder!
GUI: GUI:
title: "&f&lMy Prefixes List" # Title of the GUI title: "&f&lMy Prefixes List" # Title of the GUI
items: items:
+26 -29
View File
@@ -9,7 +9,7 @@ name: "&b&lPro&b"
# Content [Necessary] # Content [Necessary]
# Use in Placeholders # Use in Placeholders
content: "§b§lPro §b" content: "&b&lPro &b"
# Weight [Necessary] # Weight [Necessary]
# used for sorting in the GUI and TabList # used for sorting in the GUI and TabList
@@ -29,43 +29,40 @@ itemHasPermission:
==: org.bukkit.inventory.ItemStack ==: org.bukkit.inventory.ItemStack
type: DIAMOND type: DIAMOND
meta: meta:
==: org.bukkit.inventory.ItemStack ==: ItemMeta
type: DIAMOND meta-type: UNSPECIFIC
meta: display-name: "&b&lVIP Prefix"
==: ItemMeta lore:
meta-type: UNSPECIFIC - ""
display-name: "§b§lVIP Prefix" - "&a➥ Click to use"
lore:
- ""
- "§a➥ Click to use"
# itemUsing [Unnecessary] # itemUsing [Unnecessary]
# 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".
itemUsing: itemUsing:
==: org.bukkit.inventory.ItemStack ==: org.bukkit.inventory.ItemStack
type: DIAMOND type: DIAMOND
meta: meta:
==: ItemMeta ==: ItemMeta
meta-type: UNSPECIFIC meta-type: UNSPECIFIC
display-name: "§b§lVIP Prefix" display-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
lore: lore:
- "" - ""
- "§a✔ Selected" - "&a✔ Selected"
# itemNoPermission [Unnecessary] # itemNoPermission [Unnecessary]
# 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.
itemNoPermission: itemNoPermission:
==: org.bukkit.inventory.ItemStack ==: org.bukkit.inventory.ItemStack
type: INK_SACK type: INK_SACK
damage: 8 damage: 8
meta: meta:
==: ItemMeta ==: ItemMeta
meta-type: UNSPECIFIC meta-type: UNSPECIFIC
display-name: "§b§lVIP §c(Buy it!)" display-name: "&b&lVIP &c(Buy it!)"
lore: lore:
- "" - ""
- "§e✯ Buy the VIP to use it!" - "&e✯ Buy the VIP to use it!"
+2
View File
@@ -3,6 +3,8 @@ selected:
expired: expired:
- "&7Your prefix &f%(oldName) &7has expired," - "&7Your prefix &f%(oldName) &7has expired,"
- "&7Now the prefix is changed to &f%(newName) &7." - "&7Now the prefix is changed to &f%(newName) &7."
removed:
- "&7Your using prefix has been removed, now the prefix is changed to &f%(newName) &7."
reload: reload:
- "&a&lReload completed&7costs &f%(time)ms&7." - "&a&lReload completed&7costs &f%(time)ms&7."
help: help:
+2
View File
@@ -3,6 +3,8 @@ selected:
expired: expired:
- "&7您先前使用的前缀 &f%(oldName) &7已到期。" - "&7您先前使用的前缀 &f%(oldName) &7已到期。"
- "&7现在已为您重新调整为 &f%(newName) &7。" - "&7现在已为您重新调整为 &f%(newName) &7。"
removed:
- "&7您先前使用的前缀已被移除,现在已为您重新调整为 &f%(newName) &7。"
reload: reload:
- "&a&l重载完成!&7共耗时 &f%(time)ms&7。" - "&a&l重载完成!&7共耗时 &f%(time)ms&7。"
help: help:
+5 -3
View File
@@ -1,11 +1,13 @@
main: cc.carm.plugin.userprefix.Main main: cc.carm.plugin.userprefix.Main
name: UserPrefix name: ${project.name}
version: ${project.version} version: ${project.version}
authors: authors:
- Carm - Carm
- YourCraft - ${project.organization.name}
- SakuraGame - SakuraGame
website: "https://github.com/CarmJos/UserPrefix" website: ${project.url}
description: ${project.description}
depend: depend:
- LuckPerms - LuckPerms
softdepend: softdepend:
+17 -17
View File
@@ -9,7 +9,7 @@ name: "&b&lPro&b"
# 内容 [必须] # 内容 [必须]
# 显示在名字前面的内容 # 显示在名字前面的内容
content: "§b§lPro §b" content: "&b&lPro &b"
# 权重 [必须] # 权重 [必须]
# 用于GUI、TabList的排序和自动前缀显示 # 用于GUI、TabList的排序和自动前缀显示
@@ -30,14 +30,14 @@ itemHasPermission: #
meta: meta:
==: ItemMeta ==: ItemMeta
meta-type: UNSPECIFIC meta-type: UNSPECIFIC
display-name: "§b§lPro §b会员前缀" display-name: "&b&lPro &b会员前缀"
lore: lore:
- "§7Pro会员专属称号" - "&7Pro会员专属称号"
- "" - ""
- "§f尊贵的Pro会员专属称号。" - "&f尊贵的Pro会员专属称号。"
- "§f您将获得多种特权与更好的游戏体验。" - "&f您将获得多种特权与更好的游戏体验。"
- "" - ""
- "§a➥ 点击切换到该前缀" - "&a➥ 点击切换到该前缀"
# 正在使用时显示的物品 [非必需] # 正在使用时显示的物品 [非必需]
# 当用户正在使用时会显示这个物品,不配置即自动加载“itemHasPermission” # 当用户正在使用时会显示这个物品,不配置即自动加载“itemHasPermission”
@@ -47,16 +47,16 @@ itemUsing:
meta: meta:
==: ItemMeta ==: ItemMeta
meta-type: UNSPECIFIC meta-type: UNSPECIFIC
display-name: "§b§lPro §b会员前缀" display-name: "&b&lPro &b会员前缀"
enchants: enchants:
PROTECTION_ENVIRONMENTAL: 1 #加一个附魔这样看上去就像是选中了的 PROTECTION_ENVIRONMENTAL: 1 #加一个附魔这样看上去就像是选中了的
lore: lore:
- "§7Pro会员专属称号" - "&7Pro会员专属称号"
- "" - ""
- "§f尊贵的Pro会员专属称号。" - "&f尊贵的Pro会员专属称号。"
- "§f您将获得多种特权与更好的游戏体验。" - "&f您将获得多种特权与更好的游戏体验。"
- "" - ""
- "§a✔ 您正在使用该前缀" - "&a✔ 您正在使用该前缀"
# 没有权限时显示的物品 [非必需] # 没有权限时显示的物品 [非必需]
# 如果没有权限就会显示这个item。如果不配置该物品,则玩家没有使用权限时不会显示在GUI里面。 # 如果没有权限就会显示这个item。如果不配置该物品,则玩家没有使用权限时不会显示在GUI里面。
@@ -67,12 +67,12 @@ itemNoPermission:
meta: meta:
==: ItemMeta ==: ItemMeta
meta-type: UNSPECIFIC meta-type: UNSPECIFIC
display-name: "§b§lPro+ §b会员前缀 §c(未拥有)" display-name: "&b&lPro+ &b会员前缀 &c(未拥有)"
lore: lore:
- "§7Pro+会员专属称号" - "&7Pro+会员专属称号"
- "" - ""
- "§f尊贵的Pro会员专属称号。" - "&f尊贵的Pro会员专属称号。"
- "§f您将获得多种特权与更好的游戏体验。" - "&f您将获得多种特权与更好的游戏体验。"
- "§f您可以输入 §b/vip §f指令查看详细特权!" - "&f您可以输入 &b/vip &f指令查看详细特权!"
- "" - ""
- "§e✯ 加入Pro+会员以使用该前缀!" - "&e✯ 加入Pro+会员以使用该前缀!"