diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 7db4ee0..0000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -name: Bug report -about: If you think you encountered something unexpected -title: '' -labels: bug -assignees: alexcrea - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Technical informations** -Server version & framework. (/version) -Plugin version if applicable (/version CustomAnvil) -List of plugin that may interact with CustomAnvil if applicable - -**Errors** -If any errors was displayed on the console. please provide it. - -**Configuration** -Provide relavent configuration files if no error found or if you think the error is related to your configuration. - -**Additional context** -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 1f9c4e1..0000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for Custom Anvil -title: '' -labels: enhancement -assignees: alexcrea - ---- - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Idea how to integrate it** -How and where do you think the config of your feature should like -How and where do you think the config gui for your feature should look like - -**Additional context** -Add any other context about the feature request here. diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml deleted file mode 100644 index a50cacd..0000000 --- a/.github/workflows/gradle.yml +++ /dev/null @@ -1,163 +0,0 @@ -# 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. -# This workflow will build a Java project with Gradle 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-gradle - -name: Java CI with Gradle - -on: - push: - branches: [ "v1.x.x", "v2.x.x" ] - pull_request: - branches: [ "v1.x.x", "v2.x.x" ] - release: - types: [published] - -concurrency: - group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - build: - runs-on: ubuntu-latest - permissions: - contents: write - - env: - MODRINTH_VERSIONS: '["1.18.x", "1.19.x", "1.20.x", "1.21.x", "26.1.x", "26.2.x"]' - MODRINTH_PLATFORMS: '["spigot", "paper", "purpur", "folia"]' - - steps: - - uses: actions/checkout@v4 - - name: Set up JDKs - uses: actions/setup-java@v4 - with: - java-version: | - 21 - distribution: 'temurin' - cache: gradle - - - name: Cache Gradle root and wrapper - uses: actions/cache@v3 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: gradle-root-${{ runner.os }}-${{ hashFiles('build.gradle*') }} - restore-keys: gradle-root-${{ runner.os }}- - - # Setup paperweight cache - - name: Cache paperweight - uses: actions/cache@v3 - with: - path: | - ./nms/*/.gradle/caches/paperweight - key: paperweight-submodules-${{ runner.os }}-${{ hashFiles('nms/*/build.gradle*') }} - restore-keys: | - paperweight-submodules-${{ runner.os }}- - - # Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies. - # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 - - - name: Make gradlew executable - run: chmod +x ./gradlew - - - name: Get small commit hash - if: ${{ github.event_name != 'release' && success() }} - run: echo "SMALL_COMMIT_HASH=$(git rev-parse --short ${{ github.sha }})" >> $GITHUB_ENV - - - name: Build with Gradle Wrapper - run: ./gradlew build --parallel --stacktrace - - # only submit dependency on push - - name: Generate and submit dependency graph - uses: gradle/actions/dependency-submission@v4 - if: ${{ github.event_name == 'push' && success() }} - continue-on-error: true - - # Get the names of the online and offline jars - # grep -v "offline" to exclude offline jar as the regex would catch it otherwise - - name: Get file name for jars - run: | - ONLINE_JAR_PATH=$(ls build/libs/CustomAnvil-*.jar | grep -v "offline") - OFFLINE_JAR_PATH=$(ls build/libs/CustomAnvil-*-offline.jar) - - echo "ONLINE_JAR_NAME=$(basename $ONLINE_JAR_PATH)" >> $GITHUB_ENV - echo "OFFLINE_JAR_NAME=$(basename $OFFLINE_JAR_PATH)" >> $GITHUB_ENV - - # upload the named jars as artifact - - name: Upload online JAR artifact - uses: actions/upload-artifact@v4 - with: - name: CustomAnvil.jar - path: build/libs/${{ env.ONLINE_JAR_NAME }} - - - name: Upload offline JAR file - uses: actions/upload-artifact@v4 - with: - name: CustomAnvil-offline.jar - path: build/libs/${{ env.OFFLINE_JAR_NAME }} - - - name: Summarize tests results - uses: jeantessier/test-summary-action@v1 - if: ${{ always() }} - - # upload the jar to release - - name: Upload jar to release - if: ${{ github.event_name == 'release' && success() }} - uses: softprops/action-gh-release@v2 - with: - files: | - build/libs/${{ env.ONLINE_JAR_NAME }} - build/libs/${{ env.OFFLINE_JAR_NAME }} - - - name: Hangar release - if: ${{ (github.event_name != 'release' || github.event_name != 'push') && github.repository_owner == 'alexcrea' && success() }} - env: - HANGAR_API_TOKEN: ${{ secrets.HANGAR_API_TOKEN }} - RELEASE_CHANGELOG: ${{ github.event.release.body }} - run: ./gradlew publishAllPublicationsToHangar --stacktrace - - - name: Modrinth publish alpha - if: ${{ github.event_name == 'push' && github.repository_owner == 'alexcrea' && success() }} - uses: cloudnode-pro/modrinth-publish@v2 - with: - token: ${{ secrets.MODRINTH_TOKEN }} - project: S75Ueiq9 - name: dev-${{ env.SMALL_COMMIT_HASH }} - version: dev-${{ env.SMALL_COMMIT_HASH }} - loaders: ${{ env.MODRINTH_PLATFORMS }} - game-versions: ${{ env.MODRINTH_VERSIONS }} - channel: alpha - files: build/libs/${{ env.ONLINE_JAR_NAME }} - changelog: ${{ github.event.head_commit.message }} - - - name: Modrinth publish release - if: ${{ github.event_name == 'release' && github.repository_owner == 'alexcrea' && success() }} - uses: cloudnode-pro/modrinth-publish@v2 - with: - token: ${{ secrets.MODRINTH_TOKEN }} - project: S75Ueiq9 - name: ${{ github.event.release.name }} - version: ${{ github.event.release.tag_name }}${{ github.event.release.prerelease && '-pre' || '' }} - loaders: ${{ env.MODRINTH_PLATFORMS }} - game-versions: ${{ env.MODRINTH_VERSIONS }} - channel: ${{ github.event.release.prerelease == false && 'release' || 'beta' }} - files: build/libs/${{ env.ONLINE_JAR_NAME }} - changelog: ${{ github.event.release.body }} - - - name: Send release note to discord - if: ${{ github.event_name == 'release' && github.repository_owner == 'alexcrea' && success() }} - uses: tsickert/discord-webhook@v7.0.0 - with: - webhook-url: ${{ secrets.RELEASE_WEBHOOK_URL }} - content: | - ${{ github.event.release.prerelease == false && '<@&1338546156325568642>' || '<@&1352296092989001768>' }} - # New ${{ github.event.release.prerelease && 'beta ' || '' }}version of custom anvil ! <:CustomAnvil:1262550667986342001>([Modrinth](https://modrinth.com/plugin/customanvil), [Hangar](https://hangar.papermc.io/alexcrea/CustomAnvil) and [GitHub](${{ github.event.release.html_url }}) links) - -# note: automated release. spigot is not uploaded yet. - - ${{ github.event.release.body }} diff --git a/.gitignore b/.gitignore index 982299c..80d6030 100644 --- a/.gitignore +++ b/.gitignore @@ -2,21 +2,3 @@ /.gradle/ /build/ /out/ -.lastDeploymentsId - -#nms & impl submodule build directory ignored -/nms/build -/nms/.gradle -/nms/*/build -/nms/*/.gradle -/impl/build -/impl/.gradle -/impl/*/build -/impl/*/.gradle - -# run folder -/run/ - -# other random folders -/htmlReport -/.kotlin/errors diff --git a/.idea/icon.png b/.idea/icon.png deleted file mode 100644 index 06945f2..0000000 Binary files a/.idea/icon.png and /dev/null differ diff --git a/.run/Server.run.xml b/.run/Server.run.xml deleted file mode 100644 index 9a8887f..0000000 --- a/.run/Server.run.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - \ No newline at end of file diff --git a/COMPATIBILITY.md b/COMPATIBILITY.md deleted file mode 100644 index 9d37521..0000000 --- a/COMPATIBILITY.md +++ /dev/null @@ -1,63 +0,0 @@ -### Bedrock issue -For server using geyser, bedrock player cannot use custom "recipes" in the anvil. -This is cannot be fixed on geyser or my side. - -### Plugin Compatibility -Here is various plugins that had issues with CustomAnvil -where efforts was made for compatibility and should be working right: - -some if not all of them are cool ! I recommend checking them out ! - -## Supported By CustomAnvil -These plugins have compatibility handled by custom anvil. seek help on custom anvil and do not bother these developers - -#### Enchantment Plugins -- [ExcellentEnchants](https://www.spigotmc.org/resources/excellentenchants-%E2%AD%90-75-vanilla-like-enchantments.61693/) by NightExpress: - Use ExcellentEnchants item type \ - Also use ExcellentEnchant max enchant limit - -- [EcoEnchant](https://www.spigotmc.org/resources/ecoenchants-%E2%AD%95-250-enchantments-%E2%9C%85-create-custom-enchants-%E2%9C%A8-essentials-cmi-support.79573/) by Auxilor: - Need to use /anvilconfigreload or a server restart to add newly added enchantment. - Use EcoEnchant restriction system but new restriction can be added in custom anvil - -- [Enchantment²](https://www.spigotmc.org/resources/enchants-squared-the-enchantsplus-rewrite-custom-enchantments-that-act-like-vanilla-ones.86747/) by Athlaeos: - Support by Custom Anvil but still experimental. Automatic configuration. Plugin is not actively developed anymore - -- [SuperEnchants](https://modrinth.com/plugin/superenchants) by Aznos: - Use SuperEnchant restrictions system but new restriction can be added in custom anvil - - -#### Custom Items Plugins -Custom Items support is considered unstable. If you find issue please report it ! - -- [EcoItem](https://www.spigotmc.org/resources/30-sale%E2%8F%B3-ecoitems-%E2%AD%95-create-custom-items-%E2%9C%85-weapons-armors-tools-charms-%E2%9C%A8-item-levels-rarities.94601/) by Exanthiax: - May have some issue. but should partially work I hope - -- [ItemAdder](https://www.spigotmc.org/resources/%E2%9C%A8itemsadder%E2%AD%90emotes-mobs-items-armors-hud-gui-emojis-blocks-wings-hats-liquids.73355/) by LoneDev: - Need to fix unit item not working completly correctly as in can't have twice same base item - -#### Anvil Mechanics Plugins -- [Disenchantment](https://www.spigotmc.org/resources/disenchantment-1-21-1-1-20-6-new-book-splitting-mechanics.110741/) by H7KZ - Partially use Custom Anvil maximum XP settings (>= 6.1.5) - -- [HavenBags](https://www.spigotmc.org/resources/havenbags-shulker-like-player-bound-bags-1-17-1-21-4.110420/) by hyperdefined - For bag upgrade and skin via anvil. (version >= 1.31.0) - -- [AxPlayerWarp](https://modrinth.com/project/QDJHDKvi) by ArtillexStudios - For its anvil inventory usage - -- [ToolsStats](https://modrinth.com/project/oBZj9E15) by Valorless - For token application using anvil - -### Known Partially Incompatible -- [UberEnchant](https://modrinth.com/plugin/uberenchant) by coltonj96 - Anvil handling as they are doing something similar to CustomAnvil. -It is by no mean there faults and I recommend checking them out especially if custom anvil do not work for your use case ! - -- [AdvencedEnchantments](https://ae.advancedplugins.net/) by Advanced Plugins - Paid plugin I do not own as I did not get commissioned for support. - may be able to use api but cannot test on my side - -If you like Custom Anvil to support a specific plugin (custom enchant or anvil mechanic). -You can ask, but please note implementing compatibility will be considered -as low priority as I work for the plugin as an hobby on my free time for free. diff --git a/CREDITS.md b/CREDITS.md deleted file mode 100644 index 56409f5..0000000 --- a/CREDITS.md +++ /dev/null @@ -1,34 +0,0 @@ -Thanks **DelilahEve** for making [Unsafe Enchants](https://github.com/DelilahEve/UnsafeEnchants). \ -CustomAnvil was initially a fork of Unsafe Enchants where I wanted to add more and more and here we are now ! - -Thanks for all the contributors of bukkit, spigot, the paper team and the adventure API developers \ -Thanks JetBrain for making IntelliJ - -### Dependencies -These dependencies (or a modified version of) are used by custom anvil -- [IF](https://github.com/stefvanschie/IF) an inventory framework by stefvanschie -- [Mockbukkit](https://github.com/MockBukkit/MockBukkit) for unit testing -- [CentralPortalPlus](https://github.com/lalakii/central-portal-plus) by lalakii -- [test-summary-action](https://github.com/jeantessier/test-summary-action) by jeantessier -- [modrinth-publish](https://github.com/cloudnode-pro/modrinth-publish) by Zefir -- [discord-webhook](https://github.com/tsickert/discord-webhook) by tsickert -- Thanks [bstats](https://bstats.org/) for keeping me motivated -- And [FastStats](https://faststats.dev/) alternative to bstats in beta test -- [ModrinthUpdateChecker](https://github.com/Clickism/ModrinthUpdateChecker) by Clickism and thanks to the modrinth team - -### Compatibility -Thanks to all the cool creator making the minecraft plugin's ecosystem works ! \ -See [Compatibility list](https://github.com/alexcrea/CustomAnvil/blob/v1.x.x/COMPATIBILITY.md) for details - -but especially, Big Thanks for H7KZ maker of [Disenchantment](https://github.com/H7KZ/Disenchantment) - -### Special Thanks - -Thanks for all the users trying my plugin for these niche use cases -, reporting issues and giving ideas ! - -Thanks coltonj96 for [UberEnchant](https://modrinth.com/plugin/uberenchant). -we may be incompatible with the anvil, but I do think it is a good alternative ! \ -I wish one day to work on cross compatibiltiy \ -* If custom anvil do not work well for you or your use case give it a try ! * - diff --git a/LICENSE b/LICENSE deleted file mode 100644 index f288702..0000000 --- a/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/README.md b/README.md index 9d9e678..85fcbf0 100644 --- a/README.md +++ b/README.md @@ -1,111 +1,40 @@ -# Custom Anvil +# UnsafeEnchants+ -**Custom Anvil** is a plugin that allows server administrators to customize every aspect of the anvil's mechanics. +**UnsafeEnchants+** is a fully configurable plugin for bukkit, spigot, and paper minecraft servers +allowing custom enchantment limits and customising combination restrictions. + +**UnsafeEnchants+** is based on [UnsafeEnchants](https://github.com/DelilahEve/UnsafeEnchants). You can find it on +[GitHub](https://github.com/DelilahEve/UnsafeEnchants/releases/latest), +[Spigot](https://www.spigotmc.org/resources/unsafe-enchants.104708/) or +[CurseForge](https://www.curseforge.com/minecraft/bukkit-plugins/unsafe-enchants/files/all) + +**UnsafeEnchants+** add the following to [UnsafeEnchants](https://github.com/DelilahEve/UnsafeEnchants): +- Make default configuration more vanilla like +- Fix a xp bug with enchanted book +- Custom enchantment restriction configuration +--- +### Know issue: +There is non known issue, if you find one please report the issue. + +--- ### Download Locations: -the plugin can be downloaded on - [Modrinth](https://modrinth.com/plugin/customanvil), - [Hangar](https://hangar.papermc.io/alexcrea/CustomAnvil) - or here [on GitHub](https://github.com/alexcrea/CustomAnvil/releases/latest) +the plugin can be downloaded on the +[Spigot site](https://www.spigotmc.org/resources/unsafe-enchants.114884/) +or [on GitHub](https://github.com/alexcrea/UnsafeEnchantsPlus/releases/latest) ---- -**Custom Anvil** have the following features: -- Vanilla like default configuration. -- Custom enchantment level limit. -- Custom anvil recipes. -- Custom enchant restrictions (allows unsafe enchantment only for a group of item or create new restriction). -- Custom items of unit repairs (repair damaged with unit of "material", for example the repair of diamond sword by diamonds). -- Custom XP cost for every aspect of the anvil. -- Permissions to bypass level limit or enchantment restriction. -- Display XP cost instead of "too expensive" when above level 40. (see below for more information) -- Can handle some custom enchantment plugins (see below for more information) -- Gui to configure the plugin in game. -- Support use of color code, hexadecimal color and minimessage for color/decoration -- (Experimental) Folia support (gui do not work) -- (Experimental) Dialog rename (allows longer rename) -- (Experimental) Anvil with monetary cost (using vault) (require dialog rename) - -And more ! - ---- ### Permissions: -Note that for most of them you also need to enable feature and in most case enable use of permission for the specfic feature (indicated with `(toggleable)`) ```yml -# Generic and bypass permissions -ca.affected: Player with this permission will be affected by the plugin -ca.bypass.fuse: Allow player to combine every enchantments to every item (no custom limit) -ca.bypass.level: Allow player to bypass every level limit (no custom limit) - -# Command permissions -ca.command.reload: Allow administrator to reload the plugin's configs -ca.command.diagnostic: Allow adminastator to diagnistic some simple problem with the plugin -ca.config.edit: Allow administrator to edit the plugin's config in game - -# ----------------------------------------------------------------------------- -# Bellow permissions also require some config change to allow usage of features -# Usage of these permission is toggleable in basic config gui or config.yml -# ----------------------------------------------------------------------------- -# Permissions related to use of color and minimessage -ca.color.code: Allow player to use color code on rename if enabled (toggleable) -ca.color.code.[thecode] (for example ca.color.code.a): Allows usage of only certain color code (toggleable) -ca.color.hex: Allow player to use hexadecimal color on rename if enabled (toggleable) -ca.rename.minimessage: Allow player to use minimessage formating on rename if enabled (toggleable) - -# Permissions related to edition of the lore -ca.lore_edit.book: Allow player to edit lore via book and quil if enabled (toggleable) -ca.lore_edit.paper: Allow player to edit lore via paper if enabled (toggleable) - -# Others -ca.rename.dialog: Allow player to use the rename dialog (toggleable) +ue.unsafe: Allows use of custom restriction rules +ue.bypass.fuse: Bypass every enchantment restriction check. Including custom restrictions +ue.bypass.level: Bypass max level check. Including custom max level ``` -### Commands +### Default Configuration: -run `/customanvil help` to get information about available commands \ -this only show subcommands you have permission for +Default configuration can be found on following links: +- [config.yml](https://github.com/alexcrea/UnsafeEnchantsPlus/blob/master/src/main/resources/config.yml) +- [enchant_conflict.yml](https://github.com/alexcrea/UnsafeEnchantsPlus/blob/master/src/main/resources/enchant_conflict.yml) +- [item_groups.yml](https://github.com/alexcrea/UnsafeEnchantsPlus/blob/master/src/main/resources/item_groups.yml) -### Supported Plugins -See the [Compatibility list](https://github.com/alexcrea/CustomAnvil/blob/v1.x.x/COMPATIBILITY.md) - -### Overriding Too Expensive - -One of the configurations allow displaying price about 40 and removing Too Expensive. \ -By how the minecraft client work: price above 40 can only be displayed green, even if the player does not own enough experience level. -spigot version 1.18 to 1.21.11 do not need any ProtocoLib dependency. (26.1.0 or above requires it) \ -Any recent paper version also are supported for this feature. -But you should wait for update for new version containing new enchantable item or new enchantments if any of this got added. -Else it is, likely, fine to use the current version you are ussing on a new paper version - -### For custom enchantment plugin developers -For information about the API, please refer to [the Wiki](https://github.com/alexcrea/CustomAnvil/wiki) \ -(Please note that the wiki is currently incomplete) - ---- - -### Default Plugin's Configurations -see [Here](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs) - ---- -### Metric And Telemetry -Custom anvil [use bstat](https://bstats.org/plugin/bukkit/Unsafe%20Enchants%20Plus/20923) -and [faststats](https://faststats.dev/project/customanvil/minecraft-plugin) for metric and error reporting. - -You can select specific telemetry or disable all in config.yml. \ -You can also [disable bstat](https://bstats.org/getting-started) and [faststats](https://faststats.dev/info) in their /plugin folder if you like too. - -faststats is in beta testing please report me or them any error you encounter - -### Credits and Thanks -Credits and thanks can be seen [here](https://github.com/alexcrea/CustomAnvil/blob/v1.x.x/CREDITS.md) - -### Planned: -- Better Folia support (make gui work. fix some dirty handled parts) -- Get restriction on unknown enchantments (planned for V2) -- More features for custom anvil craft - -### Known issue: -Most unknown registered enchantments (by unsupported custom enchantment plugin & datapacks) will not have restriction by default. Planned but no eta. - -### Do you need help with the plugin, or have any issue or suggestion? -You can ask on the discussion page, create a [GitHub issue](https://github.com/alexcrea/CustomAnvil/issues) or join my [discord](https://discord.gg/KHUNsUfRYJ)​ diff --git a/build.gradle.kts b/build.gradle.kts index a5dc7c3..c726534 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,455 +1,45 @@ -import cn.lalaki.pub.BaseCentralPortalPlusExtension -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import groovy.util.Node -import groovy.util.NodeList -import io.papermc.hangarpublishplugin.model.HangarPublication -import io.papermc.hangarpublishplugin.model.Platforms -import org.jetbrains.kotlin.gradle.dsl.JvmTarget -import java.io.ByteArrayOutputStream - plugins { - kotlin("jvm") version "2.3.0" + kotlin("jvm") version "1.6.21" java - id("org.jetbrains.dokka").version("1.9.20") - id("com.gradleup.shadow").version("9.3.0") - // Maven publish - `maven-publish` - signing - id("cn.lalaki.central").version("1.2.8") - // Paper - id("io.papermc.paperweight.userdev") version "2.0.0-beta.17" apply false - id("io.papermc.hangar-publish-plugin") version "0.1.2" } -group = "xyz.alexcrea" -version = "1.17.5" - -val isDevBuild = System.getenv("SMALL_COMMIT_HASH") != null -val isPreRelease = System.getenv("IS_GITHUB_PRERELEASE") == "true" - -val effectiveVersion = "$version" + - (if (isDevBuild) "-dev-${System.getenv("SMALL_COMMIT_HASH")!!}" else "") +group = "io.delilaheve" +version = "1.1.4" repositories { - // EcoEnchants - maven(url = "https://repo.auxilor.io/repository/maven-public/") - - // ExcellentEnchants - maven(url = "https://repo.nightexpressdev.com/releases") - - // ItemsAdder - maven(url = "https://maven.devs.beer/") - - // For fast stats - maven { - name = "thenextlvlReleases" - url = uri("https://repo.thenextlvl.net/releases") - } - - // For vault unlocked - maven { url = uri("https://repo.codemc.io/repository/creatorfromhell/") } + mavenCentral() + maven(url = "https://hub.spigotmc.org/nexus/content/repositories/snapshots/") } -val reobfNMS = providers.gradleProperty("subprojects.reobfnms") - .get().split(",") - dependencies { - // Spigot api - compileOnly("org.spigotmc:spigot-api:1.18-R0.1-SNAPSHOT") - // fast stats - implementation("dev.faststats.metrics:bukkit:0.27.0") + compileOnly(kotlin("stdlib")) - // minimessage - implementation("net.kyori:adventure-text-minimessage:4.25.0") + compileOnly("org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT") - // Gui library - val inventoryFramework = "xyz.alexcrea.cuanvil.inventoryframework:IF-CustomAnvil:0.10.18.2" - implementation(inventoryFramework) - testRuntimeOnly(inventoryFramework) + testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.0") - // EnchantsSquaredRewritten - compileOnly(files("libs/EnchantsSquared.jar")) - - // EcoEnchants & item - compileOnly("com.willfp:libreforge:4.79.0:all") - compileOnly("com.willfp:eco:6.74.5") - - compileOnly("com.willfp:EcoEnchants:12.11.1") - compileOnly(project(":impl:LegacyEcoEnchant")) - - compileOnly("com.willfp:EcoItems:5.66.0") - - // ExcellentEnchants - implementation(project(":impl:ExcellentEnchant5_4")) - compileOnly("su.nightexpress.excellentenchants:Core:5.1.0") { - exclude("org.spigotmc") - } - compileOnly(files("libs/ExcellentEnchants-4.3.3-striped.jar")) // For pre v5 excellent enchants - compileOnly(files("libs/ExcellentEnchants-4.1.0-striped.jar")) // For legacy excellent enchants - - // Disenchantment - compileOnly(files("libs/Disenchantment-6.1.5.jar")) - - // HavenBags - compileOnly(files("libs/HavenBags-1.31.0.1760.jar")) - - // ToolStats - compileOnly(files("libs/toolstats-1.9.6-stripped.jar")) - - // AxPlayerWarps - compileOnly(files("libs/AxPlayerWarps-1.10.3.jar")) - - // SuperEnchants - compileOnly(files("libs/SuperEnchants-4.6.2-all.jar")) - - // ItemsAdder API - compileOnly("dev.lone:api-itemsadder:4.0.10") - - // Vault api - compileOnly("net.milkbowl.vault:VaultUnlockedAPI:2.16") - - // Include nms - implementation(project(":nms:nms-common")) - implementation(project(":nms:nms-paper")) - for (nmsPart in reobfNMS) { - implementation(project(":nms:$nmsPart", configuration = "reobf")) - } - - // include kotlin for the offline jar - implementation(kotlin("stdlib")) - - // Test dependency - testImplementation("org.mockbukkit.mockbukkit:mockbukkit-v1.21:4.48.0") - testRuntimeOnly("commons-lang:commons-lang:2.6") -} - -allprojects { - apply(plugin = "java") - apply(plugin = "kotlin") - - repositories { - mavenCentral() - - // Spigot repository - maven(url = "https://hub.spigotmc.org/nexus/content/repositories/snapshots/") - - // Paper repository - maven("https://repo.papermc.io/repository/maven-public/") - } - - dependencies { - compileOnly(kotlin("stdlib")) - - // Test dependency - testImplementation(platform("org.junit:junit-bom:5.12.2")) - testImplementation("org.junit.jupiter:junit-jupiter") - testRuntimeOnly("org.junit.platform:junit-platform-launcher") - } - - tasks.getByName("test") { - useJUnitPlatform() - } - - // Configure used version of kotlin and java - java { - disableAutoTargetJvm() - toolchain.languageVersion.set(JavaLanguageVersion.of(21)) - } - - // Set target version - tasks.withType().configureEach { - sourceCompatibility = - "16" // We aim for java 16 for minecraft 1.16.5. even if it not really supported by custom anvil. - targetCompatibility = "16" - - options.encoding = "UTF-8" - } - - kotlin { - compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) - jvmTarget.set(JvmTarget.JVM_16) - } - } + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") } - -tasks { - - fun ShadowJar.configureBaseShadow(suffix: String, libraries: Array) { - val processedSuffix = if(suffix.isEmpty()) "" else "-$suffix" - val name = "${rootProject.name}-${effectiveVersion}${processedSuffix}.jar" - archiveFileName.set(name) - - // Shadow necessary dependency - relocate("com.github.stefvanschie.inventoryframework", "xyz.alexcrea.cuanvil.inventoryframework") - relocate("dev.faststats", "xyz.alexcrea.cuanvil.faststats") - - filesMatching("plugin.yml") { - expand( - "version" to effectiveVersion + processedSuffix, - "libraries" to libraries.joinToString(transform = { "\"$it\"" }), - ) - } - - // Process resource for plugin.yml - dependsOn(processResources) - } - - // Online jar (use of libraries) - shadowJar { - configureBaseShadow("", - arrayOf( - "org.jetbrains.kotlin:kotlin-stdlib:2.3.0", - "net.kyori:adventure-text-minimessage:4.25.0", - "net.kyori:adventure-text-serializer-plain:4.25.0", - "net.kyori:adventure-text-serializer-legacy:4.25.0", - )) - - // Exclude kotlin std, annotations and adventure api - exclude("*kotlin/**") - exclude("**/annotations/**") - exclude("net/kyori/**") - } - - val offlineJar by registering(ShadowJar::class) { - configureBaseShadow("offline", emptyArray()) - - from(sourceSets.main.get().output) - configurations = listOf(project.configurations.runtimeClasspath.get()) - } - - // Make the online and offline jar on build - named("build") { - dependsOn(shadowJar, offlineJar) - } - +tasks.getByName("test") { + useJUnitPlatform() } -val sourcesJar by tasks.registering(Jar::class) { - archiveClassifier.set("sources") - from(kotlin.sourceSets.main.get().kotlin) -} - -val javadocJar by tasks.registering(Jar::class, fun Jar.() { - group = JavaBasePlugin.DOCUMENTATION_GROUP - description = "Assembles Javadoc JAR" - archiveClassifier.set("javadoc") - from(tasks.named("dokkaHtml")) -}) - -signing { - useGpgCmd() - val extension = extensions - .getByName("publishing") as PublishingExtension - sign(extension.publications) -} - -// ------------------------------------ -// PUBLISHING TO SONATYPE CONFIGURATION -// ------------------------------------ - -// The path is recommended to be set to an empty directory -val localMavenRepo = uri( - project.findProperty("localMavenRepo") as String? - ?: rootProject.layout.buildDirectory.dir("local-maven-repo").get().asFile.toURI() // Convert to URI -) - -centralPortalPlus { - url = localMavenRepo - username = System.getenv("SONATYPE_USERNAME") - password = System.getenv("SONATYPE_PASSWORD") - publishingType = BaseCentralPortalPlusExtension.PublishingType.USER_MANAGED // or PublishingType.AUTOMATIC -} - -object Meta { - const val desc = "spigot plugin to control every aspect of the anvil." - const val license = "GPL-3.0" - const val githubRepo = "alexcrea/CustomAnvil" - const val release = "https://s01.oss.sonatype.org/service/local/" - const val snapshot = "https://s01.oss.sonatype.org/content/repositories/snapshots/" -} - -val disallowedDependency = HashSet() -disallowedDependency.addAll(reobfNMS) -disallowedDependency.addAll(listOf("nms-common", "nms-paper", "kotlin-stdlib")) - -publishing { - repositories { - maven { - url = localMavenRepo // Specify the same local repo path in the configuration. - } - } - - publications { - create("maven") { - groupId = project.group.toString() - artifactId = project.name - version = project.version.toString() - from(components["kotlin"]) - artifact(tasks["sourcesJar"]) - artifact(tasks["javadocJar"]) - - versionMapping { - usage("java-api") { - fromResolutionOf("runtimeClasspath") - } - usage("java-runtime") { - fromResolutionResult() - } - } - - pom { - name.set(project.name) - description.set(Meta.desc) - url.set("https://github.com/${Meta.githubRepo}") - licenses { - license { - name.set(Meta.license) - url.set("https://www.gnu.org/licenses/gpl-3.0.en.html") - } - } - developers { - developer { - id.set("alexcrea") - name.set("alexcrea") - email.set("alexcrea.of@laposte.net") - url.set("https://github.com/alexcrea") - } - } - scm { - url.set( - "https://github.com/${Meta.githubRepo}.git" - ) - connection.set( - "scm:git:git://github.com/${Meta.githubRepo}.git" - ) - developerConnection.set( - "scm:git:git://github.com/${Meta.githubRepo}.git" - ) - } - issueManagement { - url.set("https://github.com/${Meta.githubRepo}/issues") - } - - withXml { - val dependenciesNode = (asNode().get("dependencies") as NodeList)[0] as Node - - val toRemove = ArrayList() - for (child in dependenciesNode.children()) { - val artifactNode = ((child as Node).get("artifactId") as NodeList)[0] as Node - val artifactID = artifactNode.value() as String - - if(disallowedDependency.contains(artifactID)) { - toRemove.add(child) - } - } - - for (node in toRemove) { - dependenciesNode.remove(node) - } - } - } - } +// Fat-jar builder +val fatJar = tasks.register("fatJar") { + manifest { + attributes.apply { put("Main-Class", "io.delilaheve.UnsafeEnchants") } } + archiveFileName.set("${rootProject.name}-${archiveVersion}.jar") + exclude("META-INF/*.RSA", "META-INF/*.SF", "META-INF/*.DSA") + duplicatesStrategy = DuplicatesStrategy.WARN + from(configurations.runtimeClasspath.get().map { if (it.isDirectory) it else zipTree(it) }) + with(tasks.jar.get() as CopySpec) } -// hangar publish - -fun executeGitCommand(vararg command: String): String { - val byteOut = ByteArrayOutputStream() - exec { - commandLine = listOf("git", *command) - standardOutput = byteOut - } - return byteOut.toString(Charsets.UTF_8.name()).trim() -} - - -fun latestCommitMessage(): String { - return executeGitCommand("log", "-1", "--pretty=%B") -} - -fun changelog(isOnline: Boolean): String { - var changelog = if(isDevBuild) latestCommitMessage() - else System.getenv("RELEASE_CHANGELOG") - - if(!isOnline) { - changelog = "This is an offline version of the plugin. \\\n" + - "This mean that this plugin libraries are shaded into this plugin \\\n" + - "You likely want to use the normal version of this plugin\n\n" + changelog - } - - if(changelog == null || changelog.isEmpty()) { - changelog = "empty changelog" - } - - return changelog -} - -hangarPublish { - - fun HangarPublication.configure(isOnline: Boolean, devChannel: String, releaseChannel: String) { - var versionName = effectiveVersion - if(isPreRelease) versionName+= "-pre" - if(!isOnline) versionName+= "-offline" - - version.set(versionName) - channel.set(if (isDevBuild || isPreRelease) devChannel else releaseChannel) - - changelog.set(changelog(isOnline)) - id.set("CustomAnvil") - apiKey.set(System.getenv("HANGAR_API_TOKEN")) - - platforms { - register(Platforms.PAPER) { - // Set the JAR file to upload - var task = if(isOnline) tasks.shadowJar - else tasks.named("offlineJar") - - jar.set(task.flatMap { it.archiveFile }) - - // Set platform versions from gradle.properties file - val versions: List = (property("paperVersion") as String) - .split(",") - .map { it.trim() } - platformVersions.set(versions) - - dependencies { - hangar("ProtocolLib") { - required.set(false) - } - url("Disenchantment", "https://modrinth.com/plugin/disenchantment") { - required.set(false) - } - url("ToolStats", "https://modrinth.com/plugin/toolstats") { - required.set(false) - } - url("HavenBags", "https://www.spigotmc.org/resources/havenbags-shulker-like-player-bound-bags-1-17-1-21-4.110420/") { - required.set(false) - } - url("EcoEnchants", "https://www.spigotmc.org/resources/ecoenchants-%E2%AD%95-250-enchantments-%E2%9C%85-create-custom-enchants-%E2%9C%A8-essentials-cmi-support.79573/") { - required.set(false) - } - hangar("EnchantsSquared") { - required.set(false) - } - url("ExcellentEnchants", "https://www.spigotmc.org/resources/excellentenchants-%E2%AD%90-75-vanilla-like-enchantments.61693/") { - required.set(false) - } - } - } - } - } - - publications.register("plugin") { - configure(true, "DevSnapshot", "Release") - } - - publications.register("offline") { - configure(false, "OfflineSnapshot", "OfflineRelease") - } - -} +// Ensure fatJar and copyJar are run +tasks.getByName("build") { + dependsOn(fatJar) +} \ No newline at end of file diff --git a/defaultconfigs/1.18/README.md b/defaultconfigs/1.18/README.md deleted file mode 100644 index d390f3f..0000000 --- a/defaultconfigs/1.18/README.md +++ /dev/null @@ -1,6 +0,0 @@ -### Default Plugin's Configurations For 1.18 to 1.20.6 -- [config.yml](https://github.com/alexcrea/CustomAnvil/blob/master/defaultconfigs/1.18/config.yml) -- [enchant_conflict.yml](https://github.com/alexcrea/CustomAnvil/blob/master/defaultconfigs/1.18/enchant_conflict.yml) -- [item_groups.yml](https://github.com/alexcrea/CustomAnvil/blob/master/defaultconfigs/1.18/item_groups.yml) -- [unit_repair_item.yml](https://github.com/alexcrea/CustomAnvil/blob/master/defaultconfigs/1.18/unit_repair_item.yml) -- [custom_recipes.yml](https://github.com/alexcrea/CustomAnvil/blob/master/defaultconfigs/1.18/custom_recipes.yml) diff --git a/defaultconfigs/1.18/config.yml b/defaultconfigs/1.18/config.yml deleted file mode 100644 index b5ad3b0..0000000 --- a/defaultconfigs/1.18/config.yml +++ /dev/null @@ -1,466 +0,0 @@ -# -# It is recommended that you use /configanvil to edit theses config. -# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! -# - -# What service of metric should custom anvil use -# Custom anvil collect generic information like server minecraft version, type, etc... -# It can also collect error information if error is happening (currently faststats only) -# It can also be disabled -# Please refer to README for public metric link -# Possible options: auto, bstat, faststats, disabled (auto by default) -metric_type: auto - -# Allow to report errors made caused by this plugin (only for faststats) -# This allows me to fix potentials issue that I'm not aware of -# Accept true or false (true by default) -metric_collect_errors: true - -# All anvil cost will be capped to limit_repair_value if enabled. -# -# In other words: -# For any anvil cost greater than limit_repair_value, Cost will be set to limit_repair_value. -limit_repair_cost: false - -# Max cost value the Anvil can get to. -# -# Valid values include 0 to 1000. -# Cost will be displayed as "Too Expensive": -# - If Cost is above 39 -# - And replace_too_expensive is disabled (false) -limit_repair_value: 39 - -# Whether the anvil's cost limit should be removed entirely. -# -# The anvil will still visually display "Too Expensive" if "replace_too_expensive" is disabled -# However, the action will be completable if xp requirement is meet. -remove_repair_limit: false - -# Whenever anvil cost is above 39 should display the true price and not "Too Expensive". -# -# However, when bypassing "Too Expensive", anvil price will be displayed as Green. -# If the action is not completable, the cost will still be displayed as "Too expensive". -# That mean you also need to change other settings like remove_repair_limit or limit_repair_cost. -# -# Require ProtocoLib. -replace_too_expensive: false - -# XP Level amount added to the anvil when the item is repaired by another item of the same type -# -# Valid values include 0 to 1000 -item_repair_cost: 2 - -# XP Level amount added to the anvil when the item is renamed -# -# Valid values include 0 to 1000 -item_rename_cost: 1 - -# XP Level amount added to the anvil when the item is repaired by an "unit" -# For example: a Diamond on a Diamond Sword -# What's considered unit for what can be edited on the unit repair configuration. -# -# Valid values include 0 to 1000 -unit_repair_cost: 1 - -# XP Level amount added to the anvil when a sacrifice enchantment -# conflict with one of the left item enchantment -# -# Valid values include 0 to 1000 -sacrifice_illegal_enchant_cost: 1 - -# Allow using color code and hexadecimal color. -# -# Color code are prefixed by "&" and hexadecimal color by "#". -# Color code will not be applied if it colors nothing. "&&" can be used to write "&". -# For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ -allow_color_code: false -allow_hexadecimal_color: false -allow_minimessage: false - -# This enables restricting color code for player having specific permission -# It requires allow_color_code enabled for... obvious reasons -# -# For example: if player want to use "&aHello" it will be required that the player has -# the permission "ca.color.code.a" as he used the color code "a" -# In general permission to give to the player is "ca.color.code.[code]" -# where [code] is the color code you wish to allow the player -# -# It is kinda of useless when minimessage is supported as players would be able to bypass -# that using the equivalent minimessage tag -per_color_code_permission: false - -# Toggle if color should only be applicable if the player a certain permission. -# -# permission are "ca.color.code" for use of color code and "ca.color.hex" for use of hexadecimal color. -permission_needed_for_color: true - -# Xp cost if the player use color in the items name on rename. -# -# Valid values include 0 to 1000. -use_of_color_cost: 0 - -# Dialogue rename menu make use of dialog menu to allow bigger rename -# You can also change the maximum size and set it to -1 or less for maximum -# -# This feature only work on paper 1.21.7 or later -# -# At the moment only english is available for this menu... sorry ! -# -# CustomAnvil use "ca.rename.dialog" when permission -enable_dialog_rename: false -dialog_rename_max_size: 256 -permission_needed_for_dialog_rename: false - -# This allows custom anvil to not "guess" the text used for rename but store it in the item -# It will make item stackable only and only if it had used the same rename text -# -# For practical reason. this only work when dialog rename is enabled -dialog_rename_keep_user_text: true - -# Override limits for specific enchants -# -# Enchantments not listed here will use the value of default_limit -# -# Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels -# -# Valid range of 0 - 255 for each enchantment -# -1 mean keep default -enchant_limits: - minecraft:aqua_affinity: 1 - minecraft:binding_curse: 1 - minecraft:channeling: 1 - minecraft:flame: 1 - minecraft:infinity: 1 - minecraft:mending: 1 - minecraft:multishot: 1 - minecraft:silk_touch: 1 - minecraft:vanishing_curse: 1 - minecraft:depth_strider: 3 # anything more than 3 is treated as 3 by the game - minecraft:protection: 4 - minecraft:fire_protection: 4 - minecraft:blast_protection: 4 - minecraft:projectile_protection: 4 - minecraft:feather_falling: 4 - minecraft:thorns: 3 - minecraft:respiration: 3 - minecraft:sharpness: 5 - minecraft:smite: 5 - minecraft:bane_of_arthropods: 5 - minecraft:knockback: 2 - minecraft:fire_aspect: 2 - minecraft:looting: 3 - minecraft:sweeping: 3 - minecraft:sweeping_edge: 3 - minecraft:efficiency: 5 - minecraft:unbreaking: 3 - minecraft:fortune: 3 - minecraft:power: 5 - minecraft:punch: 2 - minecraft:luck_of_the_sea: 3 - minecraft:lure: 3 - minecraft:frost_walker: 2 - minecraft:impaling: 5 - minecraft:riptide: 3 - minecraft:loyalty: 3 - minecraft:piercing: 4 - minecraft:quick_charge: 3 - minecraft:soul_speed: 3 - minecraft:swift_sneak: 3 - -# Multipliers used to calculate the enchantment's value in repair/combining -# -# Values here are pulled from the fandom wiki: -# https://minecraft.fandom.com/wiki/Anvil_mechanics#Costs_for_combining_enchantments -# -# If an enchantment is missing values here, or is less than 0, it will default to 0 -# -# Calculated as: [Enchantment lvl] * [multiplier] -# -# With default values protection 4 would have a value of 4 when -# coming from either a book (4 * 1) or an item (4 * 1) -enchant_values: - minecraft:aqua_affinity: - item: 4 - book: 2 - minecraft:bane_of_arthropods: - item: 2 - book: 1 - minecraft:binding_curse: - item: 8 - book: 4 - minecraft:blast_protection: - item: 4 - book: 2 - minecraft:channeling: - item: 8 - book: 4 - minecraft:depth_strider: - item: 4 - book: 2 - minecraft:efficiency: - item: 1 - book: 1 - minecraft:flame: - item: 4 - book: 2 - minecraft:feather_falling: - item: 2 - book: 1 - minecraft:fire_aspect: - item: 4 - book: 2 - minecraft:fire_protection: - item: 2 - book: 1 - minecraft:fortune: - item: 4 - book: 2 - minecraft:frost_walker: - item: 4 - book: 2 - minecraft:impaling: - item: 4 - book: 2 - minecraft:infinity: - item: 8 - book: 4 - minecraft:knockback: - item: 2 - book: 1 - minecraft:looting: - item: 4 - book: 2 - minecraft:loyalty: - item: 1 - book: 1 - minecraft:luck_of_the_sea: - item: 4 - book: 2 - minecraft:lure: - item: 4 - book: 2 - minecraft:mending: - item: 4 - book: 2 - minecraft:multishot: - item: 4 - book: 2 - minecraft:piercing: - item: 1 - book: 1 - minecraft:power: - item: 1 - book: 1 - minecraft:projectile_protection: - item: 2 - book: 1 - minecraft:protection: - item: 1 - book: 1 - minecraft:punch: - item: 4 - book: 2 - minecraft:quick_charge: - item: 2 - book: 1 - minecraft:respiration: - item: 4 - book: 2 - minecraft:riptide: - item: 4 - book: 2 - minecraft:silk_touch: - item: 8 - book: 4 - minecraft:sharpness: - item: 1 - book: 1 - minecraft:smite: - item: 2 - book: 1 - minecraft:soul_speed: - item: 8 - book: 4 - minecraft:swift_sneak: - item: 8 - book: 4 - minecraft:sweeping: - item: 4 - book: 2 - minecraft:sweeping_edge: - item: 4 - book: 2 - minecraft:thorns: - item: 8 - book: 4 - minecraft:unbreaking: - item: 2 - book: 1 - minecraft:vanishing_curse: - item: 8 - book: 4 - -# Disable enchantment merging for level above the set value -# Enchantment merging is when, for example, 2 unbreaking II book combine to give sharpness III -# But Enchantment above this value can still be applied. following the previous example, we could still apply a unbreaking III book to a sword -# Even if disable-merge-over of unbreaking is set to 2 -# -1 mean enchantment merge for this enchantment is not disabled. default to -1 if absent. -disable-merge-over: - # Sharpness is set to -1. it equivalent to it not being set to anything (and work as vanilla on default configuration) - minecraft:sharpness: -1 - # If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied - #minecraft:unbreaking: 2 - -# The maximum number of enchantment an item can get. -1 for infinity -# Use eco enchant enchant_limit if present by default unless "default" is not equal to -1 -enchantment_count_limit: - default: -1 - # Limit for specific items. example bellow is an example with stick - # Per item enchantment limit override eco enchant enchant_limit and default limit - items: - stick: -1 - -# Settings for lore modification -lore_edit: - book_and_quil: - # Permission is ca.lore_edit.book - use_permission: true - append: - # If adding lore using book & quil is enabled - enabled: false - # Cost used every time - fixed_cost: 1 - # Cost used for every lore line added - per_line_cost: 0 - # Use left item vanilla cost penalty if any - shared_increase: false - # Increase shared left item cost penalty - shared_additive: false - # If adding the lore consume the book & quil - do_consume: false - # Allow using color code and hexadecimal color when editing lore via book & quil - # - # Color code are prefixed by "&" and hexadecimal color by "#" - # Color code will not be applied if it colors nothing. "&&" can be used to write "&" - # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # - # Note that currently minimessage would disable hex code when adding color - allow_color_code: true - allow_hexadecimal_color: false - allow_minimessage: true - - remove: - # If removing lore using book & quil is enabled - enabled: false - # Cost used every time - fixed_cost: 1 - # Cost used for every lore line removed - per_line_cost: 0 - # Use left item vanilla cost penalty if any - shared_increase: false - # Increase shared left item cost penalty - shared_additive: false - # If removing the lore consume the book & quil - do_consume: false - # Cost of replacing colors - remove_color_cost: 0 - # Allowed some color and tags to be reverted to plain text - # Custom anvil will prioritise format that result is a smaller resulting text - # Note that not allowing certain format will lead to some lost of color or tags. - # If configuration are exact as append appending this book should result in the exact same color - # - # Color code will be prefixed by "&" and hexadecimal color by "#". - # If color code is allowed, "&" in the text will get converted to "&&" - # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - allow_color_code: true - allow_hexadecimal_color: false - allow_minimessage: true - - paper: - # Permission is ca.lore_edit.paper - use_permission: true - # what order should the lines should get added/removed (start/end, if invalid or not present will be end) - order: end - - append_line: - # If adding lore line using paper is enabled - enabled: false - # Cost used every time - fixed_cost: 1 - # Use left item vanilla cost penalty if any - shared_increase: false - # Increase shared left item cost penalty - shared_additive: false - # If adding the lore line consume the paper - do_consume: false - # Allow using color code and hexadecimal color when editing lore via book & quil - # - # Color code are prefixed by "&" and hexadecimal color by "#" - # Color code will not be applied if it colors nothing. "&&" can be used to write "&" - # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # - # Note that currently minimessage would disable hex code when adding color - allow_color_code: true - allow_hexadecimal_color: false - allow_minimessage: true - color_use_cost: 0 - - remove_line: - # If removing lore line using paper is enabled - enabled: false - # Cost used every time - fixed_cost: 1 - # Use left item vanilla cost penalty if any - shared_increase: false - # Increase shared left item cost penalty - shared_additive: false - # If removing the lore line consume the paper - do_consume: false - # Cost of replacing colors - remove_color_cost: 0 - # Allowed some color and tags to be reverted to plain text - # Custom anvil will prioritise format that result is a smaller resulting text - # Note that not allowing certain format will lead to some lost of color or tags. - # If configuration are exact as append appending this paper should result in the exact same color - # - # Color code will be prefixed by "&" and hexadecimal color by "#". - # If color code is allowed, "&" in the text will get converted to "&&" - # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - allow_color_code: true - allow_hexadecimal_color: false - allow_minimessage: true - -# Allow to replace the xp cost by a monetary cost -# If enabled it will not be bound to the experience level limits -# -# It also requires to enable dialog rename (set "enable_dialog_rename: false" a bit higher) -# If dialog rename permission is enabled and player do not have the permission merge will fall back to vanilla xp cost -# -# If you are using custom craft I recommend using Linear Xp Cost with Exact Linear Xp as normal Xp Cost will act "weird" -# But Linear Xp will act as 1$ time global multiplier. In other word: like you expect -# -# As this feature require dialog rename, it can only be enabled starting with paper 1.21.6 and later -monetary_cost: - enabled: false - # If using vault unlocked this allow to specify what currency should be used for anvil usage - # default being the default currency - currency: default - # multiply the anvil cost by a value to allow to have price a big bigger than like 40 - multipliers: - # global multipliers. all usage type will be multiplied by this value - global: 1.0 - # usage specific type. it will only apply for specific xp "reason" - enchantment: 1.0 # related to enchantments level - repair: 1.0 # for repairing via unit repair (per unit) - rename: 1.0 # for renaming the item - lore_edit: 1.0 # for changing the lore of the item (only if lore edit is enabled) - work_penalty: 1.0 # for work penalty (aka use penalty) - recipe: 1.0 # for custom anvil recipe cost - -# Whether to show debug logging -debug_log: false - -# Whether to show verbose debug logging -debug_log_verbose: false - -configVersion: 1.11.0 diff --git a/defaultconfigs/1.18/custom_recipes.yml b/defaultconfigs/1.18/custom_recipes.yml deleted file mode 100644 index 57c2220..0000000 --- a/defaultconfigs/1.18/custom_recipes.yml +++ /dev/null @@ -1,5 +0,0 @@ -# ---------------------------------------------------- -# This config file is to store custom craft -# It is recommended to use the in game config editor for this configuration. -# /customanvilconfig With ca.config.edit permission -# ---------------------------------------------------- diff --git a/defaultconfigs/1.18/enchant_conflict.yml b/defaultconfigs/1.18/enchant_conflict.yml deleted file mode 100644 index 45d62c3..0000000 --- a/defaultconfigs/1.18/enchant_conflict.yml +++ /dev/null @@ -1,247 +0,0 @@ -# -# It is recommended that you use /configanvil to edit theses config. -# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! -# - -# material conflicts -# -# If you want to edit this file: -# - A conflict will apply to every item except if in one of the notAffectedGroups group -# - the conflict will count only if the user try to combine at least as -# many conflicting enchantment as "maxEnchantmentBeforeConflict" -# -# -# ---------------------------------------------------- -# These restriction are about not allowing enchantment -# on illegal items -# ---------------------------------------------------- - -restriction_aqua_affinity: - enchantments: [ minecraft:aqua_affinity ] - notAffectedGroups: [ enchanted_book, helmets ] - -restriction_bane_of_arthropods: - enchantments: [ minecraft:bane_of_arthropods ] - notAffectedGroups: [ enchanted_book, melee_weapons ] - -restriction_blast_protection: - enchantments: [ minecraft:blast_protection ] - notAffectedGroups: [ enchanted_book, armors ] - -restriction_channeling: - enchantments: [ minecraft:channeling ] - notAffectedGroups: [ enchanted_book, trident ] - -restriction_binding_curse: - enchantments: [ minecraft:binding_curse ] - notAffectedGroups: [ enchanted_book, wearable ] - -restriction_vanishing_curse: - enchantments: [ minecraft:vanishing_curse ] - notAffectedGroups: [ enchanted_book, can_vanish ] - -restriction_depth_strider: - enchantments: [ minecraft:depth_strider ] - notAffectedGroups: [ enchanted_book, boots ] - -restriction_efficiency: - enchantments: [ minecraft:efficiency ] - notAffectedGroups: [ enchanted_book, tools, shears ] - -restriction_feather_falling: - enchantments: [ minecraft:feather_falling ] - notAffectedGroups: [ enchanted_book, boots ] - -restriction_fire_aspect: - enchantments: [ minecraft:fire_aspect ] - notAffectedGroups: [ enchanted_book, swords ] - -restriction_fire_protection: - enchantments: [ minecraft:fire_protection ] - notAffectedGroups: [ enchanted_book, armors ] - -restriction_flame: - enchantments: [ minecraft:flame ] - notAffectedGroups: [ enchanted_book, bow ] - -restriction_fortune: - enchantments: [ minecraft:fortune ] - notAffectedGroups: [ enchanted_book, tools ] - -restriction_frost_walker: - enchantments: [ minecraft:frost_walker ] - notAffectedGroups: [ enchanted_book, boots ] - -restriction_impaling: - enchantments: [ minecraft:impaling ] - notAffectedGroups: [ enchanted_book, trident ] - -restriction_infinity: - enchantments: [ minecraft:infinity ] - notAffectedGroups: [ enchanted_book, bow ] - -restriction_knockback: - enchantments: [ minecraft:knockback ] - notAffectedGroups: [ enchanted_book, swords ] - -restriction_looting: - enchantments: [ minecraft:looting ] - notAffectedGroups: [ enchanted_book, swords ] - -restriction_loyalty: - enchantments: [ minecraft:loyalty ] - notAffectedGroups: [ enchanted_book, trident ] - -restriction_luck_of_the_sea: - enchantments: [ minecraft:luck_of_the_sea ] - notAffectedGroups: [ enchanted_book, fishing_rod ] - -restriction_lure: - enchantments: [ minecraft:lure ] - notAffectedGroups: [ enchanted_book, fishing_rod ] - -restriction_mending: - enchantments: [ minecraft:mending ] - notAffectedGroups: [ enchanted_book, can_unbreak ] - -restriction_minecraft_multishot: - enchantments: [ minecraft:multishot ] - notAffectedGroups: [ enchanted_book, crossbow ] - -restriction_piercing: - enchantments: [ minecraft:piercing ] - notAffectedGroups: [ enchanted_book, crossbow ] - -restriction_power: - enchantments: [ minecraft:power ] - notAffectedGroups: [ enchanted_book, bow ] - -restriction_projectile_protection: - enchantments: [ minecraft:projectile_protection ] - notAffectedGroups: [ enchanted_book, armors ] - -restriction_protection: - enchantments: [ minecraft:protection ] - notAffectedGroups: [ enchanted_book, armors ] - -restriction_punch: - enchantments: [ minecraft:punch ] - notAffectedGroups: [ enchanted_book, bow ] - -restriction_quick_charge: - enchantments: [ minecraft:quick_charge ] - notAffectedGroups: [ enchanted_book, crossbow ] - -restriction_respiration: - enchantments: [ minecraft:respiration ] - notAffectedGroups: [ enchanted_book, helmets ] - -restriction_riptide: - enchantments: [ minecraft:riptide ] - notAffectedGroups: [ enchanted_book, trident ] - -restriction_sharpness: - enchantments: [ minecraft:sharpness ] - notAffectedGroups: [ enchanted_book, melee_weapons ] - -restriction__silk_touch: - enchantments: [ minecraft:silk_touch ] - notAffectedGroups: [ enchanted_book, tools ] - -restriction_smite: - enchantments: [ minecraft:smite ] - notAffectedGroups: [ enchanted_book, melee_weapons ] - -restriction_soul_speed: - enchantments: [ minecraft:soul_speed ] - notAffectedGroups: [ enchanted_book, boots ] - -restriction_sweeping_edge: - enchantments: [ minecraft:sweeping, minecraft:sweeping_edge ] - notAffectedGroups: [ enchanted_book, swords ] - -# Do not exist in 1.18, that mean useInFuture will be set to true -# useInFuture set to true also mean it will not warn if there is an issue -restriction_swift_sneak: - useInFuture: true - enchantments: [ minecraft:swift_sneak ] - notAffectedGroups: [ enchanted_book, leggings ] - -restriction_thorns: - enchantments: [ minecraft:thorns ] - notAffectedGroups: [ enchanted_book, armors ] - -restriction__unbreaking: - enchantments: [ minecraft:unbreaking ] - notAffectedGroups: [ enchanted_book, can_unbreak ] - -# ---------------------------------------------------- -# Now we have conflicts about enchantment Incompatibility -# We just filtered what item enchantments can be applied -# notAffectedGroups is empty as we don't want anything to not respect theses rules -# maxEnchantmentBeforeConflict is set to 1 to only have 1 on those enchantment available -# ---------------------------------------------------- - -sword_enchant_conflict: - enchantments: - - minecraft:bane_of_arthropods - - minecraft:smite - - minecraft:sharpness - notAffectedGroups: [ ] - maxEnchantmentBeforeConflict: 1 - -protection_enchant_conflict: - enchantments: - - minecraft:blast_protection - - minecraft:fire_protection - - minecraft:projectile_protection - - minecraft:protection - notAffectedGroups: [ ] - maxEnchantmentBeforeConflict: 1 - -trident_conflict1: - enchantments: - - minecraft:channeling - - minecraft:riptide - notAffectedGroups: [ ] - maxEnchantmentBeforeConflict: 1 - -trident_conflict2: - enchantments: - - minecraft:loyalty - - minecraft:riptide - notAffectedGroups: [ ] - maxEnchantmentBeforeConflict: 1 - -boot_conflict: - enchantments: - - minecraft:depth_strider - - minecraft:frost_walker - notAffectedGroups: [ ] - maxEnchantmentBeforeConflict: 1 - -tool_conflict: - enchantments: - - minecraft:fortune - - minecraft:silk_touch - notAffectedGroups: [ ] - maxEnchantmentBeforeConflict: 1 - -bow_conflict: - enchantments: - - minecraft:mending - - minecraft:infinity - notAffectedGroups: [ ] - maxEnchantmentBeforeConflict: 1 - -crossbow_conflict: - enchantments: - - minecraft:multishot - - minecraft:piercing - notAffectedGroups: [ ] - maxEnchantmentBeforeConflict: 1 - -# ---------------------------------------------------- -# Bellow is for custom conflicts. -# This is also where conflict create from the gui will be placed. -# ---------------------------------------------------- diff --git a/defaultconfigs/1.18/item_groups.yml b/defaultconfigs/1.18/item_groups.yml deleted file mode 100644 index 3c1eb5d..0000000 --- a/defaultconfigs/1.18/item_groups.yml +++ /dev/null @@ -1,210 +0,0 @@ -# -# It is recommended that you use /configanvil to edit theses config. -# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! -# - -# Please note this config use spigot material names. -# It should match minecraft name in most case, maybe every case, but I can't be sure -# In case there an issue with material name, you can found them here: -# https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html - -# An empty Exclude group exclude nothing, so it contain everything -everything: - type: exclude - -# An empty include group will include nothing -nothing: - type: include - -# This group is an example of a group including only stone and polished granite -example_include: - type: include - items: - - stone - - polished_granite - -# This group contain everything except polished granite and elements of example_include -example_exclude: - type: exclude - items: - - polished_granite - groups: - - example_include - -# Default configuration should be vanilla enchantment conflict group -# there may have error, if you find one you can fix it ! -# https://minecraft.fandom.com/wiki/Enchanting - -swords: - type: include - items: - - wooden_sword - - stone_sword - - iron_sword - - diamond_sword - - golden_sword - - netherite_sword - -axes: - type: include - items: - - wooden_axe - - stone_axe - - iron_axe - - diamond_axe - - golden_axe - - netherite_axe - -melee_weapons: - type: include - groups: - - swords - - axes - -helmets: - type: include - items: - - leather_helmet - - chainmail_helmet - - iron_helmet - - diamond_helmet - - golden_helmet - - netherite_helmet - - turtle_helmet - -chestplate: - type: include - items: - - leather_chestplate - - chainmail_chestplate - - iron_chestplate - - diamond_chestplate - - golden_chestplate - - netherite_chestplate - -leggings: - type: include - items: - - leather_leggings - - chainmail_leggings - - iron_leggings - - diamond_leggings - - golden_leggings - - netherite_leggings - -boots: - type: include - items: - - leather_boots - - chainmail_boots - - iron_boots - - diamond_boots - - golden_boots - - netherite_boots - -armors: - type: include - groups: - - helmets - - chestplate - - leggings - - boots - -wearable: - type: include - items: - - elytra - - carved_pumpkin - - skeleton_skull - - wither_skeleton_skull - - zombie_head - - player_head - - creeper_head - - dragon_head - # do not exist in 1.18 but exist in future update - - piglin_head - groups: - - armors - -tools: - type: include - items: - - wooden_pickaxe - - stone_pickaxe - - iron_pickaxe - - diamond_pickaxe - - golden_pickaxe - - netherite_pickaxe - - wooden_shovel - - stone_shovel - - iron_shovel - - diamond_shovel - - golden_shovel - - netherite_shovel - - wooden_hoe - - stone_hoe - - iron_hoe - - diamond_hoe - - golden_hoe - - netherite_hoe - groups: - - axes - -enchanted_book: - type: include - items: - - enchanted_book - -trident: - type: include - items: - - trident - -bow: - type: include - items: - - bow - -crossbow: - type: include - items: - - crossbow - -fishing_rod: - type: include - items: - - fishing_rod - -shears: - type: include - items: - - shears - -can_unbreak: - type: include - items: - - elytra - - flint_and_steel - - shield - - carrot_on_a_stick - - warped_fungus_on_a_stick - # do not exist in 1.18 but exist in future update - - brush - groups: - - melee_weapons - - tools - - armors - - trident - - bow - - crossbow - - fishing_rod - - shears - -can_vanish: - type: include - items: - - compass - groups: - - wearable - - can_unbreak - diff --git a/defaultconfigs/1.18/unit_repair_item.yml b/defaultconfigs/1.18/unit_repair_item.yml deleted file mode 100644 index 2902cce..0000000 --- a/defaultconfigs/1.18/unit_repair_item.yml +++ /dev/null @@ -1,190 +0,0 @@ -# -# It is recommended that you use /configanvil to edit theses config. -# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! -# - -# Unit repair configuration -# -# This configuration is to make custom unit repair -# A unit repair is, for example, a diamond to repair a diamond sword -# In vanilla, a unit repair 25% of object durability -# you can make a custom value here -# -# Item name should NOT combine caps and no caps (example: Stone) - -# Default value if the config is an invalid value (value <= 0 ) -# If value > 1 it will be treated as being = 1 -default_repair_amount: 0.25 - -# You can add custom unit repair -# The example bellow make a shield repaired by 10% by sticks - -#stick: -# shield: 0.10 - - -# Vanilla unit repair group is bellow -diamond: - diamond_helmet: 0.25 - diamond_chestplate: 0.25 - diamond_leggings: 0.25 - diamond_boots: 0.25 - diamond_sword: 0.25 - diamond_pickaxe: 0.25 - diamond_axe: 0.25 - diamond_shovel: 0.25 - diamond_hoe: 0.25 - -netherite_ingot: - netherite_helmet: 0.25 - netherite_chestplate: 0.25 - netherite_leggings: 0.25 - netherite_boots: 0.25 - netherite_sword: 0.25 - netherite_pickaxe: 0.25 - netherite_axe: 0.25 - netherite_shovel: 0.25 - netherite_hoe: 0.25 - -gold_ingot: - golden_helmet: 0.25 - golden_chestplate: 0.25 - golden_leggings: 0.25 - golden_boots: 0.25 - golden_sword: 0.25 - golden_pickaxe: 0.25 - golden_axe: 0.25 - golden_shovel: 0.25 - golden_hoe: 0.25 - -iron_ingot: - iron_helmet: 0.25 - iron_chestplate: 0.25 - iron_leggings: 0.25 - iron_boots: 0.25 - iron_sword: 0.25 - iron_pickaxe: 0.25 - iron_axe: 0.25 - iron_shovel: 0.25 - iron_hoe: 0.25 - -cobblestone: - stone_sword: 0.25 - stone_pickaxe: 0.25 - stone_axe: 0.25 - stone_shovel: 0.25 - stone_hoe: 0.25 - -cobbled_deepslate: - stone_sword: 0.25 - stone_pickaxe: 0.25 - stone_axe: 0.25 - stone_shovel: 0.25 - stone_hoe: 0.25 - -blackstone: - stone_sword: 0.25 - stone_pickaxe: 0.25 - stone_axe: 0.25 - stone_shovel: 0.25 - stone_hoe: 0.25 - -leather: - leather_helmet: 0.25 - leather_chestplate: 0.25 - leather_leggings: 0.25 - leather_boots: 0.25 - -phantom_membrane: - elytra: 0.25 - -scute: - turtle_helmet: 0.25 - -oak_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -spruce_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -birch_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -jungle_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -acacia_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -dark_oak_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -mangrove_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -cherry_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -bamboo_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -crimson_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -warped_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 diff --git a/defaultconfigs/1.21.11/README.md b/defaultconfigs/1.21.11/README.md deleted file mode 100644 index a33a09b..0000000 --- a/defaultconfigs/1.21.11/README.md +++ /dev/null @@ -1,6 +0,0 @@ -### Default Plugin's Configurations For 1.21.11 -- [config.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.11/config.yml) -- [enchant_conflict.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.11/enchant_conflict.yml) -- [item_groups.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.11/item_groups.yml) -- [unit_repair_item.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.11/unit_repair_item.yml) -- [custom_recipes.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.11/custom_recipes.yml) diff --git a/defaultconfigs/1.21.11/config.yml b/defaultconfigs/1.21.11/config.yml deleted file mode 100644 index 44885b7..0000000 --- a/defaultconfigs/1.21.11/config.yml +++ /dev/null @@ -1,487 +0,0 @@ -# -# It is recommended that you use /configanvil to edit theses config. -# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! -# - -# What service of metric should custom anvil use -# Custom anvil collect generic information like server minecraft version, type, etc... -# It can also collect error information if error is happening (currently faststats only) -# It can also be disabled -# Please refer to README for public metric link -# Possible options: auto, bstat, faststats, disabled (auto by default) -metric_type: auto - -# Allow to report errors made caused by this plugin (only for faststats) -# This allows me to fix potentials issue that I'm not aware of -# Accept true or false (true by default) -metric_collect_errors: true - -# All anvil cost will be capped to limit_repair_value if enabled. -# -# In other words: -# For any anvil cost greater than limit_repair_value, Cost will be set to limit_repair_value. -limit_repair_cost: false - -# Max cost value the Anvil can get to. -# -# Valid values include 0 to 1000. -# Cost will be displayed as "Too Expensive": -# - If Cost is above 39 -# - And replace_too_expensive is disabled (false) -limit_repair_value: 39 - -# Whether the anvil's cost limit should be removed entirely. -# -# The anvil will still visually display "Too Expensive" if "replace_too_expensive" is disabled -# However, the action will be completable if xp requirement is meet. -remove_repair_limit: false - -# Whenever anvil cost is above 39 should display the true price and not "Too Expensive". -# -# However, when bypassing "Too Expensive", anvil price will be displayed as Green. -# If the action is not completable, the cost will still be displayed as "Too expensive". -# That mean you also need to change other settings like remove_repair_limit or limit_repair_cost. -# -# Require ProtocoLib. -replace_too_expensive: false - -# XP Level amount added to the anvil when the item is repaired by another item of the same type -# -# Valid values include 0 to 1000 -item_repair_cost: 2 - -# XP Level amount added to the anvil when the item is renamed -# -# Valid values include 0 to 1000 -item_rename_cost: 1 - -# XP Level amount added to the anvil when the item is repaired by an "unit" -# For example: a Diamond on a Diamond Sword -# What's considered unit for what can be edited on the unit repair configuration. -# -# Valid values include 0 to 1000 -unit_repair_cost: 1 - -# XP Level amount added to the anvil when a sacrifice enchantment -# conflict with one of the left item enchantment -# -# Valid values include 0 to 1000 -sacrifice_illegal_enchant_cost: 1 - -# Allow using color code and hexadecimal color. -# -# Color code are prefixed by "&" and hexadecimal color by "#". -# Color code will not be applied if it colors nothing. "&&" can be used to write "&". -# For minimessage search for minimessage formating https://docs.papermc.io/adventure/minimessage/format/ -# Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin -# but any global tag will be allowed later when v2 release -allow_color_code: false -allow_hexadecimal_color: false -allow_minimessage: false - -# This enables restricting color code for player having specific permission -# It requires allow_color_code enabled for... obvious reasons -# -# For example: if player want to use "&aHello" it will be required that the player has -# the permission "ca.color.code.a" as he used the color code "a" -# In general permission to give to the player is "ca.color.code.[code]" -# where [code] is the color code you wish to allow the player -# -# It is kinda of useless when minimessage is supported as players would be able to bypass -# that using the equivalent minimessage tag -per_color_code_permission: false - -# Toggle if color should only be applicable if the player a certain permission. -# -# permission are "ca.color.code" for use of color code and "ca.color.hex" for use of hexadecimal color. -permission_needed_for_color: true - -# Xp cost if the player use color in the items name on rename. -# -# Valid values include 0 to 1000. -use_of_color_cost: 0 - -# Dialogue rename menu make use of dialog menu to allow bigger rename -# You can also change the maximum size and set it to -1 or less for maximum -# -# This feature only work on paper 1.21.7 or later -# -# At the moment only english is available for this menu... sorry ! -# -# CustomAnvil use "ca.rename.dialog" when permission -enable_dialog_rename: false -dialog_rename_max_size: 256 -permission_needed_for_dialog_rename: false - -# This allows custom anvil to not "guess" the text used for rename but store it in the item -# It will make item stackable only and only if it had used the same rename text -# -# For practical reason. this only work when dialog rename is enabled -dialog_rename_keep_user_text: true - -# Override limits for specific enchants -# -# Enchantments not listed here will use the value of default_limit -# -# Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels -# -# Valid range of 0 - 255 for each enchantment -# -1 mean keep default -enchant_limits: - minecraft:aqua_affinity: 1 - minecraft:binding_curse: 1 - minecraft:channeling: 1 - minecraft:flame: 1 - minecraft:infinity: 1 - minecraft:mending: 1 - minecraft:multishot: 1 - minecraft:silk_touch: 1 - minecraft:vanishing_curse: 1 - minecraft:depth_strider: 3 # anything more than 3 is treated as 3 by the game - minecraft:protection: 4 - minecraft:fire_protection: 4 - minecraft:blast_protection: 4 - minecraft:projectile_protection: 4 - minecraft:feather_falling: 4 - minecraft:thorns: 3 - minecraft:respiration: 3 - minecraft:sharpness: 5 - minecraft:smite: 5 - minecraft:bane_of_arthropods: 5 - minecraft:knockback: 2 - minecraft:fire_aspect: 2 - minecraft:looting: 3 - minecraft:sweeping: 3 - minecraft:sweeping_edge: 3 - minecraft:efficiency: 5 - minecraft:unbreaking: 3 - minecraft:fortune: 3 - minecraft:power: 5 - minecraft:punch: 2 - minecraft:luck_of_the_sea: 3 - minecraft:lure: 3 - minecraft:frost_walker: 2 - minecraft:impaling: 5 - minecraft:riptide: 3 - minecraft:loyalty: 3 - minecraft:piercing: 4 - minecraft:quick_charge: 3 - minecraft:soul_speed: 3 - minecraft:swift_sneak: 3 - minecraft:density: 5 - minecraft:breach: 4 - minecraft:wind_burst: 3 - minecraft:lunge: 3 - -# Multipliers used to calculate the enchantment's value in repair/combining -# -# Values here are pulled from the fandom wiki: -# https://minecraft.fandom.com/wiki/Anvil_mechanics#Costs_for_combining_enchantments -# -# If an enchantment is missing values here, or is less than 0, it will default to 0 -# -# Calculated as: [Enchantment lvl] * [multiplier] -# -# With default values protection 4 would have a value of 4 when -# coming from either a book (4 * 1) or an item (4 * 1) -enchant_values: - minecraft:aqua_affinity: - item: 4 - book: 2 - minecraft:bane_of_arthropods: - item: 2 - book: 1 - minecraft:binding_curse: - item: 8 - book: 4 - minecraft:blast_protection: - item: 4 - book: 2 - minecraft:channeling: - item: 8 - book: 4 - minecraft:depth_strider: - item: 4 - book: 2 - minecraft:efficiency: - item: 1 - book: 1 - minecraft:flame: - item: 4 - book: 2 - minecraft:feather_falling: - item: 2 - book: 1 - minecraft:fire_aspect: - item: 4 - book: 2 - minecraft:fire_protection: - item: 2 - book: 1 - minecraft:fortune: - item: 4 - book: 2 - minecraft:frost_walker: - item: 4 - book: 2 - minecraft:impaling: - item: 4 - book: 2 - minecraft:infinity: - item: 8 - book: 4 - minecraft:knockback: - item: 2 - book: 1 - minecraft:looting: - item: 4 - book: 2 - minecraft:loyalty: - item: 1 - book: 1 - minecraft:luck_of_the_sea: - item: 4 - book: 2 - minecraft:lure: - item: 4 - book: 2 - minecraft:mending: - item: 4 - book: 2 - minecraft:multishot: - item: 4 - book: 2 - minecraft:piercing: - item: 1 - book: 1 - minecraft:power: - item: 1 - book: 1 - minecraft:projectile_protection: - item: 2 - book: 1 - minecraft:protection: - item: 1 - book: 1 - minecraft:punch: - item: 4 - book: 2 - minecraft:quick_charge: - item: 2 - book: 1 - minecraft:respiration: - item: 4 - book: 2 - minecraft:riptide: - item: 4 - book: 2 - minecraft:silk_touch: - item: 8 - book: 4 - minecraft:sharpness: - item: 1 - book: 1 - minecraft:smite: - item: 2 - book: 1 - minecraft:soul_speed: - item: 8 - book: 4 - minecraft:swift_sneak: - item: 8 - book: 4 - minecraft:sweeping: - item: 4 - book: 2 - minecraft:sweeping_edge: - item: 4 - book: 2 - minecraft:thorns: - item: 8 - book: 4 - minecraft:unbreaking: - item: 2 - book: 1 - minecraft:vanishing_curse: - item: 8 - book: 4 - minecraft:density: - item: 2 - book: 1 - minecraft:breach: - item: 4 - book: 2 - minecraft:wind_burst: - item: 4 - book: 2 - minecraft:lunge: - item: 2 - book: 1 - -# Disable enchantment merging for level above the set value -# Enchantment merging is when, for example, 2 unbreaking II book combine to give sharpness III -# But Enchantment above this value can still be applied. following the previous example, we could still apply a unbreaking III book to a sword -# Even if disable-merge-over of unbreaking is set to 2 -# -1 mean enchantment merge for this enchantment is not disabled. default to -1 if absent. -disable-merge-over: - # Sharpness is set to -1. it equivalent to it not being set to anything (and work as vanilla on default configuration) - minecraft:sharpness: -1 -# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied -# minecraft:unbreaking: 2 - -# The maximum number of enchantment an item can get. -1 for infinity -# Use eco enchant enchant_limit if present by default unless "default" is not equal to -1 -enchantment_count_limit: - default: -1 - # Limit for specific items. example bellow is an example with stick - # Per item enchantment limit override eco enchant enchant_limit and default limit - items: - stick: -1 - -# Settings for lore modification -lore_edit: - book_and_quil: - # Permission is ca.lore_edit.book - use_permission: true - append: - # If adding lore using book & quil is enabled - enabled: false - # Cost used every time - fixed_cost: 1 - # Cost used for every lore line added - per_line_cost: 0 - # Use left item vanilla cost penalty if any - shared_increase: false - # Increase shared left item cost penalty - shared_additive: false - # If adding the lore consume the book & quil - do_consume: false - # Allow using color code and hexadecimal color when editing lore via book & quil - # - # Color code are prefixed by "&" and hexadecimal color by "#" - # Color code will not be applied if it colors nothing. "&&" can be used to write "&" - # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # - # Note that currently minimessage would disable hex code when adding color - allow_color_code: true - allow_hexadecimal_color: false - allow_minimessage: true - use_cost: 0 - - remove: - # If removing lore using book & quil is enabled - enabled: false - # Cost used every time - fixed_cost: 1 - # Cost used for every lore line removed - per_line_cost: 0 - # Use left item vanilla cost penalty if any - shared_increase: false - # Increase shared left item cost penalty - shared_additive: false - # If removing the lore consume the book & quil - do_consume: false - # Cost of replacing colors - remove_color_cost: 0 - # Allowed some color and tags to be reverted to plain text - # Custom anvil will prioritise format that result is a smaller resulting text - # Note that not allowing certain format will lead to some lost of color or tags. - # If configuration are exact as append appending this book should result in the exact same color - # - # Color code will be prefixed by "&" and hexadecimal color by "#". - # If color code is allowed, "&" in the text will get converted to "&&" - # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - allow_color_code: true - allow_hexadecimal_color: false - allow_minimessage: true - - paper: - # Permission is ca.lore_edit.paper - use_permission: true - # what order should the lines should get added/removed (start/end, if invalid or not present will be end) - order: end - - append_line: - # If adding lore line using paper is enabled - enabled: false - # Cost used every time - fixed_cost: 1 - # Use left item vanilla cost penalty if any - shared_increase: false - # Increase shared left item cost penalty - shared_additive: false - # If adding the lore line consume the paper - do_consume: false - # Allow using color code and hexadecimal color when editing lore via book & quil - # - # Color code are prefixed by "&" and hexadecimal color by "#" - # Color code will not be applied if it colors nothing. "&&" can be used to write "&" - # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # - # Note that currently minimessage would disable hex code when adding color - allow_color_code: true - allow_hexadecimal_color: false - allow_minimessage: true - color_use_cost: 0 - use_cost: 0 - - remove_line: - # If removing lore line using paper is enabled - enabled: false - # Cost used every time - fixed_cost: 1 - # Use left item vanilla cost penalty if any - shared_increase: false - # Increase shared left item cost penalty - shared_additive: false - # If removing the lore line consume the paper - do_consume: false - # Cost of replacing colors - remove_color_cost: 0 - # Allowed some color and tags to be reverted to plain text - # Custom anvil will prioritise format that result is a smaller resulting text - # Note that not allowing certain format will lead to some lost of color or tags. - # If configuration are exact as append appending this paper should result in the exact same color - # - # Color code will be prefixed by "&" and hexadecimal color by "#". - # If color code is allowed, "&" in the text will get converted to "&&" - # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - allow_color_code: true - allow_hexadecimal_color: false - allow_minimessage: true - -# Allow to replace the xp cost by a monetary cost -# If enabled it will not be bound to the experience level limits -# -# It also requires to enable dialog rename (set "enable_dialog_rename: false" a bit higher) -# If dialog rename permission is enabled and player do not have the permission merge will fall back to vanilla xp cost -# -# If you are using custom craft I recommend using Linear Xp Cost with Exact Linear Xp as normal Xp Cost will act "weird" -# But Linear Xp will act as 1$ time global multiplier. In other word: like you expect -# -# As this feature require dialog rename, it can only be enabled starting with paper 1.21.6 and later -monetary_cost: - enabled: false - # If using vault unlocked this allow to specify what currency should be used for anvil usage - # default being the default currency - currency: default - # multiply the anvil cost by a value to allow to have price a big bigger than like 40 - multipliers: - # global multipliers. all usage type will be multiplied by this value - global: 1.0 - # usage specific type. it will only apply for specific xp "reason" - enchantment: 1.0 # related to enchantments level - repair: 1.0 # for repairing via unit repair (per unit) - rename: 1.0 # for renaming the item - lore_edit: 1.0 # for changing the lore of the item (only if lore edit is enabled) - work_penalty: 1.0 # for work penalty (aka use penalty) - recipe: 1.0 # for custom anvil recipe cost - -# Whether to show debug logging -debug_log: false - -# Whether to show verbose debug logging -debug_log_verbose: false - -configVersion: 1.15.5 -lowMinecraftVersion: 1.21.11 diff --git a/defaultconfigs/1.21.11/custom_recipes.yml b/defaultconfigs/1.21.11/custom_recipes.yml deleted file mode 100644 index 57c2220..0000000 --- a/defaultconfigs/1.21.11/custom_recipes.yml +++ /dev/null @@ -1,5 +0,0 @@ -# ---------------------------------------------------- -# This config file is to store custom craft -# It is recommended to use the in game config editor for this configuration. -# /customanvilconfig With ca.config.edit permission -# ---------------------------------------------------- diff --git a/defaultconfigs/1.21.11/enchant_conflict.yml b/defaultconfigs/1.21.11/enchant_conflict.yml deleted file mode 100644 index 3d62dae..0000000 --- a/defaultconfigs/1.21.11/enchant_conflict.yml +++ /dev/null @@ -1,398 +0,0 @@ -# -# It is recommended that you use /configanvil to edit theses config. -# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! -# - -# material conflicts -# -# If you want to edit this file: -# - A conflict will apply to every item except if in one of the notAffectedGroups group -# - the conflict will count only if the user try to combine at least as -# many conflicting enchantment as "maxEnchantmentBeforeConflict" -# -# -# ---------------------------------------------------- -# These restriction are about not allowing enchantment -# on illegal items -# ---------------------------------------------------- - -restriction_aqua_affinity: - enchantments: - - minecraft:aqua_affinity - notAffectedGroups: - - enchanted_book - - helmets - -restriction_bane_of_arthropods: - enchantments: - - minecraft:bane_of_arthropods - notAffectedGroups: - - enchanted_book - - melee_weapons - - mace - -restriction_blast_protection: - enchantments: - - minecraft:blast_protection - notAffectedGroups: - - enchanted_book - - armors - -restriction_channeling: - enchantments: - - minecraft:channeling - notAffectedGroups: - - enchanted_book - - trident - -restriction_binding_curse: - enchantments: - - minecraft:binding_curse - notAffectedGroups: - - enchanted_book - - wearable - -restriction_vanishing_curse: - enchantments: - - minecraft:vanishing_curse - notAffectedGroups: - - enchanted_book - - can_vanish - -restriction_depth_strider: - enchantments: - - minecraft:depth_strider - notAffectedGroups: - - enchanted_book - - boots - -restriction_efficiency: - enchantments: - - minecraft:efficiency - notAffectedGroups: - - enchanted_book - - tools - - shears - -restriction_feather_falling: - enchantments: - - minecraft:feather_falling - notAffectedGroups: - - enchanted_book - - boots - -restriction_fire_aspect: - enchantments: - - minecraft:fire_aspect - notAffectedGroups: - - enchanted_book - - swords - - mace - - spears - -restriction_fire_protection: - enchantments: - - minecraft:fire_protection - notAffectedGroups: - - enchanted_book - - armors - -restriction_flame: - enchantments: - - minecraft:flame - notAffectedGroups: - - enchanted_book - - bow - -restriction_fortune: - enchantments: - - minecraft:fortune - notAffectedGroups: - - enchanted_book - - tools - -restriction_frost_walker: - enchantments: - - minecraft:frost_walker - notAffectedGroups: - - enchanted_book - - boots - -restriction_impaling: - enchantments: - - minecraft:impaling - notAffectedGroups: - - enchanted_book - - trident - -restriction_infinity: - enchantments: - - minecraft:infinity - notAffectedGroups: - - enchanted_book - - bow - -restriction_knockback: - enchantments: - - minecraft:knockback - notAffectedGroups: - - enchanted_book - - swords - - spears - -restriction_looting: - enchantments: - - minecraft:looting - notAffectedGroups: - - enchanted_book - - swords - - spears - -restriction_loyalty: - enchantments: - - minecraft:loyalty - notAffectedGroups: - - enchanted_book - - trident - -restriction_luck_of_the_sea: - enchantments: - - minecraft:luck_of_the_sea - notAffectedGroups: - - enchanted_book - - fishing_rod - -restriction_lure: - enchantments: - - minecraft:lure - notAffectedGroups: - - enchanted_book - - fishing_rod - -restriction_mending: - enchantments: - - minecraft:mending - notAffectedGroups: - - enchanted_book - - can_unbreak - -restriction_minecraft_multishot: - enchantments: - - minecraft:multishot - notAffectedGroups: - - enchanted_book - - crossbow - -restriction_piercing: - enchantments: - - minecraft:piercing - notAffectedGroups: - - enchanted_book - - crossbow - -restriction_power: - enchantments: - - minecraft:power - notAffectedGroups: - - enchanted_book - - bow - -restriction_projectile_protection: - enchantments: - - minecraft:projectile_protection - notAffectedGroups: - - enchanted_book - - armors - -restriction_protection: - enchantments: - - minecraft:protection - notAffectedGroups: - - enchanted_book - - armors - -restriction_punch: - enchantments: - - minecraft:punch - notAffectedGroups: - - enchanted_book - - bow - -restriction_quick_charge: - enchantments: - - minecraft:quick_charge - notAffectedGroups: - - enchanted_book - - crossbow - -restriction_respiration: - enchantments: - - minecraft:respiration - notAffectedGroups: - - enchanted_book - - helmets - -restriction_riptide: - enchantments: - - minecraft:riptide - notAffectedGroups: - - enchanted_book - - trident - -restriction_sharpness: - enchantments: - - minecraft:sharpness - notAffectedGroups: - - enchanted_book - - melee_weapons - -restriction__silk_touch: - enchantments: - - minecraft:silk_touch - notAffectedGroups: - - enchanted_book - - tools - -restriction_smite: - enchantments: - - minecraft:smite - notAffectedGroups: - - enchanted_book - - melee_weapons - - mace - -restriction_soul_speed: - enchantments: - - minecraft:soul_speed - notAffectedGroups: - - enchanted_book - - boots - -restriction_sweeping_edge: - enchantments: - - minecraft:sweeping - - minecraft:sweeping_edge - notAffectedGroups: - - enchanted_book - - swords - -# Do not exist in 1.18, that mean useInFuture will be set to true -# useInFuture set to true also mean it will not warn if there is an issue -restriction_swift_sneak: - useInFuture: true - enchantments: - - minecraft:swift_sneak - notAffectedGroups: - - enchanted_book - - leggings - -restriction_thorns: - enchantments: - - minecraft:thorns - notAffectedGroups: - - enchanted_book - - armors - -restriction__unbreaking: - enchantments: - - minecraft:unbreaking - notAffectedGroups: - - enchanted_book - - can_unbreak - -# ---------------------------------------------------- -# Now we have conflicts about enchantment Incompatibility -# We just filtered what item enchantments can be applied -# notAffectedGroups is empty as we don't want anything to not respect theses rules -# maxEnchantmentBeforeConflict is set to 1 to only have 1 on those enchantment available -# ---------------------------------------------------- - -sword_enchant_conflict: - enchantments: - - minecraft:bane_of_arthropods - - minecraft:smite - - minecraft:sharpness - - minecraft:density - - minecraft:breach - notAffectedGroups: [] - maxEnchantmentBeforeConflict: 1 - -protection_enchant_conflict: - enchantments: - - minecraft:blast_protection - - minecraft:fire_protection - - minecraft:projectile_protection - - minecraft:protection - notAffectedGroups: [] - maxEnchantmentBeforeConflict: 1 - -trident_conflict1: - enchantments: - - minecraft:channeling - - minecraft:riptide - notAffectedGroups: [] - maxEnchantmentBeforeConflict: 1 - -trident_conflict2: - enchantments: - - minecraft:loyalty - - minecraft:riptide - notAffectedGroups: [] - maxEnchantmentBeforeConflict: 1 - -boot_conflict: - enchantments: - - minecraft:depth_strider - - minecraft:frost_walker - notAffectedGroups: [] - maxEnchantmentBeforeConflict: 1 - -tool_conflict: - enchantments: - - minecraft:fortune - - minecraft:silk_touch - notAffectedGroups: [] - maxEnchantmentBeforeConflict: 1 - -bow_conflict: - enchantments: - - minecraft:mending - - minecraft:infinity - notAffectedGroups: [] - maxEnchantmentBeforeConflict: 1 - -crossbow_conflict: - enchantments: - - minecraft:multishot - - minecraft:piercing - notAffectedGroups: [] - maxEnchantmentBeforeConflict: 1 -restriction_density: - enchantments: - - minecraft:density - notAffectedGroups: - - mace - - enchanted_book -restriction_breach: - enchantments: - - minecraft:breach - notAffectedGroups: - - mace - - enchanted_book -restriction_wind_burst: - enchantments: - - minecraft:wind_burst - notAffectedGroups: - - mace - - enchanted_book -restriction_lunge: - enchantments: - - minecraft:lunge - notAffectedGroups: - - spears - - enchanted_book - -# ---------------------------------------------------- -# Bellow is for custom conflicts. -# This is also where conflict create from the gui will be placed. -# ---------------------------------------------------- diff --git a/defaultconfigs/1.21.11/item_groups.yml b/defaultconfigs/1.21.11/item_groups.yml deleted file mode 100644 index 9f2a877..0000000 --- a/defaultconfigs/1.21.11/item_groups.yml +++ /dev/null @@ -1,247 +0,0 @@ -# -# It is recommended that you use /configanvil to edit theses config. -# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! -# - -# Please note this config use spigot material names. -# It should match minecraft name in most case, maybe every case, but I can't be sure -# In case there an issue with material name, you can found them here: -# https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html - -# An empty Exclude group exclude nothing, so it contain everything -everything: - type: exclude - -# An empty include group will include nothing -nothing: - type: include - -# This group is an example of a group including only stone and polished granite -example_include: - type: include - items: - - stone - - polished_granite - -# This group contain everything except polished granite and elements of example_include -example_exclude: - type: exclude - items: - - polished_granite - groups: - - example_include - -# Default configuration should be vanilla enchantment conflict group -# there may have error, if you find one you can fix it ! -# https://minecraft.fandom.com/wiki/Enchanting - -swords: - type: include - items: - - wooden_sword - - stone_sword - - iron_sword - - diamond_sword - - golden_sword - - netherite_sword - - copper_sword - -axes: - type: include - items: - - wooden_axe - - stone_axe - - iron_axe - - diamond_axe - - golden_axe - - netherite_axe - - copper_axe - -melee_weapons: - type: include - groups: - - swords - - axes - - spears - -helmets: - type: include - items: - - leather_helmet - - chainmail_helmet - - iron_helmet - - diamond_helmet - - golden_helmet - - netherite_helmet - - turtle_helmet - - copper_helmet - -chestplate: - type: include - items: - - leather_chestplate - - chainmail_chestplate - - iron_chestplate - - diamond_chestplate - - golden_chestplate - - netherite_chestplate - - copper_chestplate - -leggings: - type: include - items: - - leather_leggings - - chainmail_leggings - - iron_leggings - - diamond_leggings - - golden_leggings - - netherite_leggings - - copper_leggings - -boots: - type: include - items: - - leather_boots - - chainmail_boots - - iron_boots - - diamond_boots - - golden_boots - - netherite_boots - - copper_boots - -armors: - type: include - groups: - - helmets - - chestplate - - leggings - - boots - -wearable: - type: include - items: - - elytra - - carved_pumpkin - - skeleton_skull - - wither_skeleton_skull - - zombie_head - - player_head - - creeper_head - - dragon_head - - piglin_head - groups: - - armors - -pickaxes: - type: include - items: - - wooden_pickaxe - - stone_pickaxe - - iron_pickaxe - - diamond_pickaxe - - golden_pickaxe - - netherite_pickaxe - - copper_pickaxe - -shovels: - type: include - items: - - wooden_shovel - - stone_shovel - - iron_shovel - - diamond_shovel - - golden_shovel - - netherite_shovel - - copper_shovel - -hoes: - type: include - items: - - wooden_hoe - - stone_hoe - - iron_hoe - - diamond_hoe - - golden_hoe - - netherite_hoe - - copper_hoe - -tools: - type: include - groups: - - pickaxes - - shovels - - hoes - - axes - -enchanted_book: - type: include - items: - - enchanted_book - -trident: - type: include - items: - - trident - -bow: - type: include - items: - - bow - -crossbow: - type: include - items: - - crossbow - -fishing_rod: - type: include - items: - - fishing_rod - -shears: - type: include - items: - - shears - -can_unbreak: - type: include - items: - - elytra - - flint_and_steel - - shield - - carrot_on_a_stick - - warped_fungus_on_a_stick - - brush - groups: - - melee_weapons - - tools - - armors - - trident - - bow - - crossbow - - fishing_rod - - shears - - mace - -can_vanish: - type: include - items: - - compass - groups: - - wearable - - can_unbreak -mace: - type: include - items: - - mace -spears: - type: include - items: - - wooden_spear - - golden_spear - - stone_spear - - copper_spear - - iron_spear - - diamond_spear - - netherite_spear - diff --git a/defaultconfigs/1.21.11/unit_repair_item.yml b/defaultconfigs/1.21.11/unit_repair_item.yml deleted file mode 100644 index ed981b1..0000000 --- a/defaultconfigs/1.21.11/unit_repair_item.yml +++ /dev/null @@ -1,220 +0,0 @@ -# -# It is recommended that you use /configanvil to edit theses config. -# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! -# - -# Unit repair configuration -# -# This configuration is to make custom unit repair -# A unit repair is, for example, a diamond to repair a diamond sword -# In vanilla, a unit repair 25% of object durability -# you can make a custom value here -# -# Item name should NOT combine caps and no caps (example: Stone) - -# Default value if the config is an invalid value (value <= 0 ) -# If value > 1 it will be treated as being = 1 -default_repair_amount: 0.25 - -# You can add custom unit repair -# The example bellow make a shield repaired by 10% by sticks - -# stick: -# shield: 0.10 - - -# Vanilla unit repair group is bellow -diamond: - diamond_helmet: 0.25 - diamond_chestplate: 0.25 - diamond_leggings: 0.25 - diamond_boots: 0.25 - diamond_sword: 0.25 - diamond_pickaxe: 0.25 - diamond_axe: 0.25 - diamond_shovel: 0.25 - diamond_hoe: 0.25 - diamond_spear: 0.25 - -netherite_ingot: - netherite_helmet: 0.25 - netherite_chestplate: 0.25 - netherite_leggings: 0.25 - netherite_boots: 0.25 - netherite_sword: 0.25 - netherite_pickaxe: 0.25 - netherite_axe: 0.25 - netherite_shovel: 0.25 - netherite_hoe: 0.25 - netherite_spear: 0.25 - -gold_ingot: - golden_helmet: 0.25 - golden_chestplate: 0.25 - golden_leggings: 0.25 - golden_boots: 0.25 - golden_sword: 0.25 - golden_pickaxe: 0.25 - golden_axe: 0.25 - golden_shovel: 0.25 - golden_hoe: 0.25 - golden_spear: 0.25 - -iron_ingot: - iron_helmet: 0.25 - iron_chestplate: 0.25 - iron_leggings: 0.25 - iron_boots: 0.25 - iron_sword: 0.25 - iron_pickaxe: 0.25 - iron_axe: 0.25 - iron_shovel: 0.25 - iron_hoe: 0.25 - iron_spear: 0.25 - -cobblestone: - stone_sword: 0.25 - stone_pickaxe: 0.25 - stone_axe: 0.25 - stone_shovel: 0.25 - stone_hoe: 0.25 - stone_spear: 0.25 - -cobbled_deepslate: - stone_sword: 0.25 - stone_pickaxe: 0.25 - stone_axe: 0.25 - stone_shovel: 0.25 - stone_hoe: 0.25 - stone_spear: 0.25 - -blackstone: - stone_sword: 0.25 - stone_pickaxe: 0.25 - stone_axe: 0.25 - stone_shovel: 0.25 - stone_hoe: 0.25 - -leather: - leather_helmet: 0.25 - leather_chestplate: 0.25 - leather_leggings: 0.25 - leather_boots: 0.25 - -phantom_membrane: - elytra: 0.25 - -scute: - turtle_helmet: 0.25 - -oak_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - wooden_spear: 0.25 - -spruce_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - wooden_spear: 0.25 - -birch_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - wooden_spear: 0.25 - -jungle_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - wooden_spear: 0.25 - -acacia_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - wooden_spear: 0.25 - -dark_oak_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - wooden_spear: 0.25 - -mangrove_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - wooden_spear: 0.25 - -cherry_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - wooden_spear: 0.25 - -bamboo_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - wooden_spear: 0.25 - -crimson_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - wooden_spear: 0.25 - -warped_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - wooden_spear: 0.25 -breeze_rod: - mace: 0.25 -copper_ingot: - copper_helmet: 0.25 - copper_chestplate: 0.25 - copper_leggings: 0.25 - copper_boots: 0.25 - copper_pickaxe: 0.25 - copper_shovel: 0.25 - copper_hoe: 0.25 - copper_axe: 0.25 - copper_sword: 0.25 - copper_spear: 0.25 diff --git a/defaultconfigs/1.21.9/README.md b/defaultconfigs/1.21.9/README.md deleted file mode 100644 index 2b3bfa8..0000000 --- a/defaultconfigs/1.21.9/README.md +++ /dev/null @@ -1,6 +0,0 @@ -### Default Plugin's Configurations For 1.21.9 -- [config.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.9/config.yml) -- [enchant_conflict.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.9/enchant_conflict.yml) -- [item_groups.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.9/item_groups.yml) -- [unit_repair_item.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.9/unit_repair_item.yml) -- [custom_recipes.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.9/custom_recipes.yml) diff --git a/defaultconfigs/1.21.9/config.yml b/defaultconfigs/1.21.9/config.yml deleted file mode 100644 index 4df5876..0000000 --- a/defaultconfigs/1.21.9/config.yml +++ /dev/null @@ -1,479 +0,0 @@ -# -# It is recommended that you use /configanvil to edit theses config. -# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! -# - -# What service of metric should custom anvil use -# Custom anvil collect generic information like server minecraft version, type, etc... -# It can also collect error information if error is happening (currently faststats only) -# It can also be disabled -# Please refer to README for public metric link -# Possible options: auto, bstat, faststats, disabled (auto by default) -metric_type: auto - -# Allow to report errors made caused by this plugin (only for faststats) -# This allows me to fix potentials issue that I'm not aware of -# Accept true or false (true by default) -metric_collect_errors: true - -# All anvil cost will be capped to limit_repair_value if enabled. -# -# In other words: -# For any anvil cost greater than limit_repair_value, Cost will be set to limit_repair_value. -limit_repair_cost: false - -# Max cost value the Anvil can get to. -# -# Valid values include 0 to 1000. -# Cost will be displayed as "Too Expensive": -# - If Cost is above 39 -# - And replace_too_expensive is disabled (false) -limit_repair_value: 39 - -# Whether the anvil's cost limit should be removed entirely. -# -# The anvil will still visually display "Too Expensive" if "replace_too_expensive" is disabled -# However, the action will be completable if xp requirement is meet. -remove_repair_limit: false - -# Whenever anvil cost is above 39 should display the true price and not "Too Expensive". -# -# However, when bypassing "Too Expensive", anvil price will be displayed as Green. -# If the action is not completable, the cost will still be displayed as "Too expensive". -# That mean you also need to change other settings like remove_repair_limit or limit_repair_cost. -# -# Require ProtocoLib. -replace_too_expensive: false - -# XP Level amount added to the anvil when the item is repaired by another item of the same type -# -# Valid values include 0 to 1000 -item_repair_cost: 2 - -# XP Level amount added to the anvil when the item is renamed -# -# Valid values include 0 to 1000 -item_rename_cost: 1 - -# XP Level amount added to the anvil when the item is repaired by an "unit" -# For example: a Diamond on a Diamond Sword -# What's considered unit for what can be edited on the unit repair configuration. -# -# Valid values include 0 to 1000 -unit_repair_cost: 1 - -# XP Level amount added to the anvil when a sacrifice enchantment -# conflict with one of the left item enchantment -# -# Valid values include 0 to 1000 -sacrifice_illegal_enchant_cost: 1 - -# Allow using color code and hexadecimal color. -# -# Color code are prefixed by "&" and hexadecimal color by "#". -# Color code will not be applied if it colors nothing. "&&" can be used to write "&". -# For minimessage search for minimessage formating https://docs.papermc.io/adventure/minimessage/format/ -allow_color_code: false -allow_hexadecimal_color: false -allow_minimessage: false - -# This enables restricting color code for player having specific permission -# It requires allow_color_code enabled for... obvious reasons -# -# For example: if player want to use "&aHello" it will be required that the player has -# the permission "ca.color.code.a" as he used the color code "a" -# In general permission to give to the player is "ca.color.code.[code]" -# where [code] is the color code you wish to allow the player -# -# It is kinda of useless when minimessage is supported as players would be able to bypass -# that using the equivalent minimessage tag -per_color_code_permission: false - -# Toggle if color should only be applicable if the player a certain permission. -# -# permission are "ca.color.code" for use of color code and "ca.color.hex" for use of hexadecimal color. -permission_needed_for_color: true - -# Xp cost if the player use color in the items name on rename. -# -# Valid values include 0 to 1000. -use_of_color_cost: 0 - -# Dialogue rename menu make use of dialog menu to allow bigger rename -# You can also change the maximum size and set it to -1 or less for maximum -# -# This feature only work on paper 1.21.7 or later -# -# At the moment only english is available for this menu... sorry ! -# -# CustomAnvil use "ca.rename.dialog" when permission -enable_dialog_rename: false -dialog_rename_max_size: 256 -permission_needed_for_dialog_rename: false - -# This allows custom anvil to not "guess" the text used for rename but store it in the item -# It will make item stackable only and only if it had used the same rename text -# -# For practical reason. this only work when dialog rename is enabled -dialog_rename_keep_user_text: true - -# Override limits for specific enchants -# -# Enchantments not listed here will use the value of default_limit -# -# Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels -# -# Valid range of 0 - 255 for each enchantment -# -1 mean keep default -enchant_limits: - minecraft:aqua_affinity: 1 - minecraft:binding_curse: 1 - minecraft:channeling: 1 - minecraft:flame: 1 - minecraft:infinity: 1 - minecraft:mending: 1 - minecraft:multishot: 1 - minecraft:silk_touch: 1 - minecraft:vanishing_curse: 1 - minecraft:depth_strider: 3 # anything more than 3 is treated as 3 by the game - minecraft:protection: 4 - minecraft:fire_protection: 4 - minecraft:blast_protection: 4 - minecraft:projectile_protection: 4 - minecraft:feather_falling: 4 - minecraft:thorns: 3 - minecraft:respiration: 3 - minecraft:sharpness: 5 - minecraft:smite: 5 - minecraft:bane_of_arthropods: 5 - minecraft:knockback: 2 - minecraft:fire_aspect: 2 - minecraft:looting: 3 - minecraft:sweeping: 3 - minecraft:sweeping_edge: 3 - minecraft:efficiency: 5 - minecraft:unbreaking: 3 - minecraft:fortune: 3 - minecraft:power: 5 - minecraft:punch: 2 - minecraft:luck_of_the_sea: 3 - minecraft:lure: 3 - minecraft:frost_walker: 2 - minecraft:impaling: 5 - minecraft:riptide: 3 - minecraft:loyalty: 3 - minecraft:piercing: 4 - minecraft:quick_charge: 3 - minecraft:soul_speed: 3 - minecraft:swift_sneak: 3 - minecraft:density: 5 - minecraft:breach: 4 - minecraft:wind_burst: 3 - -# Multipliers used to calculate the enchantment's value in repair/combining -# -# Values here are pulled from the fandom wiki: -# https://minecraft.fandom.com/wiki/Anvil_mechanics#Costs_for_combining_enchantments -# -# If an enchantment is missing values here, or is less than 0, it will default to 0 -# -# Calculated as: [Enchantment lvl] * [multiplier] -# -# With default values protection 4 would have a value of 4 when -# coming from either a book (4 * 1) or an item (4 * 1) -enchant_values: - minecraft:aqua_affinity: - item: 4 - book: 2 - minecraft:bane_of_arthropods: - item: 2 - book: 1 - minecraft:binding_curse: - item: 8 - book: 4 - minecraft:blast_protection: - item: 4 - book: 2 - minecraft:channeling: - item: 8 - book: 4 - minecraft:depth_strider: - item: 4 - book: 2 - minecraft:efficiency: - item: 1 - book: 1 - minecraft:flame: - item: 4 - book: 2 - minecraft:feather_falling: - item: 2 - book: 1 - minecraft:fire_aspect: - item: 4 - book: 2 - minecraft:fire_protection: - item: 2 - book: 1 - minecraft:fortune: - item: 4 - book: 2 - minecraft:frost_walker: - item: 4 - book: 2 - minecraft:impaling: - item: 4 - book: 2 - minecraft:infinity: - item: 8 - book: 4 - minecraft:knockback: - item: 2 - book: 1 - minecraft:looting: - item: 4 - book: 2 - minecraft:loyalty: - item: 1 - book: 1 - minecraft:luck_of_the_sea: - item: 4 - book: 2 - minecraft:lure: - item: 4 - book: 2 - minecraft:mending: - item: 4 - book: 2 - minecraft:multishot: - item: 4 - book: 2 - minecraft:piercing: - item: 1 - book: 1 - minecraft:power: - item: 1 - book: 1 - minecraft:projectile_protection: - item: 2 - book: 1 - minecraft:protection: - item: 1 - book: 1 - minecraft:punch: - item: 4 - book: 2 - minecraft:quick_charge: - item: 2 - book: 1 - minecraft:respiration: - item: 4 - book: 2 - minecraft:riptide: - item: 4 - book: 2 - minecraft:silk_touch: - item: 8 - book: 4 - minecraft:sharpness: - item: 1 - book: 1 - minecraft:smite: - item: 2 - book: 1 - minecraft:soul_speed: - item: 8 - book: 4 - minecraft:swift_sneak: - item: 8 - book: 4 - minecraft:sweeping: - item: 4 - book: 2 - minecraft:sweeping_edge: - item: 4 - book: 2 - minecraft:thorns: - item: 8 - book: 4 - minecraft:unbreaking: - item: 2 - book: 1 - minecraft:vanishing_curse: - item: 8 - book: 4 - minecraft:density: - item: 2 - book: 1 - minecraft:breach: - item: 4 - book: 2 - minecraft:wind_burst: - item: 4 - book: 2 - -# Disable enchantment merging for level above the set value -# Enchantment merging is when, for example, 2 unbreaking II book combine to give sharpness III -# But Enchantment above this value can still be applied. following the previous example, we could still apply a unbreaking III book to a sword -# Even if disable-merge-over of unbreaking is set to 2 -# -1 mean enchantment merge for this enchantment is not disabled. default to -1 if absent. -disable-merge-over: - # Sharpness is set to -1. it equivalent to it not being set to anything (and work as vanilla on default configuration) - minecraft:sharpness: -1 -# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied -# minecraft:unbreaking: 2 - -# The maximum number of enchantment an item can get. -1 for infinity -# Use eco enchant enchant_limit if present by default unless "default" is not equal to -1 -enchantment_count_limit: - default: -1 - # Limit for specific items. example bellow is an example with stick - # Per item enchantment limit override eco enchant enchant_limit and default limit - items: - stick: -1 - -# Settings for lore modification -lore_edit: - book_and_quil: - # Permission is ca.lore_edit.book - use_permission: true - append: - # If adding lore using book & quil is enabled - enabled: false - # Cost used every time - fixed_cost: 1 - # Cost used for every lore line added - per_line_cost: 0 - # Use left item vanilla cost penalty if any - shared_increase: false - # Increase shared left item cost penalty - shared_additive: false - # If adding the lore consume the book & quil - do_consume: false - # Allow using color code and hexadecimal color when editing lore via book & quil - # - # Color code are prefixed by "&" and hexadecimal color by "#" - # Color code will not be applied if it colors nothing. "&&" can be used to write "&" - # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # - # Note that currently minimessage would disable hex code when adding color - allow_color_code: true - allow_hexadecimal_color: false - allow_minimessage: true - - remove: - # If removing lore using book & quil is enabled - enabled: false - # Cost used every time - fixed_cost: 1 - # Cost used for every lore line removed - per_line_cost: 0 - # Use left item vanilla cost penalty if any - shared_increase: false - # Increase shared left item cost penalty - shared_additive: false - # If removing the lore consume the book & quil - do_consume: false - # Cost of replacing colors - remove_color_cost: 0 - # Allowed some color and tags to be reverted to plain text - # Custom anvil will prioritise format that result is a smaller resulting text - # Note that not allowing certain format will lead to some lost of color or tags. - # If configuration are exact as append appending this book should result in the exact same color - # - # Color code will be prefixed by "&" and hexadecimal color by "#". - # If color code is allowed, "&" in the text will get converted to "&&" - # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - allow_color_code: true - allow_hexadecimal_color: false - allow_minimessage: true - - paper: - # Permission is ca.lore_edit.paper - use_permission: true - # what order should the lines should get added/removed (start/end, if invalid or not present will be end) - order: end - - append_line: - # If adding lore line using paper is enabled - enabled: false - # Cost used every time - fixed_cost: 1 - # Use left item vanilla cost penalty if any - shared_increase: false - # Increase shared left item cost penalty - shared_additive: false - # If adding the lore line consume the paper - do_consume: false - # Allow using color code and hexadecimal color when editing lore via book & quil - # - # Color code are prefixed by "&" and hexadecimal color by "#" - # Color code will not be applied if it colors nothing. "&&" can be used to write "&" - # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # - # Note that currently minimessage would disable hex code when adding color - allow_color_code: true - allow_hexadecimal_color: false - allow_minimessage: true - color_use_cost: 0 - - remove_line: - # If removing lore line using paper is enabled - enabled: false - # Cost used every time - fixed_cost: 1 - # Use left item vanilla cost penalty if any - shared_increase: false - # Increase shared left item cost penalty - shared_additive: false - # If removing the lore line consume the paper - do_consume: false - # Cost of replacing colors - remove_color_cost: 0 - # Allowed some color and tags to be reverted to plain text - # Custom anvil will prioritise format that result is a smaller resulting text - # Note that not allowing certain format will lead to some lost of color or tags. - # If configuration are exact as append appending this paper should result in the exact same color - # - # Color code will be prefixed by "&" and hexadecimal color by "#". - # If color code is allowed, "&" in the text will get converted to "&&" - # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - allow_color_code: true - allow_hexadecimal_color: false - allow_minimessage: true - -# Allow to replace the xp cost by a monetary cost -# If enabled it will not be bound to the experience level limits -# -# It also requires to enable dialog rename (set "enable_dialog_rename: false" a bit higher) -# If dialog rename permission is enabled and player do not have the permission merge will fall back to vanilla xp cost -# -# If you are using custom craft I recommend using Linear Xp Cost with Exact Linear Xp as normal Xp Cost will act "weird" -# But Linear Xp will act as 1$ time global multiplier. In other word: like you expect -# -# As this feature require dialog rename, it can only be enabled starting with paper 1.21.6 and later -monetary_cost: - enabled: false - # If using vault unlocked this allow to specify what currency should be used for anvil usage - # default being the default currency - currency: default - # multiply the anvil cost by a value to allow to have price a big bigger than like 40 - multipliers: - # global multipliers. all usage type will be multiplied by this value - global: 1.0 - # usage specific type. it will only apply for specific xp "reason" - enchantment: 1.0 # related to enchantments level - repair: 1.0 # for repairing via unit repair (per unit) - rename: 1.0 # for renaming the item - lore_edit: 1.0 # for changing the lore of the item (only if lore edit is enabled) - work_penalty: 1.0 # for work penalty (aka use penalty) - recipe: 1.0 # for custom anvil recipe cost - -# Whether to show debug logging -debug_log: false - -# Whether to show verbose debug logging -debug_log_verbose: false - -configVersion: 1.11.0 -lowMinecraftVersion: 1.21.9 diff --git a/defaultconfigs/1.21.9/custom_recipes.yml b/defaultconfigs/1.21.9/custom_recipes.yml deleted file mode 100644 index 57c2220..0000000 --- a/defaultconfigs/1.21.9/custom_recipes.yml +++ /dev/null @@ -1,5 +0,0 @@ -# ---------------------------------------------------- -# This config file is to store custom craft -# It is recommended to use the in game config editor for this configuration. -# /customanvilconfig With ca.config.edit permission -# ---------------------------------------------------- diff --git a/defaultconfigs/1.21.9/enchant_conflict.yml b/defaultconfigs/1.21.9/enchant_conflict.yml deleted file mode 100644 index 9205061..0000000 --- a/defaultconfigs/1.21.9/enchant_conflict.yml +++ /dev/null @@ -1,389 +0,0 @@ -# -# It is recommended that you use /configanvil to edit theses config. -# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! -# - -# material conflicts -# -# If you want to edit this file: -# - A conflict will apply to every item except if in one of the notAffectedGroups group -# - the conflict will count only if the user try to combine at least as -# many conflicting enchantment as "maxEnchantmentBeforeConflict" -# -# -# ---------------------------------------------------- -# These restriction are about not allowing enchantment -# on illegal items -# ---------------------------------------------------- - -restriction_aqua_affinity: - enchantments: - - minecraft:aqua_affinity - notAffectedGroups: - - enchanted_book - - helmets - -restriction_bane_of_arthropods: - enchantments: - - minecraft:bane_of_arthropods - notAffectedGroups: - - enchanted_book - - melee_weapons - - mace - -restriction_blast_protection: - enchantments: - - minecraft:blast_protection - notAffectedGroups: - - enchanted_book - - armors - -restriction_channeling: - enchantments: - - minecraft:channeling - notAffectedGroups: - - enchanted_book - - trident - -restriction_binding_curse: - enchantments: - - minecraft:binding_curse - notAffectedGroups: - - enchanted_book - - wearable - -restriction_vanishing_curse: - enchantments: - - minecraft:vanishing_curse - notAffectedGroups: - - enchanted_book - - can_vanish - -restriction_depth_strider: - enchantments: - - minecraft:depth_strider - notAffectedGroups: - - enchanted_book - - boots - -restriction_efficiency: - enchantments: - - minecraft:efficiency - notAffectedGroups: - - enchanted_book - - tools - - shears - -restriction_feather_falling: - enchantments: - - minecraft:feather_falling - notAffectedGroups: - - enchanted_book - - boots - -restriction_fire_aspect: - enchantments: - - minecraft:fire_aspect - notAffectedGroups: - - enchanted_book - - swords - - mace - -restriction_fire_protection: - enchantments: - - minecraft:fire_protection - notAffectedGroups: - - enchanted_book - - armors - -restriction_flame: - enchantments: - - minecraft:flame - notAffectedGroups: - - enchanted_book - - bow - -restriction_fortune: - enchantments: - - minecraft:fortune - notAffectedGroups: - - enchanted_book - - tools - -restriction_frost_walker: - enchantments: - - minecraft:frost_walker - notAffectedGroups: - - enchanted_book - - boots - -restriction_impaling: - enchantments: - - minecraft:impaling - notAffectedGroups: - - enchanted_book - - trident - -restriction_infinity: - enchantments: - - minecraft:infinity - notAffectedGroups: - - enchanted_book - - bow - -restriction_knockback: - enchantments: - - minecraft:knockback - notAffectedGroups: - - enchanted_book - - swords - -restriction_looting: - enchantments: - - minecraft:looting - notAffectedGroups: - - enchanted_book - - swords - -restriction_loyalty: - enchantments: - - minecraft:loyalty - notAffectedGroups: - - enchanted_book - - trident - -restriction_luck_of_the_sea: - enchantments: - - minecraft:luck_of_the_sea - notAffectedGroups: - - enchanted_book - - fishing_rod - -restriction_lure: - enchantments: - - minecraft:lure - notAffectedGroups: - - enchanted_book - - fishing_rod - -restriction_mending: - enchantments: - - minecraft:mending - notAffectedGroups: - - enchanted_book - - can_unbreak - -restriction_minecraft_multishot: - enchantments: - - minecraft:multishot - notAffectedGroups: - - enchanted_book - - crossbow - -restriction_piercing: - enchantments: - - minecraft:piercing - notAffectedGroups: - - enchanted_book - - crossbow - -restriction_power: - enchantments: - - minecraft:power - notAffectedGroups: - - enchanted_book - - bow - -restriction_projectile_protection: - enchantments: - - minecraft:projectile_protection - notAffectedGroups: - - enchanted_book - - armors - -restriction_protection: - enchantments: - - minecraft:protection - notAffectedGroups: - - enchanted_book - - armors - -restriction_punch: - enchantments: - - minecraft:punch - notAffectedGroups: - - enchanted_book - - bow - -restriction_quick_charge: - enchantments: - - minecraft:quick_charge - notAffectedGroups: - - enchanted_book - - crossbow - -restriction_respiration: - enchantments: - - minecraft:respiration - notAffectedGroups: - - enchanted_book - - helmets - -restriction_riptide: - enchantments: - - minecraft:riptide - notAffectedGroups: - - enchanted_book - - trident - -restriction_sharpness: - enchantments: - - minecraft:sharpness - notAffectedGroups: - - enchanted_book - - melee_weapons - -restriction__silk_touch: - enchantments: - - minecraft:silk_touch - notAffectedGroups: - - enchanted_book - - tools - -restriction_smite: - enchantments: - - minecraft:smite - notAffectedGroups: - - enchanted_book - - melee_weapons - - mace - -restriction_soul_speed: - enchantments: - - minecraft:soul_speed - notAffectedGroups: - - enchanted_book - - boots - -restriction_sweeping_edge: - enchantments: - - minecraft:sweeping - - minecraft:sweeping_edge - notAffectedGroups: - - enchanted_book - - swords - -# Do not exist in 1.18, that mean useInFuture will be set to true -# useInFuture set to true also mean it will not warn if there is an issue -restriction_swift_sneak: - useInFuture: true - enchantments: - - minecraft:swift_sneak - notAffectedGroups: - - enchanted_book - - leggings - -restriction_thorns: - enchantments: - - minecraft:thorns - notAffectedGroups: - - enchanted_book - - armors - -restriction__unbreaking: - enchantments: - - minecraft:unbreaking - notAffectedGroups: - - enchanted_book - - can_unbreak - -# ---------------------------------------------------- -# Now we have conflicts about enchantment Incompatibility -# We just filtered what item enchantments can be applied -# notAffectedGroups is empty as we don't want anything to not respect theses rules -# maxEnchantmentBeforeConflict is set to 1 to only have 1 on those enchantment available -# ---------------------------------------------------- - -sword_enchant_conflict: - enchantments: - - minecraft:bane_of_arthropods - - minecraft:smite - - minecraft:sharpness - - minecraft:density - - minecraft:breach - notAffectedGroups: [] - maxEnchantmentBeforeConflict: 1 - -protection_enchant_conflict: - enchantments: - - minecraft:blast_protection - - minecraft:fire_protection - - minecraft:projectile_protection - - minecraft:protection - notAffectedGroups: [] - maxEnchantmentBeforeConflict: 1 - -trident_conflict1: - enchantments: - - minecraft:channeling - - minecraft:riptide - notAffectedGroups: [] - maxEnchantmentBeforeConflict: 1 - -trident_conflict2: - enchantments: - - minecraft:loyalty - - minecraft:riptide - notAffectedGroups: [] - maxEnchantmentBeforeConflict: 1 - -boot_conflict: - enchantments: - - minecraft:depth_strider - - minecraft:frost_walker - notAffectedGroups: [] - maxEnchantmentBeforeConflict: 1 - -tool_conflict: - enchantments: - - minecraft:fortune - - minecraft:silk_touch - notAffectedGroups: [] - maxEnchantmentBeforeConflict: 1 - -bow_conflict: - enchantments: - - minecraft:mending - - minecraft:infinity - notAffectedGroups: [] - maxEnchantmentBeforeConflict: 1 - -crossbow_conflict: - enchantments: - - minecraft:multishot - - minecraft:piercing - notAffectedGroups: [] - maxEnchantmentBeforeConflict: 1 -restriction_density: - enchantments: - - minecraft:density - notAffectedGroups: - - mace - - enchanted_book -restriction_breach: - enchantments: - - minecraft:breach - notAffectedGroups: - - mace - - enchanted_book -restriction_wind_burst: - enchantments: - - minecraft:wind_burst - notAffectedGroups: - - mace - - enchanted_book - -# ---------------------------------------------------- -# Bellow is for custom conflicts. -# This is also where conflict create from the gui will be placed. -# ---------------------------------------------------- diff --git a/defaultconfigs/1.21.9/item_groups.yml b/defaultconfigs/1.21.9/item_groups.yml deleted file mode 100644 index 2dbd5db..0000000 --- a/defaultconfigs/1.21.9/item_groups.yml +++ /dev/null @@ -1,236 +0,0 @@ -# -# It is recommended that you use /configanvil to edit theses config. -# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! -# - -# Please note this config use spigot material names. -# It should match minecraft name in most case, maybe every case, but I can't be sure -# In case there an issue with material name, you can found them here: -# https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html - -# An empty Exclude group exclude nothing, so it contain everything -everything: - type: exclude - -# An empty include group will include nothing -nothing: - type: include - -# This group is an example of a group including only stone and polished granite -example_include: - type: include - items: - - stone - - polished_granite - -# This group contain everything except polished granite and elements of example_include -example_exclude: - type: exclude - items: - - polished_granite - groups: - - example_include - -# Default configuration should be vanilla enchantment conflict group -# there may have error, if you find one you can fix it ! -# https://minecraft.fandom.com/wiki/Enchanting - -swords: - type: include - items: - - wooden_sword - - stone_sword - - iron_sword - - diamond_sword - - golden_sword - - netherite_sword - - copper_sword - -axes: - type: include - items: - - wooden_axe - - stone_axe - - iron_axe - - diamond_axe - - golden_axe - - netherite_axe - - copper_axe - -melee_weapons: - type: include - groups: - - swords - - axes - -helmets: - type: include - items: - - leather_helmet - - chainmail_helmet - - iron_helmet - - diamond_helmet - - golden_helmet - - netherite_helmet - - turtle_helmet - - copper_helmet - -chestplate: - type: include - items: - - leather_chestplate - - chainmail_chestplate - - iron_chestplate - - diamond_chestplate - - golden_chestplate - - netherite_chestplate - - copper_chestplate - -leggings: - type: include - items: - - leather_leggings - - chainmail_leggings - - iron_leggings - - diamond_leggings - - golden_leggings - - netherite_leggings - - copper_leggings - -boots: - type: include - items: - - leather_boots - - chainmail_boots - - iron_boots - - diamond_boots - - golden_boots - - netherite_boots - - copper_boots - -armors: - type: include - groups: - - helmets - - chestplate - - leggings - - boots - -wearable: - type: include - items: - - elytra - - carved_pumpkin - - skeleton_skull - - wither_skeleton_skull - - zombie_head - - player_head - - creeper_head - - dragon_head - - piglin_head - groups: - - armors - -pickaxes: - type: include - items: - - wooden_pickaxe - - stone_pickaxe - - iron_pickaxe - - diamond_pickaxe - - golden_pickaxe - - netherite_pickaxe - - copper_pickaxe - -shovels: - type: include - items: - - wooden_shovel - - stone_shovel - - iron_shovel - - diamond_shovel - - golden_shovel - - netherite_shovel - - copper_shovel - -hoes: - type: include - items: - - wooden_hoe - - stone_hoe - - iron_hoe - - diamond_hoe - - golden_hoe - - netherite_hoe - - copper_hoe - -tools: - type: include - groups: - - pickaxes - - shovels - - hoes - - axes - -enchanted_book: - type: include - items: - - enchanted_book - -trident: - type: include - items: - - trident - -bow: - type: include - items: - - bow - -crossbow: - type: include - items: - - crossbow - -fishing_rod: - type: include - items: - - fishing_rod - -shears: - type: include - items: - - shears - -can_unbreak: - type: include - items: - - elytra - - flint_and_steel - - shield - - carrot_on_a_stick - - warped_fungus_on_a_stick - - brush - groups: - - melee_weapons - - tools - - armors - - trident - - bow - - crossbow - - fishing_rod - - shears - - mace - -can_vanish: - type: include - items: - - compass - groups: - - wearable - - can_unbreak -mace: - type: include - items: - - mace - diff --git a/defaultconfigs/1.21.9/unit_repair_item.yml b/defaultconfigs/1.21.9/unit_repair_item.yml deleted file mode 100644 index 0ce2bce..0000000 --- a/defaultconfigs/1.21.9/unit_repair_item.yml +++ /dev/null @@ -1,192 +0,0 @@ -# -# It is recommended that you use /configanvil to edit theses config. -# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! -# - -# Unit repair configuration -# -# This configuration is to make custom unit repair -# A unit repair is, for example, a diamond to repair a diamond sword -# In vanilla, a unit repair 25% of object durability -# you can make a custom value here -# -# Item name should NOT combine caps and no caps (example: Stone) - -# Default value if the config is an invalid value (value <= 0 ) -# If value > 1 it will be treated as being = 1 -default_repair_amount: 0.25 - -# You can add custom unit repair -# The example bellow make a shield repaired by 10% by sticks - -# stick: -# shield: 0.10 - - -# Vanilla unit repair group is bellow -diamond: - diamond_helmet: 0.25 - diamond_chestplate: 0.25 - diamond_leggings: 0.25 - diamond_boots: 0.25 - diamond_sword: 0.25 - diamond_pickaxe: 0.25 - diamond_axe: 0.25 - diamond_shovel: 0.25 - diamond_hoe: 0.25 - -netherite_ingot: - netherite_helmet: 0.25 - netherite_chestplate: 0.25 - netherite_leggings: 0.25 - netherite_boots: 0.25 - netherite_sword: 0.25 - netherite_pickaxe: 0.25 - netherite_axe: 0.25 - netherite_shovel: 0.25 - netherite_hoe: 0.25 - -gold_ingot: - golden_helmet: 0.25 - golden_chestplate: 0.25 - golden_leggings: 0.25 - golden_boots: 0.25 - golden_sword: 0.25 - golden_pickaxe: 0.25 - golden_axe: 0.25 - golden_shovel: 0.25 - golden_hoe: 0.25 - -iron_ingot: - iron_helmet: 0.25 - iron_chestplate: 0.25 - iron_leggings: 0.25 - iron_boots: 0.25 - iron_sword: 0.25 - iron_pickaxe: 0.25 - iron_axe: 0.25 - iron_shovel: 0.25 - iron_hoe: 0.25 - -cobblestone: - stone_sword: 0.25 - stone_pickaxe: 0.25 - stone_axe: 0.25 - stone_shovel: 0.25 - stone_hoe: 0.25 - -cobbled_deepslate: - stone_sword: 0.25 - stone_pickaxe: 0.25 - stone_axe: 0.25 - stone_shovel: 0.25 - stone_hoe: 0.25 - -blackstone: - stone_sword: 0.25 - stone_pickaxe: 0.25 - stone_axe: 0.25 - stone_shovel: 0.25 - stone_hoe: 0.25 - -leather: - leather_helmet: 0.25 - leather_chestplate: 0.25 - leather_leggings: 0.25 - leather_boots: 0.25 - -phantom_membrane: - elytra: 0.25 - -scute: - turtle_helmet: 0.25 - -oak_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -spruce_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -birch_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -jungle_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -acacia_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -dark_oak_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -mangrove_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -cherry_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -bamboo_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -crimson_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -warped_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 -breeze_rod: - mace: 0.25 diff --git a/defaultconfigs/1.21/README.md b/defaultconfigs/1.21/README.md deleted file mode 100644 index 7105d8a..0000000 --- a/defaultconfigs/1.21/README.md +++ /dev/null @@ -1,6 +0,0 @@ -### Default Plugin's Configurations For 1.21 -- [config.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21/config.yml) -- [enchant_conflict.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21/enchant_conflict.yml) -- [item_groups.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21/item_groups.yml) -- [unit_repair_item.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21/unit_repair_item.yml) -- [custom_recipes.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21/custom_recipes.yml) diff --git a/defaultconfigs/1.21/config.yml b/defaultconfigs/1.21/config.yml deleted file mode 100644 index 5d59e5a..0000000 --- a/defaultconfigs/1.21/config.yml +++ /dev/null @@ -1,466 +0,0 @@ -# -# It is recommended that you use /configanvil to edit theses config. -# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! -# - -# What service of metric should custom anvil use -# Custom anvil collect generic information like server minecraft version, type, etc... -# It can also collect error information if error is happening (currently faststats only) -# It can also be disabled -# Please refer to README for public metric link -# Possible options: auto, bstat, faststats, disabled (auto by default) -metric_type: auto - -# Allow to report errors made caused by this plugin (only for faststats) -# This allows me to fix potentials issue that I'm not aware of -# Accept true or false (true by default) -metric_collect_errors: true - -# All anvil cost will be capped to limit_repair_value if enabled. -# -# In other words: -# For any anvil cost greater than limit_repair_value, Cost will be set to limit_repair_value. -limit_repair_cost: false - -# Max cost value the Anvil can get to. -# -# Valid values include 0 to 1000. -# Cost will be displayed as "Too Expensive": -# - If Cost is above 39 -# - And replace_too_expensive is disabled (false) -limit_repair_value: 39 - -# Whether the anvil's cost limit should be removed entirely. -# -# The anvil will still visually display "Too Expensive" if "replace_too_expensive" is disabled -# However, the action will be completable if xp requirement is meet. -remove_repair_limit: false - -# Whenever anvil cost is above 39 should display the true price and not "Too Expensive". -# -# However, when bypassing "Too Expensive", anvil price will be displayed as Green. -# If the action is not completable, the cost will still be displayed as "Too expensive". -# That mean you also need to change other settings like remove_repair_limit or limit_repair_cost. -# -# Require ProtocoLib. -replace_too_expensive: false - -# XP Level amount added to the anvil when the item is repaired by another item of the same type -# -# Valid values include 0 to 1000 -item_repair_cost: 2 - -# XP Level amount added to the anvil when the item is renamed -# -# Valid values include 0 to 1000 -item_rename_cost: 1 - -# XP Level amount added to the anvil when the item is repaired by an "unit" -# For example: a Diamond on a Diamond Sword -# What's considered unit for what can be edited on the unit repair configuration. -# -# Valid values include 0 to 1000 -unit_repair_cost: 1 - -# XP Level amount added to the anvil when a sacrifice enchantment -# conflict with one of the left item enchantment -# -# Valid values include 0 to 1000 -sacrifice_illegal_enchant_cost: 1 - -# Allow using color code and hexadecimal color. -# -# Color code are prefixed by "&" and hexadecimal color by "#". -# Color code will not be applied if it colors nothing. "&&" can be used to write "&". -# For minimessage search for minimessage formating https://docs.papermc.io/adventure/minimessage/format/ -allow_color_code: false -allow_hexadecimal_color: false -allow_minimessage: false - -# This enables restricting color code for player having specific permission -# It requires allow_color_code enabled for... obvious reasons -# -# For example: if player want to use "&aHello" it will be required that the player has -# the permission "ca.color.code.a" as he used the color code "a" -# In general permission to give to the player is "ca.color.code.[code]" -# where [code] is the color code you wish to allow the player -# -# It is kinda of useless when minimessage is supported as players would be able to bypass -# that using the equivalent minimessage tag -per_color_code_permission: false - -# Toggle if color should only be applicable if the player a certain permission. -# -# permission are "ca.color.code" for use of color code and "ca.color.hex" for use of hexadecimal color. -permission_needed_for_color: true - -# Xp cost if the player use color in the items name on rename. -# -# Valid values include 0 to 1000. -use_of_color_cost: 0 - -# Dialogue rename menu make use of dialog menu to allow bigger rename -# You can also change the maximum size and set it to -1 or less for maximum -# -# This feature only work on paper 1.21.7 or later -# -# At the moment only english is available for this menu... sorry ! -# -# CustomAnvil use "ca.rename.dialog" when permission -enable_dialog_rename: false -dialog_rename_max_size: 256 -permission_needed_for_dialog_rename: false - -# This allows custom anvil to not "guess" the text used for rename but store it in the item -# It will make item stackable only and only if it had used the same rename text -# -# For practical reason. this only work when dialog rename is enabled -dialog_rename_keep_user_text: true - -# Override limits for specific enchants -# -# Enchantments not listed here will use the value of default_limit -# -# Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels -# -# Valid range of 0 - 255 for each enchantment -# -1 mean keep default -enchant_limits: - minecraft:aqua_affinity: 1 - minecraft:binding_curse: 1 - minecraft:channeling: 1 - minecraft:flame: 1 - minecraft:infinity: 1 - minecraft:mending: 1 - minecraft:multishot: 1 - minecraft:silk_touch: 1 - minecraft:vanishing_curse: 1 - minecraft:depth_strider: 3 # anything more than 3 is treated as 3 by the game - minecraft:protection: 4 - minecraft:fire_protection: 4 - minecraft:blast_protection: 4 - minecraft:projectile_protection: 4 - minecraft:feather_falling: 4 - minecraft:thorns: 3 - minecraft:respiration: 3 - minecraft:sharpness: 5 - minecraft:smite: 5 - minecraft:bane_of_arthropods: 5 - minecraft:knockback: 2 - minecraft:fire_aspect: 2 - minecraft:looting: 3 - minecraft:sweeping: 3 - minecraft:sweeping_edge: 3 - minecraft:efficiency: 5 - minecraft:unbreaking: 3 - minecraft:fortune: 3 - minecraft:power: 5 - minecraft:punch: 2 - minecraft:luck_of_the_sea: 3 - minecraft:lure: 3 - minecraft:frost_walker: 2 - minecraft:impaling: 5 - minecraft:riptide: 3 - minecraft:loyalty: 3 - minecraft:piercing: 4 - minecraft:quick_charge: 3 - minecraft:soul_speed: 3 - minecraft:swift_sneak: 3 - -# Multipliers used to calculate the enchantment's value in repair/combining -# -# Values here are pulled from the fandom wiki: -# https://minecraft.fandom.com/wiki/Anvil_mechanics#Costs_for_combining_enchantments -# -# If an enchantment is missing values here, or is less than 0, it will default to 0 -# -# Calculated as: [Enchantment lvl] * [multiplier] -# -# With default values protection 4 would have a value of 4 when -# coming from either a book (4 * 1) or an item (4 * 1) -enchant_values: - minecraft:aqua_affinity: - item: 4 - book: 2 - minecraft:bane_of_arthropods: - item: 2 - book: 1 - minecraft:binding_curse: - item: 8 - book: 4 - minecraft:blast_protection: - item: 4 - book: 2 - minecraft:channeling: - item: 8 - book: 4 - minecraft:depth_strider: - item: 4 - book: 2 - minecraft:efficiency: - item: 1 - book: 1 - minecraft:flame: - item: 4 - book: 2 - minecraft:feather_falling: - item: 2 - book: 1 - minecraft:fire_aspect: - item: 4 - book: 2 - minecraft:fire_protection: - item: 2 - book: 1 - minecraft:fortune: - item: 4 - book: 2 - minecraft:frost_walker: - item: 4 - book: 2 - minecraft:impaling: - item: 4 - book: 2 - minecraft:infinity: - item: 8 - book: 4 - minecraft:knockback: - item: 2 - book: 1 - minecraft:looting: - item: 4 - book: 2 - minecraft:loyalty: - item: 1 - book: 1 - minecraft:luck_of_the_sea: - item: 4 - book: 2 - minecraft:lure: - item: 4 - book: 2 - minecraft:mending: - item: 4 - book: 2 - minecraft:multishot: - item: 4 - book: 2 - minecraft:piercing: - item: 1 - book: 1 - minecraft:power: - item: 1 - book: 1 - minecraft:projectile_protection: - item: 2 - book: 1 - minecraft:protection: - item: 1 - book: 1 - minecraft:punch: - item: 4 - book: 2 - minecraft:quick_charge: - item: 2 - book: 1 - minecraft:respiration: - item: 4 - book: 2 - minecraft:riptide: - item: 4 - book: 2 - minecraft:silk_touch: - item: 8 - book: 4 - minecraft:sharpness: - item: 1 - book: 1 - minecraft:smite: - item: 2 - book: 1 - minecraft:soul_speed: - item: 8 - book: 4 - minecraft:swift_sneak: - item: 8 - book: 4 - minecraft:sweeping: - item: 4 - book: 2 - minecraft:sweeping_edge: - item: 4 - book: 2 - minecraft:thorns: - item: 8 - book: 4 - minecraft:unbreaking: - item: 2 - book: 1 - minecraft:vanishing_curse: - item: 8 - book: 4 - -# Disable enchantment merging for level above the set value -# Enchantment merging is when, for example, 2 unbreaking II book combine to give sharpness III -# But Enchantment above this value can still be applied. following the previous example, we could still apply a unbreaking III book to a sword -# Even if disable-merge-over of unbreaking is set to 2 -# -1 mean enchantment merge for this enchantment is not disabled. default to -1 if absent. -disable-merge-over: - # Sharpness is set to -1. it equivalent to it not being set to anything (and work as vanilla on default configuration) - minecraft:sharpness: -1 -# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied -# minecraft:unbreaking: 2 - -# The maximum number of enchantment an item can get. -1 for infinity -# Use eco enchant enchant_limit if present by default unless "default" is not equal to -1 -enchantment_count_limit: - default: -1 - # Limit for specific items. example bellow is an example with stick - # Per item enchantment limit override eco enchant enchant_limit and default limit - items: - stick: -1 - -# Settings for lore modification -lore_edit: - book_and_quil: - # Permission is ca.lore_edit.book - use_permission: true - append: - # If adding lore using book & quil is enabled - enabled: false - # Cost used every time - fixed_cost: 1 - # Cost used for every lore line added - per_line_cost: 0 - # Use left item vanilla cost penalty if any - shared_increase: false - # Increase shared left item cost penalty - shared_additive: false - # If adding the lore consume the book & quil - do_consume: false - # Allow using color code and hexadecimal color when editing lore via book & quil - # - # Color code are prefixed by "&" and hexadecimal color by "#" - # Color code will not be applied if it colors nothing. "&&" can be used to write "&" - # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # - # Note that currently minimessage would disable hex code when adding color - allow_color_code: true - allow_hexadecimal_color: false - allow_minimessage: true - - remove: - # If removing lore using book & quil is enabled - enabled: false - # Cost used every time - fixed_cost: 1 - # Cost used for every lore line removed - per_line_cost: 0 - # Use left item vanilla cost penalty if any - shared_increase: false - # Increase shared left item cost penalty - shared_additive: false - # If removing the lore consume the book & quil - do_consume: false - # Cost of replacing colors - remove_color_cost: 0 - # Allowed some color and tags to be reverted to plain text - # Custom anvil will prioritise format that result is a smaller resulting text - # Note that not allowing certain format will lead to some lost of color or tags. - # If configuration are exact as append appending this book should result in the exact same color - # - # Color code will be prefixed by "&" and hexadecimal color by "#". - # If color code is allowed, "&" in the text will get converted to "&&" - # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - allow_color_code: true - allow_hexadecimal_color: false - allow_minimessage: true - - paper: - # Permission is ca.lore_edit.paper - use_permission: true - # what order should the lines should get added/removed (start/end, if invalid or not present will be end) - order: end - - append_line: - # If adding lore line using paper is enabled - enabled: false - # Cost used every time - fixed_cost: 1 - # Use left item vanilla cost penalty if any - shared_increase: false - # Increase shared left item cost penalty - shared_additive: false - # If adding the lore line consume the paper - do_consume: false - # Allow using color code and hexadecimal color when editing lore via book & quil - # - # Color code are prefixed by "&" and hexadecimal color by "#" - # Color code will not be applied if it colors nothing. "&&" can be used to write "&" - # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # - # Note that currently minimessage would disable hex code when adding color - allow_color_code: true - allow_hexadecimal_color: false - allow_minimessage: true - color_use_cost: 0 - - remove_line: - # If removing lore line using paper is enabled - enabled: false - # Cost used every time - fixed_cost: 1 - # Use left item vanilla cost penalty if any - shared_increase: false - # Increase shared left item cost penalty - shared_additive: false - # If removing the lore line consume the paper - do_consume: false - # Cost of replacing colors - remove_color_cost: 0 - # Allowed some color and tags to be reverted to plain text - # Custom anvil will prioritise format that result is a smaller resulting text - # Note that not allowing certain format will lead to some lost of color or tags. - # If configuration are exact as append appending this paper should result in the exact same color - # - # Color code will be prefixed by "&" and hexadecimal color by "#". - # If color code is allowed, "&" in the text will get converted to "&&" - # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - allow_color_code: true - allow_hexadecimal_color: false - allow_minimessage: true - -# Allow to replace the xp cost by a monetary cost -# If enabled it will not be bound to the experience level limits -# -# It also requires to enable dialog rename (set "enable_dialog_rename: false" a bit higher) -# If dialog rename permission is enabled and player do not have the permission merge will fall back to vanilla xp cost -# -# If you are using custom craft I recommend using Linear Xp Cost with Exact Linear Xp as normal Xp Cost will act "weird" -# But Linear Xp will act as 1$ time global multiplier. In other word: like you expect -# -# As this feature require dialog rename, it can only be enabled starting with paper 1.21.6 and later -monetary_cost: - enabled: false - # If using vault unlocked this allow to specify what currency should be used for anvil usage - # default being the default currency - currency: default - # multiply the anvil cost by a value to allow to have price a big bigger than like 40 - multipliers: - # global multipliers. all usage type will be multiplied by this value - global: 1.0 - # usage specific type. it will only apply for specific xp "reason" - enchantment: 1.0 # related to enchantments level - repair: 1.0 # for repairing via unit repair (per unit) - rename: 1.0 # for renaming the item - lore_edit: 1.0 # for changing the lore of the item (only if lore edit is enabled) - work_penalty: 1.0 # for work penalty (aka use penalty) - recipe: 1.0 # for custom anvil recipe cost - -# Whether to show debug logging -debug_log: false - -# Whether to show verbose debug logging -debug_log_verbose: false - -configVersion: 1.11.0 \ No newline at end of file diff --git a/defaultconfigs/1.21/custom_recipes.yml b/defaultconfigs/1.21/custom_recipes.yml deleted file mode 100644 index 57c2220..0000000 --- a/defaultconfigs/1.21/custom_recipes.yml +++ /dev/null @@ -1,5 +0,0 @@ -# ---------------------------------------------------- -# This config file is to store custom craft -# It is recommended to use the in game config editor for this configuration. -# /customanvilconfig With ca.config.edit permission -# ---------------------------------------------------- diff --git a/defaultconfigs/1.21/enchant_conflict.yml b/defaultconfigs/1.21/enchant_conflict.yml deleted file mode 100644 index 45d62c3..0000000 --- a/defaultconfigs/1.21/enchant_conflict.yml +++ /dev/null @@ -1,247 +0,0 @@ -# -# It is recommended that you use /configanvil to edit theses config. -# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! -# - -# material conflicts -# -# If you want to edit this file: -# - A conflict will apply to every item except if in one of the notAffectedGroups group -# - the conflict will count only if the user try to combine at least as -# many conflicting enchantment as "maxEnchantmentBeforeConflict" -# -# -# ---------------------------------------------------- -# These restriction are about not allowing enchantment -# on illegal items -# ---------------------------------------------------- - -restriction_aqua_affinity: - enchantments: [ minecraft:aqua_affinity ] - notAffectedGroups: [ enchanted_book, helmets ] - -restriction_bane_of_arthropods: - enchantments: [ minecraft:bane_of_arthropods ] - notAffectedGroups: [ enchanted_book, melee_weapons ] - -restriction_blast_protection: - enchantments: [ minecraft:blast_protection ] - notAffectedGroups: [ enchanted_book, armors ] - -restriction_channeling: - enchantments: [ minecraft:channeling ] - notAffectedGroups: [ enchanted_book, trident ] - -restriction_binding_curse: - enchantments: [ minecraft:binding_curse ] - notAffectedGroups: [ enchanted_book, wearable ] - -restriction_vanishing_curse: - enchantments: [ minecraft:vanishing_curse ] - notAffectedGroups: [ enchanted_book, can_vanish ] - -restriction_depth_strider: - enchantments: [ minecraft:depth_strider ] - notAffectedGroups: [ enchanted_book, boots ] - -restriction_efficiency: - enchantments: [ minecraft:efficiency ] - notAffectedGroups: [ enchanted_book, tools, shears ] - -restriction_feather_falling: - enchantments: [ minecraft:feather_falling ] - notAffectedGroups: [ enchanted_book, boots ] - -restriction_fire_aspect: - enchantments: [ minecraft:fire_aspect ] - notAffectedGroups: [ enchanted_book, swords ] - -restriction_fire_protection: - enchantments: [ minecraft:fire_protection ] - notAffectedGroups: [ enchanted_book, armors ] - -restriction_flame: - enchantments: [ minecraft:flame ] - notAffectedGroups: [ enchanted_book, bow ] - -restriction_fortune: - enchantments: [ minecraft:fortune ] - notAffectedGroups: [ enchanted_book, tools ] - -restriction_frost_walker: - enchantments: [ minecraft:frost_walker ] - notAffectedGroups: [ enchanted_book, boots ] - -restriction_impaling: - enchantments: [ minecraft:impaling ] - notAffectedGroups: [ enchanted_book, trident ] - -restriction_infinity: - enchantments: [ minecraft:infinity ] - notAffectedGroups: [ enchanted_book, bow ] - -restriction_knockback: - enchantments: [ minecraft:knockback ] - notAffectedGroups: [ enchanted_book, swords ] - -restriction_looting: - enchantments: [ minecraft:looting ] - notAffectedGroups: [ enchanted_book, swords ] - -restriction_loyalty: - enchantments: [ minecraft:loyalty ] - notAffectedGroups: [ enchanted_book, trident ] - -restriction_luck_of_the_sea: - enchantments: [ minecraft:luck_of_the_sea ] - notAffectedGroups: [ enchanted_book, fishing_rod ] - -restriction_lure: - enchantments: [ minecraft:lure ] - notAffectedGroups: [ enchanted_book, fishing_rod ] - -restriction_mending: - enchantments: [ minecraft:mending ] - notAffectedGroups: [ enchanted_book, can_unbreak ] - -restriction_minecraft_multishot: - enchantments: [ minecraft:multishot ] - notAffectedGroups: [ enchanted_book, crossbow ] - -restriction_piercing: - enchantments: [ minecraft:piercing ] - notAffectedGroups: [ enchanted_book, crossbow ] - -restriction_power: - enchantments: [ minecraft:power ] - notAffectedGroups: [ enchanted_book, bow ] - -restriction_projectile_protection: - enchantments: [ minecraft:projectile_protection ] - notAffectedGroups: [ enchanted_book, armors ] - -restriction_protection: - enchantments: [ minecraft:protection ] - notAffectedGroups: [ enchanted_book, armors ] - -restriction_punch: - enchantments: [ minecraft:punch ] - notAffectedGroups: [ enchanted_book, bow ] - -restriction_quick_charge: - enchantments: [ minecraft:quick_charge ] - notAffectedGroups: [ enchanted_book, crossbow ] - -restriction_respiration: - enchantments: [ minecraft:respiration ] - notAffectedGroups: [ enchanted_book, helmets ] - -restriction_riptide: - enchantments: [ minecraft:riptide ] - notAffectedGroups: [ enchanted_book, trident ] - -restriction_sharpness: - enchantments: [ minecraft:sharpness ] - notAffectedGroups: [ enchanted_book, melee_weapons ] - -restriction__silk_touch: - enchantments: [ minecraft:silk_touch ] - notAffectedGroups: [ enchanted_book, tools ] - -restriction_smite: - enchantments: [ minecraft:smite ] - notAffectedGroups: [ enchanted_book, melee_weapons ] - -restriction_soul_speed: - enchantments: [ minecraft:soul_speed ] - notAffectedGroups: [ enchanted_book, boots ] - -restriction_sweeping_edge: - enchantments: [ minecraft:sweeping, minecraft:sweeping_edge ] - notAffectedGroups: [ enchanted_book, swords ] - -# Do not exist in 1.18, that mean useInFuture will be set to true -# useInFuture set to true also mean it will not warn if there is an issue -restriction_swift_sneak: - useInFuture: true - enchantments: [ minecraft:swift_sneak ] - notAffectedGroups: [ enchanted_book, leggings ] - -restriction_thorns: - enchantments: [ minecraft:thorns ] - notAffectedGroups: [ enchanted_book, armors ] - -restriction__unbreaking: - enchantments: [ minecraft:unbreaking ] - notAffectedGroups: [ enchanted_book, can_unbreak ] - -# ---------------------------------------------------- -# Now we have conflicts about enchantment Incompatibility -# We just filtered what item enchantments can be applied -# notAffectedGroups is empty as we don't want anything to not respect theses rules -# maxEnchantmentBeforeConflict is set to 1 to only have 1 on those enchantment available -# ---------------------------------------------------- - -sword_enchant_conflict: - enchantments: - - minecraft:bane_of_arthropods - - minecraft:smite - - minecraft:sharpness - notAffectedGroups: [ ] - maxEnchantmentBeforeConflict: 1 - -protection_enchant_conflict: - enchantments: - - minecraft:blast_protection - - minecraft:fire_protection - - minecraft:projectile_protection - - minecraft:protection - notAffectedGroups: [ ] - maxEnchantmentBeforeConflict: 1 - -trident_conflict1: - enchantments: - - minecraft:channeling - - minecraft:riptide - notAffectedGroups: [ ] - maxEnchantmentBeforeConflict: 1 - -trident_conflict2: - enchantments: - - minecraft:loyalty - - minecraft:riptide - notAffectedGroups: [ ] - maxEnchantmentBeforeConflict: 1 - -boot_conflict: - enchantments: - - minecraft:depth_strider - - minecraft:frost_walker - notAffectedGroups: [ ] - maxEnchantmentBeforeConflict: 1 - -tool_conflict: - enchantments: - - minecraft:fortune - - minecraft:silk_touch - notAffectedGroups: [ ] - maxEnchantmentBeforeConflict: 1 - -bow_conflict: - enchantments: - - minecraft:mending - - minecraft:infinity - notAffectedGroups: [ ] - maxEnchantmentBeforeConflict: 1 - -crossbow_conflict: - enchantments: - - minecraft:multishot - - minecraft:piercing - notAffectedGroups: [ ] - maxEnchantmentBeforeConflict: 1 - -# ---------------------------------------------------- -# Bellow is for custom conflicts. -# This is also where conflict create from the gui will be placed. -# ---------------------------------------------------- diff --git a/defaultconfigs/1.21/item_groups.yml b/defaultconfigs/1.21/item_groups.yml deleted file mode 100644 index 3c1eb5d..0000000 --- a/defaultconfigs/1.21/item_groups.yml +++ /dev/null @@ -1,210 +0,0 @@ -# -# It is recommended that you use /configanvil to edit theses config. -# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! -# - -# Please note this config use spigot material names. -# It should match minecraft name in most case, maybe every case, but I can't be sure -# In case there an issue with material name, you can found them here: -# https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html - -# An empty Exclude group exclude nothing, so it contain everything -everything: - type: exclude - -# An empty include group will include nothing -nothing: - type: include - -# This group is an example of a group including only stone and polished granite -example_include: - type: include - items: - - stone - - polished_granite - -# This group contain everything except polished granite and elements of example_include -example_exclude: - type: exclude - items: - - polished_granite - groups: - - example_include - -# Default configuration should be vanilla enchantment conflict group -# there may have error, if you find one you can fix it ! -# https://minecraft.fandom.com/wiki/Enchanting - -swords: - type: include - items: - - wooden_sword - - stone_sword - - iron_sword - - diamond_sword - - golden_sword - - netherite_sword - -axes: - type: include - items: - - wooden_axe - - stone_axe - - iron_axe - - diamond_axe - - golden_axe - - netherite_axe - -melee_weapons: - type: include - groups: - - swords - - axes - -helmets: - type: include - items: - - leather_helmet - - chainmail_helmet - - iron_helmet - - diamond_helmet - - golden_helmet - - netherite_helmet - - turtle_helmet - -chestplate: - type: include - items: - - leather_chestplate - - chainmail_chestplate - - iron_chestplate - - diamond_chestplate - - golden_chestplate - - netherite_chestplate - -leggings: - type: include - items: - - leather_leggings - - chainmail_leggings - - iron_leggings - - diamond_leggings - - golden_leggings - - netherite_leggings - -boots: - type: include - items: - - leather_boots - - chainmail_boots - - iron_boots - - diamond_boots - - golden_boots - - netherite_boots - -armors: - type: include - groups: - - helmets - - chestplate - - leggings - - boots - -wearable: - type: include - items: - - elytra - - carved_pumpkin - - skeleton_skull - - wither_skeleton_skull - - zombie_head - - player_head - - creeper_head - - dragon_head - # do not exist in 1.18 but exist in future update - - piglin_head - groups: - - armors - -tools: - type: include - items: - - wooden_pickaxe - - stone_pickaxe - - iron_pickaxe - - diamond_pickaxe - - golden_pickaxe - - netherite_pickaxe - - wooden_shovel - - stone_shovel - - iron_shovel - - diamond_shovel - - golden_shovel - - netherite_shovel - - wooden_hoe - - stone_hoe - - iron_hoe - - diamond_hoe - - golden_hoe - - netherite_hoe - groups: - - axes - -enchanted_book: - type: include - items: - - enchanted_book - -trident: - type: include - items: - - trident - -bow: - type: include - items: - - bow - -crossbow: - type: include - items: - - crossbow - -fishing_rod: - type: include - items: - - fishing_rod - -shears: - type: include - items: - - shears - -can_unbreak: - type: include - items: - - elytra - - flint_and_steel - - shield - - carrot_on_a_stick - - warped_fungus_on_a_stick - # do not exist in 1.18 but exist in future update - - brush - groups: - - melee_weapons - - tools - - armors - - trident - - bow - - crossbow - - fishing_rod - - shears - -can_vanish: - type: include - items: - - compass - groups: - - wearable - - can_unbreak - diff --git a/defaultconfigs/1.21/unit_repair_item.yml b/defaultconfigs/1.21/unit_repair_item.yml deleted file mode 100644 index 2902cce..0000000 --- a/defaultconfigs/1.21/unit_repair_item.yml +++ /dev/null @@ -1,190 +0,0 @@ -# -# It is recommended that you use /configanvil to edit theses config. -# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! -# - -# Unit repair configuration -# -# This configuration is to make custom unit repair -# A unit repair is, for example, a diamond to repair a diamond sword -# In vanilla, a unit repair 25% of object durability -# you can make a custom value here -# -# Item name should NOT combine caps and no caps (example: Stone) - -# Default value if the config is an invalid value (value <= 0 ) -# If value > 1 it will be treated as being = 1 -default_repair_amount: 0.25 - -# You can add custom unit repair -# The example bellow make a shield repaired by 10% by sticks - -#stick: -# shield: 0.10 - - -# Vanilla unit repair group is bellow -diamond: - diamond_helmet: 0.25 - diamond_chestplate: 0.25 - diamond_leggings: 0.25 - diamond_boots: 0.25 - diamond_sword: 0.25 - diamond_pickaxe: 0.25 - diamond_axe: 0.25 - diamond_shovel: 0.25 - diamond_hoe: 0.25 - -netherite_ingot: - netherite_helmet: 0.25 - netherite_chestplate: 0.25 - netherite_leggings: 0.25 - netherite_boots: 0.25 - netherite_sword: 0.25 - netherite_pickaxe: 0.25 - netherite_axe: 0.25 - netherite_shovel: 0.25 - netherite_hoe: 0.25 - -gold_ingot: - golden_helmet: 0.25 - golden_chestplate: 0.25 - golden_leggings: 0.25 - golden_boots: 0.25 - golden_sword: 0.25 - golden_pickaxe: 0.25 - golden_axe: 0.25 - golden_shovel: 0.25 - golden_hoe: 0.25 - -iron_ingot: - iron_helmet: 0.25 - iron_chestplate: 0.25 - iron_leggings: 0.25 - iron_boots: 0.25 - iron_sword: 0.25 - iron_pickaxe: 0.25 - iron_axe: 0.25 - iron_shovel: 0.25 - iron_hoe: 0.25 - -cobblestone: - stone_sword: 0.25 - stone_pickaxe: 0.25 - stone_axe: 0.25 - stone_shovel: 0.25 - stone_hoe: 0.25 - -cobbled_deepslate: - stone_sword: 0.25 - stone_pickaxe: 0.25 - stone_axe: 0.25 - stone_shovel: 0.25 - stone_hoe: 0.25 - -blackstone: - stone_sword: 0.25 - stone_pickaxe: 0.25 - stone_axe: 0.25 - stone_shovel: 0.25 - stone_hoe: 0.25 - -leather: - leather_helmet: 0.25 - leather_chestplate: 0.25 - leather_leggings: 0.25 - leather_boots: 0.25 - -phantom_membrane: - elytra: 0.25 - -scute: - turtle_helmet: 0.25 - -oak_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -spruce_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -birch_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -jungle_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -acacia_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -dark_oak_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -mangrove_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -cherry_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -bamboo_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -crimson_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -warped_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 diff --git a/defaultconfigs/README.md b/defaultconfigs/README.md deleted file mode 100644 index daa2088..0000000 --- a/defaultconfigs/README.md +++ /dev/null @@ -1,5 +0,0 @@ -### Default Plugin's Configurations -From 1.18 to 1.20.6 use [1.18 configurations](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.18) \ -From 1.21 to 1.21.8 use [1.21 configurations](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21) \ -From 1.21.9 to 1.21.10 use [1.21.9 configurations](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.9) \ -From 1.21.11 use [1.21.11 configurations](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.11) diff --git a/gradle.properties b/gradle.properties index 4397d2e..29e08e8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,13 +1 @@ -kotlin.code.style=official - -# Signing -signing.secretKeyRingFile=~/.gnupg/secring.gpg - -kotlin.daemon.jvmargs=-Xmx8G - -# list of nms -subprojects.reobfnms=v1_17R1,v1_18R1,v1_18R2,v1_19R1,v1_19R2,v1_19R3,v1_20R1,v1_20R2,v1_20R3,v1_20R4,v1_21R1,v1_21R2,v1_21R3,v1_21R4,v1_21R5,v1_21R6,v1_21R7 - -# list of version for hangar release -paperVersion=1.18-26.2 - +kotlin.code.style=official \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0b55a3b..69a9715 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew old mode 100755 new mode 100644 diff --git a/impl/ExcellentEnchant5_4/build.gradle.kts b/impl/ExcellentEnchant5_4/build.gradle.kts deleted file mode 100644 index 9fe598b..0000000 --- a/impl/ExcellentEnchant5_4/build.gradle.kts +++ /dev/null @@ -1,17 +0,0 @@ -group = rootProject.group -version = rootProject.version - -plugins { - kotlin("jvm") version "2.3.0" -} - -repositories { - // ExcellentEnchants - maven(url = "https://repo.nightexpressdev.com/releases") -} - -dependencies { - // Excellent Enchant - compileOnly("su.nightexpress.excellentenchants:Core:5.4.3") - compileOnly("su.nightexpress.nightcore:main:2.16.2") -} \ No newline at end of file diff --git a/impl/ExcellentEnchant5_4/src/main/java/xyz/alexcrea/cuanvil/dependency/plugins/ExcellentEnchant5_3Registry.java b/impl/ExcellentEnchant5_4/src/main/java/xyz/alexcrea/cuanvil/dependency/plugins/ExcellentEnchant5_3Registry.java deleted file mode 100644 index 51e7302..0000000 --- a/impl/ExcellentEnchant5_4/src/main/java/xyz/alexcrea/cuanvil/dependency/plugins/ExcellentEnchant5_3Registry.java +++ /dev/null @@ -1,16 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.plugins; - -import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.api.enchantment.CustomEnchantment; -import su.nightexpress.excellentenchants.enchantment.EnchantRegistry; - -import java.util.Set; - -public class ExcellentEnchant5_3Registry { - - public static @NotNull Set getRegistered(){ - return EnchantRegistry.getRegistered(); - } - - -} diff --git a/impl/ExcellentEnchant5_4/src/main/java/xyz/alexcrea/cuanvil/dependency/plugins/ExcellentEnchant5_4EnchantSettings.java b/impl/ExcellentEnchant5_4/src/main/java/xyz/alexcrea/cuanvil/dependency/plugins/ExcellentEnchant5_4EnchantSettings.java deleted file mode 100644 index 49dde3e..0000000 --- a/impl/ExcellentEnchant5_4/src/main/java/xyz/alexcrea/cuanvil/dependency/plugins/ExcellentEnchant5_4EnchantSettings.java +++ /dev/null @@ -1,12 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.plugins; - -import su.nightexpress.excellentenchants.EnchantsAPI; - -public class ExcellentEnchant5_4EnchantSettings { - - - public static int anvilLimit() { - return EnchantsAPI.getEnchantManager().getSettings().getAnvilEnchantsLimit(); - } - -} diff --git a/impl/LegacyEcoEnchant/.gitignore b/impl/LegacyEcoEnchant/.gitignore deleted file mode 100644 index 47374f1..0000000 --- a/impl/LegacyEcoEnchant/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.lastDeploymentsId \ No newline at end of file diff --git a/impl/LegacyEcoEnchant/build.gradle.kts b/impl/LegacyEcoEnchant/build.gradle.kts deleted file mode 100644 index 83057a7..0000000 --- a/impl/LegacyEcoEnchant/build.gradle.kts +++ /dev/null @@ -1,13 +0,0 @@ -group = rootProject.group -version = rootProject.version - -plugins { - kotlin("jvm") version "2.3.0" -} - -// Imitate needed class and method to support legacy version of EcoEnchant -dependencies { - // Spigot api - compileOnly("org.spigotmc:spigot-api:1.18-R0.1-SNAPSHOT") - -} \ No newline at end of file diff --git a/impl/LegacyEcoEnchant/src/main/java/com/willfp/ecoenchants/enchantments/EcoEnchant.java b/impl/LegacyEcoEnchant/src/main/java/com/willfp/ecoenchants/enchantments/EcoEnchant.java deleted file mode 100644 index edfe1e9..0000000 --- a/impl/LegacyEcoEnchant/src/main/java/com/willfp/ecoenchants/enchantments/EcoEnchant.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.willfp.ecoenchants.enchantments; - -import com.willfp.ecoenchants.enchantments.meta.EnchantmentTarget; -import com.willfp.ecoenchants.enchantments.meta.EnchantmentType; -import org.bukkit.enchantments.Enchantment; -import org.jetbrains.annotations.NotNull; - -import java.util.Set; - -/** - * Mock class for legacy package of eco enchants - */ -public class EcoEnchant { - - public boolean conflictsWith(@NotNull Enchantment enchant) { - return false; - } - - public Set getTargets() { - return null; - } - - public EnchantmentType getType() { - return null; - } -} diff --git a/impl/LegacyEcoEnchant/src/main/java/com/willfp/ecoenchants/enchantments/EcoEnchants.java b/impl/LegacyEcoEnchant/src/main/java/com/willfp/ecoenchants/enchantments/EcoEnchants.java deleted file mode 100644 index 39f8064..0000000 --- a/impl/LegacyEcoEnchant/src/main/java/com/willfp/ecoenchants/enchantments/EcoEnchants.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.willfp.ecoenchants.enchantments; - -import java.util.List; - -/** - * Mock class for legacy package of eco enchants - */ -public class EcoEnchants { - - public static List values(){ - return null; // We don't care here. - } - -} diff --git a/impl/LegacyEcoEnchant/src/main/java/com/willfp/ecoenchants/enchantments/meta/EnchantmentTarget.java b/impl/LegacyEcoEnchant/src/main/java/com/willfp/ecoenchants/enchantments/meta/EnchantmentTarget.java deleted file mode 100644 index 19a667b..0000000 --- a/impl/LegacyEcoEnchant/src/main/java/com/willfp/ecoenchants/enchantments/meta/EnchantmentTarget.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.willfp.ecoenchants.enchantments.meta; - -import org.bukkit.Material; - -import java.util.Set; - -/** - * Mock class for legacy package of eco enchants - */ -public class EnchantmentTarget { - - public Set getMaterials() { - return null; - } - -} diff --git a/impl/LegacyEcoEnchant/src/main/java/com/willfp/ecoenchants/enchantments/meta/EnchantmentType.java b/impl/LegacyEcoEnchant/src/main/java/com/willfp/ecoenchants/enchantments/meta/EnchantmentType.java deleted file mode 100644 index 183ec74..0000000 --- a/impl/LegacyEcoEnchant/src/main/java/com/willfp/ecoenchants/enchantments/meta/EnchantmentType.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.willfp.ecoenchants.enchantments.meta; - -public class EnchantmentType { - - public boolean isSingular() { - return false; - } - -} diff --git a/libs/AxPlayerWarps-1.10.3.jar b/libs/AxPlayerWarps-1.10.3.jar deleted file mode 100644 index a32b23c..0000000 Binary files a/libs/AxPlayerWarps-1.10.3.jar and /dev/null differ diff --git a/libs/Disenchantment-6.1.5.jar b/libs/Disenchantment-6.1.5.jar deleted file mode 100644 index a574f38..0000000 Binary files a/libs/Disenchantment-6.1.5.jar and /dev/null differ diff --git a/libs/EnchantsSquared.jar b/libs/EnchantsSquared.jar deleted file mode 100644 index add5768..0000000 Binary files a/libs/EnchantsSquared.jar and /dev/null differ diff --git a/libs/ExcellentEnchants-4.1.0-striped.jar b/libs/ExcellentEnchants-4.1.0-striped.jar deleted file mode 100644 index a3500aa..0000000 Binary files a/libs/ExcellentEnchants-4.1.0-striped.jar and /dev/null differ diff --git a/libs/ExcellentEnchants-4.3.3-striped.jar b/libs/ExcellentEnchants-4.3.3-striped.jar deleted file mode 100644 index ff0656b..0000000 Binary files a/libs/ExcellentEnchants-4.3.3-striped.jar and /dev/null differ diff --git a/libs/HavenBags-1.31.0.1760.jar b/libs/HavenBags-1.31.0.1760.jar deleted file mode 100644 index aed122d..0000000 Binary files a/libs/HavenBags-1.31.0.1760.jar and /dev/null differ diff --git a/libs/SuperEnchants-4.6.2-all.jar b/libs/SuperEnchants-4.6.2-all.jar deleted file mode 100644 index f4c832a..0000000 Binary files a/libs/SuperEnchants-4.6.2-all.jar and /dev/null differ diff --git a/libs/nightcore-2.7.3.jar b/libs/nightcore-2.7.3.jar deleted file mode 100644 index 7ecad8e..0000000 Binary files a/libs/nightcore-2.7.3.jar and /dev/null differ diff --git a/libs/toolstats-1.9.6-stripped.jar b/libs/toolstats-1.9.6-stripped.jar deleted file mode 100644 index eb17393..0000000 Binary files a/libs/toolstats-1.9.6-stripped.jar and /dev/null differ diff --git a/nms/nms-common/.gitignore b/nms/nms-common/.gitignore deleted file mode 100644 index 4f41170..0000000 --- a/nms/nms-common/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.lastDeploymentsId diff --git a/nms/nms-common/build.gradle.kts b/nms/nms-common/build.gradle.kts deleted file mode 100644 index 950d807..0000000 --- a/nms/nms-common/build.gradle.kts +++ /dev/null @@ -1,35 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -group = rootProject.group -version = rootProject.version - -plugins { - id("io.papermc.paperweight.userdev") -} - -dependencies { - // Used for nms - paperweight.paperDevBundle("1.21.10-R0.1-SNAPSHOT") - - // Protocolib - compileOnly("net.dmulloy2:ProtocolLib:5.4.0") -} - -repositories { - maven("https://repo.papermc.io/repository/maven-public/") -} - -// Set target version -tasks.withType().configureEach { - sourceCompatibility = "16" - targetCompatibility = "16" - - options.encoding = "UTF-8" -} - -kotlin { - compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) - jvmTarget.set(JvmTarget.JVM_16) - } -} diff --git a/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/NoPacketManager.kt b/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/NoPacketManager.kt deleted file mode 100644 index c3367f5..0000000 --- a/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/NoPacketManager.kt +++ /dev/null @@ -1,14 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet - -import org.bukkit.entity.Player - -class NoPacketManager: PacketManager { - - override val canSetInstantBuild: Boolean - get() = false - - override fun setInstantBuild(player: Player, instantBuild: Boolean) { - // ProtocoLib not installed and not in a supported version: We do nothing - } - -} diff --git a/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/PacketManager.kt b/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/PacketManager.kt deleted file mode 100644 index 857bfab..0000000 --- a/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/PacketManager.kt +++ /dev/null @@ -1,17 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet - -import org.bukkit.entity.Player - -interface PacketManager { - - /** - * If the provided packet manager if able to set instant build. - */ - val canSetInstantBuild: Boolean - - /** - * Try to set instant build properties - */ - fun setInstantBuild(player: Player, instantBuild: Boolean) - -} diff --git a/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/PacketManagerBase.kt b/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/PacketManagerBase.kt deleted file mode 100644 index 184aa0e..0000000 --- a/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/PacketManagerBase.kt +++ /dev/null @@ -1,16 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet - -import org.bukkit.entity.Player -import org.bukkit.event.Listener - -abstract class PacketManagerBase() : PacketManager, Listener { - - override val canSetInstantBuild: Boolean - get() = false - - override fun setInstantBuild(player: Player, instantBuild: Boolean) { - // Default implementation is empty. - } - - -} diff --git a/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/ProtocoLibWrapper.kt b/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/ProtocoLibWrapper.kt deleted file mode 100644 index 8143b6b..0000000 --- a/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/ProtocoLibWrapper.kt +++ /dev/null @@ -1,39 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet - -import com.comphenix.protocol.PacketType -import com.comphenix.protocol.ProtocolLibrary -import com.comphenix.protocol.ProtocolManager -import com.comphenix.protocol.events.PacketContainer -import org.bukkit.entity.Player -import java.lang.reflect.InvocationTargetException - -class ProtocoLibWrapper: PacketManager { - - private val protocolManager: ProtocolManager = ProtocolLibrary.getProtocolManager(); - - override val canSetInstantBuild: Boolean - get() = true - - override fun setInstantBuild(player: Player, instantBuild: Boolean) { - val packet = PacketContainer(PacketType.Play.Server.ABILITIES) - - // Set player's properties - packet.float - .write(0, player.flySpeed / 2) - .write(1, player.walkSpeed / 2) - - packet.booleans - .write(0, player.isInvulnerable) - .write(1, player.isFlying) - .write(2, player.allowFlight) - .write(3, instantBuild) - - // Send packet - try { - protocolManager.sendServerPacket(player, packet) - } catch (e: InvocationTargetException) { - e.printStackTrace() - } - } - -} diff --git a/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/scheduler/TaskScheduler.kt b/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/scheduler/TaskScheduler.kt deleted file mode 100644 index e6a70dd..0000000 --- a/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/scheduler/TaskScheduler.kt +++ /dev/null @@ -1,18 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.scheduler - -import org.bukkit.entity.Entity -import org.bukkit.plugin.Plugin - -interface TaskScheduler { - - fun scheduleGlobally(plugin: Plugin, task: Runnable, time: Long): Any? - fun scheduleGlobally(plugin: Plugin, task: Runnable): Any?{ - return scheduleGlobally(plugin, task, 0L) - } - - fun scheduleOnEntity(plugin: Plugin, entity: Entity, task: Runnable, time: Long): Any? - fun scheduleOnEntity(plugin: Plugin, entity: Entity, task: Runnable): Any?{ - return scheduleOnEntity(plugin, entity, task, 0L) - } - -} \ No newline at end of file diff --git a/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/util/PaperSpigotUtil.kt b/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/util/PaperSpigotUtil.kt deleted file mode 100644 index 3f709c7..0000000 --- a/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/util/PaperSpigotUtil.kt +++ /dev/null @@ -1,102 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.util - -import net.kyori.adventure.text.Component -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer -import org.bukkit.inventory.ItemStack -import org.bukkit.inventory.meta.ItemMeta - -// Mostly made for paper, spigot and folia support -@Suppress("DEPRECATION") -object PlatformUtil { - - private fun hasClass(className: String): Boolean { - try { - Class.forName(className) - return true - } catch (_: ClassNotFoundException) { - return false - } - } - - private fun hasMethod(clazz: Class<*>, name: String, vararg parameterTypes: Class<*>): Boolean { - try { - clazz.getDeclaredMethod(name, *parameterTypes) - return true - } catch (_: NoSuchMethodException) { - return false - } - } - - val isPaper = hasClass("com.destroystokyo.paper.PaperConfig") || - hasClass("io.papermc.paper.configuration.Configuration") - - val isFolia = hasClass("io.papermc.paper.threadedregions.RegionizedServer") - - private val legacy_mm = LegacyComponentSerializer.legacySection() - - // Lore - fun ItemMeta.componentLore(): MutableList { - val lore: List? - if(isPaper){ - lore = this.lore() - } else { - val legacyLores = this.lore ?: return ArrayList() - - lore = ArrayList(legacyLores.size) - for (legacyLore in legacyLores) { - lore.add(legacy_mm.deserialize(legacyLore)) - } - } - - return lore ?: ArrayList() - } - - fun ItemMeta.setComponentLore(lore: List) { - if(isPaper){ - this.lore(lore) - } else { - val legacyLore = ArrayList(lore.size) - for (component in lore) { - legacyLore.add(if(component == null) null - else legacy_mm.serialize(component)) - } - - this.lore = legacyLore - } - } - - // Display name - private val useCustomName = hasMethod(ItemStack::class.java, "customName") - - fun ItemMeta.componentDisplayName(): Component? { - if(useCustomName){ - if(!this.hasCustomName()) return null - return this.customName() - }else if(isPaper){ - if(!this.hasDisplayName()) return null - return this.displayName() - } else { - if(!this.hasDisplayName()) return null - - val legacy = this.displayName - return legacy_mm.deserialize(legacy) - } - } - - fun ItemMeta.setComponentDisplayName(component: Component?) { - if(useCustomName){ - this.customName(component) - }else if(isPaper){ - this.displayName(component) - } else { - if(component == null){ - this.setDisplayName(null) - return - } - - val legacy = legacy_mm.serialize(component) - this.setDisplayName(legacy) - } - } - -} diff --git a/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dialog/AnvilRenameDialog.kt b/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dialog/AnvilRenameDialog.kt deleted file mode 100644 index df6e883..0000000 --- a/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dialog/AnvilRenameDialog.kt +++ /dev/null @@ -1,23 +0,0 @@ -package xyz.alexcrea.cuanvil.dialog - -import org.bukkit.NamespacedKey -import org.bukkit.entity.HumanEntity -import org.bukkit.event.inventory.PrepareAnvilEvent - -interface AnvilRenameDialog { - - companion object { - val PCD_KEEP_RENAME_TEXT_KEY = NamespacedKey.fromString("customanvil:last_rename_text")!! - } - - fun canSendDialog(): Boolean - - fun tryShowDialog(player: HumanEntity, event: PrepareAnvilEvent) - - fun closeInventory(player: HumanEntity) - - fun currentText(player: HumanEntity): String? - - fun isOpenFor(player: HumanEntity): Boolean - -} \ No newline at end of file diff --git a/nms/nms-paper/.gitignore b/nms/nms-paper/.gitignore deleted file mode 100644 index 47374f1..0000000 --- a/nms/nms-paper/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.lastDeploymentsId \ No newline at end of file diff --git a/nms/nms-paper/build.gradle.kts b/nms/nms-paper/build.gradle.kts deleted file mode 100644 index d0e12a7..0000000 --- a/nms/nms-paper/build.gradle.kts +++ /dev/null @@ -1,35 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -group = rootProject.group -version = rootProject.version - -plugins { - id("io.papermc.paperweight.userdev") -} - -dependencies { - implementation(project(":nms:nms-common")) - - // Used for nms - paperweight.paperDevBundle("1.21.7-R0.1-SNAPSHOT") -} - -repositories { - maven("https://repo.papermc.io/repository/maven-public/") - -} - -// Set target version -tasks.withType().configureEach { - sourceCompatibility = "18" - targetCompatibility = "18" - - options.encoding = "UTF-8" -} - -kotlin { - compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) - jvmTarget.set(JvmTarget.JVM_18) - } -} diff --git a/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/datapack/DataPackTester.kt b/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/datapack/DataPackTester.kt deleted file mode 100644 index 9003fdf..0000000 --- a/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/datapack/DataPackTester.kt +++ /dev/null @@ -1,38 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.datapack - -import io.papermc.paper.datapack.Datapack -import org.bukkit.Bukkit -import org.bukkit.packs.DataPack -import java.util.* - -object DataPackTester { - val legacyNames: List - get() = Bukkit.getDataPackManager().dataPacks - .stream().filter { obj -> obj.isEnabled } - .map { pack -> pack.key.key } - .toList() - - val enabledPacks: List - get() { - try { - // will throw error if do not exist - Bukkit::class.java.getDeclaredMethod("getDatapackManager") - - return Bukkit.getDatapackManager().enabledPacks - .stream().map { obj: Datapack -> obj.name } - .toList() - } catch (e: NoSuchMethodException) { - try { - DataPack::class.java.getDeclaredMethod("getKey") - } catch (e: NoSuchMethodException) { - System.err.println("Could not find compatible datapack manager") - System.err.println("If you are using a datapack that should be compatible with CustomAnvil. It will not get detected...") - return emptyList() - } - return legacyNames - } catch (e: Exception){ - // Assume cause UnimplementedOperationException on mock server - return Collections.emptyList() - } - } -} diff --git a/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/PaperPacketManager.kt b/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/PaperPacketManager.kt deleted file mode 100644 index ee0c101..0000000 --- a/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/PaperPacketManager.kt +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet.versions - -import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket -import net.minecraft.world.entity.player.Abilities -import org.bukkit.craftbukkit.entity.CraftPlayer -import org.bukkit.entity.Player -import xyz.alexcrea.cuanvil.dependency.packet.PacketManager -import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerBase - -class PaperPacketManager : PacketManagerBase(), PacketManager { - override val canSetInstantBuild: Boolean - get() = true - - override fun setInstantBuild(player: Player, instantBuild: Boolean) { - val nmsPlayer = (player as CraftPlayer).handle - val playerAbilities = nmsPlayer.abilities - val sendedAbilities: Abilities - if (playerAbilities.instabuild == instantBuild) { - sendedAbilities = playerAbilities - } else { - sendedAbilities = Abilities() - sendedAbilities.invulnerable = playerAbilities.invulnerable - sendedAbilities.flying = playerAbilities.flying - sendedAbilities.mayfly = playerAbilities.mayfly - sendedAbilities.instabuild = instantBuild - sendedAbilities.mayBuild = playerAbilities.mayBuild - sendedAbilities.setFlyingSpeed(playerAbilities.getFlyingSpeed()) - sendedAbilities.setWalkingSpeed(playerAbilities.getWalkingSpeed()) - } - val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities) - nmsPlayer.connection.send(packet) - } -} diff --git a/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/scheduler/FoliaScheduler.kt b/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/scheduler/FoliaScheduler.kt deleted file mode 100644 index a9bd79f..0000000 --- a/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/scheduler/FoliaScheduler.kt +++ /dev/null @@ -1,40 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.scheduler - -import io.papermc.paper.threadedregions.scheduler.ScheduledTask -import org.bukkit.Bukkit -import org.bukkit.entity.Entity -import org.bukkit.plugin.Plugin -import java.util.function.Consumer - -class FoliaScheduler : TaskScheduler { - override fun scheduleGlobally(plugin: Plugin, task: Runnable, time: Long): Any? { - if(time < 1){ - return Bukkit.getGlobalRegionScheduler().run( - plugin - ) { scheduledTask: ScheduledTask? -> task.run() } - } - return Bukkit.getGlobalRegionScheduler().runDelayed( - plugin, - { scheduledTask: ScheduledTask? -> task.run() }, - time - ) - } - - - override fun scheduleOnEntity(plugin: Plugin, entity: Entity, task: Runnable, time: Long): Any? { - if(time < 1){ - return entity.scheduler.run( - plugin, - { scheduledTask: ScheduledTask? -> task.run() }, - {} - ) - } - return entity.scheduler.runDelayed( - plugin, - { scheduledTask: ScheduledTask? -> task.run() }, - {}, - time - ) - } - -} diff --git a/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dialog/AnvilRenameDialogImpl.kt b/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dialog/AnvilRenameDialogImpl.kt deleted file mode 100644 index e210daa..0000000 --- a/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dialog/AnvilRenameDialogImpl.kt +++ /dev/null @@ -1,236 +0,0 @@ -package xyz.alexcrea.cuanvil.dialog - -import io.papermc.paper.dialog.Dialog -import io.papermc.paper.registry.data.dialog.ActionButton -import io.papermc.paper.registry.data.dialog.DialogBase -import io.papermc.paper.registry.data.dialog.action.DialogAction -import io.papermc.paper.registry.data.dialog.body.DialogBody -import io.papermc.paper.registry.data.dialog.input.DialogInput -import io.papermc.paper.registry.data.dialog.type.DialogType -import io.papermc.paper.threadedregions.scheduler.ScheduledTask -import net.kyori.adventure.text.Component -import net.kyori.adventure.text.event.ClickCallback -import net.kyori.adventure.text.format.TextColor -import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer -import net.minecraft.world.inventory.AnvilMenu -import org.bukkit.craftbukkit.event.CraftEventFactory -import org.bukkit.craftbukkit.inventory.CraftInventoryView -import org.bukkit.craftbukkit.inventory.view.CraftAnvilView -import org.bukkit.entity.HumanEntity -import org.bukkit.event.inventory.PrepareAnvilEvent -import org.bukkit.inventory.InventoryView -import org.bukkit.inventory.ItemStack -import org.bukkit.persistence.PersistentDataType -import org.bukkit.plugin.Plugin -import java.util.* -import java.util.function.BiFunction -import java.util.function.Consumer -import java.util.function.Supplier - -@Suppress("UnstableApiUsage") -class AnvilRenameDialogImpl( - val fromFormated: BiFunction, - val keepUserPreviousDialog: Supplier, - val maxLength: Supplier, - val plugin: Plugin, -) : AnvilRenameDialog { - - companion object { - private const val RENAME_TEXT_KEY = "rename" - - private const val MAX_WIDTH = 512 - - private val PLAIN_TEXT_SERIALIZER = PlainTextComponentSerializer.plainText() - - // Need to be able to translate it later ! - private val USER_FACING_RENAME_TITLE = Component.text("Rename Your Item") - private val USER_FACING_WARNING = Component.text( - "Note that the repair text will appear blank after Confirm\n" + - "But the name will be correctly applied" - ) - private val USER_FACING_CONFIRM = Component.text("Confirm").color(TextColor.fromHexString("#40FF40")) - private val USER_FACING_CANCEL = Component.text("Cancel").color(TextColor.fromHexString("#FF4040")) - - fun itemDefaultName(item: ItemStack?): String? { - return PLAIN_TEXT_SERIALIZER.serializeOrNull(item?.effectiveName()) - } - } - - private val lastNames = HashMap() - private val lastRenames = HashMap() - - - private val lastLeftItem = HashMap() - private val runTaskMap = HashMap() - - // For monetary cost - val hasUiOpen = HashSet() - - private val containerField = CraftInventoryView::class.java.getDeclaredField("container") - - init { - containerField.setAccessible(true) - } - - override fun canSendDialog(): Boolean { - return true - } - - fun makeDialog(playerID: UUID, initial: String?, callback: Consumer): Dialog { - val maxLength = this.maxLength.get() - val initialFinal = initial?.take(maxLength) - - val baseBuilder = DialogBase.builder(USER_FACING_RENAME_TITLE) - .canCloseWithEscape(true) - .afterAction(DialogBase.DialogAfterAction.CLOSE) - .inputs( - listOf( - DialogInput.text(RENAME_TEXT_KEY, Component.text("Rename text")) - .maxLength(maxLength) - .initial(initialFinal ?: "") - .labelVisible(false) - .width(MAX_WIDTH) - .build(), - ), - ) - baseBuilder.body( - listOf( - DialogBody.plainMessage(USER_FACING_WARNING, MAX_WIDTH) - ) - ) - - return Dialog.create { builder -> - builder.empty() - .base(baseBuilder.build()) - .type( - DialogType.confirmation( - ActionButton.builder(USER_FACING_CONFIRM) - .action(DialogAction.customClick({ response, _ -> - hasUiOpen.remove(playerID) - val text = response.getText(RENAME_TEXT_KEY)!! - callback.accept(text) - }, ClickCallback.Options.builder().build())) - .build(), - ActionButton.builder(USER_FACING_CANCEL) - .action(DialogAction.customClick({ response, _ -> - hasUiOpen.remove(playerID) - }, ClickCallback.Options.builder().build())) - .build(), - ) - ) - } - } - - private fun setResult(player: HumanEntity, view: InventoryView, result: String?) { - val defaultName = itemDefaultName(view.getItem(0)) - if (defaultName == result) { - setName(player, view, "", null) - if (defaultName != null) lastNames[player.uniqueId] = defaultName - } else setName(player, view, result, result) - } - - private fun setName(player: HumanEntity, view: InventoryView, name: String?, rename: String?) { - val menu = (containerField.get(view) as AnvilMenu) - val isSameName = menu.itemName == name - menu.itemName = rename - - if (name == null) - lastNames.remove(player.uniqueId) - else - lastNames[player.uniqueId] = name - - if (rename == null) - lastRenames.remove(player.uniqueId) - else - lastRenames[player.uniqueId] = rename - - if (!isSameName) - CraftEventFactory.callPrepareResultEvent(menu, 2); - } - - private fun nameFromItem(player: HumanEntity, item: ItemStack?): String? { - // Already has text - if (item?.hasItemMeta() != true || !item.itemMeta.hasCustomName()) - return PLAIN_TEXT_SERIALIZER.serializeOrNull(item?.effectiveName()) - - if (keepUserPreviousDialog.get() && item.hasItemMeta()) { - val lastName = item.itemMeta.persistentDataContainer.get( - AnvilRenameDialog.PCD_KEEP_RENAME_TEXT_KEY, - PersistentDataType.STRING - ) - - if (lastName != null) return lastName - } - - return fromFormated.apply(player, item.effectiveName()) - } - - private fun tryShowDialogScheduled(player: HumanEntity, event: PrepareAnvilEvent) { - val view = event.view - if (view !is CraftAnvilView) return - - val renameText = view.renameText - val leftItem = view.getItem(0) - val leftItemStr = leftItem?.toString() - - val lastName = lastNames.getOrDefault(player.uniqueId, null) - val lastRename = lastRenames.getOrDefault(player.uniqueId, null) - - if (lastLeftItem.getOrDefault(player.uniqueId, null) != leftItemStr) { - if (leftItemStr == null) - lastLeftItem.remove(player.uniqueId) - else lastLeftItem[player.uniqueId] = leftItemStr - - setName(player, view, renameText, nameFromItem(player, leftItem)) - return - } - - if (lastName == renameText || lastRename == renameText) - return - - if (renameText?.isBlank() == true || renameText == itemDefaultName(leftItem)) { - setName(player, view, lastName, lastRename) - return - } - - val dialog = makeDialog(player.uniqueId, lastRename) - { result -> setResult(player, view, result) } - player.showDialog(dialog) - - hasUiOpen.add(player.uniqueId) - } - - // We need to wait for a short time as changing item will change the name BEFORE the item change - // no guaranty both of them came in the same tick too so let's wait 2 tick.... - override fun tryShowDialog(player: HumanEntity, event: PrepareAnvilEvent) { - runTaskMap.remove(player.uniqueId)?.cancel() - - val task = player.scheduler.runDelayed( - plugin, - { _ -> - run { tryShowDialogScheduled(player, event) } - }, - {}, - 2 - ) - if (task == null) return - - runTaskMap[player.uniqueId] = task - } - - override fun closeInventory(player: HumanEntity) { - lastNames.remove(player.uniqueId) - lastRenames.remove(player.uniqueId) - lastLeftItem.remove(player.uniqueId) - runTaskMap.remove(player.uniqueId)?.cancel() - } - - override fun currentText(player: HumanEntity): String? { - return lastNames[player.uniqueId] - } - - override fun isOpenFor(player: HumanEntity): Boolean { - return hasUiOpen.contains(player.uniqueId) - } - -} \ No newline at end of file diff --git a/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilTitleUtil.kt b/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilTitleUtil.kt deleted file mode 100644 index e40e7ed..0000000 --- a/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilTitleUtil.kt +++ /dev/null @@ -1,45 +0,0 @@ -package xyz.alexcrea.cuanvil.util - -import io.papermc.paper.threadedregions.scheduler.ScheduledTask -import org.bukkit.entity.HumanEntity -import org.bukkit.inventory.InventoryView -import org.bukkit.plugin.Plugin -import xyz.alexcrea.cuanvil.dialog.AnvilRenameDialog -import java.util.HashMap -import java.util.UUID - -object AnvilTitleUtil { - - private val runTaskMap = HashMap() - - private fun actualRename(view: InventoryView, name: String, player: HumanEntity, anvilDialog: AnvilRenameDialog) { - runTaskMap.remove(player.uniqueId) - if (view.title == name) return - - // We assume rename impl is used - if (anvilDialog.isOpenFor(player)) return - - view.title = name - } - - // We don't want to rename instantly it is causing issue with rename text - // especially as it can "override" current ui when it is rename ui time but rename ui also need some delay - fun rename(view: InventoryView, name: String, player: HumanEntity, anvilDialog: AnvilRenameDialog, plugin: Plugin) { - runTaskMap.remove(player.uniqueId)?.cancel() - - val task = player.scheduler.runDelayed( - plugin, - { _ -> - run { actualRename(view, name, player, anvilDialog) } - }, - { - runTaskMap.remove(player.uniqueId) - }, - 2 - ) - - if (task == null) return - runTaskMap[player.uniqueId] = task - } - -} \ No newline at end of file diff --git a/nms/v1_17R1/.gitignore b/nms/v1_17R1/.gitignore deleted file mode 100644 index 47374f1..0000000 --- a/nms/v1_17R1/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.lastDeploymentsId \ No newline at end of file diff --git a/nms/v1_17R1/build.gradle.kts b/nms/v1_17R1/build.gradle.kts deleted file mode 100644 index c354b1c..0000000 --- a/nms/v1_17R1/build.gradle.kts +++ /dev/null @@ -1,35 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -group = rootProject.group -version = rootProject.version - -plugins { - id("io.papermc.paperweight.userdev") -} - -dependencies { - implementation(project(":nms:nms-common")) - - // Used for nms - paperweight.paperDevBundle("1.17.1-R0.1-SNAPSHOT") -} - -repositories { - maven("https://repo.papermc.io/repository/maven-public/") - -} - -// Set target version -tasks.withType().configureEach { - sourceCompatibility = "16" - targetCompatibility = "16" - - options.encoding = "UTF-8" -} - -kotlin { - compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) - jvmTarget.set(JvmTarget.JVM_16) - } -} diff --git a/nms/v1_17R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_17R1_PacketManager.kt b/nms/v1_17R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_17R1_PacketManager.kt deleted file mode 100644 index c820eab..0000000 --- a/nms/v1_17R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_17R1_PacketManager.kt +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet.versions - -import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket -import net.minecraft.world.entity.player.Abilities -import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer -import org.bukkit.entity.Player -import xyz.alexcrea.cuanvil.dependency.packet.PacketManager -import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerBase - -class V1_17R1_PacketManager : PacketManagerBase(), PacketManager { - override val canSetInstantBuild: Boolean - get() = true - - override fun setInstantBuild(player: Player, instantBuild: Boolean) { - val nmsPlayer = (player as CraftPlayer).handle - val playerAbilities = nmsPlayer.abilities - val sendedAbilities: Abilities - if (playerAbilities.instabuild == instantBuild) { - sendedAbilities = playerAbilities - } else { - sendedAbilities = Abilities() - sendedAbilities.invulnerable = playerAbilities.invulnerable - sendedAbilities.flying = playerAbilities.flying - sendedAbilities.mayfly = playerAbilities.mayfly - sendedAbilities.instabuild = instantBuild - sendedAbilities.mayBuild = playerAbilities.mayBuild - sendedAbilities.flyingSpeed = playerAbilities.flyingSpeed - sendedAbilities.walkingSpeed = playerAbilities.walkingSpeed - } - val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities) - nmsPlayer.connection.send(packet) - } -} diff --git a/nms/v1_18R1/.gitignore b/nms/v1_18R1/.gitignore deleted file mode 100644 index 47374f1..0000000 --- a/nms/v1_18R1/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.lastDeploymentsId \ No newline at end of file diff --git a/nms/v1_18R1/build.gradle.kts b/nms/v1_18R1/build.gradle.kts deleted file mode 100644 index 44873d5..0000000 --- a/nms/v1_18R1/build.gradle.kts +++ /dev/null @@ -1,35 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -group = rootProject.group -version = rootProject.version - -plugins { - id("io.papermc.paperweight.userdev") -} - -dependencies { - implementation(project(":nms:nms-common")) - - // Used for nms - paperweight.paperDevBundle("1.18.1-R0.1-SNAPSHOT") -} - -repositories { - maven("https://repo.papermc.io/repository/maven-public/") - -} - -// Set target version -tasks.withType().configureEach { - sourceCompatibility = "17" - targetCompatibility = "17" - - options.encoding = "UTF-8" -} - -kotlin { - compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) - jvmTarget.set(JvmTarget.JVM_17) - } -} diff --git a/nms/v1_18R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_18R1_PacketManager.kt b/nms/v1_18R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_18R1_PacketManager.kt deleted file mode 100644 index 71df5c7..0000000 --- a/nms/v1_18R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_18R1_PacketManager.kt +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet.versions - -import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket -import net.minecraft.world.entity.player.Abilities -import org.bukkit.craftbukkit.v1_18_R1.entity.CraftPlayer -import org.bukkit.entity.Player -import xyz.alexcrea.cuanvil.dependency.packet.PacketManager -import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerBase - -class V1_18R1_PacketManager : PacketManagerBase(), PacketManager { - override val canSetInstantBuild: Boolean - get() = true - - override fun setInstantBuild(player: Player, instantBuild: Boolean) { - val nmsPlayer = (player as CraftPlayer).handle - val playerAbilities = nmsPlayer.abilities - val sendedAbilities: Abilities - if (playerAbilities.instabuild == instantBuild) { - sendedAbilities = playerAbilities - } else { - sendedAbilities = Abilities() - sendedAbilities.invulnerable = playerAbilities.invulnerable - sendedAbilities.flying = playerAbilities.flying - sendedAbilities.mayfly = playerAbilities.mayfly - sendedAbilities.instabuild = instantBuild - sendedAbilities.mayBuild = playerAbilities.mayBuild - sendedAbilities.flyingSpeed = playerAbilities.flyingSpeed - sendedAbilities.walkingSpeed = playerAbilities.walkingSpeed - } - val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities) - nmsPlayer.connection.send(packet) - } -} diff --git a/nms/v1_18R2/.gitignore b/nms/v1_18R2/.gitignore deleted file mode 100644 index 47374f1..0000000 --- a/nms/v1_18R2/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.lastDeploymentsId \ No newline at end of file diff --git a/nms/v1_18R2/build.gradle.kts b/nms/v1_18R2/build.gradle.kts deleted file mode 100644 index cf349ec..0000000 --- a/nms/v1_18R2/build.gradle.kts +++ /dev/null @@ -1,35 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -group = rootProject.group -version = rootProject.version - -plugins { - id("io.papermc.paperweight.userdev") -} - -dependencies { - implementation(project(":nms:nms-common")) - - // Used for nms - paperweight.paperDevBundle("1.18.2-R0.1-SNAPSHOT") -} - -repositories { - maven("https://repo.papermc.io/repository/maven-public/") - -} - -// Set target version -tasks.withType().configureEach { - sourceCompatibility = "17" - targetCompatibility = "17" - - options.encoding = "UTF-8" -} - -kotlin { - compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) - jvmTarget.set(JvmTarget.JVM_17) - } -} diff --git a/nms/v1_18R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_18R2_PacketManager.kt b/nms/v1_18R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_18R2_PacketManager.kt deleted file mode 100644 index ee442f5..0000000 --- a/nms/v1_18R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_18R2_PacketManager.kt +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet.versions - -import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket -import net.minecraft.world.entity.player.Abilities -import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer -import org.bukkit.entity.Player -import xyz.alexcrea.cuanvil.dependency.packet.PacketManager -import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerBase - -class V1_18R2_PacketManager : PacketManagerBase(), PacketManager { - override val canSetInstantBuild: Boolean - get() = true - - override fun setInstantBuild(player: Player, instantBuild: Boolean) { - val nmsPlayer = (player as CraftPlayer).handle - val playerAbilities = nmsPlayer.abilities - val sendedAbilities: Abilities - if (playerAbilities.instabuild == instantBuild) { - sendedAbilities = playerAbilities - } else { - sendedAbilities = Abilities() - sendedAbilities.invulnerable = playerAbilities.invulnerable - sendedAbilities.flying = playerAbilities.flying - sendedAbilities.mayfly = playerAbilities.mayfly - sendedAbilities.instabuild = instantBuild - sendedAbilities.mayBuild = playerAbilities.mayBuild - sendedAbilities.flyingSpeed = playerAbilities.flyingSpeed - sendedAbilities.walkingSpeed = playerAbilities.walkingSpeed - } - val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities) - nmsPlayer.connection.send(packet) - } -} diff --git a/nms/v1_19R1/.gitignore b/nms/v1_19R1/.gitignore deleted file mode 100644 index 47374f1..0000000 --- a/nms/v1_19R1/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.lastDeploymentsId \ No newline at end of file diff --git a/nms/v1_19R1/build.gradle.kts b/nms/v1_19R1/build.gradle.kts deleted file mode 100644 index 9791b9b..0000000 --- a/nms/v1_19R1/build.gradle.kts +++ /dev/null @@ -1,35 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -group = rootProject.group -version = rootProject.version - -plugins { - id("io.papermc.paperweight.userdev") -} - -dependencies { - implementation(project(":nms:nms-common")) - - // Used for nms - paperweight.paperDevBundle("1.19.2-R0.1-SNAPSHOT") -} - -repositories { - maven("https://repo.papermc.io/repository/maven-public/") - -} - -// Set target version -tasks.withType().configureEach { - sourceCompatibility = "17" - targetCompatibility = "17" - - options.encoding = "UTF-8" -} - -kotlin { - compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) - jvmTarget.set(JvmTarget.JVM_17) - } -} diff --git a/nms/v1_19R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_19R1_PacketManager.kt b/nms/v1_19R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_19R1_PacketManager.kt deleted file mode 100644 index 7a057fc..0000000 --- a/nms/v1_19R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_19R1_PacketManager.kt +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet.versions - -import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket -import net.minecraft.world.entity.player.Abilities -import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer -import org.bukkit.entity.Player -import xyz.alexcrea.cuanvil.dependency.packet.PacketManager -import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerBase - -class V1_19R1_PacketManager : PacketManagerBase(), PacketManager { - override val canSetInstantBuild: Boolean - get() = true - - override fun setInstantBuild(player: Player, instantBuild: Boolean) { - val nmsPlayer = (player as CraftPlayer).handle - val playerAbilities = nmsPlayer.abilities - val sendedAbilities: Abilities - if (playerAbilities.instabuild == instantBuild) { - sendedAbilities = playerAbilities - } else { - sendedAbilities = Abilities() - sendedAbilities.invulnerable = playerAbilities.invulnerable - sendedAbilities.flying = playerAbilities.flying - sendedAbilities.mayfly = playerAbilities.mayfly - sendedAbilities.instabuild = instantBuild - sendedAbilities.mayBuild = playerAbilities.mayBuild - sendedAbilities.flyingSpeed = playerAbilities.flyingSpeed - sendedAbilities.walkingSpeed = playerAbilities.walkingSpeed - } - val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities) - nmsPlayer.connection.send(packet) - } -} diff --git a/nms/v1_19R2/.gitignore b/nms/v1_19R2/.gitignore deleted file mode 100644 index 47374f1..0000000 --- a/nms/v1_19R2/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.lastDeploymentsId \ No newline at end of file diff --git a/nms/v1_19R2/build.gradle.kts b/nms/v1_19R2/build.gradle.kts deleted file mode 100644 index 88f1a8a..0000000 --- a/nms/v1_19R2/build.gradle.kts +++ /dev/null @@ -1,35 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -group = rootProject.group -version = rootProject.version - -plugins { - id("io.papermc.paperweight.userdev") -} - -dependencies { - implementation(project(":nms:nms-common")) - - // Used for nms - paperweight.paperDevBundle("1.19.3-R0.1-SNAPSHOT") -} - -repositories { - maven("https://repo.papermc.io/repository/maven-public/") - -} - -// Set target version -tasks.withType().configureEach { - sourceCompatibility = "17" - targetCompatibility = "17" - - options.encoding = "UTF-8" -} - -kotlin { - compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) - jvmTarget.set(JvmTarget.JVM_17) - } -} diff --git a/nms/v1_19R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_19R2_PacketManager.kt b/nms/v1_19R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_19R2_PacketManager.kt deleted file mode 100644 index 0d04cd1..0000000 --- a/nms/v1_19R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_19R2_PacketManager.kt +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet.versions - -import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket -import net.minecraft.world.entity.player.Abilities -import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer -import org.bukkit.entity.Player -import xyz.alexcrea.cuanvil.dependency.packet.PacketManager -import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerBase - -class V1_19R2_PacketManager : PacketManagerBase(), PacketManager { - override val canSetInstantBuild: Boolean - get() = true - - override fun setInstantBuild(player: Player, instantBuild: Boolean) { - val nmsPlayer = (player as CraftPlayer).handle - val playerAbilities = nmsPlayer.abilities - val sendedAbilities: Abilities - if (playerAbilities.instabuild == instantBuild) { - sendedAbilities = playerAbilities - } else { - sendedAbilities = Abilities() - sendedAbilities.invulnerable = playerAbilities.invulnerable - sendedAbilities.flying = playerAbilities.flying - sendedAbilities.mayfly = playerAbilities.mayfly - sendedAbilities.instabuild = instantBuild - sendedAbilities.mayBuild = playerAbilities.mayBuild - sendedAbilities.flyingSpeed = playerAbilities.flyingSpeed - sendedAbilities.walkingSpeed = playerAbilities.walkingSpeed - } - val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities) - nmsPlayer.connection.send(packet) - } -} diff --git a/nms/v1_19R3/.gitignore b/nms/v1_19R3/.gitignore deleted file mode 100644 index 47374f1..0000000 --- a/nms/v1_19R3/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.lastDeploymentsId \ No newline at end of file diff --git a/nms/v1_19R3/build.gradle.kts b/nms/v1_19R3/build.gradle.kts deleted file mode 100644 index 3d609af..0000000 --- a/nms/v1_19R3/build.gradle.kts +++ /dev/null @@ -1,35 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -group = rootProject.group -version = rootProject.version - -plugins { - id("io.papermc.paperweight.userdev") -} - -dependencies { - implementation(project(":nms:nms-common")) - - // Used for nms - paperweight.paperDevBundle("1.19.4-R0.1-SNAPSHOT") -} - -repositories { - maven("https://repo.papermc.io/repository/maven-public/") - -} - -// Set target version -tasks.withType().configureEach { - sourceCompatibility = "17" - targetCompatibility = "17" - - options.encoding = "UTF-8" -} - -kotlin { - compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) - jvmTarget.set(JvmTarget.JVM_17) - } -} diff --git a/nms/v1_19R3/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_19R3_PacketManager.kt b/nms/v1_19R3/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_19R3_PacketManager.kt deleted file mode 100644 index 7c72791..0000000 --- a/nms/v1_19R3/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_19R3_PacketManager.kt +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet.versions - -import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket -import net.minecraft.world.entity.player.Abilities -import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer -import org.bukkit.entity.Player -import xyz.alexcrea.cuanvil.dependency.packet.PacketManager -import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerBase - -class V1_19R3_PacketManager : PacketManagerBase(), PacketManager { - override val canSetInstantBuild: Boolean - get() = true - - override fun setInstantBuild(player: Player, instantBuild: Boolean) { - val nmsPlayer = (player as CraftPlayer).handle - val playerAbilities = nmsPlayer.abilities - val sendedAbilities: Abilities - if (playerAbilities.instabuild == instantBuild) { - sendedAbilities = playerAbilities - } else { - sendedAbilities = Abilities() - sendedAbilities.invulnerable = playerAbilities.invulnerable - sendedAbilities.flying = playerAbilities.flying - sendedAbilities.mayfly = playerAbilities.mayfly - sendedAbilities.instabuild = instantBuild - sendedAbilities.mayBuild = playerAbilities.mayBuild - sendedAbilities.flyingSpeed = playerAbilities.flyingSpeed - sendedAbilities.walkingSpeed = playerAbilities.walkingSpeed - } - val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities) - nmsPlayer.connection.send(packet) - } -} diff --git a/nms/v1_20R1/.gitignore b/nms/v1_20R1/.gitignore deleted file mode 100644 index 47374f1..0000000 --- a/nms/v1_20R1/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.lastDeploymentsId \ No newline at end of file diff --git a/nms/v1_20R1/build.gradle.kts b/nms/v1_20R1/build.gradle.kts deleted file mode 100644 index 67b46b5..0000000 --- a/nms/v1_20R1/build.gradle.kts +++ /dev/null @@ -1,35 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -group = rootProject.group -version = rootProject.version - -plugins { - id("io.papermc.paperweight.userdev") -} - -dependencies { - implementation(project(":nms:nms-common")) - - // Used for nms - paperweight.paperDevBundle("1.20.1-R0.1-SNAPSHOT") -} - -repositories { - maven("https://repo.papermc.io/repository/maven-public/") - -} - -// Set target version -tasks.withType().configureEach { - sourceCompatibility = "18" - targetCompatibility = "18" - - options.encoding = "UTF-8" -} - -kotlin { - compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) - jvmTarget.set(JvmTarget.JVM_18) - } -} diff --git a/nms/v1_20R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_20R1_PacketManager.kt b/nms/v1_20R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_20R1_PacketManager.kt deleted file mode 100644 index 1fbac83..0000000 --- a/nms/v1_20R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_20R1_PacketManager.kt +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet.versions - -import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket -import net.minecraft.world.entity.player.Abilities -import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer -import org.bukkit.entity.Player -import xyz.alexcrea.cuanvil.dependency.packet.PacketManager -import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerBase - -class V1_20R1_PacketManager : PacketManagerBase(), PacketManager { - override val canSetInstantBuild: Boolean - get() = true - - override fun setInstantBuild(player: Player, instantBuild: Boolean) { - val nmsPlayer = (player as CraftPlayer).handle - val playerAbilities = nmsPlayer.abilities - val sendedAbilities: Abilities - if (playerAbilities.instabuild == instantBuild) { - sendedAbilities = playerAbilities - } else { - sendedAbilities = Abilities() - sendedAbilities.invulnerable = playerAbilities.invulnerable - sendedAbilities.flying = playerAbilities.flying - sendedAbilities.mayfly = playerAbilities.mayfly - sendedAbilities.instabuild = instantBuild - sendedAbilities.mayBuild = playerAbilities.mayBuild - sendedAbilities.flyingSpeed = playerAbilities.flyingSpeed - sendedAbilities.walkingSpeed = playerAbilities.walkingSpeed - } - val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities) - nmsPlayer.connection.send(packet) - } -} diff --git a/nms/v1_20R2/.gitignore b/nms/v1_20R2/.gitignore deleted file mode 100644 index 47374f1..0000000 --- a/nms/v1_20R2/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.lastDeploymentsId \ No newline at end of file diff --git a/nms/v1_20R2/build.gradle.kts b/nms/v1_20R2/build.gradle.kts deleted file mode 100644 index e8417cd..0000000 --- a/nms/v1_20R2/build.gradle.kts +++ /dev/null @@ -1,35 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -group = rootProject.group -version = rootProject.version - -plugins { - id("io.papermc.paperweight.userdev") -} - -dependencies { - implementation(project(":nms:nms-common")) - - // Used for nms - paperweight.paperDevBundle("1.20.2-R0.1-SNAPSHOT") -} - -repositories { - maven("https://repo.papermc.io/repository/maven-public/") - -} - -// Set target version -tasks.withType().configureEach { - sourceCompatibility = "18" - targetCompatibility = "18" - - options.encoding = "UTF-8" -} - -kotlin { - compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) - jvmTarget.set(JvmTarget.JVM_18) - } -} diff --git a/nms/v1_20R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_20R2_PacketManager.kt b/nms/v1_20R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_20R2_PacketManager.kt deleted file mode 100644 index a2db371..0000000 --- a/nms/v1_20R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_20R2_PacketManager.kt +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet.versions - -import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket -import net.minecraft.world.entity.player.Abilities -import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer -import org.bukkit.entity.Player -import xyz.alexcrea.cuanvil.dependency.packet.PacketManager -import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerBase - -class V1_20R2_PacketManager : PacketManagerBase(), PacketManager { - override val canSetInstantBuild: Boolean - get() = true - - override fun setInstantBuild(player: Player, instantBuild: Boolean) { - val nmsPlayer = (player as CraftPlayer).handle - val playerAbilities = nmsPlayer.abilities - val sendedAbilities: Abilities - if (playerAbilities.instabuild == instantBuild) { - sendedAbilities = playerAbilities - } else { - sendedAbilities = Abilities() - sendedAbilities.invulnerable = playerAbilities.invulnerable - sendedAbilities.flying = playerAbilities.flying - sendedAbilities.mayfly = playerAbilities.mayfly - sendedAbilities.instabuild = instantBuild - sendedAbilities.mayBuild = playerAbilities.mayBuild - sendedAbilities.flyingSpeed = playerAbilities.flyingSpeed - sendedAbilities.walkingSpeed = playerAbilities.walkingSpeed - } - val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities) - nmsPlayer.connection.send(packet) - } -} diff --git a/nms/v1_20R3/.gitignore b/nms/v1_20R3/.gitignore deleted file mode 100644 index 47374f1..0000000 --- a/nms/v1_20R3/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.lastDeploymentsId \ No newline at end of file diff --git a/nms/v1_20R3/build.gradle.kts b/nms/v1_20R3/build.gradle.kts deleted file mode 100644 index c49ff48..0000000 --- a/nms/v1_20R3/build.gradle.kts +++ /dev/null @@ -1,35 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -group = rootProject.group -version = rootProject.version - -plugins { - id("io.papermc.paperweight.userdev") -} - -dependencies { - implementation(project(":nms:nms-common")) - - // Used for nms - paperweight.paperDevBundle("1.20.4-R0.1-SNAPSHOT") -} - -repositories { - maven("https://repo.papermc.io/repository/maven-public/") - -} - -// Set target version -tasks.withType().configureEach { - sourceCompatibility = "18" - targetCompatibility = "18" - - options.encoding = "UTF-8" -} - -kotlin { - compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) - jvmTarget.set(JvmTarget.JVM_18) - } -} diff --git a/nms/v1_20R3/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_20R3_PacketManager.kt b/nms/v1_20R3/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_20R3_PacketManager.kt deleted file mode 100644 index 51c2ecb..0000000 --- a/nms/v1_20R3/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_20R3_PacketManager.kt +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet.versions - -import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket -import net.minecraft.world.entity.player.Abilities -import org.bukkit.craftbukkit.v1_20_R3.entity.CraftPlayer -import org.bukkit.entity.Player -import xyz.alexcrea.cuanvil.dependency.packet.PacketManager -import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerBase - -class V1_20R3_PacketManager : PacketManagerBase(), PacketManager { - override val canSetInstantBuild: Boolean - get() = true - - override fun setInstantBuild(player: Player, instantBuild: Boolean) { - val nmsPlayer = (player as CraftPlayer).handle - val playerAbilities = nmsPlayer.abilities - val sendedAbilities: Abilities - if (playerAbilities.instabuild == instantBuild) { - sendedAbilities = playerAbilities - } else { - sendedAbilities = Abilities() - sendedAbilities.invulnerable = playerAbilities.invulnerable - sendedAbilities.flying = playerAbilities.flying - sendedAbilities.mayfly = playerAbilities.mayfly - sendedAbilities.instabuild = instantBuild - sendedAbilities.mayBuild = playerAbilities.mayBuild - sendedAbilities.flyingSpeed = playerAbilities.flyingSpeed - sendedAbilities.walkingSpeed = playerAbilities.walkingSpeed - } - val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities) - nmsPlayer.connection.send(packet) - } -} diff --git a/nms/v1_20R4/.gitignore b/nms/v1_20R4/.gitignore deleted file mode 100644 index 47374f1..0000000 --- a/nms/v1_20R4/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.lastDeploymentsId \ No newline at end of file diff --git a/nms/v1_20R4/build.gradle.kts b/nms/v1_20R4/build.gradle.kts deleted file mode 100644 index 3b98361..0000000 --- a/nms/v1_20R4/build.gradle.kts +++ /dev/null @@ -1,35 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -group = rootProject.group -version = rootProject.version - -plugins { - id("io.papermc.paperweight.userdev") -} - -dependencies { - implementation(project(":nms:nms-common")) - - // Used for nms - paperweight.paperDevBundle("1.20.6-R0.1-SNAPSHOT") -} - -repositories { - maven("https://repo.papermc.io/repository/maven-public/") - -} - -// Set target version -tasks.withType().configureEach { - sourceCompatibility = "18" - targetCompatibility = "18" - - options.encoding = "UTF-8" -} - -kotlin { - compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) - jvmTarget.set(JvmTarget.JVM_18) - } -} diff --git a/nms/v1_20R4/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_20R4_PacketManager.kt b/nms/v1_20R4/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_20R4_PacketManager.kt deleted file mode 100644 index ac1e504..0000000 --- a/nms/v1_20R4/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_20R4_PacketManager.kt +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet.versions - -import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket -import net.minecraft.world.entity.player.Abilities -import org.bukkit.craftbukkit.entity.CraftPlayer -import org.bukkit.entity.Player -import xyz.alexcrea.cuanvil.dependency.packet.PacketManager -import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerBase - -class V1_20R4_PacketManager : PacketManagerBase(), PacketManager { - override val canSetInstantBuild: Boolean - get() = true - - override fun setInstantBuild(player: Player, instantBuild: Boolean) { - val nmsPlayer = (player as CraftPlayer).handle - val playerAbilities = nmsPlayer.abilities - val sendedAbilities: Abilities - if (playerAbilities.instabuild == instantBuild) { - sendedAbilities = playerAbilities - } else { - sendedAbilities = Abilities() - sendedAbilities.invulnerable = playerAbilities.invulnerable - sendedAbilities.flying = playerAbilities.flying - sendedAbilities.mayfly = playerAbilities.mayfly - sendedAbilities.instabuild = instantBuild - sendedAbilities.mayBuild = playerAbilities.mayBuild - sendedAbilities.flyingSpeed = playerAbilities.flyingSpeed - sendedAbilities.walkingSpeed = playerAbilities.walkingSpeed - } - val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities) - nmsPlayer.connection.send(packet) - } -} diff --git a/nms/v1_20R4/src/main/kotlin/xyz/alexcrea/cuanvil/util/MaxDamageCheckerUtil.kt b/nms/v1_20R4/src/main/kotlin/xyz/alexcrea/cuanvil/util/MaxDamageCheckerUtil.kt deleted file mode 100644 index b3ce0ff..0000000 --- a/nms/v1_20R4/src/main/kotlin/xyz/alexcrea/cuanvil/util/MaxDamageCheckerUtil.kt +++ /dev/null @@ -1,18 +0,0 @@ -package xyz.alexcrea.cuanvil.util - -import org.bukkit.inventory.meta.Damageable - -// I LOVE support of old versions and needing to do modules like that -// That truly is my favorite activity -// TODO clean this one of legacy removal branch -object MaxDamageCheckerUtil { - - /** - * @return max damage or int max if not set - */ - fun getMaxDamage(meta: Damageable): Int { - if(!meta.hasMaxDamage()) return Integer.MAX_VALUE - return meta.maxDamage - } - -} \ No newline at end of file diff --git a/nms/v1_21R1/.gitignore b/nms/v1_21R1/.gitignore deleted file mode 100644 index 47374f1..0000000 --- a/nms/v1_21R1/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.lastDeploymentsId \ No newline at end of file diff --git a/nms/v1_21R1/build.gradle.kts b/nms/v1_21R1/build.gradle.kts deleted file mode 100644 index bf2152c..0000000 --- a/nms/v1_21R1/build.gradle.kts +++ /dev/null @@ -1,35 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -group = rootProject.group -version = rootProject.version - -plugins { - id("io.papermc.paperweight.userdev") -} - -dependencies { - implementation(project(":nms:nms-common")) - - // Used for nms - paperweight.paperDevBundle("1.21.1-R0.1-SNAPSHOT") -} - -repositories { - maven("https://repo.papermc.io/repository/maven-public/") - -} - -// Set target version -tasks.withType().configureEach { - sourceCompatibility = "21" - targetCompatibility = "21" - - options.encoding = "UTF-8" -} - -kotlin { - compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) - jvmTarget.set(JvmTarget.JVM_21) - } -} diff --git a/nms/v1_21R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_21R1_PacketManager.kt b/nms/v1_21R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_21R1_PacketManager.kt deleted file mode 100644 index 4ea9950..0000000 --- a/nms/v1_21R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_21R1_PacketManager.kt +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet.versions - -import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket -import net.minecraft.world.entity.player.Abilities -import org.bukkit.craftbukkit.entity.CraftPlayer -import org.bukkit.entity.Player -import xyz.alexcrea.cuanvil.dependency.packet.PacketManager -import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerBase - -class V1_21R1_PacketManager : PacketManagerBase(), PacketManager { - override val canSetInstantBuild: Boolean - get() = true - - override fun setInstantBuild(player: Player, instantBuild: Boolean) { - val nmsPlayer = (player as CraftPlayer).handle - val playerAbilities = nmsPlayer.abilities - val sendedAbilities: Abilities - if (playerAbilities.instabuild == instantBuild) { - sendedAbilities = playerAbilities - } else { - sendedAbilities = Abilities() - sendedAbilities.invulnerable = playerAbilities.invulnerable - sendedAbilities.flying = playerAbilities.flying - sendedAbilities.mayfly = playerAbilities.mayfly - sendedAbilities.instabuild = instantBuild - sendedAbilities.mayBuild = playerAbilities.mayBuild - sendedAbilities.flyingSpeed = playerAbilities.flyingSpeed - sendedAbilities.walkingSpeed = playerAbilities.walkingSpeed - } - val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities) - nmsPlayer.connection.send(packet) - } -} diff --git a/nms/v1_21R2/.gitignore b/nms/v1_21R2/.gitignore deleted file mode 100644 index 47374f1..0000000 --- a/nms/v1_21R2/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.lastDeploymentsId \ No newline at end of file diff --git a/nms/v1_21R2/build.gradle.kts b/nms/v1_21R2/build.gradle.kts deleted file mode 100644 index e65f6fd..0000000 --- a/nms/v1_21R2/build.gradle.kts +++ /dev/null @@ -1,35 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -group = rootProject.group -version = rootProject.version - -plugins { - id("io.papermc.paperweight.userdev") -} - -dependencies { - implementation(project(":nms:nms-common")) - - // Used for nms - paperweight.paperDevBundle("1.21.3-R0.1-SNAPSHOT") -} - -repositories { - maven("https://repo.papermc.io/repository/maven-public/") - -} - -// Set target version -tasks.withType().configureEach { - sourceCompatibility = "21" - targetCompatibility = "21" - - options.encoding = "UTF-8" -} - -kotlin { - compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) - jvmTarget.set(JvmTarget.JVM_21) - } -} diff --git a/nms/v1_21R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_21R2_PacketManager.kt b/nms/v1_21R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_21R2_PacketManager.kt deleted file mode 100644 index 9d88c20..0000000 --- a/nms/v1_21R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_21R2_PacketManager.kt +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet.versions - -import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket -import net.minecraft.world.entity.player.Abilities -import org.bukkit.craftbukkit.entity.CraftPlayer -import org.bukkit.entity.Player -import xyz.alexcrea.cuanvil.dependency.packet.PacketManager -import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerBase - -class V1_21R2_PacketManager : PacketManagerBase(), PacketManager { - override val canSetInstantBuild: Boolean - get() = true - - override fun setInstantBuild(player: Player, instantBuild: Boolean) { - val nmsPlayer = (player as CraftPlayer).handle - val playerAbilities = nmsPlayer.abilities - val sendedAbilities: Abilities - if (playerAbilities.instabuild == instantBuild) { - sendedAbilities = playerAbilities - } else { - sendedAbilities = Abilities() - sendedAbilities.invulnerable = playerAbilities.invulnerable - sendedAbilities.flying = playerAbilities.flying - sendedAbilities.mayfly = playerAbilities.mayfly - sendedAbilities.instabuild = instantBuild - sendedAbilities.mayBuild = playerAbilities.mayBuild - sendedAbilities.flyingSpeed = playerAbilities.flyingSpeed - sendedAbilities.walkingSpeed = playerAbilities.walkingSpeed - } - val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities) - nmsPlayer.connection.send(packet) - } -} diff --git a/nms/v1_21R3/.gitignore b/nms/v1_21R3/.gitignore deleted file mode 100644 index 47374f1..0000000 --- a/nms/v1_21R3/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.lastDeploymentsId \ No newline at end of file diff --git a/nms/v1_21R3/build.gradle.kts b/nms/v1_21R3/build.gradle.kts deleted file mode 100644 index d06816c..0000000 --- a/nms/v1_21R3/build.gradle.kts +++ /dev/null @@ -1,35 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -group = rootProject.group -version = rootProject.version - -plugins { - id("io.papermc.paperweight.userdev") -} - -dependencies { - implementation(project(":nms:nms-common")) - - // Used for nms - paperweight.paperDevBundle("1.21.4-R0.1-SNAPSHOT") -} - -repositories { - maven("https://repo.papermc.io/repository/maven-public/") - -} - -// Set target version -tasks.withType().configureEach { - sourceCompatibility = "21" - targetCompatibility = "21" - - options.encoding = "UTF-8" -} - -kotlin { - compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) - jvmTarget.set(JvmTarget.JVM_21) - } -} diff --git a/nms/v1_21R3/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_21R3_PacketManager.kt b/nms/v1_21R3/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_21R3_PacketManager.kt deleted file mode 100644 index 0f581d9..0000000 --- a/nms/v1_21R3/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_21R3_PacketManager.kt +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet.versions - -import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket -import net.minecraft.world.entity.player.Abilities -import org.bukkit.craftbukkit.entity.CraftPlayer -import org.bukkit.entity.Player -import xyz.alexcrea.cuanvil.dependency.packet.PacketManager -import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerBase - -class V1_21R3_PacketManager : PacketManagerBase(), PacketManager { - override val canSetInstantBuild: Boolean - get() = true - - override fun setInstantBuild(player: Player, instantBuild: Boolean) { - val nmsPlayer = (player as CraftPlayer).handle - val playerAbilities = nmsPlayer.abilities - val sendedAbilities: Abilities - if (playerAbilities.instabuild == instantBuild) { - sendedAbilities = playerAbilities - } else { - sendedAbilities = Abilities() - sendedAbilities.invulnerable = playerAbilities.invulnerable - sendedAbilities.flying = playerAbilities.flying - sendedAbilities.mayfly = playerAbilities.mayfly - sendedAbilities.instabuild = instantBuild - sendedAbilities.mayBuild = playerAbilities.mayBuild - sendedAbilities.flyingSpeed = playerAbilities.flyingSpeed - sendedAbilities.walkingSpeed = playerAbilities.walkingSpeed - } - val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities) - nmsPlayer.connection.send(packet) - } -} diff --git a/nms/v1_21R4/.gitignore b/nms/v1_21R4/.gitignore deleted file mode 100644 index 47374f1..0000000 --- a/nms/v1_21R4/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.lastDeploymentsId \ No newline at end of file diff --git a/nms/v1_21R4/build.gradle.kts b/nms/v1_21R4/build.gradle.kts deleted file mode 100644 index 8bd22b9..0000000 --- a/nms/v1_21R4/build.gradle.kts +++ /dev/null @@ -1,34 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -group = rootProject.group -version = rootProject.version - -plugins { - id("io.papermc.paperweight.userdev") -} - -dependencies { - implementation(project(":nms:nms-common")) - - // Used for nms - paperweight.paperDevBundle("1.21.5-R0.1-SNAPSHOT") -} - -repositories { - maven("https://repo.papermc.io/repository/maven-public/") -} - -// Set target version -tasks.withType().configureEach { - sourceCompatibility = "21" - targetCompatibility = "21" - - options.encoding = "UTF-8" -} - -kotlin { - compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) - jvmTarget.set(JvmTarget.JVM_21) - } -} diff --git a/nms/v1_21R4/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_21R4_PacketManager.kt b/nms/v1_21R4/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_21R4_PacketManager.kt deleted file mode 100644 index b123625..0000000 --- a/nms/v1_21R4/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_21R4_PacketManager.kt +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet.versions - -import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket -import net.minecraft.world.entity.player.Abilities -import org.bukkit.craftbukkit.entity.CraftPlayer -import org.bukkit.entity.Player -import xyz.alexcrea.cuanvil.dependency.packet.PacketManager -import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerBase - -class V1_21R4_PacketManager : PacketManagerBase(), PacketManager { - override val canSetInstantBuild: Boolean - get() = true - - override fun setInstantBuild(player: Player, instantBuild: Boolean) { - val nmsPlayer = (player as CraftPlayer).handle - val playerAbilities = nmsPlayer.abilities - val sendedAbilities: Abilities - if (playerAbilities.instabuild == instantBuild) { - sendedAbilities = playerAbilities - } else { - sendedAbilities = Abilities() - sendedAbilities.invulnerable = playerAbilities.invulnerable - sendedAbilities.flying = playerAbilities.flying - sendedAbilities.mayfly = playerAbilities.mayfly - sendedAbilities.instabuild = instantBuild - sendedAbilities.mayBuild = playerAbilities.mayBuild - sendedAbilities.flyingSpeed = playerAbilities.flyingSpeed - sendedAbilities.walkingSpeed = playerAbilities.walkingSpeed - } - val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities) - nmsPlayer.connection.send(packet) - } -} diff --git a/nms/v1_21R5/.gitignore b/nms/v1_21R5/.gitignore deleted file mode 100644 index 47374f1..0000000 --- a/nms/v1_21R5/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.lastDeploymentsId \ No newline at end of file diff --git a/nms/v1_21R5/build.gradle.kts b/nms/v1_21R5/build.gradle.kts deleted file mode 100644 index e7f7c47..0000000 --- a/nms/v1_21R5/build.gradle.kts +++ /dev/null @@ -1,34 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -group = rootProject.group -version = rootProject.version - -plugins { - id("io.papermc.paperweight.userdev") -} - -dependencies { - implementation(project(":nms:nms-common")) - - // Used for nms - paperweight.paperDevBundle("1.21.6-R0.1-SNAPSHOT") -} - -repositories { - maven("https://repo.papermc.io/repository/maven-public/") -} - -// Set target version -tasks.withType().configureEach { - sourceCompatibility = "21" - targetCompatibility = "21" - - options.encoding = "UTF-8" -} - -kotlin { - compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) - jvmTarget.set(JvmTarget.JVM_21) - } -} diff --git a/nms/v1_21R5/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_21R5_PacketManager.kt b/nms/v1_21R5/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_21R5_PacketManager.kt deleted file mode 100644 index 561a6af..0000000 --- a/nms/v1_21R5/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_21R5_PacketManager.kt +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet.versions - -import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket -import net.minecraft.world.entity.player.Abilities -import org.bukkit.craftbukkit.entity.CraftPlayer -import org.bukkit.entity.Player -import xyz.alexcrea.cuanvil.dependency.packet.PacketManager -import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerBase - -class V1_21R5_PacketManager : PacketManagerBase(), PacketManager { - override val canSetInstantBuild: Boolean - get() = true - - override fun setInstantBuild(player: Player, instantBuild: Boolean) { - val nmsPlayer = (player as CraftPlayer).handle - val playerAbilities = nmsPlayer.abilities - val sendedAbilities: Abilities - if (playerAbilities.instabuild == instantBuild) { - sendedAbilities = playerAbilities - } else { - sendedAbilities = Abilities() - sendedAbilities.invulnerable = playerAbilities.invulnerable - sendedAbilities.flying = playerAbilities.flying - sendedAbilities.mayfly = playerAbilities.mayfly - sendedAbilities.instabuild = instantBuild - sendedAbilities.mayBuild = playerAbilities.mayBuild - sendedAbilities.flyingSpeed = playerAbilities.flyingSpeed - sendedAbilities.walkingSpeed = playerAbilities.walkingSpeed - } - val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities) - nmsPlayer.connection.send(packet) - } -} diff --git a/nms/v1_21R6/.gitignore b/nms/v1_21R6/.gitignore deleted file mode 100644 index 47374f1..0000000 --- a/nms/v1_21R6/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.lastDeploymentsId \ No newline at end of file diff --git a/nms/v1_21R6/build.gradle.kts b/nms/v1_21R6/build.gradle.kts deleted file mode 100644 index 3189b5c..0000000 --- a/nms/v1_21R6/build.gradle.kts +++ /dev/null @@ -1,34 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -group = rootProject.group -version = rootProject.version - -plugins { - id("io.papermc.paperweight.userdev") -} - -dependencies { - implementation(project(":nms:nms-common")) - - // Used for nms - paperweight.paperDevBundle("1.21.10-R0.1-SNAPSHOT") -} - -repositories { - maven("https://repo.papermc.io/repository/maven-public/") -} - -// Set target version -tasks.withType().configureEach { - sourceCompatibility = "21" - targetCompatibility = "21" - - options.encoding = "UTF-8" -} - -kotlin { - compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) - jvmTarget.set(JvmTarget.JVM_21) - } -} diff --git a/nms/v1_21R6/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/PaperPacketManager.kt b/nms/v1_21R6/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/PaperPacketManager.kt deleted file mode 100644 index ee00666..0000000 --- a/nms/v1_21R6/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/PaperPacketManager.kt +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet.versions - -import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket -import net.minecraft.world.entity.player.Abilities -import org.bukkit.craftbukkit.entity.CraftPlayer -import org.bukkit.entity.Player -import xyz.alexcrea.cuanvil.dependency.packet.PacketManager -import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerBase - -class V1_21R6_PacketManager : PacketManagerBase(), PacketManager { - override val canSetInstantBuild: Boolean - get() = true - - override fun setInstantBuild(player: Player, instantBuild: Boolean) { - val nmsPlayer = (player as CraftPlayer).handle - val playerAbilities = nmsPlayer.abilities - val sendedAbilities: Abilities - if (playerAbilities.instabuild == instantBuild) { - sendedAbilities = playerAbilities - } else { - sendedAbilities = Abilities() - sendedAbilities.invulnerable = playerAbilities.invulnerable - sendedAbilities.flying = playerAbilities.flying - sendedAbilities.mayfly = playerAbilities.mayfly - sendedAbilities.instabuild = instantBuild - sendedAbilities.mayBuild = playerAbilities.mayBuild - sendedAbilities.flyingSpeed = playerAbilities.flyingSpeed - sendedAbilities.walkingSpeed = playerAbilities.walkingSpeed - } - val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities) - nmsPlayer.connection.send(packet) - } -} \ No newline at end of file diff --git a/nms/v1_21R7/.gitignore b/nms/v1_21R7/.gitignore deleted file mode 100644 index 47374f1..0000000 --- a/nms/v1_21R7/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.lastDeploymentsId \ No newline at end of file diff --git a/nms/v1_21R7/build.gradle.kts b/nms/v1_21R7/build.gradle.kts deleted file mode 100644 index 91c3111..0000000 --- a/nms/v1_21R7/build.gradle.kts +++ /dev/null @@ -1,34 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -group = rootProject.group -version = rootProject.version - -plugins { - id("io.papermc.paperweight.userdev") -} - -dependencies { - implementation(project(":nms:nms-common")) - - // Used for nms - paperweight.paperDevBundle("1.21.11-R0.1-SNAPSHOT") -} - -repositories { - maven("https://repo.papermc.io/repository/maven-public/") -} - -// Set target version -tasks.withType().configureEach { - sourceCompatibility = "21" - targetCompatibility = "21" - - options.encoding = "UTF-8" -} - -kotlin { - compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) - jvmTarget.set(JvmTarget.JVM_21) - } -} diff --git a/nms/v1_21R7/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_21R7_PacketManager.kt b/nms/v1_21R7/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_21R7_PacketManager.kt deleted file mode 100644 index 59ae9ce..0000000 --- a/nms/v1_21R7/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/versions/V1_21R7_PacketManager.kt +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet.versions - -import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket -import net.minecraft.world.entity.player.Abilities -import org.bukkit.craftbukkit.entity.CraftPlayer -import org.bukkit.entity.Player -import xyz.alexcrea.cuanvil.dependency.packet.PacketManager -import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerBase - -class V1_21R7_PacketManager : PacketManagerBase(), PacketManager { - override val canSetInstantBuild: Boolean - get() = true - - override fun setInstantBuild(player: Player, instantBuild: Boolean) { - val nmsPlayer = (player as CraftPlayer).handle - val playerAbilities = nmsPlayer.abilities - val sendedAbilities: Abilities - if (playerAbilities.instabuild == instantBuild) { - sendedAbilities = playerAbilities - } else { - sendedAbilities = Abilities() - sendedAbilities.invulnerable = playerAbilities.invulnerable - sendedAbilities.flying = playerAbilities.flying - sendedAbilities.mayfly = playerAbilities.mayfly - sendedAbilities.instabuild = instantBuild - sendedAbilities.mayBuild = playerAbilities.mayBuild - sendedAbilities.flyingSpeed = playerAbilities.flyingSpeed - sendedAbilities.walkingSpeed = playerAbilities.walkingSpeed - } - val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities) - nmsPlayer.connection.send(packet) - } -} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 9de7d8c..6ffcb1a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,22 +1,2 @@ -rootProject.name = "CustomAnvil" +rootProject.name = "UnsafeEnchants" -// NMS subproject -include("nms:nms-common") -findProject(":nms:nms-common")?.name = "nms-common" -include("nms:nms-paper") -findProject(":nms:nms-paper")?.name = "nms-paper" - - -val reobfNMS = providers.gradleProperty("subprojects.reobfnms") - .get().split(",") - -for (nmsPart in reobfNMS) { - include("nms:$nmsPart") - findProject(":nms:$nmsPart")?.name = nmsPart -} - -// compatibility subprojects -include(":impl:LegacyEcoEnchant") -findProject(":impl:LegacyEcoEnchant")?.name = "LegacyEcoEnchant" -include("impl:ExcellentEnchant5_4") -findProject(":impl:ExcellentEnchant5_4")?.name = "ExcellentEnchant5_4" \ No newline at end of file diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/AnvilRecipeBuilder.java b/src/main/java/xyz/alexcrea/cuanvil/api/AnvilRecipeBuilder.java deleted file mode 100644 index 4292fa0..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/api/AnvilRecipeBuilder.java +++ /dev/null @@ -1,283 +0,0 @@ -package xyz.alexcrea.cuanvil.api; - -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe; - -/** - * A Builder for custom craft using anvil. - */ -@SuppressWarnings("unused") -public class AnvilRecipeBuilder { - - private @NotNull String name; - private boolean exactCount; - - private int levelCostPerCraft; - private int linearXpCostPerCraft; - - private boolean removeExactLinearXp; - - private @Nullable ItemStack leftItem; - private @Nullable ItemStack rightItem; - private @Nullable ItemStack resultItem; - - /** - * Instantiates a new Anvil recipe builder. - * exact count default to true. - * xp level and linear cost per craft default to 0. - * - * @param name The recipe name - */ - public AnvilRecipeBuilder(@NotNull String name) { - this.name = name; - - this.exactCount = true; - this.levelCostPerCraft = 0; - this.linearXpCostPerCraft = 0; - this.removeExactLinearXp = false; - - this.leftItem = null; - this.rightItem = null; - this.resultItem = null; - } - - /** - * Gets the recipe name. - * - * @return This recipe builder instance. - */ - @NotNull - public String getName() { - return name; - } - - /** - * Sets the recipe name. - * - * @param name The recipe name - * @return This recipe builder instance. - */ - public AnvilRecipeBuilder setName(String name) { - this.name = name; - return this; - } - - /** - * Get if the recipe is exact count. (default 0) - *

- * Exact count mean the recipe can only be crafted 1 by 1. - * If set to false, then it will craft as much as possible in 1 go and will keep unused material onto the anvil inventory. - * - * @return If the recipe is exact count. - */ - public boolean isExactCount() { - return exactCount; - } - - /** - * Sets if the recipe is exact count. - *

- * Exact count mean the recipe can only be crafted 1 by 1. - * If set to false, then it will craft as much as possible in 1 go and will keep unused material onto the anvil inventory. - * - * @param exactCount If the recipe is exact count - * @return This recipe builder instance. - */ - public AnvilRecipeBuilder setExactCount(boolean exactCount) { - this.exactCount = exactCount; - return this; - } - - /** - * Get the xp level cost per craft. (default 0) - * - * @return The xp level cost per craft - * @deprecated use {@link #getLevelCostPerCraft() getLevelCostPerCraft} instead - */ - @Deprecated(since = "1.13.0") - public int getXpCostPerCraft() { - return getLevelCostPerCraft(); - } - - /** - * Sets the xp level cost per craft. - * - * @param xpCostPerCraft The xp level cost per craft - * @return This recipe builder instance. - * @deprecated use {@link #setLevelCostPerCraft(int) setLevelCostPerCraft} instead - */ - @Deprecated(since = "1.13.0") - public AnvilRecipeBuilder setXpCostPerCraft(int xpCostPerCraft) { - return setLevelCostPerCraft(xpCostPerCraft); - } - - /** - * Get the xp level cost per craft. (default 0) - * - * @return The xp level cost per craft - */ - public int getLevelCostPerCraft() { - return levelCostPerCraft; - } - - /** - * Sets the xp level cost per craft. - * - * @param levelCostPerCraft The xp level cost per craft - * @return This recipe builder instance. - */ - public AnvilRecipeBuilder setLevelCostPerCraft(int levelCostPerCraft) { - this.levelCostPerCraft = levelCostPerCraft; - return this; - } - - /** - * Get the linear xp cost (not xp level cost) per craft. - * - * @return The xp level cost per craft - */ - public int getLinearXpCostPerCraft() { - return linearXpCostPerCraft; - } - - /** - * Sets the linear xp cost (not xp level cost) per craft. - * - * @param linearXpCostPerCraft The linear xp cost per craft - * @return This recipe builder instance. - */ - public AnvilRecipeBuilder setLinearXpCostPerCraft(int linearXpCostPerCraft) { - this.linearXpCostPerCraft = linearXpCostPerCraft; - return this; - } - - /** - * Get if the linear xp should get removed by an exact amount. - *

- * If false (default) level cost will be the level that would be reached by a player with this amount of xp. - * If true will require the level that has at least the specified level of xp then on click remove only the necessary xp - *

- * linear xp cost are applied after level cost - * @return if we should remove the exact amount of linear xp - */ - public boolean isRemoveExactLinearXp() { - return removeExactLinearXp; - } - - /** - * Set if the linear xp should get removed by an exact amount. - *

- * If false (default) level cost will be the level that would be reached by a player with this amount of xp. - * If true will require the level that has at least the specified level of xp then on click remove only the necessary xp - *

- * linear xp cost are applied after level cost - * @param removeExactLinearXp if we should remove the exact amount of linear xp - * @return This recipe builder instance. - */ - public AnvilRecipeBuilder setRemoveExactLinearXp(boolean removeExactLinearXp) { - this.removeExactLinearXp = removeExactLinearXp; - return this; - } - - /** - * Get the left item of the recipe. - * If null (default) then the recipe will not be able to be registered. - * - * @return The left item - */ - @Nullable - public ItemStack getLeftItem() { - return leftItem; - } - - /** - * Set the left item. - * If null (default) then the recipe will not be able to be registered. - * - * @param leftItem the left item - * @return This recipe builder instance. - */ - public AnvilRecipeBuilder setLeftItem(ItemStack leftItem) { - this.leftItem = leftItem; - return this; - } - - /** - * Get the recipe right item. - * null on default new instance. - * - * @return The right item - */ - @Nullable - public ItemStack getRightItem() { - return rightItem; - } - - /** - * Set the recipe right item. - * null on default new instance. - * - * @param rightItem the right item - * @return This recipe builder instance. - */ - public AnvilRecipeBuilder setRightItem(ItemStack rightItem) { - this.rightItem = rightItem; - return this; - } - - /** - * Get the recipe result item. - * If null (default) then the recipe will not be able to be registered. - * - * @return The result item - */ - @Nullable - public ItemStack getResultItem() { - return resultItem; - } - - /** - * Set the recipe result item. - * If null (default) then the recipe will not be able to be registered. - * - * @param resultItem The result item - * @return This recipe builder instance. - */ - public AnvilRecipeBuilder setResultItem(ItemStack resultItem) { - this.resultItem = resultItem; - return this; - } - - /** - * Build the anvil custom recipe. - * Should probably use {@link #registerIfAbsent() registerIfAbsent} or {@link ConflictAPI#addConflict(ConflictBuilder) addConflict}. - * - * @return A new anvil custom recipe base on this builder. - */ - @Nullable // null if missing argument - public AnvilCustomRecipe build() { - if (leftItem == null || resultItem == null) return null; - - return new AnvilCustomRecipe( - this.name, - this.exactCount, - this.levelCostPerCraft, - this.linearXpCostPerCraft, - this.removeExactLinearXp, - this.leftItem, this.rightItem, this.resultItem - ); - } - - /** - * Register this recipe if absent. - * Equivalent to {@link ConflictAPI#addConflict(ConflictBuilder)} - * - * @return True if successful. - */ - public boolean registerIfAbsent() { - return CustomAnvilRecipeApi.addRecipe(this); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/ConflictAPI.java b/src/main/java/xyz/alexcrea/cuanvil/api/ConflictAPI.java deleted file mode 100644 index fe2715e..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/api/ConflictAPI.java +++ /dev/null @@ -1,196 +0,0 @@ -package xyz.alexcrea.cuanvil.api; - -import io.delilaheve.CustomAnvil; -import org.bukkit.NamespacedKey; -import org.bukkit.configuration.file.FileConfiguration; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.dependency.DependencyManager; -import xyz.alexcrea.cuanvil.group.EnchantConflictGroup; -import xyz.alexcrea.cuanvil.gui.config.global.EnchantConflictGui; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Custom Anvil api for conflict registry. - */ -@SuppressWarnings("unused") -public class ConflictAPI { - - private ConflictAPI() { - } - - private static Object saveChangeTask = null; - private static Object reloadChangeTask = null; - - /** - * Write and add a conflict. - * Will not write the conflict if it already exists. - * Will not be successful if the conflict is empty. - * - * @param builder The conflict builder to be based on - * @return True if successful. - */ - public static boolean addConflict(@NotNull ConflictBuilder builder) { - return addConflict(builder, false); - } - - /** - * Write and add a conflict. - * Will not write the conflict if it already exists. - * Will not be successful if the conflict is empty. - * - * @param builder The conflict builder to be based on - * @param overrideDeleted If we should write even if the conflict was previously deleted. - * @return True if successful. - */ - public static boolean addConflict(@NotNull ConflictBuilder builder, boolean overrideDeleted) { - FileConfiguration config = ConfigHolder.CONFLICT_HOLDER.getConfig(); - - // Test if conflict can be added - if (!overrideDeleted && ConfigHolder.CONFLICT_HOLDER.isDeleted(builder.getName())) return false; - if (config.contains(builder.getName())) return false; - - if (!writeConflict(builder, false)) return false; - - EnchantConflictGroup conflict = builder.build(); - // Register conflict - ConfigHolder.CONFLICT_HOLDER.getConflictManager().addConflict(conflict); - - // Add conflict to gui - EnchantConflictGui conflictGui = EnchantConflictGui.getCurrentInstance(); - if (conflictGui != null) conflictGui.updateValueForGeneric(conflict, true); - - return true; - } - - /** - * Write a conflict to the config file and plan an update of conflicts. - *

- * You may want to use {@link #addConflict(ConflictBuilder)} instead as it is more performance in most case as this function will reload every conflict. - * - * @param builder the builder - * @return true if was written successfully. - */ - public static boolean writeConflict(@NotNull ConflictBuilder builder) { - return writeConflict(builder, true); - } - - /** - * Write a conflict to the config file. - *

- * You should use {@link #addConflict(ConflictBuilder)} or {@link #writeConflict(ConflictBuilder)} instead - * - * @param builder The builder - * @param updatePlanned If we should plan a global update for conflicts - * @return true if was written successfully. - */ - public static boolean writeConflict(@NotNull ConflictBuilder builder, boolean updatePlanned) { - FileConfiguration config = ConfigHolder.CONFLICT_HOLDER.getConfig(); - - String name = builder.getName(); - if (name.contains(".")) { - CustomAnvil.instance.getLogger().warning("Conflict " + name + " contain \".\" in its name but should not. this conflict is ignored."); - logConflictOrigin(builder); - return false; - } - - String basePath = name + "."; - - List enchantments = extractEnchantments(builder); - List excludedGroups = new ArrayList<>(builder.getExcludedGroupNames()); - if (!enchantments.isEmpty()) config.set(basePath + "enchantments", enchantments); - if (!excludedGroups.isEmpty()) config.set(basePath + "notAffectedGroups", excludedGroups); - if (builder.getMaxBeforeConflict() > 0) - config.set(basePath + "maxEnchantmentBeforeConflict", builder.getMaxBeforeConflict()); - - if (!config.isConfigurationSection(name)) return false; - - prepareSaveTask(); - if (updatePlanned) prepareUpdateTask(); - - return true; - } - - /** - * Extract every enchantment names from a builder. - * - * @param builder The builder storing the enchantments - * @return Builder's stored enchantment. - */ - @NotNull - private static List extractEnchantments(@NotNull ConflictBuilder builder) { - List result = new ArrayList<>(builder.getEnchantmentNames()); - for (NamespacedKey enchantmentKey : builder.getEnchantmentKeys()) { - result.add(enchantmentKey.toString()); - } - - return result; - } - - /** - * Remove a conflict. - * - * @param conflict The conflict to remove - * @return True if successful. - */ - public static boolean removeConflict(@NotNull EnchantConflictGroup conflict) { - // Remove from registry - ConfigHolder.CONFLICT_HOLDER.getConflictManager().removeConflict(conflict); - - // Delete and save to file - ConfigHolder.CONFLICT_HOLDER.delete(conflict.getName()); - prepareSaveTask(); - - // Remove from gui - EnchantConflictGui conflictGui = EnchantConflictGui.getCurrentInstance(); - if (conflictGui != null) conflictGui.removeGeneric(conflict); - - return true; - } - - /** - * Prepare a task to save conflict configuration. - */ - private static void prepareSaveTask() { - if (saveChangeTask != null) return; - - saveChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, () -> { - ConfigHolder.CONFLICT_HOLDER.saveToDisk(true); - saveChangeTask = null; - }); - } - - /** - * Prepare a task to reload every conflict. - */ - private static void prepareUpdateTask() { - if (reloadChangeTask != null) return; - - reloadChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, () -> { - ConfigHolder.CONFLICT_HOLDER.reload(); - EnchantConflictGui conflictGui = EnchantConflictGui.getCurrentInstance(); - if (conflictGui != null) conflictGui.reloadValues(); - - reloadChangeTask = null; - }); - } - - static void logConflictOrigin(@NotNull ConflictBuilder builder) { - CustomAnvil.instance.getLogger().warning("Conflict " + builder.getName() + " came from " + builder.getSourceName() + "."); - } - - /** - * Get every registered conflict. - * - * @return An immutable collection of conflict. - */ - @NotNull - public static List getRegisteredConflict() { - List mutableList = ConfigHolder.CONFLICT_HOLDER.getConflictManager().getConflictList(); - return Collections.unmodifiableList(mutableList); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/ConflictBuilder.java b/src/main/java/xyz/alexcrea/cuanvil/api/ConflictBuilder.java deleted file mode 100644 index 1460766..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/api/ConflictBuilder.java +++ /dev/null @@ -1,459 +0,0 @@ -package xyz.alexcrea.cuanvil.api; - -import io.delilaheve.CustomAnvil; -import org.bukkit.NamespacedKey; -import org.bukkit.plugin.Plugin; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; -import xyz.alexcrea.cuanvil.group.*; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -//TODO add conflict after level -/** - * A Builder for material conflict. - */ -@SuppressWarnings("unused") -public class ConflictBuilder { - - private final @Nullable Plugin source; - private @NotNull String name; - - private final @NotNull Set enchantmentNames; - private final @NotNull Set enchantmentKeys; - - private final @NotNull Set excludedGroupNames; - - private int maxBeforeConflict; - - /** - * Instantiates a new Conflict builder. - * - * @param name The conflict name - * @param maxBeforeConflict Maximum number of conflicting enchantment before conflict is active - * @param source The conflict source - */ - public ConflictBuilder(@NotNull String name, int maxBeforeConflict, @Nullable Plugin source) { - this.source = source; - this.name = name; - - this.enchantmentNames = new HashSet<>(); - this.enchantmentKeys = new HashSet<>(); - - this.excludedGroupNames = new HashSet<>(); - - this.maxBeforeConflict = maxBeforeConflict; - } - - /** - * Instantiates a new Conflict builder. - * - * @param name The conflict name - * @param source The conflict source - */ - public ConflictBuilder(@NotNull String name, @Nullable Plugin source) { - this(name, 0, source); - } - - /** - * Instantiates a new Conflict builder. - * - * @param name The conflict name - */ - public ConflictBuilder(@NotNull String name) { - this(name, null); - } - - /** - * Gets conflict source. - * - * @return The conflict source. - */ - @Nullable - public Plugin getSource() { - return source; - } - - /** - * Gets conflict source name. - * - * @return The conflict source name. - */ - @NotNull - public String getSourceName() { - if (source == null) return "an unknown source"; - - return source.getName(); - } - - /** - * Gets conflict name. - * - * @return The conflict name. - */ - @NotNull - public String getName() { - return name; - } - - /** - * Gets stored conflicting enchantment names. - * - * @return The stored enchantment names. - */ - @NotNull - public Set getEnchantmentNames() { - return enchantmentNames; - } - - /** - * Gets stored conflicting enchantment keys. - * - * @return The stored enchantment keys. - */ - @NotNull - public Set getEnchantmentKeys() { - return enchantmentKeys; - } - - /** - * Gets stored excluded group names. - * - * @return The stored group names. - */ - @NotNull - public Set getExcludedGroupNames() { - return excludedGroupNames; - } - - /** - * Gets maximum number of conflicting enchantment before conflict is active. - *

- * This value represent how many enchantment contained on this conflict can be applied to before conflict is considered active. - * That mean new enchantment will not be able to be added to the item and present enchantment will not have its level upgraded. - *

- * In vanilla. material restriction have this value set to 0 and enchantment conflict set to 1. - * - * @return the max number of conflicting enchantment before conflict. 0 by default. - */ - public int getMaxBeforeConflict() { - return maxBeforeConflict; - } - - /** - * Sets conflict name. - * - * @param name The name - * @return This conflict builder instance. - */ - public ConflictBuilder setName(String name) { - this.name = name; - return this; - } - - /** - * Sets maximum number of conflicting enchantment before conflict is active. - *

- * This value represent how many enchantment contained on this conflict can be applied to before conflict is considered active. - * That mean new enchantment will not be able to be added to the item and present enchantment will not have its level upgraded. - *

- * In vanilla. material restriction have this value set to 0 and enchantment conflict set to 1. - * - * @param maxBeforeConflict The max before conflict - * @return This conflict builder instance. - */ - public ConflictBuilder setMaxBeforeConflict(int maxBeforeConflict) { - this.maxBeforeConflict = maxBeforeConflict; - return this; - } - - /** - * Add a conflicting enchantment by name. - * - * @param enchantmentName The enchantment name - * @return This conflict builder instance. - */ - @NotNull - public ConflictBuilder addEnchantment(@NotNull String enchantmentName) { - enchantmentNames.add(enchantmentName); - return this; - } - - /** - * Add a conflicting enchantment by key. - * - * @param enchantmentKey The enchantment key - * @return This conflict builder instance. - */ - @NotNull - public ConflictBuilder addEnchantment(@NotNull NamespacedKey enchantmentKey) { - enchantmentKeys.add(enchantmentKey); - return this; - } - - /** - * Add a conflicting enchantment by instance. - * - * @param enchantment The enchantment - * @return This conflict builder instance. - */ - @NotNull - public ConflictBuilder addEnchantment(@NotNull CAEnchantment enchantment) { - addEnchantment(enchantment.getKey()); - return this; - } - - /** - * Remove conflicting enchantment by name. - * - * @param enchantmentName The enchantment name - * @return This conflict builder instance. - */ - @NotNull - public ConflictBuilder removeEnchantment(@NotNull String enchantmentName) { - enchantmentNames.remove(enchantmentName); - return this; - } - - /** - * Remove conflicting enchantment by key. - * - * @param enchantmentKey The enchantment key - * @return This conflict builder instance. - */ - @NotNull - public ConflictBuilder removeEnchantment(@NotNull NamespacedKey enchantmentKey) { - enchantmentKeys.remove(enchantmentKey); - return removeEnchantment(enchantmentKey.getKey()); - } - - /** - * Remove enchantment by instance. - * - * @param enchantment The enchantment - * @return This conflict builder instance. - */ - @NotNull - public ConflictBuilder removeEnchantment(@NotNull CAEnchantment enchantment) { - return removeEnchantment(enchantment.getKey()); - } - - /** - * Add an excluded group by name. - *

- * If left item of an anvil craft is included on one of the excluded group it will ignore this conflict. - *

- * This allows to create conflict only for some item. Material restriction can be written like that. - *

- * For example: If we exclude a material group containing every pickaxe and add efficiency enchantment - * with {@link #setMaxBeforeConflict(int) maxBeforeConflict} set to 0. - * Then only pickaxe will be able to have efficiency. - * - * @param groupName The group name - * @return This conflict builder instance. - */ - @NotNull - public ConflictBuilder addExcludedGroup(@NotNull String groupName) { - excludedGroupNames.add(groupName); - return this; - } - - /** - * Add an excluded group by instance. - *

- * If left item of an anvil craft is included on one of the excluded group it will ignore this conflict. - *

- * This allows to create conflict only for some item. Material restriction can be written like that. - *

- * For example: If we exclude a material group containing every pickaxe and add efficiency enchantment - * with {@link #setMaxBeforeConflict(int) maxBeforeConflict} set to 0. - * Then only pickaxe will be able to have efficiency. - * - * @param group The group - * @return this conflict builder instance. - */ - @NotNull - public ConflictBuilder addExcludedGroup(@NotNull AbstractMaterialGroup group) { - return addExcludedGroup(group.getName()); - } - - /** - * Remove an excluded group by name. - *

- * If left item of an anvil craft is included on one of the excluded group it will ignore this conflict. - *

- * This allows to create conflict only for some item. Material restriction can be written like that. - *

- * For example: If we exclude a material group containing every pickaxe and add efficiency enchantment - * with {@link #setMaxBeforeConflict(int) maxBeforeConflict} set to 0. - * Then only pickaxe will be able to have efficiency. - * - * @param groupName The group name - * @return This conflict builder instance. - */ - @NotNull - public ConflictBuilder removeExcludedGroup(@NotNull String groupName) { - excludedGroupNames.remove(groupName); - return this; - } - - /** - * Remove an excluded group by instance. - *

- * If left item of an anvil craft is included on one of the excluded group it will ignore this conflict. - *

- * This allows to create conflict only for some item. Material restriction can be written like that. - *

- * For example: If we exclude a material group containing every pickaxe and add efficiency enchantment - * with {@link #setMaxBeforeConflict(int) maxBeforeConflict} set to 0. - * Then only pickaxe will be able to have efficiency. - * - * @param group The group - * @return This conflict builder instance. - */ - @NotNull - public ConflictBuilder removeExcludedGroup(@NotNull AbstractMaterialGroup group) { - return removeExcludedGroup(group.getName()); - } - - /** - * Copy this conflict builder. - * - * @return A copy of this conflict builder. - */ - @NotNull - public ConflictBuilder copy() { - ConflictBuilder copy = new ConflictBuilder(this.name, this.source); - - copy.setMaxBeforeConflict(this.maxBeforeConflict); - - // Set Enchantments - for (NamespacedKey key : this.enchantmentKeys) { - copy.addEnchantment(key); - } - for (String enchantName : this.enchantmentNames) { - copy.addEnchantment(enchantName); - } - - // Set Groups - for (String groupName : this.excludedGroupNames) { - copy.addExcludedGroup(groupName); - } - - return copy; - } - - /** - * Build a new Enchant conflict group by this builder. - * - * @return An Enchant conflict group with this builder parameters. - */ - public EnchantConflictGroup build() { - AbstractMaterialGroup materials = extractGroups(); - EnchantConflictGroup conflict = new EnchantConflictGroup(getName(), materials, getMaxBeforeConflict()); - appendEnchantments(conflict); - - return conflict; - } - - /** - * Register this conflict if not yet registered. - * Equivalent to {@link ConflictAPI#addConflict(ConflictBuilder, boolean) ConflictAPI.addConflict(this, true)}} - * - * @return True if successful. - */ - public boolean registerIfAbsent() { - return ConflictAPI.addConflict(this, true); - } - - /** - * Register this conflict if not yet registered or deleted. - * Equivalent to {@link ConflictAPI#addConflict(ConflictBuilder) ConflictAPI.addConflict(this)} - * - * @return True if successful. - */ - public boolean registerIfNew() { - return ConflictAPI.addConflict(this); - } - - /** - * Append builders stored enchantments into conflict. - * - * @param conflict The conflict target - */ - protected void appendEnchantments(@NotNull EnchantConflictGroup conflict) { - for (String enchantmentName : getEnchantmentNames()) { - if (appendEnchantments(conflict, EnchantmentApi.getListByName(enchantmentName)) == 0) { - CustomAnvil.instance.getLogger().warning("Could not find enchantment " + enchantmentName + " for conflict " + getName()); - ConflictAPI.logConflictOrigin(this); - } - } - for (NamespacedKey enchantmentKey : getEnchantmentKeys()) { - if (!appendEnchantment(conflict, EnchantmentApi.getByKey(enchantmentKey))) { - CustomAnvil.instance.getLogger().warning("Could not find enchantment " + enchantmentKey + " for conflict " + getName()); - ConflictAPI.logConflictOrigin(this); - } - } - } - - /** - * Append an enchantment. - * - * @param conflict The conflict target - * @param enchantment The enchantment - * @return True if successful. - */ - protected static boolean appendEnchantment(@NotNull EnchantConflictGroup conflict, @Nullable CAEnchantment enchantment) { - if (enchantment == null) - return false; - conflict.addEnchantment(enchantment); - return true; - } - - /** - * Append a list of enchantments. - * - * @param conflict The conflict target - * @param enchantments List of enchantment to add - * @return Number of enchantment added - */ - protected static int appendEnchantments(@NotNull EnchantConflictGroup conflict, @NotNull List enchantments) { - int numberValid = 0; - for (CAEnchantment enchantment : enchantments) { - if (appendEnchantment(conflict, enchantment)) { - numberValid++; - } - } - - return numberValid; - } - - /** - * Extract group abstract material group. - * - * @return The abstract material group from the builder. - */ - protected AbstractMaterialGroup extractGroups() { - ItemGroupManager itemGroupManager = ConfigHolder.ITEM_GROUP_HOLDER.getItemGroupsManager(); - IncludeGroup group = new IncludeGroup(EnchantConflictManager.DEFAULT_GROUP_NAME); - - for (String groupName : getExcludedGroupNames()) { - AbstractMaterialGroup materialGroup = itemGroupManager.get(groupName); - - if (materialGroup == null) { - CustomAnvil.instance.getLogger().warning("Material group " + groupName + " do not exist but is ask by conflict " + getName()); - ConflictAPI.logConflictOrigin(this); - continue; - } - - group.addToPolicy(materialGroup); - } - - return group; - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApi.java b/src/main/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApi.java deleted file mode 100644 index 8f80aa3..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApi.java +++ /dev/null @@ -1,126 +0,0 @@ -package xyz.alexcrea.cuanvil.api; - -import io.delilaheve.CustomAnvil; -import org.bukkit.configuration.file.FileConfiguration; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.dependency.DependencyManager; -import xyz.alexcrea.cuanvil.gui.config.global.CustomRecipeConfigGui; -import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe; - -import java.util.Collections; -import java.util.List; - -/** - * Custom Anvil api for custom anvil recipes. - */ -@SuppressWarnings("unused") -public class CustomAnvilRecipeApi { - - private CustomAnvilRecipeApi(){} - - private static Object saveChangeTask = null; - - /** - * Write and add a custom anvil recipe. - * Will not write the recipe if it already exists. - * - * @param builder The recipe builder to be based on - * @return True if successful. - */ - public static boolean addRecipe(@NotNull AnvilRecipeBuilder builder){ - return addRecipe(builder, false); - } - - /** - * Write and add a custom anvil recipe. - * Will not write the recipe if it already exists. - * - * @param builder The recipe builder to be based on - * @param overrideDeleted If we should write even if the recipe was previously deleted. - * @return True if successful. - */ - public static boolean addRecipe(@NotNull AnvilRecipeBuilder builder, boolean overrideDeleted){ - FileConfiguration config = ConfigHolder.CUSTOM_RECIPE_HOLDER.getConfig(); - String name = builder.getName(); - - if(!overrideDeleted && ConfigHolder.CUSTOM_RECIPE_HOLDER.isDeleted(builder.getName())) return false; - if(config.contains(builder.getName())) return false; - - if(builder.getName().contains(".")) { - CustomAnvil.instance.getLogger().warning("Custom anvil recipe " + name + " contain \".\" in its name but should not. this recipe is ignored."); - return false; - } - - AnvilCustomRecipe recipe = builder.build(); - if(recipe == null){ - CustomAnvil.instance.getLogger().warning("Custom anvil recipe " + name + " could not be parsed."); - if(builder.getLeftItem() == null){ - CustomAnvil.instance.getLogger().warning("It look like left item of the recipe is null."); - } - if(builder.getResultItem() == null){ - CustomAnvil.instance.getLogger().warning("It look like result item of the recipe is null."); - } - return false; - } - - // Add to registry - ConfigHolder.CUSTOM_RECIPE_HOLDER.getRecipeManager().cleanAddNew(recipe); - - // Save to file - recipe.saveToFile(false, false); - prepareSaveTask(); - - // Add from gui - CustomRecipeConfigGui recipeConfigGui = CustomRecipeConfigGui.getCurrentInstance(); - if(recipeConfigGui != null) recipeConfigGui.updateValueForGeneric(recipe, true); - - return true; - } - - // TODO remove by name and/or by builder (as name is keept) (and maybe create a get by name) - /** - * Remove a custom anvil recipe. - * - * @param recipe The recipe to remove - * @return True if successful. - */ - public static boolean removeRecipe(@NotNull AnvilCustomRecipe recipe){ - // Remove from registry - boolean result = ConfigHolder.CUSTOM_RECIPE_HOLDER.getRecipeManager().cleanRemove(recipe); - if(!result) return false; - - // Delete and save to file - ConfigHolder.CUSTOM_RECIPE_HOLDER.delete(recipe.getName()); - prepareSaveTask(); - - // Remove from gui - CustomRecipeConfigGui recipeConfigGui = CustomRecipeConfigGui.getCurrentInstance(); - if(recipeConfigGui != null) recipeConfigGui.removeGeneric(recipe); - - return true; - } - - /** - * Prepare a task to save custom recipe configuration. - */ - private static void prepareSaveTask() { - if(saveChangeTask != null) return; - - saveChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, ()->{ - ConfigHolder.CONFLICT_HOLDER.saveToDisk(true); - saveChangeTask = null; - }); - } - - /** - * Get every registered recipes. - * @return An immutable collection of recipes. - */ - @NotNull - public static List getRegisteredRecipes(){ - List mutableList = ConfigHolder.CUSTOM_RECIPE_HOLDER.getRecipeManager().getRecipeList(); - return Collections.unmodifiableList(mutableList); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/EnchantmentApi.java b/src/main/java/xyz/alexcrea/cuanvil/api/EnchantmentApi.java deleted file mode 100644 index ac98225..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/api/EnchantmentApi.java +++ /dev/null @@ -1,235 +0,0 @@ -package xyz.alexcrea.cuanvil.api; - -import io.delilaheve.CustomAnvil; -import io.delilaheve.util.ConfigOptions; -import org.bukkit.NamespacedKey; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.enchantments.Enchantment; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.dependency.DependencyManager; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; -import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry; -import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity; -import xyz.alexcrea.cuanvil.enchant.bulk.BulkCleanEnchantOperation; -import xyz.alexcrea.cuanvil.enchant.bulk.BulkGetEnchantOperation; -import xyz.alexcrea.cuanvil.enchant.wrapped.CABukkitEnchantment; -import xyz.alexcrea.cuanvil.gui.config.global.EnchantCostConfigGui; -import xyz.alexcrea.cuanvil.gui.config.global.EnchantLimitConfigGui; - -import java.util.Collections; -import java.util.List; -import java.util.Map; - -/** - * Custom Anvil api for enchantment registry. - */ -@SuppressWarnings("unused") -public class EnchantmentApi { - - private static Object saveChangeTask = null; - - private EnchantmentApi() {} - - /** - * Register an enchantment. - * - * @param enchantment The enchantment to register - * @return True if successful. - */ - public static boolean registerEnchantment(@NotNull CAEnchantment enchantment){ - if(!CAEnchantmentRegistry.getInstance().register(enchantment)) return false; - - // Add enchantment to gui. - if(EnchantCostConfigGui.getInstance() != null){ - EnchantCostConfigGui.getInstance().updateValueForGeneric(enchantment, true); - } - if(EnchantLimitConfigGui.getInstance() != null){ - EnchantLimitConfigGui.getInstance().updateValueForGeneric(enchantment, true); - } - - // Write default if do not exist - writeDefaultConfig(enchantment, false); - - return true; - } - - /** - * Register an enchantment by minecraft registered enchantment instance. - * - * @param enchantment The enchantment to register - * @param defaultRarity The default rarity of the provided enchantment - * @return True if successful. - */ - public static boolean registerEnchantment(@NotNull Enchantment enchantment, @Nullable EnchantmentRarity defaultRarity){ - if(defaultRarity == null) - return registerEnchantment(new CABukkitEnchantment(enchantment)); - - return registerEnchantment(new CABukkitEnchantment(enchantment, defaultRarity)); - } - - /** - * Register an enchantment by minecraft registered enchantment instance. - *

- * Please note that this function assume the provided enchantment is registered into minecraft registry. - * - * @param enchantment The enchantment to register - * @return True if successful. - */ - public static boolean registerEnchantment(@NotNull Enchantment enchantment){ - return registerEnchantment(new CABukkitEnchantment(enchantment)); - } - - /** - * Unregister an enchantment. - * - * @param enchantment The enchantment to unregister - * @return True if successful. - */ - public static boolean unregisterEnchantment(@Nullable CAEnchantment enchantment){ - // Remove from gui - if(EnchantCostConfigGui.getInstance() != null){ - EnchantCostConfigGui.getInstance().removeGeneric(enchantment); - } - if(EnchantLimitConfigGui.getInstance() != null){ - EnchantLimitConfigGui.getInstance().removeGeneric(enchantment); - } - - return CAEnchantmentRegistry.getInstance().unregister(enchantment); - } - - /** - * Unregister an enchantment by its key. - * - * @param key The enchantment key to unregister - * @return True if successful. - */ - public static boolean unregisterEnchantment(@NotNull NamespacedKey key){ - CAEnchantment enchantment = CAEnchantment.getByKey(key); - return unregisterEnchantment(enchantment); - } - - /** - * Unregister an enchantment by his bukkit enchantment. - * - * @param enchantment The enchantment to unregister - * @return True if successful. - */ - public static boolean unregisterEnchantment(@NotNull Enchantment enchantment){ - return unregisterEnchantment(enchantment.getKey()); - } - - /** - * Get by key an enchantment. - * - * @param key The key used to fetch - * @return The custom anvil enchantment of this key. null if not found. - */ - @Nullable - public static CAEnchantment getByKey(@NotNull NamespacedKey key){ - return CAEnchantment.getByKey(key); - } - - /** - * Get by name an enchantment. - * - * @param name The name used to fetch - * @return The custom anvil enchantment of this name. null if not found. - * @deprecated use {@link #getListByName(String)} - */ - @Deprecated(since = "1.6.3") - @Nullable - public static CAEnchantment getByName(@NotNull String name){ - return CAEnchantment.getByName(name); - } - - /** - * Get list of enchantment using the provided name. - * - * @param name The name used to fetch - * @return List of custom anvil enchantments of this name. May be empty if not found. - */ - public static List getListByName(@NotNull String name){ - return CAEnchantment.getListByName(name); - } - - /** - * Get every registered custom anvil enchantments. - * @return An immutable map of enchantment key as map key and custom anvil enchantment as value. - */ - @NotNull - public static Map getRegisteredEnchantments(){ - return Collections.unmodifiableMap(CAEnchantmentRegistry.getInstance().registeredEnchantments()); - } - - /** - * Write the default level and rarity configuration of the enchantment. - * @param enchantment The enchantment to write default configuration - * @param override If it should override old configuration - * @return Return false if override is false and a configuration exist. true otherwise. - */ - public static boolean writeDefaultConfig(CAEnchantment enchantment, boolean override){ - FileConfiguration config = ConfigHolder.DEFAULT_CONFIG.getConfig(); - - if(tryWriteDefaultConfig(config, enchantment, override)){ - prepareSaveTask(); - } - return true; - } - - private static boolean tryWriteDefaultConfig(FileConfiguration defaultConfig, CAEnchantment enchantment, boolean override) { - boolean hasChange = false; - - String levelPath = ConfigOptions.ENCHANT_LIMIT_ROOT + "." + enchantment.getKey(); - if(override || !defaultConfig.isSet(levelPath)){ - defaultConfig.set(levelPath, enchantment.defaultMaxLevel()); - hasChange = true; - } - - String basePath = ConfigOptions.ENCHANT_VALUES_ROOT + "." + enchantment.getKey(); - EnchantmentRarity rarity = enchantment.defaultRarity(); - - String itemPath = basePath + ".item"; - String bookPath = basePath + ".book"; - if(override || !defaultConfig.isSet(itemPath)){ - defaultConfig.set(itemPath, rarity.getItemValue()); - hasChange = true; - } - if(override || !defaultConfig.isSet(bookPath)){ - defaultConfig.set(bookPath, rarity.getBookValue()); - hasChange = true; - } - - return hasChange; - } - - /** - * Prepare a task to save custom recipe configuration. - */ - private static void prepareSaveTask() { - if(saveChangeTask != null) return; - - saveChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, ()->{ - ConfigHolder.DEFAULT_CONFIG.saveToDisk(true); - saveChangeTask = null; - }); - } - - /** - * Add a bulk get operator. - * @param operation An optimised get enchantments operation - */ - public static void addBulkGet(@NotNull BulkGetEnchantOperation operation){ - CAEnchantmentRegistry.getInstance().getOptimisedGetOperators().add(operation); - } - - /** - * Add a bulk clean operator. - * @param operation An optimised clean enchantments operation - */ - public static void addBulkClean(@NotNull BulkCleanEnchantOperation operation){ - CAEnchantmentRegistry.getInstance().getOptimisedCleanOperators().add(operation); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/MaterialGroupApi.java b/src/main/java/xyz/alexcrea/cuanvil/api/MaterialGroupApi.java deleted file mode 100644 index cd71c7a..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/api/MaterialGroupApi.java +++ /dev/null @@ -1,251 +0,0 @@ -package xyz.alexcrea.cuanvil.api; - -import io.delilaheve.CustomAnvil; -import io.delilaheve.util.ConfigOptions; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.configuration.file.FileConfiguration; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.dependency.DependencyManager; -import xyz.alexcrea.cuanvil.group.AbstractMaterialGroup; -import xyz.alexcrea.cuanvil.group.ExcludeGroup; -import xyz.alexcrea.cuanvil.group.IncludeGroup; -import xyz.alexcrea.cuanvil.group.ItemGroupManager; -import xyz.alexcrea.cuanvil.gui.config.global.GroupConfigGui; - -import java.util.*; - -/** - * Custom Anvil api for material group registry. - */ -@SuppressWarnings("unused") -public class MaterialGroupApi { - - private MaterialGroupApi() { - } - - private static Object saveChangeTask = null; - private static Object reloadChangeTask = null; - - /** - * Write and add a group. - * Will not write the group if it already exists. - * Will not be successful if the group is empty. - * - * @param group The group to add - * @return true if successful. - */ - public static boolean addMaterialGroup(@NotNull AbstractMaterialGroup group) { - return addMaterialGroup(group, false); - } - - /** - * Write and add a group. - * Will not write the group if it already exists. - * Will not be successful if the group is empty. - * - * @param group The group to add - * @param overrideDeleted If we should write even if the group was previously deleted. - * @return true if successful. - */ - public static boolean addMaterialGroup(@NotNull AbstractMaterialGroup group, boolean overrideDeleted) { - ItemGroupManager itemGroupManager = ConfigHolder.ITEM_GROUP_HOLDER.getItemGroupsManager(); - - // Test if it exists/existed - if (!overrideDeleted && ConfigHolder.ITEM_GROUP_HOLDER.isDeleted(group.getName())) return false; - if (itemGroupManager.get(group.getName()) != null) return false; - - // Add group - itemGroupManager.getGroupMap().put(group.getName(), group); - - if (!writeMaterialGroup(group, false)) return false; - - if (group instanceof IncludeGroup includeGroup) { - GroupConfigGui configGui = GroupConfigGui.getCurrentInstance(); - if (configGui != null) configGui.updateValueForGeneric(includeGroup, true); - } - - if (ConfigOptions.INSTANCE.getVerboseDebugLog()) { - CustomAnvil.instance.getLogger().info("Registered group " + group.getName()); - } - - return true; - } - - /** - * Write a material group to the config file and plan an update of groups. - *

- * You may want to use {@link #addMaterialGroup(AbstractMaterialGroup)} instead as it is more performance in most case as this function will reload every conflict. - * - * @param group the group to write - * @return true if was written successfully. - */ - public static boolean writeMaterialGroup(@NotNull AbstractMaterialGroup group) { - return writeMaterialGroup(group, true); - } - - /** - * Write a material group to the config file. - *

- * You should use {@link #addMaterialGroup(AbstractMaterialGroup)} or {@link #writeMaterialGroup(AbstractMaterialGroup)} instead - * - * @param group the group to write - * @param updatePlanned if we should plan a global update for material groups - * @return true if was written successfully. - */ - public static boolean writeMaterialGroup(@NotNull AbstractMaterialGroup group, boolean updatePlanned) { - String name = group.getName(); - if (name.contains(".")) { - CustomAnvil.instance.getLogger().warning("Group " + name + " contain . in its name but should not. this material group is ignored."); - return false; - } - - boolean changed; - if (group instanceof IncludeGroup includeGroup) { - changed = writeKnownGroup("include", includeGroup); - } else if (group instanceof ExcludeGroup excludeGroup) { - throw new UnsupportedOperationException("exclude group is temporarily disable for the time being. sorry"); - // This code do not do what is intended ? idk why do it exist - //changed = writeKnownGroup("exclude", excludeGroup); - } else { - changed = writeUnknownGroup(group); - } - if (!changed) return false; - - prepareSaveTask(); - if (updatePlanned) prepareUpdateTask(); - - return true; - } - - private static boolean writeKnownGroup(@NotNull String groupType, @NotNull AbstractMaterialGroup group) { - FileConfiguration config = ConfigHolder.ITEM_GROUP_HOLDER.getConfig(); - - String basePath = group.getName() + "."; - Set materialSet = group.getNonGroupInheritedMaterials(); - Set groupSet = group.getGroups(); - - boolean empty = true; - if (!materialSet.isEmpty()) { - config.set(basePath + ItemGroupManager.MATERIAL_LIST_PATH, materialSetToStringList(materialSet)); - empty = false; - } else { - config.set(basePath + ItemGroupManager.MATERIAL_LIST_PATH, null); - } - if (!groupSet.isEmpty()) { - config.set(basePath + ItemGroupManager.GROUP_LIST_PATH, materialGroupSetToStringList(groupSet)); - empty = false; - } else { - config.set(basePath + ItemGroupManager.GROUP_LIST_PATH, null); - } - - if (empty) { - config.set(basePath + ItemGroupManager.GROUP_TYPE_PATH, null); - return false; - } - - config.set(basePath + ItemGroupManager.GROUP_TYPE_PATH, groupType); - return true; - } - - private static boolean writeUnknownGroup(@NotNull AbstractMaterialGroup group) { - FileConfiguration config = ConfigHolder.ITEM_GROUP_HOLDER.getConfig(); - - String basePath = group.getName() + "."; - Set materials = group.getMaterials(); - - if (materials.isEmpty()) return false; - - config.set(basePath + ItemGroupManager.GROUP_TYPE_PATH, "include"); - config.set(basePath + ItemGroupManager.MATERIAL_LIST_PATH, materialSetToStringList(materials)); - - return true; - } - - public static List materialSetToStringList(@NotNull Set materials) { - return materials.stream().map(NamespacedKey::toString).toList(); - } - - public static List materialGroupSetToStringList(@NotNull Set groups) { - return groups.stream().map(AbstractMaterialGroup::getName).toList(); - } - - /** - * Remove a material group. - * Caution ! It will not be removed from depending conflict or other material group at runtime. - * For that reason, it is not recommended to use this function. - * - * @param group The recipe to remove - * @return True if the group was present. - */ - public static boolean removeGroup(@NotNull AbstractMaterialGroup group) { - // Remove from registry - AbstractMaterialGroup removed = ConfigHolder.ITEM_GROUP_HOLDER.getItemGroupsManager().groupMap.remove(group.getName()); - if (removed == null) return false; - - // Delete and save to file - ConfigHolder.ITEM_GROUP_HOLDER.delete(group.getName()); - prepareSaveTask(); - - // Remove from gui - if (group instanceof IncludeGroup includeGroup) { - GroupConfigGui configGui = GroupConfigGui.getCurrentInstance(); - if (configGui != null) configGui.removeGeneric(includeGroup); - } - - return true; - } - - /** - * Prepare a task to reload every conflict. - */ - private static void prepareSaveTask() { - if (saveChangeTask != null) return; - - saveChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, () -> { - ConfigHolder.ITEM_GROUP_HOLDER.saveToDisk(true); - saveChangeTask = null; - }); - } - - /** - * Prepare a task to save configuration. - */ - private static void prepareUpdateTask() { - if (reloadChangeTask != null) return; - - reloadChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, () -> { - ConfigHolder.ITEM_GROUP_HOLDER.reload(); - - GroupConfigGui configGui = GroupConfigGui.getCurrentInstance(); - if (configGui != null) configGui.reloadValues(); - - reloadChangeTask = null; - }); - - } - - /** - * Get by name a group. - * - * @param groupName the group name used to fetch - * @return the abstract group of this name. null if not found. - */ - @Nullable - public static AbstractMaterialGroup getGroup(@NotNull String groupName) { - return ConfigHolder.ITEM_GROUP_HOLDER.getItemGroupsManager().get(groupName); - } - - /** - * Get every registered material groups. - * - * @return An immutable map of group name as its key and group as mapped value. - */ - @NotNull - public static Map getRegisteredGroups() { - return Collections.unmodifiableMap(ConfigHolder.ITEM_GROUP_HOLDER.getItemGroupsManager().getGroupMap()); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/UnitRepairApi.java b/src/main/java/xyz/alexcrea/cuanvil/api/UnitRepairApi.java deleted file mode 100644 index bc50c16..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/api/UnitRepairApi.java +++ /dev/null @@ -1,218 +0,0 @@ -package xyz.alexcrea.cuanvil.api; - -import io.delilaheve.CustomAnvil; -import kotlin.Triple; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.FileConfiguration; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.dependency.DependencyManager; -import xyz.alexcrea.cuanvil.gui.config.global.UnitRepairConfigGui; -import xyz.alexcrea.cuanvil.gui.config.list.MappedGuiListConfigGui; -import xyz.alexcrea.cuanvil.gui.config.list.UnitRepairElementListGui; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Custom Anvil api for unit repair. - */ -@SuppressWarnings("unused") -public class UnitRepairApi { - - private UnitRepairApi(){} - - private static Object saveChangeTask = null; - - /** - * Write and add a custom anvil unit repair recipe. - * Will not write the recipe if it already exists or was deleted. - * Set the value to minecraft default value (0.25 = 25%) - * - * @param unit The unit material used to repair the bellow item. - * @param repairable The item to be repaired. - * @return true if successful. - */ - public static boolean addUnitRepair(@NotNull Material unit, @NotNull Material repairable){ - return addUnitRepair(unit, repairable, 0.25, false); - } - - /** - * Write and add a custom anvil unit repair recipe. - * Will not write the recipe if it already exists or was deleted. - * - * @param unit The unit material used to repair the bellow item. - * @param repairable The item to be repaired. - * @param value The amount to be repaired by every unit. (1% = 0.01) - * @return true if successful. - */ - public static boolean addUnitRepair(@NotNull Material unit, @NotNull Material repairable, double value){ - return addUnitRepair(unit, repairable, value, false); - } - - /** - * Write and add a custom anvil unit repair recipe. - * Will not write the recipe if it already exists. - * - * @param unit The unit material used to repair the bellow item. - * @param repairable The item to be repaired. - * @param value The amount to be repaired by every unit. (1% = 0.01) - * @param overrideDeleted If we should write even if the recipe was previously deleted. - * @return true if successful. - */ - public static boolean addUnitRepair(@NotNull Material unit, @NotNull Material repairable, double value, boolean overrideDeleted){ - FileConfiguration config = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig(); - String path = unit.name().toLowerCase() + "." + repairable.name().toLowerCase(); - - if(!overrideDeleted && ConfigHolder.UNIT_REPAIR_HOLDER.isDeleted(path)) return false; - if(config.contains(path)) return false; - - // Set unit repair - return setUnitRepair(unit, repairable, value); - } - - /** - * Write and add a custom anvil unit repair recipe. - * Do not check if it previously existed or exist. - * - * @param unit The unit material used to repair the bellow item. - * @param repairable The item to be repaired. - * @param value The amount to be repaired by every unit. (1% = 0.01) - * @return true if successful. - */ - public static boolean setUnitRepair(@NotNull Material unit, @NotNull Material repairable, double value){ - FileConfiguration config = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig(); - - String repairableName = repairable.name().toLowerCase(); - String path = unit.name().toLowerCase() + "." + repairableName; - - // Add to config then prepare save - config.set(path, value); - prepareSaveTask(); - - // Add to gui - UnitRepairConfigGui repairConfigGui = UnitRepairConfigGui.getCurrentInstance(); - if(repairConfigGui != null) { - UnitRepairElementListGui elementGui = repairConfigGui.getInstanceOrCreate(unit).getStored(); - - if(elementGui != null) elementGui.updateValueForGeneric(repairableName, true); - repairConfigGui.updateValueForGeneric(unit, true); - } - - return true; - } - - /** - * Remove a custom anvil unit repair recipe. - * - * @param unit The unit material used to repair the bellow item. - * @param repairable The item used to be repaired. - * @return true if successful. - */ - public static boolean removeUnitRepair(@NotNull Material unit, @NotNull Material repairable){ - // Delete every possible variation and save to file - String unitName = unit.name(); - String repairableName = repairable.name(); - - FileConfiguration config = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig(); - config.set(unitName.toLowerCase() + "." + repairableName.toUpperCase(), null); - config.set(unitName.toUpperCase() + "." + repairableName.toLowerCase(), null); - config.set(unitName.toUpperCase() + "." + repairableName.toUpperCase(), null); - config.set(unitName.toLowerCase() + "." + repairableName.toLowerCase(), null); - - // Test if it was the last value of this section - boolean lastValue = false; - if(config.isConfigurationSection(unitName.toLowerCase())) { - ConfigurationSection section = config.getConfigurationSection(unitName.toLowerCase()); - - if(section != null && section.getKeys(false).isEmpty()) { - lastValue = true; - config.set(unitName.toLowerCase(), null); - } - - } else if (config.isConfigurationSection(unitName.toUpperCase())) { - ConfigurationSection section = config.getConfigurationSection(unitName.toUpperCase()); - if(section != null && section.getKeys(false).isEmpty()) { - lastValue = true; - config.set(unitName.toUpperCase(), null); - } - - } else lastValue = true; - - - // We only need to "delete" as the lower case to be counted as deleted - ConfigHolder.UNIT_REPAIR_HOLDER.delete(unitName.toLowerCase() + "." + repairableName.toLowerCase()); - prepareSaveTask(); - - // Remove from gui - UnitRepairConfigGui repairConfigGui = UnitRepairConfigGui.getCurrentInstance(); - if(repairConfigGui != null) { - UnitRepairElementListGui elementGui = repairConfigGui.getInstanceOrCreate(unit).getStored(); - - if(elementGui != null) elementGui.removeGeneric(repairableName); - if(lastValue){ - repairConfigGui.removeGeneric(unit); - } - } - - return true; - } - - /** - * Prepare a task to save custom unit repair recipe configuration. - */ - private static void prepareSaveTask() { - if(saveChangeTask != null) return; - - saveChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, ()->{ - ConfigHolder.UNIT_REPAIR_HOLDER.saveToDisk(true); - saveChangeTask = null; - }); - } - - /** - * Get every unit repair recipes. - * @return An immutable collection of unit repair recipes. - *

- * Each element of the provided triple represent a part of the recipe - *

    - *
  • First object is the unit material used to repair the bellow item. - *
  • Second object is the item to be repaired. - *
  • Last object is the amount to be repaired by every unit. (1% = 0.01) - *
- */ - @NotNull - public static List> getUnitRepairs(){ - List> mutableList = new ArrayList<>(); - - FileConfiguration config = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig(); - for (String unitKey : config.getKeys(false)) { - // Test if config section exist - if(!config.isConfigurationSection(unitKey)) continue; - - // Test if unit is a material - Material unit = Material.getMaterial(unitKey.toUpperCase()); - if(unit == null) continue; - - // Iterate over reparable items - ConfigurationSection section = config.getConfigurationSection(unitKey); - for (String repairableKey : section.getKeys(false)) { - // Test if value section exist - if(!section.isDouble(repairableKey)) continue; - - // Test if repairable is valid a material - Material repairable = Material.getMaterial(repairableKey.toUpperCase()); - if(repairable == null) continue; - - // Add the values - mutableList.add(new Triple<>(unit, repairable, section.getDouble(repairableKey))); - - } - } - - return Collections.unmodifiableList(mutableList); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/event/CAConfigReadyEvent.java b/src/main/java/xyz/alexcrea/cuanvil/api/event/CAConfigReadyEvent.java deleted file mode 100644 index 67d27a8..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/api/event/CAConfigReadyEvent.java +++ /dev/null @@ -1,36 +0,0 @@ -package xyz.alexcrea.cuanvil.api.event; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -/** - * Called when the configuration of CustomAnvil is ready. - * It is called either on the plugin startup or on the plugin config reload. - *

- * If you want to listen to the first trigger of this event (first configuration load. aka plugin load) - * you will need to register the listener on your plugin onEnable or earlier - *

- * This event indicate that can start to register your recipes, item groups and conflicts. - * The vanilla and custom enchantments should already have been provided to CustomAnvil. - * Configuration can be changed any time after this event is triggered but never before. - *

- * use {@link xyz.alexcrea.cuanvil.api.ConflictAPI ConflictApi}, - * {@link xyz.alexcrea.cuanvil.gui.config.global.CustomRecipeConfigGui CustomRecipeConfigGui}, - * {@link xyz.alexcrea.cuanvil.api.MaterialGroupApi MaterialGroupApi} - * and {@link xyz.alexcrea.cuanvil.api.UnitRepairApi UnitRepairApi} - * to add/remove/edit configurations - */ -public class CAConfigReadyEvent extends Event { - - private static final HandlerList HANDLERS = new HandlerList(); - - public static HandlerList getHandlerList() { - return HANDLERS; - } - - @Override - public HandlerList getHandlers() { - return HANDLERS; - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/event/CAEnchantRegistryReadyEvent.java b/src/main/java/xyz/alexcrea/cuanvil/api/event/CAEnchantRegistryReadyEvent.java deleted file mode 100644 index 3ffe372..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/api/event/CAEnchantRegistryReadyEvent.java +++ /dev/null @@ -1,29 +0,0 @@ -package xyz.alexcrea.cuanvil.api.event; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -/** - * Called when custom anvil is ready to accept registration on custom enchantment. - *

- * If you want to listen this event - * you will need to register the listener on your plugin onEnable or earlier - *

- * Custom enchantments may be registered later but may cause issue if registered too later - * (after configuration loading phase. see {@link CAConfigReadyEvent}) - *

- * use {@link xyz.alexcrea.cuanvil.api.EnchantmentApi EnchantmentApi} to register and unregister your custom enchantments - */ -public class CAEnchantRegistryReadyEvent extends Event { - - private static final HandlerList HANDLERS = new HandlerList(); - - public static HandlerList getHandlerList() { - return HANDLERS; - } - - @Override - public HandlerList getHandlers() { - return HANDLERS; - } -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CAClickResultBypassEvent.java b/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CAClickResultBypassEvent.java deleted file mode 100644 index fe5e199..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CAClickResultBypassEvent.java +++ /dev/null @@ -1,63 +0,0 @@ -package xyz.alexcrea.cuanvil.api.event.listener; - -import org.bukkit.event.Cancellable; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.jetbrains.annotations.NotNull; - -/** - * Called before custom anvil process the click on the result on the anvil inventory. - *

- * This event is called after checking that the inventory is an anvil inventory and that the click is on the result slot - * but before checking if the player has the custom anvil affected permission. - *

- * This event being cancelled will make CustomAnvil abort the click on result process. - *

- * Most of the time you would likely need {@link CAPreAnvilBypassEvent} or {@link CAEarlyPreAnvilBypassEvent} - * for this event to be useful. - *

- * There is also {@link CATreatAnvilResult2Event} that may be better for some use case. - */ -public class CAClickResultBypassEvent extends Event implements Cancellable { - - private static final HandlerList HANDLERS = new HandlerList(); - - public static HandlerList getHandlerList() { - return HANDLERS; - } - - @Override - public @NotNull HandlerList getHandlers() { - return HANDLERS; - } - - private boolean cancelled = false; - - @Override - public boolean isCancelled() { - return cancelled; - } - - @Override - public void setCancelled(boolean cancel) { - this.cancelled = cancel; - } - - @NotNull - private final InventoryClickEvent event; - - /** - * Get the bukkit inventory click event causing to this event - * - * @return The click event causing to this event - */ - @NotNull - public InventoryClickEvent getEvent() { - return event; - } - - public CAClickResultBypassEvent(@NotNull InventoryClickEvent event) { - this.event = event; - } -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CAEarlyPreAnvilBypassEvent.java b/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CAEarlyPreAnvilBypassEvent.java deleted file mode 100644 index e92b4cd..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CAEarlyPreAnvilBypassEvent.java +++ /dev/null @@ -1,63 +0,0 @@ -package xyz.alexcrea.cuanvil.api.event.listener; - -import org.bukkit.event.Cancellable; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; -import org.bukkit.event.inventory.PrepareAnvilEvent; -import org.jetbrains.annotations.NotNull; - -/** - * Called before custom anvil process the prepare anvil event. - *

- * This event will always get called when CustomAnvil need to handle - *

- * This event being cancelled will make CustomAnvil abort the anvil process. - *

- * You should also use {@link CAClickResultBypassEvent} if you want to use this event for something useful. - *

- * It is also recommended that you read about {@link CAPreAnvilBypassEvent} and {@link CATreatAnvilResult2Event} - * as your use case may be more prone to use theses. - */ -public class CAEarlyPreAnvilBypassEvent extends Event implements Cancellable { - - private static final HandlerList HANDLERS = new HandlerList(); - - public static HandlerList getHandlerList() { - return HANDLERS; - } - - @Override - public @NotNull HandlerList getHandlers() { - return HANDLERS; - } - - private boolean cancelled = false; - - @Override - public boolean isCancelled() { - return cancelled; - } - - @Override - public void setCancelled(boolean cancel) { - this.cancelled = cancel; - } - - @NotNull - private final PrepareAnvilEvent event; - - /** - * Get the bukkit pre anvil event causing this event - * - * @return The pre anvil event causing to this event - */ - @NotNull - public PrepareAnvilEvent getEvent() { - return event; - } - - public CAEarlyPreAnvilBypassEvent(@NotNull PrepareAnvilEvent event) { - this.event = event; - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CAPreAnvilBypassEvent.java b/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CAPreAnvilBypassEvent.java deleted file mode 100644 index 9103a4b..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CAPreAnvilBypassEvent.java +++ /dev/null @@ -1,66 +0,0 @@ -package xyz.alexcrea.cuanvil.api.event.listener; - -import org.bukkit.event.Cancellable; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; -import org.bukkit.event.inventory.PrepareAnvilEvent; -import org.jetbrains.annotations.NotNull; - -/** - * Called before custom anvil process the prepare anvil event. - *

- * This event is called after {@link CAEarlyPreAnvilBypassEvent}, - * after checking that there is at least an item on the left slot - * and after checking if any of the 2 item is marked as immutable - * but before checking if the player has the custom anvil affected permission. - *

- * This event being cancelled will make CustomAnvil abort the anvil process. - *

- * You should also use {@link CAClickResultBypassEvent} if you want to use this event for something useful. - *

- * It is also recommended that you read about {@link CAEarlyPreAnvilBypassEvent} and {@link CATreatAnvilResult2Event} - * as your use case may be more prone to use theses. - */ -public class CAPreAnvilBypassEvent extends Event implements Cancellable { - - private static final HandlerList HANDLERS = new HandlerList(); - - public static HandlerList getHandlerList() { - return HANDLERS; - } - - @Override - public @NotNull HandlerList getHandlers() { - return HANDLERS; - } - - private boolean cancelled = false; - - @Override - public boolean isCancelled() { - return cancelled; - } - - @Override - public void setCancelled(boolean cancel) { - this.cancelled = cancel; - } - - @NotNull - private final PrepareAnvilEvent event; - - /** - * Get the bukkit pre anvil event causing this event - * - * @return The pre anvil event causing this event - */ - @NotNull - public PrepareAnvilEvent getEvent() { - return event; - } - - public CAPreAnvilBypassEvent(@NotNull PrepareAnvilEvent event) { - this.event = event; - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CATreatAnvilResult2Event.java b/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CATreatAnvilResult2Event.java deleted file mode 100644 index 30c5380..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CATreatAnvilResult2Event.java +++ /dev/null @@ -1,196 +0,0 @@ -package xyz.alexcrea.cuanvil.api.event.listener; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.InventoryView; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.anvil.AnvilCost; -import xyz.alexcrea.cuanvil.anvil.AnvilUseType; - -/** - * Called after custom anvil processed the click on the result on the anvil inventory. - * This event should be used to modify the result of an anvil use. - *

- * You may also want to check {@link CAClickResultBypassEvent}, - * {@link CAPreAnvilBypassEvent} - * and {@link CAEarlyPreAnvilBypassEvent} for your use case - *

- * A null result will cancel this event - */ -@SuppressWarnings("unused") -public class CATreatAnvilResult2Event extends Event { - - private static final HandlerList HANDLERS = new HandlerList(); - - public static HandlerList getHandlerList() { - return HANDLERS; - } - - @Override - public @NotNull HandlerList getHandlers() { - return HANDLERS; - } - - @NotNull - private final InventoryView view; - - private final AnvilUseType useType; - - @Nullable - private final ItemStack left; - @Nullable - private final ItemStack right; - - @Nullable - private ItemStack result; - - private final AnvilCost cost; - - @ApiStatus.Internal - public CATreatAnvilResult2Event( - @NotNull InventoryView view, - Inventory inv, - AnvilUseType useType, - @Nullable ItemStack result, - AnvilCost cost) { - this.view = view; - this.useType = useType; - - this.left = inv.getItem(0); // TODO use view here - this.right = inv.getItem(1); - this.result = result; - this.cost = cost; - } - - /** - * Get the bukkit inventory view. - *

- * Temporarily marked as internal as it will get changed to anvil view on legacy removal - * so signature will change - * - * @return The inventory view of this event. - */ - @ApiStatus.Internal - public @NotNull InventoryView getView() { - return view; - } - - - /** - * Get the type of use source of the result. - * - * @return The craft use type. - */ - public AnvilUseType getUseType() { - return useType; - } - - /** - * Get the left item of the anvil use - * - * @return the left item - */ - public @Nullable ItemStack getLeftItem() { - return left; - } - - /** - * Get the right item of the anvil use - * - * @return the right item - */ - public @Nullable ItemStack getRightItem() { - return right; - } - - /** - * Get the current result - *

- * note that it will not be null unless another listener previously set it to null. - * - * @return The current result. - */ - public @Nullable ItemStack getResult() { - return result; - } - - /** - * Set the current result - *

- * note that a null result will cancel this anvil use. - * - * @param result The new result - */ - public void setResult(@Nullable ItemStack result) { - this.result = result; - } - - /** - * Get the level cost displayed on the anvil. - *

Important note:

- * the final price are re calculated on click for the following use case: - *
    - *
  • Custom craft
  • - *
  • Unit repair
  • - *
  • Lore edit
  • - *
- * This value will be used as final price for: - *
  • Item merge
  • - *
  • Item rename
  • - * - * - * @return The current cost. - * @deprecated use #{@link #getCost()} instead - */ - @Deprecated(forRemoval = true, since = "1.17.0") - public int getLevelCost() { - return cost.asXpCost(); - } - - /** - * Set the level cost displayed on the anvil. - *

    Important note:

    - * the final price are re calculated on click for the following use case: - *
      - *
    • Custom craft
    • - *
    • Unit repair
    • - *
    • Lore edit
    • - *
    - * This value will be used as final price for: - *
  • Item merge
  • - *
  • Item rename
  • - * - * - * @param levelCost The new cost. - * @deprecated use #{@link #getCost()} and set value on this instead - */ - @Deprecated(forRemoval = true, since = "1.17.0") - public void setLevelCost(int levelCost) { - cost.setGeneric(levelCost - cost.getGeneric() - cost.asXpCost()); - } - - /** - * Allow access to the current cost of the event - * Note that modifying this object will change the event resulting cost - * - *

    Important note:

    - * the final price are re calculated on click for the following use case: - *
      - *
    • Custom craft
    • - *
    • Unit repair
    • - *
    • Lore edit
    • - *
    - * This value will be used as final price for: - *
  • Item merge
  • - *
  • Item rename
  • - * - * @return the current anvil cost - */ - public AnvilCost getCost() { - return cost; - } -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CATreatAnvilResultEvent.java b/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CATreatAnvilResultEvent.java deleted file mode 100644 index 80965b5..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CATreatAnvilResultEvent.java +++ /dev/null @@ -1,162 +0,0 @@ -package xyz.alexcrea.cuanvil.api.event.listener; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; -import org.bukkit.event.inventory.PrepareAnvilEvent; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.anvil.AnvilCost; -import xyz.alexcrea.cuanvil.anvil.AnvilUseType; - -/** - * Called after custom anvil processed the click on the result on the anvil inventory. - * This event should be used to modify the result of an anvil use. - *

    - * You may also want to check {@link CAClickResultBypassEvent}, - * {@link CAPreAnvilBypassEvent} - * and {@link CAEarlyPreAnvilBypassEvent} for your use case - *

    - * A null result will cancel this pre anvil event - * - * @deprecated Prepare anvil Event cannot be provided as it can be called on result and therefore not have prepared anvil event - * use {@link CATreatAnvilResult2Event} instead - */ -@SuppressWarnings("unused") -@Deprecated(forRemoval = true, since = "1.17.0") -public class CATreatAnvilResultEvent extends Event { - - private static final HandlerList HANDLERS = new HandlerList(); - - public static HandlerList getHandlerList() { - return HANDLERS; - } - - @Override - public @NotNull HandlerList getHandlers() { - return HANDLERS; - } - - @NotNull - private final PrepareAnvilEvent event; - - private final AnvilUseType useType; - - @Nullable - private ItemStack result; - - private final AnvilCost cost; - - public CATreatAnvilResultEvent(@NotNull PrepareAnvilEvent event, AnvilUseType useType, @Nullable ItemStack result, AnvilCost cost) { - this.event = event; - this.useType = useType; - this.result = result; - this.cost = cost; - } - - /** - * Get the bukkit inventory click event causing to this event. - * - * @return The click event causing to this event. - */ - public @NotNull PrepareAnvilEvent getEvent() { - return event; - } - - /** - * Get the type of use source of the result. - * - * @return The craft use type. - */ - public AnvilUseType getUseType() { - return useType; - } - - /** - * Get the current result - *

    - * note that it will not be null unless another listener previously set it to null. - * - * @return The current result. - */ - public @Nullable ItemStack getResult() { - return result; - } - - /** - * Set the current result - *

    - * note that a null result will cancel this anvil use. - * - * @param result The new result - */ - public void setResult(@Nullable ItemStack result) { - this.result = result; - } - - /** - * Get the level cost displayed on the anvil. - *

    Important note:

    - * the final price are re calculated on click for the following use case: - *
      - *
    • Custom craft
    • - *
    • Unit repair
    • - *
    • Lore edit
    • - *
    - * This value will be used as final price for: - *
  • Item merge
  • - *
  • Item rename
  • - * - * - * @return The current cost. - * @deprecated use #{@link #getCost()} instead - */ - @Deprecated(forRemoval = true, since = "1.17.0") - public int getLevelCost() { - return cost.asXpCost(); - } - - /** - * Set the level cost displayed on the anvil. - *

    Important note:

    - * the final price are re calculated on click for the following use case: - *
      - *
    • Custom craft
    • - *
    • Unit repair
    • - *
    • Lore edit
    • - *
    - * This value will be used as final price for: - *
  • Item merge
  • - *
  • Item rename
  • - * - * - * @param levelCost The new cost. - * @deprecated use #{@link #getCost()} and set value on this instead - */ - @Deprecated(forRemoval = true, since = "1.17.0") - public void setLevelCost(int levelCost) { - cost.setGeneric(levelCost - cost.getGeneric() - cost.asXpCost()); - } - - /** - * Allow access to the current cost of the event - * Note that modifying this object will change the event resulting cost - * - *

    Important note:

    - * the final price are re calculated on click for the following use case: - *
      - *
    • Custom craft
    • - *
    • Unit repair
    • - *
    • Lore edit
    • - *
    - * This value will be used as final price for: - *
  • Item merge
  • - *
  • Item rename
  • - * - * @return the current anvil cost - */ - public AnvilCost getCost() { - return cost; - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/config/ConfigHolder.java b/src/main/java/xyz/alexcrea/cuanvil/config/ConfigHolder.java deleted file mode 100644 index f6a7e80..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/config/ConfigHolder.java +++ /dev/null @@ -1,416 +0,0 @@ -package xyz.alexcrea.cuanvil.config; - -import com.google.common.io.Files; -import io.delilaheve.CustomAnvil; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.group.EnchantConflictManager; -import xyz.alexcrea.cuanvil.group.ItemGroupManager; -import xyz.alexcrea.cuanvil.recipe.CustomAnvilRecipeManager; -import xyz.alexcrea.cuanvil.util.MetricsUtil; - -import java.io.File; -import java.io.IOException; -import java.util.logging.Level; - -@SuppressWarnings("unused") -public abstract class ConfigHolder { - - // Available configuration: - public static DefaultConfigHolder DEFAULT_CONFIG; - public static ItemGroupConfigHolder ITEM_GROUP_HOLDER; - public static ConflictConfigHolder CONFLICT_HOLDER; - public static UnitRepairHolder UNIT_REPAIR_HOLDER; - public static CustomAnvilCraftHolder CUSTOM_RECIPE_HOLDER; - - /** - * Load default configuration. - * @return True if successful. - */ - public static boolean loadDefaultConfig() { - DEFAULT_CONFIG = new DefaultConfigHolder(); - - return DEFAULT_CONFIG.reloadFromDisk(true); - } - - /** - * Load non default configuration. - * @return True if successful. - */ - public static boolean loadNonDefaultConfig() { - ITEM_GROUP_HOLDER = new ItemGroupConfigHolder(); - CONFLICT_HOLDER = new ConflictConfigHolder(); - UNIT_REPAIR_HOLDER = new UnitRepairHolder(); - CUSTOM_RECIPE_HOLDER = new CustomAnvilCraftHolder(); - - return removeNonDefaultFromDisk(true); - } - - public static boolean reloadAllFromDisk(boolean hardfail) { - boolean sucess = DEFAULT_CONFIG.reloadFromDisk(hardfail); - if (!sucess) return false; - - return removeNonDefaultFromDisk(hardfail); - } - - private static boolean removeNonDefaultFromDisk(boolean hardfail){ - boolean sucess = ITEM_GROUP_HOLDER.reloadFromDisk(hardfail); - if (!sucess) return false; - sucess = CONFLICT_HOLDER.reloadFromDisk(hardfail); - if (!sucess) return false; - sucess = UNIT_REPAIR_HOLDER.reloadFromDisk(hardfail); - if (!sucess) return false; - sucess = CUSTOM_RECIPE_HOLDER.reloadFromDisk(hardfail); - - return sucess; - } - - - // usefull part of the file - private static final File BACKUP_FOLDER = new File(CustomAnvil.instance.getDataFolder(), "backup"); - - protected FileConfiguration configuration; - - protected ConfigHolder() { - - } - - public abstract boolean reloadFromDisk(boolean hardFail); - - public abstract void reload(); - - public FileConfiguration getConfig() { - return configuration; - } - - // Config name and files - protected abstract String getConfigFileName(); - - protected String getConfigFileExtension() { - return ".yml"; - } - - protected File getConfigFile() { - return new File(CustomAnvil.instance.getDataFolder(), getConfigFileName() + getConfigFileExtension()); - } - - protected File getFirstBackup() { - return new File(BACKUP_FOLDER, getConfigFileName() + "-first" + getConfigFileExtension()); - } - - protected File getLastBackup() { - return new File(BACKUP_FOLDER, getConfigFileName() + "-latest" + getConfigFileExtension()); - } - - // Save logic - public boolean saveToDisk(boolean doBackup) { - CustomAnvil.Companion.log("Saving "+getConfigFileName()); - if (doBackup) { - if (!saveBackup()) { - CustomAnvil.instance.getLogger().severe("Could not save backup. see above."); - return false; - } - } - File base = getConfigFile(); - // if file exist and can't be deleted the file, then we gave up. - if (base.exists() && !base.delete()) { - CustomAnvil.instance.getLogger().severe("Could not save config: can't delete existing file."); - return false; - } - FileConfiguration config = getConfig(); - try { - config.save(base); - } catch (IOException e) { - e.printStackTrace(); - CustomAnvil.instance.getLogger().severe("Could not save config..."); - return false; - } - - CustomAnvil.Companion.log(getConfigFileName()+" saved successfully"); - return true; - } - - protected boolean saveBackup() { - File base = getConfigFile(); - if (!base.exists()) return true; // We did back up everything we had to (nothing in this case) - boolean sufficientSuccess = false; - - BACKUP_FOLDER.mkdirs(); - // save first backup if do not exist - File firstBackup = getFirstBackup(); - if (!firstBackup.exists()) { - try { - Files.copy(base, firstBackup); - sufficientSuccess = true; - } catch (IOException e) { - CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not copy backup saving config " + base.getName(), e); - MetricsUtil.INSTANCE.trackError(e); - } - } - // save last backup - File lastBackup = getLastBackup(); - // if file exist and can't be deleted the file, then we gave up. - if (lastBackup.exists() && !lastBackup.delete()) { - return sufficientSuccess; - } - - try { - Files.move(base, lastBackup); - sufficientSuccess = true; - } catch (IOException e) { - e.printStackTrace(); - } - - return sufficientSuccess; - } - - public static class DefaultConfigHolder extends ConfigHolder { - - @Override - protected String getConfigFileName() { - return "config"; - } - - @Override - public boolean reloadFromDisk(boolean hardFail) { - CustomAnvil.instance.saveDefaultConfig(); - CustomAnvil.instance.reloadConfig(); - this.configuration = CustomAnvil.instance.getConfig(); - return true; - } - - @Override - public void reload() { - }// Nothing to do - - } - - // Abstract class for non default config - public abstract static class ResourceConfigHolder extends ConfigHolder { - - String resourceName; - - private ResourceConfigHolder(String resourceName) { - this.resourceName = resourceName; - } - - @Override - protected String getConfigFileName() { - return resourceName; - } - - @Override - public boolean reloadFromDisk(boolean hardFail) { - YamlConfiguration configuration = CustomAnvil.instance.reloadResource( - getConfigFileName() + getConfigFileExtension(), hardFail); - if (configuration == null) return false; - - this.configuration = configuration; - reload(); - - return true; - } - - } - - public abstract static class DeletableResource extends ResourceConfigHolder{ - - private static final String DELETED_FOLDER_PATH = "deleted"; - - private final @NotNull File parent; - private final @NotNull File deletedConfigFile; - - private @Nullable YamlConfiguration deletedListConfig; - private DeletableResource(String resourceName) { - super(resourceName); - this.parent = new File(CustomAnvil.instance.getDataFolder(), DELETED_FOLDER_PATH); - this.deletedConfigFile = new File(this.parent, "deleted_" + resourceName + getConfigFileExtension()); - } - - @Override - public boolean reloadFromDisk(boolean hardFail) { - if(!super.reloadFromDisk(hardFail)) return false; - loadDeletedListFile(hardFail); - - return true; - } - - private void loadDeletedListFile(boolean hardFail){ - this.deletedListConfig = CustomAnvil.instance.reloadResource(this.deletedConfigFile, hardFail); - - } - - /** - * Test if the provided element was deleted. - * @param objectPath The object path to delete. - * @return True if successful. - */ - public boolean isDeleted(String objectPath){ - if(this.deletedListConfig == null) return false; - - return this.deletedListConfig.getBoolean(objectPath, false); - } - - /** - * Delete a certain object by its path. do not save the config. - * @param objectPath The object path to delete. - * @return True if successful. - */ - public boolean delete(String objectPath){ - return delete(objectPath, false, false); - } - - /** - * Delete a certain object by its path. - * @param objectPath The object path to delete. - * @param doSave If we should save the config after deleting. - * @param doBackup If we should create a backup. - * @return True if successful. - */ - public boolean delete(String objectPath, boolean doSave, boolean doBackup){ - // Create deleted list if it does not yet exist - if(this.deletedListConfig == null){ - this.parent.mkdirs(); - try { - this.deletedConfigFile.createNewFile(); - } catch (IOException e) { - CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not create " + this.deletedConfigFile.getPath(), e); - MetricsUtil.INSTANCE.trackError(e); - } - loadDeletedListFile(false); - - // Something was wrong somehow - if(this.deletedListConfig == null) return false; - } - - // Add to the deleted config - this.deletedListConfig.set(objectPath, true); - this.getConfig().set(objectPath, null); - - // Save the deleted config (may not be the most efficient, but I will handle it later) - if(doSave){ - return saveToDisk(doBackup); - } - - return true; - } - - @Override - public boolean saveToDisk(boolean doBackup) { - boolean deletedSaveSuccess = saveDeletedList(); - - return super.saveToDisk(doBackup) && deletedSaveSuccess; - } - - /** - * Save list of deleted elements. - * @return true if successful. - */ - public boolean saveDeletedList() { - if(this.deletedListConfig == null) return true; - - try { - this.deletedListConfig.save(this.deletedConfigFile); - } catch (IOException e) { - CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not save " + this.deletedConfigFile.getPath(), e); - MetricsUtil.INSTANCE.trackError(e); - return false; - } - - return true; - } - - - } - - - // Class for itemGroupsManager config - public static class ItemGroupConfigHolder extends DeletableResource { - private static final String FILE_NAME = "item_groups"; - - ItemGroupManager itemGroupsManager; - - private ItemGroupConfigHolder() { - super(FILE_NAME); - } - - public ItemGroupManager getItemGroupsManager() { - return itemGroupsManager; - } - - @Override - public void reload() { - // not the most efficient way for in game reload TODO optimise - this.itemGroupsManager = new ItemGroupManager(); - this.itemGroupsManager.prepareGroups(this.configuration); - - if (CONFLICT_HOLDER.getConfig() != null) { - CONFLICT_HOLDER.reload(); - } - } - - } - - // Class for enchant conflict config - public static class ConflictConfigHolder extends DeletableResource { - private static final String FILE_NAME = "enchant_conflict"; - - EnchantConflictManager conflictManager; - - private ConflictConfigHolder() { - super(FILE_NAME); - } - - public EnchantConflictManager getConflictManager() { - return conflictManager; - } - - // We assume this is called after item group manager reload;, - @Override - public void reload() { - // not the most efficient way for in game reload TODO optimise - this.conflictManager = new EnchantConflictManager(); - this.conflictManager.prepareConflicts(this.configuration, ITEM_GROUP_HOLDER.getItemGroupsManager()); - } - - } - - // Class for unit repair config - public static class UnitRepairHolder extends DeletableResource { - private static final String ITEM_GROUP_FILE_NAME = "unit_repair_item"; - - private UnitRepairHolder() { - super(ITEM_GROUP_FILE_NAME); - } - - @Override - public void reload() { - } // Do nothing - - } - - - // Class for custom anvil craft - public static class CustomAnvilCraftHolder extends DeletableResource { - private static final String CUSTOM_RECIPE_FILE_NAME = "custom_recipes"; - CustomAnvilRecipeManager recipeManager; - - private CustomAnvilCraftHolder() { - super(CUSTOM_RECIPE_FILE_NAME); - } - - public CustomAnvilRecipeManager getRecipeManager() { - return recipeManager; - } - - @Override - public void reload() { - this.recipeManager = new CustomAnvilRecipeManager(); - this.recipeManager.prepareRecipes(this.configuration); - } - } - - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/config/WorkPenaltyType.java b/src/main/java/xyz/alexcrea/cuanvil/config/WorkPenaltyType.java deleted file mode 100644 index d374999..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/config/WorkPenaltyType.java +++ /dev/null @@ -1,66 +0,0 @@ -package xyz.alexcrea.cuanvil.config; - -import com.google.common.collect.ImmutableMap; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.anvil.AnvilUseType; - -import java.util.EnumMap; - -public class WorkPenaltyType { - - public record WorkPenaltyPart( - boolean penaltyIncrease, - boolean penaltyAdditive, - boolean exclusivePenaltyIncrease, - boolean exclusivePenaltyAdditive - ) { - - @Override - public boolean equals(Object obj) { - if(!(obj instanceof WorkPenaltyPart other)) return false; - - return other.penaltyIncrease == this.penaltyIncrease && - other.penaltyAdditive == this.penaltyAdditive && - other.exclusivePenaltyIncrease == this.exclusivePenaltyIncrease && - other.exclusivePenaltyAdditive == this.exclusivePenaltyAdditive; - } - - public WorkPenaltyPart(boolean penaltyIncrease, boolean penaltyAdditive) { - this(penaltyIncrease, penaltyAdditive, false, false); - } - } - - private final EnumMap partMap; - - public WorkPenaltyType(@Nullable EnumMap partMap) { - this.partMap = new EnumMap<>(partMap != null ? partMap : new EnumMap<>(AnvilUseType.class)); - } - - public ImmutableMap getPartMap() { - return ImmutableMap.copyOf(partMap); - } - - public WorkPenaltyPart getPenaltyInfo(AnvilUseType type) { - return partMap.getOrDefault(type, type.getDefaultPenalty()); - } - - public boolean isPenaltyIncreasing(AnvilUseType type) { - return partMap.getOrDefault(type, type.getDefaultPenalty()).penaltyIncrease; - } - - public boolean isPenaltyAdditive(AnvilUseType type) { - return partMap.getOrDefault(type, type.getDefaultPenalty()).penaltyAdditive; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof WorkPenaltyType that)) return false; - - for (AnvilUseType type : AnvilUseType.getEntries()) { - if(!getPenaltyInfo(type).equals(that.getPenaltyInfo(type))) return false; - } - return true; - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/AdditionalTestEnchantment.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/AdditionalTestEnchantment.java deleted file mode 100644 index 821838f..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/AdditionalTestEnchantment.java +++ /dev/null @@ -1,34 +0,0 @@ -package xyz.alexcrea.cuanvil.enchant; - -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; - -import java.util.Map; - -public interface AdditionalTestEnchantment { - - /** - * Test if the provided enchantments can be compatible with this enchantment. only non-Custom Anvil conflict. - * @param enchantments Immutable map of validated enchantments for the item. - * @param itemType Material namespaced key of the tested item. - * @return If there is a conflict with the enchantments. - */ - boolean isEnchantConflict( - @NotNull Map enchantments, - @NotNull NamespacedKey itemType); - - /** - * Test if the provided item can be compatible with this enchantment. only non-Custom Anvil conflict. - * @param enchantments Immutable map of validated enchantments for the item. - * @param itemType Material namespaced key of the tested item. - * @param item Provide a new instance of the used item stack with the partial enchantment applied. - * @return If there is a conflict with the enchantment and the item. - */ - boolean isItemConflict( - @NotNull Map enchantments, - @NotNull NamespacedKey itemType, - @NotNull ItemStack item); - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantment.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantment.java deleted file mode 100644 index ea657ac..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantment.java +++ /dev/null @@ -1,249 +0,0 @@ -package xyz.alexcrea.cuanvil.enchant; - -import org.bukkit.NamespacedKey; -import org.bukkit.entity.HumanEntity; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.enchant.bulk.BulkCleanEnchantOperation; -import xyz.alexcrea.cuanvil.enchant.bulk.BulkGetEnchantOperation; -import xyz.alexcrea.cuanvil.group.EnchantConflictGroup; - -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Represent an enchantment compatible with Custom Anvil. - * One issue with custom anvil is: it does not handle well duplicate key name (ignoring namespace) - * as the plugin was initially coded with vanilla enchantment in head - */ -@SuppressWarnings("unused") -public interface CAEnchantment { - - - /** - * Get the default rarity of this enchant. - * @return The default rarity of this enchant. - */ - @NotNull - EnchantmentRarity defaultRarity(); - - /** - * Get the enchantment key. - * @return The enchantment key. - */ - @NotNull - NamespacedKey getKey(); - - /** - * Get the enchantment name. - * @return The enchantment name. - */ - @NotNull - String getName(); - - /** - * Get the default maximum level of this enchantment. - * @return The default maximum level of this enchantment. - */ - int defaultMaxLevel(); - - /** - * Check if the enchantment have specialised get bulk operation. - * @return If the enchantment is optimised for get bulk operation. - */ - boolean isGetOptimised(); - - /** - * Check if the enchantment have specialised clean bulk operation. - * @return If the enchantment is optimised for clean bulk operation. - */ - boolean isCleanOptimised(); - - /** - * Check if the player is allowed to use this enchantment. - * @param player The player to test. - * @return If the player is allowed to use this enchantment. - */ - boolean isAllowed(@NotNull HumanEntity player); - - /** - * Add a conflict to this enchantment conflict list. - * @param conflict The conflict to add. - */ - void addConflict(@NotNull EnchantConflictGroup conflict); - - /** - * Remove a conflict from the conflict list of this enchantment. - * @param conflict The conflict to remove from this enchantment. - */ - void removeConflict(@NotNull EnchantConflictGroup conflict); - - /** - * Clear Custom Anvil conflicts for this enchantment. - */ - void clearConflict(); - - /** - * Get a collection of Custom Anvil conflict containing this enchantment. - * @return A collection of Custom Anvil conflict containing this enchantment. - */ - @NotNull Collection getConflicts(); - - /** - * Get current level of the enchantment. - * @param item Item to search the level for. Should not get changed. - * @return Current leve of this enchantment on item. or 0 if absent. - */ - default int getLevel(@NotNull ItemStack item){ - ItemMeta meta = item.getItemMeta(); - if(meta == null) return 0; - - return getLevel(item, meta); - } - - /** - * Get current level of the enchantment. - * @param item Item to search the level for. Should not get changed. - * @param meta Meta of the provided item. Should not get changed. - * @return Current leve of this enchantment on item. or 0 if absent. - */ - int getLevel(@NotNull ItemStack item, @NotNull ItemMeta meta); - - /** - * Check if this enchantment is present on the provided level. - * @param item The item to set the enchantment level. - * @return If the enchantment have been found. - */ - boolean isEnchantmentPresent(@NotNull ItemStack item); - - /** - * Check if this enchantment is present on the provided level. - * @param item The item to set the enchantment level. - * @param meta Meta of the provided item. It will not be changed and not be set on the item. - * @return If the enchantment have been found. - */ - boolean isEnchantmentPresent(@NotNull ItemStack item, @NotNull ItemMeta meta); - - /** - * Force add an enchantment at the provided level. - * @param item The item to set the enchantment level. - * @param level The level to set the enchantment to. - */ - void addEnchantmentUnsafe(@NotNull ItemStack item, int level); - - /** - * Remove this enchantment from the provided ItemStack. - * @param item The item to remove the enchantment. - */ - void removeFrom(@NotNull ItemStack item); - - // Static functions - /** - * Clear every enchantment from this item. - * @param item Item to be cleared from enchantments. - */ - static void clearEnchants(@NotNull ItemStack item){ - // Optimised enchantment clean using item stack - for (BulkCleanEnchantOperation cleanOperator : CAEnchantmentRegistry.getInstance().getOptimisedCleanOperators()) { - cleanOperator.bulkClear(item); - } - - ItemMeta meta = item.getItemMeta(); - if(meta == null) return; - - // Optimised enchantment clean using item meta - for (BulkCleanEnchantOperation cleanOperator : CAEnchantmentRegistry.getInstance().getOptimisedCleanOperators()) { - cleanOperator.bulkClear(item, meta); - } - - item.setItemMeta(meta); - - // Clean unoptimised enchants - for (CAEnchantment enchant : CAEnchantmentRegistry.getInstance().unoptimisedCleanValues()) { - if(enchant.isEnchantmentPresent(item)){ - enchant.removeFrom(item); - } - } - - } - - /** - * Get enchantments of an item. - * @param item Item to get enchantment from. - * @return A map of the set enchantments and there's respective levels. - */ - static Map getEnchants(@NotNull ItemStack item){ - Map enchantments = new HashMap<>(); - CAEnchantmentRegistry registry = CAEnchantmentRegistry.getInstance(); - - ItemMeta meta = item.getItemMeta(); - if(meta == null) return enchantments; - - // Optimised enchantment get - for (BulkGetEnchantOperation getOperator : CAEnchantmentRegistry.getInstance().getOptimisedGetOperators()) { - getOperator.bulkGet(enchantments, item, meta); - } - - // Unoptimised enchantment get - findEnchantsFromSelectedList(item, meta, enchantments, registry.unoptimisedGetValues()); - - return enchantments; - } - - - /** - * Find enchantments of an item. only test the enchantment from the list. - * @param item Item to get enchantment from. - * @param meta Meta of the provided item. - * @param enchantments Map of enchantment to complete. - * @param enchantmentToTest Enchantment to test - */ - static void findEnchantsFromSelectedList( - @NotNull ItemStack item, - @NotNull ItemMeta meta, - @NotNull Map enchantments, - @NotNull Collection enchantmentToTest){ - for (CAEnchantment enchantment : enchantmentToTest) { - if(enchantment.isEnchantmentPresent(item, meta)){ - enchantments.put(enchantment, enchantment.getLevel(item, meta)); - } - } - - } - - /** - * Gets an array of all the registered enchantments. - * - * @param key The enchantment key - * @return Array of enchantment. - */ - static @Nullable CAEnchantment getByKey(@NotNull NamespacedKey key){ - return CAEnchantmentRegistry.getInstance().getByKey(key); - } - - /** - * Gets the enchantment by the provided name. - * @param name Name to fetch. - * @return Registered enchantment. null if absent. - * - * @deprecated use {@link #getListByName(String)} - */ - @Deprecated(since = "1.6.3") - static @Nullable CAEnchantment getByName(@NotNull String name){ - return CAEnchantmentRegistry.getInstance().getByName(name); - } - - /** - * Gets list of enchantment using the provided name. - * @param name Name to fetch. - * @return List of registered enchantment. - */ - static List getListByName(@NotNull String name){ - return CAEnchantmentRegistry.getInstance().getListByName(name); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentBase.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentBase.java deleted file mode 100644 index 05718d5..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentBase.java +++ /dev/null @@ -1,115 +0,0 @@ -package xyz.alexcrea.cuanvil.enchant; - -import org.bukkit.NamespacedKey; -import org.bukkit.entity.HumanEntity; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.group.EnchantConflictGroup; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -/** - * Default implementation of an enchantment compatible with Custom Anvil. - * One issue with custom anvil is: it does not handle well duplicate key name (ignoring namespace) - * as the plugin was initially coded with vanilla enchantment in head - */ -public abstract class CAEnchantmentBase implements CAEnchantment { - - @NotNull - private final NamespacedKey key; - @NotNull - private final String name; - @NotNull - private final EnchantmentRarity defaultRarity; - private final int defaultMaxLevel; - - private final List conflicts; - - /** - * Constructor of Wrapped Enchantment. - * @param key The enchantment's key. - * @param defaultRarity Default rarity the enchantment should be. - * @param defaultMaxLevel Default max level the enchantment can be applied with. - */ - protected CAEnchantmentBase( - @NotNull NamespacedKey key, - @Nullable EnchantmentRarity defaultRarity, - int defaultMaxLevel){ - this.key = key; - this.name = key.getKey(); - this.defaultMaxLevel = defaultMaxLevel; - - this.defaultRarity = Objects.requireNonNullElse(defaultRarity, EnchantmentRarity.COMMON); - - this.conflicts = new ArrayList<>(); - } - - @NotNull - @Override - public final EnchantmentRarity defaultRarity(){ - return defaultRarity; - } - - @NotNull - @Override - public final NamespacedKey getKey(){ - return key; - } - - @NotNull - @Override - public final String getName(){ - return name; - } - - @Override - public final int defaultMaxLevel(){ - return defaultMaxLevel; - } - - @Override - public boolean isGetOptimised(){ - return false; - } - - @Override - public boolean isCleanOptimised(){ - return false; - } - - @Override - public boolean isAllowed(@NotNull HumanEntity player){ - return true; - } - - public boolean isEnchantmentPresent(@NotNull ItemStack item){ - ItemMeta meta = item.getItemMeta(); - if(meta == null) return false; - return isEnchantmentPresent(item, meta); - } - - @Override - public void addConflict(@NotNull EnchantConflictGroup conflict){ - this.conflicts.add(conflict); - } - - @Override - public void removeConflict(@NotNull EnchantConflictGroup conflict){ - this.conflicts.remove(conflict); - } - - @Override - public void clearConflict(){ - this.conflicts.clear(); - } - - @Override - public @NotNull List getConflicts() { - return conflicts; - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentRegistry.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentRegistry.java deleted file mode 100644 index 854ed55..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentRegistry.java +++ /dev/null @@ -1,250 +0,0 @@ -package xyz.alexcrea.cuanvil.enchant; - -import io.delilaheve.CustomAnvil; -import org.bukkit.NamespacedKey; -import org.bukkit.enchantments.Enchantment; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.enchant.bulk.BukkitEnchantBulkOperation; -import xyz.alexcrea.cuanvil.enchant.bulk.BulkCleanEnchantOperation; -import xyz.alexcrea.cuanvil.enchant.bulk.BulkGetEnchantOperation; -import xyz.alexcrea.cuanvil.enchant.wrapped.CABukkitEnchantment; -import xyz.alexcrea.cuanvil.util.MetricsUtil; - -import java.util.*; -import java.util.logging.Level; - -public class CAEnchantmentRegistry { - - private static final CAEnchantmentRegistry instance = new CAEnchantmentRegistry(); - - public static CAEnchantmentRegistry getInstance() { - return instance; - } - - // Register enchantment functions - private final HashMap byKeyMap; - private final HashMap> byNameMap; - - private final SortedSet nameSortedEnchantments; - - private final List unoptimisedGetValues; - private final List unoptimisedCleanValues; - - private final List optimisedGetOperators; - private final List optimisedCleanOperators; - - private CAEnchantmentRegistry() { - byKeyMap = new HashMap<>(); - byNameMap = new HashMap<>(); - - nameSortedEnchantments = new TreeSet<>(Comparator.comparing(CAEnchantment::getName)); - - unoptimisedGetValues = new ArrayList<>(); - unoptimisedCleanValues = new ArrayList<>(); - - optimisedGetOperators = new ArrayList<>(); - optimisedCleanOperators = new ArrayList<>(); - } - - /** - * This should only be called on main of custom anvil. - * If called more than one time, chance of thing being broken will be high. - */ - public void registerBukkit() { - // Register enchantment - for (Enchantment enchantment : Enchantment.values()) { - register(new CABukkitEnchantment(enchantment)); - } - - // Add bukkit enchantment bulk operation - BukkitEnchantBulkOperation bukkitOperation = new BukkitEnchantBulkOperation(); - optimisedGetOperators.add(bukkitOperation); - optimisedCleanOperators.add(bukkitOperation); - } - - private static boolean hasWarnedRegistering = false; - - /** - * Can be used to register new enchantment. - *

    - * No guarantee that the enchantment will be present on the config gui if registered late. - * (By late I mean after custom anvil startup.) - * - * @param enchantment The enchantment to be registered. - * @return If the operation was successful. - */ - public boolean register(@NotNull CAEnchantment enchantment) { - if (byKeyMap.containsKey(enchantment.getKey())) { - if (Objects.equals(enchantment, byKeyMap.get(enchantment.getKey()))) { - // We are trying to register the exact same enchantment. so we just skip it. - return false; - } - - if (ConfigHolder.DEFAULT_CONFIG.getConfig().getBoolean("caution_secret_do_not_log_duplicated_registered_key", false)) { - return false; - } - - var error = new IllegalStateException("enchantment " + enchantment.getKey() + " was already registered"); - CustomAnvil.instance.getLogger().log(Level.WARNING, - "Duplicate distinct registered enchantment. This should NOT happen any time.\n" + - "If you are a custom anvil developer: Maybe custom anvil detected your enchantment as a bukkit enchantment. " + - "you should maybe remove enchantment with the same key before registering yours", - error); - MetricsUtil.INSTANCE.trackError(error); - return false; - } - - if ((!hasWarnedRegistering) && byNameMap.containsKey(enchantment.getName())) { - hasWarnedRegistering = true; - - CustomAnvil.instance.getLogger().log(Level.WARNING, - "Duplicate registered enchantment name. Please check that configuration is using namespace."); - } - - byKeyMap.put(enchantment.getKey(), enchantment); - - byNameMap.putIfAbsent(enchantment.getName(), new ArrayList<>()); - byNameMap.get(enchantment.getName()).add(enchantment); - - nameSortedEnchantments.add(enchantment); - - if (!enchantment.isGetOptimised()) { - unoptimisedGetValues.add(enchantment); - } - if (!enchantment.isCleanOptimised()) { - unoptimisedCleanValues.add(enchantment); - } - - return true; - } - - /** - * Can be used to unregister new enchantment. - * Please be cautious with this function. - * It should probably rarely be used. - *

    - * No guarantee that the enchantment will absent if the config guis if unregistered late. - * (By late I mean after custom anvil startup.) - * - * @param enchantment The enchantment to be unregistered. - * @return If the operation was successful. - */ - - public boolean unregister(@Nullable CAEnchantment enchantment) { - if (enchantment == null) return false; - byKeyMap.remove(enchantment.getKey()); - byNameMap.get(enchantment.getName()).remove(enchantment); - - nameSortedEnchantments.remove(enchantment); - - unoptimisedGetValues.remove(enchantment); - unoptimisedCleanValues.remove(enchantment); - return true; - } - - /** - * Gets the enchantment by the provided key. - * - * @param key Key to fetch. - * @return Registered enchantment. null if absent. - */ - @Nullable - public CAEnchantment getByKey(@NotNull NamespacedKey key) { - return byKeyMap.get(key); - } - - /** - * Gets the enchantment by the provided name. - * - * @param name Name to fetch. - * @return Registered enchantment. null if absent. - * @deprecated use {@link #getListByName(String)} - */ - @Deprecated(since = "1.6.3") - @Nullable - public CAEnchantment getByName(@NotNull String name) { - List enchantments = getListByName(name); - if (enchantments.isEmpty()) return null; - - return enchantments.get(0); - } - - /** - * Gets list of enchantment using the provided name. - * - * @param name Name to fetch. - * @return List of registered enchantment. - */ - @NotNull - public List getListByName(@NotNull String name) { - return byNameMap.getOrDefault(name, Collections.emptyList()); - } - - /** - * Gets an array of all the registered enchantments. - * - * @return Array of enchantments. - */ - @NotNull - public Collection values() { - return byKeyMap.values(); - } - - /** - * Gets a map of all the registered enchantments. - * - * @return Immutable map of enchantments. - */ - public Map registeredEnchantments() { - return Collections.unmodifiableMap(byKeyMap); - } - - /** - * Gets a list of all the unoptimised get operation enchantments. - * - * @return List of unoptimised enchantments. - */ - @NotNull - public List unoptimisedGetValues() { - return unoptimisedGetValues; - } - - /** - * Gets a list of all the unoptimised clean operation enchantments. - * - * @return List of unoptimised enchantments. - */ - @NotNull - public List unoptimisedCleanValues() { - return unoptimisedCleanValues; - } - - /** - * Get "clean optimised operation" for get enchantments. - * - * @return Mutable "clean enchantments optimised operation" list. - */ - public List getOptimisedCleanOperators() { - return optimisedCleanOperators; - } - - /** - * Get "get optimised operation" for get enchantments. - * - * @return Mutable "get enchantments optimised operation" list. - */ - public List getOptimisedGetOperators() { - return optimisedGetOperators; - } - - /** - * Get custom anvil enchantment sorted by name. - * - * @return An immutable sorted set of every registered enchantment sorted by name. - */ - public SortedSet getNameSortedEnchantments() { - return Collections.unmodifiableSortedSet(nameSortedEnchantments); - } -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/EnchantmentProperties.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/EnchantmentProperties.java deleted file mode 100644 index 1137feb..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/EnchantmentProperties.java +++ /dev/null @@ -1,61 +0,0 @@ -package xyz.alexcrea.cuanvil.enchant; - -// to bind EnchantmentRarity to an enchantment... -public enum EnchantmentProperties { - - AQUA_AFFINITY(EnchantmentRarity.RARE), - BANE_OF_ARTHROPODS(EnchantmentRarity.UNCOMMON), - BINDING_CURSE(EnchantmentRarity.VERY_RARE), - BLAST_PROTECTION(EnchantmentRarity.RARE), - BREACH(EnchantmentRarity.RARE), - CHANNELING(EnchantmentRarity.VERY_RARE), - DENSITY(EnchantmentRarity.UNCOMMON), - DEPTH_STRIDER(EnchantmentRarity.RARE), - EFFICIENCY(EnchantmentRarity.COMMON), - FLAME(EnchantmentRarity.RARE), - FEATHER_FALLING(EnchantmentRarity.UNCOMMON), - FIRE_ASPECT(EnchantmentRarity.RARE), - FIRE_PROTECTION(EnchantmentRarity.UNCOMMON), - FORTUNE(EnchantmentRarity.RARE), - FROST_WALKER(EnchantmentRarity.RARE), - IMPALING(EnchantmentRarity.RARE), - INFINITY(EnchantmentRarity.VERY_RARE), - KNOCKBACK(EnchantmentRarity.UNCOMMON), - LOOTING(EnchantmentRarity.RARE), - LOYALTY(EnchantmentRarity.COMMON), - LUCK_OF_THE_SEA(EnchantmentRarity.RARE), - LURE(EnchantmentRarity.RARE), - MENDING(EnchantmentRarity.RARE), - MULTISHOT(EnchantmentRarity.RARE), - PIERCING(EnchantmentRarity.COMMON), - POWER(EnchantmentRarity.COMMON), - PROJECTILE_PROTECTION(EnchantmentRarity.UNCOMMON), - PROTECTION(EnchantmentRarity.COMMON), - PUNCH(EnchantmentRarity.RARE), - QUICK_CHARGE(EnchantmentRarity.UNCOMMON), - RESPIRATION(EnchantmentRarity.RARE), - RIPTIDE(EnchantmentRarity.RARE), - SILK_TOUCH(EnchantmentRarity.VERY_RARE), - SHARPNESS(EnchantmentRarity.COMMON), - SMITE(EnchantmentRarity.UNCOMMON), - SOUL_SPEED(EnchantmentRarity.VERY_RARE), - SWIFT_SNEAK(EnchantmentRarity.VERY_RARE), - SWEEPING(EnchantmentRarity.RARE), - SWEEPING_EDGE(EnchantmentRarity.RARE), - THORNS(EnchantmentRarity.VERY_RARE), - UNBREAKING(EnchantmentRarity.UNCOMMON), - VANISHING_CURSE(EnchantmentRarity.VERY_RARE), - WIND_BURST(EnchantmentRarity.RARE), - ; - - private final EnchantmentRarity rarity; - - EnchantmentProperties(EnchantmentRarity rarity) { - this.rarity = rarity; - } - - public EnchantmentRarity getRarity() { - return rarity; - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/EnchantmentRarity.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/EnchantmentRarity.java deleted file mode 100644 index 3718f39..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/EnchantmentRarity.java +++ /dev/null @@ -1,52 +0,0 @@ -package xyz.alexcrea.cuanvil.enchant; - -// because spigot (1.18) do not look like to provide access to enchantment rarity I need to do it myself... -public class EnchantmentRarity { - - public static final EnchantmentRarity NO_RARITY = new EnchantmentRarity(0, 0); - public static final EnchantmentRarity COMMON = new EnchantmentRarity(1); - public static final EnchantmentRarity UNCOMMON = new EnchantmentRarity(2); - public static final EnchantmentRarity RARE = new EnchantmentRarity(4); - public static final EnchantmentRarity VERY_RARE = new EnchantmentRarity(8); - - private final int itemValue; - private final int bookValue; - - private EnchantmentRarity(int itemValue, int bookValue) { - this.itemValue = itemValue; - this.bookValue = bookValue; - } - - private EnchantmentRarity(int itemValue) { - this(itemValue, Math.max(1, itemValue / 2)); - } - - public final int getBookValue() { - return bookValue; - } - - public final int getItemValue() { - return itemValue; - } - - - public static EnchantmentRarity getRarity(int itemValue, int bookValue){ - int expectedBook = Math.max(1, itemValue / 2); - if((expectedBook == bookValue) && (itemValue != 0)) return getRarity(itemValue); - - if(itemValue == 0 && bookValue == 0) return NO_RARITY; - return new EnchantmentRarity(itemValue, bookValue); - } - - public static EnchantmentRarity getRarity(int itemValue){ - return switch (itemValue) { - case 0 -> NO_RARITY; - case 1 -> COMMON; - case 2 -> UNCOMMON; - case 4 -> RARE; - case 8 -> VERY_RARE; - default -> new EnchantmentRarity(itemValue); - }; - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/BukkitEnchantBulkOperation.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/BukkitEnchantBulkOperation.java deleted file mode 100644 index 73e4185..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/BukkitEnchantBulkOperation.java +++ /dev/null @@ -1,66 +0,0 @@ -package xyz.alexcrea.cuanvil.enchant.bulk; - -import io.delilaheve.CustomAnvil; -import io.delilaheve.util.ConfigOptions; -import io.delilaheve.util.ItemUtil; -import org.bukkit.Material; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.EnchantmentStorageMeta; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.api.EnchantmentApi; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; - -import java.util.Map; - -public class BukkitEnchantBulkOperation implements BulkGetEnchantOperation, BulkCleanEnchantOperation { - - @Override - public void bulkGet(@NotNull Map enchantmentMap, @NotNull ItemStack item, @NotNull ItemMeta meta) { - boolean isBook = ItemUtil.INSTANCE.isEnchantedBook(item); - - if (isBook) { - ((EnchantmentStorageMeta) meta).getStoredEnchants().forEach((enchantment, level) -> - addEnchantment(enchantmentMap, enchantment, level) - ); - } - if(!isBook || ConfigOptions.INSTANCE.getAddBookEnchantmentAsStoredEnchantment()){ - item.getEnchantments().forEach((enchantment, level) -> - addEnchantment(enchantmentMap, enchantment, level) - ); - } - } - - public void addEnchantment(@NotNull Map enchantmentMap, @NotNull Enchantment enchantment, int level) { - CAEnchantment enchant = EnchantmentApi.getByKey(enchantment.getKey()); - if (enchant == null) { - CustomAnvil.instance.getLogger().warning("Enchantment of key " + enchantment.getKey() + - " somehow not found in CustomAnvil ?"); - return; - } - - enchantmentMap.put(enchant, level); - } - - @Override - public void bulkClear(@NotNull ItemStack item) { - if (item.getType() != Material.ENCHANTED_BOOK || ConfigOptions.INSTANCE.getAddBookEnchantmentAsStoredEnchantment()) { - - item.getEnchantments().forEach((enchantment, level) -> - item.removeEnchantment(enchantment) - ); - } - } - - @Override - public void bulkClear(@NotNull ItemStack item, @NotNull ItemMeta meta) { - if (item.getType() == Material.ENCHANTED_BOOK) { - EnchantmentStorageMeta bookMeta = (EnchantmentStorageMeta) meta; - bookMeta.getStoredEnchants().forEach((enchantment, leve) -> - bookMeta.removeStoredEnchant(enchantment) - ); - } - - } -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/BulkCleanEnchantOperation.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/BulkCleanEnchantOperation.java deleted file mode 100644 index 4b1a225..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/BulkCleanEnchantOperation.java +++ /dev/null @@ -1,28 +0,0 @@ -package xyz.alexcrea.cuanvil.enchant.bulk; - -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; - -/** - * Bulk operation for clean enchantments operations. - */ -public interface BulkCleanEnchantOperation { - - /** - * Bulk clear part of the enchantments from this item. - * The item can be edited freely. If you need the meta it is preferred to use {@link #bulkClear(ItemStack, ItemMeta)} if possible - * @param item The item to clear enchantment from. - */ - void bulkClear(@NotNull ItemStack item); - - /** - * Bulk clear part of the enchantments from this item meta. - * Item should not be edited as meta will be applied later. - * If you need to edit the item and do not need the meta use {@link #bulkClear(ItemStack)} - * @param item The item source of the item meta. should not be edited. - * @param meta The item meta to clear enchantment from. - */ - void bulkClear(@NotNull ItemStack item, @NotNull ItemMeta meta); - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/BulkGetEnchantOperation.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/BulkGetEnchantOperation.java deleted file mode 100644 index 7c66e8a..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/BulkGetEnchantOperation.java +++ /dev/null @@ -1,23 +0,0 @@ -package xyz.alexcrea.cuanvil.enchant.bulk; - -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; - -import java.util.Map; - -/** - * Bulk operation for get enchantments operations. - */ -public interface BulkGetEnchantOperation { - - /** - * Bulk get part of the stored enchantment of this item. - * @param enchantmentMap Mutable map of collected enchantment. should b - * @param item The item to get enchantment from. Should not get edited. - * @param meta The item meta to get enchantment from. Should not get edited. - */ - void bulkGet(@NotNull Map enchantmentMap, @NotNull ItemStack item, @NotNull ItemMeta meta); - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/EnchantSquaredBulkOperation.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/EnchantSquaredBulkOperation.java deleted file mode 100644 index 57ecf60..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/EnchantSquaredBulkOperation.java +++ /dev/null @@ -1,37 +0,0 @@ -package xyz.alexcrea.cuanvil.enchant.bulk; - -import me.athlaeos.enchantssquared.managers.CustomEnchantManager; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.dependency.DependencyManager; -import xyz.alexcrea.cuanvil.dependency.plugins.EnchantmentSquaredDependency; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; - -import java.util.Collections; -import java.util.Map; - -public class EnchantSquaredBulkOperation implements BulkGetEnchantOperation, BulkCleanEnchantOperation { - - @Override - public void bulkGet(@NotNull Map enchantmentMap, @NotNull ItemStack item, @NotNull ItemMeta meta) { - EnchantmentSquaredDependency enchantmentSquared = DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility(); - if(enchantmentSquared != null){ - enchantmentSquared.getEnchantmentsSquared(item, enchantmentMap); - } - } - - - @Override - public void bulkClear(@NotNull ItemStack item) { - EnchantmentSquaredDependency enchantmentSquared = DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility(); - if(enchantmentSquared != null){ - CustomEnchantManager.getInstance().setItemEnchants(item, Collections.emptyMap()); - } - } - - @Override - public void bulkClear(@NotNull ItemStack item, @NotNull ItemMeta meta) { - // item meta is not preferred for enchantment squared clear - } -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/SuperEnchantBulkOperation.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/SuperEnchantBulkOperation.java deleted file mode 100644 index 8bc729a..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/SuperEnchantBulkOperation.java +++ /dev/null @@ -1,47 +0,0 @@ -package xyz.alexcrea.cuanvil.enchant.bulk; - -import com.maddoxh.superEnchants.items.EnchantApplicator; -import com.maddoxh.superEnchants.items.EnchantReader; -import io.delilaheve.CustomAnvil; -import org.bukkit.NamespacedKey; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.plugin.Plugin; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.api.EnchantmentApi; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; - -import java.util.Map; - -public class SuperEnchantBulkOperation implements BulkGetEnchantOperation, BulkCleanEnchantOperation { - - private Plugin plugin; - public SuperEnchantBulkOperation(Plugin plugin) { - this.plugin = plugin; - } - - @Override - public void bulkGet(@NotNull Map enchantmentMap, @NotNull ItemStack item, @NotNull ItemMeta meta) { - EnchantReader.INSTANCE.readEnchants(item).forEach((ench, level) -> { - var enchantment = EnchantmentApi.getByKey(NamespacedKey.fromString(ench, plugin)); - if(enchantment == null) { - CustomAnvil.log("Enchantment " + ench + " not found in custom anvil"); - return; - } - - enchantmentMap.put(enchantment, level); - } - ); - } - - @Override - public void bulkClear(@NotNull ItemStack item) { - EnchantApplicator.INSTANCE.clearAllCustomEnchants(item); - } - - @Override - public void bulkClear(@NotNull ItemStack item, @NotNull ItemMeta meta) { - // item meta is not preferred for enchantment squared clear - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CABukkitEnchantment.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CABukkitEnchantment.java deleted file mode 100644 index 0e630ea..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CABukkitEnchantment.java +++ /dev/null @@ -1,174 +0,0 @@ -package xyz.alexcrea.cuanvil.enchant.wrapped; - -import io.delilaheve.CustomAnvil; -import io.delilaheve.util.ConfigOptions; -import io.delilaheve.util.ItemUtil; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.EnchantmentStorageMeta; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.enchant.CAEnchantmentBase; -import xyz.alexcrea.cuanvil.enchant.EnchantmentProperties; -import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; -import java.util.logging.Level; - -/** - * Custom Anvil enchantment implementation for vanilla registered enchantment. - */ -public class CABukkitEnchantment extends CAEnchantmentBase { - - public final @NotNull Enchantment bukkit; - - public CABukkitEnchantment(@NotNull Enchantment bukkit, @Nullable EnchantmentRarity rarity) { - super(bukkit.getKey(), - rarity, - bukkit.getMaxLevel()); - this.bukkit = bukkit; - } - - public CABukkitEnchantment(@NotNull Enchantment bukkit) { - this(bukkit, getRarity(bukkit)); - } - - @Override - public boolean isGetOptimised() { - return true; - } - - @Override - public boolean isCleanOptimised() { - return true; - } - - @Override - public int getLevel(@NotNull ItemStack item, @NotNull ItemMeta meta) { - if (ItemUtil.INSTANCE.isEnchantedBook(item)) { - return ((EnchantmentStorageMeta) meta).getStoredEnchantLevel(this.bukkit); - } else { - return meta.getEnchantLevel(this.bukkit); - } - } - - @Override - public boolean isEnchantmentPresent(@NotNull ItemStack item, @NotNull ItemMeta meta) { - if (ItemUtil.INSTANCE.isEnchantedBook(item)) { - EnchantmentStorageMeta bookMeta = ((EnchantmentStorageMeta) meta); - - return bookMeta.getStoredEnchants().containsKey(this.bukkit) || - (ConfigOptions.INSTANCE.getAddBookEnchantmentAsStoredEnchantment() && item.containsEnchantment(this.bukkit)); - } else { - return item.containsEnchantment(this.bukkit); - } - } - - @Override - public void addEnchantmentUnsafe(@NotNull ItemStack item, int level) { - if (ItemUtil.INSTANCE.isEnchantedBook(item)) { - EnchantmentStorageMeta bookMeta = ((EnchantmentStorageMeta) item.getItemMeta()); - - assert bookMeta != null; - bookMeta.addStoredEnchant(this.bukkit, level, true); - item.setItemMeta(bookMeta); - } else { - item.addUnsafeEnchantment(this.bukkit, level); - } - - } - - @Override - public void removeFrom(@NotNull ItemStack item) { - if (ItemUtil.INSTANCE.isEnchantedBook(item)) { - EnchantmentStorageMeta bookMeta = ((EnchantmentStorageMeta) item.getItemMeta()); - - assert bookMeta != null; - bookMeta.removeStoredEnchant(this.bukkit); - bookMeta.removeEnchant(this.bukkit); - item.setItemMeta(bookMeta); - } else { - item.removeEnchantment(this.bukkit); - } - - } - - @NotNull - public static EnchantmentRarity getRarity(Enchantment enchantment) { - try { - return EnchantmentProperties.valueOf(enchantment.getKey().getKey().toUpperCase(Locale.ENGLISH)).getRarity(); - } catch (IllegalArgumentException ignored) { - return findRarity(enchantment); - } - } - - @NotNull - protected Enchantment getEnchant() { - return this.bukkit; - } - - private static Method getAnvilCostMethod; - - static { - Class clazz = Enchantment.class; - try { - getAnvilCostMethod = clazz.getDeclaredMethod("getAnvilCost"); - getAnvilCostMethod.setAccessible(true); - - CustomAnvil.Companion.log("Detected getAnvilCost method"); - } catch (NoSuchMethodException e) { - getAnvilCostMethod = null; - } - - } - - private static final Map targetToGroup = new HashMap<>(); - static { - targetToGroup.put(EnchantmentTarget.ARMOR, "armors"); - targetToGroup.put(EnchantmentTarget.ARMOR_HEAD, "helmets"); - targetToGroup.put(EnchantmentTarget.ARMOR_TORSO, "chestplate"); - targetToGroup.put(EnchantmentTarget.ARMOR_LEGS, "leggings"); - targetToGroup.put(EnchantmentTarget.ARMOR_FEET, "boots"); - targetToGroup.put(EnchantmentTarget.BOW, "bow"); - targetToGroup.put(EnchantmentTarget.BREAKABLE, "can_unbreak"); - targetToGroup.put(EnchantmentTarget.CROSSBOW, "crossbow"); - targetToGroup.put(EnchantmentTarget.FISHING_ROD, "fishing_rod"); - targetToGroup.put(EnchantmentTarget.TOOL, "tools"); - targetToGroup.put(EnchantmentTarget.TRIDENT, "trident"); - targetToGroup.put(EnchantmentTarget.VANISHABLE, "can_vanish"); - targetToGroup.put(EnchantmentTarget.WEAPON, "swords"); - targetToGroup.put(EnchantmentTarget.WEARABLE, "wearable"); - } - - private static EnchantmentRarity findRarity(Enchantment enchantment) { - if (getAnvilCostMethod == null) return EnchantmentRarity.COMMON; - - try { - int itemCost = (int) getAnvilCostMethod.invoke(enchantment); - - return EnchantmentRarity.getRarity(itemCost); - } catch (IllegalAccessException | InvocationTargetException e) { - CustomAnvil.instance.getLogger().log(Level.SEVERE, "could not find cost for enchantment " + enchantment.getKey(), e); - - return EnchantmentRarity.COMMON; - } - - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof CABukkitEnchantment other)) { - return false; - } - - return Objects.equals(this.bukkit, other.getEnchant()); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEEPreV5Enchantment.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEEPreV5Enchantment.java deleted file mode 100644 index 783798d..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEEPreV5Enchantment.java +++ /dev/null @@ -1,61 +0,0 @@ -package xyz.alexcrea.cuanvil.enchant.wrapped; - -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.api.enchantment.CustomEnchantment; -import su.nightexpress.excellentenchants.api.enchantment.Definition; -import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Map; -import java.util.Set; - -public class CAEEPreV5Enchantment extends CABukkitEnchantment implements AdditionalTestEnchantment { - - @NotNull CustomEnchantment eeenchantment; - @NotNull Definition definition; - - public CAEEPreV5Enchantment(@NotNull CustomEnchantment enchantment) { - super(enchantment.getBukkitEnchantment(), getRarity(enchantment.getBukkitEnchantment())); - this.eeenchantment = enchantment; - try { - this.definition = (Definition) getDefinition.invoke(enchantment); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - - } - - private final static Method getDefinition; - static { - try { - getDefinition = CustomEnchantment.class.getMethod("getDefinition"); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - } - - @Override - public boolean isEnchantConflict(@NotNull Map enchantments, @NotNull NamespacedKey itemType) { - if (!definition.hasConflicts()) return false; - - Set conflicts = definition.getConflicts(); - - for (CAEnchantment caEnchantment : enchantments.keySet()) { - if (conflicts.contains(caEnchantment.getName())) return true; - } - - return false; - } - - @Override - public boolean isItemConflict(@NotNull Map enchantments, @NotNull NamespacedKey itemType, @NotNull ItemStack item) { - if (Material.ENCHANTED_BOOK.getKey().equals(itemType)) return false; - - return !definition.getSupportedItems().is(item); - } -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEEV5Enchantment.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEEV5Enchantment.java deleted file mode 100644 index 2d8f945..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEEV5Enchantment.java +++ /dev/null @@ -1,128 +0,0 @@ -package xyz.alexcrea.cuanvil.enchant.wrapped; - -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.api.enchantment.CustomEnchantment; -import su.nightexpress.excellentenchants.api.item.ItemSet; -import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; -import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Map; -import java.util.Set; - -public class CAEEV5Enchantment extends CABukkitEnchantment implements AdditionalTestEnchantment { - - @NotNull CustomEnchantment eeenchantment; - @NotNull Object definition; - - public CAEEV5Enchantment(@NotNull CustomEnchantment enchantment) { - super(enchantment.getBukkitEnchantment(), EnchantmentRarity.getRarity(getAnvilCost(enchantment))); - this.eeenchantment = enchantment; - this.definition = getDefinition(enchantment); - - } - - @Override - public boolean isEnchantConflict(@NotNull Map enchantments, @NotNull NamespacedKey itemType) { - if (!hasConflicts()) return false; - - Set conflicts = getExclusiveSet(); - - for (CAEnchantment caEnchantment : enchantments.keySet()) { - if (conflicts.contains(caEnchantment.getName())) return true; - if (conflicts.contains(caEnchantment.getKey().toString())) return true; - } - - return false; - } - - @Override - public boolean isItemConflict(@NotNull Map enchantments, @NotNull NamespacedKey itemType, @NotNull ItemStack item) { - if (Material.ENCHANTED_BOOK.getKey().equals(itemType)) return false; - - String key = itemType.getKey(); - ItemSet primary = eeenchantment.getPrimaryItems(); - if (primary.getMaterials().contains(key)) return false; - - ItemSet supported = eeenchantment.getSupportedItems(); - if (supported.getMaterials().contains(key)) return false; - - return true; - } - - - private static final Method getDefinitonMethod; - - private static final Method getAnvilCostMethod; - private static final Method hasConflictsMethod; - private static final Method getExclusiveSetMethod; - static { - var enchClazz = CustomEnchantment.class; - try { - getDefinitonMethod = enchClazz.getDeclaredMethod("getDefinition"); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - - Class definitionClazz; - try { - definitionClazz = Class.forName("su.nightexpress.excellentenchants.api.EnchantDefinition"); - } catch (ClassNotFoundException e) { - try { - definitionClazz = Class.forName("su.nightexpress.excellentenchants.api.wrapper.EnchantDefinition"); - } catch (ClassNotFoundException ex) { - throw new RuntimeException(ex); - } - } - - // Now definition methods - try { - getAnvilCostMethod = definitionClazz.getDeclaredMethod("getAnvilCost"); - hasConflictsMethod = definitionClazz.getDeclaredMethod("hasConflicts"); - getExclusiveSetMethod = definitionClazz.getDeclaredMethod("getExclusiveSet"); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - - } - - private static Object getDefinition(CustomEnchantment enchantment) { - try { - return getDefinitonMethod.invoke(enchantment); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private static int getAnvilCost(CustomEnchantment enchantment) { - try { - return (int) getAnvilCostMethod.invoke(getDefinition(enchantment)); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - } - - private boolean hasConflicts() { - try { - return (boolean) hasConflictsMethod.invoke(definition); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - } - - - private Set getExclusiveSet() { - try { - return (Set) getExclusiveSetMethod.invoke(definition); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - } - - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEEV5_4Enchantment.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEEV5_4Enchantment.java deleted file mode 100644 index 7fb8627..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEEV5_4Enchantment.java +++ /dev/null @@ -1,29 +0,0 @@ -package xyz.alexcrea.cuanvil.enchant.wrapped; - -import org.bukkit.NamespacedKey; -import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.api.enchantment.CustomEnchantment; -import xyz.alexcrea.cuanvil.dependency.plugins.ExcellentEnchant5_4EnchantSettings; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; - -import java.util.Map; - -public class CAEEV5_4Enchantment extends CAEEV5Enchantment { - - public CAEEV5_4Enchantment(@NotNull CustomEnchantment enchantment) { - super(enchantment); - } - - @Override - public boolean isEnchantConflict(@NotNull Map enchantments, @NotNull NamespacedKey itemMat) { - if(super.isEnchantConflict(enchantments, itemMat)) return true; - - var limit = ExcellentEnchant5_4EnchantSettings.anvilLimit(); - var count = enchantments.keySet().stream() - .filter(key -> key instanceof CAEEV5_4Enchantment) - .count(); - - return count > limit; - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEcoEnchant.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEcoEnchant.java deleted file mode 100644 index 32d1346..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEcoEnchant.java +++ /dev/null @@ -1,79 +0,0 @@ -package xyz.alexcrea.cuanvil.enchant.wrapped; - -import com.willfp.ecoenchants.enchant.EcoEnchant; -import com.willfp.ecoenchants.target.EnchantmentTarget; -import com.willfp.ecoenchants.type.EnchantmentType; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; -import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity; - -import java.util.HashMap; -import java.util.Map; - -public class CAEcoEnchant extends CABukkitEnchantment implements AdditionalTestEnchantment { - - private final @NotNull EcoEnchant ecoEnchant; - - public CAEcoEnchant(@NotNull EcoEnchant enchant) { - super(enchant.getEnchantment(), EnchantmentRarity.COMMON); - this.ecoEnchant = enchant; - } - - @Override - public boolean isEnchantConflict(@NotNull Map enchantments, @NotNull NamespacedKey itemType) { - if (enchantments.isEmpty()) return false; - - // Check if there is only self - if (enchantments.size() == 1 && this.equals(enchantments.keySet().stream().findFirst().get())) - return false; - - if (this.ecoEnchant.getConflictsWithEverything()) { - return true; - } - - HashMap typeAmountMap = new HashMap<>(); - - for (CAEnchantment other : enchantments.keySet()) { - if (other instanceof CABukkitEnchantment otherVanilla - && this.ecoEnchant.conflictsWith(otherVanilla.getEnchant())) { - return true; - } - - if (other instanceof CAEcoEnchant ecoOther) { - EnchantmentType type = ecoOther.ecoEnchant.getType(); - typeAmountMap.putIfAbsent(type, 0); - - int amount = typeAmountMap.get(type) + 1; - if (amount > type.getLimit()) { - return true; - } - - typeAmountMap.put(type, amount); - } - - } - - return false; - } - - @Override - public boolean isItemConflict(@NotNull Map enchantments, - @NotNull NamespacedKey itemType, - @NotNull ItemStack item) { - if (Material.ENCHANTED_BOOK.getKey().equals(itemType)) { - return false; - } - - for (EnchantmentTarget target : this.ecoEnchant.getTargets()) { - if (target.matches(item)) { - return false; - } - } - - return true; - } -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEnchantSquaredEnchantment.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEnchantSquaredEnchantment.java deleted file mode 100644 index 8f1058e..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEnchantSquaredEnchantment.java +++ /dev/null @@ -1,79 +0,0 @@ -package xyz.alexcrea.cuanvil.enchant.wrapped; - -import me.athlaeos.enchantssquared.enchantments.CustomEnchant; -import me.athlaeos.enchantssquared.managers.CustomEnchantManager; -import org.bukkit.entity.HumanEntity; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.dependency.DependencyManager; -import xyz.alexcrea.cuanvil.enchant.CAEnchantmentBase; -import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity; - -import java.util.Map; -import java.util.Objects; - -public class CAEnchantSquaredEnchantment extends CAEnchantmentBase { - - public final @NotNull CustomEnchant enchant; - - public CAEnchantSquaredEnchantment(@NotNull CustomEnchant enchant) { - super(Objects.requireNonNull( - Objects.requireNonNull(DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility()).getKeyFromEnchant(enchant)), - EnchantmentRarity.COMMON, - enchant.getMaxLevel()); - this.enchant = enchant; - - } - - public @NotNull CustomEnchant getEnchant() { - return enchant; - } - - @Override - public boolean isGetOptimised() { - return true; - } - - @Override - public boolean isCleanOptimised() { - return true; - } - - @Override - public boolean isAllowed(@NotNull HumanEntity human) { - return this.enchant.hasPermission(human); - } - - @Override - public int getLevel(@NotNull ItemStack item, @NotNull ItemMeta meta) { - return CustomEnchantManager.getInstance().getEnchantStrength(item, this.enchant.getType()); - } - - @Override - public boolean isEnchantmentPresent(@NotNull ItemStack item, @NotNull ItemMeta meta) { - Map enchants = CustomEnchantManager.getInstance().getItemsEnchantsFromPDC(item); - return enchants.containsKey(this.enchant); - } - - @Override - public void addEnchantmentUnsafe(@NotNull ItemStack item, int level) { - CustomEnchantManager.getInstance().addEnchant(item, this.enchant.getType(), level); - } - - @Override - public void removeFrom(@NotNull ItemStack item) { - CustomEnchantManager.getInstance().removeEnchant(item, this.enchant.getType()); - } - - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof CAEnchantSquaredEnchantment other)) { - return false; - } - - return this.enchant.equals(other.getEnchant()); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAIncompatibleAllEnchant.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAIncompatibleAllEnchant.java deleted file mode 100644 index 552ecd4..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAIncompatibleAllEnchant.java +++ /dev/null @@ -1,36 +0,0 @@ -package xyz.alexcrea.cuanvil.enchant.wrapped; - -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.enchant.*; - -import java.util.Map; - -/** - * Represent an enchantment incompatible with every other enchantments - */ -public class CAIncompatibleAllEnchant extends CABukkitEnchantment implements AdditionalTestEnchantment { - - public CAIncompatibleAllEnchant(@NotNull Enchantment enchantment, @Nullable EnchantmentRarity rarity) { - super(enchantment, rarity); - } - - public CAIncompatibleAllEnchant(@NotNull Enchantment enchantment) { - super(enchantment); - } - - - @Override - public boolean isEnchantConflict(@NotNull Map enchantments, @NotNull NamespacedKey itemType) { - return !enchantments.isEmpty() && !(enchantments.size() == 1 && enchantments.containsKey(this)); - } - - @Override - public boolean isItemConflict(@NotNull Map enchantments, @NotNull NamespacedKey itemType, @NotNull ItemStack item) { - return false; - } -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CALegacyEEEnchantment.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CALegacyEEEnchantment.java deleted file mode 100644 index 74068d4..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CALegacyEEEnchantment.java +++ /dev/null @@ -1,44 +0,0 @@ -package xyz.alexcrea.cuanvil.enchant.wrapped; - -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; -import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; -import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity; - -import java.util.Map; -import java.util.Set; - -public class CALegacyEEEnchantment extends CABukkitEnchantment implements AdditionalTestEnchantment { - - @NotNull EnchantmentData eeenchantment; - - public CALegacyEEEnchantment(@NotNull EnchantmentData enchantment) { - super(enchantment.getEnchantment(), EnchantmentRarity.getRarity(enchantment.getAnvilCost())); - this.eeenchantment = enchantment; - - } - - @Override - public boolean isEnchantConflict(@NotNull Map enchantments, @NotNull NamespacedKey itemType) { - if (!eeenchantment.hasConflicts()) return false; - - Set conflicts = eeenchantment.getConflicts(); - - for (CAEnchantment caEnchantment : enchantments.keySet()) { - if (conflicts.contains(caEnchantment.getName())) return true; - } - - return false; - } - - @Override - public boolean isItemConflict(@NotNull Map enchantments, @NotNull NamespacedKey itemType, @NotNull ItemStack item) { - if (Material.ENCHANTED_BOOK.getKey().equals(itemType)) return false; - - return !eeenchantment.getSupportedItems().is(item); - } -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CALegacyEcoEnchant.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CALegacyEcoEnchant.java deleted file mode 100644 index cb24def..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CALegacyEcoEnchant.java +++ /dev/null @@ -1,68 +0,0 @@ -package xyz.alexcrea.cuanvil.enchant.wrapped; - -import com.willfp.ecoenchants.enchantments.EcoEnchant; -import com.willfp.ecoenchants.enchantments.meta.EnchantmentTarget; -import com.willfp.ecoenchants.enchantments.meta.EnchantmentType; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; -import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity; -import xyz.alexcrea.cuanvil.util.MaterialUtil; - -import java.util.Map; - -public class CALegacyEcoEnchant extends CABukkitEnchantment implements AdditionalTestEnchantment { - - private final @NotNull EcoEnchant ecoEnchant; - - public CALegacyEcoEnchant(@NotNull EcoEnchant ecoEnchant, @NotNull Enchantment enchantment) { - super(enchantment, EnchantmentRarity.COMMON); - this.ecoEnchant = ecoEnchant; - } - - @Override - public boolean isEnchantConflict(@NotNull Map enchantments, @NotNull NamespacedKey itemType) { - if (enchantments.isEmpty()) return false; - - EnchantmentType type = this.ecoEnchant.getType(); - boolean isSingular = type.isSingular(); - - for (CAEnchantment other : enchantments.keySet()) { - if (other instanceof CABukkitEnchantment otherVanilla - && this.ecoEnchant.conflictsWith(otherVanilla.getEnchant())) { - return true; - } - - if (isSingular && - other != this && - (other instanceof CALegacyEcoEnchant otherEco) && - type.equals(otherEco.ecoEnchant.getType())) { - return true; - } - } - - return false; - } - - @Override - public boolean isItemConflict(@NotNull Map enchantments, - @NotNull NamespacedKey itemType, - @NotNull ItemStack item) { - if (Material.ENCHANTED_BOOK.getKey().equals(itemType)) { - return false; - } - - var mat = MaterialUtil.INSTANCE.getMatFromKey(itemType); - for (EnchantmentTarget target : this.ecoEnchant.getTargets()) { - if (target.getMaterials().contains(mat)) { - return false; - } - } - - return true; - } -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CASuperEnchantEnchantment.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CASuperEnchantEnchantment.java deleted file mode 100644 index 6039dc8..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CASuperEnchantEnchantment.java +++ /dev/null @@ -1,76 +0,0 @@ -package xyz.alexcrea.cuanvil.enchant.wrapped; - -import com.maddoxh.superEnchants.enchants.CustomEnchant; -import com.maddoxh.superEnchants.enchants.EnchantManager; -import com.maddoxh.superEnchants.items.EnchantApplicator; -import com.maddoxh.superEnchants.items.EnchantReader; -import com.maddoxh.superEnchants.util.ConflictChecker; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.plugin.Plugin; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; -import xyz.alexcrea.cuanvil.enchant.CAEnchantmentBase; -import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity; - -import java.util.HashMap; -import java.util.Map; - -public class CASuperEnchantEnchantment extends CAEnchantmentBase implements AdditionalTestEnchantment { - - private @NotNull CustomEnchant enchant; - private @NotNull EnchantManager enchantManager; - - public CASuperEnchantEnchantment(@NotNull CustomEnchant enchant, @NotNull Plugin plugin, @NotNull EnchantManager enchantManager) { - super(NamespacedKey.fromString(enchant.getId(), plugin), EnchantmentRarity.COMMON, enchant.getMaxLevel()); - - this.enchant = enchant; - this.enchantManager = enchantManager; - } - - @Override - public int getLevel(@NotNull ItemStack item, @NotNull ItemMeta meta) { - return EnchantReader.INSTANCE.getEnchantLevel(item, enchant.getId()); - } - - @Override - public boolean isEnchantmentPresent(@NotNull ItemStack item, @NotNull ItemMeta meta) { - return EnchantReader.INSTANCE.hasEnchant(item, enchant.getId()); - } - - @Override - public void addEnchantmentUnsafe(@NotNull ItemStack item, int level) { - EnchantApplicator.INSTANCE.applyEnchant(item, enchant.getId(), level); - } - - @Override - public void removeFrom(@NotNull ItemStack item) { - EnchantApplicator.INSTANCE.removeEnchant(item, enchant.getId()); - } - - @Override - public boolean isEnchantConflict(@NotNull Map enchantments, @NotNull NamespacedKey itemType) { - var idMap = new HashMap(); - - enchantments.forEach((enchant, level) -> { - if(!(enchant instanceof CASuperEnchantEnchantment superEnch)) return; - idMap.put(superEnch.enchant.getId(), level); - }); - - return ConflictChecker.INSTANCE.hasConflict( - idMap, - enchant.getId(), - enchantManager - ) != null; - } - - @Override - public boolean isItemConflict(@NotNull Map enchantments, @NotNull NamespacedKey itemType, @NotNull ItemStack item) { - if(Material.ENCHANTED_BOOK.equals(item.getType())) return false; - - return !enchant.canApplyTo(item.getType()); - } -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/ValueUpdatableGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/ValueUpdatableGui.java deleted file mode 100644 index 16bc082..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/ValueUpdatableGui.java +++ /dev/null @@ -1,11 +0,0 @@ -package xyz.alexcrea.cuanvil.gui; - -import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; - -public interface ValueUpdatableGui { - - void updateGuiValues(); - - Gui getConnectedGui(); - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/MainConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/MainConfigGui.java deleted file mode 100644 index cc4fddc..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/MainConfigGui.java +++ /dev/null @@ -1,154 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.gui.type.ChestGui; -import com.github.stefvanschie.inventoryframework.pane.PatternPane; -import com.github.stefvanschie.inventoryframework.pane.util.Pattern; -import io.delilaheve.CustomAnvil; -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import xyz.alexcrea.cuanvil.dependency.packet.PacketManager; -import xyz.alexcrea.cuanvil.gui.config.global.*; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; - -import java.util.Collections; - -public class MainConfigGui extends ChestGui { - - private static final MainConfigGui INSTANCE = new MainConfigGui(); - - public static MainConfigGui getInstance() { - return INSTANCE; - } - - private MainConfigGui() { - super(3, "§8Anvil Config", CustomAnvil.instance); - } - - public void init(PacketManager packetManager) { - Pattern pattern = new Pattern( - GuiSharedConstant.EMPTY_GUI_FULL_LINE, - "012345678", - "Q00000000" - ); - PatternPane pane = new PatternPane(0, 0, 9, 3, pattern); - addPane(pane); - - GuiGlobalItems.addBackgroundItem(pane); - - // Basic config item - ItemStack basicConfigItemstack = new ItemStack(Material.COMMAND_BLOCK); - ItemMeta basicConfigMeta = basicConfigItemstack.getItemMeta(); - assert basicConfigMeta != null; - - basicConfigMeta.setDisplayName("§aBasic Config Menu"); - basicConfigMeta.setLore(Collections.singletonList("§7Click here to open basic config menu")); - basicConfigItemstack.setItemMeta(basicConfigMeta); - - GuiItem basicConfigItem = GuiGlobalItems.goToGuiItem(basicConfigItemstack, new BasicConfigGui(packetManager)); - pane.bindItem('1', basicConfigItem); - - // enchant level limit item - ItemStack enchantLimitItemstack = new ItemStack(Material.ENCHANTED_BOOK); - ItemMeta enchantLimitMeta = enchantLimitItemstack.getItemMeta(); - assert enchantLimitMeta != null; - - enchantLimitMeta.setDisplayName("§aEnchantment Level Limit"); - enchantLimitMeta.setLore(Collections.singletonList("§7Click here to open enchantment level limit menu")); - enchantLimitItemstack.setItemMeta(enchantLimitMeta); - - GuiItem enchantLimitItem = GuiGlobalItems.goToGuiItem(enchantLimitItemstack, new EnchantLimitConfigGui()); - pane.bindItem('2', enchantLimitItem); - - // enchant level limit item - ItemStack enchantMergeLimitItemstack = new ItemStack(Material.ENCHANTED_BOOK); - ItemMeta enchantMergeLimitMeta = enchantMergeLimitItemstack.getItemMeta(); - assert enchantMergeLimitMeta != null; - - enchantMergeLimitMeta.setDisplayName("§aEnchantment Merge Limit"); - enchantMergeLimitMeta.setLore(Collections.singletonList("§7Click here to open enchantment merge limit menu")); - enchantMergeLimitItemstack.setItemMeta(enchantMergeLimitMeta); - - GuiItem enchantMergeLimitItem = GuiGlobalItems.goToGuiItem(enchantMergeLimitItemstack, new EnchantMergeLimitConfigGui()); - pane.bindItem('3', enchantMergeLimitItem); - - // enchant cost item - ItemStack enchantCostItemstack = new ItemStack(Material.EXPERIENCE_BOTTLE); - ItemMeta enchantCostMeta = enchantCostItemstack.getItemMeta(); - assert enchantCostMeta != null; - - enchantCostMeta.setDisplayName("§aEnchantment Cost"); - enchantCostMeta.setLore(Collections.singletonList("§7Click here to open enchantment costs menu")); - enchantCostItemstack.setItemMeta(enchantCostMeta); - - GuiItem enchantCostItem = GuiGlobalItems.goToGuiItem(enchantCostItemstack, new EnchantCostConfigGui()); - pane.bindItem('4', enchantCostItem); - - // Enchantment Conflicts item - ItemStack enchantConflictItemstack = new ItemStack(Material.OAK_FENCE); - ItemMeta enchantConflictMeta = enchantConflictItemstack.getItemMeta(); - assert enchantConflictMeta != null; - - enchantConflictMeta.setDisplayName("§aEnchantment Conflict"); - enchantConflictMeta.setLore(Collections.singletonList("§7Click here to open enchantment conflict menu")); - enchantConflictItemstack.setItemMeta(enchantConflictMeta); - - GuiItem enchantConflictItem = GuiGlobalItems.goToGuiItem(enchantConflictItemstack, EnchantConflictGui.getInstance()); - pane.bindItem('5', enchantConflictItem); - - // Group config items - ItemStack groupItemstack = new ItemStack(Material.CHEST); - ItemMeta groupMeta = groupItemstack.getItemMeta(); - assert groupMeta != null; - - groupMeta.setDisplayName("§aItem Groups"); - groupMeta.setLore(Collections.singletonList("§7Click here to open item group menu")); - groupItemstack.setItemMeta(groupMeta); - - GuiItem groupConfigItem = GuiGlobalItems.goToGuiItem(groupItemstack, GroupConfigGui.getInstance()); - - pane.bindItem('6', groupConfigItem); - - // Unit repair item - ItemStack unirRepairItemstack = new ItemStack(Material.DIAMOND); - ItemMeta unitRepairMeta = unirRepairItemstack.getItemMeta(); - assert unitRepairMeta != null; - - unitRepairMeta.setDisplayName("§aUnit Repair"); - unitRepairMeta.setLore(Collections.singletonList("§7Click here to open anvil unit repair menu")); - unirRepairItemstack.setItemMeta(unitRepairMeta); - - GuiItem unitRepairItem = GuiGlobalItems.goToGuiItem(unirRepairItemstack, UnitRepairConfigGui.getInstance()); - pane.bindItem('7', unitRepairItem); - - // Custom recipe item - ItemStack customRecipeItemstack = new ItemStack(Material.CRAFTING_TABLE); - ItemMeta customRecipeMeta = customRecipeItemstack.getItemMeta(); - assert customRecipeMeta != null; - - customRecipeMeta.setDisplayName("§aCustom recipes"); - customRecipeMeta.setLore(Collections.singletonList("§7Click here to open anvil custom recipe menu")); - customRecipeItemstack.setItemMeta(customRecipeMeta); - - GuiItem customRecipeItem = GuiGlobalItems.goToGuiItem(customRecipeItemstack, CustomRecipeConfigGui.getInstance()); - pane.bindItem('8', customRecipeItem); - - // quit item - ItemStack quitItemstack = new ItemStack(Material.BARRIER); - ItemMeta quitMeta = quitItemstack.getItemMeta(); - assert quitMeta != null; - - quitMeta.setDisplayName("§cQuit"); - quitItemstack.setItemMeta(quitMeta); - - GuiItem quitItem = new GuiItem(quitItemstack, event -> { - event.setCancelled(true); - event.getWhoClicked().closeInventory(); - }, CustomAnvil.instance); - pane.bindItem('Q', quitItem); - - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/SelectEnchantmentContainer.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/SelectEnchantmentContainer.java deleted file mode 100644 index 1174209..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/SelectEnchantmentContainer.java +++ /dev/null @@ -1,15 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config; - -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; - -import java.util.Set; - -public interface SelectEnchantmentContainer { - - Set getSelectedEnchantments(); - - boolean setSelectedEnchantments(Set enchantments); - - Set illegalEnchantments(); - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/SelectGroupContainer.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/SelectGroupContainer.java deleted file mode 100644 index 49f8b3b..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/SelectGroupContainer.java +++ /dev/null @@ -1,45 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config; - -import xyz.alexcrea.cuanvil.group.AbstractMaterialGroup; -import xyz.alexcrea.cuanvil.util.CasedStringUtil; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -public interface SelectGroupContainer { - - Set getSelectedGroups(); - - boolean setSelectedGroups(Set groups); - - Set illegalGroups(); - - static List getGroupLore(SelectGroupContainer container, String containerType, String groupAction){ - // Prepare group lore - ArrayList groupLore = new ArrayList<>(); - groupLore.add("§7Allow you to select a list of §3Groups §7that this " + containerType + " should " + groupAction); - Set grouos = container.getSelectedGroups(); - if (grouos.isEmpty()) { - groupLore.add("§7There is no "+groupAction+"d group for this "+containerType+"."); - } else { - groupLore.add("§7List of "+groupAction+"d groups for this "+containerType+":"); - Iterator groupIterator = grouos.iterator(); - - boolean greaterThanMax = grouos.size() > 5; - int maxindex = (greaterThanMax ? 4 : grouos.size()); - for (int i = 0; i < maxindex; i++) { - // format string like "- Melee Weapons" - String formattedName = CasedStringUtil.snakeToUpperSpacedCase(groupIterator.next().getName()); - groupLore.add("§7- §3" + formattedName); - - } - if (greaterThanMax) { - groupLore.add("§7And " + (grouos.size() - 4) + " more..."); - } - } - return groupLore; - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/SelectMaterialContainer.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/SelectMaterialContainer.java deleted file mode 100644 index 3756341..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/SelectMaterialContainer.java +++ /dev/null @@ -1,43 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config; - -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import xyz.alexcrea.cuanvil.util.CasedStringUtil; - -import java.util.*; - -public interface SelectMaterialContainer { - - Set getSelectedMaterials(); - - boolean setSelectedMaterials(Set materials); - - Set illegalMaterials(); - - static List getMaterialLore(SelectMaterialContainer container, String containerType, String action){ - // Prepare material lore - ArrayList groupLore = new ArrayList<>(); - groupLore.add("§7Allow you to select a list of §ematerials §7that this " + containerType + " should " + action); - Set materialSet = container.getSelectedMaterials(); - if (materialSet.isEmpty()) { - groupLore.add("§7There is no "+action+"d material for this "+containerType+"."); - } else { - groupLore.add("§7List of "+action+"d materials for this "+containerType+":"); - Iterator materialIterator = materialSet.iterator(); - - boolean greaterThanMax = materialSet.size() > 5; - int maxindex = (greaterThanMax ? 4 : materialSet.size()); - for (int i = 0; i < maxindex; i++) { - // format string like "- Stone Sword" - String formattedName = CasedStringUtil.snakeToUpperSpacedCase(materialIterator.next().getKey().toLowerCase()); - groupLore.add("§7- §e" + formattedName); - - } - if (greaterThanMax) { - groupLore.add("§7And " + (materialSet.size() - 4) + " more..."); - } - } - return groupLore; - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/AbstractAskGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/AbstractAskGui.java deleted file mode 100644 index 66dd936..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/AbstractAskGui.java +++ /dev/null @@ -1,42 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.ask; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.gui.type.ChestGui; -import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; -import com.github.stefvanschie.inventoryframework.pane.PatternPane; -import com.github.stefvanschie.inventoryframework.pane.util.Pattern; -import io.delilaheve.CustomAnvil; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; - -public abstract class AbstractAskGui extends ChestGui { - - protected PatternPane pane; - AbstractAskGui(int rows, @NotNull String name, - Gui backOnCancel){ - super(rows, name, CustomAnvil.instance); - - Pattern pattern = getGuiPattern(); - this.pane = new PatternPane(0, 0, pattern.getLength(), pattern.getHeight(), pattern); - addPane(this.pane); - - this.pane.bindItem('0', GuiGlobalItems.backgroundItem()); - this.pane.bindItem('B', new GuiItem(GuiSharedConstant.CANCEL_ITEM, GuiGlobalActions.openGuiAction(backOnCancel), CustomAnvil.instance)); - - } - - /** - * Used to get the gui pattern. - * Reserved character are: - *

      - *
    • B: "cancel" button.
    • - *
    • 0: default background item.
    • - *
    - * - * @return The gui's pattern. - */ - protected abstract Pattern getGuiPattern(); - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/ConfirmActionGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/ConfirmActionGui.java deleted file mode 100644 index 5839663..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/ConfirmActionGui.java +++ /dev/null @@ -1,84 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.ask; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; -import com.github.stefvanschie.inventoryframework.pane.util.Pattern; -import io.delilaheve.CustomAnvil; -import org.bukkit.Material; -import org.bukkit.entity.HumanEntity; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; -import xyz.alexcrea.cuanvil.util.MetricsUtil; - -import java.util.Arrays; -import java.util.function.Supplier; -import java.util.logging.Level; - -public class ConfirmActionGui extends AbstractAskGui { - - public ConfirmActionGui(@NotNull String title, String actionDescription, - Gui backOnCancel, Gui backOnConfirm, Supplier onConfirm, - boolean permanent) { - super(3, title, backOnCancel); - - // Save item - this.pane.bindItem('S', new GuiItem( - (permanent ? GuiSharedConstant.CONFIRM_PERMANENT_ITEM : GuiSharedConstant.CONFIRM_ITEM), - event -> { - event.setCancelled(true); - HumanEntity player = event.getWhoClicked(); - - if (!player.hasPermission(CustomAnvil.editConfigPermission)) { - player.closeInventory(); - player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); - return; - } - - boolean success; - try { - success = onConfirm.get(); - } catch (Exception e) { - CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not process confirmation supplier.", e); - MetricsUtil.INSTANCE.trackError(e); - success = false; - } - - if (!success) { - event.getWhoClicked().sendMessage("§cAction could not be completed. "); - } - backOnConfirm.show(player); - - }, CustomAnvil.instance)); - - // Info item - ItemStack infoItem = new ItemStack(Material.PAPER); - ItemMeta infoMeta = infoItem.getItemMeta(); - - infoMeta.setDisplayName("§eAre you sure ?"); - if(actionDescription != null){ - infoMeta.setLore(Arrays.asList(actionDescription.split("\n"))); - } - - infoItem.setItemMeta(infoMeta); - - pane.bindItem('I', new GuiItem(infoItem, GuiGlobalActions.stayInPlace, CustomAnvil.instance)); - } - public ConfirmActionGui(@NotNull String title, String actionDescription, - Gui backOnCancel, Gui backOnConfirm, Supplier onConfirm){ - this(title, actionDescription, backOnCancel, backOnConfirm, onConfirm, true); - } - - - @Override - protected Pattern getGuiPattern() { - return new Pattern( - GuiSharedConstant.EMPTY_GUI_FULL_LINE, - "00B0I0S00", - GuiSharedConstant.EMPTY_GUI_FULL_LINE - ); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/SelectItemTypeGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/SelectItemTypeGui.java deleted file mode 100644 index 66411bd..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/SelectItemTypeGui.java +++ /dev/null @@ -1,99 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.ask; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; -import com.github.stefvanschie.inventoryframework.pane.util.Pattern; -import io.delilaheve.CustomAnvil; -import org.bukkit.Material; -import org.bukkit.entity.HumanEntity; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; -import xyz.alexcrea.cuanvil.util.MaterialUtil; - -import java.util.Arrays; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiConsumer; - -public class SelectItemTypeGui extends AbstractAskGui { - - private ItemStack selectedItem; - public SelectItemTypeGui(@NotNull String title, - @NotNull String actionDescription, - @NotNull Gui backOnCancel, - @NotNull BiConsumer onSave, - boolean materialOnly) { - super(3, title, backOnCancel); - this.selectedItem = null; - - // Save item - GuiItem confirmItem = new GuiItem(GuiSharedConstant.CONFIRM_ITEM, event -> { - event.setCancelled(true); - HumanEntity player = event.getWhoClicked(); - - if (!player.hasPermission(CustomAnvil.editConfigPermission)) { - player.closeInventory(); - player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); - return; - } - - onSave.accept(this.selectedItem, player); - - }, CustomAnvil.instance); - this.pane.bindItem('S', GuiGlobalItems.backgroundItem()); - - // Select item - ItemStack selectItem = setDisplayMeta(new ItemStack(Material.BARRIER), actionDescription); - - AtomicReference selectGuiItem = new AtomicReference<>(); - selectGuiItem.set(new GuiItem(selectItem, event -> { - event.setCancelled(true); - - ItemStack cursor = event.getWhoClicked().getItemOnCursor(); - if(MaterialUtil.INSTANCE.isAir(cursor)) return; - - ItemStack finalItem; - if(materialOnly){ - finalItem = setDisplayMeta(new ItemStack(cursor.getType()), actionDescription); - }else{ - finalItem = cursor.clone(); - } - this.selectedItem = finalItem.clone(); - - selectGuiItem.get().setItem(finalItem); - this.pane.bindItem('S', confirmItem); - - update(); - }, CustomAnvil.instance)); - - this.pane.bindItem('V', selectGuiItem.get()); - - // Temporary leave item - GuiItem temporaryLeave = GuiGlobalItems.temporaryCloseGuiToSelectItem(Material.YELLOW_STAINED_GLASS_PANE, this); - - this.pane.bindItem('s', temporaryLeave); - - } - - private ItemStack setDisplayMeta(ItemStack item, String actionDescription){ - ItemMeta meta = item.getItemMeta(); - - meta.setDisplayName("§ePlace an item here"); - meta.setLore(Arrays.asList(actionDescription.split("\n"))); - - item.setItemMeta(meta); - return item; - } - - @Override - protected Pattern getGuiPattern() { - return new Pattern( - GuiSharedConstant.EMPTY_GUI_FULL_LINE, - "0000V000s", - "B0000000S" - ); - } -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/AbstractEnchantConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/AbstractEnchantConfigGui.java deleted file mode 100644 index 6bd7ea3..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/AbstractEnchantConfigGui.java +++ /dev/null @@ -1,117 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.global; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.pane.util.Pattern; -import org.bukkit.event.inventory.InventoryClickEvent; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; -import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry; -import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; -import xyz.alexcrea.cuanvil.gui.config.list.SettingGuiListConfigGui; -import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui; -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.function.Consumer; - -/** - * Abstract Global Config gui for enchantment setting configuration. - * - * @param Type of the factory of the type of setting the gui should edit. - */ -public abstract class AbstractEnchantConfigGui extends SettingGuiListConfigGui{ - - /** - * Constructor for a gui displaying available enchantment to edit a enchantment setting. - * - * @param title Title of the gui. - */ - protected AbstractEnchantConfigGui(String title) { - super(title); - } - - @Override - public void updateGuiValues() { //TODO maybe optimise it. - reloadValues(); - } - - @Override - protected Collection getEveryDisplayableInstanceOfGeneric() { - return CAEnchantmentRegistry.getInstance().getNameSortedEnchantments(); - } - - @Override - protected Pattern getBackgroundPattern(){ - return new Pattern( - GuiSharedConstant.UPPER_FILLER_FULL_PLANE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - "B11L1R111" - ); - } - - @Override - public void updateValueForGeneric(CAEnchantment generic, boolean shouldUpdate) { - updateValueForGeneric(generic, shouldUpdate, true); - } - - public void updateValueForGeneric(CAEnchantment generic, boolean shouldUpdate, boolean prepareSorting) { - if(!prepareSorting) { - super.updateValueForGeneric(generic, shouldUpdate); - return; - } - - if(!this.factoryMap.containsKey(generic)){ - // We need to sort elements again - super.updateValueForGeneric(generic, false); - - // Clear page then refill all of them - this.firstPage.clear(); - this.pages.clear(); - this.pages.add(this.firstPage); - - for (CAEnchantment enchantment : getEveryDisplayableInstanceOfGeneric()) { - GuiItem item = this.guiItemMap.get(enchantment); - - if(item == null) { - updateValueForGeneric(enchantment, false, false); - }else { - addToPage(item); - } - - } - - if(shouldUpdate) update(); - - }else{ - super.updateValueForGeneric(generic, shouldUpdate); - - } - - } - - - // Unused methods - @Override - protected GuiItem prepareCreateNewItem() { - return null; - } - - @Override - protected List getCreateItemLore() { - return Collections.emptyList(); - } - @Override - protected Consumer getCreateClickConsumer() { - return null; - } - - @Override - protected String createItemName() { - return null; - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/BasicConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/BasicConfigGui.java deleted file mode 100644 index 51936c7..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/BasicConfigGui.java +++ /dev/null @@ -1,371 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.global; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.gui.type.ChestGui; -import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; -import com.github.stefvanschie.inventoryframework.pane.PatternPane; -import com.github.stefvanschie.inventoryframework.pane.util.Pattern; -import io.delilaheve.CustomAnvil; -import io.delilaheve.util.ConfigOptions; -import kotlin.ranges.IntRange; -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.dependency.MinecraftVersionUtil; -import xyz.alexcrea.cuanvil.dependency.packet.PacketManager; -import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; -import xyz.alexcrea.cuanvil.gui.config.MainConfigGui; -import xyz.alexcrea.cuanvil.gui.config.settings.BoolSettingsGui; -import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui; -import xyz.alexcrea.cuanvil.gui.config.settings.WorkPenaltyTypeSettingGui; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; - -/** - * Global config to edit basic basic settings. - */ -public class BasicConfigGui extends ChestGui implements ValueUpdatableGui { - - private static BasicConfigGui INSTANCE = null; - - @Nullable - public static BasicConfigGui getInstance() { - return INSTANCE; - } - - private final PacketManager packetManager; - /** - * Constructor of this Global gui for basic settings. - */ - public BasicConfigGui(PacketManager packetManager) { - super(4, "§8Basic Config", CustomAnvil.instance); - if(INSTANCE == null) INSTANCE = this; - - this.packetManager = packetManager; - init(); - } - - PatternPane pane; - - /** - * Initialise Basic gui - */ - private void init() { - Pattern pattern = new Pattern( - GuiSharedConstant.EMPTY_GUI_FULL_LINE, - "LT0IWS0cp", - "CR0U0r0hP", - "B00000000" - ); - pane = new PatternPane(0, 0, 9, 4, pattern); - addPane(pane); - - GuiGlobalItems.addBackItem(pane, MainConfigGui.getInstance()); - GuiGlobalItems.addBackgroundItem(pane); - - prepareValues(); - updateGuiValues(); - } - - private BoolSettingsGui.BoolSettingFactory capAnvilCost; // L character - private GuiItem noCapRepairItem; - private IntSettingsGui.IntSettingFactory maxAnvilCost; // C character - private GuiItem noMaxCostItem; - - private BoolSettingsGui.BoolSettingFactory removeAnvilCostLimit; // R character - private BoolSettingsGui.BoolSettingFactory replaceTooExpensive; // T character - - private IntSettingsGui.IntSettingFactory itemRepairCost; // I character - private IntSettingsGui.IntSettingFactory unitRepairCost; // U character - private IntSettingsGui.IntSettingFactory itemRenameCost; // r character - private IntSettingsGui.IntSettingFactory sacrificeIllegalEnchantCost; // S character - - private BoolSettingsGui.BoolSettingFactory allowColorCode; // c character - private BoolSettingsGui.BoolSettingFactory allowHexColor; // h character - - private BoolSettingsGui.BoolSettingFactory permissionNeededForColor; // p character - private GuiItem noPermissionNeededItem; - private IntSettingsGui.IntSettingFactory useOfColorCost; // P character - private GuiItem noColorCostItem; - - /** - * Prepare basic gui displayed items factory and static items.. - */ - protected void prepareValues() { - // cap anvil cost - this.capAnvilCost = new BoolSettingsGui.BoolSettingFactory("§8Cap Anvil Cost ?", this, - ConfigHolder.DEFAULT_CONFIG, - ConfigOptions.CAP_ANVIL_COST, ConfigOptions.DEFAULT_CAP_ANVIL_COST, - "§7All anvil cost will be capped to §aMax Anvil Cost§7 if enabled.", - "§7In other words:", - "§7For any anvil cost greater than §aMax Anvil Cost§7, Cost will be set to §aMax Anvil Cost§7."); - // cap anvil cost not needed - ItemStack item = new ItemStack(Material.BARRIER); - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§cCap Anvil Cost ?"); - meta.setLore(Collections.singletonList("§7This config only work if §cLimit Repair Cost§7 is disabled.")); - item.setItemMeta(meta); - this.noCapRepairItem = new GuiItem(item, GuiGlobalActions.stayInPlace, CustomAnvil.instance); - - - // repair cost item - IntRange range = ConfigOptions.MAX_ANVIL_COST_RANGE; - this.maxAnvilCost = new IntSettingsGui.IntSettingFactory("§8Max Anvil Cost", this, - ConfigOptions.MAX_ANVIL_COST, ConfigHolder.DEFAULT_CONFIG, - Arrays.asList( - "§7Max cost the Anvil can get to.", - "§7Valid values include §e0 §7to §e1000§7.", - "§7Cost will be displayed as §cToo Expensive§7:", - "§7- If Cost is above §e39", - "§7- And §eReplace Too Expensive§7 is disabled" - ), - range.getFirst(), range.getLast(), - ConfigOptions.DEFAULT_MAX_ANVIL_COST, - 1, 5, 10); - // max anvil cost not needed - item = new ItemStack(Material.BARRIER); - meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§cMax Anvil Cost"); - meta.setLore(Collections.singletonList("§7This config only work if §cLimit Repair Cost§7 is disabled.")); - item.setItemMeta(meta); - this.noMaxCostItem = new GuiItem(item, GuiGlobalActions.stayInPlace, CustomAnvil.instance); - - - // remove repair limit item - this.removeAnvilCostLimit = new BoolSettingsGui.BoolSettingFactory("§8Remove Anvil Cost Limit ?", this, - ConfigHolder.DEFAULT_CONFIG, - ConfigOptions.REMOVE_ANVIL_COST_LIMIT, ConfigOptions.DEFAULT_REMOVE_ANVIL_COST_LIMIT, - "§7Whether the anvil's cost limit should be removed entirely.", - "§7The anvil will still visually display §cToo Expensive§7 if §eReplace Too Expensive§7 is disabled.", - "§7However, the action will be completable if xp requirement is meet."); - - // replace too expensive item - this.replaceTooExpensive = new BoolSettingsGui.BoolSettingFactory("§8Replace Too Expensive ?", this, - ConfigHolder.DEFAULT_CONFIG, - ConfigOptions.REPLACE_TOO_EXPENSIVE, ConfigOptions.DEFAULT_REPLACE_TOO_EXPENSIVE, - getReplaceToExpensiveLore()); - - // ------------ - // Cost config - // ------------ - - // item repair cost - range = ConfigOptions.REPAIR_COST_RANGE; - this.itemRepairCost = new IntSettingsGui.IntSettingFactory("§8Item Repair Cost", this, - ConfigOptions.ITEM_REPAIR_COST, ConfigHolder.DEFAULT_CONFIG, - Arrays.asList( - "§7XP Level amount added to the anvil when the item", - "§7is repaired by another item of the same type." - ), - range.getFirst(), range.getLast(), - ConfigOptions.DEFAULT_ITEM_REPAIR_COST, - 1, 5, 10, 50, 100); - - // unit repair cost - this.unitRepairCost = new IntSettingsGui.IntSettingFactory("§8Unit Repair Cost", this, - ConfigOptions.UNIT_REPAIR_COST, ConfigHolder.DEFAULT_CONFIG, - Arrays.asList( - "§7XP Level amount added to the anvil when the item is repaired by an §eunit§7.", - "§7For example: a Diamond on a Diamond Sword.", - "§7What's considered unit for what can be edited on the unit repair configuration." - ), - range.getFirst(), range.getLast(), - ConfigOptions.DEFAULT_UNIT_REPAIR_COST, - 1, 5, 10, 50, 100); - - // item rename cost - range = ConfigOptions.ITEM_RENAME_COST_RANGE; - this.itemRenameCost = new IntSettingsGui.IntSettingFactory("§8Rename Cost", this, - ConfigOptions.ITEM_RENAME_COST, ConfigHolder.DEFAULT_CONFIG, - Arrays.asList( - "§7XP Level amount added to the anvil when the item is renamed." - ), - range.getFirst(), range.getLast(), - ConfigOptions.DEFAULT_ITEM_RENAME_COST, - 1, 5, 10, 50, 100); - - // sacrifice illegal enchant cost - range = ConfigOptions.SACRIFICE_ILLEGAL_COST_RANGE; - this.sacrificeIllegalEnchantCost = new IntSettingsGui.IntSettingFactory("§8Sacrifice Illegal Enchant Cost", this, - ConfigOptions.SACRIFICE_ILLEGAL_COST, ConfigHolder.DEFAULT_CONFIG, - Arrays.asList( - "§7XP Level amount added to the anvil when a sacrifice enchantment", - "§7conflict With one of the left item enchantment" - ), - range.getFirst(), range.getLast(), - ConfigOptions.DEFAULT_SACRIFICE_ILLEGAL_COST, - 1, 5, 10, 50, 100); - - // ------------- - // Color config - // ------------- - - // Allow us of color code - this.allowColorCode = new BoolSettingsGui.BoolSettingFactory("§8Allow Use Of Color Code ?", this, - ConfigHolder.DEFAULT_CONFIG, - ConfigOptions.ALLOW_COLOR_CODE, ConfigOptions.DEFAULT_ALLOW_COLOR_CODE, - "§7Whether players can use color code.", - "§7Color code a formatted like §a&a§7 and is used in the rename field of the anvil.", - "§7Player may need permission to use color code if §ePlayer need permission to use color§7 is enabled."); - - // Allow us of hexadecimal color - this.allowHexColor = new BoolSettingsGui.BoolSettingFactory("§8Allow Use Of Hexadecimal Color ?", this, - ConfigHolder.DEFAULT_CONFIG, - ConfigOptions.ALLOW_HEXADECIMAL_COLOR, ConfigOptions.DEFAULT_ALLOW_HEXADECIMAL_COLOR, - "§7Whether players can use hexadecimal color.", - "§7Color code a formatted like §2#012345 §7and is used in the rename field of the anvil.", - "§7Player may need permission to use color code if §ePermission Needed For Color§7 is enabled."); - - // Permission needed for color - this.permissionNeededForColor = new BoolSettingsGui.BoolSettingFactory("§8Need Permission To Use Color ?", this, - ConfigHolder.DEFAULT_CONFIG, - ConfigOptions.PERMISSION_NEEDED_FOR_COLOR, ConfigOptions.DEFAULT_PERMISSION_NEEDED_FOR_COLOR, - "§7Whether players should have permission to be able to use colors.", - "§7Give player §eca.color.code§7 Permission to allow use of color code.", - "§7Give player §eca.color.hex§7 Permission to allow use of hexadecimal color."); - - // Permission needed for color not necessary - item = new ItemStack(Material.BARRIER); - meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§cNeed Permission To Use Color ?"); - meta.setLore(Arrays.asList("§7This config can do something only if one of the following config is enabled:", - "§7- §aAllow Use Of Color Code", - "§7- §aAllow Use Of Hexadecimal Color")); - item.setItemMeta(meta); - this.noPermissionNeededItem = new GuiItem(item, GuiGlobalActions.stayInPlace, CustomAnvil.instance); - - // Cost of using color - range = ConfigOptions.USE_OF_COLOR_COST_RANGE; - this.useOfColorCost = new IntSettingsGui.IntSettingFactory("§8Cost Of Using Color", this, - ConfigOptions.USE_OF_COLOR_COST, ConfigHolder.DEFAULT_CONFIG, - Arrays.asList( - "§7XP level cost when using color code or hexadecimal color using the anvil.", - "§7conflict With one of the left item enchantment" - ), - range.getFirst(), range.getLast(), - ConfigOptions.DEFAULT_USE_OF_COLOR_COST, - 1, 5, 10, 50, 100); - - // Permission needed for color not necessary - item = new ItemStack(Material.BARRIER); - meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§cCost Of Using Color"); - meta.setLore(Arrays.asList("§7This config can do something only if one of the following config is enabled:", - "§7- §aAllow Use Of Color Code", - "§7- §aAllow Use Of Hexadecimal Color")); - item.setItemMeta(meta); - this.noColorCostItem = new GuiItem(item, GuiGlobalActions.stayInPlace, CustomAnvil.instance); - - } - - @NotNull - private String[] getReplaceToExpensiveLore() { - ArrayList lore = new ArrayList<>(); - lore.add("§7Whenever anvil cost is above §e39§7 should display the true price and not §cToo Expensive§7."); - lore.add("§7However, when bypassing §cToo Expensive§7, anvil price will be displayed as §aGreen§7."); - lore.add("§7Even if cost is displayed as §aGreen§7:"); - lore.add("§7If the player do not have the required xp level, the action will not be completable."); - - if(!this.packetManager.getCanSetInstantBuild()){ - lore.add(""); - lore.add("§4/!\\§cCaution§4/!\\ §cYou need ProtocoLib installed and working or a paper server."); - lore.add("§cCurrently ProtocoLib is not detected."); - } - - String[] loreAsArray = new String[lore.size()]; - return lore.toArray(loreAsArray); - } - - @Override - public void updateGuiValues() { - // limit and cap anvil cost item - GuiItem capAnvilCostItem; - GuiItem maxAnvilCostItem; - if (!this.removeAnvilCostLimit.getConfiguredValue()) { - capAnvilCostItem = this.capAnvilCost.getItem("Cap Anvil Cost"); - maxAnvilCostItem = this.maxAnvilCost.getItem(Material.EXPERIENCE_BOTTLE, "Max Anvil Cost"); - } else { - capAnvilCostItem = this.noCapRepairItem; - maxAnvilCostItem = this.noMaxCostItem; - } - - pane.bindItem('L', capAnvilCostItem); - pane.bindItem('C', maxAnvilCostItem); - - // remove repair limit item - GuiItem removeRepairLimitItem = this.removeAnvilCostLimit.getItem("Remove Anvil Cost Limit"); - pane.bindItem('R', removeRepairLimitItem); - - // replace too expensive item - GuiItem replaceToExpensiveItem = this.replaceTooExpensive.getItem(); - pane.bindItem('T', replaceToExpensiveItem); - - - // item repair cost - GuiItem itemRepairCostItem = this.itemRepairCost.getItem(Material.ANVIL); - pane.bindItem('I', itemRepairCostItem); - - // unit repair cost - GuiItem unitRepairCostItem = this.unitRepairCost.getItem(Material.DIAMOND); - pane.bindItem('U', unitRepairCostItem); - - // item rename cost - GuiItem itemRenameCostItem = this.itemRenameCost.getItem(Material.NAME_TAG); - pane.bindItem('r', itemRenameCostItem); - - // sacrifice illegal enchant cost - GuiItem illegalCostItem = this.sacrificeIllegalEnchantCost.getItem(Material.ENCHANTED_BOOK); - pane.bindItem('S', illegalCostItem); - - // work penalty type - GuiItem workPenaltyType = WorkPenaltyTypeSettingGui.getDisplayItem(this, Material.DAMAGED_ANVIL, "§aWork Penalty Type"); - pane.bindItem('W', workPenaltyType); - - // allow color code - GuiItem allowColorCodeItem = this.allowColorCode.getItem(); - pane.bindItem('c', allowColorCodeItem); - - // allow hex color - GuiItem allowHexColorItem = this.allowHexColor.getItem(); - pane.bindItem('h', allowHexColorItem); - - // True if player could place color - if(ConfigOptions.INSTANCE.getRenameColorPossible()){ - // use permission for color - GuiItem permissionNeededItem = this.permissionNeededForColor.getItem(); - pane.bindItem('p', permissionNeededItem); - - // using color cost - GuiItem useColorCostItem = this.useOfColorCost.getItem(Material.EXPERIENCE_BOTTLE, "Use color"); - pane.bindItem('P', useColorCostItem); - }else{ - pane.bindItem('p', this.noPermissionNeededItem); - pane.bindItem('P', this.noColorCostItem); - } - - - update(); - } - - @Override - public Gui getConnectedGui() { - return this; - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/CustomRecipeConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/CustomRecipeConfigGui.java deleted file mode 100644 index e21ad75..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/CustomRecipeConfigGui.java +++ /dev/null @@ -1,119 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.global; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import org.bukkit.Material; -import org.bukkit.inventory.ItemFlag; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.gui.config.list.MappedGuiListConfigGui; -import xyz.alexcrea.cuanvil.gui.config.list.elements.CustomRecipeSubSettingGui; -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; -import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe; -import xyz.alexcrea.cuanvil.util.CasedStringUtil; - -import java.util.ArrayList; -import java.util.Collection; - -public class CustomRecipeConfigGui extends MappedGuiListConfigGui> { - - private static CustomRecipeConfigGui INSTANCE = new CustomRecipeConfigGui(); - - @Nullable - public static CustomRecipeConfigGui getCurrentInstance() { - return INSTANCE; - } - - @NotNull - public static CustomRecipeConfigGui getInstance() { - if (INSTANCE == null) INSTANCE = new CustomRecipeConfigGui(); - - return INSTANCE; - } - - private CustomRecipeConfigGui() { - super("Custom Recipe Config"); - - init(); - } - - @Override - protected ItemStack createItemForGeneric(AnvilCustomRecipe recipe) { - // Get base item to display - ItemStack craftResultItem = recipe.getResultItem(); - ItemStack displayedItem; - if (craftResultItem == null) { - displayedItem = new ItemStack(Material.BARRIER); - } else { - displayedItem = craftResultItem.clone(); - } - - // edit displayed item - ItemMeta meta = displayedItem.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§e" + CasedStringUtil.snakeToUpperSpacedCase(recipe.toString()) + " §fCustom recipe"); - meta.addItemFlags(ItemFlag.values()); - - meta.setLore(getRecipeLore(recipe)); - - displayedItem.setItemMeta(meta); - return displayedItem; - } - - private static @NotNull ArrayList getRecipeLore(AnvilCustomRecipe recipe) { - boolean shouldWork = recipe.validate(); - - ArrayList lore = new ArrayList<>(); - lore.add("§7Is valid: §" + (shouldWork ? "aYes" : "cNo")); - lore.add("§7Exact count: §" + (recipe.getExactCount() ? "aYes" : "cNo")); - lore.add("§7Recipe Level Cost: §e" + recipe.getLevelCostPerCraft()); - lore.add("§7Recipe Linear Xp Cost: §e" + recipe.getXpCostPerCraft()); - if (recipe.getXpCostPerCraft() != 0) { - lore.add("§7Exact Linear xp remove: §" + (recipe.getRemoveExactLinearXp() ? "aYes" : "cNo")); - } - return lore; - } - - @Override - protected LazyElement newInstanceOfGui(AnvilCustomRecipe generic, GuiItem item) { - return new LazyElement<>(item, () -> new CustomRecipeSubSettingGui(this, generic)); - } - - @Override - protected String genericDisplayedName() { - return "custom recipe"; - } - - @Override - protected AnvilCustomRecipe createAndSaveNewEmptyGeneric(String name) { - // Create new empty conflict and display it to the admin - AnvilCustomRecipe recipe = new AnvilCustomRecipe( - name, - AnvilCustomRecipe.DEFAULT_EXACT_COUNT_CONFIG, - - AnvilCustomRecipe.DEFAULT_XP_LEVEL_COST_CONFIG, - AnvilCustomRecipe.DEFAULT_LINEAR_XP_COST_CONFIG, - AnvilCustomRecipe.DEFAULT_REMOVE_EXACT_XP_CONFIG, - - AnvilCustomRecipe.Companion.getDEFAULT_LEFT_ITEM_CONFIG(), - AnvilCustomRecipe.Companion.getDEFAULT_RIGHT_ITEM_CONFIG(), - AnvilCustomRecipe.Companion.getDEFAULT_RESULT_ITEM_CONFIG()); - - ConfigHolder.CUSTOM_RECIPE_HOLDER.getRecipeManager().cleanAddNew(recipe); - - // Save recipe to file - recipe.saveToFile(GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE, GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE); - - return recipe; - } - - - @Override - protected Collection getEveryDisplayableInstanceOfGeneric() { - return ConfigHolder.CUSTOM_RECIPE_HOLDER.getRecipeManager().getRecipeList(); - } -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/EnchantConflictGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/EnchantConflictGui.java deleted file mode 100644 index 912e6cb..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/EnchantConflictGui.java +++ /dev/null @@ -1,104 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.global; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.inventory.ItemFlag; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.group.EnchantConflictGroup; -import xyz.alexcrea.cuanvil.group.IncludeGroup; -import xyz.alexcrea.cuanvil.gui.config.list.MappedGuiListConfigGui; -import xyz.alexcrea.cuanvil.gui.config.list.elements.EnchantConflictSubSettingGui; -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; -import xyz.alexcrea.cuanvil.util.CasedStringUtil; - -import java.util.Arrays; -import java.util.Collection; - -public class EnchantConflictGui extends MappedGuiListConfigGui> { - - private static EnchantConflictGui INSTANCE; - - @Nullable - public static EnchantConflictGui getCurrentInstance(){ - return INSTANCE; - } - - @NotNull - public static EnchantConflictGui getInstance(){ - if(INSTANCE == null) INSTANCE = new EnchantConflictGui(); - - return INSTANCE; - } - - - private EnchantConflictGui() { - super( "Conflict Config"); - - init(); - } - - @Override - protected EnchantConflictGroup createAndSaveNewEmptyGeneric(String name){ - // Create new empty conflict and display it to the admin - EnchantConflictGroup conflict = new EnchantConflictGroup( - name, - new IncludeGroup("new_group"), - 0); - - ConfigHolder.CONFLICT_HOLDER.getConflictManager().addConflict(conflict); - - // save empty conflict in config - String[] emptyStringArray = new String[0]; - - FileConfiguration config = ConfigHolder.CONFLICT_HOLDER.getConfig(); - config.set(name + ".enchantments", emptyStringArray); - config.set(name + ".notAffectedGroups", emptyStringArray); - config.set(name + ".maxEnchantmentBeforeConflict", 0); - - if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) { - ConfigHolder.CONFLICT_HOLDER.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE); - } - - return conflict; - } - - @Override - public ItemStack createItemForGeneric(EnchantConflictGroup conflict) { - ItemStack item = new ItemStack(conflict.getRepresentativeMaterial()); - - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - meta.addItemFlags(ItemFlag.values()); - meta.setDisplayName("§e" + CasedStringUtil.snakeToUpperSpacedCase(conflict.toString()) + " §fConflict"); - meta.setLore(Arrays.asList( - "§7Enchantment count: §e" + conflict.getEnchants().size(), - "§7Group count: §e" + conflict.getCantConflictGroup().getGroups().size(), - "§7Min enchantments count: §e" + conflict.getMinBeforeBlock() - )); - - item.setItemMeta(meta); - return item; - } - - @Override - protected LazyElement newInstanceOfGui(EnchantConflictGroup conflict, GuiItem item) { - return new LazyElement<>(item, () -> new EnchantConflictSubSettingGui(this, conflict)); - } - - @Override - protected String genericDisplayedName() { - return "conflict"; - } - - @Override - protected Collection getEveryDisplayableInstanceOfGeneric() { - return ConfigHolder.CONFLICT_HOLDER.getConflictManager().getConflictList(); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/EnchantCostConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/EnchantCostConfigGui.java deleted file mode 100644 index a614536..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/EnchantCostConfigGui.java +++ /dev/null @@ -1,91 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.global; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; -import xyz.alexcrea.cuanvil.enchant.EnchantmentProperties; -import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity; -import xyz.alexcrea.cuanvil.gui.config.settings.EnchantCostSettingsGui; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; -import xyz.alexcrea.cuanvil.util.CasedStringUtil; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; - -/** - * Global Config gui for enchantment cost settings. - */ -public class EnchantCostConfigGui extends AbstractEnchantConfigGui { - - private static final String SECTION_NAME = "enchant_values"; - - private static EnchantCostConfigGui INSTANCE = null; - - @Nullable - public static EnchantCostConfigGui getInstance() { - return INSTANCE; - } - - /** - * Constructor of this Global gui for enchantment cost settings. - */ - public EnchantCostConfigGui() { - super("§8Enchantment Level Cost"); - if(INSTANCE == null) INSTANCE = this; - - init(); - } - - @Override - public EnchantCostSettingsGui.EnchantCostSettingFactory createFactory(CAEnchantment enchant) { - String key = enchant.getKey().toString().toLowerCase(Locale.ENGLISH); - String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key.replace(":", "_")); - - return new EnchantCostSettingsGui.EnchantCostSettingFactory(prettyKey + " Cost", this, - SECTION_NAME + '.' + key, ConfigHolder.DEFAULT_CONFIG, - Arrays.asList( - "§7How many level should " + prettyKey, - "§7cost when applied by book or by another item." - ), - enchant, 0, 255, - 1, 10, 50); - } - - @Override - public GuiItem itemFromFactory(CAEnchantment enchantment, EnchantCostSettingsGui.EnchantCostSettingFactory factory) { - // Get item properties - int itemCost = factory.getConfiguredValue(); - int bookCost = factory.getConfiguredBookValue(); - String itemName = "§a" + factory.getTitle(); - // Create item - ItemStack item = new ItemStack(Material.ENCHANTED_BOOK); - ItemMeta itemMeta = item.getItemMeta(); - assert itemMeta != null; - - // Prepare lore - List lore = new ArrayList<>(); - lore.add("§7Item Cost: §e" + itemCost); - lore.add("§7Book Cost: §e" + bookCost); - - List displayLore = factory.getDisplayLore(); - if(!displayLore.isEmpty()){ - lore.add(""); - lore.addAll(displayLore); - } - - // Edit name and lore - itemMeta.setDisplayName(itemName); - itemMeta.setLore(lore); - - item.setItemMeta(itemMeta); - - return GuiGlobalItems.openSettingGuiItem(item, factory); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/EnchantLimitConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/EnchantLimitConfigGui.java deleted file mode 100644 index e9edbeb..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/EnchantLimitConfigGui.java +++ /dev/null @@ -1,83 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.global; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import io.delilaheve.util.ConfigOptions; -import org.bukkit.Material; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; -import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui; -import xyz.alexcrea.cuanvil.util.CasedStringUtil; - -import java.util.Collections; -import java.util.Locale; - -/** - * Global Config gui for enchantment level limit settings. - */ -public class EnchantLimitConfigGui extends AbstractEnchantConfigGui { - - private static final String SECTION_NAME = ConfigOptions.ENCHANT_LIMIT_ROOT; - - private static EnchantLimitConfigGui INSTANCE = null; - - @Nullable - public static EnchantLimitConfigGui getInstance() { - return INSTANCE; - } - - /** - * Constructor of this Global gui for enchantment level limit settings. - */ - public EnchantLimitConfigGui() { - super("§8Enchantment Level Limit"); - if(INSTANCE == null) INSTANCE = this; - - init(); - } - - @Override - public IntSettingsGui.IntSettingFactory createFactory(CAEnchantment enchant) { - String key = enchant.getKey().toString().toLowerCase(Locale.ROOT); - String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key.replace(":", "_")); - - var defaultValue = enchant.defaultMaxLevel(); - - return new IntSettingsGui.IntSettingFactory(prettyKey + " Limit", this, - SECTION_NAME + '.' + key, ConfigHolder.DEFAULT_CONFIG, - Collections.singletonList( - "§7Maximum applied level of " + prettyKey - ), - -1, 255, -1, - 1, 5, 10, 50, 100){ - - @Override - public int getConfiguredValue() { - var value = ConfigOptions.INSTANCE.rawEnchantLimit(enchant); - return Math.min(value, ConfigOptions.ENCHANT_LIMIT); - } - - @Override - public String valueDisplayName(IntSettingsGui.ValueDisplayType type, int value) { - - if(value < 0) { - return switch (type) { - case CURRENT -> "Default (" + defaultValue + ")"; - case RESET -> String.valueOf(defaultValue); - default -> "Default"; - }; - - } - else return super.valueDisplayName(type, value); - } - }; - } - - @Override - public GuiItem itemFromFactory(CAEnchantment enchantment, IntSettingsGui.IntSettingFactory inventoryFactory) { - return inventoryFactory.getItem( - Material.ENCHANTED_BOOK, - inventoryFactory.getTitle()); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/EnchantMergeLimitConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/EnchantMergeLimitConfigGui.java deleted file mode 100644 index 0d391e7..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/EnchantMergeLimitConfigGui.java +++ /dev/null @@ -1,67 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.global; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import io.delilaheve.util.ConfigOptions; -import org.bukkit.Material; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; -import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui; -import xyz.alexcrea.cuanvil.util.CasedStringUtil; - -import java.util.Arrays; -import java.util.Locale; - -public class EnchantMergeLimitConfigGui extends AbstractEnchantConfigGui { - - private static final String SECTION_NAME = "disable-merge-over"; - - private static EnchantMergeLimitConfigGui INSTANCE = null; - - @Nullable - public static EnchantMergeLimitConfigGui getInstance() { - return INSTANCE; - } - - /** - * Constructor of this Global gui for enchantment level limit settings. - */ - public EnchantMergeLimitConfigGui() { - super("§8Enchantment Maximum Merge Level"); - if(INSTANCE == null) INSTANCE = this; - - init(); - } - - @Override - public IntSettingsGui.IntSettingFactory createFactory(CAEnchantment enchant) { - String key = enchant.getKey().toString().toLowerCase(Locale.ROOT); - String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key.replace(":", "_")); - - return new IntSettingsGui.IntSettingFactory(prettyKey + " Merge Limit", this, - SECTION_NAME + '.' + key, ConfigHolder.DEFAULT_CONFIG, - Arrays.asList( - "§7Maximum merge level for for " + prettyKey, - "", - "§7For example, if set to §e2§7, §alvl1 §7+ §alvl1 §7of will give a §alvl2", - "§7But §alvl2 §7+ §alvl2 §7will not give a §clv3§7.", - "§7Will still not merge above max enchantment level", - "§e-1 §7(default) will set the merge limit to enchantment's maximum level" - ), - -1, 255, -1, - 1, 5, 10, 50, 100){ - - @Override - public int getConfiguredValue() { - return ConfigOptions.INSTANCE.maxBeforeMergeDisabled(enchant); - } - }; - } - - @Override - public GuiItem itemFromFactory(CAEnchantment enchantment, IntSettingsGui.IntSettingFactory inventoryFactory) { - return inventoryFactory.getItem( - Material.ENCHANTED_BOOK, - inventoryFactory.getTitle()); - } -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/GroupConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/GroupConfigGui.java deleted file mode 100644 index 8e20751..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/GroupConfigGui.java +++ /dev/null @@ -1,97 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.global; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.inventory.ItemFlag; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.group.AbstractMaterialGroup; -import xyz.alexcrea.cuanvil.group.GroupType; -import xyz.alexcrea.cuanvil.group.IncludeGroup; -import xyz.alexcrea.cuanvil.group.ItemGroupManager; -import xyz.alexcrea.cuanvil.gui.config.list.MappedGuiListConfigGui; -import xyz.alexcrea.cuanvil.gui.config.list.elements.GroupConfigSubSettingGui; -import xyz.alexcrea.cuanvil.util.CasedStringUtil; -import xyz.alexcrea.cuanvil.util.LazyValue; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; - -public class GroupConfigGui extends MappedGuiListConfigGui> { - - private static GroupConfigGui INSTANCE; - - @Nullable - public static GroupConfigGui getCurrentInstance(){ - return INSTANCE; - } - - @NotNull - public static GroupConfigGui getInstance(){ - if(INSTANCE == null) INSTANCE = new GroupConfigGui(); - - return INSTANCE; - } - - public GroupConfigGui() { - super("Group Config"); - - init(); - } - - @Override - protected ItemStack createItemForGeneric(IncludeGroup group) { - ItemStack item = new ItemStack(group.getRepresentativeMaterial()); - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - meta.addItemFlags(ItemFlag.values()); - meta.setDisplayName("§e" + CasedStringUtil.snakeToUpperSpacedCase(group.getName())+ " §fGroup"); - meta.setLore(Arrays.asList( - "§7Number of selected groups : " + group.getGroups().size(), - "§7Number of included material : " + group.getNonGroupInheritedMaterials().size(), - "", - "§7Total number of included material "+group.getMaterials().size())); - - item.setItemMeta(meta); - return item; - } - - @Override - protected Collection getEveryDisplayableInstanceOfGeneric() { - ArrayList includeGroups = new ArrayList<>(); - - for (AbstractMaterialGroup group : ConfigHolder.ITEM_GROUP_HOLDER.getItemGroupsManager().getGroupMap().values()) { - if(group instanceof IncludeGroup){ - includeGroups.add((IncludeGroup) group); - } - } - return includeGroups; - } - - @Override - protected LazyElement newInstanceOfGui(IncludeGroup group, GuiItem item) { - return new LazyElement<>(item, () -> new GroupConfigSubSettingGui(this, group)); - } - - @Override - protected String genericDisplayedName() { - return "material group"; - } - - @Override - protected IncludeGroup createAndSaveNewEmptyGeneric(String name) { - ItemGroupManager manager = ConfigHolder.ITEM_GROUP_HOLDER.getItemGroupsManager(); - if(manager.getGroupMap().containsKey(name)) return null; - - ConfigurationSection config = ConfigHolder.ITEM_GROUP_HOLDER.getConfig(); - config.set(name+"."+ItemGroupManager.GROUP_TYPE_PATH, GroupType.INCLUDE.getGroupID()); - - return (IncludeGroup) manager.createGroup(config, name); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/UnitRepairConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/UnitRepairConfigGui.java deleted file mode 100644 index 0e366ae..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/UnitRepairConfigGui.java +++ /dev/null @@ -1,148 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.global; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import io.delilaheve.CustomAnvil; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.gui.config.ask.SelectItemTypeGui; -import xyz.alexcrea.cuanvil.gui.config.list.MappedGuiListConfigGui; -import xyz.alexcrea.cuanvil.gui.config.list.UnitRepairElementListGui; -import xyz.alexcrea.cuanvil.util.CasedStringUtil; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; - -public class UnitRepairConfigGui extends - MappedGuiListConfigGui> { - - private static UnitRepairConfigGui INSTANCE; - - @Nullable - public static UnitRepairConfigGui getCurrentInstance(){ - return INSTANCE; - } - - @NotNull - public static UnitRepairConfigGui getInstance(){ - if(INSTANCE == null) INSTANCE = new UnitRepairConfigGui(); - - return INSTANCE; - } - - private UnitRepairConfigGui() { - super("Unit Repair Config"); - - init(); - } - - @Override - protected LazyElement newInstanceOfGui(Material material, GuiItem item) { - return new LazyElement<>(item, () -> { - UnitRepairElementListGui element = new UnitRepairElementListGui(material, this); - element.init(); - return element; - }); - } - - @Override - protected ItemStack createItemForGeneric(Material material) { - ConfigurationSection materialSection = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig().getConfigurationSection(material.name().toLowerCase()); - String materialName = CasedStringUtil.snakeToUpperSpacedCase(material.name().toLowerCase()); - - if(material.isAir()){ - material = Material.BARRIER; - } - - int reparableItemCount = materialSection == null ? 0 : materialSection.getKeys(false).size(); // Probably an expensive call but... why not - - ItemStack item = new ItemStack(material); - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§eRepaired by " +materialName); - meta.setLore(Arrays.asList( - "§7There is currently §e" +reparableItemCount+ " §7reparable item with "+materialName, - "§7Click here to open the menu to edit reparable item by " + materialName - )); - - item.setItemMeta(meta); - - return item; - } - - @Override - protected Collection getEveryDisplayableInstanceOfGeneric() { - ArrayList materials = new ArrayList<>(); - - for (String matName : ConfigHolder.UNIT_REPAIR_HOLDER.getConfig().getKeys(false)) { - Material mat = Material.getMaterial(matName.toUpperCase()); - if(mat != null){ - materials.add(mat); - } - } - return materials; - } - - @Override - protected GuiItem prepareCreateNewItem() { - // Create new conflict item - ItemStack createItem = new ItemStack(Material.PAPER); - ItemMeta createMeta = createItem.getItemMeta(); - assert createMeta != null; - - createMeta.setDisplayName("§aSelect a new unit material"); - createMeta.setLore(Arrays.asList( - "§7Select a new unit material to be used.", - "§7You will be asked the material to use." - )); - - createItem.setItemMeta(createMeta); - - return new GuiItem(createItem, clickEvent -> { - clickEvent.setCancelled(true); - - new SelectItemTypeGui( - "Select unit repair item.", - "§7Click here with an item to set the item\n" + - "§7You like to be an unit repair item", - this, - (itemStack, player) -> { - Material type = itemStack.getType(); - // Add new material - updateValueForGeneric(type, true); - - // Display material edit setting - this.elementGuiMap.get(type).get().getMappedGui().show(player); - }, - true - ).show(clickEvent.getWhoClicked()); - }, CustomAnvil.instance); - } - - @NotNull - public LazyElement getInstanceOrCreate(Material mat){ - LazyElement element = this.elementGuiMap.get(mat); - if(element == null){ - updateValueForGeneric(mat, false); - - element = this.elementGuiMap.get(mat); - } - - return element; - } - - @Override // Not used in this implementation. - protected String genericDisplayedName() { - return "this function Should not be used."; - } - @Override // Not used in this implementation. - protected Material createAndSaveNewEmptyGeneric(String name) { - return null; - } -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/ElementListConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/ElementListConfigGui.java deleted file mode 100644 index f3cc0b4..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/ElementListConfigGui.java +++ /dev/null @@ -1,318 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.list; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.gui.type.ChestGui; -import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; -import com.github.stefvanschie.inventoryframework.pane.Orientable; -import com.github.stefvanschie.inventoryframework.pane.OutlinePane; -import com.github.stefvanschie.inventoryframework.pane.Pane; -import com.github.stefvanschie.inventoryframework.pane.PatternPane; -import com.github.stefvanschie.inventoryframework.pane.util.Pattern; -import io.delilaheve.CustomAnvil; -import org.bukkit.Material; -import org.bukkit.entity.HumanEntity; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.UUID; - -public abstract class ElementListConfigGui< T > extends ChestGui implements ValueUpdatableGui { - - private final String namePrefix; - - protected PatternPane backgroundPane; - - public static final int LIST_FILLER_START_X = 1; - public static final int LIST_FILLER_START_Y = 1; - public static final int LIST_FILLER_LENGTH = 7; - public static final int LIST_FILLER_HEIGHT = 4; - - protected ElementListConfigGui(@NotNull String title, Gui parent) { - super(6, title, CustomAnvil.instance); - this.namePrefix = title; - - // Back item panel - Pattern pattern = getBackgroundPattern(); - this.backgroundPane = new PatternPane(0, 0, 9, 6, Pane.Priority.LOW, pattern); - GuiGlobalItems.addBackItem(this.backgroundPane, parent); - - } - - protected Pattern getBackgroundPattern(){ - return new Pattern( - GuiSharedConstant.UPPER_FILLER_FULL_PLANE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - "B11L1R11C" - ); - } - - protected OutlinePane firstPage; - protected ArrayList pages; - protected HashMap pageMap; - - public void init() { // Why I'm using an init function ? //TODO determine why is it using a init function and not used on constructor. - GuiGlobalItems.addBackgroundItem(this.backgroundPane); - this.backgroundPane.bindItem('1', GuiSharedConstant.SECONDARY_BACKGROUND_ITEM); - addPane(this.backgroundPane); - - // Page init - this.pages = new ArrayList<>(); - this.pageMap = new HashMap<>(); - - // enchant item panel - this.firstPage = createEmptyPage(); - this.pages.add(this.firstPage); - - prepareStaticValues(); - reloadValues(); - } - - protected GuiItem goLeftItem; - protected GuiItem goRightItem; - - protected void prepareStaticValues(){ - // Left item creation for consumer & bind - this.goLeftItem = new GuiItem(new ItemStack(Material.RED_STAINED_GLASS_PANE), event -> { - HumanEntity viewer = event.getWhoClicked(); - UUID playerUUID = viewer.getUniqueId(); - int page = this.pageMap.getOrDefault(playerUUID, 0); - this.pageMap.put(playerUUID, page - 1); - - ItemStack cursor = viewer.getItemOnCursor(); - viewer.setItemOnCursor(new ItemStack(Material.AIR)); - - show(viewer); - - viewer.setItemOnCursor(cursor); - }, CustomAnvil.instance); - - // Right item creation for consumer & bind - this.goRightItem = new GuiItem(new ItemStack(Material.LIME_STAINED_GLASS_PANE), event -> { - HumanEntity viewer = event.getWhoClicked(); - UUID playerUUID = viewer.getUniqueId(); - int page = pageMap.getOrDefault(playerUUID, 0); - this.pageMap.put(playerUUID, page + 1); - - ItemStack cursor = viewer.getItemOnCursor(); - viewer.setItemOnCursor(new ItemStack(Material.AIR)); - - show(viewer); - - viewer.setItemOnCursor(cursor); - }, CustomAnvil.instance); - - GuiItem createNew = prepareCreateNewItem(); - if(createNew != null){ - this.backgroundPane.bindItem('C', createNew); - } - } - protected void reloadValues(){ - this.firstPage.clear(); - this.pages.clear(); - this.pages.add(this.firstPage); - - for (T generic : getEveryDisplayableInstanceOfGeneric()) { - updateValueForGeneric(generic, false); - } - - update(); - } - - protected abstract GuiItem prepareCreateNewItem(); - - protected OutlinePane createEmptyPage() { - OutlinePane page = new OutlinePane(LIST_FILLER_START_X, LIST_FILLER_START_Y, LIST_FILLER_LENGTH, LIST_FILLER_HEIGHT); - page.align(OutlinePane.Alignment.BEGIN); - page.setOrientation(Orientable.Orientation.HORIZONTAL); - - return page; - } - - public int getPlayerPageID(UUID uuid) { - int pageId = this.pageMap.getOrDefault(uuid, 0); - if (pageId >= this.pages.size()) { - pageId = this.pages.size() - 1; - } - return pageId; - } - - protected void addToPage(GuiItem guiItem) { - // Get first available page or create one - OutlinePane page = this.pages.get(this.pages.size() - 1); - if (page.getItems().size() >= LIST_FILLER_LENGTH * LIST_FILLER_HEIGHT) { - page = createEmptyPage(); - this.pages.add(page); - } - - page.addItem(guiItem); - } - - private void removeFromPage(GuiItem guiItem) { - // get item page - OutlinePane page = null; - int pageID = 0; - while (pageID < this.pages.size()) { - OutlinePane tempPage = this.pages.get(pageID); - if (tempPage.getItems().contains(guiItem)) { - page = tempPage; - break; - } - pageID++; - } - - if (page == null) {// Why... - return; - } - removeFromPage(page, pageID, guiItem); - } - - private void removeFromPage(OutlinePane page, int pageID, GuiItem guiItem) { - page.removeItem(guiItem); - - // There is now a slot available, let fill it if possible - if (pageID < (this.pages.size() - 1)) { - OutlinePane newPage = this.pages.get(pageID + 1); - GuiItem nextPageItem = newPage.getItems().get(0); - - removeFromPage(newPage, pageID + 1, nextPageItem); - - OutlinePane thisPage = this.pages.get(pageID); - thisPage.addItem(nextPageItem); - } else if (pageID > 0 && page.getItems().isEmpty()) { - this.pages.remove(pageID); - } - } - - public void placeArrow(int page, boolean customise) { - - // Place left arrow - addPane(this.backgroundPane); - if (page > 0) { - if (customise) { - ItemStack leftItem = this.goLeftItem.getItem(); - ItemMeta leftMeta = leftItem.getItemMeta(); - - leftMeta.setDisplayName("§eReturn to page " + (page)); - - leftItem.setItemMeta(leftMeta); - this.goLeftItem.setItem(leftItem); - } - - this.backgroundPane.bindItem('L', this.goLeftItem); - } else { - this.backgroundPane.bindItem('L', GuiSharedConstant.SECONDARY_BACKGROUND_ITEM); - } - - // Place right arrow - if (page < pages.size() - 1) { - if (customise) { - ItemStack rightItem = this.goRightItem.getItem(); - ItemMeta rightMeta = rightItem.getItemMeta(); - - rightMeta.setDisplayName("§eGo to page " + (page + 2)); - - rightItem.setItemMeta(rightMeta); - this.goRightItem.setItem(rightItem); - } - - this.backgroundPane.bindItem('R', this.goRightItem); - } else { - this.backgroundPane.bindItem('R', GuiSharedConstant.SECONDARY_BACKGROUND_ITEM); - } - } - - @Override // assume will not be called in multiple thread - public void show(@NotNull HumanEntity humanEntity) { - int pageID = getPlayerPageID(humanEntity.getUniqueId()); - OutlinePane page = this.pages.get(pageID); - - getPanes().clear(); - - // display the page arrow pane - placeArrow(pageID, true); - // and add actual page - addPane(page); - - // set title - StringBuilder title = new StringBuilder(this.namePrefix); - int pagesSize = this.pages.size(); - if(pagesSize > 1){ - title.append(" (").append(pageID + 1).append('/').append(pagesSize).append(')'); - } - setTitle(title.toString()); - - super.show(humanEntity); - - } - - @Override // assume will not be called in multiple thread - public void click(@NotNull InventoryClickEvent event) { - int pageID = getPlayerPageID(event.getWhoClicked().getUniqueId()); - OutlinePane page = this.pages.get(pageID); - - getPanes().clear(); - - // set the page arrow pane - placeArrow(pageID, false); - // and add actual page - addPane(page); - - super.click(event); - } - - // ------------------------- - // Methods using generic T - // ------------------------- - - public void updateValueForGeneric(T generic, boolean shouldUpdate) { - ItemStack item = createItemForGeneric(generic); - - updateGeneric(generic, item); - - if (shouldUpdate) { - update(); - } - - } - - public void removeGeneric(T generic) { - GuiItem item = findGuiItemForRemoval(generic); - if(item == null) return; - removeFromPage(item); - - update(); - } - - protected abstract GuiItem findGuiItemForRemoval(T generic); - - protected abstract ItemStack createItemForGeneric(T generic); - - protected abstract void updateGeneric(T generic, ItemStack usedItem); - - protected abstract Collection getEveryDisplayableInstanceOfGeneric(); - - @Override - public void updateGuiValues() { - // Not the optimised way to update this gui - // TODO maybe rework ValueUpdatableGui and it's dependency to allow a 1 item reload every time. - - reloadValues(); - } - - @Override - public Gui getConnectedGui() { - return this; - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedElementListConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedElementListConfigGui.java deleted file mode 100644 index 31ab718..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedElementListConfigGui.java +++ /dev/null @@ -1,106 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.list; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import io.delilaheve.CustomAnvil; -import org.bukkit.Material; -import org.bukkit.entity.HumanEntity; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.gui.config.MainConfigGui; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.function.Consumer; - -public abstract class MappedElementListConfigGui< T, S > extends ElementListConfigGui< T > { - - protected final HashMap elementGuiMap; - protected MappedElementListConfigGui(@NotNull String title) { - super(title, MainConfigGui.getInstance()); - this.elementGuiMap = new HashMap<>(); - - } - - @Override - protected GuiItem prepareCreateNewItem(){ - // Create new conflict item - ItemStack createItem = new ItemStack(Material.PAPER); - ItemMeta createMeta = createItem.getItemMeta(); - assert createMeta != null; - - createMeta.setDisplayName("§aCreate new "+genericDisplayedName()); - createMeta.setLore(Arrays.asList( - "§7Create a new "+genericDisplayedName()+".", - "§7You will be asked to name the "+genericDisplayedName()+" in chat.", - "§7Then, you should edit the "+genericDisplayedName()+" config as you need" - )); - - createItem.setItemMeta(createMeta); - - return new GuiItem(createItem, clickEvent -> { - clickEvent.setCancelled(true); - HumanEntity player = clickEvent.getWhoClicked(); - - // check permission - if (!player.hasPermission(CustomAnvil.editConfigPermission)) { - player.closeInventory(); - player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); - return; - } - player.closeInventory(); - - player.sendMessage("§eWrite the "+genericDisplayedName()+" name you want to create in the chat.\n" + - "§eOr write §ccancel §eto go back to "+genericDisplayedName()+" config menu"); - - CustomAnvil.Companion.getChatListener().setListenedCallback(player, prepareCreateItemConsumer(player)); - - }, CustomAnvil.instance); - } - - @Override - protected void updateGeneric(T generic, ItemStack usedItem) { - S element = this.elementGuiMap.get(generic); - - GuiItem guiItem; - if (element == null) { - // Create new sub setting element - guiItem = new GuiItem(usedItem, CustomAnvil.instance); - - element = newElementRequested(generic, guiItem); - - this.elementGuiMap.put(generic, element); - - addToPage(guiItem); - } else { - // Replace item with the updated one - guiItem = findItemFromElement(generic, element); - guiItem.setItem(usedItem); - } - updateElement(generic, element); - - } - - protected abstract void updateElement(T generic, S element); - - protected abstract S newElementRequested(T generic, GuiItem newItem); - - protected abstract GuiItem findItemFromElement(T generic, S element); - - @Override - protected GuiItem findGuiItemForRemoval(T generic) { - S element = this.elementGuiMap.get(generic); - if (element == null) return null; - - this.elementGuiMap.remove(generic); - return findGuiItemForRemoval(generic, element); - } - - protected abstract GuiItem findGuiItemForRemoval(T generic, S element); - - protected abstract Consumer prepareCreateItemConsumer(HumanEntity player); - - protected abstract String genericDisplayedName(); - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedGuiListConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedGuiListConfigGui.java deleted file mode 100644 index 3aa18e0..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedGuiListConfigGui.java +++ /dev/null @@ -1,140 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.list; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import io.delilaheve.CustomAnvil; -import org.bukkit.entity.HumanEntity; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.gui.config.list.elements.ElementMappedToListGui; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; -import xyz.alexcrea.cuanvil.util.LazyValue; - -import java.util.Locale; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; -import java.util.function.Supplier; - -public abstract class MappedGuiListConfigGui< T, S extends MappedGuiListConfigGui.LazyElement> - extends MappedElementListConfigGui< T, S > { - - protected MappedGuiListConfigGui(@NotNull String title) { - super(title); - - } - - @Override - public void reloadValues() { - this.elementGuiMap.forEach((conflict, element) -> { - ElementMappedToListGui gui = element.getStored(); - if(gui != null) gui.cleanAndBeUnusable(); - }); - this.elementGuiMap.clear(); - - super.reloadValues(); - } - - @Override - protected S newElementRequested(T generic, GuiItem newItem) { - S element = newInstanceOfGui(generic, newItem); - - newItem.setAction(element.openAction()); - return element; - } - - @Override - protected GuiItem findItemFromElement(T generic, S element) { - return element.getParentItem(); - } - - @Override - protected void updateElement(T generic, S element) { - ElementMappedToListGui gui = element.getStored(); - if(gui != null) gui.updateLocal(); - } - - @Override - protected GuiItem findGuiItemForRemoval(T generic, S element) { - return element.getParentItem(); - } - - @Override - protected Consumer prepareCreateItemConsumer(HumanEntity player){ - AtomicReference> selfRef = new AtomicReference<>(); - Consumer selfCallback = (message) -> { - if (message == null) return; - - // check permission - if (!player.hasPermission(CustomAnvil.editConfigPermission)) { - player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); - return; - } - - message = message.toLowerCase(Locale.ROOT); - if ("cancel".equalsIgnoreCase(message)) { - player.sendMessage(genericDisplayedName()+" creation cancelled..."); - show(player); - return; - } - - message = message.replace(' ', '_'); - - // Try to find if it already exists in a for loop - // Not the most efficient on large number of conflict, but it should not run often. - for (T generic : getEveryDisplayableInstanceOfGeneric()) { - if (generic.toString().equalsIgnoreCase(message)) { - player.sendMessage("§cPlease enter a "+genericDisplayedName()+" name that do not already exist..."); - // wait next message. - CustomAnvil.Companion.getChatListener().setListenedCallback(player, selfRef.get()); - return; - } - } - - T generic = createAndSaveNewEmptyGeneric(message); - if(generic == null) {// we don't know what to do. so we back up by opening this gui. - this.show(player); - return; - } - - updateValueForGeneric(generic, true); - - // show the new conflict config to the player - this.elementGuiMap.get(generic).get().getMappedGui().show(player); - - update(); - }; - - selfRef.set(selfCallback); - return selfCallback; - } - - protected abstract S newInstanceOfGui(T generic, GuiItem item); - - protected abstract String genericDisplayedName(); - - protected abstract T createAndSaveNewEmptyGeneric(String name); - - public static class LazyElement extends LazyValue { - - private final GuiItem parentItem; - private final LazyValue> lazyOpenConsumer; - public LazyElement(GuiItem parentItem, Supplier valueSupplier) { - super(valueSupplier); - this.parentItem = parentItem; - - this.lazyOpenConsumer = new LazyValue<>(() -> - GuiGlobalActions.openGuiAction(this.get().getMappedGui())) - ; - } - - public GuiItem getParentItem() { - return parentItem; - } - - @NotNull - public Consumer openAction(){ - return event -> lazyOpenConsumer.get().accept(event); - } - - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/SettingGuiListConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/SettingGuiListConfigGui.java deleted file mode 100644 index f0e7cb0..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/SettingGuiListConfigGui.java +++ /dev/null @@ -1,103 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.list; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; -import io.delilaheve.CustomAnvil; -import org.bukkit.Material; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.gui.config.MainConfigGui; -import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui; - -import java.util.HashMap; -import java.util.List; -import java.util.function.Consumer; - -public abstract class SettingGuiListConfigGui< T, S extends SettingGui.SettingGuiFactory> extends ElementListConfigGui< T >{ - - protected HashMap guiItemMap; - protected HashMap factoryMap; - protected SettingGuiListConfigGui(@NotNull String title, Gui parent) { - super(title, parent); - this.guiItemMap = new HashMap<>(); - this.factoryMap = new HashMap<>(); - } - - protected SettingGuiListConfigGui(@NotNull String title) { - this(title, MainConfigGui.getInstance()); - } - - @Override - protected GuiItem prepareCreateNewItem() { - ItemStack createItem = new ItemStack(Material.PAPER); - ItemMeta createMeta = createItem.getItemMeta(); - assert createMeta != null; - - createMeta.setDisplayName(createItemName()); - createMeta.setLore(getCreateItemLore()); - - createItem.setItemMeta(createMeta); - return new GuiItem(createItem, getCreateClickConsumer(), CustomAnvil.instance); - } - - @Override - public void updateValueForGeneric(T generic, boolean shouldUpdate) { - if(!this.factoryMap.containsKey(generic)){ - // Create new item & factory - S factory = createFactory(generic); - GuiItem newItem = itemFromFactory(generic, factory); - - addToPage(newItem); - this.guiItemMap.put(generic, newItem); - this.factoryMap.put(generic, factory); - }else{ - S factory = this.factoryMap.get(generic); - // Update old item - GuiItem oldItem = this.guiItemMap.get(generic); - - GuiItem newItem = itemFromFactory(generic, factory); - updateGuiItem(oldItem, newItem); - } - - if(shouldUpdate){ - update(); - } - } - - @Override - protected void reloadValues() { - this.guiItemMap.clear(); - this.factoryMap.clear(); - - super.reloadValues(); - } - - private void updateGuiItem(GuiItem oldITem, GuiItem newItem){ - oldITem.setItem(newItem.getItem()); - oldITem.setProperties(newItem.getProperties()); - oldITem.setVisible(newItem.isVisible()); - } - - @Override - protected GuiItem findGuiItemForRemoval(T generic) { - return this.guiItemMap.get(generic); - } - - @Override // Not used - protected void updateGeneric(T generic, ItemStack usedItem) {} - @Override // Not used - protected ItemStack createItemForGeneric(T generic) { - return null; - } - - protected abstract List getCreateItemLore(); - protected abstract Consumer getCreateClickConsumer(); - protected abstract String createItemName(); - - protected abstract S createFactory(T generic); - protected abstract GuiItem itemFromFactory(T generic, S factory); - - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/UnitRepairElementListGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/UnitRepairElementListGui.java deleted file mode 100644 index 35f8ebb..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/UnitRepairElementListGui.java +++ /dev/null @@ -1,195 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.list; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.HumanEntity; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.meta.Damageable; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.gui.config.ask.SelectItemTypeGui; -import xyz.alexcrea.cuanvil.gui.config.global.UnitRepairConfigGui; -import xyz.alexcrea.cuanvil.gui.config.list.elements.ElementMappedToListGui; -import xyz.alexcrea.cuanvil.gui.config.settings.DoubleSettingGui; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; -import xyz.alexcrea.cuanvil.util.CasedStringUtil; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.function.Consumer; - -public class UnitRepairElementListGui extends SettingGuiListConfigGui implements ElementMappedToListGui { - - private final Material parentMaterial; - private final UnitRepairConfigGui parentGui; - private final String materialName; - - private boolean shouldWork = true; - public UnitRepairElementListGui(@NotNull Material parentMaterial, - @NotNull UnitRepairConfigGui parentGui) { - super("§e" + CasedStringUtil.snakeToUpperSpacedCase(parentMaterial.name().toLowerCase()) + " §rUnit repair"); - this.parentMaterial = parentMaterial; - this.parentGui = parentGui; - this.materialName = CasedStringUtil.snakeToUpperSpacedCase(parentMaterial.name().toLowerCase()); - - GuiGlobalItems.addBackItem(this.backgroundPane, parentGui); - } - - // SettingGuiListConfigGui methods - @Override - protected List getCreateItemLore() { - return Arrays.asList( - "§7Select a new item to be repairable.", - "§7You will be asked the material to use." - ); - } - - @Override - protected Consumer getCreateClickConsumer() { - return event -> { - event.setCancelled(true); - if(!this.shouldWork){ - return; - } - event.setCancelled(true); - - new SelectItemTypeGui( - "Select item to be repaired.", - "§7Click here with an item to set the item\n" + - "§7You like to be repaired by " + this.materialName, - this, - (itemStack, player) -> { - ItemMeta meta = itemStack.getItemMeta(); - Material type = itemStack.getType(); - - if(!(meta instanceof Damageable) || (type.getMaxDurability() <= 0)) { - player.sendMessage("§cThis item can't be damaged, so it can't be repaired."); - return; - } - if(type == this.parentMaterial){ - player.sendMessage("§cItem can't repair something of the same type."); - return; - } - - String materialName = type.name().toLowerCase(); - - // Add new material - ConfigHolder.UNIT_REPAIR_HOLDER.getConfig().set(parentMaterial.name().toLowerCase() + "." + materialName,0.25); - - if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) { - ConfigHolder.UNIT_REPAIR_HOLDER.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE); - } - - // Update gui - updateValueForGeneric(materialName, true); - this.parentGui.updateValueForGeneric(this.parentMaterial, true); - - - // Display material edit setting - this.factoryMap.get(materialName).create().show(player); - }, - true - ).show(event.getWhoClicked()); - - }; - } - - @Override - protected String createItemName() { - return "§aAdd a new item reparable by " + this.materialName; - } - - @Override - protected DoubleSettingGui.DoubleSettingFactory createFactory(String materialName) { - String materialDisplayName = CasedStringUtil.snakeToUpperSpacedCase(materialName); - - return new DoubleSettingGui.DoubleSettingFactory( - "§0%§8" + materialDisplayName +" Repair", - this, - ConfigHolder.UNIT_REPAIR_HOLDER, - this.parentMaterial.name().toLowerCase()+"."+materialName, - Arrays.asList( - "§7Click here to change how many §e% §7of §a" + materialDisplayName, - "§7Should get repaired by §e"+this.materialName - ), - 2, - true, true, - 0, - 1, - 0.25, - 0.01, 0.05, 0.25 - ); - } - - @Override - protected GuiItem itemFromFactory(String materialName, DoubleSettingGui.DoubleSettingFactory factory) { - return factory.getItem(materialFromName(materialName), - "§7%§a" + CasedStringUtil.snakeToUpperSpacedCase(materialName)+ " §erepaired by §a" + this.materialName); - } - - @Override - protected Collection getEveryDisplayableInstanceOfGeneric() { - ArrayList keys = new ArrayList<>(); - if(!this.shouldWork){ - return keys; - } - - ConfigurationSection materialSection = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig().getConfigurationSection(parentMaterial.name().toLowerCase()); - if(materialSection == null){ - return keys; - } - keys.addAll(materialSection.getKeys(false)); - return keys; - } - - private Material materialFromName(String materialName){ - Material mat = Material.getMaterial(materialName.toUpperCase()); - if(mat == null || mat.isAir()) return Material.BARRIER; - return mat; - } - - @Override - public void updateGuiValues() { - super.updateGuiValues(); - this.parentGui.updateValueForGeneric(this.parentMaterial, true); - } - - // ElementMappedToListGui methods - - @Override // Not used in this implementation - public void updateLocal() {} - - @Override - public void cleanAndBeUnusable() { - this.shouldWork = false; - this.backgroundPane.bindItem('S', GuiGlobalItems.backgroundItem(Material.BLACK_STAINED_GLASS_PANE)); - this.backgroundPane.bindItem('L', GuiGlobalItems.backgroundItem(Material.BLACK_STAINED_GLASS_PANE)); - this.backgroundPane.bindItem('R', GuiGlobalItems.backgroundItem(Material.BLACK_STAINED_GLASS_PANE)); - - for (HumanEntity viewer : getViewers()) { - viewer.sendMessage("This config do not exist anymore"); - this.parentGui.show(viewer); - } - } - - @Override - public Gui getMappedGui() { - return this; - } - - @Override - public void show(@NotNull HumanEntity humanEntity) { - if(!this.shouldWork){ - humanEntity.closeInventory(); - return; - } - super.show(humanEntity); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/CustomRecipeSubSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/CustomRecipeSubSettingGui.java deleted file mode 100644 index 9db6d62..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/CustomRecipeSubSettingGui.java +++ /dev/null @@ -1,238 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.list.elements; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.pane.PatternPane; -import com.github.stefvanschie.inventoryframework.pane.util.Pattern; -import io.delilaheve.CustomAnvil; -import kotlin.ranges.IntRange; -import org.bukkit.Material; -import org.bukkit.entity.HumanEntity; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.gui.config.ask.ConfirmActionGui; -import xyz.alexcrea.cuanvil.gui.config.global.CustomRecipeConfigGui; -import xyz.alexcrea.cuanvil.gui.config.settings.BoolSettingsGui; -import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui; -import xyz.alexcrea.cuanvil.gui.config.settings.ItemSettingGui; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; -import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe; -import xyz.alexcrea.cuanvil.recipe.CustomAnvilRecipeManager; -import xyz.alexcrea.cuanvil.util.CasedStringUtil; - -import java.util.Collections; -import java.util.function.Supplier; - -public class CustomRecipeSubSettingGui extends MappedToListSubSettingGui { - - private final CustomRecipeConfigGui parent; - private final AnvilCustomRecipe anvilRecipe; - private final PatternPane pane; - private boolean shouldWork = true; - - public CustomRecipeSubSettingGui( - @NotNull CustomRecipeConfigGui parent, - @NotNull AnvilCustomRecipe anvilRecipe) { - super(4, "§e" + CasedStringUtil.snakeToUpperSpacedCase(anvilRecipe.toString()) + " §8Config"); - this.parent = parent; - this.anvilRecipe = anvilRecipe; - - Pattern pattern = new Pattern( - GuiSharedConstant.EMPTY_GUI_FULL_LINE, - "01203450D", - "0ab000000", - "B00000000" - ); - this.pane = new PatternPane(0, 0, 9, 4, pattern); - addPane(this.pane); - - prepareStaticValues(); - } - - private BoolSettingsGui.BoolSettingFactory exactCountFactory; - private BoolSettingsGui.BoolSettingFactory removeExactLinearXpFactory; - private GuiItem noRemoveExactLinearXp; - - private IntSettingsGui.IntSettingFactory levelCostFactory; - private IntSettingsGui.IntSettingFactory linearXpCostFactory; - - private ItemSettingGui.ItemSettingFactory leftItemFactory; - private ItemSettingGui.ItemSettingFactory rightItemFactory; - private ItemSettingGui.ItemSettingFactory resultItemFactory; - - private void prepareStaticValues() { - - GuiGlobalItems.addBackItem(this.pane, this.parent); - GuiGlobalItems.addBackgroundItem(this.pane); - - // Delete item - ItemStack deleteItem = new ItemStack(Material.RED_TERRACOTTA); - ItemMeta deleteMeta = deleteItem.getItemMeta(); - assert deleteMeta != null; - - deleteMeta.setDisplayName("§4DELETE RECIPE"); - deleteMeta.setLore(Collections.singletonList("§cCaution with this button !")); - - deleteItem.setItemMeta(deleteMeta); - this.pane.bindItem('D', new GuiItem(deleteItem, GuiGlobalActions.openGuiAction(createDeleteGui()), CustomAnvil.instance)); - - // Displayed item will be updated later - IntRange costRange = AnvilCustomRecipe.Companion.getXP_COST_CONFIG_RANGE(); - this.exactCountFactory = new BoolSettingsGui.BoolSettingFactory("§8Exact count ?", this, - ConfigHolder.CUSTOM_RECIPE_HOLDER, - this.anvilRecipe + "." + AnvilCustomRecipe.EXACT_COUNT_CONFIG, AnvilCustomRecipe.DEFAULT_EXACT_COUNT_CONFIG); - - this.removeExactLinearXpFactory = new BoolSettingsGui.BoolSettingFactory("§8Remove exact linear xp ?", this, - ConfigHolder.CUSTOM_RECIPE_HOLDER, - this.anvilRecipe + "." + AnvilCustomRecipe.REMOVE_EXACT_XP_CONFIG, AnvilCustomRecipe.DEFAULT_REMOVE_EXACT_XP_CONFIG); - - ItemStack item = new ItemStack(Material.BARRIER); - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§cRemove exact linear xp ?"); - meta.setLore(Collections.singletonList("§7Not usable if linear cost is 0")); - item.setItemMeta(meta); - this.noRemoveExactLinearXp = new GuiItem(item, GuiGlobalActions.stayInPlace, CustomAnvil.instance); - - this.levelCostFactory = new IntSettingsGui.IntSettingFactory("§8Recipe Level Cost", this, - this.anvilRecipe + "." + AnvilCustomRecipe.XP_LEVEL_COST_CONFIG, - ConfigHolder.CUSTOM_RECIPE_HOLDER, - null, - costRange.getFirst(), costRange.getLast(), AnvilCustomRecipe.DEFAULT_XP_LEVEL_COST_CONFIG, 1, 5, 10); - - this.linearXpCostFactory = new IntSettingsGui.IntSettingFactory("§8Recipe Linear Xp Cost", this, - this.anvilRecipe + "." + AnvilCustomRecipe.LINEAR_XP_COST_CONFIG, - ConfigHolder.CUSTOM_RECIPE_HOLDER, - null, - 0, Integer.MAX_VALUE, AnvilCustomRecipe.DEFAULT_LINEAR_XP_COST_CONFIG, 1, 10, 100, 1000, 10000); - - - // Right part of the gui - this.leftItemFactory = new ItemSettingGui.ItemSettingFactory("§eRecipe Left §8Item", this, - this.anvilRecipe + "." + AnvilCustomRecipe.LEFT_ITEM_CONFIG, - ConfigHolder.CUSTOM_RECIPE_HOLDER, - AnvilCustomRecipe.Companion.getDEFAULT_LEFT_ITEM_CONFIG(), - "§7Set the left item of the custom craft", - "§7\u25A0 + \u25A1 = \u25A1"); - - this.rightItemFactory = new ItemSettingGui.ItemSettingFactory("§eRecipe Right §8Item", this, - this.anvilRecipe + "." + AnvilCustomRecipe.RIGHT_ITEM_CONFIG, - ConfigHolder.CUSTOM_RECIPE_HOLDER, - AnvilCustomRecipe.Companion.getDEFAULT_RIGHT_ITEM_CONFIG(), - "§7Set the right item of the custom craft", - "§7\u25A1 + \u25A0 = \u25A1"); - - this.resultItemFactory = new ItemSettingGui.ItemSettingFactory("§aRecipe Result §8Item", this, - this.anvilRecipe + "." + AnvilCustomRecipe.RESULT_ITEM_CONFIG, - ConfigHolder.CUSTOM_RECIPE_HOLDER, - AnvilCustomRecipe.Companion.getDEFAULT_RESULT_ITEM_CONFIG(), - "§7Set the result item of the custom craft", - "§7\u25A1 + \u25A1 = \u25A0"); - - // Now we update the items - updateLocal(); - } - - private ConfirmActionGui createDeleteGui() { - Supplier deleteSupplier = () -> { - CustomAnvilRecipeManager manager = ConfigHolder.CUSTOM_RECIPE_HOLDER.getRecipeManager(); - - // Remove from manager - manager.cleanRemove(this.anvilRecipe); - - // Remove from parent - this.parent.removeGeneric(this.anvilRecipe); - - // Remove self - cleanAndBeUnusable(); - - // Update config file storage - ConfigHolder.CUSTOM_RECIPE_HOLDER.delete(this.anvilRecipe.toString()); - - // Save - boolean success = true; - if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) { - success = ConfigHolder.CONFLICT_HOLDER.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE); - } - - return success; - }; - - return new ConfirmActionGui("§cDelete §e" + CasedStringUtil.snakeToUpperSpacedCase(this.anvilRecipe.toString()) + "§c?", - "§7Confirm that you want to delete this conflict.", - this, this.parent, deleteSupplier - ); - } - - @Override - public void updateGuiValues() { - // update value from config to conflict - this.anvilRecipe.updateFromFile(); - - // Parent should call updateLocal with this call - this.parent.updateValueForGeneric(this.anvilRecipe, true); - } - - public void updateLocal() { - if (!this.shouldWork) return; - - GuiItem exactCountItem = this.exactCountFactory.getItem(); - this.pane.bindItem('1', exactCountItem); - - if (anvilRecipe.getXpCostPerCraft() == 0) { - this.pane.bindItem('a', noRemoveExactLinearXp); - } else { - this.pane.bindItem('a', removeExactLinearXpFactory.getItem()); - } - - GuiItem levelCostItem = this.levelCostFactory.getItem(Material.EXPERIENCE_BOTTLE); - this.pane.bindItem('2', levelCostItem); - - - GuiItem xpCostItem = this.linearXpCostFactory.getItem(Material.EXPERIENCE_BOTTLE); - this.pane.bindItem('b', xpCostItem); - - GuiItem leftGuiItem = this.leftItemFactory.getItem(); - this.pane.bindItem('3', leftGuiItem); - - GuiItem rightGuiItem = this.rightItemFactory.getItem(); - this.pane.bindItem('4', rightGuiItem); - - GuiItem resultGuiItem = this.resultItemFactory.getItem(); - this.pane.bindItem('5', resultGuiItem); - - update(); - } - - public void cleanAndBeUnusable() { - for (HumanEntity viewer : getViewers()) { - this.parent.show(viewer); - } - this.shouldWork = false; - - // Just in case something is extremely wrong - GuiItem background = GuiGlobalItems.backgroundItem(); - this.pane.bindItem('1', background); - this.pane.bindItem('2', background); - this.pane.bindItem('3', background); - this.pane.bindItem('4', background); - this.pane.bindItem('5', background); - - this.pane.bindItem('D', background); - } - - @Override - public void show(@NotNull HumanEntity humanEntity) { - if (this.shouldWork) { - super.show(humanEntity); - } else { - this.parent.show(humanEntity); - } - } - - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/ElementMappedToListGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/ElementMappedToListGui.java deleted file mode 100644 index 637f72a..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/ElementMappedToListGui.java +++ /dev/null @@ -1,13 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.list.elements; - -import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; - -public interface ElementMappedToListGui { - - void updateLocal(); - - void cleanAndBeUnusable(); - - Gui getMappedGui(); - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/EnchantConflictSubSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/EnchantConflictSubSettingGui.java deleted file mode 100644 index 97bdfcb..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/EnchantConflictSubSettingGui.java +++ /dev/null @@ -1,330 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.list.elements; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.pane.PatternPane; -import com.github.stefvanschie.inventoryframework.pane.util.Pattern; -import io.delilaheve.CustomAnvil; -import org.bukkit.Material; -import org.bukkit.entity.HumanEntity; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; -import xyz.alexcrea.cuanvil.group.AbstractMaterialGroup; -import xyz.alexcrea.cuanvil.group.EnchantConflictGroup; -import xyz.alexcrea.cuanvil.group.EnchantConflictManager; -import xyz.alexcrea.cuanvil.gui.config.SelectEnchantmentContainer; -import xyz.alexcrea.cuanvil.gui.config.SelectGroupContainer; -import xyz.alexcrea.cuanvil.gui.config.ask.ConfirmActionGui; -import xyz.alexcrea.cuanvil.gui.config.global.EnchantConflictGui; -import xyz.alexcrea.cuanvil.gui.config.settings.EnchantSelectSettingGui; -import xyz.alexcrea.cuanvil.gui.config.settings.GroupSelectSettingGui; -import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; -import xyz.alexcrea.cuanvil.util.CasedStringUtil; -import xyz.alexcrea.cuanvil.util.MetricsUtil; - -import java.util.*; -import java.util.function.Supplier; -import java.util.logging.Level; - -public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui implements SelectEnchantmentContainer, SelectGroupContainer { - - private final EnchantConflictGui parent; - private final EnchantConflictGroup enchantConflict; - private final PatternPane pane; - private boolean shouldWork = true; - - public EnchantConflictSubSettingGui( - @NotNull EnchantConflictGui parent, - @NotNull EnchantConflictGroup enchantConflict) { - super(3, - "§e" + CasedStringUtil.snakeToUpperSpacedCase(enchantConflict.toString()) + " §8Config"); - this.parent = parent; - this.enchantConflict = enchantConflict; - - Pattern pattern = new Pattern( - GuiSharedConstant.EMPTY_GUI_FULL_LINE, - "00EGM000D", - "B00000000" - ); - this.pane = new PatternPane(0, 0, 9, 3, pattern); - addPane(this.pane); - - prepareStaticValues(); - } - - private GuiItem enchantSettingItem; - private GuiItem groupSettingItem; - private IntSettingsGui.IntSettingFactory minBeforeActiveSettingFactory; - - private void prepareStaticValues() { - - GuiGlobalItems.addBackItem(this.pane, this.parent); - GuiGlobalItems.addBackgroundItem(this.pane); - - // Delete item - ItemStack deleteItem = new ItemStack(Material.RED_TERRACOTTA); - ItemMeta deleteMeta = deleteItem.getItemMeta(); - assert deleteMeta != null; - - deleteMeta.setDisplayName("§4DELETE CONFLICT"); - deleteMeta.setLore(Collections.singletonList("§cCaution with this button !")); - - deleteItem.setItemMeta(deleteMeta); - this.pane.bindItem('D', new GuiItem(deleteItem, GuiGlobalActions.openGuiAction(createDeleteGui()), CustomAnvil.instance)); - - // Displayed item will be updated later - this.enchantSettingItem = new GuiItem(new ItemStack(Material.ENCHANTED_BOOK), event -> { - event.setCancelled(true); - EnchantSelectSettingGui enchantGui = new EnchantSelectSettingGui( - "§e" + CasedStringUtil.snakeToUpperSpacedCase(enchantConflict.toString()) + "§5", - this, this); - enchantGui.show(event.getWhoClicked()); - }, CustomAnvil.instance); - - this.groupSettingItem = new GuiItem(new ItemStack(Material.PAPER), event -> { - event.setCancelled(true); - GroupSelectSettingGui enchantGui = new GroupSelectSettingGui( - "§e" + CasedStringUtil.snakeToUpperSpacedCase(this.enchantConflict.toString()) + " §3Groups", - this, this, 0); - enchantGui.show(event.getWhoClicked()); - }, CustomAnvil.instance); - - this.minBeforeActiveSettingFactory = new IntSettingsGui.IntSettingFactory( - "§8Minimum enchantment count", - this, this.enchantConflict + ".maxEnchantmentBeforeConflict", ConfigHolder.CONFLICT_HOLDER, - Arrays.asList( - "§7Minimum enchantment count set to X mean only X enchantment can be put", - "§7on an item before the conflict is active." - ), - 0, 255, 0, 1 - ); - - this.pane.bindItem('E', this.enchantSettingItem); - this.pane.bindItem('G', this.groupSettingItem); - - // Now we update the items - updateLocal(); - - } - - private ConfirmActionGui createDeleteGui() { - Supplier deleteSupplier = () -> { - EnchantConflictManager manager = ConfigHolder.CONFLICT_HOLDER.getConflictManager(); - - // Remove from enchantment - manager.removeConflict(this.enchantConflict); - - // Remove from parent - this.parent.removeGeneric(this.enchantConflict); - - // Remove self - cleanAndBeUnusable(); - - // Update config file storage - ConfigHolder.CONFLICT_HOLDER.delete(this.enchantConflict.toString()); - - // Save - boolean success = true; - if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) { - success = ConfigHolder.CONFLICT_HOLDER.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE); - } - - return success; - }; - - return new ConfirmActionGui("§cDelete §e" + CasedStringUtil.snakeToUpperSpacedCase(this.enchantConflict.toString()) + "§c?", - "§7Confirm that you want to delete this conflict.", - this, this.parent, deleteSupplier - ); - } - - @Override - public void updateGuiValues() { - // update value from config to conflict - int minBeforeBlock = ConfigHolder.CONFLICT_HOLDER.getConfig().getInt(this.enchantConflict.toString()+'.'+EnchantConflictManager.ENCH_MAX_PATH, 0); - this.enchantConflict.setMinBeforeBlock(minBeforeBlock); - - // Parent should call updateLocal with this call - this.parent.updateValueForGeneric(this.enchantConflict, true); - } - - @Override - public void updateLocal() { - if (!this.shouldWork) return; - - // Prepare enchantment lore - ArrayList enchantLore = new ArrayList<>(); - enchantLore.add("§7Allow you to select a list of §5Enchantments §7that this conflict should include"); - Set enchants = getSelectedEnchantments(); - if (enchants.isEmpty()) { - enchantLore.add("§7There is no included enchantment for this conflict."); - } else { - enchantLore.add("§7List of included enchantment for this conflict:"); - Iterator enchantIterator = enchants.iterator(); - - boolean greaterThanMax = enchants.size() > 5; - int maxindex = (greaterThanMax ? 4 : enchants.size()); - for (int i = 0; i < maxindex; i++) { - // format string like "- Fire Protection" - String formattedName = CasedStringUtil.snakeToUpperSpacedCase(enchantIterator.next().getKey().getKey()); - enchantLore.add("§7- §5" + formattedName); - } - if (greaterThanMax) { - enchantLore.add("§7And " + (enchants.size() - 4) + " more..."); - } - - } - - // Prepare group lore - List groupLore = SelectGroupContainer.getGroupLore(this, "conflict", "exclude"); - - // Configure enchant setting item - ItemStack enchantItem = this.enchantSettingItem.getItem(); - ItemMeta enchantMeta = enchantItem.getItemMeta(); - assert enchantMeta != null; - - enchantMeta.setDisplayName("§aSelect included §5Enchantments §aSettings"); - enchantMeta.setLore(enchantLore); - - enchantItem.setItemMeta(enchantMeta); - - this.enchantSettingItem.setItem(enchantItem); // Just in case - - // Configure group setting item - ItemStack groupItem = this.groupSettingItem.getItem(); - ItemMeta groupMeta = groupItem.getItemMeta(); - assert groupMeta != null; - - groupMeta.setDisplayName("§aSelect Excluded §3Groups §aSettings"); - groupMeta.setLore(groupLore); - - groupItem.setItemMeta(groupMeta); - - this.groupSettingItem.setItem(groupItem); // Just in case - - this.pane.bindItem('M', this.minBeforeActiveSettingFactory.getItem(Material.COMMAND_BLOCK, - "Minimum Enchantment Count")); - update(); - } - - @Override - public void cleanAndBeUnusable() { - for (HumanEntity viewer : getViewers()) { - this.parent.show(viewer); - } - this.shouldWork = false; - - // Just in case something is extremely wrong - GuiItem background = GuiGlobalItems.backgroundItem(); - this.pane.bindItem('E', background); - this.pane.bindItem('G', background); - this.pane.bindItem('M', background); - this.pane.bindItem('D', background); - } - - @Override - public void show(@NotNull HumanEntity humanEntity) { - if (this.shouldWork) { - super.show(humanEntity); - } else { - this.parent.show(humanEntity); - } - } - - // Select enchantment container methods - - @Override - public Set getSelectedEnchantments() { - return this.enchantConflict.getEnchants(); - } - - @Override - public boolean setSelectedEnchantments(Set enchantments) { - if (!this.shouldWork) { - CustomAnvil.instance.getLogger().info("Trying to save " + enchantConflict + " enchants but sub config is destroyed"); - return false; - } - - // Set live configuration - this.enchantConflict.setEnchants(enchantments); - - // Save on file configuration - String[] enchantKeys = new String[enchantments.size()]; - int index = 0; - for (CAEnchantment enchantment : enchantments) { - enchantKeys[index++] = enchantment.getKey().toString(); - } - ConfigHolder.CONFLICT_HOLDER.getConfig().set(enchantConflict + ".enchantments", enchantKeys); - - try { - updateGuiValues(); - } catch (Exception e) { - CustomAnvil.instance.getLogger().log(Level.WARNING, "An error occurred while updating enchants for " + this.enchantConflict, e); - MetricsUtil.INSTANCE.trackError(e); - } - - // Save file configuration to disk - if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) { - return ConfigHolder.CONFLICT_HOLDER.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE); - } - - return true; - } - - @Override - public Set illegalEnchantments() { - return Collections.emptySet(); - } - - // Select group container methods - - @Override - public Set getSelectedGroups() { - return this.enchantConflict.getCantConflictGroup().getGroups(); - } - - @Override - public boolean setSelectedGroups(Set groups) { - if (!this.shouldWork) { - CustomAnvil.instance.getLogger().info("Trying to save " + enchantConflict.toString() + " groups but sub config is destroyed"); - return false; - } - - // Set live configuration - this.enchantConflict.getCantConflictGroup().setGroups(groups); - - // Save on file configuration - String[] groupsNames = new String[groups.size()]; - int index = 0; - for (AbstractMaterialGroup group : groups) { - groupsNames[index++] = group.getName(); - } - ConfigHolder.CONFLICT_HOLDER.getConfig().set(this.enchantConflict + ".notAffectedGroups", groupsNames); - - try { - updateGuiValues(); - } catch (Exception e) { - CustomAnvil.instance.getLogger().log(Level.WARNING, "An error occurred while updating group for " + this.enchantConflict, e); - MetricsUtil.INSTANCE.trackError(e); - } - - // Save file configuration to disk - if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) { - return ConfigHolder.CONFLICT_HOLDER.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE); - } - - return true; - } - - @Override - public Set illegalGroups() { - - return Collections.emptySet(); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/GroupConfigSubSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/GroupConfigSubSettingGui.java deleted file mode 100644 index 3d05674..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/GroupConfigSubSettingGui.java +++ /dev/null @@ -1,412 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.list.elements; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.pane.PatternPane; -import com.github.stefvanschie.inventoryframework.pane.util.Pattern; -import io.delilaheve.CustomAnvil; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.entity.HumanEntity; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.ItemFlag; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.group.*; -import xyz.alexcrea.cuanvil.gui.config.SelectGroupContainer; -import xyz.alexcrea.cuanvil.gui.config.SelectMaterialContainer; -import xyz.alexcrea.cuanvil.gui.config.ask.ConfirmActionGui; -import xyz.alexcrea.cuanvil.gui.config.global.GroupConfigGui; -import xyz.alexcrea.cuanvil.gui.config.settings.GroupSelectSettingGui; -import xyz.alexcrea.cuanvil.gui.config.settings.MaterialSelectSettingGui; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; -import xyz.alexcrea.cuanvil.util.CasedStringUtil; - -import java.util.*; -import java.util.function.Consumer; -import java.util.function.Supplier; - -public class GroupConfigSubSettingGui extends MappedToListSubSettingGui implements SelectGroupContainer, SelectMaterialContainer { - - private final GroupConfigGui parent; - private final IncludeGroup group; - private final PatternPane pane; - private boolean usable = true; - - public GroupConfigSubSettingGui( - @NotNull GroupConfigGui parent, - @NotNull IncludeGroup group) { - super(3, - "§e" + CasedStringUtil.snakeToUpperSpacedCase(group.getName()) + " §rConfig"); - this.parent = parent; - this.group = group; - - Pattern pattern = new Pattern( - GuiSharedConstant.EMPTY_GUI_FULL_LINE, - "00102000D", - "B00000000" - ); - this.pane = new PatternPane(0, 0, 9, 3, pattern); - addPane(this.pane); - - prepareStaticValues(); - } - - private GuiItem materialSelection; - private GuiItem groupSelection; - private void prepareStaticValues() { - GuiGlobalItems.addBackItem(this.pane, this.parent); - GuiGlobalItems.addBackgroundItem(this.pane); - - // Delete item - ItemStack deleteItem = new ItemStack(Material.RED_TERRACOTTA); - ItemMeta deleteMeta = deleteItem.getItemMeta(); - - deleteMeta.setDisplayName("§4DELETE GROUP"); - deleteMeta.setLore(Collections.singletonList("§cCaution with this button !")); - - deleteItem.setItemMeta(deleteMeta); - this.pane.bindItem('D', new GuiItem(deleteItem, openGuiAndCheckAction(), CustomAnvil.instance)); - - // Displayed item will be updated later - String materialSelectionName = "§e" + CasedStringUtil.snakeToUpperSpacedCase(group.getName()) + " §rMaterials"; - ItemStack selectItem = new ItemStack(Material.DIAMOND_SWORD); - ItemMeta selectItemMeta = selectItem.getItemMeta(); - selectItemMeta.setDisplayName(materialSelectionName); - - selectItem.setItemMeta(selectItemMeta); - this.materialSelection = new GuiItem(selectItem, (event) -> { - event.setCancelled(true); - MaterialSelectSettingGui selectGui = new MaterialSelectSettingGui(this, - materialSelectionName - , this); - selectGui.show(event.getWhoClicked()); - - }, CustomAnvil.instance); - - String selectGroupName = "§e" + CasedStringUtil.snakeToUpperSpacedCase(this.group.getName()) + " §rGroups"; - ItemStack selectGroup = new ItemStack(Material.CHEST); - ItemMeta selectGroupMeta = selectGroup.getItemMeta(); - selectGroupMeta.setDisplayName(selectGroupName); - - selectGroup.setItemMeta(selectGroupMeta); - this.groupSelection = new GuiItem(selectGroup, (event) -> { - event.setCancelled(true); - GroupSelectSettingGui enchantGui = new GroupSelectSettingGui( - selectGroupName, - this, this, 0); - enchantGui.show(event.getWhoClicked()); - }, CustomAnvil.instance); - - this.pane.bindItem('1', this.materialSelection); - this.pane.bindItem('2', this.groupSelection); - } - - private @NotNull Consumer openGuiAndCheckAction() { - ConfirmActionGui deleteGui = createDeleteGui(); - return event -> { - event.setCancelled(true); - HumanEntity player = event.getWhoClicked(); - // Do not allow to open inventory if player do not have edit configuration permission - if (!player.hasPermission(CustomAnvil.editConfigPermission)) { - player.closeInventory(); - player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); - return; - } - // test if group is used & cancel & warn user if so - if(testAndWarnIfUsed(player)) return; - - deleteGui.show(player); - }; - } - - private @NotNull ConfirmActionGui createDeleteGui() { - Supplier deleteSupplier = () -> { - // test if group is used & cancel if so - if(!getUsedLocations(this.group).isEmpty()) return false; - - ItemGroupManager manager = ConfigHolder.ITEM_GROUP_HOLDER.getItemGroupsManager(); - - // Remove from manager - manager.getGroupMap().remove(this.group.getName()); - - // Remove from parent - this.parent.removeGeneric(this.group); - - // Remove self - cleanAndBeUnusable(); - - // Update config file storage - ConfigHolder.CUSTOM_RECIPE_HOLDER.delete(this.group.getName()); - - // Save - boolean success = true; - if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) { - success = ConfigHolder.CONFLICT_HOLDER.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE); - } - - return success; - }; - - return new ConfirmActionGui("§cDelete §e" + CasedStringUtil.snakeToUpperSpacedCase(this.group.toString()) + "§c?", - "§7Confirm that you want to delete this group.", - this, this.parent, deleteSupplier - ); - } - - public boolean testAndWarnIfUsed(HumanEntity player){ - List usedLoc = getUsedLocations(this.group); - if(usedLoc.isEmpty()){ - return false; - } - StringBuilder stb = new StringBuilder("§cCan't delete group " +this.group.getName()+ - "\n§eUsed by:"); - int maxIndex = usedLoc.size(); - int nbMore = 0; - if(maxIndex > 10){ - nbMore = maxIndex - 9; - maxIndex = 9; - } - for (int i = 0; i < maxIndex; i++) { - stb.append("\n§r-§e ").append(usedLoc.get(i)); - } - if(nbMore > 0){ - stb.append("§cAnd ").append(nbMore).append(" More..."); - } - - player.sendMessage(stb.toString()); - return true; - } - - // return a string containing every instance of where this group is used - public static List getUsedLocations(AbstractMaterialGroup group){ - ArrayList usageList = new ArrayList<>(); - - // Test used by another group - ItemGroupManager groupManager = ConfigHolder.ITEM_GROUP_HOLDER.getItemGroupsManager(); - for (AbstractMaterialGroup otherGroup : groupManager.getGroupMap().values()) { - if(otherGroup.getGroups().contains(group)) { - usageList.add("group " + otherGroup.getName()); - } - } - - // Test if used for conflict - EnchantConflictManager conflictManager = ConfigHolder.CONFLICT_HOLDER.getConflictManager(); - for (EnchantConflictGroup conflict : conflictManager.getConflictList()) { - if(conflict.getCantConflictGroup().getGroups().contains(group)) { - usageList.add("conflict " + conflict); - } - } - - return usageList; - } - - @Override - public void updateGuiValues() { - if(!this.usable) return; - // Parent should call updateLocal with this call - this.parent.updateValueForGeneric(this.group, true); - - } - - @Override - public void updateLocal() { - if(!this.usable) return; - // Prepare material lore - List matLore = SelectMaterialContainer.getMaterialLore(this, "group", "include"); - - // Prepare group lore - List groupLore = SelectGroupContainer.getGroupLore(this, "group", "include"); - - // Configure included material setting item - ItemStack matSelectItem = this.materialSelection.getItem(); - ItemMeta matSelectMeta = matSelectItem.getItemMeta(); - - matSelectMeta.setDisplayName("§aSelect included §eMaterials §aSettings"); - matSelectMeta.setLore(matLore); - matSelectMeta.addItemFlags(ItemFlag.values()); - - matSelectItem.setItemMeta(matSelectMeta); - - this.materialSelection.setItem(matSelectItem); // Just in case - - // Configure enchant setting item - ItemStack groupSelectItem = this.groupSelection.getItem(); - ItemMeta groupSelectMeta = groupSelectItem.getItemMeta(); - - groupSelectMeta.setDisplayName("§aSelect included §3Groups §aSettings"); - groupSelectMeta.setLore(groupLore); - - groupSelectItem.setItemMeta(groupSelectMeta); - - this.groupSelection.setItem(groupSelectItem); // Just in case - } - - @Override - public void cleanAndBeUnusable() { - this.usable = false; - this.pane.bindItem('1', GuiGlobalItems.backgroundItem()); - this.pane.bindItem('2', GuiGlobalItems.backgroundItem()); - this.pane.bindItem('D', GuiGlobalItems.backgroundItem()); - - } - - @Override - public void show(@NotNull HumanEntity player) { - if(!this.usable) { - this.parent.show(player); - return; - } - super.show(player); - } - - // ---------------------------- - // SelectGroupContainer related methods - // ---------------------------- - - @Override - public Set getSelectedGroups() { - return this.group.getGroups(); - } - - @Override - public boolean setSelectedGroups(Set groups) { - // update group and referencing groups - updateGroup(this.group, groups); - - // Save file configuration to disk - if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) { - return ConfigHolder.CONFLICT_HOLDER.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE); - } - - return true; - } - - private void updateGroup(@NotNull AbstractMaterialGroup group, Set groups){ - // Set live configuration - group.setGroups(groups); - - // Write to file configuration - groups = group.getGroups(); // Maybe some group may have been rejected - String[] groupNames = new String[groups.size()]; - int index = 0; - for (AbstractMaterialGroup otherGroup : groups) { - groupNames[index++] = otherGroup.getName(); - } - - ConfigHolder.ITEM_GROUP_HOLDER.getConfig().set(group.getName()+"."+ItemGroupManager.GROUP_LIST_PATH, groupNames); - - // Try to update referencing group. kind of expensive operation in some case. - updateDirectReferencingGroups(group); - - // We assume a backup & save call will be done soon after - } - - @Override - public Set illegalGroups() { - Set illegal = new HashSet<>(); - - for (AbstractMaterialGroup otherGroup : ConfigHolder.ITEM_GROUP_HOLDER.getItemGroupsManager().getGroupMap().values()) { - if(otherGroup.isReferencing(this.group)){ - illegal.add(otherGroup); - } - } - illegal.add(this.group); - - return illegal; - } - - // ---------------------------- - // End of SelectGroupContainer related methods - // ---------------------------- - // SelectMaterialContainer related methods - // ---------------------------- - - @Override - public Set getSelectedMaterials() { - return this.group.getNonGroupInheritedMaterials(); - } - - @Override - public boolean setSelectedMaterials(Set materials) { - this.group.setNonGroupInheritedMaterials(materials); - - // Write to file configuration - String[] groupNames = new String[materials.size()]; - int index = 0; - for (NamespacedKey otherGroup : materials) { - groupNames[index++] = otherGroup.getKey().toLowerCase(); - } - - ConfigHolder.ITEM_GROUP_HOLDER.getConfig().set(this.group.getName()+"."+ItemGroupManager.MATERIAL_LIST_PATH, groupNames); - - // update referencing groups - updateDirectReferencingGroups(this.group); - - // Save file configuration to disk - if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) { - return ConfigHolder.ITEM_GROUP_HOLDER.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE); - } - return true; - } - - @Override - public Set illegalMaterials() { - return Set.of(Material.AIR.getKey()); - } - - // ---------------------------- - // End of SelectMaterialContainer related methods - // ---------------------------- - - private void updateDirectReferencingGroups(AbstractMaterialGroup referenceTo){ - Collection everyStoredGroups = ConfigHolder.ITEM_GROUP_HOLDER.getItemGroupsManager().getGroupMap().values(); - List everyConflicts = ConfigHolder.CONFLICT_HOLDER.getConflictManager().getConflictList(); - - HashSet toUpdate = new HashSet<>(); - HashSet updateFuture = new HashSet<>(); - HashSet conflictGroupPlanned = new HashSet<>(); - - updateFuture.add(referenceTo); - while (!updateFuture.isEmpty()){ - HashSet temp = updateFuture; - updateFuture = toUpdate; - updateFuture.clear(); - toUpdate = temp; - - for (AbstractMaterialGroup testGroup : toUpdate) { - // Update other stored group - for (AbstractMaterialGroup otherGroup : everyStoredGroups) { - if(otherGroup.getGroups().contains(testGroup)){ - otherGroup.updateMaterials(); - updateFuture.add(otherGroup); - } - } - - // plan update for conflict groups - for (EnchantConflictGroup everyConflict : everyConflicts) { - AbstractMaterialGroup conflictGroup = everyConflict.getCantConflictGroup(); - if(conflictGroup.getGroups().contains(testGroup)){ - conflictGroupPlanned.add(conflictGroup); - } - } - - // Update parent & local by extension - if(testGroup instanceof IncludeGroup){ - this.parent.updateValueForGeneric((IncludeGroup) testGroup, false); - } - } - } - this.parent.update(); - - // Update conflict group - for (AbstractMaterialGroup conflictGroup : conflictGroupPlanned) { - conflictGroup.updateMaterials(); - } - - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/MappedToListSubSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/MappedToListSubSettingGui.java deleted file mode 100644 index 1d86781..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/MappedToListSubSettingGui.java +++ /dev/null @@ -1,28 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.list.elements; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.gui.type.ChestGui; -import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; -import io.delilaheve.CustomAnvil; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; - -public abstract class MappedToListSubSettingGui extends ChestGui implements ValueUpdatableGui, ElementMappedToListGui { - - protected MappedToListSubSettingGui( - int rows, - @NotNull String title) { - super(rows, title, CustomAnvil.instance); - } - - @Override - public Gui getMappedGui() { - return this; - } - - @Override - public Gui getConnectedGui() { - return this; - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/AbstractSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/AbstractSettingGui.java deleted file mode 100644 index b07e7c1..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/AbstractSettingGui.java +++ /dev/null @@ -1,136 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.settings; - -import com.github.stefvanschie.inventoryframework.adventuresupport.StringHolder; -import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder; -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.gui.type.ChestGui; -import com.github.stefvanschie.inventoryframework.pane.PatternPane; -import com.github.stefvanschie.inventoryframework.pane.util.Pattern; -import io.delilaheve.CustomAnvil; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; - -/** - * An instance gui used to edit a setting. - */ -public abstract class AbstractSettingGui extends ChestGui implements SettingGui { - - public static final String CLICK_LORE = "§7Click Here to change the value"; - - private PatternPane pane; - - /** - * Prepare necessary object for a setting gui. - * - * @param rows Number of row for this gui. - * @param title Title of this gui. - * @param parent Parent gui to go back when completed. - */ - protected AbstractSettingGui(int rows, @NotNull TextHolder title, ValueUpdatableGui parent) { - super(rows, title, CustomAnvil.instance); - initBase(parent); - } - - /** - * Prepare necessary object for a setting gui. - * - * @param rows Number of row for this gui. - * @param title Title of this gui. - * @param parent Parent gui to go back when completed. - */ - protected AbstractSettingGui(int rows, @NotNull String title, ValueUpdatableGui parent) { - this(rows, StringHolder.of(title), parent); - } - - protected GuiItem saveItem; - - /** - * Initialise and prepare value for this gui. - * - * @param parent Parent gui to go back when completed. - */ - protected void initBase(ValueUpdatableGui parent) { - Pattern pattern = getGuiPattern(); - pane = new PatternPane(0, 0, pattern.getLength(), pattern.getHeight(), pattern); - addPane(pane); - - GuiGlobalItems.addBackItem(pane, parent.getConnectedGui()); - GuiGlobalItems.addBackgroundItem(pane); - - saveItem = GuiGlobalItems.saveItem(this, parent); - - pane.bindItem('S', GuiGlobalItems.noChangeItem()); - - } - - @Override - public void update() { - pane.bindItem('S', hadChange() ? saveItem : GuiGlobalItems.noChangeItem()); - super.update(); - } - - /** - * Get main pane for this setting gui. - * - * @return Main pattern pain of this gui. - */ - protected PatternPane getPane() { - return pane; - } - - /** - * Used to get the gui pattern. - * Reserved character are: - *
      - *
    • S: save setting button.
    • - *
    • B: "back to previous gui" button.
    • - *
    • 0: default background item.
    • - *
    - * - * @return The gui's pattern. - */ - protected abstract Pattern getGuiPattern(); - - - /** - * Most of the time a setting gui will be called from a global gui. - *

    - * It is better to keep a factory that hold setting data than find what parameters to use every time. - */ - public abstract static class SettingGuiFactory implements SettingGui.SettingGuiFactory { - @NotNull - protected String configPath; - @NotNull - protected ConfigHolder config; - - /** - * Constructor for settings gui factory - * - * @param configPath Configuration path of this setting. - * @param config Configuration holder of this setting. - */ - protected SettingGuiFactory(@NotNull String configPath, @NotNull ConfigHolder config) { - this.configPath = configPath; - this.config = config; - } - - /** - * @return Configuration path of this setting. - */ - @NotNull - public String getConfigPath() { - return configPath; - } - - /** - * @return Configuration holder of this setting. - */ - @NotNull - public ConfigHolder getConfigHolder() { - return config; - } - - } -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/BoolSettingsGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/BoolSettingsGui.java deleted file mode 100644 index 1d5e73d..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/BoolSettingsGui.java +++ /dev/null @@ -1,267 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.settings; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; -import com.github.stefvanschie.inventoryframework.pane.PatternPane; -import com.github.stefvanschie.inventoryframework.pane.util.Pattern; -import io.delilaheve.CustomAnvil; -import org.bukkit.Material; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; -import xyz.alexcrea.cuanvil.util.CasedStringUtil; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.function.Consumer; - -/** - * An instance of a gui used to edit a boolean setting. - */ -public class BoolSettingsGui extends AbstractSettingGui { - - private final BoolSettingFactory holder; - private final boolean before; - private boolean now; - - /** - * Create a boolean setting config gui. - * - * @param holder Configuration factory of this setting. - * @param now The defined value of this setting. - */ - protected BoolSettingsGui(BoolSettingFactory holder, boolean now) { - super(3, holder.getTitle(), holder.parent); - this.holder = holder; - this.before = now; - this.now = now; - - prepareReturnToDefault(); - updateValueDisplay(); - } - - - @Override - public Pattern getGuiPattern() { - return new Pattern( - GuiSharedConstant.EMPTY_GUI_FULL_LINE, - "D0-0v0+00", - "B0000000S" - ); - } - - protected GuiItem returnToDefault; - - /** - * Prepare "return to default value" gui item. - */ - protected void prepareReturnToDefault() { - // Prepare default Value text - String defaultValueLore; - if(holder.defaultVal){ - defaultValueLore = "§aYes §7Is the default value"; - }else{ - defaultValueLore = "§cNo §7Is the default value"; - } - - // Create reset to default item - ItemStack item = new ItemStack(Material.COMMAND_BLOCK); - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§eReset to default value"); - meta.setLore(Collections.singletonList(defaultValueLore)); - item.setItemMeta(meta); - returnToDefault = new GuiItem(item, event -> { - event.setCancelled(true); - now = holder.defaultVal; - updateValueDisplay(); - update(); - }, CustomAnvil.instance); - } - - /** - * Update item using the setting value to match the new value - */ - protected void updateValueDisplay() { - PatternPane pane = getPane(); - - // Get displayed value for this config. - String displayedName; - Material displayedMat; - if (now) { - displayedName = "§aYes"; - displayedMat = Material.GREEN_TERRACOTTA; - } else { - displayedName = "§cNo"; - displayedMat = Material.RED_TERRACOTTA; - } - - // create & set Value item - ArrayList valueLore = new ArrayList<>(); - if(!holder.displayLore.isEmpty()){ - valueLore.addAll(holder.displayLore); - valueLore.add(""); - } - valueLore.add(AbstractSettingGui.CLICK_LORE); - - ItemStack valueItemStack = new ItemStack(displayedMat); - ItemMeta valueMeta = valueItemStack.getItemMeta(); - assert valueMeta != null; - - valueMeta.setDisplayName(displayedName); - valueMeta.setLore(valueLore); - valueItemStack.setItemMeta(valueMeta); - GuiItem resultItem = new GuiItem(valueItemStack, inverseNowConsumer(), CustomAnvil.instance); - - pane.bindItem('v', resultItem); - - // reset to default - GuiItem returnToDefault; - if (now != holder.defaultVal) { - returnToDefault = this.returnToDefault; - } else { - returnToDefault = GuiGlobalItems.backgroundItem(); - } - pane.bindItem('D', returnToDefault); - - } - - /** - * @return A consumer to update the current setting's value. - */ - protected Consumer inverseNowConsumer() { - return event -> { - event.setCancelled(true); - now = !now; - updateValueDisplay(); - update(); - }; - } - - @Override - public boolean onSave() { - holder.config.getConfig().set(holder.configPath, now); - - if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) { - return holder.config.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE); - } - return true; - } - - @Override - public boolean hadChange() { - return now != before; - } - - /** - * A factory for a boolean setting gui that hold setting's information. - */ - public static class BoolSettingFactory extends SettingGuiFactory { - @NotNull - String title; - @NotNull - ValueUpdatableGui parent; - boolean defaultVal; - - @NotNull - List displayLore; - - /** - * Constructor for a boolean setting gui factory. - * - * @param title The title of the gui. - * @param parent Parent gui to go back when completed. - * @param config Configuration holder of this setting. - * @param configPath Configuration path of this setting. - * @param defaultVal Default value if not found on the config. - * @param displayLore Gui display item lore. - */ - public BoolSettingFactory( - @NotNull String title, @NotNull ValueUpdatableGui parent, - @NotNull ConfigHolder config, @NotNull String configPath, - boolean defaultVal, String... displayLore) { - super(configPath, config); - this.title = title; - this.parent = parent; - - this.defaultVal = defaultVal; - this.displayLore = Arrays.asList(displayLore); - } - - /** - * @return Get setting's gui title. - */ - @NotNull - public String getTitle() { - return title; - } - - /** - * @return The configured value for the associated setting. - */ - public boolean getConfiguredValue() { - return this.config.getConfig().getBoolean(this.configPath, this.defaultVal); - } - - @Override - public Gui create() { - // Get current value or default - boolean now = getConfiguredValue(); - // create new gui - return new BoolSettingsGui(this, now); - } - - /** - * Create a new Boolean setting GuiItem. - * This item will create and open a boolean setting GUI from the factory. - * The item will have its value written in the lore part of the item. - * - * @param name Name of the item. - * @return A formatted GuiItem that will create and open a GUI for the boolean setting. - */ - public GuiItem getItem(String name){ - // Get item properties - boolean value = getConfiguredValue(); - - Material itemMat; - StringBuilder itemName = new StringBuilder("§e"); - String finalValue; - if (value) { - itemMat = Material.GREEN_TERRACOTTA; - finalValue = "§aYes"; - } else { - itemMat = Material.RED_TERRACOTTA; - finalValue = "§cNo"; - } - itemName.append(name); - - return GuiGlobalItems.createGuiItemFromProperties(this, itemMat, itemName, finalValue, this.displayLore, false); - } - - /** - * Create a new boolean setting GuiItem. - * This item will create and open a boolean setting GUI from the factory. - * The item will have its value written in the lore part of the item. - * Item's name will be the factory set title. - * - * @return A formatted GuiItem that will create and open a GUI for the boolean setting. - */ - public GuiItem getItem(){ - // Get item properties - String configPath = GuiGlobalItems.getConfigNameFromPath(getConfigPath()); - - return getItem(CasedStringUtil.detectToUpperSpacedCase(configPath)); - } - - } - -} - diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/DoubleSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/DoubleSettingGui.java deleted file mode 100644 index c0dcff6..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/DoubleSettingGui.java +++ /dev/null @@ -1,470 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.settings; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; -import com.github.stefvanschie.inventoryframework.pane.PatternPane; -import com.github.stefvanschie.inventoryframework.pane.util.Pattern; -import io.delilaheve.CustomAnvil; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; -import xyz.alexcrea.cuanvil.util.CasedStringUtil; - -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.function.Consumer; - -public class DoubleSettingGui extends AbstractSettingGui { - - protected final DoubleSettingFactory holder; - protected final boolean asPercentage; - protected final boolean nullOnZero; - @NotNull - protected final BigDecimal before; - @NotNull - protected BigDecimal now; - protected BigDecimal step; - - /** - * Create a double setting config gui. - * - * @param holder Configuration factory of this setting. - * @param now The defined value of this setting. - * @param asPercentage If the value represent a % - * @param nullOnZero If the value should be set as null on zero - */ - protected DoubleSettingGui(DoubleSettingFactory holder, @NotNull BigDecimal now, - boolean asPercentage, boolean nullOnZero) { - super(3, holder.getTitle(), holder.parent); - assert holder.steps.length > 0 && holder.steps.length <= 9; - this.holder = holder; - this.asPercentage = asPercentage; - this.nullOnZero = nullOnZero; - - this.before = now; - this.now = now; - this.step = holder.steps[0]; - - initStepsValue(); - prepareReturnToDefault(); - updateValueDisplay(); - } - - private static final ItemStack DELETE_ITEM_STACK = new ItemStack(Material.RED_TERRACOTTA); - static { - ItemMeta meta = DELETE_ITEM_STACK.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§cDisable item being repaired ?"); - meta.setLore(Arrays.asList("§7Confirm disabling unit repair for this item..", - "§4Cation: This action can't be canceled.")); - - DELETE_ITEM_STACK.setItemMeta(meta); - } - - private GuiItem askDelete; - - @Override - protected void initBase(ValueUpdatableGui parent) { - super.initBase(parent); - - this.askDelete = new GuiItem(DELETE_ITEM_STACK, - GuiGlobalActions.saveSettingAction(this, parent), - CustomAnvil.instance); - } - - @Override - public void update() { - boolean shouldDelete = isNull() && hadChange(); - - GuiItem tempSaveItem = this.saveItem; - if(shouldDelete){ - this.saveItem = this.askDelete; - } - - super.update(); - - if(shouldDelete){ - this.saveItem = tempSaveItem; - } - } - - @Override - public Pattern getGuiPattern() { - return new Pattern( - "abcdefghi", - "D0-0v0+00", - "B0000000S" - ); - } - - protected GuiItem returnToDefault; - - /** - * Prepare "return to default value" gui item. - */ - protected void prepareReturnToDefault() { - ItemStack item = new ItemStack(Material.COMMAND_BLOCK); - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§eReset to default value"); - meta.setLore(Collections.singletonList("§7Default value is §e" + displayValue(holder.defaultVal))); - item.setItemMeta(meta); - returnToDefault = new GuiItem(item, event -> { - event.setCancelled(true); - now = holder.defaultVal; - updateValueDisplay(); - update(); - }, CustomAnvil.instance); - } - - /** - * Update item using the setting value to match the new value. - */ - protected void updateValueDisplay() { - - PatternPane pane = getPane(); - - //minus item - GuiItem minusItem; - if (now.compareTo(holder.min) > 0) { - BigDecimal planned = holder.min.max(now.subtract(step)); - - minusItem = getSetValueItem(Material.RED_TERRACOTTA, planned, "§c-"); - } else { - minusItem = GuiGlobalItems.backgroundItem(Material.BARRIER); - } - pane.bindItem('-', minusItem); - - //plus item - GuiItem plusItem; - if (now.compareTo(holder.max) < 0) { - BigDecimal planned = holder.max.min(now.add(step)); - - plusItem = getSetValueItem(Material.GREEN_TERRACOTTA, planned, "§a+"); - } else { - plusItem = GuiGlobalItems.backgroundItem(Material.BARRIER); - } - pane.bindItem('+', plusItem); - - // "result" display - ItemStack resultPaper = new ItemStack(Material.PAPER); - ItemMeta resultMeta = resultPaper.getItemMeta(); - assert resultMeta != null; - - resultMeta.setDisplayName("§fValue: §e" + displayValue(now)); - resultPaper.setItemMeta(resultMeta); - GuiItem resultItem = new GuiItem(resultPaper, GuiGlobalActions.stayInPlace, CustomAnvil.instance); - - pane.bindItem('v', resultItem); - - // reset to default - GuiItem returnToDefault; - if (now.compareTo(holder.defaultVal) != 0) { - returnToDefault = this.returnToDefault; - } else { - returnToDefault = GuiGlobalItems.backgroundItem(); - } - pane.bindItem('D', returnToDefault); - - } - - private GuiItem getSetValueItem(Material mat, BigDecimal planned, String numberPrefix){ - // Create set item lore - ArrayList setLoreItem = new ArrayList<>(); - if(!holder.displayLore.isEmpty()){ - setLoreItem.addAll(holder.displayLore); - setLoreItem.add(""); - } - setLoreItem.add(AbstractSettingGui.CLICK_LORE); - - // Create & return set value item - ItemStack item = new ItemStack(mat); - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§e" + displayValue(now) + " §f-> §e" + displayValue(planned) - + " §r(" + numberPrefix + (displayValue(planned.subtract(now).abs()) + "§r)")); - meta.setLore(setLoreItem); - item.setItemMeta(meta); - - return new GuiItem(item, updateNowConsumer(planned), CustomAnvil.instance); - } - - /** - * @param planned Value to change current setting to. - * @return A consumer to update the current setting's value. - */ - protected Consumer updateNowConsumer(BigDecimal planned) { - return event -> { - event.setCancelled(true); - now = planned; - updateValueDisplay(); - update(); - }; - } - - /** - * Initialise step items. - */ - protected void initStepsValue() { - // Put background glass on the background of 'a' to 'b' - GuiItem background = GuiGlobalItems.backgroundItem(); - PatternPane pane = getPane(); - - for (char i = 'a'; i < (getMidStepChar() - 'a') * 2 + 1; i++) { - pane.bindItem(i, background); - } - // Then update legit step values - updateStepValue(); - } - - /** - * Update steps items value. - */ - protected void updateStepValue() { - if (holder.steps.length <= 1) return; - // We assume steps have a length of 2k+1 cause its more pretty - char val = getMidStepChar(); - // Offset to start (not the best way to do it) - val -= (char) ((holder.steps.length - 1) / 2); - - // Then place items - PatternPane pane = getPane(); - for (int i = 0; i < holder.steps.length; i++) { - pane.bindItem(val + i, stepGuiItem(i)); - } - - } - - /** - * Step use lower case character from 'a' to a certain char. - * - * @return The middle value of the character set for steps. - */ - protected char getMidStepChar() { - return 'e'; - } - - /** - * Create a step item from a step value. - * - * @param stepIndex the index of the step item. - * @return A step item corresponding to its index value. - */ - protected GuiItem stepGuiItem(int stepIndex) { - BigDecimal stepValue = holder.steps[stepIndex]; - - // Get material properties - Material stepMat; - StringBuilder stepName = new StringBuilder("§"); - List stepLore; - Consumer clickEvent; - if (stepValue.compareTo(step) == 0) { - stepMat = Material.GREEN_STAINED_GLASS_PANE; - stepName.append('a'); - stepLore = Collections.singletonList("§7Value is changing by " + displayValue(stepValue)); - clickEvent = GuiGlobalActions.stayInPlace; - } else { - stepMat = Material.RED_STAINED_GLASS_PANE; - stepName.append('c'); - stepLore = Collections.singletonList("§7Click here to change the value by " + displayValue(stepValue)); - clickEvent = updateStepValue(stepValue); - } - stepName.append("Step of §e").append(displayValue(stepValue)); - - // Create item stack then gui item - ItemStack item = new ItemStack(stepMat); - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName(stepName.toString()); - meta.setLore(stepLore); - item.setItemMeta(meta); - - return new GuiItem(item, clickEvent, CustomAnvil.instance); - } - - /** - * @param stepValue Value to change current step to. - * @return A consumer to update the current step of this setting. - */ - protected Consumer updateStepValue(BigDecimal stepValue) { - return event -> { - event.setCancelled(true); - this.step = stepValue; - updateStepValue(); - updateValueDisplay(); - update(); - }; - } - - @Override - public boolean onSave() { - if(isNull()){ - if(this.holder.config instanceof ConfigHolder.DeletableResource deletableResource){ - deletableResource.delete(this.holder.configPath); - }else{ - this.holder.config.getConfig().set(this.holder.configPath, null); - } - }else{ - this.holder.config.getConfig().set(this.holder.configPath, now.doubleValue()); - } - - if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) { - return holder.config.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE); - } - return true; - } - - @Override - public boolean hadChange() { - return now.compareTo(before) != 0; - } - - public boolean isNull(){ - return this.nullOnZero && (this.now.compareTo(BigDecimal.ZERO) == 0); - } - - private static final BigDecimal PERCENTAGE_OFFSET = BigDecimal.valueOf(100); - public String displayValue(BigDecimal value){ - return displayValue(value, this.asPercentage); - } - - public static String displayValue(BigDecimal value, boolean isAsPercentage){ - if(isAsPercentage){ - return value.multiply(PERCENTAGE_OFFSET).setScale(value.scale()-2, RoundingMode.HALF_UP) + "%"; - } - return value.toString(); - } - - /** - * A factory for a double setting gui that hold setting's information. - */ - public static class DoubleSettingFactory extends SettingGuiFactory { - @NotNull - String title; - @NotNull - ValueUpdatableGui parent; - - int scale; - boolean asPercentage; - boolean nullOnZero; - BigDecimal min; - BigDecimal max; - BigDecimal defaultVal; - BigDecimal[] steps; - - @NotNull - List displayLore; - - /** - * Constructor for a double setting gui factory. - * - * @param title The title of the gui. - * @param parent Parent gui to go back when completed. - * @param config Configuration holder of this setting. - * @param configPath Configuration path of this setting. - * @param displayLore Gui display item lore. - * @param scale The scale of the decimal. - * @param asPercentage If we should display the value as a %. - * @param nullOnZero Set the value as null (deleting it) when equal to 0 - * @param min Minimum value of this setting. - * @param max Maximum value of this setting. - * @param defaultVal Default value if not found on the config. - * @param steps List of step the value can increment/decrement. - * List's size should be between 1 (included) and 5 (included). - * it is visually preferable to have an odd number of step. - * If step only contain 1 value, no step item should be displayed. - */ - public DoubleSettingFactory( - @NotNull String title, @NotNull ValueUpdatableGui parent, - @NotNull ConfigHolder config, - @NotNull String configPath, - @Nullable List displayLore, - int scale, boolean asPercentage, boolean nullOnZero, - double min, double max, double defaultVal, double... steps) { - super(configPath, config); - this.title = title; - this.parent = parent; - this.scale = scale; - this.asPercentage = asPercentage; - this.nullOnZero = nullOnZero; - this.min = BigDecimal.valueOf(min).setScale(scale, RoundingMode.HALF_UP); - this.max = BigDecimal.valueOf(max).setScale(scale, RoundingMode.HALF_UP); - this.defaultVal = BigDecimal.valueOf(defaultVal).setScale(scale, RoundingMode.HALF_UP); - - this.steps = new BigDecimal[steps.length]; - for (int i = 0; i < steps.length; i++) { - this.steps[i] = BigDecimal.valueOf(steps[i]).setScale(scale, RoundingMode.HALF_UP); - } - - if(displayLore == null){ - this.displayLore = Collections.emptyList(); - }else { - this.displayLore = displayLore; - } - } - - /** - * @return Get setting's gui title - */ - @NotNull - public String getTitle() { - return title; - } - - /** - * @return The configured value for the associated setting. - */ - public BigDecimal getConfiguredValue() { - ConfigurationSection section = this.config.getConfig(); - if(section.isDouble(this.configPath)){ - return BigDecimal.valueOf(section.getDouble(this.configPath)).setScale(2, RoundingMode.HALF_UP); - } - return this.defaultVal; - } - - @Override - public Gui create() { - // Get value or default - BigDecimal now = getConfiguredValue(); - // create new gui - return new DoubleSettingGui(this, now, this.asPercentage, this.nullOnZero); - } - - - public GuiItem getItem(Material itemMat, String name){ - // Get item properties - BigDecimal value = getConfiguredValue(); - StringBuilder itemName = new StringBuilder("§a").append(name); - - return GuiGlobalItems.createGuiItemFromProperties(this, itemMat, itemName, - "§e" + displayValue(value, this.asPercentage), - this.displayLore, true); - } - - public GuiItem getItem(Material itemMat){ - // Get item properties - String configPath = GuiGlobalItems.getConfigNameFromPath(getConfigPath()); - - return getItem(itemMat, CasedStringUtil.detectToUpperSpacedCase(configPath)); - } - - } - -} \ No newline at end of file diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/EnchantCostSettingsGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/EnchantCostSettingsGui.java deleted file mode 100644 index 3bd923b..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/EnchantCostSettingsGui.java +++ /dev/null @@ -1,311 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.settings; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; -import com.github.stefvanschie.inventoryframework.pane.PatternPane; -import com.github.stefvanschie.inventoryframework.pane.util.Pattern; -import io.delilaheve.CustomAnvil; -import io.delilaheve.util.ConfigOptions; -import org.bukkit.Material; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.ItemFlag; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; -import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.function.Consumer; - -/** - * An instance of a gui used to edit an enchantment cost setting. - * May be considered as a 2 int setting. - */ -public class EnchantCostSettingsGui extends IntSettingsGui { - - protected final static String ITEM_PATH = ".item"; - protected final static String BOOK_PATH = ".book"; - - private int beforeBook; - private int nowBook; - - /** - * Create an enchantment cost setting config gui. - * - * @param holder Configuration factory of this setting. - * @param nowItem The defined value of this setting item's value. - */ - protected EnchantCostSettingsGui(EnchantCostSettingFactory holder, int nowItem) { - super(holder, nowItem); - - this.step = holder.steps[0]; - - initStaticItem(); - } - - /** - * Initialise step items. - * Also bypassed init sequence to initialise books value - * as it used as one of the first call from the init sequence of the gui - */ - @Override - protected void initStepsValue() { - super.initStepsValue(); - - int nowBook = ((EnchantCostSettingFactory) this.holder).getConfiguredBookValue(); - this.beforeBook = nowBook; - this.nowBook = nowBook; - } - - @Override - public Pattern getGuiPattern() { - return new Pattern( - "abc13-v+0", - "D0012MVP0", - "B0010000S" - ); - } - - /** - * Initialise item that should not be updated late. - */ - private void initStaticItem() { - PatternPane pane = getPane(); - - // book display - ItemStack bookItemstack = new ItemStack(Material.BOOK); - ItemMeta bookMeta = bookItemstack.getItemMeta(); - assert bookMeta != null; - - bookMeta.setDisplayName("§aCost of an Enchantment by Book"); - bookMeta.setLore(Arrays.asList( - "§7Cost per result item level of an sacrifice enchantment", - "§7Only apply if sacrificed item §cis §7a book")); - bookItemstack.setItemMeta(bookMeta); - - // sword display - ItemStack swordItemstack = new ItemStack(Material.WOODEN_SWORD); - ItemMeta swordMeta = swordItemstack.getItemMeta(); - assert swordMeta != null; - - swordMeta.addItemFlags(ItemFlag.values()); - swordMeta.setDisplayName("§aCost of an Enchantment by Item"); - swordMeta.setLore(Arrays.asList( - "§7Cost per result item level of an sacrifice enchantment", - "§7Only apply if sacrificed item §cis not §7a book")); - swordItemstack.setItemMeta(swordMeta); - - pane.bindItem('1', GuiGlobalItems.backgroundItem(Material.BLACK_STAINED_GLASS_PANE)); - pane.bindItem('2', new GuiItem(bookItemstack, GuiGlobalActions.stayInPlace, CustomAnvil.instance)); - pane.bindItem('3', new GuiItem(swordItemstack, GuiGlobalActions.stayInPlace, CustomAnvil.instance)); - } - - @Override - protected void prepareReturnToDefault() { - ItemStack item = new ItemStack(Material.COMMAND_BLOCK); - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - // assume holder is an instance of EnchantCostSettingFactory - EnchantCostSettingFactory holder = (EnchantCostSettingFactory) this.holder; - - meta.setDisplayName("§eReset to default value"); - meta.setLore(Arrays.asList( - "§7Default item value is: §e" + holder.defaultVal, - "§7Default book value is: §e" + holder.defaultBookVal)); - item.setItemMeta(meta); - returnToDefault = new GuiItem(item, event -> { - event.setCancelled(true); - nowBook = holder.defaultBookVal; - now = holder.defaultVal; - updateValueDisplay(); - update(); - }, CustomAnvil.instance); - } - - @Override - protected void updateValueDisplay() { - super.updateValueDisplay(); - PatternPane pane = getPane(); - - // assume holder is an instance of EnchantCostSettingFactory - EnchantCostSettingFactory holder = ((EnchantCostSettingFactory) this.holder); - - int nowBook = this.nowBook; - - // minus item - GuiItem minusItem; - if (nowBook > holder.min) { - int planned = Math.max(holder.min, nowBook - step); - ItemStack item = new ItemStack(Material.RED_TERRACOTTA); - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§e" + nowBook + " §f-> §e" + planned + " §r(§c-" + (nowBook - planned) + "§r)"); - meta.setLore(Collections.singletonList(AbstractSettingGui.CLICK_LORE)); - item.setItemMeta(meta); - - minusItem = new GuiItem(item, updateNowBookConsumer(planned), CustomAnvil.instance); - } else { - minusItem = GuiGlobalItems.backgroundItem(Material.BARRIER); - } - pane.bindItem('M', minusItem); - - //plus item - GuiItem plusItem; - if (nowBook < holder.max) { - int planned = Math.min(holder.max, nowBook + step); - ItemStack item = new ItemStack(Material.GREEN_TERRACOTTA); - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§e" + nowBook + " §f-> §e" + planned + " §r(§a+" + (planned - nowBook) + "§r)"); - meta.setLore(Collections.singletonList(AbstractSettingGui.CLICK_LORE)); - item.setItemMeta(meta); - - plusItem = new GuiItem(item, updateNowBookConsumer(planned), CustomAnvil.instance); - } else { - plusItem = GuiGlobalItems.backgroundItem(Material.BARRIER); - } - pane.bindItem('P', plusItem); - - // now value display - ItemStack nowPaper = new ItemStack(Material.PAPER); - ItemMeta nowMeta = nowPaper.getItemMeta(); - assert nowMeta != null; - - nowMeta.setDisplayName("§fValue: §e" + nowBook); - if(!holder.displayLore.isEmpty()){ - nowMeta.setLore(holder.displayLore); - } - - nowPaper.setItemMeta(nowMeta); - - GuiItem resultItem = new GuiItem(nowPaper, GuiGlobalActions.stayInPlace, CustomAnvil.instance); - - pane.bindItem('V', resultItem); - - // reset to default - GuiItem returnToDefault; - if (now != holder.defaultVal || nowBook != holder.defaultBookVal) { - returnToDefault = this.returnToDefault; - } else { - returnToDefault = GuiGlobalItems.backgroundItem(); - } - pane.bindItem('D', returnToDefault); - - - } - - /** - * @param planned Value to change current book cost setting to. - * @return A consumer to update the current book cost setting's value. - */ - protected Consumer updateNowBookConsumer(int planned) { - return event -> { - event.setCancelled(true); - nowBook = planned; - updateValueDisplay(); - update(); - }; - } - - @Override - protected char getMidStepChar() { - return 'b'; - } - - @Override - public boolean onSave() { - holder.config.getConfig().set(holder.configPath + ITEM_PATH, now); - holder.config.getConfig().set(holder.configPath + BOOK_PATH, nowBook); - - if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) { - return holder.config.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE); - } - return true; - } - - @Override - public boolean hadChange() { - return super.hadChange() || nowBook != beforeBook; - } - - /** - * A factory for an enchantment cost setting gui that hold setting's information. - */ - public static class EnchantCostSettingFactory extends IntSettingsGui.IntSettingFactory { - - int defaultBookVal; - @NotNull CAEnchantment enchantment; - - /** - * Constructor for an enchantment cost setting gui factory. - * - * @param title The title of the gui. - * @param parent Parent gui to go back when completed. - * @param configPath Configuration path of this setting. - * @param config Configuration holder of this setting. - * @param displayLore Gui display item lore. - * @param min Minimum value of this setting. - * @param max Maximum value of this setting. - * @param enchantment Enchantment to change the cost to - * @param steps List of step the value can increment/decrement. - * List's size should be between 1 (included) and 3 (included). - * it is visually preferable to have an odd number of step. - * If step only contain 1 value, no step item should be displayed. - */ - public EnchantCostSettingFactory( - @NotNull String title, ValueUpdatableGui parent, - @NotNull String configPath, @NotNull ConfigHolder config, - @Nullable List displayLore, - @NotNull CAEnchantment enchantment, - int min, int max, int... steps) { - - super(title, parent, - configPath, config, - displayLore, - min, max, enchantment.defaultRarity().getItemValue(), - steps); - - this.defaultBookVal = enchantment.defaultRarity().getBookValue(); - this.enchantment = enchantment; - } - - /** - * @return The configured value for the enchant setting item value. - */ - @Override - public int getConfiguredValue() { - return ConfigOptions.INSTANCE.enchantmentValue(enchantment, false); - } - - /** - * @return The configured value for the enchant setting book value. - */ - public int getConfiguredBookValue() { - return ConfigOptions.INSTANCE.enchantmentValue(enchantment, true); - } - - @Override - public Gui create() { - // Get value or default - int nowItem = getConfiguredValue(); - // create new gui - return new EnchantCostSettingsGui(this, nowItem); - } - - public List getDisplayLore() { - return this.displayLore; - } - } - -} \ No newline at end of file diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/EnchantSelectSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/EnchantSelectSettingGui.java deleted file mode 100644 index 176da55..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/EnchantSelectSettingGui.java +++ /dev/null @@ -1,217 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.settings; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; -import com.github.stefvanschie.inventoryframework.pane.util.Pattern; -import io.delilaheve.CustomAnvil; -import org.bukkit.Material; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.ItemFlag; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; -import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry; -import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; -import xyz.alexcrea.cuanvil.gui.config.MainConfigGui; -import xyz.alexcrea.cuanvil.gui.config.SelectEnchantmentContainer; -import xyz.alexcrea.cuanvil.gui.config.list.SettingGuiListConfigGui; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; -import xyz.alexcrea.cuanvil.util.CasedStringUtil; - -import java.util.*; -import java.util.function.Consumer; -import java.util.stream.Stream; - -public class EnchantSelectSettingGui extends SettingGuiListConfigGui implements SettingGui { - - private final SelectEnchantmentContainer enchantContainer; - - private final Set selectedEnchant; - private final GuiItem saveItem; - - private boolean displayUnselected; - - public EnchantSelectSettingGui(@NotNull String title, ValueUpdatableGui parent, SelectEnchantmentContainer enchantContainer) { - super(title, parent instanceof Gui parentGui ? parentGui : MainConfigGui.getInstance()) ; - this.enchantContainer = enchantContainer; - - this.selectedEnchant = new HashSet<>(enchantContainer.getSelectedEnchantments()); - - this.saveItem = GuiGlobalItems.saveItem(this, parent); - this.backgroundPane.bindItem('S', GuiGlobalItems.noChangeItem()); - - this.displayUnselected = true; - this.backgroundPane.bindItem('b', createDisplayUnusedItem()); - - init(); - } - - @Override - protected Pattern getBackgroundPattern() { - return new Pattern( - GuiSharedConstant.UPPER_FILLER_FULL_PLANE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - "B11LbR11S" - ); - } - - @Override - protected Collection getEveryDisplayableInstanceOfGeneric() { - Stream toDisplayStream; - if(this.displayUnselected){ - toDisplayStream = CAEnchantmentRegistry.getInstance().getNameSortedEnchantments().stream(); - }else{ - toDisplayStream = this.selectedEnchant.stream().sorted(Comparator.comparing(CAEnchantment::getName)); - } - Set illegalEnchantments = this.enchantContainer.illegalEnchantments(); - - - return toDisplayStream - .filter(enchantment -> !illegalEnchantments.contains(enchantment)) - .toList(); - } - - @Override - public void update() { - this.backgroundPane.bindItem('S', hadChange() ? saveItem : GuiGlobalItems.noChangeItem()); - super.update(); - } - - @Override - protected GuiItem itemFromFactory(CAEnchantment enchantment, DummyFactory factory) { - boolean isIn = this.selectedEnchant.contains(enchantment); - - Material usedMaterial; - if (isIn) { - usedMaterial = Material.ENCHANTED_BOOK; - } else { - usedMaterial = Material.BOOK; - } - ItemStack item = new ItemStack(usedMaterial); - - setEnchantItemMeta(item, enchantment.getKey().getKey(), isIn); - - GuiItem guiItem = new GuiItem(item, CustomAnvil.instance); - guiItem.setAction(getEnchantItemConsumer(enchantment, guiItem)); - return guiItem; - } - - private GuiItem createDisplayUnusedItem() { - ItemStack item = new ItemStack(this.displayUnselected ? Material.BOOK : Material.ENCHANTED_BOOK); - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName((this.displayUnselected ? "§aEverything displayed" : "§eOnly selected displayed")); - meta.setLore(Collections.singletonList( - "§7Click here to see " + - (this.displayUnselected ? "only selected" : "every") + - " enchantments")); - - item.setItemMeta(meta); - - return new GuiItem(item, clickEvent -> { - clickEvent.setCancelled(true); - this.displayUnselected = !this.displayUnselected; - - this.backgroundPane.bindItem('b', createDisplayUnusedItem()); - reloadValues(); - }, CustomAnvil.instance); - } - - private static final List TRUE_LORE = Collections.singletonList("§7Value: §aSelected"); - private static final List FALSE_LORE = Collections.singletonList("§7Value: §cNot Selected"); - - public void setEnchantItemMeta(ItemStack item, String name, boolean isIn) { - ItemMeta meta = item.getItemMeta(); - - if (meta == null) { - CustomAnvil.instance.getLogger().warning("Could not create item for enchantment: " + name + ":\n" + - "Item do not gave item meta: " + item + ". Using a placeholder item instead"); - item.setType(Material.PAPER); - meta = item.getItemMeta(); - assert meta != null; - } - - meta.setDisplayName("§" + (isIn ? 'a' : 'c') + CasedStringUtil.snakeToUpperSpacedCase(name)); - if (isIn) { - meta.addEnchant(Enchantment.DAMAGE_UNDEAD, 1, true); - meta.setLore(TRUE_LORE); - } else { - meta.removeEnchant(Enchantment.DAMAGE_UNDEAD); - meta.setLore(FALSE_LORE); - } - meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_ENCHANTS); - - item.setItemMeta(meta); - } - - private Consumer getEnchantItemConsumer(CAEnchantment enchant, GuiItem guiItem) { - return event -> { - event.setCancelled(true); - - ItemStack item = guiItem.getItem(); - - boolean isIn = this.selectedEnchant.contains(enchant); - if (isIn) { - this.selectedEnchant.remove(enchant); - item.setType(Material.BOOK); - } else { - this.selectedEnchant.add(enchant); - item.setType(Material.ENCHANTED_BOOK); - } - - setEnchantItemMeta(item, enchant.getKey().getKey(), !isIn); - guiItem.setItem(item);// Just in case - - update(); - }; - } - - @Override - public boolean onSave() { - return this.enchantContainer.setSelectedEnchantments(this.selectedEnchant); - } - - @Override - public boolean hadChange() { - Set baseGroup = this.enchantContainer.getSelectedEnchantments(); - return baseGroup.size() != this.selectedEnchant.size() || - !baseGroup.containsAll(this.selectedEnchant); - } - - - // Unused methods and class - public static class DummyFactory extends AbstractSettingGui.SettingGuiFactory{ - protected DummyFactory(@NotNull String configPath, @NotNull ConfigHolder config) { - super(configPath, config); - } - @Override - public Gui create() { - return null; - } - } - @Override - protected List getCreateItemLore() { - return Collections.emptyList(); - } - @Override - protected Consumer getCreateClickConsumer() { - return null; - } - @Override - protected String createItemName() { - return null; - } - @Override - protected DummyFactory createFactory(CAEnchantment generic) { - return null; - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/EnumSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/EnumSettingGui.java deleted file mode 100644 index 5bf4c24..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/EnumSettingGui.java +++ /dev/null @@ -1,242 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.settings; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; -import com.github.stefvanschie.inventoryframework.pane.PatternPane; -import com.github.stefvanschie.inventoryframework.pane.util.Pattern; -import io.delilaheve.CustomAnvil; -import org.bukkit.Material; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.ItemFlag; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; - -import java.util.Collections; -import java.util.List; -import java.util.function.Consumer; - -public class EnumSettingGui & EnumSettingGui.ConfigurableEnum> extends AbstractSettingGui { - - private final EnumSettingFactory holder; - private final T before; - private T now; - - /** - * Create an item setting config gui. - * - * @param holder Configuration factory of this setting. - * @param now The defined value of this setting. - */ - protected EnumSettingGui(EnumSettingFactory holder, T now) { - super(3, holder.getTitle(), holder.parent); - this.holder = holder; - this.before = now; - this.now = now; - - prepareStaticItems(); - updateValueDisplay(); - } - - @Override - public Pattern getGuiPattern() { - return new Pattern( - GuiSharedConstant.EMPTY_GUI_FULL_LINE, - "D000v0000", - "B0000000S" - ); - } - - - public void prepareStaticItems(){ - prepareReturnToDefault(); - } - - - protected GuiItem returnToDefault; - - /** - * Prepare "return to default value" gui item. - */ - protected void prepareReturnToDefault() { - ItemStack item = new ItemStack(Material.COMMAND_BLOCK); - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§eReset to default value"); - meta.setLore(Collections.singletonList("§7Default value is §e" + holder.getDefault().configurationGuiName())); - item.setItemMeta(meta); - returnToDefault = new GuiItem(item, event -> { - event.setCancelled(true); - now = holder.getDefault(); - updateValueDisplay(); - update(); - }, CustomAnvil.instance); - } - - /** - * Update item using the setting value to match the new value - */ - protected void updateValueDisplay() { - PatternPane pane = getPane(); - - // Get displayed value for this config. - ItemStack displayedItem = now.configurationGuiItem(); - - GuiItem resultItem = new GuiItem(displayedItem, selectNext(), CustomAnvil.instance); - pane.bindItem('v', resultItem); - - // reset to default - GuiItem returnToDefault; - if (now != holder.getDefault()) { - returnToDefault = this.returnToDefault; - } else { - returnToDefault = GuiGlobalItems.backgroundItem(); - } - pane.bindItem('D', returnToDefault); - - } - - /** - * @return A consumer to update the current setting's value. - */ - protected Consumer selectNext() { - return event -> { - event.setCancelled(true); - - this.now = this.holder.next(this.now); - - updateValueDisplay(); - update(); - }; - - } - - @Override - public boolean onSave() { - holder.config.getConfig().set(holder.configPath, this.now.configName()); - - if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) { - return holder.config.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE); - } - return true; - } - - @Override - public boolean hadChange() { - return !now.equals(before); - } - - - /** - * A factory for an enum setting gui that hold setting's information. - */ - public abstract static class EnumSettingFactory & ConfigurableEnum> extends SettingGuiFactory { - @NotNull - String title; - @NotNull - ValueUpdatableGui parent; - - /** - * Constructor for an enum settings gui factory - * - * @param title The title of the gui. - * @param parent Parent gui to go back when completed. - * @param configPath Configuration path of this setting. - * @param config Configuration holder of this setting. - */ - protected EnumSettingFactory( - @NotNull String title, @NotNull ValueUpdatableGui parent, - @NotNull String configPath, @NotNull ConfigHolder config) { - super(configPath, config); - this.title = title; - this.parent = parent; - - } - /** - * @return Get setting's gui title. - */ - @NotNull - public String getTitle() { - return title; - } - - /** - * @return The configured value for the associated setting. - */ - @NotNull - public abstract T getConfiguredValue(); - - @NotNull - public abstract List getDisplayLore(T value); - - /** - * @return Next value for a given enum - */ - @NotNull - public T next(@NotNull T now){ - Class clazz = now.getDeclaringClass(); - T[] values = clazz.getEnumConstants(); - - int index = now.ordinal(); - if(index == values.length - 1) - return values[0]; - - return values[index + 1]; - } - - /** - * Get default value value - * @return default value - */ - @NotNull - public abstract T getDefault(); - - @Override - public Gui create() { - // Get value or default - T now = getConfiguredValue(); - - // create new gui - return new EnumSettingGui<>(this, now); - } - - /** - * Create a new enum setting GuiItem. - * This item will create and open an enum setting GUI from the factory. - * - * @param name Name of the display. - * @return A formatted GuiItem that will create and open a GUI for the enum setting. - */ - public GuiItem getItem(@NotNull Material material, @NotNull String name) { - T value = getConfiguredValue(); - - ItemStack item = new ItemStack(material); - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName(name); - meta.setLore(getDisplayLore(value)); - meta.addItemFlags(ItemFlag.values()); - - item.setItemMeta(meta); - - return GuiGlobalItems.openSettingGuiItem(item, this); - } - } - - public interface ConfigurableEnum { - - String configName(); - - ItemStack configurationGuiItem(); - String configurationGuiName(); - - - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/GroupSelectSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/GroupSelectSettingGui.java deleted file mode 100644 index 69986a0..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/GroupSelectSettingGui.java +++ /dev/null @@ -1,157 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.settings; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.pane.Orientable; -import com.github.stefvanschie.inventoryframework.pane.OutlinePane; -import com.github.stefvanschie.inventoryframework.pane.Pane; -import com.github.stefvanschie.inventoryframework.pane.util.Pattern; -import io.delilaheve.CustomAnvil; -import org.bukkit.Material; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.ItemFlag; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.group.AbstractMaterialGroup; -import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; -import xyz.alexcrea.cuanvil.gui.config.SelectGroupContainer; -import xyz.alexcrea.cuanvil.gui.config.list.ElementListConfigGui; -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; -import xyz.alexcrea.cuanvil.util.CasedStringUtil; - -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.function.Consumer; - -public class GroupSelectSettingGui extends AbstractSettingGui { - - SelectGroupContainer groupContainer; - int page; - - Set selectedGroups; - - public GroupSelectSettingGui(@NotNull String title, ValueUpdatableGui parent, SelectGroupContainer groupContainer, int page) { - super(6, title, parent); - this.groupContainer = groupContainer; - //Not used but planned - this.page = page; - - this.selectedGroups = new HashSet<>(groupContainer.getSelectedGroups()); - - // Add secondary background item - this.getPane().bindItem('1', GuiSharedConstant.SECONDARY_BACKGROUND_ITEM); - - initGroups(); - } - - @Override - protected Pattern getGuiPattern() { - return new Pattern( - GuiSharedConstant.UPPER_FILLER_FULL_PLANE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - "B1111111S" - ); - } - - protected void initGroups() { - // Add enchantment gui item - OutlinePane filledEnchant = new OutlinePane( - ElementListConfigGui.LIST_FILLER_START_X, - ElementListConfigGui.LIST_FILLER_START_Y, - ElementListConfigGui.LIST_FILLER_LENGTH, - ElementListConfigGui.LIST_FILLER_HEIGHT); - filledEnchant.setPriority(Pane.Priority.HIGH); - filledEnchant.align(OutlinePane.Alignment.BEGIN); - filledEnchant.setOrientation(Orientable.Orientation.HORIZONTAL); - - Set illegalGroup = this.groupContainer.illegalGroups(); - for (AbstractMaterialGroup group : ConfigHolder.ITEM_GROUP_HOLDER.getItemGroupsManager().getGroupMap().values()) { - if (illegalGroup.contains(group)) { - continue; - } - filledEnchant.addItem(getGuiItemFromGroup(group)); - } - - addPane(filledEnchant); - - } - - private GuiItem getGuiItemFromGroup(AbstractMaterialGroup group) { - boolean isIn = this.selectedGroups.contains(group); - - Material usedMaterial = group.getRepresentativeMaterial(); - ItemStack item = new ItemStack(usedMaterial); - - setGroupItemMeta(item, group.getName(), isIn); - - GuiItem guiItem = new GuiItem(item, CustomAnvil.instance); - guiItem.setAction(getGroupItemConsumer(group, guiItem)); - return guiItem; - } - - private static final List TRUE_LORE = Collections.singletonList("§7Value: §aSelected"); - private static final List FALSE_LORE = Collections.singletonList("§7Value: §cNot Selected"); - - public void setGroupItemMeta(ItemStack item, String name, boolean isIn) { - ItemMeta meta = item.getItemMeta(); - - if (meta == null) { - CustomAnvil.instance.getLogger().warning("Could not create item for group: " + name + ":\n" + - "Item do not gave item meta: " + item + ". Using placeholder instead"); - item.setType(Material.PAPER); - meta = item.getItemMeta(); - assert meta != null; - } - - meta.setDisplayName("§" + (isIn ? 'a' : 'c') + CasedStringUtil.snakeToUpperSpacedCase(name)); - if (isIn) { - meta.addEnchant(Enchantment.DAMAGE_UNDEAD, 1, true); - meta.setLore(TRUE_LORE); - } else { - meta.removeEnchant(Enchantment.DAMAGE_UNDEAD); - meta.setLore(FALSE_LORE); - } - meta.addItemFlags(ItemFlag.values()); - - item.setItemMeta(meta); - } - - private Consumer getGroupItemConsumer(AbstractMaterialGroup group, GuiItem guiItem) { - return event -> { - event.setCancelled(true); - - boolean isIn = this.selectedGroups.contains(group); - if (isIn) { - this.selectedGroups.remove(group); - } else { - this.selectedGroups.add(group); - } - - ItemStack item = guiItem.getItem(); - setGroupItemMeta(item, group.getName(), !isIn); - guiItem.setItem(item);// Just in case - - update(); - }; - } - - @Override - public boolean onSave() { - return this.groupContainer.setSelectedGroups(this.selectedGroups); - } - - @Override - public boolean hadChange() { - Set baseGroup = this.groupContainer.getSelectedGroups(); - return baseGroup.size() != this.selectedGroups.size() || - !baseGroup.containsAll(this.selectedGroups); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/IntSettingsGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/IntSettingsGui.java deleted file mode 100644 index 73121a6..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/IntSettingsGui.java +++ /dev/null @@ -1,409 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.settings; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; -import com.github.stefvanschie.inventoryframework.pane.PatternPane; -import com.github.stefvanschie.inventoryframework.pane.util.Pattern; -import io.delilaheve.CustomAnvil; -import org.bukkit.Material; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; -import xyz.alexcrea.cuanvil.util.CasedStringUtil; - -import java.util.Collections; -import java.util.List; -import java.util.function.Consumer; - -/** - * An instance of a gui used to edit an int setting. - */ -public class IntSettingsGui extends AbstractSettingGui { - - protected final IntSettingFactory holder; - protected final int before; - protected int now; - protected int step; - - /** - * Create an int setting config gui. - * - * @param holder Configuration factory of this setting. - * @param now The defined value of this setting. - */ - protected IntSettingsGui(IntSettingFactory holder, int now) { - super(3, holder.getTitle(), holder.parent); - assert holder.steps.length > 0 && holder.steps.length <= 9; - this.holder = holder; - this.before = now; - this.now = now; - this.step = holder.steps[0]; - - initStepsValue(); - prepareReturnToDefault(); - updateValueDisplay(); - } - - - @Override - public Pattern getGuiPattern() { - return new Pattern( - "abcdefghi", - "D0-0v0+00", - "B0000000S" - ); - } - - protected GuiItem returnToDefault; - - /** - * Prepare "return to default value" gui item. - */ - protected void prepareReturnToDefault() { - ItemStack item = new ItemStack(Material.COMMAND_BLOCK); - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§eReset to default value"); - meta.setLore(Collections.singletonList("§7Default value is §e" + - holder.valueDisplayName(ValueDisplayType.RESET, holder.defaultVal))); - item.setItemMeta(meta); - returnToDefault = new GuiItem(item, event -> { - event.setCancelled(true); - now = holder.defaultVal; - updateValueDisplay(); - update(); - }, CustomAnvil.instance); - } - - /** - * Update item using the setting value to match the new value. - */ - protected void updateValueDisplay() { - PatternPane pane = getPane(); - - // minus item - GuiItem minusItem; - if (now > holder.min) { - int planned = Math.max(holder.min, now - step); - minusItem = valueEditItem(Material.RED_TERRACOTTA, ValueDisplayType.REMOVE, planned); - } else { - minusItem = GuiGlobalItems.backgroundItem(Material.BARRIER); - } - pane.bindItem('-', minusItem); - - //plus item - GuiItem plusItem; - if (now < holder.max) { - int planned = Math.min(holder.max, now + step); - plusItem = valueEditItem(Material.GREEN_TERRACOTTA, ValueDisplayType.ADD, planned); - } else { - plusItem = GuiGlobalItems.backgroundItem(Material.BARRIER); - } - pane.bindItem('+', plusItem); - - // "result" display - ItemStack resultPaper = new ItemStack(Material.PAPER); - ItemMeta resultMeta = resultPaper.getItemMeta(); - assert resultMeta != null; - - resultMeta.setDisplayName("§fValue: §e" + holder.valueDisplayName(ValueDisplayType.CURRENT, now)); - resultMeta.setLore(holder.displayLore); - - resultPaper.setItemMeta(resultMeta); - - GuiItem resultItem = new GuiItem(resultPaper, GuiGlobalActions.stayInPlace, CustomAnvil.instance); - - pane.bindItem('v', resultItem); - - // reset to default - GuiItem returnToDefault; - if (now != holder.defaultVal) { - returnToDefault = this.returnToDefault; - } else { - returnToDefault = GuiGlobalItems.backgroundItem(); - } - pane.bindItem('D', returnToDefault); - - } - - private GuiItem valueEditItem(Material mat, ValueDisplayType type, int planned) { - ItemStack item = new ItemStack(mat); - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - var nowDisplay = holder.valueDisplayName(type, now); - var plannedDisplay = holder.valueDisplayName(type, planned); - var deltaDisplay = holder.deltaDisplay(type, now, planned); - meta.setDisplayName("§e" + nowDisplay + " §f-> §e" + plannedDisplay + " §r(§c" + deltaDisplay + "§r)"); - - meta.setLore(Collections.singletonList(AbstractSettingGui.CLICK_LORE)); - item.setItemMeta(meta); - return new GuiItem(item, updateNowConsumer(planned), CustomAnvil.instance); - } - - /** - * @param planned Value to change current setting to. - * @return A consumer to update the current setting's value. - */ - protected Consumer updateNowConsumer(int planned) { - return event -> { - event.setCancelled(true); - now = planned; - updateValueDisplay(); - update(); - }; - } - - /** - * Initialise step items. - */ - protected void initStepsValue() { - // Put background glass on the background of 'a' to 'b' - GuiItem background = GuiGlobalItems.backgroundItem(); - PatternPane pane = getPane(); - - for (char i = 'a'; i < (getMidStepChar() - 'a') * 2 + 1; i++) { - pane.bindItem(i, background); - } - // Then update legit step values - updateStepValue(); - } - - /** - * Update steps items value. - */ - protected void updateStepValue() { - if (holder.steps.length <= 1) return; - // We assume steps have a length of 2k+1 cause its more pretty - char val = getMidStepChar(); - // Offset to start (not the best way to do it) - val -= (char) ((holder.steps.length - 1) / 2); - - // Then place items - PatternPane pane = getPane(); - for (int i = 0; i < holder.steps.length; i++) { - pane.bindItem(val + i, stepGuiItem(i)); - } - - } - - /** - * Step use lower case character from 'a' to a certain char. - * - * @return The middle value of the character set for steps. - */ - protected char getMidStepChar() { - return 'e'; - } - - /** - * Create a step item from a step value. - * - * @param stepIndex the index of the step item. - * @return A step item corresponding to its index value. - */ - protected GuiItem stepGuiItem(int stepIndex) { - int stepValue = holder.steps[stepIndex]; - - // Get material properties - Material stepMat; - StringBuilder stepName = new StringBuilder("§"); - List stepLore; - Consumer clickEvent; - if (stepValue == step) { - stepMat = Material.GREEN_STAINED_GLASS_PANE; - stepName.append('a'); - stepLore = Collections.singletonList("§7Value is changing by " + stepValue); - clickEvent = GuiGlobalActions.stayInPlace; - } else { - stepMat = Material.RED_STAINED_GLASS_PANE; - stepName.append('c'); - stepLore = Collections.singletonList("§7Click here to change the value by " + stepValue); - clickEvent = updateStepValue(stepValue); - } - stepName.append("Step of: §e").append(stepValue); - - // Create item stack then gui item - ItemStack item = new ItemStack(stepMat); - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName(stepName.toString()); - meta.setLore(stepLore); - item.setItemMeta(meta); - - return new GuiItem(item, clickEvent, CustomAnvil.instance); - } - - /** - * @param stepValue Value to change current step to. - * @return A consumer to update the current step of this setting. - */ - protected Consumer updateStepValue(int stepValue) { - return event -> { - event.setCancelled(true); - this.step = stepValue; - updateStepValue(); - updateValueDisplay(); - update(); - }; - } - - @Override - public boolean onSave() { - holder.config.getConfig().set(holder.configPath, now); - - if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) { - return holder.config.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE); - } - return true; - } - - @Override - public boolean hadChange() { - return now != before; - } - - /** - * A factory for an int setting gui that hold setting's information. - */ - public static class IntSettingFactory extends SettingGuiFactory { - - @NotNull - String title; - @NotNull - ValueUpdatableGui parent; - int min; - int max; - int defaultVal; - int[] steps; - - @NotNull - List displayLore; - - /** - * Constructor for an int setting gui factory. - * - * @param title The title of the gui. - * @param parent Parent gui to go back when completed. - * @param configPath Configuration path of this setting. - * @param config Configuration holder of this setting. - * @param displayLore Gui display item lore. - * @param min Minimum value of this setting. - * @param max Maximum value of this setting. - * @param defaultVal Default value if not found on the config. - * @param steps List of step the value can increment/decrement. - * List's size should be between 1 (included) and 5 (included). - * it is visually preferable to have an odd number of step. - * If step only contain 1 value, no step item should be displayed. - */ - public IntSettingFactory( - @NotNull String title, @NotNull ValueUpdatableGui parent, - @NotNull String configPath, @NotNull ConfigHolder config, - @Nullable List displayLore, - int min, int max, int defaultVal, int... steps) { - super(configPath, config); - this.title = title; - this.parent = parent; - this.min = min; - this.max = max; - this.defaultVal = defaultVal; - this.steps = steps; - - if(displayLore == null){ - this.displayLore = Collections.emptyList(); - }else { - this.displayLore = displayLore; - } - } - - /** - * @return Get setting's gui title - */ - @NotNull - public String getTitle() { - return title; - } - - /** - * @return The configured value for the associated setting. - */ - public int getConfiguredValue() { - return this.config.getConfig().getInt(this.configPath, this.defaultVal); - } - - @Override - public Gui create() { - // Get value or default - int now = getConfiguredValue(); - // create new gui - return new IntSettingsGui(this, now); - } - - /** - * Create a new int setting GuiItem. - * This item will create and open an int setting GUI from the factory. - * The item will have its value written in the lore part of the item. - * - * @param itemMat Displayed material of the item. - * @param name Name of the item. - * @return A formatted GuiItem that will create and open a GUI for the int setting. - */ - public GuiItem getItem( - @NotNull Material itemMat, - @NotNull String name - ) { - // Get item properties - int value = getConfiguredValue(); - StringBuilder itemName = new StringBuilder("§a").append(name); - - return GuiGlobalItems.createGuiItemFromProperties(this, itemMat, itemName, - "§e" + value, - this.displayLore, true); - } - - /** - * Create a new int setting GuiItem. - * This item will create and open an int setting GUI from the factory. - * The item will have its value written in the lore part of the item. - * Item's name will be the factory set title. - * - * @param itemMat Displayed material of the item. - * @return A formatted GuiItem that will create and open a GUI for the int setting. - */ - public GuiItem getItem( - @NotNull Material itemMat - ) { - String configPath = GuiGlobalItems.getConfigNameFromPath(getConfigPath()); - return getItem(itemMat, CasedStringUtil.detectToUpperSpacedCase(configPath)); - } - - protected String valueDisplayName(ValueDisplayType type, int value) { - return String.valueOf(value); - } - - protected String deltaDisplay(ValueDisplayType type, int now, int planned) { - var delta = planned - now; - if(delta < 0) return "§c" + delta; - else return "§a+" + delta; - } - - } - - public enum ValueDisplayType { - ADD, - CURRENT, - REMOVE, - RESET, - } - -} - diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/ItemSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/ItemSettingGui.java deleted file mode 100644 index 3df2af8..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/ItemSettingGui.java +++ /dev/null @@ -1,270 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.settings; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; -import com.github.stefvanschie.inventoryframework.pane.PatternPane; -import com.github.stefvanschie.inventoryframework.pane.util.Pattern; -import io.delilaheve.CustomAnvil; -import org.bukkit.Material; -import org.bukkit.entity.HumanEntity; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.ItemFlag; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; -import xyz.alexcrea.cuanvil.util.CasedStringUtil; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.function.Consumer; - -/** - * An instance of a gui used to edit an item setting. - */ -public class ItemSettingGui extends AbstractSettingGui { - - private final ItemSettingFactory holder; - private final ItemStack before; - private ItemStack now; - - /** - * Create an item setting config gui. - * - * @param holder Configuration factory of this setting. - * @param now The defined value of this setting. - */ - protected ItemSettingGui(ItemSettingFactory holder, ItemStack now) { - super(3, holder.getTitle(), holder.parent); - this.holder = holder; - this.before = now; - this.now = now; - - prepareStaticItems(); - updateValueDisplay(); - } - - @Override - public Pattern getGuiPattern() { - return new Pattern( - GuiSharedConstant.EMPTY_GUI_FULL_LINE, - "D0-0v0+0s", - "B0000000S" - ); - } - - - public void prepareStaticItems(){ - prepareReturnToDefault(); - - GuiItem temporaryLeave = GuiGlobalItems.temporaryCloseGuiToSelectItem(Material.YELLOW_STAINED_GLASS_PANE, this); - getPane().bindItem('s', temporaryLeave); - } - - - protected GuiItem returnToDefault; - - /** - * Prepare "return to default value" gui item. - */ - protected void prepareReturnToDefault() { - ItemStack item = new ItemStack(Material.COMMAND_BLOCK); - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§eReset to default value"); - meta.setLore(Collections.singletonList("§7Default value is §e" + holder.defaultVal)); - item.setItemMeta(meta); - returnToDefault = new GuiItem(item, event -> { - event.setCancelled(true); - now = holder.defaultVal; - updateValueDisplay(); - update(); - }, CustomAnvil.instance); - } - - protected final static List CLICK_LORE = Collections.singletonList("§7Click Here with an item to change the value"); - - /** - * Update item using the setting value to match the new value - */ - protected void updateValueDisplay() { - PatternPane pane = getPane(); - - // Get displayed value for this config. - ItemStack displayedItem; - if(this.now != null){ - displayedItem = this.now.clone(); - }else{ - displayedItem = new ItemStack(Material.BARRIER); - ItemMeta valueMeta = displayedItem.getItemMeta(); - assert valueMeta != null; - - valueMeta.setDisplayName("§4NO ITEM SET"); - valueMeta.setLore(CLICK_LORE); - - displayedItem.setItemMeta(valueMeta); - } - - GuiItem resultItem = new GuiItem(displayedItem, setItemAsCursor(), CustomAnvil.instance); - pane.bindItem('v', resultItem); - - // reset to default - GuiItem returnToDefault; - if (now != holder.defaultVal) { - returnToDefault = this.returnToDefault; - } else { - returnToDefault = GuiGlobalItems.backgroundItem(); - } - pane.bindItem('D', returnToDefault); - - } - - /** - * @return A consumer to update the current setting's value. - */ - protected Consumer setItemAsCursor() { - return event -> { - event.setCancelled(true); - - HumanEntity player = event.getWhoClicked(); - ItemStack cursor = player.getItemOnCursor(); - - if(cursor.getType().isAir()) return; - - this.now = cursor; - - updateValueDisplay(); - update(); - }; - } - - @Override - public boolean onSave() { - holder.config.getConfig().set(holder.configPath, this.now); - - if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) { - return holder.config.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE); - } - return true; - } - - @Override - public boolean hadChange() { - if(now == null) { - return before != null; - } - - return !now.equals(before); - } - - /** - * A factory for an item setting gui that hold setting's information. - */ - public static class ItemSettingFactory extends SettingGuiFactory { - @NotNull - String title; - @NotNull - ValueUpdatableGui parent; - @Nullable - ItemStack defaultVal; - @NotNull - List displayLore; - - /** - * Constructor for an item setting gui factory. - * - * @param title The title of the gui. - * @param parent Parent gui to go back when completed. - * @param configPath Configuration path of this setting. - * @param config Configuration holder of this setting. - * @param defaultVal Default value if not found on the config. - * @param displayLore Gui display item lore. - */ - public ItemSettingFactory( - @NotNull String title, @NotNull ValueUpdatableGui parent, - @NotNull String configPath, @NotNull ConfigHolder config, - @Nullable ItemStack defaultVal, - String... displayLore) { - super(configPath, config); - this.title = title; - this.parent = parent; - - this.defaultVal = defaultVal; - this.displayLore = Arrays.asList(displayLore); - } - - /** - * @return Get setting's gui title. - */ - @NotNull - public String getTitle() { - return title; - } - - /** - * @return The configured value for the associated setting. - */ - public ItemStack getConfiguredValue() { - return this.config.getConfig().getItemStack(this.configPath, this.defaultVal); - } - - @NotNull - public List getDisplayLore() { - return this.displayLore; - } - - @Override - public Gui create() { - // Get current value or default - ItemStack now = getConfiguredValue(); - // create new gui - return new ItemSettingGui(this, now); - } - - /** - * Create a new item setting GuiItem. - * This item will create and open an item setting GUI from the factory. - * Item's name will be the factory set title. - * - * @param name Name of the item. - * @return A formatted GuiItem that will create and open a GUI for the item setting. - */ - public GuiItem getItem(@NotNull String name) { - ItemStack item = getConfiguredValue(); - if(item == null || item.getType().isAir()){ - item = new ItemStack(Material.BARRIER); - }else{ - item = item.clone(); - } - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§a" + name); - meta.setLore(getDisplayLore()); - meta.addItemFlags(ItemFlag.values()); - - item.setItemMeta(meta); - - return GuiGlobalItems.openSettingGuiItem(item, this); - } - - /** - * Create a new item setting GuiItem. - * This item will create and open an item setting GUI from the factory. - * Item's name will be the factory set title. - * - * @return A formatted GuiItem that will create and open a GUI for the item setting. - */ - public GuiItem getItem() { - String configPath = GuiGlobalItems.getConfigNameFromPath(getConfigPath()); - return getItem(CasedStringUtil.detectToUpperSpacedCase(configPath)); - } - - } -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/MaterialSelectSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/MaterialSelectSettingGui.java deleted file mode 100644 index fc519ff..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/MaterialSelectSettingGui.java +++ /dev/null @@ -1,309 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.settings; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; -import com.github.stefvanschie.inventoryframework.pane.util.Pattern; -import io.delilaheve.CustomAnvil; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.entity.HumanEntity; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.ItemFlag; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.gui.config.SelectMaterialContainer; -import xyz.alexcrea.cuanvil.gui.config.ask.ConfirmActionGui; -import xyz.alexcrea.cuanvil.gui.config.list.MappedElementListConfigGui; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; -import xyz.alexcrea.cuanvil.util.CasedStringUtil; -import xyz.alexcrea.cuanvil.util.MaterialUtil; - -import java.util.*; -import java.util.function.Consumer; - -public class MaterialSelectSettingGui extends MappedElementListConfigGui { - - private final SelectMaterialContainer selector; - private final Gui backGui; - private boolean instantRemove; - - private final List defaultMaterials; - private final Set illegalMaterials; - private final int defaultMaterialHash; - private int nowMaterialHash; - - public MaterialSelectSettingGui( - @NotNull SelectMaterialContainer selector, - @NotNull String title, - @NotNull Gui backGui) { - super(title); - this.selector = selector; - this.backGui = backGui; - this.instantRemove = false; - - this.defaultMaterials = new ArrayList<>(this.selector.getSelectedMaterials()); - this.illegalMaterials = this.selector.illegalMaterials(); - - this.defaultMaterialHash = hashFromMaterialList(this.defaultMaterials); - this.nowMaterialHash = this.defaultMaterialHash; - - init(); - - // Change back item - this.backgroundPane.bindItem('B', GuiGlobalItems.backItem(backGui)); - } - - @Override - protected Pattern getBackgroundPattern(){ - return new Pattern( - GuiSharedConstant.UPPER_FILLER_FULL_PLANE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - "BT1LAR1IS" - ); - } - - private GuiItem saveItem; - private GuiItem noChangeItem; - - private GuiItem instantRemoveOn; - private GuiItem instantRemoveOff; - - @Override - protected void prepareStaticValues() { - super.prepareStaticValues(); - - // Temporary leave item - GuiItem temporaryLeave = GuiGlobalItems.temporaryCloseGuiToSelectItem(Material.YELLOW_STAINED_GLASS_PANE, this); - this.backgroundPane.bindItem('T', temporaryLeave); - - // Select new mat item - ItemStack selectItem = new ItemStack(Material.BLUE_STAINED_GLASS_PANE); - ItemMeta selectMeta = selectItem.getItemMeta(); - assert selectMeta != null; - - selectMeta.setDisplayName("§aAdd Item"); - selectMeta.setLore(Arrays.asList( - "§7Click here with an item to add", - "§7it's Material to the list.")); - - selectItem.setItemMeta(selectMeta); - - this.backgroundPane.bindItem('A', new GuiItem(selectItem, setItemAsCursor(), CustomAnvil.instance)); - - // Save item - this.saveItem = prepareSaveItem(); - - this.noChangeItem = GuiGlobalItems.noChangeItem(); - this.backgroundPane.bindItem('S', this.noChangeItem); - - // Instant Remove On item - ItemStack instantRemoveOnItem = new ItemStack(Material.LIME_STAINED_GLASS_PANE); - ItemMeta instantRemoveOnMeta = instantRemoveOnItem.getItemMeta(); - assert instantRemoveOnMeta != null; - - instantRemoveOnMeta.setDisplayName("§eInstant remove is §aEnabled §e!"); - instantRemoveOnMeta.setLore( - Collections.singletonList("§7Click here to disable the instant remove")); - - instantRemoveOnItem.setItemMeta(instantRemoveOnMeta); - - // Instant Remove Off item - ItemStack instantRemoveOffItem = new ItemStack(Material.RED_STAINED_GLASS_PANE); - ItemMeta instantRemoveOffMeta = instantRemoveOffItem.getItemMeta(); - assert instantRemoveOffMeta != null; - - instantRemoveOffMeta.setDisplayName("§eInstant remove is §cDisabled §e!"); - instantRemoveOffMeta.setLore( - Collections.singletonList("§7Click here to enable the instant remove")); - - instantRemoveOffItem.setItemMeta(instantRemoveOffMeta); - - // Instant Remove gui items - this.instantRemoveOn = new GuiItem(instantRemoveOnItem, (event -> { - this.instantRemove = false; - this.backgroundPane.bindItem('I', this.instantRemoveOff); - update(); - }), CustomAnvil.instance); - - this.instantRemoveOff = new GuiItem(instantRemoveOffItem, (event -> { - this.instantRemove = true; - this.backgroundPane.bindItem('I', this.instantRemoveOn); - update(); - }), CustomAnvil.instance); - - this.backgroundPane.bindItem('I', this.instantRemoveOff); - } - - private GuiItem prepareSaveItem() { - ItemStack saveItemStack = new ItemStack(GuiGlobalItems.DEFAULT_SAVE_ITEM); - ItemMeta saveMeta = saveItemStack.getItemMeta(); - assert saveMeta != null; - - saveMeta.setDisplayName("§aSave"); - - saveItemStack.setItemMeta(saveMeta); - - return new GuiItem(saveItemStack, event -> { - event.setCancelled(true); - - HumanEntity player = event.getWhoClicked(); - // Do not allow to save configuration if player do not have edit configuration permission - if (!player.hasPermission(CustomAnvil.editConfigPermission)) { - player.closeInventory(); - player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); - return; - } - if(testCantSave()) return; - - - // Save setting - Set result = new HashSet<>(this.elementGuiMap.keySet()); - - if(!this.selector.setSelectedMaterials(result)){ - player.sendMessage("§cSomething went wrong while saving the change of value."); - } - - // Return to parent - this.backGui.show(player); - - }, CustomAnvil.instance); - } - - /** - * @return A consumer to update the current setting's value. - */ - protected Consumer setItemAsCursor() { - return event -> { - event.setCancelled(true); - - HumanEntity player = event.getWhoClicked(); - ItemStack cursor = player.getItemOnCursor(); - - // Test if cursor material allowed - NamespacedKey cursorMat = MaterialUtil.INSTANCE.getCustomType(cursor); - if(MaterialUtil.INSTANCE.isAir(cursorMat)) return; - if(this.illegalMaterials.contains(cursorMat)) return; - - // Update gui only if item did not exist before. - if(!this.elementGuiMap.containsKey(cursorMat)){ - updateValueForGeneric(cursorMat, true); - this.nowMaterialHash ^= cursorMat.hashCode(); - - setSaveItem(); - update(); - } - }; - } - - @Override - protected ItemStack createItemForGeneric(NamespacedKey material) { - ItemStack item = new ItemStack(Objects.requireNonNull(MaterialUtil.INSTANCE.getMatFromKey(material))); - ItemMeta meta = item.getItemMeta(); - - if(meta == null) return item; - meta.setDisplayName("§a" + CasedStringUtil.snakeToUpperSpacedCase(material.getKey().toLowerCase())); - meta.setLore(Collections.singletonList("§7Click here to remove this material from the list")); - meta.addItemFlags(ItemFlag.values()); - - item.setItemMeta(meta); - - return item; - } - - @Override - protected Collection getEveryDisplayableInstanceOfGeneric() { - return this.defaultMaterials; - } - - @Override - protected void updateElement(NamespacedKey material, GuiItem element) { - // Nothing happen here I think - } - - @Override - protected GuiItem newElementRequested(NamespacedKey material, GuiItem newItem) { - newItem.setAction(event -> { - if(this.instantRemove){ - removeMaterial(material); - }else { - String materialName = CasedStringUtil.snakeToUpperSpacedCase(material.getKey().toLowerCase()); - - // Create and show confirm remove gui. - ConfirmActionGui confirmGui = new ConfirmActionGui( - "Remove " + materialName, - "§7Confirm Remove " + materialName.toLowerCase() + " from this list.", - this, this, - () -> { - removeMaterial(material); - return true; - }, false - ); - confirmGui.show(event.getWhoClicked()); - - } - }); - return newItem; - } - - private void removeMaterial(NamespacedKey material) { - if(this.elementGuiMap.containsKey(material)){ - this.nowMaterialHash ^= material.hashCode(); - setSaveItem(); - removeGeneric(material); - } - - } - - @Override - protected GuiItem findItemFromElement(NamespacedKey generic, GuiItem element) { - return element; - } - - @Override - protected GuiItem findGuiItemForRemoval(NamespacedKey generic, GuiItem element) { - return element; - } - - private static int hashFromMaterialList(List materialList){ - int defaultMaterialHash = 0; - for (NamespacedKey material : materialList) { - defaultMaterialHash ^= material.hashCode(); - } - return defaultMaterialHash; - } - - private void setSaveItem() { - if(testCantSave()){ - this.backgroundPane.bindItem('S', this.noChangeItem); - }else{ - this.backgroundPane.bindItem('S', this.saveItem); - } - - } - - private boolean testCantSave() { - return this.defaultMaterialHash == this.nowMaterialHash; - } - - - // Unused functions. - @Override - protected GuiItem prepareCreateNewItem() {// Not used - return null; - } - @Override - protected Consumer prepareCreateItemConsumer(HumanEntity player) {// Not used - return null; - } - - @Override - protected String genericDisplayedName() {// Not Used - return null; - } -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/SettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/SettingGui.java deleted file mode 100644 index a6d2784..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/SettingGui.java +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.settings; - -import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; - -public interface SettingGui { - - /** - * Called when the associated setting need to be saved. - * - * @return true if the save was successful. false otherwise - */ - boolean onSave(); - - /** - * If this function return true - * the gui assume the associated setting can be saved. - * - * @return true if there is a change to the setting. false otherwise - */ - boolean hadChange(); - - interface SettingGuiFactory { - - /** - * Create a gui using setting parameters and current setting value. - * - * @return A new instance of the implemented setting gui. - */ - Gui create(); - - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/WorkPenaltyTypeSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/WorkPenaltyTypeSettingGui.java deleted file mode 100644 index 4345aa1..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/WorkPenaltyTypeSettingGui.java +++ /dev/null @@ -1,252 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.config.settings; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.pane.PatternPane; -import com.github.stefvanschie.inventoryframework.pane.util.Pattern; -import io.delilaheve.CustomAnvil; -import io.delilaheve.util.ConfigOptions; -import org.bukkit.Material; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.entity.HumanEntity; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.anvil.AnvilUseType; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.config.WorkPenaltyType; -import xyz.alexcrea.cuanvil.gui.config.global.BasicConfigGui; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; - -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; - -public class WorkPenaltyTypeSettingGui extends AbstractSettingGui { - - private static final String INCREASING_EXPLANATION = "§eIncreasing§7: will penalty be increased (in item)"; - private static final String ADDING_EXPLANATION = "§eAdditive§7: will penalty be added to the cost"; - - private static final String SHARED_EXPLANATION = "§eShared§7: Vanilla, shared penalty. it will be kept from before the plugin installation."; - private static final String EXCLUSIVE_EXPLANATION = "§eExclusive§7: Custom, per anvil use type penalty. it will be lost after plugin uninstallation"; - - private final @NotNull WorkPenaltyType currentType; - private final @NotNull Map items; - - public WorkPenaltyTypeSettingGui(@NotNull BasicConfigGui parent) { - super(4, "§8Work Penalty Type", parent); - - this.currentType = ConfigOptions.INSTANCE.getWorkPenaltyType(); - this.items = new EnumMap<>(this.currentType.getPartMap()); - - for (AnvilUseType type : useTypes.keySet()) { - updateGuiForType(type); - } - } - - public static GuiItem getDisplayItem(@NotNull BasicConfigGui parent, - @NotNull Material itemMat, - @NotNull String name) { - List displayLore = new ArrayList<>(); - - displayLore.add("§7Work penalty increase the price for every anvil use."); - displayLore.add("§7This config allow you to choose the comportment of work penalty."); - displayLore.add(INCREASING_EXPLANATION); - displayLore.add(ADDING_EXPLANATION); - displayLore.add(""); - displayLore.add("§7About shared/exclusive penalty:"); - displayLore.add(SHARED_EXPLANATION); - displayLore.add(EXCLUSIVE_EXPLANATION); - - ItemStack item = new ItemStack(itemMat); - - ItemMeta meta = item.getItemMeta(); - meta.setDisplayName(name); - meta.setLore(displayLore); - - item.setItemMeta(meta); - - return new GuiItem(item, (event) -> { - event.setCancelled(true); - HumanEntity player = event.getWhoClicked(); - - // Do not allow to open inventory if player do not have edit configuration permission - if (!player.hasPermission(CustomAnvil.editConfigPermission)) { - player.closeInventory(); - player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); - return; - } - new WorkPenaltyTypeSettingGui(parent).show(player); - }, CustomAnvil.instance); - } - - private static final Map useTypes = - Map.of( - AnvilUseType.RENAME_ONLY, "a1z9Z", - AnvilUseType.MERGE, "b2y8Y", - AnvilUseType.UNIT_REPAIR, "c3x7X", - AnvilUseType.CUSTOM_CRAFT, "d4w6W" - ); - - @Override - protected Pattern getGuiPattern() { - return new Pattern( // Yeah that a mess - "00a1z9Z00", - "00b2y8Y00", - "00c3x7X00", - "B004w600S" - ); - } - - public void updateGuiForType(AnvilUseType type) { - PatternPane pane = getPane(); - - String typeVals = useTypes.get(type); - - char increment = typeVals.charAt(0); - char additive = typeVals.charAt(1); - char display = typeVals.charAt(2); - char exclusiveIncrement = typeVals.charAt(3); - char exclusiveAdditive = typeVals.charAt(4); - - WorkPenaltyType.WorkPenaltyPart part = items.get(type); - String increasingStr = (part.penaltyIncrease() ? "§a" : "§c") + "Increasing"; - String additiveStr = (part.penaltyAdditive() ? "§a" : "§c") + "Additive"; - String exclusiveIncreasingStr = (part.exclusivePenaltyIncrease() ? "§a" : "§c") + "Increasing"; - String exclusiveAdditiveStr = (part.exclusivePenaltyAdditive() ? "§a" : "§c") + "Additive"; - - // Display item - ItemStack displayItem = new ItemStack(type.getDisplayMat()); - - ArrayList displayLore = new ArrayList<>(); - displayLore.add("§eShared§7: " + additiveStr + " §7| " + increasingStr); - displayLore.add("§eExclusive§7: " + exclusiveAdditiveStr + " §7| " + exclusiveIncreasingStr); - - ItemMeta meta = displayItem.getItemMeta(); - meta.setDisplayName("§e" + type.getDisplayName()); - meta.setLore(displayLore); - displayItem.setItemMeta(meta); - - pane.bindItem(display, new GuiItem(displayItem, (event) -> { - event.setCancelled(true); - })); - - // Can probably put this in a function but this works so - // "Increment" item - ItemStack incrementItem = new ItemStack(part.penaltyIncrease() ? Material.GREEN_TERRACOTTA : Material.RED_TERRACOTTA); - - meta = incrementItem.getItemMeta(); - meta.setDisplayName(increasingStr); - meta.setLore(List.of(INCREASING_EXPLANATION)); - meta.setLore(List.of(SHARED_EXPLANATION)); - incrementItem.setItemMeta(meta); - - pane.bindItem(increment, new GuiItem(incrementItem, (event) -> { - event.setCancelled(true); - - WorkPenaltyType.WorkPenaltyPart newPart = new WorkPenaltyType.WorkPenaltyPart( - !part.penaltyIncrease(), part.penaltyAdditive(), - part.exclusivePenaltyIncrease(), part.exclusivePenaltyAdditive()); - items.replace(type, newPart); - updateGuiForType(type); - update(); - })); - - // "Additive" item - ItemStack additiveItem = new ItemStack(part.penaltyAdditive() ? Material.GREEN_TERRACOTTA : Material.RED_TERRACOTTA); - - meta = additiveItem.getItemMeta(); - meta.setDisplayName(additiveStr); - meta.setLore(List.of(ADDING_EXPLANATION)); - meta.setLore(List.of(SHARED_EXPLANATION)); - additiveItem.setItemMeta(meta); - - pane.bindItem(additive, new GuiItem(additiveItem, (event) -> { - event.setCancelled(true); - - WorkPenaltyType.WorkPenaltyPart newPart = new WorkPenaltyType.WorkPenaltyPart( - part.penaltyIncrease(), !part.penaltyAdditive(), - part.exclusivePenaltyIncrease(), part.exclusivePenaltyAdditive()); - items.replace(type, newPart); - updateGuiForType(type); - update(); - })); - - // exclusive "Increment" item - ItemStack exclusiveIncrementItem = new ItemStack(part.exclusivePenaltyIncrease() ? Material.GREEN_TERRACOTTA : Material.RED_TERRACOTTA); - - meta = exclusiveIncrementItem.getItemMeta(); - meta.setDisplayName(exclusiveIncreasingStr); - meta.setLore(List.of(INCREASING_EXPLANATION)); - meta.setLore(List.of(EXCLUSIVE_EXPLANATION)); - exclusiveIncrementItem.setItemMeta(meta); - - pane.bindItem(exclusiveIncrement, new GuiItem(exclusiveIncrementItem, (event) -> { - event.setCancelled(true); - - WorkPenaltyType.WorkPenaltyPart newPart = new WorkPenaltyType.WorkPenaltyPart( - part.penaltyIncrease(), part.penaltyAdditive(), - !part.exclusivePenaltyIncrease(), part.exclusivePenaltyAdditive()); - items.replace(type, newPart); - updateGuiForType(type); - update(); - })); - - // exclusive "Additive" item - ItemStack exclusiveAdditiveItem = new ItemStack(part.exclusivePenaltyAdditive() ? Material.GREEN_TERRACOTTA : Material.RED_TERRACOTTA); - - meta = exclusiveAdditiveItem.getItemMeta(); - meta.setDisplayName(exclusiveAdditiveStr); - meta.setLore(List.of(ADDING_EXPLANATION)); - meta.setLore(List.of(EXCLUSIVE_EXPLANATION)); - exclusiveAdditiveItem.setItemMeta(meta); - - pane.bindItem(exclusiveAdditive, new GuiItem(exclusiveAdditiveItem, (event) -> { - event.setCancelled(true); - - WorkPenaltyType.WorkPenaltyPart newPart = new WorkPenaltyType.WorkPenaltyPart( - part.penaltyIncrease(), part.penaltyAdditive(), - part.exclusivePenaltyIncrease(), !part.exclusivePenaltyAdditive()); - items.replace(type, newPart); - updateGuiForType(type); - update(); - })); - } - - @Override - public boolean onSave() { - return saveWorkPenalty(items); - } - - public static boolean saveWorkPenalty(Map partEnum) { - ConfigHolder configHolder = ConfigHolder.DEFAULT_CONFIG; - FileConfiguration config = configHolder.getConfig(); - - partEnum.forEach((key, value) -> { - String partPath = key.getPath(); - - if (key.getDefaultPenalty().equals(value)) { - config.set(partPath, null); - return; - } - - config.set(partPath + '.' + ConfigOptions.WORK_PENALTY_INCREASE, value.penaltyIncrease()); - config.set(partPath + '.' + ConfigOptions.WORK_PENALTY_ADDITIVE, value.penaltyAdditive()); - config.set(partPath + '.' + ConfigOptions.EXCLUSIVE_WORK_PENALTY_INCREASE, value.exclusivePenaltyIncrease()); - config.set(partPath + '.' + ConfigOptions.EXCLUSIVE_WORK_PENALTY_ADDITIVE, value.exclusivePenaltyAdditive()); - }); - - return configHolder.saveToDisk(true); - } - - @Override - public boolean hadChange() { - for (AnvilUseType type : items.keySet()) { - if (!currentType.getPenaltyInfo(type).equals(items.get(type))) { - return true; - } - } - - return false; - } -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiGlobalActions.java b/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiGlobalActions.java deleted file mode 100644 index 694fa14..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiGlobalActions.java +++ /dev/null @@ -1,145 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.util; - -import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; -import io.delilaheve.CustomAnvil; -import org.bukkit.entity.HumanEntity; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; -import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.function.Consumer; - -/** - * A utility class to store function that create generic GUI actions. - */ -public class GuiGlobalActions { - - public static final String NO_EDIT_PERM = "§cYou do not have permission to edit the config"; - - /** - * A Consumer that should be used if the item goal is to do nothing on click. - */ - public static final Consumer stayInPlace = event -> event.setCancelled(true); - - /** - * Create a consumer to create and open a new GUI. - * Used with InventoryClickEvent as the consumer argument as it is planned to be used on click on an GuiItem. - * - * @param clazz The class of the gui to open. - * It is assumed this class contain a constructor requiring arguments of argClass in the same order as argClass array. - * @param argClass Classes of the argument that will be passed to the constructor of the GUI class. - * @param args Arguments for the constructor the GUI class. - * @return A consumer to create a new gui and open it. - */ - public static @NotNull Consumer openGuiAction( - @NotNull Class clazz, - @NotNull Class[] argClass, - @NotNull Object... args) { - return event -> { - event.setCancelled(true); - HumanEntity player = event.getWhoClicked(); - // Do not allow to open inventory if player do not have edit configuration permission - if (!player.hasPermission(CustomAnvil.editConfigPermission)) { - player.closeInventory(); - player.sendMessage(NO_EDIT_PERM); - return; - } - try { - Constructor constructor = clazz.getConstructor(argClass); - // Assume constructor is accessible - Gui gui = constructor.newInstance(args); - gui.show(player); - - } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException | - InstantiationException e) { - throw new RuntimeException(e); - } - }; - } - - /** - * Create a consumer to create and open a new GUI. - * Used with InventoryClickEvent as the consumer argument as it is planned to be used on click on an GuiItem. - * - * @param clazz The class of the gui to open. - * It is assumed this class contain a constructor with no argument. - * @return A consumer to create a new gui and open it. - */ - public static @NotNull Consumer openGuiAction( - @NotNull Class clazz) { - return openGuiAction(clazz, new Class[0]); - } - - /** - * Create a consumer to open a setting gui from a setting GUI factory. - * Used with InventoryClickEvent as the consumer argument as it is planned to be used on click on an GuiItem. - * - * @param factory The setting gui factory. - * @return A consumer to create and open a new setting GUI. - */ - public static @NotNull Consumer openSettingGuiAction(SettingGui.SettingGuiFactory factory) { - return event -> { - event.setCancelled(true); - Gui gui = factory.create(); - gui.show(event.getWhoClicked()); - }; - } - - /** - * Create a consumer to open a global GUI. - * Used with InventoryClickEvent as the consumer argument as it is planned to be used on click on an GuiItem. - * - * @param goal The gui to open when consumer is run. - * @return A consumer to open a global GUI. - */ - public static @NotNull Consumer openGuiAction(@NotNull Gui goal) { - return event -> { - event.setCancelled(true); - HumanEntity player = event.getWhoClicked(); - // Do not allow to open inventory if player do not have edit configuration permission - if (!player.hasPermission(CustomAnvil.editConfigPermission)) { - player.closeInventory(); - player.sendMessage(NO_EDIT_PERM); - return; - } - goal.show(player); - }; - } - - /** - * Create a consumer to update and open an updatable GUI. - * Used with InventoryClickEvent as the consumer argument as it is planned to be used on click on an GuiItem. - * This consumer check if the player who interacted with the item have the permission to save before saving. - * - * @param setting The gui that contain the modified setting. - * @param goal The gui to update and open when consumer is run. - * @return A consumer to open a global GUI. - */ - public static @NotNull Consumer saveSettingAction( - @NotNull SettingGui setting, - @NotNull ValueUpdatableGui goal) { - return event -> { - event.setCancelled(true); - HumanEntity player = event.getWhoClicked(); - // Do not allow to save configuration if player do not have edit configuration permission - if (!player.hasPermission(CustomAnvil.editConfigPermission)) { - player.closeInventory(); - player.sendMessage(NO_EDIT_PERM); - return; - } - - // Save setting - if (!setting.onSave()) { - player.sendMessage("§cSomething went wrong while saving the change of value."); - } - // Update gui for those who have it open. - goal.updateGuiValues(); - // Then show - goal.getConnectedGui().show(player); - }; - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiGlobalItems.java b/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiGlobalItems.java deleted file mode 100644 index 79f1462..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiGlobalItems.java +++ /dev/null @@ -1,271 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.util; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; -import com.github.stefvanschie.inventoryframework.pane.PatternPane; -import io.delilaheve.CustomAnvil; -import org.bukkit.Material; -import org.bukkit.entity.HumanEntity; -import org.bukkit.inventory.ItemFlag; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; -import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * A utility class to store function that create generic GUI item. - */ -public class GuiGlobalItems { - - // statically create default back itemstack - private static final ItemStack BACK_ITEM; - - static { - BACK_ITEM = new ItemStack(Material.BARRIER); - ItemMeta meta = BACK_ITEM.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§cBack"); - BACK_ITEM.setItemMeta(meta); - } - - /** - * Create a GuiItem that open the given GUi. - * - * @param item The item to display in the GUI. - * @param goal The GUI to open on click. - * @return An GuiItem that open goal on click. - */ - public static GuiItem goToGuiItem(@NotNull ItemStack item, @NotNull Gui goal) { - return new GuiItem(item, GuiGlobalActions.openGuiAction(goal), CustomAnvil.instance); - } - - /** - * Create back button item from default back GuiItem. - * The back item will open the goal inventory when clicked. - * - * @param goal The GUI to go back to. - * @return An GuiItem that go back to goal on click. - */ - public static GuiItem backItem(@NotNull Gui goal) { - return goToGuiItem(BACK_ITEM, goal); - } - - /** - * Add default back item to a GUI pattern with the reserved character key B. - * The back item will open the target inventory when clicked. - * - * @param target The pattern to add the back item. - * @param goal The GUI to go back to. - */ - public static void addBackItem(@NotNull PatternPane target, - @NotNull Gui goal) { - target.bindItem('B', backItem(goal)); - } - - private static final Material DEFAULT_BACKGROUND_MAT = Material.LIGHT_GRAY_STAINED_GLASS_PANE; - - /** - * Get a background item with backgroundMat as the displayed material. - * A background item is a GuiItem that do nothing when interacted with and have an empty name. - * - * @param backgroundMat The material to which the background item should be made of. - * @return A background item with backgroundMat as material. - */ - public static GuiItem backgroundItem(Material backgroundMat) { - ItemStack item = new ItemStack(backgroundMat); - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§c"); - item.setItemMeta(meta); - return new GuiItem(item, GuiGlobalActions.stayInPlace, CustomAnvil.instance); - } - - /** - * Get default background GuiItem. - * A background item is a GuiItem that do nothing when interacted with and have an empty name. - * - * @return A new instance of the default background item. - */ - public static GuiItem backgroundItem() { - return backgroundItem(DEFAULT_BACKGROUND_MAT); - } - - /** - * Add default background item to a GUI pattern with the reserved character key 0. - * A background item is a GuiItem that do nothing when interacted with and have an empty name. - * - * @param target The pattern to add the background item. - * @param backgroundMat The material of the background item. - */ - public static void addBackgroundItem(@NotNull PatternPane target, - @NotNull Material backgroundMat) { - target.bindItem('0', backgroundItem(backgroundMat)); - } - - /** - * Add default background item to a GUI pattern with the reserved character key 0. - * A background item is a GuiItem that do nothing when interacted with and have an empty name. - * - * @param target The pattern to add the background item. - */ - public static void addBackgroundItem(@NotNull PatternPane target) { - addBackgroundItem(target, DEFAULT_BACKGROUND_MAT); - } - - public static final Material DEFAULT_SAVE_ITEM = Material.LIME_DYE; - public static final Material DEFAULT_NO_CHANGE_ITEM = Material.GRAY_DYE; - - /** - * Create a new save setting GuiItem. - * A save setting item is a GuiItem that save a changed setting when clicked. - * This item also check if the player who interacted with the item have the permission to save before saving. - * - * @param setting The setting to change. - * @param goal Parent GUI of this setting GUI. as setting will be change the display of goal GUI will be updated. - * @return A save setting item. - */ - public static GuiItem saveItem( - @NotNull SettingGui setting, - @NotNull ValueUpdatableGui goal) { - - ItemStack item = new ItemStack(DEFAULT_SAVE_ITEM); - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§aSave"); - item.setItemMeta(meta); - return new GuiItem(item, - GuiGlobalActions.saveSettingAction(setting, goal), - CustomAnvil.instance); - } - - // Create static non change item - private static final GuiItem NO_CHANGE_ITEM; - - static { - ItemStack item = new ItemStack(DEFAULT_NO_CHANGE_ITEM); - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§7No change. can't save."); - item.setItemMeta(meta); - NO_CHANGE_ITEM = new GuiItem(item, GuiGlobalActions.stayInPlace, CustomAnvil.instance); - } - - /** - * Get the global "no change" GuiItem. - * The no change item do nothing when interacted, only the title is change to show there is no change. - * - * @return The global "no change" item. - */ - public static GuiItem noChangeItem() { - return NO_CHANGE_ITEM; - } - - /** - * Create a new "create and go to the setting GUI" GuiItem. - * This item will create and open a setting GUI from the factory. - * - * @param item The item that will be displayed. - * @param factory The setting's GUI factory. - * @return A formatted GuiItem that will create and open a GUI for the setting. - */ - public static GuiItem openSettingGuiItem( - @NotNull ItemStack item, - @NotNull SettingGui.SettingGuiFactory factory - ) { - return new GuiItem(item, GuiGlobalActions.openSettingGuiAction(factory), CustomAnvil.instance); - } - - // Prefix of the one line lore that will be added to setting's item. - public static final String SETTING_ITEM_LORE_PREFIX = "§7value: "; - - /** - * Create an arbitrary GuiItem from a unique setting and item's property. - * - * @param factory The setting's GUI factory. - * @param itemMat Displayed material of the item. - * @param itemName Name of the item. - * @param value Value of the setting when the item is created. - * Will not update automatically, if the setting's value change, the item need to be created again. - * @param displayLore Gui display item lore. - * @return A formatted GuiItem that will create and open a GUI for the setting. - */ - public static GuiItem createGuiItemFromProperties( - @NotNull SettingGui.SettingGuiFactory factory, - @NotNull Material itemMat, - @NotNull StringBuilder itemName, - @NotNull Object value, - @NotNull List displayLore, - boolean displayValuePrefix - ) { - // Prepare lore - ArrayList lore = new ArrayList<>(); - lore.add((displayValuePrefix ? SETTING_ITEM_LORE_PREFIX : "") + value); - if(!displayLore.isEmpty()){ - lore.add(""); - lore.addAll(displayLore); - } - - // Create & initialise item - ItemStack item = new ItemStack(itemMat); - ItemMeta itemMeta = item.getItemMeta(); - assert itemMeta != null; - - itemMeta.setDisplayName(itemName.toString()); - itemMeta.setLore(lore); - itemMeta.addItemFlags(ItemFlag.values()); - - item.setItemMeta(itemMeta); - // Create GuiItem - return openSettingGuiItem(item, factory); - } - - /** - * Get the setting name from the setting path. - * For example: "gui.command.name" will return "name". - * - * @param path The setting's path. - * @return The setting's name. - */ - public static String getConfigNameFromPath(String path) { - // Get index of first dot - int indexOfDot = path.indexOf("."); - // when indexOfDot == -1 (not fond), it is implied that indexOfDot+1 = 0. substring will keep the full path as expected - return path.substring(indexOfDot + 1); - } - - public static GuiItem temporaryCloseGuiToSelectItem(Material itemMaterial, Gui openBack){ - ItemStack item = new ItemStack(itemMaterial); - ItemMeta meta = item.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§eTemporary close this menu"); - meta.setLore(Collections.singletonList("§7Allow you to chose other item then return here.")); - item.setItemMeta(meta); - - return new GuiItem(item, event -> { - event.setCancelled(true); - - HumanEntity player = event.getWhoClicked(); - - CustomAnvil.Companion.getChatListener().setListenedCallback(player, (message) ->{ - - if(message == null) return; - openBack.show(player); - - }); - - player.sendMessage("§eWrite something in chat to return to the item config menu."); - player.closeInventory(); - }, CustomAnvil.instance); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiSharedConstant.java b/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiSharedConstant.java deleted file mode 100644 index 11f3657..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiSharedConstant.java +++ /dev/null @@ -1,83 +0,0 @@ -package xyz.alexcrea.cuanvil.gui.util; - -import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.pane.Pane; -import com.github.stefvanschie.inventoryframework.pane.PatternPane; -import com.github.stefvanschie.inventoryframework.pane.util.Pattern; -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import xyz.alexcrea.cuanvil.gui.config.MainConfigGui; - -import java.util.Arrays; -import java.util.Collections; - -public class GuiSharedConstant { - - private GuiSharedConstant(){} - - public static final Material SECONDARY_BACKGROUND_MATERIAL = Material.BLACK_STAINED_GLASS_PANE; - public static final GuiItem SECONDARY_BACKGROUND_ITEM = GuiGlobalItems.backgroundItem(GuiSharedConstant.SECONDARY_BACKGROUND_MATERIAL); - - public static final String UPPER_FILLER_FULL_PLANE = "111111111"; - public static final String EMPTY_GUI_FULL_LINE = "000000000"; - public static final String EMPTY_FILLER_FULL_LINE = "100000001"; - - // Temporary values, until I get something better. - public static final boolean TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE = true; - public static final boolean TEMPORARY_DO_BACKUP_EVERY_SAVE = true; - - public static final PatternPane BACK_TO_MAIN_MENU_BIG_LIST_DISPLAY_BACKGROUND_PANE; - - static { - Pattern pattern = new Pattern( - GuiSharedConstant.UPPER_FILLER_FULL_PLANE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - GuiSharedConstant.EMPTY_FILLER_FULL_LINE, - "B11111111" - ); - BACK_TO_MAIN_MENU_BIG_LIST_DISPLAY_BACKGROUND_PANE = new PatternPane(0, 0, 9, 6, Pane.Priority.LOW, pattern); - - GuiGlobalItems.addBackItem(BACK_TO_MAIN_MENU_BIG_LIST_DISPLAY_BACKGROUND_PANE, MainConfigGui.getInstance()); - - GuiGlobalItems.addBackgroundItem(BACK_TO_MAIN_MENU_BIG_LIST_DISPLAY_BACKGROUND_PANE); - BACK_TO_MAIN_MENU_BIG_LIST_DISPLAY_BACKGROUND_PANE.bindItem('1', GuiSharedConstant.SECONDARY_BACKGROUND_ITEM); - - } - - public static final ItemStack CANCEL_ITEM; - public static final ItemStack CONFIRM_ITEM; - public static final ItemStack CONFIRM_PERMANENT_ITEM; - - static { - CANCEL_ITEM = new ItemStack(Material.RED_TERRACOTTA); - ItemMeta meta = CANCEL_ITEM.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§cCancel"); - meta.setLore(Collections.singletonList("§7Cancel current action and return to previous menu.")); - CANCEL_ITEM.setItemMeta(meta); - - CONFIRM_ITEM = new ItemStack(Material.GREEN_TERRACOTTA); - meta = CONFIRM_ITEM.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§aConfirm"); - meta.setLore(Collections.singletonList("§7Confirm current action.")); - CONFIRM_ITEM.setItemMeta(meta); - - CONFIRM_PERMANENT_ITEM = new ItemStack(Material.GREEN_TERRACOTTA); - meta = CONFIRM_PERMANENT_ITEM.getItemMeta(); - assert meta != null; - - meta.setDisplayName("§aConfirm"); - meta.setLore(Arrays.asList("§7Confirm current action.", - "§4Cation: This action can't be canceled.")); - CONFIRM_PERMANENT_ITEM.setItemMeta(meta); - } - - public static void loadConstants(){} - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/ModrinthUpdateChecker.java b/src/main/java/xyz/alexcrea/cuanvil/update/ModrinthUpdateChecker.java deleted file mode 100644 index 489c636..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/update/ModrinthUpdateChecker.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2025 Clickism - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -package xyz.alexcrea.cuanvil.update; - -import com.google.gson.*; -import org.jetbrains.annotations.Nullable; - -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; -import java.util.function.Function; - -/** - * Utility class to check for newer versions of a project hosted on Modrinth. - */ -public class ModrinthUpdateChecker { - - private static final String API_URL = "https://api.modrinth.com/v2/project/{id}/version"; - - private final String projectId; - private final String loader; - @Nullable - private final String minecraftVersion; - - @Nullable - private Boolean featured = null; - - @Nullable - public Consumer onError = null; - @Nullable - public Function getRawVersion = ModrinthUpdateChecker::getRawVersion; - - /** - * Create a new update checker for the given project. - * This will check the latest version for the given loader and any minecraft version. - * - * @param projectId the project ID - * @param loader the loader - */ - public ModrinthUpdateChecker(String projectId, String loader) { - this(projectId, loader, null); - } - - /** - * Create a new update checker for the given project. - * This will check the latest version for the given loader and minecraft version. - * - * @param projectId the project ID - * @param loader the loader - * @param minecraftVersion the minecraft version, or null for any version - */ - public ModrinthUpdateChecker(String projectId, String loader, @Nullable String minecraftVersion) { - this.projectId = projectId; - this.loader = loader; - this.minecraftVersion = minecraftVersion; - } - - /** - * Check the latest version of the project for the given loader and minecraft version - * and call the consumer with it. - * - * @param consumer the consumer - */ - public void checkVersion(Consumer consumer) { - try { - HttpClient client = HttpClient.newHttpClient(); - HttpRequest request = HttpRequest.newBuilder() - .uri(prepareURI()) - .GET() - .build(); - - client.sendAsync(request, HttpResponse.BodyHandlers.ofString()) - .thenAcceptAsync(response -> { - if (response.statusCode() != 200) { - if(onError != null) - onError.accept(new RuntimeException("wrong response status code: " + response.statusCode())); - return; - } - JsonArray versionsArray = JsonParser.parseString(response.body()).getAsJsonArray(); - String latestVersion = getLatestVersion(versionsArray); - if (latestVersion == null) { - if(onError != null) - onError.accept(new RuntimeException("latest version is null")); - return; - } - consumer.accept(latestVersion); - }); - } catch (Exception e) { - if(onError != null) onError.accept(e); - } - } - - /** - * Get the latest compatible version from the versions array. - * - * @param versions the versions array - * @return the latest compatible version - */ - @Nullable - protected String getLatestVersion(JsonArray versions) { - return versions.asList().stream().findFirst() - .map(JsonElement::getAsJsonObject) - .map(version -> version.get("version_number").getAsString()) - .map(getRawVersion != null ? getRawVersion : (v -> v)) - .orElse(null); - } - - /** - * Gets the raw version from a version string. - * i.E: "fabric-1.2+1.17.1" -> "1.2" - * - * @param version the version string - * @return the raw version string - */ - public static String getRawVersion(String version) { - if (version.isEmpty()) return version; - version = version.replaceAll("^\\D+", ""); - String[] split = version.split("\\+"); - return split[0]; - } - - /** - * Prepare this request uri based on current parameters. - * @return the request uri - */ - private URI prepareURI() { - var url = new StringBuilder(API_URL.replace("{id}", projectId)); - - var parameters = prepareParameters(); - String[] paramArray = new String[parameters.size()]; - int i = 0; - for (Map.Entry entry : parameters.entrySet()) { - paramArray[i++] = entry.getKey() + '=' + entry.getValue(); - } - url.append('?').append(String.join("&", paramArray)); - - return URI.create(url.toString()); - } - - /** - * Get the parameters for the version request. - * - * @return a map of key-value map of the request parameters - */ - private Map prepareParameters(){ - var parameters = new HashMap(); - - parameters.put("loaders", List.of(loader).toString()); - if(minecraftVersion != null) parameters.put("game_versions", List.of(minecraftVersion).toString()); - if(featured != null) parameters.put("featured", featured.toString()); - - parameters.put("include_changelog", "false"); - return parameters; - } - - /** - * Only get featured or non-featured versions. - * Null represent no filter. - * @param featured should be restricted to featured version ? default null if not called - * @return this - */ - public ModrinthUpdateChecker setFeatured(@Nullable Boolean featured) { - this.featured = featured; - return this; - } - - /** - * Function called on error calling the api. - * @param onError What should happen on error - * @return this - */ - public ModrinthUpdateChecker setOnError(@Nullable Consumer onError) { - this.onError = onError; - return this; - } - - /** - * Set the function to get raw version from the modrinth version. - * If null provided raw version will act as in the identity function. - * @param getRawVersion The function transforming modrinth version to raw version - * @return this - */ - public ModrinthUpdateChecker setGetRawVersion(@Nullable Function getRawVersion) { - this.getRawVersion = getRawVersion; - return this; - } -} \ No newline at end of file diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/PluginSetDefault.java b/src/main/java/xyz/alexcrea/cuanvil/update/PluginSetDefault.java deleted file mode 100644 index 707a218..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/update/PluginSetDefault.java +++ /dev/null @@ -1,98 +0,0 @@ -package xyz.alexcrea.cuanvil.update; - -import io.delilaheve.CustomAnvil; -import io.delilaheve.util.ConfigOptions; -import org.bukkit.configuration.file.FileConfiguration; -import org.jetbrains.annotations.NotNull; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.util.MetricType; -import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil; -import xyz.alexcrea.cuanvil.util.config.LoreEditType; - -import static io.delilaheve.util.ConfigOptions.*; -import static xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.*; - -public class PluginSetDefault { - - public static void reAddMissingDefault() { - FileConfiguration config = ConfigHolder.DEFAULT_CONFIG.getConfig(); - - int nbSet = 0; - - nbSet += trySetDefault(config, METRIC_TYPE, MetricType.AUTO.getValue()); - nbSet += trySetDefault(config, METRIC_COLLECT_ERROR, true); - - nbSet += trySetDefault(config, CAP_ANVIL_COST, DEFAULT_CAP_ANVIL_COST); - nbSet += trySetDefault(config, MAX_ANVIL_COST, DEFAULT_MAX_ANVIL_COST); - nbSet += trySetDefault(config, REMOVE_ANVIL_COST_LIMIT, DEFAULT_REMOVE_ANVIL_COST_LIMIT); - nbSet += trySetDefault(config, REPLACE_TOO_EXPENSIVE, DEFAULT_REPLACE_TOO_EXPENSIVE); - nbSet += trySetDefault(config, ITEM_REPAIR_COST, DEFAULT_ITEM_REPAIR_COST); - nbSet += trySetDefault(config, UNIT_REPAIR_COST, DEFAULT_UNIT_REPAIR_COST); - nbSet += trySetDefault(config, ITEM_RENAME_COST, DEFAULT_ITEM_RENAME_COST); - nbSet += trySetDefault(config, SACRIFICE_ILLEGAL_COST, DEFAULT_SACRIFICE_ILLEGAL_COST); - nbSet += trySetDefault(config, ConfigOptions.ALLOW_COLOR_CODE, ConfigOptions.DEFAULT_ALLOW_COLOR_CODE); - nbSet += trySetDefault(config, ALLOW_HEXADECIMAL_COLOR, DEFAULT_ALLOW_HEXADECIMAL_COLOR); - nbSet += trySetDefault(config, PERMISSION_NEEDED_FOR_COLOR, DEFAULT_PERMISSION_NEEDED_FOR_COLOR); - nbSet += trySetDefault(config, USE_OF_COLOR_COST, DEFAULT_USE_OF_COLOR_COST); - nbSet += trySetDefault(config, PER_COLOR_CODE_PERMISSION, DEFAULT_PER_COLOR_CODE_PERMISSION); - - // Lore Edit defaults - for (@NotNull LoreEditType value : LoreEditType.values()) { - String path = value.getRootPath() + "."; - - nbSet += trySetDefault(config, path + IS_ENABLED, DEFAULT_IS_ENABLED); - nbSet += trySetDefault(config, path + FIXED_COST, DEFAULT_FIXED_COST); - - nbSet += trySetDefault(config, path + DO_CONSUME, DEFAULT_DO_CONSUME); - if (value.isMultiLine()) { - nbSet += trySetDefault(config, path + PER_LINE_COST, DEFAULT_PER_LINE_COST); - } - if (value.isAppend()) { - nbSet += trySetDefault(config, path + LoreEditConfigUtil.ALLOW_COLOR_CODE, LoreEditConfigUtil.DEFAULT_ALLOW_COLOR_CODE); - nbSet += trySetDefault(config, path + ALLOW_HEX_COLOR, DEFAULT_ALLOW_HEX_COLOR); - nbSet += trySetDefault(config, path + USE_COLOR_COST, DEFAULT_USE_COLOR_COST); - } else { - nbSet += trySetDefault(config, path + REMOVE_COLOR_COST, DEFAULT_REMOVE_COLOR_COST); - } - } - - nbSet += trySetDefault(config, BOOK_PERMISSION_NEEDED, DEFAULT_BOOK_PERMISSION_NEEDED); - nbSet += trySetDefault(config, PAPER_PERMISSION_NEEDED, DEFAULT_PAPER_PERMISSION_NEEDED); - - nbSet += trySetDefault(config, PAPER_EDIT_ORDER, DEFAULT_PAPER_EDIT_ORDER); - - nbSet += trySetDefault(config, DIALOG_RENAME_ENABLED, DEFAULT_DIALOG_RENAME_ENABLED); - nbSet += trySetDefault(config, DIALOG_MAX_SIZE, DEFAULT_DIALOG_MAX_SIZE); - nbSet += trySetDefault(config, DIALOG_RENAME_USE_PERMISSION, DEFAULT_DIALOG_RENAME_USE_PERMISSION); - nbSet += trySetDefault(config, DIALOG_KEEP_USER_TEXT, DEFAULT_DIALOG_KEEP_USER_TEXT); - - if (nbSet > 0) { - CustomAnvil.instance.getLogger().info("Adding " + nbSet + " absent default config values."); - ConfigHolder.DEFAULT_CONFIG.saveToDisk(true); - } - - } - - private static int trySetDefault(@NotNull FileConfiguration config, @NotNull String path, @NotNull String value) { - if (config.isSet(path)) return 0; - - config.set(path, value); - return 1; - } - - private static int trySetDefault(@NotNull FileConfiguration config, @NotNull String path, int value) { - if (config.isSet(path)) return 0; - - config.set(path, value); - return 1; - } - - private static int trySetDefault(@NotNull FileConfiguration config, @NotNull String path, boolean value) { - if (config.isSet(path)) return 0; - - config.set(path, value); - return 1; - } - - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/UpdateHandler.java b/src/main/java/xyz/alexcrea/cuanvil/update/UpdateHandler.java deleted file mode 100644 index 660accb..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/update/UpdateHandler.java +++ /dev/null @@ -1,105 +0,0 @@ -package xyz.alexcrea.cuanvil.update; - -import io.delilaheve.CustomAnvil; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.update.minecraft.MCUpdate; -import xyz.alexcrea.cuanvil.update.minecraft.Update_1_21; -import xyz.alexcrea.cuanvil.update.minecraft.Update_1_21_11; -import xyz.alexcrea.cuanvil.update.minecraft.Update_1_21_9; -import xyz.alexcrea.cuanvil.update.plugin.*; - -import javax.annotation.Nonnull; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; - -public class UpdateHandler { - - private static final String CONFIG_VERSION_PATH = "configVersion"; - - // Handle mc version update then plugin version update - public static void handleUpdates() { - handleMCVersionUpdate(); - handlePluginUpdate(); - } - - private static final Map>> pUpdateMap = Map.of( - new Version(1, 6, 2), PUpdate_1_6_2::handleUpdate, - new Version(1, 6, 7), PUpdate_1_6_7::handleUpdate, - new Version(1, 8, 0), PUpdate_1_8_0::handleUpdate, - new Version(1, 11, 0), PUpdate_1_11_0::handleUpdate, - new Version(1, 15, 5), PUpdate_1_15_5::handleUpdate, - new Version(1, 15, 6), PUpdate_1_15_6::handleUpdate - ); - - private static final List mcUpdateMap = List.of( - new Update_1_21(), - new Update_1_21_9(), - new Update_1_21_11() - ); - - // Handle only plugin update - private static void handlePluginUpdate() { - String versionString = ConfigHolder.DEFAULT_CONFIG.getConfig().getString(CONFIG_VERSION_PATH); - Version current = versionString == null ? new Version(0) : Version.fromString(versionString); - - Set toSave = new HashSet<>(); - - AtomicReference latest = new AtomicReference<>(null); - - // Hopefully, should iterate in the "insertion" order - pUpdateMap.forEach((ver, consumer) -> { - if (ver.greaterThan(current)) { - CustomAnvil.log("handling plugin update to " + ver); - consumer.accept(toSave); - - latest.set(ver); - } - }); - - if (latest.get() != null) { - finishConfiguration(latest.get().toString(), toSave); - } - } - - // Handle minecraft version update (not plugin version update) - public static void handleMCVersionUpdate() { - Version current = UpdateUtils.currentMinecraftVersion(); - - boolean hadUpdate = false; - for (MCUpdate mcUpdate : mcUpdateMap) { - hadUpdate |= mcUpdate.handleUpdate(current, hadUpdate); - } - - if (hadUpdate) { - CustomAnvil.instance.getLogger().info("Updating Done !"); - } - - if(current.major() == 1 && current.minor() < 21) { - var logger = CustomAnvil.instance.getLogger(); - logger.warning("Your are running an old version of minecraft (lower than 1.21)"); - logger.warning("Custom Anvil will stop supporting this version on the first of july 2026"); - } - } - - private static void finishConfiguration(@Nonnull String newVersion, @Nonnull Set toSave) { - CustomAnvil.instance.getLogger().info("Configuration file updated to " + newVersion); - ConfigHolder.DEFAULT_CONFIG.getConfig().set(CONFIG_VERSION_PATH, newVersion); - - toSave.add(ConfigHolder.DEFAULT_CONFIG); - // save - for (ConfigHolder configHolder : toSave) { - configHolder.saveToDisk(true); - } - - // then reload - for (ConfigHolder configHolder : toSave) { - configHolder.reload(); - } - - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/UpdateUtils.java b/src/main/java/xyz/alexcrea/cuanvil/update/UpdateUtils.java deleted file mode 100644 index 2907fef..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/update/UpdateUtils.java +++ /dev/null @@ -1,36 +0,0 @@ -package xyz.alexcrea.cuanvil.update; - -import org.bukkit.Bukkit; -import org.bukkit.configuration.file.FileConfiguration; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class UpdateUtils { - public static final String MINECRAFT_VERSION_PATH = "lowMinecraftVersion"; - - public static Version currentMinecraftVersion() { - String versionString = Bukkit.getServer().getBukkitVersion().split("-")[0]; - return Version.fromString(versionString); - } - - public static void addToStringList(FileConfiguration config, String path, String... toAdd) { - List groups = new ArrayList<>(config.getStringList(path)); - groups.addAll(Arrays.asList(toAdd)); - config.set(path, groups); - - } - - public static void addAbsentToList(FileConfiguration config, String path, String... toAdd) { - List groups = new ArrayList<>(config.getStringList(path)); - for (String val : toAdd) { - if (groups.contains(val)) continue; - - groups.add(val); - } - config.set(path, groups); - - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/Version.java b/src/main/java/xyz/alexcrea/cuanvil/update/Version.java deleted file mode 100644 index a49fbdd..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/update/Version.java +++ /dev/null @@ -1,62 +0,0 @@ -package xyz.alexcrea.cuanvil.update; - -import org.jetbrains.annotations.NotNull; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public record Version(int major, int minor, int patch) { - - public Version(int major, int minor){ - this(major, minor, 0); - } - public Version(int major){ - this(major, 0, 0); - } - - public static Version fromString(@Nullable String versionString){ - if(versionString == null) return new Version(0, 0, 0); - - String[] partialVersion = versionString.split("\\."); - int[] versionParts = new int[]{0, 0, 0}; - - for (int i = 0; i < Math.min(3, partialVersion.length); i++) { - try { - versionParts[i] = Integer.parseInt(partialVersion[i]); - } catch (NumberFormatException e) { - break; - } - } - return new Version(versionParts[0], versionParts[1], versionParts[2]); - } - - public boolean greaterThan(@Nonnull Version other){ - return this.major > other.major || (this.major == other.major && - (this.minor > other.minor || (this.minor == other.minor && - this.patch > other.patch))); - } - - public boolean greaterEqual(@Nonnull Version other){ - return this.major > other.major || (this.major == other.major && - (this.minor > other.minor || (this.minor == other.minor && - this.patch >= other.patch))); - } - - public boolean lesserThan(@Nonnull Version other){ - return this.major < other.major || (this.major == other.major && - (this.minor < other.minor || (this.minor == other.minor && - this.patch < other.patch))); - } - - public boolean lesserEqual(@Nonnull Version other){ - return this.major < other.major || (this.major == other.major && - (this.minor < other.minor || (this.minor == other.minor && - this.patch <= other.patch))); - } - - @NotNull - @Override - public String toString() { - return major + "." + minor + "." + patch; - } -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/minecraft/MCUpdate.java b/src/main/java/xyz/alexcrea/cuanvil/update/minecraft/MCUpdate.java deleted file mode 100644 index 40fc587..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/update/minecraft/MCUpdate.java +++ /dev/null @@ -1,38 +0,0 @@ -package xyz.alexcrea.cuanvil.update.minecraft; - -import io.delilaheve.CustomAnvil; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.update.UpdateUtils; -import xyz.alexcrea.cuanvil.update.Version; - -public abstract class MCUpdate { - - public final Version version; - - public MCUpdate(Version version){ - this.version = version; - } - - public boolean handleUpdate(Version current, boolean hadUpdate){ - // Test if we are running in this update version or better - if(version.greaterThan(current)) - return false; - - // if version path is not null then check if its it's before this update version - String oldVersion = ConfigHolder.DEFAULT_CONFIG.getConfig().getString(UpdateUtils.MINECRAFT_VERSION_PATH); - if(oldVersion != null){ - var version = Version.fromString(oldVersion); - if(this.version.lesserEqual(version)) return false; - } - - if(!hadUpdate){ - CustomAnvil.instance.getLogger().info("Updating config to support minecraft " + current +" ..."); - } - doUpdate(); - return true; - } - - protected abstract void doUpdate(); - - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/minecraft/Update_1_21.java b/src/main/java/xyz/alexcrea/cuanvil/update/minecraft/Update_1_21.java deleted file mode 100644 index 3aa6073..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/update/minecraft/Update_1_21.java +++ /dev/null @@ -1,79 +0,0 @@ -package xyz.alexcrea.cuanvil.update.minecraft; - -import io.delilaheve.CustomAnvil; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.update.UpdateUtils; -import xyz.alexcrea.cuanvil.update.Version; - -import static xyz.alexcrea.cuanvil.update.UpdateUtils.addAbsentToList; - -public class Update_1_21 extends MCUpdate { - - public Update_1_21() { - super(new Version(1, 21)); - } - - @Override - protected void doUpdate() { - var baseConfig = ConfigHolder.DEFAULT_CONFIG.getConfig(); - var groupConfig = ConfigHolder.ITEM_GROUP_HOLDER.getConfig(); - var conflictConfig = ConfigHolder.CONFLICT_HOLDER.getConfig(); - var unitConfig = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig(); - - // Add mace to groups - groupConfig.set("mace.type", "include"); - addAbsentToList(groupConfig, "mace.items", "mace"); - - addAbsentToList(groupConfig, "can_unbreak.groups", "mace"); - - // Add new enchant conflicts - addAbsentToList(conflictConfig, "restriction_density.enchantments", "minecraft:density"); - addAbsentToList(conflictConfig, "restriction_density.notAffectedGroups", "mace", "enchanted_book"); - - addAbsentToList(conflictConfig, "restriction_breach.enchantments", "minecraft:breach"); - addAbsentToList(conflictConfig, "restriction_breach.notAffectedGroups", "mace", "enchanted_book"); - - addAbsentToList(conflictConfig, "restriction_wind_burst.enchantments", "minecraft:wind_burst"); - addAbsentToList(conflictConfig, "restriction_wind_burst.notAffectedGroups", "mace", "enchanted_book"); - - // Add mace to conflicts - addAbsentToList(conflictConfig, "restriction_fire_aspect.notAffectedGroups", "mace"); - addAbsentToList(conflictConfig, "restriction_smite.notAffectedGroups", "mace"); - addAbsentToList(conflictConfig, "restriction_bane_of_arthropods.notAffectedGroups", "mace"); - - addAbsentToList(conflictConfig, "sword_enchant_conflict.enchantments", - "minecraft:density", "minecraft:breach"); - - // Add level limit - baseConfig.set("enchant_limits.minecraft:density", 5); - baseConfig.set("enchant_limits.minecraft:breach", 4); - baseConfig.set("enchant_limits.minecraft:wind_burst", 3); - - // Add enchant values - baseConfig.set("enchant_values.minecraft:density.item", 2); - baseConfig.set("enchant_values.minecraft:density.book", 1); - - baseConfig.set("enchant_values.minecraft:breach.item", 4); - baseConfig.set("enchant_values.minecraft:breach.book", 2); - - baseConfig.set("enchant_values.minecraft:wind_burst.item", 4); - baseConfig.set("enchant_values.minecraft:wind_burst.book", 2); - - // Add unit repair for mace - unitConfig.set("breeze_rod.mace", 0.25); - - // Set version string as current - baseConfig.set(UpdateUtils.MINECRAFT_VERSION_PATH, version.toString()); - - // Save - ConfigHolder.DEFAULT_CONFIG.saveToDisk(true); - ConfigHolder.ITEM_GROUP_HOLDER.saveToDisk(true); - ConfigHolder.CONFLICT_HOLDER.saveToDisk(true); - ConfigHolder.UNIT_REPAIR_HOLDER.saveToDisk(true); - - // imply reload of CONFLICT_HOLDER - // We also do not need to reload base config as there is no object related to it. - ConfigHolder.ITEM_GROUP_HOLDER.reload(); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/minecraft/Update_1_21_11.java b/src/main/java/xyz/alexcrea/cuanvil/update/minecraft/Update_1_21_11.java deleted file mode 100644 index d639596..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/update/minecraft/Update_1_21_11.java +++ /dev/null @@ -1,84 +0,0 @@ -package xyz.alexcrea.cuanvil.update.minecraft; - -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.update.UpdateUtils; -import xyz.alexcrea.cuanvil.update.Version; - -import static xyz.alexcrea.cuanvil.update.UpdateUtils.addAbsentToList; - -public class Update_1_21_11 extends MCUpdate{ - - public Update_1_21_11() { - super(new Version(1, 21, 11)); - } - - @Override - protected void doUpdate() { - var baseConfig = ConfigHolder.DEFAULT_CONFIG.getConfig(); - var groupConfig = ConfigHolder.ITEM_GROUP_HOLDER.getConfig(); - var conflictConfig = ConfigHolder.CONFLICT_HOLDER.getConfig(); - var unitConfig = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig(); - - // Create spear group - groupConfig.set("spears.type", "include"); - addAbsentToList(groupConfig, "spears.items", - "wooden_spear", - "golden_spear", - "stone_spear", - "copper_spear", - "iron_spear", - "diamond_spear", - "netherite_spear"); - - // Add spear group to super group and enchantments - addAbsentToList(groupConfig, "melee_weapons.groups", "spears"); - - addAbsentToList(conflictConfig, "restriction_looting.notAffectedGroups", "spears"); - addAbsentToList(conflictConfig, "restriction_knockback.notAffectedGroups", "spears"); - addAbsentToList(conflictConfig, "restriction_fire_aspect.notAffectedGroups", "spears"); - - // Unit repair for spears - unitConfig.set("gold_ingot.golden_spear", 0.25); - unitConfig.set("copper_ingot.copper_spear", 0.25); - unitConfig.set("iron_ingot.iron_spear", 0.25); - unitConfig.set("diamond.diamond_spear", 0.25); - unitConfig.set("netherite_ingot.netherite_spear", 0.25); - - unitConfig.set("cobblestone.stone_spear", 0.25); - unitConfig.set("cobbled_deepslate.stone_spear", 0.25); - - unitConfig.set("oak_planks.wooden_spear", 0.25); - unitConfig.set("spruce_planks.wooden_spear", 0.25); - unitConfig.set("birch_planks.wooden_spear", 0.25); - unitConfig.set("jungle_planks.wooden_spear", 0.25); - unitConfig.set("acacia_planks.wooden_spear", 0.25); - unitConfig.set("dark_oak_planks.wooden_spear", 0.25); - unitConfig.set("mangrove_planks.wooden_spear", 0.25); - unitConfig.set("cherry_planks.wooden_spear", 0.25); - unitConfig.set("bamboo_planks.wooden_spear", 0.25); - unitConfig.set("crimson_planks.wooden_spear", 0.25); - unitConfig.set("warped_planks.wooden_spear", 0.25); - - // Create lunge enchant value and group - baseConfig.set("enchant_limits.minecraft:lunge", 3); - baseConfig.set("enchant_values.minecraft:lunge.item", 2); - baseConfig.set("enchant_values.minecraft:lunge.book", 1); - - addAbsentToList(conflictConfig, "restriction_lunge.enchantments", "minecraft:lunge"); - addAbsentToList(conflictConfig, "restriction_lunge.notAffectedGroups", "spears", "enchanted_book"); - - // Set version string as current - baseConfig.set(UpdateUtils.MINECRAFT_VERSION_PATH, version.toString()); - - // Save - ConfigHolder.DEFAULT_CONFIG.saveToDisk(true); - ConfigHolder.ITEM_GROUP_HOLDER.saveToDisk(true); - ConfigHolder.CONFLICT_HOLDER.saveToDisk(true); - ConfigHolder.UNIT_REPAIR_HOLDER.saveToDisk(true); - - // imply reload of CONFLICT_HOLDER - // We also do not need to reload base config as there is no object related to it. - ConfigHolder.ITEM_GROUP_HOLDER.reload(); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/minecraft/Update_1_21_9.java b/src/main/java/xyz/alexcrea/cuanvil/update/minecraft/Update_1_21_9.java deleted file mode 100644 index d289b9b..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/update/minecraft/Update_1_21_9.java +++ /dev/null @@ -1,64 +0,0 @@ -package xyz.alexcrea.cuanvil.update.minecraft; - -import org.bukkit.configuration.file.FileConfiguration; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.update.UpdateUtils; -import xyz.alexcrea.cuanvil.update.Version; - -import static xyz.alexcrea.cuanvil.update.UpdateUtils.addAbsentToList; - -public class Update_1_21_9 extends MCUpdate{ - - public Update_1_21_9() { - super(new Version(1, 21, 9)); - } - - @Override - protected void doUpdate() { - var baseConfig = ConfigHolder.DEFAULT_CONFIG.getConfig(); - var groupConfig = ConfigHolder.ITEM_GROUP_HOLDER.getConfig(); - var unitConfig = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig(); - - // Add cooper items to groups - addAbsentToList(groupConfig, "helmets.items", "copper_helmet"); - addAbsentToList(groupConfig, "chestplate.items", "copper_chestplate"); - addAbsentToList(groupConfig, "leggings.items", "copper_leggings"); - addAbsentToList(groupConfig, "boots.items", "copper_boots"); - - addAbsentToList(groupConfig, "pickaxes.items", "copper_pickaxe"); - addAbsentToList(groupConfig, "shovels.items", "copper_shovel"); - addAbsentToList(groupConfig, "hoes.items", "copper_hoe"); - addAbsentToList(groupConfig, "axes.items", "copper_axe"); - addAbsentToList(groupConfig, "swords.items", "copper_sword"); - - // Add unit repair - addCopperUnitRepair(unitConfig); - - // Set version string as current - baseConfig.set(UpdateUtils.MINECRAFT_VERSION_PATH, version.toString()); - - // Save - ConfigHolder.DEFAULT_CONFIG.saveToDisk(true); - ConfigHolder.ITEM_GROUP_HOLDER.saveToDisk(true); - ConfigHolder.UNIT_REPAIR_HOLDER.saveToDisk(true); - - // imply reload of CONFLICT_HOLDER - // We also do not need to reload base config as there is no object related to it. - ConfigHolder.ITEM_GROUP_HOLDER.reload(); - } - - public static void addCopperUnitRepair(FileConfiguration unitConfig) { - // Add unit repair - unitConfig.set("copper_ingot.copper_helmet", 0.25); - unitConfig.set("copper_ingot.copper_chestplate", 0.25); - unitConfig.set("copper_ingot.copper_leggings", 0.25); - unitConfig.set("copper_ingot.copper_boots", 0.25); - - unitConfig.set("copper_ingot.copper_pickaxe", 0.25); - unitConfig.set("copper_ingot.copper_shovel", 0.25); - unitConfig.set("copper_ingot.copper_hoe", 0.25); - unitConfig.set("copper_ingot.copper_axe", 0.25); - unitConfig.set("copper_ingot.copper_sword", 0.25); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_11_0.java b/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_11_0.java deleted file mode 100644 index 9740971..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_11_0.java +++ /dev/null @@ -1,137 +0,0 @@ -package xyz.alexcrea.cuanvil.update.plugin; - -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.FileConfiguration; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.api.MaterialGroupApi; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.group.AbstractMaterialGroup; -import xyz.alexcrea.cuanvil.group.IncludeGroup; - -import javax.annotation.Nonnull; -import java.util.Arrays; -import java.util.List; -import java.util.Set; - -import static xyz.alexcrea.cuanvil.update.UpdateUtils.addAbsentToList; - -public class PUpdate_1_11_0 { - - private static final List mace_expected = List.of( - "density", - "breach", - "smite", - "bane_of_arthropods" - ); - private static final List sword_expected = List.of( - "sharpness", - "smite", - "bane_of_arthropods" - ); - - private static final Material[] PICKAXES = new Material[]{ - Material.WOODEN_PICKAXE, Material.STONE_PICKAXE, - Material.IRON_PICKAXE, Material.DIAMOND_PICKAXE, - Material.GOLDEN_PICKAXE, Material.NETHERITE_PICKAXE - }; - - private static final Material[] SHOVELS = new Material[]{ - Material.WOODEN_SHOVEL, Material.STONE_SHOVEL, - Material.IRON_SHOVEL, Material.DIAMOND_SHOVEL, - Material.GOLDEN_SHOVEL, Material.NETHERITE_SHOVEL - }; - - private static final Material[] HOES = new Material[]{ - Material.WOODEN_HOE, Material.STONE_HOE, - Material.IRON_HOE, Material.DIAMOND_HOE, - Material.GOLDEN_HOE, Material.NETHERITE_HOE - }; - - public static void handleUpdate(@Nonnull Set toSave) { - handleToolsMigration(); - handleMaceMigration(toSave); - } - - private static void handleToolsMigration() { - // We migrate the mace conflict if exist and unmodified - AbstractMaterialGroup tools = MaterialGroupApi.getGroup("tools"); - - migrateTools(tools, "pickaxes", PICKAXES); - migrateTools(tools, "shovels", SHOVELS); - migrateTools(tools, "hoes", HOES); - } - - private static void migrateTools( - @Nullable AbstractMaterialGroup tools, - @NotNull String toolset, - @NotNull Material[] toolMats) { - - // Create new group - IncludeGroup group = new IncludeGroup(toolset); - NamespacedKey[] keys = new NamespacedKey[toolMats.length]; - for (int i = 0; i < toolMats.length; i++) { - keys[i] = toolMats[i].getKey(); - } - - group.addAll(keys); - - MaterialGroupApi.addMaterialGroup(group, true); - - // Try to see if all the materials was in the tools group. and if so, replace it with the new group - if (tools == null) return; - if (!(tools instanceof IncludeGroup include)) return; - - List mats = List.of(keys); - Set matSet = include.getNonGroupInheritedMaterials(); - if (!matSet.containsAll(mats)) return; - - mats.forEach(matSet::remove); - tools.addToPolicy(group); - MaterialGroupApi.writeMaterialGroup(tools); - } - - private static void handleMaceMigration(@Nonnull Set toSave) { - // We migrate the mace conflict if exist and unmodified - FileConfiguration config = ConfigHolder.CONFLICT_HOLDER.getConfig(); - - if (!config.isConfigurationSection("sword_enchant_conflict")) return; - if (!config.isConfigurationSection("mace_enchant_conflict")) return; - - ConfigurationSection mace_conflict = config.getConfigurationSection("mace_enchant_conflict"); - // Test mace conflict if default - if (mace_conflict == null) return; - if (mace_conflict.getInt("maxEnchantmentBeforeConflict", 0) != 1) return; - - if (mace_conflict.isList("notAffectedGroups") && !mace_conflict.getList("notAffectedGroups").isEmpty()) return; - - List enchantments = mace_conflict.getStringList("enchantments"); - if (enchantments.size() != 4) return; - for (String ench : mace_expected) { - if (!enchantments.contains(ench) && !enchantments.contains("minecraft:" + ench)) return; - } - - // Test sword_enchant_conflict is default - ConfigurationSection sword_conflict = config.getConfigurationSection("sword_enchant_conflict"); - if (sword_conflict.getInt("maxEnchantmentBeforeConflict", 0) != 1) return; - - if (sword_conflict.isList("notAffectedGroups") && !sword_conflict.getList("notAffectedGroups").isEmpty()) - return; - - enchantments = sword_conflict.getStringList("enchantments"); - if (enchantments.size() != 3) return; - for (String ench : sword_expected) { - if (!enchantments.contains(ench) && !enchantments.contains("minecraft:" + ench)) return; - } - - // Finally we know both conflict are default. so we fix - addAbsentToList(config, "sword_enchant_conflict.enchantments", - "minecraft:density", "minecraft:breach"); - - config.set("mace_enchant_conflict", null); - toSave.add(ConfigHolder.CONFLICT_HOLDER); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_15_5.java b/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_15_5.java deleted file mode 100644 index 76f51af..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_15_5.java +++ /dev/null @@ -1,27 +0,0 @@ -package xyz.alexcrea.cuanvil.update.plugin; - -import org.bukkit.configuration.file.FileConfiguration; -import xyz.alexcrea.cuanvil.config.ConfigHolder; - -import javax.annotation.Nonnull; -import java.util.Set; - -import static xyz.alexcrea.cuanvil.update.UpdateUtils.addAbsentToList; - -public class PUpdate_1_15_5 { - - public static void handleUpdate(@Nonnull Set toSave) { - FileConfiguration config = ConfigHolder.CONFLICT_HOLDER.getConfig(); - - if (config.isConfigurationSection("restriction_luck_of_the_sea")) return; - - // We fix the luck of the see enchantment - addAbsentToList(config, "restriction_luck_of_the_sea.enchantments", - "minecraft:luck_of_the_sea"); - addAbsentToList(config, "restriction_luck_of_the_sea.notAffectedGroups", - "enchanted_book", "fishing_rod"); - - toSave.add(ConfigHolder.CONFLICT_HOLDER); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_15_6.java b/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_15_6.java deleted file mode 100644 index fde7cfc..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_15_6.java +++ /dev/null @@ -1,27 +0,0 @@ -package xyz.alexcrea.cuanvil.update.plugin; - -import org.bukkit.configuration.file.FileConfiguration; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.update.UpdateUtils; -import xyz.alexcrea.cuanvil.update.Version; -import xyz.alexcrea.cuanvil.update.minecraft.Update_1_21_9; - -import javax.annotation.Nonnull; -import java.util.Set; - -public class PUpdate_1_15_6 { - - public static void handleUpdate(@Nonnull Set toSave) { - // fix only needed for 1.21.9 and above - Version current = UpdateUtils.currentMinecraftVersion(); - if (new Version(1, 21, 9).greaterThan(current)) return; - - FileConfiguration unitConfig = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig(); - - // Add unit repair - Update_1_21_9.addCopperUnitRepair(unitConfig); - - toSave.add(ConfigHolder.UNIT_REPAIR_HOLDER); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_6_2.java b/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_6_2.java deleted file mode 100644 index a4078de..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_6_2.java +++ /dev/null @@ -1,55 +0,0 @@ -package xyz.alexcrea.cuanvil.update.plugin; - -import org.bukkit.configuration.file.FileConfiguration; -import xyz.alexcrea.cuanvil.config.ConfigHolder; - -import javax.annotation.Nonnull; -import java.util.Set; - -import static xyz.alexcrea.cuanvil.update.UpdateUtils.addAbsentToList; - -public class PUpdate_1_6_2 { - - private static final String[] toUpdate = new String[] {"restriction_density", "restriction_breach", "restriction_wind_burst"}; - - public static void handleUpdate(@Nonnull Set toSave) { - FileConfiguration config = ConfigHolder.CONFLICT_HOLDER.getConfig(); - - boolean conflictUpdated = false; - for (String restriction : toUpdate) { - if(!config.isConfigurationSection(restriction)) continue; - String path = restriction + ".notAffectedGroups"; - - boolean contained = false; - for (String value : config.getStringList(path)) { - if(value.equalsIgnoreCase("enchanted_book")) { - contained = true; - break; - } - } - - if(!contained){ - addAbsentToList(config, path, "enchanted_book"); - conflictUpdated = true; - } - } - - if(conflictUpdated){ - toSave.add(ConfigHolder.CONFLICT_HOLDER); - - // May not be the most efficient for later revision, maybe move to PluginUpdates - ConfigHolder.CONFLICT_HOLDER.reload(); - } - - // Then we add the unit repair - config = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig(); - String unitRepairPath = "breeze_rod.mace"; - if(!config.isConfigurationSection(unitRepairPath)){ - config.set(unitRepairPath, 0.25); - - toSave.add(ConfigHolder.UNIT_REPAIR_HOLDER); - } - - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_6_7.java b/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_6_7.java deleted file mode 100644 index ee544dc..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_6_7.java +++ /dev/null @@ -1,25 +0,0 @@ -package xyz.alexcrea.cuanvil.update.plugin; - -import org.bukkit.configuration.file.FileConfiguration; -import xyz.alexcrea.cuanvil.config.ConfigHolder; - -import javax.annotation.Nonnull; -import java.util.Set; - -public class PUpdate_1_6_7 { - - public static void handleUpdate(@Nonnull Set toSave) { - FileConfiguration config = ConfigHolder.DEFAULT_CONFIG.getConfig(); - - // We fix the density enchantment - String value = config.getString("enchant_values.minecraft:density.item"); - if(value == null) value = config.getString("enchant_values.density.item"); - - if(value == null || "1".equalsIgnoreCase(value)){ - config.set("enchant_values.minecraft:density.item", 2); - - toSave.add(ConfigHolder.DEFAULT_CONFIG); - } - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_8_0.java b/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_8_0.java deleted file mode 100644 index 81ce1aa..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_8_0.java +++ /dev/null @@ -1,66 +0,0 @@ -package xyz.alexcrea.cuanvil.update.plugin; - -import io.delilaheve.util.ConfigOptions; -import org.bukkit.configuration.file.FileConfiguration; -import xyz.alexcrea.cuanvil.anvil.AnvilUseType; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.config.WorkPenaltyType; -import xyz.alexcrea.cuanvil.gui.config.settings.WorkPenaltyTypeSettingGui; - -import javax.annotation.Nonnull; -import java.util.EnumMap; -import java.util.Set; - -public class PUpdate_1_8_0 { - - private static final String WORK_PENALTY_TYPE = "work_penalty_type"; - - public static void handleUpdate(@Nonnull Set toSave) { - FileConfiguration config = ConfigHolder.DEFAULT_CONFIG.getConfig(); - - // We migrate the work penalty type if it exists - String penaltyTypeValue = config.getString(WORK_PENALTY_TYPE); - if (penaltyTypeValue == null) return; - - EnumMap partEnum; - partEnum = new EnumMap<>(ConfigOptions.INSTANCE.getWorkPenaltyType().getPartMap()); - - boolean keepIncrease; - boolean keepAdditive; - - switch (penaltyTypeValue.toLowerCase()) { - case "add_only": - keepIncrease = false; - keepAdditive = true; - break; - case "increase_only": - keepIncrease = true; - keepAdditive = false; - break; - case "disabled": - keepIncrease = false; - keepAdditive = false; - break; - default: - keepIncrease = true; - keepAdditive = true; - } - - for (AnvilUseType type : partEnum.keySet()) { - WorkPenaltyType.WorkPenaltyPart part = partEnum.get(type); - part = new WorkPenaltyType.WorkPenaltyPart( - keepIncrease & part.penaltyIncrease(), - keepAdditive & part.penaltyAdditive(), - part.exclusivePenaltyIncrease(), - part.exclusivePenaltyAdditive()); - partEnum.replace(type, part); - } - - if(WorkPenaltyTypeSettingGui.saveWorkPenalty(partEnum)){ - config.set(WORK_PENALTY_TYPE, null); - } - - toSave.add(ConfigHolder.DEFAULT_CONFIG); - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/util/CasedStringUtil.java b/src/main/java/xyz/alexcrea/cuanvil/util/CasedStringUtil.java deleted file mode 100644 index cb45d1c..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/util/CasedStringUtil.java +++ /dev/null @@ -1,58 +0,0 @@ -package xyz.alexcrea.cuanvil.util; - -/** - * An incomplete cased string util - */ -public class CasedStringUtil { - - /** - * Transform a snake cased string to an upper-cased spaced string. - *

    - * for example: if we use "hello_world" as an input this function will return "Hello World". - * - * @param snake_cased_string The input string. - * This argument NEED to be a snake cased string, or it will not work - * @return The input as an upper-cased string with space separator. - */ - public static String snakeToUpperSpacedCase(String snake_cased_string) { - if (snake_cased_string.contentEquals("")) return ""; - StringBuilder result = new StringBuilder(); - - for (String word : snake_cased_string.split("_")) { - result.append(" "); - if (word.isEmpty()) continue; - char firstChar = word.charAt(0); - - result.append(Character.toUpperCase(firstChar)); - result.append(word.substring(1)); - } - return result.substring(1); - } - - public static String camelCaseToUpperSpaceCase(String camelCasedString) { - if (camelCasedString.isEmpty()) return camelCasedString; - StringBuilder stb = new StringBuilder(); - - char[] chars = camelCasedString.toCharArray(); - stb.append(chars[0]); - for (int i = 1; i < chars.length; i++) { - char chr = chars[i]; - if (Character.isUpperCase(chr)) { - stb.append(" "); - } - stb.append(chr); - } - - return stb.toString(); - } - - public static String detectToUpperSpacedCase(String toDetect) { - //not advanced detection - if (toDetect.contains("_")) { - return snakeToUpperSpacedCase(toDetect); - } else { - return camelCaseToUpperSpaceCase(toDetect); - } - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/util/LazyValue.java b/src/main/java/xyz/alexcrea/cuanvil/util/LazyValue.java deleted file mode 100644 index 3ae8fdd..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/util/LazyValue.java +++ /dev/null @@ -1,36 +0,0 @@ -package xyz.alexcrea.cuanvil.util; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Supplier; - -public class LazyValue { - - private final Supplier valueSupplier; - private T storedValue; - - public LazyValue(Supplier valueSupplier) { - this.valueSupplier = valueSupplier; - this.storedValue = null; - } - - @Nullable - public T getStored(){ - return storedValue; - } - - @NotNull - public T get(){ - if (storedValue != null) return storedValue; - - synchronized(this) { - if(storedValue == null) { - storedValue = valueSupplier.get(); - } - } - - return storedValue; - } - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/util/Metrics.java b/src/main/java/xyz/alexcrea/cuanvil/util/Metrics.java deleted file mode 100644 index f21a15c..0000000 --- a/src/main/java/xyz/alexcrea/cuanvil/util/Metrics.java +++ /dev/null @@ -1,871 +0,0 @@ -/* - * This Metrics class was auto-generated and can be copied into your project if you are - * not using a build tool like Gradle or Maven for dependency management. - * - * IMPORTANT: You are not allowed to modify this class, except changing the package. - * - * Disallowed modifications include but are not limited to: - * - Remove the option for users to opt-out - * - Change the frequency for data submission - * - Obfuscate the code (every obfuscator should allow you to make an exception for specific files) - * - Reformat the code (if you use a linter, add an exception) - * - * Violations will result in a ban of your plugin and account from bStats. - */ -package xyz.alexcrea.cuanvil.util; - -import org.bukkit.Bukkit; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.java.JavaPlugin; - -import javax.net.ssl.HttpsURLConnection; -import java.io.*; -import java.lang.reflect.Method; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.concurrent.Callable; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Supplier; -import java.util.logging.Level; -import java.util.stream.Collectors; -import java.util.zip.GZIPOutputStream; - -public class Metrics { - - private final Plugin plugin; - - private final MetricsBase metricsBase; - - /** - * Creates a new Metrics instance. - * - * @param plugin Your plugin instance. - * @param serviceId The id of the service. It can be found at What is my plugin id? - */ - public Metrics(JavaPlugin plugin, int serviceId) { - this.plugin = plugin; - // Get the config file - File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats"); - File configFile = new File(bStatsFolder, "config.yml"); - YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); - if (!config.isSet("serverUuid")) { - config.addDefault("enabled", true); - config.addDefault("serverUuid", UUID.randomUUID().toString()); - config.addDefault("logFailedRequests", false); - config.addDefault("logSentData", false); - config.addDefault("logResponseStatusText", false); - // Inform the server owners about bStats - config - .options() - .header( - "bStats (https://bStats.org) collects some basic information for plugin authors, like how\n" - + "many people use their plugin and their total player count. It's recommended to keep bStats\n" - + "enabled, but if you're not comfortable with this, you can turn this setting off. There is no\n" - + "performance penalty associated with having metrics enabled, and data sent to bStats is fully\n" - + "anonymous.") - .copyDefaults(true); - try { - config.save(configFile); - } catch (IOException ignored) { - } - } - // Load the data - boolean enabled = config.getBoolean("enabled", true); - String serverUUID = config.getString("serverUuid"); - boolean logErrors = config.getBoolean("logFailedRequests", false); - boolean logSentData = config.getBoolean("logSentData", false); - boolean logResponseStatusText = config.getBoolean("logResponseStatusText", false); - metricsBase = - new MetricsBase( - "bukkit", - serverUUID, - serviceId, - enabled, - this::appendPlatformData, - this::appendServiceData, - submitDataTask -> Bukkit.getScheduler().runTask(plugin, submitDataTask), - plugin::isEnabled, - (message, error) -> this.plugin.getLogger().log(Level.WARNING, message, error), - (message) -> this.plugin.getLogger().log(Level.INFO, message), - logErrors, - logSentData, - logResponseStatusText); - } - - /** Shuts down the underlying scheduler service. */ - public void shutdown() { - metricsBase.shutdown(); - } - - /** - * Adds a custom chart. - * - * @param chart The chart to add. - */ - public void addCustomChart(CustomChart chart) { - metricsBase.addCustomChart(chart); - } - - private void appendPlatformData(JsonObjectBuilder builder) { - builder.appendField("playerAmount", getPlayerAmount()); - builder.appendField("onlineMode", Bukkit.getOnlineMode() ? 1 : 0); - builder.appendField("bukkitVersion", Bukkit.getVersion()); - builder.appendField("bukkitName", Bukkit.getName()); - builder.appendField("javaVersion", System.getProperty("java.version")); - builder.appendField("osName", System.getProperty("os.name")); - builder.appendField("osArch", System.getProperty("os.arch")); - builder.appendField("osVersion", System.getProperty("os.version")); - builder.appendField("coreCount", Runtime.getRuntime().availableProcessors()); - } - - private void appendServiceData(JsonObjectBuilder builder) { - builder.appendField("pluginVersion", plugin.getDescription().getVersion()); - } - - private int getPlayerAmount() { - try { - // Around MC 1.8 the return type was changed from an array to a collection, - // This fixes java.lang.NoSuchMethodError: - // org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection; - Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers"); - return onlinePlayersMethod.getReturnType().equals(Collection.class) - ? ((Collection) onlinePlayersMethod.invoke(Bukkit.getServer())).size() - : ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length; - } catch (Exception e) { - // Just use the new method if the reflection failed - return Bukkit.getOnlinePlayers().size(); - } - } - - public static class MetricsBase { - - /** The version of the Metrics class. */ - public static final String METRICS_VERSION = "3.0.2"; - - private static final String REPORT_URL = "https://bStats.org/api/v2/data/%s"; - - private final ScheduledExecutorService scheduler; - - private final String platform; - - private final String serverUuid; - - private final int serviceId; - - private final Consumer appendPlatformDataConsumer; - - private final Consumer appendServiceDataConsumer; - - private final Consumer submitTaskConsumer; - - private final Supplier checkServiceEnabledSupplier; - - private final BiConsumer errorLogger; - - private final Consumer infoLogger; - - private final boolean logErrors; - - private final boolean logSentData; - - private final boolean logResponseStatusText; - - private final Set customCharts = new HashSet<>(); - - private final boolean enabled; - - /** - * Creates a new MetricsBase class instance. - * - * @param platform The platform of the service. - * @param serviceId The id of the service. - * @param serverUuid The server uuid. - * @param enabled Whether or not data sending is enabled. - * @param appendPlatformDataConsumer A consumer that receives a {@code JsonObjectBuilder} and - * appends all platform-specific data. - * @param appendServiceDataConsumer A consumer that receives a {@code JsonObjectBuilder} and - * appends all service-specific data. - * @param submitTaskConsumer A consumer that takes a runnable with the submit task. This can be - * used to delegate the data collection to a another thread to prevent errors caused by - * concurrency. Can be {@code null}. - * @param checkServiceEnabledSupplier A supplier to check if the service is still enabled. - * @param errorLogger A consumer that accepts log message and an error. - * @param infoLogger A consumer that accepts info log messages. - * @param logErrors Whether or not errors should be logged. - * @param logSentData Whether or not the sent data should be logged. - * @param logResponseStatusText Whether or not the response status text should be logged. - */ - public MetricsBase( - String platform, - String serverUuid, - int serviceId, - boolean enabled, - Consumer appendPlatformDataConsumer, - Consumer appendServiceDataConsumer, - Consumer submitTaskConsumer, - Supplier checkServiceEnabledSupplier, - BiConsumer errorLogger, - Consumer infoLogger, - boolean logErrors, - boolean logSentData, - boolean logResponseStatusText) { - ScheduledThreadPoolExecutor scheduler = - new ScheduledThreadPoolExecutor(1, task -> new Thread(task, "bStats-Metrics")); - // We want delayed tasks (non-periodic) that will execute in the future to be - // cancelled when the scheduler is shutdown. - // Otherwise, we risk preventing the server from shutting down even when - // MetricsBase#shutdown() is called - scheduler.setExecuteExistingDelayedTasksAfterShutdownPolicy(false); - this.scheduler = scheduler; - this.platform = platform; - this.serverUuid = serverUuid; - this.serviceId = serviceId; - this.enabled = enabled; - this.appendPlatformDataConsumer = appendPlatformDataConsumer; - this.appendServiceDataConsumer = appendServiceDataConsumer; - this.submitTaskConsumer = submitTaskConsumer; - this.checkServiceEnabledSupplier = checkServiceEnabledSupplier; - this.errorLogger = errorLogger; - this.infoLogger = infoLogger; - this.logErrors = logErrors; - this.logSentData = logSentData; - this.logResponseStatusText = logResponseStatusText; - checkRelocation(); - if (enabled) { - // WARNING: Removing the option to opt-out will get your plugin banned from - // bStats - startSubmitting(); - } - } - - public void addCustomChart(CustomChart chart) { - this.customCharts.add(chart); - } - - public void shutdown() { - scheduler.shutdown(); - } - - private void startSubmitting() { - final Runnable submitTask = - () -> { - if (!enabled || !checkServiceEnabledSupplier.get()) { - // Submitting data or service is disabled - scheduler.shutdown(); - return; - } - if (submitTaskConsumer != null) { - submitTaskConsumer.accept(this::submitData); - } else { - this.submitData(); - } - }; - // Many servers tend to restart at a fixed time at xx:00 which causes an uneven - // distribution of requests on the - // bStats backend. To circumvent this problem, we introduce some randomness into - // the initial and second delay. - // WARNING: You must not modify and part of this Metrics class, including the - // submit delay or frequency! - // WARNING: Modifying this code will get your plugin banned on bStats. Just - // don't do it! - long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3)); - long secondDelay = (long) (1000 * 60 * (Math.random() * 30)); - scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS); - scheduler.scheduleAtFixedRate( - submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS); - } - - private void submitData() { - final JsonObjectBuilder baseJsonBuilder = new JsonObjectBuilder(); - appendPlatformDataConsumer.accept(baseJsonBuilder); - final JsonObjectBuilder serviceJsonBuilder = new JsonObjectBuilder(); - appendServiceDataConsumer.accept(serviceJsonBuilder); - JsonObjectBuilder.JsonObject[] chartData = - customCharts.stream() - .map(customChart -> customChart.getRequestJsonObject(errorLogger, logErrors)) - .filter(Objects::nonNull) - .toArray(JsonObjectBuilder.JsonObject[]::new); - serviceJsonBuilder.appendField("id", serviceId); - serviceJsonBuilder.appendField("customCharts", chartData); - baseJsonBuilder.appendField("service", serviceJsonBuilder.build()); - baseJsonBuilder.appendField("serverUUID", serverUuid); - baseJsonBuilder.appendField("metricsVersion", METRICS_VERSION); - JsonObjectBuilder.JsonObject data = baseJsonBuilder.build(); - scheduler.execute( - () -> { - try { - // Send the data - sendData(data); - } catch (Exception e) { - // Something went wrong! :( - if (logErrors) { - errorLogger.accept("Could not submit bStats metrics data", e); - } - } - }); - } - - private void sendData(JsonObjectBuilder.JsonObject data) throws Exception { - if (logSentData) { - infoLogger.accept("Sent bStats metrics data: " + data.toString()); - } - String url = String.format(REPORT_URL, platform); - HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection(); - // Compress the data to save bandwidth - byte[] compressedData = compress(data.toString()); - connection.setRequestMethod("POST"); - connection.addRequestProperty("Accept", "application/json"); - connection.addRequestProperty("Connection", "close"); - connection.addRequestProperty("Content-Encoding", "gzip"); - connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length)); - connection.setRequestProperty("Content-Type", "application/json"); - connection.setRequestProperty("User-Agent", "Metrics-Service/1"); - connection.setDoOutput(true); - try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) { - outputStream.write(compressedData); - } - StringBuilder builder = new StringBuilder(); - try (BufferedReader bufferedReader = - new BufferedReader(new InputStreamReader(connection.getInputStream()))) { - String line; - while ((line = bufferedReader.readLine()) != null) { - builder.append(line); - } - } - if (logResponseStatusText) { - infoLogger.accept("Sent data to bStats and received response: " + builder); - } - } - - /** Checks that the class was properly relocated. */ - private void checkRelocation() { - // You can use the property to disable the check in your test environment - if (System.getProperty("bstats.relocatecheck") == null - || !System.getProperty("bstats.relocatecheck").equals("false")) { - // Maven's Relocate is clever and changes strings, too. So we have to use this - // little "trick" ... :D - final String defaultPackage = - new String(new byte[] {'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's'}); - final String examplePackage = - new String(new byte[] {'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'}); - // We want to make sure no one just copy & pastes the example and uses the wrong - // package names - if (MetricsBase.class.getPackage().getName().startsWith(defaultPackage) - || MetricsBase.class.getPackage().getName().startsWith(examplePackage)) { - throw new IllegalStateException("bStats Metrics class has not been relocated correctly!"); - } - } - } - - /** - * Gzips the given string. - * - * @param str The string to gzip. - * @return The gzipped string. - */ - private static byte[] compress(final String str) throws IOException { - if (str == null) { - return null; - } - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - try (GZIPOutputStream gzip = new GZIPOutputStream(outputStream)) { - gzip.write(str.getBytes(StandardCharsets.UTF_8)); - } - return outputStream.toByteArray(); - } - } - - public static class SimplePie extends CustomChart { - - private final Callable callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public SimplePie(String chartId, Callable callable) { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - String value = callable.call(); - if (value == null || value.isEmpty()) { - // Null = skip the chart - return null; - } - return new JsonObjectBuilder().appendField("value", value).build(); - } - } - - public static class MultiLineChart extends CustomChart { - - private final Callable> callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public MultiLineChart(String chartId, Callable> callable) { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); - Map map = callable.call(); - if (map == null || map.isEmpty()) { - // Null = skip the chart - return null; - } - boolean allSkipped = true; - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue() == 0) { - // Skip this invalid - continue; - } - allSkipped = false; - valuesBuilder.appendField(entry.getKey(), entry.getValue()); - } - if (allSkipped) { - // Null = skip the chart - return null; - } - return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); - } - } - - public static class AdvancedPie extends CustomChart { - - private final Callable> callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public AdvancedPie(String chartId, Callable> callable) { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); - Map map = callable.call(); - if (map == null || map.isEmpty()) { - // Null = skip the chart - return null; - } - boolean allSkipped = true; - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue() == 0) { - // Skip this invalid - continue; - } - allSkipped = false; - valuesBuilder.appendField(entry.getKey(), entry.getValue()); - } - if (allSkipped) { - // Null = skip the chart - return null; - } - return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); - } - } - - public static class SimpleBarChart extends CustomChart { - - private final Callable> callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public SimpleBarChart(String chartId, Callable> callable) { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); - Map map = callable.call(); - if (map == null || map.isEmpty()) { - // Null = skip the chart - return null; - } - for (Map.Entry entry : map.entrySet()) { - valuesBuilder.appendField(entry.getKey(), new int[] {entry.getValue()}); - } - return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); - } - } - - public static class AdvancedBarChart extends CustomChart { - - private final Callable> callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public AdvancedBarChart(String chartId, Callable> callable) { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); - Map map = callable.call(); - if (map == null || map.isEmpty()) { - // Null = skip the chart - return null; - } - boolean allSkipped = true; - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue().length == 0) { - // Skip this invalid - continue; - } - allSkipped = false; - valuesBuilder.appendField(entry.getKey(), entry.getValue()); - } - if (allSkipped) { - // Null = skip the chart - return null; - } - return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); - } - } - - public static class DrilldownPie extends CustomChart { - - private final Callable>> callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public DrilldownPie(String chartId, Callable>> callable) { - super(chartId); - this.callable = callable; - } - - @Override - public JsonObjectBuilder.JsonObject getChartData() throws Exception { - JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); - Map> map = callable.call(); - if (map == null || map.isEmpty()) { - // Null = skip the chart - return null; - } - boolean reallyAllSkipped = true; - for (Map.Entry> entryValues : map.entrySet()) { - JsonObjectBuilder valueBuilder = new JsonObjectBuilder(); - boolean allSkipped = true; - for (Map.Entry valueEntry : map.get(entryValues.getKey()).entrySet()) { - valueBuilder.appendField(valueEntry.getKey(), valueEntry.getValue()); - allSkipped = false; - } - if (!allSkipped) { - reallyAllSkipped = false; - valuesBuilder.appendField(entryValues.getKey(), valueBuilder.build()); - } - } - if (reallyAllSkipped) { - // Null = skip the chart - return null; - } - return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); - } - } - - public abstract static class CustomChart { - - private final String chartId; - - protected CustomChart(String chartId) { - if (chartId == null) { - throw new IllegalArgumentException("chartId must not be null"); - } - this.chartId = chartId; - } - - public JsonObjectBuilder.JsonObject getRequestJsonObject( - BiConsumer errorLogger, boolean logErrors) { - JsonObjectBuilder builder = new JsonObjectBuilder(); - builder.appendField("chartId", chartId); - try { - JsonObjectBuilder.JsonObject data = getChartData(); - if (data == null) { - // If the data is null we don't send the chart. - return null; - } - builder.appendField("data", data); - } catch (Throwable t) { - if (logErrors) { - errorLogger.accept("Failed to get data for custom chart with id " + chartId, t); - } - return null; - } - return builder.build(); - } - - protected abstract JsonObjectBuilder.JsonObject getChartData() throws Exception; - } - - public static class SingleLineChart extends CustomChart { - - private final Callable callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public SingleLineChart(String chartId, Callable callable) { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - int value = callable.call(); - if (value == 0) { - // Null = skip the chart - return null; - } - return new JsonObjectBuilder().appendField("value", value).build(); - } - } - - /** - * An extremely simple JSON builder. - * - *

    While this class is neither feature-rich nor the most performant one, it's sufficient enough - * for its use-case. - */ - public static class JsonObjectBuilder { - - private StringBuilder builder = new StringBuilder(); - - private boolean hasAtLeastOneField = false; - - public JsonObjectBuilder() { - builder.append("{"); - } - - /** - * Appends a null field to the JSON. - * - * @param key The key of the field. - * @return A reference to this object. - */ - public JsonObjectBuilder appendNull(String key) { - appendFieldUnescaped(key, "null"); - return this; - } - - /** - * Appends a string field to the JSON. - * - * @param key The key of the field. - * @param value The value of the field. - * @return A reference to this object. - */ - public JsonObjectBuilder appendField(String key, String value) { - if (value == null) { - throw new IllegalArgumentException("JSON value must not be null"); - } - appendFieldUnescaped(key, "\"" + escape(value) + "\""); - return this; - } - - /** - * Appends an integer field to the JSON. - * - * @param key The key of the field. - * @param value The value of the field. - * @return A reference to this object. - */ - public JsonObjectBuilder appendField(String key, int value) { - appendFieldUnescaped(key, String.valueOf(value)); - return this; - } - - /** - * Appends an object to the JSON. - * - * @param key The key of the field. - * @param object The object. - * @return A reference to this object. - */ - public JsonObjectBuilder appendField(String key, JsonObject object) { - if (object == null) { - throw new IllegalArgumentException("JSON object must not be null"); - } - appendFieldUnescaped(key, object.toString()); - return this; - } - - /** - * Appends a string array to the JSON. - * - * @param key The key of the field. - * @param values The string array. - * @return A reference to this object. - */ - public JsonObjectBuilder appendField(String key, String[] values) { - if (values == null) { - throw new IllegalArgumentException("JSON values must not be null"); - } - String escapedValues = - Arrays.stream(values) - .map(value -> "\"" + escape(value) + "\"") - .collect(Collectors.joining(",")); - appendFieldUnescaped(key, "[" + escapedValues + "]"); - return this; - } - - /** - * Appends an integer array to the JSON. - * - * @param key The key of the field. - * @param values The integer array. - * @return A reference to this object. - */ - public JsonObjectBuilder appendField(String key, int[] values) { - if (values == null) { - throw new IllegalArgumentException("JSON values must not be null"); - } - String escapedValues = - Arrays.stream(values).mapToObj(String::valueOf).collect(Collectors.joining(",")); - appendFieldUnescaped(key, "[" + escapedValues + "]"); - return this; - } - - /** - * Appends an object array to the JSON. - * - * @param key The key of the field. - * @param values The integer array. - * @return A reference to this object. - */ - public JsonObjectBuilder appendField(String key, JsonObject[] values) { - if (values == null) { - throw new IllegalArgumentException("JSON values must not be null"); - } - String escapedValues = - Arrays.stream(values).map(JsonObject::toString).collect(Collectors.joining(",")); - appendFieldUnescaped(key, "[" + escapedValues + "]"); - return this; - } - - /** - * Appends a field to the object. - * - * @param key The key of the field. - * @param escapedValue The escaped value of the field. - */ - private void appendFieldUnescaped(String key, String escapedValue) { - if (builder == null) { - throw new IllegalStateException("JSON has already been built"); - } - if (key == null) { - throw new IllegalArgumentException("JSON key must not be null"); - } - if (hasAtLeastOneField) { - builder.append(","); - } - builder.append("\"").append(escape(key)).append("\":").append(escapedValue); - hasAtLeastOneField = true; - } - - /** - * Builds the JSON string and invalidates this builder. - * - * @return The built JSON string. - */ - public JsonObject build() { - if (builder == null) { - throw new IllegalStateException("JSON has already been built"); - } - JsonObject object = new JsonObject(builder.append("}").toString()); - builder = null; - return object; - } - - /** - * Escapes the given string like stated in https://www.ietf.org/rfc/rfc4627.txt. - * - *

    This method escapes only the necessary characters '"', '\'. and '\u0000' - '\u001F'. - * Compact escapes are not used (e.g., '\n' is escaped as "\u000a" and not as "\n"). - * - * @param value The value to escape. - * @return The escaped value. - */ - private static String escape(String value) { - final StringBuilder builder = new StringBuilder(); - for (int i = 0; i < value.length(); i++) { - char c = value.charAt(i); - if (c == '"') { - builder.append("\\\""); - } else if (c == '\\') { - builder.append("\\\\"); - } else if (c <= '\u000F') { - builder.append("\\u000").append(Integer.toHexString(c)); - } else if (c <= '\u001F') { - builder.append("\\u00").append(Integer.toHexString(c)); - } else { - builder.append(c); - } - } - return builder.toString(); - } - - /** - * A super simple representation of a JSON object. - * - *

    This class only exists to make methods of the {@link JsonObjectBuilder} type-safe and not - * allow a raw string inputs for methods like {@link JsonObjectBuilder#appendField(String, - * JsonObject)}. - */ - public static class JsonObject { - - private final String value; - - private JsonObject(String value) { - this.value = value; - } - - @Override - public String toString() { - return value; - } - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/delilaheve/AnvilEventListener.kt b/src/main/kotlin/io/delilaheve/AnvilEventListener.kt new file mode 100644 index 0000000..4139067 --- /dev/null +++ b/src/main/kotlin/io/delilaheve/AnvilEventListener.kt @@ -0,0 +1,171 @@ +package io.delilaheve + +import io.delilaheve.util.ConfigOptions +import io.delilaheve.util.EnchantmentUtil.combineWith +import io.delilaheve.util.EnchantmentUtil.enchantmentName +import io.delilaheve.util.ItemUtil.canMergeWith +import io.delilaheve.util.ItemUtil.findEnchantments +import io.delilaheve.util.ItemUtil.isBook +import io.delilaheve.util.ItemUtil.repairFrom +import io.delilaheve.util.ItemUtil.setEnchantmentsUnsafe +import org.bukkit.event.Event +import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority.HIGHEST +import org.bukkit.event.Listener +import org.bukkit.event.inventory.InventoryClickEvent +import org.bukkit.event.inventory.PrepareAnvilEvent +import org.bukkit.inventory.AnvilInventory +import org.bukkit.inventory.InventoryView.Property.REPAIR_COST +import org.bukkit.inventory.ItemStack +import org.bukkit.inventory.meta.Repairable +import xyz.alexcrea.group.ConflictType +import kotlin.math.min + +/** + * Listener for anvil events + */ +class AnvilEventListener : Listener { + + companion object { + // Anvil's output slot + private const val ANVIL_INPUT_LEFT = 0 + private const val ANVIL_INPUT_RIGHT = 1 + private const val ANVIL_OUTPUT_SLOT = 2 + } + + /** + * Event handler logic for when an anvil contains items to be combined + */ + @EventHandler(priority = HIGHEST) + fun anvilCombineCheck(event: PrepareAnvilEvent) { + val inventory = event.inventory + val first = inventory.getItem(ANVIL_INPUT_LEFT) ?: return + val second = inventory.getItem(ANVIL_INPUT_RIGHT) ?: return + if (first.canMergeWith(second)) { + // Should find player + val player = event.view.player + + val newEnchants = first.findEnchantments() + .combineWith(second.findEnchantments(), first.type, player) + val resultItem = first.clone() + resultItem.setEnchantmentsUnsafe(newEnchants) + + var anvilCost = calculateCost(first, second, resultItem) + if (!first.isBook() && !second.isBook()) { + // we only need to be concerned with repair when neither item is a book + val repaired = resultItem.repairFrom(first, second) + anvilCost += if(repaired) 2 else 0 + } + + // Test if nothing change and stop. + if(first == resultItem){ + event.result = null + return + } + + // Rename item and add renaming cost + resultItem.itemMeta?.let { + if(!it.displayName.contentEquals(inventory.renameText)){ + it.setDisplayName(inventory.renameText) + anvilCost += ConfigOptions.itemRepairCost + } + resultItem.itemMeta = it + } + + if (ConfigOptions.limitRepairCost) { + anvilCost = min(anvilCost, ConfigOptions.limitRepairValue) + } + + event.result = resultItem + + /* Because Minecraft likes to have the final say in the repair cost displayed + * we need to wait for the event to end before overriding it, this ensures that + * we have the final say in the process. */ + UnsafeEnchants.instance + .server + .scheduler + .runTask(UnsafeEnchants.instance, Runnable { + if (ConfigOptions.removeRepairLimit) { + inventory.maximumRepairCost = Int.MAX_VALUE + } + inventory.repairCost = anvilCost + event.view.setProperty(REPAIR_COST, anvilCost) + }) + } + } + + /** + * Event handler logic for when a player is trying to pull an item out of the anvil + */ + @EventHandler(ignoreCancelled = true) + fun anvilExtractionCheck(event: InventoryClickEvent) { + //val player = event.whoClicked as? Player ?: return + val inventory = event.inventory as? AnvilInventory ?: return + if (event.rawSlot != ANVIL_OUTPUT_SLOT) { return } + val output = inventory.getItem(ANVIL_OUTPUT_SLOT) ?: return + // Is true if there was no change. probably when there are conflict + if(output == inventory.getItem(ANVIL_INPUT_LEFT)){ + event.result = Event.Result.DENY + return + } + event.result = Event.Result.ALLOW + } + + /** + * Function to calculate most of the xp requirement for the anvil fuse + * Change result work penalty for future use + */ + private fun calculateCost(left: ItemStack, right: ItemStack, result: ItemStack): Int{ + // Extracted From https://minecraft.fandom.com/wiki/Anvil_mechanics#Enchantment_equation + // Calculate work penality + val leftPenality = (left.itemMeta as? Repairable)?.repairCost ?: 0 + val rightPenality = (right.itemMeta as? Repairable)?.repairCost ?: 0 + + // Calculate right value and illegal enchant penalty + var rightValue = 0 + var illegalPenalty = 0 + + val rightIsFormBook = right.isBook() + val resultEnchs = result.findEnchantments() + val resultEnchsKeys = HashSet(resultEnchs.keys) + + for (enchantment in right.findEnchantments()) { + // count enchant as illegal enchant if it conflicts with another enchant or not in result + if((enchantment.key !in resultEnchsKeys)){ + resultEnchsKeys.add(enchantment.key) + val conflictType = UnsafeEnchants.conflictManager.isConflicting(resultEnchsKeys,result.type,enchantment.key) + resultEnchsKeys.remove(enchantment.key) + + if(ConflictType.BIG_CONFLICT == conflictType){ + illegalPenalty += ConfigOptions.sacrificeIllegalCost + } + continue + } + // We know "enchantment.key in resultEnchs" true + val resultLevel = resultEnchs[enchantment.key]!! + + val enchantmentMultiplier = ConfigOptions.enchantmentValue(enchantment.key, rightIsFormBook) + val value = resultLevel * enchantmentMultiplier + UnsafeEnchants.log("Value for ${enchantment.key.enchantmentName} level ${enchantment.value} is $value") + rightValue+=value + + } + + // Try to set work penality for the result item + result.itemMeta?.let { + (it as? Repairable)?.repairCost = leftPenality*2+1 + result.itemMeta = it + } + + UnsafeEnchants.log("Calculated cost: " + + "leftPenality: $leftPenality, " + + "rightPenality: $rightPenality, " + + "rightValue: $rightValue, " + + "illegalPenalty: $illegalPenalty," + + "result penality: ${(result.itemMeta as? Repairable)?.repairCost ?: "none"}") + + // We are missing [Renaming Cost] + [Refilling Durability] but it will be handled later + return rightValue + leftPenality + rightPenality + illegalPenalty + } + +} diff --git a/src/main/kotlin/io/delilaheve/CustomAnvil.kt b/src/main/kotlin/io/delilaheve/CustomAnvil.kt deleted file mode 100644 index 4d99faf..0000000 --- a/src/main/kotlin/io/delilaheve/CustomAnvil.kt +++ /dev/null @@ -1,323 +0,0 @@ -package io.delilaheve - -import io.delilaheve.util.ConfigOptions -import org.bukkit.Bukkit -import org.bukkit.configuration.file.YamlConfiguration -import org.bukkit.plugin.java.JavaPlugin -import xyz.alexcrea.cuanvil.api.event.CAConfigReadyEvent -import xyz.alexcrea.cuanvil.api.event.CAEnchantRegistryReadyEvent -import xyz.alexcrea.cuanvil.command.CustomAnvilCommand -import xyz.alexcrea.cuanvil.command.EditConfigExecutor -import xyz.alexcrea.cuanvil.command.ReloadExecutor -import xyz.alexcrea.cuanvil.config.ConfigHolder -import xyz.alexcrea.cuanvil.dependency.DependencyManager -import xyz.alexcrea.cuanvil.dependency.MinecraftVersionUtil -import xyz.alexcrea.cuanvil.dependency.economy.EconomyManager -import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil -import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry -import xyz.alexcrea.cuanvil.gui.config.MainConfigGui -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant -import xyz.alexcrea.cuanvil.listener.AnvilCloseListener -import xyz.alexcrea.cuanvil.listener.AnvilResultListener -import xyz.alexcrea.cuanvil.listener.ChatEventListener -import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener -import xyz.alexcrea.cuanvil.update.ModrinthUpdateChecker -import xyz.alexcrea.cuanvil.update.PluginSetDefault -import xyz.alexcrea.cuanvil.update.UpdateHandler -import xyz.alexcrea.cuanvil.util.MetricsUtil -import java.io.File -import java.io.FileReader -import java.util.logging.Level - -/** - * Bukkit/Spigot/Paper plugin to alter anvil feature - */ -open class CustomAnvil : JavaPlugin() { - - companion object { - // pluginIDS - private const val modrinthPluginID = "S75Ueiq9" - - // Permission string required to use the plugin's features - const val affectedByPluginPermission = "ca.affected" - - // Permission string required to bypass enchantment conflicts test - const val bypassFusePermission = "ca.bypass.fuse" - - // Permission string required to bypass enchantment conflicts test - const val bypassLevelPermission = "ca.bypass.level" - - // Permission string required to reload the config - const val commandReloadPermission = "ca.command.reload" - - // Permission string required to get diagnostic data - const val diagnosticPermission = "ca.command.diagnostic" - - // Permission string required to edit the plugin's config - const val editConfigPermission = "ca.config.edit" - - - // Command Name to reload the config - const val commandReloadName = "anvilconfigreload" - - // Config command name - const val commandConfigName = "customanvilconfig" - - // Current plugin instance - lateinit var instance: CustomAnvil - - // Chat message listener - lateinit var chatListener: ChatEventListener - - var latestVer: String? = null - - /** - * Logging handler - */ - @JvmStatic fun log(message: String) { - if (ConfigOptions.debugLog) { - instance.logger.info(message) - } - } - - /** - * Vebose Logging handler - */ - fun verboseLog(message: String) { - if (ConfigOptions.verboseDebugLog) { - instance.logger.info(message) - } - } - - } - - // stop plugin if we do not force a dirty start (true by default) - // Return true if start was stopped - private fun tryDirtyStart(): Boolean { - if(!ConfigHolder.DEFAULT_CONFIG.config.getBoolean("dirty_start", false)) { - Bukkit.getPluginManager().disablePlugin(this) - return true - } - return false - } - - // stop plugin if we force a safe start (false by default) - // Return true if start was stopped - private fun trySafeStart(): Boolean { - if(ConfigHolder.DEFAULT_CONFIG.config.getBoolean("safe_start", false)) { - Bukkit.getPluginManager().disablePlugin(this) - return true - } - return false - } - - /** - * Setup plugin for use - */ - override fun onEnable() { - instance = this - try { - legacyCheck() - } catch (e: Exception) { - logger.log(Level.SEVERE, "error trying to check for legacy system", e) - MetricsUtil.trackError(e) - if(trySafeStart()) return - } - - // Add commands - try { - prepareCommand() - } catch (e: Exception) { - logger.log(Level.SEVERE, "error trying to register commands", e) - MetricsUtil.trackError(e) - if(trySafeStart()) return - } - - // Load default configuration - try { - if(!ConfigHolder.loadDefaultConfig()) - throw RuntimeException("Error loading configuration file") - } catch (e: Exception) { - logger.log(Level.SEVERE, "error occurred loading default configuration", e) - MetricsUtil.trackError(e) - if(tryDirtyStart()) return - } - - // Load dependency - try { - DependencyManager.loadDependency() - } catch (e: Exception) { - logger.log(Level.SEVERE, "error loading dependency compatibility", e) - MetricsUtil.trackError(e) - if(tryDirtyStart()) return - } - - // Register listeners - try { - registerListeners() - } catch (e: Exception) { - logger.log(Level.SEVERE, "error registering listeners", e) - MetricsUtil.trackError(e) - if(tryDirtyStart()) return - } - - // Load metrics - MetricsUtil.loadMetrics(this) - - // Load other thing later. - // It is so other dependent plugins can implement there event listener before we fire them. - DependencyManager.scheduler.scheduleGlobally(this) { loadEnchantmentSystemDirty() } - } - - override fun onDisable() { - MetricsUtil.shutdownMetrics() - } - - private fun loadEnchantmentSystemDirty() { - try { - loadEnchantmentSystem() - } catch (e: Exception) { - logger.log(Level.SEVERE, "error initializing enchantment system", e) - MetricsUtil.trackError(e) - tryDirtyStart() - } - } - - private fun legacyCheck() { - // Disable old plugin name if exist - val potentialPlugin = Bukkit.getPluginManager().getPlugin("UnsafeEnchantsPlus") - if (potentialPlugin != null) { - Bukkit.getPluginManager().disablePlugin(potentialPlugin) - logger.warning("An old version of this plugin was detected") - logger.warning("Please note CustomAnvil is a more recent version of UnsafeEnchantsPlus") - } - - val isPaper = PlatformUtil.isPaper - if(!isPaper) { - logger.warning("It seems you are using spigot") - logger.warning("Please take notice that spigot is less supported than paper and derivatives") - if(MinecraftVersionUtil.isTooNewForSpigot) { - logger.warning("If replace too expensive is not working this is likely because of spigot") - logger.warning("As native nms is not supported for spigot starting 26.1") - } - } - - val loader = if(isPaper) "paper" else "spigot" - - val version = description.version - val featured = if(version.contains("dev")) null else true - - ModrinthUpdateChecker(modrinthPluginID, loader, null) - .setFeatured(featured) - .setOnError { - logger.log(Level.WARNING, "error trying to fetch latest update", it) - } - .checkVersion { latestVer: String? -> - CustomAnvil.latestVer = latestVer - if(latestVer == null || version.contains(latestVer)) return@checkVersion - - logger.warning("An update may be available: $latestVer") - } - } - - private fun registerListeners() { - // Register chat listener - chatListener = ChatEventListener() - server.pluginManager.registerEvents(chatListener, this) - - // Register anvil events - server.pluginManager.registerEvents(PrepareAnvilListener(), this) - server.pluginManager.registerEvents(AnvilResultListener(), this) - server.pluginManager.registerEvents(AnvilCloseListener(DependencyManager.packetManager), this) - } - - private fun loadEnchantmentSystem(){ - // Register enchantments - CAEnchantmentRegistry.getInstance().registerBukkit() - DependencyManager.registerEnchantments() - - val enchantReadyEvent = CAEnchantRegistryReadyEvent() - server.pluginManager.callEvent(enchantReadyEvent) - - // Load config - if (!ConfigHolder.loadNonDefaultConfig()) { - logger.log(Level.SEVERE,"Plugin has an issue while trying to load non default config... exiting...") - server.pluginManager.disablePlugin(this) - return - } - - // Handle minecraft and plugin updates - UpdateHandler.handleUpdates() - - // Register enchantment of compatible plugin and load configuration change. - DependencyManager.handleCompatibilityConfig() - - // Call config event - val configReadyEvent = CAConfigReadyEvent() - server.pluginManager.callEvent(configReadyEvent) - - // Load gui constants //TODO maybe something better later - MainConfigGui.getInstance().init(DependencyManager.packetManager) - GuiSharedConstant.loadConstants() - - // Prepare economy if possible - EconomyManager.setupEconomy(this) - - // Finally, re add default we may be missing - PluginSetDefault.reAddMissingDefault() - } - - fun reloadResource( - resourceName: String, - hardFailSafe: Boolean = true - ): YamlConfiguration? { - // Save default resource - val file = File(dataFolder, resourceName) - if (!file.exists()) { - saveResource(resourceName, false) - } - - return reloadResource(file, hardFailSafe) - } - - // Unlike above function. this function will not clone default from jar. - fun reloadResource( - resourceFile: File, - hardFailSafe: Boolean = true - ): YamlConfiguration? { - // Test if file exist - if (!resourceFile.exists()) { - return null - } - - // Load resource - val yamlConfig = YamlConfiguration() - try { - val configReader = FileReader(resourceFile) - yamlConfig.load(configReader) - } catch (test: Exception) { - if (hardFailSafe) { - // This is important and may impact gameplay if it does not load. - // Failsafe is to stop the plugin - logger.severe("Resource ${resourceFile.path} Could not be load or reload.") - logger.severe("Disabling plugin.") - Bukkit.getPluginManager().disablePlugin(this) - } else { - logger.warning("Resource ${resourceFile.path} Could not be load or reload.") - } - return null - } - return yamlConfig - } - - fun prepareCommand() { - var command = getCommand(commandReloadName) - command?.setExecutor(ReloadExecutor()) - - command = getCommand(commandConfigName) - command?.setExecutor(EditConfigExecutor()) - - CustomAnvilCommand(this) - } - -} diff --git a/src/main/kotlin/io/delilaheve/UnsafeEnchants.kt b/src/main/kotlin/io/delilaheve/UnsafeEnchants.kt new file mode 100644 index 0000000..f5188b2 --- /dev/null +++ b/src/main/kotlin/io/delilaheve/UnsafeEnchants.kt @@ -0,0 +1,99 @@ +package io.delilaheve + +import io.delilaheve.util.ConfigOptions +import org.bukkit.Bukkit +import org.bukkit.configuration.file.YamlConfiguration +import org.bukkit.plugin.java.JavaPlugin +import xyz.alexcrea.group.EnchantConflictManager +import xyz.alexcrea.group.ItemGroupManager +import java.io.File +import java.io.FileReader + +/** + * Bukkit/Spigot/Paper plugin to alter enchantment max + * levels and allow unsafe enchantment combinations + */ +class UnsafeEnchants : JavaPlugin() { + + companion object { + // Permission string required to use the plugin's features + const val unsafePermission = "ue.unsafe" + // Permission string required to bypass enchantment conflicts test + const val bypassFusePermission = "ue.bypass.fuse" + // Permission string required to bypass enchantment conflicts test + const val bypassLevelPermission = "ue.bypass.level" + + // Item Grouping Configuration file name + const val itemGroupingConfigName = "item_groups.yml" + // Conflict Configuration file name + const val enchantConflicConfigName = "enchant_conflict.yml" + + // Current plugin instance + lateinit var instance: UnsafeEnchants + // Current item grouping configuration instance + lateinit var conflictManager: EnchantConflictManager + + /** + * Logging handler + */ + fun log(message: String) { + if (ConfigOptions.debugLog) { + instance.logger.info(message) + } + } + } + + /** + * Setup plugin for use + */ + override fun onEnable() { + instance = this + saveDefaultConfig() + + // Load material grouping config + val itemGroupConfig = reloadResource(itemGroupingConfigName) ?: return + // Read material groups from config + val itemGroupsManager = ItemGroupManager() + itemGroupsManager.prepareGroups(itemGroupConfig) + + // Load enchantment conflicts config + val conflictConfig = reloadResource(enchantConflicConfigName) ?: return + // Read conflicts from config and material group manager + conflictManager = EnchantConflictManager() + conflictManager.prepareConflicts(conflictConfig,itemGroupsManager) + + server.pluginManager.registerEvents( + AnvilEventListener(), + this + ) + + } + + private fun reloadResource(resourceName: String, + hardFailSafe:Boolean = true): YamlConfiguration?{ + // Save default resource + val file = File(dataFolder,resourceName) + if(!file.exists()){ + saveResource(resourceName,false) + } + // Load resource + val yamlConfig = YamlConfiguration() + try { + val configReader = FileReader(file) + yamlConfig.load(configReader) + } catch (test: Exception){ + if(hardFailSafe){ + // This is important and may impact gameplay if it does not load. + // Failsafe is to stop the plugin + logger.severe("Resource $resourceName Could not be load or reload.") + logger.severe("Disabling plugin.") + Bukkit.getPluginManager().disablePlugin(this) + }else{ + logger.warning("Resource $resourceName Could not be load or reload.") + } + return null + } + return yamlConfig + } + +} diff --git a/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt b/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt index 9dc85f9..d548cb2 100644 --- a/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt +++ b/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt @@ -1,434 +1,124 @@ package io.delilaheve.util -import io.delilaheve.CustomAnvil +import io.delilaheve.UnsafeEnchants import io.delilaheve.util.EnchantmentUtil.enchantmentName -import org.bukkit.NamespacedKey -import org.bukkit.entity.HumanEntity -import xyz.alexcrea.cuanvil.anvil.AnvilUseType -import xyz.alexcrea.cuanvil.config.ConfigHolder -import xyz.alexcrea.cuanvil.config.WorkPenaltyType -import xyz.alexcrea.cuanvil.config.WorkPenaltyType.WorkPenaltyPart -import xyz.alexcrea.cuanvil.dependency.DependencyManager -import xyz.alexcrea.cuanvil.dependency.economy.EconomyManager -import xyz.alexcrea.cuanvil.enchant.CAEnchantment -import xyz.alexcrea.cuanvil.util.dialog.AnvilRenameDialogUtil -import java.math.BigDecimal -import java.util.* +import org.bukkit.enchantments.Enchantment /** * Config option accessors */ object ConfigOptions { - // ---------------------- - // Path for config values - // ---------------------- - - const val METRIC_TYPE = "metric_type" - const val METRIC_COLLECT_ERROR = "metric_collect_errors" - - const val CAP_ANVIL_COST = "limit_repair_cost" - const val MAX_ANVIL_COST = "limit_repair_value" - const val REMOVE_ANVIL_COST_LIMIT = "remove_repair_limit" - - const val REPLACE_TOO_EXPENSIVE = "replace_too_expensive" - - const val ITEM_REPAIR_COST = "item_repair_cost" - const val UNIT_REPAIR_COST = "unit_repair_cost" - - const val ITEM_RENAME_COST = "item_rename_cost" - - const val SACRIFICE_ILLEGAL_COST = "sacrifice_illegal_enchant_cost" - const val ADD_BOOK_ENCHANTMENT_AS_STORED_ENCHANTMENT = "add_book_enchantment_as_stored_enchantment" - - // Color related config - const val ALLOW_COLOR_CODE = "allow_color_code" - const val ALLOW_HEXADECIMAL_COLOR = "allow_hexadecimal_color" - const val ALLOW_MINIMESSAGE = "allow_minimessage" - const val PERMISSION_NEEDED_FOR_COLOR = "permission_needed_for_color" - const val USE_OF_COLOR_COST = "use_of_color_cost" - - const val PER_COLOR_CODE_PERMISSION = "per_color_code_permission" - - // Work penalty config - const val WORK_PENALTY_ROOT = "work_penalty" - const val WORK_PENALTY_INCREASE = "shared_increase" - const val WORK_PENALTY_ADDITIVE = "shared_additive" - const val EXCLUSIVE_WORK_PENALTY_INCREASE = "exclusive_increase" - const val EXCLUSIVE_WORK_PENALTY_ADDITIVE = "exclusive_additive" - - // Enchant limit config - const val ENCHANT_COUNT_LIMIT_ROOT = "enchantment_count_limit" - const val ENCHANT_COUNT_LIMIT_DEFAULT = "$ENCHANT_COUNT_LIMIT_ROOT.default" - const val ENCHANT_COUNT_LIMIT_ITEMS = "$ENCHANT_COUNT_LIMIT_ROOT.items" - - const val ENCHANT_LIMIT_ROOT = "enchant_limits" - const val ENCHANT_VALUES_ROOT = "enchant_values" - - // Dialog menu rename - const val DIALOG_RENAME_ENABLED = "enable_dialog_rename" - const val DIALOG_MAX_SIZE = "dialog_rename_max_size" - const val DIALOG_RENAME_USE_PERMISSION = "permission_needed_for_dialog_rename" - const val DIALOG_KEEP_USER_TEXT = "dialog_rename_keep_user_text" - - // Others - const val DISABLE_MERGE_OVER_ROOT = "disable-merge-over" - - const val IMMUTABLE_ENCHANTMENT_LIST = "immutable_enchantments" - - // Monetary configs - const val MONETARY_USAGE_ROOT = "monetary_cost" - const val SHOULD_USE_MONEY = "$MONETARY_USAGE_ROOT.enabled" - const val MONEY_CURRENCY = "$MONETARY_USAGE_ROOT.currency" - const val MONETARY_MULTIPLIER_ROOT = "$MONETARY_USAGE_ROOT.multipliers" - + // Path for default enchantment limits + private const val DEFAULT_LIMIT_PATH = "default_limit" + // Path for limiting repair cost + private const val LIMIT_REPAIR_COST = "limit_repair_cost" + // Path for repair value limit + private const val LIMIT_REPAIR_VALUE = "limit_repair_value" + // Path for level cost on item repair + private const val ITEM_REPAIR_COST = "item_repair_cost" + // Path for level cost on illegal enchantment on sacrifice + private const val SACRIFICE_ILLEGAL_COST = "sacrifice_illegal_enchant_cost" + // Path for removing repair cost limits + private const val REMOVE_REPAIR_LIMIT = "remove_repair_limit" + // Root path for enchantment limits + private const val ENCHANT_LIMIT_ROOT = "enchant_limits" + // Root path for enchantment values + private const val ENCHANT_VALUES_ROOT = "enchant_values" // Keys for specific enchantment values private const val KEY_BOOK = "book" private const val KEY_ITEM = "item" + // Debug logging toggle path + private const val DEBUG_LOGGING = "debug_log" - // Debug flag - const val DEBUG_LOGGING = "debug_log" - const val VERBOSE_DEBUG_LOGGING = "debug_log_verbose" - - // ---------------------- - // Default config values - // ---------------------- - - const val DEFAULT_CAP_ANVIL_COST = false - const val DEFAULT_MAX_ANVIL_COST = 39 - const val DEFAULT_REMOVE_ANVIL_COST_LIMIT = false - - const val DEFAULT_REPLACE_TOO_EXPENSIVE = false - - const val DEFAULT_ITEM_REPAIR_COST = 2 - const val DEFAULT_UNIT_REPAIR_COST = 1 - - const val DEFAULT_ITEM_RENAME_COST = 1 - - const val DEFAULT_SACRIFICE_ILLEGAL_COST = 1 - const val DEFAULT_ADD_BOOK_ENCHANTMENT_AS_STORED_ENCHANTMENT = false - - const val DEFAULT_ENCHANT_COUNT_LIMIT = -1 - - // Color related config - const val DEFAULT_ALLOW_COLOR_CODE = false - const val DEFAULT_ALLOW_HEXADECIMAL_COLOR = false - const val DEFAULT_ALLOW_MINIMESSAGE = false - const val DEFAULT_PERMISSION_NEEDED_FOR_COLOR = true - const val DEFAULT_USE_OF_COLOR_COST = 0 - - const val DEFAULT_PER_COLOR_CODE_PERMISSION = false - - // Monetary configs - const val DEFAULT_SHOULD_USE_MONEY = false - const val DEFAULT_MONEY_CURRENCY = "default" - const val DEFAULT_MONEY_MULTIPLIER = 1.0 - - // Debug flag - private const val DEFAULT_DEBUG_LOG = false - private const val DEFAULT_VERBOSE_DEBUG_LOG = false - - // Dialog menu rename - const val DEFAULT_DIALOG_RENAME_ENABLED = false - const val DEFAULT_DIALOG_MAX_SIZE = 256 - const val DEFAULT_DIALOG_RENAME_USE_PERMISSION = false - const val DEFAULT_DIALOG_KEEP_USER_TEXT = true - - // ------------- - // Config Ranges - // ------------- - + // Default value for enchantment limits + private const val DEFAULT_ENCHANT_LIMIT = 5 + // Default value for limiting repair cost + private const val DEFAULT_LIMIT_REPAIR = true + // Default value for repair cost limit + private const val DEFAULT_LIMIT_REPAIR_VALUE = 39 + // Default value for level cost on item repair + private const val DEFAULT_ITEM_REPAIR_COST = 2 + // Default value for level cost on illegal enchantment on sacrifice + private const val DEFAULT_SACRIFICE_ILLEGAL_COST = 1 // Valid range for repair cost limit - @JvmField - val MAX_ANVIL_COST_RANGE = 0..1000 - - // Valid range for repair cost - @JvmField - val REPAIR_COST_RANGE = 0..1000 - - // Valid range for rename cost - @JvmField - val ITEM_RENAME_COST_RANGE = 0..1000 - - // Valid range for illegal enchantment conflict cost - @JvmField - val SACRIFICE_ILLEGAL_COST_RANGE = 0..1000 - - // Valid range for color use cost - @JvmField - val USE_OF_COLOR_COST_RANGE = 0..1000 - - @JvmField - val DIALOG_MAX_SIZE_RANGE = 0..Int.MAX_VALUE - + private val REPAIR_LIMIT_RANGE = 1..39 + // Valid range for repair cost limit + private val ITEM_REPAIR_COST_RANGE = 0..255 + // Valid range for repair cost limit + private val SACRIFICE_ILLEGAL_COST_RANGE = 0..255 + // Default for removing repair cost limits + private const val DEFAULT_REMOVE_LIMIT = false // Valid range for an enchantment limit - const val ENCHANT_LIMIT = 255 - - // Valid range for an enchantment count limit - @JvmField - val ENCHANT_COUNT_LIMIT_RANGE = -1..255 - - // -------------- - // Other defaults - // -------------- - + private val ENCHANT_LIMIT_RANGE = 1..255 // Default value for an enchantment multiplier private const val DEFAULT_ENCHANT_VALUE = 0 - - // Default max before merge disabled (negative mean enabled) - const val DEFAULT_MAX_BEFORE_MERGE_DISABLED = -1 - - // ----------- - // Permissions - // ----------- - private const val RENAME_DIALOG_PERMISSION = "ca.rename.dialog" - - // ------------- - // Get methods - // ------------- + // Default value for debug logging + private const val DEFAULT_DEBUG_LOG = false /** - * Whether to cap anvil costs + * Default enchantment limit */ - val doCapCost: Boolean + private val defaultEnchantLimit: Int get() { - return ConfigHolder.DEFAULT_CONFIG + return UnsafeEnchants.instance .config - .getBoolean(CAP_ANVIL_COST, DEFAULT_CAP_ANVIL_COST) + .getInt(DEFAULT_LIMIT_PATH, DEFAULT_ENCHANT_LIMIT) } /** - * Value to limit anvil costs to + * Whether to limit repair costs to the vanilla limit */ - val maxAnvilCost: Int + val limitRepairCost: Boolean get() { - return ConfigHolder.DEFAULT_CONFIG + return UnsafeEnchants.instance .config - .getInt(MAX_ANVIL_COST, DEFAULT_MAX_ANVIL_COST) - .takeIf { it in MAX_ANVIL_COST_RANGE } - ?: DEFAULT_MAX_ANVIL_COST + .getBoolean(LIMIT_REPAIR_COST, DEFAULT_LIMIT_REPAIR) } /** - * Whether to remove anvil cost limit + * Value to limit repair costs to */ - val doRemoveCostLimit: Boolean + val limitRepairValue: Int get() { - return ConfigHolder.DEFAULT_CONFIG + return UnsafeEnchants.instance .config - .getBoolean(REMOVE_ANVIL_COST_LIMIT, DEFAULT_REMOVE_ANVIL_COST_LIMIT) + .getInt(LIMIT_REPAIR_VALUE, DEFAULT_LIMIT_REPAIR_VALUE) + .takeIf { it in REPAIR_LIMIT_RANGE } + ?: DEFAULT_LIMIT_REPAIR_VALUE } /** - * Whether to remove repair cost limit - */ - val doReplaceTooExpensive: Boolean - get() { - return ConfigHolder.DEFAULT_CONFIG - .config - .getBoolean(REPLACE_TOO_EXPENSIVE, DEFAULT_REPLACE_TOO_EXPENSIVE) - } - - /** - * Value of an item repair + * Value to limit repair costs to */ val itemRepairCost: Int get() { - return ConfigHolder.DEFAULT_CONFIG + return UnsafeEnchants.instance .config .getInt(ITEM_REPAIR_COST, DEFAULT_ITEM_REPAIR_COST) - .takeIf { it in REPAIR_COST_RANGE } + .takeIf { it in ITEM_REPAIR_COST_RANGE } ?: DEFAULT_ITEM_REPAIR_COST } /** - * Value of an item repair - */ - val unitRepairCost: Int - get() { - return ConfigHolder.DEFAULT_CONFIG - .config - .getInt(UNIT_REPAIR_COST, DEFAULT_UNIT_REPAIR_COST) - .takeIf { it in REPAIR_COST_RANGE } - ?: DEFAULT_UNIT_REPAIR_COST - } - - /** - * Value of an item rename - */ - val itemRenameCost: Int - get() { - return ConfigHolder.DEFAULT_CONFIG - .config - .getInt(ITEM_RENAME_COST, DEFAULT_ITEM_RENAME_COST) - .takeIf { it in ITEM_RENAME_COST_RANGE } - ?: DEFAULT_ITEM_RENAME_COST - } - - /** - * Value of illegal enchantment conflict + * Value to limit repair costs to */ val sacrificeIllegalCost: Int get() { - return ConfigHolder.DEFAULT_CONFIG + return UnsafeEnchants.instance .config .getInt(SACRIFICE_ILLEGAL_COST, DEFAULT_SACRIFICE_ILLEGAL_COST) .takeIf { it in SACRIFICE_ILLEGAL_COST_RANGE } ?: DEFAULT_SACRIFICE_ILLEGAL_COST } - /** - * Consider book enchantment as book stored enchantment + * Whether to remove repair cost limit */ - val addBookEnchantmentAsStoredEnchantment : Boolean - get(){ - return ConfigHolder.DEFAULT_CONFIG + val removeRepairLimit: Boolean + get() { + return UnsafeEnchants.instance .config - .getBoolean(ADD_BOOK_ENCHANTMENT_AS_STORED_ENCHANTMENT, DEFAULT_ADD_BOOK_ENCHANTMENT_AS_STORED_ENCHANTMENT) - } - - /** - * Allow usage of color code - */ - val allowColorCode: Boolean - get() { - return ConfigHolder.DEFAULT_CONFIG - .config - .getBoolean(ALLOW_COLOR_CODE, DEFAULT_ALLOW_COLOR_CODE) - } - - /** - * Allow usage of hexadecimal color - */ - val allowHexadecimalColor: Boolean - get() { - return ConfigHolder.DEFAULT_CONFIG - .config - .getBoolean(ALLOW_HEXADECIMAL_COLOR, DEFAULT_ALLOW_HEXADECIMAL_COLOR) - } - - /** - * Allow usage of minimessage formating - */ - val allowMinimessage: Boolean - get() { - return ConfigHolder.DEFAULT_CONFIG - .config - .getBoolean(ALLOW_MINIMESSAGE, DEFAULT_ALLOW_MINIMESSAGE) - } - - /** - * If one of the color component is enabled - */ - val renameColorPossible: Boolean - get() { - return allowColorCode || allowHexadecimalColor || allowMinimessage - } - - /** - * If players need a permission to use color - */ - val permissionNeededForColor: Boolean - get() { - return ConfigHolder.DEFAULT_CONFIG - .config - .getBoolean(PERMISSION_NEEDED_FOR_COLOR, DEFAULT_PERMISSION_NEEDED_FOR_COLOR) - } - - /** - * Should each color code require a permission - */ - val usePerColorCodePermission: Boolean - get() { - return ConfigHolder.DEFAULT_CONFIG - .config - .getBoolean(PER_COLOR_CODE_PERMISSION, DEFAULT_PER_COLOR_CODE_PERMISSION) - } - - /** - * How many xp should use of color should cost - */ - val useOfColorCost: Int - get() { - return ConfigHolder.DEFAULT_CONFIG - .config - .getInt(USE_OF_COLOR_COST, DEFAULT_USE_OF_COLOR_COST) - .takeIf { it in USE_OF_COLOR_COST_RANGE } - ?: DEFAULT_USE_OF_COLOR_COST - } - - /** - * How work penalties should work - */ - val workPenaltyType: WorkPenaltyType - get() { - val penaltyMap = EnumMap(AnvilUseType::class.java) - - for (type in AnvilUseType.entries) { - penaltyMap[type] = workPenaltyPart(type) - } - - return WorkPenaltyType(penaltyMap) - } - - /** - * How work penalty should work - */ - fun workPenaltyPart(type: AnvilUseType): WorkPenaltyPart { - val config = ConfigHolder.DEFAULT_CONFIG.config - - // Find values - val defaultPenalty = type.defaultPenalty - val section = config.getConfigurationSection(type.path) ?: return defaultPenalty - - val penaltyIncrease = section.getBoolean(WORK_PENALTY_INCREASE, defaultPenalty.penaltyIncrease) - val penaltyAdditive = section.getBoolean(WORK_PENALTY_ADDITIVE, defaultPenalty.penaltyAdditive) - val exclusivePenaltyIncrease = - section.getBoolean(EXCLUSIVE_WORK_PENALTY_INCREASE, defaultPenalty.exclusivePenaltyIncrease) - val exclusivePenaltyAdditive = - section.getBoolean(EXCLUSIVE_WORK_PENALTY_ADDITIVE, defaultPenalty.exclusivePenaltyAdditive) - - return WorkPenaltyPart(penaltyIncrease, penaltyAdditive, exclusivePenaltyIncrease, exclusivePenaltyAdditive) - } - - /** - * Get material enchantment count limit - * - * @return the current enchantment limit. -1 if none - */ - fun getEnchantCountLimit(type: NamespacedKey): Int? { - val limit = materialEnchantCountLimit(type) - - if(limit != null) return limit - if(defaultEnchantCountLimit >= 0) return defaultEnchantCountLimit - - return DependencyManager.ecoEnchantCompatibility?.getEcoLevelLimit() - } - - /** - * Get the material enchantment count limit. - * - * @return The current enchantment limit. -1 if none - */ - private fun materialEnchantCountLimit(type: NamespacedKey): Int? { - val path = "$ENCHANT_COUNT_LIMIT_ITEMS.${type.key.lowercase()}" - if(!ConfigHolder.DEFAULT_CONFIG.config.isInt(path)) - return null - - return ConfigHolder.DEFAULT_CONFIG.config - .getInt(path) - .takeIf { it in ENCHANT_COUNT_LIMIT_RANGE } - } - /** - * User configured default enchantment count limit - */ - val defaultEnchantCountLimit: Int - get() { - return ConfigHolder.DEFAULT_CONFIG - .config - .getInt(ENCHANT_COUNT_LIMIT_DEFAULT, DEFAULT_ENCHANT_COUNT_LIMIT) - .takeIf { it in ENCHANT_COUNT_LIMIT_RANGE } - ?: DEFAULT_ENCHANT_COUNT_LIMIT + .getBoolean(REMOVE_REPAIR_LIMIT, DEFAULT_REMOVE_LIMIT) } /** @@ -436,105 +126,21 @@ object ConfigOptions { */ val debugLog: Boolean get() { - return ConfigHolder.DEFAULT_CONFIG + return UnsafeEnchants.instance .config .getBoolean(DEBUG_LOGGING, DEFAULT_DEBUG_LOG) } - /** - * Whether to show verbose debug logging - */ - val verboseDebugLog: Boolean - get() { - return ConfigHolder.DEFAULT_CONFIG - .config - .getBoolean(VERBOSE_DEBUG_LOGGING, DEFAULT_VERBOSE_DEBUG_LOG) - } - - /** - * Is the dialog menu for rename enabled - */ - val doRenameDialog: Boolean - get() { - return ConfigHolder.DEFAULT_CONFIG - .config - .getBoolean(DIALOG_RENAME_ENABLED, DEFAULT_DIALOG_RENAME_ENABLED) - } - - /** - * Do the dialog menu require permission - */ - val doRenameDialogUsePermission: Boolean - get() { - return ConfigHolder.DEFAULT_CONFIG - .config - .getBoolean(DIALOG_RENAME_USE_PERMISSION, DEFAULT_DIALOG_RENAME_USE_PERMISSION) - } - - fun canUseDialogRename(player: HumanEntity): Boolean { - if(!doRenameDialog || !AnvilRenameDialogUtil.anvilRenameDialog.canSendDialog()) return false - if(doRenameDialogUsePermission && !player.hasPermission(RENAME_DIALOG_PERMISSION)) return false - - return true - } - - /** - * Do the dialog menu require permission - */ - val renameDialogMaxSize: Int - get() { - return ConfigHolder.DEFAULT_CONFIG - .config - .getInt(DIALOG_MAX_SIZE, DEFAULT_DIALOG_MAX_SIZE) - .takeIf { it in DIALOG_MAX_SIZE_RANGE } - ?: Int.MAX_VALUE - } - - /** - * Should the text used for rename should be kept in the item's pdc - */ - val shouldKeepRenameText: Boolean - get() { - return ConfigHolder.DEFAULT_CONFIG - .config - .getBoolean(DIALOG_KEEP_USER_TEXT, DEFAULT_DIALOG_KEEP_USER_TEXT) - } - /** * Get the given [enchantment]'s limit */ - fun enchantLimit(enchantment: CAEnchantment): Int { - val limit = rawEnchantLimit(enchantment) - if(limit >= 0) return limit.coerceAtMost(ENCHANT_LIMIT) - - // get default - return enchantment.defaultMaxLevel() - } - - /** - * Get the given [enchantment]'s limit - */ - fun rawEnchantLimit(enchantment: CAEnchantment): Int { - // Test namespace - var limit = enchantLimit(enchantment.key.toString()) - if (limit >= 0) return limit - - // Test legacy (name only) - limit = enchantLimit(enchantment.enchantmentName) - if (limit >= 0) return limit - - // Default to negative - return -1 - } - - /** - * Get the given [enchantmentName]'s limit - */ - private fun enchantLimit(enchantmentName: String): Int { - - val path = "${ENCHANT_LIMIT_ROOT}.$enchantmentName" - return CustomAnvil.instance.config - .getInt(path, -1) + fun enchantLimit(enchantment: Enchantment): Int { + val path = "${ENCHANT_LIMIT_ROOT}.${enchantment.enchantmentName}" + return UnsafeEnchants.instance + .config + .getInt(path, defaultEnchantLimit) + .takeIf { it in ENCHANT_LIMIT_RANGE } + ?: defaultEnchantLimit } /** @@ -542,138 +148,16 @@ object ConfigOptions { * it's source [isFromBook] */ fun enchantmentValue( - enchantment: CAEnchantment, + enchantment: Enchantment, isFromBook: Boolean ): Int { - // Test namespace - var limit = enchantmentValue(enchantment.key.toString(), isFromBook) - if (limit != null) return limit - - // Test legacy (name only) - limit = enchantmentValue(enchantment.enchantmentName, isFromBook) - if (limit != null) return limit - - // get default (and test old legacy if present) - return getDefaultValue(enchantment, isFromBook) - - } - - /** - * Get the appropriate [enchantmentName]'s value dependent on whether - * it's source [isFromBook] - */ - private fun enchantmentValue( - enchantmentName: String, - isFromBook: Boolean - ): Int? { val typeKey = if (isFromBook) KEY_BOOK else KEY_ITEM - val path = "${ENCHANT_VALUES_ROOT}.${enchantmentName}.$typeKey" - return CustomAnvil.instance + val path = "${ENCHANT_VALUES_ROOT}.${enchantment.enchantmentName}.$typeKey" + return UnsafeEnchants.instance .config - .getInt(path, DEFAULT_ENCHANT_VALUE - 1) + .getInt(path, DEFAULT_ENCHANT_VALUE) .takeIf { it >= DEFAULT_ENCHANT_VALUE } - } - - /** - * Get default value if enchantment do not exist on config - */ - private fun getDefaultValue( - enchantment: CAEnchantment, // compatibility with 1.20.5. TODO better update system - isFromBook: Boolean - ): Int { - - val enchantmentName = enchantment.key.toString() - if (enchantmentName == "minecraft:sweeping_edge") { - var limit = enchantmentValue("minecraft:sweeping", isFromBook) - if (limit != null) return limit - - // legacy name - limit = enchantmentValue("sweeping", isFromBook) - if (limit != null) return limit - } - - val rarity = enchantment.defaultRarity() - return if (isFromBook) - rarity.bookValue - else - rarity.itemValue - } - - /** - * Get the given [enchantmentName]'s level before merge is disabled - * a negative value would mean never disabled - */ - fun maxBeforeMergeDisabled(enchantment: CAEnchantment): Int { - val key = enchantment.key.toString() - var value = maxBeforeMergeDisabled(key) - if (value >= 0) return value - - // Legacy name - val legacy = enchantment.enchantmentName - value = maxBeforeMergeDisabled(legacy) - if (value >= 0) return value - - if (key == "minecraft:sweeping_edge") { - value = maxBeforeMergeDisabled("minecraft:sweeping") - if (value >= 0) return value - - // legacy name of legacy enchantment name - value = maxBeforeMergeDisabled("sweeping") - if (value >= 0) return value - } - - return DEFAULT_MAX_BEFORE_MERGE_DISABLED - } - - /** - * Get the given [enchantmentName]'s level before merge is disabled - * a negative value would mean never disabled - */ - private fun maxBeforeMergeDisabled(enchantmentName: String): Int { - // find if set - val path = "${DISABLE_MERGE_OVER_ROOT}.$enchantmentName" - - return CustomAnvil.instance - .config - .getInt(path, -1) - } - - fun isImmutable(key: NamespacedKey): Boolean { - val immutables = ConfigHolder.DEFAULT_CONFIG.config.getStringList(IMMUTABLE_ENCHANTMENT_LIST) - - // We need to ignore case so can't just check "contain" - for (ench in immutables) { - if (ench.equals(key.toString(), ignoreCase = true) || - ench.equals(key.key, ignoreCase = true) - ) - return true - } - return false - } - - /* - * Monetary configs (only for 1.21.6+) - * Also require dialog rename - */ - fun shouldUseMoney(player: HumanEntity): Boolean { - return EconomyManager.economy?.initialized() == true && - canUseDialogRename(player) && - ConfigHolder.DEFAULT_CONFIG - .config - .getBoolean(SHOULD_USE_MONEY, DEFAULT_SHOULD_USE_MONEY) - } - - val usedCurrency: String - get() { - return ConfigHolder.DEFAULT_CONFIG - .config - .getString(MONEY_CURRENCY, DEFAULT_MONEY_CURRENCY)!! - } - - fun getMonetaryMultiplier(type: String): BigDecimal { - return BigDecimal(ConfigHolder.DEFAULT_CONFIG - .config - .getDouble("$MONETARY_MULTIPLIER_ROOT.$type", DEFAULT_MONEY_MULTIPLIER)) + ?: DEFAULT_ENCHANT_VALUE } } diff --git a/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt b/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt index af959f2..b60adf2 100644 --- a/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt +++ b/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt @@ -1,12 +1,10 @@ package io.delilaheve.util -import io.delilaheve.CustomAnvil +import io.delilaheve.UnsafeEnchants +import org.bukkit.Material +import org.bukkit.enchantments.Enchantment import org.bukkit.entity.HumanEntity -import org.bukkit.inventory.ItemStack -import xyz.alexcrea.cuanvil.config.ConfigHolder -import xyz.alexcrea.cuanvil.enchant.CAEnchantment -import xyz.alexcrea.cuanvil.group.ConflictType -import xyz.alexcrea.cuanvil.util.MaterialUtil.customType +import xyz.alexcrea.group.ConflictType import kotlin.math.max import kotlin.math.min @@ -18,110 +16,62 @@ object EnchantmentUtil { /** * Enchantment name without namespace */ - val CAEnchantment.enchantmentName: String + val Enchantment.enchantmentName: String get() = key.key /** * Combine 2 sets of enchantments according to our configuration */ - fun Map.combineWith( - other: Map, - item: ItemStack, + fun Map.combineWith( + other: Map, + mat: Material, player: HumanEntity - ) = mutableMapOf().apply { + ) = mutableMapOf().apply { putAll(this@combineWith) - - CustomAnvil.verboseLog("Testing merge") - val bypassFuse = player.hasPermission(CustomAnvil.bypassFusePermission) - val bypassLevel = player.hasPermission(CustomAnvil.bypassLevelPermission) - - var maxEnchantCount = ConfigOptions.getEnchantCountLimit(item.customType) - if(maxEnchantCount == null || maxEnchantCount < 0) maxEnchantCount = Int.MAX_VALUE - - val allowed = other.filter { (enchantment, _) -> enchantment.isAllowed(player) } - val new = allowed.filter{ (enchantment, _) -> !containsKey(enchantment)} - val old = allowed.filter{ (enchantment, _) -> containsKey(enchantment)} - - fun maxLevel(enchantment: CAEnchantment): Int { - val max = if (bypassLevel) { 255 } - else { ConfigOptions.enchantLimit(enchantment) } - - CustomAnvil.verboseLog("Max level of ${enchantment.key} is $max (bypassLevel is $bypassLevel)") - return max - } - - old.forEach { (enchantment, level) -> - // Get max level or 255 if player can bypass - val maxLevel = maxLevel(enchantment) - val cappedLevel = min(level, maxLevel) - - val oldLevel = this[enchantment]!! // <- should not be null. (enchantment already in result list) - - // ... and they're not the same level - if (oldLevel != cappedLevel) { - // apply the greater of the two or left one if right is above max - this[enchantment] = max(oldLevel, cappedLevel) - } - // ... and they're the same level - else { - // We test if it is allowed to merge at this level - if(!bypassLevel){ - val maxBeforeDisabled = ConfigOptions.maxBeforeMergeDisabled(enchantment) - if((maxBeforeDisabled > 0) && (oldLevel >= maxBeforeDisabled)) { - CustomAnvil.verboseLog( - "Reached max merge before disable for ${enchantment.key}: $oldLevel/$maxBeforeDisabled)") - return@forEach + other.forEach { (enchantment, level) -> + // Enchantment not yet in result list + if (!containsKey(enchantment)) { + if(player.hasPermission(UnsafeEnchants.unsafePermission)){ + // Add the enchantment if it doesn't have conflicts, or, if player is allowed to bypass enchantment restrictions + this[enchantment] = level + if(!player.hasPermission(UnsafeEnchants.bypassFusePermission) && + (UnsafeEnchants.conflictManager.isConflicting(this.keys,mat,enchantment) != ConflictType.NO_CONFLICT)){ + this.remove(enchantment) } + }else if(!keys.any { enchantment.conflictsWith(it) }){ + + this[enchantment] = level } - - // Now we increase the enchantment level by 1 - var newLevel = oldLevel + 1 - newLevel = max(min(newLevel, maxLevel), oldLevel) - this[enchantment] = newLevel } - - if(bypassFuse){ - CustomAnvil.verboseLog("Bypassed conflict check for ${enchantment.key}") - } else { - val conflictType = ConfigHolder.CONFLICT_HOLDER.conflictManager - .isConflicting(this, item, enchantment) - + // Enchantment already in result list + else{ // ... and they are conflicting - if(conflictType != ConflictType.NO_CONFLICT){ - CustomAnvil.verboseLog( - "Enchantment already in result list, and they are conflicting (${enchantment.key}, conflict: $conflictType)") - this[enchantment] = oldLevel + if((UnsafeEnchants.conflictManager.isConflicting(this.keys,mat,enchantment) != ConflictType.NO_CONFLICT) + && !player.hasPermission(UnsafeEnchants.bypassFusePermission)){ return@forEach } + + // ... and they're not the same level + if(this[enchantment] != other[enchantment]){ + val newLevel = max(this[enchantment] ?: 0, other[enchantment] ?: 0) + // apply the greater of the two if non-zero + if (newLevel > 0) { this[enchantment] = newLevel } + } + // ... and they're the same level + else { + // try to increase the enchantment level by 1 + var newLevel = this[enchantment]!! +1 + // Get max level or 255 if player can bypass + val maxLevel = if(player.hasPermission(UnsafeEnchants.bypassLevelPermission)){ + 255 + }else{ + ConfigOptions.enchantLimit(enchantment) + } + newLevel = min(newLevel, maxLevel) + if (newLevel > 0) { this[enchantment] = newLevel } + } } } - - // Try to add new now - new.forEach { (enchantment, level) -> - // Get max level or 255 if player can bypass - val maxLevel = maxLevel(enchantment) - val cappedLevel = min(level, maxLevel) - - // Do not allow new enchantment if above maximum - if(this.size >= maxEnchantCount) return@forEach - - // Add the enchantment if it doesn't have conflicts, or if player is allowed to bypass enchantment restrictions - this[enchantment] = cappedLevel - if(bypassFuse){ - CustomAnvil.verboseLog("Bypassed conflict check for ${enchantment.key}") - return@forEach - } - - val conflictType = ConfigHolder.CONFLICT_HOLDER.conflictManager - .isConflicting(this, item, enchantment) - - if (conflictType != ConflictType.NO_CONFLICT) { - CustomAnvil.verboseLog("Enchantment not yet in result list, but there is conflict (${enchantment.key}, conflict: $conflictType)") - this.remove(enchantment) - } - - } - } } diff --git a/src/main/kotlin/io/delilaheve/util/ItemUtil.kt b/src/main/kotlin/io/delilaheve/util/ItemUtil.kt index 25698ad..1f8f9c8 100644 --- a/src/main/kotlin/io/delilaheve/util/ItemUtil.kt +++ b/src/main/kotlin/io/delilaheve/util/ItemUtil.kt @@ -1,14 +1,13 @@ package io.delilaheve.util +import io.delilaheve.UnsafeEnchants +import org.bukkit.Material.BOOK import org.bukkit.Material.ENCHANTED_BOOK +import org.bukkit.enchantments.Enchantment import org.bukkit.inventory.ItemStack import org.bukkit.inventory.meta.Damageable -import xyz.alexcrea.cuanvil.enchant.CAEnchantment -import xyz.alexcrea.cuanvil.update.UpdateUtils -import xyz.alexcrea.cuanvil.util.MaterialUtil.customType -import xyz.alexcrea.cuanvil.util.MaxDamageCheckerUtil -import kotlin.math.ceil -import kotlin.math.max +import org.bukkit.inventory.meta.EnchantmentStorageMeta +import org.bukkit.inventory.meta.ItemMeta import kotlin.math.min /** @@ -16,33 +15,64 @@ import kotlin.math.min */ object ItemUtil { + /** + * Check if this [ItemStack] is a [BOOK] or [ENCHANTED_BOOK] + */ + fun ItemStack.isBook() = type in listOf(BOOK, ENCHANTED_BOOK) + /** * Check if this [ItemStack] is an [ENCHANTED_BOOK] */ - fun ItemStack.isEnchantedBook() = type == ENCHANTED_BOOK + private fun ItemStack.isEnchantedBook() = type == ENCHANTED_BOOK + + /** + * Determine if this [ItemStack] can hold enchants, this should be sufficient for + * detecting if an item is a tool/armour/etc... and not a carrot/potato/etc... + */ + private fun ItemStack.canHoldEnchants() = Enchantment.values() + .any { it.canEnchantItem(this) } /** * Find the enchantment map for this [ItemStack] and return it as a [MutableMap] */ - fun ItemStack.findEnchantments(): MutableMap = CAEnchantment.getEnchants(this) + fun ItemStack.findEnchantments() = if (isBook()) { + (itemMeta as? EnchantmentStorageMeta)?.storedEnchants ?: emptyMap() + } else { + itemMeta?.enchants ?: emptyMap() + } /** * Apply an [enchantments] map to this [ItemStack] */ - fun ItemStack.setEnchantmentsUnsafe(enchantments: Map) { - CAEnchantment.clearEnchants(this) - - enchantments.forEach { (enchantment, level) -> - enchantment.addEnchantmentUnsafe(this, level) + fun ItemStack.setEnchantmentsUnsafe(enchantments: Map) { + if (isBook()) { + /* For some god-forsaken reason, item meta is not mutable + * so, we have to get the instance, modify it, then set it + * back to the item... #BecauseMinecraft */ + val bookMeta = (itemMeta as? EnchantmentStorageMeta) + bookMeta?.replaceEnchants(enchantments) + itemMeta = bookMeta + } else { + itemMeta?.enchants?.forEach { (enchant, _) -> + removeEnchantment(enchant) + } + addUnsafeEnchantments(enchantments) } - } - private fun maxDamage(damageable: Damageable): Int { - val ver = UpdateUtils.currentMinecraftVersion() - if(ver.major <= 1 && ver.minor <= 20 && ver.patch < 5) return Integer.MAX_VALUE - - return MaxDamageCheckerUtil.getMaxDamage(damageable) + /** + * Apply an [enchantments] map to this book + */ + private fun EnchantmentStorageMeta.replaceEnchants( + enchantments: Map + ) { + storedEnchants.forEach { (enchant, _) -> + removeStoredEnchant(enchant) + } + enchantments.forEach { (enchant, level) -> + val added = addStoredEnchant(enchant, level, true) + UnsafeEnchants.log("${enchant.key} added to item? $added") + } } /** @@ -57,50 +87,26 @@ object ItemUtil { (itemMeta as? Damageable)?.let { val durability = type.maxDurability.toInt() val firstDamage = (first.itemMeta as? Damageable)?.damage ?: 0 - if (firstDamage == 0) return false + if( firstDamage == 0) return false val firstDurability = durability - firstDamage val secondDamage = (second.itemMeta as? Damageable)?.damage ?: 0 val secondDurability = durability - secondDamage val combinedDurability = firstDurability + secondDurability val newDurability = min(combinedDurability, durability) - - val maxDamage = maxDamage(it) - it.damage = min(durability - newDurability, maxDamage) - itemMeta = it + it.damage = durability - newDurability + itemMeta = it as ItemMeta return true } return false } - fun ItemStack.unitRepair( - unitAmount: Int, - percentPerUnit: Double - ): Int { - (itemMeta as? Damageable)?.let { - val durability = type.maxDurability.toInt() - val firstDamage = it.damage - if (firstDamage == 0) return 0 - var unitCount = 0 - var damage = firstDamage - while ((unitCount < unitAmount) && (damage > 0)) { - unitCount++ - damage = ceil(firstDamage - durability * percentPerUnit * unitCount).toInt() - } - - it.damage = max(damage, 0) - itemMeta = it - return unitCount - } - return 0 - } - /** * Check that this [ItemStack] can merge with the [other] * * The two items should either be the same type, or, the [other] is a book */ fun ItemStack.canMergeWith( - other: ItemStack? - ) = (other != null) && (customType == other.customType || (other.isEnchantedBook())) + other: ItemStack + ) = type == other.type || (canHoldEnchants() && other.isEnchantedBook()) } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilCost.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilCost.kt deleted file mode 100644 index 710687c..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilCost.kt +++ /dev/null @@ -1,72 +0,0 @@ -package xyz.alexcrea.cuanvil.anvil - -import io.delilaheve.util.ConfigOptions -import java.math.BigDecimal -import kotlin.math.min -import io.delilaheve.util.ConfigOptions.getMonetaryMultiplier as moneyMultiplier - -open class AnvilCost { - private val isAlone: Boolean - var valid = true // Get set as invalid if cost can be satisfied - var isMonetary = false - - var generic = 0 - var enchantment = 0 - var repair = 0 - var rename = 0 - var lore = 0 - var illegalPenalty = 0 - var workPenalty = 0 - var recipe = 0 - - constructor(generic: Int) { - this.generic = generic - isAlone = true - } - - constructor() { - isAlone = false - } - - fun asXpCost(): Int { - return generic + enchantment + repair + rename + lore + illegalPenalty + workPenalty + recipe - } - - fun filteredXpCost(ignoreRules: Boolean = false): Int { - val original = asXpCost() - - // Test repair cost limit - return if ( - !ignoreRules && - !ConfigOptions.doRemoveCostLimit && - ConfigOptions.doCapCost - ) { - min(original, ConfigOptions.maxAnvilCost) - } else { - original - } - } - - open fun asMonetaryCost(): BigDecimal { - // multiply by per use type multipliers - return BigDecimal(generic) - .add(BigDecimal(enchantment).multiply(moneyMultiplier("enchantment"))) - .add(BigDecimal(repair).multiply(moneyMultiplier("repair"))) - .add(BigDecimal(rename).multiply(moneyMultiplier("rename"))) - .add(BigDecimal(lore).multiply(moneyMultiplier("lore_edit"))) - .add(BigDecimal(enchantment).multiply(moneyMultiplier("enchantment"))) - .add(BigDecimal(illegalPenalty).multiply(moneyMultiplier("work_penalty"))) - .add(BigDecimal(workPenalty).multiply(moneyMultiplier("work_penalty"))) - .add(BigDecimal(recipe).multiply(moneyMultiplier("recipe"))) - .multiply(moneyMultiplier("global")) - } -} - -class CustomCraftCost(val rawCost: Int): AnvilCost() { - - override fun asMonetaryCost(): BigDecimal { - return BigDecimal(rawCost) - .multiply(moneyMultiplier("global")) - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilMergeLogic.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilMergeLogic.kt deleted file mode 100644 index 6b106fc..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilMergeLogic.kt +++ /dev/null @@ -1,331 +0,0 @@ -package xyz.alexcrea.cuanvil.anvil - -import io.delilaheve.CustomAnvil -import io.delilaheve.util.ConfigOptions -import io.delilaheve.util.EnchantmentUtil.combineWith -import io.delilaheve.util.ItemUtil.findEnchantments -import io.delilaheve.util.ItemUtil.isEnchantedBook -import io.delilaheve.util.ItemUtil.repairFrom -import io.delilaheve.util.ItemUtil.setEnchantmentsUnsafe -import io.delilaheve.util.ItemUtil.unitRepair -import org.bukkit.ChatColor -import org.bukkit.Material -import org.bukkit.entity.HumanEntity -import org.bukkit.entity.Player -import org.bukkit.inventory.AnvilInventory -import org.bukkit.inventory.InventoryView -import org.bukkit.inventory.ItemStack -import org.bukkit.inventory.meta.ItemMeta -import org.bukkit.persistence.PersistentDataType -import xyz.alexcrea.cuanvil.dependency.DependencyManager -import xyz.alexcrea.cuanvil.dialog.AnvilRenameDialog -import xyz.alexcrea.cuanvil.enchant.CAEnchantment -import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe -import xyz.alexcrea.cuanvil.util.CasedStringUtil -import xyz.alexcrea.cuanvil.util.CustomRecipeUtil -import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir -import xyz.alexcrea.cuanvil.util.MiniMessageUtil -import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair -import xyz.alexcrea.cuanvil.util.anvil.AnvilColorUtil -import xyz.alexcrea.cuanvil.util.anvil.AnvilLoreEditUtil -import xyz.alexcrea.cuanvil.util.anvil.AnvilXpUtil -import xyz.alexcrea.cuanvil.util.config.LoreEditType -import xyz.alexcrea.cuanvil.util.dialog.AnvilRenameDialogUtil - -object AnvilMergeLogic { - - open class AnvilResult { - companion object { - val EMPTY = AnvilResult(null, AnvilCost()) - } - - val item: ItemStack? - val cost: AnvilCost - val ignoreXpRules: Boolean - - constructor(item: ItemStack?, cost: AnvilCost, ignoreXpRules: Boolean = false) { - this.item = item - this.cost = cost - this.ignoreXpRules = ignoreXpRules - } - - fun isEmpty(): Boolean { - return item == null - } - } - - class UnitRepairResult : AnvilResult { - companion object { - val EMPTY = UnitRepairResult(null, AnvilCost(), 0) - } - - val repairAmount: Int - - constructor(item: ItemStack?, cost: AnvilCost, repairAmount: Int) : super(item, cost) { - this.repairAmount = repairAmount - } - } - - class CustomCraftResult : AnvilResult { - companion object { - val EMPTY = CustomCraftResult(null, CustomCraftCost(0), 0, null) - } - - val customCraftCost: CustomCraftCost - val amount: Int - val recipe: AnvilCustomRecipe? - - constructor( - item: ItemStack?, cost: CustomCraftCost, - amount: Int, recipe: AnvilCustomRecipe? - ) : super(item, cost, true) { - this.customCraftCost = cost - this.amount = amount - this.recipe = recipe - } - } - - class LoreEditResult : AnvilResult { - companion object { - val EMPTY = LoreEditResult(null, AnvilCost(), LoreEditType.APPEND_PAPER) - } - - val type: LoreEditType - - constructor(item: ItemStack?, cost: AnvilCost, type: LoreEditType) : super(item, cost) { - this.type = type - } - } - - fun doRenaming( - view: InventoryView, //TODO use anvil view - inventory: AnvilInventory, - player: Player, first: ItemStack - ): AnvilResult { - val resultItem = DependencyManager.cloneItem(player, first) - val cost = AnvilCost() - cost.rename = handleRename(resultItem, inventory, player) - - // Test/stop if nothing changed. - if (first == resultItem) { - CustomAnvil.log("no right item, But input is same as output") - return AnvilResult.EMPTY - } - - cost.workPenalty = AnvilXpUtil.calculatePenalty(first, null, resultItem, AnvilUseType.RENAME_ONLY) - val result = - DependencyManager.tryTreatAnvilResult(view, inventory, player, resultItem, AnvilUseType.RENAME_ONLY, cost) - - return AnvilResult(result, cost) - } - - private fun processDialogPCD(meta: ItemMeta, player: HumanEntity) { - val text = AnvilRenameDialogUtil.anvilRenameDialog.currentText(player) - return processPCD(meta, player, text) - } - - fun processPCD(meta: ItemMeta, player: HumanEntity, text: String?) { - val keepDialog = ConfigOptions.canUseDialogRename(player) && ConfigOptions.shouldKeepRenameText - - val pdc = meta.persistentDataContainer - if (!keepDialog) - pdc.remove(AnvilRenameDialog.PCD_KEEP_RENAME_TEXT_KEY) - else { - if (text == null || text.isBlank()) - pdc.remove(AnvilRenameDialog.PCD_KEEP_RENAME_TEXT_KEY) - else pdc.set(AnvilRenameDialog.PCD_KEEP_RENAME_TEXT_KEY, PersistentDataType.STRING, text) - } - } - - private fun handleRename(resultItem: ItemStack, inventory: AnvilInventory, player: HumanEntity): Int { - // Can be null - var renameText = ChatColor.stripColor(inventory.renameText) - - var sumCost = 0 - var useColor = false - if (ConfigOptions.renameColorPossible && renameText != null) { - val component = AnvilColorUtil.handleColor( - renameText, - AnvilColorUtil.renamePermission(player) - ) - - if (component != null) { - renameText = MiniMessageUtil.legacy_mm.serialize(component) - - sumCost += ConfigOptions.useOfColorCost - useColor = true - } - } - - // Rename item and add renaming cost - resultItem.itemMeta?.let { - val hasDisplayName = it.hasDisplayName() - val displayName = if (!hasDisplayName) null - else if (useColor) it.displayName - else ChatColor.stripColor(it.displayName) - - - if (!displayName.contentEquals(renameText) && !(displayName == null && - renameText == "" || - //TODO on recent paper check effective name instead - renameText == CasedStringUtil.snakeToUpperSpacedCase(resultItem.type.name.lowercase()) - ) - ) { - it.setDisplayName(renameText) - processDialogPCD(it, player) - resultItem.itemMeta = it - - sumCost += ConfigOptions.itemRenameCost - } - - return sumCost - } - return 0 - } - - fun doMerge( - view: InventoryView, //TODO use anvil view instead - inventory: AnvilInventory, - player: Player, - first: ItemStack, second: ItemStack - ): AnvilResult { - val newEnchants = first.findEnchantments() - .combineWith(second.findEnchantments(), first, player) - var hasChanged = !isIdentical(first.findEnchantments(), newEnchants) - - val resultItem = DependencyManager.cloneItem(player, first) - val cost = AnvilCost() - if (hasChanged) { - resultItem.setEnchantmentsUnsafe(newEnchants) - // Calculate enchantment cost - AnvilXpUtil.getRightValues(second, resultItem, cost) - } - - // Calculate repair cost - if (!first.isEnchantedBook() && !second.isEnchantedBook()) { - // we only need to be concerned with repair when neither item is a book - val repaired = resultItem.repairFrom(first, second) - cost.repair = if (repaired) ConfigOptions.itemRepairCost else 0 - hasChanged = hasChanged || repaired - } - - // Test/stop if nothing changed. - if (!hasChanged) { - CustomAnvil.log("Mergeable with second, But input is same as output") - return AnvilResult.EMPTY - } - // As calculatePenalty edit result, we need to calculate penalty after checking equality - cost.workPenalty = AnvilXpUtil.calculatePenalty(first, second, resultItem, AnvilUseType.MERGE) - // Calculate rename cost - cost.rename = handleRename(resultItem, inventory, player) - - val result = - DependencyManager.tryTreatAnvilResult(view, inventory, player, resultItem, AnvilUseType.MERGE, cost) - - return AnvilResult(result, cost) - } - - private fun isIdentical( - firstEnchants: MutableMap, - resultEnchants: MutableMap - ): Boolean { - if (firstEnchants.size != resultEnchants.size) return false - for (entry in resultEnchants) { - if (firstEnchants.getOrDefault(entry.key, entry.value - 1) != entry.value) return false - } - - return true - } - - // return true if a custom recipe exist with these ingredients - fun testCustomRecipe( - view: InventoryView, //TODO use anvil view instead - inventory: AnvilInventory, - player: Player, - first: ItemStack, second: ItemStack? - ): CustomCraftResult { - val recipe = CustomRecipeUtil.getCustomRecipe(first, second) - CustomAnvil.verboseLog("custom recipe not null? ${recipe != null}") - if (recipe == null) return CustomCraftResult.EMPTY - - val amount = CustomRecipeUtil.getCustomRecipeAmount(recipe, first, second) - - val resultItem: ItemStack = DependencyManager.cloneItem(player, recipe.resultItem!!) - resultItem.amount *= amount - - // Maybe add an option on custom craft to ignore/not ignore penalty ?? - val xpCost = recipe.determineCost(amount, first, resultItem) - - val cost = CustomCraftCost(xpCost) - // This is for displayed cost - cost.recipe = if (recipe.removeExactLinearXp) AnvilXpUtil.calculateMinimumLevelForXp(xpCost) - else AnvilXpUtil.calculateLevelForXp(xpCost) - - val result = - DependencyManager.tryTreatAnvilResult(view, inventory, player, resultItem, AnvilUseType.CUSTOM_CRAFT, cost) - return CustomCraftResult(result, cost, amount, recipe) - } - - fun testUnitRepair( - view: InventoryView, //TODO use anvil view - inventory: AnvilInventory, - player: Player, - first: ItemStack, second: ItemStack - ): UnitRepairResult { - val unitRepairAmount = first.getRepair(second) ?: return UnitRepairResult.EMPTY - - return testUnitRepair(view, inventory, player, first, second, unitRepairAmount) - } - - fun testUnitRepair( - view: InventoryView, //TODO use anvil view instead - inventory: AnvilInventory, - player: Player, - first: ItemStack, second: ItemStack, - unitRepairAmount: Double - ): UnitRepairResult { - val resultItem = DependencyManager.cloneItem(player, first) - val cost = AnvilCost() - cost.rename = handleRename(resultItem, inventory, player) - - val repairAmount = resultItem.unitRepair(second.amount, unitRepairAmount) - if (repairAmount > 0) - cost.repair = repairAmount * ConfigOptions.unitRepairCost - - // We do not care about right item penalty for unit repair - cost.workPenalty = AnvilXpUtil.calculatePenalty(first, null, resultItem, AnvilUseType.UNIT_REPAIR) - - // Test/stop if nothing changed. - if (first == resultItem) { - CustomAnvil.log("unit repair, But input is same as output") - return UnitRepairResult.EMPTY - } - - val result = - DependencyManager.tryTreatAnvilResult(view, inventory, player, resultItem, AnvilUseType.UNIT_REPAIR, cost) - return UnitRepairResult(result, cost, repairAmount) - } - - fun testLoreEdit( - player: Player, - first: ItemStack, second: ItemStack - ): LoreEditResult { - val type = second.type - - val result = if (Material.WRITABLE_BOOK == type) - AnvilLoreEditUtil.tryLoreEditByBook(player, first, second) - else if (Material.PAPER == type) - AnvilLoreEditUtil.tryLoreEditByPaper(player, first, second) - else LoreEditResult.EMPTY - - if (result.isEmpty()) return result - - if (result.item!!.isAir || first == result.item) { - CustomAnvil.log("lore edit, But input is same as output") - return LoreEditResult.EMPTY - } - - return result - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilUseType.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilUseType.kt deleted file mode 100644 index 67782f3..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilUseType.kt +++ /dev/null @@ -1,67 +0,0 @@ -package xyz.alexcrea.cuanvil.anvil - -import org.bukkit.Material -import xyz.alexcrea.cuanvil.config.WorkPenaltyType -import xyz.alexcrea.cuanvil.util.anvil.AnvilUseTypeUtil - -enum class AnvilUseType( - val typeName: String, val path: String, - val defaultPenalty: WorkPenaltyType.WorkPenaltyPart, - val displayName: String, val displayMat: Material -) { - - RENAME_ONLY( - "rename_only", - WorkPenaltyType.WorkPenaltyPart(false, true), - "Rename Only", Material.NAME_TAG - ), - MERGE( - "merge", - WorkPenaltyType.WorkPenaltyPart(true, true), - "Merge", Material.ANVIL - ), - UNIT_REPAIR( - "unit_repair", - WorkPenaltyType.WorkPenaltyPart(true, true), - "Unit Repair", Material.DIAMOND - ), - CUSTOM_CRAFT( - "custom_craft", - WorkPenaltyType.WorkPenaltyPart(false, false), - "Custom Craft", Material.CRAFTING_TABLE - ), - LORE_EDIT_BOOK_APPEND( - "lore_edit_book_append", "lore_edit.book_and_quil.append", - WorkPenaltyType.WorkPenaltyPart(false, false), - "Book Add", Material.WRITABLE_BOOK - ), - LORE_EDIT_BOOK_REMOVE( - "lore_edit_book_remove", "lore_edit.book_and_quil.remove", - WorkPenaltyType.WorkPenaltyPart(false, false), - "Book Remove", Material.WRITABLE_BOOK - ), - LORE_EDIT_PAPER_APPEND( - "lore_edit_paper_append", "lore_edit.paper.append_line", - WorkPenaltyType.WorkPenaltyPart(false, false), - "Paper Add", Material.WRITABLE_BOOK - ), - LORE_EDIT_PAPER_REMOVE( - "lore_edit_paper_remove", "lore_edit.paper.remove_line", - WorkPenaltyType.WorkPenaltyPart(false, false), - "Paper Remove", Material.WRITABLE_BOOK - ), - ; - - constructor( - typeName: String, - defaultPenalty: WorkPenaltyType.WorkPenaltyPart, - displayName: String, displayMat: Material - ) : - this( - typeName, - AnvilUseTypeUtil.defaultPath(typeName), // stupid util class - defaultPenalty, - displayName, displayMat - ) - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/CASubCommand.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/CASubCommand.kt deleted file mode 100644 index 4c71c68..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/CASubCommand.kt +++ /dev/null @@ -1,46 +0,0 @@ -package xyz.alexcrea.cuanvil.command - -import org.bukkit.ChatColor -import org.bukkit.command.Command -import org.bukkit.command.CommandExecutor -import org.bukkit.command.CommandSender - -abstract class CASubCommand: CommandExecutor { - - private var alreadySaid = false; - override fun onCommand( - sender: CommandSender, - cmd: Command, - cmdstr: String, - args: Array - ): Boolean { - if(!alreadySaid){ - sender.sendMessage(ChatColor.RED.toString() + - "Please not that this command will be replaced as a subcommand of `/customanvil` or `/ca`") - alreadySaid = true - } - - return executeCommand(sender, cmd, cmdstr, args) - } - - abstract fun executeCommand( - sender: CommandSender, - cmd: Command, - cmdstr: String, - args: Array): Boolean - - open fun allowed(sender: CommandSender): Boolean { - return true - } - - open fun tabCompleter( - sender: CommandSender, - args: Array, - list: MutableList) { - } - - open fun description(): String { - return "no description" - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/CustomAnvilCommand.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/CustomAnvilCommand.kt deleted file mode 100644 index e5e689e..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/CustomAnvilCommand.kt +++ /dev/null @@ -1,96 +0,0 @@ -package xyz.alexcrea.cuanvil.command - -import com.google.common.collect.ImmutableMap -import io.delilaheve.CustomAnvil -import org.bukkit.command.Command -import org.bukkit.command.CommandExecutor -import org.bukkit.command.CommandSender -import org.bukkit.command.TabCompleter -import xyz.alexcrea.cuanvil.util.MetricsUtil -import java.util.ArrayList - -class CustomAnvilCommand(plugin: CustomAnvil) : CommandExecutor, TabCompleter { - - // Name of the generic command - companion object { - private const val genericCommandName = "customanvil" - } - - private val editConfigCommand = EditConfigExecutor() - private val helpCommand = HelpExecutor() - private val commands = ImmutableMap.of( - "gui", editConfigCommand, - "reload", ReloadExecutor(), - "diagnostic", DiagnosticExecutor(), - "help", helpCommand, - ) - - init { - val self = plugin.getCommand(genericCommandName)!! - self.setExecutor(this) - self.tabCompleter = this - - helpCommand.commands = commands - } - - override fun onCommand( - sender: CommandSender, - cmd: Command, - cmdstr: String, - args: Array - ): Boolean { - // Find sub command to execute based on the provided command name - val subcmd: CASubCommand? - val newargs: Array - if(args.isEmpty()) { - subcmd = editConfigCommand - newargs = args - }else { - subcmd = commands[args[0].lowercase()] - newargs = args.copyOfRange(1, args.size) - } - - if(subcmd == null || !subcmd.allowed(sender)) { - sender.sendMessage("Invalid subcommand. run `$cmdstr help` to see available commands") - return true - } - - try { - return subcmd.executeCommand(sender, cmd, cmdstr, newargs) - } catch (e: Throwable) { - MetricsUtil.trackError(e) - sender.sendMessage("§cError running this command") - return false - } - } - - override fun onTabComplete( - sender: CommandSender, - cmd: Command, - cmdstr: String, - args: Array - ): MutableList { - val result = ArrayList() - if(args.size < 2) { - for ((key, cmd) in commands) { - if(!cmd.allowed(sender)) continue - result.add(key) - } - } else { - val subcmd = commands[args[0].lowercase()] - - if(subcmd != null) { - val newArgs = args.copyOfRange(1, args.size) - if(!subcmd.allowed(sender)) return result - - subcmd.tabCompleter(sender, newArgs, result) - } - } - - //assumed all provided tab completed string are lowercase - return result.stream() - .filter { it.startsWith(args[args.size - 1]) } - .sorted() - .toList() - } -} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/DiagnosticExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/DiagnosticExecutor.kt deleted file mode 100644 index 053a3fc..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/DiagnosticExecutor.kt +++ /dev/null @@ -1,347 +0,0 @@ -package xyz.alexcrea.cuanvil.command - -import com.github.stefvanschie.inventoryframework.inventoryview.interface_.InventoryViewUtil -import io.delilaheve.CustomAnvil -import net.md_5.bungee.api.chat.ClickEvent -import net.md_5.bungee.api.chat.HoverEvent -import net.md_5.bungee.api.chat.TextComponent -import net.md_5.bungee.api.chat.hover.content.Text -import org.bukkit.Bukkit -import org.bukkit.ChatColor -import org.bukkit.Material -import org.bukkit.command.Command -import org.bukkit.command.CommandSender -import org.bukkit.enchantments.Enchantment -import org.bukkit.entity.HumanEntity -import org.bukkit.entity.Player -import org.bukkit.event.inventory.InventoryType -import org.bukkit.event.inventory.PrepareAnvilEvent -import org.bukkit.inventory.AnvilInventory -import org.bukkit.inventory.InventoryView -import org.bukkit.inventory.ItemStack -import org.bukkit.inventory.meta.Damageable -import org.bukkit.inventory.meta.EnchantmentStorageMeta -import org.bukkit.plugin.Plugin -import org.bukkit.plugin.RegisteredListener -import xyz.alexcrea.cuanvil.dependency.DependencyManager -import xyz.alexcrea.cuanvil.dependency.packet.NoPacketManager -import xyz.alexcrea.cuanvil.dependency.packet.ProtocoLibWrapper -import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry -import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener -import xyz.alexcrea.cuanvil.util.MetricsUtil -import java.util.* -import java.util.stream.Collectors - - -class DiagnosticExecutor: CASubCommand() { - - companion object{ - private const val NO_DIAG_PERM = "You do not have permission to diagnostic this server" - - fun fetchNMSType(): String { - val packetManager = DependencyManager.packetManager - val packetManagerClass = packetManager.javaClass - - val className = packetManagerClass.name - val result = if(className.contains("PaperPacket")) { - "Paper" - } else { - when (packetManagerClass) { - ProtocoLibWrapper::class.java -> "Protocolib" - NoPacketManager::class.java -> "None" - else -> "Version Specific" - } - } - - - return "$result ${if(packetManager.canSetInstantBuild) '✅' else '❌'}" - } - } - - enum class DiagParams(val value: String) { - OS_PRIVACY("os_privacy"), - PLUGIN_PRIVACY("plugin_privacy"), - NO_MERGE_TEST("no_merge_test"), - FULL_ENCHANTMENT_DATA("full_enchantment_data"), - INCLUDE_LAST_ERROR("include_last_error"), - } - - private fun fetchParameters(args: Array): EnumSet { - val result = EnumSet.noneOf(DiagParams::class.java) - val argSet = HashSet() - - for (string in args) { - argSet.add(string.lowercase()) - } - - for (param in DiagParams.entries) { - if(argSet.contains(param.value)) - result.add(param) - } - - return result - } - - override fun tabCompleter( - sender: CommandSender, - args: Array, - list: MutableList) { - if(!allowed(sender)) return - - val map = fetchParameters(args) - for (param in DiagParams.entries) { - if(!map.contains(param)) - list.add(param.value) - } - - } - - override fun executeCommand( - sender: CommandSender, - cmd: Command, - cmdstr: String, - args: Array - ): Boolean { - if (!allowed(sender)) { - sender.sendMessage(NO_DIAG_PERM) - return false - } - - val stb = StringBuilder("```\n") - val params = fetchParameters(args) - var hasError = false - try { - diagnostic(sender, stb, params) - } catch(e: Throwable){ - stb.append("\n\nError happened trying to get diagnostic data:\n") - .append(e.message).append("\n") - .append(e.stackTrace.joinToString("\n")) - hasError = true - e.printStackTrace() - } - - stb.append("\n```") - - if (sender is HumanEntity) { - if(hasError) - sender.spigot().sendMessage(TextComponent(ChatColor.RED.toString() + "There was an error running the diagnostic")) - val message = TextComponent(ChatColor.GREEN.toString() + "Click to copy diagnostic data") - - message.clickEvent = ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, stb.toString()) - message.hoverEvent = HoverEvent(HoverEvent.Action.SHOW_TEXT, Text("§7Click to copy")) - - sender.spigot().sendMessage(message); - } else { - sender.sendMessage(stb.toString()); - } - - return true - } - - override fun allowed(sender: CommandSender): Boolean { - return sender.hasPermission(CustomAnvil.diagnosticPermission) - } - - fun diagnostic(sender: CommandSender, stb: StringBuilder, params: Set){ - stb.append("Server Info\n") - val version = CustomAnvil.instance.description.version - stb.append("\nPlugin Version: ").append(version) - if(version.contains("dev")) stb.append(" (alpha)") - - stb.append("\nLatest Update: ").append(CustomAnvil.latestVer) - stb.append("\nServer Version: ").append(Bukkit.getVersion()).append(" (").append(Bukkit.getName()).append(')') - stb.append("\nPlugin Enabled: ").append(if(CustomAnvil.instance.isEnabled) "Yes" else "No") - stb.append("\nNMS type: ").append(fetchNMSType()) - if(!params.contains(DiagParams.OS_PRIVACY)) { - stb.append("\nJava Version: ").append(System.getProperty("java.version")) - stb.append("\nOS: ").append(System.getProperty("os.name")).append(" ") - .append(System.getProperty("os.version")) - .append(System.getProperty("os.arch")) - } - - stb.append("\nHad detect error: ").append(if(MetricsUtil.lastError != null) "Yes" else "No") - - if(!params.contains(DiagParams.PLUGIN_PRIVACY)) { - pluginListDiag(sender, stb) - } - prepareAnvilListeners(stb) - - if(!params.contains(DiagParams.NO_MERGE_TEST)){ - if(sender is Player) testMerge(sender, stb) - } - - stb.append("\n\nEnchantments data:") - partialEnchantmentData(stb) - if(params.contains(DiagParams.FULL_ENCHANTMENT_DATA)){ - fullEnchantmentData(stb) - } - - if(params.contains(DiagParams.INCLUDE_LAST_ERROR)){ - includeLastError(stb) - } - } - - private fun testMerge(player: Player, stb: StringBuilder) { - val sword = ItemStack(Material.DIAMOND_SWORD) - val damagedSword = sword.clone() - val enchantedSword = sword.clone() - val enchantedBook = ItemStack(Material.ENCHANTED_BOOK) - val unitForRepair = ItemStack(Material.DIAMOND) - - var meta = damagedSword.itemMeta - (meta as Damageable).damage = 5 - damagedSword.itemMeta = meta - - meta = enchantedSword.itemMeta - meta!!.addEnchant(Enchantment.DAMAGE_ALL, 1, true) - enchantedSword.itemMeta = meta - - meta = enchantedBook.itemMeta - (meta as EnchantmentStorageMeta).addStoredEnchant(Enchantment.DAMAGE_ALL, 1, true) - enchantedBook.itemMeta = meta - - stb.append("\n\nItem to Item repair:") - simulateAnvil(player, stb, damagedSword, damagedSword, sword) - - stb.append("\n\nUnit repair:") - simulateAnvil(player, stb, damagedSword, unitForRepair, sword) - - stb.append("\n\nEnchanting an item:") - simulateAnvil(player, stb, sword, enchantedBook, enchantedSword) - } - - private val Plugin.pluginNameDisplay: String - get() { - return this.name + " v" + this.description.version - } - - override fun description(): String { - return "Basic diagnostic of this plugin" - } - - private fun pluginListDiag(sender: CommandSender, stb: StringBuilder) { - val enabledPlugins: MutableList = ArrayList() - val disabledPlugins: MutableList = ArrayList() - for (plugin in Bukkit.getPluginManager().plugins) { - if (plugin.isEnabled) { - enabledPlugins.add(plugin) - } else { - disabledPlugins.add(plugin) - } - } - - stb.append("\nEnabled Plugins: ").append( - enabledPlugins.stream() - .map { plugin -> plugin!!.pluginNameDisplay } - .reduce { a: String?, b: String? -> "$a, $b" }.orElse("None") - ) - - stb.append("\nDisabled Plugins: ").append( - disabledPlugins.stream() - .map { plugin -> plugin!!.pluginNameDisplay } - .reduce { a: String?, b: String? -> "$a, $b" }.orElse("None") - ) - } - - fun prepareAnvilListeners(stb: StringBuilder) { - val eventListeners: MutableSet = Arrays - .stream( - PrepareAnvilEvent - .getHandlerList() - .getRegisteredListeners() - ) - .map { obj: RegisteredListener? -> obj!!.plugin } - .collect(Collectors.toSet()) - - eventListeners.remove(CustomAnvil.instance) - stb.append("\nPrepare Anvil Listeners: ").append( - if (eventListeners.isEmpty()) "None" else eventListeners.stream() - .map { plugin -> plugin!!.pluginNameDisplay } - .reduce { a: String?, b: String? -> "$a, $b" }.orElse("None") - ) - } - - fun simulateAnvil(player: Player, stb: StringBuilder, left: ItemStack?, right: ItemStack?, result: ItemStack?) { - var invView: InventoryView - var event: PrepareAnvilEvent - try { - val fakeInv = Bukkit.createInventory(player, InventoryType.ANVIL) - invView = player.openInventory(fakeInv)!! - event = PrepareAnvilEvent(invView, result) - } catch (e: Throwable) { - // Help - val menuTypeClazz = Class.forName("org.bukkit.inventory.MenuType") - val anvilTypeField = menuTypeClazz.getField("ANVIL") - val anvilType = anvilTypeField.get(null) - val createMethod = anvilType.javaClass.getMethod("create", HumanEntity::class.java) - invView = createMethod.invoke(anvilType, player) as InventoryView - - player.openInventory(invView) - - val anvilViewClass = Class.forName("org.bukkit.inventory.view.AnvilView") - val constructor = PrepareAnvilEvent::class.java.getConstructor(anvilViewClass, ItemStack::class.java) - event = constructor.newInstance(invView, result) - } - - val fakeInv = InventoryViewUtil.getInstance().getTopInventory(invView) as AnvilInventory - fakeInv.setItem(0, left) - fakeInv.setItem(1, right) - - val xp = fakeInv.repairCost - val maxXp = fakeInv.maximumRepairCost - val mergeResult = fakeInv.getItem(2) - stb.append("\n${if(result == mergeResult) "E" else "Une"}xpected Result") - - PrepareAnvilListener().anvilCombineCheck(event) - // Now we check if item and xp same - stb.append("\nXP/Max XP: ") - .append(if(fakeInv.repairCost == xp) "Correct" else "Incorrect") - .append("/") - .append(if(fakeInv.maximumRepairCost == maxXp) "Correct" else "Incorrect") - .append(" (${fakeInv.repairCost} $xp|${fakeInv.maximumRepairCost} $maxXp)") - .append("\nMerge result: ") - .append(if(fakeInv.getItem(2) == mergeResult) "Correct" else "Incorrect") - - PrepareAnvilListener.IS_EMPTY_TEST = true - Bukkit.getPluginManager().callEvent(event) - stb.append("\nNull result test: ") - .append(if(event.result == null) "Correct" else "Incorrect") - - fakeInv.setItem(0, null) - fakeInv.setItem(1, null) - fakeInv.setItem(2, null) - player.closeInventory() - } - - private fun fullEnchantmentData(stb: StringBuilder) { - for (enchantment in CAEnchantmentRegistry.getInstance().values()) { - stb.append("\n- ").append(enchantment.key.toString()) - .append(" ").append(enchantment.name) - .append(" ").append(enchantment.defaultMaxLevel()) - } - } - - private fun partialEnchantmentData(stb: StringBuilder) { - val map = HashMap() - for (enchant in CAEnchantmentRegistry.getInstance().values()) { - map[enchant.key.namespace] = map.getOrDefault(enchant.key.namespace, 0) + 1 - } - - stb.append("\nNamespaces: ${ - map.entries.stream() - .map { (key, value) -> "$key ($value)" } - .reduce { a, b -> "$a, $b" }.get() - }") - - } - - private fun includeLastError(stb: StringBuilder) { - val e = MetricsUtil.lastError ?: return - - stb.append("\n\nLast stack trace: ${e.stackTraceToString()}") - - - - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt deleted file mode 100644 index fba89b7..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt +++ /dev/null @@ -1,45 +0,0 @@ -package xyz.alexcrea.cuanvil.command - -import io.delilaheve.CustomAnvil -import org.bukkit.command.Command -import org.bukkit.command.CommandSender -import org.bukkit.entity.HumanEntity -import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil -import xyz.alexcrea.cuanvil.gui.config.MainConfigGui -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions - -class EditConfigExecutor: CASubCommand() { - - override fun executeCommand(sender: CommandSender, - cmd: Command, - cmdstr: String, - args: Array): Boolean { - if (sender !is HumanEntity) return false - - if (!allowed(sender)) { - sender.sendMessage(GuiGlobalActions.NO_EDIT_PERM) - return false - } - if(PlatformUtil.isFolia){ - sender.sendMessage("§cIt look like you are using Folia. Sadly Custom Anvil do not support Config gui for Folia.") - sender.sendMessage("§eIt is may come in a future version.") - sender.sendMessage("") - sender.sendMessage("§eCurrently you need to edit manually the config or copy from another server (spigot or better)") - sender.sendMessage("§eThen /anvilconfigreload after config file is edited") - return false - } - - MainConfigGui.getInstance().show(sender) - - return true - } - - override fun allowed(sender: CommandSender): Boolean { - return sender.hasPermission(CustomAnvil.editConfigPermission) - } - - override fun description(): String { - return "Gui to edit the plugin's config" - } - -} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/HelpExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/HelpExecutor.kt deleted file mode 100644 index 697f1ee..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/HelpExecutor.kt +++ /dev/null @@ -1,32 +0,0 @@ -package xyz.alexcrea.cuanvil.command - -import com.google.common.collect.ImmutableMap -import org.bukkit.command.Command -import org.bukkit.command.CommandSender - -class HelpExecutor: CASubCommand() { - - lateinit var commands: ImmutableMap - - override fun executeCommand(sender: CommandSender, - cmd: Command, - cmdstr: String, - args: Array): Boolean { - - val stb = StringBuilder("List of available commands:") - for ((key, cmd) in commands) { - if(!cmd.allowed(sender)) continue - - stb.append("\n- $key: ").append(cmd.description()) - } - - sender.sendMessage(stb.toString()) - - return true - } - - override fun description(): String { - return "Help command" - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt deleted file mode 100644 index ef23e7d..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt +++ /dev/null @@ -1,79 +0,0 @@ -package xyz.alexcrea.cuanvil.command - -import io.delilaheve.CustomAnvil -import org.bukkit.Bukkit -import org.bukkit.command.Command -import org.bukkit.command.CommandExecutor -import org.bukkit.command.CommandSender -import xyz.alexcrea.cuanvil.api.event.CAConfigReadyEvent -import xyz.alexcrea.cuanvil.config.ConfigHolder -import xyz.alexcrea.cuanvil.dependency.DependencyManager -import xyz.alexcrea.cuanvil.gui.config.global.* -import xyz.alexcrea.cuanvil.update.UpdateHandler - -class ReloadExecutor : CASubCommand() { - - override fun executeCommand(sender: CommandSender, - cmd: Command, - cmdstr: String, - args: Array): Boolean { - if (!allowed(sender)) { - sender.sendMessage("§cYou do not have permission to reload the config") - return false - } - sender.sendMessage("§eReloading config...") - val hardfail = args.isNotEmpty() && ("hard".equals(args[0], true)) - val commandSuccess = commandBody(hardfail) - if (commandSuccess) { - sender.sendMessage("§aConfig reloaded !") - } else { - sender.sendMessage("§cConfig was not able to be reloaded...") - if (hardfail) { - sender.sendMessage("§4Hard fail, plugin disabled") - } - } - return commandSuccess - } - - override fun allowed(sender: CommandSender): Boolean { - return sender.hasPermission(CustomAnvil.commandReloadPermission) - } - - override fun description(): String { - return "Reload the configuration of this plugin" - } - - /** - * Execute the command, return true if success or false otherwise - */ - private fun commandBody(hardfail: Boolean): Boolean { - try { - if (!ConfigHolder.reloadAllFromDisk(hardfail)) return false - - // Then update all global gui containing value from config - BasicConfigGui.getInstance()?.updateGuiValues() - EnchantCostConfigGui.getInstance()?.updateGuiValues() - EnchantLimitConfigGui.getInstance()?.updateGuiValues() - - EnchantConflictGui.getCurrentInstance()?.reloadValues() - GroupConfigGui.getCurrentInstance()?.reloadValues() - UnitRepairConfigGui.getCurrentInstance()?.reloadValues() - CustomRecipeConfigGui.getCurrentInstance()?.reloadValues() - - // handle minecraft version update - UpdateHandler.handleMCVersionUpdate() - - // Handle dependency reload - DependencyManager.handleConfigReload() - - // Call event - val configReadyEvent = CAConfigReadyEvent() - Bukkit.getServer().pluginManager.callEvent(configReadyEvent) - - return true - } catch (e: Exception) { - e.printStackTrace() - return false - } - } -} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt deleted file mode 100644 index b730a0e..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt +++ /dev/null @@ -1,331 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency - -import com.maddoxh.superEnchants.SuperEnchants -import io.delilaheve.CustomAnvil -import net.kyori.adventure.text.Component -import org.bukkit.Bukkit -import org.bukkit.ChatColor -import org.bukkit.command.CommandSender -import org.bukkit.entity.HumanEntity -import org.bukkit.entity.Player -import org.bukkit.event.inventory.InventoryClickEvent -import org.bukkit.event.inventory.PrepareAnvilEvent -import org.bukkit.inventory.AnvilInventory -import org.bukkit.inventory.Inventory -import org.bukkit.inventory.InventoryView -import org.bukkit.inventory.ItemStack -import xyz.alexcrea.cuanvil.anvil.AnvilCost -import xyz.alexcrea.cuanvil.anvil.AnvilUseType -import xyz.alexcrea.cuanvil.api.event.listener.CAClickResultBypassEvent -import xyz.alexcrea.cuanvil.api.event.listener.CAEarlyPreAnvilBypassEvent -import xyz.alexcrea.cuanvil.api.event.listener.CAPreAnvilBypassEvent -import xyz.alexcrea.cuanvil.api.event.listener.CATreatAnvilResult2Event -import xyz.alexcrea.cuanvil.config.ConfigHolder -import xyz.alexcrea.cuanvil.dependency.datapack.DataPackDependency -import xyz.alexcrea.cuanvil.dependency.gui.GenericExternGuiTester -import xyz.alexcrea.cuanvil.dependency.packet.PacketManager -import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerSelector -import xyz.alexcrea.cuanvil.dependency.plugins.* -import xyz.alexcrea.cuanvil.dependency.scheduler.BukkitScheduler -import xyz.alexcrea.cuanvil.dependency.scheduler.FoliaScheduler -import xyz.alexcrea.cuanvil.dependency.scheduler.TaskScheduler -import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil -import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.componentLore -import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT -import xyz.alexcrea.cuanvil.util.MetricsUtil.trackError -import java.util.logging.Level - -object DependencyManager { - - lateinit var scheduler: TaskScheduler - lateinit var packetManager: PacketManager - var externGuiTester: GenericExternGuiTester = GenericExternGuiTester() - - var enchantmentSquaredCompatibility: EnchantmentSquaredDependency? = null - var ecoEnchantCompatibility: EcoEnchantDependency? = null - var excellentEnchantsCompatibility: ExcellentEnchantsDependency? = null - - var disenchantmentCompatibility: DisenchantmentDependency? = null - var havenBagsCompatibility: HavenBagsDependency? = null - - var axPlayerWarpsCompatibility: AxPlayerWarpsDependency? = null - - var itemsAdderCompatibility: ItemsAdderDependency? = null - - val genericDependencies = ArrayList() - - fun loadDependency() { - val pluginManager = Bukkit.getPluginManager() - - // Bukkit or Paper scheduler ? - scheduler = if (PlatformUtil.isFolia) { - CustomAnvil.instance.logger.info("Folia detected... Custom Anvil Folia support is experimental. issues are more likely to happens.") - - FoliaScheduler() - } else BukkitScheduler() - - // Packet Manager - val forceProtocolib = ConfigHolder.DEFAULT_CONFIG.config.getBoolean("force_protocolib", false) - packetManager = PacketManagerSelector.selectPacketManager(forceProtocolib) - - // Enchantment Squared dependency - if (pluginManager.isPluginEnabled("EnchantsSquared")) { - enchantmentSquaredCompatibility = EnchantmentSquaredDependency(pluginManager.getPlugin("EnchantsSquared")!!) - enchantmentSquaredCompatibility!!.disableAnvilListener() - } - - // EcoEnchants dependency - if (pluginManager.isPluginEnabled("EcoEnchants")) { - ecoEnchantCompatibility = EcoEnchantDependency(pluginManager.getPlugin("EcoEnchants")!!) - ecoEnchantCompatibility!!.disableAnvilListener() - } - - // Excellent Enchants dependency - if (pluginManager.isPluginEnabled("ExcellentEnchants")) { - excellentEnchantsCompatibility = ExcellentEnchantsDependency() - excellentEnchantsCompatibility!!.redirectListeners() - } - - // Disenchantment dependency - if (pluginManager.isPluginEnabled("Disenchantment")) { - disenchantmentCompatibility = DisenchantmentDependency() - disenchantmentCompatibility!!.redirectListeners() - } - - // HavenBags dependency - if (pluginManager.isPluginEnabled("HavenBags")) { - havenBagsCompatibility = HavenBagsDependency() - havenBagsCompatibility!!.redirectListeners() - } - - // AxPlayerWarps dependency - if (pluginManager.isPluginEnabled("AxPlayerWarps")) { - axPlayerWarpsCompatibility = AxPlayerWarpsDependency() - } - - if (pluginManager.isPluginEnabled("ItemsAdder")){ - val dependency = ItemsAdderDependency(pluginManager.getPlugin("ItemsAdder")!!) - itemsAdderCompatibility = dependency - genericDependencies.add(dependency) - } - - // "Generic" dependencies - if (pluginManager.isPluginEnabled("ToolStats")) - genericDependencies.add(ToolStatsDependency(pluginManager.getPlugin("ToolStats")!!)) - - if (pluginManager.isPluginEnabled("ItemsAdder")) - genericDependencies.add(GenericPluginDependency(pluginManager.getPlugin("ItemsAdder")!!)) - - if (pluginManager.isPluginEnabled("SuperEnchants")){ - val compatibility = SuperEnchantDependency(pluginManager.getPlugin("SuperEnchants")!! as SuperEnchants) - if(compatibility.registerEnchantments()) - genericDependencies.add(compatibility) - } - - for (dependency in genericDependencies) - dependency.redirectListeners() - - } - - fun handleCompatibilityConfig() { - enchantmentSquaredCompatibility?.registerPluginConfiguration() - - // datapacks - DataPackDependency.handleDatapackConfigs() - } - - fun registerEnchantments() { - enchantmentSquaredCompatibility?.registerEnchantments() - ecoEnchantCompatibility?.registerEnchantments() - excellentEnchantsCompatibility?.registerEnchantments() - - } - - fun handleConfigReload() { - // Register enchantment of compatible plugin and load configuration change. - handleCompatibilityConfig() - - // Then handle plugin reload - ecoEnchantCompatibility?.handleConfigReload() - } - - private fun logException(target: CommandSender, e: Exception) { - CustomAnvil.instance.logger.log( - Level.SEVERE, - "Error while trying to handle custom anvil supported plugin: ", - e - ) - trackError(e) - - // Finally, warn the player - target.sendMessage( - "[" + ChatColor.YELLOW.toString() + "CustomAnvil" + ChatColor.WHITE.toString() + "] " + - ChatColor.RED.toString() + "Error while handling the anvil." - ) - } - - private fun logExceptionAndClear(target: CommandSender, inventory: Inventory, e: Exception) { - // Just in case to avoid illegal items - inventory.setItem(ANVIL_OUTPUT_SLOT, null) - - logException(target, e) - } - - // Return true if should bypass (either by a dependency or error) - // called before immutability test - fun earlyTryEventPreAnvilBypass(event: PrepareAnvilEvent, player: HumanEntity): Boolean { - try { - return earlyUnsafeTryEventPreAnvilBypass(event, player) - } catch (e: Exception) { - logExceptionAndClear(event.view.player, event.inventory, e) - return true - } - } - - private fun earlyUnsafeTryEventPreAnvilBypass(event: PrepareAnvilEvent, player: HumanEntity): Boolean { - // Run the event - val bypassEvent = CAEarlyPreAnvilBypassEvent(event) - Bukkit.getPluginManager().callEvent(bypassEvent) - - var bypass = bypassEvent.isCancelled - - // Test if the inventory is a gui(version specific) - if (!bypass && externGuiTester.testIfGui(event.view)) bypass = true - - // Test if in an ax player warp rating gui - if (!bypass && (axPlayerWarpsCompatibility?.testIfGui(player) == true)) bypass = true - - return bypass - } - - // Return true if should bypass (either by a dependency or error) - fun tryEventPreAnvilBypass(event: PrepareAnvilEvent, player: Player): Boolean { - try { - return unsafeTryEventPreAnvilBypass(event, player) - } catch (e: Exception) { - logExceptionAndClear(event.view.player, event.inventory, e) - return true - } - } - - private fun unsafeTryEventPreAnvilBypass(event: PrepareAnvilEvent, player: Player): Boolean { - // Run the event - val bypassEvent = CAPreAnvilBypassEvent(event) - Bukkit.getPluginManager().callEvent(bypassEvent) - - var bypass = bypassEvent.isCancelled - - // Test if disenchantment used prepare anvil - if (!bypass && (disenchantmentCompatibility?.testPrepareAnvil(event, player) == true)) bypass = true - - // Test heaven bags used prepare anvil - if (!bypass && (havenBagsCompatibility?.testPrepareAnvil(event, player) == true)) bypass = true - - // Test excellent enchantments used prepare anvil - if (!bypass && (excellentEnchantsCompatibility?.testPrepareAnvil(event) == true)) bypass = true - - for (genericDependency in genericDependencies) { - if (!bypass && genericDependency.testPrepareAnvil(event)) bypass = true - } - - return bypass - } - - // Return null if there was an issue - fun tryTreatAnvilResult( - view: InventoryView, - inventory: Inventory, // TODO REMOVE, use view instead on legacy removal - player: HumanEntity, - result: ItemStack, - useType: AnvilUseType, - cost: AnvilCost - ): ItemStack? { - val treatEvent = CATreatAnvilResult2Event(view, inventory, useType, result, cost) - try { - unsafeTryTreatAnvilResult(treatEvent) - return treatEvent.result - } catch (e: Exception) { - logExceptionAndClear(player, inventory, e) - return null - } - } - - private fun unsafeTryTreatAnvilResult(event: CATreatAnvilResult2Event) { - Bukkit.getPluginManager().callEvent(event) - - excellentEnchantsCompatibility?.treatAnvilResult(event) - } - - // Return true if should bypass (either by a dependency or error) - fun tryClickAnvilResultBypass(event: InventoryClickEvent, inventory: AnvilInventory): Boolean { - try { - return unsafeTryClickAnvilResultBypass(event, inventory) - } catch (e: Exception) { - logExceptionAndClear(event.view.player, event.inventory, e) - return true - } - } - - private fun unsafeTryClickAnvilResultBypass(event: InventoryClickEvent, inventory: AnvilInventory): Boolean { - // Run the event - val bypassEvent = CAClickResultBypassEvent(event) - Bukkit.getPluginManager().callEvent(bypassEvent) - - var bypass = bypassEvent.isCancelled - - // Test if disenchantment used event click - if (!bypass && (disenchantmentCompatibility?.testAnvilResult(event, inventory) == true)) bypass = true - - // Test if haven bag used event click - if (!bypass && (havenBagsCompatibility?.testAnvilResult(event, inventory) == true)) bypass = true - - // Test if disenchantment used event click - if (!bypass && (excellentEnchantsCompatibility?.testAnvilResult(event) == true)) bypass = true - - for (genericDependency in genericDependencies) { - if (!bypass && genericDependency.testAnvilResult(event)) bypass = true - } - - // Test if the inventory is a gui(version specific) - if (!bypass && externGuiTester.testIfGui(event.view)) bypass = true - - // Test if in an ax player warp rating gui - if (!bypass && (axPlayerWarpsCompatibility?.testIfGui(event.view.player) == true)) bypass = true - - return bypass - } - - // Clone item and use plugin specific clone if needed - fun cloneItem(player: HumanEntity, item: ItemStack): ItemStack { - try { - return unsafeCloneItem(item) - } catch (e: Exception) { - logException(player, e) - return item.clone() - } - } - - private fun unsafeCloneItem(item: ItemStack): ItemStack { - val cloned = itemsAdderCompatibility?.tryClone(item) - if(cloned != null) return cloned - - return item.clone() - } - - fun stripLore(item: ItemStack): MutableList { - val dummy = item.clone() - - enchantmentSquaredCompatibility?.stripLore(dummy) - - val itemLore = dummy.itemMeta?.componentLore() ?: return ArrayList() - - val lore = ArrayList() - lore.addAll(itemLore) - return lore - } - - fun updateLore(item: ItemStack) { - enchantmentSquaredCompatibility?.updateLore(item) - } - -} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/MinecraftVersionUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/MinecraftVersionUtil.kt deleted file mode 100644 index cbd2209..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/MinecraftVersionUtil.kt +++ /dev/null @@ -1,58 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency - -import xyz.alexcrea.cuanvil.update.UpdateUtils - -object MinecraftVersionUtil { - - val craftbukkitVersion: String? - get() { - val version = UpdateUtils.currentMinecraftVersion() - if (version.major != 1) return null - - return when (version.minor) { - 17 -> when (version.patch) { - 0, 1 -> "1_17R1" - else -> null - } - - 18 -> when (version.patch) { - 0, 1 -> "1_18R1" - 2 -> "1_18R2" - else -> null - } - - 19 -> when (version.patch) { - 0, 1, 2 -> "1_19R1" - 3 -> "1_19R2" - 4 -> "1_19R3" - else -> null - } - - 20 -> when (version.patch) { - 0, 1 -> "1_20R1" - 2 -> "1_20R2" - 3, 4 -> "1_20R3" - 5, 6 -> "1_20R4" - else -> null - } - - 21 -> when (version.patch) { - 0, 1 -> "1_21R1" - 2, 3 -> "1_21R2" - 4 -> "1_21R3" - 5 -> "1_21R4" - 6, 7, 8 -> "1_21R5" - 9, 10 -> "1_21R6" - 11 -> "1_21R7" - else -> null - } - - else -> null - } - } - - val isTooNewForSpigot: Boolean get() { - return UpdateUtils.currentMinecraftVersion().major != 1 - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/datapack/DataPackDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/datapack/DataPackDependency.kt deleted file mode 100644 index 6d54456..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/datapack/DataPackDependency.kt +++ /dev/null @@ -1,305 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.datapack - -import io.delilaheve.CustomAnvil -import org.bukkit.Material -import org.bukkit.NamespacedKey -import org.bukkit.configuration.file.FileConfiguration -import org.bukkit.configuration.file.YamlConfiguration -import xyz.alexcrea.cuanvil.api.ConflictBuilder -import xyz.alexcrea.cuanvil.api.EnchantmentApi -import xyz.alexcrea.cuanvil.api.MaterialGroupApi -import xyz.alexcrea.cuanvil.config.ConfigHolder -import xyz.alexcrea.cuanvil.enchant.wrapped.CABukkitEnchantment -import xyz.alexcrea.cuanvil.enchant.wrapped.CAIncompatibleAllEnchant -import xyz.alexcrea.cuanvil.group.IncludeGroup -import xyz.alexcrea.cuanvil.update.UpdateUtils -import xyz.alexcrea.cuanvil.update.Version -import java.io.InputStreamReader - -object DataPackDependency { - private val START_DETECT_VERSION = Version(1, 20, 5) - - /** - * Map of the latest CustomAnvil update related to the pack - */ - private val LASTEST_VERSION = mapOf( - Pair("bracken", Version(1, 11, 0)), - Pair("enchantplus", Version(1, 13, 0)), - Pair("dungeons_and_taverns", Version(1, 13, 0)) - ) - - val enabledDatapacks: List - get() { - val version: Version = UpdateUtils.currentMinecraftVersion() - if (version.lesserThan(START_DETECT_VERSION)) return emptyList() - - return DataPackTester.enabledPacks - } - - fun handleDatapackConfigs() { - val enabledDatapack = enabledDatapacks - for (packName in enabledDatapack) { - // Handling of pack name is horrible: it is based on file name - // So if someone rename a datapack it will make me sad - if(!packName.startsWith("file/")) continue - - if (packName.contains("bp_post_scarcity", ignoreCase = true) - || packName.contains("bracken", ignoreCase = true)) { - handlePack("bracken") - continue - } - - if (packName.contains("neoenchant", ignoreCase = true)) { - handlePack("enchantplus") - continue - } - - if (packName.contains("Dungeons and Taverns", ignoreCase = true)) { - handlePack("dungeons_and_taverns") - continue - } - - } - } - - private fun handlePack(pack: String){ - CustomAnvil.instance.logger.info("trying to handle datapack $pack") - handlePackInitialConfig(pack) - writeDefaultByNamespace(pack) - CustomAnvil.instance.logger.info("configuration done for $pack") - } - - private fun handlePackInitialConfig(pack: String) { - val defConfig = ConfigHolder.DEFAULT_CONFIG - val version = LASTEST_VERSION[pack] - if(version == null) { - throw RuntimeException("The pack $pack has no latest version hard coded in the plugin") - } - - val currentVersion = Version.fromString(defConfig.config.getString("datapack.$pack")) - if (currentVersion.greaterEqual(version)) { - handleEnchantAllConflict(pack) - return - } - - // Add pack value or do update from previous version - // note: update thingy is not yet implemented - configureDatapack(pack) - - // Finally, set current pack version to config - defConfig.config.set("datapack.$pack", version.toString()) - defConfig.saveToDisk(true) - } - - private fun configureDatapack(pack: String) { - val itemGroups = javaClass.getResource("/datapack/$pack/item_groups.yml") - val itemConflict = javaClass.getResource("/datapack/$pack/item_conflict.yml") - val enchantConflict = javaClass.getResource("/datapack/$pack/enchant_conflict.yml") - - if (itemGroups != null) { - val reader = InputStreamReader(itemGroups.openStream()) - val yml = YamlConfiguration.loadConfiguration(reader) - - handleItemGroups(yml) - } - - val newConflictList = ArrayList() - var needSave = false - if (itemConflict != null) { - val reader = InputStreamReader(itemConflict.openStream()) - val yml = YamlConfiguration.loadConfiguration(reader) - - addItemConflicts(yml, newConflictList) - } - - if (enchantConflict != null) { - val reader = InputStreamReader(enchantConflict.openStream()) - val yml = YamlConfiguration.loadConfiguration(reader) - - needSave = addEnchantConflict(yml, newConflictList) - } - - for (conflict in newConflictList) { - needSave = !conflict.registerIfAbsent() && needSave - } - - if (needSave) { - ConfigHolder.CONFLICT_HOLDER.saveToDisk(true) - } - } - - // Order matter for this file - // Could rewrite to not matter but not really important, so I keep it like that - private fun handleItemGroups(yml: YamlConfiguration) { - for (groupName in yml.getKeys(false)) { - val section = yml.getConfigurationSection(groupName) ?: continue - - var group = MaterialGroupApi.getGroup(groupName) - val exist = group != null - - if (group == null) group = IncludeGroup(groupName) - - for (name in section.getStringList("items")) { - val mat = Material.getMaterial(name.uppercase()) - if (mat == null) { - CustomAnvil.instance.logger.warning("Could not find material $name for item group $groupName") - continue - } - group.addToPolicy(mat.key) - } - for (name in section.getStringList("groups")) { - val otherGroup = MaterialGroupApi.getGroup(name) - if (otherGroup == null) { - CustomAnvil.instance.logger.warning("Could not find sub group $name for group $groupName") - continue - } - - group.addToPolicy(otherGroup) - } - - group.updateMaterials() - - if (exist) { - MaterialGroupApi.writeMaterialGroup(group) - } else { - MaterialGroupApi.addMaterialGroup(group, true) - } - } - } - - private fun addItemConflicts(yml: FileConfiguration, conflictList: MutableList) { - for (ench in yml.getKeys(false)) { - val groups = yml.getStringList(ench) - - val conflict = ConflictBuilder( - "restriction_${ench.replace(":", "_")}", - CustomAnvil.instance - ) - conflict.addEnchantment(NamespacedKey.fromString(ench)!!) - for (group in groups) { - conflict.addExcludedGroup(group) - } - conflict.addExcludedGroup("enchanted_book") - - conflictList.add(conflict) - } - } - - private fun addEnchantConflict(yml: YamlConfiguration, conflictList: MutableList): Boolean { - var needSave = false - - val conflicts = HashMap() - for (ench in yml.getKeys(false)) { - val groups = yml.getStringList(ench) - - for (group in groups) { - if (group.startsWith('#')) { - needSave = joinGroup(conflicts, group.substring(1), ench) || needSave - } else { - createConflict(conflictList, ench, group) - } - } - } - - conflictList.addAll(conflicts.values) - return needSave - } - - private fun createConflict(conflictList: MutableList, ench: String, other: String) { - - val conflict = ConflictBuilder( - "conflict_" + - "${ench.replace(":", "_")}_" + - other.replace(":", "_"), - CustomAnvil.instance - ) - conflict.addEnchantment(NamespacedKey.fromString(ench)!!) - conflict.addEnchantment(NamespacedKey.fromString(other)!!) - - conflict.setMaxBeforeConflict(1) - - conflictList.add(conflict) - } - - private fun setEnchantAsAll(ench: String) { - // We assume current is not null and of type CABukkitEnchantment - val current = EnchantmentApi.getByKey(NamespacedKey.fromString(ench)!!) as CABukkitEnchantment - - // We need to replace current wrapped enchantment with the all conflict wrapper - EnchantmentApi.unregisterEnchantment(current) - EnchantmentApi.registerEnchantment(CAIncompatibleAllEnchant(current.bukkit, current.defaultRarity())) - } - - private fun joinGroup(conflicts: HashMap, group: String, ench: String): Boolean { - if ("all".equals(group, ignoreCase = true)) { - setEnchantAsAll(ench) - return false - } else { - val config = ConfigHolder.CONFLICT_HOLDER.config - - // If conflict do not yet exist - if (!config.isConfigurationSection(group)) { - val conflict = conflicts.getOrPut(group) { - val conflict = ConflictBuilder(group, CustomAnvil.instance) - conflict.setMaxBeforeConflict(1) - conflict - } - - conflict.addEnchantment(NamespacedKey.fromString(ench)!!) - return false - } - // Find current conflict - val manager = ConfigHolder.CONFLICT_HOLDER.conflictManager - - // This assumes that: - // - the conflict existing in the config exist in the runtime config (as configuration section exist) - // - the enchantment exist and is provided correctly - val conflict = manager.conflictList.find { - it.name.equals(group, ignoreCase = true) - } - if(conflict == null) { - // This should not happen as configuration section - CustomAnvil.instance.logger.severe("Could not find $group while its configuration section exist... this should NOT happen") - return false - } - - val key = NamespacedKey.fromString(ench)!! - val enchant = EnchantmentApi.getByKey(key) - if (enchant == null){ - CustomAnvil.instance.logger.severe("Could not find enchantment $ench while configuring pack a datapack") - return false - } - - conflict.addEnchantment(enchant) - - UpdateUtils.addAbsentToList(config, "$group.enchantments", ench) - return true - } - } - - private fun handleEnchantAllConflict(pack: String) { - val enchantConflict = javaClass.getResource("/datapack/$pack/enchant_conflict.yml") ?: return - - val reader = InputStreamReader(enchantConflict.openStream()) - val yml = YamlConfiguration.loadConfiguration(reader) - - for (ench in yml.getKeys(false)) { - val groups = yml.getStringList(ench) - - if (groups.contains("#all")) { - setEnchantAsAll(ench) - } - } - } - - private fun writeDefaultByNamespace(namespace: String) { - for (enchantment in EnchantmentApi.getRegisteredEnchantments().values) { - if(!enchantment.key.namespace.equals(namespace, ignoreCase = true)) continue - - CustomAnvil.log("Writing default for ${enchantment.key}") - EnchantmentApi.writeDefaultConfig(enchantment, false) - } - - } - -} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/economy/EconomyManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/economy/EconomyManager.kt deleted file mode 100644 index 67a6c1e..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/economy/EconomyManager.kt +++ /dev/null @@ -1,32 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.economy - -import org.bukkit.entity.Player -import org.bukkit.plugin.Plugin -import java.math.BigDecimal - -interface EconomyManager { - - companion object { - var economy: EconomyManager? = null - - fun setupEconomy(plugin: Plugin) { - if (plugin.server.pluginManager.getPlugin("Vault") == null) - return - if (UnlockedEconomyManager.unlockedAvailable()) - economy = UnlockedEconomyManager(plugin) - - if (economy == null || !economy!!.initialized()) - economy = VaultEconomyManager(plugin) - } - - } - - fun initialized(): Boolean - - // We assume "initialized" got checked before these function get called - fun has(player: Player, money: BigDecimal): Boolean - fun remove(player: Player, money: BigDecimal): Boolean - - fun format(money: BigDecimal): String; - -} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/economy/UnlockedEconomyManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/economy/UnlockedEconomyManager.kt deleted file mode 100644 index da66f30..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/economy/UnlockedEconomyManager.kt +++ /dev/null @@ -1,74 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.economy - -import io.delilaheve.util.ConfigOptions -import net.milkbowl.vault2.economy.Economy -import org.bukkit.entity.Player -import org.bukkit.plugin.Plugin -import java.math.BigDecimal - -class UnlockedEconomyManager : EconomyManager { - - val plugin: String - val economy: Economy? - - companion object { - fun unlockedAvailable(): Boolean { - try { - Class.forName("net.milkbowl.vault2.economy.Economy") - return true - } catch (_: ClassNotFoundException) { - return false - } - } - } - - constructor(plugin: Plugin) { - this.plugin = plugin.name - - val rsp = plugin.server.servicesManager.getRegistration(Economy::class.java) - economy = rsp?.getProvider() - } - - override fun initialized(): Boolean { - return economy != null - } - - private fun currency(): String { - val configured = ConfigOptions.usedCurrency - - return if ("default".equals(configured, true)) - economy!!.getDefaultCurrency(plugin) - else configured - } - - override fun has(player: Player, money: BigDecimal): Boolean { - if (money.signum() <= 0) return true - - return economy!!.has( - plugin, - player.uniqueId, - player.world.name, - currency(), - money - ) - } - - override fun remove(player: Player, money: BigDecimal): Boolean { - if (money.signum() <= 0) return true - - return economy!!.withdraw( - plugin, - player.uniqueId, - player.world.name, - currency(), - money - ) - .transactionSuccess() - } - - override fun format(money: BigDecimal): String { - return economy!!.format(plugin, money, currency()) - } - - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/economy/VaultEconomyManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/economy/VaultEconomyManager.kt deleted file mode 100644 index 058485e..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/economy/VaultEconomyManager.kt +++ /dev/null @@ -1,37 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.economy - -import net.milkbowl.vault.economy.Economy -import org.bukkit.entity.Player -import org.bukkit.plugin.Plugin -import java.math.BigDecimal - -class VaultEconomyManager : EconomyManager { - - val economy: Economy? - - constructor(plugin: Plugin) { - val rsp = plugin.server.servicesManager.getRegistration(Economy::class.java) - economy = rsp?.getProvider() - } - - override fun initialized(): Boolean { - return economy != null - } - - override fun has(player: Player, money: BigDecimal): Boolean { - if (money.signum() <= 0) return true - - return economy!!.has(player, money.toDouble()) - } - - override fun remove(player: Player, money: BigDecimal): Boolean { - if (money.signum() <= 0) return true - - return economy!!.withdrawPlayer(player, money.toDouble()).transactionSuccess() - } - - override fun format(money: BigDecimal): String { - return economy!!.format(money.toDouble()) - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/GenericExternGuiTester.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/GenericExternGuiTester.kt deleted file mode 100644 index 4046f4a..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/GenericExternGuiTester.kt +++ /dev/null @@ -1,111 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.gui - -import org.bukkit.inventory.InventoryView -import xyz.alexcrea.cuanvil.dependency.MinecraftVersionUtil -import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil -import java.lang.reflect.Method - -class GenericExternGuiTester { - - companion object { - private const val ANVIL_CLASS_NAME = "org.bukkit.craftbukkit.inventory.view.CraftAnvilView" - private const val INV_CLASS_NAME = "org.bukkit.craftbukkit.inventory.CraftInventoryView" - private const val HANDLE_METHOD_NAME = "getHandle" - - private const val CANONICAL_PAPER_ANVIL_MENU = "net.minecraft.world.inventory.AnvilMenu" - } - - var testExist = false - var inTesting = false - - var testedClass: String? = null - lateinit var getHandleMethod: Method - - private fun getContainerClass(view: InventoryView): Class? { - if(!testedClass.contentEquals(view.javaClass.name)) - return null - - val container = getHandleMethod.invoke(view) - return container.javaClass - } - - fun tryFromClass(className: String) { - val clazz = Class.forName(className) - testedClass = className - - getHandleMethod = clazz.getMethod(HANDLE_METHOD_NAME) - } - - fun isInTest(): Boolean { - if(!testExist) testClassExist() - return inTesting - } - - fun testClassExist() { - testExist = true - - // We first try to get craft anvil interface, - // but is absent on old version so we try craft inventory view before - try { - tryFromClass(ANVIL_CLASS_NAME) - return - } - catch (_: ClassNotFoundException) {} - catch (_: NoSuchMethodException) {} - - try { - tryFromClass(INV_CLASS_NAME) - return - } - catch (_: ClassNotFoundException) {} - catch (_: NoSuchMethodException) {} - - inTesting = true - } - - // Try if were in another plugin anvil inventory - fun testIfGui(inventory: InventoryView): Boolean { - // In case we are in a test environment - if(isInTest()) return false - - val clazz = getContainerClass(inventory) ?: return false - - val clazzName = clazz.name - if(!PlatformUtil.isPaper){ - // Blacklist gui causing issue - if (expectWesjd(clazzName)) return true - if (expectXenondevUI(clazzName)) return true - if (expectVanePortal(clazzName)) return true - - return false - } - - // Only allow cannonical anvil menu class - return !CANONICAL_PAPER_ANVIL_MENU.equals(clazzName, true) - } - - // Known custom implementations - fun expectWesjd(name: String): Boolean { - val expectedWesjdGuiPath = "anvilgui.version.Wrapper${MinecraftVersionUtil.craftbukkitVersion}" - - return name.contains(expectedWesjdGuiPath) - } - - private val XenondevUIPrefix: String - get() = "xyz.xenondevs.inventoryaccess." - private val XenondevUISufix: String - get() = ".AnvilInventoryImpl" - - fun expectXenondevUI(name: String): Boolean { - return name.startsWith(XenondevUIPrefix) - && name.endsWith(XenondevUISufix) - } - - fun expectVanePortal(name: String): Boolean { - val expected = "org.oddlama.vane.core.menu.AnvilMenu\$AnvilContainer" - - return name == expected - } - - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/PacketManagerSelector.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/PacketManagerSelector.kt deleted file mode 100644 index d74ef08..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/PacketManagerSelector.kt +++ /dev/null @@ -1,54 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.packet - -import org.bukkit.Bukkit -import xyz.alexcrea.cuanvil.dependency.DependencyManager -import xyz.alexcrea.cuanvil.dependency.MinecraftVersionUtil -import xyz.alexcrea.cuanvil.dependency.packet.versions.* -import xyz.alexcrea.cuanvil.update.UpdateUtils - -object PacketManagerSelector { - - private const val PAPER_CRAFT_PLAYER_CLASS = "org.bukkit.craftbukkit.entity.CraftPlayer" - - fun selectPacketManager(forceProtocolib: Boolean): PacketManager { - // Try to find version - if(DependencyManager.externGuiTester.isInTest()) - return NoPacketManager() - - return if (forceProtocolib) - protocolibIfPresent - else { - try { - Class.forName(PAPER_CRAFT_PLAYER_CLASS) - - return PaperPacketManager() - } catch (_: ClassNotFoundException) { - return reobfPacketManager ?: protocolibIfPresent - } - } - } - - private val protocolibIfPresent: PacketManager - get() = - if (Bukkit.getPluginManager().isPluginEnabled("ProtocolLib")) - ProtocoLibWrapper() - else - NoPacketManager() - - // Reobfuscated packet manager for spigot or paper as it remap - private val reobfPacketManager: PacketManagerBase? - get() { - val versionParts = UpdateUtils.currentMinecraftVersion() - if (versionParts.major != 1) return null - - try { - val clazz = Class.forName("xyz.alexcrea.cuanvil.dependency.packet.versions." + - "V${MinecraftVersionUtil.craftbukkitVersion}_PacketManager") - - val manager = clazz.getConstructor().newInstance() - return manager as PacketManagerBase - } catch (_: ClassNotFoundException) { - return null - } - } -} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/AxPlayerWarpsDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/AxPlayerWarpsDependency.kt deleted file mode 100644 index e0ca218..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/AxPlayerWarpsDependency.kt +++ /dev/null @@ -1,13 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.plugins - -import com.artillexstudios.axplayerwarps.libs.axapi.gui.AnvilInput -import org.bukkit.entity.HumanEntity -import org.bukkit.entity.Player - -class AxPlayerWarpsDependency { - - fun testIfGui(player: HumanEntity): Boolean { - return player is Player && AnvilInput.get(player) != null - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/DisenchantmentDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/DisenchantmentDependency.kt deleted file mode 100644 index 690b384..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/DisenchantmentDependency.kt +++ /dev/null @@ -1,102 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.plugins - -import com.jankominek.disenchantment.Disenchantment -import com.jankominek.disenchantment.events.DisenchantClickEvent -import com.jankominek.disenchantment.events.DisenchantEvent -import com.jankominek.disenchantment.events.ShatterClickEvent -import com.jankominek.disenchantment.events.ShatterEvent -import com.jankominek.disenchantment.listeners.DisenchantClickListener -import com.jankominek.disenchantment.listeners.ShatterClickListener -import io.delilaheve.CustomAnvil -import org.bukkit.entity.Player -import org.bukkit.event.Listener -import org.bukkit.event.inventory.InventoryClickEvent -import org.bukkit.event.inventory.PrepareAnvilEvent -import org.bukkit.inventory.AnvilInventory -import org.bukkit.inventory.ItemStack -import xyz.alexcrea.cuanvil.anvil.AnvilCost -import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener -import xyz.alexcrea.cuanvil.util.MetricsUtil.trackError -import xyz.alexcrea.cuanvil.util.anvil.AnvilXpUtil -import java.util.logging.Level -import kotlin.reflect.KClass - -class DisenchantmentDependency { - - init { - CustomAnvil.instance.logger.info("Disenchantment Detected !") - } - - fun redirectListeners() { - PrepareAnvilEvent.getHandlerList().unregister(Disenchantment.plugin) - - // unregister only the feature click event and not all - // This is to avoid the disenchantment gui breaking - try { - unregisterStaticDisenchantmentListener(ShatterClickListener::class) - unregisterStaticDisenchantmentListener(DisenchantClickListener::class) - } catch (e: Exception) { - CustomAnvil.instance.logger.log( - Level.SEVERE, "Could not initialize disenchantment support" + - "please report this bug to the developer", e - ) - trackError(e) - } - } - - private fun unregisterStaticDisenchantmentListener(clazz: KClass<*>) { - val field = clazz.java.getDeclaredField("listener") - field.isAccessible = true - val listener: Listener = field.get(null) as Listener - InventoryClickEvent.getHandlerList().unregister(listener) - } - - fun testPrepareAnvil(event: PrepareAnvilEvent, player: Player): Boolean { - val previousResult = event.result - event.result = null - - // Test if event change the result - DisenchantEvent.onEvent(event) - if (event.result != null) { - CustomAnvil.log("Detected pre anvil item extract bypass.") - AnvilXpUtil.setAnvilInvCost(event.inventory, event.view, player, AnvilCost(event.inventory.repairCost)) - return true - } - - ShatterEvent.onEvent(event) - if (event.result != null) { - CustomAnvil.log("Detected pre anvil split enchant bypass.") - AnvilXpUtil.setAnvilInvCost(event.inventory, event.view, player, AnvilCost(event.inventory.repairCost)) - return true - } - - event.result = previousResult - return false - } - - fun testAnvilResult(event: InventoryClickEvent, inventory: AnvilInventory): Boolean { - val previousResultSlot = inventory.getItem(PrepareAnvilListener.ANVIL_OUTPUT_SLOT)?.clone() - - // Test event if change the result - DisenchantClickEvent.onEvent(event) - if (!testAnvilInventoryChange(inventory, previousResultSlot) || event.isCancelled) { - CustomAnvil.log("Detected anvil click item extract bypass.") - return true - } - - ShatterClickEvent.onEvent(event) - if (!testAnvilInventoryChange(inventory, previousResultSlot) || event.isCancelled) { - CustomAnvil.log("Detected anvil click split enchant bypass.") - return true - } - - return false - } - - private fun testAnvilInventoryChange(inventory: AnvilInventory, previous: ItemStack?): Boolean { - val currentResult = inventory.getItem(PrepareAnvilListener.ANVIL_OUTPUT_SLOT) - - return currentResult == previous - } - -} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/EcoEnchantDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/EcoEnchantDependency.kt deleted file mode 100644 index 079d570..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/EcoEnchantDependency.kt +++ /dev/null @@ -1,90 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.plugins - -import com.willfp.eco.core.EcoPlugin -import com.willfp.ecoenchants.enchant.EcoEnchant -import com.willfp.ecoenchants.enchant.EcoEnchants -import com.willfp.ecoenchants.mechanics.infiniteIfNegative -import io.delilaheve.CustomAnvil -import org.bukkit.event.inventory.PrepareAnvilEvent -import org.bukkit.plugin.Plugin -import xyz.alexcrea.cuanvil.api.EnchantmentApi -import xyz.alexcrea.cuanvil.enchant.wrapped.CAEcoEnchant - -class EcoEnchantDependency(private val ecoEnchantPlugin: Plugin) { - - private val isLegacy: Boolean - private val legacyDependency: LegacyEcoEnchantDependency? - - init { - CustomAnvil.instance.logger.info("Eco Enchant Detected !") - - var isLegacy = true - try { - Class.forName("com.willfp.ecoenchants.enchant.EcoEnchants") - isLegacy = false - } catch (_: ClassNotFoundException) { - } - - this.isLegacy = isLegacy; - if (isLegacy) { - this.legacyDependency = LegacyEcoEnchantDependency() - } else { - this.legacyDependency = null - } - - } - - public fun getEcoLevelLimit(): Int { - return (ecoEnchantPlugin as EcoPlugin).configYml.getInt("anvil.enchant-limit").infiniteIfNegative() - } - - fun disableAnvilListener() { - PrepareAnvilEvent.getHandlerList().unregister(this.ecoEnchantPlugin) - } - - private var ecoEnchantOldEnchantments: MutableSet? = null - fun registerEnchantments() { - CustomAnvil.instance.logger.info("Preparing Eco Enchant compatibility...") - - if (isLegacy) { - legacyDependency!!.registerEnchantments(); - return - } - - val enchantments = EcoEnchants.values() - for (ecoEnchant in enchantments) { - EnchantmentApi.unregisterEnchantment(ecoEnchant.enchantment) // As eco enchants is loaded before custom anvil and register enchantment to registry, we need to unregister old "vanilla" enchant. - EnchantmentApi.registerEnchantment(CAEcoEnchant(ecoEnchant)) - } - - ecoEnchantOldEnchantments = HashSet(enchantments) - - CustomAnvil.instance.logger.info("Eco Enchant should now work as expected !") - } - - fun handleConfigReload() { - if (isLegacy) { - legacyDependency!!.handleConfigReload() - return - } - - // Should not happen in known case. - if (this.ecoEnchantOldEnchantments == null) return - - val newEnchantments = EcoEnchants.values() - - // Add new enchantments - for (ecoEnchant in newEnchantments) - if (!this.ecoEnchantOldEnchantments!!.contains(ecoEnchant)) - EnchantmentApi.registerEnchantment(CAEcoEnchant(ecoEnchant)) - - // Remove old enchantments that not now currently used - this.ecoEnchantOldEnchantments!!.removeAll(newEnchantments) - for (oldEnchantment in this.ecoEnchantOldEnchantments!!) { - EnchantmentApi.unregisterEnchantment(oldEnchantment.enchantment) - } - - this.ecoEnchantOldEnchantments = HashSet(newEnchantments) - } - -} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/EcoItemDependencyUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/EcoItemDependencyUtil.kt deleted file mode 100644 index 7e84231..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/EcoItemDependencyUtil.kt +++ /dev/null @@ -1,38 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.plugins - -import com.willfp.ecoitems.items.EcoItem -import com.willfp.ecoitems.items.EcoItems -import com.willfp.ecoitems.items.ecoItem -import org.bukkit.Material -import org.bukkit.NamespacedKey -import org.bukkit.inventory.ItemStack - -object EcoItemDependencyUtil { - - fun ecoItemNamespace(item: ItemStack): NamespacedKey? { - val ecoi = item.ecoItem ?: return null - - return ecoi.id - } - - fun ecoItemFromKey(key: NamespacedKey): EcoItem? { - return EcoItems.getByID(key.toString()) - } - - fun ecoItemMaterialFromKey(key: NamespacedKey): Material? { - val ecoi = ecoItemFromKey(key) ?: return null - - return ecoi.itemStack.type - } - - fun newEcoItemstack(key: NamespacedKey): ItemStack? { - val ecoi = ecoItemFromKey(key) ?: return null - - return ecoi.itemStack - } - - fun getItems(): List { - return EcoItems.values().map { item -> item.id } - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/EnchantmentSquaredDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/EnchantmentSquaredDependency.kt deleted file mode 100644 index d769986..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/EnchantmentSquaredDependency.kt +++ /dev/null @@ -1,200 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.plugins - -import io.delilaheve.CustomAnvil -import me.athlaeos.enchantssquared.enchantments.CustomEnchant -import me.athlaeos.enchantssquared.listeners.AnvilListener -import me.athlaeos.enchantssquared.managers.CustomEnchantManager -import org.bukkit.Material -import org.bukkit.NamespacedKey -import org.bukkit.event.inventory.InventoryClickEvent -import org.bukkit.event.inventory.PrepareAnvilEvent -import org.bukkit.inventory.ItemStack -import org.bukkit.plugin.Plugin -import xyz.alexcrea.cuanvil.api.ConflictBuilder -import xyz.alexcrea.cuanvil.api.EnchantmentApi -import xyz.alexcrea.cuanvil.api.MaterialGroupApi -import xyz.alexcrea.cuanvil.enchant.CAEnchantment -import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry -import xyz.alexcrea.cuanvil.enchant.bulk.EnchantSquaredBulkOperation -import xyz.alexcrea.cuanvil.enchant.wrapped.CAEnchantSquaredEnchantment -import xyz.alexcrea.cuanvil.group.IncludeGroup -import java.util.* - -class EnchantmentSquaredDependency(private val enchantmentSquaredPlugin: Plugin) { - - init { - CustomAnvil.instance.logger.info("Enchantment Squared Detected !") - CustomAnvil.instance.logger.info("Please be aware that Custom Anvil is bypassing Enchantment Squared ") - CustomAnvil.instance.logger.info( - "compatible_with, " + - "disable_anvil, " + - "incompatible_vanilla_enchantments, " + - "incompatible_custom_enchantments and max_level " + - "configuration values.") - } - - fun disableAnvilListener(){ - PrepareAnvilEvent.getHandlerList().unregister(this.enchantmentSquaredPlugin) - - // Find the anvil click event - var toRemove: AnvilListener? = null - for (registered in InventoryClickEvent.getHandlerList().registeredListeners) { - val listener = registered.listener - if(listener is AnvilListener) { - toRemove = listener - break - } - } - - if(toRemove != null) - InventoryClickEvent.getHandlerList().unregister(toRemove) - - } - - fun registerEnchantments(){ - CustomAnvil.instance.logger.info("Preparing Enchantment Squared compatibility...") - - // Register enchantments - for (enchant in CustomEnchantManager.getInstance().allEnchants.values) { - EnchantmentApi.registerEnchantment(CAEnchantSquaredEnchantment(enchant)) - } - - // Register bulk operation - val bulkOpperations = EnchantSquaredBulkOperation() - EnchantmentApi.addBulkGet(bulkOpperations) - EnchantmentApi.addBulkClean(bulkOpperations) - - } - - fun getEnchantmentsSquared(item: ItemStack, enchantments: MutableMap) { - val customEnchants = CustomEnchantManager.getInstance().getItemsEnchantsFromPDC(item) - - customEnchants.forEach{ - (enchantment, level ) -> enchantments[getWrappedEnchant(enchantment)] = level - } - - } - - fun getKeyFromEnchant(enchant: CustomEnchant): NamespacedKey{ - return NamespacedKey.fromString(enchant.type.lowercase(Locale.getDefault()), this.enchantmentSquaredPlugin)!! - } - private fun getWrappedEnchant(enchant: CustomEnchant): CAEnchantment { - return CAEnchantment.getByKey(getKeyFromEnchant(enchant))!! - } - - fun registerPluginConfiguration(){ - CustomAnvil.instance.logger.info("Preparing Enchantment Squared config...") - - // Prepare enchantments - val esEnchantments = ArrayList() - CustomEnchantManager.getInstance().allEnchants.forEach { (_, enchant) -> - esEnchantments.add(getWrappedEnchant(enchant) as CAEnchantSquaredEnchantment) - } - - // Write groups and conflicts - writeMissingGroups() - writeMaterialRestriction(esEnchantments) - writeEnchantmentConflicts(esEnchantments) - - CustomAnvil.instance.logger.info("Enchantment Squared should now work as expected !") - } - - private fun writeMissingGroups(){ - // Write group that do not exist on custom anvil. - val shield = IncludeGroup("shield") - shield.addToPolicy(Material.SHIELD.key) - MaterialGroupApi.addMaterialGroup(shield) - - val elytra = IncludeGroup("elytra") - elytra.addToPolicy(Material.ELYTRA.key) - MaterialGroupApi.addMaterialGroup(elytra) - - val trinkets = IncludeGroup("trinkets") - trinkets.addToPolicy(Material.ROTTEN_FLESH.key) - MaterialGroupApi.addMaterialGroup(trinkets) - } - - private fun writeMaterialRestriction(esEnchantments: List){ - for (enchantment in esEnchantments) { - val conflict = ConflictBuilder("restriction_${enchantment.key.key}", CustomAnvil.instance) - conflict.addEnchantment(enchantment) - - // enchanted book is allowed in any case. - conflict.addExcludedGroup("enchanted_book") - - // Get allowed groups - for (esGroup in enchantment.enchant.compatibleItems) { - val caGroup = esGroupToCAGroup(esGroup) - if(caGroup == null){ - CustomAnvil.instance.logger.info("Could not find equivalent custom anvil group for $esGroup") - continue - } - conflict.addExcludedGroup(caGroup) - } - - conflict.registerIfAbsent() - } - } - - private fun writeEnchantmentConflicts(esEnchantments: List){ - val otherEnchants = ArrayList() - otherEnchants.addAll(CAEnchantmentRegistry.getInstance().values()) - - for (enchantment in esEnchantments) { - otherEnchants.remove(enchantment) - - // find conflicting enchantment. - for (otherEnchant in otherEnchants) { - if(enchantment.enchant.conflictsWithEnchantment(otherEnchant.name)){ - writeConflict(enchantment, otherEnchant) - } - } - } - } - - private fun writeConflict(enchantment1: CAEnchantment, enchantment2: CAEnchantment){ - val conflict = ConflictBuilder("${enchantment1.name}_with_${enchantment2.name}_conflict", CustomAnvil.instance) - - conflict.addEnchantment(enchantment1).addEnchantment(enchantment2) - - conflict.setMaxBeforeConflict(1) - conflict.registerIfAbsent() - } - - /** - * Transform an Enchantment Squared group to a Custom Anvil group - */ - private fun esGroupToCAGroup(esGroup: String): String? { - return when(esGroup){ - "SWORDS" -> "swords" - "BOWS" -> "bow" - "CROSSBOWS" -> "crossbow" - "TRIDENTS" -> "trident" - "HELMETS" -> "helmets" - "CHESTPLATES" -> "chestplate" - "LEGGINGS" -> "leggings" - "BOOTS" -> "boots" - "SHEARS" -> "shears" - "FLINTANDSTEEL" -> "flint_and_steel" - "FISHINGROD" -> "fishing_rod" - "ELYTRA", "ELYTRAS" -> "elytra" - "PICKAXES" -> "pickaxes" // not on this plugin by default - "AXES" -> "axes" - "SHOVELS" -> "shovels" // not on this plugin by default - "HOES" -> "hoes" // not on this plugin by default - "SHIELDS" -> "shield" // not on this plugin by default - "TRINKETS" -> "trinkets" // not the idea way as it will also allow non trinkets rotten flesh to be enchanted. - "ALL" -> "everything" - else -> null - } - } - - fun stripLore(item: ItemStack) { - CustomEnchantManager.getInstance().removeAllEnchants(item) - } - - fun updateLore(item: ItemStack) { - CustomEnchantManager.getInstance().updateLore(item) - } - -} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ExcellentEnchantsDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ExcellentEnchantsDependency.kt deleted file mode 100644 index 816a4df..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ExcellentEnchantsDependency.kt +++ /dev/null @@ -1,258 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.plugins - -import io.delilaheve.CustomAnvil -import org.bukkit.Material -import org.bukkit.event.Listener -import org.bukkit.event.inventory.InventoryClickEvent -import org.bukkit.event.inventory.PrepareAnvilEvent -import org.bukkit.inventory.ItemStack -import org.bukkit.plugin.RegisteredListener -import xyz.alexcrea.cuanvil.api.EnchantmentApi -import xyz.alexcrea.cuanvil.api.event.listener.CATreatAnvilResult2Event -import xyz.alexcrea.cuanvil.enchant.wrapped.CAEEPreV5Enchantment -import xyz.alexcrea.cuanvil.enchant.wrapped.CAEEV5Enchantment -import xyz.alexcrea.cuanvil.enchant.wrapped.CAEEV5_4Enchantment -import xyz.alexcrea.cuanvil.enchant.wrapped.CALegacyEEEnchantment -import java.lang.reflect.Constructor -import java.lang.reflect.Method -import su.nightexpress.excellentenchants.api.EnchantRegistry as V5EnchantRegistry -import su.nightexpress.excellentenchants.enchantment.impl.universal.CurseOfFragilityEnchant as LegacyCurseOfFragilityEnchant -import su.nightexpress.excellentenchants.manager.listener.AnvilListener as V5AnvilListener -import su.nightexpress.excellentenchants.enchantment.listener.AnvilListener as PreV5AnvilListener -import su.nightexpress.excellentenchants.enchantment.listener.EnchantAnvilListener as LegacyAnvilListener -import su.nightexpress.excellentenchants.enchantment.registry.EnchantRegistry as LegacyEnchantRegistry -import su.nightexpress.excellentenchants.registry.EnchantRegistry as PreV5EnchantRegistry - -// I don't like that I need to support older version. if I could just drop older support it would be sooo nice -class ExcellentEnchantsDependency { - - enum class ListenerVersion(val classPath: String) { - V5_4("su.nightexpress.excellentenchants.enchantment.EnchantSettings"), - V5_3("su.nightexpress.excellentenchants.enchantment.EnchantRegistry"), - V5("su.nightexpress.excellentenchants.manager.listener.AnvilListener"), - PRE_V5("su.nightexpress.excellentenchants.enchantment.listener.AnvilListener"), - LEGACY("su.nightexpress.excellentenchants.enchantment.listener.EnchantAnvilListener"), - } - - private val listenerVersion: ListenerVersion? - private val isModernCurseOfFragility: Boolean - - init { - CustomAnvil.instance.logger.info("Excellent Enchants Detected !") - - var listenerVersion: ListenerVersion? = null - for (value in ListenerVersion.entries) { - try { - Class.forName(value.classPath) - - listenerVersion = value - break - } catch (ignored: ClassNotFoundException) { - } - } - - if (listenerVersion == null) { - CustomAnvil.instance.logger.severe("Found issue with listener of Excellent Enchants. compatiblity is broken. please contact CustomAnvil devs") - } else{ - CustomAnvil.log("Support version: " + listenerVersion.name) - } - - var isModernCurseOfFragility = true - try { - Class.forName("su.nightexpress.excellentenchants.enchantment.universal.CurseOfFragilityEnchant") - } catch (ignored: ClassNotFoundException) { - isModernCurseOfFragility = false - } - - this.listenerVersion = listenerVersion - this.isModernCurseOfFragility = isModernCurseOfFragility - } - - fun registerEnchantments() { - CustomAnvil.instance.logger.info("Preparing Excellent Enchants compatibility...") - - // As excellent enchants is loaded before custom anvil and register enchantment to registry, we need to unregister old "vanilla" enchant. - when (listenerVersion) { - ListenerVersion.V5_4 -> { - for (enchantment in ExcellentEnchant5_3Registry.getRegistered()) { - EnchantmentApi.unregisterEnchantment(enchantment.bukkitEnchantment.key) - EnchantmentApi.registerEnchantment(CAEEV5_4Enchantment(enchantment)) - } - } - - ListenerVersion.V5, ListenerVersion.V5_3 -> { - for (enchantment in V5EnchantRegistry.getRegistered()) { - EnchantmentApi.unregisterEnchantment(enchantment.bukkitEnchantment.key) - EnchantmentApi.registerEnchantment(CAEEV5Enchantment(enchantment)) - } - } - - ListenerVersion.PRE_V5 -> { - for (enchantment in PreV5EnchantRegistry.getRegistered()) { - EnchantmentApi.unregisterEnchantment(enchantment.bukkitEnchantment.key) - EnchantmentApi.registerEnchantment(CAEEPreV5Enchantment(enchantment)) - } - } - - ListenerVersion.LEGACY -> { - for (enchantment in LegacyEnchantRegistry.getRegistered()) { - EnchantmentApi.unregisterEnchantment(enchantment.enchantment.key) - EnchantmentApi.registerEnchantment(CALegacyEEEnchantment(enchantment)) - } - } - - null -> return - - } - - CustomAnvil.instance.logger.info("Excellent Enchants should now work as expected !") - } - - private var legacyFragilityCurse: LegacyCurseOfFragilityEnchant? = null - - private var v5AnvilListener: V5AnvilListener? = null - private var preV5AnvilListener: PreV5AnvilListener? = null - private var legacyAnvilListener: LegacyAnvilListener? = null - private lateinit var usedAnvilListener: Listener - - private lateinit var handleRechargeMethod: Method - private lateinit var handleCombineMethod: Method - - private val prepareAnvilConstructor = PrepareAnvilEvent::class.java.constructors.first() as Constructor - - fun redirectListeners() { - val toUnregister = ArrayList() - // get required PrepareAnvilEvent listener - for (registeredListener in PrepareAnvilEvent.getHandlerList().registeredListeners) { - val listener = registeredListener.listener - - if (!isModernCurseOfFragility) { - if (listener is LegacyCurseOfFragilityEnchant) { - this.legacyFragilityCurse = listener - toUnregister.add(registeredListener) - } - } - - when (listenerVersion) { - ListenerVersion.V5, - ListenerVersion.V5_3, - ListenerVersion.V5_4, - -> { - if (listener is V5AnvilListener) { - this.v5AnvilListener = listener - toUnregister.add(registeredListener) - } - } - - ListenerVersion.PRE_V5 -> { - if (listener is PreV5AnvilListener) { - this.preV5AnvilListener = listener - toUnregister.add(registeredListener) - } - } - - ListenerVersion.LEGACY -> { - if (listener is LegacyAnvilListener) { - this.legacyAnvilListener = listener - toUnregister.add(registeredListener) - } - } - - null -> { - } - } - - } - - for (listener in toUnregister) { - PrepareAnvilEvent.getHandlerList().unregister(listener) - } - - when (listenerVersion) { - ListenerVersion.V5_3, - ListenerVersion.V5, - ListenerVersion.V5_4, - -> this.usedAnvilListener = v5AnvilListener!! - ListenerVersion.PRE_V5 -> this.usedAnvilListener = preV5AnvilListener!! - ListenerVersion.LEGACY -> this.usedAnvilListener = legacyAnvilListener!! - null -> {} - } - - // Unregister inventory click event - InventoryClickEvent.getHandlerList().unregister(this.usedAnvilListener) - - findAnvilFunctions() - } - - private fun findAnvilFunctions() { - this.handleRechargeMethod = this.usedAnvilListener.javaClass.getDeclaredMethod( - "handleRecharge", - PrepareAnvilEvent::class.java, ItemStack::class.java, ItemStack::class.java - ) - this.handleRechargeMethod.setAccessible(true) - - try { - this.handleCombineMethod = this.usedAnvilListener.javaClass.getDeclaredMethod( - "anvilCombine", - PrepareAnvilEvent::class.java, ItemStack::class.java, ItemStack::class.java, ItemStack::class.java - ) - this.handleCombineMethod.setAccessible(true) - } catch (_: NoSuchMethodException) { - this.handleCombineMethod = this.usedAnvilListener.javaClass.getDeclaredMethod( - "handleCombine", - PrepareAnvilEvent::class.java, ItemStack::class.java, ItemStack::class.java, ItemStack::class.java - ) - this.handleCombineMethod.setAccessible(true) - } - - } - - fun testPrepareAnvil(event: PrepareAnvilEvent): Boolean { - if (event.result != null) { - if (!isModernCurseOfFragility) { - this.legacyFragilityCurse?.onItemAnvil(event) - } - if (event.result == null) return true - } - - val first: ItemStack = treatInput(event.inventory.getItem(0)) - val second: ItemStack = treatInput(event.inventory.getItem(1)) - - return handleRechargeMethod.invoke(this.usedAnvilListener, event, first, second) as Boolean - } - - fun treatAnvilResult(event: CATreatAnvilResult2Event) { - val result = event.result ?: return - - val first: ItemStack = treatInput(event.leftItem) - val second: ItemStack = treatInput(event.rightItem) - val fakeEvent = prepareAnvilConstructor.newInstance(event.view, result) - - handleCombineMethod.invoke(this.usedAnvilListener, fakeEvent, first, second, result) - - event.result = fakeEvent.result - } - - fun testAnvilResult(event: InventoryClickEvent): Any { - if (event.inventory.getItem(2) != null) { - when (listenerVersion) { - ListenerVersion.V5, - ListenerVersion.V5_3, - ListenerVersion.V5_4, - -> v5AnvilListener!!.onClickAnvil(event) - ListenerVersion.PRE_V5 -> preV5AnvilListener!!.onClickAnvil(event) - ListenerVersion.LEGACY -> legacyAnvilListener!!.onClickAnvil(event) - null -> {} - } - return event.inventory.getItem(2) == null - } - - return false - } - - private fun treatInput(item: ItemStack?): ItemStack { - if (item == null) return ItemStack(Material.AIR) - return item - } - -} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/GenericPluginDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/GenericPluginDependency.kt deleted file mode 100644 index 62dae9b..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/GenericPluginDependency.kt +++ /dev/null @@ -1,81 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.plugins - -import org.bukkit.event.inventory.InventoryClickEvent -import org.bukkit.event.inventory.PrepareAnvilEvent -import org.bukkit.plugin.Plugin -import org.bukkit.plugin.RegisteredListener - -open class GenericPluginDependency(protected open val plugin: Plugin, private val testPrepare: Boolean = true) { - - private val preAnvil = ArrayList() - private val postAnvil = ArrayList() - - open fun redirectListeners() { - fillPreAnvil(preAnvil) - fillPostAnvil(postAnvil, preAnvil) - - // get required PrepareAnvilEvent listener - for (listener in preAnvil) { - PrepareAnvilEvent.getHandlerList().unregister(listener) - } - - for (listener in postAnvil) { - InventoryClickEvent.getHandlerList().unregister(listener) - } - } - - open fun fillPreAnvil(preAnvil: ArrayList){ - // get PreAnvil and PostAnvil listeners - for (registeredListener in PrepareAnvilEvent.getHandlerList().registeredListeners) { - - if (registeredListener.plugin != plugin) continue - preAnvil.add(registeredListener) - } - } - - protected open fun fillPostAnvil( - postAnvil: ArrayList, - preAnvil: ArrayList) { - - } - - open fun testPrepareAnvil(event: PrepareAnvilEvent): Boolean { - if(!testPrepare) return false - - val previousResult = event.result - event.result = null - - for (registeredListener in preAnvil) { - // We do not want error from another plugin to be our fault - try { - registeredListener.callEvent(event) - } catch (e: Exception) { - e.printStackTrace() - } - - if (event.result != null) return true - } - - event.result = previousResult; - return false - } - - open fun testAnvilResult(event: InventoryClickEvent): Boolean { - if(!testPrepare) return false - - for (registeredListener in postAnvil) { - // We do not want error from another plugin to be our fault - try { - registeredListener.callEvent(event) - } catch (e: Exception) { - e.printStackTrace() - } - - if (event.inventory.getItem(2) == null) return true - } - - return false - } - - -} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/HavenBagsDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/HavenBagsDependency.kt deleted file mode 100644 index 6f30497..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/HavenBagsDependency.kt +++ /dev/null @@ -1,85 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.plugins - -import io.delilaheve.CustomAnvil -import org.bukkit.entity.Player -import org.bukkit.event.inventory.InventoryClickEvent -import org.bukkit.event.inventory.PrepareAnvilEvent -import org.bukkit.inventory.AnvilInventory -import org.bukkit.plugin.RegisteredListener -import valorless.havenbags.HavenBags -import valorless.havenbags.features.BagSkin -import valorless.havenbags.features.BagUpgrade -import xyz.alexcrea.cuanvil.anvil.AnvilCost -import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener -import xyz.alexcrea.cuanvil.util.anvil.AnvilXpUtil - -class HavenBagsDependency { - - init { - CustomAnvil.instance.logger.info("Heaven Bags Detected !") - } - - private lateinit var bagUpgrade: BagUpgrade - private lateinit var bagSkin: BagSkin - - fun redirectListeners() { - val toUnregister = ArrayList() - // get required PrepareAnvilEvent listener - for (registeredListener in PrepareAnvilEvent.getHandlerList().registeredListeners) { - val listener = registeredListener.listener - - if (listener is BagUpgrade) { - bagUpgrade = listener - toUnregister.add(registeredListener) - } - - if (listener is BagSkin) { - bagSkin = listener - toUnregister.add(registeredListener) - } - } - - for (listener in toUnregister) { - PrepareAnvilEvent.getHandlerList().unregister(listener) - InventoryClickEvent.getHandlerList().unregister(listener) - } - - } - - fun testPrepareAnvil(event: PrepareAnvilEvent, player: Player): Boolean { - val previousResult = event.result - event.result = null - - // Test if event change the result - bagSkin.onPrepareAnvil(event) - if (event.result != null) { - CustomAnvil.log("Detected pre anvil heaven bag anvil skin.") - AnvilXpUtil.setAnvilInvCost(event.inventory, event.view, player, AnvilCost(event.inventory.repairCost)) - return true - } - - bagUpgrade.onPrepareAnvil(event) - if (event.result != null) { - CustomAnvil.log("Detected pre anvil heaven bag anvil upgrade.") - AnvilXpUtil.setAnvilInvCost(event.inventory, event.view, player, AnvilCost(event.inventory.repairCost)) - return true - } - - event.result = previousResult - return false - } - - fun testAnvilResult(event: InventoryClickEvent, inventory: AnvilInventory): Boolean { - val result = inventory.getItem(PrepareAnvilListener.ANVIL_OUTPUT_SLOT)?.clone() - - if (HavenBags.IsBag(result)) { - CustomAnvil.log("Detected anvil click haven bag bypass.") - bagUpgrade.onInventoryClick(event) - bagSkin.onInventoryClick(event) - return true - } - - return false - } - -} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ItemsAdderDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ItemsAdderDependency.kt deleted file mode 100644 index 7f977e1..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ItemsAdderDependency.kt +++ /dev/null @@ -1,42 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.plugins - -import dev.lone.itemsadder.api.CustomStack -import dev.lone.itemsadder.api.ItemsAdder -import org.bukkit.NamespacedKey -import org.bukkit.inventory.ItemStack -import org.bukkit.plugin.Plugin - -class ItemsAdderDependency(plugin: Plugin) : GenericPluginDependency(plugin) { - var isLoaded: Boolean = false - get() { - if (field) return true - - // We can't be sure the event is registered before being triggered so we need to use this function - field = ItemsAdder.areItemsLoaded() - return field - } - - fun tryClone(item: ItemStack): ItemStack? { - if(!isLoaded) return null - val customItem = CustomStack.byItemStack(item) ?: return null - - return CustomStack.getInstance(customItem.namespacedID)?.itemStack - } - - fun fromKey(key: NamespacedKey): ItemStack? { - if(!isLoaded) return null - return CustomStack.getInstance(key.toString())?.itemStack - } - - fun getKey(item: ItemStack) : NamespacedKey? { - if(!isLoaded) return null - val customItem = CustomStack.byItemStack(item) ?: return null - - return NamespacedKey.fromString(customItem.namespacedID) - } - - fun idsCount(): Set { - return CustomStack.getNamespacedIdsInRegistry() - } - -} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/LegacyEcoEnchantDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/LegacyEcoEnchantDependency.kt deleted file mode 100644 index 60f00b8..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/LegacyEcoEnchantDependency.kt +++ /dev/null @@ -1,46 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.plugins - -import com.willfp.ecoenchants.enchantments.EcoEnchant -import com.willfp.ecoenchants.enchantments.EcoEnchants -import org.bukkit.enchantments.Enchantment -import xyz.alexcrea.cuanvil.api.EnchantmentApi -import xyz.alexcrea.cuanvil.enchant.wrapped.CALegacyEcoEnchant - -class LegacyEcoEnchantDependency { - - - private var ecoEnchantOldEnchantments: MutableSet? = null - fun registerEnchantments() { - val enchantments = EcoEnchants.values() - for (ecoEnchant in enchantments) { - ecoEnchant as Enchantment - - EnchantmentApi.unregisterEnchantment(ecoEnchant) // As eco enchants is loaded before custom anvil and register enchantment to registry, we need to unregister old "vanilla" enchant. - EnchantmentApi.registerEnchantment(CALegacyEcoEnchant(ecoEnchant, ecoEnchant)) - } - - ecoEnchantOldEnchantments = HashSet(enchantments) - } - - fun handleConfigReload() { - // Should not happen in known case. - if (this.ecoEnchantOldEnchantments == null) return - - val newEnchantments = EcoEnchants.values() - - // Add new enchantments - for (ecoEnchant in newEnchantments) - if (!this.ecoEnchantOldEnchantments!!.contains(ecoEnchant)) - EnchantmentApi.registerEnchantment(CALegacyEcoEnchant(ecoEnchant, ecoEnchant as Enchantment)) - - - // Remove old enchantments that not now currently used - this.ecoEnchantOldEnchantments!!.removeAll(newEnchantments) - for (oldEnchantment in this.ecoEnchantOldEnchantments!!) { - EnchantmentApi.unregisterEnchantment(oldEnchantment as Enchantment) - } - - this.ecoEnchantOldEnchantments = HashSet(newEnchantments) - } - -} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/SuperEnchantDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/SuperEnchantDependency.kt deleted file mode 100644 index 11622f9..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/SuperEnchantDependency.kt +++ /dev/null @@ -1,91 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.plugins - -import com.maddoxh.superEnchants.SuperEnchants -import com.maddoxh.superEnchants.enchants.EnchantManager -import com.maddoxh.superEnchants.listeners.AnvilListener -import io.delilaheve.CustomAnvil -import org.bukkit.command.Command -import org.bukkit.command.CommandExecutor -import org.bukkit.command.CommandSender -import org.bukkit.event.inventory.InventoryClickEvent -import org.bukkit.plugin.RegisteredListener -import xyz.alexcrea.cuanvil.api.EnchantmentApi -import xyz.alexcrea.cuanvil.enchant.bulk.SuperEnchantBulkOperation -import xyz.alexcrea.cuanvil.enchant.wrapped.CASuperEnchantEnchantment -import java.util.logging.Level - -class SuperEnchantDependency(override val plugin: SuperEnchants): GenericPluginDependency(plugin, false) { - - lateinit var enchManager: EnchantManager - val enchantments = ArrayList() - - fun registerEnchantments(): Boolean{ - CustomAnvil.instance.logger.info("Preparing Super Enchant compatibility...") - - val field = SuperEnchants::class.java.getDeclaredField("enchantManager") - if(field == null) { - CustomAnvil.instance.logger.log(Level.SEVERE, "Failed to initialize Super Enchant compatibility") - return false - } - field.setAccessible(true) - - val bulkOpperations = SuperEnchantBulkOperation(plugin) - EnchantmentApi.addBulkGet(bulkOpperations) - EnchantmentApi.addBulkClean(bulkOpperations) - - enchManager = field.get(plugin) as EnchantManager - overrideReloadCommand() - - reload() - return true - } - - fun reload() { - for (enchantment in enchantments) { - EnchantmentApi.unregisterEnchantment(enchantment) - } - enchantments.clear() - - // Register enchantments - for (enchant in enchManager.getAll()) { - val enchantment = CASuperEnchantEnchantment(enchant, plugin, enchManager) - enchantments.add(enchantment) - - EnchantmentApi.registerEnchantment(enchantment) - } - } - - private fun overrideReloadCommand() { - val reload = CustomAnvil.instance.getCommand("sereload") - - reload?.setExecutor(ReloadInterceptor(reload.executor)) - } - - inner class ReloadInterceptor(val other: CommandExecutor): CommandExecutor { - - override fun onCommand( - sender: CommandSender, - command: Command, - label: String, - args: Array - ): Boolean { - val result = other.onCommand(sender, command, label, args) - - CustomAnvil.log("Detected SuperEnchant reload") - reload() - - return result - } - - } - - override fun fillPostAnvil(postAnvil: ArrayList, preAnvil: ArrayList) { - - for (registeredListener in InventoryClickEvent.getHandlerList().registeredListeners) { - - if (registeredListener.listener.javaClass != AnvilListener::class.java) continue - postAnvil.add(registeredListener) - } - } - -} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ToolStatsDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ToolStatsDependency.kt deleted file mode 100644 index 255f737..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ToolStatsDependency.kt +++ /dev/null @@ -1,39 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.plugins - -import lol.hyper.toolstats.ToolStats -import lol.hyper.toolstats.tools.ItemChecker -import org.bukkit.event.inventory.InventoryClickEvent -import org.bukkit.inventory.ItemStack -import org.bukkit.plugin.Plugin -import org.bukkit.plugin.RegisteredListener -import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener -import java.lang.reflect.Method - -class ToolStatsDependency(plugin: Plugin) : GenericPluginDependency(plugin) { - - // Sadly, getTokens function is private, so I need to do some reflectino - private val getTokenMethod: Method = - ItemChecker::class.java.getDeclaredMethod("getTokens", ItemStack::class.java); - - init { - getTokenMethod.trySetAccessible() - } - - private fun ItemChecker.getTokenSafe(item: ItemStack?): Array { - if (item == null) return arrayOf() - return getTokenMethod.invoke(this, item) as Array - } - - override fun testAnvilResult(event: InventoryClickEvent): Boolean { - // Check if token changes from left with result - val left = event.inventory.getItem(PrepareAnvilListener.ANVIL_INPUT_LEFT) - val result = event.inventory.getItem(PrepareAnvilListener.ANVIL_OUTPUT_SLOT) - - val itemChecker = (plugin as ToolStats).itemChecker - - val leftTokens = itemChecker.getTokenSafe(left) - val resultToken = itemChecker.getTokenSafe(result) - - return !leftTokens.contentDeepEquals(resultToken); - } -} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/scheduler/BukkitScheduler.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/scheduler/BukkitScheduler.kt deleted file mode 100644 index 8c04162..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/scheduler/BukkitScheduler.kt +++ /dev/null @@ -1,17 +0,0 @@ -package xyz.alexcrea.cuanvil.dependency.scheduler - -import org.bukkit.Bukkit -import org.bukkit.entity.Entity -import org.bukkit.plugin.Plugin - -class BukkitScheduler : TaskScheduler { - - override fun scheduleGlobally(plugin: Plugin, task: Runnable, time: Long): Any { - return Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, task, time) - } - - - override fun scheduleOnEntity(plugin: Plugin, entity: Entity, task: Runnable, time: Long): Any { - return Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, task, time) - } -} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/AbstractMaterialGroup.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/AbstractMaterialGroup.kt deleted file mode 100644 index d0d2bda..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/AbstractMaterialGroup.kt +++ /dev/null @@ -1,123 +0,0 @@ -package xyz.alexcrea.cuanvil.group - -import org.bukkit.Material -import org.bukkit.NamespacedKey -import xyz.alexcrea.cuanvil.util.MaterialUtil - -abstract class AbstractMaterialGroup(private val name: String) { - protected val includedMaterial by lazy { createDefaultSet() } - - /** - * Get the group default set - */ - protected abstract fun createDefaultSet(): MutableSet - - /** - * Get if a material is allowed following the group policy - */ - open fun contain(mat: NamespacedKey): Boolean { - return mat in getMaterials() - } - - /** - * Get if a group is referenced by this: - */ - abstract fun isReferencing(other: AbstractMaterialGroup): Boolean - - /** - * Push a material to this group to follow this group policy - * @return this instance. - */ - abstract fun addToPolicy(type: NamespacedKey): AbstractMaterialGroup - - /** - * Push a list of material to this group to follow this group policy - * @return this instance. - */ - fun addAll(vararg materials: NamespacedKey): AbstractMaterialGroup { - for (material in materials) { - addToPolicy(material) - } - return this - } - - /** - * Push a group to this group to follow this group policy - * @return this instance. - */ - abstract fun addToPolicy(other: AbstractMaterialGroup): AbstractMaterialGroup - - /** - * Push a list of group to this group to follow this group policy - * @return this instance. - */ - fun addAll(vararg otherList: AbstractMaterialGroup): AbstractMaterialGroup { - for (group in otherList) { - addToPolicy(group) - } - return this - } - - /** - * Get the group contained material as a set - */ - abstract fun getMaterials(): Set - - /** - * Get the group non-inherited material as a set - */ - open fun getNonGroupInheritedMaterials(): Set { - return includedMaterial - } - - /** - * Get the group non-inherited material as a set - */ - open fun setNonGroupInheritedMaterials(materials: Set) { - this.includedMaterial.clear() - this.includedMaterial.addAll(materials) - } - - /** - * Get the group name in case something is wrong - */ - open fun getName(): String { - return name - } - - override fun toString(): String { - return name - } - - /** - * Update the contained groups of this group - */ - abstract fun setGroups(groups: MutableSet) - - /** - * Get the contained group of this material group - */ - abstract fun getGroups(): MutableSet - - open fun getRepresentativeMaterial(): Material { - // Test inner material - val matIterator = includedMaterial.iterator() - while (matIterator.hasNext()) { - val key = matIterator.next() - val material = MaterialUtil.getMatFromKey(key) - if (material == null || material.isAir) continue - return material - } - // Test included group representative material - val groupIterator = getGroups().iterator() - while (groupIterator.hasNext()) { - val groupMat = groupIterator.next().getRepresentativeMaterial() - if (groupMat.isAir) continue - return groupMat - } - return Material.PAPER - } - - abstract fun updateMaterials() - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictGroup.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictGroup.kt deleted file mode 100644 index 59841ac..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictGroup.kt +++ /dev/null @@ -1,144 +0,0 @@ -package xyz.alexcrea.cuanvil.group - -import io.delilaheve.CustomAnvil -import org.bukkit.Material -import org.bukkit.NamespacedKey -import xyz.alexcrea.cuanvil.enchant.CAEnchantment - -class EnchantConflictGroup( - val name: String, - private val cantConflict: AbstractMaterialGroup, - var minBeforeBlock: Int, -) { - - private val enchantments = HashSet() - private val conflictsAfterLevel = HashMap() - private val conflictsBeforeLevel = HashMap() - - fun addEnchantment(enchant: CAEnchantment) { - enchantments.add(enchant) - } - fun addEnchantments(enchants: List) { - enchantments.addAll(enchants) - } - - private fun canBypassByBeforeLevel(enchants: Map): Boolean { - // Either there no "conflict after" - if(conflictsAfterLevel.isEmpty()) return false - - // Or we check if any conflict after enchantment is true - for (entry in conflictsAfterLevel) { - val current = enchants.getOrDefault(entry.key, 0) - if(current > entry.value) - return false - } - - return true - } - - private fun canBypassByAfterLevel(enchants: Map): Boolean { - // Either there no "conflict after" - if(conflictsBeforeLevel.isEmpty()) return false - - // Or we check if any conflict after enchantment is true - for (entry in conflictsBeforeLevel) { - val current = enchants.getOrDefault(entry.key, 0) - if(current < entry.value) - return false - } - - return true - } - - private fun canBypassConflictByLevel(enchants: Map): Boolean { - return canBypassByBeforeLevel(enchants) || canBypassByAfterLevel(enchants) - } - - fun allowed(enchants: Map, mat: NamespacedKey): Boolean { - if (enchantments.size < minBeforeBlock) { - CustomAnvil.verboseLog("Conflicting bc of to many enchantments") - return true - } - - if (cantConflict.contain(mat)) - return true - - // If empty we skip. else we - if(canBypassConflictByLevel(enchants)) - return true - - // Count the amount of enchantment that are in the list - var enchantAmount = 0 - for (entry in enchants) { - val enchantment = entry.key - - if (enchantment !in enchantments) continue - CustomAnvil.verboseLog("Enchant ${enchantment.key} is in: ${enchantAmount + 1}/$minBeforeBlock ") - if (++enchantAmount > minBeforeBlock) { - CustomAnvil.verboseLog("it is not allowed bc of to many enchantment in conflict") - return false - } - - } - return true - } - - fun getCantConflictGroup(): AbstractMaterialGroup { - return this.cantConflict - } - - fun getEnchants(): HashSet { - return enchantments - } - - fun setEnchants(enchants: Set) { - enchantments.clear() - enchantments.addAll(enchants) - } - - fun getConflictAfters(): HashMap { - return conflictsAfterLevel - } - - fun putConflictAfterLevel(enchantment: CAEnchantment, level: Int): Boolean { - return null != ( - if(level < 0) conflictsAfterLevel.remove(enchantment) - else conflictsAfterLevel.put(enchantment, level)) - } - - fun setConflictsAfterLevel(conflictAfterLevel: HashMap) { - this.conflictsAfterLevel.clear() - this.conflictsAfterLevel.putAll(conflictAfterLevel) - } - - fun getConflictsBefore(): HashMap { - return conflictsBeforeLevel - } - - fun putConflictsBeforeLevel(enchantment: CAEnchantment, level: Int): Boolean { - return null != ( - if(level < 0) conflictsBeforeLevel.remove(enchantment) - else conflictsBeforeLevel.put(enchantment, level)) - } - - fun setConflictsBeforeLevel(conflictBeforeLevel: HashMap) { - this.conflictsBeforeLevel.clear() - this.conflictsBeforeLevel.putAll(conflictBeforeLevel) - } - - fun getRepresentativeMaterial(): Material { - val groups = getCantConflictGroup().getGroups() - val groupIterator = groups.iterator() - while (groupIterator.hasNext()) { - val mat = groupIterator.next().getRepresentativeMaterial() - if (mat != Material.ENCHANTED_BOOK) return mat - - } - return Material.ENCHANTED_BOOK - } - - override fun toString(): String { - return name - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt deleted file mode 100644 index 38d5476..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt +++ /dev/null @@ -1,312 +0,0 @@ -package xyz.alexcrea.cuanvil.group - -import io.delilaheve.CustomAnvil -import org.bukkit.NamespacedKey -import org.bukkit.configuration.ConfigurationSection -import org.bukkit.enchantments.Enchantment -import org.bukkit.inventory.ItemStack -import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment -import xyz.alexcrea.cuanvil.enchant.CAEnchantment -import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry -import xyz.alexcrea.cuanvil.util.MaterialUtil.customType -import java.util.* -import kotlin.collections.set - -class EnchantConflictManager { - - companion object { - // Path for the enchantments list - const val ENCH_LIST_PATH = "enchantments" - - // Path for list of enchantments conflicting before level - //TODO add test and gui - const val CONFLICT_AFTER_LEVEL_LIST_PATH = "conflict_after_level" - - // Path for list of enchantments conflicting before level - //TODO add test and gui - const val CONFLICT_BEFORE_LEVEL_LIST_PATH = "conflict_before_level" - - // Path for group list related to the conflict - const val CONFLICT_GROUP_PATH = "notAffectedGroups" - - // Path for the maximum number of enchantment before validating the conflict - const val ENCH_MAX_PATH = "maxEnchantmentBeforeConflict" - - // Path for a flag: if the enchantment will be used in the last supported version - // TODO maybe replace this system by a list of "future" enchantment. - private const val FUTURE_USE_PATH = "useInFuture" - - // Default name for a joining group - const val DEFAULT_GROUP_NAME = "joinedGroup" - - // 1.20.5 compatibility TODO better update system - private val SWEEPING_EDGE_ENCHANT = Collections.singletonList( - CAEnchantment.getByKey(NamespacedKey.minecraft("sweeping_edge")) - ?: CAEnchantment.getByKey(Enchantment.SWEEPING_EDGE.key) - ) - - } - - lateinit var conflictList: ArrayList - - - private fun warnBadKey(key: String) { - CustomAnvil.instance.logger.warning("Invalid key $key for conflict: is not a conflict") - } - - // Read and prepare all conflict - fun prepareConflicts(config: ConfigurationSection, itemManager: ItemGroupManager) { - conflictList = ArrayList() - - // Clear conflict if exist - for (enchant in CAEnchantmentRegistry.getInstance().values()) { - enchant.clearConflict() - } - - val keys = config.getKeys(false) - for (key in keys) { - val section = config.getConfigurationSection(key) - if(section == null) { - warnBadKey(key) - continue - } - val conflict = createConflict(section, itemManager, key) - - addConflict(conflict) - } - - } - - fun addConflict(conflict: EnchantConflictGroup) { - addConflictToEnchantments(conflict) - conflictList.add(conflict) - } - - fun removeConflict(conflict: EnchantConflictGroup) { - removeConflictFromEnchantments(conflict) - conflictList.remove(conflict) - } - - // Add the conflict to enchantments - private fun addConflictToEnchantments(conflict: EnchantConflictGroup) { - conflict.getEnchants().forEach { enchant -> - enchant.addConflict(conflict) - } - } - - // Remove the conflict from enchantments - private fun removeConflictFromEnchantments(conflict: EnchantConflictGroup) { - conflict.getEnchants().forEach { enchant -> - enchant.removeConflict(conflict) - } - } - - // create and read a conflict from a yaml section - private fun createConflict( - section: ConfigurationSection, - itemManager: ItemGroupManager, - conflictName: String - ): EnchantConflictGroup { - // Is it planed for the future - val futureUse = section.getBoolean(FUTURE_USE_PATH, false) - // Create conflict - val conflict = createConflictObject(section, itemManager, conflictName) - // Read and add enchantment to conflict - val enchantList = section.getStringList(ENCH_LIST_PATH) - for (enchantName in enchantList) { - val enchants = getEnchantByIdentifier(enchantName) - if (enchants.isEmpty()) { - if (!futureUse) { //TODO future use will be deprecated once the new update system is finished - CustomAnvil.instance.logger.warning("Enchantment $enchantName do not exist but was asked for conflict $conflictName") - } - continue - } - conflict.addEnchantments(enchants) - } - if (conflict.getEnchants().isEmpty()) { - if (!futureUse) { //TODO future use will be deprecated once the new update system is finished - CustomAnvil.instance.logger.warning("Conflict $conflictName do not have valid enchantment, it will not do anything") - } - } - - val conflictsAfterLevel = section.getConfigurationSection(CONFLICT_AFTER_LEVEL_LIST_PATH) - val conflictsAfterMap = conflict.getConflictAfters() - fetchConditionalRestriction(conflictsAfterMap, conflictsAfterLevel, conflictName) - - val conflictsBeforeLevel = section.getConfigurationSection(CONFLICT_BEFORE_LEVEL_LIST_PATH) - val conflictsBeforeMap = conflict.getConflictsBefore() - fetchConditionalRestriction(conflictsBeforeMap, conflictsBeforeLevel, conflictName) - - return conflict - } - - private fun fetchConditionalRestriction(restrictions: MutableMap, section: ConfigurationSection?, conflictName: String) { - if(section == null) return - for (enchantName in section.getKeys(false)) { - val enchants = getEnchantByIdentifier(enchantName) - if (enchants.isEmpty()) { - CustomAnvil.instance.logger.warning("Enchantment $enchantName do not exist but was asked for conditional restriction for conflict $conflictName") - continue - } - - val value = section.getInt(enchantName, -1) - if(value < 0) continue - - for (enchant in enchants) { - val previous = restrictions.getOrDefault(enchant, value) - restrictions[enchant] = value.coerceAtMost(previous) - } - } - } - - private fun getEnchantByIdentifier(enchantName: String): List { - val key = NamespacedKey.fromString(enchantName) - if (key != null) { - val enchantment = CAEnchantment.getByKey(key) - if (enchantment != null) return Collections.singletonList(enchantment) - - } - - // Temporary solution for 1.20.5 - when (enchantName) { - "minecraft:sweeping", "sweeping", - "minecraft:sweeping_edge", "sweeping_edge" -> { - return SWEEPING_EDGE_ENCHANT - } - } - - return CAEnchantment.getListByName(enchantName) - } - - - private fun createConflictObject( - section: ConfigurationSection, - itemManager: ItemGroupManager, - conflictName: String - ): EnchantConflictGroup { - // Get the maximum number of enchantment before validating the conflict - var minBeforeBlock = section.getInt(ENCH_MAX_PATH, 0) - if (minBeforeBlock < 0) { - minBeforeBlock = 0 - CustomAnvil.instance.logger.warning("Conflict $conflictName have an invalid value of $ENCH_MAX_PATH") - CustomAnvil.instance.logger.warning("It should be more or equal to 0. default to 0") - } - // Find or create the selected group for the conflict - val groupList = section.getStringList(CONFLICT_GROUP_PATH) - val finalGroup = IncludeGroup(DEFAULT_GROUP_NAME) - for (groupName in groupList) { - finalGroup.addToPolicy(findGroup(groupName, itemManager, conflictName)) - } - - // Return conflict - return EnchantConflictGroup(conflictName, finalGroup, minBeforeBlock) - } - - private fun findGroup( - groupName: String, - itemManager: ItemGroupManager, - conflictName: String - ): AbstractMaterialGroup { - val group = itemManager.get(groupName) - if (group == null) { - CustomAnvil.instance.logger.warning("Material group $groupName do not exist but is ask by conflict $conflictName") - return IncludeGroup("error_placeholder") - } - - return group - } - - fun isConflicting( - appliedEnchants: Map, - item: ItemStack, - newEnchant: CAEnchantment - ): ConflictType { - val type = item.customType - CustomAnvil.verboseLog("Testing conflict for ${newEnchant.key} on ${type}") - val conflictList = newEnchant.conflicts - - var result = ConflictType.NO_CONFLICT - for (conflict in conflictList) { - val isBigConflict = conflict.getEnchants().size > 1 - if (result == ConflictType.ITEM_CONFLICT && !isBigConflict) { - CustomAnvil.verboseLog("skipping small conflict ${conflict.name}") - continue - } - - val allowed = conflict.allowed(appliedEnchants, type) - CustomAnvil.verboseLog("Was against $conflict and conflicting: ${!allowed} ") - if (!allowed) { - if (conflict.getEnchants().size <= 1) { - result = ConflictType.ITEM_CONFLICT - CustomAnvil.verboseLog("Small conflict (${conflict.name}), continuing") - } else { - CustomAnvil.verboseLog("Big conflict (${conflict.name}), stopping") - return ConflictType.ENCHANTMENT_CONFLICT - } - } - } - - val immutableEnchants = Collections.unmodifiableMap(appliedEnchants) - for (appliedEnchant in appliedEnchants.keys) { - if (appliedEnchant is AdditionalTestEnchantment) { - val doConflict = appliedEnchant.isEnchantConflict(immutableEnchants, type) - if (doConflict) { - CustomAnvil.verboseLog("Big conflict by additional test, stopping") - return ConflictType.ENCHANTMENT_CONFLICT - } - - } - } - - if ((result != ConflictType.ITEM_CONFLICT) && (newEnchant is AdditionalTestEnchantment)) { - val partialItem = createPartialResult(item, immutableEnchants) - - if (newEnchant.isItemConflict(immutableEnchants, type, partialItem)) { - return ConflictType.ITEM_CONFLICT - } - - } - - return result - } - - private fun createPartialResult(item: ItemStack, enchantments: Map): ItemStack { - val newItem = item.clone() - - CAEnchantment.clearEnchants(newItem) - enchantments.forEach { enchantment -> - enchantment.key.addEnchantmentUnsafe(newItem, enchantment.value) - } - - return newItem - } - -} - -/** - * Provide information about the current conflict. - */ -enum class ConflictType(private val importance: Int) { - /** - * Allowed to proceed the anvil process. - */ - NO_CONFLICT(0), - - /** - * Inform that the anvil process should not change the current applied enchantment. - */ - ITEM_CONFLICT(1), - - /** - * Inform that the anvil process should not change the current applied enchantment. - * Also add sacrificeIllegalCost for every enchantment marked as big conflict. - */ - ENCHANTMENT_CONFLICT(2); - - fun getWorstConflict(otherConflict: ConflictType): ConflictType { - return if (this.importance > otherConflict.importance) this - else otherConflict - - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/ExcludeGroup.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/ExcludeGroup.kt deleted file mode 100644 index d752db5..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/ExcludeGroup.kt +++ /dev/null @@ -1,69 +0,0 @@ -package xyz.alexcrea.cuanvil.group - -import org.bukkit.NamespacedKey -import java.util.* - -class ExcludeGroup(name: String) : AbstractMaterialGroup(name) { - - override fun createDefaultSet(): MutableSet { - return NegativeMaterialSet() - } - - private var includedGroup: MutableSet = HashSet() - private val groupItems by lazy { createDefaultSet() } - - override fun isReferencing(other: AbstractMaterialGroup): Boolean { - for (materialGroup in includedGroup.iterator()) { - if ((materialGroup == other) || (materialGroup.isReferencing(other))) { - return true - } - } - return false - } - - override fun addToPolicy(type: NamespacedKey): ExcludeGroup { - includedMaterial.remove(type) - groupItems.remove(type) - - return this - } - - override fun addToPolicy(other: AbstractMaterialGroup): ExcludeGroup { - includedGroup.add(other) - groupItems.removeAll(other.getMaterials()) - - return this - } - - override fun setGroups(groups: MutableSet) { - groupItems.clear() - groupItems.addAll(includedMaterial) - - includedGroup.clear() - groups.forEach { group -> - if (!group.isReferencing(this)) { - includedGroup.add(group) - groupItems.removeAll(group.getMaterials()) - } - } - } - - override fun getGroups(): MutableSet { - return includedGroup - } - - override fun updateMaterials() { - groupItems.clear() - groupItems.addAll(includedMaterial) - - includedGroup.forEach { group -> - groupItems.addAll(group.getMaterials()) - } - } - - override fun getMaterials(): MutableSet { - return groupItems - } - - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/IncludeGroup.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/IncludeGroup.kt deleted file mode 100644 index fc9614b..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/IncludeGroup.kt +++ /dev/null @@ -1,75 +0,0 @@ -package xyz.alexcrea.cuanvil.group - -import org.bukkit.Material -import org.bukkit.NamespacedKey -import java.util.* - -class IncludeGroup(name: String) : AbstractMaterialGroup(name) { - override fun createDefaultSet(): MutableSet { - return HashSet() - } - - private var includedGroup: MutableSet = HashSet() - private val groupItems by lazy { createDefaultSet() } - - override fun isReferencing(other: AbstractMaterialGroup): Boolean { - for (materialGroup in includedGroup.iterator()) { - if ((materialGroup == other) || (materialGroup.isReferencing(other))) { - return true - } - } - return false - } - - override fun addToPolicy(type: NamespacedKey): IncludeGroup { - includedMaterial.add(type) - groupItems.add(type) - - return this - } - - override fun addToPolicy(other: AbstractMaterialGroup): IncludeGroup { - includedGroup.add(other) - groupItems.addAll(other.getMaterials()) - - return this - } - - override fun setGroups(groups: MutableSet) { - groupItems.clear() - groupItems.addAll(includedMaterial) - - includedGroup.clear() - groups.forEach { group -> - if (!group.isReferencing(this)) { - includedGroup.add(group) - groupItems.addAll(group.getMaterials()) - } - } - } - - override fun setNonGroupInheritedMaterials(materials: Set) { - super.setNonGroupInheritedMaterials(materials) - - updateMaterials() - } - - override fun getGroups(): MutableSet { - return includedGroup - } - - override fun updateMaterials() { - groupItems.clear() - groupItems.addAll(includedMaterial) - - includedGroup.forEach { group -> - groupItems.addAll(group.getMaterials()) - } - } - - override fun getMaterials(): MutableSet { - return groupItems - } - - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/NegativeMaterialSet.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/NegativeMaterialSet.kt deleted file mode 100644 index d87004d..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/NegativeMaterialSet.kt +++ /dev/null @@ -1,22 +0,0 @@ -package xyz.alexcrea.cuanvil.group - -import org.bukkit.NamespacedKey -import xyz.alexcrea.cuanvil.util.MaterialUtil -import xyz.alexcrea.cuanvil.util.NegativeSet - -class NegativeMaterialSet: NegativeSet() { - - override fun iterator(): MutableIterator { - val materials = MaterialUtil.getMaterials() - materials.removeIf { negate.contains(it) } - - return materials.iterator() - } - - override fun isEmpty(): Boolean { - return negate.size >= MaterialUtil.getMaterialCount() - } - - override val size get() = MaterialUtil.getMaterialCount() - negate.size - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilCloseListener.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilCloseListener.kt deleted file mode 100644 index d707b56..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilCloseListener.kt +++ /dev/null @@ -1,25 +0,0 @@ -package xyz.alexcrea.cuanvil.listener - -import org.bukkit.GameMode -import org.bukkit.entity.Player -import org.bukkit.event.EventHandler -import org.bukkit.event.Listener -import org.bukkit.event.inventory.InventoryCloseEvent -import org.bukkit.inventory.AnvilInventory -import xyz.alexcrea.cuanvil.dependency.packet.PacketManager -import xyz.alexcrea.cuanvil.util.dialog.AnvilRenameDialogUtil - -class AnvilCloseListener(private val packetManager: PacketManager) : Listener { - - @EventHandler - fun onAnvilClose(event: InventoryCloseEvent){ - val player = event.player - if(event.inventory !is AnvilInventory) return - if(player is Player && GameMode.CREATIVE != player.gameMode){ - packetManager.setInstantBuild(player, false) - } - - AnvilRenameDialogUtil.anvilRenameDialog.closeInventory(player) - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt deleted file mode 100644 index e393dbd..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt +++ /dev/null @@ -1,613 +0,0 @@ -package xyz.alexcrea.cuanvil.listener - -import io.delilaheve.CustomAnvil -import io.delilaheve.util.ConfigOptions -import io.delilaheve.util.ItemUtil.canMergeWith -import org.bukkit.GameMode -import org.bukkit.Material -import org.bukkit.entity.Player -import org.bukkit.event.Event -import org.bukkit.event.EventHandler -import org.bukkit.event.Listener -import org.bukkit.event.inventory.ClickType -import org.bukkit.event.inventory.InventoryClickEvent -import org.bukkit.inventory.AnvilInventory -import org.bukkit.inventory.InventoryView -import org.bukkit.inventory.ItemStack -import org.bukkit.inventory.meta.BookMeta -import xyz.alexcrea.cuanvil.anvil.AnvilCost -import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic -import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic.AnvilResult -import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic.CustomCraftResult -import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic.LoreEditResult -import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic.UnitRepairResult -import xyz.alexcrea.cuanvil.dependency.DependencyManager -import xyz.alexcrea.cuanvil.dependency.economy.EconomyManager -import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.setComponentDisplayName -import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_INPUT_LEFT -import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_INPUT_RIGHT -import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT -import xyz.alexcrea.cuanvil.util.CustomRecipeUtil -import xyz.alexcrea.cuanvil.util.MiniMessageUtil -import xyz.alexcrea.cuanvil.util.anvil.AnvilLoreEditUtil -import xyz.alexcrea.cuanvil.util.anvil.AnvilXpUtil -import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil -import xyz.alexcrea.cuanvil.util.config.LoreEditType -import java.util.* -import java.util.concurrent.atomic.AtomicReference -import kotlin.math.min - -class AnvilResultListener : Listener { - - companion object { - // static slot container - private val NO_SLOT = SlotContainer(SlotType.NO_SLOT, 0) - private val CURSOR_SLOT = SlotContainer(SlotType.CURSOR, 0) - } - - /** - * Event handler logic for when a player is trying to pull an item out of the anvil - */ - @EventHandler(ignoreCancelled = true) - fun anvilExtractionCheck(event: InventoryClickEvent) { - val player = event.whoClicked as? Player ?: return - val inventory = event.inventory as? AnvilInventory ?: return - val view = event.view - - if (event.rawSlot != ANVIL_OUTPUT_SLOT) { - return - } - - // Test if the event should bypass custom anvil. - if (DependencyManager.tryClickAnvilResultBypass(event, inventory)) return - - if (!player.hasPermission(CustomAnvil.affectedByPluginPermission)) return - - val output = inventory.getItem(ANVIL_OUTPUT_SLOT) ?: return - val leftItem = inventory.getItem(ANVIL_INPUT_LEFT) ?: return - val rightItem = inventory.getItem(ANVIL_INPUT_RIGHT) - - // Deny by default. allow if working - event.result = Event.Result.DENY - if (GameMode.CREATIVE != player.gameMode && inventory.repairCost >= inventory.maximumRepairCost) { - return - } - - // Test custom recipe - val customRecipeResult = AnvilMergeLogic.testCustomRecipe(view, inventory, player, leftItem, rightItem) - if (!customRecipeResult.isEmpty()) { - onCustomCraft( - event, player, inventory, - leftItem, rightItem, customRecipeResult - ) - return - } - - // Do not continue if there was no change - if ((output == inventory.getItem(ANVIL_INPUT_LEFT))) { - return - } - - // Rename - if (rightItem == null) { - val result = AnvilMergeLogic.doRenaming(view, inventory, player, leftItem) - if (result.isEmpty()) return - - extractAnvilResult( - event, player, inventory, - null, 0, - null, 0, - result - ) - return - } - - // Merge - val canMerge = leftItem.canMergeWith(rightItem) - if (canMerge) { - val result = AnvilMergeLogic.doMerge(view, inventory, player, leftItem, rightItem) - - extractAnvilResult( - event, player, inventory, - null, 0, - null, 0, - result - ) - return - } - - // Unit repair - val unitRepairResult = AnvilMergeLogic.testUnitRepair( - view, inventory, player, - leftItem, rightItem - ) - if (!unitRepairResult.isEmpty()) { - onUnitRepairExtract( - rightItem, event, player, inventory, - unitRepairResult - ) - return - } - - // For lore edit - val loreResult = AnvilMergeLogic.testLoreEdit(player, leftItem, rightItem) - if (!loreResult.isEmpty()) { - if (loreResult.type.isBook) - handleBookLoreEdit(event, inventory, player, leftItem, rightItem, loreResult) - else - handlePaperLoreEdit(event, inventory, player, leftItem, rightItem, loreResult) - return - } - } - - private fun onCustomCraft( - event: InventoryClickEvent, - player: Player, - inventory: AnvilInventory, - leftItem: ItemStack, - rightItem: ItemStack?, - result: CustomCraftResult, - ) { - val recipe = result.recipe!! - val rawCost = result.customCraftCost.rawCost - val finalCost = - if (recipe.removeExactLinearXp) rawCost - else AnvilXpUtil.calculateLevelForXp(rawCost) - - CustomAnvil.log( - "gamemode: ${player.gameMode != GameMode.CREATIVE}, " + - "cost: $finalCost, level: ${player.level}, " + - "result: ${player.totalExperience < finalCost} ${player.level < finalCost}" - ) - - if (player.gameMode != GameMode.CREATIVE) { - if (ConfigOptions.shouldUseMoney(player)) { - result.cost.isMonetary = true - if (!EconomyManager.economy!!.has(player, result.cost.asMonetaryCost())) return - } else if (recipe.removeExactLinearXp) { - val levelXp = AnvilXpUtil.calculateXpForLevel(player.level) - val delta = AnvilXpUtil.calculateXpForLevel(player.level + 1) - levelXp - val totalXp = levelXp + player.exp * delta - if (totalXp < finalCost) return - } else if (player.level < finalCost) return - } - - // We give the item manually - // But first we check if we should give the item - val slotDestination = getActionSlot(event, player) - if (slotDestination.type == SlotType.NO_SLOT) return - - // Handle not creative middle click... - if (event.click != ClickType.MIDDLE && - !handleCustomCraftClick( - event, - inventory, - player, - leftItem, - rightItem, - result - ) - ) return - - // Finally, we add the item to the player - if (slotDestination.type == SlotType.CURSOR) { - player.setItemOnCursor(result.item) - } else {// We assume SlotType == SlotType.INVENTORY - player.inventory.setItem(slotDestination.slot, result.item) - } - } - - private fun handleCustomCraftClick( - event: InventoryClickEvent, - inventory: AnvilInventory, player: Player, - leftItem: ItemStack, rightItem: ItemStack?, - result: CustomCraftResult - ): Boolean { - val amount = result.amount - val recipe = result.recipe!! - - // We remove what should be removed - if (rightItem != null) { - if (recipe.rightItem == null) return false// in case it changed - - rightItem.amount -= amount * recipe.rightItem!!.amount - inventory.setItem(ANVIL_INPUT_RIGHT, rightItem) - } - - leftItem.amount -= amount * recipe.leftItem!!.amount - inventory.setItem(ANVIL_INPUT_LEFT, leftItem) - - removeCustomCraftCost(player, result) - - // Then we try to find the new values for the anvil - val newAmount = CustomRecipeUtil.getCustomRecipeAmount(recipe, leftItem, rightItem) - - CustomAnvil.verboseLog("new amount is $newAmount") - if (newAmount <= 0 || recipe.exactCount) { - inventory.setItem(ANVIL_OUTPUT_SLOT, null) - } else { - val resultItem: ItemStack = recipe.resultItem!!.clone() - resultItem.amount *= newAmount - - val newXp = newAmount * newAmount - - inventory.repairCost = newXp - event.view.setProperty(InventoryView.Property.REPAIR_COST, newXp) - - inventory.setItem(ANVIL_OUTPUT_SLOT, resultItem) - - player.updateInventory() - } - return true - } - - private fun removeCustomCraftCost(player: Player, result: CustomCraftResult) { - if (player.gameMode == GameMode.CREATIVE) return - - val rawCost = result.customCraftCost.rawCost - if (result.cost.isMonetary) { - EconomyManager.economy!!.remove(player, result.cost.asMonetaryCost()) - return - } - - if (result.recipe!!.removeExactLinearXp) { - val levelXp = AnvilXpUtil.calculateXpForLevel(player.level) - val delta = AnvilXpUtil.calculateXpForLevel(player.level + 1) - levelXp - var totalXp = levelXp + player.exp * delta - totalXp -= rawCost - - val newLevel = AnvilXpUtil.calculateLevelForXp(totalXp.toInt()) - - val newLevelXp = AnvilXpUtil.calculateXpForLevel(newLevel) - val newDelta = AnvilXpUtil.calculateXpForLevel(newLevel + 1) - newLevelXp - val xp = (totalXp - newLevelXp) / newDelta - - player.level = newLevel - player.exp = xp / newDelta - } else { - player.level -= AnvilXpUtil.calculateLevelForXp(rawCost) - } - - } - - private fun tryRemoveCost(player: Player, result: AnvilResult): Boolean { - if (player.gameMode == GameMode.CREATIVE) return true - - val cost = result.cost - if (cost.isMonetary) { - val result = EconomyManager.economy!!.remove(player, cost.asMonetaryCost()) - if (!result) return false - } else { - val xpCost = cost.filteredXpCost() - if (xpCost > AnvilXpUtil.maximumXpCost(result.ignoreXpRules)) return false - if (player.level < xpCost) return false - - player.level -= xpCost - } - - return true - } - - private fun extractAnvilResult( - event: InventoryClickEvent, - player: Player, - inventory: AnvilInventory, - leftItem: ItemStack?, - leftRemoveCount: Int, - rightItem: ItemStack?, - rightRemoveCount: Int, - result: AnvilResult - ): Boolean { - if (result.isEmpty()) return false - - // To avoid vanilla, we cancel the event - event.result = Event.Result.DENY - event.isCancelled = true - val cost = result.cost - - processCost(inventory, player, cost) - if (!cost.valid && player.gameMode != GameMode.CREATIVE) return false - - // Where should we get the item - val slotDestination = getActionSlot(event, player) - if (slotDestination.type == SlotType.NO_SLOT) return false - - // If not creative middle click... - if (event.click != ClickType.MIDDLE) { - if (!tryRemoveCost(player, result)) return false - - // We remove what should be removed - if (leftItem != null) leftItem.amount -= leftRemoveCount - inventory.setItem(ANVIL_INPUT_LEFT, leftItem) - - if (rightItem != null) rightItem.amount -= rightRemoveCount - inventory.setItem(ANVIL_INPUT_RIGHT, rightItem) - - inventory.setItem(ANVIL_OUTPUT_SLOT, null) - - } - - // Finally, we add the item to the player - if (SlotType.CURSOR == slotDestination.type) { - player.setItemOnCursor(result.item) - } else {// We assume SlotType == SlotType.INVENTORY - player.inventory.setItem(slotDestination.slot, result.item) - } - - // TODO probably anvil damage & sound here ?? - return true - } - - private fun processCost(inventory: AnvilInventory, player: Player, cost: AnvilCost) { - var sum = cost.repair - - if ( - !ConfigOptions.doRemoveCostLimit && - ConfigOptions.doCapCost - ) { - val final = min(sum, ConfigOptions.maxAnvilCost) - cost.generic += (final - sum) - - sum = final - } - - if (ConfigOptions.shouldUseMoney(player)) { - cost.isMonetary = true - if (!EconomyManager.economy!!.has(player, cost.asMonetaryCost())) - cost.valid = false - } else { - if ((inventory.maximumRepairCost <= sum) - || (player.level < sum) - ) cost.valid = false - } - } - - private fun onUnitRepairExtract( - rightItem: ItemStack, - event: InventoryClickEvent, - player: Player, - inventory: AnvilInventory, - result: UnitRepairResult, - ) { - // We give the item manually - extractAnvilResult( - event, player, inventory, - null, 0, - rightItem, result.repairAmount, - result - ) - } - - private fun handleBookLoreEdit( - event: InventoryClickEvent, - inventory: AnvilInventory, - player: Player, - leftItem: ItemStack, - rightItem: ItemStack, - result: LoreEditResult - ) { - if (result.type.isAppend) - handleBookLoreAppend(event, inventory, player, rightItem, result) - else - handleBookLoreRemove(event, inventory, player, leftItem, rightItem, result) - } - - private fun handleBookLoreAppend( - event: InventoryClickEvent, - inventory: AnvilInventory, - player: Player, - rightItem: ItemStack, - result: LoreEditResult - ) { - val bookMeta = rightItem.itemMeta as BookMeta? ?: return - - // Remove pages to book - val clearedBook: ItemStack? - if (LoreEditType.APPEND_BOOK.doConsume) { - clearedBook = null - } else { - clearedBook = rightItem.clone() - bookMeta.pages = Collections.emptyList() - clearedBook.itemMeta = bookMeta - } - - extractAnvilResult( - event, player, inventory, - null, 0, - clearedBook, 0, - result - ) - } - - private fun handleBookLoreRemove( - event: InventoryClickEvent, - inventory: AnvilInventory, - player: Player, - leftItem: ItemStack, - rightItem: ItemStack, - result: LoreEditResult - ) { - val bookMeta = rightItem.itemMeta as BookMeta? ?: return - - // fill book meta - val lore = DependencyManager.stripLore(leftItem) - if (lore.isEmpty()) return - - val rightCopy: ItemStack? - if (LoreEditType.REMOVE_BOOK.doConsume) { - rightCopy = null - } else { - // Uncolor the page - AnvilLoreEditUtil.uncolorLines(player, lore, LoreEditType.REMOVE_BOOK) - - val bookPage = StringBuilder() - lore.forEach { - if (bookPage.isNotEmpty()) bookPage.append('\n') - if (it == null) return@forEach - - bookPage.append(MiniMessageUtil.plain_text_mm.serialize(it)) - } - - val resultPage = bookPage.toString() - //TODO maybe check page size ? bc it may be too big ??? - - rightCopy = rightItem.clone() - bookMeta.setPages(resultPage) - rightCopy.itemMeta = bookMeta - } - - extractAnvilResult( - event, player, inventory, - null, 0, - rightCopy, 0, - result - ) - } - - private fun handlePaperLoreEdit( - event: InventoryClickEvent, - inventory: AnvilInventory, - player: Player, - leftItem: ItemStack, - rightItem: ItemStack, - result: LoreEditResult - ) { - if (result.type.isAppend) - handlePaperLoreAppend(event, inventory, player, rightItem, result) - else - handlePaperLoreRemove(event, inventory, player, leftItem, rightItem, result) - } - - private fun handlePaperLoreAppend( - event: InventoryClickEvent, - inventory: AnvilInventory, - player: Player, - rightItem: ItemStack, - result: LoreEditResult - ) { - val paperMeta = rightItem.itemMeta ?: return - - - val paperCopy: ItemStack? - if (LoreEditType.APPEND_PAPER.doConsume) { - paperCopy = null - } else { - // Remove custom name to paper - paperCopy = rightItem.clone() - paperCopy.amount = 1 - paperMeta.setComponentDisplayName(null) - - // Remove pcd name - AnvilMergeLogic.processPCD(paperMeta, player, null) - - paperCopy.itemMeta = paperMeta - } - - if (rightItem.amount > 1) { - extractAnvilResult( - event, player, inventory, - paperCopy, 0, - rightItem, 1, - result - ) - } else { - extractAnvilResult( - event, player, inventory, - null, 0, - paperCopy, 0, - result - ) - } - } - - private fun handlePaperLoreRemove( - event: InventoryClickEvent, - inventory: AnvilInventory, - player: Player, - leftItem: ItemStack, - rightItem: ItemStack, - result: LoreEditResult - ) { - val leftMeta = leftItem.itemMeta - if (leftMeta == null || !leftMeta.hasLore()) return - - val lore = DependencyManager.stripLore(leftItem) - if (lore.isEmpty()) return - - // Create result item - val rightClone: ItemStack? - if (LoreEditType.REMOVE_PAPER.doConsume) { - rightClone = null - } else { - val removeEnd = LoreEditConfigUtil.paperLoreOrderIsEnd - val line = if (removeEnd) lore[lore.size - 1] - else lore[0] - - // uncolor the line - val ref = AtomicReference(line) - AnvilLoreEditUtil.uncolorLine(player, ref, LoreEditType.REMOVE_PAPER) - - rightClone = rightItem.clone() - rightClone.amount = 1 - - val resultMeta = rightClone.itemMeta ?: return - resultMeta.setComponentDisplayName(ref.get()) - rightClone.itemMeta = resultMeta - } - - if (rightItem.amount > 1) { - extractAnvilResult( - event, player, inventory, - rightClone, 0, - rightItem, 1, - result - ) - } else { - extractAnvilResult( - event, player, inventory, - null, 0, - rightClone, 0, - result - ) - } - } - - /** - * Get the destination slot or "NO_SLOT" slot container if there is no slot available - */ - private fun getActionSlot(event: InventoryClickEvent, player: Player): SlotContainer { - if (event.isShiftClick) { - val inventory = player.inventory - val firstEmpty = inventory.firstEmpty() - if (firstEmpty == -1) { - return NO_SLOT - } - //check hotbare full - var slotIndex = 8 - while (slotIndex >= 0 && ((inventory.getItem(slotIndex)?.type ?: Material.AIR) != Material.AIR)) { - slotIndex-- - } - if (slotIndex >= 0) { - return SlotContainer(SlotType.INVENTORY, slotIndex) - } - slotIndex = 35 //4*9 - 1 (max of player inventory) - while (slotIndex >= 9 && ((inventory.getItem(slotIndex)?.type ?: Material.AIR) != Material.AIR)) { - slotIndex-- - } - if (slotIndex < 9) { - return NO_SLOT - } - return SlotContainer(SlotType.INVENTORY, slotIndex) - } else if (player.itemOnCursor.type != Material.AIR) return NO_SLOT - return CURSOR_SLOT - } - - private class SlotContainer(val type: SlotType, val slot: Int) - private enum class SlotType { - CURSOR, - INVENTORY, - NO_SLOT - - } - -} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/ChatEventListener.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/ChatEventListener.kt deleted file mode 100644 index f166fa3..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/ChatEventListener.kt +++ /dev/null @@ -1,49 +0,0 @@ -package xyz.alexcrea.cuanvil.listener - -import io.delilaheve.CustomAnvil -import org.bukkit.entity.HumanEntity -import org.bukkit.event.EventHandler -import org.bukkit.event.Listener -import org.bukkit.event.player.AsyncPlayerChatEvent -import org.bukkit.event.player.PlayerQuitEvent -import xyz.alexcrea.cuanvil.dependency.DependencyManager -import java.util.* -import java.util.concurrent.ConcurrentHashMap -import java.util.function.Consumer - -class ChatEventListener : Listener { - - private val playerListenMap: ConcurrentHashMap> = ConcurrentHashMap() - - fun setListenedCallback(playeruuid: UUID, callback: Consumer) { - playerListenMap[playeruuid] = callback - } - - fun setListenedCallback(player: HumanEntity, callback: Consumer) { - setListenedCallback(player.uniqueId, callback) - } - - @EventHandler - fun onQuit(event: PlayerQuitEvent) { - val eventCallback = playerListenMap.remove(event.player.uniqueId) ?: return - eventCallback.accept(null) - - } - - @EventHandler - fun onChat(event: AsyncPlayerChatEvent) { - if (event.isCancelled) return - val player = event.player - val eventCallback = playerListenMap.remove(player.uniqueId) ?: return - - event.isCancelled = true - - // sync callback with default server thread - DependencyManager.scheduler.scheduleOnEntity( - CustomAnvil.instance, player, - Runnable { - eventCallback.accept(event.message) - }, 0L) - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt deleted file mode 100644 index 0217983..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt +++ /dev/null @@ -1,181 +0,0 @@ -package xyz.alexcrea.cuanvil.listener - -import com.github.stefvanschie.inventoryframework.util.InventoryViewUtil -import io.delilaheve.CustomAnvil -import io.delilaheve.util.ConfigOptions -import io.delilaheve.util.ItemUtil.canMergeWith -import org.bukkit.entity.HumanEntity -import org.bukkit.entity.Player -import org.bukkit.event.EventHandler -import org.bukkit.event.EventPriority -import org.bukkit.event.Listener -import org.bukkit.event.inventory.PrepareAnvilEvent -import org.bukkit.inventory.AnvilInventory -import org.bukkit.inventory.InventoryView -import org.bukkit.inventory.ItemStack -import org.bukkit.inventory.meta.EnchantmentStorageMeta -import org.bukkit.inventory.meta.ItemMeta -import xyz.alexcrea.cuanvil.anvil.AnvilCost -import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic.AnvilResult -import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic.doMerge -import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic.doRenaming -import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic.testCustomRecipe -import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic.testLoreEdit -import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic.testUnitRepair -import xyz.alexcrea.cuanvil.dependency.DependencyManager -import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir -import xyz.alexcrea.cuanvil.util.anvil.AnvilXpUtil -import xyz.alexcrea.cuanvil.util.dialog.AnvilRenameDialogUtil - -/** - * Listener for anvil events - */ -class PrepareAnvilListener : Listener { - - companion object { - - // Anvil's output slot - const val ANVIL_INPUT_LEFT = 0 - const val ANVIL_INPUT_RIGHT = 1 - const val ANVIL_OUTPUT_SLOT = 2 - - var IS_EMPTY_TEST = false - } - - /** - * Event handler logic for when an anvil contains items to be combined - */ - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - fun anvilCombineCheck(event: PrepareAnvilEvent) { - val view = event.view - val inventory = event.inventory - - val player = InventoryViewUtil.getInstance().getPlayer(view) - if(player !is Player) return - - tryRenameDialog(player, event) - - // Test if custom anvil is bypassed before immutability test - if (DependencyManager.earlyTryEventPreAnvilBypass(event, player)) { - // even if we got bypassed we still want to set price - AnvilXpUtil.setAnvilInvCost(inventory, view, player, AnvilCost(event.inventory.repairCost)) - return - } - - val first = inventory.getItem(ANVIL_INPUT_LEFT) - val second = inventory.getItem(ANVIL_INPUT_RIGHT) - - if(IS_EMPTY_TEST) { - IS_EMPTY_TEST = false - applyResult(event, player, AnvilResult.EMPTY) - return - } - - if (ConfigOptions.verboseDebugLog) { - CustomAnvil.verboseLog("Testing items:") - CustomAnvil.verboseLog("first: $first") - CustomAnvil.verboseLog("second: $second") - } - if (isImmutable(first) || isImmutable(second)) { - CustomAnvil.verboseLog("Skipping anvil process as one of the two item is immutable") - - applyResult(event, player, AnvilResult.EMPTY) - return - } - - // Test if the event should bypass custom anvil. - if (DependencyManager.tryEventPreAnvilBypass(event, player)) { - // even if we got bypassed we still want to set price - AnvilXpUtil.setAnvilInvCost(inventory, view, player, AnvilCost(event.inventory.repairCost)) - return - } - - if (!player.hasPermission(CustomAnvil.affectedByPluginPermission)) return - - val result = getResult(view, inventory, player, first, second) - applyResult(event, player, result) - } - - fun getResult( - view: InventoryView, //TODO use anvil view - inventory: AnvilInventory, - player: Player, - first: ItemStack?, second: ItemStack?) : AnvilResult - { - if(first == null) - return AnvilResult.EMPTY - - // Test custom recipe - var result: AnvilResult = testCustomRecipe(view, inventory, player, first, second) - if (!result.isEmpty()) - return result - - // Test rename lonely item - val shouldTryRename = second.isAir - CustomAnvil.verboseLog("checking air in main logic: $shouldTryRename") - if (shouldTryRename) - return doRenaming(view, inventory, player, first) - - // Test for merge - if (first.canMergeWith(second!!)) - return doMerge(view, inventory, player, first, second) - - // Test for unit repair - result = testUnitRepair(view, inventory, player, first, second) - if (!result.isEmpty()) - return result - - // Test for lore edit - result = testLoreEdit(player, first, second) - if (!result.isEmpty()) - return result - - return AnvilResult.EMPTY - } - - private fun tryRenameDialog( - player: HumanEntity, - event: PrepareAnvilEvent - ) { - if(!ConfigOptions.canUseDialogRename(player)) return - - AnvilRenameDialogUtil.anvilRenameDialog.tryShowDialog(player, event) - } - - private fun isImmutable(item: ItemStack?): Boolean { - if (item.isAir) return false - - val meta = item!!.itemMeta - return meta != null && - (hasImmutableEnchants(meta) || hasImmutableStoredEnchants(meta)) - } - - private fun hasImmutableEnchants(meta: ItemMeta): Boolean { - if (!meta.hasEnchants()) return false - - for (enchant in meta.enchants.keys) { - if (ConfigOptions.isImmutable(enchant.key)) return true - } - return false - } - - private fun hasImmutableStoredEnchants(meta: ItemMeta): Boolean { - if (meta !is EnchantmentStorageMeta || !meta.hasStoredEnchants()) return false - - for (enchant in meta.storedEnchants.keys) { - if (ConfigOptions.isImmutable(enchant.key)) return true - } - return false - } - - private fun applyResult(event: PrepareAnvilEvent, player: Player, result: AnvilResult) { - event.result = result.item - - if(result.item == null) { - AnvilXpUtil.onNoResult(player, event.view) - return - } - AnvilXpUtil.setAnvilInvCost(event.inventory, event.view, player, result.cost, result.ignoreXpRules) - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/AnvilCustomRecipe.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/AnvilCustomRecipe.kt deleted file mode 100644 index fd079c3..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/AnvilCustomRecipe.kt +++ /dev/null @@ -1,214 +0,0 @@ -package xyz.alexcrea.cuanvil.recipe - -import io.delilaheve.CustomAnvil -import org.bukkit.configuration.ConfigurationSection -import org.bukkit.inventory.ItemStack -import xyz.alexcrea.cuanvil.anvil.AnvilUseType -import xyz.alexcrea.cuanvil.config.ConfigHolder -import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant -import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir -import xyz.alexcrea.cuanvil.util.anvil.AnvilXpUtil - -class AnvilCustomRecipe( - val name: String, - var exactCount: Boolean, - //var exactLeft: Boolean, - //var exactRight: Boolean, - - var levelCostPerCraft: Int, - - var XpCostPerCraft: Int, - var removeExactLinearXp: Boolean, - - var leftItem: ItemStack?, - var rightItem: ItemStack?, - var resultItem: ItemStack?, -) { - - // Static config name - companion object { - const val EXACT_COUNT_CONFIG = "exact_count" - //const val EXACT_LEFT_CONFIG = "exact_left" - //const val EXACT_RIGHT_CONFIG = "exact_right" - - const val XP_LEVEL_COST_CONFIG = "xp_cost" - const val LINEAR_XP_COST_CONFIG = "linear_xp_cost" - const val REMOVE_EXACT_XP_CONFIG = "remove_exact_linear_xp" - - const val LEFT_ITEM_CONFIG = "left_item" - const val RIGHT_ITEM_CONFIG = "right_item" - const val RESULT_ITEM_CONFIG = "result_item" - - - const val DEFAULT_EXACT_COUNT_CONFIG = true - //val DEFAULT_EXACT_LEFT_CONFIG = true - //val DEFAULT_EXACT_RIGHT_CONFIG = true - - const val DEFAULT_XP_LEVEL_COST_CONFIG = 1 - const val DEFAULT_LINEAR_XP_COST_CONFIG = 0 - const val DEFAULT_REMOVE_EXACT_XP_CONFIG = false - - val DEFAULT_LEFT_ITEM_CONFIG: ItemStack? = null - val DEFAULT_RIGHT_ITEM_CONFIG: ItemStack? = null - val DEFAULT_RESULT_ITEM_CONFIG: ItemStack? = null - - val XP_COST_CONFIG_RANGE = 0..255 - - fun getFromConfig(name: String, configSection: ConfigurationSection?): AnvilCustomRecipe? { - if (configSection == null) return null - return AnvilCustomRecipe( - name, - configSection.getBoolean(EXACT_COUNT_CONFIG, DEFAULT_EXACT_COUNT_CONFIG), - //configSection.getBoolean(EXACT_LEFT_CONFIG, true), - //configSection.getBoolean(EXACT_RIGHT_CONFIG, true), - - configSection.getInt(XP_LEVEL_COST_CONFIG, DEFAULT_XP_LEVEL_COST_CONFIG), - configSection.getInt(LINEAR_XP_COST_CONFIG, DEFAULT_LINEAR_XP_COST_CONFIG), - configSection.getBoolean(REMOVE_EXACT_XP_CONFIG, DEFAULT_REMOVE_EXACT_XP_CONFIG), - - - configSection.getItemStack(LEFT_ITEM_CONFIG, DEFAULT_LEFT_ITEM_CONFIG), - - configSection.getItemStack(RIGHT_ITEM_CONFIG, DEFAULT_RIGHT_ITEM_CONFIG), - configSection.getItemStack(RESULT_ITEM_CONFIG, DEFAULT_RESULT_ITEM_CONFIG), - - ) - } - - fun getFromConfig(name: String): AnvilCustomRecipe? { - return getFromConfig(name, ConfigHolder.CUSTOM_RECIPE_HOLDER.config.getConfigurationSection(name)) - } - } - - fun validate(): Boolean { - return !leftItem.isAir && - (rightItem == null || !resultItem.isAir) && - !resultItem.isAir - } - - fun saveToFile(writeFile: Boolean, doBackup: Boolean) { - val fileConfig = ConfigHolder.CUSTOM_RECIPE_HOLDER.config - - fileConfig["$name.$EXACT_COUNT_CONFIG"] = exactCount - //fileConfig.set("$name.$EXACT_LEFT_CONFIG", exactLeft) - //fileConfig.set("$name.$EXACT_RIGHT_CONFIG", exactRight) - - fileConfig["$name.$XP_LEVEL_COST_CONFIG"] = levelCostPerCraft - fileConfig["$name.$LINEAR_XP_COST_CONFIG"] = XpCostPerCraft - fileConfig["$name.$REMOVE_EXACT_XP_CONFIG"] = removeExactLinearXp - - fileConfig["$name.$LEFT_ITEM_CONFIG"] = leftItem - fileConfig["$name.$RIGHT_ITEM_CONFIG"] = rightItem - fileConfig["$name.$RESULT_ITEM_CONFIG"] = resultItem - - - if (writeFile) { - ConfigHolder.CUSTOM_RECIPE_HOLDER.saveToDisk(doBackup) - } - } - - @Deprecated("Should use saveToFile(Boolean, Boolean) instead") //TODO determine when an where to save/do backup and remove use of variable like TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE - fun saveToFile() { - saveToFile( - GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE, - GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE - ) - } - - fun updateFromFile() { - this.exactCount = ConfigHolder.CUSTOM_RECIPE_HOLDER.config.getBoolean( - "$name.$EXACT_COUNT_CONFIG", - DEFAULT_EXACT_COUNT_CONFIG - ) - - this.levelCostPerCraft = ConfigHolder.CUSTOM_RECIPE_HOLDER.config.getInt( - "$name.$XP_LEVEL_COST_CONFIG", - DEFAULT_XP_LEVEL_COST_CONFIG - ) - - this.XpCostPerCraft = ConfigHolder.CUSTOM_RECIPE_HOLDER.config.getInt( - "$name.$LINEAR_XP_COST_CONFIG", - DEFAULT_LINEAR_XP_COST_CONFIG - ) - - this.removeExactLinearXp = ConfigHolder.CUSTOM_RECIPE_HOLDER.config.getBoolean( - "$name.$REMOVE_EXACT_XP_CONFIG", - DEFAULT_REMOVE_EXACT_XP_CONFIG - ) - - // Update items - val leftItem = ConfigHolder.CUSTOM_RECIPE_HOLDER.config.getItemStack( - "$name.$LEFT_ITEM_CONFIG", - DEFAULT_LEFT_ITEM_CONFIG - ) - - this.rightItem = ConfigHolder.CUSTOM_RECIPE_HOLDER.config.getItemStack( - "$name.$RIGHT_ITEM_CONFIG", - DEFAULT_RIGHT_ITEM_CONFIG - ) - - this.resultItem = ConfigHolder.CUSTOM_RECIPE_HOLDER.config.getItemStack( - "$name.$RESULT_ITEM_CONFIG", - DEFAULT_RESULT_ITEM_CONFIG - ) - - // Update material map - ConfigHolder.CUSTOM_RECIPE_HOLDER.recipeManager.cleanSetLeftItem(this, leftItem) - - } - - fun testItem(item1: ItemStack, item2: ItemStack?): Boolean { - CustomAnvil.verboseLog("Testing $name $leftItem") - // We assume this function can be call only if leftItem != null - - // Test if valid - if (!validate()) return false - - val leftSimilar = leftItem!!.isSimilar(item1) - CustomAnvil.verboseLog("Validated test !") - - // test of left item - if (!leftSimilar) return false // Test similar - if (exactCount) { - if ((leftItem!!.amount != item1.amount)) return false // test exact amount - } else if (item1.amount < leftItem!!.amount) return false // test if it has at least the amount we ask - - CustomAnvil.verboseLog("Left item passed !") - - // we don't know if right item can be - if (rightItem == null) { // null test - if (item2 != null) return false - } else { - val rightSimilar = rightItem!!.isSimilar(item2) - CustomAnvil.verboseLog("Right similar: $rightSimilar") - if (!rightSimilar) return false // test if similar when not null - - if (exactCount) { - if (rightItem!!.amount != item2!!.amount) return false // test exact amount - } else if (item2!!.amount < rightItem!!.amount) return false // test if it has at least the amount we ask - } - - CustomAnvil.verboseLog("Right item passed !") - - return true - } - - override fun toString(): String { - return name - } - - fun determineCost(amount: Int, first: ItemStack, resultItem: ItemStack): Int { - // First we determine the non linear level cost - var levelCost = levelCostPerCraft * amount - // TODO Maybe add an option per custom craft to ignore/not ignore penalty ?? - levelCost += AnvilXpUtil.calculatePenalty(first, null, resultItem, AnvilUseType.CUSTOM_CRAFT) - - var xpCost = AnvilXpUtil.calculateXpForLevel(levelCost) - // Then we add the linear cost - xpCost += XpCostPerCraft * amount - - return xpCost - } - - -} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/CustomAnvilRecipeManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/CustomAnvilRecipeManager.kt deleted file mode 100644 index f271d90..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/CustomAnvilRecipeManager.kt +++ /dev/null @@ -1,78 +0,0 @@ -package xyz.alexcrea.cuanvil.recipe - -import io.delilaheve.CustomAnvil -import org.bukkit.Material -import org.bukkit.configuration.file.FileConfiguration -import org.bukkit.inventory.ItemStack - -class CustomAnvilRecipeManager { - - lateinit var recipeList: ArrayList - - lateinit var recipeByMat: HashMap> - - fun prepareRecipes(config: FileConfiguration) { - recipeList = ArrayList() - recipeByMat = HashMap() - - // read all configs - val keys = config.getKeys(false) - for (key in keys) { - val recipe = AnvilCustomRecipe.getFromConfig(key) - if (recipe == null) { - CustomAnvil.log("Can't load recipe $key") - continue - } - - cleanAddNew(recipe) - } - - } - - - fun cleanAddNew(recipe: AnvilCustomRecipe) { - recipeList.add(recipe) - val leftItem = recipe.leftItem - if (leftItem != null) { - addToMatMap(recipe, leftItem) - } - - } - - fun cleanSetLeftItem(recipe: AnvilCustomRecipe, leftItem: ItemStack?) { - // Remove left item mat if exist - val oldLeftItem = recipe.leftItem - if (oldLeftItem != null) { - val oldMat = oldLeftItem.type - - val test = recipeByMat[oldMat] - test!!.remove(recipe) - } - if (leftItem != null) { - addToMatMap(recipe, leftItem) - } - - recipe.leftItem = leftItem - } - - private fun addToMatMap(recipe: AnvilCustomRecipe, leftItem: ItemStack) { - var recipeList = recipeByMat[leftItem.type] - if (recipeList == null) { - recipeList = ArrayList() - recipeByMat[leftItem.type] = recipeList - } - recipeList.add(recipe) - - } - - fun cleanRemove(recipe: AnvilCustomRecipe): Boolean { - - val exist = recipeList.remove(recipe) - if (exist) { - cleanSetLeftItem(recipe, null) - } - - return exist; - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/CustomRecipeUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/CustomRecipeUtil.kt deleted file mode 100644 index 058b25a..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/CustomRecipeUtil.kt +++ /dev/null @@ -1,54 +0,0 @@ -package xyz.alexcrea.cuanvil.util - -import io.delilaheve.CustomAnvil -import org.bukkit.inventory.ItemStack -import xyz.alexcrea.cuanvil.config.ConfigHolder -import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe -import kotlin.math.min - -object CustomRecipeUtil { - - fun getCustomRecipe ( - leftItem: ItemStack, - rightItem: ItemStack?) : AnvilCustomRecipe? { - - val recipeList = ConfigHolder.CUSTOM_RECIPE_HOLDER.recipeManager.recipeByMat[leftItem.type] ?: return null - - CustomAnvil.verboseLog("Testing " + recipeList.size + " recipe...") - for (recipe in recipeList) { - if(recipe.testItem(leftItem, rightItem)){ - return recipe - } - } - - return null - } - - fun getCustomRecipeAmount( - recipe: AnvilCustomRecipe, - leftItem: ItemStack, - rightItem: ItemStack? - ): Int{ - return if(recipe.exactCount) { - if(leftItem.amount != recipe.leftItem!!.amount){ - 0 - }else if(rightItem != null && rightItem.amount != recipe.rightItem!!.amount){ - 0 - }else{ - 1 - } - } - else { - // test amount - val resultItem = recipe.resultItem!! // we know exist as the recipe was returned to us - val maxResultAmount = resultItem.maxStackSize/resultItem.amount - val maxLeftAmount = leftItem.amount/recipe.leftItem!!.amount - val maxRightAmount = if(rightItem == null){ maxLeftAmount } else{ rightItem.amount/recipe.rightItem!!.amount } - - CustomAnvil.verboseLog("resultItem: $resultItem, maxResultAmount: $maxResultAmount, maxLeftAmount: $maxLeftAmount, maxRightAmount: $maxRightAmount") - - min(min(maxResultAmount, maxLeftAmount), maxRightAmount) - } - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/MaterialUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/MaterialUtil.kt deleted file mode 100644 index 6b55662..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/MaterialUtil.kt +++ /dev/null @@ -1,105 +0,0 @@ -package xyz.alexcrea.cuanvil.util - -import org.bukkit.Bukkit -import org.bukkit.Material -import org.bukkit.NamespacedKey -import org.bukkit.inventory.ItemStack -import xyz.alexcrea.cuanvil.dependency.DependencyManager -import xyz.alexcrea.cuanvil.dependency.plugins.EcoItemDependencyUtil - -object MaterialUtil { - - val ItemStack?.isAir: Boolean - get() { - return this == null || this.type.isAir || this.amount == 0 - } - - val NamespacedKey?.isAir: Boolean - get() { - return Material.AIR.key == this - } - - val ItemStack.customType: NamespacedKey - get() { - if(DependencyManager.ecoEnchantCompatibility != null) { - val result = EcoItemDependencyUtil.ecoItemNamespace(this) - if(result != null) return result - } - - val itemAdder = DependencyManager.itemsAdderCompatibility - if(itemAdder != null) { - val result = itemAdder.getKey(this) - if (result != null) return result - } - - return this.type.key - } - - private fun bukkitMaterialFromKey(key: NamespacedKey): Material? { - //TODO on paper only transition Registry.MATERIAL.get(key) - return Material.matchMaterial(key.toString()) - } - - fun getMatFromKey(key: NamespacedKey): Material? { - if(DependencyManager.ecoEnchantCompatibility != null) { - val result = EcoItemDependencyUtil.ecoItemMaterialFromKey(key) - if(result != null) return result - } - - val itemAdder = DependencyManager.itemsAdderCompatibility - if(itemAdder != null) { - val result = itemAdder.fromKey(key) - if (result != null) return result.type - } - - return bukkitMaterialFromKey(key) - } - - fun itemFromKey(key: NamespacedKey): ItemStack { - if(DependencyManager.ecoEnchantCompatibility != null) { - val result = EcoItemDependencyUtil.newEcoItemstack(key) - if(result != null) return result - } - - val itemAdder = DependencyManager.itemsAdderCompatibility - if(itemAdder != null) { - val result = itemAdder.fromKey(key) - if (result != null) return result - } - - return ItemStack(bukkitMaterialFromKey(key)!!) - } - - fun materialExist(key: NamespacedKey): Boolean { - return getMatFromKey(key) != null - } - - fun getMaterialCount(): Int { - var count = Material.entries.size - if(DependencyManager.ecoEnchantCompatibility != null) { - count += EcoItemDependencyUtil.getItems().size - } - - val itemAdder = DependencyManager.itemsAdderCompatibility - if(itemAdder != null) { - count += itemAdder.idsCount().size - } - - return count - } - - fun getMaterials(): MutableList { - val all = ArrayList(Material.entries.map { it.key }) - if(DependencyManager.ecoEnchantCompatibility != null) { - all.addAll(EcoItemDependencyUtil.getItems()) - } - - val itemAdder = DependencyManager.itemsAdderCompatibility - if(itemAdder != null) { - all.addAll(itemAdder.idsCount().map { NamespacedKey.fromString(it) }) - } - - return all - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/MetricsUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/MetricsUtil.kt deleted file mode 100644 index 1763db5..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/MetricsUtil.kt +++ /dev/null @@ -1,97 +0,0 @@ -package xyz.alexcrea.cuanvil.util - -import dev.faststats.ErrorTracker -import dev.faststats.bukkit.BukkitContext -import dev.faststats.data.Metric -import io.delilaheve.CustomAnvil -import io.delilaheve.util.ConfigOptions -import xyz.alexcrea.cuanvil.command.DiagnosticExecutor -import xyz.alexcrea.cuanvil.config.ConfigHolder -import xyz.alexcrea.cuanvil.dependency.DependencyManager - -object MetricsUtil { - - private const val BSTATS_PLUGIN_ID = 20923 - private const val FASTSTATS_TOKEN = "fc282b048adcc71a77bc00ace49e8a81" - - private var ERROR_TRACKER: ErrorTracker? = null - private var FAST_STATS_METRICS: BukkitContext? = null - - fun loadMetrics(plugin: CustomAnvil) { - if(DependencyManager.externGuiTester.isInTest()) return - - val config = ConfigHolder.DEFAULT_CONFIG.config - val metricString = config.getString(ConfigOptions.METRIC_TYPE, MetricType.AUTO.value)!! - val metricType = MetricType.from(metricString) - - val nmsType = DiagnosticExecutor.fetchNMSType() - val isAlpha = CustomAnvil.instance.description.version.contains("dev") - if(metricType.allowBStats) { - try { - val metric = Metrics(plugin, BSTATS_PLUGIN_ID) - metric.addCustomChart(Metrics.SimplePie("nms_type") { nmsType }) - metric.addCustomChart(Metrics.SimplePie("using_alpha") { isAlpha.toString() }) - } catch (_: Exception) {} - } - - if(metricType.allowFastStats) { - // Check support java 17 (metric only work in java 17) - val versionParts = System.getProperty("java.version").split(".") - val majorVersion = versionParts[0].toInt() - if (majorVersion >= 17) try { - faststatTelemetry(plugin, nmsType, isAlpha) - } catch (_: Throwable) {} - } - } - - private fun faststatTelemetry(plugin: CustomAnvil, nmsType: String, isAlpha: Boolean) { - val config = ConfigHolder.DEFAULT_CONFIG.config - val reportErrors = config.getBoolean(ConfigOptions.METRIC_COLLECT_ERROR, true) - if(reportErrors) - ERROR_TRACKER = ErrorTracker.contextAware() - - FAST_STATS_METRICS = BukkitContext.Factory(plugin, FASTSTATS_TOKEN) - .metrics { factory -> factory - .addMetric(Metric.string("nms_type") { nmsType }) - .addMetric(Metric.bool("replace_too_expensive") { ConfigOptions.doReplaceTooExpensive }) - .addMetric(Metric.bool("using_alpha") { isAlpha }) - .create() - } - .errorTrackerService(ERROR_TRACKER) - .create() - - if(reportErrors) FAST_STATS_METRICS!!.ready() - } - - fun shutdownMetrics() { - FAST_STATS_METRICS?.shutdown() - } - - var lastError: Throwable? = null - - fun trackError(e: Throwable) { - ERROR_TRACKER?.trackError(e) - lastError = e - } - - fun trackError(message: String) { - ERROR_TRACKER?.trackError(message) - } -} - -enum class MetricType( - val value: String, - val allowBStats: Boolean, - val allowFastStats: Boolean, -) { - AUTO("auto", true, true), - BSTATS("bstat", true, false), - FAST_STATS("faststats", false, true), - DISABLED("disabled", false, false), - ; - - companion object { - fun from(value: String): MetricType = entries.find { it.value == value } ?: AUTO - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/MiniMessageUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/MiniMessageUtil.kt deleted file mode 100644 index c33cb9c..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/MiniMessageUtil.kt +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.alexcrea.cuanvil.util - -import net.kyori.adventure.text.TextComponent -import net.kyori.adventure.text.minimessage.MiniMessage -import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver -import net.kyori.adventure.text.minimessage.tag.standard.StandardTags -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer -import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer -import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil - -object MiniMessageUtil { - - val color_only_mm = MiniMessage.builder() - .tags( - TagResolver.resolver( - StandardTags.color(), - StandardTags.decorations() - ) - ) - .build() - - val mm = if (PlatformUtil.isPaper) MiniMessage.miniMessage() - else color_only_mm - - val legacy_mm = LegacyComponentSerializer.legacySection() - val plain_text_mm = PlainTextComponentSerializer.plainText() - - // Keeping track of this as most use of this can be replaced later on v2 with pure component alternative - fun fromLegacy(legacyText: String): TextComponent { - return legacy_mm.deserialize(legacyText) - } - -} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/NegativeSet.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/NegativeSet.kt deleted file mode 100644 index a94175b..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/NegativeSet.kt +++ /dev/null @@ -1,51 +0,0 @@ -package xyz.alexcrea.cuanvil.util - -open class NegativeSet(val negate: MutableSet = HashSet()) : MutableSet { - - override fun iterator(): MutableIterator { - TODO("Not yet implemented") // can't be implemented I guess - } - - override fun add(element: T): Boolean { - return negate.remove(element) - } - - override fun remove(element: T): Boolean { - return negate.add(element) - } - - override fun addAll(elements: Collection): Boolean { - return negate.removeAll(elements.toSet()) - } - - override fun removeAll(elements: Collection): Boolean { - return negate.addAll(elements) - } - - override fun retainAll(elements: Collection): Boolean { - TODO("Not yet implemented") - } - - override fun clear() { - TODO("Not yet implemented") - } - - override fun isEmpty(): Boolean { - TODO("Not yet implemented") - } - - override val size: Int get() = TODO("Not yet implemented") - - override fun contains(element: T): Boolean { - return !negate.contains(element) - } - - override fun containsAll(elements: Collection): Boolean { - for (elm in elements) { - if(negate.contains(elm)) return false - } - - return true - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/UnitRepairUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/UnitRepairUtil.kt deleted file mode 100644 index 8463e27..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/UnitRepairUtil.kt +++ /dev/null @@ -1,61 +0,0 @@ -package xyz.alexcrea.cuanvil.util - -import org.bukkit.configuration.ConfigurationSection -import org.bukkit.inventory.ItemStack -import xyz.alexcrea.cuanvil.config.ConfigHolder -import xyz.alexcrea.cuanvil.util.MaterialUtil.customType - -object UnitRepairUtil { - - // Default value for user set default unit repair % - private const val DEFAULT_DEFAULT_UNIT_REPAIR = 0.25 - - // Path to user default unit repair value - private const val UNIT_REPAIR_DEFAULT_PATH = "default_repair_amount" - - /** - * Get the % of repair by unit [other] will do to this [ItemStack]. - * null if can't unit repaired by [other] - */ - fun ItemStack.getRepair( - other: ItemStack? - ): Double? { - if (other == null) return null - val config = ConfigHolder.UNIT_REPAIR_HOLDER.config - // Get configuration section if exist - val otherName = other.customType.key.lowercase() - var section = config.getConfigurationSection(otherName) - if (section == null) { - section = config.getConfigurationSection(otherName.uppercase()) - if (section == null) return null - - } - // Get repair amount - var userDefault = config.getDouble(UNIT_REPAIR_DEFAULT_PATH, DEFAULT_DEFAULT_UNIT_REPAIR) - if (userDefault <= 0) { - userDefault = DEFAULT_DEFAULT_UNIT_REPAIR - } - - return getRepairAmount(this, section, userDefault) - } - - /** - * Get the item % repaired by this configuration section of a unit repair. - * null if not found. - * If value is set to less than or equal to 0 then it will be set to default - */ - private fun getRepairAmount(item: ItemStack, section: ConfigurationSection, default: Double): Double? { - val itemName = item.customType.key.lowercase() - val repairValue = if (section.isDouble(itemName)) { - section.getDouble(itemName) - } else if (section.isDouble(itemName.uppercase())) { - section.getDouble(itemName.uppercase()) - } else { - return null - } - if (repairValue <= 0) - return default - return repairValue - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilColorUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilColorUtil.kt deleted file mode 100644 index 9564b2e..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilColorUtil.kt +++ /dev/null @@ -1,306 +0,0 @@ -package xyz.alexcrea.cuanvil.util.anvil - -import io.delilaheve.util.ConfigOptions -import net.kyori.adventure.text.Component -import org.bukkit.permissions.Permissible -import xyz.alexcrea.cuanvil.util.MiniMessageUtil -import java.util.regex.Matcher -import java.util.regex.Pattern - -object AnvilColorUtil { - private val HEX_PATTERN: Pattern = Pattern.compile("#[A-Fa-f0-9]{6}") // pattern to find hexadecimal string - private val TRANSFORMED_HEX_PATTERN = Pattern.compile("§x(§[0-9a-fA-F]){6}") // pattern to find minecraft hex string - - class ColorPermissions( - val canUseColorCode: Boolean, - val canUseHexColor: Boolean, - val canUseMinimessage: Boolean, - val permissible: Permissible, // source of the permission. tried to avoid needing it but meh - ) { - fun allowed(): Boolean { - return canUseColorCode || canUseHexColor || canUseMinimessage - } - - fun onlyMinimessage(): Boolean { - return canUseMinimessage && !canUseColorCode && !canUseHexColor - } - } - - fun calculatePermissions( - player: Permissible, - usePermission: Boolean, - allowColorCode: Boolean, - allowHexadecimalColor: Boolean, - allowMinimessage: Boolean, - useType: ColorUseType - ): ColorPermissions { - if (!allowColorCode && !allowHexadecimalColor && !allowMinimessage) - return ColorPermissions( - canUseColorCode = false, - canUseHexColor = false, - canUseMinimessage = false, - player, - ) - - val canUseColorCode = - allowColorCode && (!usePermission || useType.colorCodePerm == null || player.hasPermission( - useType.colorCodePerm - )) - - val canUseMinimessage = - allowMinimessage && (!usePermission || useType.minimessagePerm == null || player.hasPermission( - useType.minimessagePerm - )) - - val canUseHexColor = - allowHexadecimalColor && (!usePermission || useType.hexColorPerm == null || player.hasPermission( - useType.hexColorPerm - )) - - return ColorPermissions(canUseColorCode, canUseHexColor, canUseMinimessage, player) - } - - fun renamePermission(player: Permissible): ColorPermissions { - return calculatePermissions(player, - ConfigOptions.permissionNeededForColor, - ConfigOptions.allowColorCode, ConfigOptions.allowHexadecimalColor, ConfigOptions.allowMinimessage, - ColorUseType.RENAME) - } - - /** - * Color a string depending on permitted use - * @return colored component or null if nothing has been colored - */ - fun handleColor( - textToColorText: String, - permission: ColorPermissions, - - ): Component? { - if (!permission.allowed()) return null - - val textToColor = StringBuilder(textToColorText) - var useColor = false - // Handle color code - if (permission.canUseColorCode) { // maybe should use LegacyComponentSerializer ? - var nbReplacement = replaceAll(textToColor, "&", "§", 2) - nbReplacement -= 2 * replaceAll(textToColor, "§§", "&", 2) - - if (nbReplacement > 0) { - useColor = true - - if (ConfigOptions.usePerColorCodePermission) - filterPermissibleColorCode(textToColor, permission.permissible) - } - } - - if (permission.canUseHexColor) { - val nbReplacement = replaceHexToColor(textToColor, 7, permission.canUseMinimessage) - - if (nbReplacement > 0) useColor = true - } - - val previousStr = textToColor.toString() - var result: Component = MiniMessageUtil.legacy_mm.deserialize(previousStr) - if (permission.canUseMinimessage) { - // we dance with formats here - val toMinimessage = MiniMessageUtil.mm.serialize(result) - val hackySolution = toMinimessage.replace("\\<", "<") - val fromMinimessage = MiniMessageUtil.mm.deserialize(hackySolution) - val asPlain = MiniMessageUtil.plain_text_mm.serialize(fromMinimessage) - - if (previousStr != asPlain) { - useColor = true - result = fromMinimessage - } - } - - return if (useColor) result - else null - } - - private fun filterPermissibleColorCode(textToColor: StringBuilder, player: Permissible) { - var index = 0 - while (true) { - index = textToColor.indexOf('§', index) - if (index == -1 || index == textToColor.length - 1) return - - val next = textToColor[index + 1] - // check permission for this color - if(!player.hasPermission("ca.color.code.$next")) - textToColor.replace(index, index + 1, "&") - - index++ - } - } - - /** - * Best effort to revert a component to the smallest allowed string - * that would result in it getting closest as possible to handleColor - * with current set of permitted use - * @return a new component if had any change. null otherwise - */ - fun revertColorSmallest( - component: Component?, - permission: ColorPermissions - ): String? { - if (!permission.allowed() || component == null) return null - - val transformed = MiniMessageUtil.mm.serialize(component) - val plainTransform = MiniMessageUtil.plain_text_mm.serialize(component) - if (transformed == plainTransform) return null - if (permission.onlyMinimessage()) { - return transformed - } - - // smol dance so we transform the component that may contain other tag into only decoration & color for legacy - val coloredMessage = MiniMessageUtil.color_only_mm.deserialize(transformed) - val legacyMessage = StringBuilder(MiniMessageUtil.legacy_mm.serialize(coloredMessage)) - - // Reverse hex pattern - if (permission.canUseHexColor) { - replaceColorToHex(legacyMessage, 14) - } - - // Reverse color pattern - if (permission.canUseColorCode) { - replaceAll(legacyMessage, "&", "&&", 1) - replaceAll(legacyMessage, "§", "&", 2) - } - - // In case we still has some § around by lack of permission we need to convert it back from legacy - // In other word it's time for dance #3 - val fromLegacy = MiniMessageUtil.legacy_mm.deserialize(legacyMessage.toString()) - val middleGround = MiniMessageUtil.mm.serialize(fromLegacy) - val hackySolutionStb = StringBuilder(middleGround) - replaceAll(hackySolutionStb, "\\<", "<", 2) - val hackySolution = hackySolutionStb.toString() - - val result: String = - if (permission.canUseMinimessage) hackySolution - else MiniMessageUtil.mm.stripTags(hackySolution) - - return if (result == plainTransform) null - else result - } - - /** - * Replace every instance of "from" to "to". - * @param builder The builder to replace the string from. - * @param from The source that should be replaced. - * @param to The string that should replace. - * @param endOffset Amount of character that should be ignored at the end. - * @return The number of replacement was that was done. - */ - private fun replaceAll(builder: java.lang.StringBuilder, from: String, to: String, endOffset: Int): Int { - var index = builder.indexOf(from) - var numberOfChanges = 0 - - while (index != -1 && index < builder.length - endOffset) { - builder.replace(index, index + from.length, to) - index += to.length - index = builder.indexOf(from, index) - - numberOfChanges += 1 - } - - return numberOfChanges - } - - /** - * Replace every hex color formatted like #000000 to the minecraft format - * @param builder The builder to replace the hex color from. - * @param endOffset Amount of character that should be ignored at the end. - * @return The number of replacement was that was done. - */ - private fun replaceHexToColor(builder: StringBuilder, endOffset: Int, checkTag: Boolean): Int { - val matcher: Matcher = HEX_PATTERN.matcher(builder) - - var numberOfChanges = 0 - var startIndex = 0 - - while (matcher.find(startIndex)) { - startIndex = matcher.start() - if (startIndex >= builder.length - endOffset) break //HOW AND WHERE WOULD THIS HAPPEN ????? - if (checkTag && isInTag(builder, startIndex)) { - startIndex += 1 // Avoid infinite loop - continue - } - - builder.replace(startIndex, startIndex + 1, "§x") - startIndex += 2 - for (i in 0..5) { - builder.insert(startIndex, '§') - startIndex += 2 - } - - numberOfChanges += 1 - } - - return numberOfChanges - } - - // Simple check if < > with some smart check like <> > not taken into account - // This is easily bypassable but if the player want to bypass he has better alternative - // AKA should avoid getting into any tag - private fun isInTag(builder: StringBuilder, index: Int): Boolean { - // Check left tag we have < after last > - val left = builder.slice(0..index) - val leftIndex = left.lastIndexOf("<") - var rightIndex = left.lastIndexOf(">") - - // last < do not exist or is before last > - if (leftIndex == -1 || rightIndex > leftIndex) return false - - val right = builder.slice(index..") - - // first > do not exist or is after first < (if exist) - if (rightIndex == -1 || (newleftIndex != -1 && newleftIndex < rightIndex)) return false - - // Then finally we use minimessage to check for tag - val expectedTag = builder.substring(leftIndex, newleftIndex + index + 1) - val notag = MiniMessageUtil.mm.stripTags(expectedTag) - - return notag != expectedTag - } - - /** - * Replace every hex color from the minecraft format to a format like #000000 - * @param builder The builder to replace the minecraft hex color from. - * @param endOffset Amount of character that should be ignored at the end. - * @return The number of replacement was that was done. - */ - private fun replaceColorToHex(builder: StringBuilder, endOffset: Int): Int { - val matcher: Matcher = TRANSFORMED_HEX_PATTERN.matcher(builder) - - var numberOfChanges = 0 - var startIndex = 0 - - while (matcher.find(startIndex)) { - startIndex = matcher.start() - if (startIndex >= builder.length - endOffset) break //HOW AND WHERE WOULD THIS HAPPEN ????? - - builder.replace(startIndex, startIndex + 2, "#") - startIndex += 1 - for (i in 0..5) { - builder.deleteCharAt(startIndex) - startIndex += 1 - } - - numberOfChanges += 1 - } - - return numberOfChanges - } - - enum class ColorUseType( - val colorCodePerm: String?, - val hexColorPerm: String?, - val minimessagePerm: String? - ) { - RENAME("ca.color.code", "ca.color.hex", "ca.rename.minimessage"), - LORE_EDIT(null, null, null) - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilLoreEditUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilLoreEditUtil.kt deleted file mode 100644 index a021b46..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilLoreEditUtil.kt +++ /dev/null @@ -1,368 +0,0 @@ -package xyz.alexcrea.cuanvil.util.anvil - -import net.kyori.adventure.text.Component -import org.bukkit.entity.HumanEntity -import org.bukkit.inventory.ItemStack -import org.bukkit.inventory.meta.BookMeta -import org.bukkit.permissions.Permissible -import xyz.alexcrea.cuanvil.anvil.AnvilCost -import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic.LoreEditResult -import xyz.alexcrea.cuanvil.dependency.DependencyManager -import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.componentLore -import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.setComponentLore -import xyz.alexcrea.cuanvil.util.MiniMessageUtil -import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil -import xyz.alexcrea.cuanvil.util.config.LoreEditType -import java.util.* -import java.util.concurrent.atomic.AtomicReference - -object AnvilLoreEditUtil { - - private const val LORE_BY_BOOK: String = "ca.lore_edit.book" - private const val LORE_BY_PAPER: String = "ca.lore_edit.paper" - - private fun hasLoreEditByBookPermission(player: Permissible): Boolean { - return !LoreEditConfigUtil.bookLoreEditNeedPermission || player.hasPermission(LORE_BY_BOOK) - } - - private fun hasLoreEditByPaperPermission(player: Permissible): Boolean { - return !LoreEditConfigUtil.paperLoreEditNeedPermission || player.hasPermission(LORE_BY_PAPER) - } - - fun handleLoreAppendByBook( - player: Permissible, - first: ItemStack, - book: BookMeta, - cost: AnvilCost - ): ItemStack? { - if (!hasLoreEditByBookPermission(player)) return null - - val result = first.clone() - val meta = result.itemMeta ?: return null - val lore = meta.componentLore() - - val page = book.pages[0] - val lines = ArrayList(page.split("\n")) - val outLines = ArrayList(lines.size) - val colorCost = colorLines( - player, LoreEditType.APPEND_BOOK, - lines, outLines - ) - - lore.addAll(outLines) - - meta.setComponentLore(lore) - result.itemMeta = meta - - if (result == first) return null - - // Handle xp - cost.lore = colorCost // Cost of using color - cost.lore += outLines.size * LoreEditType.APPEND_BOOK.perLineCost // per line cost - baseEditLoreXpCost(cost, first, result, LoreEditType.APPEND_BOOK) // Fixed cost and work penalty - - return result - } - - fun handleLoreRemoveByBook(player: Permissible, first: ItemStack, cost: AnvilCost): ItemStack? { - if (!hasLoreEditByBookPermission(player)) return null - - // remove lore - val result = first.clone() - val leftMeta = result.itemMeta ?: return null - val currentLore = DependencyManager.stripLore(result) - if (currentLore.isEmpty()) return null - - val uncolorCost = uncolorLines(player, currentLore, LoreEditType.REMOVE_BOOK) - - leftMeta.lore = null - result.itemMeta = leftMeta - - DependencyManager.updateLore(result) - if (result == first) return null - - // Handle xp - cost.lore = uncolorCost - cost.lore += currentLore.size * LoreEditType.REMOVE_BOOK.perLineCost - baseEditLoreXpCost(cost, first, result, LoreEditType.REMOVE_BOOK) - - return result - } - - // Return true if appended, false if removed, null if neither - fun bookLoreEditIsAppend(first: ItemStack, second: ItemStack): Boolean? { - // Test if the book & quil contain content - val meta = second.itemMeta as BookMeta? ?: return false - - var hasContent = false - if (meta.hasPages() && meta.pageCount >= 1) { - // Test if the pages is ok - for (page in meta.pages) { - if (page.isNotBlank()) { - hasContent = true - break - } - } - } - - // We don't want to "add" the first page is there is content and the first page is empty - if (hasContent) { - if (meta.pages[0].isEmpty()) return null - if (LoreEditType.APPEND_BOOK.enabled) - return true - } else if (LoreEditType.REMOVE_BOOK.enabled) { - if (!first.hasItemMeta()) return null - - val leftMeta = first.itemMeta!! - return if (leftMeta.hasLore()) false - else null - } - return null - } - - fun tryLoreEditByBook(player: HumanEntity, first: ItemStack, second: ItemStack): LoreEditResult { - val isAppend = bookLoreEditIsAppend(first, second) ?: return LoreEditResult.EMPTY - val type = if (isAppend) LoreEditType.APPEND_BOOK else LoreEditType.REMOVE_BOOK - - val meta = second.itemMeta as BookMeta - val cost = AnvilCost() - val item = if (isAppend) - handleLoreAppendByBook(player, first, meta, cost) - else handleLoreRemoveByBook(player, first, cost) - - return LoreEditResult(item, cost, type) - } - - // Return true if appended, false if removed, null if neither - fun paperLoreEditIsAppend(first: ItemStack, second: ItemStack): Boolean? { - // Test if the paper contain a display name - val meta = second.itemMeta ?: return false - - val hasContent = meta.hasDisplayName() - if (hasContent) { - if (LoreEditType.APPEND_PAPER.enabled) - return true - } else if (LoreEditType.REMOVE_PAPER.enabled) { - if (!first.hasItemMeta()) return null - - val leftMeta = first.itemMeta!! - return if (leftMeta.hasLore() && leftMeta.lore!!.isNotEmpty()) false - else null - } - return null - } - - fun handleLoreAppendByPaper( - player: Permissible, - first: ItemStack, - second: ItemStack, - cost: AnvilCost - ): ItemStack? { - if (!hasLoreEditByPaperPermission(player)) return null - - val result = first.clone() - val meta = result.itemMeta ?: return null - val lore = meta.componentLore() - - val appendEnd = LoreEditConfigUtil.paperLoreOrderIsEnd - - // A bit overdone to color 1 line but hey - val outList = ArrayList(1) - val colorCost = colorLines( - player, LoreEditType.APPEND_PAPER, - Collections.singletonList(second.itemMeta!!.displayName), - outList - ) - - val line = outList[0] - if (appendEnd) - lore.add(line) - else - lore.add(0, line) - - meta.setComponentLore(lore) - result.itemMeta = meta - - if (result == first) return null - - // Handle xp - cost.lore = colorCost - baseEditLoreXpCost(cost, first, result, LoreEditType.APPEND_PAPER) - - return result - } - - fun handleLoreRemoveByPaper(player: Permissible, first: ItemStack, cost: AnvilCost): ItemStack? { - if (!hasLoreEditByPaperPermission(player)) return null - - // remove lore line - val result = first.clone() - val meta = result.itemMeta!! - - val removeEnd = LoreEditConfigUtil.paperLoreOrderIsEnd - val lore = DependencyManager.stripLore(result) - if (lore.isEmpty()) return null - - val line = if (removeEnd) lore.removeAt(lore.size - 1) - else lore.removeAt(0) - - meta.lore = null - result.itemMeta = meta - - // Update lore but make sure custom lore is put last - DependencyManager.updateLore(result) - - val finalLore = ArrayList() - finalLore.addAll(meta.componentLore()) - finalLore.addAll(lore) - - meta.setComponentLore(finalLore) - result.itemMeta = meta - if (result == first) return null - - // Get color cost to uncolor this line - val uncolorCost = uncolorLine(player, line, LoreEditType.REMOVE_PAPER) - - // Handle other xp - cost.lore = uncolorCost - baseEditLoreXpCost(cost, first, result, LoreEditType.REMOVE_PAPER) - - return result - } - - fun tryLoreEditByPaper( - player: HumanEntity, - first: ItemStack, - second: ItemStack - ): LoreEditResult { - val isAppend = paperLoreEditIsAppend(first, second) ?: return LoreEditResult.EMPTY - val type = if (isAppend) LoreEditType.APPEND_BOOK else LoreEditType.REMOVE_BOOK - - val cost = AnvilCost() - val item = if (isAppend) - handleLoreAppendByPaper(player, first, second, cost) - else handleLoreRemoveByPaper(player, first, cost) - - return LoreEditResult(item, cost, type) - } - - private fun baseEditLoreXpCost( - cost: AnvilCost, - first: ItemStack, - result: ItemStack, - editType: LoreEditType - ) { - cost.lore += editType.fixedCost - - cost.workPenalty = AnvilXpUtil.calculatePenalty(first, null, result, editType.useType) - } - - fun colorPermission(player: Permissible, editType: LoreEditType): AnvilColorUtil.ColorPermissions { - return AnvilColorUtil.calculatePermissions( - player, - false, - editType.allowColorCode, - editType.allowHexColor, - editType.allowMinimessage, - AnvilColorUtil.ColorUseType.LORE_EDIT - ) - } - - private fun colorLine(line: String, permission: AnvilColorUtil.ColorPermissions): Component? { - return AnvilColorUtil.handleColor( - line, - permission - ) - } - - private fun colorLines( - player: Permissible, editType: LoreEditType, - lines: List, outLines: MutableList - ): Int { - val permission = colorPermission(player, editType) - val colorCost = editType.useColorCost - - // Handle color and minimessage of each lines - var hasUsedColor = false - for (line in lines) { - val component = colorLine(line, permission) - - if (component != null) { - hasUsedColor = true - outLines.add(component) - } else { - outLines.add(Component.text(line)) - } - } - - return if (hasUsedColor) colorCost - else 0 - } - - fun uncolorLines(player: Permissible, lines: MutableList, editType: LoreEditType): Int { - val permission = colorPermission(player, editType) - - // Now handle color of each lines - var hasUndidColor = false - for ((index, line) in lines.withIndex()) { - if (line == null) { - lines[index] = null - continue - } - - val clearedLine = AnvilColorUtil.revertColorSmallest( - line, - permission - ) - - val result: String - if (clearedLine != null) { - hasUndidColor = true - result = clearedLine - } else { - result = MiniMessageUtil.plain_text_mm.serialize(line) - } - - lines[index] = MiniMessageUtil.plain_text_mm.deserialize(result) - } - - return if (hasUndidColor) { - editType.removeColorCost - } else { - 0 - } - } - - // do not output the uncolored line... - fun uncolorLine(player: Permissible, line: Component?, editType: LoreEditType): Int { - return uncolorLine(player, AtomicReference(line), editType) - } - - fun uncolorLine(player: Permissible, line: AtomicReference, editType: LoreEditType): Int { - val coloredComponent = line.get() ?: return 0 - val permission = colorPermission(player, editType) - - val clearedLine = AnvilColorUtil.revertColorSmallest( - coloredComponent, - permission - ) - - var hasUndidColor = false - val result: String - if (clearedLine != null) { - hasUndidColor = true - result = clearedLine - } else { - // Remove extra tags - result = MiniMessageUtil.plain_text_mm.serialize(coloredComponent) - } - line.set(MiniMessageUtil.plain_text_mm.deserialize(result)) - - return if (hasUndidColor) { - editType.removeColorCost - } else { - 0 - } - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilUseTypeUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilUseTypeUtil.kt deleted file mode 100644 index a9c7f39..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilUseTypeUtil.kt +++ /dev/null @@ -1,26 +0,0 @@ -package xyz.alexcrea.cuanvil.util.anvil - -import io.delilaheve.util.ConfigOptions - -object AnvilUseTypeUtil { - - /* - By stupidity of kotlin not allowing static function outside of companion object I need to do another util class only for 1 function: - Companion object on enum class seems to get initialized AFTER the enum itself - that mean. if you want to call a static function on the enum class itself YOU CAN'T. you need to do this stupid thing - or you can make a stupid top level function OR object that even worse because of global scope pollution - (btw was gpt ""solution"". fortunately I do not "vibe code" so I do what I know instead of stupid AI solution & code) - I mean, this is still global scope pollution bc of a USELESS class that SHOULD not exist but as a class is better than a random *ss function - - sorry for the rent but this made me frustrated - - Note: I still like a lot of part of kotlin compared to java but this part is one that I hate - */ - /** - * Get config path for normal anvil use - */ - fun defaultPath(typeName: String): String { - return "${ConfigOptions.WORK_PENALTY_ROOT}.$typeName" - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilXpUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilXpUtil.kt deleted file mode 100644 index 4846f31..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilXpUtil.kt +++ /dev/null @@ -1,308 +0,0 @@ -package xyz.alexcrea.cuanvil.util.anvil - -import io.delilaheve.CustomAnvil -import io.delilaheve.util.ConfigOptions -import io.delilaheve.util.EnchantmentUtil.enchantmentName -import io.delilaheve.util.ItemUtil.findEnchantments -import io.delilaheve.util.ItemUtil.isEnchantedBook -import org.bukkit.GameMode -import org.bukkit.NamespacedKey -import org.bukkit.entity.HumanEntity -import org.bukkit.entity.Player -import org.bukkit.inventory.AnvilInventory -import org.bukkit.inventory.InventoryView -import org.bukkit.inventory.ItemStack -import org.bukkit.inventory.meta.Repairable -import org.bukkit.persistence.PersistentDataType -import xyz.alexcrea.cuanvil.anvil.AnvilCost -import xyz.alexcrea.cuanvil.anvil.AnvilUseType -import xyz.alexcrea.cuanvil.config.ConfigHolder -import xyz.alexcrea.cuanvil.dependency.DependencyManager -import xyz.alexcrea.cuanvil.dependency.economy.EconomyManager -import xyz.alexcrea.cuanvil.group.ConflictType -import xyz.alexcrea.cuanvil.util.AnvilTitleUtil -import xyz.alexcrea.cuanvil.util.dialog.AnvilRenameDialogUtil - -object AnvilXpUtil { - - const val EXCLUSIVE_PENALTY_PREFIX = "repair_cost" - - /** - * Display the required cost (either as xp or as ) - */ - fun setAnvilInvCost( - inventory: AnvilInventory, - view: InventoryView, - player: Player, - cost: AnvilCost, - ignoreRules: Boolean = false - ) { - if (ConfigOptions.shouldUseMoney(player)) { - cost.isMonetary = true - setAnvilPrice(inventory, view, player, cost) - } else - setAnvilInvXp(inventory, view, player, cost.filteredXpCost(ignoreRules), ignoreRules) - } - - fun maximumXpCost(ignoreRules: Boolean = false): Int { - return if (ConfigOptions.doRemoveCostLimit || ignoreRules) { - Int.MAX_VALUE - } else { - ConfigOptions.maxAnvilCost + 1 - } - } - - /** - * Display xp needed for the work on the anvil inventory - */ - private fun setAnvilInvXp( - inventory: AnvilInventory, - view: InventoryView, - player: HumanEntity, - anvilCost: Int, - ignoreRules: Boolean = false - ) { - val maximumRepairCost = maximumXpCost(ignoreRules) - - // Try first just in case another plugin, or the test need this - inventory.maximumRepairCost = maximumRepairCost - inventory.repairCost = anvilCost - // TODO for 2.x.x use anvil view & set directly there - - /* Because Minecraft likes to have the final say in the repair cost displayed - * we need to wait for the event to end before overriding it, this ensures that - * we have the final say in the process. */ - DependencyManager.scheduler.scheduleOnEntity( - CustomAnvil.instance, player - ) { - // retry after a tick - inventory.maximumRepairCost = maximumRepairCost - inventory.repairCost = anvilCost - // TODO for 2.x.x use anvil view & set directly there - - if (player !is Player) return@scheduleOnEntity - - if (player.gameMode != GameMode.CREATIVE) { - val bypassToExpensive = (ConfigOptions.doReplaceTooExpensive) && - (anvilCost >= 40) && - anvilCost < inventory.maximumRepairCost - - DependencyManager.packetManager.setInstantBuild(player, bypassToExpensive) - } - - player.updateInventory() - } - } - - /** - * Display monetary cost needed for the work on the anvil inventory - */ - private fun setAnvilPrice( - inventory: AnvilInventory, - view: InventoryView, - player: Player, - cost: AnvilCost, - ) { - val finalCost = cost.asMonetaryCost() - - val has = player.gameMode == GameMode.CREATIVE || - EconomyManager.economy!!.has(player, finalCost) - - val text = "Cost: " + (if (has) "§2" else "§4") + - EconomyManager.economy!!.format(finalCost) - AnvilTitleUtil.rename( - view, text, - player, - AnvilRenameDialogUtil.anvilRenameDialog, - CustomAnvil.instance - ) - - clearAnvilXpCost(inventory, view, player) - } - - private fun clearAnvilXpCost( - inventory: AnvilInventory, - view: InventoryView, - player: HumanEntity, - ) { - // TODO for 2.x.x use anvil view & set directly there - inventory.repairCost = 0 - - // retry after a tick - DependencyManager.scheduler.scheduleOnEntity( - CustomAnvil.instance, player - ) { - inventory.repairCost = 0 - - if (player !is Player) return@scheduleOnEntity - player.updateInventory() - } - } - - /** - * Function to calculate work penalty of anvil work - * Also change result work penalty if right item is not null - */ - fun calculatePenalty(left: ItemStack, right: ItemStack?, result: ItemStack, useType: AnvilUseType): Int { - // Extracted From https://minecraft.wiki/w/Anvil_mechanics#Enchantment_equation - // Calculate work penalty - val penaltyType = ConfigOptions.workPenaltyPart(useType) - val leftPenalty = (left.itemMeta as? Repairable)?.repairCost ?: 0 - val leftExclusivePenalty = findExclusivePenalty(left, useType) - - val rightPenalty = - if (right == null) 0 - else (right.itemMeta as? Repairable)?.repairCost ?: 0 - val rightExclusivePenalty = findExclusivePenalty(right, useType) - - // Increase penalty on fusing or unit repair - if (penaltyType.penaltyIncrease) { - result.itemMeta?.let { - (it as? Repairable)?.repairCost = leftPenalty.coerceAtLeast(rightPenalty) * 2 + 1 - result.itemMeta = it - } - } - if (penaltyType.exclusivePenaltyIncrease) { - val resultPenalty = leftExclusivePenalty.coerceAtLeast(rightExclusivePenalty) * 2 + 1 - setExclusivePenalty(result, resultPenalty, useType) - } - - CustomAnvil.log( - "Calculated penalty: " + - "leftPenalty: $leftPenalty, " + - "rightPenalty: $rightPenalty, " + - "result penalty: ${(result.itemMeta as? Repairable)?.repairCost ?: "none"}" - ) - - var resultSum = 0 - if (penaltyType.penaltyAdditive) { - resultSum += leftPenalty + rightPenalty - } - if (penaltyType.exclusivePenaltyAdditive) { - resultSum += leftExclusivePenalty + rightExclusivePenalty - } - - return resultSum - } - - fun onNoResult(player: HumanEntity, view: InventoryView) { - if (ConfigOptions.shouldUseMoney(player)) - AnvilTitleUtil.rename( - view, "Repair & Name", - player, - AnvilRenameDialogUtil.anvilRenameDialog, - CustomAnvil.instance - ) - } - - private fun exclusivePenaltyKey(useType: AnvilUseType): NamespacedKey { - return NamespacedKey(CustomAnvil.instance, "${EXCLUSIVE_PENALTY_PREFIX}_${useType.typeName}") - } - - private fun setExclusivePenalty( - result: ItemStack, - resultPenalty: Int, - useType: AnvilUseType - ) { - val key = exclusivePenaltyKey(useType) - - val meta = result.itemMeta!! - meta.persistentDataContainer.set(key, PersistentDataType.INTEGER, resultPenalty) - result.itemMeta = meta - } - - private fun findExclusivePenalty( - item: ItemStack?, - useType: AnvilUseType - ): Int { - if (item == null || !item.hasItemMeta()) return 0 - val key = exclusivePenaltyKey(useType) - - val meta = item.itemMeta!! - return meta.persistentDataContainer.get(key, PersistentDataType.INTEGER) ?: return 0 - } - - /** - * Function to calculate right enchantment values - * it include enchantment placed on final item and conflicting enchantment - */ - fun getRightValues(right: ItemStack, result: ItemStack, cost: AnvilCost) { - // Calculate right value and illegal enchant penalty - - val rightIsFormBook = right.isEnchantedBook() - val resultEnchs = result.findEnchantments() - val resultEnchsKeys = HashMap(resultEnchs) - - for (enchantment in right.findEnchantments()) { - // count enchant as illegal enchant if it conflicts with another enchant or not in result - if ((enchantment.key !in resultEnchsKeys)) { - resultEnchsKeys[enchantment.key] = enchantment.value - val conflictType = ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting( - resultEnchsKeys, - result, - enchantment.key - ) - resultEnchsKeys.remove(enchantment.key) - - if (ConflictType.ENCHANTMENT_CONFLICT == conflictType) { - cost.illegalPenalty += ConfigOptions.sacrificeIllegalCost - CustomAnvil.verboseLog("Big conflict. Adding illegal price penalty") - } - continue - } - // We know "enchantment.key in resultEnchs" true - val resultLevel = resultEnchs[enchantment.key]!! - - val enchantmentMultiplier = ConfigOptions.enchantmentValue(enchantment.key, rightIsFormBook) - val value = resultLevel * enchantmentMultiplier - CustomAnvil.log("Value for ${enchantment.key.enchantmentName} level ${enchantment.value} is $value ($resultLevel * $enchantmentMultiplier)") - cost.enchantment += value - - } - CustomAnvil.log( - "Calculated right values: " + - "rightValue: ${cost.enchantment}, " + - "illegalPenalty: ${cost.illegalPenalty}" - ) - } - - /** - * Calculate the maximum level reachable with this amount of `xp` - * This is equivalent of the displayed level on client - * @author provided by kFor - */ - fun calculateLevelForXp(xp: Int): Int { - return when { - xp <= 352 -> (Math.sqrt((xp + 9).toDouble()) - 3).toInt() - xp <= 1507 -> { - val inner = (2.0 / 5.0) * (xp - 7839.0 / 40.0) - (81.0 / 10.0 + Math.sqrt(inner)).toInt() - } - - else -> { - val inner = (2.0 / 9.0) * (xp - 54215.0 / 72.0) - (325.0 / 18.0 + Math.sqrt(inner)).toInt() - } - } - } - - /** - * Calculate the minimum level necessary to have at least `xp` - */ - fun calculateMinimumLevelForXp(xp: Int): Int { - return calculateLevelForXp(xp - 1) + 1 - } - - /** - * Calculate the minimum amount of xp necessary to reach `level` - * @author provided by kFor - */ - fun calculateXpForLevel(level: Int): Int { - return when { - level <= 16 -> (level * level + 6 * level) - level <= 31 -> (2.5 * level * level - 40.5 * level + 360).toInt() - else -> (4.5 * level * level - 162.5 * level + 2220).toInt() - } - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditConfigUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditConfigUtil.kt deleted file mode 100644 index 9d0eb6a..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditConfigUtil.kt +++ /dev/null @@ -1,103 +0,0 @@ -package xyz.alexcrea.cuanvil.util.config - -import xyz.alexcrea.cuanvil.config.ConfigHolder.DEFAULT_CONFIG as CONFIG - -object LoreEditConfigUtil { - - // Per edit type configs Path - const val IS_ENABLED = "enabled" - const val FIXED_COST = "fixed_cost" - const val PER_LINE_COST = "per_line_cost" - const val DO_CONSUME = "do_consume" - - // Permission configs path - const val BOOK_PERMISSION_NEEDED = "lore_edit.book_and_quil.use_permission" - const val PAPER_PERMISSION_NEEDED = "lore_edit.paper.use_permission" - - // Color configs path - const val ALLOW_COLOR_CODE = "allow_color_code" - const val ALLOW_HEX_COLOR = "allow_hexadecimal_color" - const val ALLOW_MINIMESSAGE = "allow_minimessage" - const val USE_COLOR_COST = "use_cost" - - const val REMOVE_COLOR_COST = "remove_color_cost" - - // Lore order config path - const val PAPER_EDIT_ORDER = "lore_edit.paper.order" - - // -------------- - // Default Values - // -------------- - - // Per edit type configs defaults - const val DEFAULT_IS_ENABLED = false - const val DEFAULT_FIXED_COST = 1 - const val DEFAULT_PER_LINE_COST = 0 - const val DEFAULT_DO_CONSUME = false - - // Permission configs defaults - const val DEFAULT_BOOK_PERMISSION_NEEDED = true - const val DEFAULT_PAPER_PERMISSION_NEEDED = true - - // Color configs defaults - const val DEFAULT_ALLOW_COLOR_CODE = true - const val DEFAULT_ALLOW_HEX_COLOR = true - const val DEFAULT_ALLOW_MINIMESSAGE = true - const val DEFAULT_USE_COLOR_COST = 0 - - const val DEFAULT_REMOVE_COLOR_COST = 0 - - // Lore order config default - const val DEFAULT_PAPER_EDIT_ORDER = "end" - - // ------------- - // Config Ranges - // ------------- - - val FIXED_COST_RANGE = 0..1000 - val PER_LINE_COST_RANGE = 0..1000 - - val USE_COLOR_COST_RANGE = 0..1000 - val REMOVE_COLOR_COST_RANGE = 0..1000 - - // ------------------- - // Generic Get methods - // ------------------- - - /** - * Get if we should append/remove at the end or at the start of the lore list - * This may change to an "OrderType" enum or equivalent later - */ - val paperLoreOrderIsEnd: Boolean - get() { - return CONFIG - .config - .getString(PAPER_EDIT_ORDER, DEFAULT_PAPER_EDIT_ORDER) - .equals(DEFAULT_PAPER_EDIT_ORDER, ignoreCase = true) - } - - /** - * If lore edit via book need permission - */ - val bookLoreEditNeedPermission: Boolean - get() { - return CONFIG - .config - .getBoolean(BOOK_PERMISSION_NEEDED, DEFAULT_BOOK_PERMISSION_NEEDED) - } - - /** - * If lore edit via paper need permission - */ - val paperLoreEditNeedPermission: Boolean - get() { - return CONFIG - .config - .getBoolean(PAPER_PERMISSION_NEEDED, DEFAULT_PAPER_PERMISSION_NEEDED) - } - - // ----------------- - // Color Get methods - // ----------------- - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditType.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditType.kt deleted file mode 100644 index c094c71..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditType.kt +++ /dev/null @@ -1,142 +0,0 @@ -package xyz.alexcrea.cuanvil.util.config - -import xyz.alexcrea.cuanvil.anvil.AnvilUseType -import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.ALLOW_COLOR_CODE -import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.ALLOW_HEX_COLOR -import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.ALLOW_MINIMESSAGE -import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.DEFAULT_ALLOW_COLOR_CODE -import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.DEFAULT_ALLOW_HEX_COLOR -import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.DEFAULT_ALLOW_MINIMESSAGE -import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.DEFAULT_REMOVE_COLOR_COST -import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.DEFAULT_USE_COLOR_COST -import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.REMOVE_COLOR_COST -import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.REMOVE_COLOR_COST_RANGE -import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.USE_COLOR_COST -import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.USE_COLOR_COST_RANGE -import xyz.alexcrea.cuanvil.config.ConfigHolder.DEFAULT_CONFIG as CONFIG - -enum class LoreEditType( - val rootPath: String, - val useType: AnvilUseType, - val isBook: Boolean, - val isAppend: Boolean, - val isMultiLine: Boolean, -) { - APPEND_BOOK(AnvilUseType.LORE_EDIT_BOOK_APPEND, true, true, true), - REMOVE_BOOK(AnvilUseType.LORE_EDIT_BOOK_REMOVE, true, false, true), - APPEND_PAPER(AnvilUseType.LORE_EDIT_PAPER_APPEND, false, true, false), - REMOVE_PAPER(AnvilUseType.LORE_EDIT_PAPER_REMOVE, false, false, false), - ; - - constructor( - useType: AnvilUseType, - isPaper: Boolean, - isAppend: Boolean, - isMultiLine: Boolean, - ) : this(useType.path, useType, - isPaper, isAppend, isMultiLine) - - /** - * If this edit type is enabled - */ - val enabled: Boolean - get() { - return CONFIG - .config - .getBoolean("${rootPath}.${LoreEditConfigUtil.IS_ENABLED}", LoreEditConfigUtil.DEFAULT_IS_ENABLED) - } - - /** - * Fixed cost added to this edit - */ - val fixedCost: Int - get() { - return CONFIG - .config - .getInt("${rootPath}.${LoreEditConfigUtil.FIXED_COST}", LoreEditConfigUtil.DEFAULT_FIXED_COST) - .takeIf { it in LoreEditConfigUtil.FIXED_COST_RANGE } - ?: LoreEditConfigUtil.DEFAULT_FIXED_COST - } - - /** - * Cost added per line added - */ - val perLineCost: Int - get() { - if (!isMultiLine) throw IllegalStateException("Per line cost get on single line edit type") - return CONFIG - .config - .getInt("${rootPath}.${LoreEditConfigUtil.PER_LINE_COST}", LoreEditConfigUtil.DEFAULT_PER_LINE_COST) - .takeIf { it in LoreEditConfigUtil.PER_LINE_COST_RANGE } - ?: LoreEditConfigUtil.DEFAULT_PER_LINE_COST - } - - /** - * If the edit should consume the provided material - */ - val doConsume: Boolean - get() { - return CONFIG - .config - .getBoolean("${rootPath}.${LoreEditConfigUtil.DO_CONSUME}", LoreEditConfigUtil.DEFAULT_DO_CONSUME) - } - - /** - * Allow usage or removal of color code - */ - val allowColorCode: Boolean - get() { - return CONFIG - .config - .getBoolean("$rootPath.$ALLOW_COLOR_CODE", DEFAULT_ALLOW_COLOR_CODE) - } - - /** - * Allow usage or removal of hexadecimal color - */ - val allowHexColor: Boolean - get() { - return CONFIG - .config - .getBoolean("${rootPath}.$ALLOW_HEX_COLOR", DEFAULT_ALLOW_HEX_COLOR) - } - - /** - * Allow usage or removal of minimessage on lore add - */ - val allowMinimessage: Boolean - get() { - return CONFIG - .config - .getBoolean("${rootPath}.$ALLOW_MINIMESSAGE", DEFAULT_ALLOW_MINIMESSAGE) - } - - /** - * Cost when using either color code and hex color on lore add - */ - val useColorCost: Int - get() { - if (!isAppend) throw IllegalStateException("Can only call with an append edit type") - return CONFIG - .config - .getInt("${rootPath}.$USE_COLOR_COST", DEFAULT_USE_COLOR_COST) - .takeIf { it in USE_COLOR_COST_RANGE } - ?: DEFAULT_USE_COLOR_COST - - } - - /** - * Cost when using either color code and hex color on lore remove - */ - val removeColorCost: Int - get() { - if (isAppend) throw IllegalStateException("Can only call with a remove edit type") - return CONFIG - .config - .getInt("${rootPath}.$REMOVE_COLOR_COST", DEFAULT_REMOVE_COLOR_COST) - .takeIf { it in REMOVE_COLOR_COST_RANGE } - ?: DEFAULT_REMOVE_COLOR_COST - - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/dialog/AnvilRenameDialogUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/dialog/AnvilRenameDialogUtil.kt deleted file mode 100644 index 07d4e08..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/dialog/AnvilRenameDialogUtil.kt +++ /dev/null @@ -1,55 +0,0 @@ -package xyz.alexcrea.cuanvil.util.dialog - -import io.delilaheve.CustomAnvil -import io.delilaheve.util.ConfigOptions -import org.bukkit.entity.HumanEntity -import org.bukkit.event.inventory.PrepareAnvilEvent -import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil -import xyz.alexcrea.cuanvil.dialog.AnvilRenameDialog -import xyz.alexcrea.cuanvil.dialog.AnvilRenameDialogImpl -import xyz.alexcrea.cuanvil.update.UpdateUtils -import xyz.alexcrea.cuanvil.util.anvil.AnvilColorUtil - -object AnvilRenameDialogUtil { - - val anvilRenameDialog: AnvilRenameDialog; - - init { - val version = UpdateUtils.currentMinecraftVersion() - anvilRenameDialog = (if(!PlatformUtil.isPaper || - (version.major <= 1 && version.minor <= 21 && version.patch <= 6)) { - NoImplAnvilRenameDialog() - } else { - AnvilRenameDialogImpl({ player, component -> AnvilColorUtil.revertColorSmallest( - component, AnvilColorUtil.renamePermission(player) - ) }, - { ConfigOptions.shouldKeepRenameText }, - { ConfigOptions.renameDialogMaxSize }, - CustomAnvil.instance, - ) - }) - } - - class NoImplAnvilRenameDialog: AnvilRenameDialog { - - override fun canSendDialog(): Boolean { - return false - } - - override fun tryShowDialog( - player: HumanEntity, - event: PrepareAnvilEvent - ) {} - - override fun closeInventory(player: HumanEntity) {} - - override fun currentText(player: HumanEntity): String? { - return null - } - - override fun isOpenFor(player: HumanEntity): Boolean { - return false - } - - } -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/group/AbstractMaterialGroup.kt b/src/main/kotlin/xyz/alexcrea/group/AbstractMaterialGroup.kt new file mode 100644 index 0000000..b253da9 --- /dev/null +++ b/src/main/kotlin/xyz/alexcrea/group/AbstractMaterialGroup.kt @@ -0,0 +1,50 @@ +package xyz.alexcrea.group + +import org.bukkit.Material +import java.util.EnumSet + +abstract class AbstractMaterialGroup(private val name: String) { + protected val includedMaterial by lazy {createDefaultSet()} + + /** + * Get the group default set + */ + protected abstract fun createDefaultSet(): EnumSet + + /** + * Get if a material is allowed following the group policy + */ + fun contain(mat : Material): Boolean { + return mat in includedMaterial + } + + /** + * Get if a group is referenced by this: + */ + abstract fun isReferencing(other : AbstractMaterialGroup): Boolean + + /** + * Push a material to this group to follow this group policy + */ + abstract fun addToPolicy(mat : Material) + + /** + * Push a group to this group to follow this group policy + */ + abstract fun addToPolicy(other : AbstractMaterialGroup) + + /** + * Get the group name in case something is wrong + */ + fun getName(): String { + return name + } + + /** + * Get the group as a set + */ + fun getSet(): Set { + return includedMaterial + } + +} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/group/EnchantConflictGroup.kt b/src/main/kotlin/xyz/alexcrea/group/EnchantConflictGroup.kt new file mode 100644 index 0000000..adef2fe --- /dev/null +++ b/src/main/kotlin/xyz/alexcrea/group/EnchantConflictGroup.kt @@ -0,0 +1,38 @@ +package xyz.alexcrea.group + +import org.bukkit.Material +import org.bukkit.enchantments.Enchantment + +class EnchantConflictGroup(private val cantConflict: AbstractMaterialGroup, private val minBeforeBlock: Int){ + + private val enchantments = HashSet() + + fun addEnchantment(ench: Enchantment){ + enchantments.add(ench) + } + fun allowed(enchants: Set, mat: Material) : Boolean{ + if(enchantments.size < minBeforeBlock){ + return true + } + + if(cantConflict.contain(mat)){ + return true + } + + // Count the amount of enchantment that are in the list + var enchantAmount = 0 + for (enchantment in enchants) { + if(enchantment !in enchantments) continue + if(++enchantAmount > minBeforeBlock){ + return false + } + + } + return true + } + + fun getEnchants(): HashSet { + return enchantments + } + +} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/group/EnchantConflictManager.kt b/src/main/kotlin/xyz/alexcrea/group/EnchantConflictManager.kt new file mode 100644 index 0000000..b285989 --- /dev/null +++ b/src/main/kotlin/xyz/alexcrea/group/EnchantConflictManager.kt @@ -0,0 +1,149 @@ +package xyz.alexcrea.group + +import io.delilaheve.UnsafeEnchants +import org.bukkit.Material +import org.bukkit.NamespacedKey +import org.bukkit.configuration.ConfigurationSection +import org.bukkit.configuration.file.YamlConfiguration +import org.bukkit.enchantments.Enchantment +import kotlin.collections.ArrayList + +class EnchantConflictManager { + + companion object { + // Path for the enchantments list + private const val ENCH_LIST_PATH = "enchantments" + // Path for group list related to the conflict + private const val CONFLICT_GROUP_PATH = "notAffectedGroups" + // Path for the maximum number of enchantment before validating the conflict + private const val ENCH_MAX_PATH = "maxEnchantmentBeforeConflict" + // Path for a flag: if the enchantment will be used in the last supported version + // TODO maybe replace this system by a list of "future" enchantment. + private const val FUTURE_USE_PATH = "useInFuture" + // Default name for an empty Material group + private val DEFAULT_EMPTY_GROUP = IncludeGroup("empty") + // Default name for a joining group + private const val DEFAULT_GROUP_NAME = "joinedGroup" + } + + private lateinit var conflictMap: HashMap> + + // Read and prepare all conflict + fun prepareConflicts(config: YamlConfiguration, itemManager: ItemGroupManager){ + conflictMap = HashMap() + + val keys = config.getKeys(false) + for (key in keys) { + val section = config.getConfigurationSection(key)!! + val conflict = createConflict(section,itemManager,key) + if(conflict != null){ + addToMap(conflict) + } + + } + + } + + // Add the conflict to the map + private fun addToMap(conflict: EnchantConflictGroup){ + conflict.getEnchants().forEach{ enchant -> + if(!conflictMap.containsKey(enchant)){ + conflictMap[enchant] = ArrayList() + } + conflictMap[enchant]!!.add(conflict) + } + } + + // create and read a conflict from a yaml section + private fun createConflict(section: ConfigurationSection, + itemManager: ItemGroupManager, + conflictName: String): EnchantConflictGroup? { + // Is it planed for the future + val futureUse = section.getBoolean(FUTURE_USE_PATH,false) + // Create conflict + val conflict = createConflictObject(section,itemManager,conflictName) + // Read and add enchantment to conflict + val enchantList = section.getStringList(ENCH_LIST_PATH) + for (enchantName in enchantList) { + val enchantKey = NamespacedKey.minecraft(enchantName) + val enchant = Enchantment.getByKey(enchantKey) + if(enchant == null){ + if(!futureUse){ + UnsafeEnchants.instance.logger.warning("Enchantment $enchantName do not exist but was asked for conflict $conflictName") + } + continue + } + conflict.addEnchantment(enchant) + } + if(conflict.getEnchants().size == 0){ + if(!futureUse){ + UnsafeEnchants.instance.logger.warning("Conflict $conflictName do not have valid enchantment, it will not work") + } + return null + } + + return conflict + } + + private fun createConflictObject(section: ConfigurationSection, + itemManager: ItemGroupManager, + conflictName: String): EnchantConflictGroup { + // Get the maximum number of enchantment before validating the conflict + var minBeforeBlock = section.getInt(ENCH_MAX_PATH,0) + if(minBeforeBlock < 0){ + minBeforeBlock = 0 + UnsafeEnchants.instance.logger.warning("Conflict $conflictName have an invalid value of $ENCH_MAX_PATH") + UnsafeEnchants.instance.logger.warning("It should be more or equal to 0. default to 0") + } + // Find or create the selected group for the conflict + val groupList = section.getStringList(CONFLICT_GROUP_PATH) + val finalGroup: AbstractMaterialGroup + if(groupList.size < 1){ + finalGroup = DEFAULT_EMPTY_GROUP + }else if(groupList.size == 1){ + finalGroup = findGroup(groupList[0], itemManager, conflictName) + }else{ + finalGroup = IncludeGroup(DEFAULT_GROUP_NAME) + for (groupName in groupList) { + finalGroup.addToPolicy(findGroup(groupName, itemManager, conflictName)) + } + } + // Return conflict + return EnchantConflictGroup(finalGroup, minBeforeBlock) + } + + private fun findGroup(groupName: String,itemManager: ItemGroupManager, conflictName: String): AbstractMaterialGroup { + val group = itemManager.get(groupName) + if(group == null){ + UnsafeEnchants.instance.logger.warning("Group $groupName do not exist but is ask by conflict $conflictName") + return DEFAULT_EMPTY_GROUP + } + + return group + } + + fun isConflicting(base: Set,mat: Material, newEnchant: Enchantment): ConflictType{ + val conflictList = conflictMap[newEnchant] ?: return ConflictType.NO_CONFLICT + + var result = ConflictType.NO_CONFLICT + for (conflict in conflictList) { + if(!conflict.allowed(base,mat)) { + if(conflict.getEnchants().size <= 1){ + result = ConflictType.SMALL_CONFLICT + }else{ + return ConflictType.BIG_CONFLICT + } + } + } + return result + } + +} + +enum class ConflictType(){ + NO_CONFLICT, + SMALL_CONFLICT, + BIG_CONFLICT + + +} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/group/ExcludeGroup.kt b/src/main/kotlin/xyz/alexcrea/group/ExcludeGroup.kt new file mode 100644 index 0000000..e929346 --- /dev/null +++ b/src/main/kotlin/xyz/alexcrea/group/ExcludeGroup.kt @@ -0,0 +1,33 @@ +package xyz.alexcrea.group + +import org.bukkit.Material +import java.util.* +import kotlin.collections.HashSet + +class ExcludeGroup(name: String): AbstractMaterialGroup(name) { + override fun createDefaultSet(): EnumSet { + return EnumSet.allOf(Material::class.java) + } + + private val includedGroup = HashSet() + + override fun isReferencing(other: AbstractMaterialGroup): Boolean { + for (materialGroup in includedGroup.iterator()) { + if((materialGroup == other) || (materialGroup.isReferencing(other))){ + return true + } + } + return false + } + + override fun addToPolicy(mat: Material) { + includedMaterial.remove(mat) + } + + override fun addToPolicy(other: AbstractMaterialGroup) { + includedGroup.add(other) + includedMaterial.removeAll(other.getSet()) + } + + +} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/group/IncludeGroup.kt b/src/main/kotlin/xyz/alexcrea/group/IncludeGroup.kt new file mode 100644 index 0000000..d349821 --- /dev/null +++ b/src/main/kotlin/xyz/alexcrea/group/IncludeGroup.kt @@ -0,0 +1,31 @@ +package xyz.alexcrea.group + +import org.bukkit.Material +import java.util.EnumSet + +class IncludeGroup(name: String): AbstractMaterialGroup(name) { + override fun createDefaultSet(): EnumSet { + return EnumSet.noneOf(Material::class.java) + } + + private val includedGroup = HashSet() + + override fun isReferencing(other: AbstractMaterialGroup): Boolean { + for (materialGroup in includedGroup.iterator()) { + if((materialGroup == other) || (materialGroup.isReferencing(other))){ + return true + } + } + return false + } + + override fun addToPolicy(mat: Material) { + includedMaterial.add(mat) + } + + override fun addToPolicy(other: AbstractMaterialGroup) { + includedGroup.add(other) + includedMaterial.addAll(other.getSet()) + } + +} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/ItemGroupManager.kt b/src/main/kotlin/xyz/alexcrea/group/ItemGroupManager.kt similarity index 50% rename from src/main/kotlin/xyz/alexcrea/cuanvil/group/ItemGroupManager.kt rename to src/main/kotlin/xyz/alexcrea/group/ItemGroupManager.kt index 348d0ff..7c02d47 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/ItemGroupManager.kt +++ b/src/main/kotlin/xyz/alexcrea/group/ItemGroupManager.kt @@ -1,69 +1,54 @@ -package xyz.alexcrea.cuanvil.group +package xyz.alexcrea.group -import io.delilaheve.CustomAnvil +import io.delilaheve.UnsafeEnchants import org.bukkit.Material import org.bukkit.configuration.ConfigurationSection +import org.bukkit.configuration.file.YamlConfiguration import java.util.* +import kotlin.collections.HashMap class ItemGroupManager { companion object { // Path for group type - const val GROUP_TYPE_PATH = "type" - + private const val GROUP_TYPE_PATH = "type" // Path for included items list - const val MATERIAL_LIST_PATH = "items" - + private const val MATERIAL_LIST_PATH = "items" // Path for included groups list - const val GROUP_LIST_PATH = "groups" - + private const val GROUP_LIST_PATH = "groups" // Temporary list of elements in default config that are use in future - private val FUTURE_MATERIAL = setOf("PIGLIN_HEAD", "BRUSH") + private val FUTURE_MATERIAL = setOf("PIGLIN_HEAD","BRUSH") } - lateinit var groupMap: LinkedHashMap + private lateinit var groupMap : HashMap // Read and create material groups - fun prepareGroups(config: ConfigurationSection) { - groupMap = LinkedHashMap() + fun prepareGroups(config: YamlConfiguration){ + groupMap = HashMap() val keys = config.getKeys(false) for (key in keys) { - if (groupMap.containsKey(key)) - continue - if (!config.isConfigurationSection(key)) + if(groupMap.containsKey(key)) continue createGroup(config, keys, key) } } - // Create group with existing groups - fun createGroup( - config: ConfigurationSection, - name: String - ): AbstractMaterialGroup{ - return createGroup(config, groupMap.keys, name) - } - - // Create group by key - private fun createGroup( - config: ConfigurationSection, - keys: Set, - key: String - ): AbstractMaterialGroup { + private fun createGroup(config: YamlConfiguration, + keys: Set, + key: String): AbstractMaterialGroup{ val groupSection = config.getConfigurationSection(key)!! - - val groupType = groupSection.getString(GROUP_TYPE_PATH, null) + val groupType = groupSection.getString(GROUP_TYPE_PATH,null) // Create Material group according to the group type val group: AbstractMaterialGroup - if (groupType != null && GroupType.EXCLUDE.equal(groupType)) { + if(GroupType.EXCLUDE.equal(groupType)){ group = ExcludeGroup(key) - } else { + }else { group = IncludeGroup(key) - if (!GroupType.INCLUDE.equal(groupType)) { - CustomAnvil.instance.logger.warning("Group $key have an invalid group type. default to Include.") + if(!GroupType.INCLUDE.equal(groupType)){ + UnsafeEnchants.instance.logger.warning("Group $key have an invalid group type. default to Include.") } } @@ -73,56 +58,48 @@ class ItemGroupManager { } // Read Group elements - private fun readGroup( - group: AbstractMaterialGroup, - groupSection: ConfigurationSection, - config: ConfigurationSection, - keys: Set - ) { + private fun readGroup(group: AbstractMaterialGroup, + groupSection: ConfigurationSection, + config: YamlConfiguration, + keys: Set){ // Read material to include in this group policy val materialList = groupSection.getStringList(MATERIAL_LIST_PATH) for (materialTemp in materialList) { val materialName = materialTemp.uppercase(Locale.getDefault()) val material = Material.getMaterial(materialName) - if (material == null) { + if(material == null){ // Check if we should warn the user - if (materialName !in FUTURE_MATERIAL) { - CustomAnvil.instance.logger.warning( - "Unknown material $materialTemp on group ${group.getName()}" - ) + if(materialName !in FUTURE_MATERIAL){ + UnsafeEnchants.instance.logger.warning( + "Unknown material $materialTemp on group ${group.getName()}") } continue } - group.addToPolicy(material.key) + group.addToPolicy(material) } // Read group to include in this group policy. // please note the group name is case-sensitive. val groupList = groupSection.getStringList(GROUP_LIST_PATH) for (groupName in groupList) { - if (groupName !in keys) { - CustomAnvil.instance.logger.warning( - "Group $groupName do not exist but is included in group ${group.getName()}" - ) + if(groupName !in keys){ + UnsafeEnchants.instance.logger.warning( + "Group $groupName do not exist but is included in group ${group.getName()}") continue } // Get other group or create it if not yet created - val otherGroup = - if (!groupMap.containsKey(groupName)) { - if(!config.isConfigurationSection(groupName)) continue - createGroup(config, keys, groupName) + val otherGroup = if(!groupMap.containsKey(groupName)){ + createGroup(config,keys,groupName) + }else{ + groupMap[groupName]!! } - else groupMap[groupName]!! - // Avoid self reference or it will create an infinite loop - if (otherGroup.isReferencing(group)) { - CustomAnvil.instance.logger.warning( - "Group $groupName is on a reference loop with group ${group.getName()} !" - ) - CustomAnvil.instance.logger.warning( - "Please fix it in your item_groups config or the plugin will probably not work as expected." - ) + if(otherGroup.isReferencing(group)){ + UnsafeEnchants.instance.logger.warning( + "Group $groupName is on a reference loop with group ${group.getName()} !") + UnsafeEnchants.instance.logger.warning( + "Please fix it in your item_groups config or the plugin will probably not work as expected.") continue } @@ -138,17 +115,17 @@ class ItemGroupManager { } -enum class GroupType(val groupID: String) { +enum class GroupType(private val groupID: String) { INCLUDE("include"), EXCLUDE("exclude") ; // Test if string is equal to the groupID of this enum - fun equal(toTest: String?): Boolean { - if (toTest == null) + fun equal(toTest: String?): Boolean{ + if(toTest == null) return false - return groupID.contentEquals(toTest.lowercase(Locale.getDefault())) + return groupID.contentEquals(toTest.lowercase(Locale.getDefault())) } } \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 7d6e396..b434ad8 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,123 +1,33 @@ +# Whether all anvil actions should be capped # -# It is recommended that you use /configanvil to edit most of these config. -# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! +# If true, all anvil repairs will max out at the value of limit_repair_value +limit_repair_cost: true + +# Value to limit repair costs to when limit_repair_cost is true # - -# What service of metric should custom anvil use -# Custom anvil collect generic information like server minecraft version, type, etc... -# It can also collect error information if error is happening (currently faststats only) -# It can also be disabled -# Please refer to README for public metric link -# Possible options: auto, bstat, faststats, disabled (auto by default) -metric_type: auto - -# Allow to report errors made caused by this plugin (only for faststats) -# This allows me to fix potentials issue that I'm not aware of -# Accept true or false (true by default) -metric_collect_errors: true - -# All anvil cost will be capped to limit_repair_value if enabled. -# -# In other words: -# For any anvil cost greater than limit_repair_value, Cost will be set to limit_repair_value. -limit_repair_cost: false - -# Max cost value the Anvil can get to. -# -# Valid values include 0 to 1000. -# Cost will be displayed as "Too Expensive": -# - If Cost is above 39 -# - And replace_too_expensive is disabled (false) +# Valid range of 1 - 39 (vanilla will consider 40+ as "too expensive") limit_repair_value: 39 -# Whether the anvil's cost limit should be removed entirely. +# Whether the anvil's repair limit should be removed entirely # -# The anvil will still visually display "Too Expensive" if "replace_too_expensive" is disabled -# However, the action will be completable if xp requirement is meet. +# The anvil will still visually display "too expensive" however the action will be completable remove_repair_limit: false -# Whenever anvil cost is above 39 should display the true price and not "Too Expensive". +# Value added to the anvil when the item durability increase # -# However, when bypassing "Too Expensive", anvil price will be displayed as Green. -# If the action is not completable, the cost will still be displayed as "Too expensive". -# That mean you also need to change other settings like remove_repair_limit or limit_repair_cost. -# -# Require ProtocoLib. -replace_too_expensive: false - -# XP Level amount added to the anvil when the item is repaired by another item of the same type -# -# Valid values include 0 to 1000 +# Valid range of 0 - 255 item_repair_cost: 2 -# XP Level amount added to the anvil when the item is renamed +# Value added to the anvil when a sacrifice enchantment conflict +# with one of the left item enchantment # -# Valid values include 0 to 1000 -item_rename_cost: 1 - -# XP Level amount added to the anvil when the item is repaired by an "unit" -# For example: a Diamond on a Diamond Sword -# What's considered unit for what can be edited on the unit repair configuration. -# -# Valid values include 0 to 1000 -unit_repair_cost: 1 - -# XP Level amount added to the anvil when a sacrifice enchantment -# conflict with one of the left item enchantment -# -# Valid values include 0 to 1000 +# Valid range of 0 - 255 sacrifice_illegal_enchant_cost: 1 -# Allow using color code and hexadecimal color. +# Default limit to apply to any enchants missing from override_limits # -# Color code are prefixed by "&" and hexadecimal color by "#". -# Color code will not be applied if it colors nothing. "&&" can be used to write "&". -# For minimessage search for minimessage formating https://docs.papermc.io/adventure/minimessage/format/ -# Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin -# but any global tag will be allowed later when v2 release -allow_color_code: false -allow_hexadecimal_color: false -allow_minimessage: false - -# This enables restricting color code for player having specific permission -# It requires allow_color_code enabled for... obvious reasons -# -# For example: if player want to use "&aHello" it will be required that the player has -# the permission "ca.color.code.a" as he used the color code "a" -# In general permission to give to the player is "ca.color.code.[code]" -# where [code] is the color code you wish to allow the player -# -# It is kinda of useless when minimessage is supported as players would be able to bypass -# that using the equivalent minimessage tag -per_color_code_permission: false - -# Toggle if color should only be applicable if the player a certain permission. -# -# permission are "ca.color.code" for use of color code and "ca.color.hex" for use of hexadecimal color. -permission_needed_for_color: true - -# Xp cost if the player use color in the items name on rename. -# -# Valid values include 0 to 1000. -use_of_color_cost: 0 - -# Dialogue rename menu make use of dialog menu to allow bigger rename -# You can also change the maximum size and set it to -1 or less for maximum -# -# This feature only work on paper 1.21.7 or later -# -# At the moment only english is available for this menu... sorry ! -# -# CustomAnvil use "ca.rename.dialog" when permission -enable_dialog_rename: false -dialog_rename_max_size: 256 -permission_needed_for_dialog_rename: false - -# This allows custom anvil to not "guess" the text used for rename but store it in the item -# It will make item stackable only and only if it had used the same rename text -# -# For practical reason. this only work when dialog rename is enabled -dialog_rename_keep_user_text: true +# Valid range of 1 - 255 +default_limit: 5 # Override limits for specific enchants # @@ -125,49 +35,47 @@ dialog_rename_keep_user_text: true # # Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels # -# Valid range of 0 - 255 for each enchantment -# -1 mean keep default +# Valid range of 1 - 255 for each enchantment enchant_limits: - minecraft:aqua_affinity: 1 - minecraft:binding_curse: 1 - minecraft:channeling: 1 - minecraft:flame: 1 - minecraft:infinity: 1 - minecraft:mending: 1 - minecraft:multishot: 1 - minecraft:silk_touch: 1 - minecraft:vanishing_curse: 1 - minecraft:depth_strider: 3 # anything more than 3 is treated as 3 by the game - minecraft:protection: 4 - minecraft:fire_protection: 4 - minecraft:blast_protection: 4 - minecraft:projectile_protection: 4 - minecraft:feather_falling: 4 - minecraft:thorns: 3 - minecraft:respiration: 3 - minecraft:sharpness: 5 - minecraft:smite: 5 - minecraft:bane_of_arthropods: 5 - minecraft:knockback: 2 - minecraft:fire_aspect: 2 - minecraft:looting: 3 - minecraft:sweeping: 3 - minecraft:sweeping_edge: 3 - minecraft:efficiency: 5 - minecraft:unbreaking: 3 - minecraft:fortune: 3 - minecraft:power: 5 - minecraft:punch: 2 - minecraft:luck_of_the_sea: 3 - minecraft:lure: 3 - minecraft:frost_walker: 2 - minecraft:impaling: 5 - minecraft:riptide: 3 - minecraft:loyalty: 3 - minecraft:piercing: 4 - minecraft:quick_charge: 3 - minecraft:soul_speed: 3 - minecraft:swift_sneak: 3 + aqua_affinity: 1 + binding_curse: 1 + channeling: 1 + flame: 1 + infinity: 1 + mending: 1 + multishot: 1 + silk_touch: 1 + vanishing_curse: 1 + depth_strider: 3 # anything more than 3 is treated as 3 by the game + protection: 4 + fire_protection: 4 + blast_protection: 4 + projectile_protection: 4 + feather_falling: 4 + thorns: 3 + respiration: 3 + sharpness: 5 + smite: 5 + bane_of_arthropods: 5 + knockback: 2 + fire_aspect: 2 + looting: 3 + sweeping: 3 + efficiency: 5 + unbreaking: 3 + fortune: 3 + power: 5 + punch: 2 + luck_of_the_sea: 3 + lure: 3 + frost_walker: 2 + impaling: 5 + riptide: 3 + loyalty: 3 + piercing: 4 + quick_charge: 3 + soul_speed: 3 + swift_sneak: 3 # Multipliers used to calculate the enchantment's value in repair/combining # @@ -181,289 +89,123 @@ enchant_limits: # With default values protection 4 would have a value of 4 when # coming from either a book (4 * 1) or an item (4 * 1) enchant_values: - minecraft:aqua_affinity: + aqua_affinity: item: 4 book: 2 - minecraft:bane_of_arthropods: + bane_of_arthropods: item: 2 book: 1 - minecraft:binding_curse: + binding_curse: item: 8 book: 4 - minecraft:blast_protection: + blast_protection: item: 4 book: 2 - minecraft:channeling: + channeling: item: 8 book: 4 - minecraft:depth_strider: + depth_strider: item: 4 book: 2 - minecraft:efficiency: + efficiency: item: 1 book: 1 - minecraft:flame: + flame: item: 4 book: 2 - minecraft:feather_falling: + feather_falling: item: 2 book: 1 - minecraft:fire_aspect: + fire_aspect: item: 4 book: 2 - minecraft:fire_protection: + fire_protection: item: 2 book: 1 - minecraft:fortune: + fortune: item: 4 book: 2 - minecraft:frost_walker: + frost_walker: item: 4 book: 2 - minecraft:impaling: + impaling: item: 4 book: 2 - minecraft:infinity: + infinity: item: 8 book: 4 - minecraft:knockback: + knockback: item: 2 book: 1 - minecraft:looting: + looting: item: 4 book: 2 - minecraft:loyalty: + loyalty: item: 1 book: 1 - minecraft:luck_of_the_sea: + luck_of_the_sea: item: 4 book: 2 - minecraft:lure: + lure: item: 4 book: 2 - minecraft:mending: + mending: item: 4 book: 2 - minecraft:multishot: + multishot: item: 4 book: 2 - minecraft:piercing: + piercing: item: 1 book: 1 - minecraft:power: + power: item: 1 book: 1 - minecraft:projectile_protection: + projectile_protection: item: 2 book: 1 - minecraft:protection: + protection: item: 1 book: 1 - minecraft:punch: + punch: item: 4 book: 2 - minecraft:quick_charge: + quick_charge: item: 2 book: 1 - minecraft:respiration: + respiration: item: 4 book: 2 - minecraft:riptide: + riptide: item: 4 book: 2 - minecraft:silk_touch: + silk_touch: item: 8 book: 4 - minecraft:sharpness: + sharpness: item: 1 book: 1 - minecraft:smite: + smite: item: 2 book: 1 - minecraft:soul_speed: + soul_speed: item: 8 book: 4 - minecraft:swift_sneak: + swift_sneak: item: 8 book: 4 - minecraft:sweeping: + sweeping: item: 4 book: 2 - minecraft:sweeping_edge: - item: 4 - book: 2 - minecraft:thorns: + thorns: item: 8 book: 4 - minecraft:unbreaking: + unbreaking: item: 2 book: 1 - minecraft:vanishing_curse: + vanishing_curse: item: 8 book: 4 -# Disable enchantment merging for level above the set value -# Enchantment merging is when, for example, 2 unbreaking II book combine to give sharpness III -# But Enchantment above this value can still be applied. following the previous example, we could still apply a unbreaking III book to a sword -# Even if disable-merge-over of unbreaking is set to 2 -# -1 mean enchantment merge for this enchantment is not disabled. default to -1 if absent. -disable-merge-over: - # Sharpness is set to -1. it equivalent to it not being set to anything (and work as vanilla on default configuration) - minecraft:sharpness: -1 - # If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied - #minecraft:unbreaking: 2 - -# The maximum number of enchantment an item can get. -1 for infinity -# Use eco enchant enchant_limit if present by default unless "default" is not equal to -1 -enchantment_count_limit: - default: -1 - # Limit for specific items. example bellow is an example with stick - # Per item enchantment limit override eco enchant enchant_limit and default limit - items: - stick: -1 - -# Settings for lore modification -lore_edit: - book_and_quil: - # Permission is ca.lore_edit.book - use_permission: true - append: - # If adding lore using book & quil is enabled - enabled: false - # Cost used every time - fixed_cost: 1 - # Cost used for every lore line added - per_line_cost: 0 - # Use left item vanilla cost penalty if any - shared_increase: false - # Increase shared left item cost penalty - shared_additive: false - # If adding the lore consume the book & quil - do_consume: false - # Allow using color code and hexadecimal color when editing lore via book & quil - # - # Color code are prefixed by "&" and hexadecimal color by "#" - # Color code will not be applied if it colors nothing. "&&" can be used to write "&" - # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # - # Note that currently minimessage would disable hex code when adding color - allow_color_code: true - allow_hexadecimal_color: false - allow_minimessage: true - - remove: - # If removing lore using book & quil is enabled - enabled: false - # Cost used every time - fixed_cost: 1 - # Cost used for every lore line removed - per_line_cost: 0 - # Use left item vanilla cost penalty if any - shared_increase: false - # Increase shared left item cost penalty - shared_additive: false - # If removing the lore consume the book & quil - do_consume: false - # Cost of replacing colors - remove_color_cost: 0 - # Allowed some color and tags to be reverted to plain text - # Custom anvil will prioritise format that result is a smaller resulting text - # Note that not allowing certain format will lead to some lost of color or tags. - # If configuration are exact as append appending this book should result in the exact same color - # - # Color code will be prefixed by "&" and hexadecimal color by "#". - # If color code is allowed, "&" in the text will get converted to "&&" - # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - allow_color_code: true - allow_hexadecimal_color: false - allow_minimessage: true - - paper: - # Permission is ca.lore_edit.paper - use_permission: true - # what order should the lines should get added/removed (start/end, if invalid or not present will be end) - order: end - - append_line: - # If adding lore line using paper is enabled - enabled: false - # Cost used every time - fixed_cost: 1 - # Use left item vanilla cost penalty if any - shared_increase: false - # Increase shared left item cost penalty - shared_additive: false - # If adding the lore line consume the paper - do_consume: false - # Allow using color code and hexadecimal color when editing lore via book & quil - # - # Color code are prefixed by "&" and hexadecimal color by "#" - # Color code will not be applied if it colors nothing. "&&" can be used to write "&" - # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # - # Note that currently minimessage would disable hex code when adding color - allow_color_code: true - allow_hexadecimal_color: false - allow_minimessage: true - color_use_cost: 0 - - remove_line: - # If removing lore line using paper is enabled - enabled: false - # Cost used every time - fixed_cost: 1 - # Use left item vanilla cost penalty if any - shared_increase: false - # Increase shared left item cost penalty - shared_additive: false - # If removing the lore line consume the paper - do_consume: false - # Cost of replacing colors - remove_color_cost: 0 - # Allowed some color and tags to be reverted to plain text - # Custom anvil will prioritise format that result is a smaller resulting text - # Note that not allowing certain format will lead to some lost of color or tags. - # If configuration are exact as append appending this paper should result in the exact same color - # - # Color code will be prefixed by "&" and hexadecimal color by "#". - # If color code is allowed, "&" in the text will get converted to "&&" - # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - allow_color_code: true - allow_hexadecimal_color: false - allow_minimessage: true - -# Allow to replace the xp cost by a monetary cost -# If enabled it will not be bound to the experience level limits -# -# It also requires to enable dialog rename (set "enable_dialog_rename: false" a bit higher) -# If dialog rename permission is enabled and player do not have the permission merge will fall back to vanilla xp cost -# -# If you are using custom craft I recommend using Linear Xp Cost with Exact Linear Xp as normal Xp Cost will act "weird" -# But Linear Xp will act as 1$ time global multiplier. In other word: like you expect -# -# As this feature require dialog rename, it can only be enabled starting with paper 1.21.6 and later -monetary_cost: - enabled: false - # If using vault unlocked this allow to specify what currency should be used for anvil usage - # default being the default currency - currency: default - # multiply the anvil cost by a value to allow to have price a big bigger than like 40 - multipliers: - # global multipliers. all usage type will be multiplied by this value - global: 1.0 - # usage specific type. it will only apply for specific xp "reason" - enchantment: 1.0 # related to enchantments level - repair: 1.0 # for repairing via unit repair (per unit) - rename: 1.0 # for renaming the item - lore_edit: 1.0 # for changing the lore of the item (only if lore edit is enabled) - illegal_penalty: 1.0 # for trying to combine illegal enchantment - work_penalty: 1.0 # for work penalty (aka use penalty) - recipe: 1.0 # for custom anvil recipe cost - # Whether to show debug logging debug_log: false - -# Whether to show verbose debug logging -debug_log_verbose: false - -configVersion: 1.11.0 diff --git a/src/main/resources/custom_recipes.yml b/src/main/resources/custom_recipes.yml deleted file mode 100644 index 57c2220..0000000 --- a/src/main/resources/custom_recipes.yml +++ /dev/null @@ -1,5 +0,0 @@ -# ---------------------------------------------------- -# This config file is to store custom craft -# It is recommended to use the in game config editor for this configuration. -# /customanvilconfig With ca.config.edit permission -# ---------------------------------------------------- diff --git a/src/main/resources/datapack/bracken/enchant_conflict.yml b/src/main/resources/datapack/bracken/enchant_conflict.yml deleted file mode 100644 index 851a398..0000000 --- a/src/main/resources/datapack/bracken/enchant_conflict.yml +++ /dev/null @@ -1,35 +0,0 @@ -"bracken:abstraction": ['#sword_enchant_conflict'] -"bracken:antivenom": ['#protection_enchant_conflict'] -"bracken:blinding_fix": ['minecraft:fire_aspect'] -"bracken:boldness": ['#protection_enchant_conflict'] -"bracken:butchering": ['#sword_enchant_conflict'] -"bracken:defusing": ['#sword_enchant_conflict'] -"bracken:dentine_touch": ['#tool_conflict'] -"bracken:dullness_curse": ['minecraft:sharpness'] -"bracken:famine_walker": ['#boot_conflict'] -"bracken:ferocity": ['#sword_enchant_conflict'] -"bracken:flame_walker": ['#boot_conflict'] -"bracken:float_walker": ['#boot_conflict'] -"bracken:flood_walker": ['#boot_conflict'] -"bracken:fragility_curse": ['minecraft:unbreaking'] -"bracken:freezing_fix": ['minecraft:fire_aspect'] -"bracken:guarding": ['#sword_enchant_conflict'] -"bracken:huskiness": ['#bracken_pet_armor'] -"bracken:infused_fire_aspect_fix": ['minecraft:fire_aspect'] -"bracken:infused_frost_walker_fix": ['#boot_conflict'] -"bracken:infused_mending_fix": ['minecraft:mending'] -"bracken:infused_thorns_fix": ['minecraft:thorns'] -"bracken:lethargy_curse": ['bracken:ferocity'] -"bracken:lifesteal": ['#bow_conflict'] -"bracken:litheness": ['#bracken_pet_armor'] -"bracken:lunar_concordance_armor": ['#bracken_lunarite_armor'] -"bracken:lunar_concordance_weapon": ['#bracken_lunarite_weapons'] -"bracken:maiming_curse": ['bracken:vitality_fix'] -"bracken:mortality": ['#sword_enchant_conflict'] -"bracken:poisoning_fix": ['minecraft:fire_aspect'] -"bracken:pugnacity": ['#bracken_pet_armor'] -"bracken:rending": ['#crossbow_conflict'] -"bracken:silvered_fix": ['#all'] -"bracken:vitality_fix": ['bracken:maiming_curse'] -"bracken:weakening_fix": ['minecraft:fire_aspect'] -"bracken:withering_fix": ['minecraft:fire_aspect'] diff --git a/src/main/resources/datapack/bracken/item_conflict.yml b/src/main/resources/datapack/bracken/item_conflict.yml deleted file mode 100644 index 1c4d9da..0000000 --- a/src/main/resources/datapack/bracken/item_conflict.yml +++ /dev/null @@ -1,54 +0,0 @@ -"bracken:abstraction": ['melee_weapons', 'mace'] -"bracken:antivenom": ['armors'] -"bracken:astuteness_fix": ['armors'] -"bracken:blinding_fix": ['can_unbreak'] -"bracken:boldness": ['armors'] -"bracken:butchering": ['melee_weapons', 'mace'] -"bracken:chiseling_fix": ['axes', 'pickaxes', 'shovels', 'hoes'] -"bracken:decaying_fix": ['can_unbreak'] -"bracken:defusing": ['melee_weapons', 'mace'] -"bracken:dentine_touch": ['axes', 'pickaxes', 'shovels', 'hoes'] -"bracken:devouring_curse": ['melee_weapons', 'mace'] -"bracken:dullness_curse": ['melee_weapons', 'mace'] -"bracken:famine_walker": ['boots'] -"bracken:ferocity": ['melee_weapons', 'mace'] -"bracken:flame_walker": ['boots'] -"bracken:float_walker": ['boots'] -"bracken:flood_walker": ['boots'] -"bracken:fragility_curse": ['can_unbreak'] -"bracken:freezing_fix": ['can_unbreak'] -"bracken:guarding": ['melee_weapons', 'mace'] -"bracken:huskiness": ['pet_armor'] -"bracken:infused_fire_aspect_fix": ['melee_weapons', 'mace'] -"bracken:infused_frost_walker_fix": ['boots'] -"bracken:infused_mending_fix": ['can_unbreak'] -"bracken:infused_thorns_fix": ['armors'] -"bracken:integrity_fix": ['armors'] -"bracken:lethargy_curse": ['melee_weapons', 'mace'] -"bracken:lifesteal": ['bow'] -"bracken:litheness": ['pet_armor'] -"bracken:maiming_curse": ['armors'] -"bracken:mortality": ['melee_weapons', 'mace'] -"bracken:poisoning_fix": ['can_unbreak'] -"bracken:pugnacity": ['wolf_armor'] -"bracken:pushback": ['armors'] -"bracken:quenching_fix": ['armors'] -"bracken:rending": ['crossbow'] -"bracken:reverse_thorns": ['axes'] -"bracken:searing_surface": ['armors'] -"bracken:sentience_curse_1": ['can_unbreak'] -"bracken:sentience_curse_2": ['can_unbreak'] -"bracken:sentience_curse_3": ['can_unbreak'] -"bracken:sentience_curse_4": ['can_unbreak'] -"bracken:sentience_curse_5": ['can_unbreak'] -"bracken:sentience_curse_6": ['can_unbreak'] -"bracken:sentience_curse_7": ['can_unbreak'] -"bracken:shrewdness": ['swords'] -"bracken:silvered_fix": ['can_unbreak'] -"bracken:spectrality_fix": ['melee_weapons', 'mace'] -"bracken:splintering": ['bow'] -"bracken:trampling": ['horse_armor'] -"bracken:vitality_fix": ['armors'] -"bracken:weakening_fix": ['can_unbreak'] -"bracken:wisdom": ['tools'] -"bracken:withering_fix": ['can_unbreak'] diff --git a/src/main/resources/datapack/bracken/item_groups.yml b/src/main/resources/datapack/bracken/item_groups.yml deleted file mode 100644 index 8248f0c..0000000 --- a/src/main/resources/datapack/bracken/item_groups.yml +++ /dev/null @@ -1,15 +0,0 @@ -horse_armor: - items: - - leather_horse_armor - - iron_horse_armor - - golden_horse_armor - - diamond_horse_armor - -wolf_armor: - items: - - wolf_armor - -pet_armor: - groups: - - wolf_armor - - horse_armor \ No newline at end of file diff --git a/src/main/resources/datapack/dungeons_and_taverns/enchant_conflict.yml b/src/main/resources/datapack/dungeons_and_taverns/enchant_conflict.yml deleted file mode 100644 index 5ebd042..0000000 --- a/src/main/resources/datapack/dungeons_and_taverns/enchant_conflict.yml +++ /dev/null @@ -1,21 +0,0 @@ -"nova_structures:power": ['#dungeon_at_might', '#dungeon_at_powah'] -"nova_structures:ghasted": ['#crossbow_conflict'] -"nova_structures:gravity": ['#crossbow_conflict'] -"nova_structures:antidote": ['#protection_enchant_conflict'] -"nova_structures:piercing": ['#dungeon_at_structure_bow'] -"nova_structures:traveler": ['#dungeon_at_boots'] -"nova_structures:multishot": ['#dungeon_at_structure_bow'] -"nova_structures:wax_wings": ['#dungeon_at_elytra'] -"nova_structures:aerials_bane": ['#dungeon_at_powah', '#sword_enchant_conflict'] -"nova_structures:shulker_boss": ['minecraft:unbreaking'] -"nova_structures:illagers_bane": ['#sword_enchant_conflict'] -"nova_structures:wither_coated": ['#dungeon_at_sword_effect'] -"nova_structures:boss_behaviour": ['minecraft:unbreaking'] -"nova_structures:photosynthesis": ['#dungeon_at_repair'] -"nova_structures:shulker_miniboss": ['minecraft:unbreaking'] -"minecraft:soul_speed": ['#dungeon_at_boots'] -"minecraft:mending": ['#dungeon_at_repair'] -"minecraft:power": ['#dungeon_at_powah'] -"minecraft:unbreaking": ['#dungeon_at_elytra'] -"minecraft:infinity": ['#dungeon_at_structure_bow'] -"minecraft:fire_aspect": ['#dungeon_at_sword_effect'] diff --git a/src/main/resources/datapack/dungeons_and_taverns/item_conflict.yml b/src/main/resources/datapack/dungeons_and_taverns/item_conflict.yml deleted file mode 100644 index d98c5dd..0000000 --- a/src/main/resources/datapack/dungeons_and_taverns/item_conflict.yml +++ /dev/null @@ -1,18 +0,0 @@ -"nova_structures:power": ['crossbow'] -"nova_structures:ghasted": ['crossbow'] -"nova_structures:gravity": ['crossbow'] -"nova_structures:antidote": ['chestplate'] -"nova_structures:outreach": ['chestplate'] -"nova_structures:piercing": ['bow'] -"nova_structures:spiteful": ['melee_weapons'] -"nova_structures:traveler": ['boots'] -"nova_structures:multishot": ['bow'] -"nova_structures:wax_wings": ['elytra'] -"nova_structures:aerials_bane": ['combat_tools'] -"nova_structures:shulker_boss": ['stick'] -"nova_structures:illagers_bane": ['melee_weapons'] -"nova_structures:wither_coated": ['mace', 'melee_weapons'] -"nova_structures:boss_behaviour": ['stick', 'flint'] -"nova_structures:photosynthesis": ['can_unbreak'] -"nova_structures:shulker_miniboss": ['stick'] -"nova_structures:conductivity_curse": ['metal'] diff --git a/src/main/resources/datapack/dungeons_and_taverns/item_groups.yml b/src/main/resources/datapack/dungeons_and_taverns/item_groups.yml deleted file mode 100644 index 45fc3b7..0000000 --- a/src/main/resources/datapack/dungeons_and_taverns/item_groups.yml +++ /dev/null @@ -1,56 +0,0 @@ -metal: - type: include - items: - - shield - - trident - - flint_and_steel - - shears - - brush - - mace - - chainmail_chestplate - - golden_chestplate - - iron_chestplate - - netherite_chestplate - - chainmail_boots - - golden_boots - - iron_boots - - netherite_boots - - chainmail_leggings - - golden_leggings - - iron_leggings - - netherite_leggings - - chainmail_helmet - - golden_helmet - - iron_helmet - - netherite_helmet - - golden_pickaxe - - iron_pickaxe - - netherite_pickaxe - - golden_axe - - iron_axe - - netherite_axe - - golden_shovel - - iron_shovel - - netherite_shovel - - golden_sword - - iron_sword - - netherite_sword - - golden_hoe - - iron_hoe - - netherite_hoe - - trial_key - - ominous_trial_key - -combat_tools: - type: include - groups: - - melee_weapons - - bow - - crossbow - - trident - - mace - -flint: - type: include - items: - - flint \ No newline at end of file diff --git a/src/main/resources/datapack/enchantplus/enchant_conflict.yml b/src/main/resources/datapack/enchantplus/enchant_conflict.yml deleted file mode 100644 index a8e3e61..0000000 --- a/src/main/resources/datapack/enchantplus/enchant_conflict.yml +++ /dev/null @@ -1,40 +0,0 @@ -"enchantplus:bow/echo_shot": ['#enchantplus_bow'] -"enchantplus:bow/storm_arrow": ['#enchantplus_bow'] -"enchantplus:bow/eternal_frost": ['#enchantplus_bow'] -"enchantplus:bow/breezing_arrow": ['#enchantplus_bow'] -"enchantplus:bow/explosive_arrow": ['#enchantplus_bow'] -"enchantplus:mace/teluric_wave": ['#enchantplus_mace'] -"enchantplus:armor/fury": ['#enchantplus_armor'] -"enchantplus:armor/lifeplus": ['#enchantplus_armor'] -"enchantplus:armor/venom_protection": ['#protection_enchant_conflict'] -"enchantplus:boots/lava_walker": ['#boot_conflict'] -"enchantplus:boots/step_assist": ['#boot_conflict'] -"enchantplus:sword/fear": ['#enchantplus_sword_effect'] -"enchantplus:sword/pull": ['#enchantplus_sword_effect'] -"enchantplus:sword/reach": ['#enchantplus_sword_attribute'] -"enchantplus:sword/critical": ['#enchantplus_sword_attribute'] -"enchantplus:sword/xp_boost": ['#enchantplus_experience'] -"enchantplus:sword/last_hope": ['#enchantplus_sword_effect'] -"enchantplus:sword/life_steal": ['#enchantplus_sword_effect'] -"enchantplus:sword/death_touch": ['#enchantplus_sword_effect'] -"enchantplus:sword/attack_speed": ['#enchantplus_sword_attribute'] -"enchantplus:sword/poison_aspect": ['#enchantplus_aspect'] -"enchantplus:sword/runic_despair": ['#enchantplus_sword_attribute'] -"enchantplus:sword/dimensional_hit": ['#enchantplus_sword_attribute'] -"enchantplus:sword/tears_of_asflors": ['#enchantplus_sword_effect'] -"enchantplus:tools/auto_smelt": ['minecraft:silk_touch'] -"enchantplus:tools/miningplus": ['#enchantplus_mining'] -"enchantplus:pickaxe/vein_miner": ['#enchantplus_mining'] -"enchantplus:pickaxe/spawner_touch": ['#enchantplus_mining'] -"enchantplus:pickaxe/bedrock_breaker": ['#enchantplus_mining'] -"enchantplus:trident/gungnir_breath": ['#enchantplus_trident'] -"enchantplus:leggings/dwarfed": ['#enchantplus_size'] -"enchantplus:leggings/oversize": ['#enchantplus_size'] -"enchantplus:durability/curse_of_enchant": ['#enchantplus_durability', 'minecraft:unbreaking', 'minecraft:mending'] -"enchantplus:durability/curse_of_breaking": ['#enchantplus_durability', 'minecraft:unbreaking', 'minecraft:mending'] -"minecraft:protection": ['#enchantplus_armor'] -"minecraft:quick_charge": ['#enchantplus_bow'] -"minecraft:mending": ['#enchantplus_experience'] -"minecraft:fire_aspect": ['#enchantplus_aspect'] -"minecraft:channeling": ['#enchantplus_trident'] -"minecraft:wind_burst": ['#enchantplus_mace'] diff --git a/src/main/resources/datapack/enchantplus/item_conflict.yml b/src/main/resources/datapack/enchantplus/item_conflict.yml deleted file mode 100644 index 8dafc57..0000000 --- a/src/main/resources/datapack/enchantplus/item_conflict.yml +++ /dev/null @@ -1,55 +0,0 @@ -"enchantplus:axe/timber": ['axes'] -"enchantplus:bow/rebound": ['bow', 'crossbow'] -"enchantplus:bow/echo_shot": ['bow', 'crossbow'] -"enchantplus:bow/storm_arrow": ['bow', 'crossbow'] -"enchantplus:bow/accuracy_shot": ['bow', 'crossbow'] -"enchantplus:bow/eternal_frost": ['bow', 'crossbow'] -"enchantplus:bow/breezing_arrow": ['bow', 'crossbow'] -"enchantplus:bow/explosive_arrow": ['bow', 'crossbow'] -"enchantplus:hoe/harvest": ['hoes'] -"enchantplus:hoe/scyther": ['hoes'] -"enchantplus:mace/striker": ['mace'] -"enchantplus:mace/teluric_wave": ['mace'] -"enchantplus:mace/wind_propulsion": ['mace'] -"enchantplus:armor/fury": ['armors'] -"enchantplus:armor/lifeplus": ['armors'] -"enchantplus:armor/venom_protection": ['armors'] -"enchantplus:boots/agility": ['boots'] -"enchantplus:boots/lava_walker": ['boots'] -"enchantplus:boots/step_assist": ['boots'] -"enchantplus:sword/fear": ['swords'] -"enchantplus:sword/pull": ['melee_weapons'] -"enchantplus:sword/reach": ['swords'] -"enchantplus:sword/critical": ['swords'] -"enchantplus:sword/xp_boost": ['mining_and_damage'] -"enchantplus:sword/last_hope": ['swords'] -"enchantplus:sword/life_steal": ['melee_weapons'] -"enchantplus:sword/death_touch": ['melee_weapons'] -"enchantplus:sword/attack_speed": ['swords'] -"enchantplus:sword/poison_aspect": ['melee_weapons'] -"enchantplus:sword/runic_despair": ['swords'] -"enchantplus:sword/dimensional_hit": ['swords'] -"enchantplus:sword/tears_of_asflors": ['swords'] -"enchantplus:tools/auto_smelt": ['axes', 'pickaxes', 'shovels', 'hoes'] -"enchantplus:tools/miningplus": ['axes', 'pickaxes', 'shovels', 'hoes'] -"enchantplus:elytra/armored": ['elytra'] -"enchantplus:elytra/kinetic_protection": ['elytra'] -"enchantplus:helmet/voidless": ['helmets'] -"enchantplus:helmet/auto_feed": ['helmets'] -"enchantplus:helmet/bright_vision": ['helmets'] -"enchantplus:mounted/velocity": ['mounted_armor'] -"enchantplus:mounted/steel_fang": ['wolf_armor'] -"enchantplus:mounted/cavalier_egis": ['mounted_armor'] -"enchantplus:mounted/ethereal_leap": ['mounted_armor'] -"enchantplus:pickaxe/vein_miner": ['pickaxes'] -"enchantplus:pickaxe/spawner_touch": ['pickaxes'] -"enchantplus:pickaxe/bedrock_breaker": ['pickaxes'] -"enchantplus:trident/gungnir_breath": ['trident'] -"enchantplus:leggings/dwarfed": ['leggings'] -"enchantplus:leggings/leaping": ['leggings'] -"enchantplus:leggings/oversize": ['leggings'] -"enchantplus:leggings/fast_swim": ['leggings'] -"enchantplus:chestplate/builder_arm": ['chestplate'] -"enchantplus:durability/curse_of_enchant": ['can_unbreak'] -"enchantplus:durability/curse_of_breaking": ['can_unbreak'] -"enchantplus:midas_touch": ['stick'] diff --git a/src/main/resources/datapack/enchantplus/item_groups.yml b/src/main/resources/datapack/enchantplus/item_groups.yml deleted file mode 100644 index 74854de..0000000 --- a/src/main/resources/datapack/enchantplus/item_groups.yml +++ /dev/null @@ -1,30 +0,0 @@ -mining_and_damage: - groups: - - melee_weapons - - mace - - bow - - crossbow - - mace - - trident - - tools - -stick: - items: - - stick - -wolf_armor: - items: - - wolf_armor - -mounted_armor: - items: - - diamond_horse_armor - - golden_horse_armor - - iron_horse_armor - - leather_horse_armor - groups: - - wolf_armor - -elytra: - items: - - elytra \ No newline at end of file diff --git a/src/main/resources/enchant_conflict.yml b/src/main/resources/enchant_conflict.yml index 45d62c3..c5fea81 100644 --- a/src/main/resources/enchant_conflict.yml +++ b/src/main/resources/enchant_conflict.yml @@ -1,8 +1,3 @@ -# -# It is recommended that you use /configanvil to edit theses config. -# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! -# - # material conflicts # # If you want to edit this file: @@ -17,163 +12,159 @@ # ---------------------------------------------------- restriction_aqua_affinity: - enchantments: [ minecraft:aqua_affinity ] - notAffectedGroups: [ enchanted_book, helmets ] + enchantments: [aqua_affinity] + notAffectedGroups: [enchanted_book, helmets] restriction_bane_of_arthropods: - enchantments: [ minecraft:bane_of_arthropods ] - notAffectedGroups: [ enchanted_book, melee_weapons ] + enchantments: [bane_of_arthropods] + notAffectedGroups: [enchanted_book, melee_weapons] restriction_blast_protection: - enchantments: [ minecraft:blast_protection ] - notAffectedGroups: [ enchanted_book, armors ] + enchantments: [blast_protection] + notAffectedGroups: [enchanted_book, armors] restriction_channeling: - enchantments: [ minecraft:channeling ] - notAffectedGroups: [ enchanted_book, trident ] + enchantments: [channeling] + notAffectedGroups: [enchanted_book, trident] restriction_binding_curse: - enchantments: [ minecraft:binding_curse ] - notAffectedGroups: [ enchanted_book, wearable ] + enchantments: [binding_curse] + notAffectedGroups: [enchanted_book, wearable] restriction_vanishing_curse: - enchantments: [ minecraft:vanishing_curse ] - notAffectedGroups: [ enchanted_book, can_vanish ] + enchantments: [vanishing_curse] + notAffectedGroups: [enchanted_book, can_vanish] restriction_depth_strider: - enchantments: [ minecraft:depth_strider ] - notAffectedGroups: [ enchanted_book, boots ] + enchantments: [depth_strider] + notAffectedGroups: [enchanted_book, boots] restriction_efficiency: - enchantments: [ minecraft:efficiency ] - notAffectedGroups: [ enchanted_book, tools, shears ] + enchantments: [efficiency] + notAffectedGroups: [enchanted_book, tools, shears] restriction_feather_falling: - enchantments: [ minecraft:feather_falling ] - notAffectedGroups: [ enchanted_book, boots ] + enchantments: [feather_falling] + notAffectedGroups: [enchanted_book, boots] restriction_fire_aspect: - enchantments: [ minecraft:fire_aspect ] - notAffectedGroups: [ enchanted_book, swords ] + enchantments: [fire_aspect] + notAffectedGroups: [enchanted_book, swords] restriction_fire_protection: - enchantments: [ minecraft:fire_protection ] - notAffectedGroups: [ enchanted_book, armors ] + enchantments: [fire_protection] + notAffectedGroups: [enchanted_book, armors] restriction_flame: - enchantments: [ minecraft:flame ] - notAffectedGroups: [ enchanted_book, bow ] + enchantments: [flame] + notAffectedGroups: [enchanted_book, bow] restriction_fortune: - enchantments: [ minecraft:fortune ] - notAffectedGroups: [ enchanted_book, tools ] + enchantments: [fortune] + notAffectedGroups: [enchanted_book, tools] restriction_frost_walker: - enchantments: [ minecraft:frost_walker ] - notAffectedGroups: [ enchanted_book, boots ] + enchantments: [frost_walker] + notAffectedGroups: [enchanted_book, boots] restriction_impaling: - enchantments: [ minecraft:impaling ] - notAffectedGroups: [ enchanted_book, trident ] + enchantments: [impaling] + notAffectedGroups: [enchanted_book, trident] restriction_infinity: - enchantments: [ minecraft:infinity ] - notAffectedGroups: [ enchanted_book, bow ] + enchantments: [infinity] + notAffectedGroups: [enchanted_book, bow] restriction_knockback: - enchantments: [ minecraft:knockback ] - notAffectedGroups: [ enchanted_book, swords ] + enchantments: [knockback] + notAffectedGroups: [enchanted_book, swords] restriction_looting: - enchantments: [ minecraft:looting ] - notAffectedGroups: [ enchanted_book, swords ] + enchantments: [looting] + notAffectedGroups: [enchanted_book, swords] restriction_loyalty: - enchantments: [ minecraft:loyalty ] - notAffectedGroups: [ enchanted_book, trident ] - -restriction_luck_of_the_sea: - enchantments: [ minecraft:luck_of_the_sea ] - notAffectedGroups: [ enchanted_book, fishing_rod ] + enchantments: [loyalty] + notAffectedGroups: [enchanted_book, trident] restriction_lure: - enchantments: [ minecraft:lure ] - notAffectedGroups: [ enchanted_book, fishing_rod ] + enchantments: [lure] + notAffectedGroups: [enchanted_book, fishing_rod] restriction_mending: - enchantments: [ minecraft:mending ] - notAffectedGroups: [ enchanted_book, can_unbreak ] + enchantments: [mending] + notAffectedGroups: [enchanted_book, can_unbreak] -restriction_minecraft_multishot: - enchantments: [ minecraft:multishot ] - notAffectedGroups: [ enchanted_book, crossbow ] +restriction_multishot: + enchantments: [multishot] + notAffectedGroups: [enchanted_book, crossbow] restriction_piercing: - enchantments: [ minecraft:piercing ] - notAffectedGroups: [ enchanted_book, crossbow ] + enchantments: [piercing] + notAffectedGroups: [enchanted_book, crossbow] restriction_power: - enchantments: [ minecraft:power ] - notAffectedGroups: [ enchanted_book, bow ] + enchantments: [power] + notAffectedGroups: [enchanted_book, bow] restriction_projectile_protection: - enchantments: [ minecraft:projectile_protection ] - notAffectedGroups: [ enchanted_book, armors ] + enchantments: [projectile_protection] + notAffectedGroups: [enchanted_book, armors] restriction_protection: - enchantments: [ minecraft:protection ] - notAffectedGroups: [ enchanted_book, armors ] + enchantments: [protection] + notAffectedGroups: [enchanted_book, armors] restriction_punch: - enchantments: [ minecraft:punch ] - notAffectedGroups: [ enchanted_book, bow ] + enchantments: [punch] + notAffectedGroups: [enchanted_book, bow] restriction_quick_charge: - enchantments: [ minecraft:quick_charge ] - notAffectedGroups: [ enchanted_book, crossbow ] + enchantments: [quick_charge] + notAffectedGroups: [enchanted_book, crossbow] restriction_respiration: - enchantments: [ minecraft:respiration ] - notAffectedGroups: [ enchanted_book, helmets ] + enchantments: [respiration] + notAffectedGroups: [enchanted_book, helmets] restriction_riptide: - enchantments: [ minecraft:riptide ] - notAffectedGroups: [ enchanted_book, trident ] + enchantments: [riptide] + notAffectedGroups: [enchanted_book, trident] restriction_sharpness: - enchantments: [ minecraft:sharpness ] - notAffectedGroups: [ enchanted_book, melee_weapons ] + enchantments: [sharpness] + notAffectedGroups: [enchanted_book, melee_weapons] -restriction__silk_touch: - enchantments: [ minecraft:silk_touch ] - notAffectedGroups: [ enchanted_book, tools ] +restriction_silk_touch: + enchantments: [silk_touch] + notAffectedGroups: [enchanted_book, tools] restriction_smite: - enchantments: [ minecraft:smite ] - notAffectedGroups: [ enchanted_book, melee_weapons ] + enchantments: [smite] + notAffectedGroups: [enchanted_book, melee_weapons] restriction_soul_speed: - enchantments: [ minecraft:soul_speed ] - notAffectedGroups: [ enchanted_book, boots ] + enchantments: [soul_speed] + notAffectedGroups: [enchanted_book, boots] -restriction_sweeping_edge: - enchantments: [ minecraft:sweeping, minecraft:sweeping_edge ] - notAffectedGroups: [ enchanted_book, swords ] +restriction_sweeping: + enchantments: [sweeping] + notAffectedGroups: [enchanted_book, swords] # Do not exist in 1.18, that mean useInFuture will be set to true # useInFuture set to true also mean it will not warn if there is an issue restriction_swift_sneak: useInFuture: true - enchantments: [ minecraft:swift_sneak ] - notAffectedGroups: [ enchanted_book, leggings ] + enchantments: [swift_sneak] + notAffectedGroups: [enchanted_book, boots] restriction_thorns: - enchantments: [ minecraft:thorns ] - notAffectedGroups: [ enchanted_book, armors ] + enchantments: [thorns] + notAffectedGroups: [enchanted_book, armors] -restriction__unbreaking: - enchantments: [ minecraft:unbreaking ] - notAffectedGroups: [ enchanted_book, can_unbreak ] +restriction_unbreaking: + enchantments: [unbreaking] + notAffectedGroups: [enchanted_book, can_unbreak] # ---------------------------------------------------- # Now we have conflicts about enchantment Incompatibility @@ -184,64 +175,60 @@ restriction__unbreaking: sword_enchant_conflict: enchantments: - - minecraft:bane_of_arthropods - - minecraft:smite - - minecraft:sharpness - notAffectedGroups: [ ] + - bane_of_arthropods + - smite + - sharpness + notAffectedGroups: [] maxEnchantmentBeforeConflict: 1 protection_enchant_conflict: enchantments: - - minecraft:blast_protection - - minecraft:fire_protection - - minecraft:projectile_protection - - minecraft:protection - notAffectedGroups: [ ] + - blast_protection + - fire_protection + - projectile_protection + - protection + notAffectedGroups: [] maxEnchantmentBeforeConflict: 1 trident_conflict1: enchantments: - - minecraft:channeling - - minecraft:riptide - notAffectedGroups: [ ] + - channeling + - riptide + notAffectedGroups: [] maxEnchantmentBeforeConflict: 1 trident_conflict2: enchantments: - - minecraft:loyalty - - minecraft:riptide - notAffectedGroups: [ ] + - loyalty + - riptide + notAffectedGroups: [] maxEnchantmentBeforeConflict: 1 boot_conflict: enchantments: - - minecraft:depth_strider - - minecraft:frost_walker - notAffectedGroups: [ ] + - depth_strider + - frost_walker + notAffectedGroups: [] maxEnchantmentBeforeConflict: 1 tool_conflict: enchantments: - - minecraft:fortune - - minecraft:silk_touch - notAffectedGroups: [ ] + - fortune + - silk_touch + notAffectedGroups: [] maxEnchantmentBeforeConflict: 1 bow_conflict: enchantments: - - minecraft:mending - - minecraft:infinity - notAffectedGroups: [ ] + - mending + - infinity + notAffectedGroups: [] maxEnchantmentBeforeConflict: 1 crossbow_conflict: enchantments: - - minecraft:multishot - - minecraft:piercing - notAffectedGroups: [ ] + - multishot + - piercing + notAffectedGroups: [] maxEnchantmentBeforeConflict: 1 -# ---------------------------------------------------- -# Bellow is for custom conflicts. -# This is also where conflict create from the gui will be placed. -# ---------------------------------------------------- diff --git a/src/main/resources/item_groups.yml b/src/main/resources/item_groups.yml index 8a62f3d..2e222aa 100644 --- a/src/main/resources/item_groups.yml +++ b/src/main/resources/item_groups.yml @@ -1,8 +1,3 @@ -# -# It is recommended that you use /configanvil to edit theses config. -# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! -# - # Please note this config use spigot material names. # It should match minecraft name in most case, maybe every case, but I can't be sure # In case there an issue with material name, you can found them here: @@ -126,7 +121,7 @@ wearable: groups: - armors -pickaxes: +tools: type: include items: - wooden_pickaxe @@ -135,33 +130,19 @@ pickaxes: - diamond_pickaxe - golden_pickaxe - netherite_pickaxe - -shovels: - type: include - items: - wooden_shovel - stone_shovel - iron_shovel - diamond_shovel - golden_shovel - netherite_shovel - -hoes: - type: include - items: - wooden_hoe - stone_hoe - iron_hoe - diamond_hoe - golden_hoe - netherite_hoe - -tools: - type: include groups: - - pickaxes - - shovels - - hoes - axes enchanted_book: diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index dab9997..8c0e480 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,83 +1,20 @@ -main: io.delilaheve.CustomAnvil -name: CustomAnvil -prefix: "Custom Anvil" -version: ${version} -folia-supported: true -description: Allow to customise anvil mechanics -api-version: 1.16 +main: io.delilaheve.UnsafeEnchants +name: UnsafeEnchantsPlus +prefix: UnsafeEnchants+ +version: 1.1.4 +description: Allow custom illegal enchantment +api-version: 1.18 load: POSTWORLD -authors: [ DelilahEve, alexcrea ] -libraries: [${libraries}] - -commands: - customanvil: - description: Generic command for custom anvil - aliases: - - ca - anvilconfigreload: - description: Reload every config of this plugin - permission: ca.command.reload - aliases: - #- acreload # anvil config reload - #- careload # custom anvil reload - - carl # custom anvil reload - customanvilconfig: - description: open a menu for administrator to edit plugin's config in game - permission: ca.config.edit - aliases: - - configanvil - +authors: [DelilahEve, alexcrea] +libraries: + - org.jetbrains.kotlin:kotlin-stdlib:1.6.21 permissions: - ca.affected: + ue.unsafe: default: true - description: Player with this permission will be affected by the plugin - ca.bypass.fuse: + description: Allow player to combine allowed "unsafe" enchants + ue.bypass.fuse: default: false - description: Allow player to combine every enchantments to every item (no custom limit) - ca.bypass.level: + description: Allow player to combine every "unsafe" enchants + ue.bypass.level: default: false - description: Allow player to bypass every level limit (no custom limit) - ca.command.reload: - default: op - description: Allow administrator to reload the plugin's configs - ca.command.diagnostic: - default: op - description: Get debug information about the plugin and server - ca.config.edit: - default: op - description: Allow administrator to edit the plugin's config in game - # color permissions - ca.color.code: - default: op - description: Allow player to use color code if enabled (toggleable) - ca.color.hex: - default: op - description: Allow player to use hexadecimal color if enabled (toggleable) - ca.rename.minimessage: - default: op - description: Allow player to use minimessage formating on rename if enabled (toggleable) (only legacy compatible at the time) - # lore edit permissions - ca.lore_edit.book: - default: op - description: Allow player to edit lore via book and quil if enabled (toggleable) - ca.lore_edit.paper: - default: op - description: Allow player to edit lore via paper if enabled (toggleable) - # dialog menu permission - ca.rename.dialog: - default: op - description: Allow player to use the dialog rename menu (toggleable) - - -# soft depend on old name of this plugin (UnsafeEnchantsPlus), so I can disable it if it is on the same server -# Also depend to other plugin for compatibility -softdepend: - - UnsafeEnchantsPlus - - ProtocolLib - - Disenchantment - - EnchantsSquared - - EcoEnchants - - eco - - ExcellentEnchants - - HavenBags - - SuperEnchants + description: Allow player to bypass max level limit \ No newline at end of file diff --git a/src/main/resources/unit_repair_item.yml b/src/main/resources/unit_repair_item.yml deleted file mode 100644 index 2902cce..0000000 --- a/src/main/resources/unit_repair_item.yml +++ /dev/null @@ -1,190 +0,0 @@ -# -# It is recommended that you use /configanvil to edit theses config. -# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! -# - -# Unit repair configuration -# -# This configuration is to make custom unit repair -# A unit repair is, for example, a diamond to repair a diamond sword -# In vanilla, a unit repair 25% of object durability -# you can make a custom value here -# -# Item name should NOT combine caps and no caps (example: Stone) - -# Default value if the config is an invalid value (value <= 0 ) -# If value > 1 it will be treated as being = 1 -default_repair_amount: 0.25 - -# You can add custom unit repair -# The example bellow make a shield repaired by 10% by sticks - -#stick: -# shield: 0.10 - - -# Vanilla unit repair group is bellow -diamond: - diamond_helmet: 0.25 - diamond_chestplate: 0.25 - diamond_leggings: 0.25 - diamond_boots: 0.25 - diamond_sword: 0.25 - diamond_pickaxe: 0.25 - diamond_axe: 0.25 - diamond_shovel: 0.25 - diamond_hoe: 0.25 - -netherite_ingot: - netherite_helmet: 0.25 - netherite_chestplate: 0.25 - netherite_leggings: 0.25 - netherite_boots: 0.25 - netherite_sword: 0.25 - netherite_pickaxe: 0.25 - netherite_axe: 0.25 - netherite_shovel: 0.25 - netherite_hoe: 0.25 - -gold_ingot: - golden_helmet: 0.25 - golden_chestplate: 0.25 - golden_leggings: 0.25 - golden_boots: 0.25 - golden_sword: 0.25 - golden_pickaxe: 0.25 - golden_axe: 0.25 - golden_shovel: 0.25 - golden_hoe: 0.25 - -iron_ingot: - iron_helmet: 0.25 - iron_chestplate: 0.25 - iron_leggings: 0.25 - iron_boots: 0.25 - iron_sword: 0.25 - iron_pickaxe: 0.25 - iron_axe: 0.25 - iron_shovel: 0.25 - iron_hoe: 0.25 - -cobblestone: - stone_sword: 0.25 - stone_pickaxe: 0.25 - stone_axe: 0.25 - stone_shovel: 0.25 - stone_hoe: 0.25 - -cobbled_deepslate: - stone_sword: 0.25 - stone_pickaxe: 0.25 - stone_axe: 0.25 - stone_shovel: 0.25 - stone_hoe: 0.25 - -blackstone: - stone_sword: 0.25 - stone_pickaxe: 0.25 - stone_axe: 0.25 - stone_shovel: 0.25 - stone_hoe: 0.25 - -leather: - leather_helmet: 0.25 - leather_chestplate: 0.25 - leather_leggings: 0.25 - leather_boots: 0.25 - -phantom_membrane: - elytra: 0.25 - -scute: - turtle_helmet: 0.25 - -oak_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -spruce_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -birch_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -jungle_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -acacia_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -dark_oak_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -mangrove_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -cherry_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -bamboo_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -crimson_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 - -warped_planks: - wooden_sword: 0.25 - wooden_pickaxe: 0.25 - wooden_axe: 0.25 - wooden_shovel: 0.25 - wooden_hoe: 0.25 - shield: 0.25 diff --git a/src/test/java/io/delilaheve/CustomAnvilTests.java b/src/test/java/io/delilaheve/CustomAnvilTests.java deleted file mode 100644 index 12e1ec1..0000000 --- a/src/test/java/io/delilaheve/CustomAnvilTests.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.delilaheve; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import xyz.alexcrea.cuanvil.tests.DefaultCustomAnvilTest; - -public class CustomAnvilTests extends DefaultCustomAnvilTest { - - @Test - public void simpleInitTest() { - try { - Assertions.assertNotNull(server); - Assertions.assertNotNull(plugin); - - // Test shutdown - plugin.onDisable(); - } catch (Exception e) { - Assertions.fail(e); - } - } - -} diff --git a/src/test/java/io/delilaheve/util/EnchantmentUtilTests.java b/src/test/java/io/delilaheve/util/EnchantmentUtilTests.java deleted file mode 100644 index 10ea252..0000000 --- a/src/test/java/io/delilaheve/util/EnchantmentUtilTests.java +++ /dev/null @@ -1,184 +0,0 @@ -package io.delilaheve.util; - -import io.delilaheve.CustomAnvil; -import org.bukkit.Material; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.AnvilInventory; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.permissions.PermissionAttachment; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockbukkit.mockbukkit.entity.PlayerMock; -import org.mockbukkit.mockbukkit.inventory.ItemStackMock; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.tests.ConfigResetCustomAnvilTest; -import xyz.alexcrea.cuanvil.data.AnvilFuseTestData; -import xyz.alexcrea.cuanvil.util.AnvilFuseTestUtil; - -import java.util.List; - -public class EnchantmentUtilTests extends ConfigResetCustomAnvilTest { - - private AnvilInventory anvil; - private PlayerMock player; - - @Override - @BeforeEach - public void setUp() { - super.setUp(); - // Mock used player & open anvil - player = server.addPlayer(); - - Inventory anvil = server.createInventory(player, InventoryType.ANVIL); - - this.anvil = (AnvilInventory) anvil; - player.openInventory(anvil); - - ConfigHolder.DEFAULT_CONFIG.getConfig().set("debug_log", true); - ConfigHolder.DEFAULT_CONFIG.getConfig().set("debug_log_verbose", true); - } - - @Test - public void testBypassFuse(){ - // Test permission did not changed (if it do then server owner should be warned) - String permission = CustomAnvil.bypassFusePermission; - Assertions.assertEquals("ca.bypass.fuse", permission, "bypass fuse permission changed. " + - "Caution with that as it will break some server CustomAnvil setup."); - - // Create ingredient item - ItemStack normalStick = new ItemStackMock(Material.STICK); - ItemStack sharpnessBook = AnvilFuseTestUtil.prepareItem( - Material.ENCHANTED_BOOK, - List.of("sharpness"), 1); - - ItemStack sharpnessStick = AnvilFuseTestUtil.prepareItem( - Material.STICK, - List.of("sharpness"), 1); - - // Create result item - ItemStack sharpnessResultStick = AnvilFuseTestUtil.prepareItem( - Material.STICK, 1, - List.of("sharpness"), 1); - ItemStack sharpness2ResultStick = AnvilFuseTestUtil.prepareItem( - Material.STICK, 1, - List.of("sharpness"), 2); - - // Create failing anvil fuse data - AnvilFuseTestData nullResultData = new AnvilFuseTestData( - normalStick, sharpnessBook, - null - ); - AnvilFuseTestData nullResultData2 = new AnvilFuseTestData( - sharpnessStick, sharpnessStick, - null - ); - - // Create successful anvil fuse data - AnvilFuseTestData legalResultData = new AnvilFuseTestData( - normalStick, sharpnessBook, - sharpnessResultStick - // TODO add expected price - ); - AnvilFuseTestData legalResultData2 = new AnvilFuseTestData( - sharpnessStick, sharpnessStick, - sharpness2ResultStick - // TODO add expected price - ); - - // Test with no permission - nullResultData.executeTest(anvil, player); - nullResultData2.executeTest(anvil, player); - - // Add permission - PermissionAttachment attachment = player.addAttachment(plugin); - attachment.setPermission(permission, true); - - // Test with new permission - legalResultData.executeTest(anvil, player); - legalResultData2.executeTest(anvil, player); - } - - @Test - public void testLeveLimitFuse(){ - String permission = CustomAnvil.bypassLevelPermission; - Assertions.assertEquals("ca.bypass.level", permission, "level fuse permission changed. " + - "Caution with that as it will break some server CustomAnvil setup."); - - // Create ingredient item - ItemStack sharpness5Sword = AnvilFuseTestUtil.prepareItem( - Material.DIAMOND_SWORD, - List.of("sharpness"), 5); - - ItemStack sharpnessBook = AnvilFuseTestUtil.prepareItem( - Material.ENCHANTED_BOOK, - List.of("sharpness"), 1); - ItemStack sharpness5Book = AnvilFuseTestUtil.prepareItem( - Material.ENCHANTED_BOOK, - List.of("sharpness"), 5); - ItemStack sharpness6Book = AnvilFuseTestUtil.prepareItem( - Material.ENCHANTED_BOOK, - List.of("sharpness"), 6); - - // Create result item - ItemStack sharpness2BookResult = AnvilFuseTestUtil.prepareItem( - Material.ENCHANTED_BOOK, 1, - List.of("sharpness"), 2); - ItemStack sharpness6SwordResult = AnvilFuseTestUtil.prepareItem( - Material.DIAMOND_SWORD, 1, - List.of("sharpness"), 6); - - // Create failing anvil fuse data - AnvilFuseTestData nullResultData = new AnvilFuseTestData( - sharpnessBook, sharpnessBook, - null - ); - AnvilFuseTestData nullResultData2 = new AnvilFuseTestData( - sharpness5Sword, sharpness6Book, - null - ); - AnvilFuseTestData nullResultData3 = new AnvilFuseTestData( - sharpness5Sword, sharpness5Book, - null - ); - - // Create successful anvil fuse data - AnvilFuseTestData legalResultData = new AnvilFuseTestData( - sharpnessBook, sharpnessBook, - sharpness2BookResult - // TODO add expected price - ); - AnvilFuseTestData legalResultData2 = new AnvilFuseTestData( - sharpness5Sword, sharpness6Book, - sharpness6SwordResult - // TODO add expected price - ); - AnvilFuseTestData legalResultData3 = new AnvilFuseTestData( - sharpness5Sword, sharpness5Book, - sharpness6SwordResult - // TODO add expected price - ); - - // Test failing result first - nullResultData2.executeTest(anvil, player); - nullResultData3.executeTest(anvil, player); - - // Test working sharpness 2 - legalResultData.executeTest(anvil, player); - - // Set merge limit to 2 & test - ConfigHolder.DEFAULT_CONFIG.getConfig().set("disable-merge-over.minecraft:sharpness", 1); - nullResultData.executeTest(anvil, player); - - // Add permission - PermissionAttachment attachment = player.addAttachment(plugin); - attachment.setPermission(permission, true); - - // Test working sharpness 2 - legalResultData.executeTest(anvil, player); - legalResultData2.executeTest(anvil, player); - legalResultData3.executeTest(anvil, player); - } - -} diff --git a/src/test/java/xyz/alexcrea/cuanvil/anvil/AnvilFuseTests.java b/src/test/java/xyz/alexcrea/cuanvil/anvil/AnvilFuseTests.java deleted file mode 100644 index 19f1d6f..0000000 --- a/src/test/java/xyz/alexcrea/cuanvil/anvil/AnvilFuseTests.java +++ /dev/null @@ -1,126 +0,0 @@ -package xyz.alexcrea.cuanvil.anvil; - -import io.delilaheve.util.ConfigOptions; -import net.kyori.adventure.text.Component; -import org.bukkit.Material; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.AnvilInventory; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.inventory.meta.Repairable; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockbukkit.mockbukkit.entity.PlayerMock; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.tests.SharedCustomAnvilTest; -import xyz.alexcrea.cuanvil.data.AnvilFuseTestData; -import xyz.alexcrea.cuanvil.util.AnvilFuseTestUtil; -import xyz.alexcrea.cuanvil.util.CommonItemUtil; - -public class AnvilFuseTests extends SharedCustomAnvilTest { - - private static AnvilInventory anvil; - private static PlayerMock player; - - @BeforeAll - public static void setUp() { - // Mock used player & open anvil - player = server.addPlayer(); - - Inventory anvil = server.createInventory(player, InventoryType.ANVIL); - - AnvilFuseTests.anvil = (AnvilInventory) anvil; - player.openInventory(anvil); - - ConfigHolder.DEFAULT_CONFIG.getConfig().set(ConfigOptions.DEBUG_LOGGING, true); - ConfigHolder.DEFAULT_CONFIG.getConfig().set(ConfigOptions.VERBOSE_DEBUG_LOGGING, true); - ConfigHolder.DEFAULT_CONFIG.getConfig().set(ConfigOptions.ALLOW_COLOR_CODE, true); // For rename test - } - - @BeforeEach - public void prepareAnvil(){ - anvil.clear(); - } - - @AfterAll - public static void tearDown() { - player = null; - anvil = null; - } - - @Test - public void mergeFuseTest(){ - // Literally just test a sharpness 4 + sharpness 4 - ItemStack sharpness4 = CommonItemUtil.sharpness(4); - - ItemStack sharpness5Result = CommonItemUtil.sharpness(5); - Repairable meta = (Repairable) sharpness5Result.getItemMeta(); - meta.setRepairCost(1); - sharpness5Result.setItemMeta(meta); - - AnvilFuseTestData data = new AnvilFuseTestData( - sharpness4, sharpness4, - sharpness5Result, - 5 - ); - - data.executeTest(anvil, player); - } - - @Test - public void overFuseTest(){ - // Test sharpness 4 + sharpness 5 - ItemStack sharpness4 = CommonItemUtil.sharpness(4); - ItemStack sharpness5 = CommonItemUtil.sharpness(5); - - ItemStack sharpness5Result = CommonItemUtil.sharpness(5); - Repairable meta = (Repairable) sharpness5Result.getItemMeta(); - meta.setRepairCost(1); - sharpness5Result.setItemMeta(meta); - - AnvilFuseTestData data = new AnvilFuseTestData( - sharpness4, sharpness5, - sharpness5Result, - 5 - ); - - data.executeTest(anvil, player); - } - - @Test - public void underFuseTest(){ - // test sharpness 5 + 4. Custom Anvil should not allow it to be as it result as the same item as left item - ItemStack sharpness4 = CommonItemUtil.sharpness(4); - ItemStack sharpness5 = CommonItemUtil.sharpness(5); - - AnvilFuseTestData data = new AnvilFuseTestData( - sharpness5, sharpness4, - null - ); - - data.executeTest(anvil, player); - } - - // Note: currently anvil can only have null name. maybe handle differently later - @Test - public void nullNameResetTest(){ - ItemStack base = new ItemStack(Material.NETHERITE_SWORD); - ItemStack expected = base.clone(); - - ItemMeta meta = expected.getItemMeta(); - meta.displayName(Component.text("test")); - base.setItemMeta(meta); - - AnvilFuseTestData data = new AnvilFuseTestData( - base, null, - expected, expected, null, - 1, null, 1 - ); - - data.executeTest(anvil, player); - } - -} diff --git a/src/test/java/xyz/alexcrea/cuanvil/anvil/LoreEditTests.java b/src/test/java/xyz/alexcrea/cuanvil/anvil/LoreEditTests.java deleted file mode 100644 index 668da58..0000000 --- a/src/test/java/xyz/alexcrea/cuanvil/anvil/LoreEditTests.java +++ /dev/null @@ -1,622 +0,0 @@ -package xyz.alexcrea.cuanvil.anvil; - -import io.delilaheve.util.ConfigOptions; -import org.bukkit.Material; -import org.bukkit.event.Event; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.AnvilInventory; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.BookMeta; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.junit.jupiter.api.*; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.junit.jupiter.params.provider.MethodSource; -import org.junit.jupiter.params.provider.ValueSource; -import org.mockbukkit.mockbukkit.entity.PlayerMock; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.data.AnvilClickTestData; -import xyz.alexcrea.cuanvil.data.AnvilFuseTestData; -import xyz.alexcrea.cuanvil.data.TestDataContainer; -import xyz.alexcrea.cuanvil.tests.SharedCustomAnvilTest; -import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil; -import xyz.alexcrea.cuanvil.util.config.LoreEditType; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -// TODO redo test as now color split should be handled in AnvilColorUtilTest and not here -// Especially since some behavior changed -public class LoreEditTests extends SharedCustomAnvilTest { - - /*private static AnvilInventory anvil; - private static PlayerMock player; - - private static final String COLORED_LORE_LINE = "§x§1§2§3§4§5§6TEST §atest"; - private static final String UNCOLORED_LORE_LINE = "#123456TEST &atest"; - - private static final int COLOR_USE_COST = 1; - private static final int COLOR_REMOVE_COST = 2; - private static final int NON_ONE_TEST_FIXED_COST = 10; - private static final int NON_ZERO_TEST_LINE_COST = 2; - - private static ItemStack emptyItem; - private static ItemStack oneColoredLoreItem; - private static ItemStack twoColoredLoreItem; - private static ItemStack oneUncoloredLoreItem; - private static ItemStack twoUncoloredLoreItem; - - private static ItemStack emptyPaperStack; - private static ItemStack emptyPaper63Item; - private static ItemStack emptyPaperOne; - private static ItemStack coloredPaperStack; - private static ItemStack coloredPaper63Item; - private static ItemStack coloredPaperOne; - private static ItemStack uncoloredPaperStack; - private static ItemStack uncoloredPaper63Item; - private static ItemStack uncoloredPaperOne; - - private static ItemStack emptyBook; - private static ItemStack coloredBook1Line; - private static ItemStack coloredBook2Line; - private static ItemStack uncoloredBook1Line; - private static ItemStack uncoloredBook2Line; - - private static TestDataContainer defBookAppend; - private static TestDataContainer defBookRemove; - - private static TestDataContainer defPaperAppend; - private static TestDataContainer defPaperRemove; - - private static TestDataContainer defMultilineBookAppend; - private static TestDataContainer defMultilineBookRemove; - - private static TestDataContainer defMultilinePaperAppend; - private static TestDataContainer defMultilinePaperRemove; - - private static Map singleLineTypeToTest; - private static Map multiLineTypeToTest; - - @BeforeAll - public static void setUp() { - // Mock used player & open anvil - player = server.addPlayer(); - - Inventory anvil = server.createInventory(player, InventoryType.ANVIL); - - LoreEditTests.anvil = (AnvilInventory) anvil; - player.openInventory(anvil); - - ConfigHolder.DEFAULT_CONFIG.getConfig().set(ConfigOptions.DEBUG_LOGGING, true); - ConfigHolder.DEFAULT_CONFIG.getConfig().set(ConfigOptions.VERBOSE_DEBUG_LOGGING, true); - - // Applied item - ItemStack item = new ItemStack(Material.STICK, 33); - ItemMeta meta = item.getItemMeta(); - ArrayList lore = new ArrayList<>(); - - emptyItem = item.clone(); - - lore.add(COLORED_LORE_LINE); - meta.setLore(lore); - item.setItemMeta(meta); - oneColoredLoreItem = item.clone(); - - lore.add(COLORED_LORE_LINE); - meta.setLore(lore); - item.setItemMeta(meta); - twoColoredLoreItem = item.clone(); - - lore.clear(); - lore.add(UNCOLORED_LORE_LINE); - meta.setLore(lore); - item.setItemMeta(meta); - oneUncoloredLoreItem = item.clone(); - - lore.add(UNCOLORED_LORE_LINE); - meta.setLore(lore); - item.setItemMeta(meta); - twoUncoloredLoreItem = item.clone(); - lore.clear(); - - // Paper items - item = new ItemStack(Material.PAPER, 64); - meta = item.getItemMeta(); - emptyPaperStack = item.clone(); - item.setAmount(63); - emptyPaper63Item = item.clone(); - item.setAmount(1); - emptyPaperOne = item.clone(); - - item.setAmount(64); - meta.setDisplayName(COLORED_LORE_LINE); - item.setItemMeta(meta); - coloredPaperStack = item.clone(); - item.setAmount(63); - coloredPaper63Item = item.clone(); - item.setAmount(1); - coloredPaperOne = item.clone(); - - item.setAmount(64); - meta.setDisplayName(UNCOLORED_LORE_LINE); - item.setItemMeta(meta); - uncoloredPaperStack = item.clone(); - item.setAmount(63); - uncoloredPaper63Item = item.clone(); - item.setAmount(1); - uncoloredPaperOne = item.clone(); - - // Book items - item = new ItemStack(Material.WRITABLE_BOOK); - BookMeta bookmeta = (BookMeta) item.getItemMeta(); - emptyBook = item.clone(); - - bookmeta.setPages(COLORED_LORE_LINE); - item.setItemMeta(bookmeta); - coloredBook1Line = item.clone(); - - bookmeta.setPages(COLORED_LORE_LINE + "\n" + COLORED_LORE_LINE); - item.setItemMeta(bookmeta); - coloredBook2Line = item.clone(); - - bookmeta.setPages(UNCOLORED_LORE_LINE); - item.setItemMeta(bookmeta); - uncoloredBook1Line = item.clone(); - - bookmeta.setPages(UNCOLORED_LORE_LINE + "\n" + UNCOLORED_LORE_LINE); - item.setItemMeta(bookmeta); - uncoloredBook2Line = item.clone(); - - // Default working test data - defBookAppend = new TestDataContainer( - new AnvilFuseTestData( - emptyItem, uncoloredBook1Line, - oneColoredLoreItem, - 1 - ), new AnvilClickTestData( - null, emptyBook, null, oneColoredLoreItem, - 1, Event.Result.DENY, - true, Event.Result.DENY - )); - - defBookRemove = new TestDataContainer( - new AnvilFuseTestData( - oneColoredLoreItem, emptyBook, - emptyItem, - 1 - ), new AnvilClickTestData( - null, coloredBook1Line, null, emptyItem, - 1, Event.Result.DENY, - true, Event.Result.DENY - )); - - defPaperAppend = new TestDataContainer( - new AnvilFuseTestData( - emptyItem, uncoloredPaperStack, - oneColoredLoreItem, - 1 - ), new AnvilClickTestData( - emptyPaperOne, uncoloredPaper63Item, null, oneColoredLoreItem, - 1, Event.Result.DENY, - true, Event.Result.DENY - )); - - defPaperRemove = new TestDataContainer( - new AnvilFuseTestData( - oneColoredLoreItem, emptyPaperStack, - emptyItem, - 1 - ), new AnvilClickTestData( - coloredPaperOne, emptyPaper63Item, null, emptyItem, - 1, Event.Result.DENY, - true, Event.Result.DENY - )); - defMultilineBookAppend = new TestDataContainer( - new AnvilFuseTestData( - emptyItem, uncoloredBook2Line, - twoColoredLoreItem, - 1 - ), new AnvilClickTestData( - null, emptyBook, null, twoColoredLoreItem, - 1, Event.Result.DENY, - true, Event.Result.DENY - )); - - defMultilineBookRemove = new TestDataContainer( - new AnvilFuseTestData( - twoColoredLoreItem, emptyBook, - emptyItem, - 1 - ), new AnvilClickTestData( - null, coloredBook2Line, null, emptyItem, - 1, Event.Result.DENY, - true, Event.Result.DENY - )); - - defMultilinePaperAppend = new TestDataContainer( - new AnvilFuseTestData( - oneColoredLoreItem, uncoloredPaperStack, - twoColoredLoreItem, - 1 - ), new AnvilClickTestData( - emptyPaperOne, uncoloredPaper63Item, null, twoColoredLoreItem, - 1, Event.Result.DENY, - true, Event.Result.DENY - )); - - defMultilinePaperRemove = new TestDataContainer( - new AnvilFuseTestData( - twoColoredLoreItem, emptyPaperStack, - oneColoredLoreItem, - 1 - ), new AnvilClickTestData( - coloredPaperOne, emptyPaper63Item, null, oneColoredLoreItem, - 1, Event.Result.DENY, - true, Event.Result.DENY - )); - - singleLineTypeToTest = Map.of( - LoreEditType.APPEND_BOOK, defBookAppend, - LoreEditType.REMOVE_BOOK, defBookRemove, - LoreEditType.APPEND_PAPER, defPaperAppend, - LoreEditType.REMOVE_PAPER, defPaperRemove - ); - - multiLineTypeToTest = Map.of( - LoreEditType.APPEND_BOOK, defMultilineBookAppend, - LoreEditType.REMOVE_BOOK, defMultilineBookRemove, - LoreEditType.APPEND_PAPER, defMultilinePaperAppend, - LoreEditType.REMOVE_PAPER, defMultilinePaperRemove - ); - } - - @BeforeEach - public void prepareAnvil() { - anvil.clear(); - - // Make sure we reset value in case it got modified - for (@NotNull LoreEditType type : LoreEditType.values()) { - // Make sure it is enabled for the tests (unless its is enabled test) - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.IS_ENABLED, true); - - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.DO_CONSUME, false); - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.FIXED_COST, 1); - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.PER_LINE_COST, 0); - - // Make sur color is enabled by default - if (type.isAppend()) { - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.ALLOW_HEX_COLOR, true); - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.ALLOW_COLOR_CODE, true); - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.ALLOW_MINIMESSAGE, true); - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.USE_COLOR_COST, 0); - } else { - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.REMOVE_COLOR_COST, 0); - } - - } - - // Disable them by default and test them on specific tests - ConfigHolder.DEFAULT_CONFIG.getConfig().set(LoreEditConfigUtil.BOOK_PERMISSION_NEEDED, false); - ConfigHolder.DEFAULT_CONFIG.getConfig().set(LoreEditConfigUtil.PAPER_PERMISSION_NEEDED, false); - - ConfigHolder.DEFAULT_CONFIG.getConfig().set(LoreEditConfigUtil.PAPER_EDIT_ORDER, LoreEditConfigUtil.DEFAULT_PAPER_EDIT_ORDER); - } - - @AfterAll - public static void tearDown() { - player = null; - anvil = null; - } - - public @Nullable ItemStack uncoloredEquivalent(@Nullable ItemStack colored) { - // null check - if (null == colored) return null; - - if (oneColoredLoreItem == colored) return oneUncoloredLoreItem; - if (twoColoredLoreItem == colored) return twoUncoloredLoreItem; - - if (coloredPaperStack == colored) return uncoloredPaperStack; - if (coloredPaper63Item == colored) return uncoloredPaper63Item; - if (coloredPaperOne == colored) return uncoloredPaperOne; - - if (coloredBook1Line == colored) return uncoloredBook1Line; - if (coloredBook2Line == colored) return uncoloredBook2Line; - - // They already are uncolored - if (oneUncoloredLoreItem == colored) return oneUncoloredLoreItem; - if (twoUncoloredLoreItem == colored) return twoUncoloredLoreItem; - - if (uncoloredPaperStack == colored) return uncoloredPaperStack; - if (uncoloredPaper63Item == colored) return uncoloredPaper63Item; - if (uncoloredPaperOne == colored) return uncoloredPaperOne; - - if (uncoloredBook1Line == colored) return uncoloredBook1Line; - if (uncoloredBook2Line == colored) return uncoloredBook2Line; - - // No lore items return themself - if (emptyItem == colored) return emptyItem; - if (emptyBook == colored) return emptyBook; - if (emptyPaperStack == colored) return emptyPaperStack; - if (emptyPaper63Item == colored) return emptyPaper63Item; - if (emptyPaperOne == colored) return emptyPaperOne; - - Assertions.fail("Could not find uncolored version of " + colored); - return null; - } - - public static List onlyAppendTypes() { - ArrayList typeList = new ArrayList<>(); - for (@NotNull LoreEditType type : LoreEditType.values()) { - if (type.isAppend()) typeList.add(type); - } - return typeList; - } - - public static List onlyRemoveTypes() { - ArrayList typeList = new ArrayList<>(); - for (@NotNull LoreEditType type : LoreEditType.values()) { - if (!type.isAppend()) typeList.add(type); - } - return typeList; - } - - @ParameterizedTest - @EnumSource(LoreEditType.class) - public void simpleTest(LoreEditType type) { - // Test all defaults to make sure they works - singleLineTypeToTest.get(type).executeTest(anvil, player); - multiLineTypeToTest.get(type).executeTest(anvil, player); - - } - - @ParameterizedTest - @EnumSource(LoreEditType.class) - public void testPermissionNeeded_DEOP(LoreEditType type) { - ConfigHolder.DEFAULT_CONFIG.getConfig().set(LoreEditConfigUtil.BOOK_PERMISSION_NEEDED, true); - ConfigHolder.DEFAULT_CONFIG.getConfig().set(LoreEditConfigUtil.PAPER_PERMISSION_NEEDED, true); - player.setOp(false); - - singleLineTypeToTest.get(type).nullifyResult().executeTest(anvil, player); - multiLineTypeToTest.get(type).nullifyResult().executeTest(anvil, player); - } - - @ParameterizedTest - @EnumSource(LoreEditType.class) - public void testPermissionNeeded_OP(LoreEditType type) { - ConfigHolder.DEFAULT_CONFIG.getConfig().set(LoreEditConfigUtil.BOOK_PERMISSION_NEEDED, true); - ConfigHolder.DEFAULT_CONFIG.getConfig().set(LoreEditConfigUtil.PAPER_PERMISSION_NEEDED, true); - player.setOp(true); - - singleLineTypeToTest.get(type).executeTest(anvil, player); - multiLineTypeToTest.get(type).executeTest(anvil, player); - } - - @ParameterizedTest - @EnumSource(LoreEditType.class) - public void testLoreTypeDisabled(LoreEditType type) { - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.IS_ENABLED, false); - - singleLineTypeToTest.get(type).nullifyResult().executeTest(anvil, player); - multiLineTypeToTest.get(type).nullifyResult().executeTest(anvil, player); - } - - @ParameterizedTest - @EnumSource(LoreEditType.class) - public void testFixedCost_Default(LoreEditType type) { - singleLineTypeToTest.get(type).setCost(1).executeTest(anvil, player); - multiLineTypeToTest.get(type).setCost(1).executeTest(anvil, player); - } - - @ParameterizedTest - @EnumSource(LoreEditType.class) - public void testFixedCost_Modified(LoreEditType type) { - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.FIXED_COST, NON_ONE_TEST_FIXED_COST); - - singleLineTypeToTest.get(type).setCost(NON_ONE_TEST_FIXED_COST).executeTest(anvil, player); - multiLineTypeToTest.get(type).setCost(NON_ONE_TEST_FIXED_COST).executeTest(anvil, player); - } - - @ParameterizedTest - @EnumSource(LoreEditType.class) - public void testLineCost_Modified(LoreEditType type) { - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.PER_LINE_COST, NON_ZERO_TEST_LINE_COST); - - if (type.isMultiLine()) { - singleLineTypeToTest.get(type).setCost(NON_ZERO_TEST_LINE_COST + LoreEditConfigUtil.DEFAULT_FIXED_COST).executeTest(anvil, player); - multiLineTypeToTest.get(type).setCost(2 * NON_ZERO_TEST_LINE_COST + LoreEditConfigUtil.DEFAULT_FIXED_COST).executeTest(anvil, player); - } else { - singleLineTypeToTest.get(type).executeTest(anvil, player); - multiLineTypeToTest.get(type).executeTest(anvil, player); - } - } - - @ParameterizedTest - @EnumSource(LoreEditType.class) - public void testColorCost(LoreEditType type) { - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.USE_COLOR_COST, COLOR_USE_COST); - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.REMOVE_COLOR_COST, COLOR_REMOVE_COST); - - TestDataContainer singleLData = singleLineTypeToTest.get(type); - TestDataContainer multiLData = multiLineTypeToTest.get(type); - - if (type.isAppend()) { - singleLData.setCost(COLOR_USE_COST + LoreEditConfigUtil.DEFAULT_FIXED_COST).executeTest(anvil, player); - multiLData.setCost(COLOR_USE_COST + LoreEditConfigUtil.DEFAULT_FIXED_COST).executeTest(anvil, player); - } else { - singleLData - .setCost(COLOR_REMOVE_COST + LoreEditConfigUtil.DEFAULT_FIXED_COST) - .setClickRight(uncoloredEquivalent(singleLData.getRightClick())) - .setClickLeft(uncoloredEquivalent(singleLData.getLeftClick())) - .executeTest(anvil, player); - - multiLData.setCost(COLOR_REMOVE_COST + LoreEditConfigUtil.DEFAULT_FIXED_COST) - .setClickRight(uncoloredEquivalent(multiLData.getRightClick())) - .setClickLeft(uncoloredEquivalent(multiLData.getLeftClick())) - .executeTest(anvil, player); - } - } - - @ParameterizedTest - @MethodSource("onlyAppendTypes") - public void testColorDisabled(LoreEditType type) { - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.USE_COLOR_COST, COLOR_USE_COST); - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.ALLOW_HEX_COLOR, false); - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.ALLOW_COLOR_CODE, false); - - TestDataContainer singleLData = singleLineTypeToTest.get(type); - TestDataContainer multiLData = multiLineTypeToTest.get(type); - - singleLData - .setExpectedResult(uncoloredEquivalent(singleLData.getExpectedFuse())) - .executeTest(anvil, player); - multiLData - .setFuseLeft(uncoloredEquivalent(multiLData.getLeftFuse())) - .setExpectedResult(uncoloredEquivalent(multiLData.getExpectedFuse())) - .executeTest(anvil, player); - } - - @ParameterizedTest - @MethodSource("onlyRemoveTypes") - public void testColorRemoveEnabled(LoreEditType type) { - TestDataContainer singleLData = singleLineTypeToTest.get(type); - TestDataContainer multiLData = multiLineTypeToTest.get(type); - - singleLData - .setClickRight(uncoloredEquivalent(singleLData.getRightClick())) - .setClickLeft(uncoloredEquivalent(singleLData.getLeftClick())) - .executeTest(anvil, player); - multiLData - .setClickRight(uncoloredEquivalent(multiLData.getRightClick())) - .setClickLeft(uncoloredEquivalent(multiLData.getLeftClick())) - .executeTest(anvil, player); - } - - @ParameterizedTest - @MethodSource("onlyRemoveTypes") - public void testDoConsume(LoreEditType type) { - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.DO_CONSUME, true); - - TestDataContainer singleLData = singleLineTypeToTest.get(type); - TestDataContainer multiLData = multiLineTypeToTest.get(type); - - // NOTE: we set to null right item only on multi line bc the default data has more than one paper and would go to the left instead - singleLData = singleLData - .setClickRight(type.isMultiLine() ? null : singleLData.getRightClick()) - .setClickLeft(null); - singleLData.executeTest(anvil, player); - multiLData = multiLData - .setClickRight(type.isMultiLine() ? null : singleLData.getRightClick()) - .setClickLeft(null); - multiLData.executeTest(anvil, player); - - // Single paper consumed - if (!type.isMultiLine()) { - singleLData.setFuseRight(emptyPaperOne).setClickRight(null).executeTest(anvil, player); - multiLData.setFuseRight(emptyPaperOne).setClickRight(null).executeTest(anvil, player); - } - } - - private void SinglePaperTestPart(LoreEditType type, TestDataContainer data, ItemStack expectedFuse, ItemStack postFuse) { - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.DO_CONSUME, false); - data = data.setFuseRight(expectedFuse).setClickLeft(null).setClickRight(postFuse); - data.executeTest(anvil, player); - - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.DO_CONSUME, true); - data.setClickRight(null).executeTest(anvil, player); - } - - @Test - public void testSinglePaper_Append() { - SinglePaperTestPart(LoreEditType.APPEND_PAPER, - singleLineTypeToTest.get(LoreEditType.APPEND_PAPER), - uncoloredPaperOne, emptyPaperOne); - SinglePaperTestPart(LoreEditType.APPEND_PAPER, - multiLineTypeToTest.get(LoreEditType.APPEND_PAPER), - uncoloredPaperOne, emptyPaperOne); - } - - @Test - public void testSinglePaper_Remove() { - SinglePaperTestPart(LoreEditType.REMOVE_PAPER, - singleLineTypeToTest.get(LoreEditType.REMOVE_PAPER), - emptyPaperOne, coloredPaperOne); - SinglePaperTestPart(LoreEditType.REMOVE_PAPER, - multiLineTypeToTest.get(LoreEditType.REMOVE_PAPER), - emptyPaperOne, coloredPaperOne); - } - - @NotNull - private static ItemStack insertToLore(@NotNull ItemStack item, int index, @NotNull String toAppend) { - item = item.clone(); - ItemMeta meta = item.getItemMeta(); - Assertions.assertNotNull(meta); - Assertions.assertTrue(meta.hasLore()); - - ArrayList lore = new ArrayList<>(meta.getLore()); - lore.add(index, toAppend); - - meta.setLore(lore); - item.setItemMeta(meta); - return item; - } - - @NotNull - private static ItemStack setDisplayedName(@NotNull ItemStack item, @NotNull String name) { - item = item.clone(); - ItemMeta meta = item.getItemMeta(); - Assertions.assertNotNull(meta); - - meta.setDisplayName(name); - item.setItemMeta(meta); - return item; - } - - private static final String TESTED_LORE = "tested_lore"; - - @ParameterizedTest - @ValueSource(strings = {"sTaRt", "eNd"}) - public void testPaperOrder_Append(String order) { - ConfigHolder.DEFAULT_CONFIG.getConfig().set(LoreEditConfigUtil.PAPER_EDIT_ORDER, order); - - ItemStack result = insertToLore(oneColoredLoreItem, "start".equalsIgnoreCase(order) ? 0 : 1, TESTED_LORE); - ItemStack paper = setDisplayedName(emptyPaperOne, TESTED_LORE); - - new TestDataContainer( - new AnvilFuseTestData( - oneColoredLoreItem, paper, result, 1 - ), - new AnvilClickTestData( - null, emptyPaperOne, null, result, - 1, - Event.Result.DENY, true, Event.Result.DENY - ) - ).executeTest(anvil, player); - } - - @ParameterizedTest - @ValueSource(strings = {"sTaRt", "eNd"}) - public void testPaperOrder_Remove(String order) { - ConfigHolder.DEFAULT_CONFIG.getConfig().set(LoreEditConfigUtil.PAPER_EDIT_ORDER, order); - - ItemStack from = insertToLore(oneColoredLoreItem, "start".equalsIgnoreCase(order) ? 0 : 1, TESTED_LORE); - ItemStack paper = setDisplayedName(emptyPaperOne, TESTED_LORE); - - new TestDataContainer( - new AnvilFuseTestData( - from, emptyPaperOne, oneColoredLoreItem, 1 - ), - new AnvilClickTestData( - null, paper, null, oneColoredLoreItem, - 1, - Event.Result.DENY, true, Event.Result.DENY - ) - ).executeTest(anvil, player); - } - - //TODO work penalty test*/ - -} diff --git a/src/test/java/xyz/alexcrea/cuanvil/api/AnvilRecipeBuilderTest.java b/src/test/java/xyz/alexcrea/cuanvil/api/AnvilRecipeBuilderTest.java deleted file mode 100644 index d9ff329..0000000 --- a/src/test/java/xyz/alexcrea/cuanvil/api/AnvilRecipeBuilderTest.java +++ /dev/null @@ -1,107 +0,0 @@ -package xyz.alexcrea.cuanvil.api; - - -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import xyz.alexcrea.cuanvil.tests.SharedOnlyMockBukkit; - -import static org.junit.jupiter.api.Assertions.*; - -public class AnvilRecipeBuilderTest extends SharedOnlyMockBukkit { - - private AnvilRecipeBuilder builder; - private AnvilRecipeBuilder builder2; - - @BeforeEach - public void setup() { - builder = new AnvilRecipeBuilder("test"); - builder2 = new AnvilRecipeBuilder("test"); - - builder2.setLeftItem(new ItemStack(Material.STICK)); - builder2.setResultItem(new ItemStack(Material.STICK)); - } - - @Test - void createBuilder_NoLeftItem(){ - builder.setResultItem(new ItemStack(Material.STICK)); - - assertNull(builder.build()); - } - - @Test - void createBuilder_NoResultItem(){ - builder.setLeftItem(new ItemStack(Material.STICK)); - - assertNull(builder.build()); - } - - @Test - void createBuilder_minimalist(){ - builder.setLeftItem(new ItemStack(Material.STICK)) - .setResultItem(new ItemStack(Material.STICK)); - - assertNotNull(builder.build()); - assertNotNull(builder2.build()); - } - - @Test - void setLeftItem(){ - assertNull(builder.getLeftItem()); - builder.setLeftItem(new ItemStack(Material.STICK)); - assertNotNull(builder.getLeftItem()); - } - - @Test - void setRightItem(){ - assertNull(builder.getRightItem()); - builder.setRightItem(new ItemStack(Material.STICK)); - assertNotNull(builder.getRightItem()); - } - - @Test - void setResultItem(){ - assertNull(builder.getResultItem()); - builder.setResultItem(new ItemStack(Material.STICK)); - assertNotNull(builder.getResultItem()); - } - - @Test - void setXpCostPerCraft(){ - assertEquals(0, builder2.getLevelCostPerCraft()); - assertEquals(0, builder2.build().getLevelCostPerCraft()); - builder2.setLevelCostPerCraft(2); - assertEquals(2, builder2.getLevelCostPerCraft()); - assertEquals(2, builder2.build().getLevelCostPerCraft()); - } - - @Test - void setLinearXpCostPerCraft(){ - assertEquals(0, builder2.getLinearXpCostPerCraft()); - assertEquals(0, builder2.build().getXpCostPerCraft()); - builder2.setLinearXpCostPerCraft(2); - assertEquals(2, builder2.getLinearXpCostPerCraft()); - assertEquals(2, builder2.build().getXpCostPerCraft()); - } - - - @Test - void setExactCount(){ - assertTrue(builder2.isExactCount()); - assertTrue(builder2.build().getExactCount()); - builder2.setExactCount(false); - assertFalse(builder2.isExactCount()); - assertFalse(builder2.build().getExactCount()); - } - - @Test - void setName(){ - assertEquals("test", builder2.getName()); - assertEquals("test", builder2.build().getName()); - builder2.setName("other"); - assertEquals("other", builder2.getName()); - assertEquals("other", builder2.build().getName()); - } - -} diff --git a/src/test/java/xyz/alexcrea/cuanvil/api/ConflictApiTests.java b/src/test/java/xyz/alexcrea/cuanvil/api/ConflictApiTests.java deleted file mode 100644 index 1a9a256..0000000 --- a/src/test/java/xyz/alexcrea/cuanvil/api/ConflictApiTests.java +++ /dev/null @@ -1,160 +0,0 @@ -package xyz.alexcrea.cuanvil.api; - -import org.bukkit.Material; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.AnvilInventory; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockbukkit.mockbukkit.entity.PlayerMock; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; -import xyz.alexcrea.cuanvil.group.EnchantConflictGroup; -import xyz.alexcrea.cuanvil.tests.ConfigResetCustomAnvilTest; -import xyz.alexcrea.cuanvil.data.AnvilFuseTestData; -import xyz.alexcrea.cuanvil.util.AnvilFuseTestUtil; -import xyz.alexcrea.cuanvil.util.CommonItemUtil; - -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class ConflictApiTests extends ConfigResetCustomAnvilTest { - - private AnvilInventory anvil; - private PlayerMock player; - - @Override - @BeforeEach - public void setUp() { - super.setUp(); - // Mock used player & open anvil - player = server.addPlayer(); - - Inventory anvil = server.createInventory(player, InventoryType.ANVIL); - - this.anvil = (AnvilInventory) anvil; - player.openInventory(anvil); - - ConfigHolder.DEFAULT_CONFIG.getConfig().set("debug_log", true); - ConfigHolder.DEFAULT_CONFIG.getConfig().set("debug_log_verbose", true); - } - - @Test - public void testConflict() { - ItemStack sharpness1 = CommonItemUtil.sharpness(1); - ItemStack arthropods1 = CommonItemUtil.bane_of_arthropods(1); - ItemStack illegalResult = AnvilFuseTestUtil.prepareItem( - Material.DIAMOND_SWORD, 1, - List.of("bane_of_arthropods", "sharpness"), - 1, 1 - ); - - AnvilFuseTestData nullResultData = new AnvilFuseTestData( - sharpness1, arthropods1, - null - ); - - AnvilFuseTestData legalResultData = new AnvilFuseTestData( - sharpness1, arthropods1, - illegalResult, - 2 - ); - - CAEnchantment sharpness = EnchantmentApi.getByKey(Enchantment.SHARPNESS.getKey()); - Assertions.assertNotNull(sharpness); - - // Testing default conflict (illegal item should not be produced) - nullResultData.executeTest(anvil, player); - - // Try to find & remove conflict - EnchantConflictGroup conflict = findGroup("sword_enchant_conflict"); - Assertions.assertNotNull(conflict, "Could not find conflict."); - - // Test what happen when we remove the conflict (illegal item should be allowed) - ConflictAPI.removeConflict(conflict); - legalResultData.executeTest(anvil, player); - - // We create and add a new conflict - ConflictBuilder builder = new ConflictBuilder("sword_enchant_conflict"); - builder.addEnchantment("bane_of_arthropods").addEnchantment(sharpness); //TODO maybe add "add by bukkit enchantment" - builder.setMaxBeforeConflict(1); - - // Nothing should change as it is not new: it was previously deleted - Assertions.assertFalse(builder.registerIfNew()); - legalResultData.executeTest(anvil, player); - - // Now the conflict should be registered and conflict should exist - Assertions.assertTrue(builder.registerIfAbsent()); - nullResultData.executeTest(anvil, player); - } - - @Test - void writeGroup_Reload() { - String conflictName = "conflict"; - ConflictBuilder builder = new ConflictBuilder(conflictName); - builder.addEnchantment("bane_of_arthropods"); - - // Group not being set should not exist - assertFalse(doGroupExist(conflictName)); - - // Add group and reload - assertTrue(ConflictAPI.writeConflict(builder)); - assertFalse(doGroupExist(conflictName)); - - // Tick so write get reloaded - server.getScheduler().performOneTick(); - - assertTrue(doGroupExist(conflictName)); - } - - @Test - void writeGroup_Empty() { - String conflictName = "conflict"; - ConflictBuilder builder = new ConflictBuilder(conflictName); - - // Group not being set should not exist - assertFalse(doGroupExist(conflictName)); - - // Add group and reload - assertFalse(ConflictAPI.writeConflict(builder)); - assertFalse(doGroupExist(conflictName)); - - // Tick so write get reloaded - server.getScheduler().performOneTick(); - - assertFalse(doGroupExist(conflictName)); - } - - @Test - void writeGroup_InvalidDot() { - String conflictName = "conflict.conflict"; - ConflictBuilder builder = new ConflictBuilder(conflictName); - - // Try write group - assertFalse(ConflictAPI.writeConflict(builder)); - } - - // Maybe move to ConflictApi class ? - private static boolean doGroupExist(@NotNull String groupName) { - return findGroup(groupName) != null; - } - - // Maybe move to ConflictApi class ? - @Nullable - private static EnchantConflictGroup findGroup(@NotNull String groupName) { - for (EnchantConflictGroup enchantConflictGroup : ConflictAPI.getRegisteredConflict()) { - if (groupName.equalsIgnoreCase(enchantConflictGroup.getName())) { - return enchantConflictGroup; - } - } - return null; - } - -} diff --git a/src/test/java/xyz/alexcrea/cuanvil/api/ConflictBuilderTests.java b/src/test/java/xyz/alexcrea/cuanvil/api/ConflictBuilderTests.java deleted file mode 100644 index 670ae4e..0000000 --- a/src/test/java/xyz/alexcrea/cuanvil/api/ConflictBuilderTests.java +++ /dev/null @@ -1,115 +0,0 @@ -package xyz.alexcrea.cuanvil.api; - -import org.bukkit.NamespacedKey; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import xyz.alexcrea.cuanvil.group.IncludeGroup; -import xyz.alexcrea.cuanvil.tests.SharedOnlyMockBukkit; - -import static org.junit.jupiter.api.Assertions.*; - -public class ConflictBuilderTests extends SharedOnlyMockBukkit { - - private ConflictBuilder builder; - - @BeforeEach - public void setup() { - builder = new ConflictBuilder("test"); - } - - @Test - void testDefaults() { - assertNull(builder.getSource()); - assertEquals("an unknown source", builder.getSourceName()); - assertEquals("test", builder.getName()); - - assertTrue(builder.getEnchantmentNames().isEmpty()); - assertTrue(builder.getEnchantmentKeys().isEmpty()); - assertTrue(builder.getExcludedGroupNames().isEmpty()); - - assertEquals(0, builder.getMaxBeforeConflict()); - } - - @Test - void setName() { - assertEquals("test", builder.getName()); - assertEquals(builder, builder.setName("another")); - assertEquals("another", builder.getName()); - } - - @Test - void setMaxBeforeConflict() { - assertEquals(0, builder.getMaxBeforeConflict()); - assertEquals(builder, builder.setMaxBeforeConflict(1)); - assertEquals(1, builder.getMaxBeforeConflict()); - } - - @Test - void enchantmentString() { - assertTrue(builder.getEnchantmentNames().isEmpty()); - assertEquals(builder, builder.addEnchantment("bane_of_arthropods")); - assertEquals(1, builder.getEnchantmentNames().size()); - - assertEquals(builder, builder.removeEnchantment("bane_of_arthropods")); - assertTrue(builder.getEnchantmentNames().isEmpty()); - } - - @Test - void enchantmentKey() { - NamespacedKey key = NamespacedKey.fromString("bane_of_arthropods"); - assertNotNull(key); - - assertTrue(builder.getEnchantmentKeys().isEmpty()); - assertEquals(builder, builder.addEnchantment(key)); - assertEquals(1, builder.getEnchantmentKeys().size()); - - assertEquals(builder, builder.removeEnchantment(key)); - assertTrue(builder.getEnchantmentKeys().isEmpty()); - } - - @Test - void excludedGroup_String() { - assertTrue(builder.getExcludedGroupNames().isEmpty()); - assertEquals(builder, builder.addExcludedGroup("group")); - assertEquals(1, builder.getExcludedGroupNames().size()); - - assertEquals(builder, builder.removeExcludedGroup("group")); - assertTrue(builder.getExcludedGroupNames().isEmpty()); - } - - @Test - void excludedGroup_Group() { - IncludeGroup group = new IncludeGroup("group"); - - assertTrue(builder.getExcludedGroupNames().isEmpty()); - assertEquals(builder, builder.addExcludedGroup(group)); - assertEquals(1, builder.getExcludedGroupNames().size()); - - assertEquals(builder, builder.removeExcludedGroup(group)); - assertTrue(builder.getExcludedGroupNames().isEmpty()); - } - - @Test - void copy(){ - builder.setName("other"); - builder.setMaxBeforeConflict(1); - - builder.addEnchantment("bane_of_arthropods"); - builder.addEnchantment(NamespacedKey.fromString("bane_of_arthropods")); - builder.addExcludedGroup("group"); - builder.addExcludedGroup(new IncludeGroup("group2")); - - ConflictBuilder copy = builder.copy(); - assertEquals("other", copy.getName()); - assertEquals(1, copy.getMaxBeforeConflict()); - - assertEquals(1, copy.getEnchantmentNames().size()); - assertEquals("bane_of_arthropods", copy.getEnchantmentNames().stream().findFirst().orElse(null)); - - assertEquals(1, copy.getEnchantmentKeys().size()); - assertEquals(NamespacedKey.fromString("bane_of_arthropods"), copy.getEnchantmentKeys().stream().findFirst().orElse(null)); - - assertEquals(2, copy.getExcludedGroupNames().size()); - } - -} diff --git a/src/test/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApiTests.java b/src/test/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApiTests.java deleted file mode 100644 index 651b873..0000000 --- a/src/test/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApiTests.java +++ /dev/null @@ -1,259 +0,0 @@ -package xyz.alexcrea.cuanvil.api; - -import org.bukkit.Material; -import org.bukkit.event.Event; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.AnvilInventory; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.Nullable; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockbukkit.mockbukkit.entity.PlayerMock; -import org.mockbukkit.mockbukkit.inventory.ItemStackMock; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.data.AnvilClickTestData; -import xyz.alexcrea.cuanvil.data.TestDataContainer; -import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe; -import xyz.alexcrea.cuanvil.tests.ConfigResetCustomAnvilTest; -import xyz.alexcrea.cuanvil.data.AnvilFuseTestData; - -import static org.junit.jupiter.api.Assertions.*; - -public class CustomAnvilRecipeApiTests extends ConfigResetCustomAnvilTest { - - private AnvilInventory anvil; - private PlayerMock player; - - @Override - @BeforeEach - public void setUp() { - super.setUp(); - // Mock used player & open anvil - player = server.addPlayer(); - - Inventory anvil = server.createInventory(player, InventoryType.ANVIL); - - this.anvil = (AnvilInventory) anvil; - player.openInventory(anvil); - - ConfigHolder.DEFAULT_CONFIG.getConfig().set("debug_log", true); - ConfigHolder.DEFAULT_CONFIG.getConfig().set("debug_log_verbose", true); - } - - @Test - public void testBasicRecipe() { - String recipeName = "stick_recipe"; - ItemStack stick = new ItemStackMock(Material.STICK); - - AnvilFuseTestData nullResultData = new AnvilFuseTestData( - stick, stick, - null - ); - - AnvilFuseTestData legalResultData = new AnvilFuseTestData( - stick, stick, - null, stick, null, - 2, - null, null - ); - - // Testing default conflict (no recipe exist) - nullResultData.executeTest(anvil, player); - - // Add and test recipe - AnvilRecipeBuilder builder = new AnvilRecipeBuilder(recipeName); - builder.setExactCount(true).setLeftItem(stick).setResultItem(stick).setLevelCostPerCraft(2); - - assertTrue(builder.registerIfAbsent()); - legalResultData.executeTest(anvil, player); - - AnvilCustomRecipe recipe = getByName(recipeName); - assertNotNull(recipe); - - // Remove recipe - assertTrue(CustomAnvilRecipeApi.removeRecipe(recipe)); - assertFalse(CustomAnvilRecipeApi.removeRecipe(recipe)); - nullResultData.executeTest(anvil, player); - - recipe = getByName(recipeName); - assertNull(recipe); - - // Try to add deleted recipe with no override (should not add) - assertFalse(CustomAnvilRecipeApi.addRecipe(builder, false)); - nullResultData.executeTest(anvil, player); - - recipe = getByName(recipeName); - assertNull(recipe); - - // Try to add deleted recipe with override (should add) - assertTrue(CustomAnvilRecipeApi.addRecipe(builder, true)); - legalResultData.executeTest(anvil, player); - - recipe = getByName(recipeName); - assertNotNull(recipe); - } - - @Test - public void testUnitRecipe() { - String recipeName = "stick_recipe"; - ItemStack stick = new ItemStackMock(Material.STICK); - ItemStack stick2 = new ItemStackMock(Material.STICK, 2); - ItemStack stick5 = new ItemStackMock(Material.STICK, 5); - ItemStack stick10 = new ItemStackMock(Material.STICK, 10); - - AnvilFuseTestData nullResultData = new AnvilFuseTestData( - stick, stick, - null - ); - - AnvilFuseTestData legalResultData1 = new AnvilFuseTestData( - stick, stick, - null, stick2, null, - 2, - null, null - ); - - AnvilFuseTestData legalResultData2 = new AnvilFuseTestData( - stick5, stick, - null, stick10, null, - 10, // 2 * 5 - null, null - ); - - nullResultData.executeTest(anvil, player); - - AnvilRecipeBuilder builder = new AnvilRecipeBuilder(recipeName); - builder.setExactCount(false) - .setLeftItem(stick) - .setResultItem(stick2) - .setLevelCostPerCraft(2); - - assertTrue(builder.registerIfAbsent()); - - // Now working test - legalResultData1.executeTest(anvil, player); - legalResultData2.executeTest(anvil, player); - } - - @Test - public void testLinearXpCost() { - String recipeName = "stick_recipe"; - ItemStack stick = new ItemStackMock(Material.STICK); - ItemStack stick2 = new ItemStackMock(Material.STICK, 2); - ItemStack stick5 = new ItemStackMock(Material.STICK, 5); - ItemStack stick10 = new ItemStackMock(Material.STICK, 10); - - - AnvilFuseTestData nullResultData = new AnvilFuseTestData( - stick, stick, - null - ); - - TestDataContainer legalResultData1 = new TestDataContainer(new AnvilFuseTestData( - stick, stick, - null, stick2, null, - 1, - null, null - ), new AnvilClickTestData( - null, null, null, stick2, - 1, - Event.Result.DENY, true, Event.Result.DENY - - )); - - TestDataContainer legalResultData2 = new TestDataContainer(new AnvilFuseTestData( - stick5, stick, - null, stick10, null, - 4, - null, null - ), new AnvilClickTestData( - null, null, null, stick10, - 4, - Event.Result.DENY, true, Event.Result.DENY - - )); - - nullResultData.executeTest(anvil, player); - - AnvilRecipeBuilder builder = new AnvilRecipeBuilder(recipeName); - builder.setExactCount(false) - .setLeftItem(stick) - .setResultItem(stick2) - .setLevelCostPerCraft(0) - .setLinearXpCostPerCraft(10); - - assertTrue(builder.registerIfAbsent()); - - // Now working test - legalResultData1.executeTest(anvil, player); - legalResultData2.executeTest(anvil, player); - } - - @Test - public void testLinearXpCostRemoveExact() { - String recipeName = "stick_recipe"; - ItemStack stick = new ItemStackMock(Material.STICK); - ItemStack stick2 = new ItemStackMock(Material.STICK, 2); - ItemStack stick5 = new ItemStackMock(Material.STICK, 5); - ItemStack stick10 = new ItemStackMock(Material.STICK, 10); - - AnvilFuseTestData nullResultData = new AnvilFuseTestData( - stick, stick, - null - ); - - TestDataContainer legalResultData1 = new TestDataContainer(new AnvilFuseTestData( - stick, stick, - null, stick2, null, - 2, - null, null - ), new AnvilClickTestData( - null, null, null, stick2, - 2, - Event.Result.DENY, true, Event.Result.DENY - - )); - - TestDataContainer legalResultData2 = new TestDataContainer(new AnvilFuseTestData( - stick5, stick, - null, stick10, null, - 5, - null, null - ), new AnvilClickTestData( - null, null, null, stick10, - 5, - Event.Result.DENY, true, Event.Result.DENY - )); - - nullResultData.executeTest(anvil, player); - - AnvilRecipeBuilder builder = new AnvilRecipeBuilder(recipeName); - builder.setExactCount(false) - .setLeftItem(stick) - .setResultItem(stick2) - .setLinearXpCostPerCraft(10) - .setRemoveExactLinearXp(true); - - assertTrue(builder.registerIfAbsent()); - - // Now working test - legalResultData1.executeTest(anvil, player); - //TODO check exp ? - System.out.printf(String.valueOf(player.getExp())); - legalResultData2.executeTest(anvil, player); - //TODO check exp ? - } - - @Nullable - public static AnvilCustomRecipe getByName(String name) { - for (AnvilCustomRecipe registeredRecipe : CustomAnvilRecipeApi.getRegisteredRecipes()) { - if (registeredRecipe.getName().contentEquals(name)) { - return registeredRecipe; - } - } - - return null; - } - -} diff --git a/src/test/java/xyz/alexcrea/cuanvil/api/MaterialGroupApiTests.java b/src/test/java/xyz/alexcrea/cuanvil/api/MaterialGroupApiTests.java deleted file mode 100644 index 3fcafe7..0000000 --- a/src/test/java/xyz/alexcrea/cuanvil/api/MaterialGroupApiTests.java +++ /dev/null @@ -1,108 +0,0 @@ -package xyz.alexcrea.cuanvil.api; - -import org.bukkit.Material; -import org.junit.jupiter.api.Test; -import xyz.alexcrea.cuanvil.group.EnchantConflictGroup; -import xyz.alexcrea.cuanvil.group.IncludeGroup; -import xyz.alexcrea.cuanvil.tests.ConfigResetCustomAnvilTest; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class MaterialGroupApiTests extends ConfigResetCustomAnvilTest { - - @Test - void groupAddAndRemove() { - String groupName = "group"; - IncludeGroup group = new IncludeGroup(groupName); - group.addToPolicy(Material.DIAMOND_PICKAXE.getKey()); // We do not want it to be empty - - // Group not being set should not exist - assertFalse(doGroupExist(groupName)); - assertFalse(doGroupCanBeFound(groupName)); - - // Add group - assertTrue(MaterialGroupApi.addMaterialGroup(group)); - assertFalse(MaterialGroupApi.addMaterialGroup(group, true)); - - assertTrue(doGroupExist(groupName)); - assertTrue(doGroupCanBeFound(groupName)); - - // Remove group - assertTrue(MaterialGroupApi.removeGroup(group)); - assertFalse(MaterialGroupApi.removeGroup(group)); - - assertFalse(doGroupExist(groupName)); - assertFalse(doGroupCanBeFound(groupName)); - - // Re add - assertFalse(MaterialGroupApi.addMaterialGroup(group, false)); - assertTrue(MaterialGroupApi.addMaterialGroup(group, true)); - - assertTrue(doGroupExist(groupName)); - assertTrue(doGroupCanBeFound(groupName)); - - } - - @Test - void writeGroup_Reload() { - String groupName = "group"; - IncludeGroup group = new IncludeGroup(groupName); - group.addToPolicy(Material.DIAMOND_PICKAXE.getKey()); // We do not want it to be empty - - // Group not being set should not exist - assertFalse(doGroupExist(groupName)); - assertFalse(doGroupCanBeFound(groupName)); - - // Add group and reload - assertTrue(MaterialGroupApi.writeMaterialGroup(group)); - assertFalse(doGroupExist(groupName)); - assertFalse(doGroupCanBeFound(groupName)); - - // Tick so write get reloaded - server.getScheduler().performOneTick(); - - assertTrue(doGroupExist(groupName)); - assertTrue(doGroupCanBeFound(groupName)); - } - - @Test - void writeGroup_Empty() { - String groupName = "group"; - IncludeGroup group = new IncludeGroup(groupName); - - // Add group and reload - assertFalse(MaterialGroupApi.writeMaterialGroup(group)); - assertFalse(doGroupExist(groupName)); - assertFalse(doGroupCanBeFound(groupName)); - - // Tick so write get reloaded - server.getScheduler().performOneTick(); - - assertFalse(doGroupExist(groupName)); - assertFalse(doGroupCanBeFound(groupName)); - } - - @Test - void writeGroup_InvalidDot() { - String groupName = "group.group"; - IncludeGroup group = new IncludeGroup(groupName); - - // Try write group - assertFalse(MaterialGroupApi.writeMaterialGroup(group)); - } - - boolean doGroupExist(String groupName) { - return MaterialGroupApi.getGroup(groupName) != null; - } - - boolean doGroupCanBeFound(String groupName) { - ConflictBuilder builder = new ConflictBuilder(groupName); - builder.addExcludedGroup(groupName); - - EnchantConflictGroup group = builder.build(); - IncludeGroup materialGroup = (IncludeGroup) group.getCantConflictGroup(); - return materialGroup.getGroups().size() == 1; - } - -} diff --git a/src/test/java/xyz/alexcrea/cuanvil/api/UnitRepairApiTests.java b/src/test/java/xyz/alexcrea/cuanvil/api/UnitRepairApiTests.java deleted file mode 100644 index adda4e1..0000000 --- a/src/test/java/xyz/alexcrea/cuanvil/api/UnitRepairApiTests.java +++ /dev/null @@ -1,118 +0,0 @@ -package xyz.alexcrea.cuanvil.api; - -import org.bukkit.Material; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.AnvilInventory; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.inventory.meta.Repairable; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockbukkit.mockbukkit.entity.PlayerMock; -import org.mockbukkit.mockbukkit.inventory.ItemStackMock; -import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.tests.ConfigResetCustomAnvilTest; -import xyz.alexcrea.cuanvil.data.AnvilFuseTestData; -import xyz.alexcrea.cuanvil.util.AnvilFuseTestUtil; - -import static org.junit.jupiter.api.Assertions.*; - -public class UnitRepairApiTests extends ConfigResetCustomAnvilTest { - - private AnvilInventory anvil; - private PlayerMock player; - - @Override - @BeforeEach - public void setUp() { - super.setUp(); - // Mock used player & open anvil - player = server.addPlayer(); - - Inventory anvil = server.createInventory(player, InventoryType.ANVIL); - - this.anvil = (AnvilInventory) anvil; - player.openInventory(anvil); - - ConfigHolder.DEFAULT_CONFIG.getConfig().set("debug_log", true); - ConfigHolder.DEFAULT_CONFIG.getConfig().set("debug_log_verbose", true); - } - - @Test - void vanillaUnitRepair(){ - ItemStack damagedPickaxe = new ItemStackMock(Material.DIAMOND_PICKAXE); - damagedPickaxe.setDurability((short) (Material.DIAMOND_PICKAXE.getMaxDurability() -1)); - - ItemStack resultPickaxe = new ItemStackMock(Material.DIAMOND_PICKAXE); - resultPickaxe.setDurability((short) (Material.DIAMOND_PICKAXE.getMaxDurability()/2)); - ItemMeta meta = resultPickaxe.getItemMeta(); - ((Repairable) meta).setRepairCost(1); - resultPickaxe.setItemMeta(meta); - - ItemStack diamond2 = new ItemStackMock(Material.DIAMOND, 2); - - AnvilFuseTestData legalResultData = new AnvilFuseTestData( - damagedPickaxe, diamond2, - resultPickaxe, - 2 - ); - - legalResultData.executeTest(anvil, player); - } - - @Test - void removeUnitRepair(){ - ItemStack damagedPickaxe = new ItemStackMock(Material.DIAMOND_PICKAXE); - damagedPickaxe.setDurability((short) (Material.DIAMOND_PICKAXE.getMaxDurability() -1)); - - ItemStack diamond2 = new ItemStackMock(Material.DIAMOND, 2); - - AnvilFuseTestData nullResultData = new AnvilFuseTestData( - damagedPickaxe, diamond2, - null - ); - - // Remove unit repair - assertTrue(UnitRepairApi.removeUnitRepair(Material.DIAMOND, Material.DIAMOND_PICKAXE)); - - nullResultData.executeTest(anvil, player); - - // see override - assertFalse(UnitRepairApi.addUnitRepair(Material.DIAMOND, Material.DIAMOND_PICKAXE, 0.25)); - assertTrue(UnitRepairApi.addUnitRepair(Material.DIAMOND, Material.DIAMOND_PICKAXE, 0.25, true)); - } - - - @Test - void addUnitRepair(){ - ItemStack damagedPickaxe = new ItemStackMock(Material.DIAMOND_PICKAXE); - damagedPickaxe.setDurability((short) (Material.DIAMOND_PICKAXE.getMaxDurability() -1)); - - ItemStack resultPickaxe = new ItemStackMock(Material.DIAMOND_PICKAXE); - resultPickaxe.setDurability((short) (Material.DIAMOND_PICKAXE.getMaxDurability()/2)); - ItemMeta meta = resultPickaxe.getItemMeta(); - ((Repairable) meta).setRepairCost(1); - resultPickaxe.setItemMeta(meta); - - ItemStack stick2 = new ItemStackMock(Material.STICK, 2); - - AnvilFuseTestData nullResultData = new AnvilFuseTestData( - damagedPickaxe, stick2, - null - ); - AnvilFuseTestData legalResultData = new AnvilFuseTestData( - damagedPickaxe, stick2, - resultPickaxe, - 2 - ); - - nullResultData.executeTest(anvil, player); - - // Add unit repair - assertTrue(UnitRepairApi.addUnitRepair(Material.STICK, Material.DIAMOND_PICKAXE)); - assertFalse(UnitRepairApi.addUnitRepair(Material.STICK, Material.DIAMOND_PICKAXE)); - legalResultData.executeTest(anvil, player); - } - -} diff --git a/src/test/java/xyz/alexcrea/cuanvil/api/event/CAConfigReadyEventTest.java b/src/test/java/xyz/alexcrea/cuanvil/api/event/CAConfigReadyEventTest.java deleted file mode 100644 index ff73a59..0000000 --- a/src/test/java/xyz/alexcrea/cuanvil/api/event/CAConfigReadyEventTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package xyz.alexcrea.cuanvil.api.event; - -import io.delilaheve.CustomAnvil; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.mockbukkit.mockbukkit.MockBukkit; -import org.mockbukkit.mockbukkit.matcher.plugin.PluginManagerFiredEventClassMatcher; -import xyz.alexcrea.cuanvil.tests.SharedOnlyMockBukkit; - -public class CAConfigReadyEventTest extends SharedOnlyMockBukkit { - - private CustomAnvil plugin; - - @Test - public void startup() { - boolean beforeStart = PluginManagerFiredEventClassMatcher - .hasNotFiredEventInstance(CAConfigReadyEvent.class) - .matches(server.getPluginManager()); - - Assertions.assertTrue(beforeStart, "Somehow, event fired before plugin being loaded ?"); - - // Load the plugin - plugin = MockBukkit.load(CustomAnvil.class); - - boolean postStart = PluginManagerFiredEventClassMatcher - .hasNotFiredEventInstance(CAConfigReadyEvent.class) - .matches(server.getPluginManager()); - - Assertions.assertTrue(postStart, "Event fired before plugin finished being loaded"); - - // Config load phase - server.getScheduler().performOneTick(); - boolean postConfig = PluginManagerFiredEventClassMatcher - .hasFiredEventInstance(CAConfigReadyEvent.class) - .matches(server.getPluginManager()); - - Assertions.assertTrue(postConfig, "Event did not fire after the config phase"); - } - - @AfterEach - public void pluginTeardown() { - if (plugin != null) { - server.getPluginManager().disablePlugin(plugin); - plugin = null; - } - } - -} diff --git a/src/test/java/xyz/alexcrea/cuanvil/api/event/CAEnchantRegistryReadyEventTest.java b/src/test/java/xyz/alexcrea/cuanvil/api/event/CAEnchantRegistryReadyEventTest.java deleted file mode 100644 index 2c79388..0000000 --- a/src/test/java/xyz/alexcrea/cuanvil/api/event/CAEnchantRegistryReadyEventTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package xyz.alexcrea.cuanvil.api.event; - -import io.delilaheve.CustomAnvil; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.mockbukkit.mockbukkit.MockBukkit; -import org.mockbukkit.mockbukkit.matcher.plugin.PluginManagerFiredEventClassMatcher; -import xyz.alexcrea.cuanvil.tests.SharedOnlyMockBukkit; - -public class CAEnchantRegistryReadyEventTest extends SharedOnlyMockBukkit { - - private CustomAnvil plugin; - - @Test - public void startup() { - boolean beforeStart = PluginManagerFiredEventClassMatcher - .hasNotFiredEventInstance(CAEnchantRegistryReadyEvent.class) - .matches(server.getPluginManager()); - - Assertions.assertTrue(beforeStart, "Somehow, event fired before plugin being loaded ?"); - - // Load the plugin - plugin = MockBukkit.load(CustomAnvil.class); - - boolean postStart = PluginManagerFiredEventClassMatcher - .hasNotFiredEventInstance(CAEnchantRegistryReadyEvent.class) - .matches(server.getPluginManager()); - - Assertions.assertTrue(postStart, "Event fired before plugin finished being loaded"); - - // Config load phase - server.getScheduler().performOneTick(); - boolean postConfig = PluginManagerFiredEventClassMatcher - .hasFiredEventInstance(CAEnchantRegistryReadyEvent.class) - .matches(server.getPluginManager()); - - Assertions.assertTrue(postConfig, "Event did not fire after the config phase"); - } - - @AfterEach - public void pluginTeardown() { - if (plugin != null) { - server.getPluginManager().disablePlugin(plugin); - plugin = null; - } - } - -} diff --git a/src/test/java/xyz/alexcrea/cuanvil/config/DefaultConfigTests.java b/src/test/java/xyz/alexcrea/cuanvil/config/DefaultConfigTests.java deleted file mode 100644 index ac3f73e..0000000 --- a/src/test/java/xyz/alexcrea/cuanvil/config/DefaultConfigTests.java +++ /dev/null @@ -1,89 +0,0 @@ -package xyz.alexcrea.cuanvil.config; - -import io.delilaheve.util.ConfigOptions; -import io.papermc.paper.registry.RegistryAccess; -import io.papermc.paper.registry.RegistryKey; -import org.bukkit.NamespacedKey; -import org.bukkit.configuration.file.FileConfiguration; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; -import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry; -import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity; -import xyz.alexcrea.cuanvil.tests.SharedCustomAnvilTest; - -import java.util.stream.Stream; - -public class DefaultConfigTests extends SharedCustomAnvilTest { - - @ParameterizedTest - @MethodSource("provideStringsForIsConfiguredValueValid") - public void isConfiguredValueValid(String path, Object value){ - FileConfiguration config = ConfigHolder.DEFAULT_CONFIG.getConfig(); - - Assertions.assertEquals(value.toString(), config.getString(path), "Default value is not the same as in the config file"); - } - - @ParameterizedTest - @MethodSource("provideForEnchantmentsTests") - public void testDefaultEnchantLimit(NamespacedKey key){ - CAEnchantment enchantment = CAEnchantmentRegistry.getInstance().getByKey(key); - Assertions.assertNotNull(enchantment, "Enchantment was somehow not found"); - - int levelLimit = ConfigOptions.INSTANCE.enchantLimit(enchantment); - int mergeLimit = ConfigOptions.INSTANCE.maxBeforeMergeDisabled(enchantment); - - Assertions.assertEquals(enchantment.defaultMaxLevel(), levelLimit,"Default enchantment limit is not the same as expected limit "); - - if(mergeLimit >= 0) { // negative mean default - Assertions.assertEquals(enchantment.defaultMaxLevel(), mergeLimit,"Default enchantment merge limit is not the same as expected limit "); - } - - } - - @ParameterizedTest - @MethodSource("provideForEnchantmentsTests") - public void testDefaultEnchantValues(NamespacedKey key){ - CAEnchantment enchantment = CAEnchantmentRegistry.getInstance().getByKey(key); - Assertions.assertNotNull(enchantment, "Enchantment was somehow not found"); - - int itemValue = ConfigOptions.INSTANCE.enchantmentValue(enchantment, false); - int bookValue = ConfigOptions.INSTANCE.enchantmentValue(enchantment, true); - - EnchantmentRarity rarity = enchantment.defaultRarity(); - - Assertions.assertEquals(rarity.getItemValue(), itemValue,"Default enchantment item value is not the same as expected value"); - Assertions.assertEquals(rarity.getBookValue(), bookValue,"Default enchantment book value is not the same as expected value"); - } - - - private static Stream provideStringsForIsConfiguredValueValid() { - return Stream.of( - // Default options - Arguments.of(ConfigOptions.CAP_ANVIL_COST, ConfigOptions.DEFAULT_CAP_ANVIL_COST), - Arguments.of(ConfigOptions.CAP_ANVIL_COST, ConfigOptions.DEFAULT_CAP_ANVIL_COST), - Arguments.of(ConfigOptions.MAX_ANVIL_COST, ConfigOptions.DEFAULT_MAX_ANVIL_COST), - Arguments.of(ConfigOptions.REMOVE_ANVIL_COST_LIMIT, ConfigOptions.DEFAULT_REMOVE_ANVIL_COST_LIMIT), - Arguments.of(ConfigOptions.REPLACE_TOO_EXPENSIVE, ConfigOptions.DEFAULT_REPLACE_TOO_EXPENSIVE), - Arguments.of(ConfigOptions.ITEM_REPAIR_COST, ConfigOptions.DEFAULT_ITEM_REPAIR_COST), - Arguments.of(ConfigOptions.UNIT_REPAIR_COST, ConfigOptions.DEFAULT_UNIT_REPAIR_COST), - Arguments.of(ConfigOptions.ITEM_RENAME_COST, ConfigOptions.DEFAULT_ITEM_RENAME_COST), - Arguments.of(ConfigOptions.SACRIFICE_ILLEGAL_COST, ConfigOptions.DEFAULT_SACRIFICE_ILLEGAL_COST), - // Color options - Arguments.of(ConfigOptions.ALLOW_COLOR_CODE, ConfigOptions.DEFAULT_ALLOW_COLOR_CODE), - Arguments.of(ConfigOptions.ALLOW_HEXADECIMAL_COLOR, ConfigOptions.DEFAULT_ALLOW_HEXADECIMAL_COLOR), - Arguments.of(ConfigOptions.PERMISSION_NEEDED_FOR_COLOR, ConfigOptions.DEFAULT_PERMISSION_NEEDED_FOR_COLOR), - Arguments.of(ConfigOptions.USE_OF_COLOR_COST, ConfigOptions.DEFAULT_USE_OF_COLOR_COST) - - ); - } - - // Test every enchantment defaults - private static Stream provideForEnchantmentsTests() { - return RegistryAccess.registryAccess().getRegistry(RegistryKey.ENCHANTMENT) - .stream().map(enchantment -> Arguments.of(enchantment.getKey())); - } - -} diff --git a/src/test/java/xyz/alexcrea/cuanvil/data/AnvilClickTestData.java b/src/test/java/xyz/alexcrea/cuanvil/data/AnvilClickTestData.java deleted file mode 100644 index 002b194..0000000 --- a/src/test/java/xyz/alexcrea/cuanvil/data/AnvilClickTestData.java +++ /dev/null @@ -1,57 +0,0 @@ -package xyz.alexcrea.cuanvil.data; - -import org.bukkit.entity.Player; -import org.bukkit.event.Event; -import org.bukkit.inventory.AnvilInventory; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.util.AnvilFuseTestUtil; - -public record AnvilClickTestData( - @Nullable ItemStack leftItem, - @Nullable ItemStack rightItem, - @Nullable ItemStack resultSlotItem, - @Nullable ItemStack expectedCursor, - int levelCost, - @Nullable Event.Result expectedResult, - boolean testNoLevelNoChange, - @Nullable Event.Result npChangeResult -) { - - public AnvilClickTestData(@Nullable ItemStack leftItem, - @Nullable ItemStack rightItem, - @Nullable ItemStack resultSlotItem, - @Nullable ItemStack expectedCursor, - int levelCost, - @Nullable Event.Result expectedResult) { - this(leftItem, rightItem, resultSlotItem, - expectedCursor, levelCost, expectedResult, - false, null); - } - - public AnvilClickTestData(@Nullable ItemStack leftItem, - @Nullable ItemStack rightItem, - @Nullable ItemStack resultSlotItem, - @Nullable ItemStack expectedCursor, - int levelCost) { - this(leftItem, rightItem, resultSlotItem, - expectedCursor, levelCost, null); - } - - public AnvilClickTestData(@Nullable ItemStack expectedCursor, - int levelCost, - @Nullable Event.Result expectedResult) { - this(null, null, null, - expectedCursor, levelCost, expectedResult, - false, null); - } - - public AnvilClickTestData(@Nullable ItemStack expectedCursor, - int levelCost) { - this(expectedCursor, levelCost, null); - } - - public void executeTest(AnvilInventory anvil, Player player){ - AnvilFuseTestUtil.executeAnvilClickTest(anvil, player, this); - } -} diff --git a/src/test/java/xyz/alexcrea/cuanvil/data/AnvilFuseTestData.java b/src/test/java/xyz/alexcrea/cuanvil/data/AnvilFuseTestData.java deleted file mode 100644 index 8542d41..0000000 --- a/src/test/java/xyz/alexcrea/cuanvil/data/AnvilFuseTestData.java +++ /dev/null @@ -1,61 +0,0 @@ -package xyz.alexcrea.cuanvil.data; - -import org.bukkit.entity.HumanEntity; -import org.bukkit.inventory.AnvilInventory; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.util.AnvilFuseTestUtil; - -public record AnvilFuseTestData( - @Nullable ItemStack leftItem, - @Nullable ItemStack rightItem, - @Nullable ItemStack expectedResult, - - @Nullable ItemStack expectedAfterLeftPlaced, - @Nullable ItemStack expectedAfterRightPlaced, - - @Nullable Integer expectedPriceAfterLeftPlaced, - @Nullable Integer expectedPriceAfterRightPlaced, - @Nullable Integer expectedPriceAfterBothPlaced - ){ - - public AnvilFuseTestData( - @Nullable ItemStack leftItem, - @Nullable ItemStack rightItem, - @Nullable ItemStack expectedResult, - @Nullable Integer expectedPriceAfterBothPlaced - ){ - this(leftItem, rightItem, expectedResult, - null, null, null, null, - expectedPriceAfterBothPlaced - ); - } - - public AnvilFuseTestData( - @Nullable ItemStack leftItem, - @Nullable ItemStack rightItem, - @Nullable ItemStack expectedResult - ){ - this(leftItem, rightItem, expectedResult, null - ); - } - - public AnvilFuseTestData( - @Nullable ItemStack leftItem, - @Nullable ItemStack rightItem, - @Nullable ItemStack expectedResult, - - @Nullable ItemStack expectedAfterLeftPlaced, - @Nullable ItemStack expectedAfterRightPlaced - ){ - this(leftItem, rightItem, - expectedResult, expectedAfterLeftPlaced, expectedAfterRightPlaced, - null, null, null - ); - } - - public void executeTest(AnvilInventory anvil, HumanEntity player){ - AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, this); - } - -} diff --git a/src/test/java/xyz/alexcrea/cuanvil/data/TestDataContainer.java b/src/test/java/xyz/alexcrea/cuanvil/data/TestDataContainer.java deleted file mode 100644 index b4f47a5..0000000 --- a/src/test/java/xyz/alexcrea/cuanvil/data/TestDataContainer.java +++ /dev/null @@ -1,250 +0,0 @@ -package xyz.alexcrea.cuanvil.data; - -import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.AnvilInventory; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.junit.jupiter.api.Assertions; -import xyz.alexcrea.cuanvil.util.AnvilFuseTestUtil; - -@SuppressWarnings("unused") -public record TestDataContainer( - @NotNull AnvilFuseTestData fuseData, - @Nullable AnvilClickTestData clickData -) { - - public void executeTest(AnvilInventory anvil, Player player) { - fuseData.executeTest(anvil, player); - if (clickData != null) clickData.executeTest(anvil, player); - } - - public void executeFuseTest(AnvilInventory anvil, HumanEntity player) { - fuseData.executeTest(anvil, player); - } - - public void executeClickTest(AnvilInventory anvil, Player player) { - Assertions.assertNotNull(clickData); - clickData.executeTest(anvil, player); - } - - public @NotNull TestDataContainer nullifyResult() { - return new TestDataContainer( - new AnvilFuseTestData( - fuseData.leftItem(), fuseData.rightItem(), - null - ), null); - } - - public @NotNull TestDataContainer setCost( - @Nullable Integer priceAfterLeft, - @Nullable Integer priceAfterRight, - int priceAfterBoth - ) { - AnvilFuseTestData data = new AnvilFuseTestData( - fuseData.leftItem(), fuseData.rightItem(), fuseData.expectedResult(), - fuseData.expectedAfterLeftPlaced(), - fuseData.expectedAfterRightPlaced(), - priceAfterLeft, - priceAfterRight, - priceAfterBoth - ); - - AnvilClickTestData CData; - if (clickData == null) { - CData = null; - } else { - CData = new AnvilClickTestData( - clickData.leftItem(), clickData.rightItem(), clickData.resultSlotItem(), - clickData.expectedCursor(), priceAfterBoth, - clickData.expectedResult(), - clickData.testNoLevelNoChange(), clickData.npChangeResult() - ); - } - return new TestDataContainer(data, CData); - } - - public @NotNull TestDataContainer setCost( - int priceAfterBoth - ) { - return setCost(null, null, priceAfterBoth); - } - - // Set fuse items - public @NotNull TestDataContainer setFuseItems(@Nullable ItemStack left, @Nullable ItemStack right, @Nullable ItemStack expected) { - AnvilFuseTestData data = new AnvilFuseTestData( - left, right, expected, - fuseData.expectedAfterLeftPlaced(), - fuseData.expectedAfterRightPlaced(), - fuseData.expectedPriceAfterLeftPlaced(), - fuseData.expectedPriceAfterRightPlaced(), - fuseData.expectedPriceAfterBothPlaced() - ); - return new TestDataContainer(data, clickData); - } - - public @NotNull TestDataContainer setFuseItems( - @Nullable ItemStack left, @Nullable ItemStack right, @Nullable ItemStack expected, - @Nullable ItemStack leftExpected, @Nullable ItemStack rightExpected) { - AnvilFuseTestData data = new AnvilFuseTestData( - left, right, expected, - leftExpected, - rightExpected, - fuseData.expectedPriceAfterLeftPlaced(), - fuseData.expectedPriceAfterRightPlaced(), - fuseData.expectedPriceAfterBothPlaced() - ); - return new TestDataContainer(data, clickData); - } - - public @NotNull TestDataContainer setFuseLeft(@Nullable ItemStack left) { - AnvilFuseTestData data = new AnvilFuseTestData( - left, fuseData.rightItem(), fuseData.expectedResult(), - fuseData.expectedAfterLeftPlaced(), - fuseData.expectedAfterRightPlaced(), - fuseData.expectedPriceAfterLeftPlaced(), - fuseData.expectedPriceAfterRightPlaced(), - fuseData.expectedPriceAfterBothPlaced() - ); - return new TestDataContainer(data, clickData); - } - - public @NotNull TestDataContainer setFuseRight(@Nullable ItemStack right) { - AnvilFuseTestData data = new AnvilFuseTestData( - fuseData.leftItem(), right, fuseData.expectedResult(), - fuseData.expectedAfterLeftPlaced(), - fuseData.expectedAfterRightPlaced(), - fuseData.expectedPriceAfterLeftPlaced(), - fuseData.expectedPriceAfterRightPlaced(), - fuseData.expectedPriceAfterBothPlaced() - ); - return new TestDataContainer(data, clickData); - } - - public @NotNull TestDataContainer setFuseExpected(@Nullable ItemStack expected) { - AnvilFuseTestData data = new AnvilFuseTestData( - fuseData.leftItem(), fuseData.rightItem(), expected, - fuseData.expectedAfterLeftPlaced(), - fuseData.expectedAfterRightPlaced(), - fuseData.expectedPriceAfterLeftPlaced(), - fuseData.expectedPriceAfterRightPlaced(), - fuseData.expectedPriceAfterBothPlaced() - ); - return new TestDataContainer(data, clickData); - } - - public @NotNull TestDataContainer setFuseExpectedLeft(@Nullable ItemStack expected) { - AnvilFuseTestData data = new AnvilFuseTestData( - fuseData.leftItem(), fuseData.rightItem(), fuseData.expectedResult(), - expected, - fuseData.expectedAfterRightPlaced(), - fuseData.expectedPriceAfterLeftPlaced(), - fuseData.expectedPriceAfterRightPlaced(), - fuseData.expectedPriceAfterBothPlaced() - ); - return new TestDataContainer(data, clickData); - } - - public @NotNull TestDataContainer setFuseExpectedRight(@Nullable ItemStack expected) { - AnvilFuseTestData data = new AnvilFuseTestData( - fuseData.leftItem(), fuseData.rightItem(), fuseData.expectedResult(), - fuseData.expectedAfterLeftPlaced(), - expected, - fuseData.expectedPriceAfterLeftPlaced(), - fuseData.expectedPriceAfterRightPlaced(), - fuseData.expectedPriceAfterBothPlaced() - ); - return new TestDataContainer(data, clickData); - } - - // Set click items - public @NotNull TestDataContainer setClickLeft(@Nullable ItemStack left) { - if (clickData == null) return this; - AnvilClickTestData data = new AnvilClickTestData( - left, clickData.rightItem(), clickData.resultSlotItem(), clickData.expectedCursor(), - clickData.levelCost(), clickData.expectedResult(), - clickData.testNoLevelNoChange(), clickData.npChangeResult() - ); - - return new TestDataContainer(fuseData, data); - } - - public @NotNull TestDataContainer setClickRight(@Nullable ItemStack right) { - if (clickData == null) return this; - AnvilClickTestData data = new AnvilClickTestData( - clickData.leftItem(), right, clickData.resultSlotItem(), clickData.expectedCursor(), - clickData.levelCost(), clickData.expectedResult(), - clickData.testNoLevelNoChange(), clickData.npChangeResult() - ); - - return new TestDataContainer(fuseData, data); - } - - public @NotNull TestDataContainer setClickOutput(@Nullable ItemStack output) { - if (clickData == null) return this; - AnvilClickTestData data = new AnvilClickTestData( - clickData.leftItem(), clickData.rightItem(), output, clickData.expectedCursor(), - clickData.levelCost(), clickData.expectedResult(), - clickData.testNoLevelNoChange(), clickData.npChangeResult() - ); - - return new TestDataContainer(fuseData, data); - } - - public @NotNull TestDataContainer setClickCursor(@Nullable ItemStack cursor) { - if (clickData == null) return this; - AnvilClickTestData data = new AnvilClickTestData( - clickData.leftItem(), clickData.rightItem(), clickData.resultSlotItem(), cursor, - clickData.levelCost(), clickData.expectedResult(), - clickData.testNoLevelNoChange(), clickData.npChangeResult() - ); - - return new TestDataContainer(fuseData, data); - } - - // Both item - public @NotNull TestDataContainer setExpectedResult(@Nullable ItemStack result) { - return setFuseExpected(result).setClickCursor(result); - } - - // Get fuse item - public @Nullable ItemStack getLeftFuse() { - return fuseData.leftItem(); - } - - public @Nullable ItemStack getRightFuse() { - return fuseData.rightItem(); - } - - public @Nullable ItemStack getExpectedFuse() { - return fuseData.expectedResult(); - } - - public @Nullable ItemStack getLeftExpectedFuse() { - return fuseData.expectedAfterLeftPlaced(); - } - - public @Nullable ItemStack getRightExpectedFuse() { - return fuseData.expectedAfterRightPlaced(); - } - - // Get click item - public @Nullable ItemStack getLeftClick() { - return clickData == null ? null : clickData.leftItem(); - } - - public @Nullable ItemStack getRightClick() { - return clickData == null ? null : clickData.rightItem(); - } - - public @Nullable ItemStack getOutputClick() { - return clickData == null ? null : clickData.resultSlotItem(); - } - - public @Nullable ItemStack getCursorClick() { - return clickData == null ? null : clickData.expectedCursor(); - } - - -} diff --git a/src/test/java/xyz/alexcrea/cuanvil/mock/AnvilViewMock.java b/src/test/java/xyz/alexcrea/cuanvil/mock/AnvilViewMock.java deleted file mode 100644 index afcbb26..0000000 --- a/src/test/java/xyz/alexcrea/cuanvil/mock/AnvilViewMock.java +++ /dev/null @@ -1,81 +0,0 @@ -package xyz.alexcrea.cuanvil.mock; - -import org.bukkit.entity.HumanEntity; -import org.bukkit.inventory.AnvilInventory; -import org.bukkit.inventory.view.AnvilView; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.mockbukkit.mockbukkit.inventory.PlayerInventoryViewMock; - -@SuppressWarnings({"removal"}) -public class AnvilViewMock extends PlayerInventoryViewMock implements AnvilView { - - private @NotNull AnvilInventory top; - - /** - * Constructs a new {@link PlayerInventoryViewMock} for the provided player, with the specified top inventory. - * - * @param player The player to create the view for. - * @param top The top inventory. - */ - public AnvilViewMock(@NotNull HumanEntity player, @NotNull AnvilInventory top) { - super(player, top); - this.top = top; - } - - @Override - public @Nullable String getRenameText() { - return top.getRenameText(); - } - - @Override - public int getRepairItemCountCost() { - return top.getRepairCostAmount(); - } - - @Override - public int getRepairCost() { - return top.getRepairCost(); - } - - @Override - public int getMaximumRepairCost() { - return top.getMaximumRepairCost(); - } - - @Override - public void setRepairItemCountCost(int amount) { - top.setRepairCostAmount(amount); - } - - @Override - public void setRepairCost(int cost) { - top.setRepairCost(cost); - } - - @Override - public void setMaximumRepairCost(int levels) { - top.setMaximumRepairCost(levels); - } - - @Override - public boolean bypassesEnchantmentLevelRestriction() { - throw new UnsupportedOperationException("This is currently is not used in CustomAnvil"); - } - - @Override - public void bypassEnchantmentLevelRestriction(boolean bypassEnchantmentLevelRestriction) { - throw new UnsupportedOperationException("This is currently is not used in CustomAnvil"); - } - - @Override - public @NotNull AnvilInventory getTopInventory() { - return top; - } - - @Override - public void open() { - throw new UnsupportedOperationException("This is currently is not used in CustomAnvil"); - } - -} diff --git a/src/test/java/xyz/alexcrea/cuanvil/tests/ConfigResetCustomAnvilTest.java b/src/test/java/xyz/alexcrea/cuanvil/tests/ConfigResetCustomAnvilTest.java deleted file mode 100644 index 3c03bb4..0000000 --- a/src/test/java/xyz/alexcrea/cuanvil/tests/ConfigResetCustomAnvilTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package xyz.alexcrea.cuanvil.tests; - -import org.junit.jupiter.api.AfterEach; -import xyz.alexcrea.cuanvil.config.ConfigHolder; - -import java.io.File; - -public abstract class ConfigResetCustomAnvilTest extends DefaultCustomAnvilTest { - - @Override - @AfterEach - public void tearDown() { - // Destroy saved config file - String[] configs = new String[]{ - "config.yml", - "item_groups.yml", - "enchant_conflict.yml", - "unit_repair_item.yml", - "custom_recipes.yml" - }; - for (String config : configs) { - File configFile = new File(plugin.getDataFolder(), config); - configFile.delete(); - } - - // Set config to null - ConfigHolder.DEFAULT_CONFIG = null; - ConfigHolder.ITEM_GROUP_HOLDER = null; - ConfigHolder.CONFLICT_HOLDER = null; - ConfigHolder.UNIT_REPAIR_HOLDER = null; - ConfigHolder.CUSTOM_RECIPE_HOLDER = null; - - // Do parent works - super.tearDown(); - } - - -} diff --git a/src/test/java/xyz/alexcrea/cuanvil/tests/DefaultCustomAnvilTest.java b/src/test/java/xyz/alexcrea/cuanvil/tests/DefaultCustomAnvilTest.java deleted file mode 100644 index bdb280c..0000000 --- a/src/test/java/xyz/alexcrea/cuanvil/tests/DefaultCustomAnvilTest.java +++ /dev/null @@ -1,54 +0,0 @@ -package xyz.alexcrea.cuanvil.tests; - -import io.delilaheve.CustomAnvil; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.mockbukkit.mockbukkit.MockBukkit; -import org.mockbukkit.mockbukkit.ServerMock; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; -import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry; - -import java.util.ArrayList; -import java.util.List; - -public abstract class DefaultCustomAnvilTest { - - protected static ServerMock server; - protected CustomAnvil plugin; - - @BeforeAll - public static void setupMock() { - server = MockBukkit.mock(); - } - - @BeforeEach - public void setUp() { - // Load your plugin - plugin = MockBukkit.load(CustomAnvil.class); - // Continue initialization of the plugin - server.getScheduler().performOneTick(); - } - - @AfterEach - public void tearDown() { - // Unregister enchantments - List toUnregister = new ArrayList<>( - CAEnchantmentRegistry.getInstance().values() - ); - - for (CAEnchantment caEnchantment : toUnregister) { - CAEnchantmentRegistry.getInstance().unregister(caEnchantment); - } - - server.getPluginManager().disablePlugin(plugin); - } - - @AfterAll - public static void tearDownMock() { - // Stop the mock server - MockBukkit.unmock(); - } - -} diff --git a/src/test/java/xyz/alexcrea/cuanvil/tests/SharedCustomAnvilTest.java b/src/test/java/xyz/alexcrea/cuanvil/tests/SharedCustomAnvilTest.java deleted file mode 100644 index 02844f4..0000000 --- a/src/test/java/xyz/alexcrea/cuanvil/tests/SharedCustomAnvilTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package xyz.alexcrea.cuanvil.tests; - -import io.delilaheve.CustomAnvil; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.mockbukkit.mockbukkit.MockBukkit; -import org.mockbukkit.mockbukkit.ServerMock; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; -import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry; - -import java.util.ArrayList; -import java.util.List; - -public abstract class SharedCustomAnvilTest { - - protected static ServerMock server; - protected static CustomAnvil plugin; - - @BeforeAll - public static void setUp() { - // Start the mock server - server = MockBukkit.mock(); - // Load your plugin - plugin = MockBukkit.load(CustomAnvil.class); - // Continue initialization of the plugin - server.getScheduler().performOneTick(); - } - - @AfterAll - public static void tearDown() { - // Stop the mock server - MockBukkit.unmock(); - - // Unregister enchantments - List toUnregister = new ArrayList<>( - CAEnchantmentRegistry.getInstance().values() - ); - - for (CAEnchantment caEnchantment : toUnregister) { - CAEnchantmentRegistry.getInstance().unregister(caEnchantment); - } - - } - -} diff --git a/src/test/java/xyz/alexcrea/cuanvil/tests/SharedOnlyMockBukkit.java b/src/test/java/xyz/alexcrea/cuanvil/tests/SharedOnlyMockBukkit.java deleted file mode 100644 index 0f38239..0000000 --- a/src/test/java/xyz/alexcrea/cuanvil/tests/SharedOnlyMockBukkit.java +++ /dev/null @@ -1,24 +0,0 @@ -package xyz.alexcrea.cuanvil.tests; - -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.mockbukkit.mockbukkit.MockBukkit; -import org.mockbukkit.mockbukkit.ServerMock; - -public class SharedOnlyMockBukkit { - - protected static ServerMock server; - - @BeforeAll - public static void setUp() { - // Start the mock server - server = MockBukkit.mock(); - } - - @AfterAll - public static void tearDown() { - // Stop the mock server - MockBukkit.unmock(); - } - -} diff --git a/src/test/java/xyz/alexcrea/cuanvil/util/AnvilFuseTestUtil.java b/src/test/java/xyz/alexcrea/cuanvil/util/AnvilFuseTestUtil.java deleted file mode 100644 index 6f5c7bb..0000000 --- a/src/test/java/xyz/alexcrea/cuanvil/util/AnvilFuseTestUtil.java +++ /dev/null @@ -1,271 +0,0 @@ -package xyz.alexcrea.cuanvil.util; - -import io.delilaheve.util.ItemUtil; -import org.bukkit.Material; -import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.Player; -import org.bukkit.event.Event; -import org.bukkit.event.inventory.*; -import org.bukkit.inventory.AnvilInventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.inventory.meta.Repairable; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.junit.jupiter.api.Assertions; -import xyz.alexcrea.cuanvil.data.AnvilClickTestData; -import xyz.alexcrea.cuanvil.data.AnvilFuseTestData; -import xyz.alexcrea.cuanvil.enchant.CAEnchantment; -import xyz.alexcrea.cuanvil.listener.AnvilResultListener; -import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener; -import xyz.alexcrea.cuanvil.mock.AnvilViewMock; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -public class AnvilFuseTestUtil { - - private static PrepareAnvilListener PREPARE_LISTENER = new PrepareAnvilListener(); - private static AnvilResultListener RESULT_LISTENER = new AnvilResultListener(); - - public static ItemStack prepareItem(@NotNull Material material, - @NotNull List enchantments, - @NotNull List level) { - return prepareItem(material, 0, enchantments, level); - } - - public static ItemStack prepareItem(@NotNull Material material, - int repairCost, - @NotNull List enchantments, - @NotNull List level) { - Assertions.assertEquals(enchantments.size(), level.size()); - - HashMap enchantmentMap = new HashMap<>(); - for (int i = 0; i < enchantments.size(); i++) { - enchantmentMap.put(enchantments.get(i), level.get(i)); - } - - ItemStack item = new ItemStack(material); - ItemUtil.INSTANCE.setEnchantmentsUnsafe(item, enchantmentMap); - - ItemMeta meta = item.getItemMeta(); - ((Repairable) meta).setRepairCost(repairCost); - item.setItemMeta(meta); - - return item; - } - - - public static ItemStack prepareItem(@NotNull Material material, - @NotNull List enchantmentNames, - Integer... levels) { - return prepareItem(material, 0, enchantmentNames, levels); - } - - public static ItemStack prepareItem(@NotNull Material material, - int repairCost, - @NotNull List enchantmentNames, - Integer... levels) { - List enchantments = new ArrayList<>(); - - for (String enchantmentName : enchantmentNames) { - List enchantmentList = CAEnchantment.getListByName(enchantmentName); - Assertions.assertNotEquals(0, enchantmentList.size(), - "Could not find enchantment \"" + enchantmentName + "\""); - - enchantments.addAll(enchantmentList); - } - - return prepareItem(material, repairCost, enchantments, List.of(levels)); - } - - - /* - * Need to use that as it seems setting item in the inventory will not trigger the anvil click even - * - * Not the best for non-custom anvil plugins but work in the context of CA - */ - public static void imitateAnvilUpdate( - @NotNull HumanEntity player, - @NotNull AnvilInventory anvil) { - - AnvilViewMock view = new AnvilViewMock(player, anvil); - try { - PrepareAnvilEvent event = new PrepareAnvilEvent(view, anvil.getItem(2)); - - // Not ideal but possible and the easiest so why not - PREPARE_LISTENER.anvilCombineCheck(event); - anvil.setResult(event.getResult()); - } catch (Exception e) { - Assertions.fail(e); - } - } - - public static void executeAnvilFuseTest( - @NotNull AnvilInventory anvil, - @NotNull HumanEntity player, - @NotNull AnvilFuseTestData data - ) { - Assertions.assertEquals(player.getOpenInventory().getTopInventory(), anvil, - "Openned inventory is not anvil"); - - ItemStack afterLeft = data.expectedAfterLeftPlaced(); - ItemStack afterRight = data.expectedAfterRightPlaced(); - ItemStack afterBoth = data.expectedResult(); - // Fist, test null result(s) - - // Test with only the left item - if(afterLeft == null){ - anvil.setItem(1, null); // We clear the right slot in case something was there - testPlacingItem(anvil, player, - 0, data.expectedPriceAfterLeftPlaced(), - data.leftItem(), null); - } - - // Test with only the right item - if(afterRight == null){ - anvil.setItem(0, null); // We only want the right item. so we remove the left one - testPlacingItem(anvil, player, - 1, data.expectedPriceAfterRightPlaced(), - data.rightItem(), null); - } - - // Test with both placed - if(afterBoth == null){ - anvil.setItem(0, data.leftItem()); - testPlacingItem(anvil, player, - 1, data.expectedPriceAfterBothPlaced(), - data.rightItem(), data.expectedResult()); - } - - // Then, test non null result(s) - - // Test with only the left item - if(afterLeft != null){ - anvil.setItem(1, null); // We clear the right slot in case something was there - testPlacingItem(anvil, player, - 0, data.expectedPriceAfterLeftPlaced(), - data.leftItem(), afterLeft); - } - - // Test with only the right item - if(afterRight != null){ - anvil.setItem(0, null); // We only want the right item. so we remove the left one - testPlacingItem(anvil, player, - 1, data.expectedPriceAfterRightPlaced(), - data.rightItem(), afterRight); - } - - // Test with both placed - if(afterBoth != null){ - anvil.setItem(0, data.leftItem()); - testPlacingItem(anvil, player, - 1, data.expectedPriceAfterBothPlaced(), - data.rightItem(), afterBoth); - } - } - - public static void executeAnvilClickTest( - @NotNull AnvilInventory anvil, - @NotNull Player player, - @NotNull AnvilClickTestData data - ) { - if (data.testNoLevelNoChange()) { - ItemStack left = anvil.getFirstItem(); - ItemStack right = anvil.getSecondItem(); - ItemStack result = anvil.getResult(); - - player.setLevel(0); - player.setExp(0); - player.setItemOnCursor(null); - - // Do a test with not enough level - simulateClick(anvil, player, data.npChangeResult()); - - // Nothing should have changed - assertEqual(left, anvil.getFirstItem()); - assertEqual(right, anvil.getSecondItem()); - assertEqual(result, anvil.getResult()); - assertEqual(null, player.getItemOnCursor()); - } - player.setLevel(data.levelCost()); - player.setExp(0); - player.setItemOnCursor(null); - - simulateClick(anvil, player, data.expectedResult()); - - // Should have simulated the click - assertEqual(data.leftItem(), anvil.getFirstItem()); - assertEqual(data.rightItem(), anvil.getSecondItem()); - assertEqual(data.resultSlotItem(), anvil.getResult()); - assertEqual(data.expectedCursor(), data.expectedCursor()); - - // Test if the player has no more xp - Assertions.assertEquals(0, player.getLevel(), "Player has more level than expected"); - } - - private static void simulateClick( - @NotNull AnvilInventory anvil, - @NotNull Player player, - @Nullable Event.Result expectedResult - ) { - AnvilViewMock view = new AnvilViewMock(player, anvil); - try { - InventoryClickEvent event = new InventoryClickEvent(view, - InventoryType.SlotType.RESULT, - PrepareAnvilListener.ANVIL_OUTPUT_SLOT, - ClickType.LEFT, - InventoryAction.PICKUP_ALL); - - RESULT_LISTENER.anvilExtractionCheck(event); - if (expectedResult != null) { - Assertions.assertEquals(expectedResult, event.getResult()); - } - } catch (Exception e) { - Assertions.fail(e); - } - } - - @SuppressWarnings({"removal"}) - private static void testPlacingItem( - @NotNull AnvilInventory anvil, - @NotNull HumanEntity player, - int slot, - Integer expectedPrice, - @Nullable ItemStack toPlace, - @Nullable ItemStack expectedResult) { - anvil.setItem(slot, toPlace); - anvil.setItem(2, null); - AnvilFuseTestUtil.imitateAnvilUpdate(player, anvil); - - ItemStack result = anvil.getItem(2); - assertEqual(expectedResult, result); - - assertPriceEqual(expectedPrice, anvil.getRepairCost()); - } - - public static void assertEqual(@Nullable ItemStack expected, @Nullable ItemStack other) { - boolean secondIsAir = isAir(other); - if (isAir(expected)) - Assertions.assertTrue(secondIsAir, "Item " + other + " was not air but was expected to be."); - else { - Assertions.assertFalse(secondIsAir, "Item " + other + " is air but was expected to be " + expected); - - expected.setDurability(expected.getDurability()); - other.setDurability(other.getDurability()); - Assertions.assertEquals(expected, other); - } - - } - - public static boolean isAir(@Nullable ItemStack item) { - return item == null || item.isEmpty() || item.getAmount() == 0; - } - - public static void assertPriceEqual(Integer expectedPrice, int price) { - if (expectedPrice == null) return; - Assertions.assertEquals(expectedPrice, price, "Price of anvil fuse was wrong"); - } - -} diff --git a/src/test/java/xyz/alexcrea/cuanvil/util/CommonItemUtil.java b/src/test/java/xyz/alexcrea/cuanvil/util/CommonItemUtil.java deleted file mode 100644 index 1228cda..0000000 --- a/src/test/java/xyz/alexcrea/cuanvil/util/CommonItemUtil.java +++ /dev/null @@ -1,27 +0,0 @@ -package xyz.alexcrea.cuanvil.util; - -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; - -import java.util.List; - -public class CommonItemUtil { - - public static ItemStack sharpness(int level){ - return AnvilFuseTestUtil.prepareItem( - Material.DIAMOND_SWORD, - List.of("sharpness"), - level - ); - } - - public static ItemStack bane_of_arthropods(int level){ - return AnvilFuseTestUtil.prepareItem( - Material.DIAMOND_SWORD, - List.of("bane_of_arthropods"), - level - ); - } - - -} diff --git a/src/test/resources/plugin.yml b/src/test/resources/plugin.yml deleted file mode 100644 index 37fb95a..0000000 --- a/src/test/resources/plugin.yml +++ /dev/null @@ -1,73 +0,0 @@ -main: io.delilaheve.CustomAnvil -name: CustomAnvil -prefix: "Custom Anvil" -version: test -folia-supported: true -description: Allow to customise anvil mechanics -api-version: 1.16 -load: POSTWORLD -authors: [ DelilahEve, alexcrea ] -libraries: - - org.jetbrains.kotlin:kotlin-stdlib:2.0.21 - -commands: - customanvil: - description: Generic command for custom anvil - anvilconfigreload: - description: Reload every config of this plugin - permission: ca.command.reload - aliases: - #- acreload # anvil config reload - #- careload # custom anvil reload - - carl # custom anvil reload - customanvilconfig: - description: open a menu for administrator to edit plugin's config in game - permission: ca.config.edit - aliases: - - configanvil - -permissions: - ca.affected: - default: true - description: Player with this permission will be affected by the plugin - ca.bypass.fuse: - default: false - description: Allow player to combine every enchantments to every item (no custom limit) - ca.bypass.level: - default: false - description: Allow player to bypass every level limit (no custom limit) - ca.command.reload: - default: op - description: Allow administrator to reload the plugin's configs - ca.command.diagnostic: - default: op - description: Get debug information about the plugin and server - ca.config.edit: - default: op - description: Allow administrator to edit the plugin's config in game - # color permissions - ca.color.code: - default: op - description: Allow player to use color code if enabled (toggleable) - ca.color.hex: - default: op - description: Allow player to use hexadecimal color if enabled (toggleable) - # lore edit permissions - ca.lore_edit.book: - default: op - description: Allow player to edit lore via book and quil if enabled (toggleable) - ca.lore_edit.paper: - default: op - description: Allow player to edit lore via paper if enabled (toggleable) - -# soft depend on old name of this plugin (UnsafeEnchantsPlus), so I can disable it if it is on the same server -# Also depend to other plugin for compatibility -softdepend: - - UnsafeEnchantsPlus - - ProtocolLib - - Disenchantment - - EnchantsSquared - - EcoEnchants - - eco - - ExcellentEnchants - - HavenBags