diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index a50cacd..753ffaa 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -9,155 +9,74 @@ name: Java CI with Gradle on: push: - branches: [ "v1.x.x", "v2.x.x" ] + branches: [ "master" ] 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 + branches: [ "master" ] jobs: build: + + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - uses: actions/checkout@v4 + - name: Set up JDKs + uses: actions/setup-java@v4 + with: + java-version: | + 16 + 17 + 20 + 21 + distribution: 'temurin' + cache: 'gradle' + + # 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@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 + + - name: Make gradlew executable + run: chmod +x ./gradlew + - name: Build with Gradle Wrapper + run: ./gradlew build --parallel + + - name: Summarize tests results + uses: jeantessier/test-summary-action@v1 + if: ${{ always() }} + + # NOTE: The Gradle Wrapper is the default and recommended way to run Gradle (https://docs.gradle.org/current/userguide/gradle_wrapper.html). + # If your project does not have the Gradle Wrapper configured, you can use the following configuration to run Gradle with a specified version. + # + # - name: Setup Gradle + # uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 + # with: + # gradle-version: '8.9' + # + # - name: Build with Gradle 8.9 + # run: gradle build + + dependency-submission: + 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: | + - uses: actions/checkout@v4 + - name: Set up JDKs + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: | + 16 + 17 + 20 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 }} + # Generates and submits a dependency graph, enabling Dependabot Alerts for all project dependencies. + # See: https://github.com/gradle/actions/blob/main/dependency-submission/README.md + - name: Generate and submit dependency graph + uses: gradle/actions/dependency-submission@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 diff --git a/.gitignore b/.gitignore index 982299c..b005983 100644 --- a/.gitignore +++ b/.gitignore @@ -14,9 +14,6 @@ /impl/*/build /impl/*/.gradle -# run folder -/run/ - # other random folders /htmlReport -/.kotlin/errors +/.kotlin/errors \ No newline at end of file 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/README.md b/README.md index 9d9e678..1704a26 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,18 @@ # Custom Anvil **Custom Anvil** is a plugin that allows server administrators to customize every aspect of the anvil's mechanics. +It is expected to work on 1.18 to 1.21.5 minecraft servers running spigot or paper. +(the plugin support of 1.16.5 to 1.17.1 is experimental and may encounter issues) + +**Custom Anvil** was previously named **Unsafe Enchants+**. +It was renamed because it now affects every anvil aspect and not only unsafe enchants\ +**Custom Anvil** is based on [Unsafe Enchants](https://github.com/DelilahEve/UnsafeEnchants) by DelilahEve. ### Download Locations: the plugin can be downloaded on - [Modrinth](https://modrinth.com/plugin/customanvil), +[Spigot](https://www.spigotmc.org/resources/custom-anvil.114884), + [modrinth](https://modrinth.com/plugin/customanvil), [Hangar](https://hangar.papermc.io/alexcrea/CustomAnvil) or here [on GitHub](https://github.com/alexcrea/CustomAnvil/releases/latest) @@ -14,98 +21,94 @@ the plugin can be downloaded on - 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 enchant restrictions (allow 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 +- Support of color code and hexadecimal color - (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) +# usage of these permission is toggleable in basic config gui or config.yml + +# Permissions related to use of color +ca.color.code: Allow player to use color code if enabled (toggleable) +ca.color.hex: Allow player to use hexadecimal color 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) ``` ### Commands - -run `/customanvil help` to get information about available commands \ -this only show subcommands you have permission for - +```yml +anvilconfigreload or carl: Reload every config of this plugin +customanvilconfig or configanvil: open a menu for administrator to edit plugin's config in game +``` ### Supported Plugins -See the [Compatibility list](https://github.com/alexcrea/CustomAnvil/blob/v1.x.x/COMPATIBILITY.md) +Custom Anvil can be compatible with some custom enchantments and anvil mechanics plugins. + +Here is a list of supported custom enchantment plugins with support status: +- [Enchantment²](https://www.spigotmc.org/resources/enchants-squared-the-enchantsplus-rewrite-custom-enchantments-that-act-like-vanilla-ones.86747/): +Support by Custom Anvil but still experimental. Automatic configuration. + +- [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/): +Support by Custom Anvil but still experimental. Need to use /anvilconfigreload or a server restart to add newly added enchantment. +Use EcoEnchant restriction system by default. + +- [ExcellentEnchants](https://www.spigotmc.org/resources/excellentenchants-%E2%AD%90-75-vanilla-like-enchantments.61693/): +Support by Custom Anvil but still experimental. Use ExcellentEnchants item type. + +- [Superenchants](https://modrinth.com/plugin/superenchants) +support by Superenchants. Use CustomAnvil to combine enchantment in anvil in survival. + +Here is a list of supported anvil mechanic plugins with support status: +- [Disenchantment](https://www.spigotmc.org/resources/disenchantment-1-21-1-1-20-6-new-book-splitting-mechanics.110741/) +support by Custom Anvil but still experimental. Mostly use Custom Anvil basic XP settings. (version >= 6.1.5) + +- [HavenBags](https://www.spigotmc.org/resources/havenbags-shulker-like-player-bound-bags-1-17-1-21-4.110420/) +support by Custom Anvil. Not really enchantment related but CustomAnvil should not impact bag upgrade and skin via anvil. (version >= 1.31.0) + +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 on my free time for free. ### 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 +Minecraft version 1.17 to 1.21.5 do not need any dependency. Other version need ProtocoLib enabled on your server for this feature. \ +You can also wait for an update of the plugin to support a newer version. + +Please note that 1.16.5 to 1.17.1 are not officially supported. Run at your own risk. ### 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) +(Please note that the wiki is currently incomplete)​ --- ### Default Plugin's Configurations -see [Here](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs) +For 1.18 to 1.20.6 use the [1.18 configurations](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.18)\ +For 1.21 to 1.21.5 use the [1.21 configurations](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21) --- -### 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) +Custom anvil [use bstat](https://bstats.org/plugin/bukkit/Unsafe%20Enchants%20Plus/20923) for metric. You can [disable it](https://bstats.org/getting-started) if you like. ### Planned: - Better Folia support (make gui work. fix some dirty handled parts) -- Get restriction on unknown enchantments (planned for V2) +- Get restriction on unknown enchantments - 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..d83775a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,68 +1,33 @@ 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 "2.1.0" java id("org.jetbrains.dokka").version("1.9.20") - id("com.gradleup.shadow").version("9.3.0") + id("com.gradleup.shadow").version("8.3.5") // Maven publish `maven-publish` signing - id("cn.lalaki.central").version("1.2.8") + id("cn.lalaki.central").version("1.2.5") // Paper - id("io.papermc.paperweight.userdev") version "2.0.0-beta.17" apply false - id("io.papermc.hangar-publish-plugin") version "0.1.2" + id("io.papermc.paperweight.userdev") version "2.0.0-beta.16" apply false } 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 "") +version = "1.11.2" 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/") } } -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") - - // minimessage - implementation("net.kyori:adventure-text-minimessage:4.25.0") - // Gui library val inventoryFramework = "xyz.alexcrea.cuanvil.inventoryframework:IF-CustomAnvil:0.10.18.2" implementation(inventoryFramework) @@ -71,22 +36,15 @@ dependencies { // EnchantsSquaredRewritten compileOnly(files("libs/EnchantsSquared.jar")) - // EcoEnchants & item - compileOnly("com.willfp:libreforge:4.79.0:all") - compileOnly("com.willfp:eco:6.74.5") - + // EcoEnchants compileOnly("com.willfp:EcoEnchants:12.11.1") + compileOnly("com.willfp:eco:6.74.5") 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 + compileOnly(files("libs/nightcore-2.7.3.jar")) + compileOnly(files("libs/ExcellentEnchants-4.3.1.jar")) + compileOnly(files("libs/ExcellentEnchants 4.1.0-striped.jar")) // For legacy excellent enchants // Disenchantment compileOnly(files("libs/Disenchantment-6.1.5.jar")) @@ -97,24 +55,22 @@ dependencies { // 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")) - } + implementation(project(":nms:v1_17R1", configuration = "reobf")) + implementation(project(":nms:v1_18R1", configuration = "reobf")) + implementation(project(":nms:v1_18R2", configuration = "reobf")) + implementation(project(":nms:v1_19R1", configuration = "reobf")) + implementation(project(":nms:v1_19R2", configuration = "reobf")) + implementation(project(":nms:v1_19R3", configuration = "reobf")) + implementation(project(":nms:v1_20R1", configuration = "reobf")) + implementation(project(":nms:v1_20R2", configuration = "reobf")) + implementation(project(":nms:v1_20R3", configuration = "reobf")) + implementation(project(":nms:v1_20R4", configuration = "reobf")) + implementation(project(":nms:v1_21R1", configuration = "reobf")) + implementation(project(":nms:v1_21R2", configuration = "reobf")) + implementation(project(":nms:v1_21R3", configuration = "reobf")) + implementation(project(":nms:v1_21R4", configuration = "reobf")) // include kotlin for the offline jar implementation(kotlin("stdlib")) @@ -159,8 +115,7 @@ allprojects { // 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. + sourceCompatibility = "16" // We aim for java 16 for minecraft 1.16.5. even if it not really suported by custom anvil. targetCompatibility = "16" options.encoding = "UTF-8" @@ -168,29 +123,43 @@ allprojects { kotlin { compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) jvmTarget.set(JvmTarget.JVM_16) } } } +// Fat-jar builder +val fatJar = tasks.register("fatJar") { + manifest { + attributes.apply { put("Main-Class", "io.delilaheve.CustomAnvil") } + } + archiveFileName.set("${rootProject.name}-${project.version}.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) +} tasks { + // Online jar (use of libraries) + shadowJar { + // No suffix for this jar + archiveClassifier.set("") - fun ShadowJar.configureBaseShadow(suffix: String, libraries: Array) { - val processedSuffix = if(suffix.isEmpty()) "" else "-$suffix" - val name = "${rootProject.name}-${effectiveVersion}${processedSuffix}.jar" - archiveFileName.set(name) + // Exclude kotlin std and its annotation + exclude("**/kotlin-stdlib*.jar") + exclude("**/annotations*.jar") // Shadow necessary dependency - relocate("com.github.stefvanschie.inventoryframework", "xyz.alexcrea.cuanvil.inventoryframework") - relocate("dev.faststats", "xyz.alexcrea.cuanvil.faststats") + relocate("com.github.stefvanschie.inventoryframework", "xyz.alexcrea.inventoryframework") + // Replace version and example fields in plugin.yml filesMatching("plugin.yml") { expand( - "version" to effectiveVersion + processedSuffix, - "libraries" to libraries.joinToString(transform = { "\"$it\"" }), + "version" to project.version, + "libraries" to " \"org.jetbrains.kotlin:kotlin-stdlib:2.1.0\" " ) } @@ -198,28 +167,35 @@ tasks { 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", - )) + // Offline jar (include kotlin std in the final jar fine) + val offlineJar by // Shadow necessary dependency + registering( - // Exclude kotlin std, annotations and adventure api - exclude("*kotlin/**") - exclude("**/annotations/**") - exclude("net/kyori/**") - } + // Include all project other dependencies + ShadowJar - val offlineJar by registering(ShadowJar::class) { - configureBaseShadow("offline", emptyArray()) + // Add custom anvil compiled + ::class, fun ShadowJar.() { + archiveClassifier.set("offline") - from(sourceSets.main.get().output) - configurations = listOf(project.configurations.runtimeClasspath.get()) - } + // Shadow necessary dependency + relocate("com.github.stefvanschie.inventoryframework", "xyz.alexcrea.inventoryframework") + + filesMatching("plugin.yml") { + expand( + "version" to "${project.version}-offline", + "libraries" to "" + ) + } + + // Include all project other dependencies + from(project.configurations.runtimeClasspath) + + // Add custom anvil compiled + from(sourceSets.main.get().output) + + dependsOn(processResources) + }) // Make the online and offline jar on build named("build") { @@ -272,10 +248,6 @@ object Meta { 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 { @@ -291,16 +263,6 @@ publishing { 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) @@ -333,123 +295,7 @@ publishing { 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) - } - } } } } } - -// 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") - } - -} diff --git a/defaultconfigs/1.18/config.yml b/defaultconfigs/1.18/config.yml index b5ad3b0..9c1ad67 100644 --- a/defaultconfigs/1.18/config.yml +++ b/defaultconfigs/1.18/config.yml @@ -3,19 +3,6 @@ # 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: @@ -72,22 +59,8 @@ sacrifice_illegal_enchant_cost: 1 # # 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. # @@ -99,23 +72,10 @@ permission_needed_for_color: true # 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 +# Default limit to apply to any enchants missing from enchant_limits # -# 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 values include 1 to 1000 +default_limit: 5 # Override limits for specific enchants # @@ -123,8 +83,7 @@ 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 @@ -306,20 +265,11 @@ enchant_values: # 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) + # Sharpness is set to -1. it equivalent to it not being set to anything (and work as vanilla) 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: @@ -342,12 +292,9 @@ lore_edit: # # 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 + allow_hexadecimal_color: true + use_cost: 0 remove: # If removing lore using book & quil is enabled @@ -362,25 +309,16 @@ lore_edit: shared_additive: false # If removing the lore consume the book & quil do_consume: false + # If the color should get back to color code or hex format + remove_color_on_remove: true # 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 + order: "end" append_line: # If adding lore line using paper is enabled @@ -397,12 +335,8 @@ lore_edit: # # 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 + allow_hexadecimal_color: true color_use_cost: 0 remove_line: @@ -416,46 +350,10 @@ lore_edit: shared_additive: false # If removing the lore line consume the paper do_consume: false + # If the color should get back to color code or hex format + remove_color_on_remove: true # 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 @@ -463,4 +361,10 @@ debug_log: false # Whether to show verbose debug logging debug_log_verbose: false -configVersion: 1.11.0 +# In case something when wrong with CustomAnvil packet manager. +# If you see "missing class exception" or similar you may test this. +# If enabled and Protocolib absent or disabled "Replace to expensive" will not work. +# ProtocoLib may also be used if the server is in an "unsupported" version even if this option is disabled. +force_protocolib: false + +configVersion: 1.8.0 diff --git a/defaultconfigs/1.18/enchant_conflict.yml b/defaultconfigs/1.18/enchant_conflict.yml index 45d62c3..0e8b3f3 100644 --- a/defaultconfigs/1.18/enchant_conflict.yml +++ b/defaultconfigs/1.18/enchant_conflict.yml @@ -92,10 +92,6 @@ 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 ] 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/config.yml b/defaultconfigs/1.21/config.yml index 5d59e5a..9c1ad67 100644 --- a/defaultconfigs/1.21/config.yml +++ b/defaultconfigs/1.21/config.yml @@ -3,19 +3,6 @@ # 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: @@ -72,22 +59,8 @@ sacrifice_illegal_enchant_cost: 1 # # 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. # @@ -99,23 +72,10 @@ permission_needed_for_color: true # 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 +# Default limit to apply to any enchants missing from enchant_limits # -# 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 values include 1 to 1000 +default_limit: 5 # Override limits for specific enchants # @@ -123,8 +83,7 @@ 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 @@ -306,19 +265,10 @@ enchant_values: # 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) + # Sharpness is set to -1. it equivalent to it not being set to anything (and work as vanilla) 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 + # If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied + #minecraft:unbreaking: 2 # Settings for lore modification lore_edit: @@ -342,12 +292,9 @@ lore_edit: # # 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 + allow_hexadecimal_color: true + use_cost: 0 remove: # If removing lore using book & quil is enabled @@ -362,25 +309,16 @@ lore_edit: shared_additive: false # If removing the lore consume the book & quil do_consume: false + # If the color should get back to color code or hex format + remove_color_on_remove: true # 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 + order: "end" append_line: # If adding lore line using paper is enabled @@ -397,12 +335,8 @@ lore_edit: # # 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 + allow_hexadecimal_color: true color_use_cost: 0 remove_line: @@ -416,46 +350,10 @@ lore_edit: shared_additive: false # If removing the lore line consume the paper do_consume: false + # If the color should get back to color code or hex format + remove_color_on_remove: true # 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 @@ -463,4 +361,10 @@ debug_log: false # Whether to show verbose debug logging debug_log_verbose: false -configVersion: 1.11.0 \ No newline at end of file +# In case something when wrong with CustomAnvil packet manager. +# If you see "missing class exception" or similar you may test this. +# If enabled and Protocolib absent or disabled "Replace to expensive" will not work. +# ProtocoLib may also be used if the server is in an "unsupported" version even if this option is disabled. +force_protocolib: false + +configVersion: 1.8.0 diff --git a/defaultconfigs/1.21/enchant_conflict.yml b/defaultconfigs/1.21/enchant_conflict.yml index 45d62c3..0e8b3f3 100644 --- a/defaultconfigs/1.21/enchant_conflict.yml +++ b/defaultconfigs/1.21/enchant_conflict.yml @@ -92,10 +92,6 @@ 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 ] diff --git a/defaultconfigs/README.md b/defaultconfigs/README.md index daa2088..72c88ca 100644 --- a/defaultconfigs/README.md +++ b/defaultconfigs/README.md @@ -1,5 +1,3 @@ ### 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) +For 1.18 to 1.20.6 use [1.18 configurations](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.18) \ +For 1.21 use [1.21 configurations](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21) \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 4397d2e..b302864 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,13 +1,8 @@ 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 +signing.gnupg.executable=gpg +signing.gnupg.useLegacyGpg=true +signing.gnupg.keyName=2D3280C5 +kotlin.daemon.jvmargs=-Xmx8G \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0b55a3b..d6e308a 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-8.12-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/build.gradle.kts b/impl/LegacyEcoEnchant/build.gradle.kts index 83057a7..a53c04c 100644 --- a/impl/LegacyEcoEnchant/build.gradle.kts +++ b/impl/LegacyEcoEnchant/build.gradle.kts @@ -2,7 +2,7 @@ group = rootProject.group version = rootProject.version plugins { - kotlin("jvm") version "2.3.0" + kotlin("jvm") version "2.1.0" } // Imitate needed class and method to support legacy version of EcoEnchant @@ -10,4 +10,6 @@ dependencies { // Spigot api compileOnly("org.spigotmc:spigot-api:1.18-R0.1-SNAPSHOT") + + } \ No newline at end of file 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/ExcellentEnchants-4.1.0-striped.jar b/libs/ExcellentEnchants 4.1.0-striped.jar similarity index 100% rename from libs/ExcellentEnchants-4.1.0-striped.jar rename to libs/ExcellentEnchants 4.1.0-striped.jar diff --git a/libs/ExcellentEnchants-4.3.1.jar b/libs/ExcellentEnchants-4.3.1.jar new file mode 100644 index 0000000..47ea157 Binary files /dev/null and b/libs/ExcellentEnchants-4.3.1.jar 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/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/nms/nms-common/build.gradle.kts b/nms/nms-common/build.gradle.kts index 950d807..d1f224d 100644 --- a/nms/nms-common/build.gradle.kts +++ b/nms/nms-common/build.gradle.kts @@ -1,35 +1,16 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - group = rootProject.group version = rootProject.version -plugins { - id("io.papermc.paperweight.userdev") +repositories { + // ProtocoLib + maven (url = "https://repo.dmulloy2.net/repository/public/" ) + } dependencies { - // Used for nms - paperweight.paperDevBundle("1.21.10-R0.1-SNAPSHOT") + // Spigot api + compileOnly("org.spigotmc:spigot-api:1.18-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) - } -} + compileOnly("com.comphenix.protocol:ProtocolLib:5.1.0") +} \ No newline at end of file diff --git a/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/ExternGuiTester.kt b/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/ExternGuiTester.kt new file mode 100644 index 0000000..c709954 --- /dev/null +++ b/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/ExternGuiTester.kt @@ -0,0 +1,49 @@ +package xyz.alexcrea.cuanvil.dependency.gui + +import org.bukkit.inventory.InventoryView + +interface ExternGuiTester { + + val wesjdAnvilGuiName: String? + + fun getContainerClass(inventory: InventoryView): Class? + + fun testIfGui(inventory: InventoryView): Boolean { + // this mean we are on test + //TODO review why needed knowing previous mitigations should works + if(inventory.javaClass.name.endsWith("AnvilViewMock")) return false + + val clazz = getContainerClass(inventory) ?: return false + + val clazzName = clazz.name + //TODO maybe instead of testing non default, better to be testing we are default ? + if (expectWesjd(clazzName)) return true + if (expectXenondevUI(clazzName)) return true + if (expectVanePortal(clazzName)) return true + + return false + } + + fun expectWesjd(name: String): Boolean { + val expectedWesjdGuiPath = "anvilgui.version.$wesjdAnvilGuiName" + + 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/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/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/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/build.gradle.kts b/nms/v1_17R1/build.gradle.kts index c354b1c..0480a4b 100644 --- a/nms/v1_17R1/build.gradle.kts +++ b/nms/v1_17R1/build.gradle.kts @@ -19,6 +19,14 @@ repositories { } +// As minecraft 1.17 recommended java version is 1.16. we set language version to 1.16 + +// Configure used version of kotlin and java +java { + disableAutoTargetJvm() + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) +} + // Set target version tasks.withType().configureEach { sourceCompatibility = "16" @@ -29,7 +37,7 @@ tasks.withType().configureEach { kotlin { compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) jvmTarget.set(JvmTarget.JVM_16) } } diff --git a/nms/v1_17R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_17R1_ExternGuiTester.kt b/nms/v1_17R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_17R1_ExternGuiTester.kt new file mode 100644 index 0000000..8e352e0 --- /dev/null +++ b/nms/v1_17R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_17R1_ExternGuiTester.kt @@ -0,0 +1,16 @@ +package xyz.alexcrea.cuanvil.dependency.gui.version + +import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftInventoryView +import org.bukkit.inventory.InventoryView +import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester + +class v1_17R1_ExternGuiTester: ExternGuiTester { + override val wesjdAnvilGuiName = "Wrapper1_17_R1" + + override fun getContainerClass(view: InventoryView): Class? { + if (view !is CraftInventoryView) return null + val container = view.handle + + return container.javaClass + } +} \ No newline at end of file diff --git a/nms/v1_18R1/build.gradle.kts b/nms/v1_18R1/build.gradle.kts index 44873d5..cab1611 100644 --- a/nms/v1_18R1/build.gradle.kts +++ b/nms/v1_18R1/build.gradle.kts @@ -19,6 +19,14 @@ repositories { } +// As minecraft 1.18 work with java 1.17 or above. we set language version to 1.17 + +// Configure used version of kotlin and java +java { + disableAutoTargetJvm() + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) +} + // Set target version tasks.withType().configureEach { sourceCompatibility = "17" @@ -29,7 +37,7 @@ tasks.withType().configureEach { kotlin { compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) jvmTarget.set(JvmTarget.JVM_17) } } diff --git a/nms/v1_18R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_18R1_ExternGuiTester.kt b/nms/v1_18R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_18R1_ExternGuiTester.kt new file mode 100644 index 0000000..659a0f6 --- /dev/null +++ b/nms/v1_18R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_18R1_ExternGuiTester.kt @@ -0,0 +1,16 @@ +package xyz.alexcrea.cuanvil.dependency.gui.version + +import org.bukkit.craftbukkit.v1_18_R1.inventory.CraftInventoryView +import org.bukkit.inventory.InventoryView +import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester + +class v1_18R1_ExternGuiTester: ExternGuiTester { + override val wesjdAnvilGuiName = "Wrapper1_18_R1" + + override fun getContainerClass(view: InventoryView): Class? { + if (view !is CraftInventoryView) return null + val container = view.handle + + return container.javaClass + } +} \ No newline at end of file diff --git a/nms/v1_18R2/build.gradle.kts b/nms/v1_18R2/build.gradle.kts index cf349ec..9f7c5a5 100644 --- a/nms/v1_18R2/build.gradle.kts +++ b/nms/v1_18R2/build.gradle.kts @@ -19,6 +19,14 @@ repositories { } +// As minecraft 1.18 work with java 1.17 or above. we set language version to 1.17 + +// Configure used version of kotlin and java +java { + disableAutoTargetJvm() + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) +} + // Set target version tasks.withType().configureEach { sourceCompatibility = "17" @@ -29,7 +37,7 @@ tasks.withType().configureEach { kotlin { compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) jvmTarget.set(JvmTarget.JVM_17) } } diff --git a/nms/v1_18R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_18R2_ExternGuiTester.kt b/nms/v1_18R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_18R2_ExternGuiTester.kt new file mode 100644 index 0000000..1447716 --- /dev/null +++ b/nms/v1_18R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_18R2_ExternGuiTester.kt @@ -0,0 +1,16 @@ +package xyz.alexcrea.cuanvil.dependency.gui.version + +import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftInventoryView +import org.bukkit.inventory.InventoryView +import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester + +class v1_18R2_ExternGuiTester: ExternGuiTester { + override val wesjdAnvilGuiName = "Wrapper1_18_R2" + + override fun getContainerClass(view: InventoryView): Class? { + if (view !is CraftInventoryView) return null + val container = view.handle + + return container.javaClass + } +} \ No newline at end of file diff --git a/nms/v1_19R1/build.gradle.kts b/nms/v1_19R1/build.gradle.kts index 9791b9b..b9a5a1a 100644 --- a/nms/v1_19R1/build.gradle.kts +++ b/nms/v1_19R1/build.gradle.kts @@ -19,6 +19,14 @@ repositories { } +// I do not know minecraft 1.19 recommended java version. assumed 17 is good enough + +// Configure used version of kotlin and java +java { + disableAutoTargetJvm() + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) +} + // Set target version tasks.withType().configureEach { sourceCompatibility = "17" @@ -29,7 +37,7 @@ tasks.withType().configureEach { kotlin { compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) jvmTarget.set(JvmTarget.JVM_17) } } diff --git a/nms/v1_19R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_19R1_ExternGuiTester.kt b/nms/v1_19R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_19R1_ExternGuiTester.kt new file mode 100644 index 0000000..c151924 --- /dev/null +++ b/nms/v1_19R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_19R1_ExternGuiTester.kt @@ -0,0 +1,16 @@ +package xyz.alexcrea.cuanvil.dependency.gui.version + +import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftInventoryView +import org.bukkit.inventory.InventoryView +import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester + +class v1_19R1_ExternGuiTester: ExternGuiTester { + override val wesjdAnvilGuiName = "Wrapper1_19_R1" + + override fun getContainerClass(view: InventoryView): Class? { + if (view !is CraftInventoryView) return null + val container = view.handle + + return container.javaClass + } +} \ No newline at end of file diff --git a/nms/v1_19R2/build.gradle.kts b/nms/v1_19R2/build.gradle.kts index 88f1a8a..a4df488 100644 --- a/nms/v1_19R2/build.gradle.kts +++ b/nms/v1_19R2/build.gradle.kts @@ -19,6 +19,14 @@ repositories { } +// I do not know minecraft 1.19 recommended java version. assumed 17 is good enough + +// Configure used version of kotlin and java +java { + disableAutoTargetJvm() + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) +} + // Set target version tasks.withType().configureEach { sourceCompatibility = "17" @@ -29,7 +37,7 @@ tasks.withType().configureEach { kotlin { compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) jvmTarget.set(JvmTarget.JVM_17) } } diff --git a/nms/v1_19R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_19R2_ExternGuiTester.kt b/nms/v1_19R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_19R2_ExternGuiTester.kt new file mode 100644 index 0000000..ac46674 --- /dev/null +++ b/nms/v1_19R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_19R2_ExternGuiTester.kt @@ -0,0 +1,16 @@ +package xyz.alexcrea.cuanvil.dependency.gui.version + +import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftInventoryView +import org.bukkit.inventory.InventoryView +import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester + +class v1_19R2_ExternGuiTester: ExternGuiTester { + override val wesjdAnvilGuiName = "Wrapper1_19_R2" + + override fun getContainerClass(view: InventoryView): Class? { + if (view !is CraftInventoryView) return null + val container = view.handle + + return container.javaClass + } +} \ No newline at end of file diff --git a/nms/v1_19R3/build.gradle.kts b/nms/v1_19R3/build.gradle.kts index 3d609af..84476a3 100644 --- a/nms/v1_19R3/build.gradle.kts +++ b/nms/v1_19R3/build.gradle.kts @@ -19,6 +19,14 @@ repositories { } +// I do not know minecraft 1.19 recommended java version. assumed 17 is good enough + +// Configure used version of kotlin and java +java { + disableAutoTargetJvm() + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) +} + // Set target version tasks.withType().configureEach { sourceCompatibility = "17" @@ -29,7 +37,7 @@ tasks.withType().configureEach { kotlin { compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) jvmTarget.set(JvmTarget.JVM_17) } } diff --git a/nms/v1_19R3/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_19R3_ExternGuiTester.kt b/nms/v1_19R3/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_19R3_ExternGuiTester.kt new file mode 100644 index 0000000..7ce5abd --- /dev/null +++ b/nms/v1_19R3/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_19R3_ExternGuiTester.kt @@ -0,0 +1,16 @@ +package xyz.alexcrea.cuanvil.dependency.gui.version + +import org.bukkit.craftbukkit.v1_19_R3.inventory.CraftInventoryView +import org.bukkit.inventory.InventoryView +import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester + +class v1_19R3_ExternGuiTester: ExternGuiTester { + override val wesjdAnvilGuiName = "Wrapper1_19_R3" + + override fun getContainerClass(view: InventoryView): Class? { + if (view !is CraftInventoryView) return null + val container = view.handle + + return container.javaClass + } +} \ No newline at end of file diff --git a/nms/v1_20R1/build.gradle.kts b/nms/v1_20R1/build.gradle.kts index 67b46b5..e71d674 100644 --- a/nms/v1_20R1/build.gradle.kts +++ b/nms/v1_20R1/build.gradle.kts @@ -19,17 +19,25 @@ repositories { } +// minecraft 1.20 recommended java version is 18. but we assume 17 is good enough as lts + +// Configure used version of kotlin and java +java { + disableAutoTargetJvm() + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) +} + // Set target version tasks.withType().configureEach { - sourceCompatibility = "18" - targetCompatibility = "18" + 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_18) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) + jvmTarget.set(JvmTarget.JVM_17) } } diff --git a/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/datapack/DataPackTester.kt b/nms/v1_20R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/datapack/DataPackTester.kt similarity index 68% rename from nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/datapack/DataPackTester.kt rename to nms/v1_20R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/datapack/DataPackTester.kt index 9003fdf..831ba58 100644 --- a/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/datapack/DataPackTester.kt +++ b/nms/v1_20R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/datapack/DataPackTester.kt @@ -2,7 +2,6 @@ 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 { @@ -22,13 +21,6 @@ object DataPackTester { .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 diff --git a/nms/v1_20R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_20R1_ExternGuiTester.kt b/nms/v1_20R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_20R1_ExternGuiTester.kt new file mode 100644 index 0000000..dae3b98 --- /dev/null +++ b/nms/v1_20R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_20R1_ExternGuiTester.kt @@ -0,0 +1,16 @@ +package xyz.alexcrea.cuanvil.dependency.gui.version + +import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftInventoryView +import org.bukkit.inventory.InventoryView +import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester + +class v1_20R1_ExternGuiTester: ExternGuiTester { + override val wesjdAnvilGuiName = "Wrapper1_20_R1" + + override fun getContainerClass(view: InventoryView): Class? { + if (view !is CraftInventoryView) return null + val container = view.handle + + return container.javaClass + } +} diff --git a/nms/v1_20R2/build.gradle.kts b/nms/v1_20R2/build.gradle.kts index e8417cd..47ebfce 100644 --- a/nms/v1_20R2/build.gradle.kts +++ b/nms/v1_20R2/build.gradle.kts @@ -19,17 +19,25 @@ repositories { } +// minecraft 1.20 recommended java version is 18. but we assume 17 is good enough as lts + +// Configure used version of kotlin and java +java { + disableAutoTargetJvm() + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) +} + // Set target version tasks.withType().configureEach { - sourceCompatibility = "18" - targetCompatibility = "18" + 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_18) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) + jvmTarget.set(JvmTarget.JVM_17) } } diff --git a/nms/v1_20R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_20R2_ExternGuiTester.kt b/nms/v1_20R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_20R2_ExternGuiTester.kt new file mode 100644 index 0000000..6a8358a --- /dev/null +++ b/nms/v1_20R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_20R2_ExternGuiTester.kt @@ -0,0 +1,17 @@ +package xyz.alexcrea.cuanvil.dependency.gui.version + +import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftInventoryView +import org.bukkit.inventory.InventoryView +import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester +import kotlin.jvm.javaClass + +class v1_20R2_ExternGuiTester: ExternGuiTester { + override val wesjdAnvilGuiName = "Wrapper1_20_R2" + + override fun getContainerClass(view: InventoryView): Class? { + if (view !is CraftInventoryView) return null + val container = view.handle + + return container.javaClass + } +} diff --git a/nms/v1_20R3/build.gradle.kts b/nms/v1_20R3/build.gradle.kts index c49ff48..eb4d3c3 100644 --- a/nms/v1_20R3/build.gradle.kts +++ b/nms/v1_20R3/build.gradle.kts @@ -19,17 +19,25 @@ repositories { } +// minecraft 1.20 recommended java version is 18. but we assume 17 is good enough as lts + +// Configure used version of kotlin and java +java { + disableAutoTargetJvm() + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) +} + // Set target version tasks.withType().configureEach { - sourceCompatibility = "18" - targetCompatibility = "18" + 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_18) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) + jvmTarget.set(JvmTarget.JVM_17) } } diff --git a/nms/v1_20R3/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_20R3_ExternGuiTester.kt b/nms/v1_20R3/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_20R3_ExternGuiTester.kt new file mode 100644 index 0000000..80362e2 --- /dev/null +++ b/nms/v1_20R3/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_20R3_ExternGuiTester.kt @@ -0,0 +1,17 @@ +package xyz.alexcrea.cuanvil.dependency.gui.version + +import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftInventoryView +import org.bukkit.inventory.InventoryView +import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester +import kotlin.jvm.javaClass + +class v1_20R3_ExternGuiTester: ExternGuiTester { + override val wesjdAnvilGuiName = "Wrapper1_20_R3" + + override fun getContainerClass(view: InventoryView): Class? { + if (view !is CraftInventoryView) return null + val container = view.handle + + return container.javaClass + } +} diff --git a/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/scheduler/FoliaScheduler.kt b/nms/v1_20R3/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/scheduler/FoliaScheduler.kt similarity index 100% rename from nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/scheduler/FoliaScheduler.kt rename to nms/v1_20R3/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/scheduler/FoliaScheduler.kt diff --git a/nms/v1_20R4/build.gradle.kts b/nms/v1_20R4/build.gradle.kts index 3b98361..00f5c68 100644 --- a/nms/v1_20R4/build.gradle.kts +++ b/nms/v1_20R4/build.gradle.kts @@ -19,10 +19,18 @@ repositories { } +// minecraft 1.20 recommended java version is 18. but we assume 17 is good enough as lts + +// Configure used version of kotlin and java +java { + disableAutoTargetJvm() + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) +} + // Set target version tasks.withType().configureEach { - sourceCompatibility = "18" - targetCompatibility = "18" + sourceCompatibility = "17" + targetCompatibility = "17" options.encoding = "UTF-8" } @@ -30,6 +38,6 @@ tasks.withType().configureEach { kotlin { compilerOptions { apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) - jvmTarget.set(JvmTarget.JVM_18) + jvmTarget.set(JvmTarget.JVM_17) } } diff --git a/nms/v1_20R4/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_20R4_ExternGuiTester.kt b/nms/v1_20R4/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_20R4_ExternGuiTester.kt new file mode 100644 index 0000000..16e867c --- /dev/null +++ b/nms/v1_20R4/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_20R4_ExternGuiTester.kt @@ -0,0 +1,17 @@ +package xyz.alexcrea.cuanvil.dependency.gui.version + +import org.bukkit.craftbukkit.inventory.CraftInventoryView +import org.bukkit.inventory.InventoryView +import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester +import kotlin.jvm.javaClass + +class v1_20R4_ExternGuiTester: ExternGuiTester { + override val wesjdAnvilGuiName = "Wrapper1_20_R4" + + override fun getContainerClass(view: InventoryView): Class? { + if (view !is CraftInventoryView) return null + val container = view.handle + + return container.javaClass + } +} 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/build.gradle.kts b/nms/v1_21R1/build.gradle.kts index bf2152c..435d09c 100644 --- a/nms/v1_21R1/build.gradle.kts +++ b/nms/v1_21R1/build.gradle.kts @@ -19,6 +19,14 @@ repositories { } +// minecraft 1.21 java version is 21. + +// Configure used version of kotlin and java +java { + disableAutoTargetJvm() + toolchain.languageVersion.set(JavaLanguageVersion.of(21)) +} + // Set target version tasks.withType().configureEach { sourceCompatibility = "21" @@ -29,7 +37,7 @@ tasks.withType().configureEach { kotlin { compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) jvmTarget.set(JvmTarget.JVM_21) } } diff --git a/nms/v1_21R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_21R1_ExternGuiTester.kt b/nms/v1_21R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_21R1_ExternGuiTester.kt new file mode 100644 index 0000000..3111735 --- /dev/null +++ b/nms/v1_21R1/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_21R1_ExternGuiTester.kt @@ -0,0 +1,17 @@ +package xyz.alexcrea.cuanvil.dependency.gui.version + +import org.bukkit.craftbukkit.inventory.CraftInventoryView +import org.bukkit.inventory.InventoryView +import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester + +class v1_21R1_ExternGuiTester: ExternGuiTester { + override val wesjdAnvilGuiName = "Wrapper1_21_R1" + + override fun getContainerClass(view: InventoryView): Class? { + if(view !is CraftInventoryView<*, *>) return null + val container = view.handle + + return container.javaClass + } + +} diff --git a/nms/v1_21R2/build.gradle.kts b/nms/v1_21R2/build.gradle.kts index e65f6fd..36dc7ac 100644 --- a/nms/v1_21R2/build.gradle.kts +++ b/nms/v1_21R2/build.gradle.kts @@ -19,6 +19,14 @@ repositories { } +// minecraft 1.21 java version is 21. + +// Configure used version of kotlin and java +java { + disableAutoTargetJvm() + toolchain.languageVersion.set(JavaLanguageVersion.of(21)) +} + // Set target version tasks.withType().configureEach { sourceCompatibility = "21" @@ -29,7 +37,7 @@ tasks.withType().configureEach { kotlin { compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) jvmTarget.set(JvmTarget.JVM_21) } } diff --git a/nms/v1_21R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_21R2_ExternGuiTester.kt b/nms/v1_21R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_21R2_ExternGuiTester.kt new file mode 100644 index 0000000..2604a16 --- /dev/null +++ b/nms/v1_21R2/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_21R2_ExternGuiTester.kt @@ -0,0 +1,34 @@ +package xyz.alexcrea.cuanvil.dependency.gui.version + +import org.bukkit.craftbukkit.inventory.CraftInventoryView +import org.bukkit.inventory.InventoryView +import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester + +class v1_21R2_ExternGuiTester: ExternGuiTester { + override val wesjdAnvilGuiName = "Wrapper1_21_R2" + + var tested = false; + var possible = false; + + override fun getContainerClass(view: InventoryView): Class? { + // In case we are in a test environment + if(!tested) testClassExist() + if(!possible) return null + + if(view !is CraftInventoryView<*, *>) return null + val container = view.handle + + return container.javaClass + } + + fun testClassExist(){ + tested = true; + try { + Class.forName("org.bukkit.craftbukkit.inventory.CraftInventoryView") + possible = true + } catch (e: ClassNotFoundException){ + possible = false + } + } + +} diff --git a/nms/v1_21R3/build.gradle.kts b/nms/v1_21R3/build.gradle.kts index d06816c..19d2ffd 100644 --- a/nms/v1_21R3/build.gradle.kts +++ b/nms/v1_21R3/build.gradle.kts @@ -19,6 +19,14 @@ repositories { } +// minecraft 1.21 java version is 21. + +// Configure used version of kotlin and java +java { + disableAutoTargetJvm() + toolchain.languageVersion.set(JavaLanguageVersion.of(21)) +} + // Set target version tasks.withType().configureEach { sourceCompatibility = "21" @@ -29,7 +37,7 @@ tasks.withType().configureEach { kotlin { compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) jvmTarget.set(JvmTarget.JVM_21) } } diff --git a/nms/v1_21R3/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_21R3_ExternGuiTester.kt b/nms/v1_21R3/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_21R3_ExternGuiTester.kt new file mode 100644 index 0000000..70c5df9 --- /dev/null +++ b/nms/v1_21R3/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_21R3_ExternGuiTester.kt @@ -0,0 +1,17 @@ +package xyz.alexcrea.cuanvil.dependency.gui.version + +import org.bukkit.craftbukkit.inventory.CraftInventoryView +import org.bukkit.inventory.InventoryView +import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester + +class v1_21R3_ExternGuiTester: ExternGuiTester { + override val wesjdAnvilGuiName = "Wrapper1_21_R3" + + override fun getContainerClass(view: InventoryView): Class? { + if(view !is CraftInventoryView<*, *>) return null + val container = view.handle + + return container.javaClass + } + +} diff --git a/nms/v1_21R4/build.gradle.kts b/nms/v1_21R4/build.gradle.kts index 8bd22b9..dcd0a7e 100644 --- a/nms/v1_21R4/build.gradle.kts +++ b/nms/v1_21R4/build.gradle.kts @@ -11,11 +11,21 @@ dependencies { implementation(project(":nms:nms-common")) // Used for nms - paperweight.paperDevBundle("1.21.5-R0.1-SNAPSHOT") + paperweight.paperDevBundle("1.21.5-no-moonrise-SNAPSHOT") } repositories { maven("https://repo.papermc.io/repository/maven-public/") + + mavenLocal()//TODO remove when paperDevBundle 1.21.5 release +} + +// minecraft 1.21 java version is 21. + +// Configure used version of kotlin and java +java { + disableAutoTargetJvm() + toolchain.languageVersion.set(JavaLanguageVersion.of(21)) } // Set target version @@ -28,7 +38,7 @@ tasks.withType().configureEach { kotlin { compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) jvmTarget.set(JvmTarget.JVM_21) } } diff --git a/nms/v1_21R4/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_21R4_ExternGuiTester.kt b/nms/v1_21R4/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_21R4_ExternGuiTester.kt new file mode 100644 index 0000000..6b76451 --- /dev/null +++ b/nms/v1_21R4/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/version/v1_21R4_ExternGuiTester.kt @@ -0,0 +1,34 @@ +package xyz.alexcrea.cuanvil.dependency.gui.version + +import org.bukkit.craftbukkit.inventory.CraftInventoryView +import org.bukkit.inventory.InventoryView +import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester + +class v1_21R4_ExternGuiTester: ExternGuiTester { + override val wesjdAnvilGuiName = "Wrapper1_21_R4" + + var tested = false; + var possible = false; + + override fun getContainerClass(view: InventoryView): Class? { + // In case we are in a test environment + if(!tested) testClassExist() + if(!possible) return null + + if(view !is CraftInventoryView<*, *>) return null + val container = view.handle + + return container.javaClass + } + + fun testClassExist(){ + tested = true; + try { + Class.forName("org.bukkit.craftbukkit.inventory.CraftInventoryView") + possible = true + } catch (e: ClassNotFoundException){ + possible = false + } + } + +} 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..b77c2f3 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -3,20 +3,34 @@ rootProject.name = "CustomAnvil" // NMS subproject include("nms:nms-common") findProject(":nms:nms-common")?.name = "nms-common" -include("nms:nms-paper") -findProject(":nms:nms-paper")?.name = "nms-paper" +include("nms:v1_17R1") +findProject(":nms:v1_17R1")?.name = "v1_17R1" +include("nms:v1_18R1") +findProject(":nms:v1_18R1")?.name = "v1_18R1" +include("nms:v1_18R2") +findProject(":nms:v1_18R2")?.name = "v1_18R2" +include("nms:v1_19R1") +findProject(":nms:v1_19R1")?.name = "v1_19R1" +include("nms:v1_19R2") +findProject(":nms:v1_19R2")?.name = "v1_19R2" +include("nms:v1_19R3") +findProject(":nms:v1_19R3")?.name = "v1_19R3" +include("nms:v1_20R1") +findProject(":nms:v1_20R1")?.name = "v1_20R1" +include("nms:v1_20R2") +findProject(":nms:v1_20R2")?.name = "v1_20R2" +include("nms:v1_20R3") +findProject(":nms:v1_20R3")?.name = "v1_20R3" +include("nms:v1_20R4") +findProject(":nms:v1_20R4")?.name = "v1_20R4" +include("nms:v1_21R1") +findProject(":nms:v1_21R1")?.name = "v1_21R1" +include("nms:v1_21R2") +findProject(":nms:v1_21R2")?.name = "v1_21R2" +include("nms:v1_21R3") +findProject(":nms:v1_21R3")?.name = "v1_21R3" +include("nms:v1_21R4") +findProject(":nms:v1_21R4")?.name = "v1_21R4" - -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 +findProject(":impl:LegacyEcoEnchant")?.name = "LegacyEcoEnchant" \ 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 index 4292fa0..9d33bfb 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/api/AnvilRecipeBuilder.java +++ b/src/main/java/xyz/alexcrea/cuanvil/api/AnvilRecipeBuilder.java @@ -14,10 +14,7 @@ public class AnvilRecipeBuilder { private @NotNull String name; private boolean exactCount; - private int levelCostPerCraft; - private int linearXpCostPerCraft; - - private boolean removeExactLinearXp; + private int xpCostPerCraft; private @Nullable ItemStack leftItem; private @Nullable ItemStack rightItem; @@ -26,7 +23,7 @@ public class AnvilRecipeBuilder { /** * Instantiates a new Anvil recipe builder. * exact count default to true. - * xp level and linear cost per craft default to 0. + * xp cost per craft default to 1. * * @param name The recipe name */ @@ -34,9 +31,7 @@ public class AnvilRecipeBuilder { this.name = name; this.exactCount = true; - this.levelCostPerCraft = 0; - this.linearXpCostPerCraft = 0; - this.removeExactLinearXp = false; + this.xpCostPerCraft = 1; this.leftItem = null; this.rightItem = null; @@ -65,7 +60,7 @@ public class AnvilRecipeBuilder { } /** - * Get if the recipe is exact count. (default 0) + * Get 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. @@ -91,14 +86,12 @@ public class AnvilRecipeBuilder { } /** - * Get the xp level cost per craft. (default 0) + * Get the xp level cost per craft. * * @return The xp level cost per craft - * @deprecated use {@link #getLevelCostPerCraft() getLevelCostPerCraft} instead */ - @Deprecated(since = "1.13.0") public int getXpCostPerCraft() { - return getLevelCostPerCraft(); + return xpCostPerCraft; } /** @@ -106,78 +99,9 @@ public class AnvilRecipeBuilder { * * @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; + this.xpCostPerCraft = xpCostPerCraft; return this; } @@ -258,14 +182,12 @@ public class AnvilRecipeBuilder { */ @Nullable // null if missing argument public AnvilCustomRecipe build() { - if (leftItem == null || resultItem == null) return null; + if(leftItem == null || resultItem == null) return null; return new AnvilCustomRecipe( this.name, this.exactCount, - this.levelCostPerCraft, - this.linearXpCostPerCraft, - this.removeExactLinearXp, + this.xpCostPerCraft, this.leftItem, this.rightItem, this.resultItem ); } @@ -276,7 +198,7 @@ public class AnvilRecipeBuilder { * * @return True if successful. */ - public boolean registerIfAbsent() { + public boolean registerIfAbsent(){ return CustomAnvilRecipeApi.addRecipe(this); } diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/ConflictBuilder.java b/src/main/java/xyz/alexcrea/cuanvil/api/ConflictBuilder.java index 1460766..f662140 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/api/ConflictBuilder.java +++ b/src/main/java/xyz/alexcrea/cuanvil/api/ConflictBuilder.java @@ -13,7 +13,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -//TODO add conflict after level /** * A Builder for material conflict. */ diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/EnchantmentApi.java b/src/main/java/xyz/alexcrea/cuanvil/api/EnchantmentApi.java index ac98225..76f1ac2 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/api/EnchantmentApi.java +++ b/src/main/java/xyz/alexcrea/cuanvil/api/EnchantmentApi.java @@ -1,7 +1,6 @@ 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; @@ -181,13 +180,13 @@ public class EnchantmentApi { private static boolean tryWriteDefaultConfig(FileConfiguration defaultConfig, CAEnchantment enchantment, boolean override) { boolean hasChange = false; - String levelPath = ConfigOptions.ENCHANT_LIMIT_ROOT + "." + enchantment.getKey(); + String levelPath = "enchant_limits." + enchantment.getKey(); if(override || !defaultConfig.isSet(levelPath)){ defaultConfig.set(levelPath, enchantment.defaultMaxLevel()); hasChange = true; } - String basePath = ConfigOptions.ENCHANT_VALUES_ROOT + "." + enchantment.getKey(); + String basePath = "enchant_values." + enchantment.getKey(); EnchantmentRarity rarity = enchantment.defaultRarity(); String itemPath = basePath + ".item"; diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/MaterialGroupApi.java b/src/main/java/xyz/alexcrea/cuanvil/api/MaterialGroupApi.java index cd71c7a..48dd500 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/api/MaterialGroupApi.java +++ b/src/main/java/xyz/alexcrea/cuanvil/api/MaterialGroupApi.java @@ -3,7 +3,6 @@ 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; @@ -124,7 +123,7 @@ public class MaterialGroupApi { FileConfiguration config = ConfigHolder.ITEM_GROUP_HOLDER.getConfig(); String basePath = group.getName() + "."; - Set materialSet = group.getNonGroupInheritedMaterials(); + Set materialSet = group.getNonGroupInheritedMaterials(); Set groupSet = group.getGroups(); boolean empty = true; @@ -154,7 +153,7 @@ public class MaterialGroupApi { FileConfiguration config = ConfigHolder.ITEM_GROUP_HOLDER.getConfig(); String basePath = group.getName() + "."; - Set materials = group.getMaterials(); + EnumSet materials = group.getMaterials(); if (materials.isEmpty()) return false; @@ -164,8 +163,8 @@ public class MaterialGroupApi { return true; } - public static List materialSetToStringList(@NotNull Set materials) { - return materials.stream().map(NamespacedKey::toString).toList(); + public static List materialSetToStringList(@NotNull Set materials) { + return materials.stream().map(material -> material.getKey().getKey().toLowerCase()).toList(); } public static List materialGroupSetToStringList(@NotNull Set groups) { diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/event/CAConfigReadyEvent.java b/src/main/java/xyz/alexcrea/cuanvil/api/event/CAConfigReadyEvent.java index 67d27a8..24691db 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/api/event/CAConfigReadyEvent.java +++ b/src/main/java/xyz/alexcrea/cuanvil/api/event/CAConfigReadyEvent.java @@ -3,23 +3,6 @@ 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(); diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/event/CAEnchantRegistryReadyEvent.java b/src/main/java/xyz/alexcrea/cuanvil/api/event/CAEnchantRegistryReadyEvent.java index 3ffe372..3e2fdf8 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/api/event/CAEnchantRegistryReadyEvent.java +++ b/src/main/java/xyz/alexcrea/cuanvil/api/event/CAEnchantRegistryReadyEvent.java @@ -3,17 +3,6 @@ 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(); 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 index f6a7e80..2037e23 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/config/ConfigHolder.java +++ b/src/main/java/xyz/alexcrea/cuanvil/config/ConfigHolder.java @@ -9,7 +9,6 @@ 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; @@ -146,7 +145,6 @@ public abstract class ConfigHolder { 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 @@ -277,7 +275,6 @@ public abstract class ConfigHolder { 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); @@ -315,7 +312,6 @@ public abstract class ConfigHolder { 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; } diff --git a/src/main/java/xyz/alexcrea/cuanvil/config/WorkPenaltyType.java b/src/main/java/xyz/alexcrea/cuanvil/config/WorkPenaltyType.java index d374999..75b0861 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/config/WorkPenaltyType.java +++ b/src/main/java/xyz/alexcrea/cuanvil/config/WorkPenaltyType.java @@ -2,7 +2,7 @@ package xyz.alexcrea.cuanvil.config; import com.google.common.collect.ImmutableMap; import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.anvil.AnvilUseType; +import xyz.alexcrea.cuanvil.util.AnvilUseType; import java.util.EnumMap; diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/AdditionalTestEnchantment.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/AdditionalTestEnchantment.java index 821838f..832e5af 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/AdditionalTestEnchantment.java +++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/AdditionalTestEnchantment.java @@ -1,7 +1,6 @@ package xyz.alexcrea.cuanvil.enchant; import org.bukkit.Material; -import org.bukkit.NamespacedKey; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; @@ -12,23 +11,24 @@ 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. + * @param itemMat Material of the tested item. * @return If there is a conflict with the enchantments. */ boolean isEnchantConflict( @NotNull Map enchantments, - @NotNull NamespacedKey itemType); + @NotNull Material itemMat); + /** * 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 itemMat Material 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 Material itemMat, @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 index ea657ac..1d94ba2 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantment.java +++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantment.java @@ -207,6 +207,7 @@ public interface CAEnchantment { @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)); diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentRegistry.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentRegistry.java index 854ed55..4634a11 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentRegistry.java +++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentRegistry.java @@ -10,7 +10,6 @@ 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; @@ -86,13 +85,11 @@ public class CAEnchantmentRegistry { 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); + new IllegalStateException("enchantment " + enchantment.getKey() + " was already registered")); return false; } diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/BukkitEnchantBulkOperation.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/BukkitEnchantBulkOperation.java index 73e4185..c5bd07d 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/BukkitEnchantBulkOperation.java +++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/BukkitEnchantBulkOperation.java @@ -1,7 +1,6 @@ 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; @@ -18,14 +17,11 @@ public class BukkitEnchantBulkOperation implements BulkGetEnchantOperation, Bulk @Override public void bulkGet(@NotNull Map enchantmentMap, @NotNull ItemStack item, @NotNull ItemMeta meta) { - boolean isBook = ItemUtil.INSTANCE.isEnchantedBook(item); - - if (isBook) { + if (ItemUtil.INSTANCE.isEnchantedBook(item)) { ((EnchantmentStorageMeta) meta).getStoredEnchants().forEach((enchantment, level) -> addEnchantment(enchantmentMap, enchantment, level) ); - } - if(!isBook || ConfigOptions.INSTANCE.getAddBookEnchantmentAsStoredEnchantment()){ + } else { item.getEnchantments().forEach((enchantment, level) -> addEnchantment(enchantmentMap, enchantment, level) ); @@ -45,7 +41,7 @@ public class BukkitEnchantBulkOperation implements BulkGetEnchantOperation, Bulk @Override public void bulkClear(@NotNull ItemStack item) { - if (item.getType() != Material.ENCHANTED_BOOK || ConfigOptions.INSTANCE.getAddBookEnchantmentAsStoredEnchantment()) { + if (item.getType() != Material.ENCHANTED_BOOK) { item.getEnchantments().forEach((enchantment, level) -> item.removeEnchantment(enchantment) 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 index 0e630ea..1a72458 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CABukkitEnchantment.java +++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CABukkitEnchantment.java @@ -1,7 +1,6 @@ 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; @@ -29,14 +28,14 @@ public class CABukkitEnchantment extends CAEnchantmentBase { public final @NotNull Enchantment bukkit; - public CABukkitEnchantment(@NotNull Enchantment bukkit, @Nullable EnchantmentRarity rarity) { + public CABukkitEnchantment(@NotNull Enchantment bukkit, @Nullable EnchantmentRarity rarity){ super(bukkit.getKey(), rarity, bukkit.getMaxLevel()); this.bukkit = bukkit; } - public CABukkitEnchantment(@NotNull Enchantment bukkit) { + public CABukkitEnchantment(@NotNull Enchantment bukkit){ this(bukkit, getRarity(bukkit)); } @@ -53,7 +52,7 @@ public class CABukkitEnchantment extends CAEnchantmentBase { @Override public int getLevel(@NotNull ItemStack item, @NotNull ItemMeta meta) { if (ItemUtil.INSTANCE.isEnchantedBook(item)) { - return ((EnchantmentStorageMeta) meta).getStoredEnchantLevel(this.bukkit); + return ((EnchantmentStorageMeta)meta).getStoredEnchantLevel(this.bukkit); } else { return meta.getEnchantLevel(this.bukkit); } @@ -62,11 +61,10 @@ public class CABukkitEnchantment extends CAEnchantmentBase { @Override public boolean isEnchantmentPresent(@NotNull ItemStack item, @NotNull ItemMeta meta) { if (ItemUtil.INSTANCE.isEnchantedBook(item)) { - EnchantmentStorageMeta bookMeta = ((EnchantmentStorageMeta) meta); + EnchantmentStorageMeta bookMeta = ((EnchantmentStorageMeta)meta); - return bookMeta.getStoredEnchants().containsKey(this.bukkit) || - (ConfigOptions.INSTANCE.getAddBookEnchantmentAsStoredEnchantment() && item.containsEnchantment(this.bukkit)); - } else { + return bookMeta.getStoredEnchants().containsKey(this.bukkit); + }else{ return item.containsEnchantment(this.bukkit); } } @@ -74,7 +72,7 @@ public class CABukkitEnchantment extends CAEnchantmentBase { @Override public void addEnchantmentUnsafe(@NotNull ItemStack item, int level) { if (ItemUtil.INSTANCE.isEnchantedBook(item)) { - EnchantmentStorageMeta bookMeta = ((EnchantmentStorageMeta) item.getItemMeta()); + EnchantmentStorageMeta bookMeta = ((EnchantmentStorageMeta)item.getItemMeta()); assert bookMeta != null; bookMeta.addStoredEnchant(this.bukkit, level, true); @@ -88,20 +86,19 @@ public class CABukkitEnchantment extends CAEnchantmentBase { @Override public void removeFrom(@NotNull ItemStack item) { if (ItemUtil.INSTANCE.isEnchantedBook(item)) { - EnchantmentStorageMeta bookMeta = ((EnchantmentStorageMeta) item.getItemMeta()); + EnchantmentStorageMeta bookMeta = ((EnchantmentStorageMeta)item.getItemMeta()); assert bookMeta != null; bookMeta.removeStoredEnchant(this.bukkit); - bookMeta.removeEnchant(this.bukkit); item.setItemMeta(bookMeta); - } else { + }else{ item.removeEnchantment(this.bukkit); } } @NotNull - public static EnchantmentRarity getRarity(Enchantment enchantment) { + public static EnchantmentRarity getRarity(Enchantment enchantment){ try { return EnchantmentProperties.valueOf(enchantment.getKey().getKey().toUpperCase(Locale.ENGLISH)).getRarity(); } catch (IllegalArgumentException ignored) { @@ -115,7 +112,6 @@ public class CABukkitEnchantment extends CAEnchantmentBase { } private static Method getAnvilCostMethod; - static { Class clazz = Enchantment.class; try { @@ -148,14 +144,14 @@ public class CABukkitEnchantment extends CAEnchantmentBase { } private static EnchantmentRarity findRarity(Enchantment enchantment) { - if (getAnvilCostMethod == null) return EnchantmentRarity.COMMON; + 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); + CustomAnvil.instance.getLogger().log(Level.SEVERE, "could not find cost for enchantment "+enchantment.getKey(), e); return EnchantmentRarity.COMMON; } @@ -164,7 +160,7 @@ public class CABukkitEnchantment extends CAEnchantmentBase { @Override public boolean equals(Object obj) { - if (!(obj instanceof CABukkitEnchantment other)) { + if(!(obj instanceof CABukkitEnchantment other)){ return false; } diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEEPreV5Enchantment.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEEEnchantment.java similarity index 50% rename from src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEEPreV5Enchantment.java rename to src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEEEnchantment.java index 783798d..72c333f 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEEPreV5Enchantment.java +++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEEEnchantment.java @@ -1,46 +1,31 @@ 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 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 CAEEPreV5Enchantment extends CABukkitEnchantment implements AdditionalTestEnchantment { +public class CAEEEnchantment extends CABukkitEnchantment implements AdditionalTestEnchantment { @NotNull CustomEnchantment eeenchantment; @NotNull Definition definition; - public CAEEPreV5Enchantment(@NotNull CustomEnchantment enchantment) { - super(enchantment.getBukkitEnchantment(), getRarity(enchantment.getBukkitEnchantment())); + public CAEEEnchantment(@NotNull CustomEnchantment enchantment) { + super(enchantment.getBukkitEnchantment(), EnchantmentRarity.getRarity(enchantment.getDefinition().getAnvilCost())); this.eeenchantment = enchantment; - try { - this.definition = (Definition) getDefinition.invoke(enchantment); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } + this.definition = enchantment.getDefinition(); } - 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) { + public boolean isEnchantConflict(@NotNull Map enchantments, @NotNull Material itemMat) { if (!definition.hasConflicts()) return false; Set conflicts = definition.getConflicts(); @@ -53,8 +38,8 @@ public class CAEEPreV5Enchantment extends CABukkitEnchantment implements Additio } @Override - public boolean isItemConflict(@NotNull Map enchantments, @NotNull NamespacedKey itemType, @NotNull ItemStack item) { - if (Material.ENCHANTED_BOOK.getKey().equals(itemType)) return false; + public boolean isItemConflict(@NotNull Map enchantments, @NotNull Material itemMat, @NotNull ItemStack item) { + if (Material.ENCHANTED_BOOK.equals(itemMat)) 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 index 32d1346..6e74b73 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEcoEnchant.java +++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEcoEnchant.java @@ -4,7 +4,6 @@ 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; @@ -24,13 +23,9 @@ public class CAEcoEnchant extends CABukkitEnchantment implements AdditionalTestE } @Override - public boolean isEnchantConflict(@NotNull Map enchantments, @NotNull NamespacedKey itemType) { + public boolean isEnchantConflict(@NotNull Map enchantments, @NotNull Material itemMat) { 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; } @@ -62,9 +57,9 @@ public class CAEcoEnchant extends CABukkitEnchantment implements AdditionalTestE @Override public boolean isItemConflict(@NotNull Map enchantments, - @NotNull NamespacedKey itemType, + @NotNull Material itemMat, @NotNull ItemStack item) { - if (Material.ENCHANTED_BOOK.getKey().equals(itemType)) { + if (Material.ENCHANTED_BOOK.equals(itemMat)) { return false; } diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAIncompatibleAllEnchant.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAIncompatibleAllEnchant.java index 552ecd4..218ce87 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAIncompatibleAllEnchant.java +++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAIncompatibleAllEnchant.java @@ -1,7 +1,6 @@ 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; @@ -25,12 +24,12 @@ public class CAIncompatibleAllEnchant extends CABukkitEnchantment implements Add @Override - public boolean isEnchantConflict(@NotNull Map enchantments, @NotNull NamespacedKey itemType) { + public boolean isEnchantConflict(@NotNull Map enchantments, @NotNull Material itemMat) { return !enchantments.isEmpty() && !(enchantments.size() == 1 && enchantments.containsKey(this)); } @Override - public boolean isItemConflict(@NotNull Map enchantments, @NotNull NamespacedKey itemType, @NotNull ItemStack item) { + public boolean isItemConflict(@NotNull Map enchantments, @NotNull Material itemMat, @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 index 74068d4..191f8f3 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CALegacyEEEnchantment.java +++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CALegacyEEEnchantment.java @@ -1,7 +1,6 @@ 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; @@ -23,7 +22,7 @@ public class CALegacyEEEnchantment extends CABukkitEnchantment implements Additi } @Override - public boolean isEnchantConflict(@NotNull Map enchantments, @NotNull NamespacedKey itemType) { + public boolean isEnchantConflict(@NotNull Map enchantments, @NotNull Material itemMat) { if (!eeenchantment.hasConflicts()) return false; Set conflicts = eeenchantment.getConflicts(); @@ -36,8 +35,8 @@ public class CALegacyEEEnchantment extends CABukkitEnchantment implements Additi } @Override - public boolean isItemConflict(@NotNull Map enchantments, @NotNull NamespacedKey itemType, @NotNull ItemStack item) { - if (Material.ENCHANTED_BOOK.getKey().equals(itemType)) return false; + public boolean isItemConflict(@NotNull Map enchantments, @NotNull Material itemMat, @NotNull ItemStack item) { + if (Material.ENCHANTED_BOOK.equals(itemMat)) 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 index cb24def..3b4242d 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CALegacyEcoEnchant.java +++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CALegacyEcoEnchant.java @@ -4,14 +4,12 @@ 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; @@ -25,7 +23,7 @@ public class CALegacyEcoEnchant extends CABukkitEnchantment implements Additiona } @Override - public boolean isEnchantConflict(@NotNull Map enchantments, @NotNull NamespacedKey itemType) { + public boolean isEnchantConflict(@NotNull Map enchantments, @NotNull Material itemMat) { if (enchantments.isEmpty()) return false; EnchantmentType type = this.ecoEnchant.getType(); @@ -50,15 +48,14 @@ public class CALegacyEcoEnchant extends CABukkitEnchantment implements Additiona @Override public boolean isItemConflict(@NotNull Map enchantments, - @NotNull NamespacedKey itemType, + @NotNull Material itemMat, @NotNull ItemStack item) { - if (Material.ENCHANTED_BOOK.getKey().equals(itemType)) { + if (Material.ENCHANTED_BOOK.equals(itemMat)) { return false; } - var mat = MaterialUtil.INSTANCE.getMatFromKey(itemType); for (EnchantmentTarget target : this.ecoEnchant.getTargets()) { - if (target.getMaterials().contains(mat)) { + if (target.getMaterials().contains(itemMat)) { return false; } } 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/config/MainConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/MainConfigGui.java index cc4fddc..e2224f7 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/MainConfigGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/MainConfigGui.java @@ -103,8 +103,8 @@ public class MainConfigGui extends ChestGui { ItemMeta groupMeta = groupItemstack.getItemMeta(); assert groupMeta != null; - groupMeta.setDisplayName("§aItem Groups"); - groupMeta.setLore(Collections.singletonList("§7Click here to open item group menu")); + groupMeta.setDisplayName("§aGroups"); + groupMeta.setLore(Collections.singletonList("§7Click here to open material group menu")); groupItemstack.setItemMeta(groupMeta); GuiItem groupConfigItem = GuiGlobalItems.goToGuiItem(groupItemstack, GroupConfigGui.getInstance()); diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/SelectMaterialContainer.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/SelectMaterialContainer.java index 3756341..2f76694 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/SelectMaterialContainer.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/SelectMaterialContainer.java @@ -1,35 +1,34 @@ 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(); + EnumSet getSelectedMaterials(); - boolean setSelectedMaterials(Set materials); + boolean setSelectedMaterials(EnumSet materials); - Set illegalMaterials(); + EnumSet 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(); + 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(); + 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()); + String formattedName = CasedStringUtil.snakeToUpperSpacedCase(materialIterator.next().name().toLowerCase()); groupLore.add("§7- §e" + formattedName); } 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 index 5839663..56bf848 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/ConfirmActionGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/ConfirmActionGui.java @@ -11,7 +11,6 @@ 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; @@ -42,7 +41,6 @@ public class ConfirmActionGui extends AbstractAskGui { success = onConfirm.get(); } catch (Exception e) { CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not process confirmation supplier.", e); - MetricsUtil.INSTANCE.trackError(e); success = false; } 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 index 66411bd..b2d6afe 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/SelectItemTypeGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/SelectItemTypeGui.java @@ -12,7 +12,6 @@ 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; @@ -53,7 +52,7 @@ public class SelectItemTypeGui extends AbstractAskGui { event.setCancelled(true); ItemStack cursor = event.getWhoClicked().getItemOnCursor(); - if(MaterialUtil.INSTANCE.isAir(cursor)) return; + if(cursor.getType().isAir()) return; ItemStack finalItem; if(materialOnly){ 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 index 6bd7ea3..a65b54b 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/AbstractEnchantConfigGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/AbstractEnchantConfigGui.java @@ -20,7 +20,7 @@ import java.util.function.Consumer; * * @param Type of the factory of the type of setting the gui should edit. */ -public abstract class AbstractEnchantConfigGui extends SettingGuiListConfigGui{ +public abstract class AbstractEnchantConfigGui extends SettingGuiListConfigGui implements ValueUpdatableGui { /** * Constructor for a gui displaying available enchantment to edit a enchantment setting. 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 index 51936c7..a07cb3c 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/BasicConfigGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/BasicConfigGui.java @@ -14,7 +14,6 @@ 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; @@ -284,7 +283,7 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui { if(!this.packetManager.getCanSetInstantBuild()){ lore.add(""); - lore.add("§4/!\\§cCaution§4/!\\ §cYou need ProtocoLib installed and working or a paper server."); + lore.add("§4/!\\§cCaution§4/!\\ §cYou need ProtocoLib installed and working or a newer version of this plugin for this to work."); lore.add("§cCurrently ProtocoLib is not detected."); } 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 index e21ad75..feaa8dd 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/CustomRecipeConfigGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/CustomRecipeConfigGui.java @@ -14,7 +14,7 @@ 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.Arrays; import java.util.Collection; public class CustomRecipeConfigGui extends MappedGuiListConfigGui 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)); @@ -94,11 +87,7 @@ public class CustomRecipeConfigGui extends MappedGuiListConfigGui { - private static final String SECTION_NAME = ConfigOptions.ENCHANT_LIMIT_ROOT; + private static final String SECTION_NAME = "enchant_limits"; private static EnchantLimitConfigGui INSTANCE = null; @@ -41,34 +41,18 @@ public class EnchantLimitConfigGui extends AbstractEnchantConfigGui "Default (" + defaultValue + ")"; - case RESET -> String.valueOf(defaultValue); - default -> "Default"; - }; - - } - else return super.valueDisplayName(type, value); + return ConfigOptions.INSTANCE.enchantLimit(enchant); } }; } 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 index 9db6d62..d5ca2c8 100644 --- 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 @@ -36,32 +36,26 @@ public class CustomRecipeSubSettingGui extends MappedToListSubSettingGui { public CustomRecipeSubSettingGui( @NotNull CustomRecipeConfigGui parent, @NotNull AnvilCustomRecipe anvilRecipe) { - super(4, "§e" + CasedStringUtil.snakeToUpperSpacedCase(anvilRecipe.toString()) + " §8Config"); + super(3, "§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); + this.pane = new PatternPane(0, 0, 9, 3, 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; + BoolSettingsGui.BoolSettingFactory exactCountFactory; + IntSettingsGui.IntSettingFactory xpCostFactory; + ItemSettingGui.ItemSettingFactory leftItemFactory; + ItemSettingGui.ItemSettingFactory rightItemFactory; + ItemSettingGui.ItemSettingFactory resultItemFactory; private void prepareStaticValues() { @@ -80,38 +74,19 @@ public class CustomRecipeSubSettingGui extends MappedToListSubSettingGui { 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, + this.xpCostFactory = new IntSettingsGui.IntSettingFactory("§8Recipe Xp Cost", this, + this.anvilRecipe +"."+AnvilCustomRecipe.XP_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); + costRange.getFirst(), costRange.getLast(), AnvilCustomRecipe.DEFAULT_XP_COST_CONFIG, 1, 5, 10); - // Right part of the gui this.leftItemFactory = new ItemSettingGui.ItemSettingFactory("§eRecipe Left §8Item", this, this.anvilRecipe + "." + AnvilCustomRecipe.LEFT_ITEM_CONFIG, ConfigHolder.CUSTOM_RECIPE_HOLDER, @@ -183,18 +158,8 @@ public class CustomRecipeSubSettingGui extends MappedToListSubSettingGui { 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 xpCostItem = this.xpCostFactory.getItem(Material.EXPERIENCE_BOTTLE); + this.pane.bindItem('2', xpCostItem); GuiItem leftGuiItem = this.leftItemFactory.getItem(); this.pane.bindItem('3', leftGuiItem); @@ -204,7 +169,7 @@ public class CustomRecipeSubSettingGui extends MappedToListSubSettingGui { GuiItem resultGuiItem = this.resultItemFactory.getItem(); this.pane.bindItem('5', resultGuiItem); - + update(); } 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 index 97bdfcb..99bba84 100644 --- 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 @@ -25,7 +25,6 @@ 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; @@ -265,7 +264,6 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl 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 @@ -310,7 +308,6 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl 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 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 index 3d05674..efa1117 100644 --- 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 @@ -5,7 +5,6 @@ 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; @@ -40,7 +39,7 @@ public class GroupConfigSubSettingGui extends MappedToListSubSettingGui implemen @NotNull GroupConfigGui parent, @NotNull IncludeGroup group) { super(3, - "§e" + CasedStringUtil.snakeToUpperSpacedCase(group.getName()) + " §rConfig"); + CasedStringUtil.snakeToUpperSpacedCase(group.getName()) + " Config"); this.parent = parent; this.group = group; @@ -72,31 +71,20 @@ public class GroupConfigSubSettingGui extends MappedToListSubSettingGui implemen 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) -> { + this.materialSelection = new GuiItem(new ItemStack(Material.DIAMOND_SWORD), (event) -> { event.setCancelled(true); + MaterialSelectSettingGui selectGui = new MaterialSelectSettingGui(this, - materialSelectionName + CasedStringUtil.snakeToUpperSpacedCase(group.getName()) + " Materials" , 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) -> { + this.groupSelection = new GuiItem(new ItemStack(Material.CHEST), (event) -> { event.setCancelled(true); GroupSelectSettingGui enchantGui = new GroupSelectSettingGui( - selectGroupName, + CasedStringUtil.snakeToUpperSpacedCase(this.group.getName()) + " Groups", this, this, 0); enchantGui.show(event.getWhoClicked()); }, CustomAnvil.instance); @@ -322,23 +310,23 @@ public class GroupConfigSubSettingGui extends MappedToListSubSettingGui implemen // ---------------------------- // End of SelectGroupContainer related methods // ---------------------------- - // SelectMaterialContainer related methods + // SelectGroupContainer related methods // ---------------------------- @Override - public Set getSelectedMaterials() { + public EnumSet getSelectedMaterials() { return this.group.getNonGroupInheritedMaterials(); } @Override - public boolean setSelectedMaterials(Set materials) { + public boolean setSelectedMaterials(EnumSet 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(); + for (Material otherGroup : materials) { + groupNames[index++] = otherGroup.name().toLowerCase(); } ConfigHolder.ITEM_GROUP_HOLDER.getConfig().set(this.group.getName()+"."+ItemGroupManager.MATERIAL_LIST_PATH, groupNames); @@ -354,12 +342,12 @@ public class GroupConfigSubSettingGui extends MappedToListSubSettingGui implemen } @Override - public Set illegalMaterials() { - return Set.of(Material.AIR.getKey()); + public EnumSet illegalMaterials() { + return EnumSet.of(Material.AIR); } // ---------------------------- - // End of SelectMaterialContainer related methods + // End of SelectGroupContainer related methods // ---------------------------- private void updateDirectReferencingGroups(AbstractMaterialGroup referenceTo){ @@ -382,7 +370,7 @@ public class GroupConfigSubSettingGui extends MappedToListSubSettingGui implemen for (AbstractMaterialGroup otherGroup : everyStoredGroups) { if(otherGroup.getGroups().contains(testGroup)){ otherGroup.updateMaterials(); - updateFuture.add(otherGroup); + toUpdate.add(otherGroup); } } 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 index 73121a6..af977e9 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/IntSettingsGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/IntSettingsGui.java @@ -72,8 +72,7 @@ public class IntSettingsGui extends AbstractSettingGui { assert meta != null; meta.setDisplayName("§eReset to default value"); - meta.setLore(Collections.singletonList("§7Default value is §e" + - holder.valueDisplayName(ValueDisplayType.RESET, holder.defaultVal))); + meta.setLore(Collections.singletonList("§7Default value is §e" + holder.defaultVal)); item.setItemMeta(meta); returnToDefault = new GuiItem(item, event -> { event.setCancelled(true); @@ -87,23 +86,41 @@ public class IntSettingsGui extends AbstractSettingGui { * 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); + ItemStack item = new ItemStack(Material.RED_TERRACOTTA); + ItemMeta meta = item.getItemMeta(); + assert meta != null; + + meta.setDisplayName("§e" + now + " §f-> §e" + planned + " §r(§c-" + (now - planned) + "§r)"); + meta.setLore(Collections.singletonList(AbstractSettingGui.CLICK_LORE)); + item.setItemMeta(meta); + + minusItem = new GuiItem(item, updateNowConsumer(planned), CustomAnvil.instance); } else { minusItem = GuiGlobalItems.backgroundItem(Material.BARRIER); } pane.bindItem('-', minusItem); //plus item + // may do a function to generalise ? GuiItem plusItem; if (now < holder.max) { int planned = Math.min(holder.max, now + step); - plusItem = valueEditItem(Material.GREEN_TERRACOTTA, ValueDisplayType.ADD, planned); + ItemStack item = new ItemStack(Material.GREEN_TERRACOTTA); + ItemMeta meta = item.getItemMeta(); + assert meta != null; + + meta.setDisplayName("§e" + now + " §f-> §e" + planned + " §r(§a+" + (planned - now) + "§r)"); + meta.setLore(Collections.singletonList(AbstractSettingGui.CLICK_LORE)); + item.setItemMeta(meta); + + plusItem = new GuiItem(item, updateNowConsumer(planned), CustomAnvil.instance); } else { plusItem = GuiGlobalItems.backgroundItem(Material.BARRIER); } @@ -114,7 +131,7 @@ public class IntSettingsGui extends AbstractSettingGui { ItemMeta resultMeta = resultPaper.getItemMeta(); assert resultMeta != null; - resultMeta.setDisplayName("§fValue: §e" + holder.valueDisplayName(ValueDisplayType.CURRENT, now)); + resultMeta.setDisplayName("§fValue: §e" + now); resultMeta.setLore(holder.displayLore); resultPaper.setItemMeta(resultMeta); @@ -132,21 +149,7 @@ public class IntSettingsGui extends AbstractSettingGui { } 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); } /** @@ -386,23 +389,6 @@ public class IntSettingsGui extends AbstractSettingGui { 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/MaterialSelectSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/MaterialSelectSettingGui.java index fc519ff..a3963ce 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/MaterialSelectSettingGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/MaterialSelectSettingGui.java @@ -5,7 +5,6 @@ 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; @@ -19,19 +18,18 @@ 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 { +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 List defaultMaterials; + private final EnumSet illegalMaterials; private final int defaultMaterialHash; private int nowMaterialHash; @@ -163,7 +161,8 @@ public class MaterialSelectSettingGui extends MappedElementListConfigGui result = new HashSet<>(this.elementGuiMap.keySet()); + EnumSet result = EnumSet.noneOf(Material.class); + result.addAll(this.elementGuiMap.keySet()); if(!this.selector.setSelectedMaterials(result)){ player.sendMessage("§cSomething went wrong while saving the change of value."); @@ -186,8 +185,8 @@ public class MaterialSelectSettingGui extends MappedElementListConfigGui getEveryDisplayableInstanceOfGeneric() { + protected Collection getEveryDisplayableInstanceOfGeneric() { return this.defaultMaterials; } @Override - protected void updateElement(NamespacedKey material, GuiItem element) { + protected void updateElement(Material material, GuiItem element) { // Nothing happen here I think } @Override - protected GuiItem newElementRequested(NamespacedKey material, GuiItem newItem) { + protected GuiItem newElementRequested(Material material, GuiItem newItem) { newItem.setAction(event -> { if(this.instantRemove){ removeMaterial(material); }else { - String materialName = CasedStringUtil.snakeToUpperSpacedCase(material.getKey().toLowerCase()); + String materialName = CasedStringUtil.snakeToUpperSpacedCase(material.name().toLowerCase()); // Create and show confirm remove gui. ConfirmActionGui confirmGui = new ConfirmActionGui( @@ -251,7 +250,7 @@ public class MaterialSelectSettingGui extends MappedElementListConfigGui materialList){ + private static int hashFromMaterialList(List materialList){ int defaultMaterialHash = 0; - for (NamespacedKey material : materialList) { + for (Material material : materialList) { defaultMaterialHash ^= material.hashCode(); } return defaultMaterialHash; 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 index 4345aa1..888aa25 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/WorkPenaltyTypeSettingGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/WorkPenaltyTypeSettingGui.java @@ -11,11 +11,11 @@ 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 xyz.alexcrea.cuanvil.util.AnvilUseType; import java.util.ArrayList; import java.util.EnumMap; 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 index 707a218..363bd6a 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/update/PluginSetDefault.java +++ b/src/main/java/xyz/alexcrea/cuanvil/update/PluginSetDefault.java @@ -5,7 +5,6 @@ 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; @@ -19,9 +18,6 @@ public class PluginSetDefault { 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); @@ -34,7 +30,7 @@ public class PluginSetDefault { 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); + nbSet += trySetDefault(config, DEFAULT_LIMIT_PATH, DEFAULT_ENCHANT_LIMIT); // Lore Edit defaults for (@NotNull LoreEditType value : LoreEditType.values()) { @@ -52,6 +48,7 @@ public class PluginSetDefault { 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_ON_LORE_REMOVE, DEFAULT_REMOVE_COLOR_ON_LORE_REMOVE); nbSet += trySetDefault(config, path + REMOVE_COLOR_COST, DEFAULT_REMOVE_COLOR_COST); } } @@ -61,11 +58,6 @@ public class PluginSetDefault { 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); 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 index 2907fef..c13515f 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/update/UpdateUtils.java +++ b/src/main/java/xyz/alexcrea/cuanvil/update/UpdateUtils.java @@ -15,6 +15,22 @@ public class UpdateUtils { return Version.fromString(versionString); } + @Deprecated + public static int[] currentMinecraftVersionArray() { + String versionString = Bukkit.getServer().getBukkitVersion().split("-")[0]; + return UpdateUtils.readVersionFromString(versionString); + } + + public static int[] readVersionFromString(String versionString) { + String[] partialVersion = versionString.split("\\."); + int[] versionParts = new int[]{0, 0, 0}; + + for (int i = 0; i < Math.min(3, partialVersion.length); i++) { + versionParts[i] = Integer.parseInt(partialVersion[i]); + } + return versionParts; + } + public static void addToStringList(FileConfiguration config, String path, String... toAdd) { List groups = new ArrayList<>(config.getStringList(path)); groups.addAll(Arrays.asList(toAdd)); diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/minecraft/Update_1_21.java b/src/main/java/xyz/alexcrea/cuanvil/update/Update_1_21.java similarity index 64% rename from src/main/java/xyz/alexcrea/cuanvil/update/minecraft/Update_1_21.java rename to src/main/java/xyz/alexcrea/cuanvil/update/Update_1_21.java index 3aa6073..332b5fe 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/update/minecraft/Update_1_21.java +++ b/src/main/java/xyz/alexcrea/cuanvil/update/Update_1_21.java @@ -1,24 +1,42 @@ -package xyz.alexcrea.cuanvil.update.minecraft; +package xyz.alexcrea.cuanvil.update; import io.delilaheve.CustomAnvil; +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 extends MCUpdate { +// This is a temporary class that aim to handle 1.21 update. +// It will be replaced by a better system later. +public class Update_1_21 { + + private static final Version V1_21 = new Version(1, 21); + + public static void handleUpdate(){ + // Assume if version path is not null then it's 1.21 + String oldVersion = ConfigHolder.DEFAULT_CONFIG.getConfig().getString(UpdateUtils.MINECRAFT_VERSION_PATH); + if(oldVersion != null){ + Version version = Version.fromString(oldVersion); + + // Test 1.21 + if(V1_21.greaterEqual(version)) return; + } + Version current = UpdateUtils.currentMinecraftVersion(); + + // Test 1.21 + if(current.greaterEqual(V1_21)){ + doUpdate(); + } - 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(); + private static void doUpdate() { + CustomAnvil.instance.getLogger().info("Updating config to support 1.21 ..."); + + FileConfiguration baseConfig = ConfigHolder.DEFAULT_CONFIG.getConfig(); + FileConfiguration groupConfig = ConfigHolder.ITEM_GROUP_HOLDER.getConfig(); + FileConfiguration conflictConfig = ConfigHolder.CONFLICT_HOLDER.getConfig(); + FileConfiguration unitConfig = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig(); // Add mace to groups groupConfig.set("mace.type", "include"); @@ -62,8 +80,8 @@ public class Update_1_21 extends MCUpdate { // 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()); + // Set version string as 1.21 + baseConfig.set(UpdateUtils.MINECRAFT_VERSION_PATH, "1.21"); // Save ConfigHolder.DEFAULT_CONFIG.saveToDisk(true); @@ -74,6 +92,9 @@ public class Update_1_21 extends MCUpdate { // 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(); + + CustomAnvil.instance.getLogger().info("Updating Done !"); + } } diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/Version.java b/src/main/java/xyz/alexcrea/cuanvil/update/Version.java index a49fbdd..e6f63cf 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/update/Version.java +++ b/src/main/java/xyz/alexcrea/cuanvil/update/Version.java @@ -1,7 +1,5 @@ package xyz.alexcrea.cuanvil.update; -import org.jetbrains.annotations.NotNull; - import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -21,11 +19,7 @@ public record Version(int major, int minor, int patch) { 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; - } + versionParts[i] = Integer.parseInt(partialVersion[i]); } return new Version(versionParts[0], versionParts[1], versionParts[2]); } @@ -54,7 +48,6 @@ public record Version(int major, int minor, int patch) { 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_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 index 9740971..6d6baca 100644 --- 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 @@ -1,7 +1,6 @@ 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; @@ -12,7 +11,6 @@ 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; @@ -71,12 +69,7 @@ public class PUpdate_1_11_0 { // 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); + group.addAll(toolMats); MaterialGroupApi.addMaterialGroup(group, true); @@ -84,8 +77,8 @@ public class PUpdate_1_11_0 { if (tools == null) return; if (!(tools instanceof IncludeGroup include)) return; - List mats = List.of(keys); - Set matSet = include.getNonGroupInheritedMaterials(); + List mats = List.of(toolMats); + Set matSet = include.getNonGroupInheritedMaterials(); if (!matSet.containsAll(mats)) return; mats.forEach(matSet::remove); 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_8_0.java b/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_8_0.java index 81ce1aa..7685f92 100644 --- 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 @@ -2,10 +2,10 @@ 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 xyz.alexcrea.cuanvil.util.AnvilUseType; import javax.annotation.Nonnull; import java.util.EnumMap; diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PluginUpdates.java b/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PluginUpdates.java new file mode 100644 index 0000000..03c858e --- /dev/null +++ b/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PluginUpdates.java @@ -0,0 +1,52 @@ +package xyz.alexcrea.cuanvil.update.plugin; + +import io.delilaheve.CustomAnvil; +import xyz.alexcrea.cuanvil.config.ConfigHolder; +import xyz.alexcrea.cuanvil.update.Version; + +import javax.annotation.Nonnull; +import java.util.HashSet; +import java.util.Set; + +public class PluginUpdates { + + private static final String CONFIG_VERSION_PATH = "configVersion"; + + public 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<>(); + + if (new Version(1, 6, 2).greaterThan(current)) { + PUpdate_1_6_2.handleUpdate(toSave); + // We assume 1.6.7 will run. TODO a better system instead of that I guess + } + if (new Version(1, 6, 7).greaterThan(current)) { + PUpdate_1_6_7.handleUpdate(toSave); + // We assume 1.8.0 will run. + } + if (new Version(1, 8, 0).greaterThan(current)) { + PUpdate_1_8_0.handleUpdate(toSave); + // We assume 1.11.0 will run. + } + + if (new Version(1, 11, 0).greaterThan(current)) { + PUpdate_1_11_0.handleUpdate(toSave); + + finishConfiguration("1.11.0", toSave); + } + + } + + 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); + for (ConfigHolder configHolder : toSave) { + configHolder.saveToDisk(true); + } + } + +} diff --git a/src/main/kotlin/io/delilaheve/CustomAnvil.kt b/src/main/kotlin/io/delilaheve/CustomAnvil.kt index 4d99faf..442af0a 100644 --- a/src/main/kotlin/io/delilaheve/CustomAnvil.kt +++ b/src/main/kotlin/io/delilaheve/CustomAnvil.kt @@ -6,14 +6,10 @@ 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 @@ -21,10 +17,10 @@ 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 xyz.alexcrea.cuanvil.update.Update_1_21 +import xyz.alexcrea.cuanvil.update.plugin.PluginUpdates +import xyz.alexcrea.cuanvil.util.Metrics import java.io.File import java.io.FileReader import java.util.logging.Level @@ -35,8 +31,8 @@ import java.util.logging.Level open class CustomAnvil : JavaPlugin() { companion object { - // pluginIDS - private const val modrinthPluginID = "S75Ueiq9" + // bstats plugin id + private const val bstatsPluginId = 20923 // Permission string required to use the plugin's features const val affectedByPluginPermission = "ca.affected" @@ -50,18 +46,14 @@ open class CustomAnvil : JavaPlugin() { // 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" + // Test command name + const val commandTestName = "customanvilconfig" // Current plugin instance lateinit var instance: CustomAnvil @@ -69,12 +61,10 @@ open class CustomAnvil : JavaPlugin() { // Chat message listener lateinit var chatListener: ChatEventListener - var latestVer: String? = null - /** * Logging handler */ - @JvmStatic fun log(message: String) { + fun log(message: String) { if (ConfigOptions.debugLog) { instance.logger.info(message) } @@ -89,26 +79,7 @@ open class CustomAnvil : JavaPlugin() { } } - } - // 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 } /** @@ -116,74 +87,7 @@ open class CustomAnvil : JavaPlugin() { */ 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) { @@ -192,43 +96,33 @@ open class CustomAnvil : JavaPlugin() { 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") - } - } + // Add commands + prepareCommand() - 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 + // Load chat listener chatListener = ChatEventListener() server.pluginManager.registerEvents(chatListener, this) + // Load default configuration + if (!ConfigHolder.loadDefaultConfig()) { + logger.log(Level.SEVERE,"could not load default config.") + return + } + + // Load dependency + DependencyManager.loadDependency() + // Register anvil events server.pluginManager.registerEvents(PrepareAnvilListener(), this) server.pluginManager.registerEvents(AnvilResultListener(), this) server.pluginManager.registerEvents(AnvilCloseListener(DependencyManager.packetManager), this) + + // Load metrics + Metrics(this, bstatsPluginId) + + // Load other thing later. + // It is so other dependent plugins can implement there event listener before we fire them. + DependencyManager.scheduler.scheduleGlobally(this, {loadEnchantmentSystem()}) } private fun loadEnchantmentSystem(){ @@ -241,13 +135,15 @@ open class CustomAnvil : JavaPlugin() { // 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) + logger.log(Level.SEVERE,"could not load non default config.") return } - // Handle minecraft and plugin updates - UpdateHandler.handleUpdates() + // temporary: handle 1.21 update + Update_1_21.handleUpdate() + + // plugin configuration updates + PluginUpdates.handlePluginUpdate() // Register enchantment of compatible plugin and load configuration change. DependencyManager.handleCompatibilityConfig() @@ -260,11 +156,9 @@ open class CustomAnvil : JavaPlugin() { 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( @@ -314,10 +208,8 @@ open class CustomAnvil : JavaPlugin() { var command = getCommand(commandReloadName) command?.setExecutor(ReloadExecutor()) - command = getCommand(commandConfigName) + command = getCommand(commandTestName) command?.setExecutor(EditConfigExecutor()) - - CustomAnvilCommand(this) } } diff --git a/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt b/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt index 9dc85f9..980999f 100644 --- a/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt +++ b/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt @@ -3,16 +3,11 @@ package io.delilaheve.util import io.delilaheve.CustomAnvil 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 xyz.alexcrea.cuanvil.util.AnvilUseType import java.util.* /** @@ -24,9 +19,6 @@ 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" @@ -39,17 +31,13 @@ object ConfigOptions { 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" @@ -57,31 +45,15 @@ object ConfigOptions { 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 DEFAULT_LIMIT_PATH = "default_limit" 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" - // Keys for specific enchantment values private const val KEY_BOOK = "book" private const val KEY_ITEM = "item" @@ -106,34 +78,19 @@ object ConfigOptions { 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 + const val DEFAULT_ENCHANT_LIMIT = 5 // 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 // ------------- @@ -158,15 +115,9 @@ object ConfigOptions { @JvmField val USE_OF_COLOR_COST_RANGE = 0..1000 - @JvmField - val DIALOG_MAX_SIZE_RANGE = 0..Int.MAX_VALUE - // 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 + val ENCHANT_LIMIT_RANGE = 1..255 // -------------- // Other defaults @@ -178,11 +129,6 @@ object ConfigOptions { // 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 // ------------- @@ -277,16 +223,6 @@ object ConfigOptions { ?: DEFAULT_SACRIFICE_ILLEGAL_COST } - /** - * Consider book enchantment as book stored enchantment - */ - val addBookEnchantmentAsStoredEnchantment : Boolean - get(){ - return ConfigHolder.DEFAULT_CONFIG - .config - .getBoolean(ADD_BOOK_ENCHANTMENT_AS_STORED_ENCHANTMENT, DEFAULT_ADD_BOOK_ENCHANTMENT_AS_STORED_ENCHANTMENT) - } - /** * Allow usage of color code */ @@ -307,22 +243,12 @@ object ConfigOptions { .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 + return allowColorCode || allowHexadecimalColor } /** @@ -335,16 +261,6 @@ object ConfigOptions { .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 */ @@ -392,43 +308,13 @@ object ConfigOptions { } /** - * Get material enchantment count limit - * - * @return the current enchantment limit. -1 if none + * Default enchantment limit */ - 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 + private val defaultEnchantLimit: 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 + .getInt(DEFAULT_LIMIT_PATH, DEFAULT_ENCHANT_LIMIT) } /** @@ -451,90 +337,46 @@ object ConfigOptions { .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 + if (limit != null) return limit // Test legacy (name only) limit = enchantLimit(enchantment.enchantmentName) - if (limit >= 0) return limit + if (limit != null) return limit - // Default to negative - return -1 + // get default (and test old legacy if present) + return getDefaultLevel(enchantment.enchantmentName) } /** * Get the given [enchantmentName]'s limit */ - private fun enchantLimit(enchantmentName: String): Int { + private fun enchantLimit(enchantmentName: String): Int? { val path = "${ENCHANT_LIMIT_ROOT}.$enchantmentName" - return CustomAnvil.instance.config - .getInt(path, -1) + return CustomAnvil.instance + .config + .getInt(path, ENCHANT_LIMIT_RANGE.first - 1) + .takeIf { it in ENCHANT_LIMIT_RANGE } + } + + /** + * Get default value if enchantment do not exist on config + */ + private fun getDefaultLevel( + enchantmentName: String, // compatibility with 1.20.5. TODO better update system + ): Int { + if (enchantmentName == "sweeping_edge") { + val limit = enchantLimit("sweeping") + if (limit != null) return limit + + } + return defaultEnchantLimit } /** @@ -606,20 +448,20 @@ object ConfigOptions { fun maxBeforeMergeDisabled(enchantment: CAEnchantment): Int { val key = enchantment.key.toString() var value = maxBeforeMergeDisabled(key) - if (value >= 0) return value + if (value != null) return value // Legacy name val legacy = enchantment.enchantmentName value = maxBeforeMergeDisabled(legacy) - if (value >= 0) return value + if (value != null) return value if (key == "minecraft:sweeping_edge") { value = maxBeforeMergeDisabled("minecraft:sweeping") - if (value >= 0) return value + if (value != null) return value // legacy name of legacy enchantment name value = maxBeforeMergeDisabled("sweeping") - if (value >= 0) return value + if (value != null) return value } return DEFAULT_MAX_BEFORE_MERGE_DISABLED @@ -629,13 +471,14 @@ object ConfigOptions { * Get the given [enchantmentName]'s level before merge is disabled * a negative value would mean never disabled */ - private fun maxBeforeMergeDisabled(enchantmentName: String): Int { + private fun maxBeforeMergeDisabled(enchantmentName: String): Int? { // find if set val path = "${DISABLE_MERGE_OVER_ROOT}.$enchantmentName" return CustomAnvil.instance .config - .getInt(path, -1) + .getInt(path, ENCHANT_LIMIT_RANGE.min() - 1) + .takeIf { it in ENCHANT_LIMIT_RANGE } } fun isImmutable(key: NamespacedKey): Boolean { @@ -651,29 +494,4 @@ object ConfigOptions { 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)) - } - } diff --git a/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt b/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt index af959f2..87e4bae 100644 --- a/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt +++ b/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt @@ -6,7 +6,6 @@ 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 kotlin.math.max import kotlin.math.min @@ -31,97 +30,81 @@ object EnchantmentUtil { ) = 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 + other.forEach { (enchantment, level) -> + if(!enchantment.isAllowed(player)) return@forEach - 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 maxLevel = if (bypassLevel) { 255 } + else { ConfigOptions.enchantLimit(enchantment) } + CustomAnvil.verboseLog("Max level of ${enchantment.key} is $maxLevel (bypassLevel is $bypassLevel)") + val cappedLevel = min(level, maxLevel) - val oldLevel = this[enchantment]!! // <- should not be null. (enchantment already in result list) + // Enchantment not yet in result list + if (!containsKey(enchantment)) { + // 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) + } - // ... 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 + // Enchantment already in result list else { - // We test if it is allowed to merge at this level - if(!bypassLevel){ - val maxBeforeDisabled = ConfigOptions.maxBeforeMergeDisabled(enchantment) - if((maxBeforeDisabled > 0) && (oldLevel >= maxBeforeDisabled)) { + val oldLevel = this[enchantment]!! // <- should not be null. (enchantment already in result list) + + if(bypassFuse){ + CustomAnvil.verboseLog("Bypassed conflict check for ${enchantment.key}") + } else { + val conflictType = ConfigHolder.CONFLICT_HOLDER.conflictManager + .isConflicting(this, item, enchantment) + + // ... and they are conflicting + if(conflictType != ConflictType.NO_CONFLICT){ CustomAnvil.verboseLog( - "Reached max merge before disable for ${enchantment.key}: $oldLevel/$maxBeforeDisabled)") + "Enchantment already in result list, and they are conflicting (${enchantment.key}, conflict: $conflictType)") return@forEach } } - // Now we increase the enchantment level by 1 - var newLevel = oldLevel + 1 - newLevel = max(min(newLevel, maxLevel), oldLevel) - this[enchantment] = newLevel - } + // ... 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) - if(bypassFuse){ - CustomAnvil.verboseLog("Bypassed conflict check for ${enchantment.key}") - } else { - val conflictType = ConfigHolder.CONFLICT_HOLDER.conflictManager - .isConflicting(this, item, enchantment) + } + // ... 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 + } + } + + // Now we increase the enchantment level by 1 + var newLevel = oldLevel + 1 + newLevel = max(min(newLevel, maxLevel), oldLevel) + this[enchantment] = newLevel - // ... 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 - return@forEach } } } - - // 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..a85af39 100644 --- a/src/main/kotlin/io/delilaheve/util/ItemUtil.kt +++ b/src/main/kotlin/io/delilaheve/util/ItemUtil.kt @@ -4,9 +4,6 @@ import org.bukkit.Material.ENCHANTED_BOOK 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 kotlin.math.min @@ -38,13 +35,6 @@ object ItemUtil { } - 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) - } - /** * Set this [ItemStack]s durability from a combination of the * [first] and [second] item's durability values @@ -64,9 +54,7 @@ object ItemUtil { val secondDurability = durability - secondDamage val combinedDurability = firstDurability + secondDurability val newDurability = min(combinedDurability, durability) - - val maxDamage = maxDamage(it) - it.damage = min(durability - newDurability, maxDamage) + it.damage = durability - newDurability itemMeta = it return true } @@ -102,5 +90,5 @@ object ItemUtil { */ fun ItemStack.canMergeWith( other: ItemStack? - ) = (other != null) && (customType == other.customType || (other.isEnchantedBook())) + ) = (other != null) && (type == other.type || (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/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 index fba89b7..85761d9 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt @@ -2,25 +2,21 @@ package xyz.alexcrea.cuanvil.command import io.delilaheve.CustomAnvil import org.bukkit.command.Command +import org.bukkit.command.CommandExecutor import org.bukkit.command.CommandSender import org.bukkit.entity.HumanEntity -import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil +import xyz.alexcrea.cuanvil.dependency.DependencyManager import xyz.alexcrea.cuanvil.gui.config.MainConfigGui import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions -class EditConfigExecutor: CASubCommand() { +class EditConfigExecutor : CommandExecutor { - override fun executeCommand(sender: CommandSender, - cmd: Command, - cmdstr: String, - args: Array): Boolean { - if (sender !is HumanEntity) return false - - if (!allowed(sender)) { + override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array): Boolean { + if (!sender.hasPermission(CustomAnvil.editConfigPermission)) { sender.sendMessage(GuiGlobalActions.NO_EDIT_PERM) return false } - if(PlatformUtil.isFolia){ + if(DependencyManager.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("") @@ -29,17 +25,10 @@ class EditConfigExecutor: CASubCommand() { return false } + if (sender !is HumanEntity) 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 index ef23e7d..38a98c0 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt @@ -9,15 +9,11 @@ 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 +import xyz.alexcrea.cuanvil.update.Update_1_21 -class ReloadExecutor : CASubCommand() { - - override fun executeCommand(sender: CommandSender, - cmd: Command, - cmdstr: String, - args: Array): Boolean { - if (!allowed(sender)) { +class ReloadExecutor : CommandExecutor { + override fun onCommand(sender: CommandSender, cmd: Command, cmdstr: String, args: Array): Boolean { + if (!sender.hasPermission(CustomAnvil.commandReloadPermission)) { sender.sendMessage("§cYou do not have permission to reload the config") return false } @@ -35,14 +31,6 @@ class ReloadExecutor : CASubCommand() { 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 */ @@ -60,8 +48,8 @@ class ReloadExecutor : CASubCommand() { UnitRepairConfigGui.getCurrentInstance()?.reloadValues() CustomRecipeConfigGui.getCurrentInstance()?.reloadValues() - // handle minecraft version update - UpdateHandler.handleMCVersionUpdate() + // temporary: handle 1.21 update + Update_1_21.handleUpdate() // Handle dependency reload DependencyManager.handleConfigReload() diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt index b730a0e..bbe2ca3 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt @@ -1,45 +1,33 @@ package xyz.alexcrea.cuanvil.dependency -import com.maddoxh.superEnchants.SuperEnchants import io.delilaheve.CustomAnvil -import net.kyori.adventure.text.Component +import io.delilaheve.util.ConfigOptions 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.gui.ExternGuiTester +import xyz.alexcrea.cuanvil.dependency.gui.GuiTesterSelector 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 { + var isFolia: Boolean = false lateinit var scheduler: TaskScheduler lateinit var packetManager: PacketManager - var externGuiTester: GenericExternGuiTester = GenericExternGuiTester() + var externGuiTester: ExternGuiTester? = null var enchantmentSquaredCompatibility: EnchantmentSquaredDependency? = null var ecoEnchantCompatibility: EcoEnchantDependency? = null @@ -48,17 +36,14 @@ object DependencyManager { 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) { + isFolia = testIsFolia() + scheduler = if (isFolia) { CustomAnvil.instance.logger.info("Folia detected... Custom Anvil Folia support is experimental. issues are more likely to happens.") FoliaScheduler() @@ -67,6 +52,7 @@ object DependencyManager { // Packet Manager val forceProtocolib = ConfigHolder.DEFAULT_CONFIG.config.getBoolean("force_protocolib", false) packetManager = PacketManagerSelector.selectPacketManager(forceProtocolib) + externGuiTester = GuiTesterSelector.selectGuiTester // Enchantment Squared dependency if (pluginManager.isPluginEnabled("EnchantsSquared")) { @@ -98,28 +84,15 @@ object DependencyManager { 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) + if(ConfigOptions.verboseDebugLog){ + CustomAnvil.verboseLog("Number of generics comp: " + genericDependencies.size) + for (dependency in genericDependencies) { + CustomAnvil.verboseLog("- " + dependency.plugin) + } } for (dependency in genericDependencies) @@ -149,74 +122,67 @@ object DependencyManager { 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) + CustomAnvil.instance.logger.log( + Level.SEVERE, + "Error while trying to handle custom anvil supported plugin: ", + e + ) + + // Just in case to avoid illegal items + event.inventory.setItem(ANVIL_OUTPUT_SLOT, null) + + // Finally, warn the player, maybe a lot of time but better warn than do nothing + event.view.player.sendMessage( + "[" + ChatColor.YELLOW.toString() + "CustomAnvil" + ChatColor.WHITE.toString() + "] " + + ChatColor.RED.toString() + "Error while handling the anvil." + ) 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 + var bypass = false // 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 + if (externGuiTester?.testIfGui(event.view) == true) bypass = true return bypass } // Return true if should bypass (either by a dependency or error) - fun tryEventPreAnvilBypass(event: PrepareAnvilEvent, player: Player): Boolean { + fun tryEventPreAnvilBypass(event: PrepareAnvilEvent, player: HumanEntity): Boolean { try { return unsafeTryEventPreAnvilBypass(event, player) } catch (e: Exception) { - logExceptionAndClear(event.view.player, event.inventory, e) + CustomAnvil.instance.logger.log( + Level.SEVERE, + "Error while trying to handle custom anvil supported plugin: ", + e + ) + + // Just in case to avoid illegal items + event.inventory.setItem(ANVIL_OUTPUT_SLOT, null) + + // Finally, warn the player, maybe a lot of time but better warn than do nothing + event.view.player.sendMessage( + "[" + ChatColor.YELLOW.toString() + "CustomAnvil" + ChatColor.WHITE.toString() + "] " + + ChatColor.RED.toString() + "Error while handling the anvil." + ) 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 + private fun unsafeTryEventPreAnvilBypass(event: PrepareAnvilEvent, player: HumanEntity): Boolean { + var bypass = false // Test if disenchantment used prepare anvil - if (!bypass && (disenchantmentCompatibility?.testPrepareAnvil(event, player) == true)) bypass = true + if (disenchantmentCompatibility?.testPrepareAnvil(event, player) == true) bypass = true // Test heaven bags used prepare anvil if (!bypass && (havenBagsCompatibility?.testPrepareAnvil(event, player) == true)) bypass = true @@ -231,29 +197,32 @@ object DependencyManager { 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) + // Return true only if error occurred (and so should bypass rest) + fun tryTreatAnvilResult(event: PrepareAnvilEvent, result: ItemStack): Boolean { try { - unsafeTryTreatAnvilResult(treatEvent) - return treatEvent.result + unsafeTryTreatAnvilResult(event, result) + return false } catch (e: Exception) { - logExceptionAndClear(player, inventory, e) - return null + CustomAnvil.instance.logger.log( + Level.SEVERE, + "Error while trying to handle custom anvil supported plugin: ", + e + ) + + // Just in case to avoid illegal items + event.inventory.setItem(ANVIL_OUTPUT_SLOT, null) + + // Finally, warn the player, maybe a lot of time but better warn than do nothing + event.view.player.sendMessage( + "[" + ChatColor.YELLOW.toString() + "CustomAnvil" + ChatColor.WHITE.toString() + "] " + + ChatColor.RED.toString() + "Error while handling the anvil." + ) + return true } } - private fun unsafeTryTreatAnvilResult(event: CATreatAnvilResult2Event) { - Bukkit.getPluginManager().callEvent(event) - - excellentEnchantsCompatibility?.treatAnvilResult(event) + private fun unsafeTryTreatAnvilResult(event: PrepareAnvilEvent, result: ItemStack) { + excellentEnchantsCompatibility?.treatAnvilResult(event, result) } // Return true if should bypass (either by a dependency or error) @@ -261,20 +230,29 @@ object DependencyManager { try { return unsafeTryClickAnvilResultBypass(event, inventory) } catch (e: Exception) { - logExceptionAndClear(event.view.player, event.inventory, e) + CustomAnvil.instance.logger.log( + Level.SEVERE, + "Error while trying to handle custom anvil supported plugin: ", + e + ) + + // Just in case to avoid illegal items + event.inventory.setItem(ANVIL_OUTPUT_SLOT, null) + + // Finally, warn the player, maybe a lot of time but better warn than do nothing + event.whoClicked.sendMessage( + "[" + ChatColor.YELLOW.toString() + "CustomAnvil" + ChatColor.WHITE.toString() + "] " + + ChatColor.RED.toString() + "Error while handling the anvil." + ) 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 + var bypass = false // Test if disenchantment used event click - if (!bypass && (disenchantmentCompatibility?.testAnvilResult(event, inventory) == true)) bypass = true + if (disenchantmentCompatibility?.testAnvilResult(event, inventory) == true) bypass = true // Test if haven bag used event click if (!bypass && (havenBagsCompatibility?.testAnvilResult(event, inventory) == true)) bypass = true @@ -287,40 +265,20 @@ object DependencyManager { } // 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 + if (!bypass && (externGuiTester?.testIfGui(event.view) == 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 { + fun stripLore(item: ItemStack): ArrayList { + val lore = ArrayList() val dummy = item.clone() enchantmentSquaredCompatibility?.stripLore(dummy) - val itemLore = dummy.itemMeta?.componentLore() ?: return ArrayList() + val itemLore = dummy.itemMeta!!.lore + if (itemLore != null) lore.addAll(itemLore) - val lore = ArrayList() - lore.addAll(itemLore) return lore } @@ -328,4 +286,13 @@ object DependencyManager { enchantmentSquaredCompatibility?.updateLore(item) } + private fun testIsFolia(): Boolean { + try { + Class.forName("io.papermc.paper.threadedregions.RegionizedServer") + return true + } catch (e: ClassNotFoundException) { + return false + } + } + } 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 index 6d54456..59b5649 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/datapack/DataPackDependency.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/datapack/DataPackDependency.kt @@ -17,15 +17,13 @@ import xyz.alexcrea.cuanvil.update.Version import java.io.InputStreamReader object DataPackDependency { - private val START_DETECT_VERSION = Version(1, 20, 5) + private val START_DETECT_VERSION = Version(1, 19, 0) /** * 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)) + Pair("bracken", Version(1, 11, 0)) ) val enabledDatapacks: List @@ -49,16 +47,6 @@ object DataPackDependency { continue } - if (packName.contains("neoenchant", ignoreCase = true)) { - handlePack("enchantplus") - continue - } - - if (packName.contains("Dungeons and Taverns", ignoreCase = true)) { - handlePack("dungeons_and_taverns") - continue - } - } } @@ -72,12 +60,9 @@ object DataPackDependency { 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)) { + if (currentVersion.greaterEqual(version!!)) { handleEnchantAllConflict(pack) return } @@ -145,7 +130,7 @@ object DataPackDependency { CustomAnvil.instance.logger.warning("Could not find material $name for item group $groupName") continue } - group.addToPolicy(mat.key) + group.addToPolicy(mat) } for (name in section.getStringList("groups")) { val otherGroup = MaterialGroupApi.getGroup(name) 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/gui/GuiTesterSelector.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/GuiTesterSelector.kt new file mode 100644 index 0000000..8c6ad26 --- /dev/null +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/GuiTesterSelector.kt @@ -0,0 +1,54 @@ +package xyz.alexcrea.cuanvil.dependency.gui + +import xyz.alexcrea.cuanvil.dependency.gui.version.*; +import xyz.alexcrea.cuanvil.update.UpdateUtils + +object GuiTesterSelector { + + val selectGuiTester: ExternGuiTester? + get() { + val versionParts = UpdateUtils.currentMinecraftVersionArray() + if (versionParts[0] != 1) return null + + return when (versionParts[1]) { + // Can't support 1.16.5 bc 1.16.5 paper userdev do not exist + + 17 -> when (versionParts[2]) { + 0, 1 -> v1_17R1_ExternGuiTester() + else -> null + } + + 18 -> when (versionParts[2]) { + 0, 1 -> v1_18R1_ExternGuiTester() + 2 -> v1_18R2_ExternGuiTester() + else -> null + } + + 19 -> when (versionParts[2]) { + 0, 1, 2 -> v1_19R1_ExternGuiTester() + 3 -> v1_19R2_ExternGuiTester() + 4 -> v1_19R3_ExternGuiTester() + else -> null + } + + 20 -> when (versionParts[2]) { + 0, 1 -> v1_20R1_ExternGuiTester() + 2 -> v1_20R2_ExternGuiTester() + 3, 4 -> v1_20R3_ExternGuiTester() + 5, 6 -> v1_20R4_ExternGuiTester() + else -> null + } + + 21 -> when (versionParts[2]) { + 0, 1 -> v1_21R1_ExternGuiTester() + 2, 3 -> v1_21R2_ExternGuiTester() + 4 -> v1_21R3_ExternGuiTester() + 5 -> v1_21R4_ExternGuiTester() + else -> null + } + + else -> null + } + } + +} \ 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 index d74ef08..fc14921 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/PacketManagerSelector.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/packet/PacketManagerSelector.kt @@ -1,31 +1,16 @@ 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 - } - } + else + versionSpecificManager ?: protocolibIfPresent } private val protocolibIfPresent: PacketManager @@ -34,21 +19,49 @@ object PacketManagerSelector { ProtocoLibWrapper() else NoPacketManager() - - // Reobfuscated packet manager for spigot or paper as it remap - private val reobfPacketManager: PacketManagerBase? + private val versionSpecificManager: PacketManagerBase? get() { - val versionParts = UpdateUtils.currentMinecraftVersion() - if (versionParts.major != 1) return null + val versionParts = UpdateUtils.currentMinecraftVersionArray() + if (versionParts[0] != 1) return null - try { - val clazz = Class.forName("xyz.alexcrea.cuanvil.dependency.packet.versions." + - "V${MinecraftVersionUtil.craftbukkitVersion}_PacketManager") + return when (versionParts[1]) { + // Can't support 1.16.5 bc 1.16.5 paper userdev do not exist - val manager = clazz.getConstructor().newInstance() - return manager as PacketManagerBase - } catch (_: ClassNotFoundException) { - return null + 17 -> when (versionParts[2]) { + 0, 1 -> V1_17R1_PacketManager() + else -> null + } + + 18 -> when (versionParts[2]) { + 0, 1 -> V1_18R1_PacketManager() + 2 -> V1_18R2_PacketManager() + else -> null + } + + 19 -> when (versionParts[2]) { + 0, 1, 2 -> V1_19R1_PacketManager() + 3 -> V1_19R2_PacketManager() + 4 -> V1_19R3_PacketManager() + else -> null + } + + 20 -> when (versionParts[2]) { + 0, 1 -> V1_20R1_PacketManager() + 2 -> V1_20R2_PacketManager() + 3, 4 -> V1_20R3_PacketManager() + 5, 6 -> V1_20R4_PacketManager() + else -> null + } + + 21 -> when (versionParts[2]) { + 0, 1 -> V1_21R1_PacketManager() + 2, 3 -> V1_21R2_PacketManager() + 4 -> V1_21R3_PacketManager() + 5 -> V1_21R4_PacketManager() + else -> null + } + + else -> 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 index 690b384..acccabe 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/DisenchantmentDependency.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/DisenchantmentDependency.kt @@ -5,21 +5,14 @@ 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.entity.HumanEntity 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 +import xyz.alexcrea.cuanvil.util.AnvilXpUtil class DisenchantmentDependency { @@ -29,44 +22,25 @@ class DisenchantmentDependency { 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) - } + InventoryClickEvent.getHandlerList().unregister(Disenchantment.plugin) } - 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 { + fun testPrepareAnvil(event: PrepareAnvilEvent, player: HumanEntity): Boolean { val previousResult = event.result event.result = null // Test if event change the result DisenchantEvent.onEvent(event) - if (event.result != null) { + if(event.result != null) { CustomAnvil.log("Detected pre anvil item extract bypass.") - AnvilXpUtil.setAnvilInvCost(event.inventory, event.view, player, AnvilCost(event.inventory.repairCost)) + AnvilXpUtil.setAnvilInvXp(event.inventory, event.view, player, event.inventory.repairCost) return true } ShatterEvent.onEvent(event) - if (event.result != null) { + if(event.result != null) { CustomAnvil.log("Detected pre anvil split enchant bypass.") - AnvilXpUtil.setAnvilInvCost(event.inventory, event.view, player, AnvilCost(event.inventory.repairCost)) + AnvilXpUtil.setAnvilInvXp(event.inventory, event.view, player, event.inventory.repairCost) return true } @@ -79,13 +53,13 @@ class DisenchantmentDependency { // Test event if change the result DisenchantClickEvent.onEvent(event) - if (!testAnvilInventoryChange(inventory, previousResultSlot) || event.isCancelled) { + 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) { + if(!testAnvilInventoryChange(inventory, previousResultSlot) || event.isCancelled) { CustomAnvil.log("Detected anvil click split enchant bypass.") return true } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/EcoEnchantDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/EcoEnchantDependency.kt index 079d570..22fce5e 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/EcoEnchantDependency.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/EcoEnchantDependency.kt @@ -1,9 +1,7 @@ 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 @@ -34,10 +32,6 @@ class EcoEnchantDependency(private val ecoEnchantPlugin: Plugin) { } - public fun getEcoLevelLimit(): Int { - return (ecoEnchantPlugin as EcoPlugin).configYml.getInt("anvil.enchant-limit").infiniteIfNegative() - } - fun disableAnvilListener() { PrepareAnvilEvent.getHandlerList().unregister(this.ecoEnchantPlugin) } 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 index d769986..f4da612 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/EnchantmentSquaredDependency.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/EnchantmentSquaredDependency.kt @@ -102,15 +102,15 @@ class EnchantmentSquaredDependency(private val enchantmentSquaredPlugin: Plugin) private fun writeMissingGroups(){ // Write group that do not exist on custom anvil. val shield = IncludeGroup("shield") - shield.addToPolicy(Material.SHIELD.key) + shield.addToPolicy(Material.SHIELD) MaterialGroupApi.addMaterialGroup(shield) val elytra = IncludeGroup("elytra") - elytra.addToPolicy(Material.ELYTRA.key) + elytra.addToPolicy(Material.ELYTRA) MaterialGroupApi.addMaterialGroup(elytra) val trinkets = IncludeGroup("trinkets") - trinkets.addToPolicy(Material.ROTTEN_FLESH.key) + trinkets.addToPolicy(Material.ROTTEN_FLESH) MaterialGroupApi.addMaterialGroup(trinkets) } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ExcellentEnchantsDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ExcellentEnchantsDependency.kt index 816a4df..e5aa8be 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ExcellentEnchantsDependency.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ExcellentEnchantsDependency.kt @@ -7,158 +7,80 @@ import org.bukkit.event.inventory.InventoryClickEvent import org.bukkit.event.inventory.PrepareAnvilEvent import org.bukkit.inventory.ItemStack import org.bukkit.plugin.RegisteredListener +import su.nightexpress.excellentenchants.enchantment.impl.universal.CurseOfFragilityEnchant +import su.nightexpress.excellentenchants.enchantment.listener.AnvilListener +import su.nightexpress.excellentenchants.enchantment.listener.EnchantAnvilListener +import su.nightexpress.excellentenchants.registry.EnchantRegistry 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.CAEEEnchantment 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 + private val isModern: 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 + var isModern = true; try { - Class.forName("su.nightexpress.excellentenchants.enchantment.universal.CurseOfFragilityEnchant") + Class.forName("su.nightexpress.excellentenchants.enchantment.listener.AnvilListener") } catch (ignored: ClassNotFoundException) { - isModernCurseOfFragility = false + isModern = false } - this.listenerVersion = listenerVersion - this.isModernCurseOfFragility = isModernCurseOfFragility + this.isModern = isModern } 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)) - } + if (this.isModern) { + for (enchantment in EnchantRegistry.getRegistered()) { + EnchantmentApi.unregisterEnchantment(enchantment.bukkitEnchantment.key) + EnchantmentApi.registerEnchantment(CAEEEnchantment(enchantment)) } - - ListenerVersion.V5, ListenerVersion.V5_3 -> { - for (enchantment in V5EnchantRegistry.getRegistered()) { - EnchantmentApi.unregisterEnchantment(enchantment.bukkitEnchantment.key) - EnchantmentApi.registerEnchantment(CAEEV5Enchantment(enchantment)) - } + } else { + for (enchantment in su.nightexpress.excellentenchants.enchantment.registry.EnchantRegistry.getRegistered()) { + EnchantmentApi.unregisterEnchantment(enchantment.enchantment.key) + EnchantmentApi.registerEnchantment(CALegacyEEEnchantment(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 fragilityCurse: CurseOfFragilityEnchant? = null - private var v5AnvilListener: V5AnvilListener? = null - private var preV5AnvilListener: PreV5AnvilListener? = null - private var legacyAnvilListener: LegacyAnvilListener? = null + private var modernAnvilListener: AnvilListener? = null + private var legacyAnvilListener: EnchantAnvilListener? = 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) - } + if (listener is CurseOfFragilityEnchant) { + this.fragilityCurse = listener + toUnregister.add(registeredListener) } - when (listenerVersion) { - ListenerVersion.V5, - ListenerVersion.V5_3, - ListenerVersion.V5_4, - -> { - if (listener is V5AnvilListener) { - this.v5AnvilListener = listener - toUnregister.add(registeredListener) - } + if (this.isModern) { + if (listener is AnvilListener) { + this.modernAnvilListener = 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 -> { + } else { + if (listener is EnchantAnvilListener) { + this.legacyAnvilListener = listener; + toUnregister.add(registeredListener) } } @@ -168,14 +90,10 @@ class ExcellentEnchantsDependency { 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 -> {} + if (this.isModern) { + this.usedAnvilListener = this.modernAnvilListener!! + } else { + this.usedAnvilListener = this.legacyAnvilListener!! } // Unregister inventory click event @@ -191,27 +109,17 @@ class ExcellentEnchantsDependency { ) 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) - } + 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) - } + this.fragilityCurse?.onItemAnvil(event) if (event.result == null) return true } @@ -221,28 +129,19 @@ class ExcellentEnchantsDependency { return handleRechargeMethod.invoke(this.usedAnvilListener, event, first, second) as Boolean } - fun treatAnvilResult(event: CATreatAnvilResult2Event) { - val result = event.result ?: return + fun treatAnvilResult(event: PrepareAnvilEvent, result: ItemStack) { + val first: ItemStack = treatInput(event.inventory.getItem(0)) + val second: ItemStack = treatInput(event.inventory.getItem(1)) - 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 + handleCombineMethod.invoke(this.usedAnvilListener, event, first, second, 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 -> {} + if (this.isModern) { + this.modernAnvilListener!!.onClickAnvil(event) + } else { + this.legacyAnvilListener!!.onClickAnvil(event) } return event.inventory.getItem(2) == null } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/GenericPluginDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/GenericPluginDependency.kt index 62dae9b..95be29e 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/GenericPluginDependency.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/GenericPluginDependency.kt @@ -5,14 +5,20 @@ 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) { +abstract class GenericPluginDependency(val plugin: Plugin) { - private val preAnvil = ArrayList() - private val postAnvil = ArrayList() + protected val preAnvil = ArrayList() + protected val postAnvil = ArrayList() open fun redirectListeners() { - fillPreAnvil(preAnvil) - fillPostAnvil(postAnvil, preAnvil) + // get PreAnvil and PostAnvil listeners + for (registeredListener in PrepareAnvilEvent.getHandlerList().registeredListeners) { + + if (registeredListener.plugin != plugin) continue + preAnvil.add(registeredListener) + } + + postAnvil.addAll(postAnvilEvents()) // get required PrepareAnvilEvent listener for (listener in preAnvil) { @@ -22,37 +28,17 @@ open class GenericPluginDependency(protected open val plugin: Plugin, private va 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) { } + protected abstract fun postAnvilEvents(): Collection + 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() - } - + registeredListener.callEvent(event) if (event.result != null) return true } @@ -61,15 +47,8 @@ open class GenericPluginDependency(protected open val plugin: Plugin, private va } 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() - } + registeredListener.callEvent(event) if (event.inventory.getItem(2) == null) return true } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/HavenBagsDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/HavenBagsDependency.kt index 6f30497..6e7cf60 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/HavenBagsDependency.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/HavenBagsDependency.kt @@ -1,7 +1,7 @@ package xyz.alexcrea.cuanvil.dependency.plugins import io.delilaheve.CustomAnvil -import org.bukkit.entity.Player +import org.bukkit.entity.HumanEntity import org.bukkit.event.inventory.InventoryClickEvent import org.bukkit.event.inventory.PrepareAnvilEvent import org.bukkit.inventory.AnvilInventory @@ -9,9 +9,8 @@ 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 +import xyz.alexcrea.cuanvil.util.AnvilXpUtil class HavenBagsDependency { @@ -46,7 +45,7 @@ class HavenBagsDependency { } - fun testPrepareAnvil(event: PrepareAnvilEvent, player: Player): Boolean { + fun testPrepareAnvil(event: PrepareAnvilEvent, player: HumanEntity): Boolean { val previousResult = event.result event.result = null @@ -54,14 +53,14 @@ class HavenBagsDependency { 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)) + AnvilXpUtil.setAnvilInvXp(event.inventory, event.view, player, 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)) + AnvilXpUtil.setAnvilInvXp(event.inventory, event.view, player, event.inventory.repairCost) return true } 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/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 index 255f737..80fd753 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ToolStatsDependency.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ToolStatsDependency.kt @@ -1,8 +1,10 @@ package xyz.alexcrea.cuanvil.dependency.plugins +import io.delilaheve.CustomAnvil import lol.hyper.toolstats.ToolStats import lol.hyper.toolstats.tools.ItemChecker import org.bukkit.event.inventory.InventoryClickEvent +import org.bukkit.event.inventory.PrepareAnvilEvent import org.bukkit.inventory.ItemStack import org.bukkit.plugin.Plugin import org.bukkit.plugin.RegisteredListener @@ -11,7 +13,7 @@ import java.lang.reflect.Method class ToolStatsDependency(plugin: Plugin) : GenericPluginDependency(plugin) { - // Sadly, getTokens function is private, so I need to do some reflectino + // Sadly, getTokens function is private, so I need to do that private val getTokenMethod: Method = ItemChecker::class.java.getDeclaredMethod("getTokens", ItemStack::class.java); @@ -19,9 +21,15 @@ class ToolStatsDependency(plugin: Plugin) : GenericPluginDependency(plugin) { getTokenMethod.trySetAccessible() } - private fun ItemChecker.getTokenSafe(item: ItemStack?): Array { - if (item == null) return arrayOf() - return getTokenMethod.invoke(this, item) as Array + override fun postAnvilEvents(): Collection { + return listOf() + } + + override fun testPrepareAnvil(event: PrepareAnvilEvent): Boolean { + var result = super.testPrepareAnvil(event) + CustomAnvil.verboseLog("pre anvil result: $result") + + return result } override fun testAnvilResult(event: InventoryClickEvent): Boolean { @@ -31,9 +39,12 @@ class ToolStatsDependency(plugin: Plugin) : GenericPluginDependency(plugin) { val itemChecker = (plugin as ToolStats).itemChecker - val leftTokens = itemChecker.getTokenSafe(left) - val resultToken = itemChecker.getTokenSafe(result) + val leftTokens = getTokenMethod.invoke(itemChecker, left) as Array + val resultToken = getTokenMethod.invoke(itemChecker, result) as Array - return !leftTokens.contentDeepEquals(resultToken); + val resultVal = !leftTokens.contentDeepEquals(resultToken) + + CustomAnvil.verboseLog("Test anvil result: $resultVal") + return resultVal } } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/scheduler/BukkitScheduler.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/scheduler/BukkitScheduler.kt index 8c04162..b26dd42 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/scheduler/BukkitScheduler.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/scheduler/BukkitScheduler.kt @@ -6,12 +6,12 @@ import org.bukkit.plugin.Plugin class BukkitScheduler : TaskScheduler { - override fun scheduleGlobally(plugin: Plugin, task: Runnable, time: Long): Any { + 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 { + 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 index d0d2bda..ec6e7bc 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/AbstractMaterialGroup.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/group/AbstractMaterialGroup.kt @@ -1,8 +1,7 @@ package xyz.alexcrea.cuanvil.group import org.bukkit.Material -import org.bukkit.NamespacedKey -import xyz.alexcrea.cuanvil.util.MaterialUtil +import java.util.* abstract class AbstractMaterialGroup(private val name: String) { protected val includedMaterial by lazy { createDefaultSet() } @@ -10,12 +9,12 @@ abstract class AbstractMaterialGroup(private val name: String) { /** * Get the group default set */ - protected abstract fun createDefaultSet(): MutableSet + protected abstract fun createDefaultSet(): EnumSet /** * Get if a material is allowed following the group policy */ - open fun contain(mat: NamespacedKey): Boolean { + open fun contain(mat: Material): Boolean { return mat in getMaterials() } @@ -28,13 +27,13 @@ abstract class AbstractMaterialGroup(private val name: String) { * Push a material to this group to follow this group policy * @return this instance. */ - abstract fun addToPolicy(type: NamespacedKey): AbstractMaterialGroup + abstract fun addToPolicy(mat: Material): AbstractMaterialGroup /** * Push a list of material to this group to follow this group policy * @return this instance. */ - fun addAll(vararg materials: NamespacedKey): AbstractMaterialGroup { + fun addAll(vararg materials: Material): AbstractMaterialGroup { for (material in materials) { addToPolicy(material) } @@ -61,19 +60,19 @@ abstract class AbstractMaterialGroup(private val name: String) { /** * Get the group contained material as a set */ - abstract fun getMaterials(): Set + abstract fun getMaterials(): EnumSet /** * Get the group non-inherited material as a set */ - open fun getNonGroupInheritedMaterials(): Set { + open fun getNonGroupInheritedMaterials(): EnumSet { return includedMaterial } /** * Get the group non-inherited material as a set */ - open fun setNonGroupInheritedMaterials(materials: Set) { + open fun setNonGroupInheritedMaterials(materials: EnumSet) { this.includedMaterial.clear() this.includedMaterial.addAll(materials) } @@ -103,9 +102,8 @@ abstract class AbstractMaterialGroup(private val name: String) { // 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 + val material = matIterator.next() + if (material.isAir) continue return material } // Test included group representative material diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictGroup.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictGroup.kt index 59841ac..56e923f 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictGroup.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictGroup.kt @@ -2,18 +2,15 @@ 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, + var minBeforeBlock: Int ) { private val enchantments = HashSet() - private val conflictsAfterLevel = HashMap() - private val conflictsBeforeLevel = HashMap() fun addEnchantment(enchant: CAEnchantment) { enchantments.add(enchant) @@ -22,56 +19,19 @@ class EnchantConflictGroup( 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 { + fun allowed(enchants: Set, mat: Material): 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)) + if (cantConflict.contain(mat)) { return true + } // Count the amount of enchantment that are in the list var enchantAmount = 0 - for (entry in enchants) { - val enchantment = entry.key - + for (enchantment in enchants) { if (enchantment !in enchantments) continue CustomAnvil.verboseLog("Enchant ${enchantment.key} is in: ${enchantAmount + 1}/$minBeforeBlock ") if (++enchantAmount > minBeforeBlock) { @@ -96,36 +56,6 @@ class EnchantConflictGroup( 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() diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt index 38d5476..169d9e9 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt @@ -8,9 +8,7 @@ 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 { @@ -18,14 +16,6 @@ class EnchantConflictManager { // 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" @@ -49,11 +39,6 @@ class EnchantConflictManager { 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() @@ -65,11 +50,7 @@ class EnchantConflictManager { val keys = config.getKeys(false) for (key in keys) { - val section = config.getConfigurationSection(key) - if(section == null) { - warnBadKey(key) - continue - } + val section = config.getConfigurationSection(key)!! val conflict = createConflict(section, itemManager, key) addConflict(conflict) @@ -129,36 +110,9 @@ class EnchantConflictManager { } } - 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) { @@ -221,8 +175,8 @@ class EnchantConflictManager { item: ItemStack, newEnchant: CAEnchantment ): ConflictType { - val type = item.customType - CustomAnvil.verboseLog("Testing conflict for ${newEnchant.key} on ${type}") + val mat = item.type + CustomAnvil.verboseLog("Testing conflict for ${newEnchant.key} on ${mat.key}") val conflictList = newEnchant.conflicts var result = ConflictType.NO_CONFLICT @@ -233,7 +187,7 @@ class EnchantConflictManager { continue } - val allowed = conflict.allowed(appliedEnchants, type) + val allowed = conflict.allowed(appliedEnchants.keys, mat) CustomAnvil.verboseLog("Was against $conflict and conflicting: ${!allowed} ") if (!allowed) { if (conflict.getEnchants().size <= 1) { @@ -249,7 +203,7 @@ class EnchantConflictManager { val immutableEnchants = Collections.unmodifiableMap(appliedEnchants) for (appliedEnchant in appliedEnchants.keys) { if (appliedEnchant is AdditionalTestEnchantment) { - val doConflict = appliedEnchant.isEnchantConflict(immutableEnchants, type) + val doConflict = appliedEnchant.isEnchantConflict(immutableEnchants, mat) if (doConflict) { CustomAnvil.verboseLog("Big conflict by additional test, stopping") return ConflictType.ENCHANTMENT_CONFLICT @@ -261,7 +215,7 @@ class EnchantConflictManager { if ((result != ConflictType.ITEM_CONFLICT) && (newEnchant is AdditionalTestEnchantment)) { val partialItem = createPartialResult(item, immutableEnchants) - if (newEnchant.isItemConflict(immutableEnchants, type, partialItem)) { + if (newEnchant.isItemConflict(immutableEnchants, mat, partialItem)) { return ConflictType.ITEM_CONFLICT } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/ExcludeGroup.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/ExcludeGroup.kt index d752db5..7684c3f 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/ExcludeGroup.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/group/ExcludeGroup.kt @@ -1,12 +1,11 @@ package xyz.alexcrea.cuanvil.group -import org.bukkit.NamespacedKey +import org.bukkit.Material import java.util.* class ExcludeGroup(name: String) : AbstractMaterialGroup(name) { - - override fun createDefaultSet(): MutableSet { - return NegativeMaterialSet() + override fun createDefaultSet(): EnumSet { + return EnumSet.allOf(Material::class.java) } private var includedGroup: MutableSet = HashSet() @@ -21,9 +20,9 @@ class ExcludeGroup(name: String) : AbstractMaterialGroup(name) { return false } - override fun addToPolicy(type: NamespacedKey): ExcludeGroup { - includedMaterial.remove(type) - groupItems.remove(type) + override fun addToPolicy(mat: Material): ExcludeGroup { + includedMaterial.remove(mat) + groupItems.remove(mat) return this } @@ -61,7 +60,7 @@ class ExcludeGroup(name: String) : AbstractMaterialGroup(name) { } } - override fun getMaterials(): MutableSet { + override fun getMaterials(): EnumSet { return groupItems } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/IncludeGroup.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/IncludeGroup.kt index fc9614b..848789f 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/IncludeGroup.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/group/IncludeGroup.kt @@ -1,12 +1,11 @@ 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() + override fun createDefaultSet(): EnumSet { + return EnumSet.noneOf(Material::class.java) } private var includedGroup: MutableSet = HashSet() @@ -21,9 +20,9 @@ class IncludeGroup(name: String) : AbstractMaterialGroup(name) { return false } - override fun addToPolicy(type: NamespacedKey): IncludeGroup { - includedMaterial.add(type) - groupItems.add(type) + override fun addToPolicy(mat: Material): IncludeGroup { + includedMaterial.add(mat) + groupItems.add(mat) return this } @@ -48,7 +47,7 @@ class IncludeGroup(name: String) : AbstractMaterialGroup(name) { } } - override fun setNonGroupInheritedMaterials(materials: Set) { + override fun setNonGroupInheritedMaterials(materials: EnumSet) { super.setNonGroupInheritedMaterials(materials) updateMaterials() @@ -67,7 +66,7 @@ class IncludeGroup(name: String) : AbstractMaterialGroup(name) { } } - override fun getMaterials(): MutableSet { + override fun getMaterials(): EnumSet { return groupItems } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/ItemGroupManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/ItemGroupManager.kt index 348d0ff..65eef34 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/ItemGroupManager.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/group/ItemGroupManager.kt @@ -31,8 +31,6 @@ class ItemGroupManager { for (key in keys) { if (groupMap.containsKey(key)) continue - if (!config.isConfigurationSection(key)) - continue createGroup(config, keys, key) } } @@ -53,7 +51,6 @@ class ItemGroupManager { key: String ): AbstractMaterialGroup { val groupSection = config.getConfigurationSection(key)!! - val groupType = groupSection.getString(GROUP_TYPE_PATH, null) // Create Material group according to the group type @@ -94,7 +91,7 @@ class ItemGroupManager { } continue } - group.addToPolicy(material.key) + group.addToPolicy(material) } // Read group to include in this group policy. @@ -108,13 +105,11 @@ class ItemGroupManager { continue } // Get other group or create it if not yet created - val otherGroup = - if (!groupMap.containsKey(groupName)) { - if(!config.isConfigurationSection(groupName)) continue + 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( 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 index d707b56..60a0339 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilCloseListener.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilCloseListener.kt @@ -7,7 +7,6 @@ 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 { @@ -19,7 +18,6 @@ class AnvilCloseListener(private val packetManager: PacketManager) : Listener { 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 index e393dbd..e43ff62 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt @@ -3,6 +3,7 @@ package xyz.alexcrea.cuanvil.listener import io.delilaheve.CustomAnvil import io.delilaheve.util.ConfigOptions import io.delilaheve.util.ItemUtil.canMergeWith +import io.delilaheve.util.ItemUtil.unitRepair import org.bukkit.GameMode import org.bukkit.Material import org.bukkit.entity.Player @@ -15,26 +16,20 @@ 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.recipe.AnvilCustomRecipe +import xyz.alexcrea.cuanvil.util.AnvilLoreEditUtil +import xyz.alexcrea.cuanvil.util.AnvilUseType +import xyz.alexcrea.cuanvil.util.AnvilXpUtil 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.UnitRepairUtil.getRepair import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil import xyz.alexcrea.cuanvil.util.config.LoreEditType import java.util.* -import java.util.concurrent.atomic.AtomicReference +import java.util.concurrent.atomic.AtomicInteger import kotlin.math.min class AnvilResultListener : Listener { @@ -51,8 +46,8 @@ class AnvilResultListener : Listener { @EventHandler(ignoreCancelled = true) fun anvilExtractionCheck(event: InventoryClickEvent) { val player = event.whoClicked as? Player ?: return + if (!player.hasPermission(CustomAnvil.affectedByPluginPermission)) return val inventory = event.inventory as? AnvilInventory ?: return - val view = event.view if (event.rawSlot != ANVIL_OUTPUT_SLOT) { return @@ -61,116 +56,84 @@ class AnvilResultListener : Listener { // 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) { + event.result = Event.Result.DENY return } // Test custom recipe - val customRecipeResult = AnvilMergeLogic.testCustomRecipe(view, inventory, player, leftItem, rightItem) - if (!customRecipeResult.isEmpty()) { + val recipe = CustomRecipeUtil.getCustomRecipe(leftItem, rightItem) + if (recipe != null) { + event.result = Event.Result.ALLOW onCustomCraft( - event, player, inventory, - leftItem, rightItem, customRecipeResult + event, recipe, player, + leftItem, rightItem, output, inventory ) return } // Do not continue if there was no change if ((output == inventory.getItem(ANVIL_INPUT_LEFT))) { + event.result = Event.Result.DENY 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 - ) + event.result = Event.Result.ALLOW 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 - ) + event.result = Event.Result.ALLOW return } // Unit repair - val unitRepairResult = AnvilMergeLogic.testUnitRepair( - view, inventory, player, - leftItem, rightItem - ) - if (!unitRepairResult.isEmpty()) { + val unitRepairResult = leftItem.getRepair(rightItem) + if (unitRepairResult != null) { onUnitRepairExtract( - rightItem, event, player, inventory, - unitRepairResult + leftItem, rightItem, output, + unitRepairResult, event, player, inventory ) 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) + if (handleBookLoreEdit(event, inventory, player, leftItem, rightItem, output)) { + return + } else if (handlePaperLoreEdit(event, inventory, player, leftItem, rightItem, output)) { return } + + // Else there was no working situation somehow so we deny + event.result = Event.Result.DENY } private fun onCustomCraft( event: InventoryClickEvent, + recipe: AnvilCustomRecipe, player: Player, - inventory: AnvilInventory, leftItem: ItemStack, rightItem: ItemStack?, - result: CustomCraftResult, + output: ItemStack, + inventory: AnvilInventory ) { - val recipe = result.recipe!! - val rawCost = result.customCraftCost.rawCost - val finalCost = - if (recipe.removeExactLinearXp) rawCost - else AnvilXpUtil.calculateLevelForXp(rawCost) + event.result = Event.Result.DENY - CustomAnvil.log( - "gamemode: ${player.gameMode != GameMode.CREATIVE}, " + - "cost: $finalCost, level: ${player.level}, " + - "result: ${player.totalExperience < finalCost} ${player.level < finalCost}" - ) + if (recipe.leftItem == null) return // in case it changed - 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 - } + val amount = CustomRecipeUtil.getCustomRecipeAmount(recipe, leftItem, rightItem) + val xpCost = amount * recipe.xpCostPerCraft + + CustomAnvil.log("gamemode: ${player.gameMode != GameMode.CREATIVE}, cost: $xpCost, level: ${player.level}, result: ${player.level < xpCost}") + if ((player.gameMode != GameMode.CREATIVE) && (player.level < xpCost)) return // We give the item manually // But first we check if we should give the item @@ -179,33 +142,23 @@ class AnvilResultListener : Listener { // Handle not creative middle click... if (event.click != ClickType.MIDDLE && - !handleCustomCraftClick( - event, - inventory, - player, - leftItem, - rightItem, - result - ) + !handleCustomCraftClick(event, recipe, inventory, player, leftItem, rightItem, amount, xpCost) ) return // Finally, we add the item to the player if (slotDestination.type == SlotType.CURSOR) { - player.setItemOnCursor(result.item) + player.setItemOnCursor(output) } else {// We assume SlotType == SlotType.INVENTORY - player.inventory.setItem(slotDestination.slot, result.item) + player.inventory.setItem(slotDestination.slot, output) } } private fun handleCustomCraftClick( - event: InventoryClickEvent, + event: InventoryClickEvent, recipe: AnvilCustomRecipe, inventory: AnvilInventory, player: Player, leftItem: ItemStack, rightItem: ItemStack?, - result: CustomCraftResult + amount: Int, xpCost: Int ): 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 @@ -217,7 +170,9 @@ class AnvilResultListener : Listener { leftItem.amount -= amount * recipe.leftItem!!.amount inventory.setItem(ANVIL_INPUT_LEFT, leftItem) - removeCustomCraftCost(player, result) + if (player.gameMode != GameMode.CREATIVE) { + player.level -= xpCost + } // Then we try to find the new values for the anvil val newAmount = CustomRecipeUtil.getCustomRecipeAmount(recipe, leftItem, rightItem) @@ -241,53 +196,6 @@ class AnvilResultListener : Listener { 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, @@ -296,17 +204,15 @@ class AnvilResultListener : Listener { leftRemoveCount: Int, rightItem: ItemStack?, rightRemoveCount: Int, - result: AnvilResult + output: ItemStack, + repairCost: Int, ): 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 + // Assumed if player do not have enough xp then it returned MIN_VALUE + if (repairCost == Int.MIN_VALUE) return false // Where should we get the item val slotDestination = getActionSlot(event, player) @@ -314,8 +220,6 @@ class AnvilResultListener : Listener { // 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) @@ -324,58 +228,99 @@ class AnvilResultListener : Listener { inventory.setItem(ANVIL_INPUT_RIGHT, rightItem) inventory.setItem(ANVIL_OUTPUT_SLOT, null) - + player.level -= repairCost } // Finally, we add the item to the player if (SlotType.CURSOR == slotDestination.type) { - player.setItemOnCursor(result.item) + player.setItemOnCursor(output) } else {// We assume SlotType == SlotType.INVENTORY - player.inventory.setItem(slotDestination.slot, result.item) + player.inventory.setItem(slotDestination.slot, output) } // TODO probably anvil damage & sound here ?? return true } - private fun processCost(inventory: AnvilInventory, player: Player, cost: AnvilCost) { - var sum = cost.repair + private fun onUnitRepairExtract( + leftItem: ItemStack, + rightItem: ItemStack, + output: ItemStack, + unitRepairResult: Double, + event: InventoryClickEvent, + player: Player, + inventory: AnvilInventory + ) { + val resultCopy = leftItem.clone() + val resultAmount = resultCopy.unitRepair( + rightItem.amount, unitRepairResult + ) + + // Get repair cost + val repairCost = getUnitRepairCost(inventory, player, leftItem, output, resultCopy, resultAmount) + + // And then we give the item manually + extractAnvilResult( + event, player, inventory, + null, 0, + rightItem, resultAmount, + resultCopy, repairCost + ) + } + + private fun getUnitRepairCost( + inventory: AnvilInventory, player: Player, + leftItem: ItemStack, output: ItemStack, + resultCopy: ItemStack, resultAmount: Int + ): Int { + if (player.gameMode == GameMode.CREATIVE) return 0 + + var repairCost = 0 + // Get repairCost + leftItem.itemMeta?.let { leftMeta -> + val leftName = leftMeta.displayName + output.itemMeta?.let { + // Rename cost + if (!leftName.contentEquals(it.displayName)) { + repairCost += ConfigOptions.itemRenameCost + + // Color cost + if (it.displayName.contains('§')) { + repairCost += ConfigOptions.useOfColorCost + } + } + } + } + + repairCost += AnvilXpUtil.calculatePenalty(leftItem, null, resultCopy, AnvilUseType.UNIT_REPAIR) + repairCost += resultAmount * ConfigOptions.unitRepairCost if ( !ConfigOptions.doRemoveCostLimit && ConfigOptions.doCapCost ) { - val final = min(sum, ConfigOptions.maxAnvilCost) - cost.generic += (final - sum) - - sum = final + repairCost = min(repairCost, ConfigOptions.maxAnvilCost) } - 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 - } + if ((inventory.maximumRepairCost <= repairCost) + || (player.level < repairCost) + ) return Int.MIN_VALUE + + return repairCost } - private fun onUnitRepairExtract( - rightItem: ItemStack, - event: InventoryClickEvent, + private fun getFromLoreEditXpCost( + xpCost: AtomicInteger, player: Player, inventory: AnvilInventory, - result: UnitRepairResult, - ) { - // We give the item manually - extractAnvilResult( - event, player, inventory, - null, 0, - rightItem, result.repairAmount, - result - ) + ): Int { + if (GameMode.CREATIVE == player.gameMode) return 0 + + val repairCost = xpCost.get() + return if ((inventory.maximumRepairCost <= repairCost) + || (player.level < repairCost) + ) Int.MIN_VALUE + else repairCost } private fun handleBookLoreEdit( @@ -384,84 +329,70 @@ class AnvilResultListener : Listener { 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) - } + output: ItemStack, + ): Boolean { + if (Material.WRITABLE_BOOK != rightItem.type) return false + val bookMeta = rightItem.itemMeta as BookMeta? ?: return false - private fun handleBookLoreAppend( - event: InventoryClickEvent, - inventory: AnvilInventory, - player: Player, - rightItem: ItemStack, - result: LoreEditResult - ) { - val bookMeta = rightItem.itemMeta as BookMeta? ?: return + val editType = AnvilLoreEditUtil.bookLoreEditIsAppend(leftItem, rightItem) ?: return false - // 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 - } + val xpCost = AtomicInteger() + if (editType) { + if (output != AnvilLoreEditUtil.handleLoreAppendByBook(player, leftItem, bookMeta, xpCost)) return false - 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)) + // 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 } - val resultPage = bookPage.toString() - //TODO maybe check page size ? bc it may be too big ??? + return extractAnvilResult( + event, player, inventory, + null, 0, + clearedBook, 0, + output, getFromLoreEditXpCost(xpCost, player, inventory) + ) + } else { + if (output != AnvilLoreEditUtil.handleLoreRemoveByBook(player, leftItem, xpCost)) return false - rightCopy = rightItem.clone() - bookMeta.setPages(resultPage) - rightCopy.itemMeta = bookMeta + // fill book meta + val meta = leftItem.itemMeta + if (meta == null || !meta.hasLore()) return false + val lore = DependencyManager.stripLore(leftItem) + if (lore.isEmpty()) return false + + 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') + bookPage.append(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 + } + + return extractAnvilResult( + event, player, inventory, + null, 0, + rightCopy, 0, + output, getFromLoreEditXpCost(xpCost, player, inventory) + ) } - - extractAnvilResult( - event, player, inventory, - null, 0, - rightCopy, 0, - result - ) } private fun handlePaperLoreEdit( @@ -470,106 +401,91 @@ class AnvilResultListener : Listener { 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) - } + output: ItemStack, + ): Boolean { + if (Material.PAPER != rightItem.type) return false + val paperMeta = rightItem.itemMeta ?: return false - private fun handlePaperLoreAppend( - event: InventoryClickEvent, - inventory: AnvilInventory, - player: Player, - rightItem: ItemStack, - result: LoreEditResult - ) { - val paperMeta = rightItem.itemMeta ?: return + val editType = AnvilLoreEditUtil.paperLoreEditIsAppend(leftItem, rightItem) ?: return false + val xpCost = AtomicInteger() + if (editType) { + if (output != AnvilLoreEditUtil.handleLoreAppendByPaper(player, leftItem, rightItem, xpCost)) return false - val paperCopy: ItemStack? - if (LoreEditType.APPEND_PAPER.doConsume) { - paperCopy = null + val paperCopy: ItemStack? + if (LoreEditType.APPEND_PAPER.doConsume) { + paperCopy = null + } else { + // Remove custom name to paper + paperCopy = rightItem.clone() + paperCopy.amount = 1 + paperMeta.setDisplayName(null) + paperCopy.itemMeta = paperMeta + } + + return if (rightItem.amount > 1) { + extractAnvilResult( + event, player, inventory, + paperCopy, 0, + rightItem, 1, + output, getFromLoreEditXpCost(xpCost, player, inventory) + ) + } else { + extractAnvilResult( + event, player, inventory, + null, 0, + paperCopy, 0, + output, getFromLoreEditXpCost(xpCost, player, inventory) + ) + } } else { - // Remove custom name to paper - paperCopy = rightItem.clone() - paperCopy.amount = 1 - paperMeta.setComponentDisplayName(null) + if (output != AnvilLoreEditUtil.handleLoreRemoveByPaper(player, leftItem, xpCost)) return false - // Remove pcd name - AnvilMergeLogic.processPCD(paperMeta, player, null) + val leftMeta = leftItem.itemMeta + if (leftMeta == null || !leftMeta.hasLore()) return false + val lore = DependencyManager.stripLore(leftItem) + if (lore.isEmpty()) return false - paperCopy.itemMeta = paperMeta + // Create result item + val rightClone: ItemStack? + if (LoreEditType.REMOVE_PAPER.doConsume) { + rightClone = null + } else { + val removeEnd = LoreEditConfigUtil.paperLoreOrderIsEnd + var line = if (removeEnd) lore[lore.size - 1] + else lore[0] + + // Overkill but uncolor the line + val tempList = ArrayList(1) + tempList.add(line) + AnvilLoreEditUtil.uncolorLines(player, tempList, LoreEditType.REMOVE_PAPER) + line = tempList[0] + + rightClone = rightItem.clone() + rightClone.amount = 1 + + val resultMeta = rightClone.itemMeta ?: return false + resultMeta.setDisplayName(line) + rightClone.itemMeta = resultMeta + } + + return if (rightItem.amount > 1) { + extractAnvilResult( + event, player, inventory, + rightClone, 0, + rightItem, 1, + output, getFromLoreEditXpCost(xpCost, player, inventory) + ) + } else { + extractAnvilResult( + event, player, inventory, + null, 0, + rightClone, 0, + output, getFromLoreEditXpCost(xpCost, player, inventory) + ) + } } - 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 - ) - } } /** diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt index 0217983..9d7245a 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt @@ -3,29 +3,28 @@ 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.EnchantmentUtil.combineWith import io.delilaheve.util.ItemUtil.canMergeWith +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.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 +import xyz.alexcrea.cuanvil.util.* +import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair +import java.util.concurrent.atomic.AtomicInteger /** * Listener for anvil events @@ -38,8 +37,6 @@ class PrepareAnvilListener : Listener { const val ANVIL_INPUT_LEFT = 0 const val ANVIL_INPUT_RIGHT = 1 const val ANVIL_OUTPUT_SLOT = 2 - - var IS_EMPTY_TEST = false } /** @@ -47,105 +44,58 @@ class PrepareAnvilListener : Listener { */ @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) + // Should find player + val player: HumanEntity = InventoryViewUtil.getInstance().getPlayer(event.view) // 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 - } + if (DependencyManager.earlyTryEventPreAnvilBypass(event, player)) return - val first = inventory.getItem(ANVIL_INPUT_LEFT) + val inventory = event.inventory + val first = inventory.getItem(ANVIL_INPUT_LEFT) ?: return 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) + event.result = null 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 (DependencyManager.tryEventPreAnvilBypass(event, player)) 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 + if (testCustomRecipe(event, inventory, player, first, second)) return // Test rename lonely item - val shouldTryRename = second.isAir - CustomAnvil.verboseLog("checking air in main logic: $shouldTryRename") - if (shouldTryRename) - return doRenaming(view, inventory, player, first) + if (second == null) { + doRenaming(event, inventory, player, first) + return + } // Test for merge - if (first.canMergeWith(second!!)) - return doMerge(view, inventory, player, first, second) + if (first.canMergeWith(second)) { + doMerge(event, inventory, player, first, second) + return + } // Test for unit repair - result = testUnitRepair(view, inventory, player, first, second) - if (!result.isEmpty()) - return result + if (testUnitRepair(event, inventory, player, first, second)) return // Test for lore edit - result = testLoreEdit(player, first, second) - if (!result.isEmpty()) - return result + if (testLoreEdit(event, inventory, player, first, second)) return - return AnvilResult.EMPTY - } + CustomAnvil.log("no anvil fuse type found") + event.result = null - 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 + if (item == null) return false - val meta = item!!.itemMeta + val meta = item.itemMeta return meta != null && (hasImmutableEnchants(meta) || hasImmutableStoredEnchants(meta)) } @@ -168,14 +118,186 @@ class PrepareAnvilListener : Listener { return false } - private fun applyResult(event: PrepareAnvilEvent, player: Player, result: AnvilResult) { - event.result = result.item + // return true if a custom recipe exist with these ingredients + private fun testCustomRecipe( + event: PrepareAnvilEvent, inventory: AnvilInventory, + player: HumanEntity, + first: ItemStack, second: ItemStack? + ): Boolean { + val recipe = CustomRecipeUtil.getCustomRecipe(first, second) + CustomAnvil.verboseLog("custom recipe not null? ${recipe != null}") + if (recipe == null) return false - if(result.item == null) { - AnvilXpUtil.onNoResult(player, event.view) - return - } - AnvilXpUtil.setAnvilInvCost(event.inventory, event.view, player, result.cost, result.ignoreXpRules) + val amount = CustomRecipeUtil.getCustomRecipeAmount(recipe, first, second) + + val resultItem: ItemStack = recipe.resultItem!!.clone() + resultItem.amount *= amount + + event.result = resultItem + if (DependencyManager.tryTreatAnvilResult(event, resultItem)) return true + + // Maybe add an option on custom craft to ignore/not ignore penalty ?? + var xpCost = recipe.xpCostPerCraft * amount + xpCost += AnvilXpUtil.calculatePenalty(first, null, resultItem, AnvilUseType.CUSTOM_CRAFT) + + AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, xpCost, true) + + return true } + private fun doRenaming( + event: PrepareAnvilEvent, inventory: AnvilInventory, + player: HumanEntity, first: ItemStack + ) { + val resultItem = first.clone() + var anvilCost = handleRename(resultItem, inventory, player) + + // Test/stop if nothing changed. + if (first == resultItem) { + CustomAnvil.log("no right item, But input is same as output") + event.result = null + return + } + + event.result = resultItem + if (DependencyManager.tryTreatAnvilResult(event, resultItem)) return + + anvilCost += AnvilXpUtil.calculatePenalty(first, null, resultItem, AnvilUseType.RENAME_ONLY) + + AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, anvilCost) + } + + private fun handleRename(resultItem: ItemStack, inventory: AnvilInventory, player: HumanEntity): Int { + // Can be null + var inventoryName = ChatColor.stripColor(inventory.renameText) + + var sumCost = 0 + var useColor = false + if (ConfigOptions.renameColorPossible && inventoryName != null) { + val resultString = StringBuilder(inventoryName) + + useColor = AnvilColorUtil.handleColor( + resultString, player, + ConfigOptions.permissionNeededForColor, + ConfigOptions.allowColorCode, ConfigOptions.allowHexadecimalColor, + AnvilColorUtil.ColorUseType.RENAME + ) + + if (useColor) { + inventoryName = resultString.toString() + + sumCost += ConfigOptions.useOfColorCost + } + } + + // 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(inventoryName)) { + it.setDisplayName(inventoryName) + resultItem.itemMeta = it + + sumCost += ConfigOptions.itemRenameCost + } + + return sumCost + } + return 0 + } + + private fun doMerge( + event: PrepareAnvilEvent, inventory: AnvilInventory, + player: HumanEntity, + first: ItemStack, second: ItemStack + ) { + val newEnchants = first.findEnchantments() + .combineWith(second.findEnchantments(), first, player) + val resultItem = first.clone() + resultItem.setEnchantmentsUnsafe(newEnchants) + + // Calculate enchantment cost + var anvilCost = AnvilXpUtil.getRightValues(second, resultItem) + // 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) + anvilCost += if (repaired) ConfigOptions.itemRepairCost else 0 + } + + // Test/stop if nothing changed. + if (first == resultItem) { + CustomAnvil.log("Mergable with second, But input is same as output") + event.result = null + return + } + // As calculatePenalty edit result, we need to calculate penalty after checking equality + anvilCost += AnvilXpUtil.calculatePenalty(first, second, resultItem, AnvilUseType.MERGE) + // Calculate rename cost + anvilCost += handleRename(resultItem, inventory, player) + + // Finally, we set result + event.result = resultItem + if (DependencyManager.tryTreatAnvilResult(event, resultItem)) return + + AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, anvilCost) + } + + // return true if there is a valid unit repair with these ingredients + private fun testUnitRepair( + event: PrepareAnvilEvent, inventory: AnvilInventory, player: HumanEntity, + first: ItemStack, second: ItemStack + ): Boolean { + val unitRepairAmount = first.getRepair(second) ?: return false + + val resultItem = first.clone() + var anvilCost = handleRename(resultItem, inventory, player) + + val repairAmount = resultItem.unitRepair(second.amount, unitRepairAmount) + if (repairAmount > 0) { + anvilCost += repairAmount * ConfigOptions.unitRepairCost + } + // We do not care about right item penalty for unit repair + anvilCost += 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") + event.result = null + return true + } + event.result = resultItem + if (DependencyManager.tryTreatAnvilResult(event, resultItem)) return true + + AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, anvilCost) + return true + } + + private fun testLoreEdit( + event: PrepareAnvilEvent, inventory: AnvilInventory, player: HumanEntity, + first: ItemStack, second: ItemStack + ): Boolean { + val type = second.type + var result: ItemStack? = null + + val xpCost = AtomicInteger() + if (Material.WRITABLE_BOOK == type) { + result = AnvilLoreEditUtil.tryLoreEditByBook(player, first, second, xpCost) + } else if (Material.PAPER == type) { + result = AnvilLoreEditUtil.tryLoreEditByPaper(player, first, second, xpCost) + } + + if (result == null || first == result) { + CustomAnvil.log("lore edit, But input is same as output") + event.result = null + return false + } + + event.result = result + AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, xpCost.get()) + return true + } } \ 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 index fd079c3..114dbe3 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/AnvilCustomRecipe.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/AnvilCustomRecipe.kt @@ -3,11 +3,8 @@ 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, @@ -15,10 +12,7 @@ class AnvilCustomRecipe( //var exactLeft: Boolean, //var exactRight: Boolean, - var levelCostPerCraft: Int, - - var XpCostPerCraft: Int, - var removeExactLinearXp: Boolean, + var xpCostPerCraft: Int, var leftItem: ItemStack?, var rightItem: ItemStack?, @@ -31,9 +25,7 @@ class AnvilCustomRecipe( //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 XP_COST_CONFIG = "xp_cost" const val LEFT_ITEM_CONFIG = "left_item" const val RIGHT_ITEM_CONFIG = "right_item" @@ -44,9 +36,7 @@ class AnvilCustomRecipe( //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 + const val DEFAULT_XP_COST_CONFIG = 1 val DEFAULT_LEFT_ITEM_CONFIG: ItemStack? = null val DEFAULT_RIGHT_ITEM_CONFIG: ItemStack? = null @@ -55,24 +45,20 @@ class AnvilCustomRecipe( val XP_COST_CONFIG_RANGE = 0..255 fun getFromConfig(name: String, configSection: ConfigurationSection?): AnvilCustomRecipe? { - if (configSection == null) return null + 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.getInt(XP_COST_CONFIG, DEFAULT_XP_COST_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? { @@ -81,21 +67,21 @@ class AnvilCustomRecipe( } fun validate(): Boolean { - return !leftItem.isAir && - (rightItem == null || !resultItem.isAir) && - !resultItem.isAir + return (leftItem != null) && !(leftItem!!.type.isAir) && (leftItem!!.amount > 0) && + //(rightItem != null) && !(rightItem!!.type.isAir) && (rightItem!!.amount > 0) && + ((rightItem == null) || (!(rightItem!!.type.isAir) && (rightItem!!.amount > 0))) && + (resultItem != null) && !(resultItem!!.type.isAir) && (resultItem!!.amount > 0) + } - fun saveToFile(writeFile: Boolean, doBackup: Boolean) { + 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.$XP_COST_CONFIG"] = xpCostPerCraft fileConfig["$name.$LEFT_ITEM_CONFIG"] = leftItem fileConfig["$name.$RIGHT_ITEM_CONFIG"] = rightItem @@ -108,32 +94,19 @@ class AnvilCustomRecipe( } @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 saveToFile(){ + saveToFile(GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE, GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE) } - fun updateFromFile() { + 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 + this.xpCostPerCraft = ConfigHolder.CUSTOM_RECIPE_HOLDER.config.getInt( + "$name.$XP_COST_CONFIG", + DEFAULT_XP_COST_CONFIG ) // Update items @@ -161,31 +134,31 @@ class AnvilCustomRecipe( CustomAnvil.verboseLog("Testing $name $leftItem") // We assume this function can be call only if leftItem != null - // Test if valid - if (!validate()) return false + // Test is 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 + 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 { + 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(!rightSimilar) return false // test if similar when not null - if (exactCount) { + 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 + }else if(item2!!.amount < rightItem!!.amount) return false // test if it has at least the amount we ask } CustomAnvil.verboseLog("Right item passed !") @@ -197,18 +170,5 @@ class AnvilCustomRecipe( 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/util/AnvilColorUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt new file mode 100644 index 0000000..277a8d1 --- /dev/null +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt @@ -0,0 +1,186 @@ +package xyz.alexcrea.cuanvil.util + +import org.bukkit.permissions.Permissible +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 + + /** + * Color a stringbuilder object depending on allowed color type and player permissions on color use type + * @return if the stringbuilder was changed and color applied + */ + fun handleColor( + textToColor: StringBuilder, + player: Permissible, + usePermission: Boolean, + allowColorCode: Boolean, + allowHexadecimalColor: Boolean, + useType: ColorUseType + ): Boolean { + if (!allowColorCode && !allowHexadecimalColor) return false + + val canUseColorCode = + allowColorCode && (!usePermission || useType.colorCodePerm == null || player.hasPermission( + useType.colorCodePerm + )) + val canUseHexColor = + allowHexadecimalColor && (!usePermission || useType.hexColorPerm == null || player.hasPermission( + useType.hexColorPerm + )) + + if ((!canUseColorCode) && (!canUseHexColor)) return false + + var useColor = false + // Handle color code + if (canUseColorCode) { + var nbReplacement = replaceAll(textToColor, "&", "§", 2) + nbReplacement -= 2 * replaceAll(textToColor, "§§", "&", 2) + + if (nbReplacement > 0) useColor = true + } + + if (canUseHexColor) { + val nbReplacement = replaceHexToColor(textToColor, 7) + + if (nbReplacement > 0) useColor = true + } + + return useColor + } + + /** + * Revert a stringbuilder to a state where applying handleColor with the same options would give the same result + * @return if the stringbuilder was changed and color unapplied + */ + fun revertColor( + colorToText: StringBuilder, + player: Permissible, + usePermission: Boolean, + allowColorCode: Boolean, + allowHexadecimalColor: Boolean, + useType: ColorUseType + ): Boolean { + if (!allowColorCode && !allowHexadecimalColor) return false + + val canUseColorCode = + allowColorCode && (!usePermission || useType.colorCodePerm == null || player.hasPermission( + useType.colorCodePerm + )) + val canUseHexColor = + allowHexadecimalColor && (!usePermission || useType.hexColorPerm == null || player.hasPermission( + useType.hexColorPerm + )) + + if ((!canUseColorCode) && (!canUseHexColor)) return false + var hasReversed = false + + // Reverse hex pattern + if (canUseHexColor) { + val nbReplacement = replaceColorToHex(colorToText, 14) + + if (nbReplacement > 0) hasReversed = true + } + + if (canUseColorCode) { + replaceAll(colorToText, "&", "&&", 1) + val nbReplacement = replaceAll(colorToText, "§", "&", 2) + + if (nbReplacement > 0) hasReversed = true + } + + return hasReversed + } + + /** + * 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): 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 ????? + + builder.replace(startIndex, startIndex + 1, "§x") + startIndex += 2 + for (i in 0..5) { + builder.insert(startIndex, '§') + startIndex += 2 + } + + numberOfChanges += 1 + } + + return numberOfChanges + } + + /** + * 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? + ) { + RENAME("ca.color.code", "ca.color.hex"), + LORE_EDIT(null, null) + } + +} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt new file mode 100644 index 0000000..dd0da1e --- /dev/null +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt @@ -0,0 +1,301 @@ +package xyz.alexcrea.cuanvil.util + +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.dependency.DependencyManager +import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil +import xyz.alexcrea.cuanvil.util.config.LoreEditType +import java.util.concurrent.atomic.AtomicInteger + +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, + xpCost: AtomicInteger + ): ItemStack? { + if (!hasLoreEditByBookPermission(player)) return null + + val result = first.clone() + val meta = result.itemMeta ?: return null + val lore = if (meta.hasLore()) { + ArrayList(meta.lore!!) + } else ArrayList() + + val page = book.pages[0] + val lines = ArrayList(page.split("\n")) + val colorCost = colorLines(player, lines, LoreEditType.APPEND_BOOK) + + lore.addAll(lines) + + meta.lore = lore + result.itemMeta = meta + + if (result == first) return null + + // Handle xp + xpCost.addAndGet(colorCost) // Cost of using color + xpCost.addAndGet(lines.size * LoreEditType.APPEND_BOOK.perLineCost) // per line cost + xpCost.addAndGet(baseEditLoreXpCost(first, result, LoreEditType.APPEND_BOOK)) // Fixed cost and work penalty + + return result + } + + fun handleLoreRemoveByBook(player: Permissible, first: ItemStack, xpCost: AtomicInteger): ItemStack? { + if (!hasLoreEditByBookPermission(player)) return null + + // remove lore + val result = first.clone() + val leftMeta = result.itemMeta ?: return null + val currentLore: ArrayList = 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 + xpCost.addAndGet(uncolorCost) + xpCost.addAndGet(currentLore.size * LoreEditType.REMOVE_BOOK.perLineCost) + xpCost.addAndGet(baseEditLoreXpCost(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, xpCost: AtomicInteger): ItemStack? { + val bookType = bookLoreEditIsAppend(first, second) ?: return null + + val meta = second.itemMeta as BookMeta + return if (bookType) handleLoreAppendByBook(player, first, meta, xpCost) + else handleLoreRemoveByBook(player, first, xpCost) + } + + // 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, + xpCost: AtomicInteger + ): ItemStack? { + if (!hasLoreEditByPaperPermission(player)) return null + + val result = first.clone() + val meta = result.itemMeta ?: return null + val lore = if (meta.hasLore()) { + ArrayList(meta.lore!!) + } else ArrayList() + + val appendEnd = LoreEditConfigUtil.paperLoreOrderIsEnd + + // A bit overdone to color 1 line but hey + val tempList = ArrayList(1) + tempList.add(second.itemMeta!!.displayName) + val colorCost = colorLines(player, tempList, LoreEditType.APPEND_PAPER) + + val line = tempList[0] + if (appendEnd) + lore.add(line) + else + lore.add(0, line) + + meta.lore = lore + result.itemMeta = meta + + if (result == first) return null + + // Handle xp + xpCost.addAndGet(colorCost) + xpCost.addAndGet(baseEditLoreXpCost(first, result, LoreEditType.APPEND_PAPER)) + + return result + } + + fun handleLoreRemoveByPaper(player: Permissible, first: ItemStack, xpCost: AtomicInteger): ItemStack? { + if (!hasLoreEditByPaperPermission(player)) return null + + // remove lore line + val result = first.clone() + val meta = result.itemMeta!! + + val removeEnd = LoreEditConfigUtil.paperLoreOrderIsEnd + val lore: ArrayList = 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.lore ?: emptyList()) + finalLore.addAll(lore) + + meta.lore = finalLore + result.itemMeta = meta + if (result == first) return null + + // Get color cost to uncolor this line + val tempList = ArrayList(1) + tempList.add(line) + val uncolorCost = uncolorLines(player, tempList, LoreEditType.REMOVE_PAPER) + + // Handle other xp + xpCost.addAndGet(uncolorCost) + xpCost.addAndGet(baseEditLoreXpCost(first, result, LoreEditType.REMOVE_PAPER)) + + return result + } + + fun tryLoreEditByPaper( + player: HumanEntity, + first: ItemStack, + second: ItemStack, + xpCost: AtomicInteger + ): ItemStack? { + val bookType = paperLoreEditIsAppend(first, second) ?: return null + + return if (bookType) handleLoreAppendByPaper(player, first, second, xpCost) + else handleLoreRemoveByPaper(player, first, xpCost) + } + + private fun baseEditLoreXpCost( + first: ItemStack, + result: ItemStack, + editType: LoreEditType + ): Int { + var xpCost = editType.fixedCost + + xpCost += AnvilXpUtil.calculatePenalty(first, null, result, editType.useType) + return xpCost + } + + private fun colorLines(player: Permissible, lines: ArrayList, editType: LoreEditType): Int { + val canUseHex = editType.allowHexColor + val canUseColorCode = editType.allowColorCode + val colorCost = editType.useColorCost + + // Now handle color of each lines + var hasUsedColor = false + for ((index, line) in lines.withIndex()) { + val coloredLine = StringBuilder(line) + + val lineUsedColor = AnvilColorUtil.handleColor( + coloredLine, + player, + false, canUseColorCode, canUseHex, + AnvilColorUtil.ColorUseType.LORE_EDIT + ) + + if (lineUsedColor) { + hasUsedColor = true + lines[index] = coloredLine.toString() + } + } + + return if (hasUsedColor) { + colorCost + } else { + 0 + } + } + + fun uncolorLines(player: Permissible, lines: ArrayList, editType: LoreEditType): Int { + if (!editType.shouldRemoveColorOnLoreRemoval) return 0 + + // Now handle color of each lines + var hasUndidColor = false + for ((index, line) in lines.withIndex()) { + val uncoloredLine = StringBuilder(line) + + val lineUndidColor = AnvilColorUtil.revertColor( + uncoloredLine, + player, + false, true, true, + AnvilColorUtil.ColorUseType.LORE_EDIT + ) + + if (lineUndidColor) { + hasUndidColor = true + lines[index] = uncoloredLine.toString() + } + } + + return if (hasUndidColor) { + editType.removeColorCost + } else { + 0 + } + } + +} \ 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/util/AnvilUseType.kt similarity index 66% rename from src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilUseType.kt rename to src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilUseType.kt index 67782f3..d17e908 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilUseType.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilUseType.kt @@ -1,60 +1,60 @@ -package xyz.alexcrea.cuanvil.anvil +package xyz.alexcrea.cuanvil.util import org.bukkit.Material -import xyz.alexcrea.cuanvil.config.WorkPenaltyType -import xyz.alexcrea.cuanvil.util.anvil.AnvilUseTypeUtil +import xyz.alexcrea.cuanvil.config.WorkPenaltyType.WorkPenaltyPart +import xyz.alexcrea.cuanvil.util.config.LoreEditType enum class AnvilUseType( val typeName: String, val path: String, - val defaultPenalty: WorkPenaltyType.WorkPenaltyPart, + val defaultPenalty: WorkPenaltyPart, val displayName: String, val displayMat: Material ) { RENAME_ONLY( "rename_only", - WorkPenaltyType.WorkPenaltyPart(false, true), + WorkPenaltyPart(false, true), "Rename Only", Material.NAME_TAG ), MERGE( "merge", - WorkPenaltyType.WorkPenaltyPart(true, true), + WorkPenaltyPart(true, true), "Merge", Material.ANVIL ), UNIT_REPAIR( "unit_repair", - WorkPenaltyType.WorkPenaltyPart(true, true), + WorkPenaltyPart(true, true), "Unit Repair", Material.DIAMOND ), CUSTOM_CRAFT( "custom_craft", - WorkPenaltyType.WorkPenaltyPart(false, false), + 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), + 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), + 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), + 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), + WorkPenaltyPart(false, false), "Paper Remove", Material.WRITABLE_BOOK ), ; constructor( typeName: String, - defaultPenalty: WorkPenaltyType.WorkPenaltyPart, + defaultPenalty: WorkPenaltyPart, displayName: String, displayMat: Material ) : this( diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilUseTypeUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilUseTypeUtil.kt similarity index 96% rename from src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilUseTypeUtil.kt rename to src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilUseTypeUtil.kt index a9c7f39..c72a35a 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilUseTypeUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilUseTypeUtil.kt @@ -1,4 +1,4 @@ -package xyz.alexcrea.cuanvil.util.anvil +package xyz.alexcrea.cuanvil.util import io.delilaheve.util.ConfigOptions diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilXpUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilXpUtil.kt similarity index 59% rename from src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilXpUtil.kt rename to src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilXpUtil.kt index 4846f31..9220ee3 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilXpUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilXpUtil.kt @@ -1,4 +1,4 @@ -package xyz.alexcrea.cuanvil.util.anvil +package xyz.alexcrea.cuanvil.util import io.delilaheve.CustomAnvil import io.delilaheve.util.ConfigOptions @@ -14,59 +14,46 @@ 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 +import kotlin.math.min 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( + fun setAnvilInvXp( inventory: AnvilInventory, view: InventoryView, player: HumanEntity, anvilCost: Int, ignoreRules: Boolean = false ) { - val maximumRepairCost = maximumXpCost(ignoreRules) + // Test repair cost limit + val finalAnvilCost = if ( + !ignoreRules && + !ConfigOptions.doRemoveCostLimit && + ConfigOptions.doCapCost + ) { + min(anvilCost, ConfigOptions.maxAnvilCost) + } else { + anvilCost + } + + val maximumRepairCost = + if (ConfigOptions.doRemoveCostLimit || ignoreRules) { + Int.MAX_VALUE + } else { + ConfigOptions.maxAnvilCost + 1 + } // Try first just in case another plugin, or the test need this inventory.maximumRepairCost = maximumRepairCost - inventory.repairCost = anvilCost + inventory.repairCost = finalAnvilCost // TODO for 2.x.x use anvil view & set directly there /* Because Minecraft likes to have the final say in the repair cost displayed @@ -77,65 +64,21 @@ object AnvilXpUtil { ) { // retry after a tick inventory.maximumRepairCost = maximumRepairCost - inventory.repairCost = anvilCost + inventory.repairCost = finalAnvilCost // 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 + (finalAnvilCost >= 40) && + finalAnvilCost < 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() } } @@ -185,16 +128,6 @@ object AnvilXpUtil { 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}") } @@ -226,8 +159,10 @@ object AnvilXpUtil { * Function to calculate right enchantment values * it include enchantment placed on final item and conflicting enchantment */ - fun getRightValues(right: ItemStack, result: ItemStack, cost: AnvilCost) { + fun getRightValues(right: ItemStack, result: ItemStack): Int { // Calculate right value and illegal enchant penalty + var illegalPenalty = 0 + var rightValue = 0 val rightIsFormBook = right.isEnchantedBook() val resultEnchs = result.findEnchantments() @@ -245,7 +180,7 @@ object AnvilXpUtil { resultEnchsKeys.remove(enchantment.key) if (ConflictType.ENCHANTMENT_CONFLICT == conflictType) { - cost.illegalPenalty += ConfigOptions.sacrificeIllegalCost + illegalPenalty += ConfigOptions.sacrificeIllegalCost CustomAnvil.verboseLog("Big conflict. Adding illegal price penalty") } continue @@ -256,53 +191,16 @@ object AnvilXpUtil { 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 + rightValue += value } CustomAnvil.log( "Calculated right values: " + - "rightValue: ${cost.enchantment}, " + - "illegalPenalty: ${cost.illegalPenalty}" + "rightValue: $rightValue, " + + "illegalPenalty: $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() - } + return rightValue + illegalPenalty } } \ 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 index 058b25a..3ec5e71 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/CustomRecipeUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/CustomRecipeUtil.kt @@ -41,7 +41,7 @@ object CustomRecipeUtil { else { // test amount val resultItem = recipe.resultItem!! // we know exist as the recipe was returned to us - val maxResultAmount = resultItem.maxStackSize/resultItem.amount + val maxResultAmount = resultItem.type.maxStackSize/resultItem.amount val maxLeftAmount = leftItem.amount/recipe.leftItem!!.amount val maxRightAmount = if(rightItem == null){ maxLeftAmount } else{ rightItem.amount/recipe.rightItem!!.amount } 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 index 8463e27..2047e79 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/UnitRepairUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/UnitRepairUtil.kt @@ -3,7 +3,6 @@ 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 { @@ -23,7 +22,7 @@ object UnitRepairUtil { if (other == null) return null val config = ConfigHolder.UNIT_REPAIR_HOLDER.config // Get configuration section if exist - val otherName = other.customType.key.lowercase() + val otherName = other.type.name.lowercase() var section = config.getConfigurationSection(otherName) if (section == null) { section = config.getConfigurationSection(otherName.uppercase()) @@ -45,7 +44,7 @@ object UnitRepairUtil { * 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 itemName = item.type.name.lowercase() val repairValue = if (section.isDouble(itemName)) { section.getDouble(itemName) } else if (section.isDouble(itemName.uppercase())) { 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/config/LoreEditConfigUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditConfigUtil.kt index 9d0eb6a..f5758dc 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditConfigUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditConfigUtil.kt @@ -17,9 +17,9 @@ object LoreEditConfigUtil { // 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_ON_LORE_REMOVE = "remove_color_on_remove" const val REMOVE_COLOR_COST = "remove_color_cost" // Lore order config path @@ -42,9 +42,9 @@ object LoreEditConfigUtil { // 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_ON_LORE_REMOVE = false const val DEFAULT_REMOVE_COLOR_COST = 0 // Lore order config default diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditType.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditType.kt index c094c71..ed5ef1b 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditType.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditType.kt @@ -1,16 +1,16 @@ package xyz.alexcrea.cuanvil.util.config -import xyz.alexcrea.cuanvil.anvil.AnvilUseType +import xyz.alexcrea.cuanvil.util.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_REMOVE_COLOR_ON_LORE_REMOVE 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.REMOVE_COLOR_ON_LORE_REMOVE 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 @@ -18,23 +18,20 @@ 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), + APPEND_BOOK(AnvilUseType.LORE_EDIT_BOOK_APPEND, true, true), + REMOVE_BOOK(AnvilUseType.LORE_EDIT_BOOK_REMOVE, false, true), + APPEND_PAPER(AnvilUseType.LORE_EDIT_PAPER_APPEND, true, false), + REMOVE_PAPER(AnvilUseType.LORE_EDIT_PAPER_REMOVE, false, false), ; constructor( useType: AnvilUseType, - isPaper: Boolean, isAppend: Boolean, isMultiLine: Boolean, - ) : this(useType.path, useType, - isPaper, isAppend, isMultiLine) + ) : this(useType.path, useType, isAppend, isMultiLine) /** * If this edit type is enabled @@ -82,35 +79,27 @@ enum class LoreEditType( } /** - * Allow usage or removal of color code + * Allow usage of color code on lore add */ val allowColorCode: Boolean get() { + if (!isAppend) throw IllegalStateException("Can only call with an append edit type") return CONFIG .config .getBoolean("$rootPath.$ALLOW_COLOR_CODE", DEFAULT_ALLOW_COLOR_CODE) } /** - * Allow usage or removal of hexadecimal color + * Allow usage of hexadecimal color on lore add */ val allowHexColor: Boolean get() { + if (!isAppend) throw IllegalStateException("Can only call with an append edit type") 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 */ @@ -125,6 +114,17 @@ enum class LoreEditType( } + /** + * Should the color code & hex color should get removed on lore remove + */ + val shouldRemoveColorOnLoreRemoval: Boolean + get() { + if (isAppend) throw IllegalStateException("Can only call with a remove edit type") + return CONFIG + .config + .getBoolean("${rootPath}.$REMOVE_COLOR_ON_LORE_REMOVE", DEFAULT_REMOVE_COLOR_ON_LORE_REMOVE) + } + /** * Cost when using either color code and hex color on lore remove */ 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/resources/config.yml b/src/main/resources/config.yml index 7d6e396..0bad067 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,21 +1,8 @@ # -# It is recommended that you use /configanvil to edit most of these config. +# 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: @@ -72,24 +59,8 @@ sacrifice_illegal_enchant_cost: 1 # # 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. # @@ -101,23 +72,10 @@ permission_needed_for_color: true # 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 +# Default limit to apply to any enchants missing from enchant_limits # -# 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 values include 1 to 1000 +default_limit: 5 # Override limits for specific enchants # @@ -125,8 +83,7 @@ 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 @@ -308,20 +265,11 @@ enchant_values: # 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) + # Sharpness is set to -1. it equivalent to it not being set to anything (and work as vanilla) 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: @@ -344,12 +292,9 @@ lore_edit: # # 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 + allow_hexadecimal_color: true + use_cost: 0 remove: # If removing lore using book & quil is enabled @@ -364,25 +309,16 @@ lore_edit: shared_additive: false # If removing the lore consume the book & quil do_consume: false + # If the color should get back to color code or hex format + remove_color_on_remove: true # 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 + order: "end" append_line: # If adding lore line using paper is enabled @@ -399,12 +335,8 @@ lore_edit: # # 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 + allow_hexadecimal_color: true color_use_cost: 0 remove_line: @@ -418,47 +350,10 @@ lore_edit: shared_additive: false # If removing the lore line consume the paper do_consume: false + # If the color should get back to color code or hex format + remove_color_on_remove: true # 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 @@ -466,4 +361,10 @@ debug_log: false # Whether to show verbose debug logging debug_log_verbose: false +# In case something when wrong with CustomAnvil packet manager. +# If you see "missing class exception" or similar you may test this. +# If enabled and Protocolib absent or disabled "Replace to expensive" will not work. +# ProtocoLib may also be used if the server is in an "unsupported" version even if this option is disabled. +force_protocolib: false + configVersion: 1.11.0 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..0e8b3f3 100644 --- a/src/main/resources/enchant_conflict.yml +++ b/src/main/resources/enchant_conflict.yml @@ -92,10 +92,6 @@ 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 ] diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index dab9997..0e58169 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -10,10 +10,6 @@ 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 @@ -40,9 +36,6 @@ permissions: 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 @@ -53,9 +46,6 @@ permissions: 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 @@ -63,11 +53,6 @@ permissions: 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 @@ -80,4 +65,3 @@ softdepend: - eco - ExcellentEnchants - HavenBags - - SuperEnchants diff --git a/src/test/java/io/delilaheve/CustomAnvilTests.java b/src/test/java/io/delilaheve/CustomAnvilTests.java index 12e1ec1..45ecb7c 100644 --- a/src/test/java/io/delilaheve/CustomAnvilTests.java +++ b/src/test/java/io/delilaheve/CustomAnvilTests.java @@ -8,15 +8,11 @@ public class CustomAnvilTests extends DefaultCustomAnvilTest { @Test public void simpleInitTest() { - try { - Assertions.assertNotNull(server); - Assertions.assertNotNull(plugin); + Assertions.assertNotNull(server); + Assertions.assertNotNull(plugin); - // Test shutdown - plugin.onDisable(); - } catch (Exception e) { - Assertions.fail(e); - } + // Test shutdown + plugin.onDisable(); } } diff --git a/src/test/java/io/delilaheve/util/EnchantmentUtilTests.java b/src/test/java/io/delilaheve/util/EnchantmentUtilTests.java index 10ea252..48efc6b 100644 --- a/src/test/java/io/delilaheve/util/EnchantmentUtilTests.java +++ b/src/test/java/io/delilaheve/util/EnchantmentUtilTests.java @@ -88,16 +88,16 @@ public class EnchantmentUtilTests extends ConfigResetCustomAnvilTest { ); // Test with no permission - nullResultData.executeTest(anvil, player); - nullResultData2.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData2); // Add permission PermissionAttachment attachment = player.addAttachment(plugin); attachment.setPermission(permission, true); // Test with new permission - legalResultData.executeTest(anvil, player); - legalResultData2.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData2); } @Test @@ -161,24 +161,24 @@ public class EnchantmentUtilTests extends ConfigResetCustomAnvilTest { ); // Test failing result first - nullResultData2.executeTest(anvil, player); - nullResultData3.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData2); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData3); // Test working sharpness 2 - legalResultData.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData); // Set merge limit to 2 & test ConfigHolder.DEFAULT_CONFIG.getConfig().set("disable-merge-over.minecraft:sharpness", 1); - nullResultData.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData); // 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); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData2); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData3); } } diff --git a/src/test/java/xyz/alexcrea/cuanvil/anvil/AnvilFuseTests.java b/src/test/java/xyz/alexcrea/cuanvil/anvil/AnvilFuseTests.java index 19f1d6f..60df37e 100644 --- a/src/test/java/xyz/alexcrea/cuanvil/anvil/AnvilFuseTests.java +++ b/src/test/java/xyz/alexcrea/cuanvil/anvil/AnvilFuseTests.java @@ -67,7 +67,7 @@ public class AnvilFuseTests extends SharedCustomAnvilTest { 5 ); - data.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, data); } @Test @@ -87,7 +87,7 @@ public class AnvilFuseTests extends SharedCustomAnvilTest { 5 ); - data.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, data); } @Test @@ -101,7 +101,7 @@ public class AnvilFuseTests extends SharedCustomAnvilTest { null ); - data.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, data); } // Note: currently anvil can only have null name. maybe handle differently later @@ -117,10 +117,10 @@ public class AnvilFuseTests extends SharedCustomAnvilTest { AnvilFuseTestData data = new AnvilFuseTestData( base, null, expected, expected, null, - 1, null, 1 + 1, 1, null ); - data.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, data); } } diff --git a/src/test/java/xyz/alexcrea/cuanvil/anvil/LoreEditTests.java b/src/test/java/xyz/alexcrea/cuanvil/anvil/LoreEditTests.java index 668da58..ebfb84f 100644 --- a/src/test/java/xyz/alexcrea/cuanvil/anvil/LoreEditTests.java +++ b/src/test/java/xyz/alexcrea/cuanvil/anvil/LoreEditTests.java @@ -29,11 +29,9 @@ 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 AnvilInventory anvil; private static PlayerMock player; private static final String COLORED_LORE_LINE = "§x§1§2§3§4§5§6TEST §atest"; @@ -291,9 +289,9 @@ public class LoreEditTests extends SharedCustomAnvilTest { 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_ON_LORE_REMOVE, false); ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.REMOVE_COLOR_COST, 0); } @@ -439,6 +437,7 @@ public class LoreEditTests extends SharedCustomAnvilTest { 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); + ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.REMOVE_COLOR_ON_LORE_REMOVE, true); TestDataContainer singleLData = singleLineTypeToTest.get(type); TestDataContainer multiLData = multiLineTypeToTest.get(type); @@ -482,6 +481,8 @@ public class LoreEditTests extends SharedCustomAnvilTest { @ParameterizedTest @MethodSource("onlyRemoveTypes") public void testColorRemoveEnabled(LoreEditType type) { + ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.REMOVE_COLOR_ON_LORE_REMOVE, true); + TestDataContainer singleLData = singleLineTypeToTest.get(type); TestDataContainer multiLData = multiLineTypeToTest.get(type); @@ -617,6 +618,6 @@ public class LoreEditTests extends SharedCustomAnvilTest { ).executeTest(anvil, player); } - //TODO work penalty test*/ + //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 index d9ff329..2b57bda 100644 --- a/src/test/java/xyz/alexcrea/cuanvil/api/AnvilRecipeBuilderTest.java +++ b/src/test/java/xyz/alexcrea/cuanvil/api/AnvilRecipeBuilderTest.java @@ -12,15 +12,10 @@ 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 @@ -43,7 +38,6 @@ public class AnvilRecipeBuilderTest extends SharedOnlyMockBukkit { .setResultItem(new ItemStack(Material.STICK)); assertNotNull(builder.build()); - assertNotNull(builder2.build()); } @Test @@ -69,39 +63,23 @@ public class AnvilRecipeBuilderTest extends SharedOnlyMockBukkit { @Test void setXpCostPerCraft(){ - assertEquals(0, builder2.getLevelCostPerCraft()); - assertEquals(0, builder2.build().getLevelCostPerCraft()); - builder2.setLevelCostPerCraft(2); - assertEquals(2, builder2.getLevelCostPerCraft()); - assertEquals(2, builder2.build().getLevelCostPerCraft()); + assertEquals(1, builder.getXpCostPerCraft()); + builder.setXpCostPerCraft(2); + assertEquals(2, builder.getXpCostPerCraft()); } - @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()); + assertTrue(builder.isExactCount()); + builder.setExactCount(false); + assertFalse(builder.isExactCount()); } @Test void setName(){ - assertEquals("test", builder2.getName()); - assertEquals("test", builder2.build().getName()); - builder2.setName("other"); - assertEquals("other", builder2.getName()); - assertEquals("other", builder2.build().getName()); + assertEquals("test", builder.getName()); + builder.setName("other"); + assertEquals("other", builder.getName()); } } diff --git a/src/test/java/xyz/alexcrea/cuanvil/api/ConflictApiTests.java b/src/test/java/xyz/alexcrea/cuanvil/api/ConflictApiTests.java index 1a9a256..b1d7564 100644 --- a/src/test/java/xyz/alexcrea/cuanvil/api/ConflictApiTests.java +++ b/src/test/java/xyz/alexcrea/cuanvil/api/ConflictApiTests.java @@ -71,7 +71,7 @@ public class ConflictApiTests extends ConfigResetCustomAnvilTest { Assertions.assertNotNull(sharpness); // Testing default conflict (illegal item should not be produced) - nullResultData.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData); // Try to find & remove conflict EnchantConflictGroup conflict = findGroup("sword_enchant_conflict"); @@ -79,7 +79,7 @@ public class ConflictApiTests extends ConfigResetCustomAnvilTest { // Test what happen when we remove the conflict (illegal item should be allowed) ConflictAPI.removeConflict(conflict); - legalResultData.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData); // We create and add a new conflict ConflictBuilder builder = new ConflictBuilder("sword_enchant_conflict"); @@ -88,11 +88,11 @@ public class ConflictApiTests extends ConfigResetCustomAnvilTest { // Nothing should change as it is not new: it was previously deleted Assertions.assertFalse(builder.registerIfNew()); - legalResultData.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData); // Now the conflict should be registered and conflict should exist Assertions.assertTrue(builder.registerIfAbsent()); - nullResultData.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData); } @Test diff --git a/src/test/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApiTests.java b/src/test/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApiTests.java index 651b873..3ebdd7c 100644 --- a/src/test/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApiTests.java +++ b/src/test/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApiTests.java @@ -1,7 +1,6 @@ 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; @@ -12,11 +11,10 @@ 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 xyz.alexcrea.cuanvil.util.AnvilFuseTestUtil; import static org.junit.jupiter.api.Assertions.*; @@ -59,14 +57,14 @@ public class CustomAnvilRecipeApiTests extends ConfigResetCustomAnvilTest { ); // Testing default conflict (no recipe exist) - nullResultData.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData); // Add and test recipe AnvilRecipeBuilder builder = new AnvilRecipeBuilder(recipeName); - builder.setExactCount(true).setLeftItem(stick).setResultItem(stick).setLevelCostPerCraft(2); + builder.setExactCount(true).setLeftItem(stick).setResultItem(stick).setXpCostPerCraft(2); assertTrue(builder.registerIfAbsent()); - legalResultData.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData); AnvilCustomRecipe recipe = getByName(recipeName); assertNotNull(recipe); @@ -74,21 +72,21 @@ public class CustomAnvilRecipeApiTests extends ConfigResetCustomAnvilTest { // Remove recipe assertTrue(CustomAnvilRecipeApi.removeRecipe(recipe)); assertFalse(CustomAnvilRecipeApi.removeRecipe(recipe)); - nullResultData.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData); 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); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData); recipe = getByName(recipeName); assertNull(recipe); // Try to add deleted recipe with override (should add) assertTrue(CustomAnvilRecipeApi.addRecipe(builder, true)); - legalResultData.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData); recipe = getByName(recipeName); assertNotNull(recipe); @@ -121,134 +119,25 @@ public class CustomAnvilRecipeApiTests extends ConfigResetCustomAnvilTest { null, null ); - nullResultData.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData); AnvilRecipeBuilder builder = new AnvilRecipeBuilder(recipeName); builder.setExactCount(false) .setLeftItem(stick) .setResultItem(stick2) - .setLevelCostPerCraft(2); + .setXpCostPerCraft(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 ? + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData1); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData2); } @Nullable - public static AnvilCustomRecipe getByName(String name) { + public static AnvilCustomRecipe getByName(String name){ for (AnvilCustomRecipe registeredRecipe : CustomAnvilRecipeApi.getRegisteredRecipes()) { - if (registeredRecipe.getName().contentEquals(name)) { + if(registeredRecipe.getName().contentEquals(name)){ return registeredRecipe; } } diff --git a/src/test/java/xyz/alexcrea/cuanvil/api/MaterialGroupApiTests.java b/src/test/java/xyz/alexcrea/cuanvil/api/MaterialGroupApiTests.java index 3fcafe7..164bc58 100644 --- a/src/test/java/xyz/alexcrea/cuanvil/api/MaterialGroupApiTests.java +++ b/src/test/java/xyz/alexcrea/cuanvil/api/MaterialGroupApiTests.java @@ -15,7 +15,7 @@ public class MaterialGroupApiTests extends ConfigResetCustomAnvilTest { 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.addToPolicy(Material.DIAMOND_PICKAXE); // We do not want it to be empty // Group not being set should not exist assertFalse(doGroupExist(groupName)); @@ -48,7 +48,7 @@ public class MaterialGroupApiTests extends ConfigResetCustomAnvilTest { 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.addToPolicy(Material.DIAMOND_PICKAXE); // We do not want it to be empty // Group not being set should not exist assertFalse(doGroupExist(groupName)); diff --git a/src/test/java/xyz/alexcrea/cuanvil/api/UnitRepairApiTests.java b/src/test/java/xyz/alexcrea/cuanvil/api/UnitRepairApiTests.java index adda4e1..8166797 100644 --- a/src/test/java/xyz/alexcrea/cuanvil/api/UnitRepairApiTests.java +++ b/src/test/java/xyz/alexcrea/cuanvil/api/UnitRepairApiTests.java @@ -58,7 +58,7 @@ public class UnitRepairApiTests extends ConfigResetCustomAnvilTest { 2 ); - legalResultData.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData); } @Test @@ -76,7 +76,7 @@ public class UnitRepairApiTests extends ConfigResetCustomAnvilTest { // Remove unit repair assertTrue(UnitRepairApi.removeUnitRepair(Material.DIAMOND, Material.DIAMOND_PICKAXE)); - nullResultData.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData); // see override assertFalse(UnitRepairApi.addUnitRepair(Material.DIAMOND, Material.DIAMOND_PICKAXE, 0.25)); @@ -107,12 +107,12 @@ public class UnitRepairApiTests extends ConfigResetCustomAnvilTest { 2 ); - nullResultData.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData); // Add unit repair assertTrue(UnitRepairApi.addUnitRepair(Material.STICK, Material.DIAMOND_PICKAXE)); assertFalse(UnitRepairApi.addUnitRepair(Material.STICK, Material.DIAMOND_PICKAXE)); - legalResultData.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData); } } 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/data/AnvilClickTestData.java b/src/test/java/xyz/alexcrea/cuanvil/data/AnvilClickTestData.java index 002b194..65d7ddb 100644 --- a/src/test/java/xyz/alexcrea/cuanvil/data/AnvilClickTestData.java +++ b/src/test/java/xyz/alexcrea/cuanvil/data/AnvilClickTestData.java @@ -1,11 +1,8 @@ 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, @@ -50,8 +47,4 @@ public record AnvilClickTestData( 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 index 8542d41..a01d0ab 100644 --- a/src/test/java/xyz/alexcrea/cuanvil/data/AnvilFuseTestData.java +++ b/src/test/java/xyz/alexcrea/cuanvil/data/AnvilFuseTestData.java @@ -1,10 +1,7 @@ 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, @@ -54,8 +51,4 @@ public record AnvilFuseTestData( ); } - 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 index b4f47a5..2c8ff93 100644 --- a/src/test/java/xyz/alexcrea/cuanvil/data/TestDataContainer.java +++ b/src/test/java/xyz/alexcrea/cuanvil/data/TestDataContainer.java @@ -16,17 +16,17 @@ public record TestDataContainer( ) { public void executeTest(AnvilInventory anvil, Player player) { - fuseData.executeTest(anvil, player); - if (clickData != null) clickData.executeTest(anvil, player); + executeFuseTest(anvil, player); + if (clickData != null) executeClickTest(anvil, player); } public void executeFuseTest(AnvilInventory anvil, HumanEntity player) { - fuseData.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, fuseData); } public void executeClickTest(AnvilInventory anvil, Player player) { Assertions.assertNotNull(clickData); - clickData.executeTest(anvil, player); + AnvilFuseTestUtil.executeAnvilClickTest(anvil, player, clickData); } public @NotNull TestDataContainer nullifyResult() { diff --git a/src/test/java/xyz/alexcrea/cuanvil/util/AnvilFuseTestUtil.java b/src/test/java/xyz/alexcrea/cuanvil/util/AnvilFuseTestUtil.java index 6f5c7bb..b73b884 100644 --- a/src/test/java/xyz/alexcrea/cuanvil/util/AnvilFuseTestUtil.java +++ b/src/test/java/xyz/alexcrea/cuanvil/util/AnvilFuseTestUtil.java @@ -110,60 +110,22 @@ public class AnvilFuseTestUtil { 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); - } + anvil.setItem(1, null); // We clear the right slot in case something was there + testPlacingItem(anvil, player, + 0, data.expectedPriceAfterLeftPlaced(), + data.leftItem(), data.expectedAfterLeftPlaced()); // 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); - } + anvil.setItem(0, null); // We only want the right item. so we remove the left one + testPlacingItem(anvil, player, + 1, data.expectedPriceAfterRightPlaced(), + data.rightItem(), data.expectedAfterRightPlaced()); // 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); - } + testPlacingItem(anvil, player, + 0, data.expectedPriceAfterBothPlaced(), + data.leftItem(), data.expectedResult()); } public static void executeAnvilClickTest( @@ -177,7 +139,6 @@ public class AnvilFuseTestUtil { ItemStack result = anvil.getResult(); player.setLevel(0); - player.setExp(0); player.setItemOnCursor(null); // Do a test with not enough level @@ -190,12 +151,11 @@ public class AnvilFuseTestUtil { assertEqual(null, player.getItemOnCursor()); } player.setLevel(data.levelCost()); - player.setExp(0); player.setItemOnCursor(null); simulateClick(anvil, player, data.expectedResult()); - // Should have simulated the click + // Should have similated the click assertEqual(data.leftItem(), anvil.getFirstItem()); assertEqual(data.rightItem(), anvil.getSecondItem()); assertEqual(data.resultSlotItem(), anvil.getResult()); @@ -248,7 +208,7 @@ public class AnvilFuseTestUtil { 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."); + 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); @@ -260,12 +220,12 @@ public class AnvilFuseTestUtil { } public static boolean isAir(@Nullable ItemStack item) { - return item == null || item.isEmpty() || item.getAmount() == 0; + return item == null || item.isEmpty(); } public static void assertPriceEqual(Integer expectedPrice, int price) { if (expectedPrice == null) return; - Assertions.assertEquals(expectedPrice, price, "Price of anvil fuse was wrong"); + Assertions.assertEquals(expectedPrice, price); } } diff --git a/src/test/resources/plugin.yml b/src/test/resources/plugin.yml index 37fb95a..c116cce 100644 --- a/src/test/resources/plugin.yml +++ b/src/test/resources/plugin.yml @@ -11,8 +11,6 @@ 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 @@ -39,9 +37,6 @@ permissions: 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 @@ -60,7 +55,8 @@ permissions: 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 + +# soft depend on old name (UnsafeEnchantsPlus), so I can disable it if it is on the same server (old name for this plugin) # Also depend to other plugin for compatibility softdepend: - UnsafeEnchantsPlus @@ -70,4 +66,3 @@ softdepend: - EcoEnchants - eco - ExcellentEnchants - - HavenBags