mirror of
https://github.com/alexcrea/CustomAnvil.git
synced 2026-06-23 16:16:17 +02:00
Compare commits
No commits in common. "v1.x.x" and "v1.15.7" have entirely different histories.
139 changed files with 1360 additions and 5068 deletions
94
.github/workflows/gradle.yml
vendored
94
.github/workflows/gradle.yml
vendored
|
|
@ -12,11 +12,9 @@ on:
|
||||||
branches: [ "v1.x.x", "v2.x.x" ]
|
branches: [ "v1.x.x", "v2.x.x" ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ "v1.x.x", "v2.x.x" ]
|
branches: [ "v1.x.x", "v2.x.x" ]
|
||||||
release:
|
|
||||||
types: [published]
|
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }}
|
group: ${{ github.ref }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
@ -25,10 +23,6 @@ jobs:
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
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:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Set up JDKs
|
- name: Set up JDKs
|
||||||
|
|
@ -37,41 +31,21 @@ jobs:
|
||||||
java-version: |
|
java-version: |
|
||||||
21
|
21
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
cache: gradle
|
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.
|
# 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
|
# See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: gradle/actions/setup-gradle@v5
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
- name: Make gradlew executable
|
- name: Make gradlew executable
|
||||||
run: chmod +x ./gradlew
|
run: chmod +x ./gradlew
|
||||||
|
|
||||||
- name: Get small commit hash
|
- name: Get small commit hash
|
||||||
if: ${{ github.event_name != 'release' && success() }}
|
|
||||||
run: echo "SMALL_COMMIT_HASH=$(git rev-parse --short ${{ github.sha }})" >> $GITHUB_ENV
|
run: echo "SMALL_COMMIT_HASH=$(git rev-parse --short ${{ github.sha }})" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Build with Gradle Wrapper
|
- name: Build with Gradle Wrapper
|
||||||
run: ./gradlew build --parallel --stacktrace
|
run: ./gradlew build --parallel
|
||||||
|
|
||||||
# only submit dependency on push
|
# only submit dependency on push
|
||||||
- name: Generate and submit dependency graph
|
- name: Generate and submit dependency graph
|
||||||
|
|
@ -89,7 +63,7 @@ jobs:
|
||||||
echo "ONLINE_JAR_NAME=$(basename $ONLINE_JAR_PATH)" >> $GITHUB_ENV
|
echo "ONLINE_JAR_NAME=$(basename $ONLINE_JAR_PATH)" >> $GITHUB_ENV
|
||||||
echo "OFFLINE_JAR_NAME=$(basename $OFFLINE_JAR_PATH)" >> $GITHUB_ENV
|
echo "OFFLINE_JAR_NAME=$(basename $OFFLINE_JAR_PATH)" >> $GITHUB_ENV
|
||||||
|
|
||||||
# upload the named jars as artifact
|
# upload the named jars
|
||||||
- name: Upload online JAR artifact
|
- name: Upload online JAR artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
|
|
@ -104,60 +78,4 @@ jobs:
|
||||||
|
|
||||||
- name: Summarize tests results
|
- name: Summarize tests results
|
||||||
uses: jeantessier/test-summary-action@v1
|
uses: jeantessier/test-summary-action@v1
|
||||||
if: ${{ always() }}
|
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 }}
|
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -14,9 +14,6 @@
|
||||||
/impl/*/build
|
/impl/*/build
|
||||||
/impl/*/.gradle
|
/impl/*/.gradle
|
||||||
|
|
||||||
# run folder
|
|
||||||
/run/
|
|
||||||
|
|
||||||
# other random folders
|
# other random folders
|
||||||
/htmlReport
|
/htmlReport
|
||||||
/.kotlin/errors
|
/.kotlin/errors
|
||||||
|
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
<component name="ProjectRunConfigurationManager">
|
|
||||||
<configuration default="false" name="Server" type="JarApplication">
|
|
||||||
<option name="JAR_PATH" value="$PROJECT_DIR$/run/server.jar" />
|
|
||||||
<option name="PROGRAM_PARAMETERS" value="-nogui" />
|
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/run" />
|
|
||||||
<option name="ALTERNATIVE_JRE_PATH" />
|
|
||||||
<method v="2" />
|
|
||||||
</configuration>
|
|
||||||
</component>
|
|
||||||
|
|
@ -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.
|
|
||||||
34
CREDITS.md
34
CREDITS.md
|
|
@ -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 ! *
|
|
||||||
|
|
||||||
96
README.md
96
README.md
|
|
@ -1,11 +1,18 @@
|
||||||
# Custom Anvil
|
# Custom Anvil
|
||||||
|
|
||||||
**Custom Anvil** is a plugin that allows server administrators to customize every aspect of the anvil's mechanics.
|
**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.7 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:
|
### Download Locations:
|
||||||
|
|
||||||
the plugin can be downloaded on
|
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)
|
[Hangar](https://hangar.papermc.io/alexcrea/CustomAnvil)
|
||||||
or here [on GitHub](https://github.com/alexcrea/CustomAnvil/releases/latest)
|
or here [on GitHub](https://github.com/alexcrea/CustomAnvil/releases/latest)
|
||||||
|
|
||||||
|
|
@ -14,7 +21,7 @@ the plugin can be downloaded on
|
||||||
- Vanilla like default configuration.
|
- Vanilla like default configuration.
|
||||||
- Custom enchantment level limit.
|
- Custom enchantment level limit.
|
||||||
- Custom anvil recipes.
|
- 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 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.
|
- Custom XP cost for every aspect of the anvil.
|
||||||
- Permissions to bypass level limit or enchantment restriction.
|
- Permissions to bypass level limit or enchantment restriction.
|
||||||
|
|
@ -23,63 +30,75 @@ the plugin can be downloaded on
|
||||||
- Gui to configure the plugin in game.
|
- Gui to configure the plugin in game.
|
||||||
- Support use of color code, hexadecimal color and minimessage for color/decoration
|
- Support use of color code, hexadecimal color and minimessage for color/decoration
|
||||||
- (Experimental) Folia support (gui do not work)
|
- (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:
|
### 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
|
```yml
|
||||||
# Generic and bypass permissions
|
|
||||||
ca.affected: Player with this permission will be affected by the plugin
|
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.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)
|
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.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
|
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
|
# 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
|
# usage of these permission is toggleable in basic config gui or config.yml
|
||||||
# -----------------------------------------------------------------------------
|
|
||||||
# Permissions related to use of color and minimessage
|
# 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: 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.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)
|
ca.rename.minimessage: Allow player to use minimessage formating on rename if enabled (toggleable) (only legacy compatible at the time)
|
||||||
|
|
||||||
# Permissions related to edition of the lore
|
# 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.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)
|
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
|
### Commands
|
||||||
|
```yml
|
||||||
run `/customanvil help` to get information about available commands \
|
anvilconfigreload or carl: Reload every config of this plugin
|
||||||
this only show subcommands you have permission for
|
customanvilconfig or configanvil: open a menu for administrator to edit plugin's config in game
|
||||||
|
```
|
||||||
### Supported Plugins
|
### 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
|
### Overriding Too Expensive
|
||||||
|
|
||||||
One of the configurations allow displaying price about 40 and removing 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.
|
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) \
|
Minecraft version 1.17 to latest marked as supported do not need any dependency. \
|
||||||
Any recent paper version also are supported for this feature.
|
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.
|
But you should wait for update for new version containing new enchantable item or new enchantments.
|
||||||
Else it is, likely, fine to use the current version you are ussing on a new paper version
|
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 custom enchantment plugin developers
|
||||||
For information about the API, please refer to [the Wiki](https://github.com/alexcrea/CustomAnvil/wiki) \
|
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)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -87,25 +106,12 @@ For information about the API, please refer to [the Wiki](https://github.com/ale
|
||||||
see [Here](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs)
|
see [Here](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs)
|
||||||
|
|
||||||
---
|
---
|
||||||
### Metric And Telemetry
|
Custom anvil [use bstat](https://bstats.org/plugin/bukkit/Unsafe%20Enchants%20Plus/20923) for metric. You can [disable it](https://bstats.org/getting-started) if you like.
|
||||||
Custom anvil [use bstat](https://bstats.org/plugin/bukkit/Unsafe%20Enchants%20Plus/20923)
|
|
||||||
and [faststats](https://faststats.dev/project/customanvil/minecraft-plugin) for metric and error reporting.
|
|
||||||
|
|
||||||
You can select specific telemetry or disable all in config.yml. \
|
|
||||||
You can also [disable bstat](https://bstats.org/getting-started) and [faststats](https://faststats.dev/info) in their /plugin folder if you like too.
|
|
||||||
|
|
||||||
faststats is in beta testing please report me or them any error you encounter
|
|
||||||
|
|
||||||
### Credits and Thanks
|
|
||||||
Credits and thanks can be seen [here](https://github.com/alexcrea/CustomAnvil/blob/v1.x.x/CREDITS.md)
|
|
||||||
|
|
||||||
### Planned:
|
### Planned:
|
||||||
- Better Folia support (make gui work. fix some dirty handled parts)
|
- 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
|
- More features for custom anvil craft
|
||||||
|
|
||||||
### Known issue:
|
### Known issue:
|
||||||
Most unknown registered enchantments (by unsupported custom enchantment plugin & datapacks) will not have restriction by default. Planned but no eta.
|
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)
|
|
||||||
|
|
|
||||||
220
build.gradle.kts
220
build.gradle.kts
|
|
@ -2,33 +2,26 @@ import cn.lalaki.pub.BaseCentralPortalPlusExtension
|
||||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||||
import groovy.util.Node
|
import groovy.util.Node
|
||||||
import groovy.util.NodeList
|
import groovy.util.NodeList
|
||||||
import io.papermc.hangarpublishplugin.model.HangarPublication
|
|
||||||
import io.papermc.hangarpublishplugin.model.Platforms
|
|
||||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||||
import java.io.ByteArrayOutputStream
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm") version "2.3.0"
|
kotlin("jvm") version "2.1.0"
|
||||||
java
|
java
|
||||||
id("org.jetbrains.dokka").version("1.9.20")
|
id("org.jetbrains.dokka").version("1.9.20")
|
||||||
id("com.gradleup.shadow").version("9.3.0")
|
id("com.gradleup.shadow").version("9.0.0-beta16")
|
||||||
// Maven publish
|
// Maven publish
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
signing
|
signing
|
||||||
id("cn.lalaki.central").version("1.2.8")
|
id("cn.lalaki.central").version("1.2.8")
|
||||||
// Paper
|
// Paper
|
||||||
id("io.papermc.paperweight.userdev") version "2.0.0-beta.17" apply false
|
id("io.papermc.paperweight.userdev") version "2.0.0-beta.17" apply false
|
||||||
id("io.papermc.hangar-publish-plugin") version "0.1.2"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "xyz.alexcrea"
|
group = "xyz.alexcrea"
|
||||||
version = "1.17.5"
|
version = "1.15.7"
|
||||||
|
|
||||||
val isDevBuild = System.getenv("SMALL_COMMIT_HASH") != null
|
|
||||||
val isPreRelease = System.getenv("IS_GITHUB_PRERELEASE") == "true"
|
|
||||||
|
|
||||||
val effectiveVersion = "$version" +
|
val effectiveVersion = "$version" +
|
||||||
(if (isDevBuild) "-dev-${System.getenv("SMALL_COMMIT_HASH")!!}" else "")
|
(if (System.getenv("SMALL_COMMIT_HASH") != null) "-dev-${System.getenv("SMALL_COMMIT_HASH")!!}" else "")
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
// EcoEnchants
|
// EcoEnchants
|
||||||
|
|
@ -36,18 +29,6 @@ repositories {
|
||||||
|
|
||||||
// ExcellentEnchants
|
// ExcellentEnchants
|
||||||
maven(url = "https://repo.nightexpressdev.com/releases")
|
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")
|
val reobfNMS = providers.gradleProperty("subprojects.reobfnms")
|
||||||
|
|
@ -57,9 +38,6 @@ dependencies {
|
||||||
// Spigot api
|
// Spigot api
|
||||||
compileOnly("org.spigotmc:spigot-api:1.18-R0.1-SNAPSHOT")
|
compileOnly("org.spigotmc:spigot-api:1.18-R0.1-SNAPSHOT")
|
||||||
|
|
||||||
// fast stats
|
|
||||||
implementation("dev.faststats.metrics:bukkit:0.27.0")
|
|
||||||
|
|
||||||
// minimessage
|
// minimessage
|
||||||
implementation("net.kyori:adventure-text-minimessage:4.25.0")
|
implementation("net.kyori:adventure-text-minimessage:4.25.0")
|
||||||
|
|
||||||
|
|
@ -71,17 +49,13 @@ dependencies {
|
||||||
// EnchantsSquaredRewritten
|
// EnchantsSquaredRewritten
|
||||||
compileOnly(files("libs/EnchantsSquared.jar"))
|
compileOnly(files("libs/EnchantsSquared.jar"))
|
||||||
|
|
||||||
// EcoEnchants & item
|
// EcoEnchants
|
||||||
compileOnly("com.willfp:libreforge:4.79.0:all")
|
|
||||||
compileOnly("com.willfp:eco:6.74.5")
|
|
||||||
|
|
||||||
compileOnly("com.willfp:EcoEnchants:12.11.1")
|
compileOnly("com.willfp:EcoEnchants:12.11.1")
|
||||||
|
compileOnly("com.willfp:eco:6.74.5")
|
||||||
compileOnly(project(":impl:LegacyEcoEnchant"))
|
compileOnly(project(":impl:LegacyEcoEnchant"))
|
||||||
|
|
||||||
compileOnly("com.willfp:EcoItems:5.66.0")
|
|
||||||
|
|
||||||
// ExcellentEnchants
|
// ExcellentEnchants
|
||||||
implementation(project(":impl:ExcellentEnchant5_4"))
|
implementation(project(":impl:ExcellentEnchant5_3"))
|
||||||
compileOnly("su.nightexpress.excellentenchants:Core:5.1.0") {
|
compileOnly("su.nightexpress.excellentenchants:Core:5.1.0") {
|
||||||
exclude("org.spigotmc")
|
exclude("org.spigotmc")
|
||||||
}
|
}
|
||||||
|
|
@ -100,15 +74,6 @@ dependencies {
|
||||||
// AxPlayerWarps
|
// AxPlayerWarps
|
||||||
compileOnly(files("libs/AxPlayerWarps-1.10.3.jar"))
|
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
|
// Include nms
|
||||||
implementation(project(":nms:nms-common"))
|
implementation(project(":nms:nms-common"))
|
||||||
implementation(project(":nms:nms-paper"))
|
implementation(project(":nms:nms-paper"))
|
||||||
|
|
@ -160,7 +125,7 @@ allprojects {
|
||||||
// Set target version
|
// Set target version
|
||||||
tasks.withType<JavaCompile>().configureEach {
|
tasks.withType<JavaCompile>().configureEach {
|
||||||
sourceCompatibility =
|
sourceCompatibility =
|
||||||
"16" // We aim for java 16 for minecraft 1.16.5. even if it not really supported by custom anvil.
|
"16" // We aim for java 16 for minecraft 1.16.5. even if it not really suported by custom anvil.
|
||||||
targetCompatibility = "16"
|
targetCompatibility = "16"
|
||||||
|
|
||||||
options.encoding = "UTF-8"
|
options.encoding = "UTF-8"
|
||||||
|
|
@ -168,29 +133,34 @@ allprojects {
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
compilerOptions {
|
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)
|
jvmTarget.set(JvmTarget.JVM_16)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
|
|
||||||
fun ShadowJar.configureBaseShadow(suffix: String, libraries: Array<String>) {
|
// Online jar (use of libraries)
|
||||||
val processedSuffix = if(suffix.isEmpty()) "" else "-$suffix"
|
shadowJar {
|
||||||
val name = "${rootProject.name}-${effectiveVersion}${processedSuffix}.jar"
|
// No suffix for this jar
|
||||||
|
val name = "${rootProject.name}-${effectiveVersion}.jar"
|
||||||
archiveFileName.set(name)
|
archiveFileName.set(name)
|
||||||
|
|
||||||
// Shadow necessary dependency
|
// Exclude kotlin std and its annotation
|
||||||
relocate("com.github.stefvanschie.inventoryframework", "xyz.alexcrea.cuanvil.inventoryframework")
|
exclude("**/kotlin-stdlib*.jar")
|
||||||
relocate("dev.faststats", "xyz.alexcrea.cuanvil.faststats")
|
exclude("**/annotations*.jar")
|
||||||
|
|
||||||
|
// Shadow necessary dependency
|
||||||
|
relocate("com.github.stefvanschie.inventoryframework", "xyz.alexcrea.inventoryframework")
|
||||||
|
|
||||||
|
// Replace version and example fields in plugin.yml
|
||||||
filesMatching("plugin.yml") {
|
filesMatching("plugin.yml") {
|
||||||
expand(
|
expand(
|
||||||
"version" to effectiveVersion + processedSuffix,
|
"version" to effectiveVersion,
|
||||||
"libraries" to libraries.joinToString(transform = { "\"$it\"" }),
|
"libraries" to " \"org.jetbrains.kotlin:kotlin-stdlib:2.1.0\" " +
|
||||||
|
", \"net.kyori:adventure-platform-bukkit:4.4.1\""
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -198,28 +168,36 @@ tasks {
|
||||||
dependsOn(processResources)
|
dependsOn(processResources)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Online jar (use of libraries)
|
// Offline jar (include kotlin std in the final jar fine)
|
||||||
shadowJar {
|
val offlineJar by // Shadow necessary dependency
|
||||||
configureBaseShadow("",
|
registering(
|
||||||
arrayOf(
|
|
||||||
"org.jetbrains.kotlin:kotlin-stdlib:2.3.0",
|
|
||||||
"net.kyori:adventure-text-minimessage:4.25.0",
|
|
||||||
"net.kyori:adventure-text-serializer-plain:4.25.0",
|
|
||||||
"net.kyori:adventure-text-serializer-legacy:4.25.0",
|
|
||||||
))
|
|
||||||
|
|
||||||
// Exclude kotlin std, annotations and adventure api
|
// Include all project other dependencies
|
||||||
exclude("*kotlin/**")
|
ShadowJar
|
||||||
exclude("**/annotations/**")
|
|
||||||
exclude("net/kyori/**")
|
|
||||||
}
|
|
||||||
|
|
||||||
val offlineJar by registering(ShadowJar::class) {
|
// Add custom anvil compiled
|
||||||
configureBaseShadow("offline", emptyArray())
|
::class, fun ShadowJar.() {
|
||||||
|
val name = "${rootProject.name}-${effectiveVersion}-offline.jar"
|
||||||
|
archiveFileName.set(name)
|
||||||
|
|
||||||
from(sourceSets.main.get().output)
|
// Shadow necessary dependency
|
||||||
configurations = listOf(project.configurations.runtimeClasspath.get())
|
relocate("com.github.stefvanschie.inventoryframework", "xyz.alexcrea.inventoryframework")
|
||||||
}
|
|
||||||
|
filesMatching("plugin.yml") {
|
||||||
|
expand(
|
||||||
|
"version" to "$effectiveVersion-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
|
// Make the online and offline jar on build
|
||||||
named("build") {
|
named("build") {
|
||||||
|
|
@ -355,101 +333,3 @@ publishing {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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<ShadowJar>("offlineJar")
|
|
||||||
|
|
||||||
jar.set(task.flatMap { it.archiveFile })
|
|
||||||
|
|
||||||
// Set platform versions from gradle.properties file
|
|
||||||
val versions: List<String> = (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")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -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 !
|
# 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.
|
# All anvil cost will be capped to limit_repair_value if enabled.
|
||||||
#
|
#
|
||||||
# In other words:
|
# In other words:
|
||||||
|
|
@ -77,18 +64,6 @@ allow_color_code: false
|
||||||
allow_hexadecimal_color: false
|
allow_hexadecimal_color: false
|
||||||
allow_minimessage: 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.
|
# 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 are "ca.color.code" for use of color code and "ca.color.hex" for use of hexadecimal color.
|
||||||
|
|
@ -99,23 +74,10 @@ permission_needed_for_color: true
|
||||||
# Valid values include 0 to 1000.
|
# Valid values include 0 to 1000.
|
||||||
use_of_color_cost: 0
|
use_of_color_cost: 0
|
||||||
|
|
||||||
# Dialogue rename menu make use of dialog menu to allow bigger rename
|
# Default limit to apply to any enchants missing from enchant_limits
|
||||||
# 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
|
# Valid values include 1 to 1000
|
||||||
#
|
default_limit: 5
|
||||||
# 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
|
# Override limits for specific enchants
|
||||||
#
|
#
|
||||||
|
|
@ -123,8 +85,7 @@ dialog_rename_keep_user_text: true
|
||||||
#
|
#
|
||||||
# Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels
|
# Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels
|
||||||
#
|
#
|
||||||
# Valid range of 0 - 255 for each enchantment
|
# Valid range of 1 - 255 for each enchantment
|
||||||
# -1 mean keep default
|
|
||||||
enchant_limits:
|
enchant_limits:
|
||||||
minecraft:aqua_affinity: 1
|
minecraft:aqua_affinity: 1
|
||||||
minecraft:binding_curse: 1
|
minecraft:binding_curse: 1
|
||||||
|
|
@ -306,7 +267,7 @@ enchant_values:
|
||||||
# Even if disable-merge-over of unbreaking is set to 2
|
# 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.
|
# -1 mean enchantment merge for this enchantment is not disabled. default to -1 if absent.
|
||||||
disable-merge-over:
|
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
|
minecraft:sharpness: -1
|
||||||
# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied
|
# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied
|
||||||
#minecraft:unbreaking: 2
|
#minecraft:unbreaking: 2
|
||||||
|
|
@ -430,37 +391,16 @@ lore_edit:
|
||||||
allow_hexadecimal_color: false
|
allow_hexadecimal_color: false
|
||||||
allow_minimessage: true
|
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
|
# Whether to show debug logging
|
||||||
debug_log: false
|
debug_log: false
|
||||||
|
|
||||||
# Whether to show verbose debug logging
|
# Whether to show verbose debug logging
|
||||||
debug_log_verbose: false
|
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
|
configVersion: 1.11.0
|
||||||
|
|
|
||||||
|
|
@ -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 !
|
# 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.
|
# All anvil cost will be capped to limit_repair_value if enabled.
|
||||||
#
|
#
|
||||||
# In other words:
|
# In other words:
|
||||||
|
|
@ -79,18 +66,6 @@ allow_color_code: false
|
||||||
allow_hexadecimal_color: false
|
allow_hexadecimal_color: false
|
||||||
allow_minimessage: 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.
|
# 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 are "ca.color.code" for use of color code and "ca.color.hex" for use of hexadecimal color.
|
||||||
|
|
@ -101,23 +76,10 @@ permission_needed_for_color: true
|
||||||
# Valid values include 0 to 1000.
|
# Valid values include 0 to 1000.
|
||||||
use_of_color_cost: 0
|
use_of_color_cost: 0
|
||||||
|
|
||||||
# Dialogue rename menu make use of dialog menu to allow bigger rename
|
# Default limit to apply to any enchants missing from enchant_limits
|
||||||
# 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
|
# Valid values include 1 to 1000
|
||||||
#
|
default_limit: 5
|
||||||
# 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
|
# Override limits for specific enchants
|
||||||
#
|
#
|
||||||
|
|
@ -125,8 +87,7 @@ dialog_rename_keep_user_text: true
|
||||||
#
|
#
|
||||||
# Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels
|
# Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels
|
||||||
#
|
#
|
||||||
# Valid range of 0 - 255 for each enchantment
|
# Valid range of 1 - 255 for each enchantment
|
||||||
# -1 mean keep default
|
|
||||||
enchant_limits:
|
enchant_limits:
|
||||||
minecraft:aqua_affinity: 1
|
minecraft:aqua_affinity: 1
|
||||||
minecraft:binding_curse: 1
|
minecraft:binding_curse: 1
|
||||||
|
|
@ -324,7 +285,7 @@ enchant_values:
|
||||||
# Even if disable-merge-over of unbreaking is set to 2
|
# 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.
|
# -1 mean enchantment merge for this enchantment is not disabled. default to -1 if absent.
|
||||||
disable-merge-over:
|
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
|
minecraft:sharpness: -1
|
||||||
# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied
|
# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied
|
||||||
# minecraft:unbreaking: 2
|
# minecraft:unbreaking: 2
|
||||||
|
|
@ -450,38 +411,17 @@ lore_edit:
|
||||||
allow_hexadecimal_color: false
|
allow_hexadecimal_color: false
|
||||||
allow_minimessage: true
|
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
|
# Whether to show debug logging
|
||||||
debug_log: false
|
debug_log: false
|
||||||
|
|
||||||
# Whether to show verbose debug logging
|
# Whether to show verbose debug logging
|
||||||
debug_log_verbose: false
|
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.15.5
|
configVersion: 1.15.5
|
||||||
lowMinecraftVersion: 1.21.11
|
lowMinecraftVersion: 1.21.11
|
||||||
|
|
|
||||||
|
|
@ -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 !
|
# 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.
|
# All anvil cost will be capped to limit_repair_value if enabled.
|
||||||
#
|
#
|
||||||
# In other words:
|
# In other words:
|
||||||
|
|
@ -77,18 +64,6 @@ allow_color_code: false
|
||||||
allow_hexadecimal_color: false
|
allow_hexadecimal_color: false
|
||||||
allow_minimessage: 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.
|
# 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 are "ca.color.code" for use of color code and "ca.color.hex" for use of hexadecimal color.
|
||||||
|
|
@ -99,23 +74,10 @@ permission_needed_for_color: true
|
||||||
# Valid values include 0 to 1000.
|
# Valid values include 0 to 1000.
|
||||||
use_of_color_cost: 0
|
use_of_color_cost: 0
|
||||||
|
|
||||||
# Dialogue rename menu make use of dialog menu to allow bigger rename
|
# Default limit to apply to any enchants missing from enchant_limits
|
||||||
# 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
|
# Valid values include 1 to 1000
|
||||||
#
|
default_limit: 5
|
||||||
# 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
|
# Override limits for specific enchants
|
||||||
#
|
#
|
||||||
|
|
@ -123,8 +85,7 @@ dialog_rename_keep_user_text: true
|
||||||
#
|
#
|
||||||
# Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels
|
# Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels
|
||||||
#
|
#
|
||||||
# Valid range of 0 - 255 for each enchantment
|
# Valid range of 1 - 255 for each enchantment
|
||||||
# -1 mean keep default
|
|
||||||
enchant_limits:
|
enchant_limits:
|
||||||
minecraft:aqua_affinity: 1
|
minecraft:aqua_affinity: 1
|
||||||
minecraft:binding_curse: 1
|
minecraft:binding_curse: 1
|
||||||
|
|
@ -318,7 +279,7 @@ enchant_values:
|
||||||
# Even if disable-merge-over of unbreaking is set to 2
|
# 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.
|
# -1 mean enchantment merge for this enchantment is not disabled. default to -1 if absent.
|
||||||
disable-merge-over:
|
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
|
minecraft:sharpness: -1
|
||||||
# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied
|
# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied
|
||||||
# minecraft:unbreaking: 2
|
# minecraft:unbreaking: 2
|
||||||
|
|
@ -442,38 +403,17 @@ lore_edit:
|
||||||
allow_hexadecimal_color: false
|
allow_hexadecimal_color: false
|
||||||
allow_minimessage: true
|
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
|
# Whether to show debug logging
|
||||||
debug_log: false
|
debug_log: false
|
||||||
|
|
||||||
# Whether to show verbose debug logging
|
# Whether to show verbose debug logging
|
||||||
debug_log_verbose: false
|
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
|
configVersion: 1.11.0
|
||||||
lowMinecraftVersion: 1.21.9
|
lowMinecraftVersion: 1.21.9
|
||||||
|
|
|
||||||
|
|
@ -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 !
|
# 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.
|
# All anvil cost will be capped to limit_repair_value if enabled.
|
||||||
#
|
#
|
||||||
# In other words:
|
# In other words:
|
||||||
|
|
@ -77,18 +64,6 @@ allow_color_code: false
|
||||||
allow_hexadecimal_color: false
|
allow_hexadecimal_color: false
|
||||||
allow_minimessage: 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.
|
# 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 are "ca.color.code" for use of color code and "ca.color.hex" for use of hexadecimal color.
|
||||||
|
|
@ -99,23 +74,10 @@ permission_needed_for_color: true
|
||||||
# Valid values include 0 to 1000.
|
# Valid values include 0 to 1000.
|
||||||
use_of_color_cost: 0
|
use_of_color_cost: 0
|
||||||
|
|
||||||
# Dialogue rename menu make use of dialog menu to allow bigger rename
|
# Default limit to apply to any enchants missing from enchant_limits
|
||||||
# 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
|
# Valid values include 1 to 1000
|
||||||
#
|
default_limit: 5
|
||||||
# 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
|
# Override limits for specific enchants
|
||||||
#
|
#
|
||||||
|
|
@ -123,8 +85,7 @@ dialog_rename_keep_user_text: true
|
||||||
#
|
#
|
||||||
# Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels
|
# Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels
|
||||||
#
|
#
|
||||||
# Valid range of 0 - 255 for each enchantment
|
# Valid range of 1 - 255 for each enchantment
|
||||||
# -1 mean keep default
|
|
||||||
enchant_limits:
|
enchant_limits:
|
||||||
minecraft:aqua_affinity: 1
|
minecraft:aqua_affinity: 1
|
||||||
minecraft:binding_curse: 1
|
minecraft:binding_curse: 1
|
||||||
|
|
@ -306,7 +267,7 @@ enchant_values:
|
||||||
# Even if disable-merge-over of unbreaking is set to 2
|
# 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.
|
# -1 mean enchantment merge for this enchantment is not disabled. default to -1 if absent.
|
||||||
disable-merge-over:
|
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
|
minecraft:sharpness: -1
|
||||||
# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied
|
# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied
|
||||||
# minecraft:unbreaking: 2
|
# minecraft:unbreaking: 2
|
||||||
|
|
@ -430,37 +391,16 @@ lore_edit:
|
||||||
allow_hexadecimal_color: false
|
allow_hexadecimal_color: false
|
||||||
allow_minimessage: true
|
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
|
# Whether to show debug logging
|
||||||
debug_log: false
|
debug_log: false
|
||||||
|
|
||||||
# Whether to show verbose debug logging
|
# Whether to show verbose debug logging
|
||||||
debug_log_verbose: false
|
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
|
configVersion: 1.11.0
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
### Default Plugin's Configurations
|
### 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.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 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.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)
|
From 1.21.11 use [1.21.11 configurations](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.11)
|
||||||
|
|
@ -6,8 +6,4 @@ signing.secretKeyRingFile=~/.gnupg/secring.gpg
|
||||||
kotlin.daemon.jvmargs=-Xmx8G
|
kotlin.daemon.jvmargs=-Xmx8G
|
||||||
|
|
||||||
# list of nms
|
# 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
|
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
|
|
||||||
|
|
||||||
21
impl/ExcellentEnchant5_3/build.gradle.kts
Normal file
21
impl/ExcellentEnchant5_3/build.gradle.kts
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
group = rootProject.group
|
||||||
|
version = rootProject.version
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
kotlin("jvm") version "2.1.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
// ExcellentEnchants
|
||||||
|
maven(url = "https://repo.nightexpressdev.com/releases")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// Spigot api
|
||||||
|
compileOnly("org.spigotmc:spigot-api:1.18-R0.1-SNAPSHOT")
|
||||||
|
|
||||||
|
// Excellent Enchant
|
||||||
|
compileOnly("su.nightexpress.excellentenchants:Core:5.3.0") {
|
||||||
|
exclude("org.spigotmc")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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")
|
|
||||||
}
|
|
||||||
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -2,7 +2,7 @@ group = rootProject.group
|
||||||
version = rootProject.version
|
version = rootProject.version
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm") version "2.3.0"
|
kotlin("jvm") version "2.1.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Imitate needed class and method to support legacy version of EcoEnchant
|
// Imitate needed class and method to support legacy version of EcoEnchant
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -29,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
compilerOptions {
|
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)
|
jvmTarget.set(JvmTarget.JVM_16)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package xyz.alexcrea.cuanvil.dependency.gui
|
||||||
|
|
||||||
|
import org.bukkit.inventory.InventoryView
|
||||||
|
import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil
|
||||||
|
|
||||||
|
interface ExternGuiTester {
|
||||||
|
|
||||||
|
fun getContainerClass(view: InventoryView): Class<Any>?
|
||||||
|
|
||||||
|
fun testIfGui(inventory: InventoryView): Boolean {
|
||||||
|
// container class only allow default bukkit craft view class
|
||||||
|
|
||||||
|
val clazz = getContainerClass(inventory)
|
||||||
|
return clazz != 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
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -11,7 +11,7 @@ dependencies {
|
||||||
implementation(project(":nms:nms-common"))
|
implementation(project(":nms:nms-common"))
|
||||||
|
|
||||||
// Used for nms
|
// Used for nms
|
||||||
paperweight.paperDevBundle("1.21.7-R0.1-SNAPSHOT")
|
paperweight.paperDevBundle("1.20.6-R0.1-SNAPSHOT")
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
|
@ -29,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
compilerOptions {
|
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_18)
|
jvmTarget.set(JvmTarget.JVM_18)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ class PaperPacketManager : PacketManagerBase(), PacketManager {
|
||||||
sendedAbilities.mayfly = playerAbilities.mayfly
|
sendedAbilities.mayfly = playerAbilities.mayfly
|
||||||
sendedAbilities.instabuild = instantBuild
|
sendedAbilities.instabuild = instantBuild
|
||||||
sendedAbilities.mayBuild = playerAbilities.mayBuild
|
sendedAbilities.mayBuild = playerAbilities.mayBuild
|
||||||
sendedAbilities.setFlyingSpeed(playerAbilities.getFlyingSpeed())
|
sendedAbilities.flyingSpeed = playerAbilities.flyingSpeed
|
||||||
sendedAbilities.setWalkingSpeed(playerAbilities.getWalkingSpeed())
|
sendedAbilities.walkingSpeed = playerAbilities.walkingSpeed
|
||||||
}
|
}
|
||||||
val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities)
|
val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities)
|
||||||
nmsPlayer.connection.send(packet)
|
nmsPlayer.connection.send(packet)
|
||||||
|
|
|
||||||
|
|
@ -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<HumanEntity, Component?, String?>,
|
|
||||||
val keepUserPreviousDialog: Supplier<Boolean>,
|
|
||||||
val maxLength: Supplier<Int>,
|
|
||||||
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<UUID, String>()
|
|
||||||
private val lastRenames = HashMap<UUID, String>()
|
|
||||||
|
|
||||||
|
|
||||||
private val lastLeftItem = HashMap<UUID, String>()
|
|
||||||
private val runTaskMap = HashMap<UUID, ScheduledTask>()
|
|
||||||
|
|
||||||
// For monetary cost
|
|
||||||
val hasUiOpen = HashSet<UUID>()
|
|
||||||
|
|
||||||
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<String?>): 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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<UUID, ScheduledTask>()
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -29,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
compilerOptions {
|
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)
|
jvmTarget.set(JvmTarget.JVM_16)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
compilerOptions {
|
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)
|
jvmTarget.set(JvmTarget.JVM_17)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
compilerOptions {
|
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)
|
jvmTarget.set(JvmTarget.JVM_17)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
compilerOptions {
|
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)
|
jvmTarget.set(JvmTarget.JVM_17)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
compilerOptions {
|
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)
|
jvmTarget.set(JvmTarget.JVM_17)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
compilerOptions {
|
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)
|
jvmTarget.set(JvmTarget.JVM_17)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
compilerOptions {
|
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_18)
|
jvmTarget.set(JvmTarget.JVM_18)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
compilerOptions {
|
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_18)
|
jvmTarget.set(JvmTarget.JVM_18)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
compilerOptions {
|
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_18)
|
jvmTarget.set(JvmTarget.JVM_18)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -29,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
compilerOptions {
|
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)
|
jvmTarget.set(JvmTarget.JVM_21)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
compilerOptions {
|
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)
|
jvmTarget.set(JvmTarget.JVM_21)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
compilerOptions {
|
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)
|
jvmTarget.set(JvmTarget.JVM_21)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ tasks.withType<JavaCompile>().configureEach {
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
compilerOptions {
|
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)
|
jvmTarget.set(JvmTarget.JVM_21)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ tasks.withType<JavaCompile>().configureEach {
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
compilerOptions {
|
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)
|
jvmTarget.set(JvmTarget.JVM_21)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ tasks.withType<JavaCompile>().configureEach {
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
compilerOptions {
|
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)
|
jvmTarget.set(JvmTarget.JVM_21)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ tasks.withType<JavaCompile>().configureEach {
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
compilerOptions {
|
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)
|
jvmTarget.set(JvmTarget.JVM_21)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,5 +18,5 @@ for (nmsPart in reobfNMS) {
|
||||||
// compatibility subprojects
|
// compatibility subprojects
|
||||||
include(":impl:LegacyEcoEnchant")
|
include(":impl:LegacyEcoEnchant")
|
||||||
findProject(":impl:LegacyEcoEnchant")?.name = "LegacyEcoEnchant"
|
findProject(":impl:LegacyEcoEnchant")?.name = "LegacyEcoEnchant"
|
||||||
include("impl:ExcellentEnchant5_4")
|
include("impl:ExcellentEnchant5_3")
|
||||||
findProject(":impl:ExcellentEnchant5_4")?.name = "ExcellentEnchant5_4"
|
findProject(":impl:ExcellentEnchant5_3")?.name = "ExcellentEnchant5_3"
|
||||||
|
|
@ -13,7 +13,6 @@ import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
//TODO add conflict after level
|
|
||||||
/**
|
/**
|
||||||
* A Builder for material conflict.
|
* A Builder for material conflict.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package xyz.alexcrea.cuanvil.api;
|
package xyz.alexcrea.cuanvil.api;
|
||||||
|
|
||||||
import io.delilaheve.CustomAnvil;
|
import io.delilaheve.CustomAnvil;
|
||||||
import io.delilaheve.util.ConfigOptions;
|
|
||||||
import org.bukkit.NamespacedKey;
|
import org.bukkit.NamespacedKey;
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
import org.bukkit.enchantments.Enchantment;
|
import org.bukkit.enchantments.Enchantment;
|
||||||
|
|
@ -181,13 +180,13 @@ public class EnchantmentApi {
|
||||||
private static boolean tryWriteDefaultConfig(FileConfiguration defaultConfig, CAEnchantment enchantment, boolean override) {
|
private static boolean tryWriteDefaultConfig(FileConfiguration defaultConfig, CAEnchantment enchantment, boolean override) {
|
||||||
boolean hasChange = false;
|
boolean hasChange = false;
|
||||||
|
|
||||||
String levelPath = ConfigOptions.ENCHANT_LIMIT_ROOT + "." + enchantment.getKey();
|
String levelPath = "enchant_limits." + enchantment.getKey();
|
||||||
if(override || !defaultConfig.isSet(levelPath)){
|
if(override || !defaultConfig.isSet(levelPath)){
|
||||||
defaultConfig.set(levelPath, enchantment.defaultMaxLevel());
|
defaultConfig.set(levelPath, enchantment.defaultMaxLevel());
|
||||||
hasChange = true;
|
hasChange = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
String basePath = ConfigOptions.ENCHANT_VALUES_ROOT + "." + enchantment.getKey();
|
String basePath = "enchant_values." + enchantment.getKey();
|
||||||
EnchantmentRarity rarity = enchantment.defaultRarity();
|
EnchantmentRarity rarity = enchantment.defaultRarity();
|
||||||
|
|
||||||
String itemPath = basePath + ".item";
|
String itemPath = basePath + ".item";
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package xyz.alexcrea.cuanvil.api;
|
||||||
import io.delilaheve.CustomAnvil;
|
import io.delilaheve.CustomAnvil;
|
||||||
import io.delilaheve.util.ConfigOptions;
|
import io.delilaheve.util.ConfigOptions;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.NamespacedKey;
|
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
@ -124,7 +123,7 @@ public class MaterialGroupApi {
|
||||||
FileConfiguration config = ConfigHolder.ITEM_GROUP_HOLDER.getConfig();
|
FileConfiguration config = ConfigHolder.ITEM_GROUP_HOLDER.getConfig();
|
||||||
|
|
||||||
String basePath = group.getName() + ".";
|
String basePath = group.getName() + ".";
|
||||||
Set<NamespacedKey> materialSet = group.getNonGroupInheritedMaterials();
|
Set<Material> materialSet = group.getNonGroupInheritedMaterials();
|
||||||
Set<AbstractMaterialGroup> groupSet = group.getGroups();
|
Set<AbstractMaterialGroup> groupSet = group.getGroups();
|
||||||
|
|
||||||
boolean empty = true;
|
boolean empty = true;
|
||||||
|
|
@ -154,7 +153,7 @@ public class MaterialGroupApi {
|
||||||
FileConfiguration config = ConfigHolder.ITEM_GROUP_HOLDER.getConfig();
|
FileConfiguration config = ConfigHolder.ITEM_GROUP_HOLDER.getConfig();
|
||||||
|
|
||||||
String basePath = group.getName() + ".";
|
String basePath = group.getName() + ".";
|
||||||
Set<NamespacedKey> materials = group.getMaterials();
|
EnumSet<Material> materials = group.getMaterials();
|
||||||
|
|
||||||
if (materials.isEmpty()) return false;
|
if (materials.isEmpty()) return false;
|
||||||
|
|
||||||
|
|
@ -164,8 +163,8 @@ public class MaterialGroupApi {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<String> materialSetToStringList(@NotNull Set<NamespacedKey> materials) {
|
public static List<String> materialSetToStringList(@NotNull Set<Material> materials) {
|
||||||
return materials.stream().map(NamespacedKey::toString).toList();
|
return materials.stream().map(material -> material.getKey().getKey().toLowerCase()).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<String> materialGroupSetToStringList(@NotNull Set<AbstractMaterialGroup> groups) {
|
public static List<String> materialGroupSetToStringList(@NotNull Set<AbstractMaterialGroup> groups) {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ import org.jetbrains.annotations.NotNull;
|
||||||
* Most of the time you would likely need {@link CAPreAnvilBypassEvent} or {@link CAEarlyPreAnvilBypassEvent}
|
* Most of the time you would likely need {@link CAPreAnvilBypassEvent} or {@link CAEarlyPreAnvilBypassEvent}
|
||||||
* for this event to be useful.
|
* for this event to be useful.
|
||||||
* <p>
|
* <p>
|
||||||
* There is also {@link CATreatAnvilResult2Event} that may be better for some use case.
|
* There is also {@link CATreatAnvilResultEvent} that may be better for some use case.
|
||||||
*/
|
*/
|
||||||
public class CAClickResultBypassEvent extends Event implements Cancellable {
|
public class CAClickResultBypassEvent extends Event implements Cancellable {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import org.jetbrains.annotations.NotNull;
|
||||||
* <p>
|
* <p>
|
||||||
* You should also use {@link CAClickResultBypassEvent} if you want to use this event for something useful.
|
* You should also use {@link CAClickResultBypassEvent} if you want to use this event for something useful.
|
||||||
* <p>
|
* <p>
|
||||||
* It is also recommended that you read about {@link CAPreAnvilBypassEvent} and {@link CATreatAnvilResult2Event}
|
* It is also recommended that you read about {@link CAPreAnvilBypassEvent} and {@link CATreatAnvilResultEvent}
|
||||||
* as your use case may be more prone to use theses.
|
* as your use case may be more prone to use theses.
|
||||||
*/
|
*/
|
||||||
public class CAEarlyPreAnvilBypassEvent extends Event implements Cancellable {
|
public class CAEarlyPreAnvilBypassEvent extends Event implements Cancellable {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ import org.jetbrains.annotations.NotNull;
|
||||||
* <p>
|
* <p>
|
||||||
* You should also use {@link CAClickResultBypassEvent} if you want to use this event for something useful.
|
* You should also use {@link CAClickResultBypassEvent} if you want to use this event for something useful.
|
||||||
* <p>
|
* <p>
|
||||||
* It is also recommended that you read about {@link CAEarlyPreAnvilBypassEvent} and {@link CATreatAnvilResult2Event}
|
* It is also recommended that you read about {@link CAEarlyPreAnvilBypassEvent} and {@link CATreatAnvilResultEvent}
|
||||||
* as your use case may be more prone to use theses.
|
* as your use case may be more prone to use theses.
|
||||||
*/
|
*/
|
||||||
public class CAPreAnvilBypassEvent extends Event implements Cancellable {
|
public class CAPreAnvilBypassEvent extends Event implements Cancellable {
|
||||||
|
|
|
||||||
|
|
@ -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.
|
|
||||||
* <p>
|
|
||||||
* You may also want to check {@link CAClickResultBypassEvent},
|
|
||||||
* {@link CAPreAnvilBypassEvent}
|
|
||||||
* and {@link CAEarlyPreAnvilBypassEvent} for your use case
|
|
||||||
* <p>
|
|
||||||
* 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.
|
|
||||||
* <p>
|
|
||||||
* 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
|
|
||||||
* <p>
|
|
||||||
* 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
|
|
||||||
* <p>
|
|
||||||
* 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.
|
|
||||||
* <h3>Important note:</h3>
|
|
||||||
* the final price are re calculated on click for the following use case:
|
|
||||||
* <ul>
|
|
||||||
* <li>Custom craft</li>
|
|
||||||
* <li>Unit repair</li>
|
|
||||||
* <li>Lore edit</li>
|
|
||||||
* </ul>
|
|
||||||
* This value will be used as final price for:
|
|
||||||
* <li>Item merge</li>
|
|
||||||
* <li>Item rename</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @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.
|
|
||||||
* <h3>Important note:</h3>
|
|
||||||
* the final price are re calculated on click for the following use case:
|
|
||||||
* <ul>
|
|
||||||
* <li>Custom craft</li>
|
|
||||||
* <li>Unit repair</li>
|
|
||||||
* <li>Lore edit</li>
|
|
||||||
* </ul>
|
|
||||||
* This value will be used as final price for:
|
|
||||||
* <li>Item merge</li>
|
|
||||||
* <li>Item rename</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @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
|
|
||||||
*
|
|
||||||
* <h3>Important note:</h3>
|
|
||||||
* the final price are re calculated on click for the following use case:
|
|
||||||
* <ul>
|
|
||||||
* <li>Custom craft</li>
|
|
||||||
* <li>Unit repair</li>
|
|
||||||
* <li>Lore edit</li>
|
|
||||||
* </ul>
|
|
||||||
* This value will be used as final price for:
|
|
||||||
* <li>Item merge</li>
|
|
||||||
* <li>Item rename</li>
|
|
||||||
*
|
|
||||||
* @return the current anvil cost
|
|
||||||
*/
|
|
||||||
public AnvilCost getCost() {
|
|
||||||
return cost;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -6,8 +6,7 @@ import org.bukkit.event.inventory.PrepareAnvilEvent;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import xyz.alexcrea.cuanvil.anvil.AnvilCost;
|
import xyz.alexcrea.cuanvil.util.AnvilUseType;
|
||||||
import xyz.alexcrea.cuanvil.anvil.AnvilUseType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called after custom anvil processed the click on the result on the anvil inventory.
|
* Called after custom anvil processed the click on the result on the anvil inventory.
|
||||||
|
|
@ -18,12 +17,8 @@ import xyz.alexcrea.cuanvil.anvil.AnvilUseType;
|
||||||
* and {@link CAEarlyPreAnvilBypassEvent} for your use case
|
* and {@link CAEarlyPreAnvilBypassEvent} for your use case
|
||||||
* <p>
|
* <p>
|
||||||
* A null result will cancel this pre anvil event
|
* 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")
|
@SuppressWarnings("unused")
|
||||||
@Deprecated(forRemoval = true, since = "1.17.0")
|
|
||||||
public class CATreatAnvilResultEvent extends Event {
|
public class CATreatAnvilResultEvent extends Event {
|
||||||
|
|
||||||
private static final HandlerList HANDLERS = new HandlerList();
|
private static final HandlerList HANDLERS = new HandlerList();
|
||||||
|
|
@ -45,13 +40,13 @@ public class CATreatAnvilResultEvent extends Event {
|
||||||
@Nullable
|
@Nullable
|
||||||
private ItemStack result;
|
private ItemStack result;
|
||||||
|
|
||||||
private final AnvilCost cost;
|
private int levelCost;
|
||||||
|
|
||||||
public CATreatAnvilResultEvent(@NotNull PrepareAnvilEvent event, AnvilUseType useType, @Nullable ItemStack result, AnvilCost cost) {
|
public CATreatAnvilResultEvent(@NotNull PrepareAnvilEvent event, AnvilUseType useType, @Nullable ItemStack result, int levelCost) {
|
||||||
this.event = event;
|
this.event = event;
|
||||||
this.useType = useType;
|
this.useType = useType;
|
||||||
this.result = result;
|
this.result = result;
|
||||||
this.cost = cost;
|
this.levelCost = levelCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -109,11 +104,9 @@ public class CATreatAnvilResultEvent extends Event {
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @return The current cost.
|
* @return The current cost.
|
||||||
* @deprecated use #{@link #getCost()} instead
|
|
||||||
*/
|
*/
|
||||||
@Deprecated(forRemoval = true, since = "1.17.0")
|
|
||||||
public int getLevelCost() {
|
public int getLevelCost() {
|
||||||
return cost.asXpCost();
|
return levelCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -131,32 +124,8 @@ public class CATreatAnvilResultEvent extends Event {
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @param levelCost The new cost.
|
* @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) {
|
public void setLevelCost(int levelCost) {
|
||||||
cost.setGeneric(levelCost - cost.getGeneric() - cost.asXpCost());
|
this.levelCost = levelCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allow access to the current cost of the event
|
|
||||||
* Note that modifying this object will change the event resulting cost
|
|
||||||
*
|
|
||||||
* <h3>Important note:</h3>
|
|
||||||
* the final price are re calculated on click for the following use case:
|
|
||||||
* <ul>
|
|
||||||
* <li>Custom craft</li>
|
|
||||||
* <li>Unit repair</li>
|
|
||||||
* <li>Lore edit</li>
|
|
||||||
* </ul>
|
|
||||||
* This value will be used as final price for:
|
|
||||||
* <li>Item merge</li>
|
|
||||||
* <li>Item rename</li>
|
|
||||||
*
|
|
||||||
* @return the current anvil cost
|
|
||||||
*/
|
|
||||||
public AnvilCost getCost() {
|
|
||||||
return cost;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import org.jetbrains.annotations.Nullable;
|
||||||
import xyz.alexcrea.cuanvil.group.EnchantConflictManager;
|
import xyz.alexcrea.cuanvil.group.EnchantConflictManager;
|
||||||
import xyz.alexcrea.cuanvil.group.ItemGroupManager;
|
import xyz.alexcrea.cuanvil.group.ItemGroupManager;
|
||||||
import xyz.alexcrea.cuanvil.recipe.CustomAnvilRecipeManager;
|
import xyz.alexcrea.cuanvil.recipe.CustomAnvilRecipeManager;
|
||||||
import xyz.alexcrea.cuanvil.util.MetricsUtil;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
@ -146,7 +145,6 @@ public abstract class ConfigHolder {
|
||||||
sufficientSuccess = true;
|
sufficientSuccess = true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not copy backup saving config " + base.getName(), e);
|
CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not copy backup saving config " + base.getName(), e);
|
||||||
MetricsUtil.INSTANCE.trackError(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// save last backup
|
// save last backup
|
||||||
|
|
@ -277,7 +275,6 @@ public abstract class ConfigHolder {
|
||||||
this.deletedConfigFile.createNewFile();
|
this.deletedConfigFile.createNewFile();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not create " + this.deletedConfigFile.getPath(), e);
|
CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not create " + this.deletedConfigFile.getPath(), e);
|
||||||
MetricsUtil.INSTANCE.trackError(e);
|
|
||||||
}
|
}
|
||||||
loadDeletedListFile(false);
|
loadDeletedListFile(false);
|
||||||
|
|
||||||
|
|
@ -315,7 +312,6 @@ public abstract class ConfigHolder {
|
||||||
this.deletedListConfig.save(this.deletedConfigFile);
|
this.deletedListConfig.save(this.deletedConfigFile);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not save " + this.deletedConfigFile.getPath(), e);
|
CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not save " + this.deletedConfigFile.getPath(), e);
|
||||||
MetricsUtil.INSTANCE.trackError(e);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package xyz.alexcrea.cuanvil.config;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import xyz.alexcrea.cuanvil.anvil.AnvilUseType;
|
import xyz.alexcrea.cuanvil.util.AnvilUseType;
|
||||||
|
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package xyz.alexcrea.cuanvil.enchant;
|
package xyz.alexcrea.cuanvil.enchant;
|
||||||
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.NamespacedKey;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
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.
|
* 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 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.
|
* @return If there is a conflict with the enchantments.
|
||||||
*/
|
*/
|
||||||
boolean isEnchantConflict(
|
boolean isEnchantConflict(
|
||||||
@NotNull Map<CAEnchantment, Integer> enchantments,
|
@NotNull Map<CAEnchantment, Integer> enchantments,
|
||||||
@NotNull NamespacedKey itemType);
|
@NotNull Material itemMat);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if the provided item can be compatible with this enchantment. only non-Custom Anvil conflict.
|
* 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 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.
|
* @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.
|
* @return If there is a conflict with the enchantment and the item.
|
||||||
*/
|
*/
|
||||||
boolean isItemConflict(
|
boolean isItemConflict(
|
||||||
@NotNull Map<CAEnchantment, Integer> enchantments,
|
@NotNull Map<CAEnchantment, Integer> enchantments,
|
||||||
@NotNull NamespacedKey itemType,
|
@NotNull Material itemMat,
|
||||||
@NotNull ItemStack item);
|
@NotNull ItemStack item);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import xyz.alexcrea.cuanvil.enchant.bulk.BukkitEnchantBulkOperation;
|
||||||
import xyz.alexcrea.cuanvil.enchant.bulk.BulkCleanEnchantOperation;
|
import xyz.alexcrea.cuanvil.enchant.bulk.BulkCleanEnchantOperation;
|
||||||
import xyz.alexcrea.cuanvil.enchant.bulk.BulkGetEnchantOperation;
|
import xyz.alexcrea.cuanvil.enchant.bulk.BulkGetEnchantOperation;
|
||||||
import xyz.alexcrea.cuanvil.enchant.wrapped.CABukkitEnchantment;
|
import xyz.alexcrea.cuanvil.enchant.wrapped.CABukkitEnchantment;
|
||||||
import xyz.alexcrea.cuanvil.util.MetricsUtil;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
@ -86,13 +85,11 @@ public class CAEnchantmentRegistry {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var error = new IllegalStateException("enchantment " + enchantment.getKey() + " was already registered");
|
|
||||||
CustomAnvil.instance.getLogger().log(Level.WARNING,
|
CustomAnvil.instance.getLogger().log(Level.WARNING,
|
||||||
"Duplicate distinct registered enchantment. This should NOT happen any time.\n" +
|
"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. " +
|
"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",
|
"you should maybe remove enchantment with the same key before registering yours",
|
||||||
error);
|
new IllegalStateException("enchantment " + enchantment.getKey() + " was already registered"));
|
||||||
MetricsUtil.INSTANCE.trackError(error);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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<CAEnchantment, Integer> 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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package xyz.alexcrea.cuanvil.enchant.wrapped;
|
package xyz.alexcrea.cuanvil.enchant.wrapped;
|
||||||
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.NamespacedKey;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import su.nightexpress.excellentenchants.api.enchantment.CustomEnchantment;
|
import su.nightexpress.excellentenchants.api.enchantment.CustomEnchantment;
|
||||||
|
|
@ -40,7 +39,7 @@ public class CAEEPreV5Enchantment extends CABukkitEnchantment implements Additio
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnchantConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull NamespacedKey itemType) {
|
public boolean isEnchantConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull Material itemMat) {
|
||||||
if (!definition.hasConflicts()) return false;
|
if (!definition.hasConflicts()) return false;
|
||||||
|
|
||||||
Set<String> conflicts = definition.getConflicts();
|
Set<String> conflicts = definition.getConflicts();
|
||||||
|
|
@ -53,8 +52,8 @@ public class CAEEPreV5Enchantment extends CABukkitEnchantment implements Additio
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isItemConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull NamespacedKey itemType, @NotNull ItemStack item) {
|
public boolean isItemConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull Material itemMat, @NotNull ItemStack item) {
|
||||||
if (Material.ENCHANTED_BOOK.getKey().equals(itemType)) return false;
|
if (Material.ENCHANTED_BOOK.equals(itemMat)) return false;
|
||||||
|
|
||||||
return !definition.getSupportedItems().is(item);
|
return !definition.getSupportedItems().is(item);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,51 +1,48 @@
|
||||||
package xyz.alexcrea.cuanvil.enchant.wrapped;
|
package xyz.alexcrea.cuanvil.enchant.wrapped;
|
||||||
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.NamespacedKey;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import su.nightexpress.excellentenchants.api.enchantment.CustomEnchantment;
|
import su.nightexpress.excellentenchants.api.enchantment.CustomEnchantment;
|
||||||
import su.nightexpress.excellentenchants.api.item.ItemSet;
|
import su.nightexpress.excellentenchants.api.item.ItemSet;
|
||||||
|
import su.nightexpress.excellentenchants.api.wrapper.EnchantDefinition;
|
||||||
import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment;
|
import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment;
|
||||||
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
|
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
|
||||||
import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity;
|
import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class CAEEV5Enchantment extends CABukkitEnchantment implements AdditionalTestEnchantment {
|
public class CAEEV5Enchantment extends CABukkitEnchantment implements AdditionalTestEnchantment {
|
||||||
|
|
||||||
@NotNull CustomEnchantment eeenchantment;
|
@NotNull CustomEnchantment eeenchantment;
|
||||||
@NotNull Object definition;
|
@NotNull EnchantDefinition definition;
|
||||||
|
|
||||||
public CAEEV5Enchantment(@NotNull CustomEnchantment enchantment) {
|
public CAEEV5Enchantment(@NotNull CustomEnchantment enchantment) {
|
||||||
super(enchantment.getBukkitEnchantment(), EnchantmentRarity.getRarity(getAnvilCost(enchantment)));
|
super(enchantment.getBukkitEnchantment(), EnchantmentRarity.getRarity(enchantment.getDefinition().getAnvilCost()));
|
||||||
this.eeenchantment = enchantment;
|
this.eeenchantment = enchantment;
|
||||||
this.definition = getDefinition(enchantment);
|
this.definition = enchantment.getDefinition();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnchantConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull NamespacedKey itemType) {
|
public boolean isEnchantConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull Material itemMat) {
|
||||||
if (!hasConflicts()) return false;
|
if (!definition.hasConflicts()) return false;
|
||||||
|
|
||||||
Set<String> conflicts = getExclusiveSet();
|
Set<String> conflicts = definition.getExclusiveSet();
|
||||||
|
|
||||||
for (CAEnchantment caEnchantment : enchantments.keySet()) {
|
for (CAEnchantment caEnchantment : enchantments.keySet()) {
|
||||||
if (conflicts.contains(caEnchantment.getName())) return true;
|
if (conflicts.contains(caEnchantment.getName())) return true;
|
||||||
if (conflicts.contains(caEnchantment.getKey().toString())) return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isItemConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull NamespacedKey itemType, @NotNull ItemStack item) {
|
public boolean isItemConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull Material itemMat, @NotNull ItemStack item) {
|
||||||
if (Material.ENCHANTED_BOOK.getKey().equals(itemType)) return false;
|
if (Material.ENCHANTED_BOOK.equals(itemMat)) return false;
|
||||||
|
|
||||||
String key = itemType.getKey();
|
String key = itemMat.getKey().getKey();
|
||||||
ItemSet primary = eeenchantment.getPrimaryItems();
|
ItemSet primary = eeenchantment.getPrimaryItems();
|
||||||
if (primary.getMaterials().contains(key)) return false;
|
if (primary.getMaterials().contains(key)) return false;
|
||||||
|
|
||||||
|
|
@ -55,74 +52,4 @@ public class CAEEV5Enchantment extends CABukkitEnchantment implements Additional
|
||||||
return true;
|
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<String> getExclusiveSet() {
|
|
||||||
try {
|
|
||||||
return (Set<String>) getExclusiveSetMethod.invoke(definition);
|
|
||||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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<CAEnchantment, Integer> 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -4,7 +4,6 @@ import com.willfp.ecoenchants.enchant.EcoEnchant;
|
||||||
import com.willfp.ecoenchants.target.EnchantmentTarget;
|
import com.willfp.ecoenchants.target.EnchantmentTarget;
|
||||||
import com.willfp.ecoenchants.type.EnchantmentType;
|
import com.willfp.ecoenchants.type.EnchantmentType;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.NamespacedKey;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment;
|
import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment;
|
||||||
|
|
@ -24,13 +23,9 @@ public class CAEcoEnchant extends CABukkitEnchantment implements AdditionalTestE
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnchantConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull NamespacedKey itemType) {
|
public boolean isEnchantConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull Material itemMat) {
|
||||||
if (enchantments.isEmpty()) return false;
|
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()) {
|
if (this.ecoEnchant.getConflictsWithEverything()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -62,9 +57,9 @@ public class CAEcoEnchant extends CABukkitEnchantment implements AdditionalTestE
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isItemConflict(@NotNull Map<CAEnchantment, Integer> enchantments,
|
public boolean isItemConflict(@NotNull Map<CAEnchantment, Integer> enchantments,
|
||||||
@NotNull NamespacedKey itemType,
|
@NotNull Material itemMat,
|
||||||
@NotNull ItemStack item) {
|
@NotNull ItemStack item) {
|
||||||
if (Material.ENCHANTED_BOOK.getKey().equals(itemType)) {
|
if (Material.ENCHANTED_BOOK.equals(itemMat)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package xyz.alexcrea.cuanvil.enchant.wrapped;
|
package xyz.alexcrea.cuanvil.enchant.wrapped;
|
||||||
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.NamespacedKey;
|
|
||||||
import org.bukkit.enchantments.Enchantment;
|
import org.bukkit.enchantments.Enchantment;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
@ -25,12 +24,12 @@ public class CAIncompatibleAllEnchant extends CABukkitEnchantment implements Add
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnchantConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull NamespacedKey itemType) {
|
public boolean isEnchantConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull Material itemMat) {
|
||||||
return !enchantments.isEmpty() && !(enchantments.size() == 1 && enchantments.containsKey(this));
|
return !enchantments.isEmpty() && !(enchantments.size() == 1 && enchantments.containsKey(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isItemConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull NamespacedKey itemType, @NotNull ItemStack item) {
|
public boolean isItemConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull Material itemMat, @NotNull ItemStack item) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package xyz.alexcrea.cuanvil.enchant.wrapped;
|
package xyz.alexcrea.cuanvil.enchant.wrapped;
|
||||||
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.NamespacedKey;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData;
|
import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData;
|
||||||
|
|
@ -23,7 +22,7 @@ public class CALegacyEEEnchantment extends CABukkitEnchantment implements Additi
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnchantConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull NamespacedKey itemType) {
|
public boolean isEnchantConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull Material itemMat) {
|
||||||
if (!eeenchantment.hasConflicts()) return false;
|
if (!eeenchantment.hasConflicts()) return false;
|
||||||
|
|
||||||
Set<String> conflicts = eeenchantment.getConflicts();
|
Set<String> conflicts = eeenchantment.getConflicts();
|
||||||
|
|
@ -36,8 +35,8 @@ public class CALegacyEEEnchantment extends CABukkitEnchantment implements Additi
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isItemConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull NamespacedKey itemType, @NotNull ItemStack item) {
|
public boolean isItemConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull Material itemMat, @NotNull ItemStack item) {
|
||||||
if (Material.ENCHANTED_BOOK.getKey().equals(itemType)) return false;
|
if (Material.ENCHANTED_BOOK.equals(itemMat)) return false;
|
||||||
|
|
||||||
return !eeenchantment.getSupportedItems().is(item);
|
return !eeenchantment.getSupportedItems().is(item);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,12 @@ import com.willfp.ecoenchants.enchantments.EcoEnchant;
|
||||||
import com.willfp.ecoenchants.enchantments.meta.EnchantmentTarget;
|
import com.willfp.ecoenchants.enchantments.meta.EnchantmentTarget;
|
||||||
import com.willfp.ecoenchants.enchantments.meta.EnchantmentType;
|
import com.willfp.ecoenchants.enchantments.meta.EnchantmentType;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.NamespacedKey;
|
|
||||||
import org.bukkit.enchantments.Enchantment;
|
import org.bukkit.enchantments.Enchantment;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment;
|
import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment;
|
||||||
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
|
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
|
||||||
import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity;
|
import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity;
|
||||||
import xyz.alexcrea.cuanvil.util.MaterialUtil;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
@ -25,7 +23,7 @@ public class CALegacyEcoEnchant extends CABukkitEnchantment implements Additiona
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnchantConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull NamespacedKey itemType) {
|
public boolean isEnchantConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull Material itemMat) {
|
||||||
if (enchantments.isEmpty()) return false;
|
if (enchantments.isEmpty()) return false;
|
||||||
|
|
||||||
EnchantmentType type = this.ecoEnchant.getType();
|
EnchantmentType type = this.ecoEnchant.getType();
|
||||||
|
|
@ -50,15 +48,14 @@ public class CALegacyEcoEnchant extends CABukkitEnchantment implements Additiona
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isItemConflict(@NotNull Map<CAEnchantment, Integer> enchantments,
|
public boolean isItemConflict(@NotNull Map<CAEnchantment, Integer> enchantments,
|
||||||
@NotNull NamespacedKey itemType,
|
@NotNull Material itemMat,
|
||||||
@NotNull ItemStack item) {
|
@NotNull ItemStack item) {
|
||||||
if (Material.ENCHANTED_BOOK.getKey().equals(itemType)) {
|
if (Material.ENCHANTED_BOOK.equals(itemMat)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mat = MaterialUtil.INSTANCE.getMatFromKey(itemType);
|
|
||||||
for (EnchantmentTarget target : this.ecoEnchant.getTargets()) {
|
for (EnchantmentTarget target : this.ecoEnchant.getTargets()) {
|
||||||
if (target.getMaterials().contains(mat)) {
|
if (target.getMaterials().contains(itemMat)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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<CAEnchantment, Integer> enchantments, @NotNull NamespacedKey itemType) {
|
|
||||||
var idMap = new HashMap<String, Integer>();
|
|
||||||
|
|
||||||
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<CAEnchantment, Integer> enchantments, @NotNull NamespacedKey itemType, @NotNull ItemStack item) {
|
|
||||||
if(Material.ENCHANTED_BOOK.equals(item.getType())) return false;
|
|
||||||
|
|
||||||
return !enchant.canApplyTo(item.getType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,35 +1,34 @@
|
||||||
package xyz.alexcrea.cuanvil.gui.config;
|
package xyz.alexcrea.cuanvil.gui.config;
|
||||||
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.NamespacedKey;
|
|
||||||
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
|
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public interface SelectMaterialContainer {
|
public interface SelectMaterialContainer {
|
||||||
|
|
||||||
Set<NamespacedKey> getSelectedMaterials();
|
EnumSet<Material> getSelectedMaterials();
|
||||||
|
|
||||||
boolean setSelectedMaterials(Set<NamespacedKey> materials);
|
boolean setSelectedMaterials(EnumSet<Material> materials);
|
||||||
|
|
||||||
Set<NamespacedKey> illegalMaterials();
|
EnumSet<Material> illegalMaterials();
|
||||||
|
|
||||||
static List<String> getMaterialLore(SelectMaterialContainer container, String containerType, String action){
|
static List<String> getMaterialLore(SelectMaterialContainer container, String containerType, String action){
|
||||||
// Prepare material lore
|
// Prepare material lore
|
||||||
ArrayList<String> groupLore = new ArrayList<>();
|
ArrayList<String> groupLore = new ArrayList<>();
|
||||||
groupLore.add("§7Allow you to select a list of §ematerials §7that this " + containerType + " should " + action);
|
groupLore.add("§7Allow you to select a list of §ematerials §7that this " + containerType + " should " + action);
|
||||||
Set<NamespacedKey> materialSet = container.getSelectedMaterials();
|
Set<Material> materialSet = container.getSelectedMaterials();
|
||||||
if (materialSet.isEmpty()) {
|
if (materialSet.isEmpty()) {
|
||||||
groupLore.add("§7There is no "+action+"d material for this "+containerType+".");
|
groupLore.add("§7There is no "+action+"d material for this "+containerType+".");
|
||||||
} else {
|
} else {
|
||||||
groupLore.add("§7List of "+action+"d materials for this "+containerType+":");
|
groupLore.add("§7List of "+action+"d materials for this "+containerType+":");
|
||||||
Iterator<NamespacedKey> materialIterator = materialSet.iterator();
|
Iterator<Material> materialIterator = materialSet.iterator();
|
||||||
|
|
||||||
boolean greaterThanMax = materialSet.size() > 5;
|
boolean greaterThanMax = materialSet.size() > 5;
|
||||||
int maxindex = (greaterThanMax ? 4 : materialSet.size());
|
int maxindex = (greaterThanMax ? 4 : materialSet.size());
|
||||||
for (int i = 0; i < maxindex; i++) {
|
for (int i = 0; i < maxindex; i++) {
|
||||||
// format string like "- Stone Sword"
|
// 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);
|
groupLore.add("§7- §e" + formattedName);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ import org.bukkit.inventory.meta.ItemMeta;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
|
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
|
||||||
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
|
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
|
||||||
import xyz.alexcrea.cuanvil.util.MetricsUtil;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
@ -42,7 +41,6 @@ public class ConfirmActionGui extends AbstractAskGui {
|
||||||
success = onConfirm.get();
|
success = onConfirm.get();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not process confirmation supplier.", e);
|
CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not process confirmation supplier.", e);
|
||||||
MetricsUtil.INSTANCE.trackError(e);
|
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ import org.jetbrains.annotations.NotNull;
|
||||||
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
|
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
|
||||||
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
|
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
|
||||||
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
|
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
|
||||||
import xyz.alexcrea.cuanvil.util.MaterialUtil;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
@ -53,7 +52,7 @@ public class SelectItemTypeGui extends AbstractAskGui {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
|
|
||||||
ItemStack cursor = event.getWhoClicked().getItemOnCursor();
|
ItemStack cursor = event.getWhoClicked().getItemOnCursor();
|
||||||
if(MaterialUtil.INSTANCE.isAir(cursor)) return;
|
if(cursor.getType().isAir()) return;
|
||||||
|
|
||||||
ItemStack finalItem;
|
ItemStack finalItem;
|
||||||
if(materialOnly){
|
if(materialOnly){
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ import org.bukkit.inventory.meta.ItemMeta;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
||||||
import xyz.alexcrea.cuanvil.dependency.MinecraftVersionUtil;
|
|
||||||
import xyz.alexcrea.cuanvil.dependency.packet.PacketManager;
|
import xyz.alexcrea.cuanvil.dependency.packet.PacketManager;
|
||||||
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
|
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
|
||||||
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui;
|
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui;
|
||||||
|
|
@ -284,7 +283,7 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
|
||||||
|
|
||||||
if(!this.packetManager.getCanSetInstantBuild()){
|
if(!this.packetManager.getCanSetInstantBuild()){
|
||||||
lore.add("");
|
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.");
|
lore.add("§cCurrently ProtocoLib is not detected.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ import java.util.Locale;
|
||||||
*/
|
*/
|
||||||
public class EnchantLimitConfigGui extends AbstractEnchantConfigGui<IntSettingsGui.IntSettingFactory> {
|
public class EnchantLimitConfigGui extends AbstractEnchantConfigGui<IntSettingsGui.IntSettingFactory> {
|
||||||
|
|
||||||
private static final String SECTION_NAME = ConfigOptions.ENCHANT_LIMIT_ROOT;
|
private static final String SECTION_NAME = "enchant_limits";
|
||||||
|
|
||||||
private static EnchantLimitConfigGui INSTANCE = null;
|
private static EnchantLimitConfigGui INSTANCE = null;
|
||||||
|
|
||||||
|
|
@ -41,34 +41,18 @@ public class EnchantLimitConfigGui extends AbstractEnchantConfigGui<IntSettingsG
|
||||||
String key = enchant.getKey().toString().toLowerCase(Locale.ROOT);
|
String key = enchant.getKey().toString().toLowerCase(Locale.ROOT);
|
||||||
String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key.replace(":", "_"));
|
String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key.replace(":", "_"));
|
||||||
|
|
||||||
var defaultValue = enchant.defaultMaxLevel();
|
|
||||||
|
|
||||||
return new IntSettingsGui.IntSettingFactory(prettyKey + " Limit", this,
|
return new IntSettingsGui.IntSettingFactory(prettyKey + " Limit", this,
|
||||||
SECTION_NAME + '.' + key, ConfigHolder.DEFAULT_CONFIG,
|
SECTION_NAME + '.' + key, ConfigHolder.DEFAULT_CONFIG,
|
||||||
Collections.singletonList(
|
Collections.singletonList(
|
||||||
"§7Maximum applied level of " + prettyKey
|
"§7Maximum applied level of " + prettyKey
|
||||||
),
|
),
|
||||||
-1, 255, -1,
|
0, 255,
|
||||||
|
enchant.defaultMaxLevel(),
|
||||||
1, 5, 10, 50, 100){
|
1, 5, 10, 50, 100){
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getConfiguredValue() {
|
public int getConfiguredValue() {
|
||||||
var value = ConfigOptions.INSTANCE.rawEnchantLimit(enchant);
|
return ConfigOptions.INSTANCE.enchantLimit(enchant);
|
||||||
return Math.min(value, ConfigOptions.ENCHANT_LIMIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String valueDisplayName(IntSettingsGui.ValueDisplayType type, int value) {
|
|
||||||
|
|
||||||
if(value < 0) {
|
|
||||||
return switch (type) {
|
|
||||||
case CURRENT -> "Default (" + defaultValue + ")";
|
|
||||||
case RESET -> String.valueOf(defaultValue);
|
|
||||||
default -> "Default";
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
else return super.valueDisplayName(type, value);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
|
||||||
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
|
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
|
||||||
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
|
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
|
||||||
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
|
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
|
||||||
import xyz.alexcrea.cuanvil.util.MetricsUtil;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
@ -265,7 +264,6 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
|
||||||
updateGuiValues();
|
updateGuiValues();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
CustomAnvil.instance.getLogger().log(Level.WARNING, "An error occurred while updating enchants for " + this.enchantConflict, 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
|
// Save file configuration to disk
|
||||||
|
|
@ -310,7 +308,6 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
|
||||||
updateGuiValues();
|
updateGuiValues();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
CustomAnvil.instance.getLogger().log(Level.WARNING, "An error occurred while updating group for " + this.enchantConflict, 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
|
// Save file configuration to disk
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import com.github.stefvanschie.inventoryframework.pane.PatternPane;
|
||||||
import com.github.stefvanschie.inventoryframework.pane.util.Pattern;
|
import com.github.stefvanschie.inventoryframework.pane.util.Pattern;
|
||||||
import io.delilaheve.CustomAnvil;
|
import io.delilaheve.CustomAnvil;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.NamespacedKey;
|
|
||||||
import org.bukkit.entity.HumanEntity;
|
import org.bukkit.entity.HumanEntity;
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
import org.bukkit.inventory.ItemFlag;
|
import org.bukkit.inventory.ItemFlag;
|
||||||
|
|
@ -326,19 +325,19 @@ public class GroupConfigSubSettingGui extends MappedToListSubSettingGui implemen
|
||||||
// ----------------------------
|
// ----------------------------
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<NamespacedKey> getSelectedMaterials() {
|
public EnumSet<Material> getSelectedMaterials() {
|
||||||
return this.group.getNonGroupInheritedMaterials();
|
return this.group.getNonGroupInheritedMaterials();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setSelectedMaterials(Set<NamespacedKey> materials) {
|
public boolean setSelectedMaterials(EnumSet<Material> materials) {
|
||||||
this.group.setNonGroupInheritedMaterials(materials);
|
this.group.setNonGroupInheritedMaterials(materials);
|
||||||
|
|
||||||
// Write to file configuration
|
// Write to file configuration
|
||||||
String[] groupNames = new String[materials.size()];
|
String[] groupNames = new String[materials.size()];
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (NamespacedKey otherGroup : materials) {
|
for (Material otherGroup : materials) {
|
||||||
groupNames[index++] = otherGroup.getKey().toLowerCase();
|
groupNames[index++] = otherGroup.name().toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigHolder.ITEM_GROUP_HOLDER.getConfig().set(this.group.getName()+"."+ItemGroupManager.MATERIAL_LIST_PATH, groupNames);
|
ConfigHolder.ITEM_GROUP_HOLDER.getConfig().set(this.group.getName()+"."+ItemGroupManager.MATERIAL_LIST_PATH, groupNames);
|
||||||
|
|
@ -354,8 +353,8 @@ public class GroupConfigSubSettingGui extends MappedToListSubSettingGui implemen
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<NamespacedKey> illegalMaterials() {
|
public EnumSet<Material> illegalMaterials() {
|
||||||
return Set.of(Material.AIR.getKey());
|
return EnumSet.of(Material.AIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------
|
// ----------------------------
|
||||||
|
|
|
||||||
|
|
@ -72,8 +72,7 @@ public class IntSettingsGui extends AbstractSettingGui {
|
||||||
assert meta != null;
|
assert meta != null;
|
||||||
|
|
||||||
meta.setDisplayName("§eReset to default value");
|
meta.setDisplayName("§eReset to default value");
|
||||||
meta.setLore(Collections.singletonList("§7Default value is §e" +
|
meta.setLore(Collections.singletonList("§7Default value is §e" + holder.defaultVal));
|
||||||
holder.valueDisplayName(ValueDisplayType.RESET, holder.defaultVal)));
|
|
||||||
item.setItemMeta(meta);
|
item.setItemMeta(meta);
|
||||||
returnToDefault = new GuiItem(item, event -> {
|
returnToDefault = new GuiItem(item, event -> {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
|
|
@ -87,23 +86,41 @@ public class IntSettingsGui extends AbstractSettingGui {
|
||||||
* Update item using the setting value to match the new value.
|
* Update item using the setting value to match the new value.
|
||||||
*/
|
*/
|
||||||
protected void updateValueDisplay() {
|
protected void updateValueDisplay() {
|
||||||
|
|
||||||
PatternPane pane = getPane();
|
PatternPane pane = getPane();
|
||||||
|
|
||||||
// minus item
|
// minus item
|
||||||
GuiItem minusItem;
|
GuiItem minusItem;
|
||||||
if (now > holder.min) {
|
if (now > holder.min) {
|
||||||
int planned = Math.max(holder.min, now - step);
|
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 {
|
} else {
|
||||||
minusItem = GuiGlobalItems.backgroundItem(Material.BARRIER);
|
minusItem = GuiGlobalItems.backgroundItem(Material.BARRIER);
|
||||||
}
|
}
|
||||||
pane.bindItem('-', minusItem);
|
pane.bindItem('-', minusItem);
|
||||||
|
|
||||||
//plus item
|
//plus item
|
||||||
|
// may do a function to generalise ?
|
||||||
GuiItem plusItem;
|
GuiItem plusItem;
|
||||||
if (now < holder.max) {
|
if (now < holder.max) {
|
||||||
int planned = Math.min(holder.max, now + step);
|
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 {
|
} else {
|
||||||
plusItem = GuiGlobalItems.backgroundItem(Material.BARRIER);
|
plusItem = GuiGlobalItems.backgroundItem(Material.BARRIER);
|
||||||
}
|
}
|
||||||
|
|
@ -114,7 +131,7 @@ public class IntSettingsGui extends AbstractSettingGui {
|
||||||
ItemMeta resultMeta = resultPaper.getItemMeta();
|
ItemMeta resultMeta = resultPaper.getItemMeta();
|
||||||
assert resultMeta != null;
|
assert resultMeta != null;
|
||||||
|
|
||||||
resultMeta.setDisplayName("§fValue: §e" + holder.valueDisplayName(ValueDisplayType.CURRENT, now));
|
resultMeta.setDisplayName("§fValue: §e" + now);
|
||||||
resultMeta.setLore(holder.displayLore);
|
resultMeta.setLore(holder.displayLore);
|
||||||
|
|
||||||
resultPaper.setItemMeta(resultMeta);
|
resultPaper.setItemMeta(resultMeta);
|
||||||
|
|
@ -132,21 +149,7 @@ public class IntSettingsGui extends AbstractSettingGui {
|
||||||
}
|
}
|
||||||
pane.bindItem('D', returnToDefault);
|
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));
|
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,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
|
||||||
import com.github.stefvanschie.inventoryframework.pane.util.Pattern;
|
import com.github.stefvanschie.inventoryframework.pane.util.Pattern;
|
||||||
import io.delilaheve.CustomAnvil;
|
import io.delilaheve.CustomAnvil;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.NamespacedKey;
|
|
||||||
import org.bukkit.entity.HumanEntity;
|
import org.bukkit.entity.HumanEntity;
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
import org.bukkit.inventory.ItemFlag;
|
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.GuiGlobalItems;
|
||||||
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
|
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
|
||||||
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
|
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
|
||||||
import xyz.alexcrea.cuanvil.util.MaterialUtil;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class MaterialSelectSettingGui extends MappedElementListConfigGui<NamespacedKey, GuiItem> {
|
public class MaterialSelectSettingGui extends MappedElementListConfigGui<Material, GuiItem> {
|
||||||
|
|
||||||
private final SelectMaterialContainer selector;
|
private final SelectMaterialContainer selector;
|
||||||
private final Gui backGui;
|
private final Gui backGui;
|
||||||
private boolean instantRemove;
|
private boolean instantRemove;
|
||||||
|
|
||||||
private final List<NamespacedKey> defaultMaterials;
|
private final List<Material> defaultMaterials;
|
||||||
private final Set<NamespacedKey> illegalMaterials;
|
private final EnumSet<Material> illegalMaterials;
|
||||||
private final int defaultMaterialHash;
|
private final int defaultMaterialHash;
|
||||||
private int nowMaterialHash;
|
private int nowMaterialHash;
|
||||||
|
|
||||||
|
|
@ -163,7 +161,8 @@ public class MaterialSelectSettingGui extends MappedElementListConfigGui<Namespa
|
||||||
|
|
||||||
|
|
||||||
// Save setting
|
// Save setting
|
||||||
Set<NamespacedKey> result = new HashSet<>(this.elementGuiMap.keySet());
|
EnumSet<Material> result = EnumSet.noneOf(Material.class);
|
||||||
|
result.addAll(this.elementGuiMap.keySet());
|
||||||
|
|
||||||
if(!this.selector.setSelectedMaterials(result)){
|
if(!this.selector.setSelectedMaterials(result)){
|
||||||
player.sendMessage("§cSomething went wrong while saving the change of value.");
|
player.sendMessage("§cSomething went wrong while saving the change of value.");
|
||||||
|
|
@ -186,8 +185,8 @@ public class MaterialSelectSettingGui extends MappedElementListConfigGui<Namespa
|
||||||
ItemStack cursor = player.getItemOnCursor();
|
ItemStack cursor = player.getItemOnCursor();
|
||||||
|
|
||||||
// Test if cursor material allowed
|
// Test if cursor material allowed
|
||||||
NamespacedKey cursorMat = MaterialUtil.INSTANCE.getCustomType(cursor);
|
Material cursorMat = cursor.getType();
|
||||||
if(MaterialUtil.INSTANCE.isAir(cursorMat)) return;
|
if(cursorMat.isAir()) return;
|
||||||
if(this.illegalMaterials.contains(cursorMat)) return;
|
if(this.illegalMaterials.contains(cursorMat)) return;
|
||||||
|
|
||||||
// Update gui only if item did not exist before.
|
// Update gui only if item did not exist before.
|
||||||
|
|
@ -202,12 +201,12 @@ public class MaterialSelectSettingGui extends MappedElementListConfigGui<Namespa
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ItemStack createItemForGeneric(NamespacedKey material) {
|
protected ItemStack createItemForGeneric(Material material) {
|
||||||
ItemStack item = new ItemStack(Objects.requireNonNull(MaterialUtil.INSTANCE.getMatFromKey(material)));
|
ItemStack item = new ItemStack(material);
|
||||||
ItemMeta meta = item.getItemMeta();
|
ItemMeta meta = item.getItemMeta();
|
||||||
|
|
||||||
if(meta == null) return item;
|
if(meta == null) return item;
|
||||||
meta.setDisplayName("§a" + CasedStringUtil.snakeToUpperSpacedCase(material.getKey().toLowerCase()));
|
meta.setDisplayName("§a" + CasedStringUtil.snakeToUpperSpacedCase(material.name().toLowerCase()));
|
||||||
meta.setLore(Collections.singletonList("§7Click here to remove this material from the list"));
|
meta.setLore(Collections.singletonList("§7Click here to remove this material from the list"));
|
||||||
meta.addItemFlags(ItemFlag.values());
|
meta.addItemFlags(ItemFlag.values());
|
||||||
|
|
||||||
|
|
@ -217,22 +216,22 @@ public class MaterialSelectSettingGui extends MappedElementListConfigGui<Namespa
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Collection<NamespacedKey> getEveryDisplayableInstanceOfGeneric() {
|
protected Collection<Material> getEveryDisplayableInstanceOfGeneric() {
|
||||||
return this.defaultMaterials;
|
return this.defaultMaterials;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void updateElement(NamespacedKey material, GuiItem element) {
|
protected void updateElement(Material material, GuiItem element) {
|
||||||
// Nothing happen here I think
|
// Nothing happen here I think
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected GuiItem newElementRequested(NamespacedKey material, GuiItem newItem) {
|
protected GuiItem newElementRequested(Material material, GuiItem newItem) {
|
||||||
newItem.setAction(event -> {
|
newItem.setAction(event -> {
|
||||||
if(this.instantRemove){
|
if(this.instantRemove){
|
||||||
removeMaterial(material);
|
removeMaterial(material);
|
||||||
}else {
|
}else {
|
||||||
String materialName = CasedStringUtil.snakeToUpperSpacedCase(material.getKey().toLowerCase());
|
String materialName = CasedStringUtil.snakeToUpperSpacedCase(material.name().toLowerCase());
|
||||||
|
|
||||||
// Create and show confirm remove gui.
|
// Create and show confirm remove gui.
|
||||||
ConfirmActionGui confirmGui = new ConfirmActionGui(
|
ConfirmActionGui confirmGui = new ConfirmActionGui(
|
||||||
|
|
@ -251,7 +250,7 @@ public class MaterialSelectSettingGui extends MappedElementListConfigGui<Namespa
|
||||||
return newItem;
|
return newItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeMaterial(NamespacedKey material) {
|
private void removeMaterial(Material material) {
|
||||||
if(this.elementGuiMap.containsKey(material)){
|
if(this.elementGuiMap.containsKey(material)){
|
||||||
this.nowMaterialHash ^= material.hashCode();
|
this.nowMaterialHash ^= material.hashCode();
|
||||||
setSaveItem();
|
setSaveItem();
|
||||||
|
|
@ -261,18 +260,18 @@ public class MaterialSelectSettingGui extends MappedElementListConfigGui<Namespa
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected GuiItem findItemFromElement(NamespacedKey generic, GuiItem element) {
|
protected GuiItem findItemFromElement(Material generic, GuiItem element) {
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected GuiItem findGuiItemForRemoval(NamespacedKey generic, GuiItem element) {
|
protected GuiItem findGuiItemForRemoval(Material generic, GuiItem element) {
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int hashFromMaterialList(List<NamespacedKey> materialList){
|
private static int hashFromMaterialList(List<Material> materialList){
|
||||||
int defaultMaterialHash = 0;
|
int defaultMaterialHash = 0;
|
||||||
for (NamespacedKey material : materialList) {
|
for (Material material : materialList) {
|
||||||
defaultMaterialHash ^= material.hashCode();
|
defaultMaterialHash ^= material.hashCode();
|
||||||
}
|
}
|
||||||
return defaultMaterialHash;
|
return defaultMaterialHash;
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,11 @@ import org.bukkit.entity.HumanEntity;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import xyz.alexcrea.cuanvil.anvil.AnvilUseType;
|
|
||||||
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
||||||
import xyz.alexcrea.cuanvil.config.WorkPenaltyType;
|
import xyz.alexcrea.cuanvil.config.WorkPenaltyType;
|
||||||
import xyz.alexcrea.cuanvil.gui.config.global.BasicConfigGui;
|
import xyz.alexcrea.cuanvil.gui.config.global.BasicConfigGui;
|
||||||
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
|
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
|
||||||
|
import xyz.alexcrea.cuanvil.util.AnvilUseType;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
|
|
|
||||||
|
|
@ -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<Exception> onError = null;
|
|
||||||
@Nullable
|
|
||||||
public Function<String, String> 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<String> 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<String, String> 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<String, String> prepareParameters(){
|
|
||||||
var parameters = new HashMap<String, String>();
|
|
||||||
|
|
||||||
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<Exception> 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<String, String> getRawVersion) {
|
|
||||||
this.getRawVersion = getRawVersion;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -5,7 +5,6 @@ import io.delilaheve.util.ConfigOptions;
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
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.LoreEditConfigUtil;
|
||||||
import xyz.alexcrea.cuanvil.util.config.LoreEditType;
|
import xyz.alexcrea.cuanvil.util.config.LoreEditType;
|
||||||
|
|
||||||
|
|
@ -19,9 +18,6 @@ public class PluginSetDefault {
|
||||||
|
|
||||||
int nbSet = 0;
|
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, CAP_ANVIL_COST, DEFAULT_CAP_ANVIL_COST);
|
||||||
nbSet += trySetDefault(config, MAX_ANVIL_COST, DEFAULT_MAX_ANVIL_COST);
|
nbSet += trySetDefault(config, MAX_ANVIL_COST, DEFAULT_MAX_ANVIL_COST);
|
||||||
nbSet += trySetDefault(config, REMOVE_ANVIL_COST_LIMIT, DEFAULT_REMOVE_ANVIL_COST_LIMIT);
|
nbSet += trySetDefault(config, 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, ALLOW_HEXADECIMAL_COLOR, DEFAULT_ALLOW_HEXADECIMAL_COLOR);
|
||||||
nbSet += trySetDefault(config, PERMISSION_NEEDED_FOR_COLOR, DEFAULT_PERMISSION_NEEDED_FOR_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, 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
|
// Lore Edit defaults
|
||||||
for (@NotNull LoreEditType value : LoreEditType.values()) {
|
for (@NotNull LoreEditType value : LoreEditType.values()) {
|
||||||
|
|
@ -61,11 +57,6 @@ public class PluginSetDefault {
|
||||||
|
|
||||||
nbSet += trySetDefault(config, PAPER_EDIT_ORDER, DEFAULT_PAPER_EDIT_ORDER);
|
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) {
|
if (nbSet > 0) {
|
||||||
CustomAnvil.instance.getLogger().info("Adding " + nbSet + " absent default config values.");
|
CustomAnvil.instance.getLogger().info("Adding " + nbSet + " absent default config values.");
|
||||||
ConfigHolder.DEFAULT_CONFIG.saveToDisk(true);
|
ConfigHolder.DEFAULT_CONFIG.saveToDisk(true);
|
||||||
|
|
|
||||||
|
|
@ -77,12 +77,6 @@ public class UpdateHandler {
|
||||||
if (hadUpdate) {
|
if (hadUpdate) {
|
||||||
CustomAnvil.instance.getLogger().info("Updating Done !");
|
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<ConfigHolder> toSave) {
|
private static void finishConfiguration(@Nonnull String newVersion, @Nonnull Set<ConfigHolder> toSave) {
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,22 @@ public class UpdateUtils {
|
||||||
return Version.fromString(versionString);
|
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) {
|
public static void addToStringList(FileConfiguration config, String path, String... toAdd) {
|
||||||
List<String> groups = new ArrayList<>(config.getStringList(path));
|
List<String> groups = new ArrayList<>(config.getStringList(path));
|
||||||
groups.addAll(Arrays.asList(toAdd));
|
groups.addAll(Arrays.asList(toAdd));
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,7 @@ public record Version(int major, int minor, int patch) {
|
||||||
int[] versionParts = new int[]{0, 0, 0};
|
int[] versionParts = new int[]{0, 0, 0};
|
||||||
|
|
||||||
for (int i = 0; i < Math.min(3, partialVersion.length); i++) {
|
for (int i = 0; i < Math.min(3, partialVersion.length); i++) {
|
||||||
try {
|
versionParts[i] = Integer.parseInt(partialVersion[i]);
|
||||||
versionParts[i] = Integer.parseInt(partialVersion[i]);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return new Version(versionParts[0], versionParts[1], versionParts[2]);
|
return new Version(versionParts[0], versionParts[1], versionParts[2]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package xyz.alexcrea.cuanvil.update.plugin;
|
package xyz.alexcrea.cuanvil.update.plugin;
|
||||||
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.NamespacedKey;
|
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
@ -12,7 +11,6 @@ import xyz.alexcrea.cuanvil.group.AbstractMaterialGroup;
|
||||||
import xyz.alexcrea.cuanvil.group.IncludeGroup;
|
import xyz.alexcrea.cuanvil.group.IncludeGroup;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
|
@ -71,12 +69,7 @@ public class PUpdate_1_11_0 {
|
||||||
|
|
||||||
// Create new group
|
// Create new group
|
||||||
IncludeGroup group = new IncludeGroup(toolset);
|
IncludeGroup group = new IncludeGroup(toolset);
|
||||||
NamespacedKey[] keys = new NamespacedKey[toolMats.length];
|
group.addAll(toolMats);
|
||||||
for (int i = 0; i < toolMats.length; i++) {
|
|
||||||
keys[i] = toolMats[i].getKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
group.addAll(keys);
|
|
||||||
|
|
||||||
MaterialGroupApi.addMaterialGroup(group, true);
|
MaterialGroupApi.addMaterialGroup(group, true);
|
||||||
|
|
||||||
|
|
@ -84,8 +77,8 @@ public class PUpdate_1_11_0 {
|
||||||
if (tools == null) return;
|
if (tools == null) return;
|
||||||
if (!(tools instanceof IncludeGroup include)) return;
|
if (!(tools instanceof IncludeGroup include)) return;
|
||||||
|
|
||||||
List<NamespacedKey> mats = List.of(keys);
|
List<Material> mats = List.of(toolMats);
|
||||||
Set<NamespacedKey> matSet = include.getNonGroupInheritedMaterials();
|
Set<Material> matSet = include.getNonGroupInheritedMaterials();
|
||||||
if (!matSet.containsAll(mats)) return;
|
if (!matSet.containsAll(mats)) return;
|
||||||
|
|
||||||
mats.forEach(matSet::remove);
|
mats.forEach(matSet::remove);
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@ package xyz.alexcrea.cuanvil.update.plugin;
|
||||||
|
|
||||||
import io.delilaheve.util.ConfigOptions;
|
import io.delilaheve.util.ConfigOptions;
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
import xyz.alexcrea.cuanvil.anvil.AnvilUseType;
|
|
||||||
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
||||||
import xyz.alexcrea.cuanvil.config.WorkPenaltyType;
|
import xyz.alexcrea.cuanvil.config.WorkPenaltyType;
|
||||||
import xyz.alexcrea.cuanvil.gui.config.settings.WorkPenaltyTypeSettingGui;
|
import xyz.alexcrea.cuanvil.gui.config.settings.WorkPenaltyTypeSettingGui;
|
||||||
|
import xyz.alexcrea.cuanvil.util.AnvilUseType;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,10 @@ import org.bukkit.configuration.file.YamlConfiguration
|
||||||
import org.bukkit.plugin.java.JavaPlugin
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
import xyz.alexcrea.cuanvil.api.event.CAConfigReadyEvent
|
import xyz.alexcrea.cuanvil.api.event.CAConfigReadyEvent
|
||||||
import xyz.alexcrea.cuanvil.api.event.CAEnchantRegistryReadyEvent
|
import xyz.alexcrea.cuanvil.api.event.CAEnchantRegistryReadyEvent
|
||||||
import xyz.alexcrea.cuanvil.command.CustomAnvilCommand
|
|
||||||
import xyz.alexcrea.cuanvil.command.EditConfigExecutor
|
import xyz.alexcrea.cuanvil.command.EditConfigExecutor
|
||||||
import xyz.alexcrea.cuanvil.command.ReloadExecutor
|
import xyz.alexcrea.cuanvil.command.ReloadExecutor
|
||||||
import xyz.alexcrea.cuanvil.config.ConfigHolder
|
import xyz.alexcrea.cuanvil.config.ConfigHolder
|
||||||
import xyz.alexcrea.cuanvil.dependency.DependencyManager
|
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.dependency.util.PlatformUtil
|
||||||
import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry
|
import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry
|
||||||
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui
|
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui
|
||||||
|
|
@ -21,10 +18,9 @@ import xyz.alexcrea.cuanvil.listener.AnvilCloseListener
|
||||||
import xyz.alexcrea.cuanvil.listener.AnvilResultListener
|
import xyz.alexcrea.cuanvil.listener.AnvilResultListener
|
||||||
import xyz.alexcrea.cuanvil.listener.ChatEventListener
|
import xyz.alexcrea.cuanvil.listener.ChatEventListener
|
||||||
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener
|
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener
|
||||||
import xyz.alexcrea.cuanvil.update.ModrinthUpdateChecker
|
|
||||||
import xyz.alexcrea.cuanvil.update.PluginSetDefault
|
import xyz.alexcrea.cuanvil.update.PluginSetDefault
|
||||||
import xyz.alexcrea.cuanvil.update.UpdateHandler
|
import xyz.alexcrea.cuanvil.update.UpdateHandler
|
||||||
import xyz.alexcrea.cuanvil.util.MetricsUtil
|
import xyz.alexcrea.cuanvil.util.Metrics
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileReader
|
import java.io.FileReader
|
||||||
import java.util.logging.Level
|
import java.util.logging.Level
|
||||||
|
|
@ -35,8 +31,8 @@ import java.util.logging.Level
|
||||||
open class CustomAnvil : JavaPlugin() {
|
open class CustomAnvil : JavaPlugin() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
// pluginIDS
|
// bstats plugin id
|
||||||
private const val modrinthPluginID = "S75Ueiq9"
|
private const val bstatsPluginId = 20923
|
||||||
|
|
||||||
// Permission string required to use the plugin's features
|
// Permission string required to use the plugin's features
|
||||||
const val affectedByPluginPermission = "ca.affected"
|
const val affectedByPluginPermission = "ca.affected"
|
||||||
|
|
@ -50,13 +46,9 @@ open class CustomAnvil : JavaPlugin() {
|
||||||
// Permission string required to reload the config
|
// Permission string required to reload the config
|
||||||
const val commandReloadPermission = "ca.command.reload"
|
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
|
// Permission string required to edit the plugin's config
|
||||||
const val editConfigPermission = "ca.config.edit"
|
const val editConfigPermission = "ca.config.edit"
|
||||||
|
|
||||||
|
|
||||||
// Command Name to reload the config
|
// Command Name to reload the config
|
||||||
const val commandReloadName = "anvilconfigreload"
|
const val commandReloadName = "anvilconfigreload"
|
||||||
|
|
||||||
|
|
@ -69,8 +61,6 @@ open class CustomAnvil : JavaPlugin() {
|
||||||
// Chat message listener
|
// Chat message listener
|
||||||
lateinit var chatListener: ChatEventListener
|
lateinit var chatListener: ChatEventListener
|
||||||
|
|
||||||
var latestVer: String? = null
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logging handler
|
* Logging handler
|
||||||
*/
|
*/
|
||||||
|
|
@ -91,99 +81,12 @@ 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
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup plugin for use
|
* Setup plugin for use
|
||||||
*/
|
*/
|
||||||
override fun onEnable() {
|
override fun onEnable() {
|
||||||
instance = this
|
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
|
// Disable old plugin name if exist
|
||||||
val potentialPlugin = Bukkit.getPluginManager().getPlugin("UnsafeEnchantsPlus")
|
val potentialPlugin = Bukkit.getPluginManager().getPlugin("UnsafeEnchantsPlus")
|
||||||
if (potentialPlugin != null) {
|
if (potentialPlugin != null) {
|
||||||
|
|
@ -192,43 +95,38 @@ open class CustomAnvil : JavaPlugin() {
|
||||||
logger.warning("Please note CustomAnvil is a more recent version of UnsafeEnchantsPlus")
|
logger.warning("Please note CustomAnvil is a more recent version of UnsafeEnchantsPlus")
|
||||||
}
|
}
|
||||||
|
|
||||||
val isPaper = PlatformUtil.isPaper
|
if(!PlatformUtil.isPaper) {
|
||||||
if(!isPaper) {
|
|
||||||
logger.warning("It seems you are using spigot")
|
logger.warning("It seems you are using spigot")
|
||||||
logger.warning("Please take notice that spigot is less supported than paper and derivatives")
|
logger.warning("Please take notice that spigot is less supported than paper and derivatives")
|
||||||
if(MinecraftVersionUtil.isTooNewForSpigot) {
|
|
||||||
logger.warning("If replace too expensive is not working this is likely because of spigot")
|
|
||||||
logger.warning("As native nms is not supported for spigot starting 26.1")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val loader = if(isPaper) "paper" else "spigot"
|
// Add commands
|
||||||
|
prepareCommand()
|
||||||
|
|
||||||
val version = description.version
|
// Load chat listener
|
||||||
val featured = if(version.contains("dev")) null else true
|
|
||||||
|
|
||||||
ModrinthUpdateChecker(modrinthPluginID, loader, null)
|
|
||||||
.setFeatured(featured)
|
|
||||||
.setOnError {
|
|
||||||
logger.log(Level.WARNING, "error trying to fetch latest update", it)
|
|
||||||
}
|
|
||||||
.checkVersion { latestVer: String? ->
|
|
||||||
CustomAnvil.latestVer = latestVer
|
|
||||||
if(latestVer == null || version.contains(latestVer)) return@checkVersion
|
|
||||||
|
|
||||||
logger.warning("An update may be available: $latestVer")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun registerListeners() {
|
|
||||||
// Register chat listener
|
|
||||||
chatListener = ChatEventListener()
|
chatListener = ChatEventListener()
|
||||||
server.pluginManager.registerEvents(chatListener, this)
|
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
|
// Register anvil events
|
||||||
server.pluginManager.registerEvents(PrepareAnvilListener(), this)
|
server.pluginManager.registerEvents(PrepareAnvilListener(), this)
|
||||||
server.pluginManager.registerEvents(AnvilResultListener(), this)
|
server.pluginManager.registerEvents(AnvilResultListener(), this)
|
||||||
server.pluginManager.registerEvents(AnvilCloseListener(DependencyManager.packetManager), 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(){
|
private fun loadEnchantmentSystem(){
|
||||||
|
|
@ -241,8 +139,7 @@ open class CustomAnvil : JavaPlugin() {
|
||||||
|
|
||||||
// Load config
|
// Load config
|
||||||
if (!ConfigHolder.loadNonDefaultConfig()) {
|
if (!ConfigHolder.loadNonDefaultConfig()) {
|
||||||
logger.log(Level.SEVERE,"Plugin has an issue while trying to load non default config... exiting...")
|
logger.log(Level.SEVERE,"could not load non default config.")
|
||||||
server.pluginManager.disablePlugin(this)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -260,11 +157,9 @@ open class CustomAnvil : JavaPlugin() {
|
||||||
MainConfigGui.getInstance().init(DependencyManager.packetManager)
|
MainConfigGui.getInstance().init(DependencyManager.packetManager)
|
||||||
GuiSharedConstant.loadConstants()
|
GuiSharedConstant.loadConstants()
|
||||||
|
|
||||||
// Prepare economy if possible
|
|
||||||
EconomyManager.setupEconomy(this)
|
|
||||||
|
|
||||||
// Finally, re add default we may be missing
|
// Finally, re add default we may be missing
|
||||||
PluginSetDefault.reAddMissingDefault()
|
PluginSetDefault.reAddMissingDefault()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reloadResource(
|
fun reloadResource(
|
||||||
|
|
@ -316,8 +211,6 @@ open class CustomAnvil : JavaPlugin() {
|
||||||
|
|
||||||
command = getCommand(commandConfigName)
|
command = getCommand(commandConfigName)
|
||||||
command?.setExecutor(EditConfigExecutor())
|
command?.setExecutor(EditConfigExecutor())
|
||||||
|
|
||||||
CustomAnvilCommand(this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,14 @@ package io.delilaheve.util
|
||||||
|
|
||||||
import io.delilaheve.CustomAnvil
|
import io.delilaheve.CustomAnvil
|
||||||
import io.delilaheve.util.EnchantmentUtil.enchantmentName
|
import io.delilaheve.util.EnchantmentUtil.enchantmentName
|
||||||
|
import org.bukkit.Material
|
||||||
import org.bukkit.NamespacedKey
|
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.ConfigHolder
|
||||||
import xyz.alexcrea.cuanvil.config.WorkPenaltyType
|
import xyz.alexcrea.cuanvil.config.WorkPenaltyType
|
||||||
import xyz.alexcrea.cuanvil.config.WorkPenaltyType.WorkPenaltyPart
|
import xyz.alexcrea.cuanvil.config.WorkPenaltyType.WorkPenaltyPart
|
||||||
import xyz.alexcrea.cuanvil.dependency.DependencyManager
|
import xyz.alexcrea.cuanvil.dependency.DependencyManager
|
||||||
import xyz.alexcrea.cuanvil.dependency.economy.EconomyManager
|
|
||||||
import xyz.alexcrea.cuanvil.enchant.CAEnchantment
|
import xyz.alexcrea.cuanvil.enchant.CAEnchantment
|
||||||
import xyz.alexcrea.cuanvil.util.dialog.AnvilRenameDialogUtil
|
import xyz.alexcrea.cuanvil.util.AnvilUseType
|
||||||
import java.math.BigDecimal
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -24,9 +21,6 @@ object ConfigOptions {
|
||||||
// Path for config values
|
// 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 CAP_ANVIL_COST = "limit_repair_cost"
|
||||||
const val MAX_ANVIL_COST = "limit_repair_value"
|
const val MAX_ANVIL_COST = "limit_repair_value"
|
||||||
const val REMOVE_ANVIL_COST_LIMIT = "remove_repair_limit"
|
const val REMOVE_ANVIL_COST_LIMIT = "remove_repair_limit"
|
||||||
|
|
@ -48,8 +42,6 @@ object ConfigOptions {
|
||||||
const val PERMISSION_NEEDED_FOR_COLOR = "permission_needed_for_color"
|
const val PERMISSION_NEEDED_FOR_COLOR = "permission_needed_for_color"
|
||||||
const val USE_OF_COLOR_COST = "use_of_color_cost"
|
const val USE_OF_COLOR_COST = "use_of_color_cost"
|
||||||
|
|
||||||
const val PER_COLOR_CODE_PERMISSION = "per_color_code_permission"
|
|
||||||
|
|
||||||
// Work penalty config
|
// Work penalty config
|
||||||
const val WORK_PENALTY_ROOT = "work_penalty"
|
const val WORK_PENALTY_ROOT = "work_penalty"
|
||||||
const val WORK_PENALTY_INCREASE = "shared_increase"
|
const val WORK_PENALTY_INCREASE = "shared_increase"
|
||||||
|
|
@ -62,25 +54,15 @@ object ConfigOptions {
|
||||||
const val ENCHANT_COUNT_LIMIT_DEFAULT = "$ENCHANT_COUNT_LIMIT_ROOT.default"
|
const val ENCHANT_COUNT_LIMIT_DEFAULT = "$ENCHANT_COUNT_LIMIT_ROOT.default"
|
||||||
const val ENCHANT_COUNT_LIMIT_ITEMS = "$ENCHANT_COUNT_LIMIT_ROOT.items"
|
const val ENCHANT_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_LIMIT_ROOT = "enchant_limits"
|
||||||
const val ENCHANT_VALUES_ROOT = "enchant_values"
|
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 DISABLE_MERGE_OVER_ROOT = "disable-merge-over"
|
||||||
|
|
||||||
const val IMMUTABLE_ENCHANTMENT_LIST = "immutable_enchantments"
|
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
|
// Keys for specific enchantment values
|
||||||
private const val KEY_BOOK = "book"
|
private const val KEY_BOOK = "book"
|
||||||
|
|
@ -117,23 +99,12 @@ object ConfigOptions {
|
||||||
const val DEFAULT_PERMISSION_NEEDED_FOR_COLOR = true
|
const val DEFAULT_PERMISSION_NEEDED_FOR_COLOR = true
|
||||||
const val DEFAULT_USE_OF_COLOR_COST = 0
|
const val DEFAULT_USE_OF_COLOR_COST = 0
|
||||||
|
|
||||||
const val DEFAULT_PER_COLOR_CODE_PERMISSION = false
|
const val DEFAULT_ENCHANT_LIMIT = 5
|
||||||
|
|
||||||
// Monetary configs
|
|
||||||
const val DEFAULT_SHOULD_USE_MONEY = false
|
|
||||||
const val DEFAULT_MONEY_CURRENCY = "default"
|
|
||||||
const val DEFAULT_MONEY_MULTIPLIER = 1.0
|
|
||||||
|
|
||||||
// Debug flag
|
// Debug flag
|
||||||
private const val DEFAULT_DEBUG_LOG = false
|
private const val DEFAULT_DEBUG_LOG = false
|
||||||
private const val DEFAULT_VERBOSE_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
|
// Config Ranges
|
||||||
// -------------
|
// -------------
|
||||||
|
|
@ -158,11 +129,9 @@ object ConfigOptions {
|
||||||
@JvmField
|
@JvmField
|
||||||
val USE_OF_COLOR_COST_RANGE = 0..1000
|
val USE_OF_COLOR_COST_RANGE = 0..1000
|
||||||
|
|
||||||
@JvmField
|
|
||||||
val DIALOG_MAX_SIZE_RANGE = 0..Int.MAX_VALUE
|
|
||||||
|
|
||||||
// Valid range for an enchantment limit
|
// Valid range for an enchantment limit
|
||||||
const val ENCHANT_LIMIT = 255
|
@JvmField
|
||||||
|
val ENCHANT_LIMIT_RANGE = 1..255
|
||||||
|
|
||||||
// Valid range for an enchantment count limit
|
// Valid range for an enchantment count limit
|
||||||
@JvmField
|
@JvmField
|
||||||
|
|
@ -178,11 +147,6 @@ object ConfigOptions {
|
||||||
// Default max before merge disabled (negative mean enabled)
|
// Default max before merge disabled (negative mean enabled)
|
||||||
const val DEFAULT_MAX_BEFORE_MERGE_DISABLED = -1
|
const val DEFAULT_MAX_BEFORE_MERGE_DISABLED = -1
|
||||||
|
|
||||||
// -----------
|
|
||||||
// Permissions
|
|
||||||
// -----------
|
|
||||||
private const val RENAME_DIALOG_PERMISSION = "ca.rename.dialog"
|
|
||||||
|
|
||||||
// -------------
|
// -------------
|
||||||
// Get methods
|
// Get methods
|
||||||
// -------------
|
// -------------
|
||||||
|
|
@ -335,16 +299,6 @@ object ConfigOptions {
|
||||||
.getBoolean(PERMISSION_NEEDED_FOR_COLOR, DEFAULT_PERMISSION_NEEDED_FOR_COLOR)
|
.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
|
* How many xp should use of color should cost
|
||||||
*/
|
*/
|
||||||
|
|
@ -391,12 +345,22 @@ object ConfigOptions {
|
||||||
return WorkPenaltyPart(penaltyIncrease, penaltyAdditive, exclusivePenaltyIncrease, exclusivePenaltyAdditive)
|
return WorkPenaltyPart(penaltyIncrease, penaltyAdditive, exclusivePenaltyIncrease, exclusivePenaltyAdditive)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default enchantment limit
|
||||||
|
*/
|
||||||
|
private val defaultEnchantLimit: Int
|
||||||
|
get() {
|
||||||
|
return ConfigHolder.DEFAULT_CONFIG
|
||||||
|
.config
|
||||||
|
.getInt(DEFAULT_LIMIT_PATH, DEFAULT_ENCHANT_LIMIT)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get material enchantment count limit
|
* Get material enchantment count limit
|
||||||
*
|
*
|
||||||
* @return the current enchantment limit. -1 if none
|
* @return the current enchantment limit. -1 if none
|
||||||
*/
|
*/
|
||||||
fun getEnchantCountLimit(type: NamespacedKey): Int? {
|
fun getEnchantCountLimit(type: Material): Int? {
|
||||||
val limit = materialEnchantCountLimit(type)
|
val limit = materialEnchantCountLimit(type)
|
||||||
|
|
||||||
if(limit != null) return limit
|
if(limit != null) return limit
|
||||||
|
|
@ -410,8 +374,8 @@ object ConfigOptions {
|
||||||
*
|
*
|
||||||
* @return The current enchantment limit. -1 if none
|
* @return The current enchantment limit. -1 if none
|
||||||
*/
|
*/
|
||||||
private fun materialEnchantCountLimit(type: NamespacedKey): Int? {
|
private fun materialEnchantCountLimit(type: Material): Int? {
|
||||||
val path = "$ENCHANT_COUNT_LIMIT_ITEMS.${type.key.lowercase()}"
|
val path = "$ENCHANT_COUNT_LIMIT_ITEMS.${type.key.key.lowercase()}"
|
||||||
if(!ConfigHolder.DEFAULT_CONFIG.config.isInt(path))
|
if(!ConfigHolder.DEFAULT_CONFIG.config.isInt(path))
|
||||||
return null
|
return null
|
||||||
|
|
||||||
|
|
@ -451,90 +415,46 @@ object ConfigOptions {
|
||||||
.getBoolean(VERBOSE_DEBUG_LOGGING, DEFAULT_VERBOSE_DEBUG_LOG)
|
.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
|
* Get the given [enchantment]'s limit
|
||||||
*/
|
*/
|
||||||
fun enchantLimit(enchantment: CAEnchantment): Int {
|
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
|
// Test namespace
|
||||||
var limit = enchantLimit(enchantment.key.toString())
|
var limit = enchantLimit(enchantment.key.toString())
|
||||||
if (limit >= 0) return limit
|
if (limit != null) return limit
|
||||||
|
|
||||||
// Test legacy (name only)
|
// Test legacy (name only)
|
||||||
limit = enchantLimit(enchantment.enchantmentName)
|
limit = enchantLimit(enchantment.enchantmentName)
|
||||||
if (limit >= 0) return limit
|
if (limit != null) return limit
|
||||||
|
|
||||||
// Default to negative
|
// get default (and test old legacy if present)
|
||||||
return -1
|
return getDefaultLevel(enchantment.enchantmentName)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the given [enchantmentName]'s limit
|
* Get the given [enchantmentName]'s limit
|
||||||
*/
|
*/
|
||||||
private fun enchantLimit(enchantmentName: String): Int {
|
private fun enchantLimit(enchantmentName: String): Int? {
|
||||||
|
|
||||||
val path = "${ENCHANT_LIMIT_ROOT}.$enchantmentName"
|
val path = "${ENCHANT_LIMIT_ROOT}.$enchantmentName"
|
||||||
return CustomAnvil.instance.config
|
return CustomAnvil.instance
|
||||||
.getInt(path, -1)
|
.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 +526,20 @@ object ConfigOptions {
|
||||||
fun maxBeforeMergeDisabled(enchantment: CAEnchantment): Int {
|
fun maxBeforeMergeDisabled(enchantment: CAEnchantment): Int {
|
||||||
val key = enchantment.key.toString()
|
val key = enchantment.key.toString()
|
||||||
var value = maxBeforeMergeDisabled(key)
|
var value = maxBeforeMergeDisabled(key)
|
||||||
if (value >= 0) return value
|
if (value != null) return value
|
||||||
|
|
||||||
// Legacy name
|
// Legacy name
|
||||||
val legacy = enchantment.enchantmentName
|
val legacy = enchantment.enchantmentName
|
||||||
value = maxBeforeMergeDisabled(legacy)
|
value = maxBeforeMergeDisabled(legacy)
|
||||||
if (value >= 0) return value
|
if (value != null) return value
|
||||||
|
|
||||||
if (key == "minecraft:sweeping_edge") {
|
if (key == "minecraft:sweeping_edge") {
|
||||||
value = maxBeforeMergeDisabled("minecraft:sweeping")
|
value = maxBeforeMergeDisabled("minecraft:sweeping")
|
||||||
if (value >= 0) return value
|
if (value != null) return value
|
||||||
|
|
||||||
// legacy name of legacy enchantment name
|
// legacy name of legacy enchantment name
|
||||||
value = maxBeforeMergeDisabled("sweeping")
|
value = maxBeforeMergeDisabled("sweeping")
|
||||||
if (value >= 0) return value
|
if (value != null) return value
|
||||||
}
|
}
|
||||||
|
|
||||||
return DEFAULT_MAX_BEFORE_MERGE_DISABLED
|
return DEFAULT_MAX_BEFORE_MERGE_DISABLED
|
||||||
|
|
@ -629,13 +549,14 @@ object ConfigOptions {
|
||||||
* Get the given [enchantmentName]'s level before merge is disabled
|
* Get the given [enchantmentName]'s level before merge is disabled
|
||||||
* a negative value would mean never disabled
|
* a negative value would mean never disabled
|
||||||
*/
|
*/
|
||||||
private fun maxBeforeMergeDisabled(enchantmentName: String): Int {
|
private fun maxBeforeMergeDisabled(enchantmentName: String): Int? {
|
||||||
// find if set
|
// find if set
|
||||||
val path = "${DISABLE_MERGE_OVER_ROOT}.$enchantmentName"
|
val path = "${DISABLE_MERGE_OVER_ROOT}.$enchantmentName"
|
||||||
|
|
||||||
return CustomAnvil.instance
|
return CustomAnvil.instance
|
||||||
.config
|
.config
|
||||||
.getInt(path, -1)
|
.getInt(path, ENCHANT_LIMIT_RANGE.min() - 1)
|
||||||
|
.takeIf { it in ENCHANT_LIMIT_RANGE }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isImmutable(key: NamespacedKey): Boolean {
|
fun isImmutable(key: NamespacedKey): Boolean {
|
||||||
|
|
@ -651,29 +572,4 @@ object ConfigOptions {
|
||||||
return false
|
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))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@ import io.delilaheve.CustomAnvil
|
||||||
import org.bukkit.entity.HumanEntity
|
import org.bukkit.entity.HumanEntity
|
||||||
import org.bukkit.inventory.ItemStack
|
import org.bukkit.inventory.ItemStack
|
||||||
import xyz.alexcrea.cuanvil.config.ConfigHolder
|
import xyz.alexcrea.cuanvil.config.ConfigHolder
|
||||||
|
import xyz.alexcrea.cuanvil.dependency.DependencyManager
|
||||||
import xyz.alexcrea.cuanvil.enchant.CAEnchantment
|
import xyz.alexcrea.cuanvil.enchant.CAEnchantment
|
||||||
import xyz.alexcrea.cuanvil.group.ConflictType
|
import xyz.alexcrea.cuanvil.group.ConflictType
|
||||||
import xyz.alexcrea.cuanvil.util.MaterialUtil.customType
|
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
|
|
@ -31,97 +31,87 @@ object EnchantmentUtil {
|
||||||
) = mutableMapOf<CAEnchantment, Int>().apply {
|
) = mutableMapOf<CAEnchantment, Int>().apply {
|
||||||
putAll(this@combineWith)
|
putAll(this@combineWith)
|
||||||
|
|
||||||
CustomAnvil.verboseLog("Testing merge")
|
|
||||||
val bypassFuse = player.hasPermission(CustomAnvil.bypassFusePermission)
|
val bypassFuse = player.hasPermission(CustomAnvil.bypassFusePermission)
|
||||||
val bypassLevel = player.hasPermission(CustomAnvil.bypassLevelPermission)
|
val bypassLevel = player.hasPermission(CustomAnvil.bypassLevelPermission)
|
||||||
|
|
||||||
var maxEnchantCount = ConfigOptions.getEnchantCountLimit(item.customType)
|
var maxEnchantCount = ConfigOptions.getEnchantCountLimit(item.type)
|
||||||
if(maxEnchantCount == null || maxEnchantCount < 0) maxEnchantCount = Int.MAX_VALUE
|
if(maxEnchantCount == null || maxEnchantCount < 0) maxEnchantCount = Int.MAX_VALUE
|
||||||
|
|
||||||
val allowed = other.filter { (enchantment, _) -> enchantment.isAllowed(player) }
|
other.forEach { (enchantment, level) ->
|
||||||
val new = allowed.filter{ (enchantment, _) -> !containsKey(enchantment)}
|
if(!enchantment.isAllowed(player)) return@forEach
|
||||||
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
|
// 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 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)) {
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
|
||||||
// ... 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 {
|
else {
|
||||||
// We test if it is allowed to merge at this level
|
val oldLevel = this[enchantment]!! // <- should not be null. (enchantment already in result list)
|
||||||
if(!bypassLevel){
|
|
||||||
val maxBeforeDisabled = ConfigOptions.maxBeforeMergeDisabled(enchantment)
|
if(bypassFuse){
|
||||||
if((maxBeforeDisabled > 0) && (oldLevel >= maxBeforeDisabled)) {
|
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(
|
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
|
return@forEach
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we increase the enchantment level by 1
|
// ... and they're not the same level
|
||||||
var newLevel = oldLevel + 1
|
if (oldLevel != cappedLevel) {
|
||||||
newLevel = max(min(newLevel, maxLevel), oldLevel)
|
// apply the greater of the two or left one if right is above max
|
||||||
this[enchantment] = newLevel
|
this[enchantment] = max(oldLevel, cappedLevel)
|
||||||
}
|
|
||||||
|
|
||||||
if(bypassFuse){
|
}
|
||||||
CustomAnvil.verboseLog("Bypassed conflict check for ${enchantment.key}")
|
// ... and they're the same level
|
||||||
} else {
|
else {
|
||||||
val conflictType = ConfigHolder.CONFLICT_HOLDER.conflictManager
|
// We test if it is allowed to merge at this level
|
||||||
.isConflicting(this, item, enchantment)
|
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,6 @@ import org.bukkit.Material.ENCHANTED_BOOK
|
||||||
import org.bukkit.inventory.ItemStack
|
import org.bukkit.inventory.ItemStack
|
||||||
import org.bukkit.inventory.meta.Damageable
|
import org.bukkit.inventory.meta.Damageable
|
||||||
import xyz.alexcrea.cuanvil.enchant.CAEnchantment
|
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.ceil
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
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
|
* Set this [ItemStack]s durability from a combination of the
|
||||||
* [first] and [second] item's durability values
|
* [first] and [second] item's durability values
|
||||||
|
|
@ -64,9 +54,7 @@ object ItemUtil {
|
||||||
val secondDurability = durability - secondDamage
|
val secondDurability = durability - secondDamage
|
||||||
val combinedDurability = firstDurability + secondDurability
|
val combinedDurability = firstDurability + secondDurability
|
||||||
val newDurability = min(combinedDurability, durability)
|
val newDurability = min(combinedDurability, durability)
|
||||||
|
it.damage = durability - newDurability
|
||||||
val maxDamage = maxDamage(it)
|
|
||||||
it.damage = min(durability - newDurability, maxDamage)
|
|
||||||
itemMeta = it
|
itemMeta = it
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -102,5 +90,5 @@ object ItemUtil {
|
||||||
*/
|
*/
|
||||||
fun ItemStack.canMergeWith(
|
fun ItemStack.canMergeWith(
|
||||||
other: ItemStack?
|
other: ItemStack?
|
||||||
) = (other != null) && (customType == other.customType || (other.isEnchantedBook()))
|
) = (other != null) && (type == other.type || (other.isEnchantedBook()))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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"))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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<CAEnchantment, Int>,
|
|
||||||
resultEnchants: MutableMap<CAEnchantment, Int>
|
|
||||||
): 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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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<out String>
|
|
||||||
): 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<out String>): Boolean
|
|
||||||
|
|
||||||
open fun allowed(sender: CommandSender): Boolean {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun tabCompleter(
|
|
||||||
sender: CommandSender,
|
|
||||||
args: Array<out String>,
|
|
||||||
list: MutableList<String>) {
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun description(): String {
|
|
||||||
return "no description"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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<out String>
|
|
||||||
): Boolean {
|
|
||||||
// Find sub command to execute based on the provided command name
|
|
||||||
val subcmd: CASubCommand?
|
|
||||||
val newargs: Array<out String>
|
|
||||||
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<out String>
|
|
||||||
): MutableList<String> {
|
|
||||||
val result = ArrayList<String>()
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<out String>): EnumSet<DiagParams> {
|
|
||||||
val result = EnumSet.noneOf(DiagParams::class.java)
|
|
||||||
val argSet = HashSet<String>()
|
|
||||||
|
|
||||||
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<out String>,
|
|
||||||
list: MutableList<String>) {
|
|
||||||
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<out String>
|
|
||||||
): 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<DiagParams>){
|
|
||||||
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<Plugin?> = ArrayList<Plugin?>()
|
|
||||||
val disabledPlugins: MutableList<Plugin?> = ArrayList<Plugin?>()
|
|
||||||
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<Plugin?> = 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<String, Int>()
|
|
||||||
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()}")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -2,21 +2,17 @@ package xyz.alexcrea.cuanvil.command
|
||||||
|
|
||||||
import io.delilaheve.CustomAnvil
|
import io.delilaheve.CustomAnvil
|
||||||
import org.bukkit.command.Command
|
import org.bukkit.command.Command
|
||||||
|
import org.bukkit.command.CommandExecutor
|
||||||
import org.bukkit.command.CommandSender
|
import org.bukkit.command.CommandSender
|
||||||
import org.bukkit.entity.HumanEntity
|
import org.bukkit.entity.HumanEntity
|
||||||
import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil
|
import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil
|
||||||
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui
|
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui
|
||||||
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions
|
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions
|
||||||
|
|
||||||
class EditConfigExecutor: CASubCommand() {
|
class EditConfigExecutor : CommandExecutor {
|
||||||
|
|
||||||
override fun executeCommand(sender: CommandSender,
|
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
|
||||||
cmd: Command,
|
if (!sender.hasPermission(CustomAnvil.editConfigPermission)) {
|
||||||
cmdstr: String,
|
|
||||||
args: Array<out String>): Boolean {
|
|
||||||
if (sender !is HumanEntity) return false
|
|
||||||
|
|
||||||
if (!allowed(sender)) {
|
|
||||||
sender.sendMessage(GuiGlobalActions.NO_EDIT_PERM)
|
sender.sendMessage(GuiGlobalActions.NO_EDIT_PERM)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -29,17 +25,10 @@ class EditConfigExecutor: CASubCommand() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sender !is HumanEntity) return false
|
||||||
MainConfigGui.getInstance().show(sender)
|
MainConfigGui.getInstance().show(sender)
|
||||||
|
|
||||||
return true
|
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"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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<String, CASubCommand>
|
|
||||||
|
|
||||||
override fun executeCommand(sender: CommandSender,
|
|
||||||
cmd: Command,
|
|
||||||
cmdstr: String,
|
|
||||||
args: Array<out String>): 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"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -11,13 +11,9 @@ import xyz.alexcrea.cuanvil.dependency.DependencyManager
|
||||||
import xyz.alexcrea.cuanvil.gui.config.global.*
|
import xyz.alexcrea.cuanvil.gui.config.global.*
|
||||||
import xyz.alexcrea.cuanvil.update.UpdateHandler
|
import xyz.alexcrea.cuanvil.update.UpdateHandler
|
||||||
|
|
||||||
class ReloadExecutor : CASubCommand() {
|
class ReloadExecutor : CommandExecutor {
|
||||||
|
override fun onCommand(sender: CommandSender, cmd: Command, cmdstr: String, args: Array<out String>): Boolean {
|
||||||
override fun executeCommand(sender: CommandSender,
|
if (!sender.hasPermission(CustomAnvil.commandReloadPermission)) {
|
||||||
cmd: Command,
|
|
||||||
cmdstr: String,
|
|
||||||
args: Array<out String>): Boolean {
|
|
||||||
if (!allowed(sender)) {
|
|
||||||
sender.sendMessage("§cYou do not have permission to reload the config")
|
sender.sendMessage("§cYou do not have permission to reload the config")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -35,14 +31,6 @@ class ReloadExecutor : CASubCommand() {
|
||||||
return commandSuccess
|
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
|
* Execute the command, return true if success or false otherwise
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,23 @@
|
||||||
package xyz.alexcrea.cuanvil.dependency
|
package xyz.alexcrea.cuanvil.dependency
|
||||||
|
|
||||||
import com.maddoxh.superEnchants.SuperEnchants
|
import com.willfp.eco.core.gui.player
|
||||||
import io.delilaheve.CustomAnvil
|
import io.delilaheve.CustomAnvil
|
||||||
import net.kyori.adventure.text.Component
|
import net.kyori.adventure.text.Component
|
||||||
import org.bukkit.Bukkit
|
import org.bukkit.Bukkit
|
||||||
import org.bukkit.ChatColor
|
import org.bukkit.ChatColor
|
||||||
import org.bukkit.command.CommandSender
|
|
||||||
import org.bukkit.entity.HumanEntity
|
import org.bukkit.entity.HumanEntity
|
||||||
import org.bukkit.entity.Player
|
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent
|
import org.bukkit.event.inventory.InventoryClickEvent
|
||||||
import org.bukkit.event.inventory.PrepareAnvilEvent
|
import org.bukkit.event.inventory.PrepareAnvilEvent
|
||||||
import org.bukkit.inventory.AnvilInventory
|
import org.bukkit.inventory.AnvilInventory
|
||||||
import org.bukkit.inventory.Inventory
|
|
||||||
import org.bukkit.inventory.InventoryView
|
|
||||||
import org.bukkit.inventory.ItemStack
|
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.CAClickResultBypassEvent
|
||||||
import xyz.alexcrea.cuanvil.api.event.listener.CAEarlyPreAnvilBypassEvent
|
import xyz.alexcrea.cuanvil.api.event.listener.CAEarlyPreAnvilBypassEvent
|
||||||
import xyz.alexcrea.cuanvil.api.event.listener.CAPreAnvilBypassEvent
|
import xyz.alexcrea.cuanvil.api.event.listener.CAPreAnvilBypassEvent
|
||||||
import xyz.alexcrea.cuanvil.api.event.listener.CATreatAnvilResult2Event
|
import xyz.alexcrea.cuanvil.api.event.listener.CATreatAnvilResultEvent
|
||||||
import xyz.alexcrea.cuanvil.config.ConfigHolder
|
import xyz.alexcrea.cuanvil.config.ConfigHolder
|
||||||
import xyz.alexcrea.cuanvil.dependency.datapack.DataPackDependency
|
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.PacketManager
|
||||||
import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerSelector
|
import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerSelector
|
||||||
import xyz.alexcrea.cuanvil.dependency.plugins.*
|
import xyz.alexcrea.cuanvil.dependency.plugins.*
|
||||||
|
|
@ -32,14 +27,14 @@ import xyz.alexcrea.cuanvil.dependency.scheduler.TaskScheduler
|
||||||
import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil
|
import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil
|
||||||
import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.componentLore
|
import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.componentLore
|
||||||
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT
|
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT
|
||||||
import xyz.alexcrea.cuanvil.util.MetricsUtil.trackError
|
import xyz.alexcrea.cuanvil.util.AnvilUseType
|
||||||
import java.util.logging.Level
|
import java.util.logging.Level
|
||||||
|
|
||||||
object DependencyManager {
|
object DependencyManager {
|
||||||
|
|
||||||
lateinit var scheduler: TaskScheduler
|
lateinit var scheduler: TaskScheduler
|
||||||
lateinit var packetManager: PacketManager
|
lateinit var packetManager: PacketManager
|
||||||
var externGuiTester: GenericExternGuiTester = GenericExternGuiTester()
|
var externGuiTester: ExternGuiTester? = null
|
||||||
|
|
||||||
var enchantmentSquaredCompatibility: EnchantmentSquaredDependency? = null
|
var enchantmentSquaredCompatibility: EnchantmentSquaredDependency? = null
|
||||||
var ecoEnchantCompatibility: EcoEnchantDependency? = null
|
var ecoEnchantCompatibility: EcoEnchantDependency? = null
|
||||||
|
|
@ -50,8 +45,6 @@ object DependencyManager {
|
||||||
|
|
||||||
var axPlayerWarpsCompatibility: AxPlayerWarpsDependency? = null
|
var axPlayerWarpsCompatibility: AxPlayerWarpsDependency? = null
|
||||||
|
|
||||||
var itemsAdderCompatibility: ItemsAdderDependency? = null
|
|
||||||
|
|
||||||
val genericDependencies = ArrayList<GenericPluginDependency>()
|
val genericDependencies = ArrayList<GenericPluginDependency>()
|
||||||
|
|
||||||
fun loadDependency() {
|
fun loadDependency() {
|
||||||
|
|
@ -67,6 +60,7 @@ object DependencyManager {
|
||||||
// Packet Manager
|
// Packet Manager
|
||||||
val forceProtocolib = ConfigHolder.DEFAULT_CONFIG.config.getBoolean("force_protocolib", false)
|
val forceProtocolib = ConfigHolder.DEFAULT_CONFIG.config.getBoolean("force_protocolib", false)
|
||||||
packetManager = PacketManagerSelector.selectPacketManager(forceProtocolib)
|
packetManager = PacketManagerSelector.selectPacketManager(forceProtocolib)
|
||||||
|
externGuiTester = GuiTesterSelector.selectGuiTester
|
||||||
|
|
||||||
// Enchantment Squared dependency
|
// Enchantment Squared dependency
|
||||||
if (pluginManager.isPluginEnabled("EnchantsSquared")) {
|
if (pluginManager.isPluginEnabled("EnchantsSquared")) {
|
||||||
|
|
@ -103,12 +97,6 @@ object DependencyManager {
|
||||||
axPlayerWarpsCompatibility = AxPlayerWarpsDependency()
|
axPlayerWarpsCompatibility = AxPlayerWarpsDependency()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pluginManager.isPluginEnabled("ItemsAdder")){
|
|
||||||
val dependency = ItemsAdderDependency(pluginManager.getPlugin("ItemsAdder")!!)
|
|
||||||
itemsAdderCompatibility = dependency
|
|
||||||
genericDependencies.add(dependency)
|
|
||||||
}
|
|
||||||
|
|
||||||
// "Generic" dependencies
|
// "Generic" dependencies
|
||||||
if (pluginManager.isPluginEnabled("ToolStats"))
|
if (pluginManager.isPluginEnabled("ToolStats"))
|
||||||
genericDependencies.add(ToolStatsDependency(pluginManager.getPlugin("ToolStats")!!))
|
genericDependencies.add(ToolStatsDependency(pluginManager.getPlugin("ToolStats")!!))
|
||||||
|
|
@ -116,12 +104,6 @@ object DependencyManager {
|
||||||
if (pluginManager.isPluginEnabled("ItemsAdder"))
|
if (pluginManager.isPluginEnabled("ItemsAdder"))
|
||||||
genericDependencies.add(GenericPluginDependency(pluginManager.getPlugin("ItemsAdder")!!))
|
genericDependencies.add(GenericPluginDependency(pluginManager.getPlugin("ItemsAdder")!!))
|
||||||
|
|
||||||
if (pluginManager.isPluginEnabled("SuperEnchants")){
|
|
||||||
val compatibility = SuperEnchantDependency(pluginManager.getPlugin("SuperEnchants")!! as SuperEnchants)
|
|
||||||
if(compatibility.registerEnchantments())
|
|
||||||
genericDependencies.add(compatibility)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (dependency in genericDependencies)
|
for (dependency in genericDependencies)
|
||||||
dependency.redirectListeners()
|
dependency.redirectListeners()
|
||||||
|
|
||||||
|
|
@ -149,35 +131,26 @@ object DependencyManager {
|
||||||
ecoEnchantCompatibility?.handleConfigReload()
|
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)
|
// Return true if should bypass (either by a dependency or error)
|
||||||
// called before immutability test
|
// called before immutability test
|
||||||
fun earlyTryEventPreAnvilBypass(event: PrepareAnvilEvent, player: HumanEntity): Boolean {
|
fun earlyTryEventPreAnvilBypass(event: PrepareAnvilEvent, player: HumanEntity): Boolean {
|
||||||
try {
|
try {
|
||||||
return earlyUnsafeTryEventPreAnvilBypass(event, player)
|
return earlyUnsafeTryEventPreAnvilBypass(event, player)
|
||||||
} catch (e: Exception) {
|
} 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
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -190,7 +163,7 @@ object DependencyManager {
|
||||||
var bypass = bypassEvent.isCancelled
|
var bypass = bypassEvent.isCancelled
|
||||||
|
|
||||||
// Test if the inventory is a gui(version specific)
|
// Test if the inventory is a gui(version specific)
|
||||||
if (!bypass && externGuiTester.testIfGui(event.view)) bypass = true
|
if (!bypass && (externGuiTester?.testIfGui(event.view) == true)) bypass = true
|
||||||
|
|
||||||
// Test if in an ax player warp rating gui
|
// Test if in an ax player warp rating gui
|
||||||
if (!bypass && (axPlayerWarpsCompatibility?.testIfGui(player) == true)) bypass = true
|
if (!bypass && (axPlayerWarpsCompatibility?.testIfGui(player) == true)) bypass = true
|
||||||
|
|
@ -199,16 +172,29 @@ object DependencyManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true if should bypass (either by a dependency or error)
|
// 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 {
|
try {
|
||||||
return unsafeTryEventPreAnvilBypass(event, player)
|
return unsafeTryEventPreAnvilBypass(event, player)
|
||||||
} catch (e: Exception) {
|
} 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
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun unsafeTryEventPreAnvilBypass(event: PrepareAnvilEvent, player: Player): Boolean {
|
private fun unsafeTryEventPreAnvilBypass(event: PrepareAnvilEvent, player: HumanEntity): Boolean {
|
||||||
// Run the event
|
// Run the event
|
||||||
val bypassEvent = CAPreAnvilBypassEvent(event)
|
val bypassEvent = CAPreAnvilBypassEvent(event)
|
||||||
Bukkit.getPluginManager().callEvent(bypassEvent)
|
Bukkit.getPluginManager().callEvent(bypassEvent)
|
||||||
|
|
@ -233,24 +219,35 @@ object DependencyManager {
|
||||||
|
|
||||||
// Return null if there was an issue
|
// Return null if there was an issue
|
||||||
fun tryTreatAnvilResult(
|
fun tryTreatAnvilResult(
|
||||||
view: InventoryView,
|
event: PrepareAnvilEvent,
|
||||||
inventory: Inventory, // TODO REMOVE, use view instead on legacy removal
|
|
||||||
player: HumanEntity,
|
|
||||||
result: ItemStack,
|
result: ItemStack,
|
||||||
useType: AnvilUseType,
|
useType: AnvilUseType,
|
||||||
cost: AnvilCost
|
cost: Int
|
||||||
): ItemStack? {
|
): CATreatAnvilResultEvent? {
|
||||||
val treatEvent = CATreatAnvilResult2Event(view, inventory, useType, result, cost)
|
val treatEvent = CATreatAnvilResultEvent(event, useType, result, cost)
|
||||||
try {
|
try {
|
||||||
unsafeTryTreatAnvilResult(treatEvent)
|
unsafeTryTreatAnvilResult(treatEvent)
|
||||||
return treatEvent.result
|
return treatEvent;
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logExceptionAndClear(player, 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 null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun unsafeTryTreatAnvilResult(event: CATreatAnvilResult2Event) {
|
private fun unsafeTryTreatAnvilResult(event: CATreatAnvilResultEvent) {
|
||||||
Bukkit.getPluginManager().callEvent(event)
|
Bukkit.getPluginManager().callEvent(event)
|
||||||
|
|
||||||
excellentEnchantsCompatibility?.treatAnvilResult(event)
|
excellentEnchantsCompatibility?.treatAnvilResult(event)
|
||||||
|
|
@ -261,7 +258,20 @@ object DependencyManager {
|
||||||
try {
|
try {
|
||||||
return unsafeTryClickAnvilResultBypass(event, inventory)
|
return unsafeTryClickAnvilResultBypass(event, inventory)
|
||||||
} catch (e: Exception) {
|
} 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
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -287,31 +297,14 @@ object DependencyManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if the inventory is a gui(version specific)
|
// Test if the inventory is a gui(version specific)
|
||||||
if (!bypass && externGuiTester.testIfGui(event.view)) bypass = true
|
if (!bypass && (externGuiTester?.testIfGui(event.view) == true)) bypass = true
|
||||||
|
|
||||||
// Test if in an ax player warp rating gui
|
// Test if in an ax player warp rating gui
|
||||||
if (!bypass && (axPlayerWarpsCompatibility?.testIfGui(event.view.player) == true)) bypass = true
|
if (!bypass && (axPlayerWarpsCompatibility?.testIfGui(event.player) == true)) bypass = true
|
||||||
|
|
||||||
return bypass
|
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<Component?> {
|
fun stripLore(item: ItemStack): MutableList<Component?> {
|
||||||
val dummy = item.clone()
|
val dummy = item.clone()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,29 +6,29 @@ object MinecraftVersionUtil {
|
||||||
|
|
||||||
val craftbukkitVersion: String?
|
val craftbukkitVersion: String?
|
||||||
get() {
|
get() {
|
||||||
val version = UpdateUtils.currentMinecraftVersion()
|
val versionParts = UpdateUtils.currentMinecraftVersionArray()
|
||||||
if (version.major != 1) return null
|
if (versionParts[0] != 1) return null
|
||||||
|
|
||||||
return when (version.minor) {
|
return when (versionParts[1]) {
|
||||||
17 -> when (version.patch) {
|
17 -> when (versionParts[2]) {
|
||||||
0, 1 -> "1_17R1"
|
0, 1 -> "1_17R1"
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
18 -> when (version.patch) {
|
18 -> when (versionParts[2]) {
|
||||||
0, 1 -> "1_18R1"
|
0, 1 -> "1_18R1"
|
||||||
2 -> "1_18R2"
|
2 -> "1_18R2"
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
19 -> when (version.patch) {
|
19 -> when (versionParts[2]) {
|
||||||
0, 1, 2 -> "1_19R1"
|
0, 1, 2 -> "1_19R1"
|
||||||
3 -> "1_19R2"
|
3 -> "1_19R2"
|
||||||
4 -> "1_19R3"
|
4 -> "1_19R3"
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
20 -> when (version.patch) {
|
20 -> when (versionParts[2]) {
|
||||||
0, 1 -> "1_20R1"
|
0, 1 -> "1_20R1"
|
||||||
2 -> "1_20R2"
|
2 -> "1_20R2"
|
||||||
3, 4 -> "1_20R3"
|
3, 4 -> "1_20R3"
|
||||||
|
|
@ -36,7 +36,7 @@ object MinecraftVersionUtil {
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
21 -> when (version.patch) {
|
21 -> when (versionParts[2]) {
|
||||||
0, 1 -> "1_21R1"
|
0, 1 -> "1_21R1"
|
||||||
2, 3 -> "1_21R2"
|
2, 3 -> "1_21R2"
|
||||||
4 -> "1_21R3"
|
4 -> "1_21R3"
|
||||||
|
|
@ -51,8 +51,4 @@ object MinecraftVersionUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val isTooNewForSpigot: Boolean get() {
|
|
||||||
return UpdateUtils.currentMinecraftVersion().major != 1
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -17,7 +17,7 @@ import xyz.alexcrea.cuanvil.update.Version
|
||||||
import java.io.InputStreamReader
|
import java.io.InputStreamReader
|
||||||
|
|
||||||
object DataPackDependency {
|
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
|
* Map of the latest CustomAnvil update related to the pack
|
||||||
|
|
@ -145,7 +145,7 @@ object DataPackDependency {
|
||||||
CustomAnvil.instance.logger.warning("Could not find material $name for item group $groupName")
|
CustomAnvil.instance.logger.warning("Could not find material $name for item group $groupName")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
group.addToPolicy(mat.key)
|
group.addToPolicy(mat)
|
||||||
}
|
}
|
||||||
for (name in section.getStringList("groups")) {
|
for (name in section.getStringList("groups")) {
|
||||||
val otherGroup = MaterialGroupApi.getGroup(name)
|
val otherGroup = MaterialGroupApi.getGroup(name)
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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())
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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())
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue