commit d77b9f696d203047f7613070df51db45c8b69c41 Author: CarmJos Date: Tue Jan 4 20:38:29 2022 +0800 项目初始化 diff --git a/.documentation/JAVADOC-README.md b/.documentation/JAVADOC-README.md new file mode 100644 index 0000000..91fe6e3 --- /dev/null +++ b/.documentation/JAVADOC-README.md @@ -0,0 +1,9 @@ +# EasyPlugin Javadoc + +基于 [Github Pages](https://pages.github.com/) 搭建,请访问 [JavaDoc](https://carmjos.github.io/EasyPlugin) 。 + +## 如何实现? + +若您也想通过 [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) 。 \ No newline at end of file diff --git a/.documentation/README.md b/.documentation/README.md new file mode 100644 index 0000000..8a6f398 --- /dev/null +++ b/.documentation/README.md @@ -0,0 +1,3 @@ +# 欢迎使用 EasyPlugin ! + +这个项目刚刚创建,详细的Javadoc与开发指南还在补充,请给我一点时间~ \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bugs_report.md b/.github/ISSUE_TEMPLATE/bugs_report.md new file mode 100644 index 0000000..ac6d686 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bugs_report.md @@ -0,0 +1,38 @@ +--- +name: 问题提交 +about: 描述问题并提交,帮助我们对其进行检查与修复。 +title: '' +labels: bug +assignees: '' + +--- + +### **问题简述** + +用简短的话语描述一下大概问题。 + +### **问题来源** + +描述一下通过哪些操作才发现的问题,如: +1. 使用了 ... +2. 输入了 ... +3. 出现了报错 ... + +### **预期结果**(可选) + +如果问题不发生,应该是什么情况 + +### **问题截图/问题报错** + +如果有报错或输出,请提供截图。 + +### **操作环境** + +- 系统环境: `Windows 10` / `Ubuntu` / `...` +- Java版本: `JDK11` / `OPENJDK8` / `JRE8` / `...` +- 服务端版本: 请在后台输入 `version` 并复制相关输出。 + + +### **其他补充** + +如有其他补充,可以在这里描述。 diff --git a/.github/ISSUE_TEMPLATE/feature_issues.md b/.github/ISSUE_TEMPLATE/feature_issues.md new file mode 100644 index 0000000..9407bad --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_issues.md @@ -0,0 +1,20 @@ +--- +name: 功能需求 +about: 希望我们提供更多的功能。 +title: '' +labels: enhancement +assignees: '' + +--- + +### **功能简述** +简单的描述一下你想要的功能 + +### **需求来源** +简单的描述一下为什么需要这个功能。 + +### **功能参考**(可选) +如果有相关功能的参考,如文本、截图,请提供给我们。 + +### **附加内容** +如果有什么小细节需要重点注意,请在这里告诉我们。 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000..5b79227 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -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" + +on: + push: + branches: [ master ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ master ] + schedule: + - cron: '45 12 * * 1' + +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 diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..506585f --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,33 @@ +# 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 + +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: "Deploy" + run: mvn -B deploy --file pom.xml -DskipTests + env: + MAVEN_USERNAME: ${{ github.repository_owner }} + MAVEN_TOKEN: ${{secrets.GITHUB_TOKEN}} \ No newline at end of file diff --git a/.github/workflows/javadoc.yml b/.github/workflows/javadoc.yml new file mode 100644 index 0000000..c9a8b0f --- /dev/null +++ b/.github/workflows/javadoc.yml @@ -0,0 +1,73 @@ +# 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: Javadoc + +on: + # 支持手动触发构建 + workflow_dispatch: + release: + # 创建release的时候触发 + types: [ published ] + +jobs: + api-website: + runs-on: ubuntu-latest + steps: + - name: Checkout the repo + uses: actions/checkout@v2 + + - name: Set up the Java JDK + uses: actions/setup-java@v2 + with: + java-version: '11' + distribution: 'adopt' + + - name: Generate docs + run: mvn clean package -DskipTests + + - name: Copy to Location + run: | + rm -rf docs + mkdir -vp docs + cp -vrf EasyPlugin-api/target/apidocs/* docs/ + cp -vrf .documentation/JAVADOC-README.md docs/README.md + + - name: Generate the sitemap + id: sitemap + uses: cicirello/generate-sitemap@v1 + with: + base-url-path: https://carmjos.github.io/EasyPlugin + path-to-root: docs + + - name: Output 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 documentation changes + run: | + cd docs + git init + git remote add origin git@github.com:CarmJos/EasyPlugin.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 + diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 0000000..984238b --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,31 @@ +# 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: Build + +on: + # 支持手动触发构建 + workflow_dispatch: + push: + +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' + - name: "Package" + run: mvn -B package --file pom.xml -Dmaven.javadoc.skip=true + - name: "Target Stage" + run: mkdir staging && cp */target/*.jar staging + - name: "Upload artifact" + uses: actions/upload-artifact@v2 + with: + name: Artifact + path: staging diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..18faac9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/.idea/ +/target/ +/*/target/ +**.iml \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..70db2d0 --- /dev/null +++ b/README.md @@ -0,0 +1,132 @@ +```text + ______ ____ __ _ + / ____/___ ________ __ / __ \/ /_ ______ _(_)___ + / __/ / __ `/ ___/ / / / / /_/ / / / / / __ `/ / __ \ + / /___/ /_/ (__ ) /_/ / / ____/ / /_/ / /_/ / / / / / +/_____/\__,_/____/\__, / /_/ /_/\__,_/\__, /_/_/ /_/ + /____/ /____/ +``` + +# EasyPlugin + +[![version](https://img.shields.io/github/v/release/CarmJos/EasyPlugin)](https://github.com/CarmJos/EasyPlugin/releases) +[![License](https://img.shields.io/github/license/CarmJos/EasyPlugin)](https://opensource.org/licenses/GPL-3.0) +[![workflow](https://github.com/CarmJos/EasyPlugin/actions/workflows/maven.yml/badge.svg?branch=master)](https://github.com/CarmJos/EasyPlugin/actions/workflows/maven.yml) +[![CodeFactor](https://www.codefactor.io/repository/github/carmjos/EasyPlugin/badge)](https://www.codefactor.io/repository/github/carmjos/EasyPlugin) +![CodeSize](https://img.shields.io/github/languages/code-size/CarmJos/EasyPlugin) +![](https://visitor-badge.glitch.me/badge?page_id=EasyPlugin.readme) + +轻松(做)插件,旨在于方便快捷的使用Bukkit实现MC中的一些功能。 + +## 优势 + +- 轻便独立的功能模块,按需使用,避免大量打包! +- 详细的Javadoc与使用文档,轻松上手,方便使用! +- 持续的更新与优化,需求不止,更新不止! + - 如需新功能支持,请 [点击这里](https://github.com/CarmJos/EasyPlugin/issues/new?assignees=&labels=enhancement&template=feature_issues.md&title=) 提交功能需求。 + +## 内容 + +### 集合部分 +- All [`easyplugin-all`](easyplugin-all) +- Common [`easyplugin-common`](easyplugin-common) + +### 主要部分 + +- Main [`easyplugin-main`](easyplugin-main) +- Command [`easyplugin-command`](easyplugin-command) +- Configuration [`easyplugin-configuration`](easyplugin-configuration) +- Database [`easyplugin-database`](easyplugin-database) +- GUI [`easyplugin-gui`](easyplugin-gui) + +### 附属部分 +- [PlaceholderAPI](https://www.spigotmc.org/resources/6245/) [`easyplugin-placeholderapi`](easyplugin-placeholderapi) +- [Vault](https://github.com/MilkBowl/VaultAPI) [`easyplugin-vault`](easyplugin-vault) +- [LuckPerms](https://www.spigotmc.org/resources/luckperms.28140/) [`easyplugin-lp`](easyplugin-lp) + +## 开发 + +详细开发介绍请 [点击这里](.documentation/README.md) , JavaDoc(最新Release) 请 [点击这里](https://carmjos.github.io/EasyPlugin) 。 + +### 示例代码 + +您可以 [点击这里](https://github.com/CarmJos/UltraDepository) 查看实例项目演示,更多演示详见 [开发介绍](.documentation/README.md) 。 + +### 依赖方式 + +#### Maven 依赖 + +
+远程库配置 + +```xml + + + + + EasyPlugin + GitHub Packages + https://maven.pkg.github.com/CarmJos/EasyPlugin + + + +``` + +
+ +
+原生依赖 + +```xml + + + + + + cc.carm.lib + easyplugin-all + [LATEST RELEASE] + compile + + + + + cc.carm.lib + easyplugin-main + [LATEST RELEASE] + compile + + + + +``` + +
+ +## 支持与捐赠 + +若您觉得本插件做的不错,您可以通过捐赠支持我! + +感谢您对开源项目的支持! + + + +## 开源协议 + +本项目源码采用 [The MIT License](https://opensource.org/licenses/MIT) 开源协议。 +
+关于 MIT 协议 + +> MIT 协议可能是几大开源协议中最宽松的一个,核心条款是: +> +> 该软件及其相关文档对所有人免费,可以任意处置,包括使用,复制,修改,合并,发表,分发,再授权,或者销售。唯一的限制是,软件中必须包含上述版 权和许可提示。 +> +> 这意味着: +> - 你可以自由使用,复制,修改,可以用于自己的项目。 +> - 可以免费分发或用来盈利。 +> - 唯一的限制是必须包含许可声明。 +> +> MIT 协议是所有开源许可中最宽松的一个,除了必须包含许可声明外,再无任何限制。 +> +> *以上文字来自 [五种开源协议GPL,LGPL,BSD,MIT,Apache](https://www.oschina.net/question/54100_9455) 。* +
\ No newline at end of file diff --git a/easyplugin-all/pom.xml b/easyplugin-all/pom.xml new file mode 100644 index 0000000..4db0132 --- /dev/null +++ b/easyplugin-all/pom.xml @@ -0,0 +1,106 @@ + + + + easyplugin-parent + cc.carm.lib + 1.0.0-SNAPSHOT + + 4.0.0 + + + 11 + 11 + UTF-8 + UTF-8 + + + easyplugin-all + jar + + EasyPlugin-All + 轻松插件全集,将打包全部工具类与工具接口。 + https://github.com/CarmJos/EasyPlugin + + + + CarmJos + Carm Jos + carm@carm.cc + https://www.carm.cc + + + + + + GNU General Public License v3.0 + https://opensource.org/licenses/GPL-3.0 + + + + + GitHub Issues + https://github.com/CarmJos/EasyPlugin/issues + + + + GitHub Actions + https://github.com/CarmJos/EasyPlugin/actions/workflows/maven.yml + + + + + + ${project.parent.groupId} + easyplugin-common + ${project.parent.version} + compile + + + + ${project.parent.groupId} + easyplugin-lp + ${project.parent.version} + compile + + + + ${project.parent.groupId} + easyplugin-placeholderapi + ${project.parent.version} + compile + + + + ${project.parent.groupId} + easyplugin-vault + ${project.parent.version} + compile + + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + + + + \ No newline at end of file diff --git a/easyplugin-command/pom.xml b/easyplugin-command/pom.xml new file mode 100644 index 0000000..df887aa --- /dev/null +++ b/easyplugin-command/pom.xml @@ -0,0 +1,22 @@ + + + + easyplugin-parent + cc.carm.lib + 1.0.0-SNAPSHOT + + 4.0.0 + + + 11 + 11 + UTF-8 + UTF-8 + + + easyplugin-command + + + \ No newline at end of file diff --git a/easyplugin-common/pom.xml b/easyplugin-common/pom.xml new file mode 100644 index 0000000..b6d3fd8 --- /dev/null +++ b/easyplugin-common/pom.xml @@ -0,0 +1,111 @@ + + + + easyplugin-parent + cc.carm.lib + 1.0.0-SNAPSHOT + + 4.0.0 + + + 11 + 11 + UTF-8 + UTF-8 + + + easyplugin-common + jar + + EasyPlugin-Main + 轻松插件常用接口集,包含除附属模块外的所有模块。 + https://github.com/CarmJos/EasyPlugin + + + + CarmJos + Carm Jos + carm@carm.cc + https://www.carm.cc + + + + + + GNU General Public License v3.0 + https://opensource.org/licenses/GPL-3.0 + + + + + GitHub Issues + https://github.com/CarmJos/EasyPlugin/issues + + + + GitHub Actions + https://github.com/CarmJos/EasyPlugin/actions/workflows/maven.yml + + + + + ${project.parent.groupId} + easyplugin-main + ${project.parent.version} + compile + + + + ${project.parent.groupId} + easyplugin-command + ${project.parent.version} + compile + + + + ${project.parent.groupId} + easyplugin-configuration + ${project.parent.version} + compile + + + + ${project.parent.groupId} + easyplugin-gui + ${project.parent.version} + compile + + + + ${project.parent.groupId} + easyplugin-database + ${project.parent.version} + compile + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + + + + \ No newline at end of file diff --git a/easyplugin-configuration/pom.xml b/easyplugin-configuration/pom.xml new file mode 100644 index 0000000..289e19c --- /dev/null +++ b/easyplugin-configuration/pom.xml @@ -0,0 +1,62 @@ + + + + easyplugin-parent + cc.carm.lib + 1.0.0-SNAPSHOT + + 4.0.0 + + + 11 + 11 + UTF-8 + UTF-8 + + + easyplugin-configuration + jar + + + EasyPlugin-Configuration + 轻松插件配置,可以方便快捷的将配置文件作为静态参数使用。 + https://github.com/CarmJos/EasyPlugin + + + + CarmJos + Carm Jos + carm@carm.cc + https://www.carm.cc + + + + + + GNU General Public License v3.0 + https://opensource.org/licenses/GPL-3.0 + + + + + GitHub Issues + https://github.com/CarmJos/EasyPlugin/issues + + + + GitHub Actions + https://github.com/CarmJos/EasyPlugin/actions/workflows/maven.yml + + + + + ${project.parent.groupId} + easyplugin-main + ${project.parent.version} + provided + + + + \ No newline at end of file diff --git a/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/file/FileConfig.java b/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/file/FileConfig.java new file mode 100644 index 0000000..26469ac --- /dev/null +++ b/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/file/FileConfig.java @@ -0,0 +1,91 @@ +package cc.carm.lib.easyplugin.configuration.file; + + +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.IOException; +import java.util.function.Supplier; + +public class FileConfig { + + public static Supplier pluginConfiguration = null; + public static Supplier messageConfiguration = null; + + @Nullable + public static FileConfig getPluginConfiguration() { + return pluginConfiguration == null ? null : pluginConfiguration.get(); + } + + @Nullable + public static FileConfig getMessageConfiguration() { + return messageConfiguration == null ? null : messageConfiguration.get(); + } + + private long updateTime; + + private final JavaPlugin plugin; + private final String fileName; + + + private File file; + private FileConfiguration config; + + public FileConfig(final JavaPlugin plugin) { + this(plugin, "config.yml"); + } + + public FileConfig(final JavaPlugin plugin, final String name) { + this.plugin = plugin; + this.fileName = name; + initFile(); + } + + private void initFile() { + this.updateTime = System.currentTimeMillis(); + this.file = new File(plugin.getDataFolder(), fileName); + if (!this.file.exists()) { + if (!this.file.getParentFile().exists()) { + boolean success = this.file.getParentFile().mkdirs(); + } + plugin.saveResource(fileName, true); + } + this.config = YamlConfiguration.loadConfiguration(this.file); + } + + public File getFile() { + return file; + } + + public FileConfiguration getConfig() { + return config; + } + + public void save() { + try { + getConfig().save(getFile()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void reload() { + this.updateTime = System.currentTimeMillis(); + if (getFile().exists()) { + this.config = YamlConfiguration.loadConfiguration(getFile()); + } else { + initFile(); + } + } + + public long getUpdateTime() { + return updateTime; + } + + public boolean isExpired(long time) { + return getUpdateTime() > time; + } +} diff --git a/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/impl/ConfigSectionCast.java b/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/impl/ConfigSectionCast.java new file mode 100644 index 0000000..b1f9609 --- /dev/null +++ b/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/impl/ConfigSectionCast.java @@ -0,0 +1,73 @@ +package cc.carm.lib.easyplugin.configuration.impl; + +import cc.carm.lib.easyplugin.configuration.file.FileConfig; +import org.bukkit.configuration.ConfigurationSection; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Function; + +public class ConfigSectionCast { + + @Nullable FileConfig source; + + @NotNull String configSection; + @NotNull Function valueCast; + @Nullable V defaultValue; + + V valueCache; + long updateTime; + + public ConfigSectionCast(@NotNull String configSection, @NotNull Function valueCast) { + this(configSection, valueCast, null); + } + + public ConfigSectionCast(@NotNull String configSection, + @NotNull Function valueCast, + @Nullable V defaultValue) { + this(null, configSection, valueCast, defaultValue); + } + + public ConfigSectionCast(@Nullable FileConfig source, @NotNull String configSection, + @NotNull Function valueCast, + @Nullable V defaultValue) { + this.source = source; + this.configSection = configSection; + this.valueCast = valueCast; + this.defaultValue = defaultValue; + } + + + public @Nullable V get() { + FileConfig source = getSource(); + if (source == null) return defaultValue; + + if (valueCache != null && !source.isExpired(this.updateTime)) return valueCache; + if (!source.getConfig().contains(this.configSection)) return defaultValue; + try { + V finalValue = this.valueCast.apply(source.getConfig().getConfigurationSection(this.configSection)); + if (finalValue != null) { + this.valueCache = finalValue; + this.updateTime = System.currentTimeMillis(); + return finalValue; + } else { + return defaultValue; + } + } catch (Exception ignore) { + return defaultValue; + } + } + + public void set(ConfigurationSection section) { + + } + + public void save() { + if (getSource() != null) getSource().save(); + } + + public @Nullable FileConfig getSource() { + return source == null ? FileConfig.getPluginConfiguration() : source; + } + +} diff --git a/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/impl/ConfigSound.java b/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/impl/ConfigSound.java new file mode 100644 index 0000000..78c2aff --- /dev/null +++ b/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/impl/ConfigSound.java @@ -0,0 +1,110 @@ +package cc.carm.lib.easyplugin.configuration.impl; + +import cc.carm.lib.easyplugin.configuration.file.FileConfig; +import org.bukkit.Bukkit; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class ConfigSound extends ConfigStringCast { + + public ConfigSound(@NotNull String configSection) { + this(configSection, null); + } + + public ConfigSound(@NotNull String configSection, + @Nullable Sound defaultValue) { + this(null, configSection, defaultValue); + } + + public ConfigSound(@Nullable FileConfig source, @NotNull String configSection, @Nullable Sound defaultValue) { + super(source, configSection, string -> { + Sound finalSound = defaultValue; + float volume = 1; + float pitch = 1; + + if (string != null) { + String[] args = string.contains(":") ? string.split(":") : new String[]{string}; + try { + if (args.length >= 1) finalSound = Sound.valueOf(args[0]); + if (args.length >= 2) volume = Float.parseFloat(args[1]); + if (args.length >= 3) pitch = Float.parseFloat(args[2]); + } catch (Exception exception) { + Bukkit.getLogger().severe("声音 " + configSection + " 配置错误,不存在 " + string + " ,请检查。"); + Bukkit.getLogger().severe("In " + configSection + " (" + string + ") doesn't match any sound name."); + } + } + + if (finalSound != null) { + return new SoundData(finalSound, volume, pitch); + } else { + return null; + } + }, defaultValue == null ? null : new SoundData(defaultValue)); + } + + public void set(@Nullable SoundData value) { + if (value == null) { + set((String) null); + } else if (value.pitch != 1) { + set(value.type, value.volume, value.pitch); + } else if (value.volume != 1) { + set(value.type, value.volume); + } else { + set(value.type); + } + } + + public void set(Sound value) { + set(value.name()); + } + + public void set(Sound value, float volume) { + set(value.name() + (volume != 1 ? ":" + volume : "")); + } + + public void set(Sound value, float volume, float pitch) { + set(value.name() + ":" + volume + (pitch != 1 ? ":" + pitch : "")); + } + + public void play(Player player) { + SoundData data = get(); + if (data != null) data.play(player); + } + + public void save() { + if (getSource() != null) getSource().save(); + } + + public @Nullable FileConfig getSource() { + return source == null ? FileConfig.getPluginConfiguration() : source; + } + + public static class SoundData { + Sound type; + float volume; + float pitch; + + public SoundData(Sound type) { + this(type, 1, 1); + } + + public SoundData(Sound type, float volume) { + this(type, volume, 1); + } + + public SoundData(Sound type, float volume, float pitch) { + this.type = type; + this.volume = volume; + this.pitch = pitch; + } + + public void play(Player player) { + player.playSound(player.getLocation(), type, volume, pitch); + } + + } + + +} diff --git a/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/impl/ConfigStringCast.java b/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/impl/ConfigStringCast.java new file mode 100644 index 0000000..4bdd215 --- /dev/null +++ b/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/impl/ConfigStringCast.java @@ -0,0 +1,76 @@ +package cc.carm.lib.easyplugin.configuration.impl; + +import cc.carm.lib.easyplugin.configuration.file.FileConfig; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Function; + +public class ConfigStringCast { + + @Nullable FileConfig source; + + @NotNull String configSection; + @NotNull Function valueCast; + + @Nullable V defaultValue; + + V valueCache; + long updateTime; + + public ConfigStringCast(@NotNull String configSection, @NotNull Function valueCast) { + this(configSection, valueCast, null); + } + + public ConfigStringCast(@NotNull String configSection, @NotNull Function valueCast, @Nullable V defaultValue) { + this(null, configSection, valueCast, defaultValue); + } + + public ConfigStringCast(@Nullable FileConfig source, @NotNull String configSection, + @NotNull Function valueCast, @Nullable V defaultValue) { + this.source = source; + this.configSection = configSection; + this.valueCast = valueCast; + this.defaultValue = defaultValue; + } + + public @Nullable V get() { + FileConfig source = getSource(); + if (source == null) return defaultValue; + + if (valueCache != null && !source.isExpired(this.updateTime)) return valueCache; + if (!source.getConfig().contains(this.configSection)) return defaultValue; + try { + V finalValue = this.valueCast.apply(source.getConfig().getString(this.configSection)); + if (finalValue != null) { + this.valueCache = finalValue; + this.updateTime = System.currentTimeMillis(); + return finalValue; + } else { + return defaultValue; + } + } catch (Exception ignore) { + return defaultValue; + } + } + + public void set(@Nullable String value) { + FileConfig source = getSource(); + if (source != null) { + source.getConfig().set(this.configSection, value); + source.save(); + } + } + + public void save() { + if (getSource() != null) { + getSource().save(); + } + } + + public @Nullable FileConfig getSource() { + return source == null ? FileConfig.getPluginConfiguration() : source; + } + + +} diff --git a/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/message/ConfigMessage.java b/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/message/ConfigMessage.java new file mode 100644 index 0000000..8ae88ec --- /dev/null +++ b/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/message/ConfigMessage.java @@ -0,0 +1,72 @@ +package cc.carm.lib.easyplugin.configuration.message; + + +import cc.carm.lib.easyplugin.configuration.file.FileConfig; +import cc.carm.lib.easyplugin.configuration.values.ConfigValue; +import cc.carm.lib.easyplugin.utils.MessageUtils; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +public class ConfigMessage extends ConfigValue { + + String[] messageParams; + + public ConfigMessage(@NotNull String configSection) { + this(configSection, null); + } + + public ConfigMessage(@NotNull String configSection, @Nullable String defaultValue) { + this(configSection, defaultValue, null); + } + + public ConfigMessage(@NotNull String configSection, @Nullable String defaultValue, String[] messageParams) { + super(null, configSection, String.class, defaultValue); + this.messageParams = messageParams; + } + + public ConfigMessage(@Nullable FileConfig config, @NotNull String configSection, + @Nullable String defaultValue, String[] messageParams) { + super(config, configSection, String.class, defaultValue); + this.messageParams = messageParams; + } + + public @NotNull String get(CommandSender sender, Object[] values) { + if (messageParams != null) { + return get(sender, messageParams, values); + } else { + return get(sender, new String[0], new Object[0]); + } + } + + public @NotNull String get(CommandSender sender, String[] params, Object[] values) { + List messages = MessageUtils.setPlaceholders(sender, Collections.singletonList(get()), params, values); + return messages != null && !messages.isEmpty() ? messages.get(0) : ""; + } + + public void send(CommandSender sender) { + MessageUtils.sendWithPlaceholders(sender, get()); + } + + public void send(CommandSender sender, Object[] values) { + if (messageParams != null) { + send(sender, messageParams, values); + } else { + send(sender, new String[0], new Object[0]); + } + + } + + public void send(CommandSender sender, String[] params, Object[] values) { + MessageUtils.sendWithPlaceholders(sender, Collections.singletonList(get()), params, values); + } + + public @Nullable FileConfig getSource() { + return source == null ? FileConfig.getMessageConfiguration() : source; + } + + +} diff --git a/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/message/ConfigMessageList.java b/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/message/ConfigMessageList.java new file mode 100644 index 0000000..6f6b545 --- /dev/null +++ b/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/message/ConfigMessageList.java @@ -0,0 +1,73 @@ +package cc.carm.lib.easyplugin.configuration.message; + + +import cc.carm.lib.easyplugin.configuration.file.FileConfig; +import cc.carm.lib.easyplugin.configuration.values.ConfigValueList; +import cc.carm.lib.easyplugin.utils.MessageUtils; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class ConfigMessageList extends ConfigValueList { + + @Nullable String[] messageParams; + + public ConfigMessageList(String configSection) { + this(configSection, new String[0]); + } + + public ConfigMessageList(@NotNull String configSection, @Nullable String[] defaultValue) { + this(configSection, defaultValue, null); + } + + public ConfigMessageList(@NotNull String configSection, @Nullable String[] defaultValue, String[] messageParams) { + super(null, configSection, String.class, defaultValue); + this.messageParams = messageParams; + } + + public ConfigMessageList(@Nullable FileConfig config, @NotNull String configSection, + @Nullable String[] defaultValue, String[] messageParams) { + super(config, configSection, String.class, defaultValue); + this.messageParams = messageParams; + } + + public @NotNull List get(@Nullable CommandSender sender) { + return MessageUtils.setPlaceholders(sender, get()); + } + + public @NotNull List get(@Nullable CommandSender sender, Object[] values) { + if (messageParams != null) { + return get(sender, messageParams, values); + } else { + return get(sender); + } + } + + + public @NotNull List get(@Nullable CommandSender sender, String[] params, Object[] values) { + return MessageUtils.setPlaceholders(sender, get(), params, values); + } + + public void send(@Nullable CommandSender sender) { + MessageUtils.sendWithPlaceholders(sender, get()); + } + + public void send(@Nullable CommandSender sender, Object[] values) { + if (messageParams != null) { + send(sender, messageParams, values); + } else { + send(sender); + } + } + + public void send(@Nullable CommandSender sender, String[] params, Object[] values) { + MessageUtils.sendWithPlaceholders(sender, get(), params, values); + } + + @Override + public @Nullable FileConfig getSource() { + return source == null ? FileConfig.getMessageConfiguration() : source; + } +} diff --git a/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/values/ConfigValue.java b/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/values/ConfigValue.java new file mode 100644 index 0000000..9a467e0 --- /dev/null +++ b/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/values/ConfigValue.java @@ -0,0 +1,64 @@ +package cc.carm.lib.easyplugin.configuration.values; + +import cc.carm.lib.easyplugin.configuration.file.FileConfig; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class ConfigValue { + + protected @Nullable FileConfig source; + + private final @NotNull String configSection; + private final @NotNull Class clazz; + @Nullable V defaultValue; + + public ConfigValue(@NotNull String configSection, @NotNull Class clazz) { + this(configSection, clazz, null); + } + + public ConfigValue(@NotNull String configSection, @NotNull Class clazz, @Nullable V defaultValue) { + this(null, configSection, clazz, defaultValue); + } + + public ConfigValue(@Nullable FileConfig source, @NotNull String configSection, + @NotNull Class clazz, @Nullable V defaultValue) { + this.source = source; + this.configSection = configSection; + this.clazz = clazz; + this.defaultValue = defaultValue; + } + + public V get() { + FileConfig source = getSource(); + if (source == null) return this.defaultValue; + + if (source.getConfig().contains(this.configSection)) { + Object val = source.getConfig().get(this.configSection, this.defaultValue); + return this.clazz.isInstance(val) ? this.clazz.cast(val) : this.defaultValue; + } else { + // 如果没有默认值,就把配置写进去,便于配置 + return setDefault(); + } + } + + public void set(@Nullable V value) { + FileConfig source = getSource(); + if (source == null) return; + + source.getConfig().set(this.configSection, value); + source.save(); + } + + public void save() { + if (getSource() != null) getSource().save(); + } + + public V setDefault() { + set(this.defaultValue); + return this.defaultValue; + } + + public @Nullable FileConfig getSource() { + return source == null ? FileConfig.getPluginConfiguration() : source; + } +} diff --git a/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/values/ConfigValueList.java b/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/values/ConfigValueList.java new file mode 100644 index 0000000..ce24309 --- /dev/null +++ b/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/values/ConfigValueList.java @@ -0,0 +1,79 @@ +package cc.carm.lib.easyplugin.configuration.values; + + +import cc.carm.lib.easyplugin.configuration.file.FileConfig; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class ConfigValueList { + + protected @Nullable FileConfig source; + + private final @NotNull String configSection; + private final @NotNull Class clazz; + + @Nullable V[] defaultValue; + + public ConfigValueList(@NotNull String configSection, @NotNull Class clazz) { + this(configSection, clazz, null); + } + + public ConfigValueList(@NotNull String configSection, @NotNull Class clazz, @Nullable V[] defaultValue) { + this(null, configSection, clazz, defaultValue); + } + + public ConfigValueList(@Nullable FileConfig configuration, @NotNull String configSection, Class clazz) { + this(configuration, configSection, clazz, null); + } + + public ConfigValueList(@Nullable FileConfig configuration, @NotNull String configSection, + @NotNull Class clazz, @Nullable V[] defaultValue) { + this.source = configuration; + this.configSection = configSection; + this.clazz = clazz; + this.defaultValue = defaultValue; + } + + public @NotNull ArrayList get() { + FileConfig source = getSource(); + if (source == null) return new ArrayList<>(); + + List list = source.getConfig().getList(this.configSection); + if (list == null) { + if (defaultValue != null) { + return new ArrayList<>(Arrays.asList(defaultValue)); + } else { + return new ArrayList<>(); + } + } else { + ArrayList result = new ArrayList<>(); + + for (Object object : list) { + if (this.clazz.isInstance(object)) { + result.add(this.clazz.cast(object)); + } + } + return result; + } + } + + public void set(@Nullable ArrayList value) { + FileConfig source = getSource(); + if (source == null) return; + source.getConfig().set(this.configSection, value); + this.save(); + } + + public void save() { + if (getSource() != null) getSource().save(); + } + + public @Nullable FileConfig getSource() { + return this.source == null ? FileConfig.getPluginConfiguration() : this.source; + } + +} diff --git a/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/values/ConfigValueMap.java b/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/values/ConfigValueMap.java new file mode 100644 index 0000000..cbebc24 --- /dev/null +++ b/easyplugin-configuration/src/main/java/cc/carm/lib/easyplugin/configuration/values/ConfigValueMap.java @@ -0,0 +1,88 @@ +package cc.carm.lib.easyplugin.configuration.values; + +import cc.carm.lib.easyplugin.configuration.file.FileConfig; +import org.bukkit.configuration.ConfigurationSection; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; + +public class ConfigValueMap { + + @Nullable FileConfig source; + + @NotNull String configSection; + + @NotNull Function keyCast; + @NotNull Class valueClazz; + + @Nullable LinkedHashMap valueCache; + + long updateTime; + + public ConfigValueMap(@NotNull String configSection, @NotNull Function keyCast, + @NotNull Class valueClazz) { + this(null, configSection, keyCast, valueClazz); + } + + public ConfigValueMap(@Nullable FileConfig configuration, @NotNull String configSection, + @NotNull Function keyCast, @NotNull Class valueClazz) { + this.source = configuration; + this.configSection = configSection; + this.keyCast = keyCast; + this.valueClazz = valueClazz; + } + + public void clearCache() { + this.valueCache = null; + } + + @NotNull + public Map get() { + FileConfig source = getSource(); + if (source == null) return new HashMap<>(); + + if (valueCache != null && !getSource().isExpired(this.updateTime)) return valueCache; + + ConfigurationSection section = source.getConfig().getConfigurationSection(this.configSection); + if (section == null) return new LinkedHashMap<>(); + + Set keys = section.getKeys(false); + if (keys.isEmpty()) return new LinkedHashMap<>(); + + else { + LinkedHashMap result = new LinkedHashMap<>(); + for (String key : keys) { + K finalKey = keyCast.apply(key); + Object val = section.get(key); + V finalValue = this.valueClazz.isInstance(val) ? this.valueClazz.cast(val) : null; + if (finalKey != null && finalValue != null) { + result.put(finalKey, finalValue); + } + } + this.updateTime = System.currentTimeMillis(); + this.valueCache = result; + return result; + } + } + + public void set(@Nullable HashMap valuesMap) { + FileConfig source = getSource(); + if (source == null) return; + source.getConfig().createSection(this.configSection, valuesMap); + source.save(); + } + + public void save() { + if (getSource() != null) getSource().save(); + } + + public @Nullable FileConfig getSource() { + return source == null ? FileConfig.getPluginConfiguration() : source; + } + +} diff --git a/easyplugin-database/pom.xml b/easyplugin-database/pom.xml new file mode 100644 index 0000000..b71c7e8 --- /dev/null +++ b/easyplugin-database/pom.xml @@ -0,0 +1,41 @@ + + + + easyplugin-parent + cc.carm.lib + 1.0.0-SNAPSHOT + + 4.0.0 + + + 11 + 11 + UTF-8 + UTF-8 + + + easyplugin-database + jar + + + + + EasySQL + https://maven.pkg.github.com/CarmJos/EasySQL + + + + + + + cc.carm.lib + easysql-beecp + 0.2.3 + compile + + + + + \ No newline at end of file diff --git a/easyplugin-gui/pom.xml b/easyplugin-gui/pom.xml new file mode 100644 index 0000000..eac7038 --- /dev/null +++ b/easyplugin-gui/pom.xml @@ -0,0 +1,62 @@ + + + + easyplugin-parent + cc.carm.lib + 1.0.0-SNAPSHOT + + 4.0.0 + + + 11 + 11 + UTF-8 + UTF-8 + + + easyplugin-gui + jar + + EasyPlugin-GUI + 轻松插件界面相关接口,方便快捷的创建箱子GUI界面。 + https://github.com/CarmJos/EasyPlugin + + + + CarmJos + Carm Jos + carm@carm.cc + https://www.carm.cc + + + + + + GNU General Public License v3.0 + https://opensource.org/licenses/GPL-3.0 + + + + + GitHub Issues + https://github.com/CarmJos/EasyPlugin/issues + + + + GitHub Actions + https://github.com/CarmJos/EasyPlugin/actions/workflows/maven.yml + + + + + ${project.parent.groupId} + easyplugin-main + ${project.parent.version} + provided + + + + + \ No newline at end of file diff --git a/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/GUI.java b/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/GUI.java new file mode 100644 index 0000000..4b72da1 --- /dev/null +++ b/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/GUI.java @@ -0,0 +1,206 @@ +package cc.carm.lib.easyplugin.gui; + +import cc.carm.lib.easyplugin.utils.ColorParser; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryDragEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.IntStream; + +public class GUI { + + private static JavaPlugin plugin; + private static final HashMap openedGUIs = new HashMap<>(); + + public static void initialize(JavaPlugin plugin) { + GUI.plugin = plugin; + + } + + public static JavaPlugin getPlugin() { + return plugin; + } + + public static HashMap getOpenedGUIs() { + return openedGUIs; + } + + GUIType type; + String name; + public HashMap items; + public Inventory inv; + + /** + * 当玩家点击目标GUI时是否取消 + */ + boolean cancelOnTarget = true; + + /** + * 当玩家点击自己背包时是否取消 + */ + boolean cancelOnSelf = true; + + /** + * 当玩家点击界面外时是否取消 + */ + boolean cancelOnOuter = true; + + Map flags; + + GUIListener listener; + + public GUI(GUIType type, String name) { + this.type = type; + this.name = ColorParser.parse(name); + this.items = new HashMap<>(); + } + + + public HashMap<@NotNull Integer, @NotNull GUIItem> getItems() { + return new HashMap<>(items); + } + + public final void setItem(int index, @Nullable GUIItem item) { + if (item == null) { + this.items.remove(index); + } else { + this.items.put(index, item); + } + } + + public void setItem(GUIItem item, int... index) { + for (int i : index) { + setItem(i, item); + } + } + + public GUIItem getItem(int index) { + return this.items.get(index); + } + + /** + * 更新玩家箱子的视图 + */ + public void updateView() { + if (this.inv != null) { + List viewers = this.inv.getViewers(); + IntStream.range(0, this.inv.getSize()).forEach(index -> inv.setItem(index, new ItemStack(Material.AIR))); + getItems().forEach((index, item) -> inv.setItem(index, item.getDisplay())); + viewers.forEach(p -> ((Player) p).updateInventory()); + } + } + + /** + * 设置是否取消点击GUI内物品的事件 + * 如果不取消,玩家可以从GUI中拿取物品。 + * + * @param b 是否取消 + */ + public void setCancelOnTarget(boolean b) { + this.cancelOnTarget = b; + } + + /** + * 设置是否取消点击自己背包内物品的事件 + * 如果不取消,玩家可以从自己的背包中拿取物品。 + * + * @param b 是否取消 + */ + public void setCancelOnSelf(boolean b) { + this.cancelOnSelf = b; + } + + /** + * 设置是否取消点击GUI外的事件 + * 如果不取消,玩家可以把物品从GUI或背包中丢出去 + * + * @param b 是否取消 + */ + public void setCancelOnOuter(boolean b) { + this.cancelOnOuter = 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) { + if (this.type == GUIType.CANCEL) throw new NullPointerException("被取消或不存在的GUI"); + + Inventory inv = Bukkit.createInventory(null, this.type.getSize(), this.name); + IntStream.range(0, this.inv.getSize()).forEach(index -> inv.setItem(index, new ItemStack(Material.AIR))); + getItems().forEach((index, item) -> inv.setItem(index, item.getDisplay())); + + setOpenedGUI(player, this); + + this.inv = inv; + player.openInventory(inv); + + if (listener == null) { + Bukkit.getPluginManager().registerEvents(listener = new GUIListener(this), getPlugin()); + } + } + + /** + * 拖动GUI内物品是执行的代码 + * + * @param event InventoryDragEvent + */ + public void onDrag(InventoryDragEvent event) { + } + + /** + * 关闭GUI时执行的代码 + */ + public void onClose() { + } + + + public static void setOpenedGUI(Player player, GUI gui) { + getOpenedGUIs().put(player, gui); + } + + public static boolean hasOpenedGUI(Player player) { + return getOpenedGUIs().containsKey(player); + } + + public static GUI getOpenedGUI(Player player) { + return getOpenedGUIs().get(player); + } + + public static void removeOpenedGUI(Player player) { + getOpenedGUIs().remove(player); + } + +} diff --git a/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/GUIItem.java b/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/GUIItem.java new file mode 100644 index 0000000..f0c51ad --- /dev/null +++ b/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/GUIItem.java @@ -0,0 +1,73 @@ +package cc.carm.lib.easyplugin.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 actions = new HashSet<>(); + public Set 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) { + + } + + /** + * 玩家点击GUI后执行的代码 + * + * @param player 点击GUI的玩家 + */ + public void customAction(Player player) { + + } + + public abstract static class GUIClickAction { + public abstract void run(ClickType type, Player player); + } + +} diff --git a/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/GUIListener.java b/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/GUIListener.java new file mode 100644 index 0000000..085b6d6 --- /dev/null +++ b/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/GUIListener.java @@ -0,0 +1,88 @@ +package cc.carm.lib.easyplugin.gui; + +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.event.player.PlayerQuitEvent; + +public class GUIListener implements Listener { + + GUI currentGUI; + + public GUIListener(GUI gui) { + this.currentGUI = gui; + } + + public GUI getCurrentGUI() { + return currentGUI; + } + + @EventHandler + public void onInventoryClickEvent(InventoryClickEvent event) { + if (!(event.getWhoClicked() instanceof Player)) return; + Player player = (Player) event.getWhoClicked(); + if (!GUI.hasOpenedGUI(player)) return; + if (GUI.getOpenedGUI(player) != getCurrentGUI()) return; + + getCurrentGUI().rawClickListener(event); + + if (event.getSlot() == -999 && getCurrentGUI().cancelOnOuter) { + event.setCancelled(true); + return; + } + + if (event.getClickedInventory() == null) return; + + if (event.getClickedInventory().equals(getCurrentGUI().inv)) { + + if (getCurrentGUI().cancelOnTarget) event.setCancelled(true); + + if (event.getSlot() != -999) { + GUIItem clickedItem = getCurrentGUI().getItem(event.getSlot()); + if (clickedItem != null) { + if (clickedItem.isActionActive()) { + clickedItem.onClick(event.getClick()); + clickedItem.rawClickAction(event); + clickedItem.actions.forEach(action -> action.run(event.getClick(), player)); + } + clickedItem.actionsIgnoreActive.forEach(action -> action.run(event.getClick(), player)); + } + } + + } else if (event.getClickedInventory().equals(player.getInventory()) && getCurrentGUI().cancelOnSelf) { + event.setCancelled(true); + } + + } + + @EventHandler + public void onDrag(InventoryDragEvent e) { + if (!(e.getWhoClicked() instanceof Player)) return; + if (e.getInventory().equals(getCurrentGUI().inv) + || e.getInventory().equals(e.getWhoClicked().getInventory())) { + getCurrentGUI().onDrag(e); + } + } + + @EventHandler + public void onInventoryCloseEvent(InventoryCloseEvent event) { + if (!(event.getPlayer() instanceof Player)) return; + if (!event.getInventory().equals(getCurrentGUI().inv)) return; + + HandlerList.unregisterAll(this); + getCurrentGUI().listener = null; + GUI.removeOpenedGUI((Player) event.getPlayer()); + getCurrentGUI().onClose(); + + } + + @EventHandler + public void onPlayerLeave(PlayerQuitEvent event) { + GUI.removeOpenedGUI(event.getPlayer()); + } + +} diff --git a/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/GUIType.java b/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/GUIType.java new file mode 100644 index 0000000..cdf529a --- /dev/null +++ b/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/GUIType.java @@ -0,0 +1,49 @@ +package cc.carm.lib.easyplugin.gui; + +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; + +public enum GUIType { + + ONE_BY_NINE(1, 9), + TWO_BY_NINE(2, 18), + THREE_BY_NINE(3, 27), + FOUR_BY_NINE(4, 36), + FIVE_BY_NINE(5, 45), + SIX_BY_NINE(6, 54), + CANCEL(0, 0); + + int lines; + int size; + + GUIType(int lines, int size) { + this.lines = lines; + this.size = size; + } + + public int getLines() { + return lines; + } + + public int getSize() { + return size; + } + + @NotNull + public static GUIType getBySize(int size) { + return Arrays.stream(values()).filter(type -> type.getSize() == size).findFirst().orElse(CANCEL); + } + + @NotNull + public static GUIType getByLines(int lines) { + return Arrays.stream(values()).filter(type -> type.getLines() == lines).findFirst().orElse(CANCEL); + } + + + @NotNull + public static GUIType getByName(String name) { + return Arrays.stream(values()).filter(type -> type.name().equalsIgnoreCase(name)).findFirst().orElse(CANCEL); + } + +} diff --git a/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/configuration/GUIActionConfiguration.java b/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/configuration/GUIActionConfiguration.java new file mode 100644 index 0000000..fe8a32c --- /dev/null +++ b/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/configuration/GUIActionConfiguration.java @@ -0,0 +1,53 @@ +package cc.carm.lib.easyplugin.gui.configuration; + +import cc.carm.lib.easyplugin.gui.GUIItem; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class GUIActionConfiguration { + + + @Nullable ClickType clickType; + final @NotNull GUIActionType actionType; + final @Nullable String actionContent; + + public GUIActionConfiguration(@Nullable ClickType clickType, + @NotNull GUIActionType actionType, + @Nullable String actionContent) { + this.clickType = clickType; + this.actionType = actionType; + this.actionContent = actionContent; + } + + public @Nullable ClickType getClickType() { + return clickType; + } + + public @NotNull GUIActionType getActionType() { + return actionType; + } + + public @Nullable String getActionContent() { + return actionContent; + } + + public void checkAction(Player player, ClickType type) { + if (getClickType() == null || getClickType() == type) executeAction(player); + } + + public void executeAction(Player targetPlayer) { + getActionType().getExecutor().accept(targetPlayer, getActionContent()); + } + + public GUIItem.GUIClickAction toClickAction() { + return new GUIItem.GUIClickAction() { + @Override + public void run(ClickType type, Player player) { + checkAction(player, type); + } + }; + } + +} diff --git a/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/configuration/GUIActionType.java b/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/configuration/GUIActionType.java new file mode 100644 index 0000000..0230b3f --- /dev/null +++ b/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/configuration/GUIActionType.java @@ -0,0 +1,88 @@ +package cc.carm.lib.easyplugin.gui.configuration; + +import cc.carm.lib.easyplugin.utils.MessageUtils; +import org.bukkit.Bukkit; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.Collections; +import java.util.function.BiConsumer; + +public enum GUIActionType { + + /** + * 以玩家聊天的形式执行 + * 若内容以 “/" 开头,则会以玩家身份执行命令。 + */ + CHAT((player, string) -> { + if (string == null) return; + MessageUtils.setPlaceholders(player, Collections.singletonList(string)).forEach(player::chat); + }), + + /** + * 以后台的形式执行指令 + * 指令内容不需要以“/”开头。 + */ + CONSOLE((player, string) -> { + if (string == null) return; + MessageUtils.setPlaceholders(player, Collections.singletonList(string)) + .forEach(message -> Bukkit.dispatchCommand(Bukkit.getConsoleSender(), message)); + }), + + /** + * 向玩家发送消息。 + */ + MESSAGE(MessageUtils::send), + + /** + * 向玩家发送声音。 + * 允许配置音量与音调 + *
    + *
  • SOUND_NAME
  • + *
  • SOUND_NAME:VOLUME
  • + *
  • SOUND_NAME:VOLUME:PITCH
  • + *
+ */ + SOUND((player, string) -> { + if (string == null) return; + try { + String[] args = string.contains(":") ? string.split(":") : new String[]{string}; + Sound sound = Arrays.stream(Sound.values()) + .filter(s -> s.name().equals(args[0])) + .findFirst().orElse(null); + + if (sound == null) return; + float volume = args.length > 1 ? Float.parseFloat(args[1]) : 1F; + float pitch = args.length > 2 ? Float.parseFloat(args[2]) : 1F; + + player.playSound(player.getLocation(), sound, volume, pitch); + } catch (Exception ignored) { + } + }), + + /** + * 为玩家关闭GUI。 + */ + CLOSE((player, string) -> player.closeInventory()); + + BiConsumer<@NotNull Player, @Nullable String> executor; + + + GUIActionType(BiConsumer<@NotNull Player, @Nullable String> executor) { + this.executor = executor; + } + + public BiConsumer<@NotNull Player, @Nullable String> getExecutor() { + return executor; + } + + public static GUIActionType readActionType(String string) { + return Arrays.stream(GUIActionType.values()) + .filter(action -> action.name().equalsIgnoreCase(string)) + .findFirst().orElse(null); + } + +} \ No newline at end of file diff --git a/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/configuration/GUIConfiguration.java b/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/configuration/GUIConfiguration.java new file mode 100644 index 0000000..e75acdd --- /dev/null +++ b/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/configuration/GUIConfiguration.java @@ -0,0 +1,72 @@ +package cc.carm.lib.easyplugin.gui.configuration; + +import cc.carm.lib.easyplugin.gui.GUI; +import cc.carm.lib.easyplugin.gui.GUIType; +import cc.carm.lib.easyplugin.utils.ColorParser; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.jetbrains.annotations.Nullable; + +import java.util.*; +import java.util.stream.Collectors; + +public class GUIConfiguration { + + String title; + int lines; + + List guiItems; + + public GUIConfiguration(String title, int lines, List guiItems) { + this.title = title; + this.lines = lines; + this.guiItems = guiItems; + } + + public String getTitle() { + return ColorParser.parse(title); + } + + public int getLines() { + return lines; + } + + public GUIType getGUIType() { + return Optional.of(GUIType.getByLines(lines)) + .map(type -> type == GUIType.CANCEL ? GUIType.SIX_BY_NINE : type) + .get(); + } + + public List getGuiItems() { + return guiItems; + } + + public void setupItems(Player player, GUI gui) { + getGuiItems().forEach(itemConfiguration -> itemConfiguration.setupItems(player, gui)); + } + + + public static GUIConfiguration readConfiguration(@Nullable ConfigurationSection section) { + if (section == null) return new GUIConfiguration("name", 6, new ArrayList<>()); + + String title = section.getString("title", ""); + int lines = section.getInt("lines", 6); + ConfigurationSection itemsSection = section.getConfigurationSection("items"); + if (itemsSection == null) return new GUIConfiguration(title, lines, new ArrayList<>()); + + return new GUIConfiguration( + title, lines, itemsSection.getKeys(false).stream() + .map(key -> GUIItemConfiguration.readFrom(itemsSection.getConfigurationSection(key))) + .filter(Objects::nonNull) + .collect(Collectors.toList()) + ); + } + + public static ClickType readClickType(String type) { + return Arrays.stream(ClickType.values()) + .filter(click -> click.name().equalsIgnoreCase(type)) + .findFirst().orElse(null); + } + +} diff --git a/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/configuration/GUIItemConfiguration.java b/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/configuration/GUIItemConfiguration.java new file mode 100644 index 0000000..7bd7847 --- /dev/null +++ b/easyplugin-gui/src/main/java/cc/carm/lib/easyplugin/gui/configuration/GUIItemConfiguration.java @@ -0,0 +1,92 @@ +package cc.carm.lib.easyplugin.gui.configuration; + +import cc.carm.lib.easyplugin.gui.GUI; +import cc.carm.lib.easyplugin.gui.GUIItem; +import cc.carm.lib.easyplugin.utils.ItemStackFactory; +import cc.carm.lib.easyplugin.utils.MessageUtils; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +public class GUIItemConfiguration { + + Material material; + int data; + String name; + @NotNull List lore; + + @NotNull List slots; + @NotNull List actions; + + public GUIItemConfiguration(Material material, int data, + String name, @NotNull List lore, + @NotNull List actions, + @NotNull List slots) { + this.material = material; + this.data = data; + this.name = name; + this.lore = lore; + this.slots = slots; + this.actions = actions; + } + + public void setupItems(Player player, GUI gui) { + ItemStackFactory icon = new ItemStackFactory(this.material); + icon.setDurability(this.data); + if (this.name != null) icon.setDisplayName(this.name); + icon.setLore(MessageUtils.setPlaceholders(player, this.lore)); + + GUIItem item = new GUIItem(icon.toItemStack()); + this.actions.stream().map(GUIActionConfiguration::toClickAction).forEach(item::addClickAction); + this.slots.forEach(slot -> gui.setItem(slot, item)); + } + + @Nullable + public static GUIItemConfiguration readFrom(@Nullable ConfigurationSection itemSection) { + if (itemSection == null) return null; + Material material = Optional.ofNullable(Material.matchMaterial(itemSection.getString("material", "STONE"))).orElse(Material.STONE); + int data = itemSection.getInt("data", 0); + String name = itemSection.getString("name"); + List lore = itemSection.getStringList("lore"); + + List slots = itemSection.getIntegerList("slots"); + int slot = itemSection.getInt("slot", 0); + + List actionsString = itemSection.getStringList("actions"); + List actions = new ArrayList<>(); + for (String actionString : actionsString) { + int prefixStart = actionString.indexOf("["); + int prefixEnd = actionString.indexOf("]"); + if (prefixStart < 0 || prefixEnd < 0) continue; + + String prefix = actionString.substring(prefixStart + 1, prefixEnd); + ClickType clickType = null; + GUIActionType actionType; + if (prefix.contains(":")) { + String[] args = prefix.split(":"); + clickType = GUIConfiguration.readClickType(args[0]); + actionType = GUIActionType.readActionType(args[1]); + } else { + actionType = GUIActionType.readActionType(prefix); + } + + if (actionType == null) continue; + actions.add(new GUIActionConfiguration(clickType, actionType, actionString.substring(prefixEnd + 1).trim())); + } + + return new GUIItemConfiguration( + material, data, name, lore, actions, + slots.size() > 0 ? slots : Collections.singletonList(slot) + ); + } + + +} diff --git a/easyplugin-lp/pom.xml b/easyplugin-lp/pom.xml new file mode 100644 index 0000000..9fef87c --- /dev/null +++ b/easyplugin-lp/pom.xml @@ -0,0 +1,23 @@ + + + + easyplugin-parent + cc.carm.lib + 1.0.0-SNAPSHOT + + 4.0.0 + + + 11 + 11 + UTF-8 + UTF-8 + + + easyplugin-lp + jar + + + \ No newline at end of file diff --git a/easyplugin-main/pom.xml b/easyplugin-main/pom.xml new file mode 100644 index 0000000..1dc99bf --- /dev/null +++ b/easyplugin-main/pom.xml @@ -0,0 +1,74 @@ + + + + easyplugin-parent + cc.carm.lib + 1.0.0-SNAPSHOT + + 4.0.0 + + + 11 + 11 + UTF-8 + UTF-8 + + + + easyplugin-main + jar + + EasyPlugin-Main + 轻松插件主要接口集,包含方便的插件入口类与相关工具类。 + https://github.com/CarmJos/EasyPlugin + + + + CarmJos + Carm Jos + carm@carm.cc + https://www.carm.cc + + + + + + GNU General Public License v3.0 + https://opensource.org/licenses/GPL-3.0 + + + + + GitHub Issues + https://github.com/CarmJos/EasyPlugin/issues + + + + GitHub Actions + https://github.com/CarmJos/EasyPlugin/actions/workflows/maven.yml + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + + + \ No newline at end of file diff --git a/easyplugin-main/src/main/java/cc/carm/lib/easyplugin/EasyPlugin.java b/easyplugin-main/src/main/java/cc/carm/lib/easyplugin/EasyPlugin.java new file mode 100644 index 0000000..3a0a44c --- /dev/null +++ b/easyplugin-main/src/main/java/cc/carm/lib/easyplugin/EasyPlugin.java @@ -0,0 +1,135 @@ +package cc.carm.lib.easyplugin; + +import cc.carm.lib.easyplugin.utils.ColorParser; +import cc.carm.lib.easyplugin.utils.SchedulerUtils; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.PluginCommand; +import org.bukkit.command.TabCompleter; +import org.bukkit.event.Listener; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +public abstract class EasyPlugin extends JavaPlugin { + + + private SchedulerUtils scheduler; + private boolean initialized = false; + + @Override + public void onLoad() { + scheduler = new SchedulerUtils(this); + + if (!isOverride("load")) return; + + log(getName() + " " + getDescription().getVersion() + " &7开始加载..."); + long startTime = System.currentTimeMillis(); + load(); + log("加载完成 ,共耗时 " + (System.currentTimeMillis() - startTime) + " ms 。"); + } + + @Override + public void onEnable() { + + log(getName() + " " + getDescription().getVersion() + " &7开始启动..."); + long startTime = System.currentTimeMillis(); + + this.initialized = initialize(); + + if (!isInitialized()) { + setEnabled(false); + return; + } + + log("启用完成 ,共耗时 " + (System.currentTimeMillis() - startTime) + " ms 。"); + } + + + @Override + public void onDisable() { + if (!isOverride("shutdown")) return; + + log(getName() + " " + getDescription().getVersion() + " 开始卸载..."); + long startTime = System.currentTimeMillis(); + shutdown(); + log("卸载完成 ,共耗时 " + (System.currentTimeMillis() - startTime) + " ms 。"); + } + + public void load() { + } + + public abstract boolean initialize(); + + public void shutdown() { + } + + public boolean isInitialized() { + return initialized; + } + + public boolean isDebugging() { + return false; + } + + public SchedulerUtils getScheduler() { + return scheduler; + } + + public void regListener(@NotNull Listener... listeners) { + Arrays.stream(listeners).forEach(listener -> Bukkit.getPluginManager().registerEvents(listener, this)); + } + + public void registerCommand(String commandName, + @NotNull CommandExecutor executor) { + registerCommand(commandName, executor, executor instanceof TabCompleter ? (TabCompleter) executor : null); + } + + public void registerCommand(String commandName, + @NotNull CommandExecutor executor, + @Nullable TabCompleter tabCompleter) { + PluginCommand command = Bukkit.getPluginCommand(commandName); + if (command == null) return; + command.setExecutor(executor); + if (tabCompleter != null) command.setTabCompleter(tabCompleter); + } + + + public void log(@Nullable String... messages) { + print(null, messages); + } + + public void print(@Nullable String prefix, @Nullable String... messages) { + Arrays.stream(messages) + .map(message -> "[" + getName() + "] " + (prefix == null ? "" : prefix) + message) + .map(ColorParser::parse) + .forEach(message -> Bukkit.getConsoleSender().sendMessage(message)); + } + + public void error(String... messages) { + print("&c[ERROR] &r", messages); + } + + public void debug(@Nullable String... messages) { + if (isDebugging()) print("&7[DEBUG] &r", messages); + } + + + private boolean isOverride(String methodName) { + Map methodMap = new HashMap<>(); + Arrays.stream(EasyPlugin.class.getDeclaredMethods()) + .filter(method -> method.getName().equals(methodName)) + .forEach(method -> Arrays.stream(getClass().getDeclaredMethods()) + .filter(extend -> extend.getName().equals(methodName)) + .filter(extend -> extend.getReturnType().equals(method.getReturnType())) + .filter(extend -> extend.getParameterTypes().length == method.getParameterTypes().length) + .findFirst().ifPresent(extendMethod -> methodMap.put(method, extendMethod)) + ); + return !methodMap.isEmpty(); + } +} diff --git a/easyplugin-main/src/main/java/cc/carm/lib/easyplugin/utils/ColorParser.java b/easyplugin-main/src/main/java/cc/carm/lib/easyplugin/utils/ColorParser.java new file mode 100644 index 0000000..04dd78b --- /dev/null +++ b/easyplugin-main/src/main/java/cc/carm/lib/easyplugin/utils/ColorParser.java @@ -0,0 +1,33 @@ + +package cc.carm.lib.easyplugin.utils; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ColorParser { + + public static String parse(String text) { + text = parseHexColor(text); + return parseColor(text); + } + + public static String parseColor(final String text) { + return text.replaceAll("&", "§").replace("§§", "&"); + } + + public static String parseHexColor(String text) { + Pattern pattern = Pattern.compile("&\\((&?#[0-9a-fA-F]{6})\\)"); + Matcher matcher = pattern.matcher(text); + while (matcher.find()) { + String hexColor = text.substring(matcher.start() + 2, matcher.end() - 1); + hexColor = hexColor.replace("&", ""); + StringBuilder bukkitColorCode = new StringBuilder('§' + "x"); + for (int i = 1; i < hexColor.length(); i++) { + bukkitColorCode.append('§').append(hexColor.charAt(i)); + } + text = text.replaceAll("&\\(" + hexColor + "\\)", bukkitColorCode.toString().toLowerCase()); + matcher.reset(text); + } + return text; + } +} diff --git a/easyplugin-main/src/main/java/cc/carm/lib/easyplugin/utils/ItemStackFactory.java b/easyplugin-main/src/main/java/cc/carm/lib/easyplugin/utils/ItemStackFactory.java new file mode 100644 index 0000000..29a8674 --- /dev/null +++ b/easyplugin-main/src/main/java/cc/carm/lib/easyplugin/utils/ItemStackFactory.java @@ -0,0 +1,144 @@ +package cc.carm.lib.easyplugin.utils; + + +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.Damageable; +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) { + ItemMeta im = this.item.getItemMeta(); + if (im instanceof Damageable) { + ((Damageable) im).setDamage(i); + this.item.setItemMeta(im); + } + 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.parse(name)); + this.item.setItemMeta(im); + } + return this; + } + + public ItemStackFactory setLore(@NotNull List loreList) { + ItemMeta im = this.item.getItemMeta(); + if (im != null) { + im.setLore( + loreList.stream() + .map(ColorParser::parse) + .collect(Collectors.toList()) + ); + this.item.setItemMeta(im); + } + return this; + } + + public ItemStackFactory addLore(@NotNull String s) { + ItemMeta im = this.item.getItemMeta(); + if (im != null) { + List lore = im.getLore() != null ? im.getLore() : new ArrayList<>(); + lore.add(ColorParser.parse(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; + } +} diff --git a/easyplugin-main/src/main/java/cc/carm/lib/easyplugin/utils/MessageUtils.java b/easyplugin-main/src/main/java/cc/carm/lib/easyplugin/utils/MessageUtils.java new file mode 100644 index 0000000..11f8dfe --- /dev/null +++ b/easyplugin-main/src/main/java/cc/carm/lib/easyplugin/utils/MessageUtils.java @@ -0,0 +1,85 @@ +package cc.carm.lib.easyplugin.utils; + +import me.clip.placeholderapi.PlaceholderAPI; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +public class MessageUtils { + + public static boolean hasPlaceholderAPI() { + return Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null; + } + + public static void send(@Nullable CommandSender sender, List messages) { + if (messages == null || messages.isEmpty() || sender == null) return; + for (String s : messages) { + sender.sendMessage(ColorParser.parse(s)); + } + } + + public static void send(@Nullable CommandSender sender, String... messages) { + send(sender, Arrays.asList(messages)); + } + + public static void sendWithPlaceholders(CommandSender sender, String... messages) { + sendWithPlaceholders(sender, Arrays.asList(messages)); + } + + public static void sendWithPlaceholders(@Nullable CommandSender sender, List messages) { + if (messages == null || messages.isEmpty() || sender == null) return; + send(sender, setPlaceholders(sender, messages)); + } + + public static void sendWithPlaceholders(@Nullable CommandSender sender, List messages, String param, Object value) { + sendWithPlaceholders(sender, messages, new String[]{param}, new Object[]{value}); + } + + public static void sendWithPlaceholders(@Nullable CommandSender sender, List messages, String[] params, Object[] values) { + sendWithPlaceholders(sender, setCustomParams(messages, params, values)); + } + + public static List setPlaceholders(@Nullable CommandSender sender, List messages) { + if (messages == null || messages.isEmpty() || sender == null) return messages; + if (hasPlaceholderAPI() && sender instanceof Player) { + return PlaceholderAPI.setPlaceholders((Player) sender, messages); + } else { + return messages; + } + } + + public static List setPlaceholders(@Nullable CommandSender sender, List messages, String[] params, Object[] values) { + return setPlaceholders(sender, setCustomParams(messages, params, values)); + } + + public static List setCustomParams(List messages, String param, Object value) { + return setCustomParams(messages, new String[]{param}, new Object[]{value}); + } + + public static List setCustomParams(List messages, String[] params, Object[] values) { + if (params.length != values.length) return messages; + HashMap paramsMap = new HashMap<>(); + for (int i = 0; i < params.length; i++) { + paramsMap.put(params[i], values[i]); + } + return setCustomParams(messages, paramsMap); + } + + + public static List setCustomParams(List messages, HashMap params) { + List list = new ArrayList<>(); + for (String message : messages) { + String afterMessage = message; + for (Map.Entry entry : params.entrySet()) { + afterMessage = afterMessage.replace(entry.getKey(), entry.getValue().toString()); + } + list.add(afterMessage); + } + return list; + } + + +} diff --git a/easyplugin-main/src/main/java/cc/carm/lib/easyplugin/utils/SchedulerUtils.java b/easyplugin-main/src/main/java/cc/carm/lib/easyplugin/utils/SchedulerUtils.java new file mode 100644 index 0000000..e0bcc53 --- /dev/null +++ b/easyplugin-main/src/main/java/cc/carm/lib/easyplugin/utils/SchedulerUtils.java @@ -0,0 +1,352 @@ +package cc.carm.lib.easyplugin.utils; + +import org.bukkit.Bukkit; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.Queue; +import java.util.concurrent.Callable; + +@SuppressWarnings("DuplicatedCode") +public class SchedulerUtils { + + private final JavaPlugin plugin; + + public SchedulerUtils(JavaPlugin plugin) { + this.plugin = plugin; + } + + private JavaPlugin getPlugin() { + return plugin; + } + + /** + * 在主线程延时执行一个任务。 + * + * @param delay 延迟的ticks + * @param runnable 需要执行的任务 + */ + public void runLater(long delay, Runnable runnable) { + Bukkit.getScheduler().runTaskLater(getPlugin(), runnable, delay); + } + + /** + * 异步延时执行一个任务。 + * + * @param delay 延迟的ticks + * @param runnable 需要执行的任务 + */ + public void runLaterAsync(long delay, Runnable runnable) { + Bukkit.getScheduler().runTaskLaterAsynchronously(getPlugin(), runnable, delay); + } + + /** + * 异步执行一个任务。 + * + * @param runnable 需要执行的任务 + */ + public void runAsync(Runnable runnable) { + Bukkit.getScheduler().runTaskAsynchronously(getPlugin(), runnable); + } + + /** + * 在服务端主线程中执行一个任务 + * + * @param runnable 需要执行的任务 + */ + public void run(Runnable runnable) { + Bukkit.getScheduler().runTask(getPlugin(), runnable); + } + + /** + * 间隔一段时间按顺序异步执行列表中的任务 + * + * @param interval 间隔时间 + * @param tasks 任务列表 + */ + public void runAtIntervalAsync(long interval, Runnable... tasks) { + runAtIntervalAsync(0L, interval, tasks); + } + + /** + * 间隔一段时间按顺序执行列表中的任务 + * + * @param interval 间隔时间 + * @param tasks 任务列表 + */ + public void runAtInterval(long interval, Runnable... tasks) { + runAtInterval(0L, interval, tasks); + } + + /** + * 间隔一段时间按顺序异步执行列表中的任务 + * + * @param delay 延迟时间 + * @param interval 间隔时间 + * @param tasks 任务列表 + */ + public void runAtIntervalAsync(long delay, long interval, Runnable... tasks) { + new BukkitRunnable() { + private int index; + + @Override + public void run() { + if (this.index >= tasks.length) { + this.cancel(); + return; + } + + tasks[index].run(); + index++; + } + }.runTaskTimerAsynchronously(getPlugin(), delay, interval); + } + + /** + * 间隔一段时间按顺序执行列表中的任务 + * + * @param delay 延迟时间 + * @param interval 间隔时间 + * @param tasks 任务列表 + */ + public void runAtInterval(long delay, long interval, Runnable... tasks) { + new BukkitRunnable() { + private int index; + + @Override + public void run() { + if (this.index >= tasks.length) { + this.cancel(); + return; + } + + tasks[index].run(); + index++; + } + }.runTaskTimer(getPlugin(), delay, interval); + } + + /** + * 重复执行一个任务。 + * + * @param repetitions 重复次数 + * @param interval 间隔时间 + * @param task 任务 + * @param onComplete 结束时执行的任务 + */ + public void repeat(int repetitions, long interval, Runnable task, Runnable onComplete) { + new BukkitRunnable() { + private int index; + + @Override + public void run() { + index++; + if (this.index >= repetitions) { + this.cancel(); + if (onComplete == null) { + return; + } + + onComplete.run(); + return; + } + + task.run(); + } + }.runTaskTimer(getPlugin(), 0L, interval); + } + + /** + * 重复执行一个任务。 + * + * @param repetitions 重复次数 + * @param interval 间隔时间 + * @param task 任务 + * @param onComplete 结束时执行的任务 + */ + public void repeatAsync(int repetitions, long interval, Runnable task, Runnable onComplete) { + new BukkitRunnable() { + private int index; + + @Override + public void run() { + index++; + if (this.index >= repetitions) { + this.cancel(); + if (onComplete == null) { + return; + } + + onComplete.run(); + return; + } + + task.run(); + } + }.runTaskTimerAsynchronously(getPlugin(), 0L, interval); + } + + /** + * 在满足某个条件时,重复执行一个任务。 + * + * @param interval 重复间隔时间 + * @param predicate 条件 + * @param task 任务 + * @param onComplete 结束时执行的任务 + */ + public void repeatWhile(long interval, Callable predicate, Runnable task, Runnable onComplete) { + new BukkitRunnable() { + @Override + public void run() { + try { + if (!predicate.call()) { + this.cancel(); + if (onComplete == null) { + return; + } + + onComplete.run(); + return; + } + + task.run(); + } catch (Exception e) { + e.printStackTrace(); + } + } + }.runTaskTimer(getPlugin(), 0L, interval); + } + + /** + * 在满足某个条件时,重复执行一个任务。 + * + * @param interval 重复间隔时间 + * @param predicate 条件 + * @param task 任务 + * @param onComplete 结束时执行的任务 + */ + public void repeatWhileAsync(long interval, Callable predicate, Runnable task, Runnable onComplete) { + new BukkitRunnable() { + @Override + public void run() { + try { + if (!predicate.call()) { + this.cancel(); + if (onComplete == null) { + return; + } + + onComplete.run(); + return; + } + + task.run(); + } catch (Exception e) { + e.printStackTrace(); + } + } + }.runTaskTimerAsynchronously(getPlugin(), 0L, interval); + } + + public interface Task { + void start(Runnable onComplete); + } + + public class TaskBuilder { + private final Queue taskList; + + public TaskBuilder() { + this.taskList = new LinkedList<>(); + } + + public TaskBuilder append(TaskBuilder builder) { + this.taskList.addAll(builder.taskList); + return this; + } + + public TaskBuilder appendDelay(long delay) { + this.taskList.add(onComplete -> SchedulerUtils.this.runLater(delay, onComplete)); + return this; + } + + public TaskBuilder appendTask(Runnable task) { + this.taskList.add(onComplete -> + { + task.run(); + onComplete.run(); + }); + + return this; + } + + public TaskBuilder appendTask(Task task) { + this.taskList.add(task); + return this; + } + + public TaskBuilder appendDelayedTask(long delay, Runnable task) { + this.taskList.add(onComplete -> SchedulerUtils.this.runLater(delay, () -> + { + task.run(); + onComplete.run(); + })); + + return this; + } + + public TaskBuilder appendTasks(long delay, long interval, Runnable... tasks) { + this.taskList.add(onComplete -> + { + Runnable[] runnables = Arrays.copyOf(tasks, tasks.length + 1); + runnables[runnables.length - 1] = onComplete; + SchedulerUtils.this.runAtInterval(delay, interval, runnables); + }); + + return this; + } + + public TaskBuilder appendRepeatingTask(int repetitions, long interval, Runnable task) { + this.taskList.add(onComplete -> SchedulerUtils.this.repeat(repetitions, interval, task, onComplete)); + return this; + } + + public TaskBuilder appendConditionalRepeatingTask(long interval, Callable predicate, Runnable task) { + this.taskList.add(onComplete -> SchedulerUtils.this.repeatWhile(interval, predicate, task, onComplete)); + return this; + } + + public TaskBuilder waitFor(Callable predicate) { + this.taskList.add(onComplete -> new BukkitRunnable() { + @Override + public void run() { + try { + if (!predicate.call()) { + return; + } + + this.cancel(); + onComplete.run(); + } catch (Exception e) { + e.printStackTrace(); + } + } + }.runTaskTimer(getPlugin(), 0L, 1L)); + return this; + } + + public void runTasks() { + this.startNext(); + } + + private void startNext() { + Task task = this.taskList.poll(); + if (task == null) { + return; + } + + task.start(this::startNext); + } + } +} diff --git a/easyplugin-placeholderapi/pom.xml b/easyplugin-placeholderapi/pom.xml new file mode 100644 index 0000000..edc3f45 --- /dev/null +++ b/easyplugin-placeholderapi/pom.xml @@ -0,0 +1,22 @@ + + + + easyplugin-parent + cc.carm.lib + 1.0.0-SNAPSHOT + + 4.0.0 + + + 11 + 11 + UTF-8 + UTF-8 + + + easyplugin-placeholderapi + + + \ No newline at end of file diff --git a/easyplugin-vault/pom.xml b/easyplugin-vault/pom.xml new file mode 100644 index 0000000..76f16d5 --- /dev/null +++ b/easyplugin-vault/pom.xml @@ -0,0 +1,33 @@ + + + + easyplugin-parent + cc.carm.lib + 1.0.0-SNAPSHOT + + 4.0.0 + + + 11 + 11 + UTF-8 + UTF-8 + + + easyplugin-vault + jar + + + + + com.github.MilkBowl + VaultAPI + 1.7 + provided + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..036c812 --- /dev/null +++ b/pom.xml @@ -0,0 +1,242 @@ + + + 4.0.0 + + + 11 + 11 + UTF-8 + UTF-8 + + + cc.carm.lib + easyplugin-parent + pom + 1.0.0-SNAPSHOT + + easyplugin-main + + easyplugin-database + easyplugin-gui + easyplugin-configuration + easyplugin-command + + easyplugin-vault + easyplugin-placeholderapi + + easyplugin-all + easyplugin-common + easyplugin-lp + + + EasyPlugin + 轻松插件类库,简单快捷的通用Spigot插件基础类库。 + https://github.com/CarmJos/EasyPlugin + + + + CarmJos + Carm Jos + carm@carm.cc + https://www.carm.cc + + + + + + GNU General Public License v3.0 + https://opensource.org/licenses/GPL-3.0 + + + + + GitHub Issues + https://github.com/CarmJos/EasyPlugin/issues + + + + GitHub Actions + https://github.com/CarmJos/EasyPlugin/actions/workflows/maven.yml + + + + https://github.com/CarmJos/EasyPlugin/releases + + github + GitHub Packages + https://maven.pkg.github.com/CarmJos/EasyPlugin + + + + + + + github + GitHub Packages + https://maven.pkg.github.com/CarmJos/EasyPlugin + + + + central + https://repo1.maven.org/maven2/ + + + + carm-repo + Carm's Repo + https://repo.carm.cc/repository/maven-public/ + + + + nexus + https://mvn.lumine.io/repository/maven-public/ + + + + + + + + org.spigotmc + spigot-api + 1.13-R0.1-SNAPSHOT + provided + + + + org.spigotmc + spigot + 1.13-R0.1-SNAPSHOT + provided + + + + me.clip + placeholderapi + 2.10.9 + provided + + + + org.jetbrains + annotations + 22.0.0 + provided + + + + junit + junit + 4.13.2 + test + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.1 + + false + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + javadoc + + https://javadoc.io/doc/org.jetbrains/annotations/ + + false + UTF-8 + UTF-8 + UTF-8 + zh_CN + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + UTF-8 + -parameters + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + org.apache.maven.plugins + maven-source-plugin + 3.2.0 + + + package + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.3 + + + package + + shade + + + false + + + + + + + *:* + + META-INF/MANIFEST.MF + META-INF/*.txt + + + + + + + + + + src/main/resources + true + + + + + + \ No newline at end of file