Compare commits
146 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cbd2a4373d | |||
| 2beefb71d4 | |||
| 23db43604c | |||
| 899acbe2cc | |||
| d3a3529ccc | |||
| 969844dae9 | |||
| 6904f5a6d6 | |||
| b60cb89460 | |||
| ff108d0d1c | |||
| 734e5f526c | |||
| 99f2b6ff28 | |||
| 5c5a57af5b | |||
| 044cd1a84f | |||
| 29796ec455 | |||
| 898ba5bf27 | |||
| 2e46888019 | |||
| ac55fc135c | |||
| 774e9b764e | |||
| a31da83531 | |||
| 61857d6305 | |||
| dd96188b22 | |||
| eb4ecaada9 | |||
| acc9ea7e7c | |||
| 83b3c45d57 | |||
| 3ec39b9ca3 | |||
| 821b42cc03 | |||
| 81e0c0960f | |||
| 99c577c361 | |||
| 5df6e1fe34 | |||
| 7c887822ba | |||
| 6b601950a3 | |||
| d752461c74 | |||
| 548f1d366f | |||
| 686b28cf93 | |||
| 92e14e29fe | |||
| 78f9639092 | |||
| 096c23351f | |||
| b4f8404648 | |||
| 623356ce21 | |||
| 9164541e4f | |||
| 2453305420 | |||
| 1856de5e5d | |||
| c38adbeca6 | |||
| 0e90890c67 | |||
| 7e4ca870b5 | |||
| 42b71714aa | |||
| 0d6247b0f2 | |||
| 1b9f4f3e55 | |||
| b76081bb6b | |||
| b8d6862b17 | |||
| 46fb39d7bb | |||
| 523a4f872b | |||
| 5151f1f917 | |||
| 296339ca6f | |||
| 63b69defcc | |||
| 857ce5c27b | |||
| a5189ff314 | |||
| bacb0b1bed | |||
| 1826f08575 | |||
| 4df2a49c5b | |||
| cbb9928232 | |||
| 967984e0c3 | |||
| ad780a00bd | |||
| 43c2c14cb3 | |||
| 8521d87c46 | |||
| 378e518e72 | |||
| 84cbe0c61a | |||
| 90f7f7f2e5 | |||
| 48147aec16 | |||
| e7c8ce284c | |||
| e8b603debc | |||
| 72730fad1a | |||
| a87e97f744 | |||
| b2f7338ba6 | |||
| f91a2aa198 | |||
| 124ee0f9c3 | |||
| 9f738ff1ae | |||
| f23fa03f7a | |||
| cf749bf5c0 | |||
| 01e321686f | |||
| deba26c713 | |||
| 5b4d49f6ed | |||
| 2e5250dd36 | |||
| 88730c98f2 | |||
| e003a543f5 | |||
| 07edaeb401 | |||
| 2357699324 | |||
| c2fa1a1e95 | |||
| 3b03ec4616 | |||
| 1a2644210b | |||
| 83b9ced6f5 | |||
| dd96c6d6da | |||
| ba7d4b90c3 | |||
| ab984acc73 | |||
| 32df1de83d | |||
| dfe447393e | |||
| 26ce6d7e66 | |||
| 2e4d1122d9 | |||
| b5a2199e1e | |||
| 3678a201c7 | |||
| f08a5e84d3 | |||
| 7743bbb3ff | |||
| 1942c50078 | |||
| 2b701510bc | |||
| 0d17e7f1b6 | |||
| 3a41560972 | |||
| 313aa77d72 | |||
| dab774a389 | |||
| 5469c3101f | |||
| dbf826cec8 | |||
| 87c87127b9 | |||
| 50c35488ef | |||
| 29539ddb6f | |||
| cab2b60abf | |||
| 693ff4a4af | |||
| 7c90b8ff99 | |||
| e5ba217873 | |||
| 33e0e64b7d | |||
| 6eb60d83d8 | |||
| 875655bc60 | |||
| 9ca289e4ba | |||
| 41a9582d03 | |||
| e14901ac86 | |||
| 9a620d7324 | |||
| 9cff1c03dc | |||
| 3a457082b1 | |||
| 12218a2141 | |||
| 389e4d3904 | |||
| 6ac3cea7c0 | |||
| 3f14294e67 | |||
| 93521f6621 | |||
| 43a4fb08a6 | |||
| 3dd6398afa | |||
| 799bb4e52b | |||
| 7ea3934db9 | |||
| 0d20860166 | |||
| b0c6c793a8 | |||
| b6319eec78 | |||
| 8bf19a69f8 | |||
| 5d4b131a13 | |||
| 5c2b062839 | |||
| dbe4b187d3 | |||
| 419e440700 | |||
| 7052ea6ec4 | |||
| 264b69b115 | |||
| c16d12d718 |
@@ -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) 。
|
||||
@@ -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 |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 212 KiB |
|
Before Width: | Height: | Size: 920 KiB After Width: | Height: | Size: 920 KiB |
|
After Width: | Height: | Size: 60 KiB |
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: 问题提交
|
||||
about: 描述问题并提交,帮助我们对其进行检查与修复。
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
### **问题简述**
|
||||
<!--用简短的话语描述一下大概问题。-->
|
||||
|
||||
### **问题来源**
|
||||
|
||||
<!--
|
||||
描述一下通过哪些操作才发现的问题,如:
|
||||
1. 打开 '...'
|
||||
2. 点击了 '....'
|
||||
3. 出现了报错 '....'
|
||||
-->
|
||||
|
||||
### **预期结果**(可选)
|
||||
<!--如果问题不发生,应该是什么情况-->
|
||||
|
||||
### **问题截图/问题报错**
|
||||
<!--如果有报错或输出,请提供截图。-->
|
||||
|
||||
### **操作环境**
|
||||
<!--请在后台输入 `version` 并复制相关输出。-->
|
||||
|
||||
### **其他补充**
|
||||
<!--如有其他补充,可以在这里描述。-->
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: 功能需求
|
||||
about: 希望我们提供更多的功能。
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
### **功能简述**
|
||||
<!--简单的描述一下你想要的功能-->
|
||||
|
||||
### **需求来源**
|
||||
<!--简单的描述一下为什么需要这个功能。-->
|
||||
|
||||
### **功能参考**(可选)
|
||||
<!--如果有相关功能的参考,如文本、截图,请提供给我们。-->
|
||||
|
||||
### **附加内容**
|
||||
<!--如果有什么小细节需要重点注意,请在这里告诉我们。-->
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,13 +1,12 @@
|
||||
# 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: Java CI with Maven
|
||||
name: Build & Tests
|
||||
|
||||
on:
|
||||
# 支持手动触发构建
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -16,11 +15,29 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 11
|
||||
- name: "Set up JDK"
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: '11'
|
||||
distribution: 'adopt'
|
||||
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
|
||||
env:
|
||||
MAVEN_USERNAME: ${{ github.repository_owner }}
|
||||
MAVEN_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||
|
||||
- name: "Target Staging"
|
||||
run: |
|
||||
mkdir artifacts
|
||||
cp -vrf target/ artifacts/target/
|
||||
cp -vrf asset/*.jar artifacts
|
||||
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Artifact
|
||||
path: artifacts
|
||||
@@ -1,3 +1,5 @@
|
||||
/.idea/
|
||||
/target/
|
||||
./*.iml
|
||||
*.iml
|
||||
asset/
|
||||
@@ -0,0 +1,126 @@
|
||||

|
||||
|
||||
README LANGUAGES [ [中文](README.md) | [**English**](README-en.md) ]
|
||||
|
||||
# UserPrefix Plugin
|
||||
|
||||
[](https://www.codefactor.io/repository/github/carmjos/userprefix)
|
||||

|
||||
[](https://opensource.org/licenses/GPL-3.0)
|
||||
[](https://github.com/CarmJos/UserPrefix/actions/workflows/maven.yml)
|
||||

|
||||

|
||||
|
||||
Lightweight, efficient, and real-time user prefix system.
|
||||
|
||||
This plugin is implemented based on Spigot ,**Theoretically** support ALL MineCraft Versions.
|
||||
|
||||
The development of this plugin is based on Chinese which purpose is to help Chinese developers learn Bukkit plugin
|
||||
development.
|
||||
|
||||
> 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) 上发布,欢迎中文用户来这里下载。
|
||||
|
||||
## Examples
|
||||
|
||||

|
||||
|
||||
## Dependencies
|
||||
|
||||
- **[Necessary]** Plugin developed based on [Spigot-API](https://hub.spigotmc.org/stash/projects/SPIGOT)
|
||||
and [BukkitAPI](http://bukkit.org/).
|
||||
- **[Necessary]** Plugin data storage base on [LuckPerms](https://www.spigotmc.org/resources/luckperms.28140/).
|
||||
- **[Recommend]** Placeholders based on [PlaceholderAPI](https://www.spigotmc.org/resources/6245/) .
|
||||
|
||||
For development dependencies, please see [Dependencies](https://github.com/CarmJos/UserPrefix/network/dependencies) .
|
||||
|
||||
## Features
|
||||
|
||||
- **Theoretically** support ALL MineCraft Versions.
|
||||
- Reloading the configuration will automatically refresh the prefix of all players.
|
||||
- Real-time judgment and feedback to the player when permissions are changed.
|
||||
- Configurable sounds and messages.
|
||||
- The prefix icon can be configured as "Selected", "Has Permission" and “No Permission”.
|
||||
- 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 has any conflict)
|
||||
- Simple Chat Format Placeholder support. (Not Recommended)
|
||||
- GUI with automatic sorting and page turning!
|
||||
- Support PlaceholderAPI variables!
|
||||
- Support [Hex Color](https://www.hexcolortool.com/)! (Version 1.16 and above) `&(#Color)`
|
||||
- Example: LightSlateBlue `&(#8470FF)` 、 DarkSlateBlue `&(#483D8B)`
|
||||
|
||||
## Notice
|
||||
|
||||
### 1. Version support issues
|
||||
|
||||
This plugin theoretically supports all versions.
|
||||
|
||||
If the icon does not load, the sound cannot be played, etc., please check whether the type of the item and sound in the
|
||||
configuration file exists in the current version.
|
||||
|
||||
Take the SOUND as an example. The sound that the villager said "OK" is "`VILLAGER_YES`" in the lower version, but it
|
||||
becomes "`ENTITY_VILLAGER_YES`" in the higher version.
|
||||
|
||||
### 2. Scoreboard exception problem
|
||||
|
||||
The display of the prefix on the head and the sorting of the TabList both use the scoreboard API.
|
||||
|
||||
Please turn of the `functions.on-name-prefix` in the configuration if there is a conflict.
|
||||
|
||||
## Commands
|
||||
|
||||
This plugin's Commands are based on Chinese!
|
||||
**May support multi-language in the future.**
|
||||
|
||||
```text
|
||||
/UserPrefix or /prefix #Open prefix GUI
|
||||
/UserPrefixAdmin # View Admin Command Help
|
||||
/UserPrefixAdmin reload # Reload Config
|
||||
/UserPrefixAdmin list # List all configured prefixes.
|
||||
```
|
||||
|
||||
## Placeholders (PlaceholderAPI)
|
||||
|
||||
After installed the [PlaceholderAPI](https://github.com/PlaceholderAPI/PlaceholderAPI) , you can
|
||||
type `/papi info UserPrefix` to see all the placeholders.
|
||||
|
||||
```text
|
||||
# %UserPrefix_prefix%
|
||||
- Get the content of the current prefix
|
||||
# %UserPrefix_weight%
|
||||
- Get the weight of the current prefix.
|
||||
# %UserPrefix_identifier%
|
||||
- Get the identifier of the current prefix.
|
||||
# %UserPrefix_name%
|
||||
- Get the name of the current prefix.
|
||||
# %UserPrefix_has_<Identifier>%
|
||||
- Determine whether the player has a certain prefix(true/false)
|
||||
```
|
||||
|
||||
## Configuration files
|
||||
|
||||
### Plugin Configuration ([`config.yml`]() .
|
||||
|
||||
Will be generated on the first boot up.
|
||||
|
||||
### Messages Configuration ([`messages.yml`]())
|
||||
|
||||
Will be generated on the first boot up.
|
||||
|
||||
### Prefixes Configuration ([`prefixes/*.yml`](src/main/resources/en_US/example-prefix.yml))
|
||||
|
||||
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.
|
||||
|
||||
## Support and Donation
|
||||
|
||||
This project is support by the [YourCraft(你的世界)](https://www.ycraft.cn) .
|
||||

|
||||
|
||||
## Open source agreement
|
||||
|
||||
The source code of this project uses [GNU General Public License v3.0](https://opensource.org/licenses/GPL-3.0)
|
||||
License.
|
||||
|
||||
@@ -1,17 +1,32 @@
|
||||

|
||||

|
||||
|
||||
README LANGUAGES [ [**中文**](README.md) | [English](README-en.md) ]
|
||||
|
||||
# 用户前缀系统插件
|
||||
|
||||
[](https://www.codefactor.io/repository/github/carmjos/userprefix)
|
||||

|
||||
[](https://github.com/CarmJos/UserPrefix/releases)
|
||||
[](https://github.com/CarmJos/UserPrefix/actions/workflows/maven.yml)
|
||||

|
||||

|
||||
|
||||
轻便、高效、实时的用户前缀系统。
|
||||
|
||||
本插件基于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/) 上发布。
|
||||
|
||||
## 示例
|
||||
|
||||

|
||||
|
||||
## 依赖
|
||||
|
||||
- **[必须]** 插件本体基于 [Spigot-API](https://hub.spigotmc.org/stash/projects/SPIGOT)、[BukkitAPI](http://bukkit.org/) 实现。
|
||||
- **[必须]** 数据部分基于 [LuckPerms](https://www.spigotmc.org/resources/luckperms.28140/) 实现。
|
||||
- [选配] 变量部分基于 [PlaceholderAPI](https://www.spigotmc.org/resources/6245/) 实现。
|
||||
- **[推荐]** 变量部分基于 [PlaceholderAPI](https://www.spigotmc.org/resources/6245/) 实现。
|
||||
|
||||
详细依赖列表可见 [Dependencies](https://github.com/CarmJos/UserPrefix/network/dependencies) 。
|
||||
|
||||
@@ -19,15 +34,17 @@
|
||||
|
||||
- 理论上全版本支持!
|
||||
- 游戏内重载配置文件并实时更新到玩家!
|
||||
- 当玩家权限变更时会实时监测前缀,若权限不足则自动更换前缀并提示!
|
||||
- 当玩家权限变更时会实时监测前缀,若权限不足则自动更换前缀并提示
|
||||
- 可配置的声音、消息!
|
||||
- 前缀图标可配置“选中”、“有权限”与“无权限”三种状态的物品
|
||||
- 物品的配置通过ItemStack原生配置,支持MC所有的设定!
|
||||
- 具体的设定请参考其他文档哦~
|
||||
- TabList自动按照前缀的权重排序 (如有冲突可关掉)
|
||||
- 玩家头顶前缀显示 (如有冲突可关掉)
|
||||
- 自动排序,且可翻页的GUI
|
||||
- 支持PlaceholderAPI变量
|
||||
- 简单的聊天变量修改功能!(不推荐使用) `[自 v2.1.0 版本起]`
|
||||
- 自动排序,且可翻页的GUI!
|
||||
- 支持PlaceholderAPI变量!(凡支持的都可以使用,如BungeeTabListPlus)
|
||||
- 支持[Hex颜色](https://www.hexcolortool.com/)!(1.16以上版本) `[自 v1.2.3 版本起]`
|
||||
- 格式: `&(#颜色代码)`
|
||||
- 示例: LightSlateBlue `&(#8470FF)` 、 DarkSlateBlue `&(#483D8B)`
|
||||
|
||||
## 注意事项
|
||||
|
||||
@@ -41,10 +58,7 @@
|
||||
|
||||
头顶上前缀的显示与TabList的排序均使用到了计分板API。
|
||||
|
||||
如有冲突导致其他插件的计分板无法显示,请关掉配置文件中`functions.OnNamePrefix`。
|
||||
|
||||
### 3. 物品图标配置问题
|
||||
物品相关均通过Bukkit提供的ItemStack序列化方法读取,相关配置方式请参考[ItemStack Serialization(物品序列化)](https://www.spigotmc.org/wiki/itemstack-serialization/)。
|
||||
如有冲突导致其他插件的计分板无法显示,请关掉配置文件中`functions.on-name-prefix`。
|
||||
|
||||
## 指令
|
||||
|
||||
@@ -78,122 +92,57 @@
|
||||
|
||||
## 配置文件示例
|
||||
|
||||
```yaml
|
||||
version: 1.0.0-SNAPSHOT # 配置文件版本,一般不会动。
|
||||
### 基础配置文件 ([`config.yml`](src/main/java/cc/carm/plugin/userprefix/configuration/PluginConfig.java))
|
||||
|
||||
debug: false #debug输出,开发者用的
|
||||
将会在服务器首次启动时生成,如果您想要修改配置,请在服务器启动后打开配置文件。
|
||||
|
||||
functions:
|
||||
OnNamePrefix: true # 是否给头顶上添加前缀,该方法用到了头顶的那个计分板,如有冲突请关掉哦~
|
||||
autoUsePrefix: true # 自动前缀显示 当玩家没有自己选择一个前缀的时候,会自动使用所拥有的的前缀中权重最高的那一个
|
||||
### 消息配置文件 ([`messages.yml`](src/main/java/cc/carm/plugin/userprefix/configuration/PluginMessages.java))
|
||||
|
||||
messages:
|
||||
selected:
|
||||
- "&7您选择了 &f%(name) &7作为当前显示的前缀。"
|
||||
expired:
|
||||
- "&7您先前使用的前缀 &f%(oldName) &7已到期。"
|
||||
- "&7现在已为您重新调整为 &f%(newName) &7。"
|
||||
将会在服务器首次启动时生成,如果您想要修改配置,请在服务器启动后打开配置文件 。
|
||||
|
||||
Sounds: #相关的声音,注释掉则不播放声音
|
||||
# 格式为 【声音名:音量:音调】 或 【声音名:音量】 或 【声音名】
|
||||
openGUI: "BLOCK_NOTE_BLOCK_PLING:1:1"
|
||||
guiClick: "UI_BUTTON_CLICK"
|
||||
prefixChange: "ENTITY_VILLAGER_YES"
|
||||
prefixExpired: "ENTITY_VILLAGER_NO"
|
||||
### 前缀配置文件 ([`prefixes/*.yml`](src/main/resources/prefixes/example-prefix.yml))
|
||||
|
||||
# 默认前缀的配置
|
||||
# 默认前缀的权重为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✔ 您正在使用该前缀"
|
||||
所有前缀均为单独的配置文件,存放于 `插件配置目录/prefixes` 下,便于管理。
|
||||
|
||||
prefixes:
|
||||
VIP:
|
||||
name: "&b&lPro&b" # [必须] 名字(切换的时候左下角会弹提示 用的就是这个名字)
|
||||
content: "§b§lPro §b" # [必须] 显示在名字前面的内容
|
||||
weight: 1 # [必须] 权重,用于GUI里面的排序(越大显示在越后面)和自动前缀显示
|
||||
permission: "yc.pro" # [非必须] 检测的权限,如果没有就是人人都能用,也代表不用配置“itemNoPermission”了(因为压根不可能显示没权限时候的物品)
|
||||
itemHasPermission:
|
||||
# [必须] 当有权限的时候会显示这个Item
|
||||
==: org.bukkit.inventory.ItemStack
|
||||
type: DIAMOND
|
||||
meta:
|
||||
==: ItemMeta
|
||||
meta-type: UNSPECIFIC
|
||||
display-name: "§b§lPro §b会员前缀"
|
||||
lore:
|
||||
- "§7Pro会员专属称号"
|
||||
- ""
|
||||
- "§f尊贵的Pro会员专属称号。"
|
||||
- "§f您将获得多种特权与更好的游戏体验。"
|
||||
- ""
|
||||
- "§a➥ 点击切换到该前缀"
|
||||
itemUsing:
|
||||
# [非必需] 当有权限的时候会显示这个Item,如果没有这个配置就自动显示“itemHasPermission”的。
|
||||
==: 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✔ 您正在使用该前缀"
|
||||
itemNoPermission:
|
||||
# [非必需] 如果没有权限就会显示这个item。如果不配置该物品,则玩家没有使用权限时不会显示在GUI里面。
|
||||
==: 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+会员以使用该前缀!"
|
||||
```
|
||||
文件名理论上可以随便取,推荐使用英文,部分符号可能会影响正常读取,请避免使用。
|
||||
|
||||
您可以 [点击这里](src/main/resources/prefixes/example-prefix.yml) 查看示例前缀配置文件。
|
||||
|
||||
## 使用统计
|
||||
|
||||
[](https://bstats.org/plugin/bukkit/UserPrefix/13776)
|
||||
|
||||
## 支持与捐赠
|
||||
|
||||
本项目由 [YourCraft(你的世界)](https://www.ycraft.cn) 团队提供长期支持与维护。
|
||||

|
||||

|
||||
|
||||
若您觉得本插件做的不错,您可以捐赠支持我!
|
||||
|
||||
感谢您成为开源项目的支持者!
|
||||
|
||||
<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.php) 开源协议。
|
||||
|
||||
本项目源码采用 [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>
|
||||
|
Before Width: | Height: | Size: 58 KiB |
@@ -4,38 +4,66 @@
|
||||
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>
|
||||
|
||||
<groupId>cc.carm.plugin</groupId>
|
||||
<artifactId>UserPrefix</artifactId>
|
||||
<version>1.2.2-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<maven.deploy.skip>true</maven.deploy.skip>
|
||||
<project.jdk.version>8</project.jdk.version>
|
||||
<project.package>cc.carm.plugin.userprefix</project.package>
|
||||
|
||||
<maven.compiler.source>${project.jdk.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${project.jdk.version}</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||
|
||||
<easyplugin.version>1.4.9</easyplugin.version>
|
||||
<mineconfig.version>2.0.1</mineconfig.version>
|
||||
</properties>
|
||||
|
||||
<groupId>cc.carm.plugin</groupId>
|
||||
<artifactId>userprefix</artifactId>
|
||||
<version>3.0.0</version>
|
||||
|
||||
<name>UserPrefix</name>
|
||||
<description>轻便、高效、实时的用户前缀系统。</description>
|
||||
<url>https://github.com/CarmJos/UserPrefix</url>
|
||||
|
||||
<issueManagement>
|
||||
<system>GitHub Issues</system>
|
||||
<url>https://github.com/CarmJos/UserPrefix/issues</url>
|
||||
</issueManagement>
|
||||
|
||||
<ciManagement>
|
||||
<system>GitHub Actions</system>
|
||||
<url>https://github.com/CarmJos/UserPrefix/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>
|
||||
|
||||
<repository>
|
||||
<id>spigotmc-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/public/</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>placeholder-api-repo</id>
|
||||
<url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>lss233-repo</id>
|
||||
<url>https://lss233.littleservice.cn/repositories/minecraft</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>oss-repo</id>
|
||||
<url>https://oss.sonatype.org/content/groups/public/</url>
|
||||
<id>spigot-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
@@ -47,13 +75,71 @@
|
||||
<id>maven-central</id>
|
||||
<url>https://repo1.maven.org/maven2/</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>sonatype-repo</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>EasyPlugin</id>
|
||||
<url>https://raw.githubusercontent.com/CarmJos/EasyPlugin/repo/</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>carm-repo</id>
|
||||
<name>Carm's Repo</name>
|
||||
<url>https://repo.carm.cc/repository/maven-public/</url>
|
||||
</repository>
|
||||
|
||||
</repositories>
|
||||
|
||||
<distributionManagement>
|
||||
<downloadUrl>https://github.com/CarmJos/UserPrefix/releases</downloadUrl>
|
||||
<repository>
|
||||
<id>github</id>
|
||||
<name>GitHub Packages</name>
|
||||
<url>https://maven.pkg.github.com/CarmJos/UserPrefix</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easyplugin-main</artifactId>
|
||||
<version>${easyplugin.version}</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easyplugin-gui</artifactId>
|
||||
<version>${easyplugin.version}</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easyplugin-githubchecker</artifactId>
|
||||
<version>${easyplugin.version}</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>mineconfiguration-bukkit</artifactId>
|
||||
<version>${mineconfig.version}</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.17-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
@@ -72,10 +158,24 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bukkit</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jetbrains</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>23.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13</version>
|
||||
<version>4.13.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -84,15 +184,27 @@
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.1</version>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<configuration>
|
||||
<useSystemClassLoader>false</useSystemClassLoader>
|
||||
<filesets>
|
||||
<fileset>
|
||||
<directory>${project.basedir}/asset/</directory>
|
||||
<useDefaultExcludes>true</useDefaultExcludes>
|
||||
<includes>
|
||||
<include>**/*</include>
|
||||
</includes>
|
||||
</fileset>
|
||||
<fileset>
|
||||
<directory>${project.basedir}/api-docs/</directory>
|
||||
<useDefaultExcludes>true</useDefaultExcludes>
|
||||
<includes>
|
||||
<include>**/*</include>
|
||||
</includes>
|
||||
</fileset>
|
||||
</filesets>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
@@ -104,6 +216,9 @@
|
||||
</links>
|
||||
<detectJavaApiLink>true</detectJavaApiLink>
|
||||
<encoding>UTF-8</encoding>
|
||||
<charset>UTF-8</charset>
|
||||
<docencoding>UTF-8</docencoding>
|
||||
<locale>zh_CN</locale>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
@@ -119,8 +234,8 @@
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<source>${project.jdk.version}</source>
|
||||
<target>${project.jdk.version}</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
<compilerArgument>-parameters</compilerArgument>
|
||||
</configuration>
|
||||
@@ -130,6 +245,19 @@
|
||||
<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>
|
||||
@@ -140,12 +268,26 @@
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<finalName>${project.name}-${project.version}</finalName>
|
||||
<outputDirectory>${project.basedir}/asset/</outputDirectory>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.bstats</pattern>
|
||||
<shadedPattern>${project.package}.bstats</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>cc.carm.lib</pattern>
|
||||
<shadedPattern>${project.package}.lib</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.json</pattern>
|
||||
<shadedPattern>${project.package}.lib.json</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
@@ -166,7 +308,6 @@
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
|
||||
@@ -1,103 +1,116 @@
|
||||
package cc.carm.plugin.userprefix;
|
||||
|
||||
import cc.carm.plugin.userprefix.command.UserPrefixAdminCommand;
|
||||
import cc.carm.plugin.userprefix.command.UserPrefixCommand;
|
||||
import cc.carm.plugin.userprefix.configuration.PrefixConfig;
|
||||
import cc.carm.lib.easyplugin.EasyPlugin;
|
||||
import cc.carm.lib.easyplugin.gui.GUI;
|
||||
import cc.carm.lib.easyplugin.updatechecker.GHUpdateChecker;
|
||||
import cc.carm.lib.easyplugin.utils.MessageUtils;
|
||||
import cc.carm.plugin.userprefix.command.AdminCommand;
|
||||
import cc.carm.plugin.userprefix.command.UserCommand;
|
||||
import cc.carm.plugin.userprefix.configuration.PluginConfig;
|
||||
import cc.carm.plugin.userprefix.hooker.UserPrefixExpansion;
|
||||
import cc.carm.plugin.userprefix.listener.ChatListener;
|
||||
import cc.carm.plugin.userprefix.listener.UserListener;
|
||||
import cc.carm.plugin.userprefix.listener.processor.UserNodeUpdateProcessor;
|
||||
import cc.carm.plugin.userprefix.manager.ConfigManager;
|
||||
import cc.carm.plugin.userprefix.manager.PrefixManager;
|
||||
import cc.carm.plugin.userprefix.manager.ServiceManager;
|
||||
import cc.carm.plugin.userprefix.manager.UserManager;
|
||||
import cc.carm.plugin.userprefix.util.ColorParser;
|
||||
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.event.Listener;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public class Main extends JavaPlugin {
|
||||
public class Main extends EasyPlugin {
|
||||
|
||||
private static Main instance;
|
||||
|
||||
protected ConfigManager configManager;
|
||||
protected PrefixManager prefixManager;
|
||||
protected UserManager userManager;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
protected boolean initialize() {
|
||||
instance = this;
|
||||
|
||||
log(getName() + " " + getDescription().getVersion() + " &7开始加载...");
|
||||
long startTime = System.currentTimeMillis();
|
||||
log("加载插件配置...");
|
||||
this.configManager = new ConfigManager(getDataFolder());
|
||||
this.prefixManager = new PrefixManager();
|
||||
|
||||
log("加载配置文件...");
|
||||
ConfigManager.initConfig();
|
||||
PrefixManager.init();
|
||||
log("加载前缀配置...");
|
||||
int loaded = prefixManager.loadPrefixes();
|
||||
log(" 成功加载了 " + loaded + " 个前缀配置。");
|
||||
|
||||
log("加载用户管理器...");
|
||||
this.userManager = new UserManager();
|
||||
|
||||
log("注册指令...");
|
||||
Bukkit.getPluginCommand("UserPrefix").setExecutor(new UserPrefixCommand());
|
||||
Bukkit.getPluginCommand("UserPrefixAdmin").setExecutor(new UserPrefixAdminCommand());
|
||||
registerCommand("UserPrefix", new UserCommand());
|
||||
registerCommand("UserPrefixAdmin", new AdminCommand());
|
||||
|
||||
log("注册监听器...");
|
||||
regListener(new UserListener());
|
||||
ServiceManager.getService().getEventBus().subscribe(this, UserDataRecalculateEvent.class, UserNodeUpdateProcessor::process);
|
||||
GUI.initialize(this);
|
||||
registerListener(new UserListener());
|
||||
registerListener(new ChatListener());
|
||||
ServiceManager.getService().getEventBus().subscribe(
|
||||
this, UserDataRecalculateEvent.class,
|
||||
UserNodeUpdateProcessor::process
|
||||
);
|
||||
|
||||
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
|
||||
if (MessageUtils.hasPlaceholderAPI()) {
|
||||
log("注册变量...");
|
||||
new UserPrefixExpansion(getInstance()).register();
|
||||
} else {
|
||||
log("未安装 PlaceholderAPI 不进行变量注册...");
|
||||
log("未安装 PlaceholderAPI ,跳过变量注册...");
|
||||
log("若您想使用变量进行前缀的显示,请安装PlaceholderAPI!");
|
||||
}
|
||||
|
||||
|
||||
log("加载完成 ,共耗时 " + (System.currentTimeMillis() - startTime) + " ms 。");
|
||||
|
||||
showAD();
|
||||
|
||||
if (Bukkit.getOnlinePlayers().size() > 0) {
|
||||
Bukkit.getOnlinePlayers().forEach(UserManager::initPlayer); // 适配热重载
|
||||
if (PluginConfig.METRICS.getNotNull()) {
|
||||
log("启用统计数据...");
|
||||
Metrics metrics = new Metrics(this, 13776);
|
||||
metrics.addCustomChart(new SingleLineChart("active_prefixes", () -> prefixManager.getPrefixes().size()));
|
||||
metrics.addCustomChart(new SimplePie("custom_storage", () -> PluginConfig.CUSTOM_STORAGE.ENABLE.getNotNull() ? "ENABLE" : "DISABLE"));
|
||||
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();
|
||||
}));
|
||||
}
|
||||
|
||||
if (PluginConfig.CHECK_UPDATE.getNotNull()) {
|
||||
log("开始检查更新...");
|
||||
getScheduler().runAsync(GHUpdateChecker.runner(this));
|
||||
} else {
|
||||
log("已禁用检查更新,跳过。");
|
||||
}
|
||||
|
||||
Bukkit.getOnlinePlayers().forEach(userManager::initPlayer); // 适配热重载
|
||||
|
||||
log("&7感谢您使用 &3&lUserPrefix " + getDescription().getVersion() + "&7!");
|
||||
log("&7本插件由 &b&lYourCraft &7提供长期支持与维护。");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
log(getName() + " " + getDescription().getVersion() + " 开始卸载...");
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
log("卸载监听器...");
|
||||
Bukkit.getServicesManager().unregisterAll(this);
|
||||
|
||||
log("卸载完成 ,共耗时 " + (System.currentTimeMillis() - startTime) + " ms 。");
|
||||
|
||||
showAD();
|
||||
|
||||
public boolean isDebugging() {
|
||||
return PluginConfig.DEBUG.getNotNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册监听器
|
||||
*
|
||||
* @param listener 监听器
|
||||
*/
|
||||
public static void regListener(Listener listener) {
|
||||
Bukkit.getPluginManager().registerEvents(listener, getInstance());
|
||||
public static void info(String... message) {
|
||||
getInstance().log(message);
|
||||
}
|
||||
|
||||
public static void log(String message) {
|
||||
Bukkit.getConsoleSender().sendMessage(ColorParser.parseColor("[" + getInstance().getName() + "] " + message));
|
||||
public static void debugging(String... message) {
|
||||
getInstance().debug(message);
|
||||
}
|
||||
|
||||
public static void debug(String message) {
|
||||
if (PrefixConfig.DEBUG.get()) {
|
||||
log("[DEBUG] " + ColorParser.parseColor(message));
|
||||
}
|
||||
public static void serve(String... message) {
|
||||
getInstance().error(message);
|
||||
}
|
||||
|
||||
public static JavaPlugin getInstance() {
|
||||
public static Main getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private void showAD() {
|
||||
log("&7感谢您使用 &3&lUserPrefix " + getDescription().getVersion() + "&7!");
|
||||
log("&7本插件由 &b&lYourCraft &7提供长期支持与维护。");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package cc.carm.plugin.userprefix;
|
||||
|
||||
import cc.carm.plugin.userprefix.configuration.prefix.PrefixConfig;
|
||||
import cc.carm.plugin.userprefix.manager.ConfigManager;
|
||||
import cc.carm.plugin.userprefix.manager.PrefixManager;
|
||||
import cc.carm.plugin.userprefix.manager.UserManager;
|
||||
|
||||
public class UserPrefixAPI {
|
||||
|
||||
public static PrefixManager getPrefixManager() {
|
||||
return Main.getInstance().prefixManager;
|
||||
}
|
||||
|
||||
public static ConfigManager getConfigManager() {
|
||||
return Main.getInstance().configManager;
|
||||
}
|
||||
|
||||
public static UserManager getUserManager() {
|
||||
return Main.getInstance().userManager;
|
||||
}
|
||||
|
||||
public static PrefixConfig getDefaultPrefix(){
|
||||
return getPrefixManager().getDefaultPrefix();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package cc.carm.plugin.userprefix.command;
|
||||
|
||||
import cc.carm.plugin.userprefix.UserPrefixAPI;
|
||||
import cc.carm.plugin.userprefix.configuration.PluginMessages;
|
||||
import cc.carm.plugin.userprefix.configuration.prefix.PrefixConfig;
|
||||
import cc.carm.plugin.userprefix.ui.PrefixSelectGUI;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class AdminCommand implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String s, @NotNull String[] args) {
|
||||
if (args.length == 1) {
|
||||
String aim = args[0];
|
||||
if (aim.equalsIgnoreCase("list")) {
|
||||
PluginMessages.LIST.HEADER.send(sender);
|
||||
for (PrefixConfig value : UserPrefixAPI.getPrefixManager().getPrefixes().values()) {
|
||||
PluginMessages.LIST.VALUE.send(sender,
|
||||
value.getWeight(), value.getIdentifier(),
|
||||
value.getName(), value.getPermission(),
|
||||
value.getContent(), sender.getName()
|
||||
);
|
||||
}
|
||||
return true;
|
||||
} else if (aim.equalsIgnoreCase("reload")) {
|
||||
long s1 = System.currentTimeMillis();
|
||||
PrefixSelectGUI.closeAll(); // 关掉所有正在显示的前缀列表
|
||||
try {
|
||||
UserPrefixAPI.getConfigManager().reload(); // 重载配置文件
|
||||
int num = UserPrefixAPI.getPrefixManager().loadPrefixes(); //加载重载后了的前缀配置
|
||||
for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
|
||||
UserPrefixAPI.getUserManager().checkPrefix(onlinePlayer, false);
|
||||
/*
|
||||
* 这里关掉loadOthers(为其他玩家更新)了。
|
||||
* 因为每个玩家更新的时候会为其他人更新自己,
|
||||
* 全部走完一遍后,所有玩家都会加载最新的前缀内容。
|
||||
*/
|
||||
UserPrefixAPI.getUserManager().updatePrefixView(onlinePlayer, false);
|
||||
}
|
||||
PluginMessages.RELOAD.SUCCESS.send(sender, System.currentTimeMillis() - s1, num);
|
||||
} catch (Exception e) {
|
||||
PluginMessages.RELOAD.FAILED.send(sender, e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return help(sender);
|
||||
}
|
||||
return help(sender);
|
||||
}
|
||||
|
||||
public static boolean help(CommandSender sender) {
|
||||
PluginMessages.COMMAND_USAGE.ADMIN.send(sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,19 +1,30 @@
|
||||
package cc.carm.plugin.userprefix.command;
|
||||
|
||||
import cc.carm.plugin.userprefix.configuration.PluginMessages;
|
||||
import cc.carm.plugin.userprefix.ui.PrefixSelectGUI;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class UserPrefixCommand implements CommandExecutor {
|
||||
public class UserCommand implements CommandExecutor {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) {
|
||||
if (sender instanceof Player) {
|
||||
PrefixSelectGUI.open((Player) sender);
|
||||
} else {
|
||||
if (strings.length != 1) {
|
||||
PluginMessages.COMMAND_USAGE.CONSOLE.send(sender);
|
||||
} else {
|
||||
Player player = Bukkit.getPlayer(strings[0]);
|
||||
if (player != null) {
|
||||
PrefixSelectGUI.open(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package cc.carm.plugin.userprefix.command;
|
||||
|
||||
import cc.carm.plugin.userprefix.manager.ConfigManager;
|
||||
import cc.carm.plugin.userprefix.manager.PrefixManager;
|
||||
import cc.carm.plugin.userprefix.manager.UserManager;
|
||||
import cc.carm.plugin.userprefix.model.ConfiguredPrefix;
|
||||
import cc.carm.plugin.userprefix.ui.PrefixSelectGUI;
|
||||
import cc.carm.plugin.userprefix.util.ColorParser;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class UserPrefixAdminCommand implements CommandExecutor {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String s, @NotNull String[] args) {
|
||||
if (args.length == 1) {
|
||||
String aim = args[0];
|
||||
if (aim.equalsIgnoreCase("list")) {
|
||||
sender.sendMessage(ColorParser.parseColor("&3&l用户前缀系统 &f前缀列表"));
|
||||
for (ConfiguredPrefix value : PrefixManager.getPrefixes().values()) {
|
||||
sender.sendMessage(ColorParser.parseColor("&8#" + value.getWeight() + " &f" + value.getIdentifier()));
|
||||
sender.sendMessage(ColorParser.parseColor("&8- &7显示名 &r" + value.getName() + " &7权限&r " + value.getPermission()));
|
||||
sender.sendMessage(ColorParser.parseColor("&8- &7内容示例&r " + value.getContent() + sender.getName()));
|
||||
}
|
||||
return true;
|
||||
} else if (aim.equalsIgnoreCase("reload")) {
|
||||
long s1 = System.currentTimeMillis();
|
||||
PrefixSelectGUI.closeAll(); // 关掉所有正在显示的前缀列表
|
||||
ConfigManager.reloadConfig(); // 重载配置文件
|
||||
PrefixManager.loadConfiguredPrefixes(); //加载重载后了的配置文件
|
||||
for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
|
||||
UserManager.checkPrefix(onlinePlayer, false);
|
||||
/*
|
||||
* 这里关掉loadOthers(为其他玩家更新)了。
|
||||
* 因为每个玩家更新的时候会为其他人更新自己,
|
||||
* 全部走完一遍后,所有玩家都会加载最新的前缀内容。
|
||||
*/
|
||||
UserManager.updatePrefixView(onlinePlayer, false);
|
||||
}
|
||||
sender.sendMessage(ColorParser.parseColor("&a&l重载完成!&7共耗时 &f" + (System.currentTimeMillis() - s1) + " ms&7。"));
|
||||
return true;
|
||||
}
|
||||
return help(sender);
|
||||
}
|
||||
return help(sender);
|
||||
}
|
||||
|
||||
public static boolean help(CommandSender sender) {
|
||||
sender.sendMessage(ColorParser.parseColor("&3&l用户前缀系统 &f帮助"));
|
||||
sender.sendMessage(ColorParser.parseColor("&8#&f list"));
|
||||
sender.sendMessage(ColorParser.parseColor("&8- &7查看当前前缀列表。"));
|
||||
sender.sendMessage(ColorParser.parseColor("&8#&f reload"));
|
||||
sender.sendMessage(ColorParser.parseColor("&8- &7重载前缀配置。"));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
package cc.carm.plugin.userprefix.configuration;
|
||||
|
||||
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
||||
import cc.carm.lib.configuration.core.annotation.ConfigPath;
|
||||
import cc.carm.lib.configuration.core.annotation.HeaderComment;
|
||||
import cc.carm.lib.configuration.core.value.ConfigValue;
|
||||
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
|
||||
import cc.carm.lib.easyplugin.gui.configuration.GUIActionConfiguration;
|
||||
import cc.carm.lib.easyplugin.gui.configuration.GUIActionType;
|
||||
import cc.carm.lib.easyplugin.gui.configuration.GUIItemConfiguration;
|
||||
import cc.carm.lib.mineconfiguration.bukkit.value.ConfiguredItem;
|
||||
import cc.carm.lib.mineconfiguration.bukkit.value.ConfiguredSound;
|
||||
import cc.carm.plugin.userprefix.configuration.reader.GUIItemReader;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
public class PluginConfig extends ConfigurationRoot {
|
||||
|
||||
@HeaderComment({"开发者查错模式"})
|
||||
public static final ConfigValue<Boolean> DEBUG = ConfiguredValue.of(Boolean.class, false);
|
||||
|
||||
@HeaderComment({
|
||||
"统计数据设定",
|
||||
" 该选项用于帮助开发者统计插件版本与使用情况,且绝不会影响性能与使用体验。",
|
||||
" 当然,您也可以选择在这里关闭,或在plugins/bStats下的配置文件中关闭。"
|
||||
})
|
||||
public static final ConfigValue<Boolean> METRICS = ConfiguredValue.of(Boolean.class, true);
|
||||
|
||||
@HeaderComment({
|
||||
"检查更新设定",
|
||||
"该选项用于插件判断是否要检查更新,若您不希望插件检查更新并提示您,可以选择关闭。",
|
||||
"检查更新为异步操作,绝不会影响性能与使用体验。"
|
||||
})
|
||||
public static final ConfigValue<Boolean> CHECK_UPDATE = ConfiguredValue.of(Boolean.class, true);
|
||||
|
||||
@HeaderComment({"自定义存储位置设定", "可以规定到远程文件夹中去加载前缀配置"})
|
||||
public static final class CUSTOM_STORAGE {
|
||||
|
||||
@HeaderComment({"是否启用自定义存储位置"})
|
||||
public static final ConfigValue<Boolean> ENABLE = ConfiguredValue.of(Boolean.class, false);
|
||||
|
||||
@HeaderComment({
|
||||
"目标存储路径,必须指向一个文件夹。",
|
||||
"默认存储位置为 “插件文件夹”/prefixes",
|
||||
"支持绝对文件路径,如 \"/etc/minecraft/configurations/prefixes/\""
|
||||
})
|
||||
public static final ConfigValue<String> PATH = ConfiguredValue.of(String.class, "prefixes/");
|
||||
|
||||
}
|
||||
|
||||
@HeaderComment("功能设定")
|
||||
public static class FUNCTIONS {
|
||||
|
||||
@ConfigPath("on-name-prefix")
|
||||
@HeaderComment({"头顶与TabList前缀功能,该方法用到了玩家名计分板接口,如有冲突请关掉哦~"})
|
||||
public static final class NAME_PREFIX {
|
||||
|
||||
@HeaderComment("是否开启本功能")
|
||||
public static final ConfigValue<Boolean> ENABLE = ConfiguredValue.of(Boolean.class, true);
|
||||
|
||||
@HeaderComment("是否按降序排列,即权重越高的前缀显示在越上面;若为false则按升序排列。")
|
||||
public static final ConfigValue<Boolean> ORDER_DESC = ConfiguredValue.of(Boolean.class, true);
|
||||
|
||||
}
|
||||
|
||||
@ConfigPath("auto-prefix-use")
|
||||
@HeaderComment("自动使用前缀,即当玩家没有自己选择一个前缀的时候,会自动使用所拥有的的前缀中权重最高的那一个")
|
||||
public static final ConfigValue<Boolean> AUTO_USE = ConfiguredValue.of(Boolean.class, true);
|
||||
|
||||
|
||||
@HeaderComment({
|
||||
"聊天功能设定",
|
||||
"- 我不推荐使用本插件的聊天功能,而是建议使用其他的聊天插件。",
|
||||
"- 本插件仅仅提供了**最基本**的格式变量支持,不包含其他任何功能。",
|
||||
"- 注意聊天格式需要遵守Bukkit原格式,即不得缺失 “%1$s” 和 “%2$s” 。",
|
||||
"- 本插件的聊天功能不影响其他插件对聊天事件的操作。"
|
||||
})
|
||||
public static final class CHAT {
|
||||
|
||||
@HeaderComment("是否开启本功能")
|
||||
public static ConfigValue<Boolean> ENABLE = ConfiguredValue.of(Boolean.class, false);
|
||||
@HeaderComment({
|
||||
"聊天的格式,注意 “%1$s” 和 “%2$s” 不可缺少。",
|
||||
"- %1$s -> 玩家名", "- %2$s -> 聊天内容"
|
||||
})
|
||||
public static ConfigValue<String> FORMAT = ConfiguredValue.of(String.class, "<%1$s> %2$s");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@HeaderComment({"前缀GUI界面设定"})
|
||||
public static class GUI {
|
||||
|
||||
@HeaderComment("GUI的标题")
|
||||
public static final ConfigValue<String> TITLE = ConfiguredValue.of(String.class, "&f&l我的前缀 &8| 列表");
|
||||
|
||||
@HeaderComment("GUI中的按钮")
|
||||
public static final class ITEMS {
|
||||
|
||||
@HeaderComment("前往下一页的物品 (只有存在下一页时才会显示)")
|
||||
public static final ConfiguredItem NEXT_PAGE = ConfiguredItem.create()
|
||||
.defaultType(Material.ARROW)
|
||||
.defaultName("下一页")
|
||||
.defaultLore("&7&o右键可前往最后一页哦")
|
||||
.build();
|
||||
|
||||
@ConfigPath("previous-page")
|
||||
@HeaderComment({"前往上一页时的物品 (只有当前页不是第一页时才会显示)"})
|
||||
public static final ConfiguredItem PREV_PAGE = ConfiguredItem.create()
|
||||
.defaultType(Material.ARROW)
|
||||
.defaultName("上一页")
|
||||
.defaultLore("&7&o右键可前往第一页哦")
|
||||
.build();
|
||||
|
||||
@HeaderComment("GUI中其他的物品配置")
|
||||
public static final ConfigValue<GUIItemConfiguration> BACK = ConfiguredValue.builder(GUIItemConfiguration.class)
|
||||
.fromSection()
|
||||
.serializeValue(GUIItemConfiguration::serialize)
|
||||
.parseValue((v, d) -> GUIItemReader.readFrom(v))
|
||||
.defaults(new GUIItemConfiguration(
|
||||
Material.BARRIER, 0, "&c&l返回",
|
||||
Collections.singletonList("&f点击即可返回上一菜单"),
|
||||
Collections.singletonList(GUIActionConfiguration.of(GUIActionType.CHAT, "/menu")),
|
||||
Collections.singletonList(49)
|
||||
)).build();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@HeaderComment({"相关的声音,留空则不播放声音", "格式为 【声音名:音量:音调】 或 【声音名:音量】 或 【声音名】"})
|
||||
public static final class SOUNDS {
|
||||
|
||||
public static final ConfiguredSound GUI_OPEN = ConfiguredSound.of("BLOCK_NOTE_BLOCK_PLING", 0.5F, 0.8F);
|
||||
public static final ConfiguredSound GUI_CLICK = ConfiguredSound.of("UI_BUTTON_CLICK");
|
||||
public static final ConfiguredSound PREFIX_CHANGE = ConfiguredSound.of("ENTITY_VILLAGER_YES");
|
||||
public static final ConfiguredSound PREFIX_EXPIRED = ConfiguredSound.of("ENTITY_VILLAGER_NO");
|
||||
|
||||
}
|
||||
|
||||
@HeaderComment({"默认前缀配置"})
|
||||
public static final class DEFAULT_PREFIX {
|
||||
|
||||
@HeaderComment("默认前缀的显示名称,用于在消息提示中显示。")
|
||||
public static final ConfigValue<String> NAME = ConfiguredValue.of(String.class, "默认前缀");
|
||||
|
||||
@HeaderComment({"默认前缀的权重,默认为0。"})
|
||||
public static final ConfigValue<Integer> WEIGHT = ConfiguredValue.of(Integer.class, 0);
|
||||
|
||||
@HeaderComment({"默认前缀的内容,即用于显示的实际前缀"})
|
||||
public static final ConfigValue<String> CONTENT = ConfiguredValue.of(String.class, "&r");
|
||||
|
||||
@HeaderComment({"默认前缀的显示物品"})
|
||||
public static final class ITEM {
|
||||
|
||||
@HeaderComment({"当未选择默认前缀时显示的物品"})
|
||||
public static final ConfiguredItem NOT_USING = ConfiguredItem.create()
|
||||
.defaultType(Material.NAME_TAG)
|
||||
.defaultName("&f默认玩家前缀 &f(点击切换)")
|
||||
.defaultLore("", "&a➥ 点击切换到该前缀")
|
||||
.build();
|
||||
|
||||
@HeaderComment({"当选择了默认前缀时显示的物品"})
|
||||
public static final ConfiguredItem USING = ConfiguredItem.create()
|
||||
.defaultType(Material.NAME_TAG)
|
||||
.defaultEnchant(Enchantment.PROTECTION_ENVIRONMENTAL, 1)
|
||||
.defaultFlags(ItemFlag.HIDE_ENCHANTS)
|
||||
.defaultName("&f默认玩家前缀")
|
||||
.defaultLore("", "&a✔ 您正在使用该前缀")
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package cc.carm.plugin.userprefix.configuration;
|
||||
|
||||
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
||||
import cc.carm.lib.configuration.core.annotation.HeaderComment;
|
||||
import cc.carm.lib.mineconfiguration.bukkit.value.ConfiguredMessageList;
|
||||
|
||||
public class PluginMessages extends ConfigurationRoot {
|
||||
|
||||
public static final class COMMAND_USAGE {
|
||||
|
||||
public static ConfiguredMessageList<String> CONSOLE = ConfiguredMessageList.asStrings().defaults(
|
||||
"&f请输入 &b/prefix <玩家ID> &f为指定玩家打开前缀GUI。"
|
||||
).build();
|
||||
|
||||
public static ConfiguredMessageList<String> ADMIN = ConfiguredMessageList.asStrings().defaults(
|
||||
"&3&l用户前缀系统 &f帮助",
|
||||
"&8# &f/upa list",
|
||||
"&8- &7查看当前前缀列表。",
|
||||
"&8# &f/upa reload",
|
||||
"&8- &7重载前缀配置。"
|
||||
).build();
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static ConfiguredMessageList<String> SELECTED = ConfiguredMessageList.asStrings()
|
||||
.defaults("&7您选择了 &f%(name) &7作为当前显示的前缀。")
|
||||
.params("name").build();
|
||||
|
||||
public static ConfiguredMessageList<String> EXPIRED = ConfiguredMessageList.asStrings()
|
||||
.defaults(
|
||||
"&7您先前使用的前缀 &f%(oldName) &7已到期。",
|
||||
"&7现在已为您重新调整为 &f%(newName) &7。"
|
||||
).params("oldName", "newName").build();
|
||||
|
||||
public static ConfiguredMessageList<String> REMOVED = ConfiguredMessageList.asStrings()
|
||||
.defaults("&7您先前使用的前缀已被移除,现在已为您重新调整为 &f%(newName) &7。")
|
||||
.params("newName").build();
|
||||
|
||||
public static final class RELOAD {
|
||||
|
||||
public static ConfiguredMessageList<String> SUCCESS = ConfiguredMessageList.asStrings()
|
||||
.defaults("&a&l重载完成!&7耗时 &f%(time)ms&7,共加载了 &b%(count) &7个前缀。")
|
||||
.params("time", "count").build();
|
||||
|
||||
public static ConfiguredMessageList<String> FAILED = ConfiguredMessageList.asStrings()
|
||||
.defaults("&c&l重载出错!&7错误提示为 &8“&r%(error)&8”。")
|
||||
.params("error").build();
|
||||
}
|
||||
|
||||
|
||||
@HeaderComment("管理员使用的 “/upa list” 指令的格式")
|
||||
public static final class LIST {
|
||||
|
||||
public static ConfiguredMessageList<String> HEADER = ConfiguredMessageList.asStrings()
|
||||
.defaults("&3&l用户前缀系统 &f前缀列表").build();
|
||||
|
||||
public static ConfiguredMessageList<String> VALUE = ConfiguredMessageList.asStrings().defaults(
|
||||
"&8#%(weight) &f%(identifier)",
|
||||
"&8- &7显示名 &r%(name) &7权限 &r%(permission)",
|
||||
"&8- &7内容示例&r %(content) %(sender_name)"
|
||||
).params("weight", "identifier", "name", "permission", "sender_name").build();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package cc.carm.plugin.userprefix.configuration;
|
||||
|
||||
import cc.carm.plugin.userprefix.configuration.values.ConfigSound;
|
||||
import cc.carm.plugin.userprefix.configuration.values.ConfigValue;
|
||||
import cc.carm.plugin.userprefix.configuration.values.ConfigValueList;
|
||||
|
||||
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 Messages {
|
||||
|
||||
public static ConfigValueList<String> SELECTED = new ConfigValueList<>("messages.selected", String.class);
|
||||
public static ConfigValueList<String> EXPIRED = new ConfigValueList<>("messages.expired", String.class);
|
||||
|
||||
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package cc.carm.plugin.userprefix.configuration.prefix;
|
||||
|
||||
import cc.carm.lib.easyplugin.utils.ColorParser;
|
||||
import cc.carm.lib.mineconfiguration.bukkit.data.ItemConfig;
|
||||
import cc.carm.plugin.userprefix.manager.ServiceManager;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class PrefixConfig {
|
||||
|
||||
|
||||
private @Nullable File dataFile;
|
||||
private @Nullable FileConfiguration configuration;
|
||||
|
||||
protected final @NotNull String identifier;
|
||||
|
||||
protected final @NotNull String name;
|
||||
protected final @NotNull String content;
|
||||
|
||||
protected final int weight;
|
||||
|
||||
protected final @Nullable String permission;
|
||||
|
||||
protected final @NotNull ItemConfig itemHasPermission;
|
||||
protected final @Nullable ItemConfig itemNoPermission;
|
||||
protected final @Nullable ItemConfig itemWhenUsing;
|
||||
|
||||
public PrefixConfig(@NotNull String identifier, @NotNull String name,
|
||||
@NotNull String content, int weight, @Nullable String permission,
|
||||
@NotNull ItemConfig itemHasPermission,
|
||||
@Nullable ItemConfig itemWhenUsing,
|
||||
@Nullable ItemConfig itemNoPermission) {
|
||||
this.identifier = identifier;
|
||||
this.name = name;
|
||||
this.content = content;
|
||||
this.weight = weight;
|
||||
this.permission = permission;
|
||||
this.itemHasPermission = itemHasPermission;
|
||||
this.itemNoPermission = itemNoPermission;
|
||||
this.itemWhenUsing = itemWhenUsing;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getContent() {
|
||||
return ColorParser.parse(content);
|
||||
}
|
||||
|
||||
public int getWeight() {
|
||||
return weight;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getPermission() {
|
||||
return permission;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ItemStack getItemHasPermission(@Nullable Player player) {
|
||||
return this.itemHasPermission.getItemStack(player);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ItemStack getItemNoPermission(@Nullable Player player) {
|
||||
if (this.itemNoPermission == null) return null;
|
||||
return this.itemNoPermission.getItemStack(player);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ItemStack getItemWhenUsing(@Nullable Player player) {
|
||||
if (this.itemWhenUsing == null) return getItemHasPermission(player);
|
||||
else return this.itemWhenUsing.getItemStack(player);
|
||||
}
|
||||
|
||||
public boolean isPublic() {
|
||||
return getPermission() == null;
|
||||
}
|
||||
|
||||
public boolean isVisible(Player player) {
|
||||
return this.itemWhenUsing != null || checkPermission(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断某玩家是否有权限使用该前缀
|
||||
*
|
||||
* @param player 玩家
|
||||
* @return 若前缀标识不存在,则返回false;若前缀为默认前缀,或该前缀无权限,或玩家有该前缀的权限,则返回true。
|
||||
*/
|
||||
public boolean checkPermission(Player player) {
|
||||
return permission == null || ServiceManager.hasPermission(player, permission);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package cc.carm.plugin.userprefix.configuration.reader;
|
||||
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
||||
import cc.carm.lib.easyplugin.gui.configuration.GUIActionConfiguration;
|
||||
import cc.carm.lib.easyplugin.gui.configuration.GUIItemConfiguration;
|
||||
import org.bukkit.Material;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class GUIItemReader {
|
||||
|
||||
public static @Nullable GUIItemConfiguration readFrom(@Nullable ConfigurationWrapper section) {
|
||||
if (section == null) return null;
|
||||
String material = Optional.ofNullable(section.getString("type")).orElse("STONE");
|
||||
Material type = Optional.ofNullable(Material.matchMaterial(material)).orElse(Material.STONE);
|
||||
int data = section.getInt("data", 0);
|
||||
String name = section.getString("name");
|
||||
List<String> lore = section.getStringList("lore");
|
||||
|
||||
List<Integer> slots = section.getIntegerList("slots");
|
||||
int slot = section.getInt("slot", 0);
|
||||
|
||||
List<String> actionsString = section.getStringList("actions");
|
||||
List<GUIActionConfiguration> actions = new ArrayList<>();
|
||||
for (String actionString : actionsString) {
|
||||
GUIActionConfiguration action = GUIActionConfiguration.deserialize(actionString);
|
||||
if (action == null) continue;
|
||||
actions.add(action);
|
||||
}
|
||||
|
||||
return new GUIItemConfiguration(
|
||||
type, data, name, lore, actions,
|
||||
slots.size() > 0 ? slots : Collections.singletonList(slot)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package cc.carm.plugin.userprefix.configuration.values;
|
||||
|
||||
import cc.carm.plugin.userprefix.Main;
|
||||
import cc.carm.plugin.userprefix.manager.ConfigManager;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class ConfigSound {
|
||||
FileConfiguration source;
|
||||
String configSection;
|
||||
|
||||
Sound defaultValue;
|
||||
|
||||
public ConfigSound(String configSection) {
|
||||
this(configSection, null);
|
||||
}
|
||||
|
||||
public ConfigSound(String configSection, Sound defaultValue) {
|
||||
this.source = ConfigManager.getConfig();
|
||||
this.configSection = configSection;
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
public void set(Sound value, float volume) {
|
||||
this.source.set(this.configSection, value.name() + ":" + volume);
|
||||
this.save();
|
||||
}
|
||||
|
||||
public void set(Sound value, float volume, float pitch) {
|
||||
this.source.set(this.configSection, value.name() + ":" + volume + ":" + pitch);
|
||||
this.save();
|
||||
}
|
||||
|
||||
public void play(Player player) {
|
||||
Sound finalSound = defaultValue;
|
||||
float pitch = 1;
|
||||
float volume = 1;
|
||||
String soundString = this.source.getString(this.configSection);
|
||||
if (soundString != null) {
|
||||
String[] args = soundString.contains(":") ? soundString.split(":") : new String[]{soundString};
|
||||
try {
|
||||
if (args.length >= 1) finalSound = Sound.valueOf(args[0]);
|
||||
if (args.length >= 2) volume = Float.parseFloat(args[1]);
|
||||
if (args.length >= 3) volume = Float.parseFloat(args[2]);
|
||||
} catch (Exception exception) {
|
||||
Main.log("声音 " + this.configSection + " 配置错误,不存在 " + soundString + " ,请检查。");
|
||||
}
|
||||
}
|
||||
if (finalSound != null) {
|
||||
player.playSound(player.getLocation(), finalSound, volume, pitch);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void save() {
|
||||
ConfigManager.saveConfig();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package cc.carm.plugin.userprefix.configuration.values;
|
||||
|
||||
import cc.carm.plugin.userprefix.manager.ConfigManager;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
public class ConfigValue<V> {
|
||||
FileConfiguration source;
|
||||
String configSection;
|
||||
Class<V> clazz;
|
||||
V defaultValue;
|
||||
|
||||
public ConfigValue(String configSection, Class<V> clazz) {
|
||||
this(configSection, clazz, null);
|
||||
}
|
||||
|
||||
public ConfigValue(String configSection, Class<V> clazz, V defaultValue) {
|
||||
this.source = ConfigManager.getConfig();
|
||||
this.configSection = configSection;
|
||||
this.clazz = clazz;
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
public V get() {
|
||||
Object val = this.source.get(this.configSection, this.defaultValue);
|
||||
return this.clazz.isInstance(val) ? this.clazz.cast(val) : this.defaultValue;
|
||||
}
|
||||
|
||||
public void set(V value) {
|
||||
this.source.set(this.configSection, value);
|
||||
this.save();
|
||||
}
|
||||
|
||||
public void save() {
|
||||
ConfigManager.saveConfig();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package cc.carm.plugin.userprefix.configuration.values;
|
||||
|
||||
import cc.carm.plugin.userprefix.manager.ConfigManager;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ConfigValueList<V> {
|
||||
FileConfiguration source;
|
||||
String configSection;
|
||||
Class<V> clazz;
|
||||
|
||||
public ConfigValueList(String configSection, Class<V> clazz) {
|
||||
this.source = ConfigManager.getConfig();
|
||||
this.configSection = configSection;
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
public ArrayList<V> get() {
|
||||
List<?> list = this.source.getList(this.configSection);
|
||||
if (list == null) {
|
||||
return new ArrayList(0);
|
||||
} else {
|
||||
ArrayList<V> result = new ArrayList();
|
||||
|
||||
for (Object object : list) {
|
||||
if (this.clazz.isInstance(object)) {
|
||||
result.add(this.clazz.cast(object));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public void set(ArrayList<V> value) {
|
||||
this.source.set(this.configSection, value);
|
||||
this.save();
|
||||
}
|
||||
|
||||
public void save() {
|
||||
ConfigManager.saveConfig();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package cc.carm.plugin.userprefix.event;
|
||||
|
||||
import cc.carm.plugin.userprefix.Main;
|
||||
import cc.carm.plugin.userprefix.configuration.prefix.PrefixConfig;
|
||||
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;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class UserPrefixChangeEvent extends UserPrefixEvent implements Cancellable {
|
||||
|
||||
public static HandlerList handler = new HandlerList();
|
||||
|
||||
private boolean cancelled;
|
||||
|
||||
private final @Nullable PrefixConfig before;
|
||||
private @NotNull PrefixConfig after;
|
||||
|
||||
public UserPrefixChangeEvent(@NotNull Player who,
|
||||
@Nullable PrefixConfig before,
|
||||
@NotNull PrefixConfig after) {
|
||||
super(who);
|
||||
this.before = before;
|
||||
this.after = after;
|
||||
}
|
||||
|
||||
public @Nullable PrefixConfig getBefore() {
|
||||
return before;
|
||||
}
|
||||
|
||||
public @NotNull PrefixConfig getAfter() {
|
||||
return after;
|
||||
}
|
||||
|
||||
public void setAfter(@NotNull PrefixConfig 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;
|
||||
}
|
||||
|
||||
public static void call(@NotNull Player who,
|
||||
@Nullable PrefixConfig before,
|
||||
@NotNull PrefixConfig after,
|
||||
@Nullable Consumer<@Nullable PrefixConfig> finish) {
|
||||
Main.getInstance().callSync(new UserPrefixChangeEvent(who, before, after))
|
||||
.thenAccept((e) -> Optional.ofNullable(finish).ifPresent(f -> f.accept(e.getAfter())));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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,36 @@
|
||||
package cc.carm.plugin.userprefix.event;
|
||||
|
||||
import cc.carm.plugin.userprefix.Main;
|
||||
import cc.carm.plugin.userprefix.configuration.prefix.PrefixConfig;
|
||||
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 PrefixConfig expiredPrefix;
|
||||
|
||||
public UserPrefixExpireEvent(@NotNull Player who,
|
||||
@NotNull PrefixConfig expiredPrefix) {
|
||||
super(who);
|
||||
this.expiredPrefix = expiredPrefix;
|
||||
}
|
||||
|
||||
public @NotNull PrefixConfig getExpiredPrefix() {
|
||||
return expiredPrefix;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handler;
|
||||
}
|
||||
|
||||
public static void call(@NotNull Player player, @NotNull PrefixConfig currentPrefix) {
|
||||
Main.getInstance().callSync(new UserPrefixExpireEvent(player, currentPrefix));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +1,29 @@
|
||||
package cc.carm.plugin.userprefix.nametag;
|
||||
package cc.carm.plugin.userprefix.hooker;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scoreboard.Scoreboard;
|
||||
import org.bukkit.scoreboard.Team;
|
||||
import org.jetbrains.annotations.Range;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 用户头顶标签。
|
||||
*
|
||||
* @author LSeng, Tony, Carm
|
||||
*/
|
||||
public class UserNameTag {
|
||||
|
||||
public static final int MAX_ORDER = 999;
|
||||
|
||||
private final Player viewer;
|
||||
private Team team;
|
||||
private final Scoreboard sb;
|
||||
private int order = 99999;
|
||||
private int order = MAX_ORDER;
|
||||
private final Map<UUID, Integer> targetOrders = new HashMap<>();
|
||||
private final Map<UUID, String> previousTeamNames = new HashMap<>();
|
||||
|
||||
@@ -35,7 +43,7 @@ public class UserNameTag {
|
||||
/**
|
||||
* 设置自己的前缀
|
||||
*
|
||||
* @param prefix
|
||||
* @param prefix 前缀内容
|
||||
*/
|
||||
public void setPrefix(String prefix) {
|
||||
team.setPrefix(prefix);
|
||||
@@ -45,8 +53,8 @@ public class UserNameTag {
|
||||
/**
|
||||
* 设置某个玩家的前缀
|
||||
*
|
||||
* @param target
|
||||
* @param prefix
|
||||
* @param target 目标
|
||||
* @param prefix 前缀内容
|
||||
*/
|
||||
public void setPrefix(Player target, String prefix) {
|
||||
if (target == viewer) {
|
||||
@@ -63,11 +71,9 @@ public class UserNameTag {
|
||||
/**
|
||||
* 设置名字在TabList中的顺序
|
||||
*
|
||||
* @param order
|
||||
* @param order 顺序 (0~999)
|
||||
*/
|
||||
public void setOrder(int order) {
|
||||
if (order < 0 || order > 99999)
|
||||
throw new IllegalArgumentException("order must be in 0~99999");
|
||||
public void setOrder(@Range(from = 0, to = 999) int order) {
|
||||
this.order = order;
|
||||
targetOrders.put(viewer.getUniqueId(), order);
|
||||
update(viewer);
|
||||
@@ -78,16 +84,13 @@ public class UserNameTag {
|
||||
*
|
||||
* @param order 顺序
|
||||
*/
|
||||
public void setOrder(Player target, int order) {
|
||||
if (order < 0 || order > 99999)
|
||||
throw new IllegalArgumentException("order must be in 0~99999");
|
||||
public void setOrder(Player target, @Range(from = 0, to = 999) int order) {
|
||||
Team targetTeam = checkTeam(target);
|
||||
String teamName = order + UUID.randomUUID().toString().substring(0, 10);
|
||||
targetTeam.setDisplayName(teamName);
|
||||
targetOrders.put(target.getUniqueId(), order);
|
||||
update(viewer);
|
||||
if (viewer != target)
|
||||
update(target);
|
||||
if (viewer != target) update(target);
|
||||
}
|
||||
|
||||
public void update(Player target) {
|
||||
@@ -110,7 +113,7 @@ public class UserNameTag {
|
||||
team = newTeam;
|
||||
}
|
||||
} else {
|
||||
int order = targetOrders.getOrDefault(target.getUniqueId(), 99999);
|
||||
int order = targetOrders.getOrDefault(target.getUniqueId(), 999);
|
||||
String previousTeamName = previousTeamNames.get(target.getUniqueId());
|
||||
if (previousTeamName == null) {
|
||||
return;
|
||||
@@ -138,7 +141,7 @@ public class UserNameTag {
|
||||
}
|
||||
|
||||
private Team checkTeam(Player target) {
|
||||
int order = targetOrders.getOrDefault(target.getUniqueId(), 99999);
|
||||
int order = targetOrders.getOrDefault(target.getUniqueId(), 999);
|
||||
String name = order + target.getUniqueId().toString().substring(0, 10);
|
||||
Team targetTeam = this.sb.getTeam(name);
|
||||
if (targetTeam == null) {
|
||||
@@ -1,33 +1,31 @@
|
||||
package cc.carm.plugin.userprefix.hooker;
|
||||
|
||||
import cc.carm.plugin.userprefix.manager.PrefixManager;
|
||||
import cc.carm.plugin.userprefix.manager.UserManager;
|
||||
import cc.carm.plugin.userprefix.model.ConfiguredPrefix;
|
||||
import cc.carm.plugin.userprefix.Main;
|
||||
import cc.carm.plugin.userprefix.UserPrefixAPI;
|
||||
import cc.carm.plugin.userprefix.configuration.prefix.PrefixConfig;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class UserPrefixExpansion extends PlaceholderExpansion {
|
||||
|
||||
JavaPlugin plugin;
|
||||
protected final @NotNull Main plugin;
|
||||
protected final @NotNull List<String> placeholders = Arrays.asList(
|
||||
"%UserPrefix_prefix%", "%UserPrefix_weight%",
|
||||
"%UserPrefix_identifier%", "%UserPrefix_name%",
|
||||
"%UserPrefix_has_<Identifier>%"
|
||||
);
|
||||
|
||||
public UserPrefixExpansion(JavaPlugin plugin) {
|
||||
public UserPrefixExpansion(@NotNull Main plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<String> getPlaceholders() {
|
||||
List<String> placeholders = new ArrayList<>();
|
||||
placeholders.add("%UserPrefix_prefix%");
|
||||
placeholders.add("%UserPrefix_weight%");
|
||||
placeholders.add("%UserPrefix_identifier%");
|
||||
placeholders.add("%UserPrefix_name%");
|
||||
placeholders.add("%UserPrefix_has_<Identifier>%");
|
||||
return placeholders;
|
||||
return this.placeholders;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,25 +60,25 @@ public class UserPrefixExpansion extends PlaceholderExpansion {
|
||||
|
||||
switch (args[0].toLowerCase()) {
|
||||
case "identifier": {
|
||||
return UserManager.getPrefix(player).getIdentifier();
|
||||
return UserPrefixAPI.getUserManager().getPrefix(player).getIdentifier();
|
||||
}
|
||||
case "prefix": {
|
||||
return UserManager.getPrefix(player).getContent();
|
||||
return UserPrefixAPI.getUserManager().getPrefix(player).getContent();
|
||||
}
|
||||
case "name": {
|
||||
return UserManager.getPrefix(player).getName();
|
||||
return UserPrefixAPI.getUserManager().getPrefix(player).getName();
|
||||
}
|
||||
case "weight": {
|
||||
return Integer.toString(UserManager.getPrefix(player).getWeight());
|
||||
return Integer.toString(UserPrefixAPI.getUserManager().getPrefix(player).getWeight());
|
||||
}
|
||||
case "has": {
|
||||
if (args.length < 2) return "参数不足";
|
||||
ConfiguredPrefix prefix = PrefixManager.getPrefix(args[1]);
|
||||
PrefixConfig prefix = UserPrefixAPI.getPrefixManager().getPrefix(args[1]);
|
||||
if (prefix == null) return "该前缀不存在";
|
||||
return Boolean.toString(UserManager.isPrefixUsable(player, prefix));
|
||||
return Boolean.toString(prefix.checkPermission(player));
|
||||
}
|
||||
case "version": {
|
||||
return getVersion().replace("-SNAPSHOT", "");
|
||||
return getVersion();
|
||||
}
|
||||
default: {
|
||||
return "参数错误";
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package cc.carm.plugin.userprefix.listener;
|
||||
|
||||
import cc.carm.lib.easyplugin.utils.MessageUtils;
|
||||
import cc.carm.plugin.userprefix.Main;
|
||||
import cc.carm.plugin.userprefix.configuration.PluginConfig;
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
|
||||
public class ChatListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onChat(AsyncPlayerChatEvent event) {
|
||||
if (!PluginConfig.FUNCTIONS.CHAT.ENABLE.getNotNull()) return;
|
||||
|
||||
String format = PluginConfig.FUNCTIONS.CHAT.FORMAT.get();
|
||||
if (format == null || format.length() < 1) return;
|
||||
|
||||
try {
|
||||
event.setFormat(MessageUtils.setPlaceholders(event.getPlayer(), format));
|
||||
} catch (Exception exception) {
|
||||
Main.serve("请检查配置文件中聊天相关是否配置正确。");
|
||||
Main.serve("Please check the chat configuration.");
|
||||
exception.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package cc.carm.plugin.userprefix.listener;
|
||||
|
||||
import cc.carm.plugin.userprefix.manager.UserManager;
|
||||
import cc.carm.plugin.userprefix.UserPrefixAPI;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
@@ -8,17 +8,14 @@ import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
public class UserListener implements Listener {
|
||||
|
||||
|
||||
@EventHandler
|
||||
public void onJoin(PlayerJoinEvent event) {
|
||||
UserManager.initPlayer(event.getPlayer());
|
||||
UserPrefixAPI.getUserManager().initPlayer(event.getPlayer());
|
||||
}
|
||||
|
||||
|
||||
@EventHandler
|
||||
public void onLeave(PlayerQuitEvent event) {
|
||||
UserManager.unloadPlayer(event.getPlayer());
|
||||
UserPrefixAPI.getUserManager().unloadPlayer(event.getPlayer());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package cc.carm.plugin.userprefix.listener.processor;
|
||||
|
||||
import cc.carm.plugin.userprefix.manager.UserManager;
|
||||
import cc.carm.plugin.userprefix.Main;
|
||||
import cc.carm.plugin.userprefix.UserPrefixAPI;
|
||||
import cc.carm.plugin.userprefix.ui.PrefixSelectGUI;
|
||||
import net.luckperms.api.event.user.UserDataRecalculateEvent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -10,7 +12,14 @@ public class UserNodeUpdateProcessor {
|
||||
public static void process(UserDataRecalculateEvent event) {
|
||||
Player player = Bukkit.getPlayer(event.getUser().getUniqueId());
|
||||
if (player == null) return;
|
||||
UserManager.checkPrefix(player, true);
|
||||
UserPrefixAPI.getUserManager().checkPrefix(player, true);
|
||||
if (PrefixSelectGUI.openingUsers.contains(player)) {
|
||||
Main.getInstance().getScheduler().run(() -> {
|
||||
// 玩家权限更新,同步关闭其GUI,以令其重新打开刷新自己的前缀。
|
||||
player.closeInventory();
|
||||
PrefixSelectGUI.removeOpening(player);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,31 +1,51 @@
|
||||
package cc.carm.plugin.userprefix.manager;
|
||||
|
||||
import cc.carm.plugin.userprefix.Main;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||
import cc.carm.lib.easyplugin.utils.JarResourceUtils;
|
||||
import cc.carm.lib.mineconfiguration.bukkit.MineConfiguration;
|
||||
import cc.carm.plugin.userprefix.configuration.PluginConfig;
|
||||
import cc.carm.plugin.userprefix.configuration.PluginMessages;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ConfigManager {
|
||||
|
||||
private static FileConfiguration config;
|
||||
private final ConfigurationProvider<?> configProvider;
|
||||
private final ConfigurationProvider<?> messageProvider;
|
||||
|
||||
public static void initConfig() {
|
||||
Main.getInstance().saveDefaultConfig();
|
||||
Main.getInstance().reloadConfig();
|
||||
|
||||
config = Main.getInstance().getConfig();
|
||||
public ConfigManager(File dataFolder) {
|
||||
firstInitialize(dataFolder);
|
||||
this.configProvider = MineConfiguration.from(new File(dataFolder, "config.yml"));
|
||||
this.messageProvider = MineConfiguration.from(new File(dataFolder, "messages.yml"));
|
||||
this.configProvider.initialize(PluginConfig.class);
|
||||
this.messageProvider.initialize(PluginMessages.class);
|
||||
}
|
||||
|
||||
public static FileConfiguration getConfig() {
|
||||
return config;
|
||||
protected void firstInitialize(File dataFolder) {
|
||||
File configFile = new File(dataFolder, "config.yml");
|
||||
if (!configFile.exists()) {
|
||||
try {
|
||||
JarResourceUtils.copyFolderFromJar("en_US", dataFolder, JarResourceUtils.CopyOption.COPY_IF_NOT_EXIST);
|
||||
JarResourceUtils.copyFolderFromJar("prefixes", dataFolder, JarResourceUtils.CopyOption.COPY_IF_NOT_EXIST);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void reloadConfig() {
|
||||
Main.getInstance().reloadConfig();
|
||||
config = Main.getInstance().getConfig();
|
||||
}
|
||||
|
||||
public static void saveConfig() {
|
||||
Main.getInstance().saveConfig();
|
||||
public ConfigurationProvider<?> getConfigProvider() {
|
||||
return configProvider;
|
||||
}
|
||||
|
||||
public ConfigurationProvider<?> getMessageProvider() {
|
||||
return messageProvider;
|
||||
}
|
||||
|
||||
public void reload() throws Exception {
|
||||
getConfigProvider().reload();
|
||||
getMessageProvider().reload();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,141 +1,109 @@
|
||||
package cc.carm.plugin.userprefix.manager;
|
||||
|
||||
import cc.carm.lib.mineconfiguration.bukkit.data.ItemConfig;
|
||||
import cc.carm.lib.mineconfiguration.bukkit.source.CraftSectionWrapper;
|
||||
import cc.carm.plugin.userprefix.Main;
|
||||
import cc.carm.plugin.userprefix.model.ConfiguredPrefix;
|
||||
import cc.carm.plugin.userprefix.util.ItemStackFactory;
|
||||
import cc.carm.plugin.userprefix.configuration.PluginConfig;
|
||||
import cc.carm.plugin.userprefix.configuration.prefix.PrefixConfig;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class PrefixManager {
|
||||
|
||||
public static ConfiguredPrefix defaultPrefix;
|
||||
public static HashMap<String, ConfiguredPrefix> prefixes = new HashMap<>();
|
||||
protected static final String FOLDER_NAME = "prefixes";
|
||||
|
||||
protected @NotNull Map<String, PrefixConfig> prefixes = new HashMap<>();
|
||||
protected PrefixConfig defaultPrefix;
|
||||
|
||||
public static void init() {
|
||||
public int loadPrefixes() {
|
||||
loadDefaultPrefix();
|
||||
loadConfiguredPrefixes();
|
||||
Main.log("共加载了 " + prefixes.size() + " 个前缀。");
|
||||
return prefixes.size();
|
||||
}
|
||||
|
||||
public static void loadConfiguredPrefixes() {
|
||||
loadDefaultPrefix();
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
public void loadConfiguredPrefixes() {
|
||||
|
||||
ConfigurationSection prefixesSection = ConfigManager.getConfig().getConfigurationSection("prefixes");
|
||||
if (prefixesSection == null || prefixesSection.getKeys(false).isEmpty()) {
|
||||
Main.log("配置文件中暂无任何前缀配置,请检查。");
|
||||
File prefixDataFolder = getStorageFolder();
|
||||
if (!prefixDataFolder.isDirectory() || !prefixDataFolder.exists()) {
|
||||
prefixDataFolder.mkdir();
|
||||
}
|
||||
|
||||
String[] filesList = prefixDataFolder.list();
|
||||
if (filesList == null || filesList.length < 1) {
|
||||
Main.serve("配置文件夹中暂无任何前缀配置问,请检查。");
|
||||
Main.serve("There's no configured prefix.");
|
||||
Main.serve("Path: " + prefixDataFolder.getAbsolutePath());
|
||||
return;
|
||||
}
|
||||
|
||||
HashMap<String, ConfiguredPrefix> dataPrefixes = new HashMap<>();
|
||||
List<File> files = Arrays.stream(filesList)
|
||||
.map(s -> new File(prefixDataFolder, s))
|
||||
.filter(File::isFile)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
for (String prefixIdentifier : prefixesSection.getKeys(false)) {
|
||||
ConfigurationSection configuredPrefixSection = prefixesSection.getConfigurationSection(prefixIdentifier);
|
||||
if (configuredPrefixSection == null) continue;
|
||||
HashMap<String, PrefixConfig> loaded = new HashMap<>();
|
||||
|
||||
if (files.size() > 0) {
|
||||
for (File file : files) {
|
||||
try {
|
||||
String name = configuredPrefixSection.getString("name", "前缀名配置错误");
|
||||
String content = configuredPrefixSection.getString("content", "&r");
|
||||
String permission = configuredPrefixSection.getString("permission");
|
||||
int weight = configuredPrefixSection.getInt("weight", 1);
|
||||
|
||||
ItemStack itemHasPermission = configuredPrefixSection.getItemStack("itemHasPermission",
|
||||
new ItemStackFactory(Material.STONE).setDisplayName(name).addLore(" ").addLore("§a➥ 点击切换到该前缀").toItemStack()
|
||||
);
|
||||
ItemStack itemNoPermission = configuredPrefixSection.getItemStack("itemNoPermission", itemHasPermission);
|
||||
ItemStack itemUsing = configuredPrefixSection.getItemStack("itemUsing", itemHasPermission);
|
||||
|
||||
|
||||
Main.log("完成前缀加载 " + prefixIdentifier + " : " + name);
|
||||
|
||||
dataPrefixes.put(prefixIdentifier, new ConfiguredPrefix(prefixIdentifier, name, content, weight, permission, itemHasPermission, itemNoPermission, itemUsing));
|
||||
} catch (Exception exception) {
|
||||
Main.log("在加载前缀 " + prefixIdentifier + " 时出错,请检查配置!");
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
PrefixManager.prefixes.clear();
|
||||
PrefixManager.prefixes = dataPrefixes;
|
||||
}
|
||||
|
||||
public static void loadDefaultPrefix() {
|
||||
PrefixManager.defaultPrefix = null;
|
||||
ConfigurationSection defaultPrefixSection = ConfigManager.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);
|
||||
PrefixConfig prefix = adPrefix(file);
|
||||
Main.debugging("完成前缀加载 " + prefix.getIdentifier() + " : " + prefix.getName());
|
||||
loaded.put(prefix.getIdentifier(), prefix);
|
||||
} catch (Exception ex) {
|
||||
Main.log("在加载默认前缀时出错,请检查配置!");
|
||||
Main.serve("在加载前缀 " + file.getAbsolutePath() + " 时出错,请检查配置!");
|
||||
Main.serve("Error occurred when loading prefix #" + file.getAbsolutePath() + " !");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
PrefixManager.defaultPrefix = new ConfiguredPrefix("default", "默认前缀", "&r", 0, null,
|
||||
new ItemStackFactory(Material.NAME_TAG)
|
||||
.setDisplayName("&f默认前缀")
|
||||
.addLore(" ")
|
||||
.addLore("§a➥ 点击切换到该前缀")
|
||||
.toItemStack(),
|
||||
}
|
||||
}
|
||||
|
||||
this.prefixes = loaded;
|
||||
}
|
||||
|
||||
public void loadDefaultPrefix() {
|
||||
this.defaultPrefix = new PrefixConfig(
|
||||
"default",
|
||||
PluginConfig.DEFAULT_PREFIX.NAME.getNotNull(),
|
||||
PluginConfig.DEFAULT_PREFIX.CONTENT.getNotNull(),
|
||||
PluginConfig.DEFAULT_PREFIX.WEIGHT.getNotNull(),
|
||||
null,
|
||||
new ItemStackFactory(Material.NAME_TAG)
|
||||
.setDisplayName("&f默认前缀")
|
||||
.addLore(" ")
|
||||
.addLore("§a✔ 您正在使用该前缀")
|
||||
.addEnchant(Enchantment.DURABILITY, 1, false)
|
||||
.addFlag(ItemFlag.HIDE_ENCHANTS)
|
||||
.toItemStack()
|
||||
PluginConfig.DEFAULT_PREFIX.ITEM.NOT_USING.getNotNull(),
|
||||
PluginConfig.DEFAULT_PREFIX.ITEM.USING.get(),
|
||||
null
|
||||
);
|
||||
Main.debugging(" 完成默认前缀加载 " + defaultPrefix.getName());
|
||||
}
|
||||
|
||||
Main.log("完成默认前缀加载 " + defaultPrefix.getName());
|
||||
}
|
||||
|
||||
public static List<ConfiguredPrefix> getVisiblePrefix() {
|
||||
return PrefixManager.getPrefixes().values().stream()
|
||||
.filter(ConfiguredPrefix::isVisibleNoPermission)
|
||||
.sorted(Comparator.comparingInt(ConfiguredPrefix::getWeight))
|
||||
public List<PrefixConfig> getVisiblePrefix(Player player) {
|
||||
return getPrefixes().values().stream()
|
||||
.filter(c -> c.isVisible(player))
|
||||
.sorted(Comparator.comparingInt(PrefixConfig::getWeight))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ConfiguredPrefix getDefaultPrefix() {
|
||||
public PrefixConfig getDefaultPrefix() {
|
||||
return defaultPrefix;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HashMap<String, ConfiguredPrefix> getPrefixes() {
|
||||
public Map<String, PrefixConfig> getPrefixes() {
|
||||
return prefixes;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ConfiguredPrefix getPrefix(String identifier) {
|
||||
public PrefixConfig getPrefix(String identifier) {
|
||||
if (identifier == null) {
|
||||
return null;
|
||||
} else if (identifier.equalsIgnoreCase("default")) {
|
||||
@@ -146,4 +114,42 @@ public class PrefixManager {
|
||||
}
|
||||
|
||||
|
||||
protected File getStorageFolder() {
|
||||
if (PluginConfig.CUSTOM_STORAGE.ENABLE.getNotNull()) {
|
||||
return new File(PluginConfig.CUSTOM_STORAGE.PATH.getNotNull());
|
||||
} else {
|
||||
return new File(Main.getInstance().getDataFolder() + File.separator + FOLDER_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
public static @NotNull PrefixConfig adPrefix(@NotNull File file) throws Exception {
|
||||
FileConfiguration configuration = YamlConfiguration.loadConfiguration(file);
|
||||
String identifier = configuration.getString("identifier");
|
||||
if (identifier == null) throw new Exception("配置文件 " + file.getAbsolutePath() + " 中没有配置前缀的唯一标识。");
|
||||
|
||||
String name = configuration.getString("name");
|
||||
if (name == null) throw new Exception("配置文件 " + file.getAbsolutePath() + " 中没有配置前缀的显示名称。");
|
||||
|
||||
return new PrefixConfig(
|
||||
identifier, name,
|
||||
configuration.getString("content", "&r"),
|
||||
configuration.getInt("weight", 1),
|
||||
configuration.getString("permission"),
|
||||
readItem(
|
||||
configuration.getConfigurationSection("item.has-perm"),
|
||||
new ItemConfig(Material.STONE, name, Arrays.asList(" ", "§a➥ 点击切换到该前缀"))
|
||||
),
|
||||
readItem(configuration.getConfigurationSection("item.using"), null),
|
||||
readItem(configuration.getConfigurationSection("item.no-perm"), null)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Contract("_,!null->!null")
|
||||
protected static ItemConfig readItem(@Nullable ConfigurationSection section, @Nullable ItemConfig defaultValue) throws Exception {
|
||||
if (section == null) return defaultValue;
|
||||
else return ItemConfig.deserialize(CraftSectionWrapper.of(section));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -42,4 +42,8 @@ public class ServiceManager {
|
||||
return user.getCachedData().getPermissionData().checkPermission(permission).asBoolean();
|
||||
}
|
||||
|
||||
public static boolean hasPermission(Player player, String permission) {
|
||||
return hasPermission(getUser(player), permission);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package cc.carm.plugin.userprefix.manager;
|
||||
|
||||
import cc.carm.lib.easyplugin.gui.GUI;
|
||||
import cc.carm.plugin.userprefix.Main;
|
||||
import cc.carm.plugin.userprefix.configuration.PrefixConfig;
|
||||
import cc.carm.plugin.userprefix.model.ConfiguredPrefix;
|
||||
import cc.carm.plugin.userprefix.nametag.UserNameTag;
|
||||
import cc.carm.plugin.userprefix.UserPrefixAPI;
|
||||
import cc.carm.plugin.userprefix.configuration.PluginConfig;
|
||||
import cc.carm.plugin.userprefix.configuration.PluginMessages;
|
||||
import cc.carm.plugin.userprefix.configuration.prefix.PrefixConfig;
|
||||
import cc.carm.plugin.userprefix.event.UserPrefixChangeEvent;
|
||||
import cc.carm.plugin.userprefix.event.UserPrefixExpireEvent;
|
||||
import cc.carm.plugin.userprefix.hooker.UserNameTag;
|
||||
import cc.carm.plugin.userprefix.ui.PrefixSelectGUI;
|
||||
import cc.carm.plugin.userprefix.util.MessageUtil;
|
||||
import cc.carm.plugin.userprefix.util.gui.GUI;
|
||||
import net.luckperms.api.model.user.User;
|
||||
import net.luckperms.api.node.NodeType;
|
||||
import net.luckperms.api.node.types.MetaNode;
|
||||
@@ -20,32 +23,46 @@ import java.util.stream.Collectors;
|
||||
|
||||
public class UserManager {
|
||||
|
||||
public static HashMap<UUID, UserNameTag> nameTags = new HashMap<>();
|
||||
// LuckPerms竟然会把所有的metaKey全部转换为小写... 那我这里就直接写成小写吧~
|
||||
public static final @NotNull String META_KEY = "userprefix";
|
||||
|
||||
public static HashSet<UUID> checkingPlayers = new HashSet<>();
|
||||
protected final HashMap<UUID, UserNameTag> nameTags = new HashMap<>();
|
||||
|
||||
public static UserNameTag getNameTag(Player player) {
|
||||
protected final HashSet<UUID> checkingPlayers = new HashSet<>();
|
||||
|
||||
@Nullable
|
||||
public UserNameTag getNameTag(Player player) {
|
||||
if (PluginConfig.FUNCTIONS.NAME_PREFIX.ENABLE.getNotNull()) {
|
||||
if (nameTags.containsKey(player.getUniqueId())) {
|
||||
return nameTags.get(player.getUniqueId());
|
||||
} else {
|
||||
return createNameTag(player);
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static UserNameTag createNameTag(Player player) {
|
||||
@NotNull
|
||||
public UserNameTag createNameTag(Player player) {
|
||||
if (nameTags.containsKey(player.getUniqueId())) return nameTags.get(player.getUniqueId());
|
||||
UserNameTag nameTag = new UserNameTag(player);
|
||||
nameTags.put(player.getUniqueId(), nameTag);
|
||||
return nameTag;
|
||||
}
|
||||
|
||||
public static void initPlayer(Player player) {
|
||||
UserManager.checkPrefix(player, false);
|
||||
if (PrefixConfig.Functions.NAME_PREFIX.get()) {
|
||||
UserManager.createNameTag(player);
|
||||
UserManager.updatePrefixView(player, true);
|
||||
public void initPlayer(Player player) {
|
||||
checkPrefix(player, false);
|
||||
if (PluginConfig.FUNCTIONS.NAME_PREFIX.ENABLE.getNotNull()) {
|
||||
createNameTag(player);
|
||||
updatePrefixView(player, true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void unloadPlayer(Player player) {
|
||||
public void unloadPlayer(Player player) {
|
||||
PrefixSelectGUI.removeOpening(player);
|
||||
UserManager.unloadNameTag(player.getUniqueId());
|
||||
UserManager.checkingPlayers.remove(player.getUniqueId());
|
||||
unloadNameTag(player.getUniqueId());
|
||||
checkingPlayers.remove(player.getUniqueId());
|
||||
GUI.removeOpenedGUI(player); // 清空打开过的GUI缓存 (用于记录物品点击的
|
||||
}
|
||||
|
||||
@@ -55,31 +72,35 @@ public class UserManager {
|
||||
* @param player 玩家
|
||||
* @param loadOthers 是否为玩家更新其他人的前缀(一般用于加入游戏)
|
||||
*/
|
||||
public static void updatePrefixView(Player player, boolean loadOthers) {
|
||||
ConfiguredPrefix playerPrefix = UserManager.getPrefix(player);
|
||||
|
||||
public void updatePrefixView(Player player, boolean loadOthers) {
|
||||
if (!PluginConfig.FUNCTIONS.NAME_PREFIX.ENABLE.getNotNull()) return; //未启用的情况下,不需要进行任何操作。
|
||||
UserNameTag tag = getNameTag(player);
|
||||
if (tag == null) return; //未启用的情况下,不需要进行任何操作。
|
||||
|
||||
PrefixConfig playerPrefix = getPrefix(player);
|
||||
boolean descOrder = PluginConfig.FUNCTIONS.NAME_PREFIX.ORDER_DESC.getNotNull();
|
||||
|
||||
tag.setPrefix(playerPrefix.getContent());
|
||||
tag.setOrder(playerPrefix.getWeight());
|
||||
tag.setOrder(descOrder ? 999 - playerPrefix.getWeight() : playerPrefix.getWeight());
|
||||
|
||||
Main.debug("为玩家 " + player.getName() + " 设置了 " + player.getName() + "的前缀为 #" + playerPrefix.getWeight() + " " + playerPrefix.getName());
|
||||
Main.debugging("为玩家 " + player.getName() + " 设置了 " + player.getName() + "的前缀为 #" + playerPrefix.getWeight() + " " + playerPrefix.getName());
|
||||
|
||||
for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
|
||||
if (onlinePlayer.equals(player)) continue;
|
||||
UserNameTag onlinePlayerTag = getNameTag(onlinePlayer);
|
||||
|
||||
if (onlinePlayerTag != null) {
|
||||
onlinePlayerTag.setPrefix(player, playerPrefix.getContent());
|
||||
onlinePlayerTag.setOrder(player, playerPrefix.getWeight());
|
||||
Main.debug("为玩家 " + onlinePlayer.getName() + " 设置了 " + player.getName() + "的前缀为 #" + playerPrefix.getWeight() + " " + playerPrefix.getName());
|
||||
onlinePlayerTag.setOrder(player, descOrder ? 999 - playerPrefix.getWeight() : playerPrefix.getWeight());
|
||||
Main.debugging("为玩家 " + onlinePlayer.getName() + " 设置了 " + player.getName() + "的前缀为 #" + playerPrefix.getWeight() + " " + playerPrefix.getName());
|
||||
|
||||
}
|
||||
|
||||
if (loadOthers) {
|
||||
ConfiguredPrefix onlinePlayerPrefix = UserManager.getPrefix(onlinePlayer);
|
||||
PrefixConfig onlinePlayerPrefix = getPrefix(onlinePlayer);
|
||||
tag.setPrefix(onlinePlayer, onlinePlayerPrefix.getContent());
|
||||
tag.setOrder(onlinePlayer, onlinePlayerPrefix.getWeight());
|
||||
Main.debug("为玩家 " + player.getName() + " 设置了 " + onlinePlayer.getName() + "的前缀为 #" + onlinePlayerPrefix.getWeight() + " " + onlinePlayerPrefix.getName());
|
||||
tag.setOrder(onlinePlayer, descOrder ? 999 - onlinePlayerPrefix.getWeight() : onlinePlayerPrefix.getWeight());
|
||||
Main.debugging("为玩家 " + player.getName() + " 设置了 " + onlinePlayer.getName() + "的前缀为 #" + onlinePlayerPrefix.getWeight() + " " + onlinePlayerPrefix.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,7 +111,7 @@ public class UserManager {
|
||||
* @param player 玩家
|
||||
* @param updateView 是否更新头顶与TabList中的前缀
|
||||
*/
|
||||
public static void checkPrefix(Player player, boolean updateView) {
|
||||
public void checkPrefix(Player player, boolean updateView) {
|
||||
if (checkingPlayers.contains(player.getUniqueId())) {
|
||||
/*
|
||||
* 这里为了避免极短时间内的重复触发导致多次判断且结果相同误导玩家,
|
||||
@@ -99,24 +120,39 @@ public class UserManager {
|
||||
return;
|
||||
}
|
||||
checkingPlayers.add(player.getUniqueId());
|
||||
String currentPrefixIdentifier = UserManager.getPrefixData(player);
|
||||
ConfiguredPrefix currentPrefix = PrefixManager.getPrefix(currentPrefixIdentifier);
|
||||
if (!UserManager.isPrefixUsable(player, currentPrefixIdentifier)) {
|
||||
ConfiguredPrefix newPrefix = UserManager.getHighestPrefix(player);
|
||||
// 更新前缀
|
||||
UserManager.setPrefix(player, newPrefix, updateView);
|
||||
String currentPrefixData = getPrefixData(player);
|
||||
|
||||
if (!isPrefixUsable(player, currentPrefixData)) {
|
||||
PrefixConfig currentPrefix = UserPrefixAPI.getPrefixManager().getPrefix(currentPrefixData);
|
||||
PrefixConfig newPrefix = getHighestPrefix(player);
|
||||
|
||||
if (currentPrefix != null) {
|
||||
//当前前缀不为空,则代表属于前缀过期的情况
|
||||
UserPrefixExpireEvent.call(player, currentPrefix);
|
||||
|
||||
// 发送消息
|
||||
MessageUtil.sendWithPlaceholders(player, PrefixConfig.Messages.EXPIRED.get(),
|
||||
new String[]{"%(newName)", "%(oldName)"},
|
||||
new Object[]{newPrefix.getName(), currentPrefix != null ? currentPrefix.getName() : currentPrefixIdentifier}
|
||||
);
|
||||
PluginMessages.EXPIRED.send(player, newPrefix.getName(), currentPrefix.getName());
|
||||
|
||||
// 播放声音
|
||||
PrefixConfig.Sounds.PREFIX_EXPIRED.play(player);
|
||||
}
|
||||
checkingPlayers.remove(player.getUniqueId());
|
||||
PluginConfig.SOUNDS.PREFIX_EXPIRED.playTo(player);
|
||||
} else {
|
||||
// 当前前缀为空,则代表是旧的前缀不存在了,
|
||||
PluginMessages.REMOVED.send(player, newPrefix.getName(), currentPrefixData);
|
||||
}
|
||||
|
||||
public static void unloadNameTag(UUID uuid) {
|
||||
UserPrefixChangeEvent.call(player, currentPrefix, newPrefix, (after) -> {
|
||||
if (after != null) {
|
||||
setPrefix(player, after, updateView);
|
||||
}
|
||||
checkingPlayers.remove(player.getUniqueId());
|
||||
});
|
||||
|
||||
} else {
|
||||
checkingPlayers.remove(player.getUniqueId());
|
||||
}
|
||||
}
|
||||
|
||||
public void unloadNameTag(UUID uuid) {
|
||||
nameTags.remove(uuid);
|
||||
}
|
||||
|
||||
@@ -128,13 +164,13 @@ public class UserManager {
|
||||
* @return 前缀配置
|
||||
*/
|
||||
@NotNull
|
||||
public static ConfiguredPrefix getPrefix(Player player) {
|
||||
public PrefixConfig 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;
|
||||
PrefixConfig prefix = UserPrefixAPI.getPrefixManager().getPrefix(identifier);
|
||||
return prefix == null ? UserPrefixAPI.getDefaultPrefix() : prefix;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +181,7 @@ public class UserManager {
|
||||
* @param prefix 前缀配置
|
||||
* @param updateView 是否更新头顶上、TabList的前缀
|
||||
*/
|
||||
public static void setPrefix(Player player, ConfiguredPrefix prefix, boolean updateView) {
|
||||
public void setPrefix(Player player, PrefixConfig prefix, boolean updateView) {
|
||||
setPrefixData(player, prefix.getIdentifier());
|
||||
if (updateView) updatePrefixView(player, false);
|
||||
}
|
||||
@@ -157,10 +193,10 @@ public class UserManager {
|
||||
* @return 可用前缀列表
|
||||
*/
|
||||
@NotNull
|
||||
public static List<ConfiguredPrefix> getUsablePrefixes(Player player) {
|
||||
return PrefixManager.getPrefixes().values().stream()
|
||||
.filter(configuredPrefix -> isPrefixUsable(player, configuredPrefix)) //过滤出玩家可用的前缀
|
||||
.sorted(Comparator.comparingInt(ConfiguredPrefix::getWeight)) // 以前缀排序
|
||||
public List<PrefixConfig> getUsablePrefixes(Player player) {
|
||||
return UserPrefixAPI.getPrefixManager().getPrefixes().values().stream()
|
||||
.filter(prefix -> prefix.checkPermission(player)) //过滤出玩家可用的前缀
|
||||
.sorted(Comparator.comparingInt(PrefixConfig::getWeight)) // 以前缀排序
|
||||
.collect(Collectors.toList()); // 返回集合
|
||||
}
|
||||
|
||||
@@ -173,14 +209,14 @@ public class UserManager {
|
||||
* @return 权限内容
|
||||
*/
|
||||
@NotNull
|
||||
public static ConfiguredPrefix getHighestPrefix(Player player) {
|
||||
if (PrefixConfig.Functions.AUTO_USE.get()) {
|
||||
public PrefixConfig getHighestPrefix(Player player) {
|
||||
if (PluginConfig.FUNCTIONS.AUTO_USE.getNotNull()) {
|
||||
// 关闭了自动选择,就直接给默认的前缀,让玩家自己去设置吧~
|
||||
return PrefixManager.getDefaultPrefix();
|
||||
return UserPrefixAPI.getDefaultPrefix();
|
||||
}
|
||||
return getUsablePrefixes(player).stream()
|
||||
.max(Comparator.comparingInt(ConfiguredPrefix::getWeight)) // 取权重最大
|
||||
.orElseGet(PrefixManager::getDefaultPrefix); // 啥都没有? 返回默认前缀。
|
||||
.max(Comparator.comparingInt(PrefixConfig::getWeight)) // 取权重最大
|
||||
.orElseGet(UserPrefixAPI::getDefaultPrefix); // 啥都没有? 返回默认前缀。
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -190,36 +226,25 @@ public class UserManager {
|
||||
* @param prefixIdentifier 前缀标识
|
||||
* @return 若前缀标识不存在,则返回false;若前缀为默认前缀,或该前缀无权限,或玩家有该前缀的权限,则返回true。
|
||||
*/
|
||||
public static boolean isPrefixUsable(Player player, String prefixIdentifier) {
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean isPrefixUsable(Player player, String prefixIdentifier) {
|
||||
if (prefixIdentifier == null || prefixIdentifier.equalsIgnoreCase("default")) return true;
|
||||
ConfiguredPrefix prefix = PrefixManager.getPrefix(prefixIdentifier);
|
||||
if (prefix == null) return false;
|
||||
return isPrefixUsable(player, prefix);
|
||||
PrefixConfig prefix = UserPrefixAPI.getPrefixManager().getPrefix(prefixIdentifier);
|
||||
return prefix != null && prefix.checkPermission(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断一个前缀对某玩家是否可用
|
||||
*
|
||||
* @param player 玩家
|
||||
* @param configuredPrefix 前缀配置
|
||||
* @return 若前缀标识不存在,则返回false;若前缀为默认前缀,或该前缀无权限,或玩家有该前缀的权限,则返回true。
|
||||
*/
|
||||
public static boolean isPrefixUsable(Player player, ConfiguredPrefix configuredPrefix) {
|
||||
return configuredPrefix.getPermission() == null //为null的话说明无需权限了
|
||||
|| ServiceManager.hasPermission(ServiceManager.getUser(player), configuredPrefix.getPermission());
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到用户当前正在使用的前缀Identifier。
|
||||
* 该方法通过LuckPerms的MetaData实现,因此可以通过指令去操作。
|
||||
*
|
||||
* @param player 玩家
|
||||
* @return 正在使用的前缀Identifier(若不存在则返回null)
|
||||
* @return 正在使用的前缀Identifier(若不存在则返回null, 代表未设置前缀)
|
||||
*/
|
||||
@Nullable
|
||||
public static String getPrefixData(Player player) {
|
||||
public String getPrefixData(Player player) {
|
||||
return ServiceManager.getAPI().getMetaData(player)
|
||||
.getMetaValue("userprefix", String::valueOf)
|
||||
.getMetaValue(META_KEY, String::valueOf)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@@ -230,11 +255,11 @@ public class UserManager {
|
||||
* @param player 玩家
|
||||
* @param prefixIdentifier 前缀的标识
|
||||
*/
|
||||
public static void setPrefixData(Player player, String prefixIdentifier) {
|
||||
public void setPrefixData(Player player, String prefixIdentifier) {
|
||||
User user = ServiceManager.getUser(player);
|
||||
clearPrefixData(player); // 清除掉旧的数据,LuckPerms不会去覆盖一个Meta,需要手动清除。
|
||||
if (prefixIdentifier != null) {
|
||||
user.data().add(MetaNode.builder("userprefix", prefixIdentifier).build());
|
||||
user.data().add(MetaNode.builder(META_KEY, prefixIdentifier).build());
|
||||
ServiceManager.getService().getUserManager().saveUser(user); // 保存数据
|
||||
}
|
||||
}
|
||||
@@ -244,11 +269,9 @@ public class UserManager {
|
||||
*
|
||||
* @param player 玩家
|
||||
*/
|
||||
public static void clearPrefixData(Player player) {
|
||||
public void clearPrefixData(Player player) {
|
||||
User user = ServiceManager.getUser(player);
|
||||
// LuckPerms竟然会把所有的metaKey全部转换为小写... 那我这里就直接写成小写吧~
|
||||
user.data().clear(NodeType.META.predicate(mn -> mn.getMetaKey().equals("userprefix")));
|
||||
user.data().clear(NodeType.META.predicate(mn -> mn.getMetaKey().equals(META_KEY)));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
package cc.carm.plugin.userprefix.model;
|
||||
|
||||
import cc.carm.plugin.userprefix.util.ColorParser;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class ConfiguredPrefix {
|
||||
|
||||
String identifier;
|
||||
|
||||
String name;
|
||||
String content;
|
||||
|
||||
int weight;
|
||||
|
||||
String permission;
|
||||
|
||||
ItemStack itemHasPermission;
|
||||
ItemStack itemNoPermission;
|
||||
ItemStack itemWhenUsing;
|
||||
|
||||
public ConfiguredPrefix(String identifier, String name, String content, int weight, String permission, ItemStack itemHasPermission, ItemStack itemNoPermission, ItemStack itemWhenUsing) {
|
||||
this.identifier = identifier;
|
||||
this.name = name;
|
||||
this.content = content;
|
||||
this.weight = weight;
|
||||
this.permission = permission;
|
||||
this.itemHasPermission = itemHasPermission;
|
||||
this.itemNoPermission = itemNoPermission;
|
||||
this.itemWhenUsing = itemWhenUsing;
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return ColorParser.parseColor(content);
|
||||
}
|
||||
|
||||
public int getWeight() {
|
||||
return weight;
|
||||
}
|
||||
|
||||
public String getPermission() {
|
||||
return permission;
|
||||
}
|
||||
|
||||
public ItemStack getItemHasPermission() {
|
||||
return itemHasPermission;
|
||||
}
|
||||
|
||||
public ItemStack getItemNoPermission() {
|
||||
return itemNoPermission;
|
||||
}
|
||||
|
||||
public ItemStack getItemWhenUsing() {
|
||||
return itemWhenUsing;
|
||||
}
|
||||
|
||||
public boolean isVisibleNoPermission() {
|
||||
return this.itemNoPermission != null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
package cc.carm.plugin.userprefix.ui;
|
||||
|
||||
import cc.carm.plugin.userprefix.configuration.PrefixConfig;
|
||||
import cc.carm.plugin.userprefix.util.MessageUtil;
|
||||
import cc.carm.plugin.userprefix.util.gui.GUIType;
|
||||
import cc.carm.plugin.userprefix.manager.PrefixManager;
|
||||
import cc.carm.plugin.userprefix.manager.UserManager;
|
||||
import cc.carm.plugin.userprefix.model.ConfiguredPrefix;
|
||||
import cc.carm.plugin.userprefix.util.gui.AutoPagedGUI;
|
||||
import cc.carm.plugin.userprefix.util.gui.GUIItem;
|
||||
import cc.carm.lib.easyplugin.gui.GUIItem;
|
||||
import cc.carm.lib.easyplugin.gui.GUIType;
|
||||
import cc.carm.lib.easyplugin.gui.paged.AutoPagedGUI;
|
||||
import cc.carm.plugin.userprefix.UserPrefixAPI;
|
||||
import cc.carm.plugin.userprefix.configuration.PluginConfig;
|
||||
import cc.carm.plugin.userprefix.configuration.PluginMessages;
|
||||
import cc.carm.plugin.userprefix.configuration.prefix.PrefixConfig;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
|
||||
@@ -22,12 +21,13 @@ public class PrefixSelectGUI extends AutoPagedGUI {
|
||||
Player player;
|
||||
|
||||
public PrefixSelectGUI(Player player) {
|
||||
super(GUIType.SIXBYNINE, "&f&l我的前缀 &8| 列表", 10, 43);
|
||||
super(GUIType.SIX_BY_NINE, PluginConfig.GUI.TITLE.get(), 10, 43);
|
||||
this.player = player;
|
||||
|
||||
setPreviousPageSlot(18);
|
||||
setNextPageSlot(26);
|
||||
|
||||
loadBackButton();
|
||||
loadItems();
|
||||
}
|
||||
|
||||
@@ -35,34 +35,43 @@ public class PrefixSelectGUI extends AutoPagedGUI {
|
||||
return player;
|
||||
}
|
||||
|
||||
public void loadBackButton() {
|
||||
PluginConfig.GUI.ITEMS.BACK.getOptional().ifPresent(item -> item.setupItems(player, this));
|
||||
}
|
||||
|
||||
public void loadItems() {
|
||||
List<ConfiguredPrefix> prefixList = new ArrayList<>();
|
||||
prefixList.add(PrefixManager.getDefaultPrefix());
|
||||
prefixList.addAll(PrefixManager.getVisiblePrefix());
|
||||
List<PrefixConfig> prefixList = new ArrayList<>();
|
||||
prefixList.add(UserPrefixAPI.getPrefixManager().getDefaultPrefix());
|
||||
prefixList.addAll(UserPrefixAPI.getPrefixManager().getVisiblePrefix(player)); //只需要读取看得见的
|
||||
|
||||
ConfiguredPrefix usingPrefix = UserManager.getPrefix(getPlayer());
|
||||
PrefixConfig usingPrefix = UserPrefixAPI.getUserManager().getPrefix(getPlayer());
|
||||
|
||||
for (ConfiguredPrefix prefix : prefixList) {
|
||||
for (PrefixConfig prefix : prefixList) {
|
||||
if (prefix.getIdentifier().equals(usingPrefix.getIdentifier())) {
|
||||
addItem(new GUIItem(prefix.getItemWhenUsing() != null ? prefix.getItemWhenUsing() : prefix.getItemHasPermission()));
|
||||
} else if (UserManager.isPrefixUsable(player, prefix)) {
|
||||
addItem(new GUIItem(prefix.getItemHasPermission()) {
|
||||
addItem(new GUIItem(prefix.getItemWhenUsing(player) != null ? prefix.getItemWhenUsing(player) : prefix.getItemHasPermission(player)));
|
||||
} else if (prefix.checkPermission(player)) {
|
||||
addItem(new GUIItem(prefix.getItemHasPermission(player)) {
|
||||
@Override
|
||||
public void onClick(ClickType type) {
|
||||
if (UserManager.isPrefixUsable(player, prefix)) { //再次检查,防止打开GUI后、选择前的时间段内权限消失
|
||||
player.closeInventory();
|
||||
UserManager.setPrefix(player, prefix, true);
|
||||
|
||||
PrefixConfig.Sounds.PREFIX_CHANGE.play(player);
|
||||
MessageUtil.sendWithPlaceholders(player, PrefixConfig.Messages.SELECTED.get(),
|
||||
new String[]{"%(name)"},
|
||||
new Object[]{prefix.getName()});
|
||||
//再次检查,防止打开GUI后、选择前的时间段内权限消失
|
||||
if (prefix.checkPermission(player)) {
|
||||
UserPrefixAPI.getUserManager().setPrefix(player, prefix, true);
|
||||
|
||||
PluginConfig.SOUNDS.PREFIX_CHANGE.playTo(player);
|
||||
PluginMessages.SELECTED.send(player, prefix.getName());
|
||||
} else {
|
||||
PluginConfig.SOUNDS.GUI_CLICK.playTo(player);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
addItem(new GUIItem(prefix.getItemNoPermission()));
|
||||
addItem(new GUIItem(prefix.getItemNoPermission(player)) {
|
||||
@Override
|
||||
public void onClick(ClickType type) {
|
||||
PluginConfig.SOUNDS.GUI_CLICK.playTo(player);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +80,7 @@ public class PrefixSelectGUI extends AutoPagedGUI {
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
openingUsers.remove(player);
|
||||
removeOpening(player);
|
||||
}
|
||||
|
||||
public static void removeOpening(Player player) {
|
||||
@@ -82,10 +91,12 @@ public class PrefixSelectGUI extends AutoPagedGUI {
|
||||
for (Player player : new HashSet<>(openingUsers)) {
|
||||
player.closeInventory();
|
||||
}
|
||||
openingUsers.clear();
|
||||
}
|
||||
|
||||
public static void open(Player player) {
|
||||
PrefixConfig.Sounds.GUI_OPEN.play(player);
|
||||
player.closeInventory(); // 防止冲突
|
||||
PluginConfig.SOUNDS.GUI_OPEN.playTo(player);
|
||||
new PrefixSelectGUI(player).openGUI(player);
|
||||
openingUsers.add(player);
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
package cc.carm.plugin.userprefix.util;
|
||||
|
||||
public class ColorParser {
|
||||
|
||||
public static String parseColor(final String text) {
|
||||
return text.replaceAll("&", "§").replace("§§", "&");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
package cc.carm.plugin.userprefix.util;
|
||||
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ItemStackFactory {
|
||||
ItemStack item;
|
||||
|
||||
private ItemStackFactory() {
|
||||
}
|
||||
|
||||
public ItemStackFactory(ItemStack is) {
|
||||
this.item = is.clone();
|
||||
}
|
||||
|
||||
public ItemStackFactory(Material type) {
|
||||
this(type, 1);
|
||||
}
|
||||
|
||||
public ItemStackFactory(Material type, int amount) {
|
||||
this(type, amount, (short) 0);
|
||||
}
|
||||
|
||||
public ItemStackFactory(Material type, int amount, short data) {
|
||||
this.item = new ItemStack(type, amount, data);
|
||||
}
|
||||
|
||||
public ItemStackFactory(Material type, int amount, int data) {
|
||||
this(type, amount, (short) data);
|
||||
}
|
||||
|
||||
public ItemStack toItemStack() {
|
||||
return this.item;
|
||||
}
|
||||
|
||||
public ItemStackFactory setType(Material type) {
|
||||
this.item.setType(type);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackFactory setDurability(int i) {
|
||||
this.item.setDurability((short) i);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackFactory setAmount(int a) {
|
||||
this.item.setAmount(a);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackFactory setDisplayName(@NotNull String name) {
|
||||
ItemMeta im = this.item.getItemMeta();
|
||||
if (im != null) {
|
||||
im.setDisplayName(ColorParser.parseColor(name));
|
||||
this.item.setItemMeta(im);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackFactory setLore(@NotNull List<String> loreList) {
|
||||
ItemMeta im = this.item.getItemMeta();
|
||||
if (im != null) {
|
||||
im.setLore(
|
||||
loreList.stream()
|
||||
.map(ColorParser::parseColor)
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
this.item.setItemMeta(im);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackFactory addLore(@NotNull String s) {
|
||||
ItemMeta im = this.item.getItemMeta();
|
||||
if (im != null) {
|
||||
List<String> lore = im.getLore() != null ? im.getLore() : new ArrayList<>();
|
||||
lore.add(ColorParser.parseColor(s));
|
||||
im.setLore(lore);
|
||||
this.item.setItemMeta(im);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackFactory addEnchant(@NotNull Enchantment enchant, int level, boolean ignoreLevelRestriction) {
|
||||
ItemMeta im = this.item.getItemMeta();
|
||||
if (im != null) {
|
||||
im.addEnchant(enchant, level, ignoreLevelRestriction);
|
||||
this.item.setItemMeta(im);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackFactory removeEnchant(@NotNull Enchantment enchant) {
|
||||
ItemMeta im = this.item.getItemMeta();
|
||||
if (im != null) {
|
||||
im.removeEnchant(enchant);
|
||||
this.item.setItemMeta(im);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackFactory addFlag(@NotNull ItemFlag flag) {
|
||||
ItemMeta im = this.item.getItemMeta();
|
||||
if (im != null) {
|
||||
im.addItemFlags(flag);
|
||||
this.item.setItemMeta(im);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackFactory removeFlag(@NotNull ItemFlag flag) {
|
||||
ItemMeta im = this.item.getItemMeta();
|
||||
if (im != null) {
|
||||
im.removeItemFlags(flag);
|
||||
this.item.setItemMeta(im);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackFactory setUnbreakable(boolean unbreakable) {
|
||||
ItemMeta im = this.item.getItemMeta();
|
||||
if (im != null) {
|
||||
im.setUnbreakable(unbreakable);
|
||||
this.item.setItemMeta(im);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package cc.carm.plugin.userprefix.util;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class MessageUtil {
|
||||
|
||||
public static void send(Player player, List<String> messages) {
|
||||
for (String s : messages) {
|
||||
player.sendMessage(ColorParser.parseColor(s));
|
||||
}
|
||||
}
|
||||
|
||||
public static void send(Player player, String... messages) {
|
||||
send(player, Arrays.asList(messages));
|
||||
}
|
||||
|
||||
public static void sendWithPlaceholders(Player player, String... messages) {
|
||||
sendWithPlaceholders(player, Arrays.asList(messages));
|
||||
}
|
||||
|
||||
public static void sendWithPlaceholders(Player player, List<String> messages) {
|
||||
send(player, PlaceholderAPI.setPlaceholders(player, messages));
|
||||
}
|
||||
|
||||
public static void sendWithPlaceholders(Player player, List<String> messages, String param, Object value) {
|
||||
sendWithPlaceholders(player, messages, new String[]{param}, new Object[]{value});
|
||||
}
|
||||
|
||||
public static void sendWithPlaceholders(Player player, List<String> messages, String[] params, Object[] values) {
|
||||
sendWithPlaceholders(player, 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) {
|
||||
List<String> list = new ArrayList<>();
|
||||
for (String message : messages) {
|
||||
String afterMessage = message;
|
||||
for (Map.Entry<String, Object> entry : params.entrySet()) {
|
||||
afterMessage = afterMessage.replace(entry.getKey(), entry.getValue().toString());
|
||||
}
|
||||
list.add(afterMessage);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
package cc.carm.plugin.userprefix.util.gui;
|
||||
|
||||
import cc.carm.plugin.userprefix.configuration.PrefixConfig;
|
||||
import cc.carm.plugin.userprefix.util.ItemStackFactory;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class AutoPagedGUI extends CommonPagedGUI {
|
||||
|
||||
ItemStack previousPageUI;
|
||||
ItemStack nextPageUI;
|
||||
ItemStack noPreviousPageUI;
|
||||
ItemStack noNextPageUI;
|
||||
int previousPageSlot = -1;
|
||||
int nextPageSlot = -1;
|
||||
|
||||
public AutoPagedGUI(GUIType type, String name, int[] range) {
|
||||
super(type, name, range);
|
||||
}
|
||||
|
||||
public AutoPagedGUI(GUIType type, String name, int a, int b) {
|
||||
super(type, name, a, b);
|
||||
}
|
||||
|
||||
public void setPreviousPageUI(ItemStack lastPageUI) {
|
||||
this.previousPageUI = lastPageUI;
|
||||
}
|
||||
|
||||
public void setNextPageUI(ItemStack nextPageUI) {
|
||||
this.nextPageUI = nextPageUI;
|
||||
}
|
||||
|
||||
public void setNoPreviousPageUI(ItemStack noPreviousPageUI) {
|
||||
this.noPreviousPageUI = noPreviousPageUI;
|
||||
}
|
||||
|
||||
public void setNoNextPageUI(ItemStack noNextPageUI) {
|
||||
this.noNextPageUI = noNextPageUI;
|
||||
}
|
||||
|
||||
public void setPreviousPageSlot(int slot) {
|
||||
this.previousPageSlot = slot;
|
||||
}
|
||||
|
||||
public void setNextPageSlot(int slot) {
|
||||
this.nextPageSlot = slot;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void openGUI(Player user) {
|
||||
if (previousPageSlot >= 0)
|
||||
if (hasPreviousPage()) {
|
||||
setItem(previousPageSlot, new GUIItem(previousPageUI == null ? new ItemStackFactory(Material.ARROW)
|
||||
.setDisplayName("&f上一页")
|
||||
.addLore("&7&o右键可前往第一页哦")
|
||||
.toItemStack() : previousPageUI) {
|
||||
@Override
|
||||
public void onClick(ClickType type) {
|
||||
if (type == ClickType.RIGHT) {
|
||||
goFirstPage();
|
||||
} else {
|
||||
goPreviousPage();
|
||||
}
|
||||
PrefixConfig.Sounds.GUI_CLICK.play(user);
|
||||
openGUI(user);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (previousPageSlot >= 0)
|
||||
if (hasNextPage()) {
|
||||
setItem(nextPageSlot, new GUIItem(nextPageUI == null ? new ItemStackFactory(Material.ARROW)
|
||||
.setDisplayName("下一页")
|
||||
.addLore("&7&o右键可前往最后一页哦")
|
||||
.toItemStack() : nextPageUI) {
|
||||
@Override
|
||||
public void onClick(ClickType type) {
|
||||
if (type == ClickType.RIGHT) {
|
||||
goLastPage();
|
||||
} else {
|
||||
goNextPage();
|
||||
}
|
||||
PrefixConfig.Sounds.GUI_CLICK.play(user);
|
||||
openGUI(user);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
super.openGUI(user);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
package cc.carm.plugin.userprefix.util.gui;
|
||||
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class CommonPagedGUI extends PagedGUI {
|
||||
|
||||
private int[] range;
|
||||
|
||||
int a;
|
||||
int b;
|
||||
|
||||
int lineA;
|
||||
int columnA;
|
||||
int lineB;
|
||||
int columnB;
|
||||
|
||||
private CommonPagedGUI(GUIType type, String name) {
|
||||
super(type, name);
|
||||
}
|
||||
|
||||
public CommonPagedGUI(GUIType type, String Name, int[] range) {
|
||||
super(type, Name);
|
||||
Arrays.sort(range);
|
||||
this.range = range;
|
||||
|
||||
}
|
||||
|
||||
public CommonPagedGUI(GUIType type, String Name, int a, int b) {
|
||||
super(type, Name);
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
toRange(a, b);
|
||||
}
|
||||
|
||||
/*
|
||||
int[] matrix = new int[]{
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8,
|
||||
9, 10, 11, 12, 13, 14, 15, 16, 17,
|
||||
18, 19, 20, 21, 22, 23, 24, 25, 26,
|
||||
27, 28, 29, 30, 31, 32, 33, 34, 35,
|
||||
36, 37, 38, 39, 40, 41, 42, 43, 44,
|
||||
45, 46, 47, 48, 49, 50, 51, 52, 53
|
||||
}
|
||||
*/
|
||||
|
||||
private void toRange(int a, int b) {
|
||||
if (a > b) {
|
||||
a = a ^ b;
|
||||
b = a ^ b;
|
||||
a = a ^ b;
|
||||
}
|
||||
|
||||
lineA = getLine(a);
|
||||
columnA = getColumn(a);
|
||||
lineB = getLine(b);
|
||||
columnB = getColumn(b);
|
||||
|
||||
if (lineB > this.items.length / 9)
|
||||
throw new IndexOutOfBoundsException("页面内容范围超过了GUI的大小");
|
||||
|
||||
int[] range = new int[(lineB - lineA + 1) * (columnB - columnA + 1)];
|
||||
|
||||
for (int i = 0, l = 0; i < this.items.length; i++) {
|
||||
int li = getLine(i);
|
||||
int ci = getColumn(i);
|
||||
if (li >= lineA && li <= lineB && ci >= columnA && ci <= columnB) {
|
||||
range[l] = i;
|
||||
l++;
|
||||
}
|
||||
}
|
||||
|
||||
this.range = range;
|
||||
}
|
||||
|
||||
int getLine(int i) {
|
||||
return i / 9 + 1;
|
||||
}
|
||||
|
||||
int getColumn(int i) {
|
||||
return i % 9 + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPreviousPage() {
|
||||
return page > 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNextPage() {
|
||||
return page < getLastPageNumber();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 前往第一页
|
||||
*/
|
||||
public void goFirstPage() {
|
||||
if (hasPreviousPage())
|
||||
this.page = 1;
|
||||
else
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 前往最后一页
|
||||
*/
|
||||
public void goLastPage() {
|
||||
if (hasNextPage())
|
||||
this.page = getLastPageNumber();
|
||||
else
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 得到最后一页的页码
|
||||
*
|
||||
* @return 最后一页的页码
|
||||
*/
|
||||
public int getLastPageNumber() {
|
||||
return (this.container.size() / range.length) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到第一页的页码
|
||||
*
|
||||
* @return 第一页页码(默认为1)
|
||||
*/
|
||||
public int getFirstPageNumber() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void openGUI(Player player) {
|
||||
if (container.isEmpty()) {
|
||||
super.openGUI(player);
|
||||
return;
|
||||
}
|
||||
List<GUIItem> list = new ArrayList<>();
|
||||
int start = (page - 1) * range.length;
|
||||
for (int i = start; i < start + range.length; i++) {
|
||||
if (i < container.size()) {
|
||||
list.add(container.get(i));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
int i = 0;
|
||||
for (int index : range) {
|
||||
setItem(index, null);
|
||||
}
|
||||
for (int index : range) {
|
||||
if (i < list.size()) {
|
||||
setItem(index, list.get(i));
|
||||
i++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
super.openGUI(player);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,291 +0,0 @@
|
||||
package cc.carm.plugin.userprefix.util.gui;
|
||||
|
||||
import cc.carm.plugin.userprefix.Main;
|
||||
import cc.carm.plugin.userprefix.util.ColorParser;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.inventory.InventoryDragEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class GUI {
|
||||
|
||||
private static final HashMap<Player, GUI> openedGUIs = new HashMap<>();
|
||||
|
||||
GUIType type;
|
||||
String name;
|
||||
public GUIItem[] items;
|
||||
public Inventory inv;
|
||||
|
||||
boolean setCancelledIfClickOnTarget = true;
|
||||
boolean setCancelledIfClickOnSelf = true;
|
||||
boolean setCancelledIfClickOnOuter = true;
|
||||
|
||||
Map<String, Object> flags;
|
||||
|
||||
public Listener listener;
|
||||
|
||||
public GUI(GUIType type, String name) {
|
||||
this.type = type;
|
||||
this.name = ColorParser.parseColor(name);
|
||||
switch (type) {
|
||||
case ONEBYNINE:
|
||||
this.items = new GUIItem[9];
|
||||
break;
|
||||
case TWOBYNINE:
|
||||
this.items = new GUIItem[18];
|
||||
break;
|
||||
case THREEBYNINE:
|
||||
this.items = new GUIItem[27];
|
||||
break;
|
||||
case FOURBYNINE:
|
||||
this.items = new GUIItem[36];
|
||||
break;
|
||||
case FIVEBYNINE:
|
||||
this.items = new GUIItem[45];
|
||||
break;
|
||||
case SIXBYNINE:
|
||||
this.items = new GUIItem[54];
|
||||
break;
|
||||
case CANCEL:
|
||||
default:
|
||||
this.items = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public final void setItem(int index, GUIItem item) {
|
||||
if (item == null) {
|
||||
this.items[index] = new GUIItem(new ItemStack(Material.AIR));
|
||||
} else {
|
||||
this.items[index] = item;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加GUI Item
|
||||
*
|
||||
* @param item
|
||||
* @param index
|
||||
*/
|
||||
public void setItem(GUIItem item, int... index) {
|
||||
for (int i : index) {
|
||||
setItem(i, item);
|
||||
}
|
||||
}
|
||||
|
||||
public GUIItem getItem(int index) {
|
||||
return this.items[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新玩家箱子的视图
|
||||
*/
|
||||
public void updateView() {
|
||||
if (this.inv != null) {
|
||||
List<HumanEntity> viewers = this.inv.getViewers();
|
||||
for (int index = 0; index < this.items.length; index++) {
|
||||
if (items[index] == null) {
|
||||
inv.setItem(index, new ItemStack(Material.AIR));
|
||||
} else {
|
||||
inv.setItem(index, items[index].display);
|
||||
}
|
||||
}
|
||||
for (HumanEntity p : viewers) {
|
||||
((Player) p).updateInventory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否取消点击GUI内物品的事件
|
||||
* 如果不取消,玩家可以从GUI中拿取物品。
|
||||
*
|
||||
* @param b 是否取消
|
||||
*/
|
||||
public void setCancelledIfClickOnTarget(boolean b) {
|
||||
this.setCancelledIfClickOnTarget = b;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否取消点击自己背包内物品的事件
|
||||
* 如果不取消,玩家可以从自己的背包中拿取物品。
|
||||
*
|
||||
* @param b 是否取消
|
||||
*/
|
||||
public void setCancelledIfClickOnSelf(boolean b) {
|
||||
this.setCancelledIfClickOnSelf = b;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否取消点击GUI外的事件
|
||||
* 如果不取消,玩家可以把物品从GUI或背包中丢出去
|
||||
*
|
||||
* @param b 是否取消
|
||||
*/
|
||||
public void setCancelledIfClickOnOuter(boolean b) {
|
||||
this.setCancelledIfClickOnOuter = b;
|
||||
}
|
||||
|
||||
public void addFlag(String flag, Object obj) {
|
||||
if (this.flags == null) this.flags = new HashMap<>();
|
||||
this.flags.put(flag, obj);
|
||||
}
|
||||
|
||||
public Object getFlag(String flag) {
|
||||
if (this.flags == null) return null;
|
||||
else
|
||||
return this.flags.get(flag);
|
||||
}
|
||||
|
||||
public void setFlag(String flag, Object obj) {
|
||||
if (this.flags == null) this.flags = new HashMap<>();
|
||||
this.flags.replace(flag, obj);
|
||||
}
|
||||
|
||||
public void removeFlag(String flag) {
|
||||
if (this.flags == null) this.flags = new HashMap<>();
|
||||
this.flags.remove(flag);
|
||||
}
|
||||
|
||||
public void rawClickListener(InventoryClickEvent event) {
|
||||
}
|
||||
|
||||
public void openGUI(Player player) {
|
||||
Inventory inv;
|
||||
if (this.type == GUIType.CANCEL) {
|
||||
throw new NullPointerException("被取消或不存在的GUI");
|
||||
}
|
||||
inv = Bukkit.createInventory(null, this.items.length, this.name);
|
||||
|
||||
for (int index = 0; index < this.items.length; index++) {
|
||||
if (items[index] == null) {
|
||||
inv.setItem(index, new ItemStack(Material.AIR));
|
||||
} else {
|
||||
inv.setItem(index, items[index].display);
|
||||
}
|
||||
}
|
||||
setOpenedGUI(player, this);
|
||||
this.inv = inv;
|
||||
player.openInventory(inv);
|
||||
|
||||
if (listener == null)
|
||||
Bukkit.getPluginManager().registerEvents(listener = new Listener() {
|
||||
@EventHandler
|
||||
public void onInventoryClickEvent(InventoryClickEvent event) {
|
||||
if (!(event.getWhoClicked() instanceof Player)) return;
|
||||
Player p = (Player) event.getWhoClicked();
|
||||
rawClickListener(event);
|
||||
if (event.getSlot() != -999) {
|
||||
try {
|
||||
if (getOpenedGUI(p) == GUI.this
|
||||
&& event.getClickedInventory() != null
|
||||
&& event.getClickedInventory().equals(GUI.this.inv)
|
||||
&& GUI.this.items[event.getSlot()] != null) {
|
||||
GUI.this.items[event.getSlot()].realRawClickAction(event);
|
||||
}
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
System.err.print("err cause by GUI(" + GUI.this + "), name=" + name);
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
} else if (setCancelledIfClickOnOuter) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
if (hasOpenedGUI(p)
|
||||
&& getOpenedGUI(p) == GUI.this
|
||||
&& event.getClickedInventory() != null) {
|
||||
if (event.getClickedInventory().equals(GUI.this.inv)) {
|
||||
if (setCancelledIfClickOnTarget) event.setCancelled(true);
|
||||
|
||||
if (event.getSlot() != -999 && GUI.this.items[event.getSlot()] != null) {
|
||||
if (GUI.this.items[event.getSlot()].isActionActive()) {
|
||||
GUI.this.items[event.getSlot()].onClick(event.getClick());
|
||||
GUI.this.items[event.getSlot()].rawClickAction(event);
|
||||
if (!GUI.this.items[event.getSlot()].actions.isEmpty()) {
|
||||
for (GUIItem.GUIClickAction action : GUI.this.items[event.getSlot()].actions) {
|
||||
action.run(event.getClick(), player);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!GUI.this.items[event.getSlot()].actionsIgnoreActive.isEmpty()) {
|
||||
for (GUIItem.GUIClickAction action : GUI.this.items[event.getSlot()].actionsIgnoreActive) {
|
||||
action.run(event.getClick(), player);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (event.getClickedInventory().equals(p.getInventory()) && setCancelledIfClickOnSelf) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDrag(InventoryDragEvent e) {
|
||||
if (e.getWhoClicked() instanceof Player) {
|
||||
Player p = (Player) e.getWhoClicked();
|
||||
if (e.getInventory().equals(inv) || e.getInventory().equals(p.getInventory())) {
|
||||
GUI.this.onDrag(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryCloseEvent(InventoryCloseEvent event) {
|
||||
if (event.getPlayer() instanceof Player && event.getInventory().equals(inv)) {
|
||||
Player p = (Player) event.getPlayer();
|
||||
if (event.getInventory().equals(inv)) {
|
||||
HandlerList.unregisterAll(this);
|
||||
listener = null;
|
||||
removeOpenedGUI(p);
|
||||
onClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}, Main.getInstance());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 拖动GUI内物品是执行的代码
|
||||
*
|
||||
* @param event InventoryDragEvent
|
||||
*/
|
||||
public void onDrag(InventoryDragEvent event) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭GUI时执行的代码
|
||||
*/
|
||||
public void onClose() {
|
||||
}
|
||||
|
||||
|
||||
public static void setOpenedGUI(Player player, GUI gui) {
|
||||
openedGUIs.put(player, gui);
|
||||
}
|
||||
|
||||
public static boolean hasOpenedGUI(Player player) {
|
||||
return openedGUIs.containsKey(player);
|
||||
}
|
||||
|
||||
public static GUI getOpenedGUI(Player player) {
|
||||
return openedGUIs.get(player);
|
||||
}
|
||||
|
||||
public static void removeOpenedGUI(Player player) {
|
||||
openedGUIs.remove(player);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
package cc.carm.plugin.userprefix.util.gui;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class GUIItem {
|
||||
|
||||
ItemStack display;
|
||||
boolean actionActive = true;
|
||||
|
||||
public Set<GUIClickAction> actions = new HashSet<>();
|
||||
public Set<GUIClickAction> actionsIgnoreActive = new HashSet<>();
|
||||
|
||||
public GUIItem(ItemStack display) {
|
||||
this.display = display;
|
||||
}
|
||||
|
||||
public final ItemStack getDisplay() {
|
||||
return this.display;
|
||||
}
|
||||
|
||||
public final void setDisplay(ItemStack display) {
|
||||
this.display = display;
|
||||
}
|
||||
|
||||
public final boolean isActionActive() {
|
||||
return this.actionActive;
|
||||
}
|
||||
|
||||
public final void setActionActive(boolean b) {
|
||||
actionActive = b;
|
||||
}
|
||||
|
||||
/**
|
||||
* 玩家点击GUI后执行的代码
|
||||
*
|
||||
* @param type 点击的类型
|
||||
*/
|
||||
public void onClick(ClickType type) {
|
||||
|
||||
}
|
||||
|
||||
public void addClickAction(GUIClickAction action) {
|
||||
actions.add(action);
|
||||
}
|
||||
|
||||
public void addActionIgnoreActive(GUIClickAction action) {
|
||||
actionsIgnoreActive.add(action);
|
||||
}
|
||||
|
||||
public void rawClickAction(InventoryClickEvent event) {
|
||||
|
||||
}
|
||||
|
||||
public void realRawClickAction(InventoryClickEvent event) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 玩家点击GUI后执行的代码
|
||||
*
|
||||
* @param player 点击GUI的玩家
|
||||
*/
|
||||
public void customAction(Player player) {
|
||||
|
||||
}
|
||||
|
||||
public abstract static class GUIClickAction {
|
||||
public abstract void run(ClickType type, Player player);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package cc.carm.plugin.userprefix.util.gui;
|
||||
|
||||
/**
|
||||
* @author LSeng
|
||||
*/
|
||||
public enum GUIType {
|
||||
|
||||
ONEBYNINE,
|
||||
TWOBYNINE,
|
||||
THREEBYNINE,
|
||||
FOURBYNINE,
|
||||
FIVEBYNINE,
|
||||
SIXBYNINE,
|
||||
CANCEL;
|
||||
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
package cc.carm.plugin.userprefix.util.gui;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class PagedGUI extends GUI {
|
||||
|
||||
List<GUIItem> container = new ArrayList<>();
|
||||
public int page = 1;
|
||||
|
||||
public PagedGUI(GUIType type, String name) {
|
||||
super(type, name);
|
||||
}
|
||||
|
||||
public int addItem(GUIItem i) {
|
||||
container.add(i);
|
||||
return container.size() - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从GUI中移除一个物品
|
||||
*
|
||||
* @param item 物品
|
||||
*/
|
||||
public void removeItem(GUIItem item) {
|
||||
container.remove(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从GUI中移除一个物品
|
||||
*
|
||||
* @param slot 物品格子数
|
||||
*/
|
||||
public void removeItem(int slot) {
|
||||
container.remove(slot);
|
||||
}
|
||||
|
||||
public List<GUIItem> getItemsContainer() {
|
||||
return new ArrayList<>(container);
|
||||
}
|
||||
|
||||
/**
|
||||
* 前往上一页
|
||||
*/
|
||||
public void goPreviousPage() {
|
||||
if (hasPreviousPage())
|
||||
page--;
|
||||
else
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 前往下一页
|
||||
*/
|
||||
public void goNextPage() {
|
||||
if (hasNextPage())
|
||||
page++;
|
||||
else
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return 是否有上一页
|
||||
*/
|
||||
public abstract boolean hasPreviousPage();
|
||||
|
||||
/**
|
||||
* @return 是否有下一页
|
||||
*/
|
||||
public abstract boolean hasNextPage();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
&f __ __ &3___ ____
|
||||
&f / / / /__ ___ ____&3/ _ \_______ / _(_)_ __
|
||||
&f/ /_/ (_-</ -_) __&3/ ___/ __/ -_) _/ /\ \ /
|
||||
&f\____/___/\__/_/ &3/_/ /_/ \__/_//_//_\_\
|
||||
&8| &fUser&3Prefix &8(&fv${project.version}&8) &7by &bYourCraft
|
||||
&8| &7更多详情信息请参阅 &f${project.url} &7。
|
||||
@@ -1,100 +0,0 @@
|
||||
version: ${project.version}
|
||||
|
||||
debug: false
|
||||
|
||||
functions:
|
||||
OnNamePrefix: true # 是否给头顶上添加前缀,该方法用到了头顶的那个计分板,如有冲突请关掉哦~
|
||||
autoUsePrefix: true # 自动前缀显示 当玩家没有自己选择一个前缀的时候,会自动使用所拥有的的前缀中权重最高的那一个
|
||||
|
||||
messages:
|
||||
selected:
|
||||
- "&7您选择了 &f%(name) &7作为当前显示的前缀。"
|
||||
expired:
|
||||
- "&7您先前使用的前缀 &f%(oldName) &7已到期。"
|
||||
- "&7现在已为您重新调整为 &f%(newName) &7。"
|
||||
|
||||
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✔ 您正在使用该前缀"
|
||||
|
||||
prefixes:
|
||||
VIP:
|
||||
name: "&b&lPro&b" # [必须] 名字(切换的时候左下角会弹提示 用的就是这个名字)
|
||||
content: "§b§lPro §b" # [必须] 显示在名字前面的内容
|
||||
weight: 1 # [必须] 权重,用于GUI里面的排序(越大显示在越后面)和自动前缀显示
|
||||
permission: "yc.pro" # [非必须] 检测的权限,如果没有就是人人都能用,也代表不用配置“itemNoPermission”了(因为压根不可能显示没权限时候的物品)
|
||||
itemHasPermission: # [必须] 当有权限的时候会显示这个Item
|
||||
==: org.bukkit.inventory.ItemStack
|
||||
type: DIAMOND
|
||||
meta:
|
||||
==: ItemMeta
|
||||
meta-type: UNSPECIFIC
|
||||
display-name: "§b§lPro §b会员前缀"
|
||||
lore:
|
||||
- "§7Pro会员专属称号"
|
||||
- ""
|
||||
- "§f尊贵的Pro会员专属称号。"
|
||||
- "§f您将获得多种特权与更好的游戏体验。"
|
||||
- ""
|
||||
- "§a➥ 点击切换到该前缀"
|
||||
itemUsing: # [非必需] 当有权限的时候会显示这个Item,如果没有这个配置就自动显示“itemHasPermission”的。
|
||||
==: 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✔ 您正在使用该前缀"
|
||||
itemNoPermission: # [非必需] 如果没有权限就会显示这个item。如果不配置该物品,则玩家没有使用权限时不会显示在GUI里面。
|
||||
==: 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+会员以使用该前缀!"
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# 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"
|
||||
|
||||
item:
|
||||
# itemHasPermission [Necessary]
|
||||
# This Item will be displayed when player has permission
|
||||
has-perm:
|
||||
type: DIAMOND
|
||||
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".
|
||||
using:
|
||||
type: DIAMOND
|
||||
name: "&b&lVIP Prefix"
|
||||
enchants:
|
||||
PROTECTION_ENVIRONMENTAL: 1 #Add an enchantment so it looks like it’s 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.
|
||||
no-perm:
|
||||
type: INK_SACK
|
||||
data: 8
|
||||
name: "&b&lVIP &c(Buy it!)"
|
||||
lore:
|
||||
- ""
|
||||
- "&e✯ Buy the VIP to use it!"
|
||||
@@ -1,14 +1,24 @@
|
||||
main: cc.carm.plugin.userprefix.Main
|
||||
name: UserPrefix
|
||||
main: ${project.package}.Main
|
||||
name: ${project.name}
|
||||
version: ${project.version}
|
||||
authors:
|
||||
- Carm
|
||||
- YourCraft
|
||||
- ${project.organization.name}
|
||||
- SakuraGame
|
||||
website: ${project.url}
|
||||
description: ${project.description}
|
||||
api-version: 1.13
|
||||
|
||||
depend:
|
||||
- LuckPerms
|
||||
softdepend:
|
||||
- PlaceholderAPI
|
||||
|
||||
permissions:
|
||||
"UserPrefix.admin":
|
||||
description: "用户前缀系统的管理命令权限。"
|
||||
default: op
|
||||
|
||||
commands:
|
||||
UserPrefix:
|
||||
aliases:
|
||||
@@ -17,6 +27,5 @@ commands:
|
||||
UserPrefixAdmin:
|
||||
aliases:
|
||||
- upa
|
||||
- prefixAdmin
|
||||
permission: "UserPrefix.admin"
|
||||
description: "用户前缀系统管理指令,可以查看前缀列表与重载配置文件。"
|
||||
@@ -0,0 +1,71 @@
|
||||
# 唯一标识 [必须]
|
||||
# 将用于记录玩家所选的前缀,以及用于数据的缓存。
|
||||
# 必须 必须 必须 保持唯一!
|
||||
identifier: "pro"
|
||||
|
||||
# 名字 [必须]
|
||||
# 切换的时候左下角会弹提示 用的就是这个名字
|
||||
name: "&b&lPro&b"
|
||||
|
||||
# 内容 [必须]
|
||||
# 显示在名字前面的内容
|
||||
content: "&b&lPro &b"
|
||||
|
||||
# 权重 [必须]
|
||||
# 用于GUI、TabList的排序和自动前缀显示
|
||||
# 在GUI中,权重越高的会显示在越后面
|
||||
# 在TabList中,显示顺序可以在 config.yml 中自定义
|
||||
weight: 1
|
||||
|
||||
|
||||
# 检测的权限 [非必须]
|
||||
# 如果没有就是人人都能用,也代表不用配置“itemNoPermission”了(因为压根不可能显示没权限时候的物品)
|
||||
permission: "yc.pro"
|
||||
|
||||
# 该前缀的GUI物品配置
|
||||
item:
|
||||
|
||||
# 有权限时显示的物品 [必须]
|
||||
# 当用户有权限且未选中时,会显示该物品
|
||||
has-perm:
|
||||
type: DIAMOND
|
||||
name: "&b&lPro &b会员前缀"
|
||||
lore:
|
||||
- "&7Pro会员专属称号"
|
||||
- ""
|
||||
- "&f尊贵的Pro会员专属称号。"
|
||||
- "&f您将获得多种特权与更好的游戏体验。"
|
||||
- ""
|
||||
- "&a➥ 点击切换到该前缀"
|
||||
|
||||
# 正在使用时显示的物品 [非必需]
|
||||
# 当用户正在使用时会显示这个物品,不配置即自动加载“itemHasPermission”
|
||||
using:
|
||||
type: DIAMOND
|
||||
name: "&b&lPro &b会员前缀"
|
||||
flags:
|
||||
- HIDE_ENCHANTS # 隐藏附魔显示
|
||||
enchants:
|
||||
PROTECTION_ENVIRONMENTAL: 1 #加一个附魔这样看上去就像是选中了的
|
||||
lore:
|
||||
- "&7Pro会员专属称号"
|
||||
- ""
|
||||
- "&f尊贵的Pro会员专属称号。"
|
||||
- "&f您将获得多种特权与更好的游戏体验。"
|
||||
- ""
|
||||
- "&a✔ 您正在使用该前缀"
|
||||
|
||||
# 没有权限时显示的物品 [非必需]
|
||||
# 如果没有权限就会显示这个item。如果不配置该物品,则玩家没有使用权限时不会显示在GUI里面。
|
||||
no-perm:
|
||||
type: INK_SACK
|
||||
data: 8
|
||||
name: "&b&lPro+ &b会员前缀 &c(未拥有)"
|
||||
lore:
|
||||
- "&7Pro+会员专属称号"
|
||||
- ""
|
||||
- "&f尊贵的Pro会员专属称号。"
|
||||
- "&f您将获得多种特权与更好的游戏体验。"
|
||||
- "&f您可以输入 &b/vip &f指令查看详细特权!"
|
||||
- ""
|
||||
- "&e✯ 加入Pro+会员以使用该前缀!"
|
||||
@@ -0,0 +1,14 @@
|
||||
import cc.carm.lib.easyplugin.utils.ColorParser;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ColorParseTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void onTest() {
|
||||
String testString = "&f爱的人永远不爱我,为何付出得到的只有&(#aaaaaa)背叛。";
|
||||
|
||||
System.out.println(ColorParser.parseHexColor(testString));
|
||||
}
|
||||
|
||||
}
|
||||