diff --git a/.badge/economy badge.png b/.badge/economy badge.png new file mode 100644 index 0000000..5192b30 Binary files /dev/null and b/.badge/economy badge.png differ diff --git a/.badge/economy badge.psd b/.badge/economy badge.psd new file mode 100644 index 0000000..d3957df Binary files /dev/null and b/.badge/economy badge.psd differ diff --git a/.changelog/2.10.0.md b/.changelog/2.10.0.md new file mode 100644 index 0000000..d9cbb30 --- /dev/null +++ b/.changelog/2.10.0.md @@ -0,0 +1,12 @@ +# 2.10.0 + +## API Changes +- Implemented set api methods, which can be used to set the balance for accounts. +```java + EconomyResponse set(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final BigDecimal amount); + EconomyResponse set(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final String worldName, @NotNull final BigDecimal amount); + EconomyResponse set(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final String worldName, @NotNull final String currency, @NotNull final BigDecimal amount); +``` + +# 2.13 +- Added support for 1.21.7 \ No newline at end of file diff --git a/.changelog/2.14.md b/.changelog/2.14.md new file mode 100644 index 0000000..2a170b9 --- /dev/null +++ b/.changelog/2.14.md @@ -0,0 +1,39 @@ +# 2.14 +- Added a few new methods for grabbing accounts that specific accounts have access to. +```java + + /** + * Retrieves a list of account IDs owned by the specified account ID. + * + * @param pluginName the name of the plugin + * @param accountID the unique identifier of the account + * @return a list of account names owned by the specified account ID + * + * @since 2.14 + */ + List accountsOwnedBy(@NotNull final String pluginName, @NotNull final UUID accountID) + + /** + * Retrieves a list of account IDs that the specified account is a member of. + * + * @param pluginName the name of the plugin + * @param accountID the UUID of the account to check membership for + * @return a List of String values representing the accounts that the account is a member of + * + * @since 2.14 + */ + List accountsMemberOf(@NotNull final String pluginName, @NotNull final UUID accountID) + + /** + * Retrieves a list of account IDs that the specified account has the specified permissions for. + * + * @param pluginName the name of the plugin + * @param accountID the UUID of the account to check access for + * @param permissions variable number of permissions to check for + * @return a list of accounts that the account has the specified permissions to + * + * @since 2.14 + */ + List accountsAccessTo(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final AccountPermission... permissions) + +``` \ No newline at end of file diff --git a/.changelog/2.15.md b/.changelog/2.15.md new file mode 100644 index 0000000..7a1109c --- /dev/null +++ b/.changelog/2.15.md @@ -0,0 +1,2 @@ +# 2.15 +- Added support for 1.21.7 \ No newline at end of file diff --git a/.changelog/2.16.md b/.changelog/2.16.md new file mode 100644 index 0000000..685e7ff --- /dev/null +++ b/.changelog/2.16.md @@ -0,0 +1,2 @@ +# 2.16 +- Added support for 1.21.9 \ No newline at end of file diff --git a/.changelog/2.17.md b/.changelog/2.17.md new file mode 100644 index 0000000..dc0cb26 --- /dev/null +++ b/.changelog/2.17.md @@ -0,0 +1,17 @@ +# 2.17 +- Added support for 1.21.10 +- Added clarity to documentation for default behavior if the provider doesn't support share accounts. +- Added clarity to documentation for default behavior if the provider does not support multi-currency. +- Added clarity to documentation for default behavior if the provider doesn't support multiple worlds. +- Deprecated ```List accountsAccessTo(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final AccountPermission... permissions)``` + - This method will be removed in a future release as the string return allows ambiguity. +- Deprecated ```List accountsMemberOf(@NotNull final String pluginName, @NotNull final UUID accountID)``` + - This method will be removed in a future release as the string return allows ambiguity. +- Deprecated ```List accountsOwnedBy(@NotNull final String pluginName, @NotNull final UUID accountID)``` + - This method will be removed in a future release as the string return allows ambiguity. +- Added ```List accountsWithAccessTo(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final AccountPermission... permissions)``` + - This method is a replacement for the now deprecated ```List accountsAccessTo(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final AccountPermission... permissions)``` +- Added ```List accountsWithMembershipTo(@NotNull final String pluginName, @NotNull final UUID accountID)``` + - This method is a replacement for the now deprecated ```List accountsMemberOf(@NotNull final String pluginName, @NotNull final UUID accountID)``` +- Added ```List accountsWithOwnerOf(@NotNull final String pluginName, @NotNull final UUID accountID)``` + - This method is a replacement for the now deprecated ```List accountsOwnedBy(@NotNull final String pluginName, @NotNull final UUID accountID)``` \ No newline at end of file diff --git a/.changelog/2.18.md b/.changelog/2.18.md new file mode 100644 index 0000000..63c4598 --- /dev/null +++ b/.changelog/2.18.md @@ -0,0 +1,5 @@ +# 2.18 + +## API Changes +- Revamped Permission API to include a modern permission API for VaultUnlocked specifically. +- Revamped Chat API to include a modern chat API for VaultUnlocked specifically. \ No newline at end of file diff --git a/.changelog/2.9.0.md b/.changelog/2.9.0.md new file mode 100644 index 0000000..de64afe --- /dev/null +++ b/.changelog/2.9.0.md @@ -0,0 +1,16 @@ +# 2.9.0 + +## API Changes +- Added standards for minimum Vault Unlocked Support. Projects that meet these standards may request + a review to use the badge associated with the API type(economy, etc) that they use. +- Added balance methods in same format as the old getBalance methods. + +## Plugin Changes + +## Fixes + +## Deprecations +- Deprecated getBalance methods, these are marked for removal in 3 releases. Use balance methods instead. +- Deprecated createAccount methods without nonPlayer. Use the methods that include the nonPlayer parameter. + +## Removals \ No newline at end of file diff --git a/.changelog/template.md b/.changelog/template.md new file mode 100644 index 0000000..9eead67 --- /dev/null +++ b/.changelog/template.md @@ -0,0 +1,11 @@ +# Version + +## API Changes + +## Plugin Changes + +## Fixes + +## Deprecations + +## Removals \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/request-a-feature.yml b/.github/ISSUE_TEMPLATE/request-a-feature.yml new file mode 100644 index 0000000..56d4488 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/request-a-feature.yml @@ -0,0 +1,27 @@ +name: Feature Request +description: Suggest a feature to be added in order to help Vault Unlocked improve. +title: "[FEAT]: " +labels: [ "feature" ] +assignees: + - creatorfromhell + +body: + - type: markdown + attributes: + value: Thanks for helping to improve Vault Unlocked with feature requests! + - type: textarea + attributes: + label: Feature Description + description: Describe the feature you're requesting to be added here. + placeholder: | + Example: "Add a new method that gives everyone funds!" + validations: + required: true + - type: textarea + attributes: + label: Reasoning + description: Why should this be added? What is the use-case? + placeholder: | + Example: "Global wealth!@#!@#!" + validations: + required: true \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/request-badge-review.yml b/.github/ISSUE_TEMPLATE/request-badge-review.yml new file mode 100644 index 0000000..9566990 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/request-badge-review.yml @@ -0,0 +1,108 @@ +name: BADGE REVIEW +description: Request a review of a project for a Vault Unlocked Support Badge. +title: "[BADGE REVIEW]: " +labels: [ "badge review" ] +assignees: +- creatorfromhell + +body: +- type: dropdown + id: dropdown-1 + attributes: + label: Badge Type + description: The type of badge that is being requested. + options: + - Economy + default: 0 + validations: + required: true +- type: input + id: input-2 + attributes: + label: Project Name + description: The name of your project + placeholder: Example Project + validations: + required: true +- type: input + id: input-3 + attributes: + label: Project URL + description: The URL of your project. + placeholder: https://tnemc.net + validations: + required: true +- type: input + id: input-4 + attributes: + label: Source URL + description: The source of your project. + placeholder: https://github.com/TheNewEconomy/VaultUnlockedAPI + validations: + required: true + +### Economy Plugin Checklist + +- type: checkboxes + id: core-functionality + attributes: + label: Core Functionality + description: Implement all required functionality from the Economy interface. + options: + - label: "Fully implement all non-default methods from the Economy interface" + required: false + - label: "Implement boolean hasSharedAccountSupport()" + required: false + - label: "Implement boolean hasMultiCurrencySupport()" + required: false + - label: "Default to the base currency if multi-currency functionality is not supported" + required: false + - label: "Specify lack of multi-currency support on the project page or GitHub repository" + required: false + +- type: checkboxes + id: optional-features + attributes: + label: Optional Features + description: Implement optional shared account methods. + options: + - label: "Implement createSharedAccount(String pluginName, UUID accountID, String name, UUID owner)" + required: false + - label: I confirm that I have not read these checkboxes, so I just ticked them all. + required: false + - label: "Implement isAccountOwner(String pluginName, UUID accountID, UUID uuid)" + required: false + - label: "Implement addAccountMember(String pluginName, UUID accountID, UUID uuid, AccountPermission... permissions)" + required: false + - label: "Implement removeAccountMember(String pluginName, UUID accountID, UUID uuid)" + required: false + - label: "Implement hasAccountPermission(String pluginName, UUID accountID, UUID uuid, AccountPermission permission)" + required: false + - label: "Implement updateAccountPermission(String pluginName, UUID accountID, UUID uuid, AccountPermission permission, boolean value)" + required: false + +- type: checkboxes + id: user-plugin-methods + attributes: + label: Economy User Plugin Methods + description: Implement the required methods for Economy User Plugins. + options: + - label: "Implement balance(String pluginName, UUID accountID)" + required: false + - label: "Implement withdraw(String pluginName, UUID accountID, BigDecimal amount)" + required: false + - label: "Implement deposit(String pluginName, UUID accountID, BigDecimal amount)" + required: false + +- type: checkboxes + id: multi-currency-support + attributes: + label: Multi-Currency Support + description: Verify and document multi-currency support. + options: + - label: "Properly implement hasMultiCurrencySupport() and ensure it returns true if supported" + required: false + - label: "Provide functional implementation for currencies()" + required: false + - label: "Provide functional implementation for getDefaultCurrency(String pluginName)" + required: false diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml new file mode 100644 index 0000000..93b2f9a --- /dev/null +++ b/.github/workflows/gradle.yml @@ -0,0 +1,49 @@ +# 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://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Java CI with Gradle + +on: + push: + branches: + - master + - main + + pull_request: + branches: + - master + - main + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 21 + cache: gradle + + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Build with Gradle + run: ./gradlew build + + - uses: actions/upload-artifact@v4 + with: + name: VaultUnlockedAPI + path: | + **/build/libs/*.jar \ No newline at end of file diff --git a/.github/workflows/javadoc.yml b/.github/workflows/javadoc.yml new file mode 100644 index 0000000..cd916c6 --- /dev/null +++ b/.github/workflows/javadoc.yml @@ -0,0 +1,37 @@ +name: Deploy Javadoc + +on: + push: + branches: + - master + - main + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + contents: write # if you have a protection rule on your repository, you'll need to give write permission to the workflow. + + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 21 + cache: gradle + + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Deploy JavaDoc 🚀 + uses: MathieuSoysal/Javadoc-publisher.yml@v3.0.2 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + javadoc-branch: gh-pages + java-version: 21 + target-folder: javadoc # url will be https://.github.io//javadoc, This can be left as nothing to generate javadocs in the root folder. + project: gradle \ No newline at end of file diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 31df88d..41aaef1 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -15,24 +15,25 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up JDK 1.8 - uses: actions/setup-java@v1 + uses: actions/setup-java@v3 with: - java-version: 1.8 + java-version: '8' + distribution: 'temurin' - name: Cache Maven packages - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: ~/.m2 key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} restore-keys: ${{ runner.os }}-m2 - name: Build Release run: mvn -B package --file pom.xml - - name: Build javadoc - run: mvn -B javadoc:jar --file pom.xml + #- name: Build javadoc + # run: mvn -B javadoc:jar --file pom.xml - name: Stage the artifact run: mkdir staging && cp target/*.jar staging - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: - name: VaultAPI + name: VaultUnlockedAPI path: staging diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 97b9189..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Publish VaultAPI to GitHub Packages -on: - release: - types: [created] -jobs: - publish: - runs-on: ubuntu-latest - steps: - - name: Checkout main branch - uses: actions/checkout@v2 - - name: Checkout gh-pages branch - uses: actions/checkout@v2 - with: - ref: gh-pages - path: gh-pages - - uses: actions/setup-java@v1 - with: - java-version: 1.8 - - name: Build and publish package - env: - GITHUB_TOKEN: ${{ github.token }} - run: | - mvn -B javadoc:javadoc -# mvn -B deploy - - name: Commit javadocs - run: | - cp -Rfv target/javadoc-latest/* gh-pages/ - cd gh-pages - git config --local user.email "action@github.com" - git config --local user.name "GitHub Action" - git commit -m "Update javadoc pages for latest release" -a - - name: Push javadoc changes - uses: ad-m/github-push-action@master - with: - branch: gh-pages - directory: gh-pages - github_token: ${{ github.token }} - diff --git a/.gitignore b/.gitignore index 37cc1ae..e5f3421 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,29 @@ /.project /.settings /bin/ +/.idea/ +/VaultAPI.iml +/VaultUnlockedAPI.iml + +## From gitignore/Gradle.gitignore on GitHub +.gradle +**/build/ +!**/src/**/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Avoid ignore Gradle wrappper properties +!gradle-wrapper.properties + +# Cache of project +.gradletasknamecache + +# Eclipse Gradle plugin generated files +# Eclipse Core +.project +# JDT-specific (Eclipse Java Development Tools) +.classpath diff --git a/.mvn/settings.xml b/.mvn/settings.xml deleted file mode 100644 index bdef178..0000000 --- a/.mvn/settings.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - github - - - - - github - - - central - https://repo1.maven.org/maven2 - true - true - - - github - GitHub Maven Packages - https://maven.pkg.github.com/milkbowl/github-releases - - - - - - - - github - MilkBowl - ${env.GITHUB_TOKEN} - - - \ No newline at end of file diff --git a/.standard/EconomyBadge.md b/.standard/EconomyBadge.md new file mode 100644 index 0000000..e5acda2 --- /dev/null +++ b/.standard/EconomyBadge.md @@ -0,0 +1,76 @@ +# VaultUnlocked Economy Support Badge: Minimum Implementation Standard + +The following document outlines the minimum implementation standard required for projects to achieve the VaultUnlocked Economy Support Badge. The requirements are divided into two categories: **Economy Plugins** (providers of the economy) and **Economy User Plugins** (e.g., banks, chest shops). + +--- + +## **Standards Checklist** + +### **1. Economy Plugins** +Economy Plugins must implement the following core functionality from the Economy interface to provide comprehensive economy functionality: + +#### **Required Functionality** +- Fully Implement the non-default methods. +- Implement the methods for optional functionality: + - boolean hasSharedAccountSupport(); + - boolean hasMultiCurrencySupport(); +- If your plugin doesn't support the multi-currency functionality, defaulting to your base currency, and +specifying this on your project page, or GitHub repository. + +#### **Optional Features** +Economy Plugins may optionally implement shared account and permission-related APIs: +- Shared Account Methods: + - createSharedAccount(String pluginName, UUID accountID, String name, UUID owner) + - isAccountOwner(String pluginName, UUID accountID, UUID uuid) + - addAccountMember(String pluginName, UUID accountID, UUID uuid, AccountPermission... permissions) + - removeAccountMember(String pluginName, UUID accountID, UUID uuid) + - hasAccountPermission(String pluginName, UUID accountID, UUID uuid, AccountPermission permission) + - updateAccountPermission(String pluginName, UUID accountID, UUID uuid, AccountPermission permission, boolean value) + +--- + +### **2. Economy User Plugins** +Economy User Plugins, such as banks, chest shops, or auction houses, must implement a minimal set of functionality from the Economy interface to achieve "minimum implementation." + +#### **Required Methods** + +1. **Account Balance Management:** + - balance(String pluginName, UUID accountID): + - Retrieve the balance for a specific account. + - withdraw(String pluginName, UUID accountID, BigDecimal amount): + - Withdraw a specified amount from an account. + - deposit(String pluginName, UUID accountID, BigDecimal amount): + - Deposit a specified amount into an account. + +--- + +#### **Multi-Currency Support** +If you're third-party plugin doesn't support using a different currency for your plugin, please make +sure to have this specified on the project page, or GitHub repository. + +### **3. Evidence of Multi-Currency Support (For Economy Plugins Only)** +Economy Plugins must demonstrate multi-currency support by: +- Properly implementing hasMultiCurrencySupport() and returning true if supported. +- Providing functional implementations for: + - currencies() + - getDefaultCurrency(String pluginName) + +--- + +## **Submission Requirements** +1. **Economy Plugins:** + - A GitHub ticket detailing: + - **Project Name** + - **Usage of VaultUnlocked** + - **Description of multi-currency support implementation** (if applicable). + - Evidence of multi-currency support (if implemented) in the form of logs or outputs. + +2. **Economy User Plugins:** + - A GitHub ticket detailing: + - **Project Name** + - **Usage of VaultUnlocked** (e.g., bank, shop, auction house). + - Evidence of successful implementation of the required balance-related methods through logs or outputs. + +--- + +By adhering to these standards, your project will demonstrate compatibility with the VaultUnlocked Economy API and earn the Economy Support Badge. While optional features enhance the plugin's functionality, implementing the required methods ensures a baseline level of integration and interoperability. \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 708d9c4..0000000 --- a/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: java -jdk: [ openjdk8 ] -branches: - except: - - gh-pages -sudo: false -env: - global: - - secure: "lkC+9PeVPx0sFEAITPszoHvPV9jnavsJdA3Slo4FakzTB5AlERHszto4RdenAhPf347r8xKL120YvDxDeYvmffpG7NUcRXfQZxod1SRyFEFUUBC0zGHkLiJlBjAqkSEDacruldT4+1BCqRc/A96zj17knmUkvKnyutQtasOGKxk=" - - secure: "UxxyRTgZFxEbzxfpEKFC6bYVKkhVp/kOCy5QZwbctkwQP33l3eEwDUquDVXewwLWgM6yJvWdUq9Va/f2kJ8Z7NMHLj5UTj3zIWdqJ/dZIrZ32Vb6tTawXV56627ANLsGHfw55uqIIHFs3u3HUlucyYhBAxLsxJNR4XbU2IeA8fA=" - - secure: "ljUPRZkuNEqck8RIHONVD7lCr1a/aslagOQ27uB0EpuOMGfeBlDdAlpo+GnRSs2bsfvUGX9nmcgGPR6mTcV0fzHaSBg+p/BPWBuzo9wEs39H4wn8yVU70pu/wCEuRhGlFw4GE0mYp8pbHMHrc8WdxsF3dt4kAGsdVhivXuz9HHI=" -after_success: -- .utility/do-publish.sh diff --git a/.utility/do-publish.sh b/.utility/do-publish.sh deleted file mode 100755 index f663952..0000000 --- a/.utility/do-publish.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -current_dir=`pwd` - -if [[ "$TRAVIS_REPO_SLUG" != "MilkBowl/VaultAPI" || "$TRAVIS_PULL_REQUEST" == "true" || "$TRAVIS_BRANCH" != "master" ]] -then - echo 'Travis can only publish docs for release builds.' - return 0 -fi - -mvn clean javadoc:javadoc javadoc:jar deploy --settings .utility/settings.xml - -# Get to the Travis build directory, configure git and clone the repo -cd $HOME -git config --global user.email "travis@travis-ci.org" -git config --global user.name "travis-ci" -git clone --quiet --branch=gh-pages https://${GH_TOKEN}@github.com/MilkBowl/VaultAPI gh-pages > /dev/null - -# Commit and Push the Changes -cd gh-pages -git rm -rf * -cp -Rfv $current_dir/target/javadoc-latest/* ./ -git add -f . -git commit -m "Latest javadoc on successful travis build $TRAVIS_BUILD_NUMBER auto-pushed to gh-pages" -git push -fq origin gh-pages > /dev/null diff --git a/.utility/settings.xml b/.utility/settings.xml deleted file mode 100644 index e16eb13..0000000 --- a/.utility/settings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - pub-repo - ${env.DEPLOY_USER} - ${env.DEPLOY_PASS} - - - \ No newline at end of file diff --git a/README.md b/README.md index d50c704..74a6bb7 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,20 @@ -# VaultAPI - Abstraction Library API for Bukkit Plugins - [![](https://travis-ci.org/MilkBowl/VaultAPI.svg?branch=master)](https://travis-ci.org/MilkBowl/VaultAPI) +# VaultUnlockedAPI - Abstraction Library API for Bukkit Plugins - [![Javadoc](https://img.shields.io/badge/JavaDoc-Online-green)](https://theneweconomy.github.io/VaultUnlockedAPI/javadoc/) [![Build Status](https://ci.codemc.io/job/creatorfromhell/job/VaultUnlockedAPI/badge/icon)](https://ci.codemc.io/job/creatorfromhell/job/VaultUnlockedAPI/) [![Economy Badge](https://github.com/TheNewEconomy/VaultUnlockedAPI/blob/master/.badge/economy%20badge.png)](https://github.com/TheNewEconomy/VaultUnlockedAPI) + How to include the API with Maven: ```xml - jitpack.io - https://jitpack.io + codemc-creatorfromhell + https://repo.codemc.io/repository/creatorfromhell/ + - com.github.MilkBowl - VaultAPI - 1.7 + net.milkbowl.vault + VaultUnlockedAPI + 2.16 provided @@ -21,36 +23,49 @@ How to include the API with Maven: How to include the API with Gradle: ```groovy repositories { - maven { url 'https://jitpack.io' } + maven { url 'https://repo.codemc.io/repository/creatorfromhell/' } } dependencies { - compileOnly "com.github.MilkBowl:VaultAPI:1.7" + compileOnly "net.milkbowl.vault:VaultUnlockedAPI:2.16" } ``` -**Note**: The VaultAPI version has 2 numbers (major.minor), unlike Vault, which has 3. The 2 numbers in the VaultAPI will always correspond to the 2 beginning numbers in a Vault version to make it clear what versions your plugin will for sure work with. +**Note**: The VaultUnlockedAPI version has 2 numbers (major.minor), unlike Vault, which has 3. The 2 +numbers in the VaultUnlockedAPI will always correspond to the 2 beginning numbers in a VaultUnlocked +version to make it clear what versions your plugin will for sure work with. + +## Why VaultUnlocked? +I have no preference regarding which library is best suited for +your plugin development efforts. I believe a central suite (or "Vault") +of solutions is a more effective approach than focusing on a single +category of plugins. This is the concept behind VaultUnlocked. + +### Key Features You'll Appreciate + +* **No Source Code Integration Needed** + VaultUnlocked operates as a standalone plugin, so you only need to obtain an instance of it. This prevents conflicts with multiple plugins using the same namespaces. Simply include VaultUnlocked.jar in your download zip file for seamless integration! +* **Extensive Plugin Support** + VaultUnlocked provides an abstraction layer not just for Economic plugins but for Permission plugins as well, ensuring broad compatibility. +* **Freedom of Choice** + One of the best aspects of Bukkit is the freedom to choose what to use. More options benefit developers, so here’s to embracing choice! -## Why Vault? -I have no preference which library suits your plugin and development efforts -best. Really, I thought a central suite (rather...Vault) of solutions was the -the proper avenue than focusing on a single category of plugin. That's where -the idea for Vault came into play. +### Enhanced Features of VaultUnlocked -So, what features do I _think_ you'll like the most? +* **Multi-Currency Support** +* **More Friendly PR Acceptance** +* **Folia Support** - * No need to include my source code in your plugin - * Broad range of supported plugins - * Choice! +Let me know if you need any further modifications! ## License -Copyright (C) 2011-2018 Morgan Humes +Copyright (C) 2024 Daniel "creatorfromhell" Vidmar -Vault is free software: you can redistribute it and/or modify +VaultUnlocked is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -Vault is distributed in the hope that it will be useful, +VaultUnlocked is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. @@ -59,18 +74,33 @@ You should have received a copy of the GNU Lesser General Public License along with Vault. If not, see . ## Building -VaultAPI comes with all libraries needed to build from the current branch. +VaultUnlockedAPI comes with all libraries needed to build from the current branch. -## Implementing Vault -Implementing Vault is quite simple. It requires getting the Economy, Permission, or Chat service from the Bukkit ServiceManager. See the example below: +## Plugin Support +While VaultUnlocked works with plugins that support the original Vault, the VaultUnlocked-specific API adds enhanced functionality that plugins must implement specifically. +For this, we have created a VaultUnlocked Support badge, which will be assigned to projects that meet a minimum specification outlined in [Minimum Spec Standard](.standard/EconomyBadge.md). + +### Economy Plugins +Economy providers that have VaultUnlocked support. +- TheNewEconomy +- Polyconomy +- iConomyUnlocked + +### Economy User Plugins +Plugins that use VaultUnlocked to interface with Economy Plugins. + +## Implementing VaultUnlocked +Implementing VaultUnlocked is quite simple. It requires getting the Economy, Permission, or Chat service from the Bukkit ServiceManager. See the example below: ```java package com.example.plugin; -import net.milkbowl.vault.chat.Chat; -import net.milkbowl.vault.economy.Economy; -import net.milkbowl.vault.economy.EconomyResponse; -import net.milkbowl.vault.permission.Permission; +import java.util.logging.Logger; + +import net.milkbowl.vault2.chat.Chat; +import net.milkbowl.vault2.economy.Economy; +import net.milkbowl.vault2.economy.EconomyResponse; +import net.milkbowl.vault2.permission.Permission; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -91,7 +121,7 @@ public class ExamplePlugin extends JavaPlugin { @Override public void onEnable() { - if (!setupEconomy() ) { + if (!setupEconomy()) { getLogger().severe(String.format("[%s] - Disabled due to no Vault dependency found!", getDescription().getName())); getServer().getPluginManager().disablePlugin(this); return; @@ -134,8 +164,8 @@ public class ExamplePlugin extends JavaPlugin { if(command.getLabel().equals("test-economy")) { // Lets give the player 1.05 currency (note that SOME economic plugins require rounding!) - sender.sendMessage(String.format("You have %s", econ.format(econ.getBalance(player.getName())))); - EconomyResponse r = econ.depositPlayer(player, 1.05); + sender.sendMessage(String.format("You have %s", econ.format(econ.getBalance(player.getUniqueId())))); + EconomyResponse r = econ.depositPlayer(player.getUniqueId(), new BigDecimal("1.05")); if(r.transactionSuccess()) { sender.sendMessage(String.format("You were given %s and now have %s", econ.format(r.amount), econ.format(r.balance))); } else { diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..665e01a --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,121 @@ +plugins { + `java-library` + `maven-publish` +} + +group = "net.milkbowl.vault" +version = "2.17" +description = "VaultUnlockedAPI" + +repositories { + mavenCentral() + maven { + name = "Spigot" + url = uri("https://hub.spigotmc.org/nexus/content/groups/public/") + } +} + +dependencies { + // See ./gradle/libs.versions.toml for updating package groups and versions. + + //Runtime + compileOnly(libs.annotations.jetbrains) + compileOnly(libs.bukkit) { + exclude("com.google.code.gson", "gson") + exclude("com.google.guava", "guava") + exclude("commons-lang", "commons-lang") + exclude("junit", "junit") + exclude("org.yaml", "snakeyaml") + } + + //Tests + testImplementation(libs.junit) +} + + + +java { + withSourcesJar() + withJavadocJar() + toolchain { + languageVersion = JavaLanguageVersion.of(8) + } +} + +publishing { + publications.create("maven") { + from(components["java"]) + + pom { + name = rootProject.name + description = "VaultUnlocked is a Permissions & Economy API to allow plugins to more easily hook into" + + " these systems without needing to hook each individual system themselves. " + + "VaultUnlocked supports all plugins that support Vault 1.7" + url = "https://modrinth.com/plugin/vaultunlocked" + organization { + name = "The New Economy" + url = "https://tnemc.net" + } + licenses { + license { + name = "GNU Lesser General Public License, Version 3 (LGPL-3.0)" + url = "https://github.com/TheNewEconomy/VaultUnlockedAPI/blob/master/license.txt" + } + } + developers { + developer { + id = "creatorfromhell" + name = "Daniel \"creatorfromhell\" Vidmar" + email = "daniel.viddy@gmail.com" + url = "https://cfh.dev" + organization = "The New Economy" + organizationUrl = "https://tnemc.net" + } + } + scm { + connection = "scm:git:git://github.com/TheNewEconomy/VaultUnlockedAPI.git" + developerConnection = "scm:git:git://github.com/TheNewEconomy/VaultUnlockedAPI.git" + url = "https://github.com/TheNewEconomy/VaultUnlockedAPI" + } + issueManagement { + system = "GitHub" + url = "https://github.com/TheNewEconomy/VaultUnlockedAPI/issues" + } + } + } + + repositories { + maven { + name = "CodeMC" + url = uri("https://repo.codemc.io/repository/creatorfromhell/") + + val mavenUsername = System.getenv("GRADLE_PROJECT_MAVEN_USERNAME") + val mavenPassword = System.getenv("GRADLE_PROJECT_MAVEN_PASSWORD") + if (mavenUsername != null && mavenPassword != null) { + credentials { + username = mavenUsername + password = mavenPassword + } + } + } + } +} + +tasks.withType { + options.encoding = "UTF-8" + options.compilerArgs.add("-parameters") +} + +tasks.withType { + isFailOnError = false + + options.encoding = "UTF-8" + (options as StandardJavadocDocletOptions).apply { + windowTitle = "VaultUnlocked" + isAuthor = true + isVersion = true + links ("https://docs.oracle.com/javase/8/docs/api/", "") + bottom = "TheNewEconomy, 2025" + isNoTimestamp = true + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..dddb525 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,4 @@ +# https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties + +org.gradle.configuration-cache=true + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..1475df5 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,12 @@ +# This file was generated by the Gradle 'init' task. +# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format + +[versions] +junit = "4.13.1" +bukkit = "1.13.1-R0.1-SNAPSHOT" +annotations-jetbrains = "24.0.0" + +[libraries] +junit = { module = "junit:junit", version.ref = "junit" } +bukkit = { module = "org.bukkit:bukkit", version.ref = "bukkit" } +annotations-jetbrains = { module = "org.jetbrains:annotations", version.ref = "annotations-jetbrains" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..1b33c55 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..2a84e18 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..23d15a9 --- /dev/null +++ b/gradlew @@ -0,0 +1,251 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH="\\\"\\\"" + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..5eed7ee --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH= + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/pom.xml b/pom.xml index 959b534..62ee371 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,13 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 net.milkbowl.vault - VaultAPI - 1.7 + VaultUnlockedAPI + 2.16 - VaultAPI - Vault is a Permissions & Economy API to allow plugins to more easily hook into these systems without needing to hook each individual system themselves. -Vault currently supports the following: Permissions 3, PEX, GroupManager, bPerms, bPerms2, SimplyPerms, DroxPerms, zPermissions, rscPermissions, KPerms, Starburst, iConomy (4/5/6) BOSEconomy *6/7), EssentialsEcon, 3Co, MultiConomy, MineConomy, EconXP, eWallet, CurrencyCore, XPBank, CraftConomy, AEco, SDFEconomy, TAEcon - + VaultUnlockedAPI + VaultUnlocked is a Permissions & Economy API to allow plugins to more easily hook into these systems without needing to hook each individual system themselves. VaultUnlocked supports all plugins that support Vault + http://dev.bukkit.org/server-mods/vault/ @@ -18,25 +17,36 @@ Vault currently supports the following: Permissions 3, PEX, GroupManager, bPerms + - MilkBowl - https://github.com/MilkBowl + The New Economy + https://tnemc.net + + + creatorfromhell + Daniel "creatorfromhell" Vidmar + daniel.viddy@gmail.com + https://cfh.dev + The New Economy + https://tnemc.net + + developer + + America/New_York + + + - https://github.com/MilkBowl/VaultAPI - scm:git:git://github.com:MilkBowl/VaultAPI.git + https://github.com/TheNewEconomy/VaultUnlockedAPI + scm:git:git://github.com/TheNewEconomy/VaultUnlockedAPI.git scm:git:git@github.com:MilkBowl/VaultAPI.git - - Travis-CI - https://travis-ci.org/MilkBowl/VaultAPI - - GitHub - https://github.com/MilkBowl/VaultAPI/issues + https://github.com/TheNewEconomy/VaultUnlockedAPI/issues @@ -47,11 +57,14 @@ Vault currently supports the following: Permissions 3, PEX, GroupManager, bPerms - - github - GitHub Packages - https://maven.pkg.github.com/milkbowl/github-releases - + + codemc-releases + https://repo.codemc.io/repository/maven-releases/ + + + codemc-snapshots + https://repo.codemc.io/repository/maven-snapshots/ + @@ -70,6 +83,12 @@ Vault currently supports the following: Permissions 3, PEX, GroupManager, bPerms test true + + org.jetbrains + annotations + 24.0.0 + compile + @@ -78,10 +97,13 @@ Vault currently supports the following: Permissions 3, PEX, GroupManager, bPerms org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.10.1 - 1.8 - 1.8 + 8 + 8 + + -parameters + @@ -101,18 +123,16 @@ Vault currently supports the following: Permissions 3, PEX, GroupManager, bPerms org.apache.maven.plugins maven-javadoc-plugin - 3.2.0 + 3.11.2 public - Vault + VaultUnlocked false true true true true - Milkbowl, 2020]]> - ${project.build.directory} - javadoc-latest + TheNewEconomy, 2025]]> diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..cdd2252 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,5 @@ +rootProject.name = "VaultUnlockedAPI" + +plugins { + id("org.gradle.toolchains.foojay-resolver-convention").version("1.0.0") +} \ No newline at end of file diff --git a/src/main/java/net/milkbowl/vault/chat/Chat.java b/src/main/java/net/milkbowl/vault/chat/Chat.java index 2cb2091..8945223 100644 --- a/src/main/java/net/milkbowl/vault/chat/Chat.java +++ b/src/main/java/net/milkbowl/vault/chat/Chat.java @@ -24,6 +24,8 @@ /** * The main Chat API - allows for Prefix/Suffix nodes along with generic Info nodes if the linked Chat system supports them * + * @deprecated in lieu of the modern Vault2. To update alter your import to net.milkbowl.vault2.chat. + */ public abstract class Chat { diff --git a/src/main/java/net/milkbowl/vault/economy/AbstractEconomy.java b/src/main/java/net/milkbowl/vault/economy/AbstractEconomy.java index 4fe0e37..00a1523 100644 --- a/src/main/java/net/milkbowl/vault/economy/AbstractEconomy.java +++ b/src/main/java/net/milkbowl/vault/economy/AbstractEconomy.java @@ -1,87 +1,87 @@ -package net.milkbowl.vault.economy; - -import org.bukkit.OfflinePlayer; - -@SuppressWarnings("deprecation") -public abstract class AbstractEconomy implements Economy { - - @Override - public boolean hasAccount(OfflinePlayer player) { - if (player.getName() == null) return false; - return hasAccount(player.getName()); - } - - @Override - public boolean hasAccount(OfflinePlayer player, String worldName) { - if (player.getName() == null) return false; - return hasAccount(player.getName(), worldName); - } - - @Override - public double getBalance(OfflinePlayer player) { - return getBalance(player.getName()); - } - - @Override - public double getBalance(OfflinePlayer player, String world) { - return getBalance(player.getName(), world); - } - - @Override - public boolean has(OfflinePlayer player, double amount) { - if (player.getName() == null) return false; - return has(player.getName(), amount); - } - - @Override - public boolean has(OfflinePlayer player, String worldName, double amount) { - if (player.getName() == null) return false; - return has(player.getName(), worldName, amount); - } - - @Override - public EconomyResponse withdrawPlayer(OfflinePlayer player, double amount) { - return withdrawPlayer(player.getName(), amount); - } - - @Override - public EconomyResponse withdrawPlayer(OfflinePlayer player, String worldName, double amount) { - return withdrawPlayer(player.getName(), worldName, amount); - } - - @Override - public EconomyResponse depositPlayer(OfflinePlayer player, double amount) { - return depositPlayer(player.getName(), amount); - } - - @Override - public EconomyResponse depositPlayer(OfflinePlayer player, String worldName, double amount) { - return depositPlayer(player.getName(), worldName, amount); - } - - @Override - public EconomyResponse createBank(String name, OfflinePlayer player) { - return createBank(name, player.getName()); - } - - @Override - public EconomyResponse isBankOwner(String name, OfflinePlayer player) { - return isBankOwner(name, player.getName()); - } - - @Override - public EconomyResponse isBankMember(String name, OfflinePlayer player) { - return isBankMember(name, player.getName()); - } - - @Override - public boolean createPlayerAccount(OfflinePlayer player) { - return createPlayerAccount(player.getName()); - } - - @Override - public boolean createPlayerAccount(OfflinePlayer player, String worldName) { - return createPlayerAccount(player.getName(), worldName); - } - -} +package net.milkbowl.vault.economy; + +import org.bukkit.OfflinePlayer; + +@SuppressWarnings("deprecation") +public abstract class AbstractEconomy implements Economy { + + @Override + public boolean hasAccount(OfflinePlayer player) { + if (player.getName() == null) return false; + return hasAccount(player.getName()); + } + + @Override + public boolean hasAccount(OfflinePlayer player, String worldName) { + if (player.getName() == null) return false; + return hasAccount(player.getName(), worldName); + } + + @Override + public double getBalance(OfflinePlayer player) { + return getBalance(player.getName()); + } + + @Override + public double getBalance(OfflinePlayer player, String world) { + return getBalance(player.getName(), world); + } + + @Override + public boolean has(OfflinePlayer player, double amount) { + if (player.getName() == null) return false; + return has(player.getName(), amount); + } + + @Override + public boolean has(OfflinePlayer player, String worldName, double amount) { + if (player.getName() == null) return false; + return has(player.getName(), worldName, amount); + } + + @Override + public EconomyResponse withdrawPlayer(OfflinePlayer player, double amount) { + return withdrawPlayer(player.getName(), amount); + } + + @Override + public EconomyResponse withdrawPlayer(OfflinePlayer player, String worldName, double amount) { + return withdrawPlayer(player.getName(), worldName, amount); + } + + @Override + public EconomyResponse depositPlayer(OfflinePlayer player, double amount) { + return depositPlayer(player.getName(), amount); + } + + @Override + public EconomyResponse depositPlayer(OfflinePlayer player, String worldName, double amount) { + return depositPlayer(player.getName(), worldName, amount); + } + + @Override + public EconomyResponse createBank(String name, OfflinePlayer player) { + return createBank(name, player.getName()); + } + + @Override + public EconomyResponse isBankOwner(String name, OfflinePlayer player) { + return isBankOwner(name, player.getName()); + } + + @Override + public EconomyResponse isBankMember(String name, OfflinePlayer player) { + return isBankMember(name, player.getName()); + } + + @Override + public boolean createPlayerAccount(OfflinePlayer player) { + return createPlayerAccount(player.getName()); + } + + @Override + public boolean createPlayerAccount(OfflinePlayer player, String worldName) { + return createPlayerAccount(player.getName(), worldName); + } + +} \ No newline at end of file diff --git a/src/main/java/net/milkbowl/vault/economy/Economy.java b/src/main/java/net/milkbowl/vault/economy/Economy.java index 1d14587..a588d97 100644 --- a/src/main/java/net/milkbowl/vault/economy/Economy.java +++ b/src/main/java/net/milkbowl/vault/economy/Economy.java @@ -23,6 +23,7 @@ /** * The main economy API * + * @deprecated in lieu of the modern Vault2. To update alter your import to net.milkbowl.vault2.economy and update to use the new UUID-based methods where available. */ public interface Economy { @@ -30,19 +31,19 @@ public interface Economy { * Checks if economy method is enabled. * @return Success or Failure */ - public boolean isEnabled(); + boolean isEnabled(); /** * Gets name of economy method * @return Name of Economy Method */ - public String getName(); + String getName(); /** * Returns true if the given implementation supports banks. * @return true if the implementation supports banks */ - public boolean hasBankSupport(); + boolean hasBankSupport(); /** * Some economy plugins round off after a certain number of digits. @@ -50,7 +51,7 @@ public interface Economy { * or -1 if no rounding occurs. * @return number of digits after the decimal point kept */ - public int fractionalDigits(); + int fractionalDigits(); /** * Format amount into a human readable String This provides translation into @@ -59,7 +60,7 @@ public interface Economy { * @param amount to format * @return Human readable string describing amount */ - public String format(double amount); + String format(double amount); /** * Returns the name of the currency in plural form. @@ -67,7 +68,7 @@ public interface Economy { * * @return name of the currency (plural) */ - public String currencyNamePlural(); + String currencyNamePlural(); /** @@ -76,14 +77,19 @@ public interface Economy { * * @return name of the currency (singular) */ - public String currencyNameSingular(); + String currencyNameSingular(); /** - * + * Checks if this player has an account on the server yet + * This will always return true if the player has joined the server at least once + * as all major economy plugins auto-generate a player account when the player joins the server + * + * @param playerName to check + * @return success true or false * @deprecated As of VaultAPI 1.4 use {@link #hasAccount(OfflinePlayer)} instead. */ @Deprecated - public boolean hasAccount(String playerName); + boolean hasAccount(String playerName); /** * Checks if this player has an account on the server yet @@ -93,13 +99,20 @@ public interface Economy { * @param player to check * @return if the player has an account */ - public boolean hasAccount(OfflinePlayer player); + boolean hasAccount(OfflinePlayer player); /** + * Checks if this player has an account on the server yet on the given world + * This will always return true if the player has joined the server at least once + * as all major economy plugins auto-generate a player account when the player joins the server + * + * @param playerName to check in the world + * @param worldName world-specific account + * @return success true or false * @deprecated As of VaultAPI 1.4 use {@link #hasAccount(OfflinePlayer, String)} instead. */ @Deprecated - public boolean hasAccount(String playerName, String worldName); + boolean hasAccount(String playerName, String worldName); /** * Checks if this player has an account on the server yet on the given world @@ -110,13 +123,17 @@ public interface Economy { * @param worldName world-specific account * @return if the player has an account */ - public boolean hasAccount(OfflinePlayer player, String worldName); + boolean hasAccount(OfflinePlayer player, String worldName); /** + * Gets balance of a player + * + * @param playerName of the player + * @return Amount currently held in players account * @deprecated As of VaultAPI 1.4 use {@link #getBalance(OfflinePlayer)} instead. */ @Deprecated - public double getBalance(String playerName); + double getBalance(String playerName); /** * Gets balance of a player @@ -124,13 +141,18 @@ public interface Economy { * @param player of the player * @return Amount currently held in players account */ - public double getBalance(OfflinePlayer player); + double getBalance(OfflinePlayer player); /** + * Gets balance of a player on the specified world. + * IMPLEMENTATION SPECIFIC - if an economy plugin does not support this the global balance will be returned. + * @param playerName to check + * @param world name of the world + * @return Amount currently held in players account * @deprecated As of VaultAPI 1.4 use {@link #getBalance(OfflinePlayer, String)} instead. */ @Deprecated - public double getBalance(String playerName, String world); + double getBalance(String playerName, String world); /** * Gets balance of a player on the specified world. @@ -139,13 +161,18 @@ public interface Economy { * @param world name of the world * @return Amount currently held in players account */ - public double getBalance(OfflinePlayer player, String world); + double getBalance(OfflinePlayer player, String world); /** + * Checks if the player account has the amount - DO NOT USE NEGATIVE AMOUNTS + * + * @param playerName to check + * @param amount to check for + * @return True if player has amount, False else wise * @deprecated As of VaultAPI 1.4 use {@link #has(OfflinePlayer, double)} instead. */ @Deprecated - public boolean has(String playerName, double amount); + boolean has(String playerName, double amount); /** * Checks if the player account has the amount - DO NOT USE NEGATIVE AMOUNTS @@ -154,13 +181,20 @@ public interface Economy { * @param amount to check for * @return True if player has amount, False else wise */ - public boolean has(OfflinePlayer player, double amount); + boolean has(OfflinePlayer player, double amount); /** - * @deprecated As of VaultAPI 1.4 use @{link {@link #has(OfflinePlayer, String, double)} instead. + * Checks if the player account has the amount in a given world - DO NOT USE NEGATIVE AMOUNTS + * IMPLEMENTATION SPECIFIC - if an economy plugin does not support this the global balance will be returned. + * + * @param playerName to check + * @param worldName to check with + * @param amount to check for + * @return True if player has amount in the given world, False else wise + * @deprecated As of VaultAPI 1.4 use {@link #has(OfflinePlayer, String, double)} instead. */ @Deprecated - public boolean has(String playerName, String worldName, double amount); + boolean has(String playerName, String worldName, double amount); /** * Checks if the player account has the amount in a given world - DO NOT USE NEGATIVE AMOUNTS @@ -169,15 +203,20 @@ public interface Economy { * @param player to check * @param worldName to check with * @param amount to check for - * @return True if player has amount, False else wise + * @return True if player has amount in the given world, False else wise */ - public boolean has(OfflinePlayer player, String worldName, double amount); + boolean has(OfflinePlayer player, String worldName, double amount); /** + * Withdraw an amount from a player - DO NOT USE NEGATIVE AMOUNTS + * + * @param playerName to withdraw from + * @param amount Amount to withdraw + * @return Detailed response of transaction * @deprecated As of VaultAPI 1.4 use {@link #withdrawPlayer(OfflinePlayer, double)} instead. */ @Deprecated - public EconomyResponse withdrawPlayer(String playerName, double amount); + EconomyResponse withdrawPlayer(String playerName, double amount); /** * Withdraw an amount from a player - DO NOT USE NEGATIVE AMOUNTS @@ -186,13 +225,19 @@ public interface Economy { * @param amount Amount to withdraw * @return Detailed response of transaction */ - public EconomyResponse withdrawPlayer(OfflinePlayer player, double amount); + EconomyResponse withdrawPlayer(OfflinePlayer player, double amount); /** + * Withdraw an amount from a player on a given world - DO NOT USE NEGATIVE AMOUNTS + * IMPLEMENTATION SPECIFIC - if an economy plugin does not support this the global balance will be returned. + * @param playerName to withdraw from + * @param worldName - name of the world + * @param amount Amount to withdraw + * @return Detailed response of transaction * @deprecated As of VaultAPI 1.4 use {@link #withdrawPlayer(OfflinePlayer, String, double)} instead. */ @Deprecated - public EconomyResponse withdrawPlayer(String playerName, String worldName, double amount); + EconomyResponse withdrawPlayer(String playerName, String worldName, double amount); /** * Withdraw an amount from a player on a given world - DO NOT USE NEGATIVE AMOUNTS @@ -202,13 +247,18 @@ public interface Economy { * @param amount Amount to withdraw * @return Detailed response of transaction */ - public EconomyResponse withdrawPlayer(OfflinePlayer player, String worldName, double amount); + EconomyResponse withdrawPlayer(OfflinePlayer player, String worldName, double amount); /** + * Deposit an amount to a player - DO NOT USE NEGATIVE AMOUNTS + * + * @param playerName to deposit to + * @param amount Amount to deposit + * @return Detailed response of transaction * @deprecated As of VaultAPI 1.4 use {@link #depositPlayer(OfflinePlayer, double)} instead. */ @Deprecated - public EconomyResponse depositPlayer(String playerName, double amount); + EconomyResponse depositPlayer(String playerName, double amount); /** * Deposit an amount to a player - DO NOT USE NEGATIVE AMOUNTS @@ -217,16 +267,23 @@ public interface Economy { * @param amount Amount to deposit * @return Detailed response of transaction */ - public EconomyResponse depositPlayer(OfflinePlayer player, double amount); + EconomyResponse depositPlayer(OfflinePlayer player, double amount); /** + * Deposit an amount to a player on a given world - DO NOT USE NEGATIVE AMOUNTS + * IMPLEMENTATION SPECIFIC - if an economy plugin does not support this the global balance will be returned. + * + * @param playerName to deposit to + * @param worldName name of the world + * @param amount Amount to deposit + * @return Detailed response of transaction * @deprecated As of VaultAPI 1.4 use {@link #depositPlayer(OfflinePlayer, String, double)} instead. */ @Deprecated - public EconomyResponse depositPlayer(String playerName, String worldName, double amount); + EconomyResponse depositPlayer(String playerName, String worldName, double amount); /** - * Deposit an amount to a player - DO NOT USE NEGATIVE AMOUNTS + * Deposit an amount to a player on a given world - DO NOT USE NEGATIVE AMOUNTS * IMPLEMENTATION SPECIFIC - if an economy plugin does not support this the global balance will be returned. * * @param player to deposit to @@ -234,13 +291,17 @@ public interface Economy { * @param amount Amount to deposit * @return Detailed response of transaction */ - public EconomyResponse depositPlayer(OfflinePlayer player, String worldName, double amount); + EconomyResponse depositPlayer(OfflinePlayer player, String worldName, double amount); /** + * Creates a bank account with the specified name and the player as the owner + * @param name of account + * @param player the account should be linked to + * @return EconomyResponse Object * @deprecated As of VaultAPI 1.4 use {{@link #createBank(String, OfflinePlayer)} instead. */ @Deprecated - public EconomyResponse createBank(String name, String player); + EconomyResponse createBank(String name, String player); /** * Creates a bank account with the specified name and the player as the owner @@ -248,21 +309,21 @@ public interface Economy { * @param player the account should be linked to * @return EconomyResponse Object */ - public EconomyResponse createBank(String name, OfflinePlayer player); + EconomyResponse createBank(String name, OfflinePlayer player); /** * Deletes a bank account with the specified name. * @param name of the back to delete * @return if the operation completed successfully */ - public EconomyResponse deleteBank(String name); + EconomyResponse deleteBank(String name); /** * Returns the amount the bank has * @param name of the account * @return EconomyResponse Object */ - public EconomyResponse bankBalance(String name); + EconomyResponse bankBalance(String name); /** * Returns true or false whether the bank has the amount specified - DO NOT USE NEGATIVE AMOUNTS @@ -271,7 +332,7 @@ public interface Economy { * @param amount to check for * @return EconomyResponse Object */ - public EconomyResponse bankHas(String name, double amount); + EconomyResponse bankHas(String name, double amount); /** * Withdraw an amount from a bank account - DO NOT USE NEGATIVE AMOUNTS @@ -280,7 +341,7 @@ public interface Economy { * @param amount to withdraw * @return EconomyResponse Object */ - public EconomyResponse bankWithdraw(String name, double amount); + EconomyResponse bankWithdraw(String name, double amount); /** * Deposit an amount into a bank account - DO NOT USE NEGATIVE AMOUNTS @@ -289,13 +350,18 @@ public interface Economy { * @param amount to deposit * @return EconomyResponse Object */ - public EconomyResponse bankDeposit(String name, double amount); + EconomyResponse bankDeposit(String name, double amount); /** + * Check if a player is the owner of a bank account + * + * @param name of the account + * @param playerName to check for ownership + * @return EconomyResponse Object * @deprecated As of VaultAPI 1.4 use {{@link #isBankOwner(String, OfflinePlayer)} instead. */ @Deprecated - public EconomyResponse isBankOwner(String name, String playerName); + EconomyResponse isBankOwner(String name, String playerName); /** * Check if a player is the owner of a bank account @@ -304,13 +370,18 @@ public interface Economy { * @param player to check for ownership * @return EconomyResponse Object */ - public EconomyResponse isBankOwner(String name, OfflinePlayer player); + EconomyResponse isBankOwner(String name, OfflinePlayer player); /** - * @deprecated As of VaultAPI 1.4 use {{@link #isBankMember(String, OfflinePlayer)} instead. + * Check if the player is a member of the bank account + * + * @param name of the account + * @param playerName to check membership + * @return EconomyResponse Object + * @deprecated As of VaultAPI 1.4 use {@link #isBankMember(String, OfflinePlayer)} instead. */ @Deprecated - public EconomyResponse isBankMember(String name, String playerName); + EconomyResponse isBankMember(String name, String playerName); /** * Check if the player is a member of the bank account @@ -319,32 +390,40 @@ public interface Economy { * @param player to check membership * @return EconomyResponse Object */ - public EconomyResponse isBankMember(String name, OfflinePlayer player); + EconomyResponse isBankMember(String name, OfflinePlayer player); /** * Gets the list of banks * @return the List of Banks */ - public List getBanks(); + List getBanks(); /** - * @deprecated As of VaultAPI 1.4 use {{@link #createPlayerAccount(OfflinePlayer)} instead. + * Attempts to create a player account for the given player + * @param playerName username + * @return if the account creation was successful + * @deprecated As of VaultAPI 1.4 use {@link #createPlayerAccount(OfflinePlayer)} instead. */ @Deprecated - public boolean createPlayerAccount(String playerName); + boolean createPlayerAccount(String playerName); /** * Attempts to create a player account for the given player * @param player OfflinePlayer * @return if the account creation was successful */ - public boolean createPlayerAccount(OfflinePlayer player); + boolean createPlayerAccount(OfflinePlayer player); /** - * @deprecated As of VaultAPI 1.4 use {{@link #createPlayerAccount(OfflinePlayer, String)} instead. + * Attempts to create a player account for the given player on the specified world + * IMPLEMENTATION SPECIFIC - if an economy plugin does not support this then false will always be returned. + * @param playerName username + * @param worldName String name of the world + * @return if the account creation was successful + * @deprecated As of VaultAPI 1.4 use {@link #createPlayerAccount(OfflinePlayer, String)} instead. */ @Deprecated - public boolean createPlayerAccount(String playerName, String worldName); + boolean createPlayerAccount(String playerName, String worldName); /** * Attempts to create a player account for the given player on the specified world @@ -353,5 +432,5 @@ public interface Economy { * @param worldName String name of the world * @return if the account creation was successful */ - public boolean createPlayerAccount(OfflinePlayer player, String worldName); + boolean createPlayerAccount(OfflinePlayer player, String worldName); } diff --git a/src/main/java/net/milkbowl/vault/economy/EconomyResponse.java b/src/main/java/net/milkbowl/vault/economy/EconomyResponse.java index ea9807a..eb49b03 100644 --- a/src/main/java/net/milkbowl/vault/economy/EconomyResponse.java +++ b/src/main/java/net/milkbowl/vault/economy/EconomyResponse.java @@ -20,6 +20,7 @@ * It includes a {@link ResponseType} indicating whether the plugin currently being used for Economy actually allows * the method, or if the operation was a success or failure. * + * @deprecated in lieu of the modern Vault2. To update alter your import to net.milkbowl.vault2.economy. */ public class EconomyResponse { diff --git a/src/main/java/net/milkbowl/vault/permission/Permission.java b/src/main/java/net/milkbowl/vault/permission/Permission.java index 0f68eba..8c2d069 100644 --- a/src/main/java/net/milkbowl/vault/permission/Permission.java +++ b/src/main/java/net/milkbowl/vault/permission/Permission.java @@ -28,6 +28,7 @@ /** * The main Permission API - allows for group and player based permission tests * + * @deprecated in lieu of the modern Vault2. To update alter your import to net.milkbowl.vault2.permission. */ public abstract class Permission { @@ -53,10 +54,18 @@ public abstract class Permission { abstract public boolean hasSuperPermsCompat(); /** + * Checks if player has a permission node. + * Supports NULL value for World if the permission system registered supports global permissions. + * But May return odd values if the servers registered permission system does not have a global permission store. + * + * @param world String world name + * @param player to check + * @param permission Permission node + * @return Success or Failure * @deprecated As of VaultAPI 1.4 use {@link #playerHas(String, OfflinePlayer, String)} instead. */ @Deprecated - public boolean has(String world, String player, String permission) { + public boolean has(final String world, final String player, final String permission) { if (world == null) { return playerHas((String) null, player, permission); } @@ -64,10 +73,18 @@ public boolean has(String world, String player, String permission) { } /** + * Checks if player has a permission node. + * Supports NULL value for World if the permission system registered supports global permissions. + * But May return odd values if the servers registered permission system does not have a global permission store. + * + * @param world String world name + * @param player to check + * @param permission Permission node + * @return Success or Failure * @deprecated As of VaultAPI 1.4 use {@link #playerHas(String, OfflinePlayer, String)} instead. */ @Deprecated - public boolean has(World world, String player, String permission) { + public boolean has(final World world, final String player, final String permission) { if (world == null) { return playerHas((String) null, player, permission); } @@ -84,7 +101,7 @@ public boolean has(World world, String player, String permission) { * @param permission to check for * @return true if the sender has the permission */ - public boolean has(CommandSender sender, String permission) { + public boolean has(final CommandSender sender, final String permission) { return sender.hasPermission(permission); } @@ -94,21 +111,37 @@ public boolean has(CommandSender sender, String permission) { * @param permission Permission node * @return Success or Failure */ - public boolean has(Player player, String permission) { + public boolean has(final Player player, final String permission) { return player.hasPermission(permission); } /** + * Checks if player has a permission node. + * Supports NULL value for World if the permission system registered supports global permissions. + * But May return odd values if the servers registered permission system does not have a global permission store. + * + * @param world String world name + * @param player to check + * @param permission Permission node + * @return Success or Failure * @deprecated As of VaultAPI 1.4 use {@link #playerHas(String, OfflinePlayer, String)} instead. */ @Deprecated abstract public boolean playerHas(String world, String player, String permission); /** + * Checks if player has a permission node. + * Supports NULL value for World if the permission system registered supports global permissions. + * But May return odd values if the servers registered permission system does not have a global permission store. + * + * @param world String world name + * @param player to check + * @param permission Permission node + * @return Success or Failure * @deprecated As of VaultAPI 1.4 use {@link #playerHas(String, OfflinePlayer, String)} instead. */ @Deprecated - public boolean playerHas(World world, String player, String permission) { + public boolean playerHas(final World world, final String player, final String permission) { if (world == null) { return playerHas((String) null, player, permission); } @@ -125,7 +158,7 @@ public boolean playerHas(World world, String player, String permission) { * @param permission Permission node * @return Success or Failure */ - public boolean playerHas(String world, OfflinePlayer player, String permission) { + public boolean playerHas(final String world, final OfflinePlayer player, final String permission) { if (world == null) { return has((String) null, player.getName(), permission); } @@ -141,7 +174,7 @@ public boolean playerHas(String world, OfflinePlayer player, String permission) * @param permission Permission node * @return Success or Failure */ - public boolean playerHas(Player player, String permission) { + public boolean playerHas(final Player player, final String permission) { return has(player, permission); } @@ -160,10 +193,18 @@ public boolean playerHas(Player player, String permission) { abstract public boolean playerAdd(String world, String player, String permission); /** + * Add permission to a player. + * Supports NULL value for World if the permission system registered supports global permissions. + * But May return odd values if the servers registered permission system does not have a global permission store. + * + * @param world String world name + * @param player to add to + * @param permission Permission node + * @return Success or Failure * @deprecated As of VaultAPI 1.4 use {@link #playerAdd(String, OfflinePlayer, String)} instead. */ @Deprecated - public boolean playerAdd(World world, String player, String permission) { + public boolean playerAdd(final World world, final String player, final String permission) { if (world == null) { return playerAdd((String) null, player, permission); } @@ -180,7 +221,7 @@ public boolean playerAdd(World world, String player, String permission) { * @param permission Permission node * @return Success or Failure */ - public boolean playerAdd(String world, OfflinePlayer player, String permission) { + public boolean playerAdd(final String world, final OfflinePlayer player, final String permission) { if (world == null) { return playerAdd((String) null, player.getName(), permission); } @@ -196,7 +237,7 @@ public boolean playerAdd(String world, OfflinePlayer player, String permission) * @param permission Permission node * @return Success or Failure */ - public boolean playerAdd(Player player, String permission) { + public boolean playerAdd(final Player player, final String permission) { return playerAdd(player.getWorld().getName(), player, permission); } @@ -209,7 +250,7 @@ public boolean playerAdd(Player player, String permission) { * @param permission Permission node * @return Success or Failure */ - public boolean playerAddTransient(OfflinePlayer player, String permission) throws UnsupportedOperationException { + public boolean playerAddTransient(final OfflinePlayer player, final String permission) throws UnsupportedOperationException { if (player.isOnline()) { return playerAddTransient((Player) player, permission); } @@ -224,15 +265,15 @@ public boolean playerAddTransient(OfflinePlayer player, String permission) throw * @param permission Permission node * @return Success or Failure */ - public boolean playerAddTransient(Player player, String permission) { - for (PermissionAttachmentInfo paInfo : player.getEffectivePermissions()) { + public boolean playerAddTransient(final Player player, final String permission) { + for (final PermissionAttachmentInfo paInfo : player.getEffectivePermissions()) { if (paInfo.getAttachment() != null && paInfo.getAttachment().getPlugin().equals(plugin)) { paInfo.getAttachment().setPermission(permission, true); return true; } } - PermissionAttachment attach = player.addAttachment(plugin); + final PermissionAttachment attach = player.addAttachment(plugin); attach.setPermission(permission, true); return true; @@ -247,7 +288,7 @@ public boolean playerAddTransient(Player player, String permission) { * @param permission to test * @return Success or Failure */ - public boolean playerAddTransient(String worldName, OfflinePlayer player, String permission) { + public boolean playerAddTransient(final String worldName, final OfflinePlayer player, final String permission) { return playerAddTransient(player, permission); } @@ -260,7 +301,7 @@ public boolean playerAddTransient(String worldName, OfflinePlayer player, String * @param permission to check for * @return Success or Failure */ - public boolean playerAddTransient(String worldName, Player player, String permission) { + public boolean playerAddTransient(final String worldName, final Player player, final String permission) { return playerAddTransient(player, permission); } @@ -273,7 +314,7 @@ public boolean playerAddTransient(String worldName, Player player, String permis * @param permission to remove * @return Success or Failure */ - public boolean playerRemoveTransient(String worldName, OfflinePlayer player, String permission) { + public boolean playerRemoveTransient(final String worldName, final OfflinePlayer player, final String permission) { return playerRemoveTransient(player, permission); } @@ -286,11 +327,19 @@ public boolean playerRemoveTransient(String worldName, OfflinePlayer player, Str * @param permission to check for * @return Success or Failure */ - public boolean playerRemoveTransient(String worldName, Player player, String permission) { + public boolean playerRemoveTransient(final String worldName, final Player player, final String permission) { return playerRemoveTransient((OfflinePlayer) player, permission); } /** + * Remove permission from a player. + * Supports NULL value for World if the permission system registered supports global permissions. + * But May return odd values if the servers registered permission system does not have a global permission store. + * + * @param world World name + * @param player OfflinePlayer + * @param permission Permission node + * @return Success or Failure * @deprecated As of VaultAPI 1.4 use {@link #playerRemove(String, OfflinePlayer, String)} instead. */ @Deprecated @@ -306,7 +355,7 @@ public boolean playerRemoveTransient(String worldName, Player player, String per * @param permission Permission node * @return Success or Failure */ - public boolean playerRemove(String world, OfflinePlayer player, String permission) { + public boolean playerRemove(final String world, final OfflinePlayer player, final String permission) { if (world == null) { return playerRemove((String) null, player.getName(), permission); } @@ -324,7 +373,7 @@ public boolean playerRemove(String world, OfflinePlayer player, String permissio * @return Success or Failure */ @Deprecated - public boolean playerRemove(World world, String player, String permission) { + public boolean playerRemove(final World world, final String player, final String permission) { if (world == null) { return playerRemove((String) null, player, permission); } @@ -339,7 +388,7 @@ public boolean playerRemove(World world, String player, String permission) { * @param permission Permission node * @return Success or Failure */ - public boolean playerRemove(Player player, String permission) { + public boolean playerRemove(final Player player, final String permission) { return playerRemove(player.getWorld().getName(), player, permission); } @@ -354,7 +403,7 @@ public boolean playerRemove(Player player, String permission) { * @param permission Permission node * @return Success or Failure */ - public boolean playerRemoveTransient(OfflinePlayer player, String permission) { + public boolean playerRemoveTransient(final OfflinePlayer player, final String permission) { if (player.isOnline()) { return playerRemoveTransient((Player) player, permission); } else { @@ -369,8 +418,8 @@ public boolean playerRemoveTransient(OfflinePlayer player, String permission) { * @param permission Permission node * @return Success or Failure */ - public boolean playerRemoveTransient(Player player, String permission) { - for (PermissionAttachmentInfo paInfo : player.getEffectivePermissions()) { + public boolean playerRemoveTransient(final Player player, final String permission) { + for (final PermissionAttachmentInfo paInfo : player.getEffectivePermissions()) { if (paInfo.getAttachment() != null && paInfo.getAttachment().getPlugin().equals(plugin)) { paInfo.getAttachment().unsetPermission(permission); return true; @@ -401,7 +450,7 @@ public boolean playerRemoveTransient(Player player, String permission) { * @param permission Permission node * @return Success or Failure */ - public boolean groupHas(World world, String group, String permission) { + public boolean groupHas(final World world, final String group, final String permission) { if (world == null) { return groupHas((String) null, group, permission); } @@ -430,7 +479,7 @@ public boolean groupHas(World world, String group, String permission) { * @param permission Permission node * @return Success or Failure */ - public boolean groupAdd(World world, String group, String permission) { + public boolean groupAdd(final World world, final String group, final String permission) { if (world == null) { return groupAdd((String) null, group, permission); } @@ -459,7 +508,7 @@ public boolean groupAdd(World world, String group, String permission) { * @param permission Permission node * @return Success or Failure */ - public boolean groupRemove(World world, String group, String permission) { + public boolean groupRemove(final World world, final String group, final String permission) { if (world == null) { return groupRemove((String) null, group, permission); } @@ -467,16 +516,32 @@ public boolean groupRemove(World world, String group, String permission) { } /** + * Check if player is member of a group. + * Supports NULL value for World if the permission system registered supports global permissions. + * But May return odd values if the servers registered permission system does not have a global permission store. + * + * @param world World Object + * @param player to check + * @param group Group name + * @return Success or Failure * @deprecated As of VaultAPI 1.4 use {@link #playerInGroup(String, OfflinePlayer, String)} instead. */ @Deprecated abstract public boolean playerInGroup(String world, String player, String group); /** + * Check if player is member of a group. + * Supports NULL value for World if the permission system registered supports global permissions. + * But May return odd values if the servers registered permission system does not have a global permission store. + * + * @param world World Object + * @param player to check + * @param group Group name + * @return Success or Failure * @deprecated As of VaultAPI 1.4 use {@link #playerInGroup(String, OfflinePlayer, String)} instead. */ @Deprecated - public boolean playerInGroup(World world, String player, String group) { + public boolean playerInGroup(final World world, final String player, final String group) { if (world == null) { return playerInGroup((String) null, player, group); } @@ -493,7 +558,7 @@ public boolean playerInGroup(World world, String player, String group) { * @param group Group name * @return Success or Failure */ - public boolean playerInGroup(String world, OfflinePlayer player, String group) { + public boolean playerInGroup(final String world, final OfflinePlayer player, final String group) { if (world == null) { return playerInGroup((String) null, player.getName(), group); } @@ -509,21 +574,37 @@ public boolean playerInGroup(String world, OfflinePlayer player, String group) { * @param group Group name * @return Success or Failure */ - public boolean playerInGroup(Player player, String group) { + public boolean playerInGroup(final Player player, final String group) { return playerInGroup(player.getWorld().getName(), player, group); } /** + * Add player to a group. + * Supports NULL value for World if the permission system registered supports global permissions. + * But May return odd values if the servers registered permission system does not have a global permission store. + * + * @param world String world name + * @param player to add + * @param group Group name + * @return Success or Failure * @deprecated As of VaultAPI 1.4 use {@link #playerAddGroup(String, OfflinePlayer, String)} instead. */ @Deprecated abstract public boolean playerAddGroup(String world, String player, String group); /** + * Add player to a group. + * Supports NULL value for World if the permission system registered supports global permissions. + * But May return odd values if the servers registered permission system does not have a global permission store. + * + * @param world String world name + * @param player to add + * @param group Group name + * @return Success or Failure * @deprecated As of VaultAPI 1.4 use {@link #playerAddGroup(String, OfflinePlayer, String)} instead. */ @Deprecated - public boolean playerAddGroup(World world, String player, String group) { + public boolean playerAddGroup(final World world, final String player, final String group) { if (world == null) { return playerAddGroup((String) null, player, group); } @@ -540,7 +621,7 @@ public boolean playerAddGroup(World world, String player, String group) { * @param group Group name * @return Success or Failure */ - public boolean playerAddGroup(String world, OfflinePlayer player, String group) { + public boolean playerAddGroup(final String world, final OfflinePlayer player, final String group) { if (world == null) { return playerAddGroup((String) null, player.getName(), group); } @@ -556,21 +637,37 @@ public boolean playerAddGroup(String world, OfflinePlayer player, String group) * @param group Group name * @return Success or Failure */ - public boolean playerAddGroup(Player player, String group) { + public boolean playerAddGroup(final Player player, final String group) { return playerAddGroup(player.getWorld().getName(), player, group); } /** + * Remove player from a group. + * Supports NULL value for World if the permission system registered supports global permissions. + * But May return odd values if the servers registered permission system does not have a global permission store. + * + * @param world World Object + * @param player to remove + * @param group Group name + * @return Success or Failure * @deprecated As of VaultAPI 1.4 use {@link #playerRemoveGroup(String, OfflinePlayer, String)} instead. */ @Deprecated abstract public boolean playerRemoveGroup(String world, String player, String group); /** + * Remove player from a group. + * Supports NULL value for World if the permission system registered supports global permissions. + * But May return odd values if the servers registered permission system does not have a global permission store. + * + * @param world World Object + * @param player to remove + * @param group Group name + * @return Success or Failure * @deprecated As of VaultAPI 1.4 use {@link #playerRemoveGroup(String, OfflinePlayer, String)} instead. */ @Deprecated - public boolean playerRemoveGroup(World world, String player, String group) { + public boolean playerRemoveGroup(final World world, final String player, final String group) { if (world == null) { return playerRemoveGroup((String) null, player, group); } @@ -587,7 +684,7 @@ public boolean playerRemoveGroup(World world, String player, String group) { * @param group Group name * @return Success or Failure */ - public boolean playerRemoveGroup(String world, OfflinePlayer player, String group) { + public boolean playerRemoveGroup(final String world, final OfflinePlayer player, final String group) { if (world == null) { return playerRemoveGroup((String) null, player.getName(), group); } @@ -603,21 +700,35 @@ public boolean playerRemoveGroup(String world, OfflinePlayer player, String grou * @param group Group name * @return Success or Failure */ - public boolean playerRemoveGroup(Player player, String group) { + public boolean playerRemoveGroup(final Player player, final String group) { return playerRemoveGroup(player.getWorld().getName(), player, group); } /** + * Gets the list of groups that this player has + * Supports NULL value for World if the permission system registered supports global permissions. + * But May return odd values if the servers registered permission system does not have a global permission store. + * + * @param world String world name + * @param player OfflinePlayer + * @return Array of groups * @deprecated As of VaultAPI 1.4 use {@link #getPlayerGroups(String, OfflinePlayer)} instead. */ @Deprecated abstract public String[] getPlayerGroups(String world, String player); /** + * Gets the list of groups that this player has + * Supports NULL value for World if the permission system registered supports global permissions. + * But May return odd values if the servers registered permission system does not have a global permission store. + * + * @param world String world name + * @param player OfflinePlayer + * @return Array of groups * @deprecated As of VaultAPI 1.4 use {@link #getPlayerGroups(String, OfflinePlayer)} instead. */ @Deprecated - public String[] getPlayerGroups(World world, String player) { + public String[] getPlayerGroups(final World world, final String player) { if (world == null) { return getPlayerGroups((String) null, player); } @@ -633,7 +744,7 @@ public String[] getPlayerGroups(World world, String player) { * @param player OfflinePlayer * @return Array of groups */ - public String[] getPlayerGroups(String world, OfflinePlayer player) { + public String[] getPlayerGroups(final String world, final OfflinePlayer player) { return getPlayerGroups(world, player.getName()); } @@ -645,21 +756,35 @@ public String[] getPlayerGroups(String world, OfflinePlayer player) { * @param player Player Object * @return Array of groups */ - public String[] getPlayerGroups(Player player) { + public String[] getPlayerGroups(final Player player) { return getPlayerGroups(player.getWorld().getName(), player); } /** + * Gets players primary group + * Supports NULL value for World if the permission system registered supports global permissions. + * But May return odd values if the servers registered permission system does not have a global permission store. + * + * @param world String world name + * @param player to get from + * @return Players primary group * @deprecated As of VaultAPI 1.4 use {@link #getPrimaryGroup(String, OfflinePlayer)} instead. */ @Deprecated abstract public String getPrimaryGroup(String world, String player); /** + * Gets players primary group + * Supports NULL value for World if the permission system registered supports global permissions. + * But May return odd values if the servers registered permission system does not have a global permission store. + * + * @param world String world name + * @param player to get from + * @return Players primary group * @deprecated As of VaultAPI 1.4 use {@link #getPrimaryGroup(String, OfflinePlayer)} instead. */ @Deprecated - public String getPrimaryGroup(World world, String player) { + public String getPrimaryGroup(final World world, final String player) { if (world == null) { return getPrimaryGroup((String) null, player); } @@ -675,7 +800,7 @@ public String getPrimaryGroup(World world, String player) { * @param player to get from * @return Players primary group */ - public String getPrimaryGroup(String world, OfflinePlayer player) { + public String getPrimaryGroup(final String world, final OfflinePlayer player) { return getPrimaryGroup(world, player.getName()); } @@ -687,7 +812,7 @@ public String getPrimaryGroup(String world, OfflinePlayer player) { * @param player Player Object * @return Players primary group */ - public String getPrimaryGroup(Player player) { + public String getPrimaryGroup(final Player player) { return getPrimaryGroup(player.getWorld().getName(), player); } diff --git a/src/main/java/net/milkbowl/vault2/chat/ChatUnlocked.java b/src/main/java/net/milkbowl/vault2/chat/ChatUnlocked.java new file mode 100644 index 0000000..ea22c7f --- /dev/null +++ b/src/main/java/net/milkbowl/vault2/chat/ChatUnlocked.java @@ -0,0 +1,290 @@ +package net.milkbowl.vault2.chat; +/* + This file is part of Vault. + + Vault is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vault is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Vault. If not, see . + */ + +import net.milkbowl.vault2.helper.context.Context; +import net.milkbowl.vault2.helper.subject.Subject; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +/** + * Represents a chat provider that allows customization and management of prefixes, + * suffixes, and related information for both individual subjects and groups within + * a specified context. This interface provides methods to retrieve and modify these + * properties, as well as to check for feature support for group-based metadata. + * @author creatorfromhell + * @since 2.18 + */ +public interface ChatUnlocked { + + /** + * Checks whether this chat provider is enabled. + * + * @return true if the chat provider is enabled; false otherwise. + * @since 2.18 + */ + boolean isEnabled(); + + /** + * Retrieves the name of this chat provider. + * + * @return the name of the chat provider as a non-null string. + * @since 2.18 + */ + @NotNull + String getName(); + + /** + * Checks whether the chat provider supports group-based prefixes, suffixes, and info nodes. + * + * @return true if group-based prefixes, suffixes and info nodes are supported; false otherwise. + * @since 2.18 + */ + boolean hasGroupSupport(); + + /** + * Retrieves the prefix for the specified subject within the given context. + * + * @param context the context in which the prefix is being retrieved; must not be null + * @param subject the subject whose prefix is to be retrieved; must not be null + * @return an optional containing the prefix if it exists, or an empty optional if no prefix is set + * @since 2.18 + */ + Optional getPrefix(@NotNull Context context, @NotNull Subject subject); + + /** + * Asynchronously retrieves the prefix associated with the given subject in the specified context. + * The computation is executed asynchronously and returns a {@code CompletableFuture} containing + * an {@code Optional} with the prefix, or an empty {@code Optional} if no prefix is set. + * + * @param context the context in which the prefix is being retrieved; must not be null + * @param subject the subject whose prefix is to be retrieved; must not be null + * @return a {@code CompletableFuture} containing an {@code Optional} with the prefix if it exists, + * or an empty {@code Optional} if no prefix is set + * @since 2.18 + */ + CompletableFuture> getPrefixAsync(@NotNull Context context, @NotNull Subject subject); + + /** + * Retrieves the prefix for the specified subject within the provided context, or null if no prefix exists. + * + * @param context the context in which the prefix is being retrieved; must not be null + * @param subject the subject whose prefix is to be retrieved; must not be null + * @return the prefix as a string if it exists, or null if no prefix is set + * @since 2.18 + */ + default String getPrefixOrNull(@NotNull final Context context, @NotNull final Subject subject) { + return getPrefix(context, subject).orElse(null); + } + + + /** + * Retrieves the suffix for the specified subject within the given context. + * + * @param context the context in which the suffix is being retrieved; must not be null + * @param subject the subject whose suffix is to be retrieved; must not be null + * @return an optional containing the suffix if it exists, or an empty optional if no suffix is set + * @since 2.18 + */ + Optional getSuffix(@NotNull Context context, @NotNull Subject subject); + + /** + * Asynchronously retrieves the suffix associated with the provided subject + * within the given context. + * + * @param context the context in which to look up the suffix; must not be null + * @param subject the subject for which the suffix is to be retrieved; must not be null + * @return a CompletableFuture that resolves to an Optional containing the suffix, + * or an empty Optional if no suffix is found + * @since 2.18 + */ + CompletableFuture> getSuffixAsync(@NotNull Context context, @NotNull Subject subject); + + /** + * Retrieves the suffix for the specified subject in the provided context, or returns null if not available. + * + * @param context the context in which the suffix is being retrieved, must not be null + * @param subject the subject for which the suffix is being retrieved, must not be null + * @return the suffix as a string if available, or null if no suffix is present + * @since 2.18 + */ + default String getSuffixOrNull(@NotNull final Context context, @NotNull final Subject subject) { + return getSuffix(context, subject).orElse(null); + } + + /** + * Sets the prefix for the specified subject within the given context. + * + * @param context the context in which the prefix is being set; must not be null + * @param subject the subject for which the prefix is being updated; must not be null + * @param prefix the new prefix to be assigned; must not be null + * @return true if the prefix was successfully set, false otherwise + * @since 2.18 + */ + boolean setPrefix(@NotNull Context context, @NotNull Subject subject, @NotNull String prefix); + + /** + * Asynchronously sets a prefix for a given subject within a specified context. + * + * @param context the context in which the prefix is being set, must not be null + * @param subject the subject for which the prefix is being set, must not be null + * @param prefix the prefix value to be set, must not be null + * @return a CompletableFuture that resolves to a Boolean indicating whether + * the operation was successful + * @since 2.18 + */ + CompletableFuture setPrefixAsync(@NotNull Context context, @NotNull Subject subject, @NotNull String prefix); + + /** + * Copies the prefix from one subject to another within a given context. + * + * @param context the context in which the operation is performed, must not be null + * @param from the subject from which the prefix will be copied, must not be null + * @param to the subject to which the prefix will be applied, must not be null + * @return true if the prefix was successfully copied, false otherwise + * @since 2.18 + */ + boolean copyPrefix(@NotNull Context context, @NotNull Subject from, @NotNull Subject to); + + /** + * Asynchronously copies the prefix from one subject to another within the given context. + * + * @param context the context in which the operation is performed; must not be null + * @param from the subject from which the prefix will be copied; must not be null + * @param to the subject to which the prefix will be copied; must not be null + * @return a CompletableFuture that completes with {@code true} if the prefix was successfully copied, or {@code false} otherwise + * @since 2.18 + */ + CompletableFuture copyPrefixAsync(@NotNull Context context, @NotNull Subject from, @NotNull Subject to); + + /** + * Sets the suffix for the specified subject within the given context. + * + * @param context the context in which the suffix is being set; must not be null + * @param subject the subject for which the suffix is being updated; must not be null + * @param suffix the new suffix to be assigned; must not be null + * @return true if the suffix was successfully set, false otherwise + * @since 2.18 + */ + boolean setSuffix(@NotNull Context context, @NotNull Subject subject, @NotNull String suffix); + + /** + * Asynchronously sets a suffix for the given subject within the specified context. + * + * @param context the context in which the suffix should be applied, must not be null + * @param subject the subject to which the suffix will be assigned, must not be null + * @param suffix the suffix to assign to the subject, must not be null + * @return a CompletableFuture that resolves to a Boolean indicating whether the operation was successful + * @since 2.18 + */ + CompletableFuture setSuffixAsync(@NotNull Context context, @NotNull Subject subject, @NotNull String suffix); + + /** + * Copies the suffix from one subject to another within the given context. + * + * @param context the context in which the operation is performed, must not be null + * @param from the subject from which the suffix will be copied, must not be null + * @param to the subject to which the suffix will be added, must not be null + * @return true if the suffix was successfully copied, false otherwise + * @since 2.18 + */ + boolean copySuffix(@NotNull Context context, @NotNull Subject from, @NotNull Subject to); + + /** + * Asynchronously copies the suffix from one subject to another in the provided context. + * + * @param context the context in which the suffix copy operation is performed, must not be null + * @param from the source subject from which the suffix is copied, must not be null + * @param to the target subject to which the suffix is copied, must not be null + * @return a CompletableFuture that completes with true if the suffix was successfully copied, + * or false if the operation failed + * @since 2.18 + */ + CompletableFuture copySuffixAsync(@NotNull Context context, @NotNull Subject from, @NotNull Subject to); + + /** + * Retrieves the value associated with the specified key for the given subject within the provided context. + * + * @param the type of the value to be retrieved + * @param context the context in which the value is being retrieved; must not be null + * @param subject the subject for which the value is being retrieved; must not be null + * @param key the key identifying the value to be retrieved; must not be null + * @return an {@code Optional} containing the value associated with the provided key if it exists; otherwise, an empty {@code Optional} + * @since 2.18 + */ + Optional get(final Context context, final Subject subject, final InfoKey key); + + /** + * Retrieves an asynchronous result wrapped in a {@link CompletableFuture}. + * The result contains an {@link Optional} object that may hold the value corresponding + * to the specified {@link InfoKey}. + * + * @param The type of the value associated with the given {@link InfoKey}. + * @param context The context in which the asynchronous operation is executed. + * @param subject The subject associated with the requested operation. + * @param key The key that identifies the specific data to be retrieved. + * @return A {@link CompletableFuture} that completes with an {@link Optional} containing + * the result, or an empty {@link Optional} if the value is not present. + * @since 2.18 + */ + CompletableFuture> getAsync(final Context context, final Subject subject, final InfoKey key); + + /** + * Retrieves the value associated with the specified key for the given subject within the provided context. + * If no value is found, the provided default value is returned. + * + * @param the type of the value to be retrieved + * @param context the context in which the value is being retrieved; must not be null + * @param subject the subject for which the value is being retrieved; must not be null + * @param key the key identifying the value to be retrieved; must not be null + * @param defaultValue the default value to return if no value is found; must not be null + * @return the value associated with the provided key if it exists; otherwise, the specified default value + * @since 2.18 + */ + default T getOrDefault(final Context context, final Subject subject, final InfoKey key, final T defaultValue) { + final Optional value = get(context, subject, key); + return value.orElse(defaultValue); + } + + /** + * Sets the value associated with a specific key for a given subject in the specified context. + * + * @param the type of the value to be set + * @param context the context in which the operation is performed; must not be null + * @param subject the subject for which the value is being set; must not be null + * @param key the key identifying the value to be set; must not be null + * @param value the new value to associate with the given key; must not be null + * @return true if the value was successfully set, false otherwise + * @since 2.18 + */ + boolean set(final Context context, final Subject subject, final InfoKey key, final T value); + + /** + * Asynchronously sets a value in the specified context for the given subject and key. + * + * @param context the context in which the value should be set + * @param subject the subject for which the value is being set + * @param key the key associated with the value to be set + * @param value the value to be set + * @param the type of the value + * @return a CompletableFuture that resolves to a Boolean indicating whether the operation was successful + * @since 2.18 + */ + CompletableFuture setAsync(final Context context, final Subject subject, final InfoKey key, final T value); +} \ No newline at end of file diff --git a/src/main/java/net/milkbowl/vault2/chat/InfoKey.java b/src/main/java/net/milkbowl/vault2/chat/InfoKey.java new file mode 100644 index 0000000..28b7ca8 --- /dev/null +++ b/src/main/java/net/milkbowl/vault2/chat/InfoKey.java @@ -0,0 +1,54 @@ +package net.milkbowl.vault2.chat; +/* + This file is part of Vault. + + Vault is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vault is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Vault. If not, see . + */ + +/** + * Represents a key structure used to store and organize information. + * This class supports generic typing to accommodate different data types. + * + * @param the type of the value associated with this key + * @author creatorfromhell + * @since 2.18 + */ +public class InfoKey { + + private final String node; + + public InfoKey(final String node) { + this.node = node; + } + + public String node() { + return node; + } + + public static InfoKey stringKey(final String node) { + return new InfoKey<>(node); + } + + public static InfoKey boolKey(final String node) { + return new InfoKey<>(node); + } + + public static InfoKey intKey(final String node) { + return new InfoKey<>(node); + } + + public static InfoKey doubleKey(final String node) { + return new InfoKey<>(node); + } +} \ No newline at end of file diff --git a/src/main/java/net/milkbowl/vault2/economy/AccountPermission.java b/src/main/java/net/milkbowl/vault2/economy/AccountPermission.java new file mode 100644 index 0000000..18668b2 --- /dev/null +++ b/src/main/java/net/milkbowl/vault2/economy/AccountPermission.java @@ -0,0 +1,36 @@ +package net.milkbowl.vault2.economy; + +/* This file is part of Vault. + + Vault is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vault is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Vault. If not, see . + */ + +/** + * AccountPermission + * + * @author creatorfromhell + * @since 2.7 + */ +public enum AccountPermission { + + DEPOSIT, + WITHDRAW, + BALANCE, + TRANSFER_OWNERSHIP, + INVITE_MEMBER, + REMOVE_MEMBER, + CHANGE_MEMBER_PERMISSION, + OWNER, + DELETE +} \ No newline at end of file diff --git a/src/main/java/net/milkbowl/vault2/economy/Economy.java b/src/main/java/net/milkbowl/vault2/economy/Economy.java new file mode 100644 index 0000000..8243cf8 --- /dev/null +++ b/src/main/java/net/milkbowl/vault2/economy/Economy.java @@ -0,0 +1,1075 @@ +/* This file is part of Vault. + + Vault is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vault is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Vault. If not, see . + */ + +package net.milkbowl.vault2.economy; + +import net.milkbowl.vault2.economy.EconomyResponse.ResponseType; +import org.jetbrains.annotations.NotNull; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +/** + * The main economy API + * + */ +public interface Economy { + + /* + * Economy plugin-related methods follow. + */ + + /** + * Checks if economy plugin is enabled. + * + * @return true if the server's economy plugin has properly enabled. + */ + boolean isEnabled(); + + /** + * Gets name of the economy plugin. + * + * @return Name of the active economy plugin on the server. + */ + @NotNull + String getName(); + + /** + * Returns true if the economy plugin supports shared accounts. + * + * @return true if the economy plugin supports shared accounts. + */ + boolean hasSharedAccountSupport(); + + /** + * Returns true if the economy plugin supports multiple currencies. + * + * @return true if the economy plugin supports multiple currencies. + */ + boolean hasMultiCurrencySupport(); + + /* + * Currency-related methods follow. + */ + + /** + * Some economy plugins round off after a certain number of digits. This function returns the + * number of digits the plugin keeps or -1 if no rounding occurs. + * + * @param pluginName The name of the plugin that is calling the method. + * + * @return number of digits after the decimal point this plugin supports or -1 if no rounding + * occurs. + */ + int fractionalDigits(@NotNull final String pluginName); + + /** + * Retrieves the number of fractional digits for the specified currency associated with the given + * plugin. This function returns the number of digits the plugin keeps or -1 if no rounding + * occurs. + *

+ * If the provider does not support multi-currency, the provider's default currency will be + * used. + *

+ * @param pluginName the name of the plugin + * @param currency the currency for which the fractional digits are to be retrieved + * + * @return the number of fractional digits for the specified currency or -1 if no rounding occurs. + */ + default int fractionalDigits(@NotNull final String pluginName, @NotNull final String currency) { + + return fractionalDigits(pluginName); + } + + /** + * Plugins use this method to format a given BigDecimal amount into a human-readable amount using + * your economy plugin's currency names/conventions. + * + * @param amount to format. + * + * @return Human-readable string describing amount, ie 5 Dollars or 5.55 Pounds. + * + * @see #fractionalDigits(String) + * @deprecated This method is deprecated as of version 2.8, and has been replaced by + * {@link #format(String, BigDecimal)}. This allows economy plugins to know exactly if the account + * is a player or not. This may be removed in a future release. + */ + @NotNull + @Deprecated + String format(@NotNull final BigDecimal amount); + + /** + * Plugins use this method to format a given BigDecimal amount into a human-readable amount using + * your economy plugin's currency names/conventions. + * + * @param pluginName The name of the plugin that is calling the method. + * @param amount to format. + * + * @return Human-readable String describing amount, ie 5 Dollars or 5.55 Pounds. + * + * @see #fractionalDigits(String) + */ + @NotNull + String format(@NotNull final String pluginName, @NotNull final BigDecimal amount); + + /** + * Plugins use this method to format a given BigDecimal amount into a human-readable amount using + * your economy plugin's currency names/conventions. + *

+ * If the provider does not support multi-currency, the provider's default currency will be + * used. + *

+ * @param amount to format. + * @param currency the currency to use for the format. + * + * @return Human-readable string describing amount, ie 5 Dollars or 5.55 Pounds. + * + * @see #fractionalDigits(String) + * @deprecated This method is deprecated as of version 2.8, and has been replaced by + * {@link #format(String, BigDecimal, String)}. This allows economy plugins to know exactly if the + * account is a player or not. This may be removed in a future release. + */ + @NotNull + @Deprecated + String format(@NotNull final BigDecimal amount, @NotNull final String currency); + + /** + * Plugins use this method to format a given BigDecimal amount into a human-readable amount using + * your economy plugin's currency names/conventions. + *

+ * If the provider does not support multi-currency, the provider's default currency will be + * used. + *

+ * @param pluginName The name of the plugin that is calling the method. + * @param amount to format. + * @param currency the currency to use for the format. + * + * @return Human-readable String describing amount, ie 5 Dollars or 5.55 Pounds. + * + * @see #fractionalDigits(String) + */ + @NotNull + String format(@NotNull final String pluginName, @NotNull final BigDecimal amount, @NotNull final String currency); + + /** + * Returns true if a currency with the specified name exists. + *

+ * If the provider does not support multi-currency, the provider's default currency will be + * used. + *

+ * @param currency the currency to use. + * + * @return true if a currency with the specified name exists. + */ + boolean hasCurrency(@NotNull final String currency); + + /** + * Used to get the default currency. This could be the default currency for the server globally or + * for the default world if the implementation supports multi-world. + *

+ * If the economy being used does not support currency names, then the currency name itself + * should be returned. + *

+ * @param pluginName The name of the plugin that is calling the method. + * + * @return The currency that is the default for the server if multi-world support is not available + * otherwise the default for the default world. + * + */ + @NotNull + String getDefaultCurrency(@NotNull final String pluginName); + + /** + * Returns the name of the default currency in plural form. + *

+ * If the economy being used does not support currency names, then the currency name itself + * should be returned. + *

+ * @param pluginName The name of the plugin that is calling the method. + * + * @return name of the currency (plural) ie: Dollars or Pounds. + */ + @NotNull + String defaultCurrencyNamePlural(@NotNull final String pluginName); + + /** + * Returns the name of the default currency in singular form. + *

+ * If the economy being used does not support currency names, then the currency name itself + * should be returned. + *

+ * @param pluginName The name of the plugin that is calling the method. + * + * @return name of the currency (singular) ie: Dollar or Pound. + */ + @NotNull + String defaultCurrencyNameSingular(@NotNull final String pluginName); + + /** + * Returns a list of currencies used by the economy plugin. These are able to be used in the calls + * in the methods of the API. May not be human-readable. + * + * @return list of currencies used by the economy plugin. These are able to be used in the calls + * in the methods of the API. + */ + @NotNull + Collection currencies(); + + /* + * Account-related methods follow. + */ + /** + * Attempts to create an account for the given UUID. + * + * @param accountID UUID associated with the account. + * @param name the human-readable name to associate with the account. + * + * @return true if the account creation was successful. + * + * @deprecated This method is deprecated as of version 2.8, and has been replaced by + * {@link #createAccount(UUID, String, String, boolean)}. This allows economy plugins to know + * exactly if the account is a player or not. This may be removed in a future release. + */ + @Deprecated + boolean createAccount(@NotNull final UUID accountID, @NotNull final String name); + + /** + * Creates a new account with the provided information. + * + * @param accountID The UUID of the account to be created. + * @param name The name associated with the account. + * @param player A flag indicating if the account is a player account. + * + * @return true if the account was successfully created, false otherwise. + */ + boolean createAccount(@NotNull final UUID accountID, @NotNull final String name, final boolean player); + + /** + * Attempts to create an account for the given UUID on the specified world + *

+ * If the provider does not support multiple worlds, the provider's default world will be used. + *

+ * @param accountID UUID associated with the account. + * @param name the human-readable name to associate with the account. + * @param worldName String name of the world. + * + * @return if the account creation was successful + * + * @deprecated This method is deprecated as of version 2.8, and has been replaced by + * {@link #createAccount(UUID, String, String, boolean)}. This allows economy plugins to know + * exactly if the account is a player or not. This may be removed in a future release. + */ + @Deprecated + boolean createAccount(@NotNull final UUID accountID, @NotNull final String name, @NotNull final String worldName); + + /** + * Creates a new account with the given parameters. + *

+ * If the provider does not support multiple worlds, the provider's default world will be used. + *

+ * @param accountID The UUID of the account to be created. + * @param name The name of the account holder. + * @param worldName The world name associated with the account. + * @param player A boolean indicating if the account belongs to a player. + * + * @return True if the account was successfully created, false otherwise. + */ + boolean createAccount(@NotNull final UUID accountID, @NotNull final String name, @NotNull final String worldName, final boolean player); + + /** + * Returns a map that represents all the UUIDs which have accounts in the plugin, as well as their + * last-known-name. This is used for Vault's economy converter and should be given every account + * available. + * + * @return a {@link Map} composed of the accounts keyed by their UUID, along with their associated + * last-known-name. + */ + @NotNull + Map getUUIDNameMap(); + + /** + * Gets the last known name of an account owned by the given UUID. Required for messages to be + * more human-readable than UUIDs alone can provide. + * + * @param accountID UUID associated with the account. + * + * @return An optional containing the last-known name if the account exists, otherwise an empty + * optional. + */ + Optional getAccountName(@NotNull final UUID accountID); + + /** + * Checks if this UUID has an account yet. + * + * @param accountID UUID to check for an existing account. + * + * @return true if the UUID has an account. + */ + boolean hasAccount(@NotNull final UUID accountID); + + /** + * Checks if this UUID has an account yet in the given world. + *

+ * If the provider does not support multiple worlds, the provider's default world will be used. + *

+ * @param accountID UUID to check for an existing account. + * @param worldName world-specific account. + * + * @return if the UUID has an account. + */ + boolean hasAccount(@NotNull final UUID accountID, @NotNull final String worldName); + + /** + * A method which changes the name associated with the given UUID in the value returned from + * {@link #getUUIDNameMap()}. + * + * @param accountID UUID whose account is having a name change. + * @param name the human-readable name to associate with the account. + * + * @return true if the name change is successful. + */ + boolean renameAccount(@NotNull final UUID accountID, @NotNull final String name); + + /** + * Renames the account with the specified ID in the given plugin to the new name. + * + * @param plugin The plugin name where the account exists + * @param accountID The unique identifier of the account to be renamed + * @param name The new name to assign to the account + * + * @return true if the rename operation was successful, false otherwise + */ + boolean renameAccount(@NotNull final String plugin, @NotNull final UUID accountID, @NotNull final String name); + + /** + * Deletes the account associated with the specified UUID. + * + * @param plugin the name of the plugin managing the account + * @param accountID the UUID of the account to be deleted + * + * @return true if the account was successfully deleted, false otherwise + */ + boolean deleteAccount(@NotNull final String plugin, @NotNull final UUID accountID); + + /* + * Account balance related methods follow. + */ + + /** + * Determines whether an account supports a specific currency. + *

+ * Note: {@code pluginName} should be used for logging/diagnostics only and MUST NOT affect + * business logic. + *
+ * If the provider does not support multi-currency, the provider's default currency will be + * used. + *

+ * @param plugin the name of the plugin + * @param accountID the UUID of the account + * @param currency the currency to check support for. + * + * @return true if the account supports the currency, false otherwise + */ + boolean accountSupportsCurrency(@NotNull final String plugin, @NotNull final UUID accountID, @NotNull final String currency); + + /** + * Checks if the given account supports the specified currency in the given world. + *

+ * Note: {@code pluginName} should be used for logging/diagnostics only and MUST NOT affect + * business logic. + *
+ * If the provider does not support multiple worlds, the provider's default world will be used. + *
+ * If the provider does not support multi-currency, the provider's default currency will be + * used. + *

+ * @param plugin the name of the plugin requesting the check + * @param accountID the UUID of the player account + * @param currency the currency code to check support for + * @param world the name of the world to check in + * + * @return true if the account supports the currency in the world, false otherwise + */ + boolean accountSupportsCurrency(@NotNull final String plugin, @NotNull final UUID accountID, @NotNull final String currency, @NotNull final String world); + + /** + * Gets balance of an account associated with a UUID. + *

+ * Note: {@code pluginName} should be used for logging/diagnostics only and MUST NOT affect + * business logic. + *

+ * @param pluginName The name of the plugin that is calling the method. This is for logging purposes only. + * @param accountID UUID of the account to get a balance for. + * + * @return Amount currently held in account associated with the given UUID. + * + * @deprecated This method is deprecated as of version 2.9, and has been replaced by + * {@link #balance(String, UUID)}. This allows economy plugins to know exactly if the account is a + * player or not. This may be removed in a future release. + */ + @NotNull + @Deprecated + BigDecimal getBalance(@NotNull final String pluginName, @NotNull final UUID accountID); + + /** + * Gets balance of a UUID on the specified world. + *

+ * Note: {@code pluginName} should be used for logging/diagnostics only and MUST NOT affect + * business logic. + *
+ * If the provider does not support multiple worlds, the provider's default world will be used. + *

+ * @param pluginName The name of the plugin that is calling the method. + * @param accountID UUID of the account to get a balance for. + * @param world name of the world. + * + * @return Amount currently held in account associated with the given UUID. + * + * @deprecated This method is deprecated as of version 2.9, and has been replaced by + * {@link #balance(String, UUID, String)}. This allows economy plugins to know exactly if the + * account is a player or not. This may be removed in a future release. + */ + @NotNull + @Deprecated + BigDecimal getBalance(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final String world); + + /** + * Gets balance of a UUID on the specified world and currency. + *

+ * Note: {@code pluginName} should be used for logging/diagnostics only and MUST NOT affect + * business logic. + *
+ * If the provider does not support multiple worlds, the provider's default world will be used. + *
+ * If the provider does not support multi-currency, the provider's default currency will be + * used. + *

+ * @param pluginName The name of the plugin that is calling the method. This is for logging purposes only. + * @param accountID UUID of the account to get a balance for. + * @param world name of the world. + * @param currency the currency to use. + * + * @return Amount currently held in account associated with the given UUID. + * + * @deprecated This method is deprecated as of version 2.9, and has been replaced by + * {@link #balance(String, UUID, String, String)}. This allows economy plugins to know exactly if + * the account is a player or not. This may be removed in a future release. + */ + @NotNull + @Deprecated + BigDecimal getBalance(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final String world, @NotNull final String currency); + + /** + * Gets balance of an account associated with a UUID. + *

+ * Note: {@code pluginName} should be used for logging/diagnostics only and MUST NOT affect + * business logic. + *

+ * @param pluginName The name of the plugin that is calling the method. This is for logging purposes only. + * @param accountID UUID of the account to get a balance for. + * + * @return Amount currently held in account associated with the given UUID. + */ + @NotNull + default BigDecimal balance(@NotNull final String pluginName, @NotNull final UUID accountID) { + + return getBalance(pluginName, accountID); + } + + /** + * Gets balance of a UUID on the specified world. + *

+ * Note: {@code pluginName} should be used for logging/diagnostics only and MUST NOT affect + * business logic. + *
+ * If the provider does not support multiple worlds, the provider's default world will be used. + *

+ * @param pluginName The name of the plugin that is calling the method. This is for logging purposes only. + * @param accountID UUID of the account to get a balance for. + * @param world name of the world. + * + * @return Amount currently held in account associated with the given UUID. + */ + @NotNull + default BigDecimal balance(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final String world) { + + return getBalance(pluginName, accountID, world); + } + + /** + * Gets balance of a UUID on the specified world and currency. + *

+ * Note: {@code pluginName} should be used for logging/diagnostics only and MUST NOT affect + * business logic. + *
+ * If the provider does not support multiple worlds, the provider's default world will be used. + *
+ * If the provider does not support multi-currency, the provider's default currency will be + * used. + *

+ * @param pluginName The name of the plugin that is calling the method. This is for logging purposes only. + * @param accountID UUID of the account to get a balance for. + * @param world name of the world. + * @param currency the currency to use. + * + * @return Amount currently held in account associated with the given UUID. + */ + @NotNull + default BigDecimal balance(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final String world, @NotNull final String currency) { + + return getBalance(pluginName, accountID, world, currency); + } + + /** + * Checks if the account associated with the given UUID has the amount + *

+ * Note: Negative amounts should not be used. Use deposit methods instead. + *
+ * Note: {@code pluginName} should be used for logging/diagnostics only and MUST NOT affect + * business logic. + *

+ * @param pluginName The name of the plugin that is calling the method. This is for logging purposes only. + * @param accountID the UUID associated with the account to check the balance of. + * @param amount the amount to check for. + * + * @return True if UUID has amount, False else wise. + * + * @see #fractionalDigits(String) + */ + boolean has(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final BigDecimal amount); + + /** + * Checks if the account associated with the given UUID has the amount in the given world + *

+ * Note: Negative amounts should not be used. Use deposit methods instead. + *
+ * Note: {@code pluginName} should be used for logging/diagnostics only and MUST NOT affect + * business logic. + *
+ * If the provider does not support multiple worlds, the provider's default world will be used. + *

+ * @param pluginName The name of the plugin that is calling the method. + * @param accountID the UUID associated with the account to check the balance of. + * @param worldName the name of the world to check in. + * @param amount the amount to check for. + * + * @return True if UUID has amount in the given world, False else wise. + * + * @see #fractionalDigits(String) + */ + boolean has(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final String worldName, @NotNull final BigDecimal amount); + + /** + * Checks if the account associated with the given UUID has the amount in the given world + *

+ * Note: Negative amounts should not be used. Use deposit methods instead. + *
+ * Note: {@code pluginName} should be used for logging/diagnostics only and MUST NOT affect + * business logic. + *
+ * If the provider does not support multiple worlds, the provider's default world will be used. + *
+ * If the provider does not support multi-currency, the provider's default currency will be + * used. + *

+ * @param pluginName The name of the plugin that is calling the method. + * @param accountID the UUID associated with the account to check the balance of. + * @param worldName the name of the world to check in. + * @param currency the currency to use. + * @param amount the amount to check for. + * + * @return True if UUID has amount in the given world, False else wise. + * + * @see #fractionalDigits(String) + */ + boolean has(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final String worldName, @NotNull final String currency, @NotNull final BigDecimal amount); + + /** + * + * Sets the amount of monies for a player. + *

+ * Note: {@code pluginName} should be used for logging/diagnostics only and MUST NOT affect + * business logic. + *

+ * @param pluginName the name of the plugin setting the currency + * @param accountID the unique identifier of the player's account + * @param amount the amount of currency to set for the player in the specified world + * + * @return an EconomyResponse object indicating the result of the operation + */ + default EconomyResponse set(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final BigDecimal amount) { + + final BigDecimal balance = balance(pluginName, accountID); + final int compare = balance.compareTo(amount); + if(compare > 0) { + return withdraw(pluginName, accountID, balance.subtract(amount)); + } + + if(compare < 0) { + return deposit(pluginName, accountID, amount.subtract(balance)); + } + + return new EconomyResponse(BigDecimal.ZERO, amount, ResponseType.SUCCESS, ""); + } + + /** + * + * Sets the amount of monies for a player in a specific world. + *

+ * Note: {@code pluginName} should be used for logging/diagnostics only and MUST NOT affect + * business logic. + *
+ * If the provider does not support multiple worlds, the provider's default world will be used. + *

+ * @param pluginName the name of the plugin setting the currency + * @param accountID the unique identifier of the player's account + * @param worldName the name of the world where the currency amount is being set + * @param amount the amount of currency to set for the player in the specified world + * + * @return an EconomyResponse object indicating the result of the operation + */ + default EconomyResponse set(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final String worldName, @NotNull final BigDecimal amount) { + + final BigDecimal balance = balance(pluginName, accountID, worldName); + final int compare = balance.compareTo(amount); + if(compare > 0) { + return withdraw(pluginName, accountID, worldName, balance.subtract(amount)); + } + + if(compare < 0) { + return deposit(pluginName, accountID, worldName, amount.subtract(balance)); + } + + return new EconomyResponse(BigDecimal.ZERO, amount, ResponseType.SUCCESS, ""); + } + + /** + * + * Sets the amount of specified currency for a player in a specific world. + *

+ * Note: {@code pluginName} should be used for logging/diagnostics only and MUST NOT affect + * business logic. + *
+ * If the provider does not support multiple worlds, the provider's default world will be used. + *
+ * If the provider does not support multi-currency, the provider's default currency will be + * used. + *

+ * @param pluginName the name of the plugin setting the currency + * @param accountID the unique identifier of the player's account + * @param worldName the name of the world where the currency amount is being set + * @param currency the name of the currency being set + * @param amount the amount of currency to set for the player in the specified world + * + * @return an EconomyResponse object indicating the result of the operation + */ + default EconomyResponse set(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final String worldName, @NotNull final String currency, @NotNull final BigDecimal amount) { + + final BigDecimal balance = balance(pluginName, accountID, worldName, currency); + final int compare = balance.compareTo(amount); + if(compare > 0) { + return withdraw(pluginName, accountID, worldName, currency, balance.subtract(amount)); + } + + if(compare < 0) { + return deposit(pluginName, accountID, worldName, currency, amount.subtract(balance)); + } + + return new EconomyResponse(BigDecimal.ZERO, amount, ResponseType.SUCCESS, ""); + } + + /** + * Withdraw an amount from an account associated with a UUID + *

+ * Note: Negative amounts should not be used. Use deposit methods instead. + *
+ * Note: {@code pluginName} should be used for logging/diagnostics only and MUST NOT affect + * business logic. + *

+ * @param pluginName The name of the plugin that is calling the method. + * @param accountID the UUID associated with the account to withdraw from. + * @param amount Amount to withdraw. + * + * @return {@link EconomyResponse} which includes the Economy plugin's {@link ResponseType} as to + * whether the transaction was a Success, Failure, Unsupported. + * + * @see #fractionalDigits(String) + */ + @NotNull + EconomyResponse withdraw(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final BigDecimal amount); + + /** + * Withdraw an amount from an account associated with a UUID on a given world + *

+ * Note: Negative amounts should not be used. Use deposit methods instead. + *
+ * Note: {@code pluginName} should be used for logging/diagnostics only and MUST NOT affect + * business logic. + *
+ * If the provider does not support multiple worlds, the provider's default world will be used. + *

+ * @param pluginName The name of the plugin that is calling the method. + * @param accountID the UUID associated with the account to withdraw from. + * @param worldName the name of the world to check in. + * @param amount Amount to withdraw. + * + * @return {@link EconomyResponse} which includes the Economy plugin's {@link ResponseType} as to + * whether the transaction was a Success, Failure, Unsupported. + * + * @see #fractionalDigits(String) + */ + @NotNull + EconomyResponse withdraw(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final String worldName, @NotNull final BigDecimal amount); + + /** + * Withdraw an amount from an account associated with a UUID on a given world + *

+ * Note: Negative amounts should not be used. Use deposit methods instead. + *
+ * Note: {@code pluginName} should be used for logging/diagnostics only and MUST NOT affect + * business logic. + *
+ * If the provider does not support multiple worlds, the provider's default world will be used. + *
+ * If the provider does not support multi-currency, the provider's default currency will be + * used. + *

+ * @param pluginName The name of the plugin that is calling the method. + * @param accountID the UUID associated with the account to withdraw from. + * @param worldName the name of the world to check in. + * @param currency the currency to use. + * @param amount Amount to withdraw. + * + * @return {@link EconomyResponse} which includes the Economy plugin's {@link ResponseType} as to + * whether the transaction was a Success, Failure, Unsupported. + * + * @see #fractionalDigits(String) + */ + @NotNull + EconomyResponse withdraw(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final String worldName, @NotNull final String currency, @NotNull final BigDecimal amount); + + /** + * Deposit an amount to an account associated with the given UUID + *

+ * Note: Negative amounts should not be used. Use withdraw methods instead. + *
+ * Note: {@code pluginName} should be used for logging/diagnostics only and MUST NOT affect + * business logic. + *

+ * @param pluginName The name of the plugin that is calling the method. + * @param accountID the UUID associated with the account to deposit to. + * @param amount Amount to deposit. + * + * @return {@link EconomyResponse} which includes the Economy plugin's {@link ResponseType} as to + * whether the transaction was a Success, Failure, Unsupported. + * + * @see #fractionalDigits(String) + */ + @NotNull + EconomyResponse deposit(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final BigDecimal amount); + + /** + * Deposit an amount to an account associated with a UUID on a given world + *

+ * Note: Negative amounts should not be used. Use withdraw methods instead. + *
+ * Note: {@code pluginName} should be used for logging/diagnostics only and MUST NOT affect + * business logic. + *
+ * If the provider does not support multiple worlds, the provider's default world will be used. + *

+ * @param pluginName The name of the plugin that is calling the method. + * @param accountID the {@link UUID} associated with the account to deposit to. + * @param worldName the name of the world to check in. + * @param amount Amount to deposit. + * + * @return {@link EconomyResponse} which includes the Economy plugin's {@link ResponseType} as to + * whether the transaction was a Success, Failure, Unsupported. + * + * @see #fractionalDigits(String) + */ + @NotNull + EconomyResponse deposit(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final String worldName, @NotNull final BigDecimal amount); + + /** + * Deposit an amount to an account associated with a UUID on a given world + *

+ * Note: Negative amounts should not be used. Use withdraw methods instead. + *
+ * Note: {@code pluginName} should be used for logging/diagnostics only and MUST NOT affect + * business logic. + *
+ * If the provider does not support multiple worlds, the provider's default world will be used. + *
+ * If the provider does not support multi-currency, the provider's default currency will be + * used. + *

+ * @param pluginName The name of the plugin that is calling the method. + * @param accountID the {@link UUID} associated with the account to deposit to. + * @param worldName the name of the world to check in. + * @param currency the currency to use. + * @param amount Amount to deposit. + * + * @return {@link EconomyResponse} which includes the Economy plugin's {@link ResponseType} as to + * whether the transaction was a Success, Failure, Unsupported. + * + * @see #fractionalDigits(String) + */ + @NotNull + EconomyResponse deposit(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final String worldName, @NotNull final String currency, @NotNull final BigDecimal amount); + + /* + * Shared Account Methods + */ + + /** + * Creates a shared account with the specified parameters. + *

+ * If the provider does not support shared accounts, this will return false. + *

+ * @param pluginName the name of the plugin + * @param accountID the {@link UUID} of the account + * @param name the name of the account + * @param owner the {@link UUID} of the account owner + * + * @return true if the shared account is successfully created, false otherwise + */ + boolean createSharedAccount(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final String name, @NotNull final UUID owner); + + /** + * Retrieves a list of account IDs owned by the specified account ID. + *

+ * If the provider does not support shared accounts, this will return an unmodifiable empty list. + *

+ * @param pluginName the name of the plugin + * @param accountID the unique identifier of the account + * + * @return a list of account names owned by the specified account ID + * + * @since 2.14 + * @deprecated Use {@link #accountsWithOwnerOf(String, UUID)} instead as the string return allows ambiguity. + */ + default List accountsOwnedBy(@NotNull final String pluginName, @NotNull final UUID accountID) { + + return accountsAccessTo(pluginName, accountID, AccountPermission.OWNER); + } + + /** + * Retrieves a list of account IDs owned by the specified account ID. + *

+ * If the provider does not support shared accounts, this will return an unmodifiable empty list. + *

+ * @param pluginName the name of the plugin + * @param accountID the unique identifier of the account + * + * @return a list of account UUID owned by the specified account ID + * + * @since 2.17 + */ + default List accountsWithOwnerOf(@NotNull final String pluginName, @NotNull final UUID accountID) { + + return accountsWithAccessTo(pluginName, accountID, AccountPermission.OWNER); + } + + /** + * Retrieves a list of account IDs that the specified account is a member of. + *

+ * If the provider does not support shared accounts, this will return an unmodifiable empty list. + *

+ * @param pluginName the name of the plugin + * @param accountID the UUID of the account to check membership for + * + * @return a List of String values representing the accounts that the account is a member of + * + * @since 2.14 + * @deprecated Use {@link #accountsWithMembershipTo(String, UUID)} instead as the string return allows ambiguity. + */ + default List accountsMemberOf(@NotNull final String pluginName, @NotNull final UUID accountID) { + + return accountsAccessTo(pluginName, accountID, AccountPermission.BALANCE, AccountPermission.DEPOSIT, AccountPermission.WITHDRAW); + } + + /** + * Retrieves a list of account IDs that the specified account is a member of. + *

+ * If the provider does not support shared accounts, this will return an unmodifiable empty list. + *

+ * @param pluginName the name of the plugin + * @param accountID the UUID of the account to check membership for + * + * @return a List of UUID values representing the accounts that the account is a member of + * + * @since 2.17 + */ + default List accountsWithMembershipTo(@NotNull final String pluginName, @NotNull final UUID accountID) { + + return accountsWithAccessTo(pluginName, accountID, AccountPermission.BALANCE, AccountPermission.DEPOSIT, AccountPermission.WITHDRAW); + } + + /** + * Retrieves a list of account IDs that the specified account has the specified permissions for. + *

+ * If the provider does not support shared accounts, this will return an unmodifiable empty list. + *

+ * @param pluginName the name of the plugin + * @param accountID the UUID of the account to check access for + * @param permissions variable number of permissions to check for + * + * @return a list of accounts that the account has the specified permissions to + * + * @since 2.14 + * @deprecated Use {@link #accountsWithAccessTo(String, UUID, AccountPermission...)} instead as the string return allows ambiguity. + */ + @Deprecated + default List accountsAccessTo(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final AccountPermission... permissions) { + + return Collections.unmodifiableList(new ArrayList<>()); + } + + /** + * Retrieves a list of account IDs that the specified account has the specified permissions for. + *

+ * If the provider does not support shared accounts, this will return an unmodifiable empty list. + *

+ * @param pluginName the name of the plugin + * @param accountID the UUID of the account to check access for + * @param permissions variable number of permissions to check for + * + * @return a list of accounts that the account has the specified permissions to + * + * @since 2.17 + */ + default List accountsWithAccessTo(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final AccountPermission... permissions) { + + return Collections.unmodifiableList(new ArrayList<>()); + } + + /** + * Determines whether the specified owner ID is the owner of the account associated with the given + * account ID and plugin name. + *

+ * If the provider does not support shared accounts, this will return false. + *

+ * @param pluginName the name of the plugin + * @param accountID the {@link UUID} of the account + * @param uuid the {@link UUID} to check for ownership of the account + * + * @return true if the owner ID is the owner of the account, false otherwise + */ + boolean isAccountOwner(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final UUID uuid); + + /** + * Sets the owner of a specified plugin to the given accountID. + *

+ * If the provider does not support shared accounts, this will return false. + *

+ * @param pluginName The name of the plugin. + * @param accountID The {@link UUID} of the account + * @param uuid The {@link UUID} of the account to set as the owner. + * + * @return true if the owner is successfully set, false otherwise. + */ + boolean setOwner(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final UUID uuid); + + /** + * Determines whether a specific member is an account member of a given plugin. + *

+ * If the provider does not support shared accounts, this will return false. + *

+ * @param pluginName The name of the plugin. + * @param accountID The {@link UUID} of the account. + * @param uuid The {@link UUID} to check for membership. + * + * @return true if the member is an account member, false otherwise. + */ + boolean isAccountMember(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final UUID uuid); + + /** + * Adds a member to an account. + *

+ * If the provider does not support shared accounts, this will return false. + *

+ * @param pluginName The name of the plugin. + * @param accountID The {@link UUID} of the account. + * @param uuid The {@link UUID} of the member to be added. + * + * @return true if the member was successfully added, false otherwise. + */ + boolean addAccountMember(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final UUID uuid); + + /** + * Adds a member to an account with the specified initial permissions. + *

+ * If the provider does not support shared accounts, this will return false. + *

+ * @param pluginName The name of the plugin. + * @param accountID The {@link UUID} of the account. + * @param uuid The {@link UUID} of the member to be added. + * @param initialPermissions The initial permissions to be assigned to the member. The values for + * these should be assumed to be "true." + * + * @return true if the member was added successfully, false otherwise. + */ + boolean addAccountMember(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final UUID uuid, @NotNull final AccountPermission... initialPermissions); + + /** + * Removes a member from an account. + *

+ * If the provider does not support shared accounts, this will return false. + *

+ * @param pluginName the name of the plugin managing the account + * @param accountID the {@link UUID} of the account + * @param uuid the {@link UUID} of the member to be removed + * + * @return true if the member was successfully removed, false otherwise + */ + boolean removeAccountMember(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final UUID uuid); + + /** + * Checks if the specified account has the given permission for the given plugin. + *

+ * If the provider does not support shared accounts, this will return false. + *

+ * @param pluginName the name of the plugin to check permission for + * @param accountID the {@link UUID} of the account + * @param uuid the {@link UUID} to check for the permission + * @param permission the permission to check for + * + * @return true if the account has the specified permission, false otherwise + */ + boolean hasAccountPermission(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final UUID uuid, @NotNull final AccountPermission permission); + + /** + * Updates the account permission for a specific plugin and user. + *

+ * If the provider does not support shared accounts, this will return false. + *

+ * @param pluginName the name of the plugin + * @param accountID the {@link UUID} of the account + * @param uuid the {@link UUID} to update the permission for + * @param permission the new account permissions to set + * @param value the new permission value to set for this value + * + * @return true if the account permission was successfully updated, false otherwise + */ + boolean updateAccountPermission(@NotNull final String pluginName, @NotNull final UUID accountID, @NotNull final UUID uuid, @NotNull final AccountPermission permission, final boolean value); +} diff --git a/src/main/java/net/milkbowl/vault2/economy/EconomyResponse.java b/src/main/java/net/milkbowl/vault2/economy/EconomyResponse.java new file mode 100644 index 0000000..57faabc --- /dev/null +++ b/src/main/java/net/milkbowl/vault2/economy/EconomyResponse.java @@ -0,0 +1,94 @@ +/* This file is part of Vault. + + Vault is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vault is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Vault. If not, see . + */ +package net.milkbowl.vault2.economy; + +import org.jetbrains.annotations.NotNull; + +import java.math.BigDecimal; + +/** + * Indicates a typical Return for an Economy method. It includes a + * {@link ResponseType} indicating whether the plugin currently being used for + * Economy actually allows the method, or if the operation was a success or + * failure. + * + */ +public class EconomyResponse { + + /** + * Enum for types of Responses indicating the status of a method call. + */ + public enum ResponseType { + SUCCESS(1), + FAILURE(2), + NOT_IMPLEMENTED(3); + + private int id; + + ResponseType(final int id) { + this.id = id; + } + + int getId() { + return id; + } + } + + /** + * Amount modified by calling method + */ + public final BigDecimal amount; + /** + * New balance of account + */ + public final BigDecimal balance; + /** + * Success or failure of call. Using Enum of ResponseType to determine valid + * outcomes + */ + public final ResponseType type; + /** + * Error message if the variable 'type' is ResponseType.FAILURE + */ + public final String errorMessage; + + /** + * Constructor for EconomyResponse + * @param amount Amount modified during operation + * @param balance New balance of account + * @param type Success or failure type of the operation + * @param errorMessage Error message if necessary (commonly null) + */ + public EconomyResponse(@NotNull final BigDecimal amount, @NotNull final BigDecimal balance, @NotNull final ResponseType type, @NotNull final String errorMessage) { + this.amount = amount; + this.balance = balance; + this.type = type; + this.errorMessage = errorMessage; + } + + /** + * Checks if an operation was successful + * @return Value + */ + public boolean transactionSuccess() { + switch (type) { + case SUCCESS: + return true; + default: + return false; + } + } +} \ No newline at end of file diff --git a/src/main/java/net/milkbowl/vault2/helper/TriState.java b/src/main/java/net/milkbowl/vault2/helper/TriState.java new file mode 100644 index 0000000..921daa2 --- /dev/null +++ b/src/main/java/net/milkbowl/vault2/helper/TriState.java @@ -0,0 +1,39 @@ +package net.milkbowl.vault2.helper; +/* + This file is part of Vault. + + Vault is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vault is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Vault. If not, see . + */ + +/** + * Represents a tri-state value that can be TRUE, FALSE, or UNDEFINED. + * + * This enum provides a way to manage and interpret values where a third, + * undefined state is necessary beyond binary truth values. The method + * asBool() allows for interpreting the TRUE state as a boolean true while + * treating all other states (FALSE and UNDEFINED) as boolean false. + * + * @author creatorfromhell + * @since 2.18 + */ +public enum TriState { + + TRUE, + FALSE, + UNDEFINED; + + public boolean asBool() { + return this == TRUE; + } +} \ No newline at end of file diff --git a/src/main/java/net/milkbowl/vault2/helper/context/Context.java b/src/main/java/net/milkbowl/vault2/helper/context/Context.java new file mode 100644 index 0000000..6fd183c --- /dev/null +++ b/src/main/java/net/milkbowl/vault2/helper/context/Context.java @@ -0,0 +1,155 @@ +package net.milkbowl.vault2.helper.context; +/* + This file is part of Vault. + + Vault is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vault is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Vault. If not, see . + */ + +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Represents an operational context that can optionally be associated with a specific world. + * The context determines the scope in which certain operations or checks, such as permissions, are applied. + * + * A global context is represented by the {@code GLOBAL} constant, which is not tied to any specific world. + * + * This class provides methods for retrieving the name of the world associated with the context, + * if any, and is used to manage scoped operations. + * @author creatorfromhell + * @since 2.18 + */ +public class Context { + + private final Map contextValues = new ConcurrentHashMap<>(); + + public static final Context GLOBAL = new Context(); + + private LookupMode lookupMode = LookupMode.GLOBAL_FALLBACK; + + public Context() { + } + + /** + * Constructs a new Context object and associates it with the specified world. + * The world is stored as part of the context's metadata under the {@code WORLD} key. + * + * @param world the name of the world to associate with this context + */ + public Context(final String world) { + contextValues.put(ContextKeys.WORLD, world); + } + + /** + * Constructs a new {@code Context} object with the specified world and lookup mode. + * The provided world is stored as part of the context's metadata under the {@code ContextKeys.WORLD} key. + * Additionally, the lookup mode determines how values are resolved within this context. + * + * @param world the name of the world to associate with this context + * @param lookupMode the mode of lookup operation to determine how values are resolved + */ + public Context(final String world, final LookupMode lookupMode) { + contextValues.put(ContextKeys.WORLD, world); + this.lookupMode = lookupMode; + } + + /** + * Constructs a new Context object with the specified context values. + * The provided context values map allows for associating additional metadata with the context. + * If the input map is null, the context will be initialized with no values. + * + * @param contextValues a map of key-value pairs representing the context's metadata, + * or null to create an empty context + */ + public Context(@Nullable final Map contextValues) { + if(contextValues != null) { + this.contextValues.putAll(contextValues); + } + } + + /** + * Constructs a new Context object with the specified context values and lookup mode. + * The provided context values map allows for associating additional metadata with the context. + * If the input map is null, the context will be initialized with no values. + * + * @param contextValues a map of key-value pairs representing the context's metadata, + * or null to create an empty context + * @param lookupMode the mode of lookup operation to determine how values are resolved + */ + public Context(@Nullable final Map contextValues, final LookupMode lookupMode) { + if(contextValues != null) { + this.contextValues.putAll(contextValues); + } + this.lookupMode = lookupMode; + } + + public LookupMode lookupMode() { + + return lookupMode; + } + + public void lookupMode(final LookupMode lookupMode) { + + this.lookupMode = lookupMode; + } + + public Optional world() { + return Optional.ofNullable(contextValues.get(ContextKeys.WORLD)); + } + + @Nullable + public String worldOrNull() { + return contextValues.get(ContextKeys.WORLD); + } + + public Optional value(final String key) { + return Optional.ofNullable(contextValues.get(key)); + } + + @Nullable + public String valueOrNull(final String key) { + return contextValues.get(key); + } + + public Map asMap() { + return contextValues; + } + + /** + * Creates a new {@code Context} object associated with the specified world. + * The provided {@code world} is stored as part of the context's metadata. + * + * @param world the name of the world to associate with the context + * @return a new {@code Context} instance associated with the specified world + */ + public static Context fromWorld(final String world) { + return new Context(world, LookupMode.GLOBAL_FALLBACK); + } + + /** + * Creates a new {@code Context} object associated with a specific world and lookup mode. + * The provided {@code world} is stored within the context's metadata using a predefined key, + * and the specified {@code lookupMode} determines how values are resolved within the context. + * + * @param world the name of the world to associate with the context + * @param lookupMode the mode of lookup operation to determine how values are resolved + * @return a new {@code Context} instance with the specified world and lookup mode + */ + public static Context fromWorld(final String world, final LookupMode lookupMode) { + return new Context(world, lookupMode); + } +} \ No newline at end of file diff --git a/src/main/java/net/milkbowl/vault2/helper/context/ContextKeys.java b/src/main/java/net/milkbowl/vault2/helper/context/ContextKeys.java new file mode 100644 index 0000000..2eace64 --- /dev/null +++ b/src/main/java/net/milkbowl/vault2/helper/context/ContextKeys.java @@ -0,0 +1,36 @@ +package net.milkbowl.vault2.helper.context; +/* + This file is part of Vault. + + Vault is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vault is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Vault. If not, see . + */ + +/** + * Provides predefined keys used for defining or interacting with various contexts. + * + * This class serves as a centralized repository for context key constants. These keys are + * utilized within the context management system to identify specific metadata, such as the + * associated world for a given context. + * + * For example, the {@code WORLD} key is used to associate a context with a specific world. + * + * This class is designed for use in cases where constants are needed to standardize the + * management and interaction of context metadata. + * @author creatorfromhell + * @since 2.18 + */ +public class ContextKeys { + + public static final String WORLD = "world"; +} \ No newline at end of file diff --git a/src/main/java/net/milkbowl/vault2/helper/context/LookupMode.java b/src/main/java/net/milkbowl/vault2/helper/context/LookupMode.java new file mode 100644 index 0000000..806d3ad --- /dev/null +++ b/src/main/java/net/milkbowl/vault2/helper/context/LookupMode.java @@ -0,0 +1,33 @@ +package net.milkbowl.vault2.helper.context; +/* + This file is part of Vault. + + Vault is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vault is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Vault. If not, see . + */ + +/** + * Defines the modes used for resolving or retrieving values within a given context. + * + * The lookup mode determines how values are queried or resolved: + * - {@code EXACT}: The lookup is restricted to the specific context provided, without considering any fallback options. + * - {@code GLOBAL_FALLBACK}: If the lookup in the specific context fails, a fallback resolution is attempted on a global context. + * + * @author creatorfromhell + * @since 2.18 + */ +public enum LookupMode { + + EXACT, + GLOBAL_FALLBACK +} \ No newline at end of file diff --git a/src/main/java/net/milkbowl/vault2/helper/subject/Subject.java b/src/main/java/net/milkbowl/vault2/helper/subject/Subject.java new file mode 100644 index 0000000..312e5d2 --- /dev/null +++ b/src/main/java/net/milkbowl/vault2/helper/subject/Subject.java @@ -0,0 +1,96 @@ +package net.milkbowl.vault2.helper.subject; +/* + This file is part of Vault. + + Vault is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vault is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Vault. If not, see . + */ + +import java.util.UUID; + +/** + * Represents a subject with a unique identifier, a name, and a flag indicating + * whether the subject is a player. + * + * This class provides methods to retrieve the subject's identifier and name, + * with additional metadata annotations to indicate nullability. + * + * @author creatorfromhell + * @since 2.18 + */ +public class Subject { + + private final String identifier; + private final String displayIdentifier; + private final SubjectType type; + + /** + * Constructs a new {@code Subject} instance with the specified identifier, display identifier, and type. + * If this is a player, the identifier is the stringified UUID of the player, and the display identifier is the player's username. + * If this is a group, the identifier is the group name or stringified UUID of the group if applicable, + * and the display identifier is the same as the identifier or name if the identifier is UUID. + * + * @param identifier the unique identifier for the subject + * @param displayIdentifier the display name associated with the subject + * @param type the type of the subject, indicating whether it is a player or group + */ + private Subject(final String identifier, final String displayIdentifier, final SubjectType type) { + this.identifier = identifier; + this.displayIdentifier = displayIdentifier; + this.type = type; + } + + public String identifier() { + return identifier; + } + + public UUID asUUID() { + return UUID.fromString(identifier); + } + + public String displayIdentifier() { + return displayIdentifier; + } + + public SubjectType type() { + return type; + } + + /** + * Creates a {@code Subject} instance representing a player using the given unique identifier and username. + * + * This method generates a {@code Subject} with the specified UUID as the unique identifier + * and the provided username as the display identifier. The {@code SubjectType} for this + * subject is set to {@code PLAYER}. + * + * @param uuid the unique identifier (UUID) of the player + * @param username the username associated with the player + * @return a {@code Subject} instance representing the specified player + */ + public static Subject player(final UUID uuid, final String username) { + return new Subject(uuid.toString(), username, SubjectType.PLAYER); + } + + /** + * Creates a {@code Subject} instance representing a group using the given group name. + * + * This method generates a {@code Subject} with the specified group name as both + * the unique identifier and display identifier, and sets the subject type to {@code GROUP}. + * + * @param groupName the name of the group to be used as the identifier and display identifier + * @return a {@code Subject} instance representing the specified group + */ + public static Subject group(final String groupName) { + return new Subject(groupName, groupName, SubjectType.GROUP); + } +} \ No newline at end of file diff --git a/src/main/java/net/milkbowl/vault2/helper/subject/SubjectType.java b/src/main/java/net/milkbowl/vault2/helper/subject/SubjectType.java new file mode 100644 index 0000000..2a1c029 --- /dev/null +++ b/src/main/java/net/milkbowl/vault2/helper/subject/SubjectType.java @@ -0,0 +1,32 @@ +package net.milkbowl.vault2.helper.subject; +/* + This file is part of Vault. + + Vault is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vault is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Vault. If not, see . + */ + +/** + * Represents the type of a subject, which can either be a player or a group. + * + * This enumeration helps differentiate between individual player subjects + * and group subjects in the context of the application. + * + * @author creatorfromhell + * @since 2.18 + */ +public enum SubjectType { + + PLAYER, + GROUP +} \ No newline at end of file diff --git a/src/main/java/net/milkbowl/vault2/minecraft/BukkitHelper.java b/src/main/java/net/milkbowl/vault2/minecraft/BukkitHelper.java new file mode 100644 index 0000000..5b6bbb4 --- /dev/null +++ b/src/main/java/net/milkbowl/vault2/minecraft/BukkitHelper.java @@ -0,0 +1,50 @@ +package net.milkbowl.vault2.minecraft; +/* + This file is part of Vault. + + Vault is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vault is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Vault. If not, see . + */ + +import net.milkbowl.vault2.helper.subject.Subject; +import org.bukkit.OfflinePlayer; + +import static net.milkbowl.vault2.helper.subject.Subject.player; + +/** + * A utility class designed to assist with common operations and functionalities + * in the Bukkit or Spigot API environment. This class contains static methods + * and utilities that simplify plugin development tasks. + * + * This helper class is intended for use in Minecraft server plugins and + * provides abstractions or shortcuts for typical operations involving the + * Bukkit API. + * + * @author creatorfromhell + * @since 2.18 + */ +public class BukkitHelper { + + /** + * Creates a {@code Subject} instance representing a player using the provided {@link OfflinePlayer}. + * + * This method generates a {@code Subject} by extracting the player's unique identifier (UUID) + * and name from the given {@link OfflinePlayer} instance. + * + * @param player the {@link OfflinePlayer} instance containing the player's details + * @return a {@code Subject} instance representing the specified player + */ + public static Subject fromPlayer(final OfflinePlayer player) { + return player(player.getUniqueId(), player.getName()); + } +} \ No newline at end of file diff --git a/src/main/java/net/milkbowl/vault2/permission/PermissionUnlocked.java b/src/main/java/net/milkbowl/vault2/permission/PermissionUnlocked.java new file mode 100644 index 0000000..3dda94d --- /dev/null +++ b/src/main/java/net/milkbowl/vault2/permission/PermissionUnlocked.java @@ -0,0 +1,439 @@ +package net.milkbowl.vault2.permission; +/* + This file is part of Vault. + + Vault is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vault is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Vault. If not, see . + */ + +import net.milkbowl.vault2.helper.context.Context; +import net.milkbowl.vault2.helper.subject.Subject; +import net.milkbowl.vault2.helper.TriState; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.CompletableFuture; + +/** + * Represents a permission provider to manage permissions, groups, and related operations + * within specific contexts and for specific subjects. + * + * This class offers methods to query, set, and retrieve permission states, either synchronously + * or asynchronously, including support for transient permissions and group-related operations. + * + * All operations assume that neither the context, subject, nor permission identifier are null. + * Operations may return default states (such as UNDEFINED) or empty values depending on + * context, group definitions, and permission configurations. + * + * @author creatorfromhell + * @since 2.18 + */ +public interface PermissionUnlocked { + + /** + * Checks whether this permission provider is enabled. + * + * @return true if the permission provider is enabled; false otherwise. + * @since 2.18 + */ + boolean isEnabled(); + + /** + * Retrieves the name of this permission provider. + * + * @return the name of the permission provider as a non-null string. + * @since 2.18 + */ + @NotNull + String getName(); + + /** + * Checks whether the permission provider supports group-based permissions. + * + * @return true if group-based permissions are supported; false otherwise. + * @since 2.18 + */ + boolean hasGroupSupport(); + + /** + * Checks whether the permission provider supports SuperPerms. + * + * @return true if SuperPerms are supported; false otherwise. + * @since 2.18 + */ + boolean hasSuperPermsSupport(); + + /** + * Copies permissions from one subject to another. + * + * @param context the operational context in which the permissions are being copied; must not be null + * @param from the source subject from which permissions are copied; must not be null + * @param to the target subject to which permissions are copied; must not be null + * @param includeTransient if true, includes transient permissions in the copy; otherwise, only durable permissions are copied + * @return true if the permissions were successfully copied, false otherwise + * @since 2.18 + */ + boolean copyPermissions(@NotNull Context context, @NotNull Subject from, @NotNull Subject to, boolean includeTransient); + + /** + * Asynchronously copies permissions from one subject to another. + * + * @param context the context in which the operation is performed; cannot be null + * @param from the source subject from which permissions will be copied; cannot be null + * @param to the target subject to which permissions will be copied; cannot be null + * @param includeTransient a flag indicating whether transient permissions should also be copied + * @return a CompletableFuture that resolves to true if the permissions were successfully copied, + * or false if the operation failed + * @since 2.18 + */ + CompletableFuture copyPermissionsAsync(@NotNull Context context, @NotNull Subject from, @NotNull Subject to, boolean includeTransient); + + /** + * Retrieves the permission state for a given context, subject, and permission identifier. + * + * @param context the context in which the permission is being checked cannot be null + * @param subject the subject for whom the permission is being checked cannot be null + * @param permission the identifier of the permission to check cannot be null + * @return a {@link TriState} value indicating the permission state, which can be TRUE, FALSE, or UNDEFINED + * @since 2.18 + */ + @NotNull + TriState has(@NotNull Context context, @NotNull Subject subject, @NotNull String permission); + + /** + * Asynchronously retrieves the permission state for a given context, subject, and permission identifier. + * + * @param context the context in which the permission is being checked; cannot be null + * @param subject the subject for whom the permission is being checked; cannot be null + * @param permission the identifier of the permission to check; cannot be null + * @return a {@link CompletableFuture} that completes with a {@link TriState} value indicating the permission state, + * which can be TRUE, FALSE, or UNDEFINED + * @since 2.18 + */ + @NotNull + CompletableFuture hasAsync(@NotNull final Context context, @NotNull final Subject subject, + @NotNull final String permission); + + /** + * Sets the specified permission for a subject within a given context to a specified state. + * + * @param context the context in which the permission is being set; cannot be null + * @param subject the subject for whom the permission is being set; cannot be null + * @param permission the identifier of the permission to modify; cannot be null + * @param value the {@link TriState} value indicating the desired state of the permission; cannot be null + * @return true if the permission was successfully set, false otherwise + * @since 2.18 + */ + boolean setPermission(@NotNull Context context, @NotNull Subject subject, @NotNull String permission, + @NotNull TriState value); + + /** + * Asynchronously sets the specified permission to a given tri-state value for a subject within a context. + * + * @param context the context within which the permission should be set, not null + * @param subject the subject for whom the permission is being set, not null + * @param permission the specific permission to set, not null + * @param value the tri-state value to set for the permission, not null + * @return a CompletableFuture that completes with `true` if the permission was successfully set, + * or `false` if the operation failed + * @since 2.18 + */ + @NotNull + CompletableFuture setPermissionAsync(@NotNull Context context, @NotNull Subject subject, + @NotNull String permission, @NotNull TriState value); + + /** + * Sets a transient permission for a specific subject within a given context to a specified value. + * Transient permissions are temporary and do not persist beyond the current runtime. + * + * @param context the context in which the permission is being set; cannot be null + * @param subject the subject for whom the transient permission is being set; cannot be null + * @param permission the identifier of the permission to modify; cannot be null + * @param value the {@link TriState} value indicating the desired state of the permission; cannot be null + * @return true if the transient permission was successfully set, false otherwise + * @since 2.18 + */ + boolean setTransientPermission(@NotNull Context context, @NotNull Subject subject, @NotNull String permission, + @NotNull TriState value); + + /** + * Asynchronously sets a transient permission for the specified subject in the given context. + * A transient permission is not persisted and will only last for the duration of the program's runtime. + * + * @param context the context in which the permission is to be set, must not be null + * @param subject the subject to which the permission is to be assigned, must not be null + * @param permission the permission string to be set, must not be null + * @param value the state of the permission (true, false, or undefined), must not be null + * + * @return a CompletableFuture that will complete with a boolean indicating whether the permission change was successful + * @since 2.18 + */ + @NotNull + CompletableFuture setTransientPermissionAsync(@NotNull Context context, @NotNull Subject subject, + @NotNull String permission, @NotNull TriState value); + + /** + * Retrieves the array of group names associated with this permission provider. + * + * @return an array of group names as non-null strings. The array may be empty if no groups are defined. + * @since 2.18 + */ + @NotNull + String[] groups(); + + /** + * Retrieves the primary group associated with the specified subject in the given context. + * + * @param context the context in which the primary group is being queried; cannot be null + * @param subject the subject whose primary group is being retrieved; cannot be null + * @return the name of the primary group associated with the subject within the specified context, + * or null if no primary group is defined + * @since 2.18 + */ + String primaryGroup(@NotNull Context context, @NotNull Subject subject); + + /** + * Asynchronously retrieves the primary group associated with the specified subject in the given context. + * + * @param context the context in which the primary group is being queried; cannot be null + * @param subject the subject whose primary group is being retrieved; cannot be null + * @return a {@link CompletableFuture} that completes with the name of the primary group associated with the subject + * within the specified context, or completes with null if no primary group is defined + * @since 2.18 + */ + @NotNull + CompletableFuture primaryGroupAsync(@NotNull Context context, @NotNull Subject subject); + + /** + * Retrieves the groups associated with the provided subject in the specified context. + * + * @param context the context in which the subject's group memberships are being retrieved; cannot be null + * @param subject the subject whose group memberships are being retrieved; cannot be null + * @return an array of group names associated with the subject within the specified context; may be + * empty if no groups are associated + * @since 2.18 + */ + @NotNull + String[] getGroups(@NotNull Context context, @NotNull Subject subject); + + /** + * Asynchronously retrieves the groups associated with the specified subject within the given context. + * + * @param context the context in which the subject's group memberships are being retrieved; cannot be null + * @param subject the subject whose group memberships are being retrieved; cannot be null + * @return a {@link CompletableFuture} that completes with an array of group names associated with the subject + * within the specified context; the array may be empty if no groups are associated + * @since 2.18 + */ + @NotNull + CompletableFuture getGroupsAsync(@NotNull Context context, @NotNull Subject subject); + + /** + * Copies all groups from the source subject to the target subject. + * + * @param context the context in which the operation is performed, must not be null + * @param from the source subject from which the groups will be copied, must not be null + * @param to the target subject to which the groups will be copied, must not be null + * @return true if the groups were successfully copied, false otherwise + * @since 2.18 + */ + boolean copyGroups(@NotNull Context context, @NotNull Subject from, @NotNull Subject to); + + /** + * Asynchronously copies groups from one subject to another subject within the given context. + * + * @param context the context in which the groups will be copied; must not be null + * @param from the source subject from which groups will be copied; must not be null + * @param to the target subject to which groups will be copied; must not be null + * @return a {@code CompletableFuture} that completes with {@code true} if the groups are copied successfully, or {@code false} otherwise + * @since 2.18 + */ + CompletableFuture copyGroupsAsync(@NotNull Context context, @NotNull Subject from, @NotNull Subject to); + + /** + * Determines whether the specified subject is in a group within the given context. + * + * @param context the context in which the group membership is being checked; cannot be null + * @param subject the subject for whom the group membership is being checked; cannot be null + * @return true if the subject is a member of a group within the specified context; false otherwise + * @since 2.18 + */ + boolean inGroup(@NotNull Context context, @NotNull Subject subject); + + /** + * Determines whether the specified subject belongs to the given group within the provided context. + * + * @param context the context in which the group membership is being checked, must not be null + * @param subject the subject whose membership is being verified, must not be null + * @param group the name of the group to check for membership, must not be null + * @return true if the subject belongs to the specified group in the given context, false otherwise + * @since 2.18 + */ + boolean inGroup(@NotNull Context context, @NotNull Subject subject, @NotNull String group); + + /** + * Asynchronously checks if the specified subject is part of a group in the given context. + * + * @param context the context in which the group check is performed; must not be null. + * @param subject the subject to check for group membership; must not be null. + * @return a CompletableFuture that will be completed with true if the subject is in the group, false otherwise. + * @since 2.18 + */ + @NotNull + CompletableFuture inGroupAsync(@NotNull Context context, @NotNull Subject subject); + + /** + * Asynchronously checks if the given subject is part of the specified group within the provided context. + * + * @param context the context in which the group membership should be checked, must not be null + * @param subject the subject whose group membership is to be verified, must not be null + * @param group the name of the group to check membership against, must not be null + * @return a CompletableFuture that will complete with a Boolean indicating whether the subject is in the group + * @since 2.18 + */ + @NotNull + CompletableFuture inGroupAsync(@NotNull Context context, @NotNull Subject subject, @NotNull String group); + + /** + * Assigns the specified subject to a given group within the provided context. + * + * @param context the context in which the group assignment is being performed; cannot be null + * @param subject the subject to be assigned to the group; cannot be null + * @param group the name of the group the subject should be assigned to; cannot be null + * @return true if the group was successfully set for the subject, false otherwise + * @since 2.18 + */ + boolean addGroup(@NotNull Context context, @NotNull Subject subject, @NotNull String group); + + /** + * Adds a group to the specified subject within the provided context. + * + * @param context the operational context in which the group addition should occur, must not be null + * @param subject the subject to whom the group will be added, must not be null + * @param group the name of the group to be added, must not be null + * @return a CompletableFuture that resolves to true if the group was successfully added, or false otherwise + * @since 2.18 + */ + @NotNull + CompletableFuture addGroupAsync(@NotNull Context context, @NotNull Subject subject, + @NotNull String group); + + /** + * Removes the specified subject from the given group within the provided context. + * + * @param context the context in which the operation is being performed; cannot be null + * @param subject the subject to be removed from the group; cannot be null + * @param group the name of the group the subject should be removed from; cannot be null + * @return true if the subject was successfully removed from the group, false otherwise + * @since 2.18 + */ + boolean removeGroup(@NotNull Context context, @NotNull Subject subject, @NotNull String group); + + /** + * Removes the specified group from the given subject within the provided context. + * + * @param context the context in which the group is to be removed, must not be null + * @param subject the subject from which the group is to be removed, must not be null + * @param group the name of the group to remove, must not be null + * @return a CompletableFuture that resolves to a Boolean indicating whether the group was successfully removed + * @since 2.18 + */ + @NotNull + CompletableFuture removeGroupAsync(@NotNull Context context, @NotNull Subject subject, + @NotNull String group); + + /** + * Checks whether the specified group has the given permission within the context. + * + * @param context the context in which the group permission is being checked; cannot be null + * @param group the name of the group whose permission is being checked; cannot be null + * @param permission the specific permission identifier to be checked; cannot be null + * @return a {@link TriState} value indicating the state of the permission for the group, + * which can be TRUE, FALSE, or UNDEFINED + * @since 2.18 + */ + @NotNull + TriState groupHas(@NotNull Context context, @NotNull String group, @NotNull String permission); + + /** + * Checks if a specific group has a given permission within a provided context. + * + * @param context the context in which the check is performed; must not be null + * @param group the name of the group being checked; must not be null + * @param permission the permission being checked for the group; must not be null + * @return a CompletableFuture that resolves to a TriState, indicating whether the group has the + * specified permission (TRUE, FALSE, or UNDEFINED); never null + * @since 2.18 + */ + @NotNull + CompletableFuture groupHasAsync(@NotNull Context context, @NotNull String group, + @NotNull String permission); + + /** + * Sets the specified permission in a given group within a specified context to a desired state. + * + * @param context the context in which the group permission is being set; cannot be null + * @param group the name of the group for which the permission is assigned; cannot be null + * @param permission the identifier of the permission to modify; cannot be null + * @param value the {@link TriState} value indicating the desired state of the permission; cannot be null + * @return true if the permission was successfully set for the group, false otherwise + * @since 2.18 + */ + boolean groupSetPermission(@NotNull Context context, @NotNull String group, + @NotNull String permission, @NotNull TriState value); + + /** + * Sets a specific permission for a group associated in the provided context. + * The permission's state can be set to true, false, or undefined using the TriState value. + * + * @param context the context in which the group and subject operate, must not be null + * @param group the name of the group for which the permission is being set, must not be null + * @param permission the permission string to be set for the group, must not be null + * @param value the TriState value representing the desired state of the permission (true, false, or undefined), must not be null + * @return a CompletableFuture that completes with a Boolean indicating whether the operation was successful + * @since 2.18 + */ + @NotNull + CompletableFuture groupSetPermissionAsync(@NotNull Context context, + @NotNull String group, @NotNull String permission, + @NotNull TriState value); + + /** + * Sets a transient permission for a specific group within a given context. + * Transient permissions are temporary and do not persist beyond the current runtime. + * + * @param context the context in which the permission is being set; cannot be null + * @param group the name of the group for which the transient permission is assigned; cannot be null + * @param permission the identifier of the permission to modify; cannot be null + * @param value the {@link TriState} value indicating the desired state of the permission; cannot be null + * @return true if the transient permission was successfully set for the group, false otherwise + * @since 2.18 + */ + boolean groupSetTransientPermission(@NotNull Context context, @NotNull String group, + @NotNull String permission, @NotNull TriState value); + + /** + * Sets a transient permission for a specific group within the given context. + * The permission will only exist for the duration of the running session and is not persisted. + * + * @param context the context in which the permission should be applied, must not be null + * @param group the name of the group the permission applies to, must not be null + * @param permission the specific permission to be set, must not be null + * @param value the value of the permission, represented by TriState, must not be null + * @return a CompletableFuture that completes with a Boolean indicating if the operation was successful + * @since 2.18 + */ + @NotNull + CompletableFuture groupSetTransientPermissionAsync(@NotNull Context context, + @NotNull String group, @NotNull String permission, + @NotNull TriState value); +} \ No newline at end of file